예제 #1
0
    def __init__(self, size="xl", widgetattributes=None, **kwargs):
        kwargs["_class"] = kwargs.get("_class", "") + f" bx--search bx--search--{size}"
        kwargs["data-search"] = True
        kwargs["role"] = "search"

        attributes = {
            "id": "search__" + hg.html_id(self),
            "_class": "bx--search-input",
            "type": "text",
            "placeholder": _("Search"),
            **(widgetattributes or {}),
        }

        super().__init__(
            hg.LABEL(_("Search"), _class="bx--label", _for=attributes["id"]),
            hg.INPUT(**attributes),
            Icon("search", size=16, _class="bx--search-magnifier", aria_hidden="true"),
            hg.BUTTON(
                Icon("close", size=20, _class="bx--search-clear"),
                _class="bx--search-close bx--search-close--hidden",
                title=_("Clear search input"),
                aria_label=_("Clear search input"),
                type="button",
            ),
            **kwargs,
        )
예제 #2
0
    def __init__(
        self,
        fieldname,
        light=False,
        widgetattributes={},
        **attributes,
    ):
        self.fieldname = fieldname
        attributes["_class"] = (attributes.get("_class", "") +
                                " bx--form-item bx--text-input-wrapper")
        widgetattributes["_class"] = (
            widgetattributes.get("_class", "") +
            f" bx--text-input {'bx--text-input--light' if light else ''}")

        super().__init__(
            htmlgenerator.LABEL(_class="bx--label"),
            htmlgenerator.DIV(
                htmlgenerator.INPUT(**widgetattributes),
                _class="bx--text-input__field-wrapper",
            ),
            **attributes,
        )
        # for easier reference in the render method:
        self.label = self[0]
        self.input = self[1][0]
예제 #3
0
    def __init__(
        self,
        fieldname,
        placeholder="",
        rows=None,
        cols=None,
        light=False,
        widgetattributes={},
        **attributes,
    ):
        self.fieldname = fieldname
        attributes["_class"] = attributes.get("_class", "") + " bx--form-item"

        widgetattributes["_class"] = (
            widgetattributes.get("_class", "") +
            f" bx--text-area bx--text-area--v2 {'bx--text-area--light' if light else ''}",
        )
        if rows:
            widgetattributes["rows"] = rows
        if cols:
            widgetattributes["cols"] = cols

        super().__init__(
            htmlgenerator.LABEL(_class="bx--label"),
            htmlgenerator.DIV(
                htmlgenerator.TEXTAREA(placeholder=placeholder,
                                       **widgetattributes),
                _class="bx--text-area__wrapper",
            ),
            **attributes,
        )
        # for easier reference in the render method:
        self.label = self[0]
        self.input = self[1][0]
예제 #4
0
 def __init__(
     self,
     label=None,
     help_text=None,
     errors=None,
     inputelement_attrs=None,
     boundfield=None,
     **attributes,
 ):
     inputelement_attrs = inputelement_attrs or {}
     attrs = {}
     if boundfield:
         attrs["checked"] = hg.F(
             lambda c: hg.resolve_lazy(boundfield, c).field.widget.
             check_test(hg.resolve_lazy(boundfield, c).value()))
     inputelement_attrs = _combine_lazy_dict(inputelement_attrs, attrs)
     label = None if label is None else label.label
     super().__init__(
         self.get_input_element(inputelement_attrs, errors),
         hg.LABEL(
             hg.SPAN(_class="bx--radio-button__appearance"),
             hg.SPAN(label, _class="bx--radio-button__label-text"),
             _class="bx--radio-button__label",
             _for=inputelement_attrs.get("id"),
         ),
         help_text,
         errors,
         **hg.merge_html_attrs(attributes,
                               {"_class": "bx--radio-button-wrapper"}),
     )
