openadmin-dev 0.6.2__tar.gz → 0.7.3__tar.gz
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_dev-0.6.2 → openadmin_dev-0.7.3}/PKG-INFO +1 -1
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/examples/admin/analytics.py +3 -2
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/examples/admin/authors.py +3 -2
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/fastapi/admin_page.py +7 -1
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/fastapi/stat.py +2 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/spec/__init__.py +7 -2
- openadmin_dev-0.7.3/openadmin/spec/colors.py +32 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/spec/component.py +10 -2
- openadmin_dev-0.7.3/openadmin/spec/stat.py +36 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/pyproject.toml +1 -1
- openadmin_dev-0.6.2/openadmin/spec/stat.py +0 -20
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/.github/ISSUE_TEMPLATE/bug.md +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/.github/ISSUE_TEMPLATE/chore.md +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/.github/ISSUE_TEMPLATE/feature.md +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/.github/actions/branch-name/action.yml +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/.github/actions/dependency-cves/action.yml +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/.github/actions/format/action.yml +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/.github/actions/license/action.yml +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/.github/actions/lint/action.yml +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/.github/actions/security/action.yml +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/.github/actions/spell-check/action.yml +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/.github/actions/test/action.yml +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/.github/actions/typecheck/action.yml +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/.github/actions/unused-code/action.yml +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/.github/workflows/ci.yml +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/.github/workflows/publish.yml +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/.gitignore +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/.python-version +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/LICENSE +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/LICENSES/AGPL-3.0-or-later.txt +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/Makefile +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/README.md +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/REUSE.toml +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/docs/assets/logo.png +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/examples/__init__.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/examples/admin/__init__.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/examples/admin/books.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/examples/admin/genres.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/examples/admin/health.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/examples/admin/overview.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/examples/admin/publishers.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/examples/admin/reports.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/examples/admin/tags.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/examples/lib/__init__.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/examples/lib/database.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/examples/lib/lifespan.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/examples/lib/models.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/examples/lib/seed.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/examples/main.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/fastapi/__init__.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/fastapi/action.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/fastapi/admin_panel.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/fastapi/area_chart.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/fastapi/bar_chart.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/fastapi/component.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/fastapi/counters.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/fastapi/deps.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/fastapi/form.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/fastapi/line_chart.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/fastapi/markdown.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/fastapi/page_protocol.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/fastapi/pagination_params.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/fastapi/pie_chart.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/fastapi/section.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/fastapi/table.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/fastapi/utils.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/spec/action.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/spec/area_chart.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/spec/bar_chart.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/spec/form.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/spec/http_methods.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/spec/icons.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/spec/line_chart.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/spec/markdown.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/spec/page.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/spec/pie_chart.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/spec/property.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/spec/property_type.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/spec/section.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/spec/spec.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/openadmin/spec/table.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/tests/test_hello.py +0 -0
- {openadmin_dev-0.6.2 → openadmin_dev-0.7.3}/uv.lock +0 -0
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
from sqlalchemy import func, select
|
|
6
6
|
|
|
7
|
+
from openadmin import spec
|
|
7
8
|
from openadmin.fastapi import AdminPage
|
|
8
9
|
|
|
9
10
|
from ..lib import models
|
|
@@ -17,13 +18,13 @@ page = AdminPage(
|
|
|
17
18
|
|
|
18
19
|
|
|
19
20
|
@page.stat("Earliest Publication")
|
|
20
|
-
async def get_earliest_publication(session: AsyncSessionDep) ->
|
|
21
|
+
async def get_earliest_publication(session: AsyncSessionDep) -> spec.Stat:
|
|
21
22
|
result = await session.execute(
|
|
22
23
|
select(func.min(models.Book.published_year)).where(
|
|
23
24
|
models.Book.published_year.isnot(None)
|
|
24
25
|
)
|
|
25
26
|
)
|
|
26
|
-
return result.scalar_one_or_none() or "N/A"
|
|
27
|
+
return {"value": result.scalar_one_or_none() or "N/A", "icon": "sun-medium"}
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
@page.stat("Latest Publication")
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
from pydantic import BaseModel
|
|
6
6
|
from sqlalchemy import func, select
|
|
7
7
|
|
|
8
|
+
from openadmin import spec
|
|
8
9
|
from openadmin.fastapi import AdminPage
|
|
9
10
|
from openadmin.fastapi.deps import PageDep, SearchQueryDep
|
|
10
11
|
|
|
@@ -19,9 +20,9 @@ page = AdminPage(
|
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
@page.stat("Total Authors")
|
|
22
|
-
async def get_total_authors(session: AsyncSessionDep) ->
|
|
23
|
+
async def get_total_authors(session: AsyncSessionDep) -> spec.StatResponse:
|
|
23
24
|
result = await session.execute(select(func.count(models.Author.id)))
|
|
24
|
-
return result.scalar_one()
|
|
25
|
+
return {"value": result.scalar_one(), "icon": "sun"}
|
|
25
26
|
|
|
26
27
|
|
|
27
28
|
@page.stat("Authors with Bio")
|
|
@@ -53,9 +53,11 @@ class AdminPage:
|
|
|
53
53
|
|
|
54
54
|
if isinstance(item, Stat):
|
|
55
55
|
components.append(
|
|
56
|
-
spec.
|
|
56
|
+
spec.StatComponent(
|
|
57
57
|
type="stat",
|
|
58
58
|
id=item.id,
|
|
59
|
+
color=item.color,
|
|
60
|
+
icon=item.icon,
|
|
59
61
|
name=item.name,
|
|
60
62
|
description=item.description,
|
|
61
63
|
method=item.method,
|
|
@@ -222,6 +224,8 @@ class AdminPage:
|
|
|
222
224
|
self,
|
|
223
225
|
name: str,
|
|
224
226
|
*,
|
|
227
|
+
icon: spec.Icon | None = None,
|
|
228
|
+
color: spec.Color | None = None,
|
|
225
229
|
description: str | None = None,
|
|
226
230
|
):
|
|
227
231
|
kebab_name, unique_name = self.__get_kebab_and_unique_name(name)
|
|
@@ -229,6 +233,8 @@ class AdminPage:
|
|
|
229
233
|
item = Stat(
|
|
230
234
|
function_name=unique_name,
|
|
231
235
|
method="get",
|
|
236
|
+
color=color,
|
|
237
|
+
icon=icon,
|
|
232
238
|
name=name,
|
|
233
239
|
description=description,
|
|
234
240
|
id=kebab_name,
|
|
@@ -5,6 +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
9
|
from .component import Component
|
|
9
10
|
from .form import Form
|
|
10
11
|
from .http_methods import HttpMethod
|
|
@@ -17,7 +18,7 @@ from .property import Property
|
|
|
17
18
|
from .property_type import PropertyType
|
|
18
19
|
from .section import Section
|
|
19
20
|
from .spec import Spec
|
|
20
|
-
from .stat import Stat
|
|
21
|
+
from .stat import Stat, StatComponent, StatResponse, StatValue
|
|
21
22
|
from .table import Table
|
|
22
23
|
|
|
23
24
|
__all__ = [
|
|
@@ -34,8 +35,12 @@ __all__ = [
|
|
|
34
35
|
"PropertyType",
|
|
35
36
|
"Section",
|
|
36
37
|
"Spec",
|
|
37
|
-
"
|
|
38
|
+
"StatComponent",
|
|
38
39
|
"Table",
|
|
39
40
|
"Markdown",
|
|
40
41
|
"Icon",
|
|
42
|
+
"StatResponse",
|
|
43
|
+
"StatValue",
|
|
44
|
+
"Stat",
|
|
45
|
+
"Color",
|
|
41
46
|
]
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 OpenAdmin
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
from typing import Literal
|
|
6
|
+
|
|
7
|
+
type Color = Literal[
|
|
8
|
+
"slate",
|
|
9
|
+
"gray",
|
|
10
|
+
"zinc",
|
|
11
|
+
"neutral",
|
|
12
|
+
"stone",
|
|
13
|
+
"red",
|
|
14
|
+
"orange",
|
|
15
|
+
"amber",
|
|
16
|
+
"yellow",
|
|
17
|
+
"lime",
|
|
18
|
+
"green",
|
|
19
|
+
"emerald",
|
|
20
|
+
"teal",
|
|
21
|
+
"cyan",
|
|
22
|
+
"sky",
|
|
23
|
+
"blue",
|
|
24
|
+
"indigo",
|
|
25
|
+
"violet",
|
|
26
|
+
"purple",
|
|
27
|
+
"fuchsia",
|
|
28
|
+
"pink",
|
|
29
|
+
"rose",
|
|
30
|
+
"black",
|
|
31
|
+
"white",
|
|
32
|
+
]
|
|
@@ -11,9 +11,17 @@ from .form import Form
|
|
|
11
11
|
from .line_chart import LineChart
|
|
12
12
|
from .markdown import Markdown
|
|
13
13
|
from .pie_chart import PieChart
|
|
14
|
-
from .stat import
|
|
14
|
+
from .stat import StatComponent
|
|
15
15
|
from .table import Table
|
|
16
16
|
|
|
17
17
|
type Component = Union[
|
|
18
|
-
|
|
18
|
+
StatComponent,
|
|
19
|
+
Table,
|
|
20
|
+
AreaChart,
|
|
21
|
+
BarChart,
|
|
22
|
+
LineChart,
|
|
23
|
+
PieChart,
|
|
24
|
+
Action,
|
|
25
|
+
Form,
|
|
26
|
+
Markdown,
|
|
19
27
|
]
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2026 OpenAdmin
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
from typing import Literal, NotRequired, TypedDict
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, Field
|
|
8
|
+
|
|
9
|
+
from .colors import Color
|
|
10
|
+
from .http_methods import HttpMethod
|
|
11
|
+
from .icons import Icon
|
|
12
|
+
from .property import Property
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class StatComponent(BaseModel):
|
|
16
|
+
type: Literal["stat"]
|
|
17
|
+
id: str
|
|
18
|
+
icon: Icon | None
|
|
19
|
+
color: Color | None
|
|
20
|
+
name: str
|
|
21
|
+
description: str | None
|
|
22
|
+
url: str
|
|
23
|
+
method: HttpMethod
|
|
24
|
+
query: list[Property] | None = Field(None)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
type StatValue = str | int | float | bool | None
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class StatResponse(TypedDict):
|
|
31
|
+
value: StatValue
|
|
32
|
+
icon: NotRequired[Icon]
|
|
33
|
+
color: NotRequired[Color]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
type Stat = StatValue | StatResponse
|
|
@@ -1,20 +0,0 @@
|
|
|
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
|
-
id: str
|
|
16
|
-
name: str
|
|
17
|
-
description: str | None
|
|
18
|
-
url: str
|
|
19
|
-
method: HttpMethod
|
|
20
|
-
query: list[Property] | None = Field(None)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|