Commits

Rafał Selewońko committed 370f562

Comments (0)

Files changed (5)

     'django.middleware.common.CommonMiddleware',
     'django.contrib.sessions.middleware.SessionMiddleware',
     'django.middleware.csrf.CsrfViewMiddleware',
-    'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware',
     'django.contrib.auth.middleware.AuthenticationMiddleware',
     'django.contrib.messages.middleware.MessageMiddleware',
 ]
 
 ugettext = lambda s: s
 
-FLATPAGES_TEMPLATE_NAME_CHOICES = (
-    ('flatpages/default.html', ugettext('Default template')),
-    ('flatpages/advertiser.html', ugettext(u'strona reklamodawcy')),
-    ('flatpages/provider.html', ugettext(u'strona dostawcy')),
-    ('flatpages/publisher.html', ugettext(u'strona wydawcy')),
-    ('flatpages/contact.html', ugettext(u'kontakt')),
-)
 
 TINYMCE_DEFAULT_CONFIG = {
         'theme': 'advanced',

static/scripts/jquery.cookie.js

+/*jslint browser: true */ /*global jQuery: true */
+
+/**
+ * jQuery Cookie plugin
+ *
+ * Copyright (c) 2010 Klaus Hartl (stilbuero.de)
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ */
+
+// TODO JsDoc
+
+/**
+ * Create a cookie with the given key and value and other optional parameters.
+ *
+ * @example $.cookie('the_cookie', 'the_value');
+ * @desc Set the value of a cookie.
+ * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
+ * @desc Create a cookie with all available options.
+ * @example $.cookie('the_cookie', 'the_value');
+ * @desc Create a session cookie.
+ * @example $.cookie('the_cookie', null);
+ * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
+ *       used when the cookie was set.
+ *
+ * @param String key The key of the cookie.
+ * @param String value The value of the cookie.
+ * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
+ * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
+ *                             If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
+ *                             If set to null or omitted, the cookie will be a session cookie and will not be retained
+ *                             when the the browser exits.
+ * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
+ * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
+ * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
+ *                        require a secure protocol (like HTTPS).
+ * @type undefined
+ *
+ * @name $.cookie
+ * @cat Plugins/Cookie
+ * @author Klaus Hartl/klaus.hartl@stilbuero.de
+ */
+
+/**
+ * Get the value of a cookie with the given key.
+ *
+ * @example $.cookie('the_cookie');
+ * @desc Get the value of a cookie.
+ *
+ * @param String key The key of the cookie.
+ * @return The value of the cookie.
+ * @type String
+ *
+ * @name $.cookie
+ * @cat Plugins/Cookie
+ * @author Klaus Hartl/klaus.hartl@stilbuero.de
+ */
+jQuery.cookie = function (key, value, options) {
+
+    // key and value given, set cookie...
+    if (arguments.length > 1 && (value === null || typeof value !== "object")) {
+        options = jQuery.extend({}, options);
+
+        if (value === null) {
+            options.expires = -1;
+        }
+
+        if (typeof options.expires === 'number') {
+            var days = options.expires, t = options.expires = new Date();
+            t.setDate(t.getDate() + days);
+        }
+
+        return (document.cookie = [
+            encodeURIComponent(key), '=',
+            options.raw ? String(value) : encodeURIComponent(String(value)),
+            options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
+            options.path ? '; path=' + options.path : '',
+            options.domain ? '; domain=' + options.domain : '',
+            options.secure ? '; secure' : ''
+        ].join(''));
+    }
+
+    // key and possibly options given, get cookie...
+    options = value || {};
+    var result, decode = options.raw ? function (s) { return s; } : decodeURIComponent;
+    return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? decode(result[1]) : null;
+};

templates/worklogs/report.html

     <link rel="stylesheet" href="{% static "themes/base/jquery.ui.all.css" %}">
     <link rel="stylesheet" href="{% static "styles/demos.css" %}">
     <script src="{% static "scripts/jquery-1.7.2.js" %}"></script>
+    <script src="{% static "scripts/jquery.cookie.js" %}"></script>
     <script src="{% static "ui/jquery.ui.core.js" %}"></script>
     <script src="{% static "ui/jquery.ui.widget.js" %}"></script>
+    <script src="{% static "ui/jquery.ui.mouse.js" %}"></script>
+    <script src="{% static "ui/jquery.ui.sortable.js" %}"></script>
+    <script src="{% static "ui/jquery.ui.tabs.js" %}"></script>
     <script src="{% static "ui/jquery.ui.datepicker.js" %}"></script>
-    <script src="{% static "ui/jquery.ui.tabs.js" %}"></script>
     <script>
         $(function() {
-            $( "#tabs" ).tabs();
+            var tabs = $( "#reports" ).tabs({
+                cookie: {expires: 1}
+            });
+            tabs.tabs().find( ".ui-tabs-nav" ).sortable({
+                axis: "x"
+	    });
             var dates = $( "#from, #to" ).datepicker({
                 changeMonth: true,
                 changeYear: true,
                     dates.not( this ).datepicker( "option", option, date );
                 }
             });
+            $("textarea.copy").each(function(){
+                var rows = this.value.split("\n").length;
+                this.setAttribute('rows', rows + 1);
+            });
         });
     </script>