예제 #5
0
    def __init__(
        self,
        size="xl",
        placeholder=None,
        widgetattributes=None,
        backend=None,
        resultcontainerid=None,
        show_result_container=True,
        resultcontainer_onload_js=None,
        disabled=False,
        **kwargs,
    ):
        """
        :param SearchBackendConfig backend: Where and how to get search results
        """
        kwargs["_class"] = kwargs.get("_class", "") + f" bx--search bx--search--{size}"
        kwargs["data_search"] = True
        kwargs["role"] = "search"
        width = kwargs.get("width", None)
        if width:
            kwargs["style"] = kwargs.get("style", "") + f"width:{width};"

        widgetattributes = {
            "id": "search__" + hg.html_id(self),
            "_class": "bx--search-input",
            "type": "text",
            "placeholder": placeholder or _("Search"),
            "autocomplete": "off",
            **(widgetattributes or {}),
        }
        if backend:
            if resultcontainerid is None:
                resultcontainerid = f"search-result-{hg.html_id((self, backend.url))}"
            widgetattributes["hx_get"] = backend.url
            widgetattributes["hx_trigger"] = "changed, click, keyup changed delay:500ms"
            widgetattributes["hx_target"] = hg.format("#{}", resultcontainerid)
            widgetattributes["hx_indicator"] = hg.format(
                "#{}-indicator", resultcontainerid
            )
            widgetattributes["name"] = backend.query_parameter

        self.close_button = _close_button(resultcontainerid, widgetattributes)

        super().__init__(
            hg.DIV(
                hg.LABEL(_("Search"), _class="bx--label", _for=widgetattributes["id"]),
                hg.INPUT(**widgetattributes),
                _search_icon(),
                self.close_button,
                hg.If(backend is not None, _loading_indicator(resultcontainerid)),
                **kwargs,
            ),
            hg.If(
                backend is not None and show_result_container,
                _result_container(resultcontainerid, resultcontainer_onload_js, width),
            ),
            style=hg.If(disabled, hg.BaseElement("display: none")),
        )
예제 #6
0
    def __init__(
        self,
        fieldname,
        placeholder="",
        light=False,
        short=False,
        simple=False,
        widgetattributes={},
        **attributes,
    ):
        self.fieldname = fieldname
        attributes["_class"] = attributes.get("_class", "") + " bx--form-item"
        picker_attribs = (
            {}
            if simple
            else {"data-date-picker": True, "data-date-picker-type": "single"}
        )
        widgetattributes["_class"] = (
            widgetattributes.get("_class", "") + " bx--date-picker__input"
        )

        input = htmlgenerator.INPUT(
            placeholder=placeholder,
            type="text",
            **widgetattributes,
        )
        self.input = input
        if not simple:
            input.attributes["data-date-picker-input"] = True
            input = htmlgenerator.DIV(
                input,
                Icon(
                    "calendar",
                    size=16,
                    _class="bx--date-picker__icon",
                    data_date_picker_icon="true",
                ),
                _class="bx--date-picker-input__wrapper",
            )

        super().__init__(
            htmlgenerator.DIV(
                htmlgenerator.DIV(
                    htmlgenerator.LABEL(_class="bx--label"),
                    input,
                    _class="bx--date-picker-container",
                ),
                _class="bx--date-picker"
                + (" bx--date-picker--simple" if simple else "bx--date-picker--single")
                + (" bx--date-picker--short" if short else "")
                + (" bx--date-picker--light" if light else ""),
                **picker_attribs,
            ),
            **attributes,
        )
        # for easier reference in the render method:
        self.label = self[0][0][0]
        self.simple = simple
예제 #7
0
 def __init__(
     self,
     fieldname,
     widgetattributes={},
     **attributes,
 ):
     self.fieldname = fieldname
     attributes["_class"] = (attributes.get("_class", "") +
                             " bx--form-item bx--checkbox-wrapper")
     widgetattributes["_class"] = (widgetattributes.get("_class", "") +
                                   " bx--checkbox")
     widgetattributes["type"] = "checkbox"
     self.input = htmlgenerator.INPUT(**widgetattributes)
     self.label = htmlgenerator.LABEL(self.input,
                                      _class="bx--checkbox-label")
     super().__init__(self.label, **attributes)
