mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-17 05:41:25 +02:00
Merge pull request #3689 from modoboa/dashboard_statistics_widget
Added widget to display global stats about the instance
This commit is contained in:
@@ -10,4 +10,7 @@ export default {
|
||||
getNewsFeed() {
|
||||
return repository.get('/admin/news_feed/')
|
||||
},
|
||||
getStatistics() {
|
||||
return repository.get('/admin/statistics/')
|
||||
},
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
<template>
|
||||
<v-card :title="$gettext('Statistics')">
|
||||
<v-card-text>
|
||||
<v-table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{ $gettext('Domain count') }}</td>
|
||||
<td>{{ statistics.domain_count }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ $gettext('Domain alias count') }}</td>
|
||||
<td>{{ statistics.domain_alias_count }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ $gettext('Account count') }}</td>
|
||||
<td>{{ statistics.account_count }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ $gettext('Alias count') }}</td>
|
||||
<td>{{ statistics.alias_count }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</v-table>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import adminApi from '@/api/admin'
|
||||
|
||||
const statistics = ref({})
|
||||
|
||||
const response = await adminApi.getStatistics()
|
||||
statistics.value = response.data
|
||||
</script>
|
||||
@@ -7,7 +7,12 @@
|
||||
<v-row>
|
||||
<v-col sm="12" md="6">
|
||||
<NewsFeedWidget />
|
||||
<GlobalStatisticsWidget
|
||||
v-if="authStore.authUser.role === constants.SUPER_ADMIN"
|
||||
class="mt-4"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col sm="12" md="6"> </v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
@@ -15,10 +20,15 @@
|
||||
<script setup>
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { useGettext } from 'vue3-gettext'
|
||||
import { useAuthStore } from '@/stores'
|
||||
|
||||
import GlobalStatisticsWidget from '@/components/admin/dashboard/GlobalStatisticsWidget'
|
||||
import NewsFeedWidget from '@/components/admin/dashboard/NewsFeedWidget'
|
||||
import parametersApi from '@/api/parameters'
|
||||
import constants from '@/constants.json'
|
||||
|
||||
const { $gettext } = useGettext()
|
||||
const authStore = useAuthStore()
|
||||
|
||||
const welcomeMsg = ref('')
|
||||
|
||||
|
||||
@@ -692,3 +692,11 @@ class ThemeSerializer(serializers.Serializer):
|
||||
theme_primary_color_light = serializers.CharField(default="#3688F9")
|
||||
theme_secondary_color = serializers.CharField(default="#F18429")
|
||||
theme_label_color = serializers.CharField(default="#616161")
|
||||
|
||||
|
||||
class StatisticsSerializer(serializers.Serializer):
|
||||
|
||||
domain_count = serializers.IntegerField()
|
||||
domain_alias_count = serializers.IntegerField()
|
||||
account_count = serializers.IntegerField()
|
||||
alias_count = serializers.IntegerField()
|
||||
|
||||
@@ -658,3 +658,21 @@ class NewsFeedAPIViewTestCase(ModoAPITestCase):
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertIn("modoboa", response.json()[0]["link"])
|
||||
|
||||
|
||||
class StatisticsAPIViewTestCase(ModoAPITestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
"""Create test data."""
|
||||
super().setUpTestData()
|
||||
factories.populate_database()
|
||||
|
||||
def test_get_statistics(self):
|
||||
url = reverse("v2:statistics")
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
stats = response.json()
|
||||
self.assertEqual(stats["domain_count"], 2)
|
||||
self.assertEqual(stats["account_count"], 5)
|
||||
self.assertEqual(stats["alias_count"], 3)
|
||||
|
||||
@@ -42,6 +42,11 @@ urlpatterns += [
|
||||
views.NewsFeedAPIView.as_view(),
|
||||
name="news-feed",
|
||||
),
|
||||
path(
|
||||
"admin/statistics/",
|
||||
views.StatisticsAPIView.as_view(),
|
||||
name="statistics",
|
||||
),
|
||||
path("capabilities/", views.CapabilitiesAPIView.as_view(), name="capabilities"),
|
||||
path("theme/", views.ThemeAPIView.as_view(), name="theme"),
|
||||
]
|
||||
|
||||
@@ -14,7 +14,8 @@ from drf_spectacular.utils import extend_schema
|
||||
from rest_framework import permissions, response
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from modoboa.core import signals
|
||||
from modoboa.admin import models as admin_models
|
||||
from modoboa.core import models, signals
|
||||
from modoboa.core.utils import check_for_updates, get_capabilities
|
||||
from modoboa.lib.permissions import IsSuperUser, IsPrivilegedUser
|
||||
from modoboa.lib.throttle import (
|
||||
@@ -226,3 +227,21 @@ class NewsFeedAPIView(APIView):
|
||||
|
||||
serializer = serializers.NewsFeedEntrySerializer(entries, many=True)
|
||||
return response.Response(serializer.data)
|
||||
|
||||
|
||||
class StatisticsAPIView(APIView):
|
||||
"""Return some statistics about this modoboa instance."""
|
||||
|
||||
permission_classes = [permissions.IsAuthenticated, IsSuperUser]
|
||||
throttle_classes = [UserLesserDdosUser]
|
||||
|
||||
@extend_schema(responses=serializers.StatisticsSerializer())
|
||||
def get(self, request, *args, **kwargs):
|
||||
data = {
|
||||
"domain_count": admin_models.Domain.objects.count(),
|
||||
"domain_alias_count": admin_models.DomainAlias.objects.count(),
|
||||
"account_count": models.User.objects.count(),
|
||||
"alias_count": admin_models.Alias.objects.filter(internal=False).count(),
|
||||
}
|
||||
serializer = serializers.StatisticsSerializer(data)
|
||||
return response.Response(serializer.data)
|
||||
|
||||
Reference in New Issue
Block a user