summaryrefslogtreecommitdiff
path: root/ishtar_common
diff options
context:
space:
mode:
Diffstat (limited to 'ishtar_common')
-rw-r--r--ishtar_common/locale/fr/LC_MESSAGES/django.po261
-rw-r--r--ishtar_common/models.py90
-rw-r--r--ishtar_common/static/media/style.css16
-rw-r--r--ishtar_common/templates/ishtar/dashboards/dashboard_main.html3
-rw-r--r--ishtar_common/templates/ishtar/dashboards/dashboard_main_detail.html96
-rw-r--r--ishtar_common/templatetags/date_formating.py19
-rw-r--r--ishtar_common/views.py28
7 files changed, 343 insertions, 170 deletions
diff --git a/ishtar_common/locale/fr/LC_MESSAGES/django.po b/ishtar_common/locale/fr/LC_MESSAGES/django.po
index 5291ab4ff..923126974 100644
--- a/ishtar_common/locale/fr/LC_MESSAGES/django.po
+++ b/ishtar_common/locale/fr/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: alpha\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2014-10-15 01:16+0200\n"
+"POT-Creation-Date: 2014-10-21 00:43+0200\n"
"PO-Revision-Date: 2010-12-09\n"
"Last-Translator: Étienne Loks <etienne.loks at peacefrogs net>\n"
"Language-Team: \n"
@@ -54,8 +54,7 @@ msgstr "Confirmation"
#: forms.py:80
msgid "Are you sure you want to delete?"
-msgstr ""
-"Êtes vous sûr de vouloir supprimer ?"
+msgstr "Êtes vous sûr de vouloir supprimer ?"
#: forms.py:88
msgid "There are identical items."
@@ -73,12 +72,12 @@ msgstr "Vous devez sélectionner un élément."
msgid "Add a new item"
msgstr "Ajouter un nouvel élément"
-#: forms.py:164 models.py:672
+#: forms.py:164 models.py:739
msgid "Template"
msgstr "Patron"
#: forms_common.py:42 forms_common.py:104 forms_common.py:185
-#: forms_common.py:190 models.py:721 models.py:976
+#: forms_common.py:190 models.py:788 models.py:1043
#: templates/ishtar/sheet_organization.html:17
#: templates/ishtar/sheet_person.html:20 templates/ishtar/sheet_person.html:30
msgid "Town"
@@ -102,68 +101,68 @@ msgstr ""
"<p class='example'>Par exemple tapez « saint denis 93 » pour obtenir la "
"commune Saint-Denis dans le département français de Seine-Saint-Denis.</p>"
-#: forms_common.py:56 forms_common.py:354 ishtar_menu.py:30 models.py:794
-#: models.py:861 models.py:901 templates/ishtar/sheet_person.html:6
+#: forms_common.py:56 forms_common.py:354 ishtar_menu.py:30 models.py:861
+#: models.py:928 models.py:968 templates/ishtar/sheet_person.html:6
msgid "Person"
msgstr "Individu"
-#: forms_common.py:92 forms_common.py:152 ishtar_menu.py:42 models.py:746
+#: forms_common.py:92 forms_common.py:152 ishtar_menu.py:42 models.py:813
#: templates/ishtar/sheet_organization.html:6
msgid "Organization"
msgstr "Organisation"
#: forms_common.py:94 forms_common.py:130 forms_common.py:148
-#: forms_common.py:177 models.py:671 models.py:741 models.py:787 models.py:962
-#: templates/ishtar/sheet_organization.html:12
+#: forms_common.py:177 models.py:738 models.py:808 models.py:854
+#: models.py:1029 templates/ishtar/sheet_organization.html:12
#: templates/ishtar/sheet_organization.html:25
#: templates/ishtar/sheet_person.html:12 templates/ishtar/sheet_person.html:26
msgid "Name"
msgstr "Nom"
-#: forms_common.py:96 models.py:735
+#: forms_common.py:96 models.py:802
msgid "Organization type"
msgstr "Type d'organisation"
-#: forms_common.py:98 forms_common.py:179 models.py:716
+#: forms_common.py:98 forms_common.py:179 models.py:783
#: templates/ishtar/sheet_organization.html:14
#: templates/ishtar/sheet_person.html:17 templates/ishtar/sheet_person.html:27
msgid "Address"
msgstr "Adresse"
-#: forms_common.py:100 forms_common.py:181 models.py:717
+#: forms_common.py:100 forms_common.py:181 models.py:784
#: templates/ishtar/sheet_organization.html:15
#: templates/ishtar/sheet_person.html:18 templates/ishtar/sheet_person.html:28
msgid "Address complement"
msgstr "Complément d'adresse"
-#: forms_common.py:102 forms_common.py:183 models.py:719
+#: forms_common.py:102 forms_common.py:183 models.py:786
#: templates/ishtar/sheet_organization.html:16
#: templates/ishtar/sheet_person.html:19 templates/ishtar/sheet_person.html:29
msgid "Postal code"
msgstr "Code postal"
-#: forms_common.py:105 forms_common.py:186 models.py:722
+#: forms_common.py:105 forms_common.py:186 models.py:789
msgid "Country"
msgstr "Pays"
#: forms_common.py:107 forms_common.py:150 forms_common.py:188
-#: forms_common.py:240 models.py:727 templates/ishtar/sheet_person.html:15
+#: forms_common.py:240 models.py:794 templates/ishtar/sheet_person.html:15
msgid "Email"
msgstr "Courriel"
-#: forms_common.py:108 forms_common.py:189 models.py:724
+#: forms_common.py:108 forms_common.py:189 models.py:791
#: templates/ishtar/sheet_organization.html:18
#: templates/ishtar/sheet_person.html:21 templates/ishtar/sheet_person.html:31
msgid "Phone"
msgstr "Téléphone"
-#: forms_common.py:109 models.py:725
+#: forms_common.py:109 models.py:792
#: templates/ishtar/sheet_organization.html:19
#: templates/ishtar/sheet_person.html:22 templates/ishtar/sheet_person.html:32
msgid "Mobile phone"
msgstr "Téléphone portable"
-#: forms_common.py:131 forms_common.py:151 models.py:743 models.py:925
+#: forms_common.py:131 forms_common.py:151 models.py:810 models.py:992
#: templates/sheet_ope.html:85 templates/sheet_ope.html.py:105
#: templates/sheet_ope.html:126 templates/ishtar/sheet_organization.html:27
#: templates/ishtar/sheet_person.html:42 templates/ishtar/sheet_person.html:95
@@ -175,7 +174,7 @@ msgstr "Type"
msgid "Organization search"
msgstr "Recherche d'organisations"
-#: forms_common.py:149 forms_common.py:175 models.py:785
+#: forms_common.py:149 forms_common.py:175 models.py:852
#: templates/ishtar/sheet_organization.html:26
#: templates/ishtar/sheet_person.html:13
msgid "Surname"
@@ -189,7 +188,7 @@ msgstr "Recherche d'individus"
msgid "Identity"
msgstr "Identité"
-#: forms_common.py:174 forms_common.py:311 models.py:784 models.py:924
+#: forms_common.py:174 forms_common.py:311 models.py:851 models.py:991
#: templates/sheet_ope.html:104 templates/ishtar/sheet_person.html:94
#: templates/ishtar/blocks/window_tables/documents.html:5
msgid "Title"
@@ -199,7 +198,7 @@ msgstr "Titre"
msgid "Current organization"
msgstr "Organisation actuelle"
-#: forms_common.py:199 forms_common.py:222 forms_common.py:225 models.py:771
+#: forms_common.py:199 forms_common.py:222 forms_common.py:225 models.py:838
msgid "Person type"
msgstr "Type d'individu"
@@ -231,7 +230,7 @@ msgstr "Ce nom d'utilisateur existe déjà."
msgid "Send the new password by email?"
msgstr "Envoyer le nouveau mot de passe par courriel ?"
-#: forms_common.py:291 forms_common.py:303 models.py:977
+#: forms_common.py:291 forms_common.py:303 models.py:1044
#: templates/ishtar/sheet_person.html:72
msgid "Towns"
msgstr "Communes"
@@ -244,23 +243,23 @@ msgstr "Il y a des communes identiques."
msgid "Documentation informations"
msgstr "Information sur le document"
-#: forms_common.py:313 forms_common.py:332 models.py:920
+#: forms_common.py:313 forms_common.py:332 models.py:987
msgid "Source type"
msgstr "Type de source"
-#: forms_common.py:315 models.py:929
+#: forms_common.py:315 models.py:996
msgid "Numerical ressource (web address)"
msgstr "Ressource numérique (adresse web)"
-#: forms_common.py:316 models.py:931
+#: forms_common.py:316 models.py:998
msgid "Receipt date"
msgstr "Date de réception"
-#: forms_common.py:318 models.py:933
+#: forms_common.py:318 models.py:1000
msgid "Creation date"
msgstr "Date de création"
-#: forms_common.py:329 forms_common.py:348 forms_common.py:379 models.py:906
+#: forms_common.py:329 forms_common.py:348 forms_common.py:379 models.py:973
#: templates/ishtar/wizard/wizard_person_deletion.html:124
msgid "Author"
msgstr "Auteur"
@@ -269,7 +268,7 @@ msgstr "Auteur"
msgid "Would you like to delete this documentation?"
msgstr "Voulez vous supprimer ce document ?"
-#: forms_common.py:355 models.py:897 models.py:903
+#: forms_common.py:355 models.py:964 models.py:970
msgid "Author type"
msgstr "Type d'auteur"
@@ -281,7 +280,7 @@ msgstr "Sélection d'auteur"
msgid "There are identical authors."
msgstr "Il y a des auteurs identiques."
-#: forms_common.py:389 models.py:907 models.py:926
+#: forms_common.py:389 models.py:974 models.py:993
#: templates/sheet_ope.html:106
#: templates/ishtar/blocks/window_tables/documents.html:7
msgid "Authors"
@@ -303,7 +302,7 @@ msgstr "Modification"
msgid "Delete"
msgstr "Supprimer"
-#: ishtar_menu.py:57 views.py:119
+#: ishtar_menu.py:57 views.py:121
msgid "Account management"
msgstr "Gestion des comptes"
@@ -319,7 +318,7 @@ msgstr "Un élément sélectionné n'est pas valide."
msgid "This item already exist."
msgstr "Cet élément existe déjà."
-#: models.py:202 models.py:548 models.py:704
+#: models.py:202 models.py:548 models.py:771
msgid "Label"
msgstr "Libellé"
@@ -331,7 +330,7 @@ msgstr "Identifiant textuel"
msgid "Comment"
msgstr "Commentaire"
-#: models.py:206 models.py:675
+#: models.py:206 models.py:742
msgid "Available"
msgstr "Disponible"
@@ -359,161 +358,154 @@ msgstr "Ordre"
msgid "Wizard step"
msgstr "Étape de l'assistant"
-#: models.py:596 templates/sheet_ope.html:61 templates/sheet_ope.html.py:83
-#: templates/ishtar/sheet_person.html:39 templates/ishtar/sheet_person.html:68
-#: templates/ishtar/sheet_person.html:93
-#: templates/ishtar/dashboards/dashboard_main_detail.html:94
-msgid "Year"
-msgstr "Année"
+#: models.py:643 models.py:674
+msgid "Total"
+msgstr "Total"
-#: models.py:599 models.py:608 models.py:705
-#: templates/ishtar/dashboards/dashboard_main_detail.html:105
+#: models.py:650 models.py:772
+#: templates/ishtar/dashboards/dashboard_main_detail.html:135
#: templates/ishtar/dashboards/dashboard_main_detail_users.html:26
msgid "Number"
msgstr "Nombre"
-#: models.py:607 templates/ishtar/dashboards/dashboard_main_detail.html:100
-msgid "Month"
-msgstr "Mois"
-
-#: models.py:670
+#: models.py:737
msgid "Administrative Act"
msgstr "Acte administratif"
-#: models.py:673
+#: models.py:740
msgid "Associated object"
msgstr "Objet associé"
-#: models.py:678
+#: models.py:745
msgid "Document template"
msgstr "Patron de document"
-#: models.py:679
+#: models.py:746
msgid "Document templates"
msgstr "Patrons de documents"
-#: models.py:708
+#: models.py:775
msgid "Department"
msgstr "Département"
-#: models.py:709
+#: models.py:776
msgid "Departments"
msgstr "Départements"
-#: models.py:736
+#: models.py:803
msgid "Organization types"
msgstr "Types d'organisation"
-#: models.py:747
+#: models.py:814
msgid "Organizations"
msgstr "Organisations"
-#: models.py:749
+#: models.py:816
msgid "Can view all Organization"
msgstr "Peut voir toutes les Organisations"
-#: models.py:750
+#: models.py:817
msgid "Can view own Organization"
msgstr "Peut voir sa propre Organisation"
-#: models.py:751
+#: models.py:818
msgid "Can add own Organization"
msgstr "Peut ajouter sa propre Organisation"
-#: models.py:752
+#: models.py:819
msgid "Can change own Organization"
msgstr "Peut changer sa propre Organisation"
-#: models.py:753
+#: models.py:820
msgid "Can delete own Organization"
msgstr "Peut supprimer sa propre Organisation"
-#: models.py:768
+#: models.py:835
msgid "Groups"
msgstr "Groupes"
-#: models.py:772
+#: models.py:839
msgid "Person types"
msgstr "Types d'individu"
-#: models.py:777
+#: models.py:844
msgid "Mr"
msgstr "M."
-#: models.py:778
+#: models.py:845
msgid "Miss"
msgstr "Mlle"
-#: models.py:779
+#: models.py:846
msgid "Mrs"
msgstr "Mme"
-#: models.py:780
+#: models.py:847
msgid "Doctor"
msgstr "Dr."
-#: models.py:788 models.py:823
+#: models.py:855 models.py:890
msgid "Types"
msgstr "Types"
-#: models.py:791
+#: models.py:858
msgid "Is attached to"
msgstr "Est rattaché à"
-#: models.py:795
+#: models.py:862
msgid "Persons"
msgstr "Individus"
-#: models.py:797
+#: models.py:864
msgid "Can view all Person"
msgstr "Peut voir toutes les Personnes"
-#: models.py:798
+#: models.py:865
msgid "Can view own Person"
msgstr "Peut voir sa propre Personne"
-#: models.py:799
+#: models.py:866
msgid "Can add own Person"
msgstr "Peut ajouter sa propre Personne"
-#: models.py:800
+#: models.py:867
msgid "Can change own Person"
msgstr "Peut changer sa propre Personne"
-#: models.py:801
+#: models.py:868
msgid "Can delete own Person"
msgstr "Peut supprimer sa propre Personne"
-#: models.py:865
+#: models.py:932
msgid "Ishtar user"
msgstr "Utilisateur d'Ishtar"
-#: models.py:866
+#: models.py:933
msgid "Ishtar users"
msgstr "Utilisateurs d'Ishtar"
-#: models.py:898
+#: models.py:965
msgid "Author types"
msgstr "Types d'auteur"
-#: models.py:921
+#: models.py:988
msgid "Source types"
msgstr "Types de source"
-#: models.py:934 templates/ishtar/sheet_person.html:40
+#: models.py:1001 templates/ishtar/sheet_person.html:40
#: templates/ishtar/sheet_person.html:67
msgid "Ref."
msgstr "Réf."
-#: models.py:936
+#: models.py:1003
msgid "Internal reference"
msgstr "Référence interne"
-#: models.py:963
+#: models.py:1030
msgid "Surface (m²)"
msgstr "Area (m²)"
-#: models.py:964 templates/sheet_ope.html:46 templates/sheet_ope.html.py:107
+#: models.py:1031 templates/sheet_ope.html:46 templates/sheet_ope.html.py:107
msgid "Localisation"
msgstr "Localisation"
@@ -521,78 +513,78 @@ msgstr "Localisation"
msgid " (...)"
msgstr " (...)"
-#: views.py:79
+#: views.py:81
msgid "New person"
msgstr "Nouvelle personne"
-#: views.py:87
+#: views.py:89
msgid "Person modification"
msgstr "Modification d'une personne"
-#: views.py:93
+#: views.py:95
msgid "Person deletion"
msgstr "Suppresion de personne"
-#: views.py:99
+#: views.py:101
msgid "New organization"
msgstr "Nouvelle organisation"
-#: views.py:106
+#: views.py:108
msgid "Organization modification"
msgstr "Modification d'une organisation"
-#: views.py:112
+#: views.py:114
msgid "Organization deletion"
msgstr "Suppresion d'une organisation"
-#: views.py:209
+#: views.py:211
msgid "True"
msgstr "Oui"
-#: views.py:211
+#: views.py:213
msgid "False"
msgstr "Non"
-#: views.py:434 templates/base.html:75
+#: views.py:436 templates/base.html:75
#: templates/ishtar/sheet_organization.html:35
#: templates/ishtar/sheet_person.html:57 templates/ishtar/sheet_person.html:83
msgid "Details"
msgstr "Détails"
-#: views.py:644 views.py:691
+#: views.py:646 views.py:693
msgid "Operation not permitted."
msgstr "Opération non permise"
-#: views.py:646
+#: views.py:648
#, python-format
msgid "New %s"
msgstr "Nouveau %s"
-#: views.py:708 views.py:746
+#: views.py:710 views.py:766
msgid "Archaeological files"
msgstr "Dossiers archéologiques"
-#: views.py:709 views.py:750
+#: views.py:711 views.py:770
msgid "Operations"
msgstr "Opérations"
-#: views.py:711 views.py:755
+#: views.py:713 views.py:775
msgid "Context records"
msgstr "Unité d'Enregistrement"
-#: views.py:713 views.py:760
+#: views.py:715 views.py:780
msgid "Finds"
msgstr "Mobilier"
-#: widgets.py:322
+#: widgets.py:326
msgid "No results"
msgstr "Pas de résultats"
-#: widgets.py:323
+#: widgets.py:327
msgid "Loading..."
msgstr "Chargement..."
-#: widgets.py:324
+#: widgets.py:328
msgid "Remove"
msgstr "Enlever"
@@ -848,6 +840,13 @@ msgstr "Parcelles associées"
msgid "Commune"
msgstr "Commune"
+#: templates/sheet_ope.html:61 templates/sheet_ope.html.py:83
+#: templates/ishtar/sheet_person.html:39 templates/ishtar/sheet_person.html:68
+#: templates/ishtar/sheet_person.html:93
+#: templates/ishtar/dashboards/dashboard_main_detail.html:120
+msgid "Year"
+msgstr "Année"
+
#: templates/sheet_ope.html:62
msgid "Section"
msgstr "Section"
@@ -1038,7 +1037,7 @@ msgstr "Pas de document associé à cette personne"
msgid "Related to"
msgstr "Associé à"
-#: templates/ishtar/dashboards/dashboard_main.html:23
+#: templates/ishtar/dashboards/dashboard_main.html:26
msgid "Users"
msgstr "Utilisateurs"
@@ -1046,72 +1045,88 @@ msgstr "Utilisateurs"
msgid "Numbers"
msgstr "Nombre"
-#: templates/ishtar/dashboards/dashboard_main_detail.html:6
+#: templates/ishtar/dashboards/dashboard_main_detail.html:12
+msgid "Change"
+msgstr "Modifier"
+
+#: templates/ishtar/dashboards/dashboard_main_detail.html:16
msgid "Total:"
msgstr "Total :"
-#: templates/ishtar/dashboards/dashboard_main_detail.html:15
-msgid "Change"
-msgstr "Modifier"
+#: templates/ishtar/dashboards/dashboard_main_detail.html:19
+msgid "Draw rectangle on the graph to zoom. Double-click to reinitialize."
+msgstr "Dessiner un rectangle sur le graphique pour zoomer. Double-cliquer pour réinitialiser."
-#: templates/ishtar/dashboards/dashboard_main_detail.html:31
+#: templates/ishtar/dashboards/dashboard_main_detail.html:21
+msgid "Display as an image"
+msgstr "Afficher comme une image"
+
+#: templates/ishtar/dashboards/dashboard_main_detail.html:24
+msgid "Right-click on this image to save it."
+msgstr "Click droit sur l'image pour l'enregistrer."
+
+#: templates/ishtar/dashboards/dashboard_main_detail.html:39
msgid "By years"
msgstr "Par années"
-#: templates/ishtar/dashboards/dashboard_main_detail.html:33
-#: templates/ishtar/dashboards/dashboard_main_detail.html:43
+#: templates/ishtar/dashboards/dashboard_main_detail.html:41
+#: templates/ishtar/dashboards/dashboard_main_detail.html:51
msgid "Average:"
msgstr "Moyenne :"
-#: templates/ishtar/dashboards/dashboard_main_detail.html:34
-#: templates/ishtar/dashboards/dashboard_main_detail.html:44
+#: templates/ishtar/dashboards/dashboard_main_detail.html:42
+#: templates/ishtar/dashboards/dashboard_main_detail.html:52
msgid "Variance:"
msgstr "Variance :"
-#: templates/ishtar/dashboards/dashboard_main_detail.html:35
-#: templates/ishtar/dashboards/dashboard_main_detail.html:45
+#: templates/ishtar/dashboards/dashboard_main_detail.html:43
+#: templates/ishtar/dashboards/dashboard_main_detail.html:53
msgid "Standard deviation:"
msgstr "Écart-type :"
-#: templates/ishtar/dashboards/dashboard_main_detail.html:36
-#: templates/ishtar/dashboards/dashboard_main_detail.html:46
+#: templates/ishtar/dashboards/dashboard_main_detail.html:44
+#: templates/ishtar/dashboards/dashboard_main_detail.html:54
msgid "Median:"
msgstr "Médiane :"
-#: templates/ishtar/dashboards/dashboard_main_detail.html:37
-#: templates/ishtar/dashboards/dashboard_main_detail.html:47
+#: templates/ishtar/dashboards/dashboard_main_detail.html:45
+#: templates/ishtar/dashboards/dashboard_main_detail.html:55
msgid "Mode:"
msgstr "Mode :"
-#: templates/ishtar/dashboards/dashboard_main_detail.html:41
+#: templates/ishtar/dashboards/dashboard_main_detail.html:49
msgid "By operations"
msgstr "Par opérations"
-#: templates/ishtar/dashboards/dashboard_main_detail.html:50
+#: templates/ishtar/dashboards/dashboard_main_detail.html:58
msgid "Created last"
msgstr "Derniers créés"
-#: templates/ishtar/dashboards/dashboard_main_detail.html:53
+#: templates/ishtar/dashboards/dashboard_main_detail.html:61
msgid "Created"
msgstr "Créé"
-#: templates/ishtar/dashboards/dashboard_main_detail.html:57
-#: templates/ishtar/dashboards/dashboard_main_detail.html:68
+#: templates/ishtar/dashboards/dashboard_main_detail.html:65
+#: templates/ishtar/dashboards/dashboard_main_detail.html:76
msgid "Show"
msgstr "Voir"
-#: templates/ishtar/dashboards/dashboard_main_detail.html:61
+#: templates/ishtar/dashboards/dashboard_main_detail.html:69
msgid "Recent changes"
msgstr "Derniers changés"
-#: templates/ishtar/dashboards/dashboard_main_detail.html:64
+#: templates/ishtar/dashboards/dashboard_main_detail.html:72
msgid "Modified"
msgstr "Modifier"
-#: templates/ishtar/dashboards/dashboard_main_detail.html:116
+#: templates/ishtar/dashboards/dashboard_main_detail.html:108
msgid "No data for theses criteria."
msgstr "Pas de données pour ces critères."
+#: templates/ishtar/dashboards/dashboard_main_detail.html:126
+msgid "Month"
+msgstr "Mois"
+
#: templates/ishtar/dashboards/dashboard_main_detail_users.html:26
msgid "User type"
msgstr "Type d'utilisateur"
@@ -1294,7 +1309,7 @@ msgstr "La création du compte a échouée"
#: templates/registration/activation_complete.html:7
msgid "You may now login with your username and password."
-msgstr
+msgstr ""
"Vous pouvez maintenant vous identifier avec votre identifiant et votre mot "
"de passe"
diff --git a/ishtar_common/models.py b/ishtar_common/models.py
index 98f4addb7..3df557806 100644
--- a/ishtar_common/models.py
+++ b/ishtar_common/models.py
@@ -25,6 +25,7 @@ import datetime
from PIL import Image
import os
import tempfile
+import copy
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist, ValidationError
@@ -560,11 +561,53 @@ class UserDashboard:
self.types = types.annotate(number=Count('pk'))\
.order_by('person__person_types')
+class DashboardFormItem(object):
+ @classmethod
+ def get_periods(cls, slice='month', fltr={}, date_source='creation'):
+ date_var = date_source + '_date'
+ q = cls.objects.filter(**{date_var+'__isnull':False})
+ if fltr:
+ q = q.filter(**fltr)
+ if slice == 'year':
+ return [res[date_var].year for res in list(q.values(date_var
+ ).annotate(Count("id")).order_by())]
+ elif slice == 'month':
+ return [(res[date_var].year, res[date_var].month)
+ for res in list(q.values(date_var
+ ).annotate(Count("id")).order_by())]
+ return []
+
+ @classmethod
+ def get_by_year(cls, year, fltr={}, date_source='creation'):
+ date_var = date_source + '_date'
+ q = cls.objects.filter(**{date_var+'__isnull':False})
+ if fltr:
+ q = q.filter(**fltr)
+ return q.filter(**{date_var+'__year':year}).distinct('pk')
+
+ @classmethod
+ def get_by_month(cls, year, month, fltr={}, date_source='creation'):
+ date_var = date_source + '_date'
+ q = cls.objects.filter(**{date_var+'__isnull':False})
+ if fltr:
+ q = q.filter(**fltr)
+ q = q.filter(**{date_var+'__year':year, date_var+'__month':month})
+ return q.distinct('pk')
+
+ @classmethod
+ def get_total_number(cls, fltr={}):
+ q = cls.objects
+ if fltr:
+ q = q.filter(**fltr)
+ return q.distinct('pk').count()
+
class Dashboard:
- def __init__(self, model, slice='year', date_source=None, fltr={}):
+ def __init__(self, model, slice='year', date_source=None, show_detail=None,
+ fltr={}):
# don't provide date_source if it is not relevant
self.model = model
self.total_number = model.get_total_number(fltr)
+ self.show_detail = show_detail
history_model = self.model.history.model
# last edited - created
self.recents, self.lasts = [], []
@@ -587,31 +630,50 @@ class Dashboard:
obj.history_date = idx['hd']
last_lst.append(obj)
# years
- base_kwargs = {'fltr':fltr}
+ base_kwargs = {'fltr':fltr.copy()}
if date_source:
base_kwargs['date_source'] = date_source
- periods_kwargs = base_kwargs.copy()
+ periods_kwargs = copy.deepcopy(base_kwargs)
periods_kwargs['slice'] = slice
self.periods = model.get_periods(**periods_kwargs)
self.periods = list(set(self.periods))
self.periods.sort()
if not self.total_number or not self.periods:
return
+ kwargs_num = copy.deepcopy(base_kwargs)
+ self.serie_labels = [_(u"Total")]
# numbers
if slice == 'year':
- self.values = [('year', _(u"Year"), reversed(self.periods))]
- self.numbers = [model.get_by_year(year, **base_kwargs).count()
+ self.values = [('year', "",
+ list(reversed(self.periods)))]
+ self.numbers = [model.get_by_year(year, **kwargs_num).count()
for year in self.periods]
- self.values += [('number', _(u"Number"), reversed(self.numbers))]
+ self.values += [('number', _(u"Number"),
+ list(reversed(self.numbers)))]
if slice == 'month':
- self.numbers = [model.get_by_month(*period, **base_kwargs).count()
- for period in self.periods]
- periods = reversed(self.periods)
- self.periods = ["%d-%s-01" % (period[0], ('0'+str(period[1]))
- if len(str(period[1])) == 1 else period[1])
- for period in periods]
- self.values = [('month', _(u"Month"), self.periods)]
- self.values += [('number', _(u"Number"), reversed(self.numbers))]
+ periods = list(reversed(self.periods))
+ self.periods = ["%d-%s-01" % (p[0], ('0'+str(p[1]))
+ if len(str(p[1])) == 1 else p[1])
+ for p in periods]
+ self.values = [('month', "", self.periods)]
+ if show_detail:
+ for dpt in settings.ISHTAR_DPTS:
+ self.serie_labels.append(unicode(dpt))
+ idx = 'number_' + unicode(dpt)
+ kwargs_num['fltr']["towns__numero_insee__startswith"] = \
+ unicode(dpt)
+ numbers = [model.get_by_month(*p.split('-')[:2],
+ **kwargs_num).count()
+ for p in self.periods]
+ self.values += [(idx, dpt, list(numbers))]
+ # put "Total" at the end
+ self.serie_labels.append(self.serie_labels.pop(0))
+ kwargs_num = base_kwargs.copy()
+ self.numbers = [model.get_by_month(*p.split('-')[:2],
+ **kwargs_num).count()
+ for p in self.periods]
+ self.values += [('number', _(u"Total"),
+ list(self.numbers))]
# calculate
self.average = self.get_average()
self.variance = self.get_variance()
diff --git a/ishtar_common/static/media/style.css b/ishtar_common/static/media/style.css
index 341308926..3c2c429b1 100644
--- a/ishtar_common/static/media/style.css
+++ b/ishtar_common/static/media/style.css
@@ -560,6 +560,7 @@ table.confirm tr.spacer td:last-child{
.ui-tabs .ui-tabs-nav li.ui-tabs-active a{
background-color:#fff;
+ color:#666;
}
.sheet{
@@ -669,6 +670,13 @@ table.confirm tr.spacer td:last-child{
padding:0.5em 1em;
}
+.chart-img{
+ display:none;
+}
+
+.chart-img-form{
+ margin-top:1em;
+}
#window table th, .dashboard table.resume th{
background-color:#922;
@@ -783,8 +791,7 @@ table.confirm tr.spacer td:last-child{
margin:0.3em;
}
-p.alert{
- color:#D14;
+p.info-box, p.alert{
display:block;
font-style:italic;
width:670px;
@@ -794,6 +801,11 @@ p.alert{
-moz-border-radius:8px;
-webkit-border-radius:8px;
border-radius:8px;
+ font-size: 0.9em;
+}
+
+p.alert{
+ color:#D14;
background-image:url(images/red_flag.png);
background-repeat:no-repeat;
background-position:left center;
diff --git a/ishtar_common/templates/ishtar/dashboards/dashboard_main.html b/ishtar_common/templates/ishtar/dashboards/dashboard_main.html
index 8822875b5..868f8a5c3 100644
--- a/ishtar_common/templates/ishtar/dashboards/dashboard_main.html
+++ b/ishtar_common/templates/ishtar/dashboards/dashboard_main.html
@@ -6,9 +6,12 @@
<script language="javascript" type="text/javascript" src="{{STATIC_URL}}js/jqplot/jquery.jqplot.min.js"></script>
<script language="javascript" type="text/javascript" src="{{STATIC_URL}}js/jqplot/plugins/jqplot.canvasTextRenderer.min.js"></script>
<script language="javascript" type="text/javascript" src="{{STATIC_URL}}js/jqplot/plugins/jqplot.canvasAxisLabelRenderer.min.js"></script>
+<script language="javascript" type="text/javascript" src="{{STATIC_URL}}js/jqplot/plugins/jqplot.canvasAxisTickRenderer.min.js"></script>
<script language="javascript" type="text/javascript" src="{{STATIC_URL}}js/jqplot/plugins/jqplot.highlighter.min.js"></script>
<script language="javascript" type="text/javascript" src="{{STATIC_URL}}js/jqplot/plugins/jqplot.pieRenderer.min.js"></script>
<script language="javascript" type="text/javascript" src="{{STATIC_URL}}js/jqplot/plugins/jqplot.dateAxisRenderer.min.js"></script>
+<script language="javascript" type="text/javascript" src="{{STATIC_URL}}js/jqplot/plugins/jqplot.cursor.min.js"></script>
+<script language="javascript" type="text/javascript" src="{{STATIC_URL}}js/jqplot/plugins/jqplot.cursor.min.js"></script>
<link rel="stylesheet" href="{{STATIC_URL}}js/jqplot/jquery.jqplot.min.css" />
{% endblock %}
{% block content %}
diff --git a/ishtar_common/templates/ishtar/dashboards/dashboard_main_detail.html b/ishtar_common/templates/ishtar/dashboards/dashboard_main_detail.html
index 610457ae3..87ce5c528 100644
--- a/ishtar_common/templates/ishtar/dashboards/dashboard_main_detail.html
+++ b/ishtar_common/templates/ishtar/dashboards/dashboard_main_detail.html
@@ -1,11 +1,8 @@
-{% load i18n %}
+{% load i18n date_formating %}
{% load url from future %}
<div class='dashboard' id="{{unique_id}}-tab">
<div>
<h4>{% trans "Numbers" %}</h4>
- <p><strong>{% trans "Total:" %}</strong> {{dashboard.total_number}}</p>
- <div class='table'>
- <div id="chart_{{unique_id}}" style="height:400px; width:700px;"></div>
{% if form %}
<div class='form'>
<form method='post' action="{% url 'dashboard-main-detail' item_name %}" id='{{unique_id}}_form'>
@@ -16,15 +13,27 @@
</form>
</div>
{% endif %}
- {% comment %}
- <table>
+ <p><strong>{% trans "Total:" %}</strong> {{dashboard.total_number}}</p>
+ <div class='table'>
+ <div id="chart_{{unique_id}}" style="height:400px; width:700px;"></div>
+ <p class='info-box'>{% trans 'Draw rectangle on the graph to zoom. Double-click to reinitialize.' %}</p>
+ <div class='form chart-img-form'>
+ <button id="chart_img_display_{{unique_id}}" class='submit'>{% trans "Display as an image" %}</button>
+ <div id="chart_img_{{unique_id}}" class='chart-img'>
+ <div id="img_{{unique_id}}"></div>
+ <p class='info-box'>{% trans 'Right-click on this image to save it.' %}</p>
+ </div>
+ </div>
+ </div>
+ <div class='table'>
+ <table class='resume'>
{% for idx, lbl, values in dashboard.values %}
<tr class='idx {% if forloop.counter0|divisibleby:"2" %}even{%else%}odd{%endif%}'>
<th>{{lbl}}</th>
- {% for value in values %}<td>{{value}}</td>{% endfor%}
+ {% for value in values reversed %}{% if forloop.parentloop.counter0 %}<td>{% else %}<th>{%endif%}{{value|date_formating }}{% if forloop.parentloop.counter0 %}</td>{% else %}</th>{%endif%}{% endfor%}
</tr>
{% endfor%}
- </table>{% endcomment %}
+ </table>
</div>
{% if dashboard.periods %}
<h4>{% trans "By years" %}</h4>
@@ -71,23 +80,41 @@
</div>
<script language="javascript" type="text/javascript">
$(document).ready(function(){
-var values_{{unique_id}} = [];
+{% for idx, lbl, values in dashboard.values %} {% if forloop.counter0 > 0 %} var values_{{forloop.counter0}}_{{unique_id}} = []; {% for idx, lbl, values in dashboard.values %} {% for value in values %} {% if forloop.parentloop.counter0 == 0 %} values_{{forloop.parentloop.parentloop.counter0}}_{{unique_id}}.push([{{VALUE_QUOTE|safe}}{{value}}{{VALUE_QUOTE|safe}}, 0]); {% elif forloop.parentloop.parentloop.counter0 == forloop.parentloop.counter0 %} values_{{forloop.parentloop.parentloop.counter0}}_{{unique_id}}[{{forloop.counter0}}][1] = {{value}}; {% endif %} {% endfor%} {% endfor%} {% endif %} {% endfor %}
-{% for idx, lbl, values in dashboard.values %} {% for value in values %}{% ifequal forloop.parentloop.counter0 0 %}
-values_{{unique_id}}.push([{{VALUE_QUOTE|safe}}{{value}}{{VALUE_QUOTE|safe}}, 0]);
-{% else %}values_{{unique_id}}[{{forloop.counter0}}][1] = {{value}};{% endifequal %}{% endfor%}{% endfor%}
+{% comment %}
+# less compact version
+{% for idx, lbl, values in dashboard.values %}
+ {% if forloop.counter0 > 0 %}
+ {% for idx, lbl, values in dashboard.values %}
+ {% for value in values %}
+ {% if forloop.parentloop.counter0 == 0 %}
+ values_{{forloop.parentloop.counter0}}_{{unique_id}}.push([{{VALUE_QUOTE|safe}}{{value}}{{VALUE_QUOTE|safe}}, 0]);
+ {% elif forloop.parentloop.counter0 == forloop.counter0 %}
+ values_{{forloop.counter0}}_{{unique_id}}[{{forloop.counter0}}][1] = {{value}};
+ {% endif %}
+ {% endfor%}
+ {% endfor%}
+ {% endif %}
+{% endfor %}
+{% endcomment %}
+
+
+if (typeof values_1_{{unique_id}} === 'undefined'
+ || values_1_{{unique_id}}.length == 0){
-if (values_{{unique_id}}.length > 0){
+$('#chart_img_{{unique_id}}').hide();
+$('#chart_{{unique_id}}').html("<p class='alert'>{% trans 'No data for theses criteria.' %}</p>");
+} else {
var showmarker = false;
-if (values_{{unique_id}}.length < 25){
+if (values_1_{{unique_id}}.length < 25){
var showmarker = true;
}
var plot_{{unique_id}} = $.jqplot('chart_{{unique_id}}',
- [values_{{unique_id}}], {
- series:[{showMarker:showmarker}],
+ [{% for idx, lbl, values in dashboard.values %}{% if forloop.counter0 > 0 %} {% if forloop.counter0 > 1 %}, {% endif%} values_{{forloop.counter0}}_{{unique_id}} {% endif %} {% endfor%}], {
axes:{ {%ifequal slicing 'year'%}
xaxis:{
label:'{% trans "Year" %}',
@@ -98,7 +125,11 @@ var plot_{{unique_id}} = $.jqplot('chart_{{unique_id}}',
xaxis:{
label:'{% trans "Month" %}',
renderer:$.jqplot.DateAxisRenderer,
- tickOptions:{formatString:'%b %Y'},
+ tickRenderer:$.jqplot.CanvasAxisTickRenderer,
+ tickOptions:{
+ formatString:'%b %Y',
+ angle:-25
+ }
},{%endifequal%}
yaxis:{
label:'{% trans "Number"%}',
@@ -108,11 +139,28 @@ var plot_{{unique_id}} = $.jqplot('chart_{{unique_id}}',
highlighter: {
show: true,
sizeAdjust: 7.5
- }
+ },
+ series:[{% for label in dashboard.serie_labels %}
+ {%if forloop.counter0%}, {% endif %}{label:"{{label}}", showmarker:showmarker}{% endfor %}
+ ],
+ cursor:{
+ show: true,
+ zoom:true,
+ showTooltip:false
+ },
+ legend: { show:true, location: 'nw' }
+ });
+
+ $('#chart_img_display_{{unique_id}}').click(function(){
+ $('#chart_img_{{unique_id}}').hide();
+ $('#img_{{unique_id}}').html(
+ $('<img/>').attr(
+ 'src', $('#chart_{{unique_id}}').jqplotToImageStr({})
+ )
+ );
+ $('#chart_img_{{unique_id}}').show('slow');
});
-} else {
-$('#chart_{{unique_id}}').html("<p class='alert'>{% trans 'No data for theses criteria.' %}</p");
}
$('#search_{{unique_id}}').click(function (){
@@ -124,9 +172,9 @@ $('#search_{{unique_id}}').click(function (){
return false;
});
-{% ifequal item_name 'files' %}
-load_jquerydate_after();
-load_jquerydate_before();
-{% endifequal %}
+{% if item_name == 'files' or item_name == "operations"%}
+load_jquerydate_{{item_name}}_after();
+load_jquerydate_{{item_name}}_before();
+{% endif %}
});
</script>
diff --git a/ishtar_common/templatetags/date_formating.py b/ishtar_common/templatetags/date_formating.py
new file mode 100644
index 000000000..eb81cf52c
--- /dev/null
+++ b/ishtar_common/templatetags/date_formating.py
@@ -0,0 +1,19 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from datetime import datetime
+
+from django.template import Library
+from django.utils.translation import ugettext as _
+
+register = Library()
+
+@register.filter
+def date_formating(value):
+ try:
+ d = datetime.strptime(unicode(value), '%Y-%m-%d')
+ return _(d.strftime("%B")).capitalize() + u" %d" % d.year
+ except ValueError:
+ # could be passed to non date value: on error return value
+ return value
+
diff --git a/ishtar_common/views.py b/ishtar_common/views.py
index d20b8b2af..889bd3893 100644
--- a/ishtar_common/views.py
+++ b/ishtar_common/views.py
@@ -50,6 +50,8 @@ if settings.XHTML2ODT_PATH:
from menus import menu
+from archaeological_operations.forms import DashboardForm as DashboardFormOpe
+
from ishtar_common.forms import FinalForm, FinalDeleteForm
from ishtar_common import forms_common as forms
from ishtar_common import wizards
@@ -720,6 +722,8 @@ if 'archaeological_files' in settings.INSTALLED_APPS:
from archaeological_files.forms import DashboardForm as DashboardFormFile
DASHBOARD_FORMS['files'] = DashboardFormFile
+DASHBOARD_FORMS['operations'] = DashboardFormOpe
+
def dashboard_main_detail(request, item_name):
"""
Specific tab of the main dashboard
@@ -730,7 +734,11 @@ def dashboard_main_detail(request, item_name):
'ishtar/dashboards/dashboard_main_detail_users.html',
dct, context_instance=RequestContext(request))
form = None
- slicing, date_source, fltr = 'year', None, {}
+ slicing, date_source, fltr, show_detail = 'year', None, {}, False
+ if (item_name == 'files' and \
+ 'archaeological_files' in settings.INSTALLED_APPS) \
+ or item_name == 'operations':
+ slicing = 'month'
if item_name in DASHBOARD_FORMS:
if request.method == 'POST':
form = DASHBOARD_FORMS[item_name](request.POST)
@@ -739,22 +747,28 @@ def dashboard_main_detail(request, item_name):
fltr = form.get_filter()
if hasattr(form, 'get_date_source'):
date_source = form.get_date_source()
+ if hasattr(form, 'get_show_detail'):
+ show_detail = form.get_show_detail()
else:
form = DASHBOARD_FORMS[item_name]()
lbl, dashboard = None, None
- if item_name == 'files' and \
- 'archaeological_files' in settings.INSTALLED_APPS:
- from archaeological_files.models import File
- dashboard_kwargs = {'slice':slicing, 'fltr':fltr,}
+ if (item_name == 'files' and \
+ 'archaeological_files' in settings.INSTALLED_APPS) \
+ or item_name == 'operations':
+ dashboard_kwargs = {'slice':slicing, 'fltr':fltr,
+ 'show_detail':show_detail}
# date_source is only relevant when the form has set one
if date_source:
dashboard_kwargs['date_source'] = date_source
+ if item_name == 'files' and \
+ 'archaeological_files' in settings.INSTALLED_APPS:
+ from archaeological_files.models import File
lbl, dashboard = (_(u"Archaeological files"),
models.Dashboard(File, **dashboard_kwargs))
if item_name == 'operations':
from archaeological_operations.models import Operation
- lbl, dashboard = (_(u"Operations"), models.Dashboard(Operation,
- slice=slicing, fltr=fltr))
+ lbl, dashboard = (_(u"Operations"),
+ models.Dashboard(Operation, **dashboard_kwargs))
if item_name == 'contextrecords' and \
'archaeological_context_records' in settings.INSTALLED_APPS:
from archaeological_context_records.models import ContextRecord