From 5848f96f633d63248eefbabd325b17f6e36bd0e8 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Mon, 9 Jul 2018 20:59:24 +0200 Subject: Save search queries --- ishtar_common/forms_common.py | 56 ++++++++++ ishtar_common/migrations/0062_searchquery.py | 33 ++++++ ishtar_common/models.py | 19 ++++ ishtar_common/static/js/ishtar.js | 14 +++ ishtar_common/templates/base.html | 3 + ishtar_common/templates/blocks/DataTables.html | 3 +- .../templates/blocks/bs_form_snippet.html | 5 +- .../templates/ishtar/forms/search_query.html | 122 +++++++++++++++++++++ ishtar_common/templates/ishtar/forms/success.html | 20 ++++ ishtar_common/templates/ishtar/wizard/search.html | 2 +- ishtar_common/templates/widgets/search_input.html | 32 ++++-- ishtar_common/urls.py | 6 + ishtar_common/views.py | 45 ++++++++ 13 files changed, 346 insertions(+), 14 deletions(-) create mode 100644 ishtar_common/migrations/0062_searchquery.py create mode 100644 ishtar_common/templates/ishtar/forms/search_query.html create mode 100644 ishtar_common/templates/ishtar/forms/success.html (limited to 'ishtar_common') diff --git a/ishtar_common/forms_common.py b/ishtar_common/forms_common.py index 47e976452..43652ba07 100644 --- a/ishtar_common/forms_common.py +++ b/ishtar_common/forms_common.py @@ -27,6 +27,7 @@ import tempfile from django import forms from django.conf import settings from django.contrib.auth.models import User +from django.contrib.contenttypes.models import ContentType from django.core import validators from django.core.cache import cache from django.core.exceptions import ObjectDoesNotExist @@ -1276,3 +1277,58 @@ AuthorFormset = formset_factory(AuthorFormSelection, can_delete=True, AuthorFormset.form_label = _("Authors") AuthorFormset.form_admin_name = _(u"Authors") AuthorFormset.form_slug = "authors" + + +class SearchQueryForm(forms.Form): + query = forms.CharField(max_length=None, label=_(u"Query"), disabled=True, + initial='*') + search_query = forms.ChoiceField(label=_(u"Search query"), required=False, + choices=[]) + label = forms.CharField(max_length=None, label=_(u"Name"), required=False) + is_alert = forms.BooleanField(label=_(u"Is an alert"), required=False) + create_or_update = forms.ChoiceField( + choices=(('create', _(u"Create")), + ('update', _(u"Update"))), initial='create') + + def __init__(self, profile, content_type, *args, **kwargs): + self.profile = profile + self.content_type = content_type + super(SearchQueryForm, self).__init__(*args, **kwargs) + self.fields['search_query'].choices = [ + (c.pk, c.label) for c in models.SearchQuery.objects.filter( + content_type=content_type, profile=profile).all()] + if not self.fields['search_query'].choices: + self.fields.pop('search_query') + + def clean(self): + data = self.cleaned_data + if data['create_or_update'] == 'create' and not data['label']: + raise forms.ValidationError(_(u"A label is required for a new " + u"search query.")) + elif data['create_or_update'] == 'update': + if not data['search_query']: + raise forms.ValidationError(_(u"Select the search query to " + u"update")) + q = models.SearchQuery.objects.filter( + profile=self.profile, content_type=self.content_type, + pk=data['search_query']) + if not q.count(): + raise forms.ValidationError(_(u"Query does not exist.")) + return data + + def save(self): + data = self.cleaned_data + if data['create_or_update'] == 'create': + sq = models.SearchQuery.objects.create( + label=data['label'], query=data['query'], profile=self.profile, + content_type=self.content_type, is_alert=data['is_alert']) + else: + try: + sq = models.SearchQuery.objects.get( + profile=self.profile, content_type=self.content_type, + pk=data['search_query']) + except models.SearchQuery.DoesNotExist: + raise forms.ValidationError(_(u"Query does not exist.")) + sq.query = data['query'] + sq.save() + return sq diff --git a/ishtar_common/migrations/0062_searchquery.py b/ishtar_common/migrations/0062_searchquery.py new file mode 100644 index 000000000..e886fe45a --- /dev/null +++ b/ishtar_common/migrations/0062_searchquery.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.10 on 2018-07-09 13:12 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('contenttypes', '0002_remove_content_type_name'), + ('ishtar_common', '0061_auto_20180704_1225'), + ] + + operations = [ + migrations.CreateModel( + name='SearchQuery', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('label', models.TextField(blank=True, verbose_name='Label')), + ('query', models.TextField(blank=True, verbose_name='Query')), + ('is_alert', models.BooleanField(default=False, verbose_name='Is an alert')), + ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType', verbose_name='Content type')), + ('profile', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='ishtar_common.UserProfile', verbose_name='Profile')), + ], + options={ + 'ordering': ['label'], + 'verbose_name': 'Search query', + 'verbose_name_plural': 'Search queries', + }, + ), + ] diff --git a/ishtar_common/models.py b/ishtar_common/models.py index d65c08f93..016883abe 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -1110,6 +1110,8 @@ class FullSearch(models.Model): :param save: True if you want to save the object immediately :return: True if modified """ + if not hasattr(self, 'search_vector'): + return if not self.pk: logger.warning("Cannot update search vector before save or " "after deletion.") @@ -1555,6 +1557,23 @@ def post_delete_record_relation(sender, instance, **kwargs): q.delete() +class SearchQuery(models.Model): + label = models.TextField(_(u"Label"), blank=True) + query = models.TextField(_(u"Query"), blank=True) + content_type = models.ForeignKey(ContentType, + verbose_name=_(u"Content type")) + profile = models.ForeignKey("UserProfile", verbose_name=_(u"Profile")) + is_alert = models.BooleanField(_(u"Is an alert"), default=False) + + class Meta: + verbose_name = _(u"Search query") + verbose_name_plural = _(u"Search queries") + ordering = ['label'] + + def __unicode__(self): + return unicode(self.label) + + class ShortMenuItem(object): @classmethod def get_short_menu_class(cls, pk): diff --git a/ishtar_common/static/js/ishtar.js b/ishtar_common/static/js/ishtar.js index 279d43b0e..0df286c26 100644 --- a/ishtar_common/static/js/ishtar.js +++ b/ishtar_common/static/js/ishtar.js @@ -30,6 +30,8 @@ function manage_async_link(event){ $.get(url, function(data) { $(target).html(data); }); + var modal_open = $(this).attr('data-modal-open'); + if (modal_open) $(modal_open).modal('show'); } /* default function to prevent undefined */ @@ -266,6 +268,7 @@ $(document).ready(function(){ $(".chosen-select").chosen(); $(".clear-search").click(function(){ $(this).parent().parent().children('input').prop("value", ""); + enable_save(); }); }); @@ -534,9 +537,18 @@ function get_label_from_input(input){ return input.parent().attr('data-alt-name'); } +var enable_save = function(){ + if ($(".search-widget input").val()){ + $("#save-search-button").removeClass('disabled'); + } else { + $("#save-search-button").addClass('disabled'); + } +} + function clear_search_field(){ $("#id_search_vector").val(""); add_message("-", 'info', "#advanced-search-info", true); + enable_save(); } function update_search_field(){ @@ -595,6 +607,7 @@ function update_search_field(){ } else { add_message("-", 'info', "#advanced-search-info", true); } + enable_save(); } var sheet_list = new Array(); @@ -646,3 +659,4 @@ function manage_pinned_search(name, data){ $('#pinned_search_' + name).hide(); } } + diff --git a/ishtar_common/templates/base.html b/ishtar_common/templates/base.html index bbf030409..40e30706c 100644 --- a/ishtar_common/templates/base.html +++ b/ishtar_common/templates/base.html @@ -148,6 +148,9 @@ +
diff --git a/ishtar_common/templates/blocks/DataTables.html b/ishtar_common/templates/blocks/DataTables.html index fdd358363..4beabe82a 100644 --- a/ishtar_common/templates/blocks/DataTables.html +++ b/ishtar_common/templates/blocks/DataTables.html @@ -2,7 +2,8 @@

- {% if url_new %} diff --git a/ishtar_common/templates/blocks/bs_form_snippet.html b/ishtar_common/templates/blocks/bs_form_snippet.html index 7bdac3bf3..95b8ac086 100644 --- a/ishtar_common/templates/blocks/bs_form_snippet.html +++ b/ishtar_common/templates/blocks/bs_form_snippet.html @@ -40,7 +40,7 @@ {% else %} {% if search and forloop.counter0 == 1 %}