+    <style>
+        textarea.copy {
+            font-family: monospace;
+            font-size: 12px;
+            border: none;
+        }
+    </style>
 {% endblock %}
 
 {% block content %}
     <input type="submit" />
 </form>
 {% if time_per_worklog %}
-<div id="tabs">
+<div id="reports">
     <ul>
-        <li><a href="#tabs-1">{% trans "time per worklog" %}</a></li>
-        <li><a href="#tabs-2">{% trans "worklogs per day" %}</a></li>
-        <li><a href="#tabs-3">{% trans "time per project" %}</a></li>
+        <li><a href="#time_per_worklog">{% trans "time per worklog" %}</a></li>
+        <li><a href="#worklogs_per_day">{% trans "worklogs per day" %}</a></li>
+        <li><a href="#time_per_project">{% trans "time per project" %}</a></li>
     </ul>
-    <div id="tabs-1">
-    <pre>{{ from }} - {{ to }}
-{% for worklog, duration in time_per_worklog %}
+    <div id="time_per_worklog">
+    <textarea class="copy" rows="24" cols="80">{% if from != to %}{{ from }} - {{ to }}
+{% endif %}{% for worklog, duration in time_per_worklog %}
 {{ worklog.description }} ({{duration|seconds_to_time}}) - {{ worklog.get_state_display }}
 {{ worklog.bugtracker_url }}
-{% endfor %}
-</pre>
+{% endfor %}</textarea>
     </div>
-    <div id="tabs-2">
-    <pre>{{ from }} - {{ to }}
-{% for date, worklogs in worklogs_per_day.items %}
-{{ date }}:
-    {% for worklog, duration in worklogs %}
+    <div id="worklogs_per_day">
+    <textarea class="copy" rows="24" cols="80">{% if from != to %}{{ from }} - {{ to }}
+{% endif %}{% for date, data in worklogs_per_day.items %}
+{{ date }} ({{ data.time|seconds_to_time }}):
+    {% for worklog, duration in data.worklogs %}
     {{ worklog.description }} ({{duration|seconds_to_time}})
     {{ worklog.bugtracker_url }}
-    {% endfor %}
-{% endfor %}</pre>
+    {% endfor %}{% endfor %}</textarea>
     </div>
