Esempio n. 1
0
    def selector(rules):
        """
            Generate the rule selector for anonymize-form

            @param rules: the list of configured rules

            @return: the selector (DIV)
        """

        T = current.T

        selector = DIV(_class="anonymize-select", )

        for rule in rules:

            name = rule.get("name")
            if not name:
                continue

            title = T(rule.get("title", name))

            selector.append(
                DIV(
                    INPUT(
                        value="on",
                        _name=s3_str(name),
                        _type="checkbox",
                        _class="anonymize-rule",
                    ),
                    LABEL(title),
                    _class="anonymize-option",
                ))

        return selector
Esempio n. 2
0
    def widget(cls, field, value, **attributes):
        """
        Simple and best way to do radio boxes and/or checkboxes
        """
        if isinstance(value, (list, tuple)):
            value = str(value[0])
        else:
            value = str(value)

        attr = cls._attributes(field, {}, **attributes)
        attr['_class'] = add_class(attr.get('_class'), 'radio-widget')
        # attr['_class'] = 'row'

        requires = field.requires
        if not isinstance(requires, (list, tuple)):
            requires = [requires]
        if requires:
            if hasattr(requires[0], 'options'):
                options = requires[0].options()
            else:
                raise SyntaxError('widget cannot determine options of %s' %
                                  field)
            _type = 'checkbox' if getattr(requires[0], 'multiple') else 'radio'

        options = [(k, v) for k, v in options if str(v)]
        opts = []
        cols = attributes.get('cols', 1)
        totals = len(options)
        mods = totals % cols
        rows = totals / cols
        if mods:
            rows += 1

        parent, child, inner = DIV, DIV, P

        for r_index in range(rows):
            tds = []
            for k, v in options[r_index * cols:(r_index + 1) * cols]:
                checked = {'_checked': 'checked'} if k == value else {}
                tds.append(
                    inner(INPUT(_type=_type,
                                _id='%s%s' % (field.name, k),
                                _name=field.name,
                                requires=attr.get('requires', None),
                                hideerror=True,
                                _value=k,
                                value=value,
                                **checked),
                          LABEL(v, _for='%s%s' % (field.name, k)),
                          _class="col s12 m%s" % (12 / cols)))
            opts.append(child(tds, _class='row'))

        if opts:
            opts[-1][0][0]['hideerror'] = False
        if len(opts) == 1:
            opts[0].attributes.update(attr)
            return opts[0]
        return parent(*opts, **attr)
Esempio n. 3
0
 def _render_tag_div(self, label, controls, help):
     row = DIV(_class='col s12')
     label.tag = 'SPAN'
     row.append(DIV(
         DIV(label, controls[0], _class='btn'),
         DIV(INPUT(_class='file-path validate', _type='text'), _class='file-path-wrapper'),
         _class='file-field input-field'
     ))
     row.append(A(controls[3], _href=controls[1][1]['_href']))
     row.append(DIV(
         P(LABEL(controls[1][3], SPAN(controls[1][4][0])))
     ))
     return row
Esempio n. 4
0
    def render_row(row_id, label, widget, comment, hidden=False):

        # Inspect widget
        columns = None
        if hasattr(widget, "element"):
            # Check for widget columns width override
            attr = widget.element().attributes
            if "s3cols" in attr:
                columns = attr["s3cols"] or columns
            # Set additional CSS classes for submit button
            submit = widget.element("input", _type="submit")
            if submit:
                submit.add_class("small primary button")

        # Render tooltip
        hints = render_tooltip(label, comment)

        # Wrap the label
        if isinstance(label, LABEL):
            label.add_class("right inline")
        else:
            label = LABEL(
                label,
                _class="right inline",
            )
        label = DIV(
            label,
            _class="small-2 columns",
        )

        # Wrap the controls
        if columns is None:
            _columns = "small-10 columns"
        else:
            _columns = "small-%s columns end" % columns
        controls = DIV(
            widget,
            hints,
            _class=_columns,
        )

        # Render the row
        _class = "form-row row"
        if hidden:
            _class = "%s hide" % _class
        return DIV(
            label,
            controls,
            _class=_class,
            _id=row_id,
        )
