summaryrefslogtreecommitdiff
path: root/ishtar_common
diff options
context:
space:
mode:
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
commit30bf32d6768f3c013b44e1ed76d94f9954d6e565 (patch)
tree32524e3090ec9ab19d15da5aa8f82b713597f0dd /ishtar_common
parentfda191a63534f13470844bf5d7462f260801e318 (diff)
downloadIshtar-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.py6
-rw-r--r--ishtar_common/migrations/0208_auto_20201126_1217.py115
-rw-r--r--ishtar_common/models.py4
-rw-r--r--ishtar_common/static/js/ishtar.js60
-rw-r--r--ishtar_common/templates/ishtar/forms/document.html12
-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.html25
-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.py57
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