예제 #8
0
 def __init__(
     self,
     label=None,
     help_text=None,
     errors=None,
     inputelement_attrs=None,
     boundfield=None,
     **attributes,
 ):
     inputelement_attrs = inputelement_attrs or {}
     attrs = {}
     if boundfield:
         attrs["checked"] = hg.F(
             lambda c: hg.resolve_lazy(boundfield, c).field.widget.
             check_test(hg.resolve_lazy(boundfield, c).value()))
         attrs["value"] = None
     inputelement_attrs = _combine_lazy_dict(inputelement_attrs, attrs)
     # labels for checkboxes are treated a bit different, need to use plain value
     label = hg.F(lambda c, label=label: getattr(hg.resolve_lazy(label, c),
                                                 "label", label))
     required = hg.F(
         lambda c, label=label: hg.resolve_lazy(label, c) is not None)
     super().__init__(
         hg.LABEL(
             self.get_input_element(inputelement_attrs, errors),
             label,
             hg.If(inputelement_attrs.get("required"),
                   hg.If(required, REQUIRED_LABEL)),
             _class=hg.BaseElement(
                 "bx--checkbox-label",
                 hg.If(inputelement_attrs.get("disabled"),
                       " bx--label--disabled"),
             ),
             data_contained_checkbox_state=hg.If(
                 inputelement_attrs.get("checked"),
                 "true",
                 "false",
             ),
             data_invalid=hg.If(getattr(errors, "condition", False), True),
         ),
         help_text,
         errors,
         **hg.merge_html_attrs(attributes,
                               {"_class": "bx--checkbox-wrapper"}),
     )
예제 #9
0
 def __init__(
     self,
     label,
     offlabel=_("Off"),
     onlabel=_("On"),
     help_text=None,
     errors=None,
     disabled=None,
     required=None,
     widgetattributes={},
     **attributes,
 ):
     attributes["_class"] = attributes.get("_class", "") + " bx--form-item"
     widgetattributes["_class"] = (widgetattributes.get("_class", "") +
                                   " bx--toggle-input")
     widgetattributes["type"] = "checkbox"
     widgetattributes["id"] = widgetattributes.get("id",
                                                   None) or hg.html_id(self)
     self.input = hg.INPUT(**widgetattributes)
     self.label = hg.LABEL(
         label,
         hg.If(required, REQUIRED_LABEL),
         hg.SPAN(
             hg.SPAN(offlabel,
                     _class="bx--toggle__text--off",
                     aria_hidden="true"),
             hg.SPAN(onlabel,
                     _class="bx--toggle__text--on",
                     aria_hidden="true"),
             _class="bx--toggle__switch",
         ),
         _class=hg.BaseElement(
             "bx--label bx--toggle-input__label",
             hg.If(disabled, " bx--label--disabled"),
         ),
         _for=widgetattributes["id"],
     )
     super().__init__(
         self.input,
         self.label,
         HelpText(help_text),
         ErrorList(errors),
         **attributes,
     )
예제 #10
0
 def __init__(self,
              label,
              _for=None,
              required=None,
              disabled=None,
              **kwargs):
     self.label = label
     super().__init__(
         label,
         hg.LABEL(
             label,
             hg.If(required, REQUIRED_LABEL),
             _for=_for,
             _class=hg.BaseElement(
                 "bx--label",
                 hg.If(disabled, " bx--label--disabled"),
             ),
             **kwargs,
         ),
     )
