From 975b971ae6efacbd5614be7f057f32d7c302966b Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Fri, 27 Nov 2020 11:26:55 +0100 Subject: Documents: dynamic filter of support and medium by document type - collapse related fields on edition --- ishtar_common/admin.py | 20 +++- ishtar_common/forms.py | 116 ++++++++++++++++++- ishtar_common/forms_common.py | 70 +++++++++++- ishtar_common/lookups.py | 9 ++ .../migrations/0208_auto_20201126_1217.py | 115 ------------------- .../migrations/0208_auto_20201126_1516.py | 125 +++++++++++++++++++++ ishtar_common/models.py | 9 ++ ishtar_common/static/js/ishtar.js | 19 ++++ .../templates/blocks/bs_form_snippet.html | 2 +- ishtar_common/templates/ishtar/forms/document.html | 20 ++-- ishtar_common/templatetags/table_form.py | 5 +- ishtar_common/views.py | 15 ++- 12 files changed, 385 insertions(+), 140 deletions(-) delete mode 100644 ishtar_common/migrations/0208_auto_20201126_1217.py create mode 100644 ishtar_common/migrations/0208_auto_20201126_1516.py (limited to 'ishtar_common') diff --git a/ishtar_common/admin.py b/ishtar_common/admin.py index b5ff67567..26ceb01cd 100644 --- a/ishtar_common/admin.py +++ b/ishtar_common/admin.py @@ -982,8 +982,8 @@ class GeneralTypeAdmin(ImportActionAdmin, ImportJSONActionAdmin): general_models = [models.OrganizationType, models.SourceType, - models.AuthorType, models.TitleType, models.Format, - models.SupportType, models.PersonType, models.LicenseType, + models.AuthorType, models.TitleType, + models.PersonType, models.LicenseType, models.Language] for model in general_models: admin_site.register(model, GeneralTypeAdmin) @@ -1081,6 +1081,22 @@ class CreateDepartmentActionAdmin(GeneralTypeAdmin): {'form': form, 'current_action': 'create_area'} ) +@admin.register(models.SupportType, site=admin_site) +class SupportType(GeneralTypeAdmin): + model = models.SupportType + form = make_ajax_form(model, {'document_types': 'source_type'}) + + +@admin.register(models.Format, site=admin_site) +class Format(GeneralTypeAdmin): + model = models.Format + form = make_ajax_form(model, {'document_types': 'source_type'}) + + +@admin.register(models.DocumentTag, site=admin_site) +class DocumentTag(MergeActionAdmin, GeneralTypeAdmin): + pass + class AreaAdmin(CreateDepartmentActionAdmin): list_display = ('label', 'reference', 'parent', 'available') diff --git a/ishtar_common/forms.py b/ishtar_common/forms.py index 6193c72c4..f1e5b34ca 100644 --- a/ishtar_common/forms.py +++ b/ishtar_common/forms.py @@ -622,6 +622,7 @@ class FormHeader(object): class IshtarForm(forms.Form, BSForm): TYPES = [] # FieldType list CONDITIONAL_FIELDS = [] # dynamic conditions on field display + # can be dynamic with "get_conditional_fields" PROFILE_FILTER = {} # profile key associated to field list HEADERS = {} # field key associated to FormHeader instance # permission check for widget options, ex: forms_common.DocumentForm @@ -668,14 +669,19 @@ class IshtarForm(forms.Form, BSForm): self.fields[field.key].choices = field.get_choices() self.fields[field.key].help_text = field.get_help() + def get_headers(self): + return self.HEADERS + def headers(self, key): - if key not in self.HEADERS: + headers = self.get_headers() + if key not in headers: return - self.current_header = self.HEADERS[key] + self.current_header = headers[key] return self.current_header def extra_render(self): - return self.get_conditional() + return (self.get_conditional() or "") + ( + self.get_conditional_filters() or "") HIDE_JS_TEMPLATE = """ var %(id)s_item_show_list = ['%(item_list)s']; @@ -688,7 +694,6 @@ class IshtarForm(forms.Form, BSForm): var %(id)s_item_show_list = ['%(item_list)s']; var %(id)s_hide_display = function(){ var current_val = $("#id_%(name)s").val(); - console.log("#id_%(name)s"); if (%(id)s_check_list.indexOf(current_val) != -1){ for (idx in %(id)s_item_show_list){ $("#main_div-id_" + %(id)s_item_show_list[idx]).removeClass("d-none"); @@ -707,12 +712,15 @@ class IshtarForm(forms.Form, BSForm): """ def get_conditional(self): - if not self.CONDITIONAL_FIELDS or not self.TYPES: + conditional_fields = self.CONDITIONAL_FIELDS + if hasattr(self, 'get_conditional_fields'): + conditional_fields = self.get_conditional_fields() + if not conditional_fields or not self.TYPES: return type_dict = dict([(typ.key, typ.model) for typ in self.TYPES]) html = "" - for condition, target_names in self.CONDITIONAL_FIELDS: + for condition, target_names in conditional_fields: condition_field, condition_attr, condition_val = condition if condition_field not in type_dict: continue @@ -740,6 +748,102 @@ class IshtarForm(forms.Form, BSForm): html = "" return html + CONDITIONAL_FILTER_JS_TEMPLATE = """ + %(filter_list)s; + var %(id)s_prefix = "%(prefix)s"; + var %(id)s_filter_display = function(){ + var current_val = $("#id_%(name)s").val(); + if (current_val in %(id)s_filter_list){ + for (var k in %(id)s_filter_list[current_val]){ + var cname = k; + if (%(id)s_prefix) cname = %(id)s_prefix + cname; + update_select_widget( + cname, + %(id)s_all_value_list[k], + %(id)s_filter_list[current_val][k]); + } + } else { + for (var k in %(id)s_exclude_list){ + var cname = k; + if (%(id)s_prefix) cname = %(id)s_prefix + cname; + update_select_widget( + cname, + %(id)s_all_value_list[k], + null, + %(id)s_exclude_list[k]); + } + } + }; + + $("#id_%(name)s").change(%(id)s_filter_display); + setTimeout(function(){ + %(id)s_filter_display(); + }, 500); + """ + + def get_conditional_filters(self): + if not hasattr(self, 'get_conditional_filter_fields'): + return + conditional_fields, excluded_fields, all_values = \ + self.get_conditional_filter_fields() + + types = [typ.key for typ in self.TYPES] + html = "" + + outputs = set() + for input_key in conditional_fields: + if input_key not in types: + continue + name = input_key + if self.prefix: + name = self.prefix + "-" + input_key + cidx = name.replace("-", "_") + filter_list = "var %s_filter_list = {\n" % cidx + for idx, input_pk in enumerate(conditional_fields[input_key]): + if idx: + filter_list += ",\n" + filter_list += ' "%s": {\n' % input_pk + for idx2, output in enumerate( + conditional_fields[input_key][input_pk]): + if idx2: + filter_list += ",\n" + if output[0] in excluded_fields: + outputs.add(output[0]) + filter_list += ' "{}": [{}]'.format(*output) + filter_list += " }" + filter_list += "};\n" + + html += self.CONDITIONAL_FILTER_JS_TEMPLATE % { + "id": cidx, + "name": name, + "filter_list": filter_list, + "prefix": self.prefix or "" + } + html += "var %s_other_widget_list = [" % cidx + for idx, k in enumerate(all_values): + if idx: + html += ", " + html += '"' + k + '"' + html += "];\n" + + html += "var %s_exclude_list = {\n" % cidx + for idx, output in enumerate(outputs): + if idx: + html += ",\n" + html += ' "%s": [%s]' % (output, excluded_fields[output]) + html += "\n};\n" + + html += "var %s_all_value_list = {\n" % cidx + for idx, k in enumerate(all_values): + if idx: + html += ",\n" + html += ' "%s": %s' % (k, all_values[k]) + html += "\n};\n" + + if html: + html = "" + return html + class TableSelect(IshtarForm): def __init__(self, *args, **kwargs): diff --git a/ishtar_common/forms_common.py b/ishtar_common/forms_common.py index c76577e65..c191a2e6e 100644 --- a/ishtar_common/forms_common.py +++ b/ishtar_common/forms_common.py @@ -1398,6 +1398,7 @@ class DocumentForm(forms.ModelForm, CustomForm, ManageOldType): ] HEADERS = { + 'finds': FormHeader(_("Related items")), 'title': FormHeader(_("Identification")), 'format_type': FormHeader(_("Format")), 'image': FormHeader(_("Content")), @@ -1407,7 +1408,6 @@ class DocumentForm(forms.ModelForm, CustomForm, ManageOldType): 'source': FormHeader(_("Source"), collapse=True), 'container_id': FormHeader(_("Warehouse"), collapse=True), 'comment': FormHeader(_("Advanced"), collapse=True), - 'finds': FormHeader(_("Related items")), } OPTIONS_PERMISSIONS = [ # field name, permission, options @@ -1427,6 +1427,7 @@ class DocumentForm(forms.ModelForm, CustomForm, ManageOldType): self.user = None if kwargs.get("user", None): self.user = kwargs.pop("user") + self.is_instancied = bool(kwargs.get('instance', False)) super(DocumentForm, self).__init__(*args, **kwargs) fields = OrderedDict() for related_key in models.Document.RELATED_MODELS_ALT: @@ -1447,6 +1448,73 @@ class DocumentForm(forms.ModelForm, CustomForm, ManageOldType): fields[k] = self.fields[k] self.fields = fields + def get_headers(self): + headers = self.HEADERS.copy() + if self.is_instancied: + headers["finds"] = FormHeader(headers["finds"].label, collapse=True) + return headers + + def get_conditional_filter_fields(self): + """ + Helper to get values for filtering select widget on select by another + widget + :return: conditional_fields, excluded_fields, all_values + * conditional_fields: + {input_key: { + input_pk: [(output_key1, "pk1,pk2,..."), + (output_key2, "pk1,pk2,...")], + input_pk2: ... + }, + input_key2: {...} + } + * excluded_fields: {output_key: "pk1,pk2,...", ...} # list pk for all + output_key in condition_fields + * all_values: {output_key: [(pk1, label1), (pk2, label2), ...]} + """ + conditional_fields = {} + excluded_fields = {} + key = 'source_type' + for doc_type in models.SourceType.objects.filter( + available=True, formats__pk__isnull=False).all(): + if key not in conditional_fields: + conditional_fields[key] = {} + sub_key = doc_type.pk + if sub_key in conditional_fields[key]: + continue + lst = [str(f.pk) for f in models.Format.objects.filter( + available=True, document_types__pk=doc_type.pk)] + if 'format_type' not in excluded_fields: + excluded_fields['format_type'] = [] + for k in lst: + if k not in excluded_fields['format_type']: + excluded_fields['format_type'].append(k) + conditional_fields[key][sub_key] = [] + conditional_fields[key][sub_key].append( + ('format_type', ",".join(lst))) + for doc_type in models.SourceType.objects.filter( + available=True, supports__pk__isnull=False).all(): + if key not in conditional_fields: + conditional_fields[key] = {} + lst = [str(f.pk) for f in models.SupportType.objects.filter( + available=True, document_types__pk=doc_type.pk)] + if 'support_type' not in excluded_fields: + excluded_fields['support_type'] = [] + for k in lst: + if k not in excluded_fields['support_type']: + excluded_fields['support_type'].append(k) + sub_key = doc_type.pk + if sub_key not in conditional_fields[key]: + conditional_fields[key][sub_key] = [] + conditional_fields[key][sub_key].append( + ('support_type', ",".join(lst))) + for k in excluded_fields: + excluded_fields[k] = ",".join(excluded_fields[k]) + all_values = { + "format_type": [list(tp) for tp in models.Format.get_types()], + "support_type": [list(tp) for tp in models.SupportType.get_types()] + } + return conditional_fields, excluded_fields, all_values + def clean(self): cleaned_data = self.cleaned_data if not cleaned_data.get('title', None) and \ diff --git a/ishtar_common/lookups.py b/ishtar_common/lookups.py index 3481ba1a9..66b43f3e4 100644 --- a/ishtar_common/lookups.py +++ b/ishtar_common/lookups.py @@ -156,3 +156,12 @@ class DocumentLookup(LookupChannel): internal_reference__icontains=q ) return self.model.objects.filter(query).order_by('title')[:20] + + +@register('source_type') +class SourceTypeLookup(LookupChannel): + model = models.SourceType + + def get_query(self, q, request): + query = Q(label__icontains=q) + return self.model.objects.filter(query).order_by('label')[:20] diff --git a/ishtar_common/migrations/0208_auto_20201126_1217.py b/ishtar_common/migrations/0208_auto_20201126_1217.py deleted file mode 100644 index 53b883075..000000000 --- a/ishtar_common/migrations/0208_auto_20201126_1217.py +++ /dev/null @@ -1,115 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11.27 on 2020-11-26 12:17 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('ishtar_common', '0207_auto_20201118_1210'), - ] - - operations = [ - migrations.AlterField( - model_name='document', - name='isbn', - field=models.CharField(blank=True, max_length=17, null=True, verbose_name='ISBN'), - ), - migrations.AlterField( - model_name='document', - name='issn', - field=models.CharField(blank=True, max_length=10, null=True, verbose_name='ISSN'), - ), - migrations.AlterField( - model_name='ishtarsiteprofile', - name='basefind_complete_identifier', - field=models.TextField(blank=True, default='', help_text='Formula to manage base find complete identifier.', verbose_name='Base find complete identifier'), - ), - migrations.AlterField( - model_name='ishtarsiteprofile', - name='basefind_custom_index', - field=models.TextField(blank=True, default='', help_text='Key to be used to manage base find custom index. Separate keys with a semicolon.', verbose_name='Base find custom index key'), - ), - migrations.AlterField( - model_name='ishtarsiteprofile', - name='container_complete_identifier', - field=models.TextField(blank=True, default='', help_text='Formula to manage container complete identifier.', verbose_name='Container complete identifier'), - ), - migrations.AlterField( - model_name='ishtarsiteprofile', - name='container_custom_index', - field=models.TextField(blank=True, default='', help_text='Key to be used to manage container custom index. Separate keys with a semicolon.', verbose_name='Container custom index key'), - ), - migrations.AlterField( - model_name='ishtarsiteprofile', - name='contextrecord_complete_identifier', - field=models.TextField(blank=True, default='', help_text='Formula to manage context record complete identifier.', verbose_name='Context record complete identifier'), - ), - migrations.AlterField( - model_name='ishtarsiteprofile', - name='contextrecord_custom_index', - field=models.TextField(blank=True, default='', help_text='Key to be used to manage context record custom index. Separate keys with a semicolon.', verbose_name='Context record custom index key'), - ), - migrations.AlterField( - model_name='ishtarsiteprofile', - name='document_complete_identifier', - field=models.TextField(blank=True, default='', help_text='Formula to manage document complete identifier.', verbose_name='Document complete identifier'), - ), - migrations.AlterField( - model_name='ishtarsiteprofile', - name='document_custom_index', - field=models.TextField(blank=True, default='', help_text='Key to be used to manage document custom index. Separate keys with a semicolon.', verbose_name='Document custom index key'), - ), - migrations.AlterField( - model_name='ishtarsiteprofile', - name='file_complete_identifier', - field=models.TextField(blank=True, default='', help_text='Formula to manage archaeological file complete identifier.', verbose_name='Archaeological file complete identifier'), - ), - migrations.AlterField( - model_name='ishtarsiteprofile', - name='file_custom_index', - field=models.TextField(blank=True, default='', help_text='Key to be used to manage archaeological file custom index. Separate keys with a semicolon.', verbose_name='Archaeological file custom index key'), - ), - migrations.AlterField( - model_name='ishtarsiteprofile', - name='find_complete_identifier', - field=models.TextField(blank=True, default='', help_text='Formula to manage find complete identifier.', verbose_name='Find complete identifier'), - ), - migrations.AlterField( - model_name='ishtarsiteprofile', - name='find_custom_index', - field=models.TextField(blank=True, default='', help_text='Key to be used to manage find custom index. Separate keys with a semicolon.', verbose_name='Find custom index key'), - ), - migrations.AlterField( - model_name='ishtarsiteprofile', - name='operation_complete_identifier', - field=models.TextField(blank=True, default='', help_text='Formula to manage operation complete identifier.', verbose_name='Operation complete identifier'), - ), - migrations.AlterField( - model_name='ishtarsiteprofile', - name='operation_custom_index', - field=models.TextField(blank=True, default='', help_text='Keys to be used to manage operation custom index. Separate keys with a semicolon.', verbose_name='Operation custom index key'), - ), - migrations.AlterField( - model_name='ishtarsiteprofile', - name='site_complete_identifier', - field=models.TextField(blank=True, default='', help_text='Formula to manage archaeological site complete identifier.', verbose_name='Archaeological site complete identifier'), - ), - migrations.AlterField( - model_name='ishtarsiteprofile', - name='site_custom_index', - field=models.TextField(blank=True, default='', help_text='Key to be used to manage archaeological site custom index. Separate keys with a semicolon.', verbose_name='Archaeological site custom index key'), - ), - migrations.AlterField( - model_name='ishtarsiteprofile', - name='warehouse_complete_identifier', - field=models.TextField(blank=True, default='', help_text='Formula to manage warehouse complete identifier.', verbose_name='Warehouse complete identifier'), - ), - migrations.AlterField( - model_name='ishtarsiteprofile', - name='warehouse_custom_index', - field=models.TextField(blank=True, default='', help_text='Key to be used to manage warehouse custom index. Separate keys with a semicolon.', verbose_name='Warehouse custom index key'), - ), - ] diff --git a/ishtar_common/migrations/0208_auto_20201126_1516.py b/ishtar_common/migrations/0208_auto_20201126_1516.py new file mode 100644 index 000000000..0bd51e4c0 --- /dev/null +++ b/ishtar_common/migrations/0208_auto_20201126_1516.py @@ -0,0 +1,125 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.27 on 2020-11-26 15:16 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ishtar_common', '0207_auto_20201118_1210'), + ] + + operations = [ + migrations.AddField( + model_name='format', + name='document_types', + field=models.ManyToManyField(blank=True, help_text='Only available for theses document types', related_name='formats', to='ishtar_common.SourceType'), + ), + migrations.AddField( + model_name='supporttype', + name='document_types', + field=models.ManyToManyField(blank=True, help_text='Only available for theses document types', related_name='supports', to='ishtar_common.SourceType'), + ), + migrations.AlterField( + model_name='document', + name='isbn', + field=models.CharField(blank=True, max_length=17, null=True, verbose_name='ISBN'), + ), + migrations.AlterField( + model_name='document', + name='issn', + field=models.CharField(blank=True, max_length=10, null=True, verbose_name='ISSN'), + ), + migrations.AlterField( + model_name='ishtarsiteprofile', + name='basefind_complete_identifier', + field=models.TextField(blank=True, default='', help_text='Formula to manage base find complete identifier.', verbose_name='Base find complete identifier'), + ), + migrations.AlterField( + model_name='ishtarsiteprofile', + name='basefind_custom_index', + field=models.TextField(blank=True, default='', help_text='Key to be used to manage base find custom index. Separate keys with a semicolon.', verbose_name='Base find custom index key'), + ), + migrations.AlterField( + model_name='ishtarsiteprofile', + name='container_complete_identifier', + field=models.TextField(blank=True, default='', help_text='Formula to manage container complete identifier.', verbose_name='Container complete identifier'), + ), + migrations.AlterField( + model_name='ishtarsiteprofile', + name='container_custom_index', + field=models.TextField(blank=True, default='', help_text='Key to be used to manage container custom index. Separate keys with a semicolon.', verbose_name='Container custom index key'), + ), + migrations.AlterField( + model_name='ishtarsiteprofile', + name='contextrecord_complete_identifier', + field=models.TextField(blank=True, default='', help_text='Formula to manage context record complete identifier.', verbose_name='Context record complete identifier'), + ), + migrations.AlterField( + model_name='ishtarsiteprofile', + name='contextrecord_custom_index', + field=models.TextField(blank=True, default='', help_text='Key to be used to manage context record custom index. Separate keys with a semicolon.', verbose_name='Context record custom index key'), + ), + migrations.AlterField( + model_name='ishtarsiteprofile', + name='document_complete_identifier', + field=models.TextField(blank=True, default='', help_text='Formula to manage document complete identifier.', verbose_name='Document complete identifier'), + ), + migrations.AlterField( + model_name='ishtarsiteprofile', + name='document_custom_index', + field=models.TextField(blank=True, default='', help_text='Key to be used to manage document custom index. Separate keys with a semicolon.', verbose_name='Document custom index key'), + ), + migrations.AlterField( + model_name='ishtarsiteprofile', + name='file_complete_identifier', + field=models.TextField(blank=True, default='', help_text='Formula to manage archaeological file complete identifier.', verbose_name='Archaeological file complete identifier'), + ), + migrations.AlterField( + model_name='ishtarsiteprofile', + name='file_custom_index', + field=models.TextField(blank=True, default='', help_text='Key to be used to manage archaeological file custom index. Separate keys with a semicolon.', verbose_name='Archaeological file custom index key'), + ), + migrations.AlterField( + model_name='ishtarsiteprofile', + name='find_complete_identifier', + field=models.TextField(blank=True, default='', help_text='Formula to manage find complete identifier.', verbose_name='Find complete identifier'), + ), + migrations.AlterField( + model_name='ishtarsiteprofile', + name='find_custom_index', + field=models.TextField(blank=True, default='', help_text='Key to be used to manage find custom index. Separate keys with a semicolon.', verbose_name='Find custom index key'), + ), + migrations.AlterField( + model_name='ishtarsiteprofile', + name='operation_complete_identifier', + field=models.TextField(blank=True, default='', help_text='Formula to manage operation complete identifier.', verbose_name='Operation complete identifier'), + ), + migrations.AlterField( + model_name='ishtarsiteprofile', + name='operation_custom_index', + field=models.TextField(blank=True, default='', help_text='Keys to be used to manage operation custom index. Separate keys with a semicolon.', verbose_name='Operation custom index key'), + ), + migrations.AlterField( + model_name='ishtarsiteprofile', + name='site_complete_identifier', + field=models.TextField(blank=True, default='', help_text='Formula to manage archaeological site complete identifier.', verbose_name='Archaeological site complete identifier'), + ), + migrations.AlterField( + model_name='ishtarsiteprofile', + name='site_custom_index', + field=models.TextField(blank=True, default='', help_text='Key to be used to manage archaeological site custom index. Separate keys with a semicolon.', verbose_name='Archaeological site custom index key'), + ), + migrations.AlterField( + model_name='ishtarsiteprofile', + name='warehouse_complete_identifier', + field=models.TextField(blank=True, default='', help_text='Formula to manage warehouse complete identifier.', verbose_name='Warehouse complete identifier'), + ), + migrations.AlterField( + model_name='ishtarsiteprofile', + name='warehouse_custom_index', + field=models.TextField(blank=True, default='', help_text='Key to be used to manage warehouse custom index. Separate keys with a semicolon.', verbose_name='Warehouse custom index key'), + ), + ] diff --git a/ishtar_common/models.py b/ishtar_common/models.py index e251fee89..ffe302454 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -2636,6 +2636,11 @@ post_delete.connect(post_save_cache, sender=SourceType) class SupportType(GeneralType): + document_types = models.ManyToManyField( + "SourceType", blank=True, related_name='supports', + help_text=_("Only available for theses document types") + ) + class Meta: verbose_name = _("Support type") verbose_name_plural = _("Support types") @@ -2651,6 +2656,10 @@ class Format(GeneralType): help_text=_("Template to insert an iframe for this format. Use django " "template with a {{document}} variable matching the " "current document.")) + document_types = models.ManyToManyField( + "SourceType", blank=True, related_name='formats', + help_text=_("Only available for theses document types") + ) class Meta: verbose_name = _("Format type") diff --git a/ishtar_common/static/js/ishtar.js b/ishtar_common/static/js/ishtar.js index fcaa73053..6528d3797 100644 --- a/ishtar_common/static/js/ishtar.js +++ b/ishtar_common/static/js/ishtar.js @@ -1856,3 +1856,22 @@ var is_valid_issn = function(str) { } return (check == str[str.length-1].toUpperCase()); } + +var update_select_widget = function(input_name, values, only_values, excluded_values){ + cvalue = $("#id_" + input_name).val(); + var options = ""; + for (var idx in values){ + var option = values[idx]; + if (!(option[0] && option[0] != cvalue + && ((excluded_values && + excluded_values.indexOf(option[0]) != -1) || + (only_values && only_values.indexOf(option[0]) == -1) + ))){ + var selected = ""; + if (option[0] == cvalue) selected = " selected"; + options += ""; + } + } + $("#id_" + input_name).html(options); +}; \ No newline at end of file diff --git a/ishtar_common/templates/blocks/bs_form_snippet.html b/ishtar_common/templates/blocks/bs_form_snippet.html index e24220005..3d84ce3dc 100644 --- a/ishtar_common/templates/blocks/bs_form_snippet.html +++ b/ishtar_common/templates/blocks/bs_form_snippet.html @@ -1,5 +1,5 @@ {% load i18n from_dict %} -{% if form.non_field_errors %} +{% if form.non_field_errors and not no_error %} diff --git a/ishtar_common/templates/ishtar/forms/document.html b/ishtar_common/templates/ishtar/forms/document.html index ed5a39daf..8e2683a03 100644 --- a/ishtar_common/templates/ishtar/forms/document.html +++ b/ishtar_common/templates/ishtar/forms/document.html @@ -13,18 +13,18 @@
{% if form.non_field_errors or form.errors %}
-
- {% trans "Error on validation. Check all your fields. Modification not saved." %} +
+ {% trans "Error on validation. Check all your fields. Modification not saved." %} +
+ {% for key, error_details in form.errors.items %} + {% with field=key|from_dict:form.fields %}{{ field.label }}{{error_details}}{% endwith %} + {% endfor %}
- {% for error in form.non_field_errors %} -