Esempio n. 5
0
 def widget(cls, field, value, **attributes):
     """
     Turn me on. lol! (or off)
     """
     _id = str(field).replace('.', '_')
     attributes['_type'] = 'checkbox'
     return DIV(P(LABEL(
         'Off',
         INPUT(_id=_id,
               _name=field.name,
               requires=field.requires,
               value=value,
               **attributes),
         SPAN(_class='lever'),
         'On',
         _for=_id,
     ),
                  _style='padding:20px'),
                _class='switch')
Esempio n. 6
0
def customfield(form, field):
    tablefield = (form.table, field)
    maindiv = DIV(_id="%s_%s__row" % tablefield, _class="row")
    labeldiv = DIV(_class="w2p_fl")
    commentdiv = DIV(_class="w2p_fc")
    widgetdiv = DIV(_class="w2p_fw")

    label = LABEL(form.custom.label[field],
                  _for="%s_%s" % tablefield,
                  _id="%s_%s__label" % tablefield)
    comment = form.custom.comment[field]
    widget = form.custom.widget[field]

    labeldiv.append(label)
    commentdiv.append(comment)
    widgetdiv.append(widget)

    maindiv.append(labeldiv)
    maindiv.append(commentdiv)
    maindiv.append(widgetdiv)

    return maindiv
Esempio n. 7
0
    def apply_method(r, **attr):
        """
            Apply method.

            @param r: the S3Request
            @param attr: controller options for this request
        """

        if r.representation == "html":

            T = current.T
            s3db = current.s3db
            response = current.response
            table = r.table
            tracker = S3Trackable(table, record_id=r.id)

            title = T("Check-In")

            get_vars = r.get_vars

            # Are we being passed a location_id?
            location_id = get_vars.get("location_id", None)
            if not location_id:
                # Are we being passed a lat and lon?
                lat = get_vars.get("lat", None)
                if lat is not None:
                    lon = get_vars.get("lon", None)
                    if lon is not None:
                        form_vars = Storage(
                            lat=float(lat),
                            lon=float(lon),
                        )
                        form = Storage(vars=form_vars)
                        s3db.gis_location_onvalidation(form)
                        location_id = s3db.gis_location.insert(**form_vars)

            form = None
            if not location_id:
                # Give the user a form to check-in

                # Test the formstyle
                formstyle = current.deployment_settings.get_ui_formstyle()
                row = formstyle("test", "test", "test", "test")
                if isinstance(row, tuple):
                    # Formstyle with separate row for label (e.g. default Eden formstyle)
                    tuple_rows = True
                else:
                    # Formstyle with just a single row (e.g. Bootstrap, Foundation or DRRPP)
                    tuple_rows = False

                form_rows = []
                comment = ""

                _id = "location_id"
                label = LABEL("%s:" % T("Location"))

                from .s3widgets import S3LocationSelector
                field = table.location_id
                #value = tracker.get_location(_fields=["id"],
                #                             as_rows=True).first().id
                value = None  # We always want to create a new Location, not update the existing one
                widget = S3LocationSelector(show_latlon=True)(field, value)

                row = formstyle("%s__row" % _id, label, widget, comment)
                if tuple_rows:
                    form_rows.append(row[0])
                    form_rows.append(row[1])
                else:
                    form_rows.append(row)

                _id = "submit"
                label = ""
                widget = INPUT(_type="submit", _value=T("Check-In"))
                row = formstyle("%s__row" % _id, label, widget, comment)
                if tuple_rows:
                    form_rows.append(row[0])
                    form_rows.append(row[1])
                else:
                    form_rows.append(row)

                if tuple_rows:
                    # Assume TRs
                    form = FORM(TABLE(*form_rows))
                else:
                    form = FORM(*form_rows)

                if form.accepts(current.request.vars, current.session):
                    location_id = form.vars.get("location_id", None)

            if location_id:
                # We're not Checking-in in S3Track terms (that's about interlocking with another object)
                #tracker.check_in()
                #timestmp = form.vars.get("timestmp", None)
                #if timestmp:
                #    # @ToDo: Convert from string
                #    pass
                #tracker.set_location(location_id, timestmp=timestmp)
                tracker.set_location(location_id)
                response.confirmation = T("Checked-In successfully!")

            response.view = "check-in.html"
            output = dict(
                form=form,
                title=title,
            )
            return output

        # @ToDo: JSON representation for check-in from mobile devices
        else:
            raise HTTP(415, current.ERROR.BAD_FORMAT)
