Skip to content

Commit 48da788

Browse files
committed
merged Settings UI example, removed "deploy" command
1 parent 6b273c6 commit 48da788

File tree

4 files changed

+187
-87
lines changed

4 files changed

+187
-87
lines changed

Makefile

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@ help:
99
@echo " "
1010
@echo " build-push build image and upload to ghcr.io"
1111
@echo " "
12-
@echo " deploy27 deploy UiExample to registered 'docker_dev' for Nextcloud 27"
13-
@echo " deploy28 deploy UiExample to registered 'docker_dev' for Nextcloud 28"
14-
@echo " deploy deploy UiExample to registered 'docker_dev' for Nextcloud Last"
15-
@echo " "
1612
@echo " run27 install UiExample for Nextcloud 27"
1713
@echo " run28 install UiExample for Nextcloud 28"
1814
@echo " run install UiExample for Nextcloud Last"
@@ -34,40 +30,22 @@ build-push:
3430
docker login ghcr.io
3531
docker buildx build --push --platform linux/arm64/v8,linux/amd64 --tag ghcr.io/cloud-py-api/ui_example:latest .
3632

37-
.PHONY: deploy27
38-
deploy27:
39-
docker exec master-stable27-1 sudo -u www-data php occ app_api:app:unregister ui_example --silent --force || true
40-
docker exec master-stable27-1 sudo -u www-data php occ app_api:app:deploy ui_example docker_dev \
41-
--info-xml https://raw.githubusercontent.com/cloud-py-api/nc_py_api/main/examples/as_app/ui_example/appinfo/info.xml
42-
43-
.PHONY: deploy28
44-
deploy28:
45-
docker exec master-stable28-1 sudo -u www-data php occ app_api:app:unregister ui_example --silent --force || true
46-
docker exec master-stable28-1 sudo -u www-data php occ app_api:app:deploy ui_example docker_dev \
47-
--info-xml https://raw.githubusercontent.com/cloud-py-api/nc_py_api/main/examples/as_app/ui_example/appinfo/info.xml
48-
49-
.PHONY: deploy
50-
deploy:
51-
docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:unregister ui_example --silent --force || true
52-
docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:deploy ui_example docker_dev \
53-
--info-xml https://raw.githubusercontent.com/cloud-py-api/nc_py_api/main/examples/as_app/ui_example/appinfo/info.xml
54-
5533
.PHONY: run27
5634
run27:
5735
docker exec master-stable27-1 sudo -u www-data php occ app_api:app:unregister ui_example --silent --force || true
58-
docker exec master-stable27-1 sudo -u www-data php occ app_api:app:register ui_example docker_dev --force-scopes \
36+
docker exec master-stable27-1 sudo -u www-data php occ app_api:app:register ui_example --force-scopes \
5937
--info-xml https://raw.githubusercontent.com/cloud-py-api/nc_py_api/main/examples/as_app/ui_example/appinfo/info.xml
6038

6139
.PHONY: run28
6240
run28:
6341
docker exec master-stable28-1 sudo -u www-data php occ app_api:app:unregister ui_example --silent --force || true
64-
docker exec master-stable28-1 sudo -u www-data php occ app_api:app:register ui_example docker_dev --force-scopes \
42+
docker exec master-stable28-1 sudo -u www-data php occ app_api:app:register ui_example --force-scopes \
6543
--info-xml https://raw.githubusercontent.com/cloud-py-api/nc_py_api/main/examples/as_app/ui_example/appinfo/info.xml
6644

6745
.PHONY: run
6846
run:
6947
docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:unregister ui_example --silent --force || true
70-
docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:register ui_example docker_dev --force-scopes \
48+
docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:register ui_example --force-scopes \
7149
--info-xml https://raw.githubusercontent.com/cloud-py-api/nc_py_api/main/examples/as_app/ui_example/appinfo/info.xml
7250

7351
.PHONY: register27

appinfo/info.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<name>UI Example</name>
55
<summary>Example of displaying UI elements with l10n support</summary>
66
<description>
7-
<![CDATA[Simplest skeleton of the Nextcloud application written in Python]]>
7+
<![CDATA[UI & Translations skeleton of the Nextcloud application written in Python]]>
88
</description>
99
<version>1.0.0</version>
1010
<licence>MIT</licence>

lib/main.py

Lines changed: 180 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,227 @@
11
"""Example with which we test UI elements with L10N support."""
2+
23
import locale
34
import os
45
import random
5-
import typing
66
from contextlib import asynccontextmanager
77

8-
from fastapi import Depends, FastAPI, responses
8+
from fastapi import FastAPI, responses
99
from pydantic import BaseModel
1010

1111
from nc_py_api import NextcloudApp
12-
from nc_py_api.ex_app import nc_app, run_app, set_handlers
12+
from nc_py_api.ex_app import (
13+
run_app,
14+
set_handlers,
15+
AppAPIAuthMiddleware,
16+
SettingsField,
17+
SettingsFieldType,
18+
SettingsForm,
19+
)
1320