예제 #11
0
    def with_toolbar(
        self,
        title: Any,
        helper_text: Any = None,
        primary_button: Optional[Button] = None,
        bulkactions: Iterable[Link] = (),
        pagination_config: Optional[PaginationConfig] = None,
        checkbox_for_bulkaction_name: str = "_selected",
        search_urlparameter: Optional[str] = None,
        settingspanel: Any = None,
    ):
        """
        wrap this datatable with title and toolbar
        title: table title
        helper_text: sub title
        primary_button: bread.layout.button.Button instance
        bulkactions: List of bread.utils.links.Link instances. Will send a post or a get (depending
                     on its "method" attribute) to the target url the sent data will be a form with
                     the selected checkboxes as fields if the head-checkbox has been selected only
                     that field will be selected.
        """
        checkboxallid = f"datatable-check-{hg.html_id(self)}"
        header: List[hg.BaseElement] = [
            hg.H4(title, _class="bx--data-table-header__title")
        ]
        if helper_text is not None:
            header.append(
                hg.P(helper_text, _class="bx--data-table-header__description"))
        bulkactionlist = []
        for link in bulkactions:
            bulkactionlist.append(
                Button(
                    link.label,
                    icon=link.iconname,
                    onclick=hg.BaseElement(
                        "submitbulkaction(this.closest('[data-table]'), '",
                        link.href,
                        "', method='GET')",
                    ),
                ), )

        if bulkactions:
            self.head.insert(
                0,
                hg.TH(
                    hg.INPUT(
                        data_event="select-all",
                        id=checkboxallid,
                        _class="bx--checkbox",
                        type="checkbox",
                        name=checkbox_for_bulkaction_name,
                        value="all",
                    ),
                    hg.LABEL(
                        _for=checkboxallid,
                        _class="bx--checkbox-label",
                    ),
                    _class="bx--table-column-checkbox",
                ),
            )
            self.iterator[0].insert(
                0,
                hg.TD(
                    hg.INPUT(
                        data_event="select",
                        id=hg.BaseElement(
                            checkboxallid,
                            "-",
                            hg.C(self.iterator.loopvariable + "_index"),
                        ),
                        _class="bx--checkbox",
                        type="checkbox",
                        name=checkbox_for_bulkaction_name,
                        value=hg.If(
                            hg.F(lambda c: hasattr(
                                c[self.iterator.loopvariable], "pk")),
                            hg.C(f"{self.iterator.loopvariable}.pk"),
                            hg.C(f"{self.iterator.loopvariable}_index"),
                        ),
                    ),
                    hg.LABEL(
                        _for=hg.BaseElement(
                            checkboxallid,
                            "-",
                            hg.C(self.iterator.loopvariable + "_index"),
                        ),
                        _class="bx--checkbox-label",
                        aria_label="Label name",
                    ),
                    _class="bx--table-column-checkbox",
                ),
            )

        return hg.DIV(
            hg.DIV(*header, _class="bx--data-table-header"),
            hg.SECTION(
                hg.DIV(
                    hg.DIV(
                        *(bulkactionlist + [
                            Button(
                                _("Cancel"),
                                data_event="action-bar-cancel",
                                _class="bx--batch-summary__cancel",
                            )
                        ]),
                        _class="bx--action-list",
                    ),
                    hg.DIV(
                        hg.P(
                            hg.SPAN(0, data_items_selected=True),
                            _(" items selected"),
                            _class="bx--batch-summary__para",
                        ),
                        _class="bx--batch-summary",
                    ),
                    _class="bx--batch-actions",
                    aria_label=_("Table Action Bar"),
                ),
                hg.DIV(
                    searchbar(search_urlparameter)
                    if search_urlparameter else None,
                    Button(
                        icon="settings--adjust",
                        buttontype="ghost",
                        onclick="""
let settings = this.parentElement.parentElement.parentElement.querySelector('.settingscontainer');
settings.style.display = settings.style.display == 'block' ? 'none' : 'block';
event.stopPropagation()""",
                    ) if settingspanel else None,
                    primary_button or None,
                    _class="bx--toolbar-content",
                ),
                _class="bx--table-toolbar",
            ),
            hg.DIV(
                hg.DIV(
                    hg.DIV(
                        settingspanel,
                        _class="bx--tile raised",
                        style="margin: 0; padding: 0",
                    ),
                    _class="settingscontainer",
                    style=
                    "position: absolute; z-index: 999; right: 0; display: none",
                    onload=
                    "document.addEventListener('click', (e) => {this.style.display = 'none'})",
                ),
                style="position: relative",
                onclick="event.stopPropagation()",
            ),
            self,
            Pagination.from_config(pagination_config)
            if pagination_config else None,
            _class="bx--data-table-container",
            data_table=True,
        )