Esempio n. 8
0
    def layout(item):
        """ Layout Method (Item Renderer) """

        # Manage flags: hide any disabled/unauthorized items
        if not item.authorized and not item.opts.always_display:
            item.enabled = False
            item.visible = False
        elif item.enabled is None or item.enabled:
            item.enabled = True
            item.visible = True

        if item.enabled and item.visible:

            items = item.render_components()
            if item.parent is not None:

                if item.attr._class:
                    classes = item.attr._class.split(" ")
                else:
                    classes = []

                if item.parent.parent is None:
                    # Item at the top-level?
                    toplevel = True
                    if item.opts.right:
                        classes.append("menu-right")
                else:
                    toplevel = False

                if item.components:
                    classes.append("has-dropdown not-click")
                    _class = " ".join(classes)
                    # Menu item with Dropdown
                    if item.get_first(enabled=True):
                        _href = item.url()
                        return LI(
                            A(item.label, _href=_href, _id=item.attr._id),
                            UL(items, _class="dropdown"),
                            _class=_class,
                        )
                else:
                    # Menu item without Drop-Down
                    if toplevel:
                        item_url = item.url()
                        if item_url == URL(c="default", f="index"):
                            classes.append("menu-home")
                        if item.selected:
                            classes.append("active")
                        _class = " ".join(classes)
                        icon = item.opts.icon
                        if icon:
                            label = LABEL(ICON(icon), item.label)
                        else:
                            label = item.label
                        return LI(
                            A(
                                label,
                                _href=item_url,
                                _id=item.attr._id,
                                _target=item.attr._target,
                            ),
                            _class=_class,
                        )
                    else:
                        # Submenu item
                        if isinstance(item.label, dict):
                            if "id" in item.label:
                                return S3MainMenuDefaultLayout.checkbox_item(
                                    item)
                            elif "name" in item.label:
                                label = item.label["name"]
                            else:
                                return None
                        else:
                            label = item.label
                        link = A(
                            label,
                            _href=item.url(),
                            _id=item.attr._id,
                            _target=item.attr._target,
                        )
                        _class = " ".join(classes)
                        return LI(link, _class=_class)
            else:
                # The main menu itself
                T = current.T
                settings = current.deployment_settings

                if item.opts.title_area:
                    # Custom override
                    title_area = item.opts.title_area
                else:
                    # Standard: render a menu logo
                    logo = settings.get_ui_menu_logo()
                    if logo is None:
                        # Render an icon
                        logo = SPAN(
                            settings.get_system_name_short(),
                            _class="logo",
                        )
                    elif isinstance(logo, str):
                        # Assume image-URL
                        logo = IMG(
                            _src=logo,
                            _class="logo",
                            _alt=settings.get_system_name_short(),
                        )
                    #else:
                    # use as-is (assume HTML or T())
                    title_area = A(
                        logo,
                        _href=URL(c="default", f="index"),
                        _title=T("Homepage"),
                    )

                # Arrange items left/right
                right = []
                left = []
                for item in items:
                    if "menu-right" in item["_class"]:
                        item.remove_class("menu-right")
                        right.append(item)
                    else:
                        left.append(item)
                right.reverse()

                # Reverse if right-to-left
                if current.response.s3.rtl:
                    right, left = left, right

                # Build top-bar HTML
                return NAV(
                    UL(
                        LI(
                            title_area,
                            _class="name",
                        ),
                        LI(
                            A(SPAN(T("Menu"))),
                            _class="toggle-topbar menu-icon",
                        ),
                        _class="title-area",
                    ),
                    SECTION(
                        UL(
                            right,
                            _class="right",
                        ),
                        UL(
                            left,
                            _class="left",
                        ),
                        _class="top-bar-section",
                    ),
                    _class="top-bar",
                    data={"topbar": " "},
                )
        else:
            return None
