summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--archaeological_context_records/models.py4
-rw-r--r--archaeological_files/models.py80
-rw-r--r--archaeological_finds/models.py5
-rw-r--r--archaeological_operations/models.py13
-rw-r--r--example_project/settings.py4
-rw-r--r--ishtar_common/context_processors.py14
-rw-r--r--ishtar_common/models.py7
-rw-r--r--ishtar_common/static/js/ishtar.js3
-rw-r--r--ishtar_common/static/media/style.css14
-rw-r--r--ishtar_common/templates/base.html8
-rw-r--r--ishtar_common/utils.py17
11 files changed, 149 insertions, 20 deletions
diff --git a/archaeological_context_records/models.py b/archaeological_context_records/models.py
index b33b86e8c..4a288b5dc 100644
--- a/archaeological_context_records/models.py
+++ b/archaeological_context_records/models.py
@@ -23,7 +23,7 @@ from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _, ugettext, pgettext
from ishtar_common.models import GeneralType, BaseHistorizedItem, \
- HistoricalRecords, OwnPerms, Town, Person, Source
+ HistoricalRecords, OwnPerms, ShortMenuItem, Town, Person, Source
from archaeological_operations.models import Operation, Period, Parcel
class DatingType(GeneralType):
@@ -92,7 +92,7 @@ class IdentificationType(GeneralType):
def __unicode__(self):
return self.label
-class ContextRecord(BaseHistorizedItem, OwnPerms):
+class ContextRecord(BaseHistorizedItem, OwnPerms, ShortMenuItem):
TABLE_COLS = ['parcel.town', 'operation.year',
'operation.operation_code',
'label', 'unit']
diff --git a/archaeological_files/models.py b/archaeological_files/models.py
index db33ed9b2..b3dd99edf 100644
--- a/archaeological_files/models.py
+++ b/archaeological_files/models.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-# Copyright (C) 2012-2013 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
+# Copyright (C) 2012-2014 Étienne Loks <etienne.loks_AT_peacefrogsDOTnet>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@@ -21,15 +21,16 @@ import datetime
from django.conf import settings
from django.contrib.gis.db import models
+from django.core.cache import cache
from django.db.models import Q, Count, Sum
from django.db.models.signals import post_save, m2m_changed
from django.utils.translation import ugettext_lazy as _, ugettext
-from ishtar_common.utils import cached_label_changed
+from ishtar_common.utils import cached_label_changed, get_cache
from ishtar_common.models import GeneralType, BaseHistorizedItem, \
HistoricalRecords, OwnPerms, Person, Organization, Department, Town, \
- Dashboard, IshtarUser, ValueGetter
+ Dashboard, IshtarUser, ValueGetter, ShortMenuItem
class FileType(GeneralType):
class Meta:
@@ -60,7 +61,7 @@ if settings.COUNTRY == 'fr':
verbose_name_plural = u"Types Saisine"
ordering = ('label',)
-class File(BaseHistorizedItem, OwnPerms, ValueGetter):
+class File(BaseHistorizedItem, OwnPerms, ValueGetter, ShortMenuItem):
TABLE_COLS = ['numeric_reference', 'year', 'internal_reference',
'file_type', 'saisine_type', 'towns', ]
year = models.IntegerField(_(u"Year"),
@@ -162,6 +163,71 @@ class File(BaseHistorizedItem, OwnPerms, ValueGetter):
def short_class_name(self):
return _(u"FILE")
+ @property
+ def delay_date(self):
+ cache_key, val = get_cache(self.__class__, [self.pk, 'delay_date'])
+ if val:
+ return val
+ return self.update_delay_date(cache_key)
+
+ def update_delay_date(self, cache_key=None):
+ if not cache_key:
+ cache_key, val = get_cache(self.__class__,
+ [self.pk, 'delay_date'])
+ date = self.reception_date
+ if not date:
+ date = datetime.date(2500, 1, 1)
+ elif settings.COUNTRY == 'fr' and self.saisine_type \
+ and self.saisine_type.delay:
+ date += datetime.timedelta(days=self.saisine_type.delay)
+ cache.set(cache_key, date, settings.CACHE_TIMEOUT)
+ return date
+
+ @property
+ def has_adminact(self):
+ cache_key, val = get_cache(self.__class__, [self.pk,
+ 'has_adminact'])
+ if val:
+ return val
+ return self.update_has_admin_act(cache_key)
+
+ def update_has_admin_act(self, cache_key=None):
+ if not cache_key:
+ cache_key, val = get_cache(self.__class__, [self.pk,
+ 'has_adminact'])
+ has_adminact = self.administrative_act.count()
+ cache.set(cache_key, has_adminact, settings.CACHE_TIMEOUT)
+ return has_adminact
+
+ def get_short_menu_class(self):
+ cache_key, val = get_cache(self.__class__, [self.pk,
+ 'short_class_name'])
+ if val:
+ return val
+ return self.update_short_menu_class(cache_key)
+
+ def update_short_menu_class(self, cache_key=None):
+ if not cache_key:
+ cache_key, val = get_cache(self.__class__, [self.pk,
+ 'short_class_name'])
+ cls = 'normal'
+ if not self.has_adminact and self.reception_date:
+ delta = datetime.date.today() - self.reception_date
+ cls = 'red'
+ if self.saisine_type and self.saisine_type.delay:
+ if delta.days < (self.saisine_type.delay*1/3):
+ cls = 'green'
+ elif delta.days < (self.saisine_type.delay*2/3):
+ cls = 'orange'
+ cache.set(cache_key, cls, settings.CACHE_TIMEOUT)
+ return cls
+
+ @classmethod
+ def get_owns(cls, user):
+ owns = super(File, cls).get_owns(user)
+ return sorted(owns.all(), key=lambda x:(x.has_adminact,
+ x.delay_date))
+
@classmethod
def get_years(cls):
return [res['year'] for res in list(cls.objects.values('year').annotate(
@@ -263,6 +329,12 @@ class File(BaseHistorizedItem, OwnPerms, ValueGetter):
acts.append(act)
return acts
+ def save(self, *args, **kwargs):
+ returned = super(File, self).save(*args, **kwargs)
+ self.update_delay_date()
+ self.update_short_menu_class()
+ return returned
+
def is_preventive(self):
return FileType.is_preventive(self.file_type.pk)
diff --git a/archaeological_finds/models.py b/archaeological_finds/models.py
index 592788b88..cdc87ea95 100644
--- a/archaeological_finds/models.py
+++ b/archaeological_finds/models.py
@@ -24,7 +24,8 @@ from django.db.models import Max
from django.utils.translation import ugettext_lazy as _, ugettext
from ishtar_common.models import GeneralType, ImageModel, BaseHistorizedItem, \
- LightHistorizedItem, HistoricalRecords, OwnPerms, Source, Person
+ ShortMenuItem, LightHistorizedItem, HistoricalRecords, OwnPerms, Source, \
+ Person
from archaeological_operations.models import AdministrativeAct
from archaeological_context_records.models import ContextRecord, Dating
@@ -141,7 +142,7 @@ class BaseFind(BaseHistorizedItem, OwnPerms):
self.context_record.label,
lbl) if it])
-class Find(BaseHistorizedItem, ImageModel, OwnPerms):
+class Find(BaseHistorizedItem, ImageModel, OwnPerms, ShortMenuItem):
TABLE_COLS = ['label', 'material_type', 'dating.period',
'base_finds.context_record.parcel.town',
'base_finds.context_record.operation.year',
diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py
index 020e66bfb..a3f61f713 100644
--- a/archaeological_operations/models.py
+++ b/archaeological_operations/models.py
@@ -33,7 +33,7 @@ from ishtar_common.utils import cached_label_changed
from ishtar_common.models import GeneralType, BaseHistorizedItem, \
HistoricalRecords, LightHistorizedItem, OwnPerms, Department, Source,\
Person, Organization, Town, Dashboard, IshtarUser, ValueGetter, \
- DocumentTemplate
+ DocumentTemplate, ShortMenuItem
FILES_AVAILABLE = 'archaeological_files' in settings.INSTALLED_APPS
class OperationType(GeneralType):
@@ -132,7 +132,7 @@ class ArchaeologicalSite(BaseHistorizedItem):
name += u" %s %s" % (settings.JOINT, self.name)
return name
-class Operation(BaseHistorizedItem, OwnPerms, ValueGetter):
+class Operation(BaseHistorizedItem, OwnPerms, ValueGetter, ShortMenuItem):
TABLE_COLS = ['year_index', 'operation_type', 'remains', 'towns',
'associated_file_short_label', 'start_date',
'excavation_end_date']
@@ -225,6 +225,12 @@ class Operation(BaseHistorizedItem, OwnPerms, ValueGetter):
("close_operation", ugettext(u"Can close Operation")),
)
+ @classmethod
+ def get_owns(cls, user):
+ owns = super(Operation, cls).get_owns(user)
+ #owns = owns.annotate(null_count=Count('operation_code'))
+ return owns.order_by("-year", "operation_code")
+
def __unicode__(self):
if self.cached_label:
return self.cached_label
@@ -614,6 +620,9 @@ class AdministrativeAct(BaseHistorizedItem, OwnPerms, ValueGetter):
self._get_index()
super(AdministrativeAct, self).save(*args, **kwargs)
+ if hasattr(self, 'associated_file') and self.associated_file:
+ self.associated_file.update_has_admin_act()
+ self.associated_file.update_short_menu_class()
class Parcel(LightHistorizedItem):
if FILES_AVAILABLE:
diff --git a/example_project/settings.py b/example_project/settings.py
index 201750936..d276ef6bf 100644
--- a/example_project/settings.py
+++ b/example_project/settings.py
@@ -14,6 +14,10 @@ SQL_DEBUG = False
IMAGE_MAX_SIZE = (1024, 768)
THUMB_MAX_SIZE = (300, 300)
+CACHE_SMALLTIMEOUT = 120
+CACHE_TIMEOUT = 3600
+CACHE_BACKEND = 'memcached://127.0.0.1:11211/'
+
ROOT_PATH = os.path.abspath(os.path.curdir) + os.path.sep
STATIC_URL = '/static/'
STATIC_ROOT = ROOT_PATH + 'static/'
diff --git a/ishtar_common/context_processors.py b/ishtar_common/context_processors.py
index 293a5ad44..e3b14cdda 100644
--- a/ishtar_common/context_processors.py
+++ b/ishtar_common/context_processors.py
@@ -44,7 +44,7 @@ def get_base_context(request):
dct = {'URL_PATH':settings.URL_PATH}
dct["APP_NAME"] = Site.objects.get_current().name
dct["COUNTRY"] = settings.COUNTRY
- """
+ """
if 'MENU' not in request.session or \
request.session['MENU'].user != request.user:
menu = Menu(request.user)
@@ -66,13 +66,17 @@ def get_base_context(request):
dct['current_menu'] = []
for lbl, model in CURRENT_ITEMS:
model_name = model.__name__.lower()
+ cls = ''
current = model_name in request.session and request.session[model_name]
items = []
- for item in sorted(model.get_owns(request.user),
- key=lambda x:x.cached_label):
+ for item in model.get_owns(request.user):
+ selected = unicode(item.pk) == current
+ if selected:
+ cls = item.get_short_menu_class()
items.append((item.pk, shortify(unicode(item), 60),
- unicode(item.pk) == current))
+ selected,
+ item.get_short_menu_class()))
if items:
- dct['current_menu'].append((lbl, model_name, items))
+ dct['current_menu'].append((lbl, model_name, cls, items))
return dct
diff --git a/ishtar_common/models.py b/ishtar_common/models.py
index 3c33928a9..9eba9ccd0 100644
--- a/ishtar_common/models.py
+++ b/ishtar_common/models.py
@@ -193,7 +193,7 @@ class OwnPerms:
query = cls.get_query_owns(user)
if not query:
return []
- return cls.objects.filter(query).order_by(*cls._meta.ordering).all()
+ return cls.objects.filter(query).order_by(*cls._meta.ordering)
class GeneralType(models.Model):
"""
@@ -518,6 +518,11 @@ class BaseHistorizedItem(models.Model):
items.append('00000000')
return u"-".join([unicode(item) for item in items])
+
+class ShortMenuItem(object):
+ def get_short_menu_class(self):
+ return ''
+
class LightHistorizedItem(BaseHistorizedItem):
history_date = models.DateTimeField(default=datetime.datetime.now)
class Meta:
diff --git a/ishtar_common/static/js/ishtar.js b/ishtar_common/static/js/ishtar.js
index 0a15bfc23..b91558194 100644
--- a/ishtar_common/static/js/ishtar.js
+++ b/ishtar_common/static/js/ishtar.js
@@ -51,6 +51,9 @@ $(document).ready(function(){
if ($.isFunction($(".prettyPhoto a").prettyPhoto)){
$(".prettyPhoto a").prettyPhoto({'social_tools':''});
}
+ $('#current_items select').change(function(){
+ $(this).attr('class', $(this).children("option:selected").attr('class'));
+ })
});
$('#to_bottom_arrow').live('click', function(){
diff --git a/ishtar_common/static/media/style.css b/ishtar_common/static/media/style.css
index 5a7de3694..8722b5d05 100644
--- a/ishtar_common/static/media/style.css
+++ b/ishtar_common/static/media/style.css
@@ -17,9 +17,11 @@ div.form {
}
/* color */
+#context_menu .red,
a, a.remove {
color:#D14;
}
+
a.add-button{
color:#61615C;
}
@@ -28,6 +30,18 @@ a.add-button{
color:#fff;
}
+#context_menu .orange {
+ color:#dd6011;
+}
+
+#context_menu .green {
+ color:#13ae0c;
+}
+
+#context_menu .normal{
+ color:#000;
+}
+
/* borders */
a.add-button, a.remove,
#progress-content,
diff --git a/ishtar_common/templates/base.html b/ishtar_common/templates/base.html
index cea906f26..bfacee069 100644
--- a/ishtar_common/templates/base.html
+++ b/ishtar_common/templates/base.html
@@ -63,13 +63,13 @@
<fieldset>
<legend>{% trans "Default selected items"%}</legend>
<table id='current_items'>
- {% for lbl, model_name, items in current_menu %}
+ {% for lbl, model_name, main_cls, items in current_menu %}
<tr>
<td><label for="current_{{model_name}}">{{lbl}}</label></td>
<td>
- <select id='current_{{model_name}}'>
- <option value=''>--</option>
- {% for val, label, selected in items %}<option value='{{val}}'{%if selected%} selected="selected"{%endif%}>{{label}}</option>
+ <select class='{{main_cls}}' id='current_{{model_name}}'>
+ <option class='normal' value=''>--</option>
+ {% for val, label, selected, cls in items %}<option class='{{cls}}' value='{{val}}'{%if selected%} selected="selected"{%endif%}>{{label}}</option>
{% endfor %}</select>
</td>{% with 'show-'|add:model_name as model_url%}
<td><a href='#' onclick='load_current_window("{% url model_url 0 %}", "{{model_name}}");' class='display_details'>{% trans "Details" %}</a></td>
diff --git a/ishtar_common/utils.py b/ishtar_common/utils.py
index d5fc37276..f50031d5d 100644
--- a/ishtar_common/utils.py
+++ b/ishtar_common/utils.py
@@ -17,7 +17,24 @@
# See the file COPYING for details.
+from django.core.cache import cache
from django.utils.translation import ugettext
+from django.template.defaultfilters import slugify
+
+def get_cache(cls, extra_args=[]):
+ cache_key = cls.__name__
+ for arg in extra_args:
+ if not arg:
+ cache_key += '-0'
+ else:
+ if type(arg) == dict:
+ cache_key += '-' + "_".join([unicode(arg[k]) for k in arg])
+ elif type(arg) in (list, tuple):
+ cache_key += '-' + "_".join([unicode(v) for v in arg])
+ else:
+ cache_key += '-' + unicode(arg)
+ cache_key = slugify(cache_key)
+ return cache_key, cache.get(cache_key)
def cached_label_changed(sender, **kwargs):
if not kwargs.get('instance'):