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; |