summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2016-09-09 00:41:57 +0200
committerÉtienne Loks <etienne.loks@iggdrasil.net>2016-09-09 00:41:57 +0200
commit5230a8e0a06a5d67d6c13f2359bc51be07b4fb5a (patch)
tree5df1cfe674759003b1599f7334448f9c7f00637d
parent06f8d8f45d5c08ec9ed17cee4836f3311703e6df (diff)
downloadIshtar-5230a8e0a06a5d67d6c13f2359bc51be07b4fb5a.tar.bz2
Ishtar-5230a8e0a06a5d67d6c13f2359bc51be07b4fb5a.zip
Shortcut menu: menu is now dynamic - selected items filter dependant items (refs #2996) - can now pin items from sheet (refs #3078)
-rw-r--r--archaeological_context_records/models.py10
-rw-r--r--archaeological_context_records/templates/ishtar/sheet_contextrecord.html2
-rw-r--r--archaeological_files/models.py3
-rw-r--r--archaeological_files/templates/ishtar/sheet_file.html2
-rw-r--r--archaeological_finds/models.py9
-rw-r--r--archaeological_finds/templates/ishtar/sheet_find.html2
-rw-r--r--archaeological_operations/models.py8
-rw-r--r--archaeological_operations/templates/ishtar/sheet_operation.html2
-rw-r--r--ishtar_common/context_processors.py35
-rw-r--r--ishtar_common/models.py8
-rw-r--r--ishtar_common/static/js/ishtar.js58
-rw-r--r--ishtar_common/static/media/style.css34
-rw-r--r--ishtar_common/templates/base.html35
-rw-r--r--ishtar_common/templates/ishtar/blocks/shortcut_menu.html24
-rw-r--r--ishtar_common/templates/ishtar/blocks/window_nav.html7
-rw-r--r--ishtar_common/templatetags/window_header.py8
-rw-r--r--ishtar_common/urls.py3
-rw-r--r--ishtar_common/views.py123
18 files changed, 285 insertions, 88 deletions
diff --git a/archaeological_context_records/models.py b/archaeological_context_records/models.py
index a98f7792a..fa2d5b430 100644
--- a/archaeological_context_records/models.py
+++ b/archaeological_context_records/models.py
@@ -108,6 +108,7 @@ class IdentificationType(GeneralType):
class ContextRecord(BaseHistorizedItem, ImageModel, OwnPerms, ShortMenuItem):
SHOW_URL = 'show-contextrecord'
+ SLUG = 'contextrecord'
TABLE_COLS = ['parcel.town', 'operation.year',
'operation.operation_code',
'label', 'unit']
@@ -220,6 +221,15 @@ class ContextRecord(BaseHistorizedItem, ImageModel, OwnPerms, ShortMenuItem):
Q(operation__in_charge=user.ishtaruser.person) |\
Q(history_creator=user)
+ @classmethod
+ def get_owns(cls, user, menu_filtr=None):
+ extra_query = {}
+ if menu_filtr:
+ extra_query = {'operation': menu_filtr}
+ owns = super(ContextRecord, cls).get_owns(user,
+ extra_query=extra_query)
+ return sorted(owns, key=lambda x: x.cached_label)
+
def full_label(self):
return unicode(self)
if not self.operation:
diff --git a/archaeological_context_records/templates/ishtar/sheet_contextrecord.html b/archaeological_context_records/templates/ishtar/sheet_contextrecord.html
index 2c2bf98fe..bd883ac0b 100644
--- a/archaeological_context_records/templates/ishtar/sheet_contextrecord.html
+++ b/archaeological_context_records/templates/ishtar/sheet_contextrecord.html
@@ -4,7 +4,7 @@
{% block head_title %}{% trans "Context Record" %}{% endblock %}
{% block content %}
-{% window_nav item window_id 'show-contextrecord' 'record_modify' 'show-historized-contextrecord' 'revert-contextrecord' previous next %}
+{% window_nav item window_id 'show-contextrecord' 'record_modify' 'show-historized-contextrecord' 'revert-contextrecord' previous next 1 %}
{% if item.image %}
<a href='{{item.image.url}}' rel="prettyPhoto" title="{{item.label}}" class='photo'><img src='{{item.thumbnail.url}}'/></a>
diff --git a/archaeological_files/models.py b/archaeological_files/models.py
index eaa9d832e..740ae9a71 100644
--- a/archaeological_files/models.py
+++ b/archaeological_files/models.py
@@ -74,6 +74,7 @@ class File(ClosedItem, BaseHistorizedItem, OwnPerms, ValueGetter,
TABLE_COLS = ['numeric_reference', 'year', 'internal_reference',
'file_type', 'saisine_type', 'towns', ]
SHOW_URL = 'show-file'
+ SLUG = 'file'
year = models.IntegerField(_(u"Year"),
default=lambda: datetime.datetime.now().year)
numeric_reference = models.IntegerField(
@@ -333,7 +334,7 @@ class File(ClosedItem, BaseHistorizedItem, OwnPerms, ValueGetter,
return cls
@classmethod
- def get_owns(cls, user):
+ def get_owns(cls, user, menu_filtr=None):
owns = super(File, cls).get_owns(user)
return sorted(owns, key=lambda x: x.cached_label)
diff --git a/archaeological_files/templates/ishtar/sheet_file.html b/archaeological_files/templates/ishtar/sheet_file.html
index 5165a0425..211d2b181 100644
--- a/archaeological_files/templates/ishtar/sheet_file.html
+++ b/archaeological_files/templates/ishtar/sheet_file.html
@@ -8,7 +8,7 @@
{% if can_add_operation %}
{% window_file_nav item window_id previous next %}
{% else %}
-{% window_nav item window_id 'show-file' 'file_modify' 'show-historized-file' 'revert-file' previous next %}
+{% window_nav item window_id 'show-file' 'file_modify' 'show-historized-file' 'revert-file' previous next 1 %}
{% endif %}
<h3>{% trans "General"%}</h3>
diff --git a/archaeological_finds/models.py b/archaeological_finds/models.py
index 15ed32120..0f069e1d8 100644
--- a/archaeological_finds/models.py
+++ b/archaeological_finds/models.py
@@ -275,6 +275,7 @@ class FindBasket(Basket):
class Find(BaseHistorizedItem, ImageModel, OwnPerms, ShortMenuItem):
CHECK_DICT = dict(CHECK_CHOICES)
SHOW_URL = 'show-find'
+ SLUG = 'find'
TABLE_COLS = ['label', 'material_types', 'datings.period',
'base_finds.context_record.parcel.town',
'base_finds.context_record.operation.year',
@@ -564,6 +565,14 @@ class Find(BaseHistorizedItem, ImageModel, OwnPerms, ShortMenuItem):
ishtaruser.person) |\
Q(history_creator=user)
+ @classmethod
+ def get_owns(cls, user, menu_filtr=None):
+ extra_query = {}
+ if menu_filtr:
+ extra_query = {'base_finds__context_record': menu_filtr}
+ owns = super(Find, cls).get_owns(user, extra_query=extra_query)
+ return sorted(owns, key=lambda x: x.cached_label)
+
def save(self, *args, **kwargs):
super(Find, self).save(*args, **kwargs)
diff --git a/archaeological_finds/templates/ishtar/sheet_find.html b/archaeological_finds/templates/ishtar/sheet_find.html
index c867b46ee..fbd7cec1a 100644
--- a/archaeological_finds/templates/ishtar/sheet_find.html
+++ b/archaeological_finds/templates/ishtar/sheet_find.html
@@ -4,7 +4,7 @@
{% block head_title %}{% trans "Find" %}{% endblock %}
{% block content %}
-{% window_nav item window_id 'show-find' 'find_modify' 'show-historized-find' 'revert-find' previous next %}
+{% window_nav item window_id 'show-find' 'find_modify' 'show-historized-find' 'revert-find' previous next 1 %}
{% if item.image %}
<a href='{{item.image.url}}' rel="prettyPhoto" title="{{item.label}}" class='photo'><img src='{{item.thumbnail.url}}'/></a>
diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py
index f5a1ca8b0..701ae4593 100644
--- a/archaeological_operations/models.py
+++ b/archaeological_operations/models.py
@@ -174,6 +174,7 @@ class Operation(ClosedItem, BaseHistorizedItem, ImageModel, OwnPerms,
'start_date', 'excavation_end_date']
TABLE_COLS.insert(4, 'associated_file_short_label')
IMAGE_PREFIX = 'operations/'
+ SLUG = 'operation'
creation_date = models.DateField(_(u"Creation date"),
default=datetime.date.today)
end_date = models.DateField(_(u"Closing date"), null=True, blank=True)
@@ -298,8 +299,11 @@ class Operation(ClosedItem, BaseHistorizedItem, ImageModel, OwnPerms,
ordering = ('cached_label',)
@classmethod
- def get_owns(cls, user):
- owns = super(Operation, cls).get_owns(user)
+ def get_owns(cls, user, menu_filtr=None):
+ extra_query = {}
+ if menu_filtr:
+ extra_query = {'associated_file': menu_filtr}
+ owns = super(Operation, cls).get_owns(user, extra_query=extra_query)
# owns = owns.annotate(null_count=Count('operation_code'))
# return owns.order_by("common_name", "-year", "operation_code")
return sorted(owns, key=lambda x: x.cached_label)
diff --git a/archaeological_operations/templates/ishtar/sheet_operation.html b/archaeological_operations/templates/ishtar/sheet_operation.html
index 2f6dbdf4c..6b2030f5e 100644
--- a/archaeological_operations/templates/ishtar/sheet_operation.html
+++ b/archaeological_operations/templates/ishtar/sheet_operation.html
@@ -4,7 +4,7 @@
{% block head_title %}{% trans "Operation" %}{% endblock %}
{% block content %}
-{% window_nav item window_id 'show-operation' 'operation_modify' 'show-historized-operation' 'revert-operation' previous next %}
+{% window_nav item window_id 'show-operation' 'operation_modify' 'show-historized-operation' 'revert-operation' previous next 1 %}
{% if item.image %}
<a href='{{item.image.url}}' rel="prettyPhoto" title="{{item.label}}" class='photo'><img src='{{item.thumbnail.url}}'/></a>
diff --git a/ishtar_common/context_processors.py b/ishtar_common/context_processors.py
index f8a4a0f95..bb12a401d 100644
--- a/ishtar_common/context_processors.py
+++ b/ishtar_common/context_processors.py
@@ -19,29 +19,11 @@
from django.conf import settings
from django.contrib.sites.models import Site
-from django.utils.translation import ugettext_lazy as _
from ishtar_common.version import VERSION
-from ishtar_common.utils import shortify
from menus import Menu
-from ishtar_common.models import get_current_profile
-from archaeological_operations.models import Operation
-from archaeological_files.models import File
-from archaeological_context_records.models import ContextRecord
-from archaeological_finds.models import Find
-
-profile = get_current_profile()
-CURRENT_ITEMS = []
-if profile.files:
- CURRENT_ITEMS.append((_(u"Archaeological file"), File))
-CURRENT_ITEMS.append((_(u"Operation"), Operation))
-if profile.context_record:
- CURRENT_ITEMS.append((_(u"Context record"), ContextRecord))
-if profile.find:
- CURRENT_ITEMS.append((_(u"Find"), Find))
-
def get_base_context(request):
dct = {'URL_PATH': settings.URL_PATH}
@@ -74,21 +56,4 @@ def get_base_context(request):
dct['VERSION'] = u".".join([unicode(n) for n in VERSION])
if settings.EXTRA_VERSION:
dct['VERSION'] += unicode(settings.EXTRA_VERSION)
- 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 model.get_owns(request.user):
- pk = unicode(item.pk)
- if item.IS_BASKET:
- pk = "basket-" + pk
- selected = pk == current
- if selected:
- cls = item.get_short_menu_class()
- items.append((pk, shortify(unicode(item), 60),
- selected, item.get_short_menu_class()))
- if 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 6150ab0aa..9e48df8d2 100644
--- a/ishtar_common/models.py
+++ b/ishtar_common/models.py
@@ -235,7 +235,7 @@ class OwnPerms:
return cls.objects.filter(query).count()
@classmethod
- def get_owns(cls, user):
+ def get_owns(cls, user, extra_query={}):
"""
Get Own items
"""
@@ -249,8 +249,10 @@ class OwnPerms:
query = cls.get_query_owns(user)
if not query:
return cls.objects.filter(pk__isnull=True)
- items += list(
- cls.objects.filter(query).order_by(*cls._meta.ordering).all())
+ q = cls.objects.filter(query)
+ if extra_query:
+ q = q.filter(**extra_query)
+ items += list(q.order_by(*cls._meta.ordering).all())
return items
diff --git a/ishtar_common/static/js/ishtar.js b/ishtar_common/static/js/ishtar.js
index 4d82cb238..fecefe0a9 100644
--- a/ishtar_common/static/js/ishtar.js
+++ b/ishtar_common/static/js/ishtar.js
@@ -1,5 +1,5 @@
-
/* CSRFToken management */
+
$.ajaxSetup({
beforeSend: function(xhr, settings) {
function getCookie(name) {
@@ -23,6 +23,8 @@ beforeSend: function(xhr, settings) {
}
}});
+var shortcut_url = '';
+
function manage_async_link(event){
event.preventDefault();
var url = $(this).attr('href');
@@ -36,30 +38,66 @@ function manage_async_link(event){
function get_next_table_id(){}
function get_previous_table_id(){}
-$(document).ready(function(){
- $("#main_menu > ul > li > ul").hide();
- $("#main_menu ul ul .selected").parents().show();
- var items = new Array('file', 'operation');
+function init_shortcut_menu(html){
+ $("#progress").hide();
+ $("#context_menu").html(html);
+ $(".chosen-select").chosen();
$("#current_file").change(function(){
$.post('/' + url_path + 'update-current-item/',
- {item:'file', value:$("#current_file").val()}
+ {item:'file', value:$("#current_file").val()},
+ load_shortcut_menu
);
});
$("#current_operation").change(function(){
$.post('/' + url_path + 'update-current-item/',
- {item:'operation', value:$("#current_operation").val()}
+ {item:'operation', value:$("#current_operation").val()},
+ load_shortcut_menu
);
});
$("#current_contextrecord").change(function(){
$.post('/' + url_path + 'update-current-item/',
- {item:'contextrecord', value:$("#current_contextrecord").val()}
+ {item:'contextrecord', value:$("#current_contextrecord").val()},
+ load_shortcut_menu
);
});
$("#current_find").change(function(){
$.post('/' + url_path + 'update-current-item/',
- {item:'find', value:$("#current_find").val()}
+ {item:'find', value:$("#current_find").val()},
+ load_shortcut_menu
);
});
+}
+
+function display_info(msg){
+ $('#message .information .content').html(msg);
+ $('#message').fadeIn('slow');
+ $('#message .information').fadeIn('slow');
+ setTimeout(
+ function(){
+ $('#message .information').fadeOut('slow');
+ $('#message').fadeOut('slow');
+ }, 5000);
+}
+
+function load_shortcut_menu(){
+ if (!shortcut_url) return;
+ $("#progress").show();
+ $.ajax({
+ url: shortcut_url,
+ cache: false,
+ success:function(html){
+ init_shortcut_menu(html);
+ },
+ error:function(XMLHttpRequest, textStatus, errorThrows){
+ $("#progress").hide();
+ }
+ });
+}
+
+$(document).ready(function(){
+ $("#main_menu > ul > li > ul").hide();
+ $("#main_menu ul ul .selected").parents().show();
+ var items = new Array('file', 'operation');
if ($(document).height() < 1.5*$(window).height()){
$('#to_bottom_arrow').hide();
$('#to_top_arrow').hide();
@@ -67,6 +105,7 @@ $(document).ready(function(){
$('#language_selector').change(function(){
$('#language_form').submit();
});
+ load_shortcut_menu();
if ($.isFunction($(".prettyPhoto a").prettyPhoto)){
$(".prettyPhoto a").prettyPhoto({'social_tools':''});
}
@@ -74,6 +113,7 @@ $(document).ready(function(){
$(this).attr('class', $(this).children("option:selected").attr('class'));
});
$("a.async-link").click(manage_async_link);
+ $(".chosen-select").chosen();
});
$(document).on("click", '#to_bottom_arrow', function(){
diff --git a/ishtar_common/static/media/style.css b/ishtar_common/static/media/style.css
index ebd13d4b7..bff3ef473 100644
--- a/ishtar_common/static/media/style.css
+++ b/ishtar_common/static/media/style.css
@@ -21,6 +21,8 @@ div.form, ul.form {
}
/* color */
+
+.pin-action,
#window hr,
#context_menu .red,
a, a.remove {
@@ -46,6 +48,7 @@ a.add-button,
color:#000;
}
+.chosen-container,
#context_menu .green,
#context_menu .red,
#context_menu .orange,
@@ -248,6 +251,13 @@ button.ui-widget-header:hover {
z-index: 100 !important;
}
+.chosen-container-active.chosen-with-drop .chosen-single,
+.chosen-container-single .chosen-single{
+ background: none;
+ background-color: #fff;
+ border-radius:4px;
+}
+
textarea,
input[type=text],
input[type=password],
@@ -293,6 +303,26 @@ div.nav-button{
border: 0 solid transparent;
}
+#message,
+#message div{
+ display: none;
+}
+
+#message {
+ z-index: 42200;
+ position: absolute;
+ top: 5px;
+ right: 5px;
+ background: #fff;
+ padding: 0.5em 1em;
+ border: 1px solid;
+ border-radius: 3px;
+}
+
+#message span{
+ padding: 0 1em;
+}
+
#to_bottom_arrow{
bottom:80px;
}
@@ -731,6 +761,10 @@ ul.form .help_text{
font-style: normal;
}
+.pin-action:hover{
+ cursor:pointer;
+}
+
.autocomplete{
width:350px;
}
diff --git a/ishtar_common/templates/base.html b/ishtar_common/templates/base.html
index 47ea61594..703644a35 100644
--- a/ishtar_common/templates/base.html
+++ b/ishtar_common/templates/base.html
@@ -14,12 +14,14 @@
<script language="javascript" type="text/javascript" src="{{JQUERY_URL}}?ver={{VERSION}}"></script>
<script language="javascript" type="text/javascript" src="{{JQUERY_UI_URL}}jquery-ui.js?ver={{VERSION}}"></script>
<script language="javascript" type="text/javascript" src="{{JQUERY_UI_URL}}ui/i18n/jquery.ui.datepicker-{{COUNTRY}}.js?ver={{VERSION}}"></script>
+ <script language="javascript" type="text/javascript" src="{{STATIC_URL}}js/chosen/chosen.jquery.min.js?ver={{VERSION}}"></script>
<script language="javascript" type="text/javascript" src="{{STATIC_URL}}/js/prettyPhoto/js/jquery.prettyPhoto.js?ver={{VERSION}}"></script>
<script language="javascript" type="text/javascript" src="{{STATIC_URL}}js/i18n/grid.locale-{{COUNTRY}}.js?ver={{VERSION}}"></script>
<script language="javascript" type="text/javascript" src="{{STATIC_URL}}js/jquery.jqGrid.min.js?ver={{VERSION}}"></script>
<script language="javascript" type="text/javascript" src="{{STATIC_URL}}js/grid.tbltogrid.js?ver={{VERSION}}"></script>
<script language="javascript" type="text/javascript" src="{{STATIC_URL}}/js/ishtar.js?ver={{VERSION}}"></script>
<link type="text/css" href="{{JQUERY_UI_URL}}jquery-ui.css?ver={{VERSION}}" rel="stylesheet" />
+ <link type="text/css" href="{{STATIC_URL}}js/chosen/chosen.min.css?ver={{VERSION}}" rel="stylesheet" />
<link rel="stylesheet" href="{{STATIC_URL}}/font-awesome/css/font-awesome.min.css?ver={{VERSION}}" />
<link rel="stylesheet" href="{{STATIC_URL}}/js/prettyPhoto/css/prettyPhoto.css?ver={{VERSION}}" />
<link rel="stylesheet" href="{{STATIC_URL}}media/ui.jqgrid.css?ver={{VERSION}}" />
@@ -28,6 +30,9 @@
{% include "blocks/extra_head.html" %}
{% block extra_head %}
{% endblock %}
+ <script type='text/javascript'>
+ var shortcut_url = '{% url "shortcut-menu" %}';
+ </script>
</head>
<body{% if current_theme%} id='{{current_theme}}'{%endif%}>
<div id="header">
@@ -64,31 +69,8 @@
<a href='{% url "start" %}' id="logo">
{% if APP_NAME %}<p id="app_name">{{APP_NAME}}</p>{%endif%}
</a>
- {% if not reminders %}<div id="context_menu">
- {% block context %}{% if current_menu %}
- <form method="post" action="{% url 'update-current-item' %}">
- <fieldset>
- <i class="icon fa fa-thumb-tack fa-2x" aria-hidden="true" title="{% trans 'Pin an item in order to constrain default searches with this item. New created and modified items are auto-pin.' %}"></i>
- <table id='current_items'>
- {% for lbl, model_name, main_cls, items in current_menu %}
- <tr>
- <td><label for="current_{{model_name}}">{{lbl}}</label></td>
- <td>
- <select class='{{main_cls}}' id='current_{{model_name}}'>
- <option class='normal' value=''>--</option>
- {% for val, label, selected, cls in items %}<option{% if cls %} class='{{cls}}'{% endif %} value='{{val}}'{% if selected %} selected="selected"{% endif %}>{% ifequal cls 'basket' %}&#xf291; {% endifequal %}{% ifequal cls 'green' %}&#xf058; {% endifequal %}{% ifequal cls 'orange' %}&#xf06a; {% endifequal %}{% ifequal cls 'red' %}&#xf071; {% endifequal %}{{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'><i class="fa fa-info-circle" aria-hidden="true"></i></a></td>
- {% endwith %}
- </tr>
- {% endfor %}
- </table>
- </fieldset>
- </form>
- {% endif %}{% endblock %}
- </div>{% endif %}
-{% if reminders %}<fieldset id='reminder'><legend>{% trans "Current items" %}</legend>
+ {% if not reminders %}<div id="context_menu"></div>
+ {% else %}<fieldset id='reminder'><legend>{% trans "Current items" %}</legend>
{% for lbl, value in reminders %}
<p><strong class='lbl'>{{lbl}}{% trans ":"%}</strong> <span class='value'>{{value}}</span></p>
{% endfor %}
@@ -128,6 +110,9 @@
<p class='progress-detail progress-4'>{% trans "Time to take another coffee?" %} <i class="fa fa-coffee" aria-hidden="true"></i></p>
</div>
</div>
+ <div id='message'>
+ <div class='information'><i class="fa fa-info-circle" aria-hidden="true"></i> <span class='content'></span></div>
+ </div>
</body>
</html>
diff --git a/ishtar_common/templates/ishtar/blocks/shortcut_menu.html b/ishtar_common/templates/ishtar/blocks/shortcut_menu.html
new file mode 100644
index 000000000..29c975e79
--- /dev/null
+++ b/ishtar_common/templates/ishtar/blocks/shortcut_menu.html
@@ -0,0 +1,24 @@
+{% load i18n %}
+{% load url from future%}
+{% if current_menu %}
+<form method="post" action="{% url 'update-current-item' %}">
+<fieldset>
+<i class="icon fa fa-thumb-tack fa-2x" aria-hidden="true" title="{% trans 'Pin an item in order to constrain default searches with this item. By default only your items are displayed. New created and modified items are auto-pin.' %}"></i>
+<table id='current_items'>
+{% for lbl, model_name, main_cls, items in current_menu %}
+<tr>
+ <td><label for="current_{{model_name}}">{{lbl}}</label></td>
+ <td>
+ <select class='{{main_cls}} chosen-select' id='current_{{model_name}}'>
+ <option class='normal' value=''>--</option>
+ {% for val, label, selected, cls in items %}<option{% if cls %} class='{{cls}}'{% endif %} value='{{val}}'{% if selected %} selected="selected"{% endif %}>{% ifequal cls 'basket' %}&#xf291; {% endifequal %}{% ifequal cls 'green' %}&#xf058; {% endifequal %}{% ifequal cls 'orange' %}&#xf06a; {% endifequal %}{% ifequal cls 'red' %}&#xf071; {% endifequal %}{{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'><i class="fa fa-info-circle" aria-hidden="true"></i></a></td>
+ {% endwith %}
+</tr>
+{% endfor %}
+</table>
+</fieldset>
+</form>
+{% endif %}
diff --git a/ishtar_common/templates/ishtar/blocks/window_nav.html b/ishtar_common/templates/ishtar/blocks/window_nav.html
index 13069b1eb..c0d1ba9fe 100644
--- a/ishtar_common/templates/ishtar/blocks/window_nav.html
+++ b/ishtar_common/templates/ishtar/blocks/window_nav.html
@@ -42,6 +42,13 @@
<i class="fa fa-pencil fa-stack-1x fa-inverse"></i>
</span>
</a>{% endif %}
+ {% if pin_action %}
+ <span class='pin-action' onclick='$.get("{% url 'pin' item.SLUG item.pk %}", function(){load_shortcut_menu(); display_info("{% trans 'Item pined in your shortcut menu.' %}")});' title="{% trans 'Pin' %}">
+ <span class="fa-stack fa-lg">
+ <i class="fa fa-circle fa-stack-2x"></i>
+ <i class="fa fa-thumb-tack fa-stack-1x fa-inverse"></i>
+ </span>
+ </span>{% endif %}
<a class='badge' href='{% url show_url item.pk "odt" %}' title='{% trans "Export as OpenOffice.org file"%}'>ODT</a> <a class='badge' href='{% url show_url item.pk "pdf" %}' title='{% trans "Export as PDF file"%}'>PDF</a>
</div>
<hr class='clear'>
diff --git a/ishtar_common/templatetags/window_header.py b/ishtar_common/templatetags/window_header.py
index b137f24a5..5322c4478 100644
--- a/ishtar_common/templatetags/window_header.py
+++ b/ishtar_common/templatetags/window_header.py
@@ -6,7 +6,7 @@ register = template.Library()
@register.inclusion_tag('ishtar/blocks/window_nav.html')
def window_nav(item, window_id, show_url, modify_url='', histo_url='',
- revert_url='', previous=None, nxt=None):
+ revert_url='', previous=None, nxt=None, pin_action=False):
return {
'show_url': show_url,
'modify_url': modify_url,
@@ -15,7 +15,8 @@ def window_nav(item, window_id, show_url, modify_url='', histo_url='',
'item': item,
'window_id': window_id,
'previous': previous,
- 'next': nxt}
+ 'next': nxt,
+ 'pin_action': pin_action}
@register.inclusion_tag('ishtar/blocks/window_file_nav.html')
@@ -34,4 +35,5 @@ def window_file_nav(item, window_id, previous=None, nxt=None):
'extra_action': mark_safe(add_operation),
'window_id': window_id,
'previous': previous,
- 'next': nxt}
+ 'next': nxt,
+ 'pin_action': True}
diff --git a/ishtar_common/urls.py b/ishtar_common/urls.py
index a6f24beed..802e6ca0d 100644
--- a/ishtar_common/urls.py
+++ b/ishtar_common/urls.py
@@ -34,6 +34,7 @@ urlpatterns = patterns(
# internationalization
url(r'^i18n/', include('django.conf.urls.i18n')),
# General
+ url(r'shortcut_menu/', views.shortcut_menu, name='shortcut-menu'),
url(r'person_search/(?P<step>.+)?$',
check_rights(['add_person'])(
views.person_search_wizard), name='person_search'),
@@ -129,6 +130,8 @@ urlpatterns += patterns(
name='dashboard-main-detail'),
url(r'update-current-item/$', 'update_current_item',
name='update-current-item'),
+ url(r'pin/(?P<item_type>[a-z-]+)/(?P<pk>\d+)/$', 'update_current_item',
+ name='pin'),
url(r'new-person/(?:(?P<parent_name>[^/]+)/)?(?:(?P<limits>[^/]+)/)?$',
'new_person', name='new-person'),
url(r'new-person-noorga/'
diff --git a/ishtar_common/views.py b/ishtar_common/views.py
index 46a8ceb6a..5022aa08e 100644
--- a/ishtar_common/views.py
+++ b/ishtar_common/views.py
@@ -62,7 +62,7 @@ from archaeological_operations.forms import DashboardForm as DashboardFormOpe
from archaeological_files.forms import DashboardForm as DashboardFormFile
from ishtar_common.forms import FinalForm, FinalDeleteForm
-from ishtar_common.utils import get_random_item_image_link
+from ishtar_common.utils import get_random_item_image_link, shortify
from ishtar_common import forms_common as forms
from ishtar_common import wizards
from ishtar_common.models import HistoryError, PRIVATE_FIELDS, \
@@ -198,11 +198,122 @@ def get_autocomplete_generic(model, extra={'available': True}):
return func
-def update_current_item(request):
- if not request.is_ajax() and not request.method == 'POST':
- raise Http404
- if 'value' in request.POST and 'item' in request.POST:
- request.session[request.POST['item']] = request.POST['value']
+def shortcut_menu(request):
+ from archaeological_operations.models import Operation
+ from archaeological_files.models import File
+ from archaeological_context_records.models import ContextRecord
+ from archaeological_finds.models import Find
+
+ profile = get_current_profile()
+ CURRENT_ITEMS = []
+ if profile.files:
+ CURRENT_ITEMS.append((_(u"Archaeological file"), File))
+ CURRENT_ITEMS.append((_(u"Operation"), Operation))
+ if profile.context_record:
+ CURRENT_ITEMS.append((_(u"Context record"), ContextRecord))
+ if profile.find:
+ CURRENT_ITEMS.append((_(u"Find"), Find))
+ dct = {'current_menu': []}
+ current_selected_item = None
+ for lbl, model in CURRENT_ITEMS:
+ new_selected_item = None
+ model_name = model.SLUG
+ cls = ''
+ current = model_name in request.session and request.session[model_name]
+ items = []
+ for item in model.get_owns(request.user,
+ menu_filtr=current_selected_item):
+ pk = unicode(item.pk)
+ if item.IS_BASKET:
+ pk = "basket-" + pk
+ selected = pk == current
+ if selected:
+ cls = item.get_short_menu_class()
+ new_selected_item = item
+ items.append((pk, shortify(unicode(item), 60),
+ selected, item.get_short_menu_class()))
+ # selected is not in owns - add it to the list
+ if not new_selected_item and current:
+ try:
+ item = model.objects.get(pk=int(current))
+ items.append((item.pk, shortify(unicode(item), 60),
+ True, item.get_short_menu_class()))
+ except (model.DoesNotExist, ValueError):
+ pass
+ if items:
+ dct['current_menu'].append((lbl, model_name, cls, items))
+ current_selected_item = new_selected_item
+ return render_to_response('ishtar/blocks/shortcut_menu.html', dct,
+ context_instance=RequestContext(request))
+
+
+def get_current_items(request):
+ from archaeological_files.models import File
+ from archaeological_operations.models import Operation
+ from archaeological_context_records.models import ContextRecord
+ from archaeological_finds.models import Find
+ currents = {}
+ for key, model in (('file', File),
+ ('operation', Operation),
+ ('contextrecord', ContextRecord),
+ ('find', Find)):
+ currents[key] = None
+ if key in request.session and request.session[key]:
+ try:
+ currents[key] = model.objects.get(pk=int(request.session[key]))
+ except (ValueError, File.DoesNotExist):
+ continue
+ return currents
+
+
+def update_current_item(request, item_type=None, pk=None):
+ if not item_type or not pk:
+ if not request.is_ajax() and not request.method == 'POST':
+ raise Http404
+ item_type = request.POST['item']
+ if 'value' in request.POST and 'item' in request.POST:
+ request.session[item_type] = request.POST['value']
+ else:
+ request.session[item_type] = str(pk)
+
+ currents = get_current_items(request)
+ # reinit when descending item are not relevant
+ if item_type == 'file' and currents['file'] and currents['operation'] and \
+ currents['operation'].associated_file != currents['file']:
+ request.session["operation"] = ''
+ currents['operation'] = None
+ if item_type in ('operation', 'file') and currents['contextrecord'] and \
+ (not request.session["operation"] or
+ currents['contextrecord'].operation != currents['operation']):
+ request.session["contextrecord"] = ''
+ currents['contextrecord'] = None
+ from archaeological_finds.models import Find
+ if item_type in ('contextrecord', 'operation', 'file') and currents['find'] and\
+ (not request.session["contextrecord"] or
+ not Find.objects.filter(
+ downstream_treatment__isnull=True,
+ base_finds__context_record__pk=request.session["contextrecord"],
+ pk=currents['find'].pk).count()):
+ request.session["find"] = ''
+ currents['find'] = None
+
+ # re-init ascending item with relevant values
+ if item_type == "find" and currents['find']:
+ from archaeological_context_records.models import ContextRecord
+ q = ContextRecord.objects.filter(
+ base_finds__find__pk=currents['find'].pk)
+ if q.count():
+ currents['contextrecord'] = q.all()[0]
+ request.session['contextrecord'] = str(
+ currents['contextrecord'].pk)
+ if item_type in ("find", 'contextrecord') and currents['contextrecord']:
+ currents['operation'] = currents['contextrecord'].operation
+ request.session['operation'] = str(currents['operation'].pk)
+ if item_type in ("find", 'contextrecord', 'operation') and \
+ currents['operation']:
+ currents['file'] = currents['operation'].associated_file
+ request.session['file'] = str(currents['file'].pk) if currents['file'] \
+ else None
return HttpResponse('ok')