Skip to content

Commit

Permalink
Declarative Settings UI API (Nextcloud 29) (#222)
Browse files Browse the repository at this point in the history
Signed-off-by: Alexander Piskun <[email protected]>
  • Loading branch information
bigcat88 committed Feb 11, 2024
1 parent c6e4aa9 commit 5354584
Show file tree
Hide file tree
Showing 10 changed files with 412 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file.
### Added

- set_handlers: `models_to_fetch` can now accept direct links to a files to download. #217
- DeclarativeSettings API for Nextcloud 29. #222

### Changed

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Python library that provides a robust and well-documented API that allows develo
| User & Weather status |||||
| Other APIs*** |||||
| Talk Bot API* | N/A ||||
| Settings UI API* | N/A | N/A | N/A ||
| AI Providers API** | N/A | N/A | N/A ||

&ast;_available only for **NextcloudApp**_<br>
Expand Down
7 changes: 7 additions & 0 deletions docs/NextcloudUiApp.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,20 @@ Here we will simply describe in detail what happens in the example.
)
nc.ui.resources.set_script("top_menu", "first_menu", "js/ui_example-main")
nc.ui.top_menu.register("first_menu", "UI example", "img/icon.svg")
if nc.srv_version["major"] >= 29:
nc.ui.settings.register_form(SETTINGS_EXAMPLE)
**set_initial_state** is analogue of PHP ``OCP\AppFramework\Services\IInitialState::provideInitialState``

**set_script** is analogue of PHP ``Util::addScript``

There is also **set_style** (``Util::addStyle``) that can be used for CSS files and works the same way as **set_script**.

Starting with Nextcloud **29** AppAPI supports declaring Settings UI, with very simple and robust API.

Settings values you declare will be saved to ``preferences_ex`` or ``appconfig_ex`` tables and can be retrieved using
:py:class:`nc_py_api._preferences_ex.PreferencesExAPI` or :py:class:`nc_py_api._preferences_ex.AppConfigExAPI` APIs.

Backend
-------

