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:
Roberto Rosario
2017-08-10 02:56:40 -04:00
parent bda44212b1
commit 6ec235afc0
11 changed files with 162 additions and 55 deletions

View File

@@ -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)
================== ==================

View File

@@ -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>

View File

@@ -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(

View 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
)

View File

@@ -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 = []

View 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'))

View File

@@ -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

View File

@@ -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

View File

@@ -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,

View 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')
)

View File

@@ -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