Source code for shoop.notify.admin_module.forms
# -*- coding: utf-8 -*-
# This file is part of Shoop.
#
# Copyright (c) 2012-2016, Shoop Ltd. All rights reserved.
#
# This source code is licensed under the AGPLv3 license found in the
# LICENSE file in the root directory of this source tree.
from __future__ import unicode_literals
import copy
from collections import defaultdict, OrderedDict
from django import forms
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from shoop.notify.admin_module.utils import get_name_map
from shoop.notify.enums import TemplateUse, UNILINGUAL_TEMPLATE_LANGUAGE
from shoop.notify.models import Script
from shoop.utils.i18n import get_language_name
[docs]class ScriptForm(forms.ModelForm):
event_identifier = forms.ChoiceField(
label=_(u"Event"),
help_text=_(u"Choose which event to bind this script to.")
)
name = forms.CharField(
label=_(u"Script Name"),
help_text=_(u"Type in a descriptive name for your new script.")
)
enabled = forms.BooleanField(
label=_(u"Enable Script"),
help_text=_(u"Choose whether this script should be activated when its event fires."),
required=False
)
def __init__(self, **kwargs):
super(ScriptForm, self).__init__(**kwargs)
event_choices = get_name_map("notify_event")
self.fields["event_identifier"].choices = event_choices
self.fields["event_identifier"].widget.choices = event_choices
if self.instance.pk:
self.fields["event_identifier"].help_text = (
_(u"Warning: Changing the event for an existing script may have unexpected effects.")
)
[docs]class ScriptItemEditForm(forms.Form):
def __init__(self, *args, **kwargs):
self.script_item = kwargs.pop("script_item")
self.event_class = kwargs.pop("event_class")
super(ScriptItemEditForm, self).__init__(*args, **kwargs)
self.variables = self.event_class.variables.copy()
self.populate_form()
[docs] def populate_form(self):
self.binding_field_info = OrderedDict()
self.template_field_info = defaultdict(OrderedDict)
self.template_languages = []
for identifier, binding in sorted(self.script_item.bindings.items(), key=lambda ib: ib[1].position):
self._populate_binding_fields(identifier, binding)
self._populate_template_fields()
def _populate_template_fields(self):
template_use = getattr(self.script_item, "template_use", TemplateUse.NONE)
if template_use == TemplateUse.MULTILINGUAL:
self.template_languages = []
# TODO: Should we get this list from somewhere else?
for language_code, language_name in settings.LANGUAGES:
self.template_languages.append((language_code, get_language_name(language_code)))
elif template_use == TemplateUse.UNILINGUAL:
self.template_languages = [UNILINGUAL_TEMPLATE_LANGUAGE, _(u"Template")]
else: # Nothing to do
return
ordered_fields = sorted(self.script_item.template_fields.items(), key=lambda p: p[1].creation_counter)
for lang_code, lang_name in self.template_languages:
for t_field_name, base_field in ordered_fields:
field = copy.deepcopy(base_field)
field.label = "%s (%s)" % (field.label, lang_name)
field.required = False
field_name = "t_%s_%s" % (lang_code, t_field_name)
self.fields[field_name] = field
self.template_field_info[lang_code][t_field_name] = field_name
def _populate_binding_fields(self, binding_identifier, binding):
"""
:param binding_identifier: Binding identifier
:type binding_identifier: str
:param binding: Binding object
:type binding: Binding
"""
binding_field_info = self.binding_field_info.setdefault(binding_identifier, {"binding": binding})
if binding.allow_constant:
field_name = "b_%s_c" % binding_identifier
self.fields[field_name] = binding.type.get_field(
label=u"Constant",
required=(binding.required and not binding.allow_variable),
initial=binding.default
)
binding_field_info["constant"] = field_name
if binding.allow_variable:
variables = [
(var_identifier, var.name)
for (var_identifier, var)
in self.variables.items()
if binding.accepts_any_type or binding.type.is_coercible_from(var.type)
]
if variables:
choices = [("", "")] + variables
field_name = "b_%s_v" % binding_identifier
self.fields[field_name] = forms.ChoiceField(
choices=choices,
label=_("Bind to Variable"),
required=(binding.required and not binding.allow_constant)
)
binding_field_info["variable"] = field_name
# TODO: Maybe show a disabled field instead of nothing?
[docs] def get_initial(self):
initial = {}
for identifier, binding in self.script_item.bindings.items():
bind_data = self.script_item.data.get(identifier, {})
field_info = self.binding_field_info.get(identifier)
if not field_info:
return
for f in ("constant", "variable"):
if field_info.get(f):
initial[field_info[f]] = bind_data.get(f)
template_data = self.script_item.data.get("template_data", {})
for lang_code, field_info in self.template_field_info.items():
lang_templates = template_data.get(lang_code, {})
for t_field_name, field_name in field_info.items():
if lang_templates.get(t_field_name):
initial[field_name] = lang_templates.get(t_field_name)
return initial
def _save_binding(self, new_data, identifier, binding):
field_info = self.binding_field_info.get(identifier)
if not field_info:
return
if binding.allow_variable and "variable" in field_info:
variable_name = self.cleaned_data.get(field_info["variable"])
if variable_name:
new_data[identifier] = {"variable": variable_name}
return
if binding.allow_constant and "constant" in field_info:
constant_value = self.cleaned_data.get(field_info["constant"])
if constant_value:
if hasattr(constant_value, "value"): # Might be an enum TODO: fixme
constant_value = constant_value.value
new_data[identifier] = {"constant": constant_value}
return
if binding.required:
message = "Binding %s is required but has no value" % binding.name
if field_info.get("constant"):
self.add_error(field_info["constant"], message)
if field_info.get("variable"):
self.add_error(field_info["variable"], message)
def _save_bindings(self, new_data):
for identifier, binding in self.script_item.bindings.items():
self._save_binding(new_data, identifier, binding)
def _save_template(self, new_data):
template_data = {}
for lang_code, field_info in self.template_field_info.items():
lang_vals = dict(
(t_field_name, (self.cleaned_data.get(field_name) or "").strip())
for (t_field_name, field_name)
in field_info.items()
)
if not any(lang_vals.values()): # Not worth saving
continue
can_save = True
for t_field_name, content in lang_vals.items():
if not content:
self.add_error(field_info[t_field_name], u"This field is missing content")
can_save = False
if can_save:
template_data[lang_code] = lang_vals
new_data["template_data"] = template_data
[docs] def save(self):
new_data = {}
self._save_bindings(new_data)
self._save_template(new_data)
if self.errors:
raise forms.ValidationError("There are errors")
self.script_item.data.update(new_data)
return self.script_item