Expand Down
12 changes: 12 additions & 0 deletions docs/reference/ExApp.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,18 @@ UI methods should be accessed with the help of :class:`~nc_py_api.nextcloud.Next
.. autoclass:: nc_py_api.ex_app.ui.resources.UiStyle
:members:

.. autoclass:: nc_py_api.ex_app.ui.settings.SettingsField
:members:

.. autoclass:: nc_py_api.ex_app.ui.settings.SettingsForm
:members:

.. autoclass:: nc_py_api.ex_app.ui.settings.SettingsFieldType
:members:

.. autoclass:: nc_py_api.ex_app.ui.settings._DeclarativeSettingsAPI
:members:

.. autoclass:: nc_py_api.ex_app.providers.providers.ProvidersApi
:members:

Expand Down
135 changes: 134 additions & 1 deletion examples/as_app/ui_example/lib/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,14 @@
from pydantic import BaseModel

from nc_py_api import NextcloudApp
from nc_py_api.ex_app import nc_app, run_app, set_handlers
from nc_py_api.ex_app import (
SettingsField,
SettingsFieldType,
SettingsForm,
nc_app,
run_app,
set_handlers,
)


@asynccontextmanager
Expand All @@ -19,6 +26,130 @@ async def lifespan(_app: FastAPI):

APP = FastAPI(lifespan=lifespan)

SETTINGS_EXAMPLE = SettingsForm(
id="settings_example",
section_type="admin",
section_id="ai_integration_team",
title="Example of declarative settings",
description="These fields are rendered dynamically from declarative schema",
fields=[
SettingsField(
id="field1",
title="Multi-selection",
description="Select some option setting",
type=SettingsFieldType.MULTI_SELECT,
default=["foo", "bar"],
placeholder="Select some multiple options",
options=["foo", "bar", "baz"],
),
SettingsField(
id="some_real_setting",
title="Choose init status check background job interval",
description="How often ExApp should check for initialization status",
type=SettingsFieldType.RADIO,
default="40m",
placeholder="Choose init status check background job interval",
options={
"Each 40 minutes": "40m",
"Each 60 minutes": "60m",
"Each 120 minutes": "120m",
"Each day": f"{60 * 24}m",
},
),
SettingsField(
id="test_ex_app_field_1",
title="Default text field",
description="Set some simple text setting",
type=SettingsFieldType.TEXT,
default="foo",
placeholder="Enter text setting",
),
SettingsField(
id="test_ex_app_field_1_1",
title="Email field",
description="Set email config",
type=SettingsFieldType.EMAIL,
default="",
placeholder="Enter email",
),
SettingsField(
id="test_ex_app_field_1_2",
title="Tel field",
description="Set tel config",
type=SettingsFieldType.TEL,
default="",
placeholder="Enter your tel",
),
SettingsField(
id="test_ex_app_field_1_3",
title="Url (website) field",
description="Set url config",
type=SettingsFieldType.URL,
default="",
placeholder="Enter url",
),
SettingsField(
id="test_ex_app_field_1_4",
title="Number field",
description="Set number config",
type=SettingsFieldType.NUMBER,
default=0,
placeholder="Enter number value",
),
SettingsField(
id="test_ex_app_field_2",
title="Password",
description="Set some secure value setting",
type=SettingsFieldType.PASSWORD,
default="",
placeholder="Set secure value",
),
SettingsField(
id="test_ex_app_field_3",
title="Selection",
description="Select some option setting",
type=SettingsFieldType.SELECT,
default="foo",
placeholder="Select some option setting",
options=["foo", "bar", "baz"],
),
SettingsField(
id="test_ex_app_field_3",
title="Selection",
description="Select some option setting",
type=SettingsFieldType.SELECT,
default="foo",
placeholder="Select some option setting",
options=["foo", "bar", "baz"],
),
SettingsField(
id="test_ex_app_field_4",
title="Toggle something",
description="Select checkbox option setting",
type=SettingsFieldType.CHECKBOX,
default=False,
label="Verify something if enabled",
),
SettingsField(
id="test_ex_app_field_5",
title="Multiple checkbox toggles, describing one setting",
description="Select checkbox option setting",
type=SettingsFieldType.MULTI_CHECKBOX,
default={"foo": True, "bar": True},
options={"Foo": "foo", "Bar": "bar", "Baz": "baz", "Qux": "qux"},
),
SettingsField(
id="test_ex_app_field_6",
title="Radio toggles, describing one setting like single select",
description="Select radio option setting",
type=SettingsFieldType.RADIO,
label="Select single toggle",
default="foo",
options={"First radio": "foo", "Second radio": "bar", "Third radie": "baz"},
),
],
)


def enabled_handler(enabled: bool, nc: NextcloudApp) -> str:
print(f"enabled={enabled}")
Expand All @@ -28,6 +159,8 @@ def enabled_handler(enabled: bool, nc: NextcloudApp) -> str:
)
nc.ui.resources.set_script("top_menu", "first_menu", "js/ui_example-main")
nc.ui.top_menu.register("first_menu", "UI example", "img/icon.svg")
if nc.srv_version["major"] >= 29:
nc.ui.settings.register_form(SETTINGS_EXAMPLE)
return ""


Expand Down
4 changes: 2 additions & 2 deletions nc_py_api/_preferences_ex.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ async def delete(self, keys: str | list[str], not_fail=True) -> None:


class PreferencesExAPI(_BasicAppCfgPref):
"""User specific preferences API."""
"""User specific preferences API, avalaible as **nc.preferences_ex**."""

_url_suffix = "ex-app/preference"

Expand Down Expand Up @@ -134,7 +134,7 @@ async def set_value(self, key: str, value: str) -> None:


class AppConfigExAPI(_BasicAppCfgPref):
"""Non-user(App) specific preferences API."""
"""Non-user(App) specific preferences API, avalaible as **nc.appconfig_ex**."""

_url_suffix = "ex-app/config"

Expand Down
1 change: 1 addition & 0 deletions nc_py_api/ex_app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@
)
from .misc import get_model_path, persistent_storage, verify_version
from .ui.files_actions import UiActionFileInfo
from .ui.settings import SettingsField, SettingsFieldType, SettingsForm
from .uvicorn_fastapi import run_app
Loading

0 comments on commit 5354584

Please sign in to comment.