From 03ff40ddd400b3da48790348842ad1f52dd64817 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Barrag=C3=A1n=20Merino?= Date: Thu, 2 Jul 2015 11:33:26 +0200 Subject: [PATCH 1/2] Add system-stats endpoint --- settings/common.py | 4 ++++ settings/local.py.example | 7 ++++++ taiga/routers.py | 7 +++++- taiga/stats/__init__.py | 15 +++++++++++++ taiga/stats/api.py | 33 ++++++++++++++++++++++++++++ taiga/stats/apps.py | 30 ++++++++++++++++++++++++++ taiga/stats/permissions.py | 20 +++++++++++++++++ taiga/stats/routers.py | 20 +++++++++++++++++ taiga/stats/services.py | 44 ++++++++++++++++++++++++++++++++++++++ 9 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 taiga/stats/__init__.py create mode 100644 taiga/stats/api.py create mode 100644 taiga/stats/apps.py create mode 100644 taiga/stats/permissions.py create mode 100644 taiga/stats/routers.py create mode 100644 taiga/stats/services.py diff --git a/settings/common.py b/settings/common.py index 1a441e92..716760aa 100644 --- a/settings/common.py +++ b/settings/common.py @@ -283,6 +283,7 @@ INSTALLED_APPS = [ "taiga.mdrender", "taiga.export_import", "taiga.feedback", + "taiga.stats", "taiga.hooks.github", "taiga.hooks.gitlab", "taiga.hooks.bitbucket", @@ -434,6 +435,9 @@ TAGS_PREDEFINED_COLORS = ["#fce94f", "#edd400", "#c4a000", "#8ae234", FEEDBACK_ENABLED = True FEEDBACK_EMAIL = "support@taiga.io" +# Stats module settings +STATS_ENABLED = False + # 0 notifications will work in a synchronous way # >0 an external process will check the pending notifications and will send them # collapsed during that interval diff --git a/settings/local.py.example b/settings/local.py.example index a74baa27..dd4ce8c9 100644 --- a/settings/local.py.example +++ b/settings/local.py.example @@ -63,6 +63,13 @@ DATABASES = { #GITHUB_API_CLIENT_ID = "yourgithubclientid" #GITHUB_API_CLIENT_SECRET = "yourgithubclientsecret" +# FEEDBACK MODULE (See config in taiga-front too) +#FEEDBACK_ENABLED = True +#FEEDBACK_EMAIL = "support@taiga.io" + +# STATS MODULE +#STATS_ENABLED = False + # SITEMAP # If is True /front/sitemap.xml show a valid sitemap of taiga-front client #FRONT_SITEMAP_ENABLED = False diff --git a/taiga/routers.py b/taiga/routers.py index 968c6354..0f8bc675 100644 --- a/taiga/routers.py +++ b/taiga/routers.py @@ -1,3 +1,4 @@ + # Copyright (C) 2014 Andrey Antukh # Copyright (C) 2014 Jesús Espino # Copyright (C) 2014 David Barragán @@ -192,5 +193,9 @@ router.register(r"importer", ProjectImporterViewSet, base_name="importer") router.register(r"exporter", ProjectExporterViewSet, base_name="exporter") -# feedback +# Stats +# - see taiga.stats.routers and taiga.stats.apps + + +# Feedback # - see taiga.feedback.routers and taiga.feedback.apps diff --git a/taiga/stats/__init__.py b/taiga/stats/__init__.py new file mode 100644 index 00000000..92ed9d3d --- /dev/null +++ b/taiga/stats/__init__.py @@ -0,0 +1,15 @@ +# Copyright (C) 2015 Taiga Agile LLC +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +default_app_config = "taiga.stats.apps.StatsAppConfig" diff --git a/taiga/stats/api.py b/taiga/stats/api.py new file mode 100644 index 00000000..dae5cfdd --- /dev/null +++ b/taiga/stats/api.py @@ -0,0 +1,33 @@ +# Copyright (C) 2015 Taiga Agile LLC +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + + +from taiga.base.api import viewsets +from taiga.base import response + +from . import permissions +from . import services + + +class SystemStatsViewSet(viewsets.ViewSet): + permission_classes = (permissions.SystemStatsPermission,) + + def list(self, request, **kwargs): + stats = { + "total_users": services.get_total_users(), + "total_projects": services.get_total_projects(), + "total_userstories": services.grt_total_user_stories(), + "total_issues": services.get_total_issues(), + } + return response.Ok(stats) diff --git a/taiga/stats/apps.py b/taiga/stats/apps.py new file mode 100644 index 00000000..e8b8e63a --- /dev/null +++ b/taiga/stats/apps.py @@ -0,0 +1,30 @@ +# Copyright (C) 2015 Taiga Agile LLC +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +from django.apps import AppConfig +from django.apps import apps +from django.conf import settings +from django.conf.urls import include, url + +from .routers import router + + +class StatsAppConfig(AppConfig): + name = "taiga.stats" + verbose_name = "Stats" + + def ready(self): + if settings.STATS_ENABLED: + from taiga.urls import urlpatterns + urlpatterns.append(url(r'^api/v1/', include(router.urls))) diff --git a/taiga/stats/permissions.py b/taiga/stats/permissions.py new file mode 100644 index 00000000..0eb1a362 --- /dev/null +++ b/taiga/stats/permissions.py @@ -0,0 +1,20 @@ +# Copyright (C) 2015 Taiga Agile LLC +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + + +from taiga.base.api import permissions + + +class SystemStatsPermission(permissions.TaigaResourcePermission): + global_perms = permissions.AllowAny() diff --git a/taiga/stats/routers.py b/taiga/stats/routers.py new file mode 100644 index 00000000..7257b473 --- /dev/null +++ b/taiga/stats/routers.py @@ -0,0 +1,20 @@ +# Copyright (C) 2015 Taiga Agile LLC +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +from taiga.base import routers +from . import api + + +router = routers.DefaultRouter(trailing_slash=False) +router.register(r"stats/system", api.SystemStatsViewSet, base_name="system-stats") diff --git a/taiga/stats/services.py b/taiga/stats/services.py new file mode 100644 index 00000000..11f41d37 --- /dev/null +++ b/taiga/stats/services.py @@ -0,0 +1,44 @@ +# Copyright (C) 2015 Taiga Agile LLC +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + + +from django.apps import apps + + +def get_total_projects(): + model = apps.get_model("projects", "Project") + queryset = model.objects.all() + return queryset.count() + + +def grt_total_user_stories(): + model = apps.get_model("userstories", "UserStory") + queryset = model.objects.all() + return queryset.count() + + +def get_total_issues(): + model = apps.get_model("issues", "Issue") + queryset = model.objects.all() + return queryset.count() + + +def get_total_users(only_active=True, no_system=True): + model = apps.get_model("users", "User") + queryset = model.objects.all() + if only_active: + queryset = queryset.filter(is_active=True) + if no_system: + queryset = queryset.filter(is_system=False) + return queryset.count() From 69d1ed91a3b7838e3e90cc245b9e3783f620b120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Barrag=C3=A1n=20Merino?= Date: Thu, 2 Jul 2015 11:33:42 +0200 Subject: [PATCH 2/2] Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9798b058..8798a560 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ ### Misc - API: Mixin fields 'users', 'members' and 'memberships' in ProjectDetailSerializer +- API: Add stats/system resource with global server stats (total project, total users....) - Lots of small and not so small bugfixes.