1421
import gettext
1522

1623
# ../locale/<lang>/LC_MESSAGES/<app_id>.(mo|po)
1724
localedir = os.path.join(os.path.dirname(os.path.dirname(__file__)), "locale")
1825
locale.setlocale(locale.LC_ALL)
1926
locale.bindtextdomain(os.getenv("APP_ID"), localedir)
20-
my_l10n = gettext.translation(os.getenv("APP_ID"), localedir, fallback=True, languages=['en', 'uk'])
27+
my_l10n = gettext.translation(
28+
os.getenv("APP_ID"), localedir, fallback=True, languages=["en", "uk"]
29+
)
2130
my_l10n.install()
2231

2332
_ = my_l10n.gettext
2433
_n = my_l10n.ngettext
2534

2635

2736
@asynccontextmanager
28-
async def lifespan(_app: FastAPI):
29-
set_handlers(APP, enabled_handler)
30-
print(_('UI example'))
31-
yield
37+
async def lifespan(app: FastAPI):
38+
set_handlers(app, enabled_handler)
39+
print(_("UI example"))
40+
yield
3241

3342

3443
APP = FastAPI(lifespan=lifespan)
44+
APP.add_middleware(AppAPIAuthMiddleware)
45+
46+
SETTINGS_EXAMPLE = SettingsForm(
47+
id="settings_example",
48+
section_type="admin",
49+
section_id="ai_integration_team",
50+
title="Example of declarative settings",
51+
description="These fields are rendered dynamically from declarative schema",
52+
fields=[
53+
SettingsField(
54+
id="field1",
55+
title="Multi-selection",
56+
description="Select some option setting",
57+
type=SettingsFieldType.MULTI_SELECT,
58+
default=["foo", "bar"],
59+
placeholder="Select some multiple options",
60+
options=["foo", "bar", "baz"],
61+
),
62+
SettingsField(
63+
id="some_real_setting",
64+
title="Choose init status check background job interval",
65+
description="How often ExApp should check for initialization status",
66+
type=SettingsFieldType.RADIO,
67+
default="40m",
68+
placeholder="Choose init status check background job interval",
69+
options={
70+
"Each 40 minutes": "40m",
71+
"Each 60 minutes": "60m",
72+
"Each 120 minutes": "120m",
73+
"Each day": f"{60 * 24}m",
74+
},
75+
),
76+
SettingsField(
77+
id="test_ex_app_field_1",
78+
title="Default text field",
79+
description="Set some simple text setting",
80+
type=SettingsFieldType.TEXT,
81+
default="foo",
82+
placeholder="Enter text setting",
83+
),
84+
SettingsField(
85+
id="test_ex_app_field_1_1",
86+
title="Email field",
87+
description="Set email config",
88+
type=SettingsFieldType.EMAIL,
89+
default="",
90+
placeholder="Enter email",
91+
),
92+
SettingsField(
93+
id="test_ex_app_field_1_2",
94+
title="Tel field",
95+
description="Set tel config",
96+
type=SettingsFieldType.TEL,
97+
default="",
98+
placeholder="Enter your tel",
99+
),
100+
SettingsField(
101+
id="test_ex_app_field_1_3",
102+
title="Url (website) field",
103+
description="Set url config",
104+
type=SettingsFieldType.URL,
105+
default="",
106+
placeholder="Enter url",
107+
),
108+
SettingsField(
109+
id="test_ex_app_field_1_4",
110+
title="Number field",
111+
description="Set number config",
112+
type=SettingsFieldType.NUMBER,
113+
default=0,
114+
placeholder="Enter number value",
115+
),
116+
SettingsField(
117+
id="test_ex_app_field_2",
118+
title="Password",
119+
description="Set some secure value setting",
120+
type=SettingsFieldType.PASSWORD,
121+
default="",
122+
placeholder="Set secure value",
123+
),
124+
SettingsField(
125+
id="test_ex_app_field_3",
126+
title="Selection",
127+
description="Select some option setting",
128+
type=SettingsFieldType.SELECT,
129+
default="foo",
130+
placeholder="Select some option setting",
131+
options=["foo", "bar", "baz"],
132+
),
133+
SettingsField(
134+
id="test_ex_app_field_3",
135+
title="Selection",
136+
description="Select some option setting",
137+
type=SettingsFieldType.SELECT,
138+
default="foo",
139+
placeholder="Select some option setting",
140+
options=["foo", "bar", "baz"],
141+
),
142+
SettingsField(
143+
id="test_ex_app_field_4",
144+
title="Toggle something",
145+
description="Select checkbox option setting",
146+
type=SettingsFieldType.CHECKBOX,
147+
default=False,
148+
label="Verify something if enabled",
149+
),
150+
SettingsField(
151+
id="test_ex_app_field_5",
152+
title="Multiple checkbox toggles, describing one setting",
153+
description="Select checkbox option setting",
154+
type=SettingsFieldType.MULTI_CHECKBOX,
155+
default={"foo": True, "bar": True},
156+
options={"Foo": "foo", "Bar": "bar", "Baz": "baz", "Qux": "qux"},
157+
),
158+
SettingsField(
159+
id="test_ex_app_field_6",
160+
title="Radio toggles, describing one setting like single select",
161+
description="Select radio option setting",
162+
type=SettingsFieldType.RADIO,
163+
label="Select single toggle",
164+
default="foo",
165+
options={"First radio": "foo", "Second radio": "bar", "Third radie": "baz"},
166+
),
167+
],
168+
)
35169

