openadmin-dev 0.7.3__py3-none-any.whl → 0.7.4__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/admin_page.py +25 -1
- openadmin/fastapi/admin_panel.py +4 -5
- openadmin/fastapi/component.py +11 -4
- openadmin/fastapi/pie_chart.py +8 -0
- openadmin/fastapi/section.py +1 -1
- openadmin/spec/__init__.py +18 -7
- openadmin/spec/action.py +4 -4
- openadmin/spec/colors.py +27 -0
- openadmin/spec/component.py +12 -13
- openadmin/spec/form.py +4 -4
- openadmin/spec/markdown.py +2 -2
- openadmin/spec/page.py +1 -2
- openadmin/spec/pie_chart.py +35 -2
- openadmin/spec/property.py +1 -2
- openadmin/spec/section.py +1 -2
- openadmin/spec/spec.py +1 -2
- openadmin/spec/table.py +4 -4
- {openadmin_dev-0.7.3.dist-info → openadmin_dev-0.7.4.dist-info}/METADATA +47 -21
- {openadmin_dev-0.7.3.dist-info → openadmin_dev-0.7.4.dist-info}/RECORD +21 -21
- {openadmin_dev-0.7.3.dist-info → openadmin_dev-0.7.4.dist-info}/WHEEL +0 -0
- {openadmin_dev-0.7.3.dist-info → openadmin_dev-0.7.4.dist-info}/licenses/LICENSE +0 -0
openadmin/fastapi/admin_page.py
CHANGED
|
@@ -117,9 +117,17 @@ class AdminPage:
|
|
|
117
117
|
)
|
|
118
118
|
elif isinstance(item, PieChart):
|
|
119
119
|
components.append(
|
|
120
|
-
spec.
|
|
120
|
+
spec.PieChartComponent(
|
|
121
121
|
type="pie-chart",
|
|
122
122
|
id=item.id,
|
|
123
|
+
config=item.config,
|
|
124
|
+
icon=item.icon,
|
|
125
|
+
name_key=item.name_key,
|
|
126
|
+
color=item.color,
|
|
127
|
+
value_key=item.value_key,
|
|
128
|
+
caption=item.caption,
|
|
129
|
+
caption_icon=item.caption_icon,
|
|
130
|
+
caption_description=item.caption_description,
|
|
123
131
|
name=item.name,
|
|
124
132
|
description=item.description,
|
|
125
133
|
method=item.method,
|
|
@@ -572,6 +580,14 @@ class AdminPage:
|
|
|
572
580
|
name: str,
|
|
573
581
|
*,
|
|
574
582
|
description: str | None = None,
|
|
583
|
+
config: dict[str, spec.PieChartConfigValue] | None = None,
|
|
584
|
+
icon: spec.Icon | None = None,
|
|
585
|
+
name_key: str | None = None,
|
|
586
|
+
value_key: str | None = None,
|
|
587
|
+
color: spec.Color | None = None,
|
|
588
|
+
caption: str | None = None,
|
|
589
|
+
caption_description: str | None = None,
|
|
590
|
+
caption_icon: spec.Icon | None = None,
|
|
575
591
|
):
|
|
576
592
|
kebab_name, unique_name = self.__get_kebab_and_unique_name(name)
|
|
577
593
|
|
|
@@ -581,6 +597,14 @@ class AdminPage:
|
|
|
581
597
|
name=name,
|
|
582
598
|
description=description,
|
|
583
599
|
id=kebab_name,
|
|
600
|
+
config=config,
|
|
601
|
+
icon=icon,
|
|
602
|
+
name_key=name_key,
|
|
603
|
+
value_key=value_key,
|
|
604
|
+
color=color,
|
|
605
|
+
caption=caption,
|
|
606
|
+
caption_description=caption_description,
|
|
607
|
+
caption_icon=caption_icon,
|
|
584
608
|
)
|
|
585
609
|
self.state.append(item)
|
|
586
610
|
return self._wrap_user_handler(
|
openadmin/fastapi/admin_panel.py
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
#
|
|
3
3
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
4
|
|
|
5
|
-
from typing import Dict, List
|
|
6
5
|
|
|
7
6
|
from fastapi import FastAPI, HTTPException, status
|
|
8
7
|
from openadmin import spec
|
|
@@ -16,14 +15,14 @@ class AdminPanel:
|
|
|
16
15
|
self.version = "1.0.0"
|
|
17
16
|
self.name = name
|
|
18
17
|
self.description = description
|
|
19
|
-
self.state:
|
|
18
|
+
self.state: list[Section] = []
|
|
20
19
|
self.app = FastAPI()
|
|
21
|
-
self.key_repeat_count:
|
|
20
|
+
self.key_repeat_count: dict[str, int] = {}
|
|
22
21
|
self.__init_spec_route(self.app)
|
|
23
22
|
self.root: FastAPI | None = None
|
|
24
23
|
|
|
25
24
|
def get_panel_spec(self, app: FastAPI) -> spec.Spec:
|
|
26
|
-
sections:
|
|
25
|
+
sections: list[spec.Section] = []
|
|
27
26
|
|
|
28
27
|
for section in self.state:
|
|
29
28
|
sections.append(
|
|
@@ -49,7 +48,7 @@ class AdminPanel:
|
|
|
49
48
|
*,
|
|
50
49
|
description: str | None = None,
|
|
51
50
|
icon: spec.Icon | None = None,
|
|
52
|
-
pages:
|
|
51
|
+
pages: list[AdminPage],
|
|
53
52
|
) -> None:
|
|
54
53
|
kebab_name = name.lower().replace(" ", "-")
|
|
55
54
|
|
openadmin/fastapi/component.py
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
#
|
|
3
3
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
4
|
|
|
5
|
-
from typing import Union
|
|
6
5
|
|
|
7
6
|
from .action import Action
|
|
8
7
|
from .area_chart import AreaChart
|
|
@@ -14,6 +13,14 @@ from .pie_chart import PieChart
|
|
|
14
13
|
from .stat import Stat
|
|
15
14
|
from .table import Table
|
|
16
15
|
|
|
17
|
-
type Component =
|
|
18
|
-
Stat
|
|
19
|
-
|
|
16
|
+
type Component = (
|
|
17
|
+
Stat
|
|
18
|
+
| Table
|
|
19
|
+
| AreaChart
|
|
20
|
+
| BarChart
|
|
21
|
+
| LineChart
|
|
22
|
+
| PieChart
|
|
23
|
+
| Action
|
|
24
|
+
| Form
|
|
25
|
+
| Markdown
|
|
26
|
+
)
|
openadmin/fastapi/pie_chart.py
CHANGED
|
@@ -13,6 +13,14 @@ class PieChart:
|
|
|
13
13
|
function_name: str
|
|
14
14
|
id: str
|
|
15
15
|
name: str
|
|
16
|
+
config: dict[str, spec.PieChartConfigValue] | None
|
|
17
|
+
icon: spec.Icon | None
|
|
18
|
+
name_key: str | None
|
|
19
|
+
value_key: str | None
|
|
20
|
+
color: spec.Color | None
|
|
21
|
+
caption: str | None
|
|
22
|
+
caption_description: str | None
|
|
23
|
+
caption_icon: spec.Icon | None
|
|
16
24
|
description: str | None
|
|
17
25
|
method: spec.HttpMethod
|
|
18
26
|
func: Callable | None = field(default=None)
|
openadmin/fastapi/section.py
CHANGED
openadmin/spec/__init__.py
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
from .action import Action
|
|
6
6
|
from .area_chart import AreaChart
|
|
7
7
|
from .bar_chart import BarChart
|
|
8
|
-
from .colors import Color
|
|
8
|
+
from .colors import COLORS, Color
|
|
9
9
|
from .component import Component
|
|
10
10
|
from .form import Form
|
|
11
11
|
from .http_methods import HttpMethod
|
|
@@ -13,7 +13,13 @@ from .icons import Icon
|
|
|
13
13
|
from .line_chart import LineChart
|
|
14
14
|
from .markdown import Markdown
|
|
15
15
|
from .page import Page
|
|
16
|
-
from .pie_chart import
|
|
16
|
+
from .pie_chart import (
|
|
17
|
+
PieChart,
|
|
18
|
+
PieChartComponent,
|
|
19
|
+
PieChartConfigValue,
|
|
20
|
+
PieChartData,
|
|
21
|
+
PieChartResponce,
|
|
22
|
+
)
|
|
17
23
|
from .property import Property
|
|
18
24
|
from .property_type import PropertyType
|
|
19
25
|
from .section import Section
|
|
@@ -22,25 +28,30 @@ from .stat import Stat, StatComponent, StatResponse, StatValue
|
|
|
22
28
|
from .table import Table
|
|
23
29
|
|
|
24
30
|
__all__ = [
|
|
31
|
+
"COLORS",
|
|
25
32
|
"Action",
|
|
26
33
|
"AreaChart",
|
|
27
34
|
"BarChart",
|
|
35
|
+
"Color",
|
|
28
36
|
"Component",
|
|
29
37
|
"Form",
|
|
30
38
|
"HttpMethod",
|
|
39
|
+
"Icon",
|
|
31
40
|
"LineChart",
|
|
41
|
+
"Markdown",
|
|
32
42
|
"Page",
|
|
33
43
|
"PieChart",
|
|
44
|
+
"PieChartComponent",
|
|
45
|
+
"PieChartConfigValue",
|
|
46
|
+
"PieChartData",
|
|
47
|
+
"PieChartResponce",
|
|
34
48
|
"Property",
|
|
35
49
|
"PropertyType",
|
|
36
50
|
"Section",
|
|
37
51
|
"Spec",
|
|
52
|
+
"Stat",
|
|
38
53
|
"StatComponent",
|
|
39
|
-
"Table",
|
|
40
|
-
"Markdown",
|
|
41
|
-
"Icon",
|
|
42
54
|
"StatResponse",
|
|
43
55
|
"StatValue",
|
|
44
|
-
"
|
|
45
|
-
"Color",
|
|
56
|
+
"Table",
|
|
46
57
|
]
|
openadmin/spec/action.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
#
|
|
3
3
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
4
|
|
|
5
|
-
from typing import
|
|
5
|
+
from typing import Literal
|
|
6
6
|
|
|
7
7
|
from pydantic import BaseModel, Field
|
|
8
8
|
|
|
@@ -18,6 +18,6 @@ class Action(BaseModel):
|
|
|
18
18
|
url: str
|
|
19
19
|
method: HttpMethod
|
|
20
20
|
is_hidden: bool
|
|
21
|
-
form:
|
|
22
|
-
body:
|
|
23
|
-
query:
|
|
21
|
+
form: list[Property] | None = Field(None)
|
|
22
|
+
body: list[Property] | None = Field(None)
|
|
23
|
+
query: list[Property] | None = Field(None)
|
openadmin/spec/colors.py
CHANGED
|
@@ -30,3 +30,30 @@ type Color = Literal[
|
|
|
30
30
|
"black",
|
|
31
31
|
"white",
|
|
32
32
|
]
|
|
33
|
+
|
|
34
|
+
COLORS: list[Color] = [
|
|
35
|
+
"slate",
|
|
36
|
+
"gray",
|
|
37
|
+
"zinc",
|
|
38
|
+
"neutral",
|
|
39
|
+
"stone",
|
|
40
|
+
"red",
|
|
41
|
+
"orange",
|
|
42
|
+
"amber",
|
|
43
|
+
"yellow",
|
|
44
|
+
"lime",
|
|
45
|
+
"green",
|
|
46
|
+
"emerald",
|
|
47
|
+
"teal",
|
|
48
|
+
"cyan",
|
|
49
|
+
"sky",
|
|
50
|
+
"blue",
|
|
51
|
+
"indigo",
|
|
52
|
+
"violet",
|
|
53
|
+
"purple",
|
|
54
|
+
"fuchsia",
|
|
55
|
+
"pink",
|
|
56
|
+
"rose",
|
|
57
|
+
"black",
|
|
58
|
+
"white",
|
|
59
|
+
]
|
openadmin/spec/component.py
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
#
|
|
3
3
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
4
|
|
|
5
|
-
from typing import Union
|
|
6
5
|
|
|
7
6
|
from .action import Action
|
|
8
7
|
from .area_chart import AreaChart
|
|
@@ -10,18 +9,18 @@ from .bar_chart import BarChart
|
|
|
10
9
|
from .form import Form
|
|
11
10
|
from .line_chart import LineChart
|
|
12
11
|
from .markdown import Markdown
|
|
13
|
-
from .pie_chart import
|
|
12
|
+
from .pie_chart import PieChartComponent
|
|
14
13
|
from .stat import StatComponent
|
|
15
14
|
from .table import Table
|
|
16
15
|
|
|
17
|
-
type Component =
|
|
18
|
-
StatComponent
|
|
19
|
-
Table
|
|
20
|
-
AreaChart
|
|
21
|
-
BarChart
|
|
22
|
-
LineChart
|
|
23
|
-
|
|
24
|
-
Action
|
|
25
|
-
Form
|
|
26
|
-
Markdown
|
|
27
|
-
|
|
16
|
+
type Component = (
|
|
17
|
+
StatComponent
|
|
18
|
+
| Table
|
|
19
|
+
| AreaChart
|
|
20
|
+
| BarChart
|
|
21
|
+
| LineChart
|
|
22
|
+
| PieChartComponent
|
|
23
|
+
| Action
|
|
24
|
+
| Form
|
|
25
|
+
| Markdown
|
|
26
|
+
)
|
openadmin/spec/form.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
#
|
|
3
3
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
4
|
|
|
5
|
-
from typing import
|
|
5
|
+
from typing import Literal
|
|
6
6
|
|
|
7
7
|
from pydantic import BaseModel, Field
|
|
8
8
|
|
|
@@ -18,6 +18,6 @@ class Form(BaseModel):
|
|
|
18
18
|
url: str
|
|
19
19
|
method: HttpMethod
|
|
20
20
|
is_hidden: bool
|
|
21
|
-
form:
|
|
22
|
-
body:
|
|
23
|
-
query:
|
|
21
|
+
form: list[Property] | None = Field(None)
|
|
22
|
+
body: list[Property] | None = Field(None)
|
|
23
|
+
query: list[Property] | None = Field(None)
|
openadmin/spec/markdown.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
#
|
|
3
3
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
4
|
|
|
5
|
-
from typing import
|
|
5
|
+
from typing import Literal
|
|
6
6
|
|
|
7
7
|
from pydantic import BaseModel, Field
|
|
8
8
|
|
|
@@ -17,4 +17,4 @@ class Markdown(BaseModel):
|
|
|
17
17
|
description: str | None
|
|
18
18
|
url: str
|
|
19
19
|
method: HttpMethod
|
|
20
|
-
query:
|
|
20
|
+
query: list[Property] | None = Field(None)
|
openadmin/spec/page.py
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
#
|
|
3
3
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
4
|
|
|
5
|
-
from typing import List
|
|
6
5
|
|
|
7
6
|
from pydantic import BaseModel
|
|
8
7
|
|
|
@@ -15,4 +14,4 @@ class Page(BaseModel):
|
|
|
15
14
|
name: str
|
|
16
15
|
description: str | None
|
|
17
16
|
icon: Icon | None
|
|
18
|
-
components:
|
|
17
|
+
components: list[Component]
|
openadmin/spec/pie_chart.py
CHANGED
|
@@ -2,19 +2,52 @@
|
|
|
2
2
|
#
|
|
3
3
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
4
|
|
|
5
|
-
from typing import Literal
|
|
5
|
+
from typing import Literal, NotRequired, TypedDict
|
|
6
6
|
|
|
7
7
|
from pydantic import BaseModel, Field
|
|
8
8
|
|
|
9
|
+
from .colors import Color
|
|
9
10
|
from .http_methods import HttpMethod
|
|
11
|
+
from .icons import Icon
|
|
10
12
|
from .property import Property
|
|
11
13
|
|
|
12
14
|
|
|
13
|
-
class
|
|
15
|
+
class PieChartConfigValue(TypedDict):
|
|
16
|
+
name: NotRequired[str]
|
|
17
|
+
color: NotRequired[Color]
|
|
18
|
+
icon: NotRequired[Icon]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class PieChartComponent(BaseModel):
|
|
14
22
|
type: Literal["pie-chart"]
|
|
15
23
|
id: str
|
|
16
24
|
name: str
|
|
25
|
+
config: dict[str, PieChartConfigValue] | None
|
|
26
|
+
icon: Icon | None
|
|
27
|
+
name_key: str | None
|
|
28
|
+
value_key: str | None
|
|
29
|
+
color: Color | None
|
|
17
30
|
description: str | None
|
|
31
|
+
caption: str | None
|
|
32
|
+
caption_description: str | None
|
|
33
|
+
caption_icon: Icon | None
|
|
18
34
|
url: str
|
|
19
35
|
method: HttpMethod
|
|
20
36
|
query: list[Property] | None = Field(None)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
type PieChartData = (
|
|
40
|
+
list[dict[str, int | float | str]]
|
|
41
|
+
| list[dict[Literal["name", "value"], int | float | str]]
|
|
42
|
+
| object
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class PieChartResponce(TypedDict):
|
|
47
|
+
config: NotRequired[dict[str, PieChartConfigValue]]
|
|
48
|
+
icon: NotRequired[Icon]
|
|
49
|
+
color: NotRequired[Color]
|
|
50
|
+
data: PieChartData
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
type PieChart = PieChartData | PieChartResponce
|
openadmin/spec/property.py
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
#
|
|
3
3
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
4
|
|
|
5
|
-
from typing import List
|
|
6
5
|
|
|
7
6
|
from pydantic import BaseModel, Field
|
|
8
7
|
|
|
@@ -14,4 +13,4 @@ class Property(BaseModel):
|
|
|
14
13
|
alias: str = Field(..., description="This name goes to body or form for backend")
|
|
15
14
|
type: PropertyType
|
|
16
15
|
is_required: bool
|
|
17
|
-
properties:
|
|
16
|
+
properties: list[Property] | None = Field(None)
|
openadmin/spec/section.py
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
#
|
|
3
3
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
4
|
|
|
5
|
-
from typing import List
|
|
6
5
|
|
|
7
6
|
from pydantic import BaseModel
|
|
8
7
|
|
|
@@ -15,4 +14,4 @@ class Section(BaseModel):
|
|
|
15
14
|
name: str
|
|
16
15
|
description: str | None
|
|
17
16
|
icon: Icon | None
|
|
18
|
-
pages:
|
|
17
|
+
pages: list[Page]
|
openadmin/spec/spec.py
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
#
|
|
3
3
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
4
|
|
|
5
|
-
from typing import List
|
|
6
5
|
|
|
7
6
|
from pydantic import BaseModel
|
|
8
7
|
|
|
@@ -13,4 +12,4 @@ class Spec(BaseModel):
|
|
|
13
12
|
version: str
|
|
14
13
|
name: str
|
|
15
14
|
description: str | None = None
|
|
16
|
-
sections:
|
|
15
|
+
sections: list[Section]
|
openadmin/spec/table.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
#
|
|
3
3
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
4
|
|
|
5
|
-
from typing import
|
|
5
|
+
from typing import Literal
|
|
6
6
|
|
|
7
7
|
from pydantic import BaseModel, Field
|
|
8
8
|
|
|
@@ -17,6 +17,6 @@ class Table(BaseModel):
|
|
|
17
17
|
description: str | None
|
|
18
18
|
url: str
|
|
19
19
|
method: HttpMethod
|
|
20
|
-
form:
|
|
21
|
-
body:
|
|
22
|
-
query:
|
|
20
|
+
form: list[Property] | None = Field(None)
|
|
21
|
+
body: list[Property] | None = Field(None)
|
|
22
|
+
query: list[Property] | None = Field(None)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openadmin-dev
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.4
|
|
4
4
|
Summary: Add your description here
|
|
5
5
|
Project-URL: Homepage, https://github.com/openadmin-team/openadmin-py
|
|
6
6
|
Project-URL: Issues, https://github.com/openadmin-team/openadmin-py/issues
|
|
@@ -60,16 +60,21 @@ admin = AdminPanel()
|
|
|
60
60
|
# Define a page
|
|
61
61
|
page = AdminPage("Dashboard")
|
|
62
62
|
|
|
63
|
+
|
|
63
64
|
@page.stat("Total Users")
|
|
64
65
|
async def total_users() -> Stat:
|
|
65
66
|
return Stat(value=1_024)
|
|
66
67
|
|
|
68
|
+
|
|
67
69
|
@page.table("Recent Users")
|
|
68
70
|
async def recent_users() -> Table:
|
|
69
|
-
return Table(
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
return Table(
|
|
72
|
+
data=[
|
|
73
|
+
{"id": 1, "name": "Alice", "role": "admin"},
|
|
74
|
+
{"id": 2, "name": "Bob", "role": "viewer"},
|
|
75
|
+
]
|
|
76
|
+
)
|
|
77
|
+
|
|
73
78
|
|
|
74
79
|
# Register the page and mount the panel
|
|
75
80
|
admin.include_page(page)
|
|
@@ -87,6 +92,7 @@ Display a single numeric or boolean value.
|
|
|
87
92
|
```python
|
|
88
93
|
from openadmin.types import Stat
|
|
89
94
|
|
|
95
|
+
|
|
90
96
|
@page.stat("Active Sessions")
|
|
91
97
|
async def active_sessions() -> Stat:
|
|
92
98
|
return Stat(value=42)
|
|
@@ -100,6 +106,7 @@ Paginated tables with optional search. Use the built-in dependency types to rece
|
|
|
100
106
|
from openadmin.fastapi import PaginationParamsDep, SearchQueryDep
|
|
101
107
|
from openadmin.types import Table
|
|
102
108
|
|
|
109
|
+
|
|
103
110
|
@page.table("Users")
|
|
104
111
|
async def users_table(
|
|
105
112
|
pagination: PaginationParamsDep,
|
|
@@ -117,18 +124,23 @@ Attach per-row action buttons by including `__actions__` in each row:
|
|
|
117
124
|
```python
|
|
118
125
|
from openadmin.types import Action, Table, TableRow
|
|
119
126
|
|
|
127
|
+
|
|
120
128
|
@page.table("Users")
|
|
121
129
|
async def users_table() -> Table:
|
|
122
|
-
return Table(
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
return Table(
|
|
131
|
+
data=[
|
|
132
|
+
TableRow(
|
|
133
|
+
id=1,
|
|
134
|
+
name="Alice",
|
|
135
|
+
__actions__=[
|
|
136
|
+
Action(color="danger", method="DELETE", url="/users/1", body=None),
|
|
137
|
+
Action(
|
|
138
|
+
color="info", method="POST", url="/users/1/reset", body=None
|
|
139
|
+
),
|
|
140
|
+
],
|
|
141
|
+
)
|
|
142
|
+
]
|
|
143
|
+
)
|
|
132
144
|
```
|
|
133
145
|
|
|
134
146
|
### Charts
|
|
@@ -138,6 +150,7 @@ All chart types share the same structure: a `data` list of dicts and a `config`
|
|
|
138
150
|
```python
|
|
139
151
|
from openadmin.types import BarChart, PieChart
|
|
140
152
|
|
|
153
|
+
|
|
141
154
|
@page.bar_chart("Sales by Region", "Total sales per region this quarter")
|
|
142
155
|
async def sales_chart() -> BarChart:
|
|
143
156
|
return BarChart(
|
|
@@ -148,11 +161,12 @@ async def sales_chart() -> BarChart:
|
|
|
148
161
|
config={"sales": {"label": "Sales", "color": "#6366f1"}},
|
|
149
162
|
)
|
|
150
163
|
|
|
164
|
+
|
|
151
165
|
@page.pie_chart("User Roles", "Breakdown of user roles")
|
|
152
166
|
async def roles_chart() -> PieChart:
|
|
153
167
|
return PieChart(
|
|
154
168
|
data=[
|
|
155
|
-
{"segment": "Admin",
|
|
169
|
+
{"segment": "Admin", "count": 5},
|
|
156
170
|
{"segment": "Editor", "count": 20},
|
|
157
171
|
{"segment": "Viewer", "count": 75},
|
|
158
172
|
],
|
|
@@ -178,10 +192,12 @@ Forms collect user input and submit it to your endpoint. Mark a form hidden if i
|
|
|
178
192
|
```python
|
|
179
193
|
from pydantic import BaseModel
|
|
180
194
|
|
|
195
|
+
|
|
181
196
|
class InvitePayload(BaseModel):
|
|
182
197
|
email: str
|
|
183
198
|
role: str
|
|
184
199
|
|
|
200
|
+
|
|
185
201
|
@page.form_post("Invite User", "Send an invitation email to a new user")
|
|
186
202
|
async def invite_user(payload: InvitePayload):
|
|
187
203
|
# send invite...
|
|
@@ -209,27 +225,37 @@ from openadmin.types import Stat, Table, BarChart
|
|
|
209
225
|
|
|
210
226
|
page = AdminPage("Library")
|
|
211
227
|
|
|
228
|
+
|
|
212
229
|
@page.stat("Total Books")
|
|
213
230
|
async def total_books(session: AsyncSessionDep) -> Stat:
|
|
214
231
|
result = await session.execute(select(func.count()).select_from(Book))
|
|
215
232
|
return Stat(value=result.scalar_one())
|
|
216
233
|
|
|
234
|
+
|
|
217
235
|
@page.table("Books")
|
|
218
236
|
async def books_table(
|
|
219
237
|
session: AsyncSessionDep,
|
|
220
238
|
pagination: PaginationParamsDep,
|
|
221
239
|
search: SearchQueryDep,
|
|
222
240
|
) -> Table:
|
|
223
|
-
stmt =
|
|
241
|
+
stmt = (
|
|
242
|
+
select(Book)
|
|
243
|
+
.offset(pagination.page * pagination.per_page)
|
|
244
|
+
.limit(pagination.per_page)
|
|
245
|
+
)
|
|
224
246
|
books = (await session.execute(stmt)).scalars().all()
|
|
225
247
|
return Table(data=[{"title": b.title, "year": b.published_year} for b in books])
|
|
226
248
|
|
|
249
|
+
|
|
227
250
|
@page.bar_chart("Books per Genre", "Number of books in each genre")
|
|
228
251
|
async def books_per_genre(session: AsyncSessionDep) -> BarChart:
|
|
229
|
-
rows = (
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
252
|
+
rows = (
|
|
253
|
+
await session.execute(
|
|
254
|
+
select(Genre.name, func.count().label("books"))
|
|
255
|
+
.join(BookToGenre)
|
|
256
|
+
.group_by(Genre.id)
|
|
257
|
+
)
|
|
258
|
+
).all()
|
|
233
259
|
return BarChart(
|
|
234
260
|
data=[{"genre": name, "books": count} for name, count in rows],
|
|
235
261
|
config={"books": {"label": "Books", "color": "#6366f1"}},
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
openadmin/fastapi/__init__.py,sha256=ssQtgZVSRIZfh7I2mpsj2wdlUryjPoEB3sLwDmMVv5I,269
|
|
2
2
|
openadmin/fastapi/action.py,sha256=M1U8_M3PycsxFwlErP-FoNQr6s1pJ1TO2c0qAubhcDo,395
|
|
3
|
-
openadmin/fastapi/admin_page.py,sha256=
|
|
4
|
-
openadmin/fastapi/admin_panel.py,sha256=
|
|
3
|
+
openadmin/fastapi/admin_page.py,sha256=fyAx2w6TLtvl4j8j5xcV1fRDLJ_RK2IwwCN-jH4veWM,18152
|
|
4
|
+
openadmin/fastapi/admin_panel.py,sha256=8MfPSGiH9A4n4vSby9bXNiWCktEidOjDE9rqHcM5Ha0,2747
|
|
5
5
|
openadmin/fastapi/area_chart.py,sha256=UxJHoyw6gUv35gy3OEuzewV4NUPflaLSxk_30nXmqBI,378
|
|
6
6
|
openadmin/fastapi/bar_chart.py,sha256=VeyiTZY9TUHohvYhhKtkZGHEOZvBYCR8HI2afZZR2qM,377
|
|
7
|
-
openadmin/fastapi/component.py,sha256=
|
|
7
|
+
openadmin/fastapi/component.py,sha256=wjyHZr0SB6AsR9P0o_jYfKlKpXp1HWw6n3ale6Nq8eg,495
|
|
8
8
|
openadmin/fastapi/counters.py,sha256=uv8__iZEHRivWOlTci3y07W438x6QE9UhakTmq6fOIo,308
|
|
9
9
|
openadmin/fastapi/deps.py,sha256=tckYrl059ReKMv5hVnV2URCbTmAdgaNVr0A0WVJ210Y,734
|
|
10
10
|
openadmin/fastapi/form.py,sha256=IBYdkJ_MsrOAFsmXSjMGpaiTGpSUA8JSGBxUGeDYsjE,393
|
|
@@ -12,31 +12,31 @@ openadmin/fastapi/line_chart.py,sha256=oQjom6zVrEOOduTg1dru9VnYUYV8K3Tc99C5eHfhI
|
|
|
12
12
|
openadmin/fastapi/markdown.py,sha256=vhUHLxxUjyygAMUyHuL8Y2w1IuOTpYBwUDI4Jw4xHzI,377
|
|
13
13
|
openadmin/fastapi/page_protocol.py,sha256=zMio8SamTFO6_Dxp_8_xnErTC6VEfryVtW_5jOM6oDw,265
|
|
14
14
|
openadmin/fastapi/pagination_params.py,sha256=oVI5VkYYwqpZkJBErQTCbDzGgvjRJFY0rl50rbWII5g,189
|
|
15
|
-
openadmin/fastapi/pie_chart.py,sha256=
|
|
16
|
-
openadmin/fastapi/section.py,sha256
|
|
15
|
+
openadmin/fastapi/pie_chart.py,sha256=wsjAGdkt_SbL4zTTy6PGC3R4_8b8WSHuyhNY_4I6qws,634
|
|
16
|
+
openadmin/fastapi/section.py,sha256=-L9ZbbsSkZoHX14uRdDVK6G61vjwArXtEaqWJJXC7Y8,372
|
|
17
17
|
openadmin/fastapi/stat.py,sha256=hX749_KYPnGubVA9naWxxCeyE7D1Zq5psPatb4M-6pE,429
|
|
18
18
|
openadmin/fastapi/table.py,sha256=oCl6Go_YznJerXA6vk1XxAKt5QUa4c3ASdH_pTlbOD8,374
|
|
19
19
|
openadmin/fastapi/utils.py,sha256=IPG2uSJSe8AeIW4iYSLrMx_8DoDiMr3z_dzG1Gxr4wo,5806
|
|
20
|
-
openadmin/spec/__init__.py,sha256=
|
|
21
|
-
openadmin/spec/action.py,sha256=
|
|
20
|
+
openadmin/spec/__init__.py,sha256=mrb-rWhD9I_5o1GH9Kb14UVke8nBT0s6SEZqV0BOfcE,1212
|
|
21
|
+
openadmin/spec/action.py,sha256=rrxX5IP7NzH2drIR4Jn4Eb2h8BfSL8Gj6AnP8-6-60Y,528
|
|
22
22
|
openadmin/spec/area_chart.py,sha256=3TzJHsVZtG6pmpqSG_T6z4KOAWVeNM4VRHDwU4V1A5I,423
|
|
23
23
|
openadmin/spec/bar_chart.py,sha256=63vRdmwSOlUz-DtL5n9-qxC_TL63IikiW0zWCrx0KoM,421
|
|
24
|
-
openadmin/spec/colors.py,sha256
|
|
25
|
-
openadmin/spec/component.py,sha256=
|
|
26
|
-
openadmin/spec/form.py,sha256=
|
|
24
|
+
openadmin/spec/colors.py,sha256=2mQ5wsDJNL2YKa5qZWTxU8Jo1vlaDTdvSjpTw0PbofQ,790
|
|
25
|
+
openadmin/spec/component.py,sha256=uc3dvlxEYtfbsNPknx0Wah0Go_IW9PPHBecg1BsYYoo,531
|
|
26
|
+
openadmin/spec/form.py,sha256=OLF4EILlWbBEPJEbkYOvNP0DN48qZLwSbiBK5MSdSqA,524
|
|
27
27
|
openadmin/spec/http_methods.py,sha256=gRcLLnMCHvXYyq_8T4aVmjxy_kfOAc7x8SLc3MJmAl0,192
|
|
28
28
|
openadmin/spec/icons.py,sha256=ltCrSyPuynEQzL_Kz8PyvKDwrlPiaPrNUecDGHo9bO8,38782
|
|
29
29
|
openadmin/spec/line_chart.py,sha256=IACCzgP6dUfN-MLwtYS0s2jJElxz99KAqx9y1qVhbaQ,423
|
|
30
|
-
openadmin/spec/markdown.py,sha256=
|
|
31
|
-
openadmin/spec/page.py,sha256=
|
|
32
|
-
openadmin/spec/pie_chart.py,sha256=
|
|
33
|
-
openadmin/spec/property.py,sha256=
|
|
30
|
+
openadmin/spec/markdown.py,sha256=odcvjgWYYb3p_3r3t2rAQ0A2bKhwYeQPuvjq9o24kiI,420
|
|
31
|
+
openadmin/spec/page.py,sha256=k2zomMepICs4Wc8fAJz_KgsffupKtojWKzJLNL9r0FU,312
|
|
32
|
+
openadmin/spec/pie_chart.py,sha256=3iPj7v1d2Qf38LII1LSK_MyAijan4DyESTbvshuK4Xs,1230
|
|
33
|
+
openadmin/spec/property.py,sha256=uifjcPHwI7GL63zE7pRaD3DEim6fzRy5id0xGt2lyJA,468
|
|
34
34
|
openadmin/spec/property_type.py,sha256=m1eJ7H5YIP4dhaa899Qc9BCRkZOwP_DELl6vPZB31HY,306
|
|
35
|
-
openadmin/spec/section.py,sha256=
|
|
36
|
-
openadmin/spec/spec.py,sha256=
|
|
35
|
+
openadmin/spec/section.py,sha256=nLGwfyyejWpyVDNbhPCmYqh5QxK0ep0X7Hw8nDGmC4g,295
|
|
36
|
+
openadmin/spec/spec.py,sha256=3QilIsnbJetMJn_-mxwysRccrPiI-6UTdSuxSCgneNw,270
|
|
37
37
|
openadmin/spec/stat.py,sha256=XXoxfGQUmkkjCDdpAW217Ha4OYguimjHCzyJiV--lSM,743
|
|
38
|
-
openadmin/spec/table.py,sha256=
|
|
39
|
-
openadmin_dev-0.7.
|
|
40
|
-
openadmin_dev-0.7.
|
|
41
|
-
openadmin_dev-0.7.
|
|
42
|
-
openadmin_dev-0.7.
|
|
38
|
+
openadmin/spec/table.py,sha256=juAEse_l2BzeRaQR2JIlsZH6JMB6WWdloUWbwxg4754,506
|
|
39
|
+
openadmin_dev-0.7.4.dist-info/METADATA,sha256=mkri9a9YAF_ZhFiKcQAarCWv-usEWKRxA4luIJBVUZ0,9141
|
|
40
|
+
openadmin_dev-0.7.4.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
|
|
41
|
+
openadmin_dev-0.7.4.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
|
|
42
|
+
openadmin_dev-0.7.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|