from importlib import import_module try: from django.core.urlresolvers import reverse except ImportError: # Django 1.11 from django.urls import reverse from django.template.loader import render_to_string from jet.dashboard import modules from jet.dashboard.models import UserDashboardModule from django.utils.translation import ugettext_lazy as _ from jet.ordered_set import OrderedSet from jet.utils import get_admin_site_name, context_to_dict try: from django.template.context_processors import csrf except ImportError: from django.core.context_processors import csrf class Dashboard(object): """ Base dashboard class. All custom dashboards should inherit it. """ #: Number of columns in which widgets can be placed columns = 2 #: Dashboard Modules (widgets) that dashboard is filled with, when the user open it for the first time #: #: List of dashboard module **instances** children = None #: Dashboard Modules (widgets) that user can add to dashboard at any time # (not created when the user open dashboard for the first time) #: #: List of dashboard module **classes** available_children = None app_label = None context = None modules = None class Media: css = () js = () def __init__(self, context, **kwargs): for key in kwargs: if hasattr(self.__class__, key): setattr(self, key, kwargs[key]) self.children = self.children or [] self.available_children = self.available_children or [] self.set_context(context) def set_context(self, context): self.context = context self.init_with_context(context) self.load_modules() def init_with_context(self, context): """ Override this method to fill your custom **Dashboard** class with widgets. You should add your widgets to ``children`` and ``available_children`` attributes. Usage example: .. code-block:: python from django.utils.translation import ugettext_lazy as _ from jet.dashboard import modules from jet.dashboard.dashboard import Dashboard, AppIndexDashboard class CustomIndexDashboard(Dashboard): columns = 3 def init_with_context(self, context): self.available_children.append(modules.LinkList) self.children.append(modules.LinkList( _('Support'), children=[ { 'title': _('Django documentation'), 'url': 'http://docs.djangoproject.com/', 'external': True, }, { 'title': _('Django "django-users" mailing list'), 'url': 'http://groups.google.com/group/django-users', 'external': True, }, { 'title': _('Django irc channel'), 'url': 'irc://irc.freenode.net/django', 'external': True, }, ], column=0, order=0 )) """ pass def load_module(self, module_fullname): package, module_name = module_fullname.rsplit('.', 1) package = import_module(package) module = getattr(package, module_name) return module def create_initial_module_models(self, user): module_models = [] i = 0 for module in self.children: column = module.column if module.column is not None else i % self.columns order = module.order if module.order is not None else int(i / self.columns) module_models.append(UserDashboardModule.objects.create( title=module.title, app_label=self.app_label, user=user.pk, module=module.fullname(), column=column, order=order, settings=module.dump_settings(), children=module.dump_children() )) i += 1 return module_models def load_modules(self): module_models = UserDashboardModule.objects.filter( app_label=self.app_label, user=self.context['request'].user.pk ).all() if len(module_models) == 0: module_models = self.create_initial_module_models(self.context['request'].user) loaded_modules = [] for module_model in module_models: module_cls = module_model.load_module() if module_cls is not None: module = module_cls(model=module_model, context=self.context) loaded_modules.append(module) self.modules = loaded_modules def render(self): context = context_to_dict(self.context) context.update({ 'columns': range(self.columns), 'modules': self.modules, 'app_label': self.app_label, }) context.update(csrf(context['request'])) return render_to_string('jet.dashboard/dashboard.html', context) def render_tools(self): context = context_to_dict(self.context) context.update({ 'children': self.children, 'app_label': self.app_label, 'available_children': self.available_children }) context.update(csrf(context['request'])) return render_to_string('jet.dashboard/dashboard_tools.html', context) def media(self): unique_css = OrderedSet() unique_js = OrderedSet() for js in getattr(self.Media, 'js', ()): unique_js.add(js) for css in getattr(self.Media, 'css', ()): unique_css.add(css) for module in self.modules: for js in getattr(module.Media, 'js', ()): unique_js.add(js) for css in getattr(module.Media, 'css', ()): unique_css.add(css) class Media: css = list(unique_css) js = list(unique_js) return Media class AppIndexDashboard(Dashboard): def get_app_content_types(self): return self.app_label + '.*', def models(self): return self.app_label + '.*', class DefaultIndexDashboard(Dashboard): columns = 3 def init_with_context(self, context): self.available_children.append(modules.LinkList) self.available_children.append(modules.Feed) site_name = get_admin_site_name(context) # append a link list module for "quick links" self.children.append(modules.LinkList( _('Quick links'), layout='inline', draggable=False, deletable=False, collapsible=False, children=[ [_('Return to site'), '/'], [_('Change password'), reverse('%s:password_change' % site_name)], [_('Log out'), reverse('%s:logout' % site_name)], ], column=0, order=0 )) # append an app list module for "Applications" self.children.append(modules.AppList( _('Applications'), exclude=('auth.*',), column=1, order=0 )) # append an app list module for "Administration" self.children.append(modules.AppList( _('Administration'), models=('auth.*',), column=2, order=0 )) # append a recent actions module self.children.append(modules.RecentActions( _('Recent Actions'), 10, column=0, order=1 )) # append a feed module self.children.append(modules.Feed( _('Latest Django News'), feed_url='http://www.djangoproject.com/rss/weblog/', limit=5, column=1, order=1 )) # append another link list module for "support". self.children.append(modules.LinkList( _('Support'), children=[ { 'title': _('Django documentation'), 'url': 'http://docs.djangoproject.com/', 'external': True, }, { 'title': _('Django "django-users" mailing list'), 'url': 'http://groups.google.com/group/django-users', 'external': True, }, { 'title': _('Django irc channel'), 'url': 'irc://irc.freenode.net/django', 'external': True, }, ], column=2, order=1 )) class DefaultAppIndexDashboard(AppIndexDashboard): def init_with_context(self, context): self.available_children.append(modules.LinkList) self.children.append(modules.ModelList( title=_('Application models'), models=self.models(), column=0, order=0 )) self.children.append(modules.RecentActions( include_list=self.get_app_content_types(), column=1, order=0 )) class DashboardUrls(object): _urls = [] def get_urls(self): return self._urls def register_url(self, url): self._urls.append(url) def register_urls(self, urls): self._urls.extend(urls) urls = DashboardUrls()