From 30bf32d6768f3c013b44e1ed76d94f9954d6e565 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Thu, 26 Nov 2020 13:06:35 +0100 Subject: Refactor custom widgets templates - ISSN/ISBN check --- ishtar_common/forms_common.py | 6 +- .../migrations/0208_auto_20201126_1217.py | 115 +++++++++++++++++++++ ishtar_common/models.py | 4 +- ishtar_common/static/js/ishtar.js | 60 +++++++++++ .../templates/blocks/CentimeterMeterWidget.html | 21 ---- .../templates/blocks/GramKilogramWidget.html | 21 ---- .../templates/blocks/SquareMeterWidget.html | 21 ---- ishtar_common/templates/ishtar/forms/document.html | 12 ++- .../templates/widgets/CentimeterMeterWidget.html | 21 ++++ .../templates/widgets/CheckTextWidget.html | 25 +++++ .../templates/widgets/GramKilogramWidget.html | 21 ++++ .../templates/widgets/SquareMeterWidget.html | 21 ++++ ishtar_common/widgets.py | 57 +++++----- 13 files changed, 307 insertions(+), 98 deletions(-) create mode 100644 ishtar_common/migrations/0208_auto_20201126_1217.py delete mode 100644 ishtar_common/templates/blocks/CentimeterMeterWidget.html delete mode 100644 ishtar_common/templates/blocks/GramKilogramWidget.html delete mode 100644 ishtar_common/templates/blocks/SquareMeterWidget.html create mode 100644 ishtar_common/templates/widgets/CentimeterMeterWidget.html create mode 100644 ishtar_common/templates/widgets/CheckTextWidget.html create mode 100644 ishtar_common/templates/widgets/GramKilogramWidget.html create mode 100644 ishtar_common/templates/widgets/SquareMeterWidget.html (limited to 'ishtar_common') diff --git a/ishtar_common/forms_common.py b/ishtar_common/forms_common.py index 8169fb64f..c76577e65 100644 --- a/ishtar_common/forms_common.py +++ b/ishtar_common/forms_common.py @@ -1326,10 +1326,12 @@ class DocumentForm(forms.ModelForm, CustomForm, ManageOldType): required=False) issn = forms.CharField( label=_("ISSN"), - validators=[validators.MaxLengthValidator(8)], required=False) + widget=widgets.ISSNWidget, + validators=[validators.MaxLengthValidator(9)], required=False) isbn = forms.CharField( label=_("ISBN"), - validators=[validators.MaxLengthValidator(13)], required=False) + widget=widgets.ISBNWidget, + validators=[validators.MaxLengthValidator(17)], required=False) source = widgets.ModelJQueryAutocompleteField( label=_("Source"), model=models.Document, required=False) diff --git a/ishtar_common/migrations/0208_auto_20201126_1217.py b/ishtar_common/migrations/0208_auto_20201126_1217.py new file mode 100644 index 000000000..53b883075 --- /dev/null +++ b/ishtar_common/migrations/0208_auto_20201126_1217.py @@ -0,0 +1,115 @@ +# -*- 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/models.py b/ishtar_common/models.py index 1762674e8..e251fee89 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -3015,8 +3015,8 @@ class Document(BaseHistorizedItem, CompleteIdentifierItem, OwnPerms, ImageModel, blank=True) language = models.ForeignKey( Language, verbose_name=_("Language"), blank=True, null=True) - issn = models.CharField(_("ISSN"), blank=True, null=True, max_length=8) - isbn = models.CharField(_("ISBN"), blank=True, null=True, max_length=13) + issn = models.CharField(_("ISSN"), blank=True, null=True, max_length=10) + isbn = models.CharField(_("ISBN"), blank=True, null=True, max_length=17) source = models.ForeignKey("Document", verbose_name=_("Source"), blank=True, null=True) source_free_input = models.CharField( diff --git a/ishtar_common/static/js/ishtar.js b/ishtar_common/static/js/ishtar.js index 655a91eb4..fcaa73053 100644 --- a/ishtar_common/static/js/ishtar.js +++ b/ishtar_common/static/js/ishtar.js @@ -1796,3 +1796,63 @@ var render_stats = function(stats_values, name){ jqvalues, stats_options ); }; + +var is_valid_isbn = function(str) { + var sum, weight, digit, check, i; + + str = str.replace(/[^0-9X]/gi, ''); + + if (str.length != 10 && str.length != 13) { + return false; + } + + if (str.length == 13) { + sum = 0; + for (i = 0; i < 12; i++) { + digit = parseInt(str[i]); + if (i % 2 == 1) { + sum += 3*digit; + } else { + sum += digit; + } + } + check = (10 - (sum % 10)) % 10; + return (check == str[str.length-1]); + } + + if (str.length == 10) { + weight = 10; + sum = 0; + for (i = 0; i < 9; i++) { + digit = parseInt(str[i]); + sum += weight*digit; + weight--; + } + check = (11 - (sum % 11)) % 11 + if (check == 10) { + check = 'X'; + } + return (check == str[str.length-1].toUpperCase()); + } +} + +var is_valid_issn = function(str) { + var sum, weight, digit, check, i; + + str = str.replace(/[^0-9X]/gi, ''); + + if (str.length != 8) { + return false; + } + + sum = 0; + for (i = 0; i < 7; i++) { + digit = parseInt(str[i]); + sum += digit * (8 - i) + } + check = 11 - sum % 11; + if (check == 10) { + check = 'X'; + } + return (check == str[str.length-1].toUpperCase()); +} diff --git a/ishtar_common/templates/blocks/CentimeterMeterWidget.html b/ishtar_common/templates/blocks/CentimeterMeterWidget.html deleted file mode 100644 index 00c1614b5..000000000 --- a/ishtar_common/templates/blocks/CentimeterMeterWidget.html +++ /dev/null @@ -1,21 +0,0 @@ -
- -
-
- {{unit}} (0 m) -
-
-
- diff --git a/ishtar_common/templates/blocks/GramKilogramWidget.html b/ishtar_common/templates/blocks/GramKilogramWidget.html deleted file mode 100644 index 27c066d13..000000000 --- a/ishtar_common/templates/blocks/GramKilogramWidget.html +++ /dev/null @@ -1,21 +0,0 @@ -
- -
-
- {{unit}} (0 kg) -
-
-
- diff --git a/ishtar_common/templates/blocks/SquareMeterWidget.html b/ishtar_common/templates/blocks/SquareMeterWidget.html deleted file mode 100644 index 09e93b425..000000000 --- a/ishtar_common/templates/blocks/SquareMeterWidget.html +++ /dev/null @@ -1,21 +0,0 @@ -
- -
-
- {{unit}} (0 ha) -
-
-
- diff --git a/ishtar_common/templates/ishtar/forms/document.html b/ishtar_common/templates/ishtar/forms/document.html index b3a9a8e15..ed5a39daf 100644 --- a/ishtar_common/templates/ishtar/forms/document.html +++ b/ishtar_common/templates/ishtar/forms/document.html @@ -1,5 +1,5 @@ {% extends "base.html" %} -{% load i18n inline_formset table_form %} +{% load i18n inline_formset table_form from_dict %} {% block extra_head %} {{form.media}} {% endblock %} @@ -11,9 +11,19 @@ {% block content %}