예제 #12
0
    def __init__(
        self,
        label=None,
        help_text=None,
        errors=None,
        inputelement_attrs=None,
        boundfield=None,
        **attributes,
    ):
        inputelement_attrs = inputelement_attrs or {}
        uploadbutton = hg.LABEL(
            hg.SPAN(_("Select file"), role="button"),
            tabindex=0,
            _class=hg.BaseElement(
                "bx--btn bx--btn--tertiary",
                hg.If(inputelement_attrs.get("disabled"),
                      " bx--btn--disabled"),
            ),
            data_file_drop_container=True,
            disabled=inputelement_attrs.get("disabled"),
            data_invalid=hg.If(getattr(errors, "condition", False), True),
            _for=inputelement_attrs.get("id"),
        )
        input = self.get_input_element(
            inputelement_attrs,
            errors,
            onload="""
that = this;
document.addEventListener('change', (e) => {
    that.parentElement.querySelector('[data-file-container]').innerHTML = '';
    var widget = new CarbonComponents.FileUploader(that.parentElement);
    widget._displayFilenames();
    widget.setState('edit');
});
""",
        )
        # we can only clear the field if it originates form a django field
        # otherwise it has no use
        clearbox = None
        if boundfield:
            checkbox_name = hg.F(
                lambda c: hg.resolve_lazy(boundfield, c).field.widget.
                clear_checkbox_name(hg.resolve_lazy(boundfield, c).html_name))
            checkbox_id = hg.F(
                lambda c: hg.resolve_lazy(boundfield, c).field.widget.
                clear_checkbox_id(hg.resolve_lazy(checkbox_name, c)))
            clearbox = hg.If(
                self.clearable,
                hg.INPUT(
                    type="checkbox",
                    name=checkbox_name,
                    id=checkbox_id,
                    style="display: none",
                ),
            )

        # clearbutton is always used, to allow clearing a just selected field in the browser
        clearbutton = hg.If(
            self.clearable,
            hg.SPAN(
                hg.BUTTON(
                    Icon("close", size=16),
                    _class="bx--file-close",
                    type="button",
                    aria_label="close",
                    onclick=hg.If(
                        clearbox,
                        hg.format("$('#{}').checked = 'checked';",
                                  checkbox_id),
                    ),
                ),
                data_for=inputelement_attrs.get("id"),
                _class="bx--file__state-container",
            ),
        )

        super().__init__(
            label,
            hg.DIV(
                uploadbutton,
                input,
                clearbox,
                hg.DIV(
                    hg.If(
                        inputelement_attrs.get("value"),
                        hg.SPAN(
                            hg.P(
                                hg.If(
                                    hg.F(lambda c: hasattr(
                                        hg.resolve_lazy(inputelement_attrs, c).
                                        get("value").file,
                                        "name",
                                    )),
                                    hg.A(
                                        hg.F(lambda c: os.path.basename(
                                            hg.resolve_lazy(
                                                inputelement_attrs, c).get(
                                                    "value").name)),
                                        href=hg.F(lambda c: settings.MEDIA_URL
                                                  + hg.resolve_lazy(
                                                      inputelement_attrs, c
                                                  ).get("value").name),
                                    ),
                                    hg.F(lambda c: os.path.basename(
                                        hg.resolve_lazy(inputelement_attrs, c).
                                        get("value").name)),
                                ),
                                _class="bx--file-filename",
                            ),
                            clearbutton,
                            _class="bx--file__selected-file",
                        ),
                    ),
                    data_file_container=True,
                    _class="bx--file-container",
                ),
                help_text,
                errors,
                _class="bx--file",
                data_file=True,
            ),
            **attributes,
        )
