From 92a4b16985155b8553b914ae296c83318d11ecbb Mon Sep 17 00:00:00 2001 From: Jonathan Weth <git@jonathanweth.de> Date: Mon, 4 Jan 2021 15:26:25 +0100 Subject: [PATCH] Show a default dashboard if a user didn't selected any dashboard wigets --- .../core/migrations/0009_default_dashboard.py | 30 ++++++++++++ aleksis/core/models.py | 11 ++++- aleksis/core/rules.py | 3 ++ .../templates/core/dashboard_widget/list.html | 5 ++ .../core/templates/core/edit_dashboard.html | 41 +++++++++++++--- aleksis/core/templates/core/index.html | 19 ++++---- aleksis/core/urls.py | 6 +++ aleksis/core/views.py | 48 +++++++++++++------ 8 files changed, 132 insertions(+), 31 deletions(-) create mode 100644 aleksis/core/migrations/0009_default_dashboard.py diff --git a/aleksis/core/migrations/0009_default_dashboard.py b/aleksis/core/migrations/0009_default_dashboard.py new file mode 100644 index 000000000..401396bb0 --- /dev/null +++ b/aleksis/core/migrations/0009_default_dashboard.py @@ -0,0 +1,30 @@ +# Generated by Django 3.1.4 on 2021-01-04 13:39 + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0008_data_check_result'), + ] + + operations = [ + migrations.AddField( + model_name='dashboardwidgetorder', + name='default', + field=models.BooleanField(default=False, verbose_name='Part of the default dashboard'), + ), + migrations.AlterField( + model_name='dashboardwidgetorder', + name='person', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='core.person', verbose_name='Person'), + ), + migrations.AlterModelOptions( + name='dashboardwidget', + options={'permissions': (('edit_default_dashboard', 'Can edit default dashboard'),), + 'verbose_name': 'Dashboard Widget', 'verbose_name_plural': 'Dashboard Widgets'}, + ), + ] diff --git a/aleksis/core/models.py b/aleksis/core/models.py index 5f5facd33..5e3a9e85a 100644 --- a/aleksis/core/models.py +++ b/aleksis/core/models.py @@ -731,6 +731,7 @@ class DashboardWidget(PolymorphicModel, PureDjangoModel): return self.title class Meta: + permissions = (("edit_default_dashboard", _("Can edit default dashboard")),) verbose_name = _("Dashboard Widget") verbose_name_plural = _("Dashboard Widgets") @@ -739,8 +740,16 @@ class DashboardWidgetOrder(ExtensibleModel): widget = models.ForeignKey( DashboardWidget, on_delete=models.CASCADE, verbose_name=_("Dashboard widget") ) - person = models.ForeignKey(Person, on_delete=models.CASCADE, verbose_name=_("Person")) + person = models.ForeignKey( + Person, on_delete=models.CASCADE, verbose_name=_("Person"), null=True, blank=True + ) order = models.PositiveIntegerField(verbose_name=_("Order")) + default = models.BooleanField(default=False, verbose_name=_("Part of the default dashboard")) + + @classproperty + def default_dashboard_widgets(cls): + """Get default order for dashboard widgets.""" + return [w.widget for w in cls.objects.filter(person=None, default=True).order_by("order")] class Meta: verbose_name = _("Dashboard widget order") diff --git a/aleksis/core/rules.py b/aleksis/core/rules.py index 8ad48fbf1..ac713bbe5 100644 --- a/aleksis/core/rules.py +++ b/aleksis/core/rules.py @@ -306,3 +306,6 @@ rules.add_perm("core.edit_dashboardwidget", edit_dashboard_widget_predicate) delete_dashboard_widget_predicate = has_person & has_global_perm("core.delete_dashboardwidget") rules.add_perm("core.delete_dashboardwidget", delete_dashboard_widget_predicate) + +edit_default_dashboard_predicate = has_person & has_global_perm("core.edit_default_dashboard") +rules.add_perm("core.edit_default_dashboard", edit_default_dashboard_predicate) diff --git a/aleksis/core/templates/core/dashboard_widget/list.html b/aleksis/core/templates/core/dashboard_widget/list.html index ab384e862..022101b9e 100644 --- a/aleksis/core/templates/core/dashboard_widget/list.html +++ b/aleksis/core/templates/core/dashboard_widget/list.html @@ -17,6 +17,11 @@ {% blocktrans with name=widget_name %}Create {{ name }}{% endblocktrans %} </a> {% endfor %} + <a class="btn orange waves-effect waves-light" href="{% url "edit_default_dashboard" %}"> + <i class="material-icons left">edit</i> + {% trans "Edit default dashboard" %} + </a> + {% render_table table %} {% endblock %} diff --git a/aleksis/core/templates/core/edit_dashboard.html b/aleksis/core/templates/core/edit_dashboard.html index a15f24bff..2e8c633a3 100644 --- a/aleksis/core/templates/core/edit_dashboard.html +++ b/aleksis/core/templates/core/edit_dashboard.html @@ -1,16 +1,38 @@ {% extends 'core/base.html' %} {% load i18n static dashboard any_js %} -{% block browser_title %}{% blocktrans %}Edit dashboard{% endblocktrans %}{% endblock %} -{% block page_title %}{% blocktrans %}Edit dashboard{% endblocktrans %}{% endblock %} +{% block browser_title %} + {% if not default_dashboard %} + {% blocktrans %}Edit dashboard{% endblocktrans %} + {% else %} + {% trans "Edit default dashboard" %} + {% endif %} +{% endblock %} +{% block page_title %} + {% if not default_dashboard %} + {% blocktrans %}Edit dashboard{% endblocktrans %} + {% else %} + {% trans "Edit default dashboard" %} + {% endif %} +{% endblock %} {% block content %} <div class="alert primary"> <p> <i class="material-icons left">info</i> - On this page you can arrange your personal dashboard. You can drag any items from "Available widgets" to "Your - Dashboard" or change the order by moving the widgets. After you have finished, please don't forget to click on - "Save". + {% if not default_dashboard %} + {% blocktrans %} + On this page you can arrange your personal dashboard. You can drag any items from "Available widgets" to "Your + Dashboard" or change the order by moving the widgets. After you have finished, please don't forget to click on + "Save". + {% endblocktrans %} + {% else %} + {% blocktrans %} + On this page you can arrange the default dashboard which is shown when a user doesn't arrange his own + dashboard. You can drag any items from "Available widgets" to "Default Dashboard" or change the order + by moving the widgets. After you have finished, please don't forget to click on "Save". + {% endblocktrans %} + {% endif %} </p> </div> @@ -30,7 +52,14 @@ {% endfor %} </div> - <h5>{% trans "Your dashboard" %}</h5> + <h5> + {% if not default_dashboard %} + {% trans "Your dashboard" %} + {% else %} + {% trans "Default dashboard" %} + {% endif %} + </h5> + <div class="row card-panel grey lighten-3" id="widgets"> {% for widget in widgets %} {% include "core/partials/edit_dashboard_widget.html" %} diff --git a/aleksis/core/templates/core/index.html b/aleksis/core/templates/core/index.html index 93b80ddef..419bb59f1 100644 --- a/aleksis/core/templates/core/index.html +++ b/aleksis/core/templates/core/index.html @@ -42,19 +42,18 @@ <div class="col s{{ widget.size_s }} m{{ widget.size_m }} l{{ widget.size_l }} xl{{ widget.size_xl }}"> {% include_widget widget %} </div> - {% empty %} - <div class="col s12 grey-text center"> - <i class="material-icons medium ">widgets</i> - <p class="flow-text"> - {% blocktrans %} - You haven't selected any dashboard widgets. Please click on "Edit dashboard" to add widgets to your - personal dashboard. - {% endblocktrans %} - </p> - </div> {% endfor %} </div> + {% if default_dashboard and widgets %} + <div class="grey-text right"> + {% blocktrans %} + You didn't customise your dashboard so that you see the system default. Please click on "Edit dashboard" to + customise your personal dashboard. + {% endblocktrans %} + </div> + {% endif %} + <div class="row"> <div class="col s12 m6"> <h5>{% blocktrans %}Last activities{% endblocktrans %}</h5> diff --git a/aleksis/core/urls.py b/aleksis/core/urls.py index 930b3fbc8..30c38b11c 100644 --- a/aleksis/core/urls.py +++ b/aleksis/core/urls.py @@ -177,6 +177,12 @@ urlpatterns = [ views.DashboardWidgetCreateView.as_view(), name="create_dashboard_widget", ), + path( + "dashboard_widgets/default/", + views.EditDashboardView.as_view(), + {"default": True}, + name="edit_default_dashboard", + ), ] # Serve static files from STATIC_ROOT to make it work with runserver diff --git a/aleksis/core/views.py b/aleksis/core/views.py index c9f9c5cd3..1da251a8a 100644 --- a/aleksis/core/views.py +++ b/aleksis/core/views.py @@ -95,6 +95,12 @@ def index(request: HttpRequest) -> HttpResponse: context["announcements"] = announcements widgets = request.user.person.dashboard_widgets + + if len(widgets) <= 0: + # Use default dashboard if there are no widgets + widgets = DashboardWidgetOrder.default_dashboard_widgets + context["default_dashboard"] = True + media = DashboardWidget.get_media(widgets) context["widgets"] = widgets @@ -848,10 +854,20 @@ class DashboardWidgetDeleteView(PermissionRequiredMixin, AdvancedDeleteView): class EditDashboardView(View): """View for editing dashboard widget order.""" - def get_context_data(self, request): + def get_context_data(self, request, **kwargs): context = {} + self.default_dashboard = kwargs.get("default", False) + + if self.default_dashboard and not request.user.has_perm("core.edit_default_dashboard"): + raise PermissionDenied() + + context["default_dashboard"] = self.default_dashboard - widgets = request.user.person.dashboard_widgets + widgets = ( + request.user.person.dashboard_widgets + if not self.default_dashboard + else DashboardWidgetOrder.default_dashboard_widgets + ) not_used_widgets = DashboardWidget.objects.exclude(pk__in=[w.pk for w in widgets]) context["widgets"] = widgets context["not_used_widgets"] = not_used_widgets @@ -871,8 +887,8 @@ class EditDashboardView(View): return context - def post(self, request): - context = self.get_context_data(request) + def post(self, request, **kwargs): + context = self.get_context_data(request, **kwargs) if context["formset"].is_valid(): added_objects = [] @@ -882,22 +898,26 @@ class EditDashboardView(View): obj, created = DashboardWidgetOrder.objects.update_or_create( widget=form.cleaned_data["pk"], - person=request.user.person, + person=request.user.person if not self.default_dashboard else None, + default=self.default_dashboard, defaults={"order": form.cleaned_data["order"]}, ) added_objects.append(obj.pk) - DashboardWidgetOrder.objects.filter(person=request.user.person).exclude( - pk__in=added_objects - ).delete() + DashboardWidgetOrder.objects.filter( + person=request.user.person if not self.default_dashboard else None, + default=self.default_dashboard, + ).exclude(pk__in=added_objects).delete() - messages.success( - request, _("Your dashboard configuration has been saved successfully.") - ) - return redirect("index") + if not self.default_dashboard: + msg = _("Your dashboard configuration has been saved successfully.") + else: + msg = _("The configuration of the default dashboard has been saved successfully.") + messages.success(request, msg) + return redirect("index" if not self.default_dashboard else "dashboard_widgets") - def get(self, request): - context = self.get_context_data(request) + def get(self, request, **kwargs): + context = self.get_context_data(request, **kwargs) return render(request, "core/edit_dashboard.html", context=context) -- GitLab