Passed
Push — 2.x ( 4c0257...3f8ac8 )
by Jordi
06:15
created

SenaiteRenderWidget.is_input_mode()   A

Complexity

Conditions 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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