openadmin-dev 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- openadmin/fastapi/__init__.py +11 -0
- openadmin/fastapi/admin_page.py +526 -0
- openadmin/fastapi/admin_panel.py +89 -0
- openadmin/fastapi/types/__init__.py +36 -0
- openadmin/fastapi/types/action.py +20 -0
- openadmin/fastapi/types/area_chart.py +19 -0
- openadmin/fastapi/types/bar_chart.py +19 -0
- openadmin/fastapi/types/form.py +20 -0
- openadmin/fastapi/types/line_chart.py +19 -0
- openadmin/fastapi/types/markdown.py +19 -0
- openadmin/fastapi/types/page_protocol.py +12 -0
- openadmin/fastapi/types/pie_chart.py +19 -0
- openadmin/fastapi/types/section.py +15 -0
- openadmin/fastapi/types/stat.py +19 -0
- openadmin/fastapi/types/table.py +19 -0
- openadmin/fastapi/utils.py +167 -0
- openadmin/spec/__init__.py +41 -0
- openadmin/spec/components/__init__.py +35 -0
- openadmin/spec/components/action.py +22 -0
- openadmin/spec/components/area_chart.py +19 -0
- openadmin/spec/components/bar_chart.py +19 -0
- openadmin/spec/components/form.py +22 -0
- openadmin/spec/components/http_methods.py +7 -0
- openadmin/spec/components/line_chart.py +19 -0
- openadmin/spec/components/markdown.py +19 -0
- openadmin/spec/components/pie_chart.py +19 -0
- openadmin/spec/components/property.py +17 -0
- openadmin/spec/components/property_type.py +18 -0
- openadmin/spec/components/stat.py +19 -0
- openadmin/spec/components/table.py +21 -0
- openadmin/spec/page.py +15 -0
- openadmin/spec/section.py +15 -0
- openadmin/spec/spec.py +16 -0
- openadmin_dev-0.1.0.dist-info/METADATA +304 -0
- openadmin_dev-0.1.0.dist-info/RECORD +37 -0
- openadmin_dev-0.1.0.dist-info/WHEEL +4 -0
- openadmin_dev-0.1.0.dist-info/licenses/LICENSE +661 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 OpenAdmin
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
from collections.abc import Callable
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, ConfigDict
|
|
8
|
+
|
|
9
|
+
from openadmin import spec
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class BarChart(BaseModel):
|
|
13
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
14
|
+
|
|
15
|
+
function_name: str
|
|
16
|
+
name: str
|
|
17
|
+
description: str | None
|
|
18
|
+
method: spec.HttpMethod
|
|
19
|
+
func: Callable | None = None
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 OpenAdmin
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
from collections.abc import Callable
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, ConfigDict
|
|
8
|
+
|
|
9
|
+
from openadmin import spec
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Form(BaseModel):
|
|
13
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
14
|
+
|
|
15
|
+
function_name: str
|
|
16
|
+
name: str
|
|
17
|
+
description: str | None
|
|
18
|
+
method: spec.HttpMethod
|
|
19
|
+
is_hiden: bool
|
|
20
|
+
func: Callable | None = None
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 OpenAdmin
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
from collections.abc import Callable
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, ConfigDict
|
|
8
|
+
|
|
9
|
+
from openadmin import spec
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class LineChart(BaseModel):
|
|
13
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
14
|
+
|
|
15
|
+
function_name: str
|
|
16
|
+
name: str
|
|
17
|
+
description: str | None
|
|
18
|
+
method: spec.HttpMethod
|
|
19
|
+
func: Callable | None = None
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 OpenAdmin
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
from collections.abc import Callable
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, ConfigDict
|
|
8
|
+
|
|
9
|
+
from openadmin import spec
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Markdown(BaseModel):
|
|
13
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
14
|
+
|
|
15
|
+
function_name: str
|
|
16
|
+
name: str
|
|
17
|
+
description: str | None
|
|
18
|
+
method: spec.HttpMethod
|
|
19
|
+
func: Callable | None = None
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 OpenAdmin
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
from typing import Protocol
|
|
6
|
+
|
|
7
|
+
from fastapi import FastAPI
|
|
8
|
+
from openadmin import spec
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class PageProtocol(Protocol):
|
|
12
|
+
def get_page_spec(self, app: FastAPI) -> spec.Page: ...
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 OpenAdmin
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
from collections.abc import Callable
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, ConfigDict
|
|
8
|
+
|
|
9
|
+
from openadmin import spec
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class PieChart(BaseModel):
|
|
13
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
14
|
+
|
|
15
|
+
function_name: str
|
|
16
|
+
name: str
|
|
17
|
+
description: str | None
|
|
18
|
+
method: spec.HttpMethod
|
|
19
|
+
func: Callable | None = None
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 OpenAdmin
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Sequence
|
|
7
|
+
|
|
8
|
+
from .page_protocol import PageProtocol
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass
|
|
12
|
+
class Section:
|
|
13
|
+
name: str
|
|
14
|
+
description: str | None
|
|
15
|
+
pages: Sequence[PageProtocol]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 OpenAdmin
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
from collections.abc import Callable
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, ConfigDict
|
|
8
|
+
|
|
9
|
+
from openadmin import spec
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Stat(BaseModel):
|
|
13
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
14
|
+
|
|
15
|
+
function_name: str
|
|
16
|
+
method: spec.HttpMethod
|
|
17
|
+
name: str
|
|
18
|
+
description: str | None
|
|
19
|
+
func: Callable | None = None
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 OpenAdmin
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
from collections.abc import Callable
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, ConfigDict
|
|
8
|
+
|
|
9
|
+
from openadmin import spec
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Table(BaseModel):
|
|
13
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
14
|
+
|
|
15
|
+
function_name: str
|
|
16
|
+
method: spec.HttpMethod
|
|
17
|
+
name: str
|
|
18
|
+
description: str | None
|
|
19
|
+
func: Callable | None = None
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 OpenAdmin
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
import inspect
|
|
6
|
+
from typing import Annotated, get_args, get_origin, get_type_hints
|
|
7
|
+
|
|
8
|
+
import pydantic
|
|
9
|
+
|
|
10
|
+
from fastapi.params import Body as BodyParam
|
|
11
|
+
from fastapi.params import Form as FormParam
|
|
12
|
+
from fastapi.params import Query as QueryParam
|
|
13
|
+
from openadmin import spec
|
|
14
|
+
|
|
15
|
+
_SCALAR_LIST_TYPES: dict[type, spec.PropertyType] = {
|
|
16
|
+
str: "list[string]",
|
|
17
|
+
int: "list[integer]",
|
|
18
|
+
float: "list[float]",
|
|
19
|
+
bool: "list[bool]",
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _type_to_property_type(tp) -> spec.PropertyType:
|
|
24
|
+
origin = get_origin(tp)
|
|
25
|
+
if origin is list:
|
|
26
|
+
inner = get_args(tp)
|
|
27
|
+
if inner:
|
|
28
|
+
scalar = _SCALAR_LIST_TYPES.get(inner[0])
|
|
29
|
+
if scalar:
|
|
30
|
+
return scalar
|
|
31
|
+
return "list"
|
|
32
|
+
if tp is str:
|
|
33
|
+
return "string"
|
|
34
|
+
if tp is int:
|
|
35
|
+
return "integer"
|
|
36
|
+
if tp is float:
|
|
37
|
+
return "float"
|
|
38
|
+
if tp is bool:
|
|
39
|
+
return "bool"
|
|
40
|
+
if isinstance(tp, type) and issubclass(tp, pydantic.BaseModel):
|
|
41
|
+
return "object"
|
|
42
|
+
return "string"
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _model_to_properties(model: type) -> list[spec.Property]:
|
|
46
|
+
props = []
|
|
47
|
+
for field_name, field_info in model.model_fields.items():
|
|
48
|
+
tp = field_info.annotation
|
|
49
|
+
prop_type = _type_to_property_type(tp)
|
|
50
|
+
nested = None
|
|
51
|
+
if (
|
|
52
|
+
prop_type == "object"
|
|
53
|
+
and isinstance(tp, type)
|
|
54
|
+
and issubclass(tp, pydantic.BaseModel)
|
|
55
|
+
):
|
|
56
|
+
nested = _model_to_properties(tp)
|
|
57
|
+
elif prop_type == "list":
|
|
58
|
+
inner = get_args(tp)
|
|
59
|
+
if (
|
|
60
|
+
inner
|
|
61
|
+
and isinstance(inner[0], type)
|
|
62
|
+
and issubclass(inner[0], pydantic.BaseModel)
|
|
63
|
+
):
|
|
64
|
+
nested = _model_to_properties(inner[0])
|
|
65
|
+
display = field_info.title or field_name.replace("_", " ").title()
|
|
66
|
+
alias = field_info.alias or field_name
|
|
67
|
+
props.append(
|
|
68
|
+
spec.Property(
|
|
69
|
+
name=display,
|
|
70
|
+
alias=alias,
|
|
71
|
+
type=prop_type,
|
|
72
|
+
is_required=field_info.is_required(),
|
|
73
|
+
properties=nested,
|
|
74
|
+
)
|
|
75
|
+
)
|
|
76
|
+
return props
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _make_property(param_name: str, tp, marker) -> spec.Property:
|
|
80
|
+
prop_type = _type_to_property_type(tp)
|
|
81
|
+
nested = None
|
|
82
|
+
if (
|
|
83
|
+
prop_type == "object"
|
|
84
|
+
and isinstance(tp, type)
|
|
85
|
+
and issubclass(tp, pydantic.BaseModel)
|
|
86
|
+
):
|
|
87
|
+
nested = _model_to_properties(tp)
|
|
88
|
+
|
|
89
|
+
display = param_name.replace("_", " ").title()
|
|
90
|
+
alias = param_name
|
|
91
|
+
required = True
|
|
92
|
+
|
|
93
|
+
if marker is not None:
|
|
94
|
+
if marker.alias:
|
|
95
|
+
alias = marker.alias
|
|
96
|
+
if marker.title:
|
|
97
|
+
display = marker.title
|
|
98
|
+
required = marker.is_required()
|
|
99
|
+
|
|
100
|
+
return spec.Property(
|
|
101
|
+
name=display,
|
|
102
|
+
alias=alias,
|
|
103
|
+
type=prop_type,
|
|
104
|
+
is_required=required,
|
|
105
|
+
properties=nested,
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def extract_params(
|
|
110
|
+
func,
|
|
111
|
+
) -> tuple[
|
|
112
|
+
list[spec.Property] | None, list[spec.Property] | None, list[spec.Property] | None
|
|
113
|
+
]:
|
|
114
|
+
"""Return (query, body, form) properties extracted from a function's signature."""
|
|
115
|
+
try:
|
|
116
|
+
hints = get_type_hints(func, include_extras=True)
|
|
117
|
+
except Exception:
|
|
118
|
+
return None, None, None
|
|
119
|
+
|
|
120
|
+
sig = inspect.signature(func)
|
|
121
|
+
query: list[spec.Property] = []
|
|
122
|
+
body: list[spec.Property] = []
|
|
123
|
+
form: list[spec.Property] = []
|
|
124
|
+
|
|
125
|
+
for param_name, param in sig.parameters.items():
|
|
126
|
+
if param_name in ("self", "cls"):
|
|
127
|
+
continue
|
|
128
|
+
|
|
129
|
+
annotation = hints.get(param_name, inspect.Parameter.empty)
|
|
130
|
+
default = param.default
|
|
131
|
+
marker = None
|
|
132
|
+
actual_type = annotation
|
|
133
|
+
|
|
134
|
+
if get_origin(annotation) is Annotated:
|
|
135
|
+
args = get_args(annotation)
|
|
136
|
+
actual_type = args[0]
|
|
137
|
+
for arg in args[1:]:
|
|
138
|
+
if isinstance(arg, (QueryParam, BodyParam, FormParam)):
|
|
139
|
+
marker = arg
|
|
140
|
+
break
|
|
141
|
+
|
|
142
|
+
if marker is None and isinstance(default, (QueryParam, BodyParam, FormParam)):
|
|
143
|
+
marker = default
|
|
144
|
+
|
|
145
|
+
# FormParam must be checked before BodyParam — Form is a subclass of Body
|
|
146
|
+
if isinstance(marker, QueryParam):
|
|
147
|
+
query.append(_make_property(param_name, actual_type, marker))
|
|
148
|
+
elif isinstance(marker, FormParam):
|
|
149
|
+
form.append(_make_property(param_name, actual_type, marker))
|
|
150
|
+
elif isinstance(marker, BodyParam):
|
|
151
|
+
if isinstance(actual_type, type) and issubclass(
|
|
152
|
+
actual_type, pydantic.BaseModel
|
|
153
|
+
):
|
|
154
|
+
body.extend(_model_to_properties(actual_type))
|
|
155
|
+
else:
|
|
156
|
+
body.append(_make_property(param_name, actual_type, marker))
|
|
157
|
+
elif (
|
|
158
|
+
annotation is not inspect.Parameter.empty
|
|
159
|
+
and default is inspect.Parameter.empty
|
|
160
|
+
):
|
|
161
|
+
# Unannotated Pydantic model with no default → implicit JSON body
|
|
162
|
+
if isinstance(actual_type, type) and issubclass(
|
|
163
|
+
actual_type, pydantic.BaseModel
|
|
164
|
+
):
|
|
165
|
+
body.extend(_model_to_properties(actual_type))
|
|
166
|
+
|
|
167
|
+
return query or None, body or None, form or None
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 OpenAdmin
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
from .components import (
|
|
6
|
+
Action,
|
|
7
|
+
AreaChart,
|
|
8
|
+
BarChart,
|
|
9
|
+
Component,
|
|
10
|
+
Form,
|
|
11
|
+
LineChart,
|
|
12
|
+
Markdown,
|
|
13
|
+
PieChart,
|
|
14
|
+
Property,
|
|
15
|
+
PropertyType,
|
|
16
|
+
Stat,
|
|
17
|
+
Table,
|
|
18
|
+
)
|
|
19
|
+
from .components.http_methods import HttpMethod
|
|
20
|
+
from .page import Page
|
|
21
|
+
from .section import Section
|
|
22
|
+
from .spec import Spec
|
|
23
|
+
|
|
24
|
+
__all__ = [
|
|
25
|
+
"Action",
|
|
26
|
+
"AreaChart",
|
|
27
|
+
"BarChart",
|
|
28
|
+
"Component",
|
|
29
|
+
"Form",
|
|
30
|
+
"HttpMethod",
|
|
31
|
+
"LineChart",
|
|
32
|
+
"Page",
|
|
33
|
+
"PieChart",
|
|
34
|
+
"Property",
|
|
35
|
+
"PropertyType",
|
|
36
|
+
"Section",
|
|
37
|
+
"Spec",
|
|
38
|
+
"Stat",
|
|
39
|
+
"Table",
|
|
40
|
+
"Markdown",
|
|
41
|
+
]
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 OpenAdmin
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
from typing import Union
|
|
6
|
+
|
|
7
|
+
from .action import Action
|
|
8
|
+
from .area_chart import AreaChart
|
|
9
|
+
from .bar_chart import BarChart
|
|
10
|
+
from .form import Form
|
|
11
|
+
from .line_chart import LineChart
|
|
12
|
+
from .markdown import Markdown
|
|
13
|
+
from .pie_chart import PieChart
|
|
14
|
+
from .property import Property
|
|
15
|
+
from .property_type import PropertyType
|
|
16
|
+
from .stat import Stat
|
|
17
|
+
from .table import Table
|
|
18
|
+
|
|
19
|
+
type Component = Union[
|
|
20
|
+
Stat, Table, AreaChart, BarChart, LineChart, PieChart, Action, Form, Markdown
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
__all__ = [
|
|
24
|
+
"AreaChart",
|
|
25
|
+
"BarChart",
|
|
26
|
+
"Component",
|
|
27
|
+
"LineChart",
|
|
28
|
+
"PieChart",
|
|
29
|
+
"Stat",
|
|
30
|
+
"Action",
|
|
31
|
+
"Table",
|
|
32
|
+
"Form",
|
|
33
|
+
"Property",
|
|
34
|
+
"PropertyType",
|
|
35
|
+
]
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 OpenAdmin
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
from typing import List, Literal
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, Field
|
|
8
|
+
|
|
9
|
+
from .http_methods import HttpMethod
|
|
10
|
+
from .property import Property
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Action(BaseModel):
|
|
14
|
+
type: Literal["action"]
|
|
15
|
+
name: str
|
|
16
|
+
description: str | None
|
|
17
|
+
url: str
|
|
18
|
+
method: HttpMethod
|
|
19
|
+
is_hidden: bool
|
|
20
|
+
form: List[Property] | None = Field(None)
|
|
21
|
+
body: List[Property] | None = Field(None)
|
|
22
|
+
query: List[Property] | None = Field(None)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 OpenAdmin
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
from typing import Literal
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, Field
|
|
8
|
+
|
|
9
|
+
from .http_methods import HttpMethod
|
|
10
|
+
from .property import Property
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class AreaChart(BaseModel):
|
|
14
|
+
type: Literal["area-chart"]
|
|
15
|
+
name: str
|
|
16
|
+
description: str | None
|
|
17
|
+
url: str
|
|
18
|
+
method: HttpMethod
|
|
19
|
+
query: list[Property] | None = Field(None)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 OpenAdmin
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
from typing import Literal
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, Field
|
|
8
|
+
|
|
9
|
+
from .http_methods import HttpMethod
|
|
10
|
+
from .property import Property
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class BarChart(BaseModel):
|
|
14
|
+
type: Literal["bar-chart"]
|
|
15
|
+
name: str
|
|
16
|
+
description: str | None
|
|
17
|
+
url: str
|
|
18
|
+
method: HttpMethod
|
|
19
|
+
query: list[Property] | None = Field(None)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 OpenAdmin
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
from typing import List, Literal
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, Field
|
|
8
|
+
|
|
9
|
+
from .http_methods import HttpMethod
|
|
10
|
+
from .property import Property
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Form(BaseModel):
|
|
14
|
+
type: Literal["form"]
|
|
15
|
+
name: str
|
|
16
|
+
description: str | None
|
|
17
|
+
url: str
|
|
18
|
+
method: HttpMethod
|
|
19
|
+
is_hiden: bool
|
|
20
|
+
form: List[Property] | None = Field(None)
|
|
21
|
+
body: List[Property] | None = Field(None)
|
|
22
|
+
query: List[Property] | None = Field(None)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 OpenAdmin
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
from typing import Literal
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, Field
|
|
8
|
+
|
|
9
|
+
from .http_methods import HttpMethod
|
|
10
|
+
from .property import Property
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class LineChart(BaseModel):
|
|
14
|
+
type: Literal["line-chart"]
|
|
15
|
+
name: str
|
|
16
|
+
description: str | None
|
|
17
|
+
url: str
|
|
18
|
+
method: HttpMethod
|
|
19
|
+
query: list[Property] | None = Field(None)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 OpenAdmin
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
from typing import List, Literal
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, Field
|
|
8
|
+
|
|
9
|
+
from .http_methods import HttpMethod
|
|
10
|
+
from .property import Property
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Markdown(BaseModel):
|
|
14
|
+
type: Literal["markdown"]
|
|
15
|
+
name: str
|
|
16
|
+
description: str | None
|
|
17
|
+
url: str
|
|
18
|
+
method: HttpMethod
|
|
19
|
+
query: List[Property] | None = Field(None)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 OpenAdmin
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
from typing import Literal
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, Field
|
|
8
|
+
|
|
9
|
+
from .http_methods import HttpMethod
|
|
10
|
+
from .property import Property
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class PieChart(BaseModel):
|
|
14
|
+
type: Literal["pie-chart"]
|
|
15
|
+
name: str
|
|
16
|
+
description: str | None
|
|
17
|
+
url: str
|
|
18
|
+
method: HttpMethod
|
|
19
|
+
query: list[Property] | None = Field(None)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 OpenAdmin
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
from typing import List
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, Field
|
|
8
|
+
|
|
9
|
+
from .property_type import PropertyType
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Property(BaseModel):
|
|
13
|
+
name: str = Field(..., description="This name for showing to user in admin panel")
|
|
14
|
+
alias: str = Field(..., description="This name goes to body or form for backend")
|
|
15
|
+
type: PropertyType
|
|
16
|
+
is_required: bool
|
|
17
|
+
properties: List[Property] | None = Field(None)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 OpenAdmin
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
from typing import Literal
|
|
6
|
+
|
|
7
|
+
type PropertyType = Literal[
|
|
8
|
+
"integer",
|
|
9
|
+
"string",
|
|
10
|
+
"bool",
|
|
11
|
+
"float",
|
|
12
|
+
"object",
|
|
13
|
+
"list",
|
|
14
|
+
"list[integer]",
|
|
15
|
+
"list[string]",
|
|
16
|
+
"list[bool]",
|
|
17
|
+
"list[float]",
|
|
18
|
+
]
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 OpenAdmin
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
from typing import Literal
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, Field
|
|
8
|
+
|
|
9
|
+
from .http_methods import HttpMethod
|
|
10
|
+
from .property import Property
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Stat(BaseModel):
|
|
14
|
+
type: Literal["stat"]
|
|
15
|
+
name: str
|
|
16
|
+
description: str | None
|
|
17
|
+
url: str
|
|
18
|
+
method: HttpMethod
|
|
19
|
+
query: list[Property] | None = Field(None)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 OpenAdmin
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
from typing import List, Literal
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, Field
|
|
8
|
+
|
|
9
|
+
from .http_methods import HttpMethod
|
|
10
|
+
from .property import Property
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Table(BaseModel):
|
|
14
|
+
type: Literal["table"]
|
|
15
|
+
name: str
|
|
16
|
+
description: str | None
|
|
17
|
+
url: str
|
|
18
|
+
method: HttpMethod
|
|
19
|
+
form: List[Property] | None = Field(None)
|
|
20
|
+
body: List[Property] | None = Field(None)
|
|
21
|
+
query: List[Property] | None = Field(None)
|
openadmin/spec/page.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 OpenAdmin
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
from typing import List
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel
|
|
8
|
+
|
|
9
|
+
from .components import Component
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Page(BaseModel):
|
|
13
|
+
name: str
|
|
14
|
+
description: str | None
|
|
15
|
+
components: List[Component]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 OpenAdmin
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
from typing import List
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel
|
|
8
|
+
|
|
9
|
+
from .page import Page
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Section(BaseModel):
|
|
13
|
+
name: str
|
|
14
|
+
description: str | None
|
|
15
|
+
pages: List[Page]
|