from dectate import Action
from itertools import count
from typing import cast, Any, ClassVar, TYPE_CHECKING
if TYPE_CHECKING:
from collections.abc import Callable
from onegov.core.elements import LinkGroup
from onegov.directory.models import DirectoryEntry
from onegov.event.models import Occurrence
from onegov.org.models import Boardlet as _Boardlet
from onegov.org.request import OrgRequest
from onegov.user import User
from sqlalchemy.orm import Query
from typing import Protocol, TypeAlias, TypeVar, TypedDict
[docs]
DirectoryEntryT = TypeVar('DirectoryEntryT', bound=DirectoryEntry)
DirectorySearchWidgetRegistry: TypeAlias = dict[
str,
type['RegisteredDirectorySearchWidget[Any]']
]
EventSearchWidgetRegistry: TypeAlias = dict[
str,
type['RegisteredEventSearchWidget']
]
LinkGroupFactory: TypeAlias = Callable[[OrgRequest, User], LinkGroup]
class HomepageWidget(Protocol):
@property
def template(self) -> str: ...
class RegisteredHomepageWidget(HomepageWidget, Protocol):
tag: str
class DirectorySearchWidget(Protocol[DirectoryEntryT]):
@property
def search_query(self) -> Query[DirectoryEntryT]: ...
def adapt(
self,
query: Query[DirectoryEntryT]
) -> Query[DirectoryEntryT]: ...
class RegisteredDirectorySearchWidget(
DirectorySearchWidget[DirectoryEntryT],
Protocol[DirectoryEntryT]
):
name: str
class EventSearchWidget(Protocol):
@property
def search_query(self) -> Query[Occurrence]: ...
def adapt(
self,
query: Query[Occurrence]
) -> Query[Occurrence]: ...
class RegisteredEventSearchWidget(EventSearchWidget, Protocol):
name: str
class SettingsDict(TypedDict):
name: str
title: str
order: int
icon: str
class BoardletConfig(TypedDict):
cls: type[_Boardlet]
order: tuple[int, int]
[docs]
class HomepageWidgetAction(Action):
""" Register a cronjob. """
[docs]
config = {
'homepage_widget_registry': dict
}
def __init__(self, tag: str) -> None:
[docs]
def identifier( # type:ignore[override]
self,
homepage_widget_registry: dict[str, 'RegisteredHomepageWidget']
) -> str:
return self.tag
[docs]
def perform( # type:ignore[override]
self,
func: 'Callable[[], HomepageWidget]',
homepage_widget_registry: dict[str, 'RegisteredHomepageWidget']
) -> None:
widget = cast('RegisteredHomepageWidget', func())
widget.tag = self.tag # keep redundantly for ease of access
homepage_widget_registry[self.tag] = widget
[docs]
class ExportAction(Action):
""" Register an export. """
[docs]
config = {
'export_registry': dict
}
def __init__(self, id: str, **kwargs: Any) -> None:
self.kwargs['id'] = id
[docs]
def identifier( # type:ignore[override]
self,
export_registry: dict[str, Any]
) -> str:
return self.id
[docs]
class UserlinkAction(Action):
""" Registers a user link group. """
[docs]
config = {
'linkgroup_registry': list
}
[docs]
counter: ClassVar = count(1)
def __init__(self) -> None:
[docs]
self.name = next(self.counter)
[docs]
def identifier( # type:ignore[override]
self,
linkgroup_registry: list['LinkGroupFactory']
) -> int:
return self.name
[docs]
class SettingsView(Action):
""" Registers a settings view. """
[docs]
config = {
'settings_view_registry': dict
}
def __init__(
self,
name: str,
title: str,
order: int = 0,
icon: str =
'fa-cogs'
) -> None:
[docs]
self.setting: SettingsDict = {
'name': name,
'title': title,
'order': order,
'icon': icon
}
[docs]
def identifier( # type:ignore[override]
self,
settings_view_registry: dict[str, 'SettingsDict']
) -> str:
return self.name
[docs]
class Boardlet(Action):
""" Registers a boardlet on the Dashboard. """
[docs]
config = {
'boardlets_registry': dict
}
def __init__(self, name: str, order: tuple[int, int]):
assert isinstance(order, tuple) and len(order) == 2, """
The order should consist of two values, a group and an order
within the group.
"""
[docs]
def identifier( # type:ignore[override]
self,
boardlets_registry: dict[str, 'BoardletConfig']
) -> str:
return self.name