diff options
| -rw-r--r-- | archaeological_operations/views.py | 6 | ||||
| -rw-r--r-- | archaeological_operations/wizards.py | 5 | ||||
| -rw-r--r-- | ishtar_common/static/js/ishtar.js | 32 | ||||
| -rw-r--r-- | ishtar_common/templates/base.html | 1 | ||||
| -rw-r--r-- | ishtar_common/templates/blocks/DataTables.html | 20 | ||||
| -rw-r--r-- | ishtar_common/templates/ishtar/blocks/base_shortcut_menu.html | 4 | ||||
| -rw-r--r-- | ishtar_common/templates/ishtar/wizard/search.html | 8 | ||||
| -rw-r--r-- | ishtar_common/urls.py | 6 | ||||
| -rw-r--r-- | ishtar_common/utils.py | 3 | ||||
| -rw-r--r-- | ishtar_common/views.py | 50 | ||||
| -rw-r--r-- | ishtar_common/views_item.py | 17 | ||||
| -rw-r--r-- | ishtar_common/wizards.py | 22 | ||||
| -rw-r--r-- | scss/custom.scss | 4 | 
13 files changed, 161 insertions, 17 deletions
| diff --git a/archaeological_operations/views.py b/archaeological_operations/views.py index 0721bb707..10e60c2bb 100644 --- a/archaeological_operations/views.py +++ b/archaeological_operations/views.py @@ -22,7 +22,7 @@ import json  from django.conf import settings  from django.core.urlresolvers import reverse  from django.db.models import Q -from django.http import HttpResponse, HttpResponseRedirect +from django.http import HttpResponse, HttpResponseRedirect, Http404  from django.shortcuts import render, redirect  from django.utils.translation import ugettext_lazy as _, pgettext_lazy @@ -45,7 +45,7 @@ from archaeological_operations.wizards import has_associated_file, \      OperationClosingWizard, OperationDeletionWizard, SiteSearch, \      OperationAdministrativeActWizard, OperationEditAdministrativeActWizard, \      AdministrativeActDeletionWizard, SiteWizard, SiteModificationWizard, \ -    SiteDeletionWizard +    SiteDeletionWizard, OperationSearch  from ishtar_common.forms import ClosingDateFormSelection, FinalForm, \      FinalDeleteForm  from ishtar_common.models import get_current_profile, IshtarSiteProfile @@ -175,7 +175,7 @@ def dashboard_operation(request, *args, **kwargs):      return render(request, 'ishtar/dashboards/dashboard_operation.html', dct) -operation_search_wizard = SearchWizard.as_view( +operation_search_wizard = OperationSearch.as_view(      [('general-operation_search', OperationFormSelection)],      label=_(u"Operation search"),      url_name='operation_search',) diff --git a/archaeological_operations/wizards.py b/archaeological_operations/wizards.py index a8f8ef80b..ba9709807 100644 --- a/archaeological_operations/wizards.py +++ b/archaeological_operations/wizards.py @@ -37,6 +37,10 @@ from ishtar_common.wizards import Wizard, ClosingWizard, DeletionWizard, \  logger = logging.getLogger(__name__) +class OperationSearch(SearchWizard): +    model = models.Operation + +  class OperationWizard(Wizard):      model = models.Operation      object_parcel_type = 'operation' @@ -419,6 +423,7 @@ class SiteLabel(object):  class SiteSearch(SiteLabel, SearchWizard):      SITE_KEY = "search" +    model = models.ArchaeologicalSite  class SiteWizard(SiteLabel, Wizard): diff --git a/ishtar_common/static/js/ishtar.js b/ishtar_common/static/js/ishtar.js index a71450fab..60840bcf8 100644 --- a/ishtar_common/static/js/ishtar.js +++ b/ishtar_common/static/js/ishtar.js @@ -38,7 +38,10 @@ function manage_async_link(event){  function get_next_table_id(){}  function get_previous_table_id(){} +var datatable_submit_search = function() {}; +  var shortcut_url = ''; +var alert_url = '';  var datatables_i18n;  var current_modal; @@ -222,6 +225,7 @@ function load_shortcut_menu(opened){          cache: false,          success:function(html){              init_shortcut_menu(html); +            load_alerts();              if(opened){                  $("#dropdown-toggle-shortcut-menu").click();              } @@ -232,6 +236,34 @@ function load_shortcut_menu(opened){      });  } +var load_alerts = function(){ +    if (!alert_url) return; +    $('.modal-progress').modal('show'); +    $.ajax({ +        url: alert_url, +        cache: false, +        success:function(json){ +            $('.modal-progress').modal('hide'); +            var html = ""; +            for (idx in json["alerts"]){ +                var b = json["alerts"][idx]; +                var url = "/bookmark/" + b["query_id"] + "/" ; +                html += '<a class="badge badge-secondary" href="' + url + '">'; +                html += b["label"]; +                html += ' <span class="badge badge-light">'; +                html += b["number"]; +                html += '</span>'; +                html += '</a> '; +            } +            $("#alert-list").html(html); +        }, +        error:function(XMLHttpRequest, textStatus, errorThrows){ +            close_wait(); +        }, +        dataType: 'json' +    }); +} +  function dynamic_load(url, target){      $.ajax({          url: url, diff --git a/ishtar_common/templates/base.html b/ishtar_common/templates/base.html index 40e30706c..72c6a9b65 100644 --- a/ishtar_common/templates/base.html +++ b/ishtar_common/templates/base.html @@ -30,6 +30,7 @@      {{EXTRA_JS|safe}}      <script type='text/javascript'>      var shortcut_url = '{% url "shortcut-menu" %}'; +    var alert_url = '{% url "alert-list" %}';      var get_file_url = '{% url "get-file-shortcut" %}';      var get_operation_url = '{% url "get-operation-shortcut" %}';      var get_contextrecord_url = '{% url "get-contextrecord-shortcut" %}'; diff --git a/ishtar_common/templates/blocks/DataTables.html b/ishtar_common/templates/blocks/DataTables.html index 0ae6ba7d0..c3ca16395 100644 --- a/ishtar_common/templates/blocks/DataTables.html +++ b/ishtar_common/templates/blocks/DataTables.html @@ -99,8 +99,9 @@ $('#modal_grid_{{name}}').on('hide.bs.modal', function (e) {  var query_vars = new Array({{col_idx|safe}});  var selItems_{{sname}} = new Array(); -jQuery(document).ready(function(){ -  jQuery("#search_{{name}}").click(function (){ + + +datatable_submit_search = function(){      $("#id_search_vector").removeClass('input-progress');      if ($('.modal-progress').length > 0){          $('.modal-progress').modal('show'); @@ -137,11 +138,22 @@ jQuery(document).ready(function(){          $('.modal-progress').modal('hide');      }      return false; -  }); +}; + + + +jQuery(document).ready(function(){ +  jQuery("#search_{{name}}").click(datatable_submit_search); + +  var base_source = "{{source}}"; + +  if (default_search_vector){ +    base_source += "?search_vector=" + default_search_vector; +  }    datatable_options = {      "ajax": { -        "url": "{{source}}", +        "url": base_source,          "dataSrc": function (json) {              manage_pinned_search("{{name}}", json);              return json.rows; diff --git a/ishtar_common/templates/ishtar/blocks/base_shortcut_menu.html b/ishtar_common/templates/ishtar/blocks/base_shortcut_menu.html index 6faf37670..77ef9804b 100644 --- a/ishtar_common/templates/ishtar/blocks/base_shortcut_menu.html +++ b/ishtar_common/templates/ishtar/blocks/base_shortcut_menu.html @@ -8,7 +8,9 @@      <span class="navbar-toggler-icon"></span>  </button>  {% endcomment %} -<div class="navbar-collapse collapse justify-content-end"> +<div class="navbar-collapse collapse justify-content-between"> +    <span id="alert-list"> +    </span>      <ul class="navbar-nav" id="navbar-shortcut">        <li class="nav-item">            <ol class="breadcrumb"> diff --git a/ishtar_common/templates/ishtar/wizard/search.html b/ishtar_common/templates/ishtar/wizard/search.html index eebd58d89..a7a6faec7 100644 --- a/ishtar_common/templates/ishtar/wizard/search.html +++ b/ishtar_common/templates/ishtar/wizard/search.html @@ -5,6 +5,14 @@  {% endblock %}  {% block content %}  <h3>{{wizard_label}}</h3> +{% if default_search_vector %} +<script type="text/javascript"> +    var default_search_vector = "{{default_search_vector|safe}}".replace(/''/g, '"'); +    $(document).ready(function() { +        $("#id_search_vector").val(default_search_vector.replace(/''/g, '"')); +    }); +</script> +{% endif %}  {% comment %}  <nav aria-label="breadcrumb" role="navigation"> diff --git a/ishtar_common/urls.py b/ishtar_common/urls.py index 44ebd0f93..ee1b3805e 100644 --- a/ishtar_common/urls.py +++ b/ishtar_common/urls.py @@ -128,8 +128,10 @@ urlpatterns = [          views.SearchQueryEdit.as_view(),          name='save-search-query'),      url(r'^bookmarks/(?P<app_label>[a-z-]+)/(?P<model>[a-z-]+)/$', -        views.BookmarkList.as_view(), -        name='bookmark-list'), +        views.BookmarkList.as_view(), name='bookmark-list'), +    url(r'^bookmark/(?P<pk>[0-9]+)/$', +        views.get_bookmark, name='bookmark'), +    url(r'^alerts/$', views.AlertList.as_view(), name='alert-list'),      url(r'^success(?:/(?P<context>[a-z-]+))?/$',          TemplateView.as_view(template_name="ishtar/forms/success.html"),          name='success'), diff --git a/ishtar_common/utils.py b/ishtar_common/utils.py index 34d170892..0e5dd286a 100644 --- a/ishtar_common/utils.py +++ b/ishtar_common/utils.py @@ -794,7 +794,8 @@ def create_default_json_fields(model):          ) -def get_urls_for_model(model, views, own=False, autocomplete=False): +def get_urls_for_model(model, views, own=False, autocomplete=False, +                       ):      """      Generate get and show url for a model      """ diff --git a/ishtar_common/views.py b/ishtar_common/views.py index 1f8b46fd6..c713b9972 100644 --- a/ishtar_common/views.py +++ b/ishtar_common/views.py @@ -21,6 +21,7 @@ import csv  import datetime  import json  import logging +import importlib  import unicodedata  import unicodecsv @@ -1676,6 +1677,19 @@ document_deletion_wizard = wizards.DocumentDeletionWizard.as_view(      url_name='document_deletion',) +def get_bookmark(request, pk): +    try: +        sq = models.SearchQuery.objects.get( +            pk=pk, +            profile__person__ishtaruser__user_ptr=request.user) +    except models.SearchQuery.DoesNotExist: +        raise Http404() +    slug = sq.content_type.model_class().SLUG +    return redirect( +        reverse(slug + '_search') + "?bookmark={}".format(sq.pk) +    ) + +  class SearchQueryMixin(object):      """      Manage content type and profile init @@ -1736,3 +1750,39 @@ class BookmarkList(SearchQueryMixin, JSONResponseMixin, LoginRequiredMixin,              'bookmarks': [                  {'label': sq.label, 'query': sq.query} for sq in q.all()]          } + + +class AlertList(JSONResponseMixin, LoginRequiredMixin, +                TemplateView): +    def dispatch(self, request, *args, **kwargs): +        if not request.user.pk: +            raise Http404() +        try: +            self.profile = models.UserProfile.objects.get( +                current=True, person__ishtaruser__user_ptr=request.user) +        except models.UserProfile.DoesNotExist: +            # no current profile +            raise Http404() +        return super(AlertList, self).dispatch(request, *args, **kwargs) + +    def get_data(self, context): +        q = models.SearchQuery.objects.filter( +            profile=self.profile, +            is_alert=True +        ) +        alerts = [] +        for sq in q.all(): +            model = sq.content_type.model_class() +            module = model.__module__.split('.')[0] +            views = importlib.import_module(module + '.views') +            get_view = getattr(views, "get_" + model.SLUG) +            nb = get_view( +                self.request, +                query={'search_vector': sq.query}, +                count=True +            ) +            alerts.append( +                {'label': sq.label, 'query_id': sq.pk, +                 'number': nb} +            ) +        return {'alerts': alerts} diff --git a/ishtar_common/views_item.py b/ishtar_common/views_item.py index 854c91ce5..85ef5339a 100644 --- a/ishtar_common/views_item.py +++ b/ishtar_common/views_item.py @@ -12,7 +12,6 @@ from tempfile import NamedTemporaryFile  from django.conf import settings  from django.contrib.gis.geos import GEOSException -from django.contrib.postgres.search import SearchQuery  from django.contrib.staticfiles.templatetags.staticfiles import static  from django.core.exceptions import ObjectDoesNotExist  from django.core.urlresolvers import reverse, NoReverseMatch @@ -821,14 +820,22 @@ def get_item(model, func_name, default_name, extra_request_keys=[],                         (hasattr(field, 'rel') and field.rel and '__pk' or ''))                        for field in associated_fields]))          request_keys.update(my_extra_request_keys) -        request_items = request.method == 'POST' and request.POST \ -                        or request.GET + +        if "query" in dct: +            request_items = dct["query"] +        elif request.method == 'POST': +            request_items = request.POST +        else: +            request_items = request.GET + +        count = dct.get('count', False)          # pager          try:              row_nb = int(request_items.get('length'))          except (ValueError, TypeError):              row_nb = DEFAULT_ROW_NUMBER +          dct_request_items = {}          # filter requested fields @@ -839,6 +846,7 @@ def get_item(model, func_name, default_name, extra_request_keys=[],              if key.startswith('searchprefix_'):                  key = key[len('searchprefix_'):]              dct_request_items[key] = request_items[k] +          request_items = dct_request_items          dct = my_base_request @@ -985,6 +993,9 @@ def get_item(model, func_name, default_name, extra_request_keys=[],              items = items.extra(**extra)          items = items.distinct() + +        if count: +            return items.count()          # print(items.query)          if search_vector:  # for serialization diff --git a/ishtar_common/wizards.py b/ishtar_common/wizards.py index 4a55345d2..b1e0c7fd2 100644 --- a/ishtar_common/wizards.py +++ b/ishtar_common/wizards.py @@ -1413,9 +1413,25 @@ class SearchWizard(IshtarWizard):          context = super(SearchWizard, self).get_context_data(form)          self.request.session['CURRENT_ACTION'] = self.get_wizard_name()          current_step = self.steps.current -        context.update({'current_step': self.form_list[current_step], -                        'is_search': True, -                        'wizard_label': self.get_label()}) +        bookmark = self.request.GET.get('bookmark', None) +        default_search_vector = None +        if bookmark: +            try: +                app_label = self.model.__module__.split('.')[0] +                sq = models.SearchQuery.objects.get( +                    pk=bookmark, +                    content_type__app_label=app_label, +                    content_type__model=self.model.SLUG, +                    profile__person__ishtaruser__user_ptr=self.request.user +                ) +                default_search_vector = sq.query.replace('"', "''") +            except models.SearchQuery.DoesNotExist: +                pass +        context.update({ +            'current_step': self.form_list[current_step], +            'is_search': True, 'wizard_label': self.get_label(), +            'default_search_vector': default_search_vector +        })          return context diff --git a/scss/custom.scss b/scss/custom.scss index f35078862..7ccc8dbc6 100644 --- a/scss/custom.scss +++ b/scss/custom.scss @@ -348,6 +348,10 @@ div#validation-bar{      padding: 0.6em 1em 0.1em 1em;  } +#alert-list a{ +    font-size: 1.1rem; +} +  .confirm-message{      text-align:center;      margin: 0; | 