Esempio n. 9
0
    def layout(item):
        """ Layout Method (Item Renderer) """

        # Manage flags: hide any disabled/unauthorized items
        if not item.authorized and not item.opts.always_display:
            item.enabled = False
            item.visible = False
        elif item.enabled is None or item.enabled:
            item.enabled = True
            item.visible = True

        if item.enabled and item.visible:
            items = item.render_components()

            if item.parent is None:
                # The menu itself

                number_of_links = 0

                components = []
                append = components.append
                for submenu in items:
                    append(submenu)
                    number_of_links += len(submenu.elements("a"))

                # Hide the entire menu if it doesn't contain any links
                if not number_of_links:
                    return None

                title = H3(item.label) if item.label else ""
                menu = DIV(
                    title,
                    DIV(
                        TAG[""](components),
                        _class="icon-bar four-up",
                    ),
                    _id=item.attr._id,
                    _class=item.attr._class,
                )

                return menu

            else:
                # A menu item
                _class = item.attr._class
                if _class:
                    _class = "%s item" % _class
                else:
                    _class = "item"
                _id = item.attr._id

                icon = item.opts.icon
                if icon:
                    label = LABEL(ICON(icon), item.label)
                else:
                    label = LABEL(item.label)
                return A(
                    label,
                    _class=_class,
                    _href=item.url(),
                    _id=_id,
                )
        else:
            return None
Esempio n. 10
0
    def layout(item):
        """ Layout Method (Item Renderer) """

        # Manage flags: hide any disabled/unauthorized items
        if not item.authorized and not item.opts.always_display:
            item.enabled = False
            item.visible = False
        elif item.enabled is None or item.enabled:
            item.enabled = True
            item.visible = True

        if item.enabled and item.visible:

            items = item.render_components()
            if item.parent is not None:

                if item.attr._class:
                    classes = item.attr._class.split(" ")
                else:
                    classes = []

                if item.parent.parent is None:
                    # Item at the top-level?
                    toplevel = True
                    if item.opts.right:
                        classes.append("menu-right")
                else:
                    toplevel = False

                if item.components:
                    # Menu item with Dropdown
                    if item.get_first(enabled=True):
                        classes.append(
                            "is-dropdown-submenu-parent")  # Prevent FoUC
                        _class = " ".join(classes)
                        return LI(
                            A(
                                item.label,
                                _href=item.url(),
                                _id=item.attr._id,
                            ),
                            UL(
                                items,
                                _class="menu",
                            ),
                            _class=_class,
                        )
                else:
                    # Menu item without Drop-Down
                    if toplevel:
                        item_url = item.url()
                        if item_url == URL(c="default", f="index"):
                            classes.append("menu-home")
                        if item.selected:
                            classes.append("active")
                        _class = " ".join(classes)
                        icon = item.opts.icon
                        if icon:
                            label = LABEL(ICON(icon), item.label)
                        else:
                            label = item.label
                        return LI(
                            A(
                                label,
                                _href=item_url,
                                _id=item.attr._id,
                                _target=item.attr._target,
                            ),
                            _class=_class,
                        )
                    else:
                        # Submenu item
                        if isinstance(item.label, dict):
                            if "id" in item.label:
                                return S3MainMenuDefaultLayout.checkbox_item(
                                    item)
                            elif "name" in item.label:
                                label = item.label["name"]
                            else:
                                return None
                        else:
                            label = item.label
                        link = A(
                            label,
                            _href=item.url(),
                            _id=item.attr._id,
                            _target=item.attr._target,
                        )
                        _class = " ".join(classes)
                        return LI(
                            link,
                            _class=_class,
                        )
            else:
                # The main menu itself

                # Arrange items left/right
                right = []
                left = []
                for item in items:
                    if "menu-right" in item["_class"]:
                        item.remove_class("menu-right")
                        right.append(item)
                    else:
                        left.append(item)
                right.reverse()

                # Reverse if right-to-left
                if current.response.s3.rtl:
                    right, left = left, right

                left = UL(
                    left,
                    _class="menu dropdown",
                )
                left["_data-dropdown-menu"] = ""
                right = UL(
                    right,
                    _class="menu dropdown",
                )
                right["_data-dropdown-menu"] = ""

                # Build top-bar HTML
                return NAV(
                    DIV(
                        left,
                        _class="top-bar-left",
                    ),
                    DIV(
                        right,
                        _class="top-bar-right",
                    ),
                    _class="top-bar",
                )
        else:
            return None
