Source code for shuup.notify.admin_module.views.editor

# -*- coding: utf-8 -*-
# This file is part of Shuup.
#
# Copyright (c) 2012-2021, Shuup Commerce Inc. All rights reserved.
#
# This source code is licensed under the OSL-3.0 license found in the
# LICENSE file in the root directory of this source tree.
from __future__ import unicode_literals

import json
from django.conf import settings
from django.core.exceptions import ValidationError
from django.http import JsonResponse
from django.shortcuts import render
from django.utils.text import camel_case_to_spaces
from django.utils.translation import ugettext_lazy as _
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import DetailView

from shuup.admin.toolbar import JavaScriptActionButton, Toolbar, get_discard_button
from shuup.admin.utils.urls import get_model_url
from shuup.admin.utils.views import get_create_or_change_title
from shuup.notify.admin_module.forms import ScriptItemEditForm
from shuup.notify.admin_module.utils import get_enum_choices_dict
from shuup.notify.base import Action, Condition, Event
from shuup.notify.enums import StepConditionOperator, StepNext
from shuup.notify.models.script import Script
from shuup.utils.text import snake_case


@csrf_exempt  # This is fine -- the editor itself saves naught
[docs]def script_item_editor(request): # This is a regular non-CBV view because the way it processes the data it received # would be more awkward to do in a CBV. request.POST = dict(request.POST.items()) # Make it mutable init_data_json = request.POST.pop("init_data") init_data = json.loads(init_data_json) item_class = {"action": Action, "condition": Condition}[init_data["itemType"]] form = ScriptItemEditForm( script_item=item_class.unserialize(init_data["data"], validate=False), event_class=Event.class_for_identifier(init_data["eventIdentifier"]), data=(request.POST if request.POST else None), files=(request.FILES if request.FILES else None), ) form.initial = form.get_initial() context = { "form": form, "script_item": form.script_item, "event_class": form.event_class, "init_data": init_data_json, } if form.data and form.is_valid(): try: form.save() except ValidationError as verr: form.add_error(None, verr) else: context["post_message"] = {"new_data": form.script_item.data} # Unbind so we'll use the initial data form.is_bound = False form.data = {} form.initial = form.get_initial() return render(request, "notify/admin/script_item_editor.jinja", context)
[docs]class ScriptAPI(object): def __init__(self, request, script): """ :param request: Request. :type request: django.http.HttpRequest :param script: Script. :type script: shuup.notify.models.Script """ self.request = request self.script = script
[docs] def dispatch(self): data = json.loads(self.request.body.decode("UTF-8")) command = data.pop("command") func_name = "handle_%s" % snake_case(camel_case_to_spaces(command)) func = getattr(self, func_name, None) if not callable(func): return JsonResponse({"error": "Error! No handler: %s." % func_name}) return func(data)
[docs] def handle_get_data(self, data): return JsonResponse( { "steps": self.script.get_serialized_steps(), } )
[docs] def handle_save_data(self, data): try: self.script.set_serialized_steps(data["steps"]) except Exception as exc: if settings.DEBUG: raise return JsonResponse({"error": exc}) self.script.save(update_fields=("_step_data",)) return JsonResponse({"success": "Success! Changes were saved."})
[docs]class EditScriptContentView(DetailView): template_name = "notify/admin/script_content_editor.jinja" model = Script context_object_name = "script"
[docs] def post(self, request, *args, **kwargs): return ScriptAPI(request, self.get_object()).dispatch()
[docs] def get_context_data(self, **kwargs): context = super(EditScriptContentView, self).get_context_data(**kwargs) context["title"] = get_create_or_change_title(self.request, self.object) context["action_infos"] = Action.get_ui_info_map() context["condition_infos"] = Condition.get_ui_info_map() context["cond_op_names"] = get_enum_choices_dict(StepConditionOperator) context["step_next_names"] = get_enum_choices_dict(StepNext) context["toolbar"] = Toolbar( [ JavaScriptActionButton( text=_("Save"), icon="fa fa-save", extra_css_class="btn-success", onclick="window.ScriptEditor.save();return false", ), get_discard_button(get_model_url(self.object, "edit")), ], view=self, ) return context