-    <div id="tabs-3">
-    <pre>{{ from }} - {{ to }}{% if week %} ({% trans "week" %} {{ week }}){% endif %}
-{% for project, data in time_per_project.items %}
-{{ project }}: {{ data.time|seconds_to_hours:2|floatformat }}h
-{% endfor %}</pre>
+    <div id="time_per_project">
+    <textarea class="copy" rows="24" cols="80">{% if from != to %}{{ from }} - {{ to }}
+{% endif %}{% for project, data in time_per_project.items %}
+{{ project }}: {{ data.time|seconds_to_hours:2|floatformat }}h{% endfor %}</textarea>
     </div>
 </div>{% else %}{% trans "No worklogs in selected date range" %}{% endif %}
 </div>

worklogs/managers.py

 
         return self.get_query_set().filter(
                 models.Q(start__gte=start)
-                & models.Q(end__gte=start)
+                & (models.Q(end__gte=start) | models.Q(end__isnull=True))
                 & models.Q(start__lt=end)
-                & models.Q(end__lt=end)
+                & (models.Q(end__lt=end) | models.Q(end__isnull=True))
             )
 

worklogs/views.py

 # -*- coding: utf-8 -*-
 import datetime
 from django.contrib import messages
+from django.contrib.auth.decorators import login_required
 from django.http import HttpResponseRedirect
 from django.shortcuts import render_to_response
 from django.utils.translation import ugettext as _
     return ret
 
 
+@login_required
 def worklog_start(request, object_id):
     worklog = WorkLog.objects.get(id=object_id)
-    worklog.start()
-    messages.success(request, _(u'WorkLog "{}" has been started.').format(worklog))
+    if request.user == worklog.user or request.user.is_superuser:
+        # FIXME: zamienic na "user_passes_test"
+        worklog.start()
+        messages.success(request, _(u'WorkLog "{}" has been started.').format(worklog))
+    else:
+        messages.error(request, _(u'WorkLog "{}" has <b>not</b> been started. Insufficient permissions.').format(worklog))
     return HttpResponseRedirect('/worklogs/worklog/')
 
 
+@login_required
 def worklog_stop(request, object_id):
     worklog = WorkLog.objects.get(id=object_id)
-    worklog.stop()
-    messages.success(request, _(u'WorkLog "{}" has been stopped.').format(worklog))
+    if request.user == worklog.user or request.user.is_superuser:
+        # FIXME: zamienic na "user_passes_test"
+        worklog.stop()
+        messages.success(request, _(u'WorkLog "{}" has been stopped.').format(worklog))
+    else:
+        messages.error(request, _(u'WorkLog "{}" has <b>not</b> been stopped. Insufficient permissions.').format(worklog))
     return HttpResponseRedirect('/worklogs/worklog/')
 
 
+@login_required
 def report(request):
 
     get_from_date = request.GET.get('from')
     else:
         to_date = from_date + datetime.timedelta(days=5)
 
-    entries = WorkLogEntry.objects.in_range(from_date, to_date)
+    entries = WorkLogEntry.objects.in_range(from_date, to_date).filter(worklog__user=request.user)
 
     time_per_project = {}
     time_per_worklog = []
         date = entry.start.date()
         if date in worklogs_per_day:
             try:
-                index = list(map(lambda a: a[0].id, worklogs_per_day[date])).index(entry.worklog.id)
+                index = list(map(lambda a: a[0].id, worklogs_per_day[date]['worklogs'])).index(entry.worklog.id)
             except ValueError:
-                worklogs_per_day[date].append([entry.worklog, entry.duration])
+                worklogs_per_day[date]['worklogs'].append([entry.worklog, entry.duration])
             else:
-                worklogs_per_day[date][index][1] += entry.duration
+                worklogs_per_day[date]['worklogs'][index][1] += entry.duration
+            worklogs_per_day[date]['time'] += entry.duration
         else:
-            worklogs_per_day[date] = [[entry.worklog, entry.duration]]
+            worklogs_per_day[date] = {
+                    'time': entry.duration,
+                    'worklogs': [[entry.worklog, entry.duration]]
+                }
 
         if entry.worklog.project in time_per_project:
             time_per_project[entry.worklog.project]['time'] += entry.duration