django-cfg 1.4.87__py3-none-any.whl → 1.4.89__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.
Potentially problematic release.
This version of django-cfg might be problematic. Click here for more details.
- django_cfg/__init__.py +1 -1
- django_cfg/apps/centrifugo/views/__init__.py +0 -2
- django_cfg/apps/dashboard/permissions.py +48 -0
- django_cfg/apps/dashboard/serializers/__init__.py +8 -1
- django_cfg/apps/dashboard/serializers/commands.py +29 -0
- django_cfg/apps/dashboard/services/__init__.py +2 -0
- django_cfg/{modules/django_unfold/callbacks/base.py → apps/dashboard/services/commands_security.py} +28 -90
- django_cfg/apps/dashboard/services/commands_service.py +208 -9
- django_cfg/apps/dashboard/services/overview_service.py +205 -0
- django_cfg/apps/dashboard/views/commands_views.py +92 -4
- django_cfg/apps/frontend/test_routing.py +134 -0
- django_cfg/apps/frontend/views.py +73 -28
- django_cfg/apps/urls.py +0 -1
- django_cfg/core/builders/apps_builder.py +0 -58
- django_cfg/modules/django_unfold/__init__.py +5 -24
- django_cfg/modules/django_unfold/models/__init__.py +0 -23
- django_cfg/modules/django_unfold/models/config.py +11 -65
- django_cfg/modules/django_unfold/{dashboard.py → navigation.py} +21 -152
- django_cfg/modules/django_unfold/tailwind.py +2 -4
- django_cfg/pyproject.toml +1 -1
- django_cfg/registry/third_party.py +0 -9
- django_cfg/routing/callbacks.py +1 -43
- django_cfg/static/frontend/admin/404/index.html +1 -1
- django_cfg/static/frontend/admin/404.html +1 -1
- django_cfg/static/frontend/admin/500/index.html +1 -1
- django_cfg/static/frontend/admin/_next/static/{ZJZBgOL9mO1koHrgaaLEV → 0sN9ktsgXH48ygtGSrhfu}/_buildManifest.js +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/{19430.fe7bff7372f8a256.js → 19430.c4c95603c23c17fe.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/50314-9443faa6df24aebf.js +1 -0
- django_cfg/static/frontend/admin/_next/static/chunks/94141-bc6d47f419b26b21.js +1 -0
- django_cfg/static/frontend/admin/_next/static/chunks/pages/{_app-c336f254967dd101.js → _app-c7dcd3aa616fab68.js} +6 -6
- django_cfg/static/frontend/admin/_next/static/chunks/pages/legal/{cookies-b39c7f22c066e2c6.js → cookies-97d279800f12aab4.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/pages/legal/{privacy-5aedad0cf3a4f80f.js → privacy-1d5e6cd94689247e.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/pages/legal/{security-dbd854d0d5d483e2.js → security-55e49700e7a01f5a.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/pages/legal/{terms-f3e1d2b9e5edf12f.js → terms-14c02bb2d3198352.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/pages/private/{centrifugo-22532c65971225eb.js → centrifugo-f9ecbc3ae0052a03.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/pages/private-d4ccbe1265cbd853.js +1 -0
- django_cfg/static/frontend/admin/_next/static/chunks/{webpack-da114020a6b940f5.js → webpack-5a92f81363b62aa7.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/css/3063068f0d5a8a00.css +3 -0
- django_cfg/static/frontend/admin/_next/static/media/19cfc7226ec3afaa-s.woff2 +0 -0
- django_cfg/static/frontend/admin/_next/static/media/21350d82a1f187e9-s.p.woff2 +0 -0
- django_cfg/static/frontend/admin/_next/static/media/8e9860b6e62d6359-s.woff2 +0 -0
- django_cfg/static/frontend/admin/_next/static/media/ba9851c3c22cd980-s.woff2 +0 -0
- django_cfg/static/frontend/admin/_next/static/media/c5fe6dc8356a8c31-s.woff2 +0 -0
- django_cfg/static/frontend/admin/_next/static/media/df0a9ae256c0569c-s.woff2 +0 -0
- django_cfg/static/frontend/admin/_next/static/media/e4af272ccee01ff0-s.p.woff2 +0 -0
- django_cfg/static/frontend/admin/auth/index.html +1 -1
- django_cfg/static/frontend/admin/index.html +1 -1
- django_cfg/static/frontend/admin/legal/cookies/index.html +1 -1
- django_cfg/static/frontend/admin/legal/privacy/index.html +1 -1
- django_cfg/static/frontend/admin/legal/security/index.html +1 -1
- django_cfg/static/frontend/admin/legal/terms/index.html +1 -1
- django_cfg/static/frontend/admin/private/centrifugo/index.html +1 -1
- django_cfg/static/frontend/admin/private/index.html +1 -1
- django_cfg/static/frontend/admin/private/profile/index.html +1 -1
- django_cfg/static/frontend/admin/private/ui/index.html +2 -2
- django_cfg/templates/admin/index.html +1 -1
- {django_cfg-1.4.87.dist-info → django_cfg-1.4.89.dist-info}/METADATA +1 -1
- {django_cfg-1.4.87.dist-info → django_cfg-1.4.89.dist-info}/RECORD +62 -163
- django_cfg/apps/centrifugo/static/django_cfg_centrifugo/css/dashboard.css +0 -260
- django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/live_channels.mjs +0 -313
- django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/live_testing.mjs +0 -803
- django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/main.mjs +0 -341
- django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/overview.mjs +0 -432
- django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/testing.mjs +0 -33
- django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/websocket.mjs +0 -210
- django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/channels_content.html +0 -46
- django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/live_channels_content.html +0 -123
- django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/overview_content.html +0 -45
- django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/publishes_content.html +0 -84
- django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/stat_cards.html +0 -53
- django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/system_status.html +0 -91
- django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/tab_navigation.html +0 -29
- django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/testing_tools.html +0 -415
- django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/layout/base.html +0 -61
- django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/pages/dashboard.html +0 -58
- django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/tags/connection_script.html +0 -48
- django_cfg/apps/centrifugo/templatetags/__init__.py +0 -1
- django_cfg/apps/centrifugo/templatetags/centrifugo_tags.py +0 -81
- django_cfg/apps/centrifugo/urls_admin.py +0 -20
- django_cfg/apps/centrifugo/views/dashboard.py +0 -28
- django_cfg/modules/django_dashboard/__init__.py +0 -23
- django_cfg/modules/django_dashboard/components.py +0 -312
- django_cfg/modules/django_dashboard/debug.py +0 -174
- django_cfg/modules/django_dashboard/management/__init__.py +0 -0
- django_cfg/modules/django_dashboard/management/commands/__init__.py +0 -0
- django_cfg/modules/django_dashboard/management/commands/debug_dashboard.py +0 -109
- django_cfg/modules/django_dashboard/sections/__init__.py +0 -1
- django_cfg/modules/django_dashboard/sections/base.py +0 -129
- django_cfg/modules/django_dashboard/sections/commands.py +0 -33
- django_cfg/modules/django_dashboard/sections/documentation.py +0 -393
- django_cfg/modules/django_dashboard/sections/overview.py +0 -398
- django_cfg/modules/django_dashboard/sections/stats.py +0 -48
- django_cfg/modules/django_dashboard/sections/system.py +0 -74
- django_cfg/modules/django_dashboard/sections/widgets.py +0 -222
- django_cfg/modules/django_unfold/callbacks/__init__.py +0 -9
- django_cfg/modules/django_unfold/callbacks/actions.py +0 -51
- django_cfg/modules/django_unfold/callbacks/apizones.py +0 -122
- django_cfg/modules/django_unfold/callbacks/charts.py +0 -223
- django_cfg/modules/django_unfold/callbacks/commands.py +0 -40
- django_cfg/modules/django_unfold/callbacks/main.py +0 -322
- django_cfg/modules/django_unfold/callbacks/statistics.py +0 -240
- django_cfg/modules/django_unfold/callbacks/system.py +0 -180
- django_cfg/modules/django_unfold/callbacks/users.py +0 -65
- django_cfg/modules/django_unfold/models/dashboard.py +0 -207
- django_cfg/modules/django_unfold/models/tabs.py +0 -26
- django_cfg/modules/django_unfold/models.py +0 -98
- django_cfg/modules/django_unfold/templates/unfold/helpers/app_list.html +0 -102
- django_cfg/static/frontend/admin/_next/static/chunks/23004-faae121bbfecc163.js +0 -1
- django_cfg/static/frontend/admin/_next/static/chunks/50314-48bd5701f62faf27.js +0 -1
- django_cfg/static/frontend/admin/_next/static/chunks/pages/private-fe9faa86ecdb0ce6.js +0 -1
- django_cfg/static/frontend/admin/_next/static/css/5f9a37b6e6a72303.css +0 -3
- django_cfg/static/frontend/admin/_next/static/media/438aa629764e75f3-s.woff2 +0 -0
- django_cfg/static/frontend/admin/_next/static/media/4c9affa5bc8f420e-s.p.woff2 +0 -0
- django_cfg/static/frontend/admin/_next/static/media/51251f8b9793cdb3-s.woff2 +0 -0
- django_cfg/static/frontend/admin/_next/static/media/875ae681bfde4580-s.p.woff2 +0 -0
- django_cfg/static/frontend/admin/_next/static/media/cc978ac5ee68c2b6-s.woff2 +0 -0
- django_cfg/static/frontend/admin/_next/static/media/e857b654a2caa584-s.woff2 +0 -0
- django_cfg/templates/admin/sections/commands_section.html +0 -5
- django_cfg/templates/admin/sections/documentation_section.html +0 -5
- django_cfg/templates/admin/sections/overview_section.html +0 -5
- django_cfg/templates/admin/sections/stats_section.html +0 -5
- django_cfg/templates/admin/sections/system_section.html +0 -5
- django_cfg/templates/admin/sections/widgets_section.html +0 -11
- django_cfg/templates/admin_old/components/action_grid.html +0 -49
- django_cfg/templates/admin_old/components/card.html +0 -50
- django_cfg/templates/admin_old/components/data_table.html +0 -67
- django_cfg/templates/admin_old/components/metric_card.html +0 -39
- django_cfg/templates/admin_old/components/modal.html +0 -58
- django_cfg/templates/admin_old/components/progress_bar.html +0 -20
- django_cfg/templates/admin_old/components/section_header.html +0 -26
- django_cfg/templates/admin_old/components/stat_item.html +0 -32
- django_cfg/templates/admin_old/components/stats_grid.html +0 -72
- django_cfg/templates/admin_old/components/status_badge.html +0 -28
- django_cfg/templates/admin_old/components/user_avatar.html +0 -27
- django_cfg/templates/admin_old/constance/change_list.html +0 -74
- django_cfg/templates/admin_old/constance/includes/default_value.html +0 -24
- django_cfg/templates/admin_old/constance/includes/fieldset_header.html +0 -15
- django_cfg/templates/admin_old/constance/includes/results_list.html +0 -16
- django_cfg/templates/admin_old/constance/includes/setting_row.html +0 -50
- django_cfg/templates/admin_old/constance/includes/table_headers.html +0 -10
- django_cfg/templates/admin_old/examples/component_class_example.html +0 -156
- django_cfg/templates/admin_old/import_export/change_list_export.html +0 -24
- django_cfg/templates/admin_old/import_export/change_list_import.html +0 -24
- django_cfg/templates/admin_old/import_export/change_list_import_export.html +0 -34
- django_cfg/templates/admin_old/index.html +0 -80
- django_cfg/templates/admin_old/index_new.html +0 -119
- django_cfg/templates/admin_old/layouts/base_dashboard.html +0 -62
- django_cfg/templates/admin_old/layouts/dashboard_with_tabs.html +0 -176
- django_cfg/templates/admin_old/sections/commands_section.html +0 -549
- django_cfg/templates/admin_old/sections/documentation_section.html +0 -152
- django_cfg/templates/admin_old/sections/overview_section.html +0 -112
- django_cfg/templates/admin_old/sections/stats_section.html +0 -35
- django_cfg/templates/admin_old/sections/system_section.html +0 -99
- django_cfg/templates/admin_old/sections/widgets_section.html +0 -129
- django_cfg/templates/admin_old/snippets/components/activity_tracker.html +0 -70
- django_cfg/templates/admin_old/snippets/components/charts_section.html +0 -113
- django_cfg/templates/admin_old/snippets/components/django_commands.html +0 -270
- django_cfg/templates/admin_old/snippets/components/quick_actions.html +0 -66
- django_cfg/templates/admin_old/snippets/components/recent_activity_improved.html +0 -25
- django_cfg/templates/admin_old/snippets/components/recent_users_table.html +0 -102
- django_cfg/templates/admin_old/snippets/components/stats_cards.html +0 -4
- django_cfg/templates/admin_old/snippets/components/stats_tiles.html +0 -92
- django_cfg/templates/admin_old/snippets/components/system_health.html +0 -22
- django_cfg/templates/admin_old/snippets/components/system_metrics.html +0 -199
- django_cfg/templates/admin_old/snippets/components/user_permissions.html +0 -57
- django_cfg/templates/admin_old/snippets/tabs/app_stats_tab.html +0 -201
- django_cfg/templates/admin_old/snippets/tabs/commands_tab.html +0 -114
- django_cfg/templates/admin_old/snippets/tabs/documentation_tab.html +0 -42
- django_cfg/templates/admin_old/snippets/tabs/overview_tab.html +0 -116
- django_cfg/templates/admin_old/snippets/tabs/stats_tab.html +0 -89
- django_cfg/templates/admin_old/snippets/tabs/users_tab.html +0 -51
- django_cfg/templates/admin_old/snippets/tabs/widgets_tab.html +0 -38
- django_cfg/templates/admin_old/snippets/zones/zones_table.html +0 -176
- /django_cfg/static/frontend/admin/_next/static/{ZJZBgOL9mO1koHrgaaLEV → 0sN9ktsgXH48ygtGSrhfu}/_ssgManifest.js +0 -0
- {django_cfg-1.4.87.dist-info → django_cfg-1.4.89.dist-info}/WHEEL +0 -0
- {django_cfg-1.4.87.dist-info → django_cfg-1.4.89.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.4.87.dist-info → django_cfg-1.4.89.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Django CFG Unfold Module
|
|
3
3
|
|
|
4
|
-
Provides complete Unfold admin interface integration with
|
|
5
|
-
navigation
|
|
4
|
+
Provides complete Unfold admin interface integration with
|
|
5
|
+
navigation and theming support.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
from .callbacks import UnfoldCallbacks
|
|
9
|
-
from .dashboard import DashboardManager, get_dashboard_manager
|
|
10
8
|
from .models import *
|
|
9
|
+
from .navigation import NavigationManager, get_navigation_manager
|
|
11
10
|
from .system_monitor import SystemMonitor
|
|
12
11
|
from .tailwind import get_css_variables, get_unfold_colors
|
|
13
12
|
|
|
@@ -20,19 +19,10 @@ def get_system_monitor() -> SystemMonitor:
|
|
|
20
19
|
globals()['_system_monitor'] = SystemMonitor()
|
|
21
20
|
return globals()['_system_monitor']
|
|
22
21
|
|
|
23
|
-
def get_unfold_callbacks() -> UnfoldCallbacks:
|
|
24
|
-
"""Get the global unfold callbacks instance."""
|
|
25
|
-
global _unfold_callbacks
|
|
26
|
-
if '_unfold_callbacks' not in globals():
|
|
27
|
-
globals()['_unfold_callbacks'] = UnfoldCallbacks()
|
|
28
|
-
return globals()['_unfold_callbacks']
|
|
29
|
-
|
|
30
22
|
# Export main components
|
|
31
23
|
__all__ = [
|
|
32
|
-
'
|
|
33
|
-
'
|
|
34
|
-
'UnfoldCallbacks',
|
|
35
|
-
'get_unfold_callbacks',
|
|
24
|
+
'NavigationManager',
|
|
25
|
+
'get_navigation_manager',
|
|
36
26
|
'SystemMonitor',
|
|
37
27
|
'get_system_monitor',
|
|
38
28
|
'get_unfold_colors',
|
|
@@ -48,15 +38,6 @@ __all__ = [
|
|
|
48
38
|
'NavigationSection',
|
|
49
39
|
'NavigationItemType',
|
|
50
40
|
'SiteDropdownItem',
|
|
51
|
-
'StatCard',
|
|
52
|
-
'SystemHealthItem',
|
|
53
|
-
'QuickAction',
|
|
54
|
-
'DashboardWidget',
|
|
55
|
-
'DashboardData',
|
|
56
|
-
'ChartDataset',
|
|
57
|
-
'ChartData',
|
|
58
|
-
'TabConfiguration',
|
|
59
|
-
'TabItem',
|
|
60
41
|
]
|
|
61
42
|
|
|
62
43
|
# Version info
|
|
@@ -12,18 +12,8 @@ from .config import (
|
|
|
12
12
|
UnfoldTheme,
|
|
13
13
|
UnfoldThemeConfig,
|
|
14
14
|
)
|
|
15
|
-
from .dashboard import (
|
|
16
|
-
ChartData,
|
|
17
|
-
ChartDataset,
|
|
18
|
-
DashboardData,
|
|
19
|
-
DashboardWidget,
|
|
20
|
-
QuickAction,
|
|
21
|
-
StatCard,
|
|
22
|
-
SystemHealthItem,
|
|
23
|
-
)
|
|
24
15
|
from .dropdown import SiteDropdownItem
|
|
25
16
|
from .navigation import NavigationItem, NavigationItemType, NavigationSection
|
|
26
|
-
from .tabs import TabConfiguration, TabItem
|
|
27
17
|
|
|
28
18
|
__all__ = [
|
|
29
19
|
# Config models
|
|
@@ -41,17 +31,4 @@ __all__ = [
|
|
|
41
31
|
|
|
42
32
|
# Dropdown models
|
|
43
33
|
'SiteDropdownItem',
|
|
44
|
-
|
|
45
|
-
# Dashboard models
|
|
46
|
-
'StatCard',
|
|
47
|
-
'SystemHealthItem',
|
|
48
|
-
'QuickAction',
|
|
49
|
-
'DashboardWidget',
|
|
50
|
-
'DashboardData',
|
|
51
|
-
'ChartDataset',
|
|
52
|
-
'ChartData',
|
|
53
|
-
|
|
54
|
-
# Tab models
|
|
55
|
-
'TabConfiguration',
|
|
56
|
-
'TabItem',
|
|
57
34
|
]
|
|
@@ -13,7 +13,6 @@ from django_cfg.modules.django_admin.icons import Icons
|
|
|
13
13
|
|
|
14
14
|
from .dropdown import SiteDropdownItem
|
|
15
15
|
from .navigation import NavigationSection
|
|
16
|
-
from .tabs import TabConfiguration
|
|
17
16
|
|
|
18
17
|
logger = logging.getLogger(__name__)
|
|
19
18
|
|
|
@@ -61,7 +60,6 @@ class UnfoldTheme(BaseModel):
|
|
|
61
60
|
sidebar: UnfoldSidebar = Field(default_factory=UnfoldSidebar, description="Sidebar config")
|
|
62
61
|
|
|
63
62
|
# Dashboard
|
|
64
|
-
dashboard_callback: Optional[str] = Field(None, description="Dashboard callback function")
|
|
65
63
|
environment_callback: Optional[str] = Field(None, description="Environment callback function")
|
|
66
64
|
|
|
67
65
|
# Navigation
|
|
@@ -115,11 +113,11 @@ class UnfoldTheme(BaseModel):
|
|
|
115
113
|
# Project has custom navigation - add it first
|
|
116
114
|
nav_items.extend([group.to_dict() for group in self.navigation])
|
|
117
115
|
|
|
118
|
-
# Add default navigation from
|
|
116
|
+
# Add default navigation from navigation manager
|
|
119
117
|
try:
|
|
120
|
-
from ..
|
|
121
|
-
|
|
122
|
-
default_nav_items =
|
|
118
|
+
from ..navigation import NavigationManager
|
|
119
|
+
nav_manager = NavigationManager()
|
|
120
|
+
default_nav_items = nav_manager.get_navigation_config()
|
|
123
121
|
nav_items.extend(default_nav_items)
|
|
124
122
|
except ImportError:
|
|
125
123
|
pass
|
|
@@ -140,10 +138,6 @@ class UnfoldTheme(BaseModel):
|
|
|
140
138
|
if self.site_dropdown:
|
|
141
139
|
settings["SITE_DROPDOWN"] = [item.to_dict() for item in self.site_dropdown]
|
|
142
140
|
|
|
143
|
-
# Dashboard callback
|
|
144
|
-
if self.dashboard_callback:
|
|
145
|
-
settings["DASHBOARD_CALLBACK"] = self.dashboard_callback
|
|
146
|
-
|
|
147
141
|
# Environment callback
|
|
148
142
|
if self.environment_callback:
|
|
149
143
|
settings["ENVIRONMENT_CALLBACK"] = self.environment_callback
|
|
@@ -224,11 +218,6 @@ class UnfoldConfig(BaseModel):
|
|
|
224
218
|
description="Enable custom dashboard"
|
|
225
219
|
)
|
|
226
220
|
|
|
227
|
-
dashboard_callback: Optional[str] = Field(
|
|
228
|
-
default="django_cfg.routing.callbacks.dashboard_callback",
|
|
229
|
-
description="Dashboard callback function path"
|
|
230
|
-
)
|
|
231
|
-
|
|
232
221
|
environment_callback: Optional[str] = Field(
|
|
233
222
|
default="django_cfg.routing.callbacks.environment_callback",
|
|
234
223
|
description="Environment callback function path"
|
|
@@ -290,12 +279,6 @@ class UnfoldConfig(BaseModel):
|
|
|
290
279
|
description="Site dropdown menu items (legacy)"
|
|
291
280
|
)
|
|
292
281
|
|
|
293
|
-
# Tab configurations
|
|
294
|
-
tab_configurations: List[Dict[str, Any]] = Field(
|
|
295
|
-
default_factory=list,
|
|
296
|
-
description="Tab configurations for admin"
|
|
297
|
-
)
|
|
298
|
-
|
|
299
282
|
@field_validator('theme')
|
|
300
283
|
@classmethod
|
|
301
284
|
def validate_theme(cls, v: Optional[str]) -> Optional[str]:
|
|
@@ -441,9 +424,6 @@ class UnfoldConfig(BaseModel):
|
|
|
441
424
|
}
|
|
442
425
|
|
|
443
426
|
# Add callbacks if configured
|
|
444
|
-
if self.dashboard_callback:
|
|
445
|
-
unfold_settings["DASHBOARD_CALLBACK"] = self.dashboard_callback
|
|
446
|
-
|
|
447
427
|
if self.environment_callback:
|
|
448
428
|
unfold_settings["ENVIRONMENT"] = self.environment_callback
|
|
449
429
|
|
|
@@ -459,11 +439,11 @@ class UnfoldConfig(BaseModel):
|
|
|
459
439
|
"""Generate navigation - called when Django is ready, not during settings init."""
|
|
460
440
|
nav_items = []
|
|
461
441
|
|
|
462
|
-
# Get default navigation from
|
|
442
|
+
# Get default navigation from navigation manager first
|
|
463
443
|
try:
|
|
464
|
-
from ..
|
|
465
|
-
|
|
466
|
-
nav_items =
|
|
444
|
+
from ..navigation import NavigationManager
|
|
445
|
+
nav_manager = NavigationManager()
|
|
446
|
+
nav_items = nav_manager.get_navigation_config()
|
|
467
447
|
except Exception:
|
|
468
448
|
pass
|
|
469
449
|
|
|
@@ -514,10 +494,10 @@ class UnfoldConfig(BaseModel):
|
|
|
514
494
|
# Add site dropdown - combine default from dashboard + project dropdown
|
|
515
495
|
dropdown_items = []
|
|
516
496
|
|
|
517
|
-
# First add default dropdown
|
|
497
|
+
# First add default dropdown items
|
|
518
498
|
try:
|
|
519
|
-
from
|
|
520
|
-
dropdown_items.extend(
|
|
499
|
+
from django_cfg.config import get_default_dropdown_items
|
|
500
|
+
dropdown_items.extend([item.to_dict() for item in get_default_dropdown_items()])
|
|
521
501
|
except (ImportError, Exception):
|
|
522
502
|
pass
|
|
523
503
|
|
|
@@ -530,10 +510,6 @@ class UnfoldConfig(BaseModel):
|
|
|
530
510
|
if dropdown_items:
|
|
531
511
|
unfold_settings["SITE_DROPDOWN"] = dropdown_items
|
|
532
512
|
|
|
533
|
-
# Add tabs if configured
|
|
534
|
-
if self.tab_configurations:
|
|
535
|
-
unfold_settings["TABS"] = self.tab_configurations
|
|
536
|
-
|
|
537
513
|
# Command interface - Enhanced for better UX
|
|
538
514
|
unfold_settings["COMMAND"] = {
|
|
539
515
|
"search_models": True,
|
|
@@ -586,7 +562,6 @@ class UnfoldDashboardConfig(BaseModel):
|
|
|
586
562
|
show_theme_switcher: bool = Field(default=True, description="Show theme switcher (requires theme=None)")
|
|
587
563
|
|
|
588
564
|
# Callbacks
|
|
589
|
-
dashboard_callback: Optional[str] = Field(None, description="Dashboard callback path")
|
|
590
565
|
environment_callback: Optional[str] = Field(None, description="Environment callback path")
|
|
591
566
|
|
|
592
567
|
# Navigation configuration
|
|
@@ -601,12 +576,6 @@ class UnfoldDashboardConfig(BaseModel):
|
|
|
601
576
|
description="Site dropdown items"
|
|
602
577
|
)
|
|
603
578
|
|
|
604
|
-
# Tab configurations
|
|
605
|
-
tab_configurations: List[TabConfiguration] = Field(
|
|
606
|
-
default_factory=list,
|
|
607
|
-
description="Tab configurations"
|
|
608
|
-
)
|
|
609
|
-
|
|
610
579
|
def to_unfold_dict(self) -> Dict[str, Any]:
|
|
611
580
|
"""Convert to Unfold configuration dictionary."""
|
|
612
581
|
base_config = {
|
|
@@ -630,9 +599,6 @@ class UnfoldDashboardConfig(BaseModel):
|
|
|
630
599
|
base_config["THEME"] = self.theme
|
|
631
600
|
|
|
632
601
|
# Add callbacks if configured
|
|
633
|
-
if self.dashboard_callback:
|
|
634
|
-
base_config["DASHBOARD_CALLBACK"] = self.dashboard_callback
|
|
635
|
-
|
|
636
602
|
if self.environment_callback:
|
|
637
603
|
base_config["ENVIRONMENT"] = self.environment_callback
|
|
638
604
|
|
|
@@ -653,24 +619,4 @@ class UnfoldDashboardConfig(BaseModel):
|
|
|
653
619
|
if self.site_dropdown_items:
|
|
654
620
|
base_config["SITE_DROPDOWN"] = [item.to_dict() for item in self.site_dropdown_items]
|
|
655
621
|
|
|
656
|
-
# Convert tabs
|
|
657
|
-
if self.tab_configurations:
|
|
658
|
-
tabs = []
|
|
659
|
-
for tab in self.tab_configurations:
|
|
660
|
-
tab_items = []
|
|
661
|
-
for item in tab.items:
|
|
662
|
-
tab_item = {
|
|
663
|
-
"title": item.title,
|
|
664
|
-
"link": item.get_link_for_unfold() if hasattr(item, 'get_link_for_unfold') else item.link,
|
|
665
|
-
}
|
|
666
|
-
if item.permission:
|
|
667
|
-
tab_item["permission"] = item.permission
|
|
668
|
-
tab_items.append(tab_item)
|
|
669
|
-
|
|
670
|
-
tabs.append({
|
|
671
|
-
"models": tab.models,
|
|
672
|
-
"items": tab_items,
|
|
673
|
-
})
|
|
674
|
-
base_config["TABS"] = tabs
|
|
675
|
-
|
|
676
622
|
return base_config
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
2
|
+
Default Navigation Configuration for Django CFG Unfold
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
based on the working configuration from the old version.
|
|
4
|
+
Provides default navigation sections based on enabled django-cfg modules.
|
|
6
5
|
"""
|
|
7
6
|
|
|
8
7
|
from typing import Any, Dict, List
|
|
@@ -10,21 +9,21 @@ from typing import Any, Dict, List
|
|
|
10
9
|
from django.urls import reverse_lazy
|
|
11
10
|
|
|
12
11
|
from django_cfg.modules.django_admin.icons import Icons
|
|
12
|
+
from django_cfg.modules.base import BaseCfgModule
|
|
13
13
|
|
|
14
|
-
from ..base import BaseCfgModule
|
|
15
|
-
from .models.dashboard import StatCard, StatsCardsWidget
|
|
16
14
|
from .models.navigation import NavigationItem, NavigationSection
|
|
17
15
|
|
|
18
16
|
|
|
19
|
-
class
|
|
17
|
+
class NavigationManager(BaseCfgModule):
|
|
20
18
|
"""
|
|
21
|
-
|
|
19
|
+
Navigation configuration manager for Unfold.
|
|
20
|
+
|
|
21
|
+
Generates default navigation sections based on enabled django-cfg modules.
|
|
22
22
|
"""
|
|
23
23
|
|
|
24
24
|
def __init__(self, config=None):
|
|
25
|
-
"""Initialize
|
|
25
|
+
"""Initialize navigation manager."""
|
|
26
26
|
super().__init__()
|
|
27
|
-
# Lazy load config to avoid circular import during settings generation
|
|
28
27
|
self._config = config
|
|
29
28
|
self._config_loaded = config is not None
|
|
30
29
|
|
|
@@ -35,23 +34,11 @@ class DashboardManager(BaseCfgModule):
|
|
|
35
34
|
try:
|
|
36
35
|
self._config = self.get_config()
|
|
37
36
|
except Exception:
|
|
38
|
-
# Config cannot be loaded (e.g., during settings generation)
|
|
39
|
-
# Set to None and mark as loaded to avoid repeated attempts
|
|
40
37
|
self._config = None
|
|
41
38
|
finally:
|
|
42
39
|
self._config_loaded = True
|
|
43
40
|
return self._config
|
|
44
41
|
|
|
45
|
-
@staticmethod
|
|
46
|
-
def _get_default_dropdown_items() -> List[Dict[str, Any]]:
|
|
47
|
-
"""Get default dropdown menu items for Unfold admin (lazy import to avoid circular imports)."""
|
|
48
|
-
from django_cfg.config import get_default_dropdown_items
|
|
49
|
-
dropdown_items = get_default_dropdown_items()
|
|
50
|
-
|
|
51
|
-
# Convert SiteDropdownItem objects to dictionaries for Unfold
|
|
52
|
-
return [item.to_dict() for item in dropdown_items]
|
|
53
|
-
|
|
54
|
-
|
|
55
42
|
def get_navigation_config(self) -> List[Dict[str, Any]]:
|
|
56
43
|
"""Get complete default navigation configuration for Unfold sidebar."""
|
|
57
44
|
navigation_sections = [
|
|
@@ -76,11 +63,12 @@ class DashboardManager(BaseCfgModule):
|
|
|
76
63
|
title="Centrifugo",
|
|
77
64
|
separator=True,
|
|
78
65
|
collapsible=True,
|
|
79
|
-
items=[
|
|
80
|
-
|
|
81
|
-
|
|
66
|
+
items=[
|
|
67
|
+
NavigationItem(title="Dashboard", icon=Icons.MONITOR_HEART, link="/cfg/admin/private/centrifugo"),
|
|
68
|
+
NavigationItem(title="Logs", icon=Icons.LIST_ALT, link=str(reverse_lazy("admin:django_cfg_centrifugo_centrifugolog_changelist"))),
|
|
69
|
+
]
|
|
70
|
+
)
|
|
82
71
|
)
|
|
83
|
-
)
|
|
84
72
|
|
|
85
73
|
# Add Operations section (System & Monitoring tools)
|
|
86
74
|
operations_items = []
|
|
@@ -217,131 +205,12 @@ class DashboardManager(BaseCfgModule):
|
|
|
217
205
|
return [section.to_dict() for section in navigation_sections]
|
|
218
206
|
|
|
219
207
|
|
|
220
|
-
|
|
221
|
-
def get_unfold_config(self) -> Dict[str, Any]:
|
|
222
|
-
"""Get complete Unfold configuration based on working old version."""
|
|
223
|
-
return {
|
|
224
|
-
# Site branding and appearance
|
|
225
|
-
"SITE_TITLE": "Admin",
|
|
226
|
-
"SITE_HEADER": "Admin",
|
|
227
|
-
"SITE_SUBHEADER": "",
|
|
228
|
-
"SITE_URL": "/",
|
|
229
|
-
"SITE_SYMBOL": "dashboard",
|
|
230
|
-
|
|
231
|
-
# UI visibility controls
|
|
232
|
-
"SHOW_HISTORY": True,
|
|
233
|
-
"SHOW_VIEW_ON_SITE": True,
|
|
234
|
-
"SHOW_BACK_BUTTON": False,
|
|
235
|
-
|
|
236
|
-
# Dashboard callback
|
|
237
|
-
"DASHBOARD_CALLBACK": "api.dashboard.callbacks.main_dashboard_callback",
|
|
238
|
-
|
|
239
|
-
# Theme configuration
|
|
240
|
-
"THEME": None, # Auto-detect or force "dark"/"light"
|
|
241
|
-
|
|
242
|
-
# Login page customization
|
|
243
|
-
"LOGIN": {
|
|
244
|
-
"redirect_after": lambda request: "/admin/",
|
|
245
|
-
},
|
|
246
|
-
|
|
247
|
-
# Design system
|
|
248
|
-
"BORDER_RADIUS": "8px",
|
|
249
|
-
# COLORS removed - use UnfoldConfig.get_color_scheme() instead
|
|
250
|
-
|
|
251
|
-
# Sidebar navigation - KEY STRUCTURE!
|
|
252
|
-
"SIDEBAR": {
|
|
253
|
-
"show_search": True,
|
|
254
|
-
"command_search": True,
|
|
255
|
-
"show_all_applications": True,
|
|
256
|
-
"navigation": self.get_navigation_config(),
|
|
257
|
-
},
|
|
258
|
-
|
|
259
|
-
# Site dropdown menu - handled by config.py to allow extending
|
|
260
|
-
# "SITE_DROPDOWN": self._get_default_dropdown_items(),
|
|
261
|
-
|
|
262
|
-
# Command interface
|
|
263
|
-
"COMMAND": {
|
|
264
|
-
"search_models": True,
|
|
265
|
-
"show_history": True,
|
|
266
|
-
},
|
|
267
|
-
|
|
268
|
-
# Multi-language support - DISABLED
|
|
269
|
-
"SHOW_LANGUAGES": False,
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
def get_widgets_config(self) -> List[Dict[str, Any]]:
|
|
273
|
-
"""Get dashboard widgets configuration using Pydantic models."""
|
|
274
|
-
widgets = []
|
|
275
|
-
|
|
276
|
-
# Create system overview widget with StatCard models
|
|
277
|
-
system_overview_widget = StatsCardsWidget(
|
|
278
|
-
title="System Overview",
|
|
279
|
-
cards=[
|
|
280
|
-
StatCard(
|
|
281
|
-
title="CPU Usage",
|
|
282
|
-
value="{{ cpu_percent }}%",
|
|
283
|
-
icon=Icons.MEMORY,
|
|
284
|
-
color="blue",
|
|
285
|
-
),
|
|
286
|
-
StatCard(
|
|
287
|
-
title="Memory Usage",
|
|
288
|
-
value="{{ memory_percent }}%",
|
|
289
|
-
icon=Icons.STORAGE,
|
|
290
|
-
color="green",
|
|
291
|
-
),
|
|
292
|
-
StatCard(
|
|
293
|
-
title="Disk Usage",
|
|
294
|
-
value="{{ disk_percent }}%",
|
|
295
|
-
icon=Icons.FOLDER,
|
|
296
|
-
color="orange",
|
|
297
|
-
),
|
|
298
|
-
]
|
|
299
|
-
)
|
|
300
|
-
widgets.append(system_overview_widget.to_dict())
|
|
301
|
-
|
|
302
|
-
# Add Centrifugo monitoring widget if enabled
|
|
303
|
-
if self.is_centrifugo_enabled():
|
|
304
|
-
centrifugo_monitoring_widget = StatsCardsWidget(
|
|
305
|
-
title="Centrifugo Monitoring",
|
|
306
|
-
cards=[
|
|
307
|
-
StatCard(
|
|
308
|
-
title="Total Publishes",
|
|
309
|
-
value="{{ centrifugo_total_publishes }}",
|
|
310
|
-
icon=Icons.API,
|
|
311
|
-
color="blue",
|
|
312
|
-
),
|
|
313
|
-
StatCard(
|
|
314
|
-
title="Success Rate",
|
|
315
|
-
value="{{ centrifugo_success_rate }}%",
|
|
316
|
-
icon=Icons.CHECK_CIRCLE,
|
|
317
|
-
color="green",
|
|
318
|
-
),
|
|
319
|
-
StatCard(
|
|
320
|
-
title="Avg Duration",
|
|
321
|
-
value="{{ centrifugo_avg_duration }}ms",
|
|
322
|
-
icon=Icons.SPEED,
|
|
323
|
-
color="purple",
|
|
324
|
-
),
|
|
325
|
-
StatCard(
|
|
326
|
-
title="Failed Publishes",
|
|
327
|
-
value="{{ centrifugo_failed_publishes }}",
|
|
328
|
-
icon=Icons.ERROR,
|
|
329
|
-
color="red",
|
|
330
|
-
),
|
|
331
|
-
]
|
|
332
|
-
)
|
|
333
|
-
widgets.append(centrifugo_monitoring_widget.to_dict())
|
|
334
|
-
|
|
335
|
-
# Convert to dictionaries for Unfold
|
|
336
|
-
return widgets
|
|
337
|
-
|
|
338
|
-
|
|
339
208
|
# Lazy initialization to avoid circular imports
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
def
|
|
343
|
-
"""Get the global
|
|
344
|
-
global
|
|
345
|
-
if
|
|
346
|
-
|
|
347
|
-
return
|
|
209
|
+
_navigation_manager = None
|
|
210
|
+
|
|
211
|
+
def get_navigation_manager() -> NavigationManager:
|
|
212
|
+
"""Get the global navigation manager instance."""
|
|
213
|
+
global _navigation_manager
|
|
214
|
+
if _navigation_manager is None:
|
|
215
|
+
_navigation_manager = NavigationManager()
|
|
216
|
+
return _navigation_manager
|
|
@@ -147,9 +147,8 @@ def get_css_variables() -> str:
|
|
|
147
147
|
"""
|
|
148
148
|
Get CSS variables for semantic colors matching Next.js UI package.
|
|
149
149
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
and is kept for backward compatibility.
|
|
150
|
+
This function provides base color definitions for the Unfold admin interface.
|
|
151
|
+
Color variables are defined in OKLCH format for proper color-mix() support.
|
|
153
152
|
|
|
154
153
|
Returns:
|
|
155
154
|
str: CSS variables as string
|
|
@@ -157,7 +156,6 @@ def get_css_variables() -> str:
|
|
|
157
156
|
return """
|
|
158
157
|
/* ============================================== */
|
|
159
158
|
/* CSS Variables - Base Color Definitions */
|
|
160
|
-
/* NOTE: Background overrides in skeleton.html */
|
|
161
159
|
/* ============================================== */
|
|
162
160
|
|
|
163
161
|
/* Tailwind Dark Mode Class Support */
|
django_cfg/pyproject.toml
CHANGED
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "django-cfg"
|
|
7
|
-
version = "1.4.
|
|
7
|
+
version = "1.4.89"
|
|
8
8
|
description = "Django AI framework with built-in agents, type-safe Pydantic v2 configuration, and 8 enterprise apps. Replace settings.py, validate at startup, 90% less code. Production-ready AI workflows for Django."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
keywords = [ "django", "configuration", "pydantic", "settings", "type-safety", "pydantic-settings", "django-environ", "startup-validation", "ide-autocomplete", "ai-agents", "enterprise-django", "django-settings", "type-safe-config",]
|
|
@@ -19,15 +19,6 @@ THIRD_PARTY_REGISTRY = {
|
|
|
19
19
|
"NavigationSection": ("django_cfg.modules.django_unfold.models.navigation", "NavigationSection"),
|
|
20
20
|
"NavigationItemType": ("django_cfg.modules.django_unfold.models.navigation", "NavigationItemType"),
|
|
21
21
|
"SiteDropdownItem": ("django_cfg.modules.django_unfold.models.dropdown", "SiteDropdownItem"),
|
|
22
|
-
"StatCard": ("django_cfg.modules.django_unfold.models.dashboard", "StatCard"),
|
|
23
|
-
"SystemHealthItem": ("django_cfg.modules.django_unfold.models.dashboard", "SystemHealthItem"),
|
|
24
|
-
"QuickAction": ("django_cfg.modules.django_unfold.models.dashboard", "QuickAction"),
|
|
25
|
-
"DashboardWidget": ("django_cfg.modules.django_unfold.models.dashboard", "DashboardWidget"),
|
|
26
|
-
"DashboardData": ("django_cfg.modules.django_unfold.models.dashboard", "DashboardData"),
|
|
27
|
-
"ChartDataset": ("django_cfg.modules.django_unfold.models.dashboard", "ChartDataset"),
|
|
28
|
-
"ChartData": ("django_cfg.modules.django_unfold.models.dashboard", "ChartData"),
|
|
29
|
-
"TabConfiguration": ("django_cfg.modules.django_unfold.models.tabs", "TabConfiguration"),
|
|
30
|
-
"TabItem": ("django_cfg.modules.django_unfold.models.tabs", "TabItem"),
|
|
31
22
|
|
|
32
23
|
# Django REST Framework
|
|
33
24
|
"DRFConfig": ("django_cfg.models.api.drf", "DRFConfig"),
|
django_cfg/routing/callbacks.py
CHANGED
|
@@ -10,52 +10,11 @@ from typing import Any, Dict, List
|
|
|
10
10
|
from django.conf import settings
|
|
11
11
|
from django.contrib.auth import get_user_model
|
|
12
12
|
from django.contrib.contenttypes.models import ContentType
|
|
13
|
-
from django.db import connection
|
|
14
13
|
from django.http import HttpRequest
|
|
15
14
|
|
|
16
15
|
from ..modules.base import BaseCfgModule
|
|
17
16
|
|
|
18
17
|
|
|
19
|
-
def dashboard_callback(request: HttpRequest, context: Dict[str, Any]) -> Dict[str, Any]:
|
|
20
|
-
"""
|
|
21
|
-
Default dashboard callback for Unfold admin.
|
|
22
|
-
|
|
23
|
-
Returns enhanced context with dashboard data.
|
|
24
|
-
"""
|
|
25
|
-
User = get_user_model()
|
|
26
|
-
|
|
27
|
-
# Get basic stats
|
|
28
|
-
user_count = User.objects.count()
|
|
29
|
-
|
|
30
|
-
# Database info
|
|
31
|
-
with connection.cursor() as cursor:
|
|
32
|
-
cursor.execute("SELECT COUNT(*) FROM django_session")
|
|
33
|
-
session_count = cursor.fetchone()[0]
|
|
34
|
-
|
|
35
|
-
# Add dashboard data to context
|
|
36
|
-
context.update({
|
|
37
|
-
"dashboard": [
|
|
38
|
-
{
|
|
39
|
-
"title": "System Overview",
|
|
40
|
-
"metric": f"{user_count} users",
|
|
41
|
-
"footer": f"{session_count} active sessions",
|
|
42
|
-
"chart": {
|
|
43
|
-
"labels": ["Users", "Sessions"],
|
|
44
|
-
"data": [user_count, session_count],
|
|
45
|
-
}
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
"title": "Quick Actions",
|
|
49
|
-
"metric": "Admin Tools",
|
|
50
|
-
"footer": "Manage your system",
|
|
51
|
-
"link": "/admin/",
|
|
52
|
-
}
|
|
53
|
-
]
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
return context
|
|
57
|
-
|
|
58
|
-
|
|
59
18
|
def environment_callback(request: HttpRequest) -> Dict[str, Any]:
|
|
60
19
|
"""
|
|
61
20
|
Environment callback for Unfold admin.
|
|
@@ -187,11 +146,10 @@ def badge_callback(request: HttpRequest) -> List[Dict[str, Any]]:
|
|
|
187
146
|
def get_unfold_callbacks() -> Dict[str, str]:
|
|
188
147
|
"""
|
|
189
148
|
Get callback function paths for Unfold configuration.
|
|
190
|
-
|
|
149
|
+
|
|
191
150
|
Returns dictionary mapping callback types to function paths.
|
|
192
151
|
"""
|
|
193
152
|
return {
|
|
194
|
-
"dashboard_callback": "django_cfg.routing.callbacks.dashboard_callback",
|
|
195
153
|
"environment_callback": "django_cfg.routing.callbacks.environment_callback",
|
|
196
154
|
"permission_callback": "django_cfg.routing.callbacks.permission_callback",
|
|
197
155
|
"search_callback": "django_cfg.routing.callbacks.search_callback",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><html><head><meta charSet="utf-8" data-next-head=""/><meta name="viewport" content="width=device-width" data-next-head=""/><title data-next-head="">Django CFG</title><meta name="description" content="Django CFG Admin Panel" data-next-head=""/><link rel="icon" type="image/png" href="/cfg/admin/static/logos/192x192.png" data-next-head=""/><meta property="og:title" content="Django CFG" data-next-head=""/><meta property="og:description" content="Django CFG Admin Panel" data-next-head=""/><meta property="og:type" content="website" data-next-head=""/><meta name="twitter:card" content="summary_large_image" data-next-head=""/><meta name="twitter:title" content="Django CFG" data-next-head=""/><meta name="twitter:description" content="Django CFG Admin Panel" data-next-head=""/><meta property="og:image" content="/cfg/admin//api/og?data=eyJ0aXRsZSI6IkRqYW5nbyBDRkciLCJzdWJ0aXRsZSI6IkRqYW5nbyBDRkcgQWRtaW4gUGFuZWwiLCJkZXNjcmlwdGlvbiI6IkRqYW5nbyBDRkcgQWRtaW4gUGFuZWwifQ==" data-next-head=""/><meta property="og:image:width" content="1200" data-next-head=""/><meta property="og:image:height" content="630" data-next-head=""/><meta property="og:image:type" content="image/png" data-next-head=""/><meta name="twitter:image" content="/cfg/admin//api/og?data=eyJ0aXRsZSI6IkRqYW5nbyBDRkciLCJzdWJ0aXRsZSI6IkRqYW5nbyBDRkcgQWRtaW4gUGFuZWwiLCJkZXNjcmlwdGlvbiI6IkRqYW5nbyBDRkcgQWRtaW4gUGFuZWwifQ==" data-next-head=""/><link rel="preload" href="/cfg/admin/_next/static/media/
|
|
1
|
+
<!DOCTYPE html><html><head><meta charSet="utf-8" data-next-head=""/><meta name="viewport" content="width=device-width" data-next-head=""/><title data-next-head="">Django CFG</title><meta name="description" content="Django CFG Admin Panel" data-next-head=""/><link rel="icon" type="image/png" href="/cfg/admin/static/logos/192x192.png" data-next-head=""/><meta property="og:title" content="Django CFG" data-next-head=""/><meta property="og:description" content="Django CFG Admin Panel" data-next-head=""/><meta property="og:type" content="website" data-next-head=""/><meta name="twitter:card" content="summary_large_image" data-next-head=""/><meta name="twitter:title" content="Django CFG" data-next-head=""/><meta name="twitter:description" content="Django CFG Admin Panel" data-next-head=""/><meta property="og:image" content="/cfg/admin//api/og?data=eyJ0aXRsZSI6IkRqYW5nbyBDRkciLCJzdWJ0aXRsZSI6IkRqYW5nbyBDRkcgQWRtaW4gUGFuZWwiLCJkZXNjcmlwdGlvbiI6IkRqYW5nbyBDRkcgQWRtaW4gUGFuZWwifQ==" data-next-head=""/><meta property="og:image:width" content="1200" data-next-head=""/><meta property="og:image:height" content="630" data-next-head=""/><meta property="og:image:type" content="image/png" data-next-head=""/><meta name="twitter:image" content="/cfg/admin//api/og?data=eyJ0aXRsZSI6IkRqYW5nbyBDRkciLCJzdWJ0aXRsZSI6IkRqYW5nbyBDRkcgQWRtaW4gUGFuZWwiLCJkZXNjcmlwdGlvbiI6IkRqYW5nbyBDRkcgQWRtaW4gUGFuZWwifQ==" data-next-head=""/><link rel="preload" href="/cfg/admin/_next/static/media/21350d82a1f187e9-s.p.woff2" as="font" type="font/woff2" crossorigin="anonymous" data-next-font="size-adjust"/><link rel="preload" href="/cfg/admin/_next/static/media/e4af272ccee01ff0-s.p.woff2" as="font" type="font/woff2" crossorigin="anonymous" data-next-font="size-adjust"/><link rel="preload" href="/cfg/admin/_next/static/css/3063068f0d5a8a00.css" as="style"/><link rel="stylesheet" href="/cfg/admin/_next/static/css/3063068f0d5a8a00.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" noModule="" src="/cfg/admin/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/cfg/admin/_next/static/chunks/webpack-5a92f81363b62aa7.js" defer=""></script><script src="/cfg/admin/_next/static/chunks/framework-46f25b115ad0e595.js" defer=""></script><script src="/cfg/admin/_next/static/chunks/main-d4b1d5245e3e8c42.js" defer=""></script><script src="/cfg/admin/_next/static/chunks/pages/_app-c7dcd3aa616fab68.js" defer=""></script><script src="/cfg/admin/_next/static/chunks/pages/404-9c41b6ebfe67f15e.js" defer=""></script><script src="/cfg/admin/_next/static/0sN9ktsgXH48ygtGSrhfu/_buildManifest.js" defer=""></script><script src="/cfg/admin/_next/static/0sN9ktsgXH48ygtGSrhfu/_ssgManifest.js" defer=""></script></head><body><div id="__next"><style>html { font-family: 'Inter', 'Inter Fallback'; }</style><div class="p-6"><div class="min-h-screen flex items-center justify-center px-4"><div class="max-w-2xl w-full text-center space-y-8"><div class="relative"><h1 class="text-[12rem] font-bold leading-none text-muted/20 select-none" aria-hidden="true">404</h1></div><div class="flex justify-center py-8"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-file-question w-24 h-24 text-muted-foreground/50"><path d="M12 17h.01"></path><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7z"></path><path d="M9.1 9a3 3 0 0 1 5.82 1c0 2-3 3-3 3"></path></svg></div><div class="space-y-4"><h2 class="text-4xl font-bold text-foreground">Page Not Found</h2><p class="text-lg text-muted-foreground max-w-md mx-auto">The page you're looking for doesn't exist or has been moved.</p></div><div class="flex flex-col sm:flex-row items-center justify-center gap-4 pt-4"><button class="inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap text-sm font-semibold transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground h-11 rounded-md px-8 min-w-[140px]">Go Back</button><button class="inline-flex cursor-pointer items-center justify-center gap-2 whitespace-nowrap text-sm font-semibold transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 bg-primary text-primary-foreground shadow hover:bg-primary/90 h-11 rounded-md px-8 min-w-[140px]">Go Home</button></div><div class="pt-8 text-sm text-muted-foreground"><p>Need help? Contact<!-- --> <a href="mailto:support@djangocfg.com" class="text-primary hover:underline">support</a></p></div></div></div></div><div role="region" aria-label="Notifications (F8)" tabindex="-1" style="pointer-events:none"><ol tabindex="-1" class="fixed top-0 z-[9999] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]"></ol></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{}},"page":"/404","query":{},"buildId":"0sN9ktsgXH48ygtGSrhfu","assetPrefix":"/cfg/admin","nextExport":true,"autoExport":true,"isFallback":false,"scriptLoader":[]}</script></body></html>
|