Commit 9f5eee5304320158aa36ebe323d69aef0f86462e
Exists in
master
and in
3 other branches
fixing conflict on base.html
Showing
7 changed files
with
237 additions
and
29 deletions
Show diff stats
amadeus/templates/base.html
@@ -89,36 +89,36 @@ | @@ -89,36 +89,36 @@ | ||
89 | </div> | 89 | </div> |
90 | <ul class="nav navbar-nav navbar-right notifications"> | 90 | <ul class="nav navbar-nav navbar-right notifications"> |
91 | {% if user.is_staff %} | 91 | {% if user.is_staff %} |
92 | - | ||
93 | - | ||
94 | - <li class="dropdown-accordion dropdown" data-accordion="#system_accordion" title data-original-title="{% trans 'settings' %}"> | ||
95 | - <a href="#" data-toggle="dropdown"><i class="fa fa-cog" aria-hidden="true"></i></a> | ||
96 | - <ul class="dropdown-menu pull-right" role="menu"> | ||
97 | - <li><a href="{% url 'users:manage' %}">{% trans 'Manage Users' %}</a></li> | ||
98 | - <li><a href="{% url 'categories:index' %}">{% trans 'Manage Categories' %}</a></li> | ||
99 | - <li> | ||
100 | - <div class="panel-group" id="system_accordion"> | ||
101 | - <div class="panel panel-default"> | ||
102 | - <div class="panel-heading"> | ||
103 | - <a href="#system_menu" data-toggle="collapse" data-parent="#system_accordion"> | ||
104 | - <h4 class="panel-title"> | ||
105 | - {% trans 'System' %} | ||
106 | - </h4> | ||
107 | - </a> | ||
108 | - </div> | ||
109 | - <div class="panel-collapse collapse" id="system_menu"> | ||
110 | - <div class="panel-body"> | ||
111 | - <a href="{% url 'categories:index' %}">{% trans 'Mail Sender' %}</a><br /> | ||
112 | - <a href="{% url 'categories:index' %}">{% trans 'Security' %}</a><br /> | ||
113 | - <a href="{% url 'categories:index' %}">{% trans 'Theme' %}</a> | 92 | + |
93 | + <li class="dropdown-accordion dropdown" data-accordion="#system_accordion" title data-original-title="{% trans 'settings' %}"> | ||
94 | + <a href="#" data-toggle="dropdown"><i class="fa fa-cog" aria-hidden="true"></i></a> | ||
95 | + <ul class="dropdown-menu pull-right" role="menu"> | ||
96 | + <li><a href="{% url 'users:manage' %}">{% trans 'Manage Users' %}</a></li> | ||
97 | + <li><a href="{% url 'categories:index' %}">{% trans 'Manage Categories' %}</a></li> | ||
98 | + <li> | ||
99 | + <div class="panel-group" id="system_accordion"> | ||
100 | + <div class="panel panel-default"> | ||
101 | + <div class="panel-heading"> | ||
102 | + <a href="#system_menu" data-toggle="collapse" data-parent="#system_accordion"> | ||
103 | + <h4 class="panel-title"> | ||
104 | + {% trans 'System' %} | ||
105 | + </h4> | ||
106 | + </a> | ||
107 | + </div> | ||
108 | + <div class="panel-collapse collapse" id="system_menu"> | ||
109 | + <div class="panel-body"> | ||
110 | + <a href="{% url 'categories:index' %}">{% trans 'Mail Sender' %}</a><br /> | ||
111 | + <a href="{% url 'categories:index' %}">{% trans 'Security' %}</a><br /> | ||
112 | + <a href="{% url 'categories:index' %}">{% trans 'Theme' %}</a> | ||
113 | + </div> | ||
114 | </div> | 114 | </div> |
115 | </div> | 115 | </div> |
116 | </div> | 116 | </div> |
117 | - </div> | ||
118 | - </li> | ||
119 | - </ul> | ||
120 | - </li> | ||
121 | - {% endif %} | 117 | + </li> |
118 | + </ul> | ||
119 | + </li> | ||
120 | + {% endif %} | ||
121 | + | ||
122 | <li title data-original-title="{% trans 'account' %}"> | 122 | <li title data-original-title="{% trans 'account' %}"> |
123 | <a href="" data-toggle="dropdown" style="padding-top: 15px;padding-bottom:15px;"> | 123 | <a href="" data-toggle="dropdown" style="padding-top: 15px;padding-bottom:15px;"> |
124 | <img src="{{ user.image_url }}" style="width:30px;height:30px" /> | 124 | <img src="{{ user.image_url }}" style="width:30px;height:30px" /> |
log/admin.py
1 | from django.contrib import admin | 1 | from django.contrib import admin |
2 | 2 | ||
3 | -# Register your models here. | 3 | +from .models import Log |
4 | + | ||
5 | +class LogAdmin(admin.ModelAdmin): | ||
6 | + list_display = ['datetime', 'user', 'action', 'resource', 'context'] | ||
7 | + search_fields = ['user', 'action', 'resource'] | ||
8 | + | ||
9 | +admin.site.register(Log, LogAdmin) | ||
4 | \ No newline at end of file | 10 | \ No newline at end of file |
@@ -0,0 +1,78 @@ | @@ -0,0 +1,78 @@ | ||
1 | +import json | ||
2 | +import time | ||
3 | +from functools import wraps | ||
4 | +from django.shortcuts import get_object_or_404 | ||
5 | + | ||
6 | +from .models import Log | ||
7 | + | ||
8 | +def log_decorator(log_component = '', log_action = '', log_resource = ''): | ||
9 | + | ||
10 | + def _log_decorator(view_function): | ||
11 | + | ||
12 | + def _decorator(request, *args, **kwargs): | ||
13 | + | ||
14 | + response = view_function(request, *args, **kwargs) | ||
15 | + | ||
16 | + if request.user.is_authenticated: | ||
17 | + | ||
18 | + log = Log() | ||
19 | + log.user = request.user | ||
20 | + log.component = log_component | ||
21 | + log.context = request.log_context | ||
22 | + log.action = log_action | ||
23 | + log.resource = log_resource | ||
24 | + | ||
25 | + log.save() | ||
26 | + | ||
27 | + return response | ||
28 | + | ||
29 | + return wraps(view_function)(_decorator) | ||
30 | + | ||
31 | + return _log_decorator | ||
32 | + | ||
33 | +def log_decorator_ajax(log_component = '', log_action = '', log_resource = ''): | ||
34 | + | ||
35 | + def _log_decorator_ajax(view_function): | ||
36 | + | ||
37 | + def _decorator(request, *args, **kwargs): | ||
38 | + view_action = request.GET.get("action") | ||
39 | + | ||
40 | + if view_action == 'open': | ||
41 | + if request.user.is_authenticated: | ||
42 | + | ||
43 | + log = Log() | ||
44 | + log.user = request.user | ||
45 | + log.component = log_component | ||
46 | + log.context = "" | ||
47 | + log.action = log_action | ||
48 | + log.resource = log_resource | ||
49 | + | ||
50 | + log.save() | ||
51 | + | ||
52 | + response = view_function(request, *args, **kwargs) | ||
53 | + | ||
54 | + log = Log.objects.latest('id') | ||
55 | + log.context = request.log_context | ||
56 | + log.save() | ||
57 | + elif view_action == 'close': | ||
58 | + if request.user.is_authenticated: | ||
59 | + log = get_object_or_404(Log, id = request.GET.get('log_id')) | ||
60 | + | ||
61 | + if type(log.context) == dict: | ||
62 | + log_context = log.context | ||
63 | + else: | ||
64 | + log_context = json.loads(log.context) | ||
65 | + | ||
66 | + log_context['timestamp_end'] = str(int(time.time())) | ||
67 | + | ||
68 | + log.context = log_context | ||
69 | + | ||
70 | + log.save() | ||
71 | + | ||
72 | + response = view_function(request, *args, **kwargs) | ||
73 | + | ||
74 | + return response | ||
75 | + | ||
76 | + return wraps(view_function)(_decorator) | ||
77 | + | ||
78 | + return _log_decorator_ajax | ||
0 | \ No newline at end of file | 79 | \ No newline at end of file |
@@ -0,0 +1,47 @@ | @@ -0,0 +1,47 @@ | ||
1 | +import time | ||
2 | +import json | ||
3 | +from django.core.urlresolvers import resolve | ||
4 | +from django.shortcuts import get_object_or_404 | ||
5 | + | ||
6 | +from .models import Log | ||
7 | + | ||
8 | +class TimeSpentMiddleware(object): | ||
9 | + def __init__(self, get_response = None): | ||
10 | + self.get_response = get_response | ||
11 | + | ||
12 | + def process_request(self, request): | ||
13 | + app_names = resolve(request.path).app_names | ||
14 | + | ||
15 | + if not 'admin' in app_names: | ||
16 | + if not request.is_ajax(): | ||
17 | + log_id = request.session.get('log_id', None) | ||
18 | + | ||
19 | + if not log_id is None: | ||
20 | + log = get_object_or_404(Log, id = log_id) | ||
21 | + | ||
22 | + if type(log.context) == dict: | ||
23 | + log_context = log.context | ||
24 | + else: | ||
25 | + log_context = json.loads(log.context) | ||
26 | + | ||
27 | + log_context['timestamp_end'] = str(int(time.time())) | ||
28 | + | ||
29 | + log.context = log_context | ||
30 | + | ||
31 | + log.save() | ||
32 | + | ||
33 | + request.session['log_id'] = None | ||
34 | + | ||
35 | + oppened_logs = Log.objects.filter(user = request.user, context__contains={'timestamp_end': '-1'}) | ||
36 | + | ||
37 | + for op_log in oppened_logs: | ||
38 | + if type(op_log.context) == dict: | ||
39 | + log_context = op_log.context | ||
40 | + else: | ||
41 | + log_context = json.loads(op_log.context) | ||
42 | + | ||
43 | + log_context['timestamp_end'] = str(int(time.time())) | ||
44 | + | ||
45 | + op_log.context = log_context | ||
46 | + | ||
47 | + op_log.save() | ||
0 | \ No newline at end of file | 48 | \ No newline at end of file |
@@ -0,0 +1,36 @@ | @@ -0,0 +1,36 @@ | ||
1 | +# -*- coding: utf-8 -*- | ||
2 | +# Generated by Django 1.10 on 2016-12-29 20:07 | ||
3 | +from __future__ import unicode_literals | ||
4 | + | ||
5 | +from django.conf import settings | ||
6 | +import django.contrib.postgres.fields.jsonb | ||
7 | +from django.db import migrations, models | ||
8 | +import django.db.models.deletion | ||
9 | + | ||
10 | + | ||
11 | +class Migration(migrations.Migration): | ||
12 | + | ||
13 | + initial = True | ||
14 | + | ||
15 | + dependencies = [ | ||
16 | + migrations.swappable_dependency(settings.AUTH_USER_MODEL), | ||
17 | + ] | ||
18 | + | ||
19 | + operations = [ | ||
20 | + migrations.CreateModel( | ||
21 | + name='Log', | ||
22 | + fields=[ | ||
23 | + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||
24 | + ('component', models.TextField(verbose_name='Component (Module / App)')), | ||
25 | + ('context', django.contrib.postgres.fields.jsonb.JSONField(blank=True, verbose_name='Context')), | ||
26 | + ('action', models.TextField(verbose_name='Action')), | ||
27 | + ('resource', models.TextField(verbose_name='Resource')), | ||
28 | + ('datetime', models.DateTimeField(auto_now_add=True, verbose_name='Date and Time of action')), | ||
29 | + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Actor')), | ||
30 | + ], | ||
31 | + options={ | ||
32 | + 'verbose_name_plural': 'Logs', | ||
33 | + 'verbose_name': 'Log', | ||
34 | + }, | ||
35 | + ), | ||
36 | + ] |
@@ -0,0 +1,24 @@ | @@ -0,0 +1,24 @@ | ||
1 | +import json | ||
2 | + | ||
3 | +from .models import Log | ||
4 | + | ||
5 | +from users.models import User | ||
6 | + | ||
7 | +class LogMixin(object): | ||
8 | + log_component = "" | ||
9 | + log_context = {} | ||
10 | + log_action = "" | ||
11 | + log_resource = "" | ||
12 | + | ||
13 | + def createLog(self, actor = None, component = '', log_action = '', log_resource = '', context = {}): | ||
14 | + log = Log() | ||
15 | + log.user = actor | ||
16 | + log.context = context | ||
17 | + log.component = component | ||
18 | + log.action = log_action | ||
19 | + log.resource = log_resource | ||
20 | + | ||
21 | + log.save() | ||
22 | + | ||
23 | + def dispatch(self, request, *args, **kwargs): | ||
24 | + return super(LogMixin, self).dispatch(request, *args, **kwargs) | ||
0 | \ No newline at end of file | 25 | \ No newline at end of file |
log/models.py
1 | from django.db import models | 1 | from django.db import models |
2 | +from django.contrib.postgres.fields import JSONField | ||
3 | +from django.utils.translation import ugettext_lazy as _ | ||
2 | 4 | ||
3 | -# Create your models here. | 5 | +from users.models import User |
6 | + | ||
7 | +class Log(models.Model): | ||
8 | + component = models.TextField(_('Component (Module / App)')) | ||
9 | + context = JSONField(_('Context'), blank = True) | ||
10 | + action = models.TextField(_('Action')) | ||
11 | + resource = models.TextField(_('Resource')) | ||
12 | + user = models.ForeignKey(User, verbose_name = _('Actor')) | ||
13 | + datetime = models.DateTimeField(_("Date and Time of action"), auto_now_add = True) | ||
14 | + | ||
15 | + class Meta: | ||
16 | + verbose_name = _('Log') | ||
17 | + verbose_name_plural = _('Logs') | ||
18 | + | ||
19 | + def __str__(self): | ||
20 | + return str(self.user) + ' / ' + self.component | ||
4 | \ No newline at end of file | 21 | \ No newline at end of file |