django-cfg 1.4.84__py3-none-any.whl → 1.4.86__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/dashboard/serializers/__init__.py +55 -0
- django_cfg/apps/dashboard/serializers/activity.py +38 -0
- django_cfg/apps/dashboard/serializers/apizones.py +26 -0
- django_cfg/apps/dashboard/serializers/base.py +16 -0
- django_cfg/apps/dashboard/serializers/charts.py +44 -0
- django_cfg/apps/dashboard/serializers/commands.py +26 -0
- django_cfg/apps/dashboard/serializers/overview.py +34 -0
- django_cfg/apps/dashboard/serializers/statistics.py +46 -0
- django_cfg/apps/dashboard/serializers/system.py +58 -0
- django_cfg/apps/dashboard/services/__init__.py +10 -1
- django_cfg/apps/dashboard/services/apizones_service.py +119 -0
- django_cfg/apps/dashboard/services/charts_service.py +266 -0
- django_cfg/apps/dashboard/services/commands_service.py +142 -0
- django_cfg/apps/dashboard/services/statistics_service.py +262 -104
- django_cfg/apps/dashboard/urls.py +25 -6
- django_cfg/apps/dashboard/views/__init__.py +23 -0
- django_cfg/apps/dashboard/views/activity_views.py +83 -0
- django_cfg/apps/dashboard/views/apizones_views.py +73 -0
- django_cfg/apps/dashboard/views/charts_views.py +159 -0
- django_cfg/apps/dashboard/views/commands_views.py +73 -0
- django_cfg/apps/dashboard/views/overview_views.py +92 -0
- django_cfg/apps/dashboard/views/statistics_views.py +105 -0
- django_cfg/apps/dashboard/views/system_views.py +73 -0
- django_cfg/modules/django_client/core/generator/typescript/templates/fetchers/fetchers.ts.jinja +0 -1
- django_cfg/modules/django_client/core/generator/typescript/templates/fetchers/function.ts.jinja +1 -1
- django_cfg/modules/django_unfold/callbacks/main.py +7 -6
- django_cfg/modules/django_unfold/dashboard.py +1 -36
- django_cfg/modules/django_unfold/models/config.py +102 -73
- django_cfg/modules/django_unfold/tailwind.py +31 -79
- django_cfg/pyproject.toml +1 -1
- django_cfg/static/frontend/admin/404.html +1 -1
- django_cfg/static/frontend/admin/500.html +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/23004-faae121bbfecc163.js +1 -0
- django_cfg/static/frontend/admin/_next/static/chunks/{20695.a7d37b6c40ad3f58.js → 43076.55dd23b6cd68edb0.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/50314-3b9d15242191c8bc.js +1 -0
- django_cfg/static/frontend/admin/_next/static/chunks/{64330.2ef79bccd7d4e363.js → 64330.41858e98c0e5173b.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/6766.8d01e44e83070e83.js +1 -0
- django_cfg/static/frontend/admin/_next/static/chunks/{96168.eb7fdb721b9cdb00.js → 96168.b7197f890097df6e.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/pages/{404-c283223d1afd02a2.js → 404-cf71cd7b3cb005e5.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/pages/{500-389d6d3e1f2f7fda.js → 500-ff19c7842e3df415.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/pages/_app-f62e5528fbcbb6b3.js +272 -0
- django_cfg/static/frontend/admin/_next/static/chunks/pages/{_error-5291033275c26d09.js → _error-87f3fdc2aa131e77.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/pages/{index-d7bc30185f52cbca.js → index-69f737d4802cc5b7.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/pages/private/centrifugo-f24beb6ed3955aa8.js +1 -0
- django_cfg/static/frontend/admin/_next/static/chunks/pages/private/{profile-e93a65e8e7d9022b.js → profile-b8045f993287f1a7.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/pages/private/{ui-669e8f2a785beba2.js → ui-373fff8b42878e64.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/pages/private-fe9faa86ecdb0ce6.js +1 -0
- django_cfg/static/frontend/admin/_next/static/chunks/{webpack-92add5f95c66e349.js → webpack-7c456a65e96eb97e.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/css/5f9a37b6e6a72303.css +3 -0
- django_cfg/static/frontend/admin/_next/static/wg0mGdXjT00H_1BUxoOSH/_buildManifest.js +1 -0
- django_cfg/static/frontend/admin/auth.html +1 -1
- django_cfg/static/frontend/admin/index.html +1 -1
- django_cfg/static/frontend/admin/legal/cookies.html +1 -1
- django_cfg/static/frontend/admin/legal/privacy.html +1 -1
- django_cfg/static/frontend/admin/legal/security.html +1 -1
- django_cfg/static/frontend/admin/legal/terms.html +1 -1
- django_cfg/static/frontend/admin/private/centrifugo.html +1 -1
- django_cfg/static/frontend/admin/private/profile.html +1 -1
- django_cfg/static/frontend/admin/private/ui.html +1 -1
- django_cfg/static/frontend/admin/private.html +1 -1
- django_cfg/templates/admin/index.html +237 -5
- django_cfg/templates/admin/sections/commands_section.html +5 -0
- django_cfg/templates/admin/sections/documentation_section.html +5 -0
- django_cfg/templates/admin/sections/overview_section.html +5 -0
- django_cfg/templates/admin/sections/stats_section.html +5 -0
- django_cfg/templates/admin/sections/system_section.html +5 -0
- django_cfg/templates/admin/sections/widgets_section.html +11 -0
- django_cfg/templates/unfold/layouts/skeleton.html +27 -0
- django_cfg/templatetags/django_cfg.py +53 -0
- {django_cfg-1.4.84.dist-info → django_cfg-1.4.86.dist-info}/METADATA +1 -1
- {django_cfg-1.4.84.dist-info → django_cfg-1.4.86.dist-info}/RECORD +76 -53
- django_cfg/apps/dashboard/api/__init__.py +0 -27
- django_cfg/apps/dashboard/api/serializers.py +0 -165
- django_cfg/apps/dashboard/api/viewsets.py +0 -257
- django_cfg/static/frontend/admin/_next/static/-Zk0eDB7OJOEFrFyR5BwZ/_buildManifest.js +0 -1
- django_cfg/static/frontend/admin/_next/static/chunks/43076-4be6a9794e9c3e8b.js +0 -1
- django_cfg/static/frontend/admin/_next/static/chunks/50314-79c02212788f1ec7.js +0 -1
- django_cfg/static/frontend/admin/_next/static/chunks/6766.d62fed7cd4761148.js +0 -1
- django_cfg/static/frontend/admin/_next/static/chunks/82296-a2c8d38f62224be5.js +0 -1
- django_cfg/static/frontend/admin/_next/static/chunks/pages/_app-f25bec36bbdc9625.js +0 -272
- django_cfg/static/frontend/admin/_next/static/chunks/pages/private/centrifugo-22532c65971225eb.js +0 -1
- django_cfg/static/frontend/admin/_next/static/chunks/pages/private-a8a9ba76f2c75354.js +0 -1
- django_cfg/static/frontend/admin/_next/static/css/78d677ac1677c210.css +0 -3
- /django_cfg/static/frontend/admin/_next/static/{-Zk0eDB7OJOEFrFyR5BwZ → wg0mGdXjT00H_1BUxoOSH}/_ssgManifest.js +0 -0
- {django_cfg-1.4.84.dist-info → django_cfg-1.4.86.dist-info}/WHEEL +0 -0
- {django_cfg-1.4.84.dist-info → django_cfg-1.4.86.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.4.84.dist-info → django_cfg-1.4.86.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""
|
|
2
|
+
API Zones ViewSet
|
|
3
|
+
|
|
4
|
+
Endpoints for OpenAPI zones/groups management:
|
|
5
|
+
- GET /zones/ - All API zones
|
|
6
|
+
- GET /zones/summary/ - Zones summary with statistics
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
|
|
11
|
+
from drf_spectacular.utils import extend_schema
|
|
12
|
+
from rest_framework import status, viewsets
|
|
13
|
+
from rest_framework.authentication import BasicAuthentication, SessionAuthentication
|
|
14
|
+
from rest_framework.decorators import action
|
|
15
|
+
from rest_framework.permissions import IsAdminUser
|
|
16
|
+
from rest_framework.response import Response
|
|
17
|
+
|
|
18
|
+
from ..services import APIZonesService
|
|
19
|
+
from ..serializers import APIZoneSerializer, APIZonesSummarySerializer
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class APIZonesViewSet(viewsets.GenericViewSet):
|
|
25
|
+
"""
|
|
26
|
+
API Zones ViewSet
|
|
27
|
+
|
|
28
|
+
Provides endpoints for OpenAPI zones (groups) management.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
authentication_classes = [SessionAuthentication, BasicAuthentication]
|
|
32
|
+
permission_classes = [IsAdminUser]
|
|
33
|
+
serializer_class = APIZoneSerializer
|
|
34
|
+
pagination_class = None # Disable pagination for zones list
|
|
35
|
+
|
|
36
|
+
@extend_schema(
|
|
37
|
+
summary="Get all API zones",
|
|
38
|
+
description="Retrieve all OpenAPI zones/groups with their configuration",
|
|
39
|
+
responses={200: APIZoneSerializer(many=True)},
|
|
40
|
+
tags=["Dashboard - API Zones"]
|
|
41
|
+
)
|
|
42
|
+
def list(self, request):
|
|
43
|
+
"""Get all API zones."""
|
|
44
|
+
try:
|
|
45
|
+
zones_service = APIZonesService()
|
|
46
|
+
zones_list, _ = zones_service.get_zones_data()
|
|
47
|
+
return Response(zones_list)
|
|
48
|
+
|
|
49
|
+
except Exception as e:
|
|
50
|
+
logger.error(f"API zones list error: {e}")
|
|
51
|
+
return Response({
|
|
52
|
+
'error': str(e)
|
|
53
|
+
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
54
|
+
|
|
55
|
+
@extend_schema(
|
|
56
|
+
summary="Get zones summary",
|
|
57
|
+
description="Retrieve zones summary with statistics",
|
|
58
|
+
responses={200: APIZonesSummarySerializer},
|
|
59
|
+
tags=["Dashboard - API Zones"]
|
|
60
|
+
)
|
|
61
|
+
@action(detail=False, methods=['get'], url_path='summary', serializer_class=APIZonesSummarySerializer)
|
|
62
|
+
def summary(self, request):
|
|
63
|
+
"""Get zones summary with statistics."""
|
|
64
|
+
try:
|
|
65
|
+
zones_service = APIZonesService()
|
|
66
|
+
summary = zones_service.get_zones_summary()
|
|
67
|
+
return Response(summary)
|
|
68
|
+
|
|
69
|
+
except Exception as e:
|
|
70
|
+
logger.error(f"API zones summary error: {e}")
|
|
71
|
+
return Response({
|
|
72
|
+
'error': str(e)
|
|
73
|
+
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Charts ViewSet
|
|
3
|
+
|
|
4
|
+
Endpoints for dashboard charts and analytics:
|
|
5
|
+
- GET /charts/registrations/ - User registration chart
|
|
6
|
+
- GET /charts/activity/ - User activity chart
|
|
7
|
+
- GET /charts/tracker/ - Activity tracker (52 weeks)
|
|
8
|
+
- GET /charts/recent-users/ - Recent users list
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import logging
|
|
12
|
+
|
|
13
|
+
from drf_spectacular.utils import OpenApiParameter, extend_schema
|
|
14
|
+
from rest_framework import status, viewsets
|
|
15
|
+
from rest_framework.authentication import BasicAuthentication, SessionAuthentication
|
|
16
|
+
from rest_framework.decorators import action
|
|
17
|
+
from rest_framework.permissions import IsAdminUser
|
|
18
|
+
from rest_framework.response import Response
|
|
19
|
+
|
|
20
|
+
from ..services import ChartsService, StatisticsService
|
|
21
|
+
from ..serializers import (
|
|
22
|
+
ChartDataSerializer,
|
|
23
|
+
ActivityTrackerDaySerializer,
|
|
24
|
+
RecentUserSerializer,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
logger = logging.getLogger(__name__)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class ChartsViewSet(viewsets.GenericViewSet):
|
|
31
|
+
"""
|
|
32
|
+
Charts ViewSet
|
|
33
|
+
|
|
34
|
+
Provides endpoints for dashboard charts and analytics.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
authentication_classes = [SessionAuthentication, BasicAuthentication]
|
|
38
|
+
permission_classes = [IsAdminUser]
|
|
39
|
+
serializer_class = ChartDataSerializer
|
|
40
|
+
|
|
41
|
+
@extend_schema(
|
|
42
|
+
summary="Get user registration chart",
|
|
43
|
+
description="Retrieve user registration data for chart visualization",
|
|
44
|
+
parameters=[
|
|
45
|
+
OpenApiParameter(
|
|
46
|
+
name='days',
|
|
47
|
+
description='Number of days to include',
|
|
48
|
+
required=False,
|
|
49
|
+
type=int,
|
|
50
|
+
default=7
|
|
51
|
+
),
|
|
52
|
+
],
|
|
53
|
+
responses={200: ChartDataSerializer},
|
|
54
|
+
tags=["Dashboard - Charts"]
|
|
55
|
+
)
|
|
56
|
+
@action(detail=False, methods=['get'], url_path='registrations', serializer_class=ChartDataSerializer)
|
|
57
|
+
def registrations(self, request):
|
|
58
|
+
"""Get user registration chart data."""
|
|
59
|
+
try:
|
|
60
|
+
days = int(request.query_params.get('days', 7))
|
|
61
|
+
charts_service = ChartsService()
|
|
62
|
+
chart_data = charts_service.get_user_registration_chart(days=days)
|
|
63
|
+
return Response(chart_data)
|
|
64
|
+
|
|
65
|
+
except Exception as e:
|
|
66
|
+
logger.error(f"Registration chart API error: {e}")
|
|
67
|
+
return Response({
|
|
68
|
+
'error': str(e)
|
|
69
|
+
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
70
|
+
|
|
71
|
+
@extend_schema(
|
|
72
|
+
summary="Get user activity chart",
|
|
73
|
+
description="Retrieve user activity data for chart visualization",
|
|
74
|
+
parameters=[
|
|
75
|
+
OpenApiParameter(
|
|
76
|
+
name='days',
|
|
77
|
+
description='Number of days to include',
|
|
78
|
+
required=False,
|
|
79
|
+
type=int,
|
|
80
|
+
default=7
|
|
81
|
+
),
|
|
82
|
+
],
|
|
83
|
+
responses={200: ChartDataSerializer},
|
|
84
|
+
tags=["Dashboard - Charts"]
|
|
85
|
+
)
|
|
86
|
+
@action(detail=False, methods=['get'], url_path='activity', serializer_class=ChartDataSerializer)
|
|
87
|
+
def activity(self, request):
|
|
88
|
+
"""Get user activity chart data."""
|
|
89
|
+
try:
|
|
90
|
+
days = int(request.query_params.get('days', 7))
|
|
91
|
+
charts_service = ChartsService()
|
|
92
|
+
chart_data = charts_service.get_user_activity_chart(days=days)
|
|
93
|
+
return Response(chart_data)
|
|
94
|
+
|
|
95
|
+
except Exception as e:
|
|
96
|
+
logger.error(f"Activity chart API error: {e}")
|
|
97
|
+
return Response({
|
|
98
|
+
'error': str(e)
|
|
99
|
+
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
100
|
+
|
|
101
|
+
@extend_schema(
|
|
102
|
+
summary="Get activity tracker",
|
|
103
|
+
description="Retrieve activity tracker data (GitHub-style contribution graph)",
|
|
104
|
+
parameters=[
|
|
105
|
+
OpenApiParameter(
|
|
106
|
+
name='weeks',
|
|
107
|
+
description='Number of weeks to include',
|
|
108
|
+
required=False,
|
|
109
|
+
type=int,
|
|
110
|
+
default=52
|
|
111
|
+
),
|
|
112
|
+
],
|
|
113
|
+
responses=ActivityTrackerDaySerializer(many=True),
|
|
114
|
+
tags=["Dashboard - Charts"]
|
|
115
|
+
)
|
|
116
|
+
@action(detail=False, methods=['get'], url_path='tracker', pagination_class=None, serializer_class=ActivityTrackerDaySerializer)
|
|
117
|
+
def tracker(self, request):
|
|
118
|
+
"""Get activity tracker data."""
|
|
119
|
+
try:
|
|
120
|
+
weeks = int(request.query_params.get('weeks', 52))
|
|
121
|
+
charts_service = ChartsService()
|
|
122
|
+
tracker_data = charts_service.get_activity_tracker(weeks=weeks)
|
|
123
|
+
return Response(tracker_data)
|
|
124
|
+
|
|
125
|
+
except Exception as e:
|
|
126
|
+
logger.error(f"Activity tracker API error: {e}")
|
|
127
|
+
return Response({
|
|
128
|
+
'error': str(e)
|
|
129
|
+
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
130
|
+
|
|
131
|
+
@extend_schema(
|
|
132
|
+
summary="Get recent users",
|
|
133
|
+
description="Retrieve list of recently registered users",
|
|
134
|
+
parameters=[
|
|
135
|
+
OpenApiParameter(
|
|
136
|
+
name='limit',
|
|
137
|
+
description='Maximum number of users to return',
|
|
138
|
+
required=False,
|
|
139
|
+
type=int,
|
|
140
|
+
default=10
|
|
141
|
+
),
|
|
142
|
+
],
|
|
143
|
+
responses=RecentUserSerializer(many=True),
|
|
144
|
+
tags=["Dashboard - Charts"]
|
|
145
|
+
)
|
|
146
|
+
@action(detail=False, methods=['get'], url_path='recent-users', pagination_class=None, serializer_class=RecentUserSerializer)
|
|
147
|
+
def recent_users(self, request):
|
|
148
|
+
"""Get recent users list."""
|
|
149
|
+
try:
|
|
150
|
+
limit = int(request.query_params.get('limit', 10))
|
|
151
|
+
stats_service = StatisticsService()
|
|
152
|
+
users = stats_service.get_recent_users(limit=limit)
|
|
153
|
+
return Response(users)
|
|
154
|
+
|
|
155
|
+
except Exception as e:
|
|
156
|
+
logger.error(f"Recent users API error: {e}")
|
|
157
|
+
return Response({
|
|
158
|
+
'error': str(e)
|
|
159
|
+
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Commands ViewSet
|
|
3
|
+
|
|
4
|
+
Endpoints for Django management commands:
|
|
5
|
+
- GET /commands/ - All available commands
|
|
6
|
+
- GET /commands/summary/ - Commands summary with statistics
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
|
|
11
|
+
from drf_spectacular.utils import extend_schema
|
|
12
|
+
from rest_framework import status, viewsets
|
|
13
|
+
from rest_framework.authentication import BasicAuthentication, SessionAuthentication
|
|
14
|
+
from rest_framework.decorators import action
|
|
15
|
+
from rest_framework.permissions import IsAdminUser
|
|
16
|
+
from rest_framework.response import Response
|
|
17
|
+
|
|
18
|
+
from ..services import CommandsService
|
|
19
|
+
from ..serializers import CommandSerializer, CommandsSummarySerializer
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class CommandsViewSet(viewsets.GenericViewSet):
|
|
25
|
+
"""
|
|
26
|
+
Commands ViewSet
|
|
27
|
+
|
|
28
|
+
Provides endpoints for Django management commands discovery.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
authentication_classes = [SessionAuthentication, BasicAuthentication]
|
|
32
|
+
permission_classes = [IsAdminUser]
|
|
33
|
+
serializer_class = CommandSerializer
|
|
34
|
+
pagination_class = None # Disable pagination for commands list
|
|
35
|
+
|
|
36
|
+
@extend_schema(
|
|
37
|
+
summary="Get all commands",
|
|
38
|
+
description="Retrieve all available Django management commands",
|
|
39
|
+
responses=CommandSerializer(many=True),
|
|
40
|
+
tags=["Dashboard - Commands"]
|
|
41
|
+
)
|
|
42
|
+
def list(self, request):
|
|
43
|
+
"""Get all Django management commands."""
|
|
44
|
+
try:
|
|
45
|
+
commands_service = CommandsService()
|
|
46
|
+
commands = commands_service.get_all_commands()
|
|
47
|
+
return Response(commands)
|
|
48
|
+
|
|
49
|
+
except Exception as e:
|
|
50
|
+
logger.error(f"Commands list API error: {e}")
|
|
51
|
+
return Response({
|
|
52
|
+
'error': str(e)
|
|
53
|
+
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
54
|
+
|
|
55
|
+
@extend_schema(
|
|
56
|
+
summary="Get commands summary",
|
|
57
|
+
description="Retrieve commands summary with statistics and categorization",
|
|
58
|
+
responses={200: CommandsSummarySerializer},
|
|
59
|
+
tags=["Dashboard - Commands"]
|
|
60
|
+
)
|
|
61
|
+
@action(detail=False, methods=['get'], url_path='summary', serializer_class=CommandsSummarySerializer)
|
|
62
|
+
def summary(self, request):
|
|
63
|
+
"""Get commands summary with statistics."""
|
|
64
|
+
try:
|
|
65
|
+
commands_service = CommandsService()
|
|
66
|
+
summary = commands_service.get_commands_summary()
|
|
67
|
+
return Response(summary)
|
|
68
|
+
|
|
69
|
+
except Exception as e:
|
|
70
|
+
logger.error(f"Commands summary API error: {e}")
|
|
71
|
+
return Response({
|
|
72
|
+
'error': str(e)
|
|
73
|
+
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Overview ViewSet
|
|
3
|
+
|
|
4
|
+
Endpoint for complete dashboard overview:
|
|
5
|
+
- GET /overview/ - Complete dashboard data in single request
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
from datetime import datetime
|
|
10
|
+
|
|
11
|
+
from drf_spectacular.utils import extend_schema
|
|
12
|
+
from rest_framework import status, viewsets
|
|
13
|
+
from rest_framework.authentication import BasicAuthentication, SessionAuthentication
|
|
14
|
+
from rest_framework.decorators import action
|
|
15
|
+
from rest_framework.permissions import IsAdminUser
|
|
16
|
+
from rest_framework.response import Response
|
|
17
|
+
|
|
18
|
+
from ..services import StatisticsService, SystemHealthService, ChartsService
|
|
19
|
+
from ..serializers import DashboardOverviewSerializer
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class OverviewViewSet(viewsets.GenericViewSet):
|
|
25
|
+
"""
|
|
26
|
+
Dashboard Overview ViewSet
|
|
27
|
+
|
|
28
|
+
Provides a single endpoint that returns all dashboard data at once.
|
|
29
|
+
Useful for initial page load.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
authentication_classes = [SessionAuthentication, BasicAuthentication]
|
|
33
|
+
permission_classes = [IsAdminUser]
|
|
34
|
+
serializer_class = DashboardOverviewSerializer
|
|
35
|
+
|
|
36
|
+
@extend_schema(
|
|
37
|
+
summary="Get dashboard overview",
|
|
38
|
+
description="Retrieve complete dashboard data including stats, health, actions, and metrics",
|
|
39
|
+
responses={200: DashboardOverviewSerializer},
|
|
40
|
+
tags=["Dashboard - Overview"]
|
|
41
|
+
)
|
|
42
|
+
@action(detail=False, methods=['get'], url_path='', url_name='overview')
|
|
43
|
+
def overview(self, request):
|
|
44
|
+
"""
|
|
45
|
+
Get complete dashboard overview.
|
|
46
|
+
|
|
47
|
+
Returns all dashboard data in a single request:
|
|
48
|
+
- Statistics cards
|
|
49
|
+
- System health status
|
|
50
|
+
- Quick actions
|
|
51
|
+
- Recent activity
|
|
52
|
+
- System metrics
|
|
53
|
+
- User statistics
|
|
54
|
+
"""
|
|
55
|
+
try:
|
|
56
|
+
stats_service = StatisticsService()
|
|
57
|
+
health_service = SystemHealthService()
|
|
58
|
+
charts_service = ChartsService()
|
|
59
|
+
|
|
60
|
+
data = {
|
|
61
|
+
# Statistics
|
|
62
|
+
'stat_cards': stats_service.get_stat_cards(),
|
|
63
|
+
'user_statistics': stats_service.get_user_statistics(),
|
|
64
|
+
'app_statistics': stats_service.get_app_statistics(),
|
|
65
|
+
|
|
66
|
+
# System
|
|
67
|
+
'system_health': health_service.get_all_health_checks(),
|
|
68
|
+
'system_metrics': stats_service.get_system_metrics(),
|
|
69
|
+
|
|
70
|
+
# Activity
|
|
71
|
+
'recent_activity': stats_service.get_recent_activity(limit=10),
|
|
72
|
+
'recent_users': stats_service.get_recent_users(limit=10),
|
|
73
|
+
'quick_actions': health_service.get_quick_actions(),
|
|
74
|
+
|
|
75
|
+
# Charts
|
|
76
|
+
'charts': {
|
|
77
|
+
'user_registrations': charts_service.get_user_registration_chart(days=7),
|
|
78
|
+
'user_activity': charts_service.get_user_activity_chart(days=7),
|
|
79
|
+
},
|
|
80
|
+
'activity_tracker': charts_service.get_activity_tracker(weeks=52),
|
|
81
|
+
|
|
82
|
+
# Meta
|
|
83
|
+
'timestamp': datetime.now().isoformat(),
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return Response(data)
|
|
87
|
+
|
|
88
|
+
except Exception as e:
|
|
89
|
+
logger.error(f"Dashboard overview API error: {e}", exc_info=True)
|
|
90
|
+
return Response({
|
|
91
|
+
'error': str(e)
|
|
92
|
+
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Statistics ViewSet
|
|
3
|
+
|
|
4
|
+
Endpoints for dashboard statistics:
|
|
5
|
+
- GET /statistics/cards/ - Statistics cards
|
|
6
|
+
- GET /statistics/users/ - User statistics
|
|
7
|
+
- GET /statistics/apps/ - Application statistics
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import logging
|
|
11
|
+
|
|
12
|
+
from drf_spectacular.utils import extend_schema
|
|
13
|
+
from rest_framework import status, viewsets
|
|
14
|
+
from rest_framework.authentication import BasicAuthentication, SessionAuthentication
|
|
15
|
+
from rest_framework.decorators import action
|
|
16
|
+
from rest_framework.permissions import IsAdminUser
|
|
17
|
+
from rest_framework.response import Response
|
|
18
|
+
|
|
19
|
+
from ..services import StatisticsService
|
|
20
|
+
from ..serializers import (
|
|
21
|
+
StatCardSerializer,
|
|
22
|
+
UserStatisticsSerializer,
|
|
23
|
+
AppStatisticsSerializer,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
logger = logging.getLogger(__name__)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class StatisticsViewSet(viewsets.GenericViewSet):
|
|
30
|
+
"""
|
|
31
|
+
Statistics ViewSet
|
|
32
|
+
|
|
33
|
+
Provides endpoints for retrieving various dashboard statistics.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
authentication_classes = [SessionAuthentication, BasicAuthentication]
|
|
37
|
+
permission_classes = [IsAdminUser]
|
|
38
|
+
serializer_class = StatCardSerializer
|
|
39
|
+
|
|
40
|
+
@extend_schema(
|
|
41
|
+
summary="Get statistics cards",
|
|
42
|
+
description="Retrieve dashboard statistics cards with key metrics",
|
|
43
|
+
responses=StatCardSerializer(many=True),
|
|
44
|
+
tags=["Dashboard - Statistics"]
|
|
45
|
+
)
|
|
46
|
+
@action(detail=False, methods=['get'], url_path='cards', pagination_class=None, serializer_class=StatCardSerializer)
|
|
47
|
+
def cards(self, request):
|
|
48
|
+
"""Get dashboard statistics cards."""
|
|
49
|
+
try:
|
|
50
|
+
stats_service = StatisticsService()
|
|
51
|
+
cards = stats_service.get_stat_cards()
|
|
52
|
+
return Response(cards)
|
|
53
|
+
|
|
54
|
+
except Exception as e:
|
|
55
|
+
logger.error(f"Stat cards API error: {e}")
|
|
56
|
+
return Response({
|
|
57
|
+
'error': str(e)
|
|
58
|
+
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
59
|
+
|
|
60
|
+
@extend_schema(
|
|
61
|
+
summary="Get user statistics",
|
|
62
|
+
description="Retrieve user-related statistics",
|
|
63
|
+
responses={200: UserStatisticsSerializer},
|
|
64
|
+
tags=["Dashboard - Statistics"]
|
|
65
|
+
)
|
|
66
|
+
@action(detail=False, methods=['get'], url_path='users', serializer_class=UserStatisticsSerializer)
|
|
67
|
+
def users(self, request):
|
|
68
|
+
"""Get user statistics."""
|
|
69
|
+
try:
|
|
70
|
+
stats_service = StatisticsService()
|
|
71
|
+
user_stats = stats_service.get_user_statistics()
|
|
72
|
+
return Response(user_stats)
|
|
73
|
+
|
|
74
|
+
except Exception as e:
|
|
75
|
+
logger.error(f"User statistics API error: {e}")
|
|
76
|
+
return Response({
|
|
77
|
+
'error': str(e)
|
|
78
|
+
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
79
|
+
|
|
80
|
+
@extend_schema(
|
|
81
|
+
summary="Get application statistics",
|
|
82
|
+
description="Retrieve statistics for all enabled django-cfg applications",
|
|
83
|
+
responses=AppStatisticsSerializer(many=True),
|
|
84
|
+
tags=["Dashboard - Statistics"]
|
|
85
|
+
)
|
|
86
|
+
@action(detail=False, methods=['get'], url_path='apps', pagination_class=None, serializer_class=AppStatisticsSerializer)
|
|
87
|
+
def apps(self, request):
|
|
88
|
+
"""Get application-specific statistics."""
|
|
89
|
+
try:
|
|
90
|
+
stats_service = StatisticsService()
|
|
91
|
+
app_stats = stats_service.get_app_statistics()
|
|
92
|
+
|
|
93
|
+
# Convert dict to list of {app_name, statistics} objects
|
|
94
|
+
data = [
|
|
95
|
+
{'app_name': app_name, 'statistics': stats}
|
|
96
|
+
for app_name, stats in app_stats.items()
|
|
97
|
+
]
|
|
98
|
+
|
|
99
|
+
return Response(data)
|
|
100
|
+
|
|
101
|
+
except Exception as e:
|
|
102
|
+
logger.error(f"App statistics API error: {e}")
|
|
103
|
+
return Response({
|
|
104
|
+
'error': str(e)
|
|
105
|
+
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""
|
|
2
|
+
System ViewSet
|
|
3
|
+
|
|
4
|
+
Endpoints for system monitoring:
|
|
5
|
+
- GET /system/health/ - System health status
|
|
6
|
+
- GET /system/metrics/ - System performance metrics
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
|
|
11
|
+
from drf_spectacular.utils import extend_schema
|
|
12
|
+
from rest_framework import status, viewsets
|
|
13
|
+
from rest_framework.authentication import BasicAuthentication, SessionAuthentication
|
|
14
|
+
from rest_framework.decorators import action
|
|
15
|
+
from rest_framework.permissions import IsAdminUser
|
|
16
|
+
from rest_framework.response import Response
|
|
17
|
+
|
|
18
|
+
from ..services import SystemHealthService, StatisticsService
|
|
19
|
+
from ..serializers import SystemHealthSerializer, SystemMetricsSerializer
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class SystemViewSet(viewsets.GenericViewSet):
|
|
25
|
+
"""
|
|
26
|
+
System Monitoring ViewSet
|
|
27
|
+
|
|
28
|
+
Provides endpoints for system health and performance metrics.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
authentication_classes = [SessionAuthentication, BasicAuthentication]
|
|
32
|
+
permission_classes = [IsAdminUser]
|
|
33
|
+
serializer_class = SystemHealthSerializer
|
|
34
|
+
|
|
35
|
+
@extend_schema(
|
|
36
|
+
summary="Get system health status",
|
|
37
|
+
description="Retrieve overall system health including all component checks",
|
|
38
|
+
responses={200: SystemHealthSerializer},
|
|
39
|
+
tags=["Dashboard - System"]
|
|
40
|
+
)
|
|
41
|
+
@action(detail=False, methods=['get'], url_path='health', serializer_class=SystemHealthSerializer)
|
|
42
|
+
def health(self, request):
|
|
43
|
+
"""Get overall system health status."""
|
|
44
|
+
try:
|
|
45
|
+
health_service = SystemHealthService()
|
|
46
|
+
health_data = health_service.get_overall_health_status()
|
|
47
|
+
return Response(health_data)
|
|
48
|
+
|
|
49
|
+
except Exception as e:
|
|
50
|
+
logger.error(f"System health API error: {e}")
|
|
51
|
+
return Response({
|
|
52
|
+
'error': str(e)
|
|
53
|
+
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
54
|
+
|
|
55
|
+
@extend_schema(
|
|
56
|
+
summary="Get system metrics",
|
|
57
|
+
description="Retrieve system performance metrics (CPU, memory, disk, etc.)",
|
|
58
|
+
responses={200: SystemMetricsSerializer},
|
|
59
|
+
tags=["Dashboard - System"]
|
|
60
|
+
)
|
|
61
|
+
@action(detail=False, methods=['get'], url_path='metrics', serializer_class=SystemMetricsSerializer)
|
|
62
|
+
def metrics(self, request):
|
|
63
|
+
"""Get system performance metrics."""
|
|
64
|
+
try:
|
|
65
|
+
stats_service = StatisticsService()
|
|
66
|
+
metrics = stats_service.get_system_metrics()
|
|
67
|
+
return Response(metrics)
|
|
68
|
+
|
|
69
|
+
except Exception as e:
|
|
70
|
+
logger.error(f"System metrics API error: {e}")
|
|
71
|
+
return Response({
|
|
72
|
+
'error': str(e)
|
|
73
|
+
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
django_cfg/modules/django_client/core/generator/typescript/templates/fetchers/fetchers.ts.jinja
CHANGED
|
@@ -36,7 +36,6 @@ import { {{ schema_name }}Schema, type {{ schema_name }} } from '../schemas/{{ s
|
|
|
36
36
|
{% endif %}
|
|
37
37
|
{% if has_client %}
|
|
38
38
|
import { getAPIInstance } from '../../api-instance'
|
|
39
|
-
import type { API } from '../../index'
|
|
40
39
|
{% endif %}
|
|
41
40
|
|
|
42
41
|
{% for fetcher in fetchers %}
|
|
@@ -291,12 +291,13 @@ class UnfoldCallbacks(
|
|
|
291
291
|
# logger.info(f"Activity tracker data count: {len(activity_tracker_data)}")
|
|
292
292
|
|
|
293
293
|
# Debug: save full rendered page (only in debug mode)
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
294
|
+
# DISABLED: Commenting out dashboard render saving to disk
|
|
295
|
+
# if config and config.debug:
|
|
296
|
+
# try:
|
|
297
|
+
# full_html = render_to_string('admin/index.html', context, request)
|
|
298
|
+
# save_dashboard_render(full_html, name='dashboard_full_page', context=context)
|
|
299
|
+
# except Exception as e:
|
|
300
|
+
# logger.error(f"Failed to save full dashboard render: {e}", exc_info=True)
|
|
300
301
|
|
|
301
302
|
return context
|
|
302
303
|
|
|
@@ -246,42 +246,7 @@ class DashboardManager(BaseCfgModule):
|
|
|
246
246
|
|
|
247
247
|
# Design system
|
|
248
248
|
"BORDER_RADIUS": "8px",
|
|
249
|
-
|
|
250
|
-
"base": {
|
|
251
|
-
"50": "249, 250, 251",
|
|
252
|
-
"100": "243, 244, 246",
|
|
253
|
-
"200": "229, 231, 235",
|
|
254
|
-
"300": "209, 213, 219",
|
|
255
|
-
"400": "156, 163, 175",
|
|
256
|
-
"500": "107, 114, 128",
|
|
257
|
-
"600": "75, 85, 99",
|
|
258
|
-
"700": "55, 65, 81",
|
|
259
|
-
"800": "31, 41, 55",
|
|
260
|
-
"900": "17, 24, 39",
|
|
261
|
-
"950": "3, 7, 18",
|
|
262
|
-
},
|
|
263
|
-
"primary": {
|
|
264
|
-
"50": "239, 246, 255",
|
|
265
|
-
"100": "219, 234, 254",
|
|
266
|
-
"200": "191, 219, 254",
|
|
267
|
-
"300": "147, 197, 253",
|
|
268
|
-
"400": "96, 165, 250",
|
|
269
|
-
"500": "59, 130, 246",
|
|
270
|
-
"600": "37, 99, 235",
|
|
271
|
-
"700": "29, 78, 216",
|
|
272
|
-
"800": "30, 64, 175",
|
|
273
|
-
"900": "30, 58, 138",
|
|
274
|
-
"950": "23, 37, 84",
|
|
275
|
-
},
|
|
276
|
-
"font": {
|
|
277
|
-
"subtle-light": "var(--color-base-500)",
|
|
278
|
-
"subtle-dark": "var(--color-base-400)",
|
|
279
|
-
"default-light": "var(--color-base-600)",
|
|
280
|
-
"default-dark": "var(--color-base-300)",
|
|
281
|
-
"important-light": "var(--color-base-900)",
|
|
282
|
-
"important-dark": "var(--color-base-100)",
|
|
283
|
-
},
|
|
284
|
-
},
|
|
249
|
+
# COLORS removed - use UnfoldConfig.get_color_scheme() instead
|
|
285
250
|
|
|
286
251
|
# Sidebar navigation - KEY STRUCTURE!
|
|
287
252
|
"SIDEBAR": {
|