def management_form(self): # the management form is required for Django formsets return hg.BaseElement( # management forms, for housekeeping of inline forms hg.F(lambda c: Form( c[self.formname][self.fieldname].formset.management_form, *[ FormField( f, no_wrapper=True, no_label=True, no_helptext=True) for f in c[self.formname][self.fieldname].formset. management_form.fields ], standalone=False, )), # Empty form as template for new entries. The script tag works very well # for this since we need a single, raw, unescaped HTML string hg.SCRIPT( Form( hg.C(f"{self.formname}.{self.fieldname}.formset.empty_form" ), hg.WithContext( self.content, **{ DEFAULT_FORMSET_CONTEXTNAME: hg. C(f"{self.formname}.{self.fieldname}.formset.empty_form" ) }, ), standalone=False, ), id=hg.BaseElement( "empty_", hg.C(f"{self.formname}.{self.fieldname}.formset.prefix"), "_form", ), type="text/plain", ), hg.SCRIPT( mark_safe( "document.addEventListener('DOMContentLoaded', e => init_formset('" ), hg.C(f"{self.formname}.{self.fieldname}.formset.prefix"), mark_safe("'));"), ), hg.SPAN(onload=hg.BaseElement( mark_safe("init_formset('"), hg.C(f"{self.formname}.{self.fieldname}.formset.prefix"), mark_safe("');"), ), ), )
def __init__( self, label=None, help_text=None, errors=None, inputelement_attrs=None, boundfield=None, backend=None, **attributes, ): """ :param SearchBackendConfig backend: Where and how to get search results """ inputelement_attrs = inputelement_attrs or {} # This works inside a formset. Might need to be changed for other usages. widget_id = inputelement_attrs.get("id") resultcontainerid = hg.format("search-result-{}", widget_id) tag_id = hg.format("{}-tag", widget_id) super().__init__( label, Tag( hg.F(lambda c: hg.resolve_lazy(boundfield, c).field.to_python( hg.resolve_lazy(boundfield, c).value())) if boundfield else "", id=tag_id, style=hg.If( inputelement_attrs.get("value"), hg.BaseElement(""), hg.BaseElement("display: none;"), ), onclick="return false;", ), self.get_input_element(inputelement_attrs, errors, type="hidden"), Search( backend=backend, resultcontainerid=resultcontainerid, resultcontainer_onload_js=_resultcontainer_onload_js( backend, resultcontainerid, tag_id, widget_id), size="lg", disabled=inputelement_attrs.get("disabled", False), widgetattributes={"id": hg.format("search__{}", widget_id)}, ), help_text, errors, **hg.merge_html_attrs(attributes, {"_class": "bx--text-input-wrapper"}), )
def variable_size_header_part(platform, company, searchbar, searchbar_position): return hg.BaseElement( hg.A( logo(), platform, _class="bx--header__name", style="font-weight: 400", # override carbon design href=hg.F(lambda c: c["request"].META["SCRIPT_NAME"] or "/"), ), hg.If( searchbar, hg.SPAN( searchbar, style=f"position: absolute; left: {searchbar_position}", _class="theme-gray-100", ), "", ), hg.A( hg.SPAN( company, style=hg.format( "position: absolute; left: {}", hg.If(searchbar, "50%", searchbar_position), ), ), _class="bx--header__name", style="font-weight: 400", # override carbon design href=hg.F(lambda c: c["request"].META["SCRIPT_NAME"] or "/"), ), )
def personform_shortcut(request, formlayout): return hg.BaseElement( layout.grid.Grid( editperson_head(request), formlayout, gutter=False, ))
def get_layout(self): if hasattr(self, "layout") and self.layout is not None: ret = self.layout else: formfields = filter_fieldlist( self.model, [f for f in self.fields if isinstance(f, str)] if self.fields else None, for_form=True, ) ret = hg.BaseElement() for field in self.fields or formfields: if field in formfields: ret.append(breadlayout.forms.FormField(field)) else: ret.append(field) if self.ajax_urlparameter in self.request.GET: return breadlayout.forms.Form(hg.C("form"), ret) # wrap with form will add a submit button return hg.DIV( header(), breadlayout.tile.Tile( breadlayout.forms.Form( hg.C("form"), ret, breadlayout.forms.helpers.Submit() ), _class="theme-white", ), )
def generalsettings(request): if request.method == "POST": form = global_preference_form_builder( preferences=["general__organizationname"] )(request.POST, request.FILES) if form.is_valid(): form.update_preferences() else: form = global_preference_form_builder( preferences=["general__organizationname"] )() return layout.grid.Grid( R(C(hg.H3(_("Settings")))), R(C(hg.H4(_("General")))), R(C(hg.H5(_("Information about our organization")))), R( C( layout.forms.Form( form, hg.BaseElement(F("general__organizationname")), layout.forms.helpers.Submit(), style="max-width: 480px", ) ) ), gutter=False, )
def get_layout(self): if self.section_name: section_names = [self.section_name] else: section_names = self.form_class.registry.section_objects.keys() section_fields = {} for section in section_names: section_fields[section] = [] for field in self.form_class.registry[section]: section_fields[section].append(f"{section}__{field}") return breadlayout.forms.Form( hg.C("form"), hg.H3(_("Global preferences")), Tabs( *[ Tab( self.form_class.registry.section_objects[section]. verbose_name, hg.BaseElement(*[ breadlayout.forms.FormField(f) for f in section_fields.get(section) ]), ) for section in section_fields.keys() ], tabpanel_attributes={"style": "padding-left:0;"}, ), breadlayout.forms.helpers.Submit(), )
def get_layout(self): return hg.If( hg.C("validlink"), auth_page( layout.forms.Form( hg.C("form"), layout.forms.FormField( "new_password1", inputelement_attrs={"_class": "field-02-background"}, style="width: 100%", ), layout.forms.FormField( "new_password2", inputelement_attrs={"_class": "field-02-background"}, ), id="authform", ), _("Change password"), ), auth_page( hg.BaseElement( hg.FORM(id="authform", action=reverse("login")), layout.notification.InlineNotification( _("Invalid password reset link"), _( "The password reset link was invalid, possibly because it has already been used. Please request a new password reset." ), kind="error", lowcontrast=True, style="margin-bottom: 4rem", ), ), _("Back to Login"), ), )
def preview(self): columns = [] for column in self.columns.all(): columns.append( DataTableColumn(column.header, layout.FC(f"row.{column.column}"))) qs = self.queryset if qs is None: return hg.BaseElement("Model does no longer exists!") return hg.BaseElement( hg.HR(), hg.H3(_("Preview"), style="margin-top: 1rem"), layout.datatable.DataTable.from_queryset(qs[:25], columns=columns, primary_button=""), )
def wrapper_func(context): _classlist = [] for _class in _classes: _classlist.append(_class) _classlist.append(" ") ret = hg.resolve_lazy(lazy_attrs, context) or {} ret["_class"] = hg.BaseElement(ret.get("_class", ""), " ", *_classlist) return ret
def _generate_formset_class( request, model, modelfield, baseinlineformclass, formsetfieldelement, instance, cache_querysets, ): """Returns a FormSet class which handles inline forms correctly.""" formfieldelements = _get_form_fields_from_layout( hg.BaseElement(*formsetfieldelement) ) # make sure the _layout.forms.FormsetField does not be considered recursively formclass = breadmodelform_factory( request=request, model=modelfield.related_model, layout=formfieldelements, instance=instance, baseformclass=baseinlineformclass, cache_querysets=cache_querysets, ) base_formset_kwargs = { "fields": [field.fieldname for field in formfieldelements], "form": formclass, "extra": 0, "can_delete": True, } if modelfield.one_to_one: base_formset_kwargs["absolute_max"] = 1 base_formset_kwargs["min_num"] = 0 base_formset_kwargs["max_num"] = 1 base_formset_kwargs["extra"] = 1 base_formset_kwargs.update(formsetfieldelement.formsetfactory_kwargs) if isinstance(modelfield, GenericRelation): return generic_inlineformset_factory( modelfield.related_model, ct_field=modelfield.content_type_field_name, fk_field=modelfield.object_id_field_name, formset=GenericInlineFormSetWithLimits, formfield_callback=lambda field: _formfield_callback_with_request( field, request, modelfield.related_model, instance, cache_querysets), **base_formset_kwargs, ) else: return forms.models.inlineformset_factory( model, modelfield.related_model, formset=InlineFormSetWithLimits, formfield_callback=lambda field: _formfield_callback_with_request( field, request, model, instance, cache_querysets), fk_name=modelfield.field.name, **base_formset_kwargs, )
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")), )
def get_layout(self): modelclass = self.object.model.model_class() if modelclass is None: return layout.notification.InlineNotification( "Error", f"Model '{self.object.model}' does no longer exist.", kind="error", ) column_helper = layout.get_attribute_description_modal(modelclass) F = layout.forms.FormField fieldstable = layout.forms.FormsetField.as_datatable( "columns", ["header", "column", "sortingname"], formsetfield_kwargs={ "extra": 1, "can_order": True, }, ) fieldstable[0][1].insert( 0, layout.button.Button(_("Help"), buttontype="ghost", **column_helper.openerattributes), ) fieldstable.append(hg.DIV(style="height: 1rem")) ret = hg.BaseElement( views.header(), layout.forms.Form( hg.C("form"), hg.DIV( _("Base model"), ": ", hg.C("object.model"), style="margin: 2rem 0 2rem 0", ), F("name"), F( "filter", inputelement_attrs={"rows": 1}, style="width: 100%", ), fieldstable, layout.tile.ExpandableTile( hg.H4(_("Extended settings")), hg.DIV( F("custom_queryset"), F("pagination"), ), ), layout.forms.helpers.Submit(style="margin-top: 1rem"), column_helper, ), hg.C("object.preview"), ) return ret
def header(): editbutton = breadlayout.button.Button( _("Edit"), buttontype="ghost", icon="edit", notext=True, ).as_href(ModelHref.from_object(hg.C("object"), "edit")) readbutton = breadlayout.button.Button( _("Read"), buttontype="ghost", icon="view", notext=True, ).as_href(ModelHref.from_object(hg.C("object"), "read")) deletebutton = breadlayout.button.Button( _("Delete"), buttontype="tertiary", icon="trash-can", notext=True, style="border-color: red; background-color: inherit", ).as_href(ModelHref.from_object(hg.C("object"), "delete")) deletebutton[1].attributes["style"] = "fill: red; color: red;" copybutton = breadlayout.button.Button( _("Copy"), buttontype="ghost", icon="copy", notext=True, ).as_href(ModelHref.from_object(hg.C("object"), "copy")) return hg.DIV( hg.H3( hg.If( hg.C("object"), hg.BaseElement( hg.SPAN(hg.C("object")), hg.SPAN( hg.If( hg.C("request").resolver_match.url_name.endswith(".read"), editbutton, readbutton, ), copybutton, breadlayout.button.PrintPageButton(buttontype="ghost"), deletebutton, _class="no-print", style="margin-bottom: 1rem; margin-left: 1rem", width=3, ), ), hg.SPAN(hg.format(_("Add {}"), hg.C("view").model._meta.verbose_name)), ), ), style="padding-top: 1rem", )
def tile_col_edit_modal_displayed_fields(heading, model: type, action: str, icon: Icon, displayed_fields: List): return tile_with_icon( icon, hg.BaseElement( hg.H4(heading), *displayed_fields, open_modal_popup_button(heading, model, action), ), )
def get_layout(self): fields = hg.BaseElement( *[layout.forms.FormField(f) for f in self.object.active_fields()] ) return hg.BaseElement( hg.H1(self.object, style="margin-bottom: 2rem"), hg.DIV( hg.DIV( layout.forms.Form( hg.C("form"), fields, layout.forms.helpers.Submit() ), style="padding: 1rem", ), hg.DIV( self.object.as_svg(), style="width: 40%; border: 1px solid gray" ), style="display: flex", ), )
def get_context_data(self, *args, **kwargs): layout = hg.BaseElement( hg.H3(_("Add %s") % pretty_modelname(self.model), ), self._get_layout_cached(), ) return { **super().get_context_data(*args, **kwargs), "layout": layout, "pagetitle": _("Add %s") % pretty_modelname(self.model), }
def __init__( self, fieldname, content, formname, formsetinitial=None, **formsetfactory_kwargs, ): self.fieldname = fieldname self.formname = formname self.formsetfactory_kwargs = formsetfactory_kwargs self.formsetinitial = formsetinitial self.content = content if isinstance(self.content, FormFieldMarker): self.content = hg.BaseElement(self.content) # search fields which have explicitly been defined in the content element declared_fields = set(f.fieldname for f in self.content.filter( lambda e, ancestors: isinstance(e, FormFieldMarker))) # append all additional fields of the form which are not rendered explicitly # These should be internal, hidden fields (can we test this somehow?) self.content.append( hg.F(lambda c: hg.BaseElement(*[ FormField( field, formname=DEFAULT_FORMSET_CONTEXTNAME, no_wrapper=True, no_label=True, no_helptext=True, ) for field in c[self.formname][ self.fieldname].formset.empty_form.fields if field not in declared_fields and field != forms.formsets.DELETION_FIELD_NAME ]))) super().__init__( iterator=hg.C(f"{self.formname}.{self.fieldname}.formset"), loopvariable=DEFAULT_FORMSET_CONTEXTNAME, content=Form(hg.C(DEFAULT_FORMSET_CONTEXTNAME), self.content, standalone=False), )
def __init__(self, helptext, disabled=False): super().__init__( helptext, hg.DIV( helptext, _class=hg.BaseElement( "bx--form__helper-text", hg.If(disabled, " bx--form__helper-text--disabled"), ), ), )
def __init__(self, platform, company, searchbar, actions=(), *args, **kwargs): super().__init__( hg.If( HasBreadCookieValue("sidenav-hidden", "true"), variable_size_header_part(hg.BaseElement(), company, searchbar, "5rem"), variable_size_header_part( hg.SPAN(platform, _class="bx--header__name--prefix"), company, searchbar, "18rem", ), ), hg.DIV( hg.If( hg.F(lambda c: c["request"].user.is_authenticated), hg.A( hg.SPAN( hg.C("request.user.get_username"), _class="bx--header__name--prefix", ), _class="bx--header__name", href=reverse("userprofile"), title=hg.C("request.user.get_username"), style="padding: 0; margin-right: 1rem", ), ), hg.If( hg.F(lambda c: c["request"].user.is_authenticated), hg.BUTTON( Icon( "logout", size=20, _class="bx--navigation-menu-panel-expand-icon", aria_hidden="true", ), Icon( "logout", size=20, _class="bx--navigation-menu-panel-collapse-icon", aria_hidden="true", ), _class="bx--header__menu-trigger bx--header__action", title=_("Logout"), data_navigation_menu_panel_label_expand=_("Logout"), data_navigation_menu_panel_label_collapse=_("Close"), onclick=f"document.location = '{reverse('logout')}'", ), ), _class="bx--header__global", ), _class="bx--header", data_header=True, )
def profile_field_password(fieldname): ret = profile_field(fieldname) ret[1] = C( hg.BaseElement( "●●●●●●●●●●●●", hg.A( _("Request reset"), href=reverse("userprofile.password_reset"), style="float: right", ), )) return ret
def __init__(self, label, tabid, panelid, selected): super().__init__( hg.A( label, tabindex="0", id=tabid, _class="bx--tabs__nav-link", href="javascript:void(0)", aria_controls=panelid, aria_selected=hg.If(selected, "true", "false"), role="tab", ), _class=hg.BaseElement( "bx--tabs__nav-item", hg.If(selected, " bx--tabs__nav-item--selected"), ), data_target="#" + panelid, aria_selected=hg.If(selected, "true", "false"), role="tab", onclick=hg.BaseElement("setBreadCookie('selected-tab', '", tabid, "')"), )
def _display_email_without_subscription(email): modal_add = modal_add_subscription(email) return hg.BaseElement( hg.DIV(email.email, style="font-weight: bold;"), hg.DIV(_("No subscription yet for "), email.email), layout.button.Button( _("Add subscription"), buttontype="ghost", icon="add", **modal_add.openerattributes, ), modal_add, )
def maintenance_database_optimization(request): database_path = settings.DATABASES["default"]["NAME"] current_db_size = os.stat(database_path).st_size / 1000 class OptimizeForm(forms.Form): previous = forms.DecimalField( widget=forms.HiddenInput, initial=current_db_size, ) form: OptimizeForm ret = hg.BaseElement() received_post = False if request.method == "POST": form = OptimizeForm(request.POST) if form.is_valid() and "previous" in form.cleaned_data: received_post = True connection.cursor().execute("VACUUM;") # get the previous size previous_size = form.cleaned_data["previous"] current_db_size = os.stat(database_path).st_size / 1000 # try adding some message here. messages.info( request, _("The database size has been minimized from %.2f kB to %.2f kB." ) % (previous_size, current_db_size), ) ret.append( hg.H5( _("Previous Size: %.2f kB") % form.cleaned_data["previous"])) if not received_post: form = OptimizeForm() optimize_btn = Form( form, FormField("previous"), Button( _("Optimize"), type="submit", ), ) ret.append(hg.H5(_("Current Size: %.2f kB") % current_db_size)) ret.append(optimize_btn) return ret
def add_button(self, container_css_selector, label=_("Add"), **kwargs): prefix = hg.C(f"{self.formname}.{self.fieldname}.formset.prefix") defaults = { "icon": "add", "notext": True, "buttontype": "tertiary", "id": hg.BaseElement( "add_", prefix, "_button"), # required for javascript to work correctly "onclick": hg.BaseElement( "formset_add('", prefix, "', '", container_css_selector, "');", ), } return Button(label, **{**defaults, **kwargs})
def as_plain(*args, add_label=_("Add"), **kwargs): """Shortcut to render a complete formset with add-button""" formset = FormsetField(*args, **kwargs) id = hg.html_id(formset, prefix="formset-") return hg.BaseElement( hg.DIV(formset, id=id), formset.management_form, formset.add_button( buttontype="ghost", notext=False, label=add_label, container_css_selector=f"#{id}", ), )
def get_layout(self): return auth_page( hg.BaseElement( layout.notification.InlineNotification( _("Password successfully changed"), _("Please login again"), kind="success", lowcontrast=True, style="margin-bottom: 4rem", ), hg.FORM(action=reverse("login"), id="authform"), ), _("Back to Login"), )
def common_tiles(request): return hg.BaseElement( R( tags(), addresses.email(request), ), R( addresses.postals(), addresses.numbers(request), ), R( other(), addresses.urls(request), ), )
def _close_button(resultcontainerid, widgetattributes): kwargs = { "_class": hg.BaseElement( "bx--search-close", hg.If(widgetattributes.get("value"), None, " bx--search-close--hidden"), ), "title": _("Clear search input"), "aria_label": _("Clear search input"), "type": "button", } if resultcontainerid is not None: kwargs["onclick"] = hg.format( "document.getElementById('{}').innerHTML = '';", resultcontainerid ) return hg.BUTTON(Icon("close", size=20, _class="bx--search-clear"), **kwargs)
def contact_details_naturalperson(request): return hg.BaseElement( R( addresses.postals(), addresses.numbers(request), ), R( addresses.email(request), addresses.urls(request), ), R( base_data.tags(), base_data.other(), ), )