{{page_name}}

+ {% if form.non_field_errors or form.errors %} +
+
+ {% trans "Error on validation. Check all your fields. Modification not saved." %} +
{% 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 %}
{% endblock %} diff --git a/ishtar_common/templates/widgets/CentimeterMeterWidget.html b/ishtar_common/templates/widgets/CentimeterMeterWidget.html new file mode 100644 index 000000000..00c1614b5 --- /dev/null +++ b/ishtar_common/templates/widgets/CentimeterMeterWidget.html @@ -0,0 +1,21 @@ +
+ +
+
+ {{unit}} (0 m) +
+
+
+ diff --git a/ishtar_common/templates/widgets/CheckTextWidget.html b/ishtar_common/templates/widgets/CheckTextWidget.html new file mode 100644 index 000000000..593fcbb5b --- /dev/null +++ b/ishtar_common/templates/widgets/CheckTextWidget.html @@ -0,0 +1,25 @@ +
+ +
+
+ + +
+
+
+ diff --git a/ishtar_common/templates/widgets/GramKilogramWidget.html b/ishtar_common/templates/widgets/GramKilogramWidget.html new file mode 100644 index 000000000..27c066d13 --- /dev/null +++ b/ishtar_common/templates/widgets/GramKilogramWidget.html @@ -0,0 +1,21 @@ +
+ +
+
+ {{unit}} (0 kg) +
+
+
+ diff --git a/ishtar_common/templates/widgets/SquareMeterWidget.html b/ishtar_common/templates/widgets/SquareMeterWidget.html new file mode 100644 index 000000000..09e93b425 --- /dev/null +++ b/ishtar_common/templates/widgets/SquareMeterWidget.html @@ -0,0 +1,21 @@ +
+ +
+
+ {{unit}} (0 ha) +
+
+
+ diff --git a/ishtar_common/widgets.py b/ishtar_common/widgets.py index 93352ccf3..724e5d08c 100644 --- a/ishtar_common/widgets.py +++ b/ishtar_common/widgets.py @@ -475,57 +475,54 @@ class ImageFileInput(ClearableFileInput): return value -class SquareMeterWidget(forms.TextInput): +class CustomWidget(forms.TextInput): + TEMPLATE = "" + EXTRA_DCT = {} + def render(self, name, value, attrs=None, renderer=None): if not value: value = u"" final_attrs = flatatt( self.build_attrs(attrs, {"name": name, "value": value})) dct = {'final_attrs': final_attrs, - 'unit': settings.SURFACE_UNIT_LABEL, 'id': attrs['id'], "safe_id": attrs['id'].replace('-', '_')} - t = loader.get_template('blocks/SquareMeterWidget.html') + dct.update(self.EXTRA_DCT) + t = loader.get_template(self.TEMPLATE) rendered = t.render(dct) return mark_safe(rendered) -class GramKilogramWidget(forms.TextInput): - def render(self, name, value, attrs=None, renderer=None): - if not value: - value = u"" - final_attrs = flatatt( - self.build_attrs(attrs, {"name": name, "value": value})) - dct = {'final_attrs': final_attrs, - 'unit': u"g", - 'id': attrs['id'], - "safe_id": attrs['id'].replace('-', '_')} - t = loader.get_template('blocks/GramKilogramWidget.html') - rendered = t.render(dct) - return mark_safe(rendered) +class SquareMeterWidget(CustomWidget): + TEMPLATE = 'widgets/SquareMeterWidget.html' + EXTRA_DCT = {'unit': settings.SURFACE_UNIT_LABEL} -class CentimeterMeterWidget(forms.TextInput): - def render(self, name, value, attrs=None, renderer=None): - if not value: - value = u"" - final_attrs = flatatt( - self.build_attrs(attrs, {"name": name, "value": value})) - dct = {'final_attrs': final_attrs, - 'unit': u"cm", - 'id': attrs['id'], - "safe_id": attrs['id'].replace('-', '_')} - t = loader.get_template('blocks/CentimeterMeterWidget.html') - rendered = t.render(dct) - return mark_safe(rendered) +class GramKilogramWidget(CustomWidget): + TEMPLATE = 'widgets/GramKilogramWidget.html' + EXTRA_DCT = {'unit': "g"} -AreaWidget = forms.TextInput +class CentimeterMeterWidget(CustomWidget): + TEMPLATE = 'widgets/CentimeterMeterWidget.html' + EXTRA_DCT = {'unit': "cm"} + +AreaWidget = forms.TextInput if settings.SURFACE_UNIT == 'square-metre': AreaWidget = SquareMeterWidget +class ISBNWidget(CustomWidget): + TEMPLATE = 'widgets/CheckTextWidget.html' + EXTRA_DCT = {'validator': "is_valid_isbn"} + + +class ISSNWidget(CustomWidget): + TEMPLATE = 'widgets/CheckTextWidget.html' + EXTRA_DCT = {'validator': "is_valid_issn"} + + class CheckboxInput(forms.CheckboxInput): NO_FORM_CONTROL = True -- cgit v1.2.3