diff options
| 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 | 
| commit | 13790d69392535543991be2f9de453b6a2fe9493 (patch) | |
| tree | 5df1cfe674759003b1599f7334448f9c7f00637d | |
| parent | b9fad2cce5388c1f32a936521149cf2fa36e783e (diff) | |
| download | Ishtar-13790d69392535543991be2f9de453b6a2fe9493.tar.bz2 Ishtar-13790d69392535543991be2f9de453b6a2fe9493.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.py | 10 | ||||
| -rw-r--r-- | archaeological_context_records/templates/ishtar/sheet_contextrecord.html | 2 | ||||
| -rw-r--r-- | archaeological_files/models.py | 3 | ||||
| -rw-r--r-- | archaeological_files/templates/ishtar/sheet_file.html | 2 | ||||
| -rw-r--r-- | archaeological_finds/models.py | 9 | ||||
| -rw-r--r-- | archaeological_finds/templates/ishtar/sheet_find.html | 2 | ||||
| -rw-r--r-- | archaeological_operations/models.py | 8 | ||||
| -rw-r--r-- | archaeological_operations/templates/ishtar/sheet_operation.html | 2 | ||||
| -rw-r--r-- | ishtar_common/context_processors.py | 35 | ||||
| -rw-r--r-- | ishtar_common/models.py | 8 | ||||
| -rw-r--r-- | ishtar_common/static/js/ishtar.js | 58 | ||||
| -rw-r--r-- | ishtar_common/static/media/style.css | 34 | ||||
| -rw-r--r-- | ishtar_common/templates/base.html | 35 | ||||
| -rw-r--r-- | ishtar_common/templates/ishtar/blocks/shortcut_menu.html | 24 | ||||
| -rw-r--r-- | ishtar_common/templates/ishtar/blocks/window_nav.html | 7 | ||||
| -rw-r--r-- | ishtar_common/templatetags/window_header.py | 8 | ||||
| -rw-r--r-- | ishtar_common/urls.py | 3 | ||||
| -rw-r--r-- | ishtar_common/views.py | 123 | 
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' %} {% endifequal %}{% ifequal cls 'green' %} {% endifequal %}{% ifequal cls 'orange' %} {% endifequal %}{% ifequal cls 'red' %} {% 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' %} {% endifequal %}{% ifequal cls 'green' %} {% endifequal %}{% ifequal cls 'orange' %} {% endifequal %}{% ifequal cls 'red' %} {% 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')  | 
