diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2020-11-26 13:06:35 +0100 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2021-02-28 12:15:21 +0100 |
commit | 30bf32d6768f3c013b44e1ed76d94f9954d6e565 (patch) | |
tree | 32524e3090ec9ab19d15da5aa8f82b713597f0dd /ishtar_common | |
parent | fda191a63534f13470844bf5d7462f260801e318 (diff) | |
download | Ishtar-30bf32d6768f3c013b44e1ed76d94f9954d6e565.tar.bz2 Ishtar-30bf32d6768f3c013b44e1ed76d94f9954d6e565.zip |
Refactor custom widgets templates - ISSN/ISBN check
Diffstat (limited to 'ishtar_common')
-rw-r--r-- | ishtar_common/forms_common.py | 6 | ||||
-rw-r--r-- | ishtar_common/migrations/0208_auto_20201126_1217.py | 115 | ||||
-rw-r--r-- | ishtar_common/models.py | 4 | ||||
-rw-r--r-- | ishtar_common/static/js/ishtar.js | 60 | ||||
-rw-r--r-- | ishtar_common/templates/ishtar/forms/document.html | 12 | ||||
-rw-r--r-- | ishtar_common/templates/widgets/CentimeterMeterWidget.html (renamed from ishtar_common/templates/blocks/CentimeterMeterWidget.html) | 0 | ||||
-rw-r--r-- | ishtar_common/templates/widgets/CheckTextWidget.html | 25 | ||||
-rw-r--r-- | ishtar_common/templates/widgets/GramKilogramWidget.html (renamed from ishtar_common/templates/blocks/GramKilogramWidget.html) | 0 | ||||
-rw-r--r-- | ishtar_common/templates/widgets/SquareMeterWidget.html (renamed from ishtar_common/templates/blocks/SquareMeterWidget.html) | 0 | ||||
-rw-r--r-- | ishtar_common/widgets.py | 57 |
10 files changed, 244 insertions, 35 deletions
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/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 %} <h2>{{page_name}}</h2> <div class='form{% if not form.SEARCH_AND_SELECT %} container{% endif %}'> + {% if form.non_field_errors or form.errors %} + <div class="alert alert-danger"> + <div><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> + {% trans "Error on validation. Check all your fields. Modification not saved." %} + </div> {% for error in form.non_field_errors %} <p>{{ error }}</p> {% endfor %} + {% for key, error_details in form.errors.items %} + {% with field=key|from_dict:form.fields %}<strong>{{ field.label }}</strong>{{error_details}}{% endwith %} + {% endfor %} +</div> + {% endif %} {% bs_form form %} </div> {% endblock %} diff --git a/ishtar_common/templates/blocks/CentimeterMeterWidget.html b/ishtar_common/templates/widgets/CentimeterMeterWidget.html index 00c1614b5..00c1614b5 100644 --- a/ishtar_common/templates/blocks/CentimeterMeterWidget.html +++ b/ishtar_common/templates/widgets/CentimeterMeterWidget.html 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 @@ +<div class="input-group"> + <input class="area_widget form-control" type="text"{{final_attrs|safe}}> + <div class="input-group-append"> + <div class="input-group-text" id="check-{{id}}"> + <i class="text-success fa fa-check"></i> + <i class="text-danger fa fa-times"></i> + </div> + </div> +</div> +<script type="text/javascript"><!--// + $("#check-{{id}} .text-danger").hide(); + $("#check-{{id}} .text-success").hide(); + function evaluate_{{safe_id}}(){ + value = $("#{{id}}").val(); + if ({{validator}}(value)){ + $("#check-{{id}} .text-danger").hide(); + $("#check-{{id}} .text-success").show(); + } else { + $("#check-{{id}} .text-danger").show(); + $("#check-{{id}} .text-success").hide(); + } + } + $("#{{id}}").keyup(evaluate_{{safe_id}}); + $(document).ready(evaluate_{{safe_id}}()); +//--></script> diff --git a/ishtar_common/templates/blocks/GramKilogramWidget.html b/ishtar_common/templates/widgets/GramKilogramWidget.html index 27c066d13..27c066d13 100644 --- a/ishtar_common/templates/blocks/GramKilogramWidget.html +++ b/ishtar_common/templates/widgets/GramKilogramWidget.html diff --git a/ishtar_common/templates/blocks/SquareMeterWidget.html b/ishtar_common/templates/widgets/SquareMeterWidget.html index 09e93b425..09e93b425 100644 --- a/ishtar_common/templates/blocks/SquareMeterWidget.html +++ b/ishtar_common/templates/widgets/SquareMeterWidget.html 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 |