Source code for ferrosoft.apps.ferrobase.apps
"""Django application configuration, menu registration types, and platform app metadata."""
from dataclasses import dataclass, field
from typing import Iterable, Any
from django.apps import AppConfig
from django.http import HttpRequest
from django.utils.translation import gettext_lazy as _
from django_asgi_lifespan.register import register_lifespan_manager
[docs]
class FerrobaseConfig(AppConfig):
"""Django AppConfig for the ferrobase application.
Initialises the dependency injection container on startup and registers
the HTTPX lifespan manager so a single connection pool is shared across
all inbound requests.
"""
default_auto_field = "django.db.models.BigAutoField"
name = "ferrosoft.apps.ferrobase"
verbose_name = _("Ferrosoft Base")
container = None
[docs]
def ready(self):
"""Wire up the DI container and register the HTTPX lifespan manager."""
# These imports have to stay here to avoid AppRegistryNotReady error.
from django.conf import settings
from ferrosoft.apps.ferrobase.containers import Container
from ferrosoft.apps.ferrobase.context import httpx_lifespan_manager
self.container = Container()
self.container.config.from_dict(getattr(settings, "FERROBASE_CONTAINER", {}))
self.container.wire(
modules=[".services.taskqueue"],
warn_unresolved=True,
)
# Allow connection caching across all inbound requests.
register_lifespan_manager(context_manager=httpx_lifespan_manager)
[docs]
@dataclass
class AppMeta:
"""AppMeta provides information about platform applications."""
title: Any
"""Human readable title of the application."""
app_name: str
"""Django identifier of the application."""
home_view: str
"""Django view name of the home page."""
icon_path: str
"""File path to app icon. It must be a static file if templated_icon = False, otherwise a template file."""
restricted_app_menu: bool = False
"""Show to the user only the menu of the app, even if the user navigates to a different app."""
templated_icon: bool = False
"""If true, the icon is {% include %}'d in the template (useful for SVG)."""
[docs]
@dataclass
class MenuItem:
"""A single entry in a navigation or settings menu."""
display_name: str | Any
view_name: str
permissions: list = field(default_factory=lambda: [])
category_name: str | Any | None = None
icon: str | None = None
[docs]
class SettingsMenuRegistry:
"""Registry of settings-page menu items with permission-based filtering."""
ITEMS = [
MenuItem(
category_name="",
display_name=_("My settings"),
view_name="ferrobase:my_settings",
),
MenuItem(
category_name="",
display_name=_("Account Security"),
view_name="two_factor:profile",
),
MenuItem(
category_name=_("Core Data"),
display_name=_("Business partners"),
view_name="ferrobase:businesspartner_index",
permissions=["ferrobase.view_businesspartner"],
),
MenuItem(
category_name=_("System"),
display_name=_("API Tokens"),
view_name="ferrobase:apitoken_index",
permissions=["ferrobase.view_apitoken"],
),
MenuItem(
category_name=_("System"),
display_name=_("ID Sequences"),
view_name="ferrobase:idsequenceconfig_index",
permissions=["ferrobase.view_idsequenceconfig"],
),
MenuItem(
category_name=_("Core Data"),
display_name=_("Material"),
view_name="ferrobase:material_index",
permissions=["ferrobase.view_material"],
),
MenuItem(
category_name=_("Core Data"),
display_name=_("Company Sites"),
view_name="ferrobase:companysite_index",
permissions=["ferrobase.view_companysite"],
),
MenuItem(
category_name=_("System"),
display_name=_("Users"),
view_name="ferrobase:user_index",
permissions=["ferrobase.view_user"],
),
MenuItem(
category_name=_("System"),
display_name=_("Groups"),
view_name="ferrobase:group_index",
permissions=["auth.view_group"],
),
MenuItem(
category_name=_("System"),
display_name=_("Organizations"),
view_name="ferrobase:organization_index",
permissions=["ferrobase.view_organization"],
),
MenuItem(
category_name=_("System"),
display_name=_("Subscription Plans"),
view_name="ferrobase:subscriptionplan_index",
permissions=["ferrobase.view_subscriptionplan"],
),
MenuItem(
category_name="",
display_name=_("Files"),
view_name="ferrobase:directory_root",
permissions=["ferrobase.view_directory"],
),
]
[docs]
@classmethod
def add_items(cls, *items: MenuItem):
"""Add menu items to the registry.
Args:
*items: ``MenuItem`` instances to append to the shared registry.
"""
cls.ITEMS += items
@staticmethod
def _settings_menu_filter(user):
def _filter(item: MenuItem):
user_has_permissions = all(
map(
lambda perm: user.has_perm(perm),
item.permissions,
)
)
return user_has_permissions
return _filter
PLATFORM_APPS = {
"emiflow": AppMeta(
title=_("Emiflow"),
app_name="emiflow",
home_view="emiflow:index",
icon_path="ferrobase/app-icons/emiflow.svg",
restricted_app_menu=True,
templated_icon=True,
),
"ferrobase": AppMeta(
title=_("Ferrosoft"),
app_name="ferrobase",
home_view="ferrobase:index",
icon_path="ferrobase/app-icons/ferrobase.svg",
templated_icon=True,
),
}
INDEX_MENU = [
MenuItem(
category_name="",
display_name=_("Emiflow"),
view_name="emiflow:index",
),
MenuItem(
category_name="",
display_name=_("Data import"),
view_name="dataimport:index",
),
MenuItem(
category_name="",
display_name=_("Examination report"),
view_name="befundung:log",
),
]
MENU_ITEMS = {
"dataimport": [
MenuItem(
category_name="",
display_name=_("Recent Imports"),
view_name="dataimport:index",
),
MenuItem(
category_name="",
display_name=_("New Import"),
view_name="dataimport:job_new",
),
],
"emiflow": [
MenuItem(
category_name="",
display_name=_("Home"),
view_name="emiflow:index",
),
MenuItem(
category_name="",
display_name=_("Transports"),
view_name="emiflow:transportchain_index",
),
MenuItem(
category_name="",
display_name=_("Treatments"),
view_name="emiflow:treatment_index",
),
MenuItem(
category_name="",
display_name=_("Reporting"),
view_name="emiflow:report_index",
),
MenuItem(
category_name="",
display_name=_("File Import"),
view_name="emiflow:file_import_index",
),
],
}