36170

37171
def enabled_handler(enabled: bool, nc: NextcloudApp) -> str:
38-
print(f"enabled={enabled}")
39-
if enabled:
40-
nc.ui.resources.set_initial_state(
41-
"top_menu", "first_menu", "ui_example_state", {"initial_value": "test init value"}
42-
)
43-
nc.ui.resources.set_script("top_menu", "first_menu", "js/ui_example-main")
44-
nc.ui.top_menu.register("first_menu", "UI example", "img/app.svg")
45-
else:
46-
nc.ui.resources.delete_initial_state("top_menu", "first_menu", "ui_example_state")
47-
nc.ui.resources.delete_script("top_menu", "first_menu", "js/ui_example-main")
48-
nc.ui.top_menu.unregister("first_menu")
49-
return ""
172+
print(f"enabled={enabled}")
173+
if enabled:
174+
nc.ui.resources.set_initial_state(
175+
"top_menu",
176+
"first_menu",
177+
"ui_example_state",
178+
{"initial_value": "test init value"},
179+
)
180+
nc.ui.resources.set_script("top_menu", "first_menu", "js/ui_example-main")
181+
nc.ui.top_menu.register("first_menu", "UI example", "img/app.svg")
182+
if nc.srv_version["major"] >= 29:
183+
nc.ui.settings.register_form(SETTINGS_EXAMPLE)
184+
else:
185+
nc.ui.resources.delete_initial_state(
186+
"top_menu", "first_menu", "ui_example_state"
187+
)
188+
nc.ui.resources.delete_script("top_menu", "first_menu", "js/ui_example-main")
189+
nc.ui.top_menu.unregister("first_menu")
190+
return ""
50191

51192

52193
class Button1Format(BaseModel):
53-
initial_value: str
194+
initial_value: str
54195

55196

56197
@APP.post("/verify_initial_value")
57198
async def verify_initial_value(
58-
_nc: typing.Annotated[NextcloudApp, Depends(nc_app)],
59-
input1: Button1Format,
199+
input1: Button1Format,
60200
):
61-
print("Old value: ", input1.initial_value)
62-
return responses.JSONResponse(content={"initial_value": str(random.randint(0, 100))}, status_code=200)
201+
print("Old value: ", input1.initial_value)
202+
return responses.JSONResponse(
203+
content={"initial_value": str(random.randint(0, 100))}, status_code=200
204+
)
63205

64206

65207
class FileInfo(BaseModel):
66-
getlastmodified: str
67-
getetag: str
68-
getcontenttype: str
69-
fileid: int
70-
permissions: str
71-
size: int
72-
getcontentlength: int
73-
favorite: int
208+
getlastmodified: str
209+
getetag: str
210+
getcontenttype: str
211+
fileid: int
212+
permissions: str
213+
size: int
214+
getcontentlength: int
215+
favorite: int
74216

75217

76218
@APP.post("/nextcloud_file")
77219
async def nextcloud_file(
78-
_nc: typing.Annotated[NextcloudApp, Depends(nc_app)],
79-
args: dict,
220+
args: dict,
80221
):
81-
print(args["file_info"])
82-
return responses.Response()
222+
print(args["file_info"])
223+
return responses.Response()
224+
83225

84226
if __name__ == "__main__":
85-
run_app("main:APP", log_level="trace")
227+
run_app("main:APP", log_level="trace")

requirements.txt

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,3 @@
1-
annotated-types==0.6.0
2-
anyio==4.2.0
3-
certifi==2024.2.2
4-
click==8.1.7
5-
fastapi==0.109.2
6-
h11==0.14.0
7-
httpcore==1.0.3
8-
httptools==0.6.1
9-
httpx==0.26.0
10-
idna==3.6
11-
nc-py-api @ file:///home/andrey/coding/nc_py_api
12-
pydantic==2.6.1
13-
pydantic_core==2.16.2
14-
python-dotenv==1.0.1
15-
PyYAML==6.0.1
16-
sniffio==1.3.0
17-
starlette==0.36.3
18-
typing_extensions==4.9.0
19-
uvicorn==0.27.1
20-
uvloop==0.19.0
21-
watchfiles==0.21.0
22-
websockets==12.0
23-
xmltodict==0.13.0
1+
nc-py-api[app]>=0.10.0
2+
fastapi
3+
pydantic

0 commit comments

Comments
 (0)