Passed
Push — 2.x ( 823daf...cad85d )
by Jordi
06:44
created

senaite.core.browser.form.ajax.FormView.submit()   A

Complexity

Conditions 3

Size

Total Lines 8
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 8
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 3
nop 1
1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of SENAITE.CORE.
4
#
5
# SENAITE.CORE is free software: you can redistribute it and/or modify it under
6
# the terms of the GNU General Public License as published by the Free Software
7
# Foundation, version 2.
8
#
9
# This program is distributed in the hope that it will be useful, but WITHOUT
10
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
# details.
13
#
14
# You should have received a copy of the GNU General Public License along with
15
# this program; if not, write to the Free Software Foundation, Inc., 51
16
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
#
18
# Copyright 2018-2021 by it's authors.
19
# Some rights reserved, see README and LICENSE.
20
21
import json
22
23
from bika.lims.browser import BrowserView
24
from bika.lims.decorators import returns_json
25
from senaite.core.decorators import readonly_transaction
26
from senaite.core.interfaces import IAjaxEditForm
27
from zope.component import queryMultiAdapter
28
29
__doc__ = """
30
The edit form handler is the server part of `editform.js` JS and must implement
31
the following two methods:
32
33
    def initialized():
34
        payload = self.get_data()
35
        return {}
36
37
This method is called after the edit form has been loaded on the client side.
38
The JSON `payload` provides only one key `form`, which contains the serialized
39
and raw keys/values of the HTML form elements (including ZPublisher
40
field converters, e.g. `fieldname:boolean:default` etc.).
41
42
    def modified():
43
        payload = self.get_data()
44
        return {}
45
46
This method is called on each field modification. The JSON `payload` provides
47
the key `form` with the HTML form data as described above.
48
49
Furthermore, it provides the keys `name` and `value` with the name and value of
50
the changed field. The `key` is the fieldname w/o the coverter to match the
51
schema of the object and the value is converted as follows:
52
53
    - checkbox fields: True/False
54
    - single reference fields: UID
55
    - multi reference fields: list of UIDs
56
    - select fields: list of selected values
57
58
The return value of both methods is a dictionary with instructions to be done
59
in the fronted.
60
61
The following keys are supported in the returned dictionary:
62
63
    hide: [
64
        {"name": "title"},
65
        {"name": "description"},
66
    ]
67
68
A list of field records containing at least the `name` of the field.
69
70
    show: [
71
        {"name": "title"},
72
        {"name": "description"},
73
    ]
74
75
A list of field records containing at least the `name` of the field.
76
77
    readonly: [
78
        {"name": "title"},
79
        {"name": "description"},
80
    ]
81
82
A list of field records containing at least the `name` of the field.
83
84
    update: [
85
        {"name": "title", value="My Title"},
86
        {"name": "description", "value": "My Description"},
87
        {"name": "Department", "value": {
88
            "selected": ["6f3cb33f10e04ac19b32b8bd47fcd43b"],
89
            "options": [
90
                {
91
                    "title": "Clinical Lab",
92
                    "value": "6f3cb33f10e04ac19b32b8bd47fcd43b",
93
                }
94
            ]
95
        }
96
    ]
97
98
A list of records containing at least the `name` and the `value` of the fields
99
to update.
100
101
    errors: [
102
        {"name": "title", error="Invalid characters detected"},
103
    ]
104
105
A list of records containing at least the `name` and the `error` of the fields
106
that should be displayed as erroneous.
107
108
Note: Form submission is disabled when fields are marked as erroneous!
109
110
    notifications: [
111
        {"title": "Heads Up", message": "Notifications are awesome!"},
112
    ]
113
114
A list of records containing at least the `title` and the `message` of the
115
notifications messages to display.
116
117
    messages: [
118
        {"message": "Changes Saved", level="info"},
119
    ]
120
121
A list of records containing at least the `message` and the `level` of the
122
status messages to display.
123
124
The level can be one of the following values:
125
126
    - info
127
    - success
128
    - warning
129
    - dangrous
130
    - success
131
132
The `message` should be an i18n message factory and are translated with
133
`jsi18n` in JS.
134
"""
135
136
137
class FormView(BrowserView):
138
    """Form View
139
140
    NOTE: No persistent operations are allowed!
141
    """
142
143
    @property
144
    def adapter(self):
145
        name = self.get_form_adapter_name()
146
        if name is not None:
147
            # query a named form adapter
148
            return queryMultiAdapter(
149
                (self.context, self.request), IAjaxEditForm, name=name)
150
        return queryMultiAdapter((self.context, self.request), IAjaxEditForm)
151
152
    @readonly_transaction
153
    @returns_json
154
    def initialized(self):
155
        data = self.get_data()
156
        if not data:
157
            data = {}
158
        if not self.adapter:
159
            return {}
160
        return self.adapter.initialized(data)
161
162
    @readonly_transaction
163
    @returns_json
164
    def modified(self):
165
        data = self.get_data()
166
        if not data:
167
            data = {}
168
        if not self.adapter:
169
            return {}
170
        return self.adapter.modified(data)
171
172
    @returns_json
173
    def submit(self):
174
        data = self.get_data()
175
        if not data:
176
            data = {}
177
        if not self.adapter:
178
            return {}
179
        return self.adapter.submit(data)
180
181
    def get_data(self):
182
        body = self.request.get("BODY")
183
        if body:
184
            return json.loads(body)
185
        form = self.request.form
186
        if form:
187
            return {"form": form}
188
        return {}
189
190
    def get_form_adapter_name(self):
191
        """Returns the form adapter name for the query
192
        """
193
        data = self.get_data()
194
        form = data.get("form", {})
195
        return form.get("form_adapter_name")
196