Esempio n. 11
0
    def widget(
        cls,
        r,
        record_ids=None,
        _class="action-lnk",
    ):
        """
            Render an action item (link or button) to anonymize the
            provided records

            @param r: the S3Request
            @param record_ids: The list of record_ids to act on
            @param _class: HTML class for the action item

            @returns: the action item (a HTML helper instance), or an empty
                      string if no anonymize-rules are configured for the
                      target table, no target record was specified or the
                      user is not permitted to anonymize it
        """

        T = current.T

        default = ""

        # Determine target table
        if r.component:
            resource = r.component
            if resource.link and not r.actuate_link():
                resource = resource.link
        else:
            resource = r.resource
        table = resource.table

        # Determine target record
        if not record_ids:
            return default

        # Check if target is configured for anonymize
        rules = resource.get_config("anonymize")
        if not rules:
            return default
        if not isinstance(rules, (tuple, list)):
            # Single rule
            rules["name"] = "default"
            rules = [rules]

        # Determine widget ID
        widget_id = "%s-anonymize" % table

        # Dialog and Form
        INFO = T(
            "The following information will be deleted from all the selected records"
        )
        CONFIRM = T("Are you sure you want to delete the selected details?")
        #SUCCESS = T("Action successful - please wait...")

        form = FORM(
            P("%s:" % INFO),
            cls.selector(rules),
            P(CONFIRM),
            DIV(
                INPUT(
                    value="anonymize_confirm",
                    _name="anonymize_confirm",
                    _type="checkbox",
                ),
                LABEL(T("Yes, delete the selected details")),
                _class="anonymize-confirm",
            ),
            DIV(
                INPUT(
                    _class="small alert button anonymize-submit",
                    _disabled="disabled",
                    _type="submit",
                    _value=T("Anonymize"),
                ),
                _class="anonymize-buttons",
            ),
            _class="anonymize-form",
            # Store action key in form
            hidden={"action-key": cls.action_key(widget_id)},
        )

        script = '''var submitButton=$('.anonymize-submit');
$('input[name="anonymize_confirm"]').off('.anonymize').on('click.anonymize',function(){if ($(this).prop('checked')){submitButton.prop('disabled',false);}else{submitButton.prop('disabled',true);}});'''
        current.response.s3.jquery_ready.append(script)

        return form
Esempio n. 12
0
    def widget(
        cls,
        r,
        label="Anonymize",
        ajaxURL=None,
        _class="action-lnk",
    ):
        """
            Render an action item (link or button) to anonymize the
            target record of an S3Request, which can be embedded in
            the record view

            @param r: the S3Request
            @param label: The label for the action item
            @param ajaxURL: The URL for the AJAX request
            @param _class: HTML class for the action item

            @returns: the action item (a HTML helper instance), or an empty
                      string if no anonymize-rules are configured for the
                      target table, no target record was specified or the
                      user is not permitted to anonymize it
        """

        T = current.T

        default = ""

        # Determine target table
        if r.component:
            resource = r.component
            if resource.link and not r.actuate_link():
                resource = resource.link
        else:
            resource = r.resource
        table = resource.table

        # Determine target record
        record_id = S3Anonymize._record_id(r)
        if not record_id:
            return default

        # Check if target is configured for anonymize
        rules = resource.get_config("anonymize")
        if not rules:
            return default
        if not isinstance(rules, (tuple, list)):
            # Single rule
            rules["name"] = "default"
            rules = [rules]

        # Check permissions to anonymize
        if not S3Anonymize.permitted(table, record_id):
            return default

        # Determine widget ID
        widget_id = "%s-%s-anonymize" % (table, record_id)

        # Inject script
        if ajaxURL is None:
            ajaxURL = r.url(
                method="anonymize",
                representation="json",
            )
        script_options = {
            "ajaxURL": ajaxURL,
        }
        next_url = resource.get_config("anonymize_next")
        if next_url:
            script_options["nextURL"] = next_url
        cls.inject_script(widget_id, script_options)

        # Action button
        translated_label = T(label)
        action_button = A(translated_label, _class="anonymize-btn")
        if _class:
            action_button.add_class(_class)

        # Dialog and Form
        INFO = T("The following information will be deleted from the record")
        CONFIRM = T("Are you sure you want to delete the selected details?")
        SUCCESS = T("Action successful - please wait...")

        form = FORM(
            P("%s:" % INFO),
            cls.selector(rules),
            P(CONFIRM),
            DIV(
                INPUT(
                    value="anonymize_confirm",
                    _name="anonymize_confirm",
                    _type="checkbox",
                ),
                LABEL(T("Yes, delete the selected details")),
                _class="anonymize-confirm",
            ),
            cls.buttons(),
            _class="anonymize-form",
            # Store action key in form
            hidden={"action-key": cls.action_key(widget_id)},
        )

        dialog = DIV(
            form,
            DIV(
                P(SUCCESS),
                _class="hide anonymize-success",
            ),
            _class="anonymize-dialog hide",
            _title=translated_label,
        )

        # Assemble widget
        widget = DIV(
            action_button,
            dialog,
            _class="s3-anonymize",
            _id=widget_id,
        )

        return widget