예제 #13
0
    def __init__(
            self,
            label=None,
            help_text=None,
            errors=None,
            inputelement_attrs=None,
            boundfield=None,  # for django-form select elements use this
            choices=None,  # for non-django-form select elements use this
            **attributes,  # for non-django-form select elements use this
    ):
        inputelement_attrs = inputelement_attrs or {}
        optgroups = (_optgroups_from_choices(
            choices,
            name=inputelement_attrs.get("name"),
            value=inputelement_attrs.get("value"),
        ) if choices else _gen_optgroup(boundfield))

        def countselected(context):
            options = [
                o for og in hg.resolve_lazy(optgroups, context) for o in og[1]
            ]
            return len([o for o in options if o and o["selected"]])

        searchfieldid = hg.html_id(self)
        super().__init__(
            label,
            hg.If(
                inputelement_attrs.get("disabled"),
                hg.DIV(
                    hg.Iterator(
                        optgroups,
                        "optiongroup",
                        hg.Iterator(
                            hg.C("optiongroup.1"),
                            "option",
                            hg.If(hg.C("option.selected"),
                                  Tag(hg.C("option.label"))),
                        ),
                    )),
                hg.DIV(
                    hg.DIV(
                        hg.DIV(
                            hg.F(countselected),
                            Icon(
                                "close",
                                focusable="false",
                                size=15,
                                role="img",
                                onclick=
                                "clearMultiselect(this.parentElement.parentElement.parentElement)",
                            ),
                            role="button",
                            _class=
                            "bx--list-box__selection bx--list-box__selection--multi bx--tag--filter",
                            tabindex="0",
                            title="Clear all selected items",
                        ),
                        hg.INPUT(
                            id=searchfieldid,
                            _class="bx--text-input",
                            placeholder="Filter...",
                            onclick=
                            "this.parentElement.nextElementSibling.style.display = 'block'",
                            onkeyup=
                            "filterOptions(this.parentElement.parentElement)",
                        ),
                        hg.DIV(
                            Icon("chevron--down",
                                 size=16,
                                 role="img",
                                 focusable="false"),
                            _class="bx--list-box__menu-icon",
                            onclick=
                            "this.parentElement.nextElementSibling.style.display = this.parentElement.nextElementSibling.style.display == 'none' ? 'block' : 'none';",
                        ),
                        role="button",
                        _class="bx--list-box__field",
                        tabindex="0",
                        onload=
                        "window.addEventListener('click', (e) => {this.nextElementSibling.style.display = 'none'})",
                    ),
                    hg.FIELDSET(
                        hg.Iterator(
                            optgroups,
                            "optgroup",
                            hg.Iterator(
                                hg.C("optgroup.1"),
                                "option",
                                hg.DIV(
                                    hg.DIV(
                                        hg.DIV(
                                            hg.LABEL(
                                                hg.INPUT(
                                                    type="checkbox",
                                                    readonly=True,
                                                    _class="bx--checkbox",
                                                    value=hg.C("option.value"),
                                                    lazy_attributes=hg.C(
                                                        "option.attrs"),
                                                    onchange=
                                                    "updateMultiselect(this.closest('.bx--multi-select'))",
                                                    checked=hg.C(
                                                        "option.selected"),
                                                    name=hg.C("option.name"),
                                                ),
                                                hg.SPAN(
                                                    _class=
                                                    "bx--checkbox-appearance"),
                                                hg.SPAN(
                                                    hg.C("option.label"),
                                                    _class=
                                                    "bx--checkbox-label-text",
                                                ),
                                                title=hg.C("option.label"),
                                                _class="bx--checkbox-label",
                                            ),
                                            _class=
                                            "bx--form-item bx--checkbox-wrapper",
                                        ),
                                        _class=
                                        "bx--list-box__menu-item__option",
                                    ),
                                    _class="bx--list-box__menu-item",
                                ),
                            ),
                        ),
                        _class="bx--list-box__menu",
                        role="listbox",
                        style="display: none",
                    ),
                    _class=hg.BaseElement(
                        "bx--multi-select bx--list-box bx--multi-select--selected bx--combo-box bx--multi-select--filterable",
                        hg.If(
                            inputelement_attrs.get("disabled"),
                            " bx--list-box--disabled",
                        ),
                    ),
                    data_invalid=hg.If(getattr(errors, "condition", None),
                                       True),
                ),
            ),
            help_text,
            errors,
            **hg.merge_html_attrs(
                attributes,
                {
                    "onclick": "event.stopPropagation()",
                    "_class": "bx--list-box__wrapper",
                },
            ),
        )