django-cfg 1.4.83__py3-none-any.whl → 1.4.85__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/__init__.py +8 -0
- django_cfg/apps/dashboard/apps.py +23 -0
- 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 +20 -0
- 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 +393 -0
- django_cfg/apps/dashboard/services/system_health_service.py +280 -0
- django_cfg/apps/dashboard/urls.py +42 -0
- 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/apps/frontend/views.py +5 -0
- django_cfg/apps/urls.py +2 -1
- django_cfg/core/builders/apps_builder.py +1 -0
- django_cfg/modules/django_client/core/parser/openapi30.py +12 -5
- django_cfg/modules/django_client/core/parser/openapi31.py +12 -5
- 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/BembwiEtlu4eFl3OX7n1k/_buildManifest.js +1 -0
- django_cfg/static/frontend/admin/_next/static/chunks/23004-faae121bbfecc163.js +1 -0
- django_cfg/static/frontend/admin/_next/static/chunks/{25033.d626f78bc99bc4a1.js → 25033.ee3e206d5a2877b6.js} +2 -2
- django_cfg/static/frontend/admin/_next/static/chunks/{25892.964150a58f94ce06.js → 25892.5cbed319f9226fdc.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/{2d7a934f.dfef67639279d59d.js → 2d7a934f.329c61f23af1a7ec.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/{30649.00c679812a56aee3.js → 30649.963cfb7268b5864a.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/{30875.784491146c38dbcb.js → 30875.82c3741757b8aa32.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/{32163.ab0ca435b3f26c04.js → 32163.109a03a7252f1508.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/{49978.fb8ba7ee52ffe666.js → 49978.db5a86a8eb233f35.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/50314-3b9d15242191c8bc.js +1 -0
- django_cfg/static/frontend/admin/_next/static/chunks/{50319.f786248384877960.js → 50319.fd78c7f7e3f1966e.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/{52908.b690e323d8f8efdd.js → 52908.da5b850b0bc0970c.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/{53710.80ca863525d137db.js → 53710.7176bbee6c7b78be.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/{57982.251fed8d58adcf53.js → 57982.2c90b33b0934522a.js} +2 -2
- django_cfg/static/frontend/admin/_next/static/chunks/{60181.86e18057c4caaa97.js → 60181.c94d78d10eb5da37.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/{60374.bde0ec1249aa79c6.js → 60374.5d80cfc45439b2b0.js} +1 -1
- 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/{6884.7b1db804c88280ed.js → 6884.624d563508cf6db4.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/{69436.9515b854cdf4b57a.js → 69436.be44021e3d7c99c7.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/{70628.00cdd98f672e684f.js → 70628.58e8c38a66543d5e.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/{73218.a826c2248612b37f.js → 73218.d712e7bd678e23a8.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/{76334.64fbaa923d9ac293.js → 76334.f43f2d8b4bbf8dd6.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/{7799.2b280f8ddf067d49.js → 7799.1575cc212bc750c7.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/{80574.620a8a5b4eb91c25.js → 80574.92638dd7b9979664.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/{81127.a0603c3394892d4e.js → 81127.3ead500eec887152.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/{8383.eb6188b22c453e14.js → 8383.e25a442df26b2e26.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/{85833.35e6ca25ac32a7d2.js → 85833.b0dead4fbcbfdd1b.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/{95365.fc9d7653a78839d0.js → 95365.2b430045fc2e5acf.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/{96168.eb7fdb721b9cdb00.js → 96168.b7197f890097df6e.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/{96424.0793b94836eb13a6.js → 96424.11d76570e9a94b85.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-69f737d4802cc5b7.js +1 -0
- django_cfg/static/frontend/admin/_next/static/chunks/pages/legal/{cookies-bb5507a122775f30.js → cookies-b39c7f22c066e2c6.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/pages/legal/{privacy-f8a3d8db1a197be3.js → privacy-5aedad0cf3a4f80f.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/pages/legal/{security-aba50addd2179f8f.js → security-dbd854d0d5d483e2.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/chunks/pages/legal/{terms-4aa35cd30b5c08ad.js → terms-f3e1d2b9e5edf12f.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-373fff8b42878e64.js +1 -0
- django_cfg/static/frontend/admin/_next/static/chunks/pages/private-fe9faa86ecdb0ce6.js +1 -0
- django_cfg/static/frontend/admin/_next/static/chunks/{webpack-905bba30877f6490.js → webpack-7c456a65e96eb97e.js} +1 -1
- django_cfg/static/frontend/admin/_next/static/css/5f9a37b6e6a72303.css +3 -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 -0
- django_cfg/static/frontend/admin/private.html +1 -1
- django_cfg/templates/admin/index.html +328 -62
- django_cfg/templates/admin/sections/commands_section.html +5 -549
- django_cfg/templates/admin/sections/documentation_section.html +5 -152
- django_cfg/templates/admin/sections/overview_section.html +5 -112
- django_cfg/templates/admin/sections/stats_section.html +5 -35
- django_cfg/templates/admin/sections/system_section.html +5 -99
- django_cfg/templates/admin/sections/widgets_section.html +10 -128
- django_cfg/templates/admin_old/index.html +80 -0
- django_cfg/templates/admin_old/sections/commands_section.html +549 -0
- django_cfg/templates/admin_old/sections/documentation_section.html +152 -0
- django_cfg/templates/admin_old/sections/overview_section.html +112 -0
- django_cfg/templates/admin_old/sections/stats_section.html +35 -0
- django_cfg/templates/admin_old/sections/system_section.html +99 -0
- django_cfg/templates/admin_old/sections/widgets_section.html +129 -0
- django_cfg/templates/unfold/layouts/skeleton.html +27 -0
- django_cfg/templatetags/django_cfg.py +53 -0
- {django_cfg-1.4.83.dist-info → django_cfg-1.4.85.dist-info}/METADATA +1 -1
- {django_cfg-1.4.83.dist-info → django_cfg-1.4.85.dist-info}/RECORD +160 -124
- django_cfg/static/frontend/admin/_next/static/chunks/6766.d62fed7cd4761148.js +0 -1
- django_cfg/static/frontend/admin/_next/static/chunks/pages/_app-16701a4e1bc3e6ac.js +0 -272
- django_cfg/static/frontend/admin/_next/static/chunks/pages/index-88751d9f44a32105.js +0 -1
- django_cfg/static/frontend/admin/_next/static/chunks/pages/private/centrifugo-1c5f00c26c77a47b.js +0 -1
- django_cfg/static/frontend/admin/_next/static/chunks/pages/private-2f58633ddf63a5bc.js +0 -1
- django_cfg/static/frontend/admin/_next/static/chunks/pages/ui-0e6c0e35862789ec.js +0 -1
- django_cfg/static/frontend/admin/_next/static/css/806300fb98c42afb.css +0 -3
- django_cfg/static/frontend/admin/_next/static/ibMHm1p66p0UGKsKnDWxn/_buildManifest.js +0 -1
- django_cfg/static/frontend/admin/ui.html +0 -92
- /django_cfg/static/frontend/admin/_next/static/{ibMHm1p66p0UGKsKnDWxn → BembwiEtlu4eFl3OX7n1k}/_ssgManifest.js +0 -0
- /django_cfg/templates/{admin → admin_old}/components/action_grid.html +0 -0
- /django_cfg/templates/{admin → admin_old}/components/card.html +0 -0
- /django_cfg/templates/{admin → admin_old}/components/data_table.html +0 -0
- /django_cfg/templates/{admin → admin_old}/components/metric_card.html +0 -0
- /django_cfg/templates/{admin → admin_old}/components/modal.html +0 -0
- /django_cfg/templates/{admin → admin_old}/components/progress_bar.html +0 -0
- /django_cfg/templates/{admin → admin_old}/components/section_header.html +0 -0
- /django_cfg/templates/{admin → admin_old}/components/stat_item.html +0 -0
- /django_cfg/templates/{admin → admin_old}/components/stats_grid.html +0 -0
- /django_cfg/templates/{admin → admin_old}/components/status_badge.html +0 -0
- /django_cfg/templates/{admin → admin_old}/components/user_avatar.html +0 -0
- /django_cfg/templates/{admin → admin_old}/constance/change_list.html +0 -0
- /django_cfg/templates/{admin → admin_old}/constance/includes/default_value.html +0 -0
- /django_cfg/templates/{admin → admin_old}/constance/includes/fieldset_header.html +0 -0
- /django_cfg/templates/{admin → admin_old}/constance/includes/results_list.html +0 -0
- /django_cfg/templates/{admin → admin_old}/constance/includes/setting_row.html +0 -0
- /django_cfg/templates/{admin → admin_old}/constance/includes/table_headers.html +0 -0
- /django_cfg/templates/{admin → admin_old}/examples/component_class_example.html +0 -0
- /django_cfg/templates/{admin → admin_old}/import_export/change_list_export.html +0 -0
- /django_cfg/templates/{admin → admin_old}/import_export/change_list_import.html +0 -0
- /django_cfg/templates/{admin → admin_old}/import_export/change_list_import_export.html +0 -0
- /django_cfg/templates/{admin → admin_old}/index_new.html +0 -0
- /django_cfg/templates/{admin → admin_old}/layouts/base_dashboard.html +0 -0
- /django_cfg/templates/{admin → admin_old}/layouts/dashboard_with_tabs.html +0 -0
- /django_cfg/templates/{admin → admin_old}/snippets/components/activity_tracker.html +0 -0
- /django_cfg/templates/{admin → admin_old}/snippets/components/charts_section.html +0 -0
- /django_cfg/templates/{admin → admin_old}/snippets/components/django_commands.html +0 -0
- /django_cfg/templates/{admin → admin_old}/snippets/components/quick_actions.html +0 -0
- /django_cfg/templates/{admin → admin_old}/snippets/components/recent_activity_improved.html +0 -0
- /django_cfg/templates/{admin → admin_old}/snippets/components/recent_users_table.html +0 -0
- /django_cfg/templates/{admin → admin_old}/snippets/components/stats_cards.html +0 -0
- /django_cfg/templates/{admin → admin_old}/snippets/components/stats_tiles.html +0 -0
- /django_cfg/templates/{admin → admin_old}/snippets/components/system_health.html +0 -0
- /django_cfg/templates/{admin → admin_old}/snippets/components/system_metrics.html +0 -0
- /django_cfg/templates/{admin → admin_old}/snippets/components/user_permissions.html +0 -0
- /django_cfg/templates/{admin → admin_old}/snippets/tabs/app_stats_tab.html +0 -0
- /django_cfg/templates/{admin → admin_old}/snippets/tabs/commands_tab.html +0 -0
- /django_cfg/templates/{admin → admin_old}/snippets/tabs/documentation_tab.html +0 -0
- /django_cfg/templates/{admin → admin_old}/snippets/tabs/overview_tab.html +0 -0
- /django_cfg/templates/{admin → admin_old}/snippets/tabs/stats_tab.html +0 -0
- /django_cfg/templates/{admin → admin_old}/snippets/tabs/users_tab.html +0 -0
- /django_cfg/templates/{admin → admin_old}/snippets/tabs/widgets_tab.html +0 -0
- /django_cfg/templates/{admin → admin_old}/snippets/zones/zones_table.html +0 -0
- {django_cfg-1.4.83.dist-info → django_cfg-1.4.85.dist-info}/WHEEL +0 -0
- {django_cfg-1.4.83.dist-info → django_cfg-1.4.85.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.4.83.dist-info → django_cfg-1.4.85.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Dashboard URLs
|
|
3
|
+
|
|
4
|
+
RESTful API endpoints for dashboard data organized by domain.
|
|
5
|
+
|
|
6
|
+
API Structure:
|
|
7
|
+
- /api/overview/ - Complete dashboard overview
|
|
8
|
+
- /api/statistics/ - Statistics endpoints (cards, users, apps)
|
|
9
|
+
- /api/system/ - System monitoring (health, metrics)
|
|
10
|
+
- /api/activity/ - Activity tracking (recent, actions)
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from django.urls import include, path
|
|
14
|
+
from rest_framework.routers import DefaultRouter
|
|
15
|
+
|
|
16
|
+
from .views import (
|
|
17
|
+
OverviewViewSet,
|
|
18
|
+
StatisticsViewSet,
|
|
19
|
+
SystemViewSet,
|
|
20
|
+
ActivityViewSet,
|
|
21
|
+
ChartsViewSet,
|
|
22
|
+
CommandsViewSet,
|
|
23
|
+
APIZonesViewSet,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
app_name = 'django_cfg_dashboard'
|
|
27
|
+
|
|
28
|
+
# Main router for ViewSets
|
|
29
|
+
router = DefaultRouter()
|
|
30
|
+
router.register(r'overview', OverviewViewSet, basename='overview')
|
|
31
|
+
router.register(r'statistics', StatisticsViewSet, basename='statistics')
|
|
32
|
+
router.register(r'system', SystemViewSet, basename='system')
|
|
33
|
+
router.register(r'activity', ActivityViewSet, basename='activity')
|
|
34
|
+
router.register(r'charts', ChartsViewSet, basename='charts')
|
|
35
|
+
router.register(r'commands', CommandsViewSet, basename='commands')
|
|
36
|
+
router.register(r'zones', APIZonesViewSet, basename='zones')
|
|
37
|
+
|
|
38
|
+
urlpatterns = [
|
|
39
|
+
# RESTful API endpoints using ViewSets
|
|
40
|
+
# Mounted at /cfg/dashboard/api/
|
|
41
|
+
path('api/', include(router.urls)),
|
|
42
|
+
]
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Dashboard Views
|
|
3
|
+
|
|
4
|
+
ViewSets organized by domain for better maintainability.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .overview_views import OverviewViewSet
|
|
8
|
+
from .statistics_views import StatisticsViewSet
|
|
9
|
+
from .system_views import SystemViewSet
|
|
10
|
+
from .activity_views import ActivityViewSet
|
|
11
|
+
from .charts_views import ChartsViewSet
|
|
12
|
+
from .commands_views import CommandsViewSet
|
|
13
|
+
from .apizones_views import APIZonesViewSet
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
'OverviewViewSet',
|
|
17
|
+
'StatisticsViewSet',
|
|
18
|
+
'SystemViewSet',
|
|
19
|
+
'ActivityViewSet',
|
|
20
|
+
'ChartsViewSet',
|
|
21
|
+
'CommandsViewSet',
|
|
22
|
+
'APIZonesViewSet',
|
|
23
|
+
]
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Activity ViewSet
|
|
3
|
+
|
|
4
|
+
Endpoints for activity tracking:
|
|
5
|
+
- GET /activity/recent/ - Recent activity entries
|
|
6
|
+
- GET /activity/actions/ - Quick action buttons
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
|
|
11
|
+
from drf_spectacular.utils import OpenApiParameter, 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
|
|
19
|
+
from ..serializers import ActivityEntrySerializer, QuickActionSerializer
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class ActivityViewSet(viewsets.GenericViewSet):
|
|
25
|
+
"""
|
|
26
|
+
Activity Tracking ViewSet
|
|
27
|
+
|
|
28
|
+
Provides endpoints for recent activity and quick actions.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
authentication_classes = [SessionAuthentication, BasicAuthentication]
|
|
32
|
+
permission_classes = [IsAdminUser]
|
|
33
|
+
serializer_class = ActivityEntrySerializer
|
|
34
|
+
|
|
35
|
+
@extend_schema(
|
|
36
|
+
summary="Get recent activity",
|
|
37
|
+
description="Retrieve recent system activity entries",
|
|
38
|
+
parameters=[
|
|
39
|
+
OpenApiParameter(
|
|
40
|
+
name='limit',
|
|
41
|
+
description='Maximum number of entries to return',
|
|
42
|
+
required=False,
|
|
43
|
+
type=int,
|
|
44
|
+
default=10
|
|
45
|
+
),
|
|
46
|
+
],
|
|
47
|
+
responses=ActivityEntrySerializer(many=True),
|
|
48
|
+
tags=["Dashboard - Activity"]
|
|
49
|
+
)
|
|
50
|
+
@action(detail=False, methods=['get'], url_path='recent', pagination_class=None, serializer_class=ActivityEntrySerializer)
|
|
51
|
+
def recent(self, request):
|
|
52
|
+
"""Get recent activity entries."""
|
|
53
|
+
try:
|
|
54
|
+
limit = int(request.query_params.get('limit', 10))
|
|
55
|
+
stats_service = StatisticsService()
|
|
56
|
+
activity = stats_service.get_recent_activity(limit=limit)
|
|
57
|
+
return Response(activity)
|
|
58
|
+
|
|
59
|
+
except Exception as e:
|
|
60
|
+
logger.error(f"Recent activity API error: {e}")
|
|
61
|
+
return Response({
|
|
62
|
+
'error': str(e)
|
|
63
|
+
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
64
|
+
|
|
65
|
+
@extend_schema(
|
|
66
|
+
summary="Get quick actions",
|
|
67
|
+
description="Retrieve quick action buttons for dashboard",
|
|
68
|
+
responses=QuickActionSerializer(many=True),
|
|
69
|
+
tags=["Dashboard - Activity"]
|
|
70
|
+
)
|
|
71
|
+
@action(detail=False, methods=['get'], url_path='actions', pagination_class=None, serializer_class=QuickActionSerializer)
|
|
72
|
+
def actions(self, request):
|
|
73
|
+
"""Get quick action buttons."""
|
|
74
|
+
try:
|
|
75
|
+
health_service = SystemHealthService()
|
|
76
|
+
actions = health_service.get_quick_actions()
|
|
77
|
+
return Response(actions)
|
|
78
|
+
|
|
79
|
+
except Exception as e:
|
|
80
|
+
logger.error(f"Quick actions API error: {e}")
|
|
81
|
+
return Response({
|
|
82
|
+
'error': str(e)
|
|
83
|
+
}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
|
@@ -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)
|