Passed
Push — 2.x ( 7be1e3...9538a4 )
by Jordi
07:43
created

SenaiteDefaultView.render_widget_tabs()   A

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 2
rs 10
c 0
b 0
f 0
cc 1
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-2024 by it's authors.
19
# Some rights reserved, see README and LICENSE.
20
21
import os
22
from string import Template
23
24
import plone.app.z3cform
25
import plone.app.z3cform.interfaces
26
import plone.z3cform.interfaces
27
import plone.z3cform.templates
28
import senaite.core.browser.dexterity
29
import z3c.form.interfaces
30
from bika.lims import senaiteMessageFactory as _
31
from plone.app.z3cform.views import Macros
32
from plone.app.z3cform.views import RenderWidget
33
from plone.dexterity.browser.edit import DefaultEditView
34
from plone.dexterity.browser.view import DefaultView
35
from senaite.core.interfaces import ISenaiteFormLayer
36
from z3c.form.interfaces import INPUT_MODE
37
from zope.browserpage.viewpagetemplatefile import ViewPageTemplateFile
38
39
FORMAT_TPL = Template("""<span class="$css">
40
  $text
41
</span>
42
""")
43
44
45
def path(filepart):
46
    return os.path.join(
47
        os.path.dirname(senaite.core.browser.dexterity.__file__),
48
        "templates",
49
        filepart,
50
    )
51
52
53
class SenaiteMacros(Macros):
54
    """Override class for templates/form.pt
55
    """
56
    def __init__(self, context, request):
57
        super(SenaiteMacros, self).__init__(context, request)
58
        self.context = context
59
        self.request = request
60
61
62
class SenaiteRenderWidget(RenderWidget):
63
    index = ViewPageTemplateFile("templates/widget.pt")
64
65
    def __init__(self, context, request):
66
        super(SenaiteRenderWidget, self).__init__(context, request)
67
        self.context = context
68
        self.request = request
69
        # allow per mode styling
70
        if context:
71
            context.klass = self.get_widget_mode_css(context)
72
73
    def get_mode(self):
74
        """Get the current widget mode
75
76
        returns either input, display or hidden
77
        """
78
        return self.context.mode
79
80
    def is_input_mode(self):
81
        """Check if we are in INPUT mode
82
        """
83
        return self.get_mode() == INPUT_MODE
84
85
    def is_view_mode(self):
86
        """Checks if we are in view (DISPLAY/HIDDEN) mode
87
        """
88
        return not self.is_input_mode()
89
90
    def get_widget_mode_css(self, widget):
91
        """Allows mode specific css styling for the widget itself
92
93
        Example:
94
95
            directives.widget("department_id",
96
                              widget_css_display="text-danger text-monospace",
97
                              widget_css_input="text-primary")
98
            department_id = schema.TextLine(...)
99
        """
100
        mode = self.get_mode()
101
102
        widget_css = getattr(widget, "widget_css_%s" % mode, None)
103
        if not widget_css:
104
            widget_css = getattr(widget, "widget_css", None)
105
106
        if not widget_css:
107
            return widget.klass
108
109
        # append the mode specific widget css classes
110
        current_css = widget.klass.split()
111
        for cls in widget_css.split():
112
            if cls not in current_css:
113
                current_css.append(cls)
114
        return " ".join(current_css)
115
116
    def get_prepend_text(self):
117
        """Get the text/style to prepend to the input field
118
119
120
        Example:
121
122
            directives.widget("department_id",
123
                              before_text_input="ID",
124
                              before_css_input="text-secondary",
125
                              before_text_display="ID:",
126
                              before_css_display="font-weight-bold")
127
            department_id = schema.TextLine(...)
128
        """
129
        mode = self.get_mode()
130
        widget = self.context
131
132
        # omit the text in the current mode
133
        omit = getattr(widget, "before_text_omit_%s" % mode, False)
134
        if omit:
135
            return
136
137
        # get the append text
138
        before_text = getattr(widget, "before_text_%s" % mode, None)
139
        if not before_text:
140
            before_text = getattr(widget, "before_text", None)
141
142
        # get the CSS classes for the append text
143
        before_css = getattr(widget, "before_css_%s" % mode, None)
144
        if not before_css:
145
            before_css = getattr(widget, "before_css", None)
146
147
        return self.format_text(before_text, css=before_css)
148
149
    def get_append_text(self):
150
        """Get the text/style to append to the input field
151
152
        Example:
153
154
            directives.widget("department_id",
155
                              after_text="<i class='fas fa-id-card'></i>",
156
                              after_css="text-primary",
157
                              after_text_omit_display=True)
158
            department_id = schema.TextLine(...)
159
        """
160
        mode = self.get_mode()
161
        widget = self.context
162
163
        # omit the text in the current mode
164
        omit = getattr(widget, "after_text_omit_%s" % mode, False)
165
        if omit:
166
            return
167
168
        # get the append text
169
        after_text = getattr(widget, "after_text_%s" % mode, None)
170
        if not after_text:
171
            after_text = getattr(widget, "after_text", None)
172
173
        # get the CSS classes for the append text
174
        after_css = getattr(widget, "after_css_%s" % mode, None)
175
        if not after_css:
176
            after_css = getattr(widget, "after_css", None)
177
178
        return self.format_text(after_text, css=after_css)
179
180
    def format_text(self, text, css=None):
181
        """HTML format the text
182
        """
183
        if not text:
184
            return ""
185
        if css is None:
186
            css = ""
187
        context = {
188
            "text": text,
189
            "css": css,
190
191
        }
192
        return FORMAT_TPL.safe_substitute(context)
193
194
195
class SenaiteDefaultView(DefaultView):
196
    """The default view for Dexterity content.
197
    This uses a WidgetsView and renders all widgets in display mode.
198
    """
199
    tabs_template = ViewPageTemplateFile("templates/tabs.pt")
200
201
    def __init__(self, context, request):
202
        super(SenaiteDefaultView, self).__init__(context, request)
203
        self.context = context
204
        self.request = request
205
        self.enable_form_tabbing = self.get_default_form_tabbing()
206
        self.default_fieldset_label = _("General")
207
208
    def get_default_form_tabbing(self):
209
        tabbing = self.request.get("enable_form_tabbing", "1")
210
        if tabbing.lower() in ["0", "no"]:
211
            return False
212
        return True
213
214
    def render_widget_tabs(self):
215
        return self.tabs_template()
216
217
218
class SenaiteDefaultEditView(DefaultEditView):
219
    """The default edit view for Dexterity content.
220
    """
221
    def __init__(self, context, request):
222
        super(SenaiteDefaultEditView, self).__init__(context, request)
223
        self.context = context
224
        self.request = request
225
226
227
# Override the form for the standard full-page form rendering
228
# Code taken from plone.app.z3cform.views
229
230
form_factory = plone.z3cform.templates.ZopeTwoFormTemplateFactory(
231
    path("form.pt"),
232
    form=z3c.form.interfaces.IForm,
233
    request=ISenaiteFormLayer)
234