diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2021-07-07 09:39:29 +0200 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2022-07-08 09:58:47 +0200 |
commit | 54d83f529206ba9e62e376dae922aa397d516790 (patch) | |
tree | a324f582ed88df9fa6230809600a665baacde36c | |
parent | 96ad40f28ff3e17f8173ec8de8b63ef6056e6e55 (diff) | |
download | Ishtar-54d83f529206ba9e62e376dae922aa397d516790.tar.bz2 Ishtar-54d83f529206ba9e62e376dae922aa397d516790.zip |
Preventive file - inline forms
-rw-r--r-- | DEVELOP.md | 7 | ||||
-rw-r--r-- | archaeological_files/forms.py | 87 | ||||
-rw-r--r-- | archaeological_files/templates/ishtar/forms/preventive_detail.html | 45 | ||||
-rw-r--r-- | archaeological_files/views.py | 9 | ||||
-rw-r--r-- | ishtar_common/static/js/ishtar.js | 23 | ||||
-rw-r--r-- | ishtar_common/templates/base.html | 4 | ||||
-rw-r--r-- | ishtar_common/templates/blocks/bs_field_snippet.html | 2 | ||||
-rw-r--r-- | ishtar_common/templates/blocks/bs_formset_snippet.html | 20 | ||||
-rw-r--r-- | ishtar_common/templates/ishtar/forms/base_form.html | 5 |
9 files changed, 160 insertions, 42 deletions
diff --git a/DEVELOP.md b/DEVELOP.md index e91ca3ccf..2c9c6aaf3 100644 --- a/DEVELOP.md +++ b/DEVELOP.md @@ -42,10 +42,12 @@ cd ishtar ISHTAR_PATH=`pwd` cp example_project/local_settings.py.sample example_project/local_settings.py editor example_project/local_settings.py -# edit settings: SECRET_KEY, DATABASE +# edit settings: SECRET_KEY, DATABASE, comment STATIC_URL and MEDIA_URL ``` ``` python +SECRET_KEY = "change-this-secret" + DATABASES = { 'default': { 'NAME': 'ishtar', @@ -56,6 +58,9 @@ DATABASES = { 'PASSWORD': 'mypassword', }, } + +# STATIC_URL = BASE_URL + 'static/' +# MEDIA_URL = BASE_URL + 'mydomain/media/' ``` ``` bash diff --git a/archaeological_files/forms.py b/archaeological_files/forms.py index 51d1fdeb0..1710a5560 100644 --- a/archaeological_files/forms.py +++ b/archaeological_files/forms.py @@ -528,14 +528,20 @@ class FileFormPreventiveDetail(forms.ModelForm, CustomForm, ManageOldType): pk = forms.IntegerField(label="", required=False, widget=forms.HiddenInput) start_date = forms.DateField( - label=_("Start date"), widget=DatePicker, required=False + label=_("Start date"), required=False, + widget=DatePicker(attrs={"bs_col_width": "col-6 col-lg-3"}), + ) + end_date = forms.DateField( + label=_("End date"), required=False, + widget=DatePicker(attrs={"bs_col_width": "col-6 col-lg-3"}), ) - end_date = forms.DateField(label=_("End date"), widget=DatePicker, required=False) ground_start_date = forms.DateField( - label=_("Ground start date"), widget=DatePicker, required=False + label=_("Ground start date"), required=False, + widget=DatePicker(attrs={"bs_col_width": "col-6 col-lg-3"}), ) ground_end_date = forms.DateField( - label=_("Ground end date"), widget=DatePicker, required=False + label=_("Ground end date"), required=False, + widget=DatePicker(attrs={"bs_col_width": "col-6 col-lg-3"}), ) study_period = forms.CharField( label=_("Study period"), @@ -543,10 +549,11 @@ class FileFormPreventiveDetail(forms.ModelForm, CustomForm, ManageOldType): required=False, ) execution_report_date = forms.DateField( - label=_("Execution report date"), widget=DatePicker, required=False + label=_("Execution report date"), required=False, + widget=DatePicker(attrs={"bs_col_width": "col-6 col-lg-3"}), ) total_developed_surface = forms.FloatField( - widget=widgets.AreaWidget, + widget=widgets.AreaWidget(attrs={"bs_col_width": "col-6 col-lg-3"}), label=_("Total developed surface (m2)"), required=False, validators=[ @@ -556,7 +563,7 @@ class FileFormPreventiveDetail(forms.ModelForm, CustomForm, ManageOldType): ) total_surface = forms.FloatField( required=False, - widget=widgets.AreaWidget, + widget=widgets.AreaWidget(attrs={"bs_col_width": "col-6 col-lg-3"}), label=_("Total surface (m2)"), validators=[ validators.MinValueValidator(0), @@ -565,7 +572,7 @@ class FileFormPreventiveDetail(forms.ModelForm, CustomForm, ManageOldType): ) linear_meter = forms.IntegerField( label=_("Linear meter (m)"), required=False, - widget=widgets.MeterKilometerWidget, + widget=widgets.MeterKilometerWidget(attrs={"bs_col_width": "col-6 col-lg-3"}), ) def __init__(self, *args, **kwargs): @@ -586,17 +593,32 @@ class FileBaseFormset(forms.BaseModelFormSet): self.queryset = self.model.objects.filter(file_id=self.instance.pk) +INLINE_JOB_FIELDS = ["man_by_day_planned", "days_planned", "man_by_day_worked", + "days_worked"] +JOB_WIDGETS = { + "man_by_day_planned": forms.NumberInput(attrs={"class": "w-50 form-planned"}), + "days_planned": forms.NumberInput(attrs={"class": "w-50 form-planned"}), + "man_by_day_worked": forms.NumberInput(attrs={"class": "w-50 form-worked"}), + "days_worked": forms.NumberInput(attrs={"class": "w-50 form-worked"}) +} + +JOB_LABELS = { + "man_by_day_planned": _("Man by day"), + "days_planned": _("Days"), + "man_by_day_worked": _("Man by day"), + "days_worked": _("Days"), +} + class PreventiveFileJobForm(forms.ModelForm): file_id = forms.IntegerField(widget=forms.HiddenInput) - job = forms.ChoiceField(choices=[]) - man_by_day_planned = forms.FloatField(_("Man by day - planned"), required=False) - days_planned = forms.FloatField(_("Days - planned"), required=False) - man_by_day_worked = forms.FloatField(_("Man by day - worked"), required=False) - days_worked = forms.FloatField(_("Days - worked"), required=False) class Meta: model = models.PreventiveFileJob + fields = ["job"] + INLINE_JOB_FIELDS exclude = ["file"] + widgets = JOB_WIDGETS + labels = JOB_LABELS + class PreventiveFileJobBaseFormSet(FileBaseFormset): @@ -605,22 +627,20 @@ class PreventiveFileJobBaseFormSet(FileBaseFormset): PreventiveFileJobFormSet = formset_factory( PreventiveFileJobForm, formset=PreventiveFileJobBaseFormSet, can_delete=True) -PreventiveFileJobFormSet.form_label = _("Preventive - Jobs") +PreventiveFileJobFormSet.form_label = _("Jobs") PreventiveFileJobFormSet.form_admin_name = _("Preventive file - 030 - Jobs") PreventiveFileJobFormSet.form_slug = "preventive-030-jobs" +PreventiveFileJobFormSet.dynamic_add = True class PreventiveFileGroundJobForm(forms.ModelForm): file_id = forms.IntegerField(widget=forms.HiddenInput) - ground_job = forms.ChoiceField(choices=[]) - man_by_day_planned = forms.FloatField(_("Man by day - planned"), required=False) - days_planned = forms.FloatField(_("Days - planned"), required=False) - man_by_day_worked = forms.FloatField(_("Man by day - worked"), required=False) - days_worked = forms.FloatField(_("Days - worked"), required=False) class Meta: model = models.PreventiveFileGroundJob - exclude = ["file"] + fields = ["job"] + INLINE_JOB_FIELDS + widgets = JOB_WIDGETS + labels = JOB_LABELS class PreventiveFileGroundJobBaseFormSet(FileBaseFormset): @@ -631,24 +651,22 @@ PreventiveFileGroundJobFormSet = formset_factory( PreventiveFileGroundJobForm, formset=PreventiveFileGroundJobBaseFormSet, can_delete=True ) -PreventiveFileGroundJobFormSet.form_label = _("Preventive - Ground jobs") +PreventiveFileGroundJobFormSet.form_label = _("Ground jobs") PreventiveFileGroundJobFormSet.form_admin_name = _( "Preventive file - 040 - Ground jobs" ) PreventiveFileGroundJobFormSet.form_slug = "preventive-040-ground-jobs" +PreventiveFileGroundJobFormSet.dynamic_add = True class PreventiveFileEquipmentForm(forms.ModelForm): file_id = forms.IntegerField(widget=forms.HiddenInput) - equipment = forms.ChoiceField(choices=[]) - man_by_day_planned = forms.FloatField(_("Man by day - planned"), required=False) - days_planned = forms.FloatField(_("Days - planned"), required=False) - man_by_day_worked = forms.FloatField(_("Man by day - worked"), required=False) - days_worked = forms.FloatField(_("Days - worked"), required=False) class Meta: model = models.PreventiveFileEquipmentCost - exclude = ["file"] + fields = ["equipment_cost"] + INLINE_JOB_FIELDS + widgets = JOB_WIDGETS + labels = JOB_LABELS class PreventiveFileEquipmentBaseFormSet(FileBaseFormset): @@ -659,22 +677,20 @@ PreventiveFileEquipmentFormSet = formset_factory( PreventiveFileEquipmentForm, formset=PreventiveFileEquipmentBaseFormSet, can_delete=True ) -PreventiveFileEquipmentFormSet.form_label = _("Preventive - Equipment") +PreventiveFileEquipmentFormSet.form_label = _("Equipment") PreventiveFileEquipmentFormSet.form_admin_name = _("Preventive file - 050 - Equipments") PreventiveFileEquipmentFormSet.form_slug = "preventive-050-equipments" +PreventiveFileEquipmentFormSet.dynamic_add = True class PreventiveFileTechnicalServiceForm(forms.ModelForm): file_id = forms.IntegerField(widget=forms.HiddenInput) - technical_service = forms.ChoiceField(choices=[]) - man_by_day_planned = forms.FloatField(_("Man by day - planned"), required=False) - days_planned = forms.FloatField(_("Days - planned"), required=False) - man_by_day_worked = forms.FloatField(_("Man by day - worked"), required=False) - days_worked = forms.FloatField(_("Days - worked"), required=False) class Meta: model = models.PreventiveFileTechnicalServiceCost - exclude = ["file"] + fields = ["technical_service_cost"] + INLINE_JOB_FIELDS + widgets = JOB_WIDGETS + labels = JOB_LABELS class PreventiveFileTechnicalServiceBaseFormSet(FileBaseFormset): @@ -685,11 +701,12 @@ PreventiveFileTechnicalServiceFormSet = formset_factory( PreventiveFileTechnicalServiceForm, formset=PreventiveFileTechnicalServiceBaseFormSet, can_delete=True ) -PreventiveFileTechnicalServiceFormSet.form_label = _("Preventive - Technical Services") +PreventiveFileTechnicalServiceFormSet.form_label = _("Technical Services") PreventiveFileTechnicalServiceFormSet.form_admin_name = _( "Preventive file - 060 - TechnicalServices" ) PreventiveFileTechnicalServiceFormSet.form_slug = "preventive-060-technical_services" +PreventiveFileTechnicalServiceFormSet.dynamic_add = True class AdministrativeActFileModifySelect(TableSelect): diff --git a/archaeological_files/templates/ishtar/forms/preventive_detail.html b/archaeological_files/templates/ishtar/forms/preventive_detail.html index 3cdfb3da0..20adcccfb 100644 --- a/archaeological_files/templates/ishtar/forms/preventive_detail.html +++ b/archaeological_files/templates/ishtar/forms/preventive_detail.html @@ -1,2 +1,45 @@ {% extends "ishtar/forms/base_form.html" %} -{% load i18n %} +{% load i18n table_form %} + +{% block bs_form_inlines %} +<div class="card"> + <div class="card-body"> + <div class="w-100 pb-3 text-center"> + <div class="btn-group btn-group-toggle" data-toggle="buttons"> + <label class="btn btn-lg btn-secondary active"> + <input value="true" type="radio" name="planned-toggle" id="planned-toggle-true" autocomplete="off" checked> + {% trans "Planned" %} + </label> + <label class="btn btn-lg btn-secondary"> + <input value="false" type="radio" name="planned-toggle" id="planned-toggle-false" autocomplete="off"> + {% trans "Worked" %} + </label> + </div> + </div> + <div class="w-100 pb-3 text-center"> + <button class="btn btn-secondary btn-sm form-planned" type="button">{% trans "Add default costs" %}</button> + </div> + <div class="w-100 pb-3 text-center"> + <button class="btn btn-secondary btn-sm form-worked" type="button">{% trans "Copy planned costs" %}</button> + </div> + {{block.super}} + </div> +</div> +{% endblock %} + +{# <script type='text/javascript'> #} +{% block end_js %} + {{block.super}} + var check_planned_value = function() { + if (this.value == 'false'){ + $(".form-planned").parent().hide() + $(".form-worked").parent().show() + } else { + $(".form-planned").parent().show() + $(".form-worked").parent().hide() + } + }; + $('input[type=radio][name=planned-toggle]').change(check_planned_value); + $(document).ready(check_planned_value); +{% endblock %} +{# </script> #} diff --git a/archaeological_files/views.py b/archaeological_files/views.py index a927a94e6..366ef3754 100644 --- a/archaeological_files/views.py +++ b/archaeological_files/views.py @@ -364,15 +364,19 @@ class MixFormFormsetUpdateView(UpdateView): def get(self, request, *args, **kwargs): self.object = self.get_object() self.inline_forms = [ - inline(instance=self.object) for inline in self.form_inlines_class + inline(instance=self.object, + prefix=getattr(inline, "form_slug", "form")) + for inline in self.form_inlines_class ] return super(MixFormFormsetUpdateView, self).get(request, *args, **kwargs) def post(self, request, *args, **kwargs): self.object = self.get_object() + attrs = {"instance": self.object} form = self.form_class(data=request.POST, instance=self.object) inline_forms = [ - inline(instance=self.object, data=request.POST) + inline(instance=self.object, data=request.POST, + prefix=getattr(inline, "form_slug", "form")) for inline in self.form_inlines_class ] if form.is_valid() and all((inline.is_valid() for inline in inline_forms)): @@ -410,7 +414,6 @@ class PreventiveEditView(IshtarMixin, LoginRequiredMixin, MixFormFormsetUpdateVi template_name = "ishtar/forms/preventive_detail.html" model = models.File - def get_success_url(self): return reverse("file_modification") + "?open_item={}".format(self.object.pk) diff --git a/ishtar_common/static/js/ishtar.js b/ishtar_common/static/js/ishtar.js index 897356fe3..3fa293deb 100644 --- a/ishtar_common/static/js/ishtar.js +++ b/ishtar_common/static/js/ishtar.js @@ -1874,4 +1874,27 @@ var update_select_widget = function(input_name, values, only_values, excluded_va } } $("#id_" + input_name).html(options); +}; + +var inline_register_add_button = function(slug){ + let inline_form = document.querySelectorAll(".form-" + slug); + let inline_container = document.querySelector("#formset-container-" + slug); + let inline_add_button = document.querySelector("#add-form-" + slug); + let inline_div_add_button = document.querySelector("#div-add-form-" + slug); + let inline_total_forms = document.querySelector("#id_" + slug + "-TOTAL_FORMS"); + let inline_form_num = inline_form.length - 1; + inline_add_button.addEventListener( + 'click', function(e){ + e.preventDefault(); + let new_form = inline_form[0].cloneNode(true); + let form_regex_var = slug + '(\\d){1}-'; + let form_regex = new RegExp(form_regex_var, 'g'); + inline_form_num++; + console.log(new_form); + new_form.innerHTML = new_form.innerHTML.replace( + form_regex, slug + `-${inline_form_num}-`); + inline_container.insertBefore(new_form, inline_div_add_button); + inline_total_forms.setAttribute('value', `${inline_form_num+1}`); + } + ); };
\ No newline at end of file diff --git a/ishtar_common/templates/base.html b/ishtar_common/templates/base.html index f9feef533..af4396be3 100644 --- a/ishtar_common/templates/base.html +++ b/ishtar_common/templates/base.html @@ -265,6 +265,10 @@ <div id='message'> <div class='information'><i class="fa fa-info-circle" aria-hidden="true"></i> <span class='content'></span></div> </div> + <script type='text/javascript'> + {% block end_js %} + {% endblock %} + </script> </body> </html> diff --git a/ishtar_common/templates/blocks/bs_field_snippet.html b/ishtar_common/templates/blocks/bs_field_snippet.html index dcee87f7f..beecf624f 100644 --- a/ishtar_common/templates/blocks/bs_field_snippet.html +++ b/ishtar_common/templates/blocks/bs_field_snippet.html @@ -1,5 +1,5 @@ {% load i18n %} - <div id="main_div-{{field.auto_id}}" class="form-group{% if not field.label %} no-label{% endif %} {% if field.field.widget.attrs.cols or force_large_col %}col-lg-12{% else %}col-lg-6{% endif %}{% if field.errors %} is-invalid{% endif %}{% if field.field.required %} required{% endif %}{% if force_large_col %} full-width{% endif %}" + <div id="main_div-{{field.auto_id}}" class="form-group{% if not field.label %} no-label{% endif %} {% if bs_col_width %}{{bs_col_width}}{% elif field.field.widget.attrs.bs_col_width %}{{field.field.widget.attrs.bs_col_width}}{% else %}{% if field.field.widget.attrs.cols or force_large_col %}col-lg-12{% else %}col-lg-6{% endif %}{% endif %}{% if field.errors %} is-invalid{% endif %}{% if field.field.required %} required{% endif %}{% if force_large_col %} full-width{% endif %}" data-alt-name="{{field.field.alt_name}}"> {% if field.label %}{{ field.label_tag }}{% endif %} {% if extra_field_label %}<label><em>{{extra_field_label}}</em></label>{% endif %} diff --git a/ishtar_common/templates/blocks/bs_formset_snippet.html b/ishtar_common/templates/blocks/bs_formset_snippet.html index 0d089ee1b..3a7e537d3 100644 --- a/ishtar_common/templates/blocks/bs_formset_snippet.html +++ b/ishtar_common/templates/blocks/bs_formset_snippet.html @@ -1,6 +1,9 @@ {% load i18n from_dict %} -<div class="form-row"> +<div id="formset-container-{{formset.prefix}}"> + {{ formset.non_form_errors.as_ul }} + {{ formset.management_form }} {% for form in formset %} + <div class="form-row form-{{formset.prefix}}"> {% if form.non_field_errors and not no_error %} <div class="alert alert-danger" role="alert"> {{form.non_field_errors}} @@ -16,11 +19,26 @@ {% csrf_token %} {% for field in form.visible_fields %} + {% with bs_col_width='col-3' %} {% include "blocks/bs_field_snippet.html" %} + {% endwith %} {% endfor %} {% if form.extra_render %} {{form.extra_render|safe}} {% endif %} + </div> {% endfor %} + {% if formset.dynamic_add %} + <div class="form-row pb-2" id="div-add-form-{{formset.prefix}}"> + <div class="col"> + <button class="btn btn-secondary" id="add-form-{{formset.prefix}}" type="button">{% trans "Add" %}</button> + </div> + </div> + <script> + $(document).ready(function(){ + inline_register_add_button("{{formset.prefix}}"); + }); + </script> + {% endif %} </div> diff --git a/ishtar_common/templates/ishtar/forms/base_form.html b/ishtar_common/templates/ishtar/forms/base_form.html index fb1fc997f..3f069e7d6 100644 --- a/ishtar_common/templates/ishtar/forms/base_form.html +++ b/ishtar_common/templates/ishtar/forms/base_form.html @@ -23,10 +23,15 @@ {% endif %} {% block form_head %} {% endblock %} + {% block bs_form %} {% bs_form form 0 True %} + {% endblock %} + {% block bs_form_inlines %} {% for inline in inline_forms %} + <h4>{{inline.form_label}}</h4> {% bs_formset inline 0 True %} {% endfor %} + {% endblock %} </div> {% endblock %} |