{{ error }}

- {% endfor %} - {% for key, error_details in form.errors.items %} - {% with field=key|from_dict:form.fields %}{{ field.label }}{{error_details}}{% endwith %} - {% endfor %} -
{% endif %} - {% bs_form form %} + {% if item_related_label %}
+ {% trans "Related items" %}{% trans ":" %} {{ item_related_label }} +
{% endif %} + {% bs_form form 0 True %}
{% endblock %} diff --git a/ishtar_common/templatetags/table_form.py b/ishtar_common/templatetags/table_form.py index 5da2171d0..d5b20da26 100644 --- a/ishtar_common/templatetags/table_form.py +++ b/ishtar_common/templatetags/table_form.py @@ -8,11 +8,12 @@ register = Library() @register.inclusion_tag('blocks/bs_form_snippet.html', takes_context=True) -def bs_form(context, form, position=0): +def bs_form(context, form, position=0, no_error=False): user = context['user'] show_field_number = user.ishtaruser and user.ishtaruser.show_field_number() return {'form': form, 'odd': position % 2, - 'show_field_number': show_field_number} + 'show_field_number': show_field_number, + 'no_error': no_error} @register.inclusion_tag('blocks/bs_compact_form_snippet.html', diff --git a/ishtar_common/views.py b/ishtar_common/views.py index 704894d52..ceb8db200 100644 --- a/ishtar_common/views.py +++ b/ishtar_common/views.py @@ -1923,7 +1923,7 @@ display_document = display_item(models.Document) document_search_wizard = wizards.DocumentSearch.as_view( [('selec-document_search', forms.DocumentFormSelection)], - label=_(u"Document: search"), + label=_("Document: search"), url_name='search-document', ) @@ -2016,12 +2016,21 @@ class DocumentEditView(DocumentFormMixin, UpdateView): for related_item in getattr(document, k).all(): key = "{}_{}_main_image".format(k, related_item.pk) kwargs["main_items_fields"][k].append( - (key, u"{} - {}".format( - _(u"Main image for"), related_item))) + (key, "{} - {}".format( + _("Main image for"), related_item))) if related_item.main_image == document: initial[key] = True kwargs['initial'] = initial kwargs["user"] = self.request.user + self.document = document + return kwargs + + def get_context_data(self, **kwargs): + kwargs = super(DocumentEditView, self).get_context_data(**kwargs) + rel = self.document.cache_related_label + if len(rel) == 1000: # truncated + rel += " (...)" + kwargs["item_related_label"] = rel return kwargs -- cgit v1.2.3