Esempio n. 13
0
 def _render_tag_input_boolean(self, label, controls, help):
     row = DIV(_class='input-field col s12')
     row.append(P(LABEL(controls, SPAN(label[0]))))
     return row
Esempio n. 14
0
    def __call__(self, field, value, **attributes):
        """
            Widget renderer for the input field; to be set as widget=self
            for the field returned by the resolve()-method.

            @param field: the input field
            @param value: the value to populate the widget
            @param attributes: attributes for the widget
            @return: the widget for this form element as HTML helper
        """

        T = current.T
        settings = current.deployment_settings

        # Check current value
        if isinstance(value, str):
            try:
                value = json.loads(value) if value else {}
            except JSONERRORS:
                value = {}
        elif not value:
            value = {}
        delegation_id = value.get("delegationID") if value else None

        # Form name and widget ID
        formname = self._formname()
        widget_id = attributes.get("_id")
        if not widget_id:
            widget_id = str(field).replace(".", "_")

        # Ajax parameters
        if delegation_id:
            ajax_args = [delegation_id, "notifications.json"]
            ajax_vars = {}
        else:
            ajax_args = ["notifications.json"]
            dtable = current.s3db.hrm_delegation
            person_id = dtable.person_id.default
            ajax_vars = {
                "viewing": "pr_person.%s" % person_id
            } if person_id else {}

        # Sender and recipient types
        sender = self.options.get("sender")
        if sender:
            ajax_vars["sender"] = sender
        notifications = DeploymentNotifications(delegation_id, sender=sender)
        recipients = list(notifications.recipients.keys())

        # Selectable organisations
        organisations = self.options.get("organisations")

        # Inject script
        options = {
            "ajaxURL":
            URL(
                c="hrm",
                f="delegation",
                args=ajax_args,
                vars=ajax_vars,
            ),
            "formName":
            formname,
            "recipients":
            recipients,
            "organisations":
            organisations,
        }
        self.inject_js(widget_id, options)

        # The widget
        widget = DIV(
            INPUT(
                _type="hidden",
                _name=field.name,
                _value=json.dumps(value),
                _class="notification-data",
            ),
            _id=widget_id,
        )

        # Add field set per recipient type
        labels = {
            "organisation": T("Requesting Organisation"),
            "volunteer": T("Volunteer"),
            "office": T("Office##gov"),
        }
        formstyle = settings.get_ui_formstyle()
        for recipient in recipients:
            input_name = "%s_%s" % (formname, recipient)
            formfields = [
                Field(
                    "%s_email" % input_name,
                    label=T("Email"),
                ),
                Field(
                    "%s_subject" % input_name,
                    label=T("Subject"),
                    widget=self.subject_widget,
                ),
                Field(
                    "%s_message" % input_name,
                    "text",
                    label=T("Message"),
                    widget=self.message_widget,
                ),
            ]
            form = SQLFORM.factory(record=None,
                                   showid=False,
                                   formstyle=formstyle,
                                   buttons=[],
                                   table_name="sub",
                                   *formfields)
            toggle_name = "%s_notify_%s" % (formname, recipient)

            toggle_edit = DIV(
                A(
                    T("Preview"),
                    _class="preview-toggle action-lnk",
                    _style="display:none",
                ),
                A(
                    T("Edit"),
                    _class="preview-toggle action-lnk",
                ),
                _class="preview-toggles",
            )
            subform = DIV(
                FIELDSET(
                    LEGEND(
                        LABEL(
                            INPUT(
                                _type="checkbox",
                                _class="notify-toggle",
                                value=True,
                                _name=toggle_name,
                                _id=toggle_name,
                            ),
                            labels.get(recipient, "?"),
                        ), ),
                    form[0],
                    toggle_edit,
                ),
                _class="notification",
            )
            widget.append(subform)

        return widget