diff --git a/conreq/app/register/components.py b/conreq/app/register/components.py index 73917fdb..49bad50e 100644 --- a/conreq/app/register/components.py +++ b/conreq/app/register/components.py @@ -1,4 +1,4 @@ -from typing import Literal +from typing import Callable, Literal from idom.core.component import Component @@ -6,7 +6,7 @@ def user_management( - component: Component | None = None, + component: Callable[..., Component] | None = None, selector: Literal[ "main", "manage_users", @@ -22,7 +22,7 @@ def user_management( def server_settings( - component: Component | None = None, + component: Callable[..., Component] | None = None, selector: Literal[ "main", "general", "styling", "webserver", "email", "system_info" ] = "main", @@ -33,7 +33,7 @@ def server_settings( def user_settings( - component: Component | None = None, + component: Callable[..., Component] | None = None, selector: Literal["main", "general", "change_password", "delete_account"] = "main", ): """Changes the user settings component.""" @@ -41,7 +41,10 @@ def user_settings( return component -def app_store(component: Component | None = None, selector: Literal["main"] = "main"): +def app_store( + component: Callable[..., Component] | None = None, + selector: Literal["main"] = "main", +): """Changes the app store component.""" # TODO: Add more selectors after fleshing out the app store tab setattr(config.components.app_store, selector, component) @@ -49,7 +52,8 @@ def app_store(component: Component | None = None, selector: Literal["main"] = "m def loading_animation( - component: Component | None = None, selector: Literal["small", "large"] = "large" + component: Callable[..., Component] | None = None, + selector: Literal["small", "large"] = "large", ): """Changes the default component loading animation.""" if component: diff --git a/conreq/app/register/homepage.py b/conreq/app/register/homepage.py index 0da3c426..0022b9f5 100644 --- a/conreq/app/register/homepage.py +++ b/conreq/app/register/homepage.py @@ -1,6 +1,7 @@ from typing import Callable from idom.core.component import Component +from idom.types import ComponentConstructor from conreq import config from conreq.types import ( @@ -29,7 +30,7 @@ def sidebar_tab( # TODO: Implement auth level # TODO: URL support (Requires IDOM to support URL routing) - def decorator(component: Component): + def decorator(component: ComponentConstructor | Callable[..., Component]): if config.homepage.sidebar_tabs and group not in config.homepage.sidebar_tabs: config.homepage.sidebar_tabs.add(group) diff --git a/conreq/config/types.py b/conreq/config/types.py index 6f093e8c..9f97e23e 100644 --- a/conreq/config/types.py +++ b/conreq/config/types.py @@ -5,9 +5,8 @@ from typing import Callable from django.views import View -from idom.core.component import Component from idom.html import div, span -from idom.types import VdomDict +from idom.types import ComponentConstructor, VdomDict from sortedcontainers import SortedList from conreq.types import CSS, SCSS, HTMLTemplate, JavaScript, SidebarTab, SubTab @@ -22,17 +21,17 @@ class _UserSettingsComponents: """Used to store user-defined components.""" - main: Component | None = None - general: Component | None = None - change_password: Component | None = None - delete_account: Component | None = None + main: ComponentConstructor | None = None + general: ComponentConstructor | None = None + change_password: ComponentConstructor | None = None + delete_account: ComponentConstructor | None = None @dataclass class _SignOutComponents: """Used to store user-defined components.""" - main: Component | None = None + main: ComponentConstructor | None = None event: Callable | None = None @@ -40,24 +39,24 @@ class _SignOutComponents: class _UserManagementComponents: """Used to store user-defined components.""" - main: Component | None = None - manage_users: Component | None = None - edit_user: Component | None = None - delete_user: Component | None = None - manage_invites: Component | None = None - create_invite: Component | None = None + main: ComponentConstructor | None = None + manage_users: ComponentConstructor | None = None + edit_user: ComponentConstructor | None = None + delete_user: ComponentConstructor | None = None + manage_invites: ComponentConstructor | None = None + create_invite: ComponentConstructor | None = None @dataclass class _ServerSettingsComponents: """Used to store user-defined components.""" - main: Component | None = None - general: Component | None = None - styling: Component | None = None - webserver: Component | None = None - email: Component | None = None - system_info: Component | None = None + main: ComponentConstructor | None = None + general: ComponentConstructor | None = None + styling: ComponentConstructor | None = None + webserver: ComponentConstructor | None = None + email: ComponentConstructor | None = None + system_info: ComponentConstructor | None = None @dataclass @@ -70,7 +69,7 @@ class _LoadingAnimationComponents: span({"className": "sr-only"}, "Loading..."), ), ) - small: Component | VdomDict = field( + small: ComponentConstructor | VdomDict = field( default_factory=lambda: div( {"className": "spinner-border loading-animation", "role": "status"}, span({"className": "sr-only"}, "Loading..."), @@ -82,7 +81,7 @@ class _LoadingAnimationComponents: class _AppStoreComponents: """Used to store user-defined components.""" - main: Component | None = None + main: ComponentConstructor | None = None # Tab Configuration diff --git a/conreq/config/utils.py b/conreq/config/utils.py index 3f401cb6..a30c14b1 100644 --- a/conreq/config/utils.py +++ b/conreq/config/utils.py @@ -1,11 +1,13 @@ from typing import Callable +from idom.core.component import Component + from conreq.types import AuthLevel, SidebarTab, Viewport def tab_constructor( name: str, - component: Callable, + component: Callable[..., Component], on_click: Callable | None = None, padding: bool = True, auth: str = AuthLevel.user, diff --git a/conreq/config/wrappers/components.py b/conreq/config/wrappers/components.py index 148a4714..533e1c3a 100644 --- a/conreq/config/wrappers/components.py +++ b/conreq/config/wrappers/components.py @@ -8,57 +8,58 @@ # pylint: disable=import-outside-toplevel @component def homepage(*args, **kwargs): - component = config.components.homepage - if component is None: + _component = config.components.homepage + if _component is None: from conreq._core.home import components return html._(components.homepage(*args, **kwargs)) - return component(*args, **kwargs) + return _component(*args, **kwargs) @component def user_settings(*args, **kwargs): - component = config.components.user_settings.main - if component is None: + _component = config.components.user_settings.main + if _component is None: from conreq._core.user_settings import components return html._(components.user_settings(*args, **kwargs)) - return component(*args, **kwargs) + return _component(*args, **kwargs) @component def user_settings_general(*args, **kwargs): - component = config.components.user_settings.general - if component is None: + _component = config.components.user_settings.general + if _component is None: from conreq._core.user_settings import components return html._(components.general(*args, **kwargs)) - return component(*args, **kwargs) + return _component(*args, **kwargs) @component def user_settings_change_password(*args, **kwargs): - component = config.components.user_settings.change_password - if component is None: + _component = config.components.user_settings.change_password + if _component is None: from conreq._core.user_settings import components return html._(components.change_password(*args, **kwargs)) - return component(*args, **kwargs) + return _component(*args, **kwargs) @component def user_settings_delete_account(*args, **kwargs): - component = config.components.user_settings.delete_account - if component is None: + _component = config.components.user_settings.delete_account + if _component is None: from conreq._core.user_settings import components return html._(components.delete_my_account(*args, **kwargs)) - return component(*args, **kwargs) + return _component(*args, **kwargs) @component def sign_out(*args, **kwargs): - return html._(config.components.sign_out.main) + _component = config.components.sign_out.main + return None if _component is None else _component(*args, **kwargs) async def sign_out_event(*args, **kwargs): @@ -74,139 +75,139 @@ async def sign_out_event(*args, **kwargs): @component def user_management(*args, **kwargs): - component = config.components.user_management.main - if component is None: + _component = config.components.user_management.main + if _component is None: from conreq._core.user_management import components return html._(components.user_management(*args, **kwargs)) - return component(*args, **kwargs) + return _component(*args, **kwargs) @component def user_management_manage_users(*args, **kwargs): - component = config.components.user_management.manage_users - if component is None: + _component = config.components.user_management.manage_users + if _component is None: from conreq._core.user_management import components return html._(components.manage_users(*args, **kwargs)) - return component(*args, **kwargs) + return _component(*args, **kwargs) @component def user_management_edit_user(*args, **kwargs): - component = config.components.user_management.edit_user - if component is None: + _component = config.components.user_management.edit_user + if _component is None: from conreq._core.user_management import components return html._(components.edit_user(*args, **kwargs)) - return component(*args, **kwargs) + return _component(*args, **kwargs) @component def user_management_delete_user(*args, **kwargs): - component = config.components.user_management.delete_user - if component is None: + _component = config.components.user_management.delete_user + if _component is None: from conreq._core.user_management import components return html._(components.delete_user(*args, **kwargs)) - return component(*args, **kwargs) + return _component(*args, **kwargs) @component def user_management_manage_invites(*args, **kwargs): - component = config.components.user_management.manage_invites - if component is None: + _component = config.components.user_management.manage_invites + if _component is None: from conreq._core.user_management import components return html._(components.manage_invites(*args, **kwargs)) - return component(*args, **kwargs) + return _component(*args, **kwargs) @component def user_management_create_invite(*args, **kwargs): - component = config.components.user_management.create_invite - if component is None: + _component = config.components.user_management.create_invite + if _component is None: from conreq._core.user_management import components return html._(components.create_invite(*args, **kwargs)) - return component(*args, **kwargs) + return _component(*args, **kwargs) @component def app_store(*args, **kwargs): - component = config.components.app_store.main - if component is None: + _component = config.components.app_store.main + if _component is None: from conreq._core.app_store import components return html._(components.app_store(*args, **kwargs)) - return component(*args, **kwargs) + return _component(*args, **kwargs) @component def server_settings(*args, **kwargs): - component = config.components.server_settings.main - if component is None: + _component = config.components.server_settings.main + if _component is None: from conreq._core.server_settings import components return html._(components.server_settings(*args, **kwargs)) - return component(*args, **kwargs) + return _component(*args, **kwargs) @component def server_settings_general(*args, **kwargs): - component = config.components.server_settings.general - if component is None: + _component = config.components.server_settings.general + if _component is None: from conreq._core.server_settings import components return html._(components.general_settings(*args, **kwargs)) - return component(*args, **kwargs) + return _component(*args, **kwargs) @component def server_settings_styling(*args, **kwargs): - component = config.components.server_settings.styling - if component is None: + _component = config.components.server_settings.styling + if _component is None: from conreq._core.server_settings import components return html._(components.styling_settings(*args, **kwargs)) - return component(*args, **kwargs) + return _component(*args, **kwargs) @component def server_settings_webserver(*args, **kwargs): - component = config.components.server_settings.webserver - if component is None: + _component = config.components.server_settings.webserver + if _component is None: from conreq._core.server_settings import components return html._(components.webserver_settings(*args, **kwargs)) - return component(*args, **kwargs) + return _component(*args, **kwargs) @component def server_settings_email(*args, **kwargs): - component = config.components.server_settings.email - if component is None: + _component = config.components.server_settings.email + if _component is None: from conreq._core.server_settings import components return html._(components.email_settings(*args, **kwargs)) - return component(*args, **kwargs) + return _component(*args, **kwargs) @component def server_settings_system_info(*args, **kwargs): - component = config.components.server_settings.system_info - if component is None: + _component = config.components.server_settings.system_info + if _component is None: from conreq._core.server_settings import components return html._(components.system_info(*args, **kwargs)) - return component(*args, **kwargs) + return _component(*args, **kwargs) @component def server_settings_licenses(*args, **kwargs): - component = config.components.server_settings.system_info - if component is None: + _component = config.components.server_settings.system_info + if _component is None: from conreq._core.server_settings import components return html._(components.licenses(*args, **kwargs)) - return component(*args, **kwargs) + return _component(*args, **kwargs) diff --git a/conreq/types.py b/conreq/types.py index 5f0f1ea5..32f99021 100644 --- a/conreq/types.py +++ b/conreq/types.py @@ -3,8 +3,9 @@ from dataclasses import dataclass, field from typing import Any, Callable +from idom.core.component import Component from idom.core.hooks import Context, create_context -from idom.core.types import VdomDict +from idom.core.types import ComponentConstructor, VdomDict from sortedcontainers import SortedSet # pylint: disable=protected-access, too-few-public-methods @@ -33,7 +34,7 @@ class AuthLevel: @dataclass(frozen=True) class Viewport: - component: Callable + component: ComponentConstructor | Callable[..., Component] html_class: str = "" padding: bool = True page_title: str | None = None @@ -60,7 +61,7 @@ def __gt__(self, __o: object) -> bool: @dataclass(frozen=True) class SubTab: name: str - component: Callable + component: ComponentConstructor | Callable[..., Component] html_class: str = "" padding: bool = True on_click: Callable[[SubTabEvent], None] | None = None