Improve statistics subclassing. Split class module into classes and renderers.
Signed-off-by: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>
This commit is contained in:
@@ -106,6 +106,8 @@
|
|||||||
- After queuing a chart for update, the view will now redirect
|
- After queuing a chart for update, the view will now redirect
|
||||||
to the same chart.
|
to the same chart.
|
||||||
- The multiple document action dropdown is now sorted alphabetically.
|
- The multiple document action dropdown is now sorted alphabetically.
|
||||||
|
- Improve statistics subclassing. Split class module into classes
|
||||||
|
and renderers.
|
||||||
|
|
||||||
3.0.3 (2018-08-17)
|
3.0.3 (2018-08-17)
|
||||||
==================
|
==================
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from django.utils.translation import ugettext_lazy as _
|
|||||||
|
|
||||||
import qsstats
|
import qsstats
|
||||||
|
|
||||||
from mayan_statistics.classes import StatisticNamespace, CharJSLine
|
from mayan_statistics import StatisticLineChart, StatisticNamespace
|
||||||
|
|
||||||
from .permissions import permission_document_view
|
from .permissions import permission_document_view
|
||||||
|
|
||||||
@@ -230,44 +230,44 @@ def total_document_page_per_month():
|
|||||||
|
|
||||||
namespace = StatisticNamespace(slug='documents', label=_('Documents'))
|
namespace = StatisticNamespace(slug='documents', label=_('Documents'))
|
||||||
namespace.add_statistic(
|
namespace.add_statistic(
|
||||||
|
klass=StatisticLineChart,
|
||||||
slug='new-documents-per-month',
|
slug='new-documents-per-month',
|
||||||
label=_('New documents per month'),
|
label=_('New documents per month'),
|
||||||
func=new_documents_per_month,
|
func=new_documents_per_month,
|
||||||
renderer=CharJSLine,
|
|
||||||
minute='0'
|
minute='0'
|
||||||
)
|
)
|
||||||
namespace.add_statistic(
|
namespace.add_statistic(
|
||||||
|
klass=StatisticLineChart,
|
||||||
slug='new-document-versions-per-month',
|
slug='new-document-versions-per-month',
|
||||||
label=_('New document versions per month'),
|
label=_('New document versions per month'),
|
||||||
func=new_document_versions_per_month,
|
func=new_document_versions_per_month,
|
||||||
renderer=CharJSLine,
|
|
||||||
minute='0'
|
minute='0'
|
||||||
)
|
)
|
||||||
namespace.add_statistic(
|
namespace.add_statistic(
|
||||||
|
klass=StatisticLineChart,
|
||||||
slug='new-document-pages-per-month',
|
slug='new-document-pages-per-month',
|
||||||
label=_('New document pages per month'),
|
label=_('New document pages per month'),
|
||||||
func=new_document_pages_per_month,
|
func=new_document_pages_per_month,
|
||||||
renderer=CharJSLine,
|
|
||||||
minute='0'
|
minute='0'
|
||||||
)
|
)
|
||||||
namespace.add_statistic(
|
namespace.add_statistic(
|
||||||
|
klass=StatisticLineChart,
|
||||||
slug='total-documents-at-each-month',
|
slug='total-documents-at-each-month',
|
||||||
label=_('Total documents at each month'),
|
label=_('Total documents at each month'),
|
||||||
func=total_document_per_month,
|
func=total_document_per_month,
|
||||||
renderer=CharJSLine,
|
|
||||||
minute='0'
|
minute='0'
|
||||||
)
|
)
|
||||||
namespace.add_statistic(
|
namespace.add_statistic(
|
||||||
|
klass=StatisticLineChart,
|
||||||
slug='total-document-versions-at-each-month',
|
slug='total-document-versions-at-each-month',
|
||||||
label=_('Total document versions at each month'),
|
label=_('Total document versions at each month'),
|
||||||
func=total_document_version_per_month,
|
func=total_document_version_per_month,
|
||||||
renderer=CharJSLine,
|
|
||||||
minute='0'
|
minute='0'
|
||||||
)
|
)
|
||||||
namespace.add_statistic(
|
namespace.add_statistic(
|
||||||
|
klass=StatisticLineChart,
|
||||||
slug='total-document-pages-at-each-month',
|
slug='total-document-pages-at-each-month',
|
||||||
label=_('Total document pages at each month'),
|
label=_('Total document pages at each month'),
|
||||||
func=total_document_page_per_month,
|
func=total_document_page_per_month,
|
||||||
renderer=CharJSLine,
|
|
||||||
minute='0'
|
minute='0'
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from .classes import StatisticLineChart, StatisticNamespace
|
||||||
|
|
||||||
default_app_config = 'mayan_statistics.apps.StatisticsApp'
|
default_app_config = 'mayan_statistics.apps.StatisticsApp'
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ from common import MayanAppConfig, menu_object, menu_secondary, menu_tools
|
|||||||
|
|
||||||
from navigation import SourceColumn
|
from navigation import SourceColumn
|
||||||
|
|
||||||
from .classes import Statistic, StatisticNamespace
|
from .classes import Statistic, StatisticLineChart, StatisticNamespace
|
||||||
from .links import (
|
from .links import (
|
||||||
link_execute, link_namespace_details, link_namespace_list,
|
link_execute, link_namespace_details, link_namespace_list,
|
||||||
link_statistics, link_view
|
link_statistics, link_view
|
||||||
@@ -29,9 +29,9 @@ class StatisticsApp(MayanAppConfig):
|
|||||||
super(StatisticsApp, self).ready()
|
super(StatisticsApp, self).ready()
|
||||||
|
|
||||||
SourceColumn(
|
SourceColumn(
|
||||||
source=Statistic,
|
source=StatisticLineChart,
|
||||||
# Translators: Schedule here is a verb, the 'schedule' at which the
|
# Translators: Schedule here is a verb, the 'schedule' at
|
||||||
# statistic will be updated
|
# which the statistic will be updated
|
||||||
label=_('Schedule'),
|
label=_('Schedule'),
|
||||||
attribute='schedule',
|
attribute='schedule',
|
||||||
)
|
)
|
||||||
@@ -54,7 +54,7 @@ class StatisticsApp(MayanAppConfig):
|
|||||||
)
|
)
|
||||||
|
|
||||||
menu_object.bind_links(
|
menu_object.bind_links(
|
||||||
links=(link_execute, link_view), sources=(Statistic,)
|
links=(link_execute, link_view), sources=(StatisticLineChart,)
|
||||||
)
|
)
|
||||||
menu_object.bind_links(
|
menu_object.bind_links(
|
||||||
links=(link_namespace_details,), sources=(StatisticNamespace,)
|
links=(link_namespace_details,), sources=(StatisticNamespace,)
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ from celery.schedules import crontab
|
|||||||
|
|
||||||
from mayan.celery import app
|
from mayan.celery import app
|
||||||
|
|
||||||
|
from .renderers import ChartJSLine
|
||||||
|
|
||||||
|
|
||||||
@python_2_unicode_compatible
|
@python_2_unicode_compatible
|
||||||
class StatisticNamespace(object):
|
class StatisticNamespace(object):
|
||||||
@@ -31,8 +33,8 @@ class StatisticNamespace(object):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return force_text(self.label)
|
return force_text(self.label)
|
||||||
|
|
||||||
def add_statistic(self, *args, **kwargs):
|
def add_statistic(self, klass, *args, **kwargs):
|
||||||
statistic = Statistic(*args, **kwargs)
|
statistic = klass(*args, **kwargs)
|
||||||
statistic.namespace = self
|
statistic.namespace = self
|
||||||
self._statistics.append(statistic)
|
self._statistics.append(statistic)
|
||||||
|
|
||||||
@@ -44,6 +46,7 @@ class StatisticNamespace(object):
|
|||||||
@python_2_unicode_compatible
|
@python_2_unicode_compatible
|
||||||
class Statistic(object):
|
class Statistic(object):
|
||||||
_registry = {}
|
_registry = {}
|
||||||
|
renderer = None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def purge_schedules():
|
def purge_schedules():
|
||||||
@@ -82,11 +85,10 @@ class Statistic(object):
|
|||||||
def get_task_names(cls):
|
def get_task_names(cls):
|
||||||
return [task.get_task_name() for task in cls.get_all()]
|
return [task.get_task_name() for task in cls.get_all()]
|
||||||
|
|
||||||
def __init__(self, slug, label, func, renderer, minute='*', hour='*', day_of_week='*', day_of_month='*', month_of_year='*'):
|
def __init__(self, slug, label, func, minute='*', hour='*', day_of_week='*', day_of_month='*', month_of_year='*'):
|
||||||
self.slug = slug
|
self.slug = slug
|
||||||
self.label = label
|
self.label = label
|
||||||
self.func = func
|
self.func = func
|
||||||
self.renderer = renderer
|
|
||||||
|
|
||||||
self.schedule = crontab(
|
self.schedule = crontab(
|
||||||
minute=minute, hour=hour, day_of_week=day_of_week,
|
minute=minute, hour=hour, day_of_week=day_of_week,
|
||||||
@@ -123,7 +125,9 @@ class Statistic(object):
|
|||||||
return 'mayan_statistics.task_execute_statistic_{}'.format(self.slug)
|
return 'mayan_statistics.task_execute_statistic_{}'.format(self.slug)
|
||||||
|
|
||||||
def store_results(self, results):
|
def store_results(self, results):
|
||||||
from .models import StatisticResult
|
StatisticResult = apps.get_model(
|
||||||
|
app_label='mayan_statistics', model_name='StatisticResult'
|
||||||
|
)
|
||||||
|
|
||||||
StatisticResult.objects.filter(slug=self.slug).delete()
|
StatisticResult.objects.filter(slug=self.slug).delete()
|
||||||
|
|
||||||
@@ -133,7 +137,9 @@ class Statistic(object):
|
|||||||
statistic_result.store_data(data=results)
|
statistic_result.store_data(data=results)
|
||||||
|
|
||||||
def get_results(self):
|
def get_results(self):
|
||||||
from .models import StatisticResult
|
StatisticResult = apps.get_model(
|
||||||
|
app_label='mayan_statistics', model_name='StatisticResult'
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return StatisticResult.objects.get(slug=self.slug).get_data()
|
return StatisticResult.objects.get(slug=self.slug).get_data()
|
||||||
@@ -144,66 +150,5 @@ class Statistic(object):
|
|||||||
return self.renderer(data=self.get_results()).get_chart_data()
|
return self.renderer(data=self.get_results()).get_chart_data()
|
||||||
|
|
||||||
|
|
||||||
class ChartRenderer(object):
|
class StatisticLineChart(Statistic):
|
||||||
def __init__(self, data):
|
renderer = ChartJSLine
|
||||||
self.data = data
|
|
||||||
|
|
||||||
def get_chart_data(self):
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
|
|
||||||
class CharJSLine(ChartRenderer):
|
|
||||||
template_name = 'statistics/backends/chartjs/line.html'
|
|
||||||
|
|
||||||
dataset_palette = (
|
|
||||||
{
|
|
||||||
'fillColor': "rgba(220,220,220,0.2)",
|
|
||||||
'strokeColor': "rgba(220,220,220,1)",
|
|
||||||
'pointColor': "rgba(220,220,220,1)",
|
|
||||||
'pointStrokeColor': "#fff",
|
|
||||||
'pointHighlightFill': "#fff",
|
|
||||||
'pointHighlightStroke': "rgba(220,220,220,1)",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'fillColor': "rgba(151,187,205,0.2)",
|
|
||||||
'strokeColor': "rgba(151,187,205,1)",
|
|
||||||
'pointColor': "rgba(151,187,205,1)",
|
|
||||||
'pointStrokeColor': "#fff",
|
|
||||||
'pointHighlightFill': "#fff",
|
|
||||||
'pointHighlightStroke': "rgba(151,187,205,1)",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_chart_data(self):
|
|
||||||
labels = []
|
|
||||||
datasets = []
|
|
||||||
|
|
||||||
for count, serie in enumerate(self.data['series'].items()):
|
|
||||||
series_name, series_data = serie
|
|
||||||
dataset_labels = []
|
|
||||||
dataset_values = []
|
|
||||||
|
|
||||||
for data_point in series_data:
|
|
||||||
dataset_labels.extend(data_point.keys())
|
|
||||||
dataset_values.extend(data_point.values())
|
|
||||||
|
|
||||||
labels = dataset_labels
|
|
||||||
dataset = {
|
|
||||||
'label': series_name,
|
|
||||||
'data': dataset_values,
|
|
||||||
}
|
|
||||||
dataset.update(
|
|
||||||
CharJSLine.dataset_palette[
|
|
||||||
count % len(CharJSLine.dataset_palette)
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
datasets.append(dataset)
|
|
||||||
|
|
||||||
data = {
|
|
||||||
'labels': labels,
|
|
||||||
'datasets': datasets,
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return json.dumps(data)
|
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
from django.apps import apps
|
||||||
|
from django.utils.encoding import force_text, python_2_unicode_compatible
|
||||||
|
|
||||||
|
from celery.schedules import crontab
|
||||||
|
|
||||||
|
from mayan.celery import app
|
||||||
|
|
||||||
|
|
||||||
|
class ChartRenderer(object):
|
||||||
|
def __init__(self, data):
|
||||||
|
self.data = data
|
||||||
|
|
||||||
|
def get_chart_data(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
class ChartJSLine(ChartRenderer):
|
||||||
|
template_name = 'statistics/renderers/chartjs/line.html'
|
||||||
|
|
||||||
|
dataset_palette = (
|
||||||
|
{
|
||||||
|
'fillColor': "rgba(220,220,220,0.2)",
|
||||||
|
'strokeColor': "rgba(220,220,220,1)",
|
||||||
|
'pointColor': "rgba(220,220,220,1)",
|
||||||
|
'pointStrokeColor': "#fff",
|
||||||
|
'pointHighlightFill': "#fff",
|
||||||
|
'pointHighlightStroke': "rgba(220,220,220,1)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'fillColor': "rgba(151,187,205,0.2)",
|
||||||
|
'strokeColor': "rgba(151,187,205,1)",
|
||||||
|
'pointColor': "rgba(151,187,205,1)",
|
||||||
|
'pointStrokeColor': "#fff",
|
||||||
|
'pointHighlightFill': "#fff",
|
||||||
|
'pointHighlightStroke': "rgba(151,187,205,1)",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_chart_data(self):
|
||||||
|
labels = []
|
||||||
|
datasets = []
|
||||||
|
|
||||||
|
for count, serie in enumerate(self.data['series'].items()):
|
||||||
|
series_name, series_data = serie
|
||||||
|
dataset_labels = []
|
||||||
|
dataset_values = []
|
||||||
|
|
||||||
|
for data_point in series_data:
|
||||||
|
dataset_labels.extend(data_point.keys())
|
||||||
|
dataset_values.extend(data_point.values())
|
||||||
|
|
||||||
|
labels = dataset_labels
|
||||||
|
dataset = {
|
||||||
|
'label': series_name,
|
||||||
|
'data': dataset_values,
|
||||||
|
}
|
||||||
|
dataset.update(
|
||||||
|
ChartJSLine.dataset_palette[
|
||||||
|
count % len(ChartJSLine.dataset_palette)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
datasets.append(dataset)
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'labels': labels,
|
||||||
|
'datasets': datasets,
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.dumps(data)
|
||||||
Reference in New Issue
Block a user