Add support for multiple dashboards.
Add support for removing dashboard widgets. Signed-off-by: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>
This commit is contained in:
@@ -20,6 +20,8 @@
|
|||||||
- Add support for unbinding sub menus.
|
- Add support for unbinding sub menus.
|
||||||
- Fix mailing profile test view.
|
- Fix mailing profile test view.
|
||||||
- Disregard the last 3 dots that mark the end of the YAML document.
|
- Disregard the last 3 dots that mark the end of the YAML document.
|
||||||
|
- Add support for multiple dashboards.
|
||||||
|
- Add support for removing dashboard widgets.
|
||||||
|
|
||||||
2.6.4 (2017-07-26)
|
2.6.4 (2017-07-26)
|
||||||
==================
|
==================
|
||||||
|
|||||||
@@ -72,9 +72,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% get_dashboard_widgets as dashboard_widgets %}
|
{% get_dashboard 'main' as dashboard %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{% for widget in dashboard_widgets %}
|
{% for widget in dashboard.get_widgets %}
|
||||||
{% include 'appearance/dashboard_widget.html' %}
|
{% include 'appearance/dashboard_widget.html' %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -11,10 +11,11 @@ from django.utils.translation import ugettext_lazy as _
|
|||||||
|
|
||||||
from acls import ModelPermission
|
from acls import ModelPermission
|
||||||
from common import MayanAppConfig, menu_facet, menu_main, menu_sidebar
|
from common import MayanAppConfig, menu_facet, menu_main, menu_sidebar
|
||||||
from common.classes import DashboardWidget
|
from common.dashboards import dashboard_main
|
||||||
from mayan.celery import app
|
from mayan.celery import app
|
||||||
from rest_api.classes import APIEndPoint
|
from rest_api.classes import APIEndPoint
|
||||||
|
|
||||||
|
from .dashboard_widgets import widget_checkouts
|
||||||
from .handlers import check_new_version_creation
|
from .handlers import check_new_version_creation
|
||||||
from .links import (
|
from .links import (
|
||||||
link_checkin_document, link_checkout_document, link_checkout_info,
|
link_checkin_document, link_checkout_document, link_checkout_info,
|
||||||
@@ -49,13 +50,6 @@ class CheckoutsApp(MayanAppConfig):
|
|||||||
|
|
||||||
DocumentCheckout = self.get_model('DocumentCheckout')
|
DocumentCheckout = self.get_model('DocumentCheckout')
|
||||||
|
|
||||||
DashboardWidget(
|
|
||||||
icon='fa fa-shopping-cart',
|
|
||||||
queryset=DocumentCheckout.objects.all(),
|
|
||||||
label=_('Checkedout documents'),
|
|
||||||
link=reverse_lazy('checkouts:checkout_list')
|
|
||||||
)
|
|
||||||
|
|
||||||
Document.add_to_class(
|
Document.add_to_class(
|
||||||
'check_in',
|
'check_in',
|
||||||
lambda document, user=None: DocumentCheckout.objects.check_in_document(document, user)
|
lambda document, user=None: DocumentCheckout.objects.check_in_document(document, user)
|
||||||
@@ -114,6 +108,8 @@ class CheckoutsApp(MayanAppConfig):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
dashboard_main.add_widget(order=-1, widget=widget_checkouts)
|
||||||
|
|
||||||
menu_facet.bind_links(links=(link_checkout_info,), sources=(Document,))
|
menu_facet.bind_links(links=(link_checkout_info,), sources=(Document,))
|
||||||
menu_main.bind_links(links=(link_checkout_list,), position=98)
|
menu_main.bind_links(links=(link_checkout_list,), position=98)
|
||||||
menu_sidebar.bind_links(
|
menu_sidebar.bind_links(
|
||||||
|
|||||||
21
mayan/apps/checkouts/dashboard_widgets.py
Normal file
21
mayan/apps/checkouts/dashboard_widgets.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
|
from django.apps import apps
|
||||||
|
from django.urls import reverse_lazy
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from common.classes import DashboardWidget
|
||||||
|
|
||||||
|
|
||||||
|
def checkedout_documents_queryset():
|
||||||
|
DocumentCheckout = apps.get_model(
|
||||||
|
app_label='checkouts', model_name='DocumentCheckout'
|
||||||
|
)
|
||||||
|
return DocumentCheckout.objects.all()
|
||||||
|
|
||||||
|
|
||||||
|
widget_checkouts = DashboardWidget(
|
||||||
|
label=_('Checkedout documents'),
|
||||||
|
link=reverse_lazy('checkouts:checkout_list'),
|
||||||
|
icon='fa fa-shopping-cart', queryset=checkedout_documents_queryset
|
||||||
|
)
|
||||||
@@ -45,6 +45,43 @@ class Collection(object):
|
|||||||
return self._model.objects.all()
|
return self._model.objects.all()
|
||||||
|
|
||||||
|
|
||||||
|
class Dashboard(object):
|
||||||
|
_registry = {}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get(cls, name):
|
||||||
|
return cls._registry[name]
|
||||||
|
|
||||||
|
def __init__(self, name, label):
|
||||||
|
self.name = name
|
||||||
|
self.label = label
|
||||||
|
self.widgets = {}
|
||||||
|
self.removed_widgets = []
|
||||||
|
self.__class__._registry[name] = self
|
||||||
|
|
||||||
|
def add_widget(self, widget, order=0):
|
||||||
|
self.widgets[widget] = {'widget': widget, 'order': order}
|
||||||
|
|
||||||
|
def get_widgets(self):
|
||||||
|
"""
|
||||||
|
Returns a list of widgets sorted by their 'order'.
|
||||||
|
If two or more widgets have the same 'order', sort by label.
|
||||||
|
"""
|
||||||
|
return map(
|
||||||
|
lambda x: x['widget'],
|
||||||
|
filter(
|
||||||
|
lambda x: x['widget'] not in self.removed_widgets,
|
||||||
|
sorted(
|
||||||
|
self.widgets.values(),
|
||||||
|
key=lambda x: (x['order'], x['widget'].label)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def remove_widget(self, widget):
|
||||||
|
self.removed_widgets.append(widget)
|
||||||
|
|
||||||
|
|
||||||
class DashboardWidget(object):
|
class DashboardWidget(object):
|
||||||
_registry = []
|
_registry = []
|
||||||
|
|
||||||
|
|||||||
7
mayan/apps/common/dashboards.py
Normal file
7
mayan/apps/common/dashboards.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from .classes import Dashboard
|
||||||
|
|
||||||
|
dashboard_main = Dashboard(name='main', label=_('Main'))
|
||||||
@@ -6,7 +6,6 @@ from django.core.exceptions import PermissionDenied
|
|||||||
from django.db.models.query import QuerySet
|
from django.db.models.query import QuerySet
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
from django.shortcuts import resolve_url
|
from django.shortcuts import resolve_url
|
||||||
from django.urls import reverse
|
|
||||||
from django.utils.translation import ungettext, ugettext_lazy as _
|
from django.utils.translation import ungettext, ugettext_lazy as _
|
||||||
|
|
||||||
from permissions import Permission
|
from permissions import Permission
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from django.utils.encoding import force_text
|
|||||||
|
|
||||||
import mayan
|
import mayan
|
||||||
|
|
||||||
from ..classes import Collection, DashboardWidget
|
from ..classes import Collection, Dashboard
|
||||||
from ..utils import return_attrib
|
from ..utils import return_attrib
|
||||||
|
|
||||||
register = Library()
|
register = Library()
|
||||||
@@ -30,8 +30,8 @@ def get_collections():
|
|||||||
|
|
||||||
|
|
||||||
@register.simple_tag
|
@register.simple_tag
|
||||||
def get_dashboard_widgets():
|
def get_dashboard(name):
|
||||||
return DashboardWidget.get_all()
|
return Dashboard.get(name=name)
|
||||||
|
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ from datetime import timedelta
|
|||||||
|
|
||||||
from kombu import Exchange, Queue
|
from kombu import Exchange, Queue
|
||||||
|
|
||||||
from django.urls import reverse_lazy
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from acls import ModelPermission
|
from acls import ModelPermission
|
||||||
@@ -14,7 +13,8 @@ from common import (
|
|||||||
MayanAppConfig, MissingItem, menu_facet, menu_main, menu_object,
|
MayanAppConfig, MissingItem, menu_facet, menu_main, menu_object,
|
||||||
menu_secondary, menu_setup, menu_sidebar, menu_multi_item, menu_tools
|
menu_secondary, menu_setup, menu_sidebar, menu_multi_item, menu_tools
|
||||||
)
|
)
|
||||||
from common.classes import DashboardWidget, ModelAttribute
|
from common.classes import ModelAttribute
|
||||||
|
from common.dashboards import dashboard_main
|
||||||
from common.signals import post_initial_setup
|
from common.signals import post_initial_setup
|
||||||
from common.widgets import two_state_template
|
from common.widgets import two_state_template
|
||||||
from converter.links import link_transformation_list
|
from converter.links import link_transformation_list
|
||||||
@@ -31,6 +31,11 @@ from rest_api.classes import APIEndPoint
|
|||||||
from rest_api.fields import DynamicSerializerField
|
from rest_api.fields import DynamicSerializerField
|
||||||
from statistics.classes import StatisticNamespace, CharJSLine
|
from statistics.classes import StatisticNamespace, CharJSLine
|
||||||
|
|
||||||
|
from .dashboard_widgets import (
|
||||||
|
widget_document_types, widget_documents_in_trash,
|
||||||
|
widget_new_documents_this_month, widget_pages_per_month,
|
||||||
|
widget_total_documents
|
||||||
|
)
|
||||||
from .handlers import (
|
from .handlers import (
|
||||||
create_default_document_type, handler_scan_duplicates_for
|
create_default_document_type, handler_scan_duplicates_for
|
||||||
)
|
)
|
||||||
@@ -81,7 +86,6 @@ from .search import document_search, document_page_search # NOQA
|
|||||||
from .signals import post_version_upload
|
from .signals import post_version_upload
|
||||||
from .statistics import (
|
from .statistics import (
|
||||||
new_documents_per_month, new_document_pages_per_month,
|
new_documents_per_month, new_document_pages_per_month,
|
||||||
new_document_pages_this_month, new_documents_this_month,
|
|
||||||
new_document_versions_per_month, total_document_per_month,
|
new_document_versions_per_month, total_document_per_month,
|
||||||
total_document_page_per_month, total_document_version_per_month
|
total_document_page_per_month, total_document_version_per_month
|
||||||
)
|
)
|
||||||
@@ -113,42 +117,6 @@ class DocumentsApp(MayanAppConfig):
|
|||||||
serializer_class='documents.serializers.DocumentSerializer'
|
serializer_class='documents.serializers.DocumentSerializer'
|
||||||
)
|
)
|
||||||
|
|
||||||
DashboardWidget(
|
|
||||||
func=new_document_pages_this_month, icon='fa fa-calendar',
|
|
||||||
label=_('New pages this month'),
|
|
||||||
link=reverse_lazy(
|
|
||||||
'statistics:statistic_detail',
|
|
||||||
args=('new-document-pages-per-month',)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
DashboardWidget(
|
|
||||||
func=new_documents_this_month, icon='fa fa-calendar',
|
|
||||||
label=_('New documents this month'),
|
|
||||||
link=reverse_lazy(
|
|
||||||
'statistics:statistic_detail',
|
|
||||||
args=('new-documents-per-month',)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
DashboardWidget(
|
|
||||||
icon='fa fa-file', queryset=Document.objects.all(),
|
|
||||||
label=_('Total documents'),
|
|
||||||
link=reverse_lazy('documents:document_list')
|
|
||||||
)
|
|
||||||
|
|
||||||
DashboardWidget(
|
|
||||||
icon='fa fa-book', queryset=DocumentType.objects.all(),
|
|
||||||
label=_('Document types'),
|
|
||||||
link=reverse_lazy('documents:document_type_list')
|
|
||||||
)
|
|
||||||
|
|
||||||
DashboardWidget(
|
|
||||||
icon='fa fa-trash', queryset=DeletedDocument.objects.all(),
|
|
||||||
label=_('Documents in trash'),
|
|
||||||
link=reverse_lazy('documents:document_list_deleted')
|
|
||||||
)
|
|
||||||
|
|
||||||
MissingItem(
|
MissingItem(
|
||||||
label=_('Create a document type'),
|
label=_('Create a document type'),
|
||||||
description=_(
|
description=_(
|
||||||
@@ -365,6 +333,12 @@ class DocumentsApp(MayanAppConfig):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
dashboard_main.add_widget(widget=widget_document_types)
|
||||||
|
dashboard_main.add_widget(widget=widget_documents_in_trash)
|
||||||
|
dashboard_main.add_widget(widget=widget_new_documents_this_month)
|
||||||
|
dashboard_main.add_widget(widget=widget_pages_per_month)
|
||||||
|
dashboard_main.add_widget(widget=widget_total_documents)
|
||||||
|
|
||||||
menu_documents.bind_links(
|
menu_documents.bind_links(
|
||||||
links=(
|
links=(
|
||||||
link_document_list_recent, link_document_list,
|
link_document_list_recent, link_document_list,
|
||||||
|
|||||||
71
mayan/apps/documents/dashboard_widgets.py
Normal file
71
mayan/apps/documents/dashboard_widgets.py
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
|
from django.apps import apps
|
||||||
|
from django.urls import reverse_lazy
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from common.classes import DashboardWidget
|
||||||
|
|
||||||
|
from .statistics import (
|
||||||
|
new_document_pages_this_month, new_documents_this_month,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_total_documents_queryset():
|
||||||
|
Document = apps.get_model(
|
||||||
|
app_label='documents', model_name='Document'
|
||||||
|
)
|
||||||
|
return Document.objects.all()
|
||||||
|
|
||||||
|
|
||||||
|
def get_document_types_queryset():
|
||||||
|
DocumentType = apps.get_model(
|
||||||
|
app_label='documents', model_name='DocumentType'
|
||||||
|
)
|
||||||
|
return DocumentType.objects.all()
|
||||||
|
|
||||||
|
|
||||||
|
def get_deleted_documents_queryset():
|
||||||
|
DeletedDocument = apps.get_model(
|
||||||
|
app_label='documents', model_name='DeletedDocument'
|
||||||
|
)
|
||||||
|
return DeletedDocument.objects.all()
|
||||||
|
|
||||||
|
|
||||||
|
widget_pages_per_month = DashboardWidget(
|
||||||
|
func=new_document_pages_this_month, icon='fa fa-calendar',
|
||||||
|
label=_('New pages this month'),
|
||||||
|
link=reverse_lazy(
|
||||||
|
'statistics:statistic_detail',
|
||||||
|
args=('new-document-pages-per-month',)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
widget_new_documents_this_month = DashboardWidget(
|
||||||
|
func=new_documents_this_month, icon='fa fa-calendar',
|
||||||
|
label=_('New documents this month'),
|
||||||
|
link=reverse_lazy(
|
||||||
|
'statistics:statistic_detail',
|
||||||
|
args=('new-documents-per-month',)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
widget_total_documents = DashboardWidget(
|
||||||
|
icon='fa fa-file', queryset=get_total_documents_queryset,
|
||||||
|
label=_('Total documents'),
|
||||||
|
link=reverse_lazy('documents:document_list')
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
widget_document_types = DashboardWidget(
|
||||||
|
icon='fa fa-book', queryset=get_document_types_queryset,
|
||||||
|
label=_('Document types'),
|
||||||
|
link=reverse_lazy('documents:document_type_list')
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
widget_documents_in_trash = DashboardWidget(
|
||||||
|
icon='fa fa-trash', queryset=get_deleted_documents_queryset,
|
||||||
|
label=_('Documents in trash'),
|
||||||
|
link=reverse_lazy('documents:document_list_deleted')
|
||||||
|
)
|
||||||
@@ -11,7 +11,7 @@ from django.core.exceptions import PermissionDenied
|
|||||||
from django.shortcuts import resolve_url
|
from django.shortcuts import resolve_url
|
||||||
from django.template import VariableDoesNotExist, Variable
|
from django.template import VariableDoesNotExist, Variable
|
||||||
from django.template.defaulttags import URLNode
|
from django.template.defaulttags import URLNode
|
||||||
from django.urls import resolve, reverse
|
from django.urls import resolve
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
from django.utils.http import urlencode, urlquote
|
from django.utils.http import urlencode, urlquote
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ class Menu(object):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def reset(cls):
|
def reset(cls):
|
||||||
cls._registry={}
|
cls._registry = {}
|
||||||
|
|
||||||
def __init__(self, name, icon=None, label=None):
|
def __init__(self, name, icon=None, label=None):
|
||||||
if name in self.__class__._registry:
|
if name in self.__class__._registry:
|
||||||
|
|||||||
Reference in New Issue
Block a user