diff options
| -rw-r--r-- | ishtar_common/forms.py | 8 | ||||
| -rw-r--r-- | ishtar_common/forms_common.py | 22 | ||||
| -rw-r--r-- | ishtar_common/templates/ishtar/wizard/confirm_wizard.html | 8 | ||||
| -rw-r--r-- | ishtar_common/views.py | 1 | ||||
| -rw-r--r-- | ishtar_common/widgets.py | 28 | ||||
| -rw-r--r-- | ishtar_common/wizards.py | 128 | 
6 files changed, 138 insertions, 57 deletions
| diff --git a/ishtar_common/forms.py b/ishtar_common/forms.py index 70e144980..c314e4f13 100644 --- a/ishtar_common/forms.py +++ b/ishtar_common/forms.py @@ -193,6 +193,8 @@ class CustomForm(object):  class FormSet(CustomForm, BaseFormSet): +    delete_widget = widgets.DeleteWidget +      def __init__(self, *args, **kwargs):          self.readonly = False          if 'readonly' in kwargs: @@ -240,7 +242,11 @@ class FormSet(CustomForm, BaseFormSet):                  setattr(form, clean.__name__, types.MethodType(clean, form))          if self.can_delete:              form.fields[DELETION_FIELD_NAME].label = '' -            form.fields[DELETION_FIELD_NAME].widget = widgets.DeleteWidget() +            form.fields[DELETION_FIELD_NAME].widget = self.delete_widget() + + +class FormSetWithDeleteSwitches(FormSet): +    delete_widget = widgets.DeleteSwitchWidget  class FieldType(object): diff --git a/ishtar_common/forms_common.py b/ishtar_common/forms_common.py index 72b33b4c4..bde5e47ed 100644 --- a/ishtar_common/forms_common.py +++ b/ishtar_common/forms_common.py @@ -37,7 +37,7 @@ import widgets  from bootstrap_datepicker.widgets import DatePicker  from ishtar_common.templatetags.link_to_window import link_to_window  from forms import FinalForm, FormSet, reverse_lazy, name_validator, \ -    TableSelect, ManageOldType, CustomForm, FieldType +    TableSelect, ManageOldType, CustomForm, FieldType, FormSetWithDeleteSwitches  def get_town_field(label=_(u"Town"), required=True): @@ -721,6 +721,26 @@ class AccountForm(forms.Form):          return cleaned_data +class ProfileForm(ManageOldType): +    form_label = _("Profiles") +    base_model = 'profile' +    associated_models = {'profile_type': models.ProfileType} +    profile_type = forms.ChoiceField(label=_(u"Type"), choices=[], +                                     required=False) +    pk = forms.IntegerField(label=" ", widget=forms.HiddenInput, required=False) + +    TYPES = [ +        FieldType('profile_type', models.ProfileType), +    ] + + +ProfileFormset = formset_factory(ProfileForm, can_delete=True, +                                 formset=FormSetWithDeleteSwitches) +ProfileFormset.form_label = _("Profiles") +ProfileFormset.form_admin_name = _(u"Profiles") +ProfileFormset.form_slug = "profiles" + +  class FinalAccountForm(forms.Form):      final = True      form_label = _("Confirm") diff --git a/ishtar_common/templates/ishtar/wizard/confirm_wizard.html b/ishtar_common/templates/ishtar/wizard/confirm_wizard.html index 1128e9561..401fe570c 100644 --- a/ishtar_common/templates/ishtar/wizard/confirm_wizard.html +++ b/ishtar_common/templates/ishtar/wizard/confirm_wizard.html @@ -9,7 +9,7 @@  <form action="." method="post">{% csrf_token %}  <div class='form'>    {% block "warning_informations" %}{% endblock %} -  <p>{%if confirm_msg %}{{confirm_msg|safe}}{%else%}{% trans "You have entered the following informations:" %}{%endif%}</p> +  <p>{% if confirm_msg %}{{confirm_msg|safe}}{%else%}{% trans "You have entered the following informations:" %}{%endif%}</p>    {% for form_label, form_data in datas %}    <div class="card"> @@ -20,7 +20,7 @@      <div class="card-body form-row">        <table class='table'>          {% for data in form_data %} -        <tr{%if data.2%} class='{{data.2}}'{%endif%}><th>{{data.0}}</th><td>{{data.1}}</td></tr> +        <tr{% if data.2 %} class='{{data.2}}'{%endif%}><th>{{data.0}}</th><td>{{data.1}}</td></tr>          {% endfor %}        </table> @@ -29,8 +29,8 @@    {% endfor %} -{{wizard.management_form}} -  {%if not wizard.form.is_hidden %} +  {{wizard.management_form}} +  {% if not wizard.form.is_hidden %}    <table>      {{ wizard.form.as_table }}     </table> diff --git a/ishtar_common/views.py b/ishtar_common/views.py index 863722ac8..2023df305 100644 --- a/ishtar_common/views.py +++ b/ishtar_common/views.py @@ -193,6 +193,7 @@ organization_deletion_wizard = wizards.OrganizationDeletionWizard.as_view(  account_wizard_steps = [      ('selec-account_management', forms.PersonUserFormSelection),      ('account-account_management', forms.AccountForm), +    ('profile-account_management', forms.ProfileFormset),      ('final-account_management', forms.FinalAccountForm)]  account_management_wizard = wizards.AccountWizard.as_view( diff --git a/ishtar_common/widgets.py b/ishtar_common/widgets.py index 2df06cf21..60e5fc016 100644 --- a/ishtar_common/widgets.py +++ b/ishtar_common/widgets.py @@ -261,19 +261,35 @@ class DeleteWidget(forms.CheckboxInput):  class SwitchWidget(forms.CheckboxInput): +    extra_class = "" +    extra_label = "" +      def render(self, name, value, attrs=None, renderer=None): +        extra_class = (" " + self.extra_class) if self.extra_class else "" +        default = {"name": name, "value": "1", +                   'class': "switch" + extra_class, +                   'type': 'checkbox'} +        if value: +            default['checked'] = 'checked'          attrs = self.build_attrs( -            attrs, {"name": name, "value": '0', -                    'class': "switch", -                    'type': 'checkbox'} +            attrs, default          )          final_attrs = flatatt(attrs) -        output = u"""<span class="switch"> -      <input{}> -</span>""".format(final_attrs, attrs['id']) +        extra_label = "" +        if self.extra_label: +            extra_label = '<label for="{}">{}</label>'.format(attrs['id'], +                                                              self.extra_label) +        output = u"""<span class="switch{}"> +      <input{}>{} +</span>""".format(extra_class, final_attrs, extra_label)          return mark_safe(output) +class DeleteSwitchWidget(SwitchWidget): +    extra_class = "danger" +    extra_label = _(u"Delete") + +  class ImageFileInput(ClearableFileInput):      template_name = 'widgets/image_input.html'      NO_FORM_CONTROL = True diff --git a/ishtar_common/wizards.py b/ishtar_common/wizards.py index d486474d8..68ca640a0 100644 --- a/ishtar_common/wizards.py +++ b/ishtar_common/wizards.py @@ -39,6 +39,7 @@ from django.forms import ValidationError  from django.shortcuts import redirect, render  from django.template import loader  from django.utils.translation import ugettext_lazy as _ +from django.utils.safestring import mark_safe  from ishtar_common import models  from ishtar_common.forms import CustomForm @@ -136,6 +137,7 @@ class Wizard(NamedUrlWizardView):      ignore_init_steps = []      file_storage = default_storage      main_item_select_keys = ('selec-',) +    formset_pop_deleted = True      saved_args = {}  # argument to pass on object save @@ -347,7 +349,8 @@ class Wizard(NamedUrlWizardView):          """Get the data to present in the last page"""          datas = []          for form in forms: -            base_form = hasattr(form, 'forms') and form.forms[0] or form +            is_formset = hasattr(form, 'forms') +            base_form = is_formset and form.forms[0] or form              associated_models = hasattr(base_form, 'associated_models') and \                  base_form.associated_models or {}              if not hasattr(form, 'cleaned_data') and hasattr(form, 'forms'): @@ -368,10 +371,10 @@ class Wizard(NamedUrlWizardView):              for cleaned_data in cleaned_datas:                  if not cleaned_data:                      continue -                if form_datas: -                    form_datas.append(("", "", "spacer")) +                current_form_data = []                  items = hasattr(base_form, 'fields') and \                      base_form.fields.keys() or cleaned_data.keys() +                is_deleted = False                  for key in items:                      lbl = None                      if key.startswith('hidden_'): @@ -382,10 +385,13 @@ class Wizard(NamedUrlWizardView):                          if hasattr(base_form, 'associated_labels') \                             and key in base_form.associated_labels:                              lbl = base_form.associated_labels[key] -                    if not lbl or key not in cleaned_data: +                    if key not in cleaned_data:  # no value                          continue                      value = cleaned_data[key] -                    if value is None or value == '': +                    if key == "DELETE" and value: +                        is_deleted = True +                    # no display when no label or no value +                    if not lbl.strip() or value is None or value == '':                          continue                      if key in self.translated_keys:                          value = _(value) @@ -412,9 +418,32 @@ class Wizard(NamedUrlWizardView):                                  value = unicode(item)                              rendered_values.append(value)                          value = u" ; ".join(rendered_values) -                    form_datas.append((lbl, value, '')) -            if form_datas: -                datas.append((form.form_label, form_datas)) +                    current_form_data.append((lbl, value, '')) + +                if is_formset: +                    # regroup each line +                    displayed_values = [] +                    for lbl, value, cls in current_form_data: +                        displayed_value = u"" +                        if lbl.strip(): +                            displayed_value = u"<strong>{}{}</strong> ".format( +                                 lbl, _(u":")) +                        displayed_value += unicode(value) +                        displayed_values.append(displayed_value) +                    value = u" ; ".join(displayed_values) +                    if is_deleted: +                        value = u"<span class='text-danger'>{}</span>".format( +                            value) +                    deleted = u"<span class='text-danger'>{}</span>".format( +                        _(u"Deleted")) if is_deleted else "" +                    form_datas.append((mark_safe(deleted), mark_safe(value), +                                       '')) +                else: +                    form_datas += current_form_data + +            if not form_datas: +                continue +            datas.append((form.form_label, form_datas))          return datas      def get_extra_model(self, dct, form_list): @@ -832,24 +861,25 @@ class Wizard(NamedUrlWizardView):                  # manage deletion                  to_delete, not_to_delete = self.get_deleted(data.keys())                  # raz deleted fields -                for key in data.keys(): -                    items = key.split('-') -                    if len(items) < 2 or items[-2] not in to_delete: -                        continue -                    data.pop(key) -                if to_delete: -                    # reorganize -                    for idx, number in enumerate(sorted(not_to_delete, -                                                        key=lambda x: int(x))): -                        idx = unicode(idx) -                        if idx == number: +                if self.formset_pop_deleted: +                    for key in data.keys(): +                        items = key.split('-') +                        if len(items) < 2 or items[-2] not in to_delete:                              continue -                        for key in data.keys(): -                            items = key.split('-') -                            if len(items) > 2 and number == items[-2]: -                                items[-2] = unicode(idx) -                                k = u'-'.join(items) -                                data[k] = data.pop(key)[0] +                        data.pop(key) +                    if to_delete: +                        # reorganize +                        for idx, number in enumerate( +                                sorted(not_to_delete, key=lambda x: int(x))): +                            idx = unicode(idx) +                            if idx == number: +                                continue +                            for key in data.keys(): +                                items = key.split('-') +                                if len(items) > 2 and number == items[-2]: +                                    items[-2] = unicode(idx) +                                    k = u'-'.join(items) +                                    data[k] = data.pop(key)[0]                  # get a form key                  frm = form.form                  if callable(frm): @@ -914,7 +944,6 @@ class Wizard(NamedUrlWizardView):                      if frm.fields[key].widget.source_full is not None:                          frm.fields[key].widget.source_full = unicode(                              frm.fields[key].widget.source_full) + "own/" -          return form      def render_next_step(self, form, **kwargs): @@ -926,8 +955,9 @@ class Wizard(NamedUrlWizardView):          request = self.request          if request.POST.get('formset_modify') \             or request.POST.get('formset_add') \ -           or [key for key in request.POST.keys() -               if key.endswith('DELETE') and request.POST[key]]: +           or (self.formset_pop_deleted and [ +            key for key in request.POST.keys() +            if key.endswith('DELETE') and request.POST[key]]):              return self.render(form)          elif 'validate_and_end' in request.POST \                  and request.POST['validate_and_end']: @@ -1382,6 +1412,7 @@ class OrganizationDeletionWizard(DeletionWizard):  class AccountWizard(Wizard): +    formset_pop_deleted = False      model = models.Person      def get_formated_datas(self, forms): @@ -1398,23 +1429,26 @@ class AccountWizard(Wizard):          """          Save the account          """ +        form_dict = kwargs['form_dict'] + +        main_form = form_dict['account-account_management'] +        if not main_form.is_valid(): +            return self.render(main_form) +          dct = {} -        for form in form_list: -            if not form.is_valid(): -                return self.render(form) -            associated_models = hasattr(form, 'associated_models') and \ -                form.associated_models or {} -            if type(form.cleaned_data) == dict: -                for key in form.cleaned_data: -                    if key == 'pk': -                        continue -                    value = form.cleaned_data[key] -                    if key in associated_models and value: -                        value = associated_models[key].objects.get(pk=value) -                    dct[key] = value +        associated_models = main_form.associated_models +        if type(main_form.cleaned_data) == dict: +            for key in main_form.cleaned_data: +                if key == 'pk': +                    continue +                value = main_form.cleaned_data[key] +                if key in associated_models and value: +                    value = associated_models[key].objects.get(pk=value) +                dct[key] = value          person = self.get_current_object()          if not person: -            return self.render(form) +            return self.render(form_dict['selec-account_management']) +          for key in dct.keys():              if key.startswith('hidden_password'):                  dct['password'] = dct.pop(key) @@ -1441,10 +1475,14 @@ class AccountWizard(Wizard):              account.set_password(dct['password'])          account.save() -        if 'send_password' in dct and dct['send_password'] and \ -           settings.ADMINS: -            site = Site.objects.get_current() +        profile_form = form_dict['profile-account_management'] +        for form in profile_form: +            print(form.cleaned_data) +        final_form = form_dict['final-account_management'] +        if settings.ADMINS and type(final_form.cleaned_data) == dict and \ +                 final_form.cleaned_data.get('send_password', None): +            site = Site.objects.get_current()              app_name = site and ("Ishtar - " + site.name) \                  or "Ishtar"              context = { | 
