Source code for wildewidgets.widgets.headers

from __future__ import annotations

import warnings
from typing import Any

from .base import Block, TemplateWidget
from .buttons import CollapseButton, FormButton, LinkButton, ModalButton


[docs]class BasicHeader(TemplateWidget): """ The base header class for all header widgets in the wildewidgets library. This class provides the core functionality for rendering HTML headers with various styling options, including optional badges. All other header classes inherit from this class. Example: .. code-block:: python from wildewidgets import BasicHeader header = BasicHeader( header_text="Welcome to the Dashboard", header_level=1, badge_text="New", badge_class="success" ) Attributes: template_name: Path to the Django template used for rendering header_level: HTML heading level (1-6) to use header_type: Type of header styling ("h" for standard, "display" for larger) header_text: The text content of the header css_class: CSS classes to apply to the header container css_id: Optional ID attribute for the header element badge_text: Optional text for a badge beside the header badge_class: Bootstrap color class for the badge (e.g., "primary", "warning") badge_rounded_pill: Whether to style the badge as a rounded pill Keyword Args: header_level: the header depth, as in h1, h2, h3... header_type: the Boostrap 5 header class, either h-*, or display-*. header_text: the text of the header. css_class: any css classes to apply to the header. css_id: an ID to add to the header div. badge_text: text to add in a badge to the right of the main header text. badge_class: the css class to add to the badge. """ template_name: str = "wildewidgets/header_with_controls.html" header_level: int = 1 header_type: str = "h" header_text: str | None = None css_class: str = "my-3" css_id: str | None = None badge_text: str | None = None badge_class: str = "warning" badge_rounded_pill: bool = True def __init__( self, header_level: int | None = None, header_type: str | None = None, header_text: str | None = None, css_class: str | None = None, css_id: str | None = None, badge_text: str | None = None, badge_class: str | None = None, badge_rounded_pill: bool | None = None, **kwargs: Any, ): self.header_level = header_level or self.header_level self.header_type = header_type or self.header_type self.header_text = header_text or self.header_text self.css_class = css_class or self.css_class self.css_id = css_id or self.css_id self.badge_text = badge_text or self.badge_text self.badge_class = badge_class or self.badge_class self.badge_rounded_pill = ( badge_rounded_pill if badge_rounded_pill is not None else self.badge_rounded_pill ) kwargs["title"] = self.header_text super().__init__(**kwargs)
[docs] def get_context_data(self, **kwargs: Any) -> dict[str, Any]: """ Prepare the context data for template rendering. Processes header settings and adds them to the template context. Sets the appropriate header class based on the header type and level, and includes all other header properties. Args: **kwargs: Initial context dictionary Returns: dict: Updated context dictionary with header properties """ if self.header_type == "h": kwargs["header_class"] = f"h{self.header_level}" elif self.header_type == "display": kwargs["header_class"] = f"display-{self.header_level}" kwargs["header_level"] = self.header_level kwargs["header_text"] = self.header_text kwargs["header_type"] = self.header_type kwargs["css_class"] = self.css_class kwargs["css_id"] = self.css_id kwargs["badge_text"] = self.badge_text kwargs["badge_class"] = self.badge_class kwargs["badge_rounded_pill"] = self.badge_rounded_pill return kwargs
[docs]class HeaderWithLinkButton(BasicHeader): """ A header with an attached link button. This combines a heading element with a button that links to a specified URL. The button appears to the right of the header text. Deprecated: This class is deprecated since version 0.13.45. Use :py:class:`HeaderWithWidget` with the :py:meth:`add_link_button` method instead. Example: .. code-block:: python from wildewidgets import HeaderWithLinkButton header = HeaderWithLinkButton( header_text="Users", header_level=2, url="/users/add/", link_text="Add User", button_class="success" ) Attributes: template_name: Path to the template for rendering this widget url: The URL that the button links to link_text: The text displayed on the button button_class: Bootstrap contextual class for the button """ template_name = "wildewidgets/header_with_link_button.html" url: str | None = None link_text: str | None = None button_class: str = "primary" def __init__( self, url: str | None = None, link_text: str | None = None, button_class: str | None = None, **kwargs: Any, ): warnings.warn( "HeaderWithLinkButton is deprecated. Use " "wildewidgets.HeaderWithWidget instead", DeprecationWarning, stacklevel=2, ) self.url = url or self.url self.link_text = link_text or self.link_text self.button_class = button_class or self.button_class super().__init__(**kwargs)
[docs] def get_context_data(self, **kwargs: Any) -> dict[str, Any]: """ Prepare the context data for template rendering. Adds link button specific variables to the context dictionary. Args: **kwargs: Initial context dictionary from parent class Returns: dict: Updated context with url, link_text, and button_class """ kwargs = super().get_context_data(**kwargs) kwargs["url"] = self.url kwargs["link_text"] = self.link_text kwargs["button_class"] = self.button_class return kwargs
[docs]class HeaderWithFormButton(BasicHeader): """ A header with an attached form submission button. This combines a heading element with a button that submits a form when clicked. The form must be defined elsewhere in your template. Deprecated: This class is deprecated since version 0.13.45. Use :py:class:`HeaderWithWidget` with the :py:meth:`add_form_button` method instead. Example: .. code-block:: python from wildewidgets import HeaderWithFormButton header = HeaderWithFormButton( header_text="Dangerous Action", header_level=3, url="/api/delete-all/", button_text="Delete All" ) Attributes: template_name: Path to the template for rendering this widget url: The URL that the form will submit to button_text: The text displayed on the button """ template_name = "wildewidgets/header_with_form_button.html" url: str | None = None button_text: str | None = None def __init__( self, url: str | None = None, button_text: str | None = None, **kwargs: Any ): warnings.warn( "HeaderWithFormButton is deprecated. Use " "wildewidgets.HeaderWithWidget instead", DeprecationWarning, stacklevel=2, ) self.url = url or self.url self.button_text = button_text or self.button_text super().__init__(**kwargs)
[docs] def get_context_data(self, **kwargs: Any) -> dict[str, Any]: """ Prepare the context data for template rendering. Adds form button specific variables to the context dictionary. Args: **kwargs: Initial context dictionary from parent class Returns: dict: Updated context with url and button_text """ kwargs = super().get_context_data(**kwargs) kwargs["url"] = self.url kwargs["button_text"] = self.button_text return kwargs
[docs]class HeaderWithCollapseButton(BasicHeader): """ A header with a button that toggles a Bootstrap collapsible element. This combines a heading element with a button that expands or collapses a target element when clicked. The collapsible element must be defined elsewhere in your template. Deprecated: This class is deprecated since version 0.13.45. Use :py:class:`HeaderWithWidget` with the :py:meth:`add_collapse_button` method instead. Example: .. code-block:: python from wildewidgets import HeaderWithCollapseButton header = HeaderWithCollapseButton( header_text="Advanced Options", header_level=3, collapse_id="advanced-options", button_text="Toggle" ) Attributes: template_name: Path to the template for rendering this widget collapse_id: ID of the collapsible element to toggle button_text: Text displayed on the button button_class: Bootstrap contextual class for the button """ template_name: str = "wildewidgets/header_with_collapse_button.html" collapse_id: str | None = None button_text: str | None = None button_class: str | None = "primary" def __init__( self, collapse_id: str | None = None, button_text: str | None = None, button_class: str | None = None, **kwargs: Any, ): warnings.warn( "HeaderWithCollapseButton is deprecated. Use " "wildewidgets.HeaderWithWidget instead", DeprecationWarning, stacklevel=2, ) self.collapse_id = collapse_id or self.collapse_id self.button_text = button_text or self.button_text self.button_class = button_class or self.button_class super().__init__(**kwargs)
[docs] def get_context_data(self, **kwargs: Any) -> dict[str, Any]: """ Prepare the context data for template rendering. Adds collapse button specific variables to the context dictionary. Args: **kwargs: Initial context dictionary from parent class Returns: dict: Updated context with collapse_id, button_text, and button_class """ kwargs = super().get_context_data(**kwargs) kwargs["collapse_id"] = self.collapse_id kwargs["button_text"] = self.button_text kwargs["button_class"] = self.button_class return kwargs
[docs]class HeaderWithModalButton(BasicHeader): """ A header widget with a button that triggers a Bootstrap modal. This class combines a heading element with a button that opens a modal dialog when clicked. The modal must be defined elsewhere in your template. Deprecated: This class is deprecated since version 0.13.45. Use :py:class:`HeaderWithWidget` with the :py:meth:`add_modal_button` Attributes: template_name: Path to the template for rendering this widget modal_id: ID of the modal to be triggered by the button button_text: Text to display on the button button_class: Bootstrap button class (e.g., "primary", "secondary") Keyword Args: **kwargs: Keyword arguments including modal_id, button_text, and button_class, plus any arguments for BasicHeader """ template_name = "wildewidgets/header_with_modal_button.html" modal_id: str | None = None button_text: str | None = None button_class: str = "primary" def __init__(self, **kwargs: Any): warnings.warn( "Use wildewidgets.HeaderWithWidget instead", DeprecationWarning, stacklevel=2, ) super().__init__(**kwargs) self.modal_id = kwargs.get("modal_id", self.modal_id) self.button_text = kwargs.get("button_text", self.button_text) self.button_class = kwargs.get("button_class", self.button_class)
[docs] def get_context_data(self, **kwargs: Any) -> dict[str, Any]: """ Prepare the context data for template rendering. Adds modal button specific variables to the context dictionary. Args: **kwargs: Initial context dictionary from parent class Returns: dict: Updated context with modal_id, button_text, and button_class """ kwargs = super().get_context_data(**kwargs) kwargs["modal_id"] = self.modal_id kwargs["button_text"] = self.button_text kwargs["button_class"] = self.button_class return kwargs
[docs]class HeaderWithWidget(BasicHeader): """ A header widget that can contain another widget (typically a button). This flexible header class allows adding any widget (most commonly buttons) next to the header text. This is the recommended approach for creating headers with interactive elements. Example: .. code-block:: python from wildewidgets import HeaderWithWidget, LinkButton # Create a header with a link button header = HeaderWithWidget( header_text="Products List", header_level=2, widget=LinkButton(text="Add Product", url="/products/add/") ) # Or add the button after initialization header = HeaderWithWidget(header_text="Products List") header.add_link_button(text="Add Product", url="/products/add/") Args: widget: Widget to display next to the header text Keyword Args: header_text: Text content of the header header_level: HTML heading level (1-6) **kwargs: Additional arguments passed to BasicHeader """ template_name = "wildewidgets/header_with_widget.html" def __init__(self, widget: Block | None = None, **kwargs: Any): super().__init__(**kwargs) self.widget = widget
[docs] def add_form_button(self, **kwargs: Any) -> None: """ Add a form submission button to the header. This method creates a FormButton instance and adds it to the header. The button will submit a form when clicked. Args: **kwargs: Arguments passed to :py:class:`wildewidgets.FormButton` constructor. Common arguments include: * text: Button label text * action: Form submission URL * color: Bootstrap color class (default: "secondary") * method: HTTP method (default: "post") * confirm_text: Text for confirmation dialog (if needed) """ self.widget = FormButton(**kwargs)
[docs] def add_modal_button(self, **kwargs: Any) -> None: """ Add a button that triggers a Bootstrap modal dialog. This method creates a ModalButton instance and adds it to the header. The button will open the specified modal when clicked. Args: **kwargs: Arguments passed to :py:class:`wildewidgets.ModalButton` constructor. Common arguments include: * text: Button label text * target: Modal ID to target (with # prefix) * color: Bootstrap color class (default: "secondary") """ self.widget = ModalButton(**kwargs)
[docs] def add_collapse_button(self, **kwargs: Any) -> None: """ Add a button that toggles a Bootstrap collapsible element. This method creates a CollapseButton instance and adds it to the header. The button will toggle the visibility of the specified collapsible element. Args: **kwargs: Arguments passed to :py:class:`wildewidgets.CollapseButton` constructor. Common arguments include: * text: Button label text * target: Collapse target ID (with # prefix) * color: Bootstrap color class (default: "secondary") """ self.widget = CollapseButton(**kwargs)
[docs] def set_widget(self, widget: Block) -> None: """ Set or replace the widget displayed next to the header. This method allows setting any widget (not just buttons) to appear next to the header text. This provides flexibility beyond the specialized button methods. Args: widget: Any Block-derived widget to display in the header """ self.widget = widget
[docs] def get_context_data(self, **kwargs: Any) -> dict[str, Any]: """ Get the context data for rendering the template. Adds the widget to the template context, along with other header properties. Args: **kwargs: Additional context variables Returns: dict: Updated context dictionary including the widget """ kwargs = super().get_context_data(**kwargs) kwargs["widget"] = self.widget return kwargs
[docs]class CardHeader(HeaderWithWidget): """ A header specifically designed for Bootstrap card components. This provides an H2 header with appropriate styling for use as a card header, with the option to include an action button or other widget. Example: .. code-block:: python from wildewidgets import CardHeader, LinkButton header = CardHeader( header_text="User Details", widget=LinkButton(text="Edit", url="/users/123/edit/") ) """ css_class: str = "my-3" header_level: int = 2
[docs]class WidgetListLayoutHeader(HeaderWithWidget): """ A specialized header for use with WidgetListLayout components. This header is designed to match the styling of the WidgetListLayout component, providing consistent margins and header size. It can include an optional action button or other widget. Example: .. code-block:: python from wildewidgets import WidgetListLayoutHeader, LinkButton header = WidgetListLayoutHeader( header_text="Dashboard Widgets", widget=LinkButton(text="Add Widget", url="/widgets/add/") ) """ css_class: str = "mb-4" header_level: int = 2