summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2018-04-17 12:04:08 +0200
committerÉtienne Loks <etienne.loks@iggdrasil.net>2018-06-12 08:41:54 +0200
commit0666e34337b965e85ce3920363ad04e87958e8e7 (patch)
tree67d308063f0c78cbf26e3b040821e762fed5b4e3
parent022d362b707f0396461a1b32f001baab96a885fc (diff)
downloadIshtar-0666e34337b965e85ce3920363ad04e87958e8e7.tar.bz2
Ishtar-0666e34337b965e85ce3920363ad04e87958e8e7.zip
WIP on account wizard. Wizard: can use switch for deletion. Better display of formsets on done wizard.
-rw-r--r--ishtar_common/forms.py8
-rw-r--r--ishtar_common/forms_common.py22
-rw-r--r--ishtar_common/templates/ishtar/wizard/confirm_wizard.html8
-rw-r--r--ishtar_common/views.py1
-rw-r--r--ishtar_common/widgets.py28
-rw-r--r--ishtar_common/wizards.py128
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 = {