Add a dashboard for showing relevant links and apps to users
This commit is contained in:
parent
52fad7ccb0
commit
2c474bf751
@ -40,6 +40,7 @@ INSTALLED_APPS = [
|
|||||||
"membershipworks.apps.MembershipworksConfig",
|
"membershipworks.apps.MembershipworksConfig",
|
||||||
"paperwork.apps.PaperworkConfig",
|
"paperwork.apps.PaperworkConfig",
|
||||||
"doorcontrol.apps.DoorControlConfig",
|
"doorcontrol.apps.DoorControlConfig",
|
||||||
|
"dashboard.apps.DashboardConfig",
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
@ -29,7 +29,7 @@ router.registry.extend(paperwork_router.registry)
|
|||||||
router.registry.extend(membershipworks_router.registry)
|
router.registry.extend(membershipworks_router.registry)
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", lambda request: redirect("/tasks/"), name="root"),
|
path("", include("dashboard.urls")),
|
||||||
path("tasks/", include("tasks.urls")),
|
path("tasks/", include("tasks.urls")),
|
||||||
path("rentals/", include("rentals.urls")),
|
path("rentals/", include("rentals.urls")),
|
||||||
path("membershipworks/", include("membershipworks.urls")),
|
path("membershipworks/", include("membershipworks.urls")),
|
||||||
|
20
dashboard/__init__.py
Normal file
20
dashboard/__init__.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from django.http import HttpRequest
|
||||||
|
|
||||||
|
DASHBOARD_CARDS = {}
|
||||||
|
|
||||||
|
|
||||||
|
def register(fragment):
|
||||||
|
DASHBOARD_CARDS[fragment.name] = fragment
|
||||||
|
return fragment
|
||||||
|
|
||||||
|
|
||||||
|
class DashboardFragment:
|
||||||
|
name: str
|
||||||
|
template: str
|
||||||
|
context: Any = None
|
||||||
|
visible: bool = True
|
||||||
|
|
||||||
|
def __init__(self, request: HttpRequest):
|
||||||
|
self.request = request
|
11
dashboard/apps.py
Normal file
11
dashboard/apps.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
from django.utils.module_loading import autodiscover_modules
|
||||||
|
|
||||||
|
|
||||||
|
class DashboardConfig(AppConfig):
|
||||||
|
default_auto_field = "django.db.models.BigAutoField"
|
||||||
|
name = "dashboard"
|
||||||
|
|
||||||
|
def ready(self):
|
||||||
|
super().ready()
|
||||||
|
autodiscover_modules("dashboard")
|
0
dashboard/dashboard.py
Normal file
0
dashboard/dashboard.py
Normal file
26
dashboard/templates/dashboard/dashboard.dj.html
Normal file
26
dashboard/templates/dashboard/dashboard.dj.html
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{% extends "base.dj.html" %}
|
||||||
|
|
||||||
|
{% block title %}Claremont MakerSpace Management{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
{% if not user.is_authenticated %}
|
||||||
|
<div class="alert alert-warning">
|
||||||
|
You are not logged in. Much of this site is inaccessible until you <a href="{% url 'login' %}">log in</a>.
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<div class="container">
|
||||||
|
<div style="display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(20em, auto));
|
||||||
|
gap: 0.5em">
|
||||||
|
{% for app, app_dash in apps.items %}
|
||||||
|
{% if app_dash.visible %}
|
||||||
|
<div>
|
||||||
|
<div class="card">
|
||||||
|
<h5 class="card-header">{{ app }}</h5>
|
||||||
|
{% include app_dash.template with ctx=app_dash.context %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
7
dashboard/templates/dashboard/links_card.dj.html
Normal file
7
dashboard/templates/dashboard/links_card.dj.html
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<ul class="list-group list-group-flush">
|
||||||
|
{% for text, link in ctx.links.items %}
|
||||||
|
<li class="list-group-item">
|
||||||
|
<a class="card-link" href="{{ link }}">{{ text }}</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
3
dashboard/tests.py
Normal file
3
dashboard/tests.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
9
dashboard/urls.py
Normal file
9
dashboard/urls.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
from django.urls import path
|
||||||
|
|
||||||
|
from . import views
|
||||||
|
|
||||||
|
app_name = "dashboard"
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path("", views.DashboardView.as_view(), name="dashboard"),
|
||||||
|
]
|
14
dashboard/views.py
Normal file
14
dashboard/views.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
from django.views.generic.base import TemplateView
|
||||||
|
|
||||||
|
from dashboard import DASHBOARD_CARDS
|
||||||
|
|
||||||
|
|
||||||
|
class DashboardView(TemplateView):
|
||||||
|
template_name = "dashboard/dashboard.dj.html"
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
context["apps"] = {
|
||||||
|
name: card(self.request) for name, card in DASHBOARD_CARDS.items()
|
||||||
|
}
|
||||||
|
return context
|
30
doorcontrol/dashboard.py
Normal file
30
doorcontrol/dashboard.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from django.urls import reverse
|
||||||
|
|
||||||
|
import dashboard
|
||||||
|
|
||||||
|
|
||||||
|
@dashboard.register
|
||||||
|
class DoorControlDashboardFragment(dashboard.DashboardFragment):
|
||||||
|
name = "Door Controls"
|
||||||
|
template = "dashboard/links_card.dj.html"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def context(self) -> Any:
|
||||||
|
return {
|
||||||
|
"links": {
|
||||||
|
"Access Per Day": reverse(
|
||||||
|
"doorcontrol:access-per-unit-time", kwargs={"unit_time": "day"}
|
||||||
|
),
|
||||||
|
"Access Per Month": reverse(
|
||||||
|
"doorcontrol:access-per-unit-time", kwargs={"unit_time": "month"}
|
||||||
|
),
|
||||||
|
"Access Failures": reverse("doorcontrol:denied-access"),
|
||||||
|
"Most Active Members": reverse("doorcontrol:most-active-members"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@property
|
||||||
|
def visible(self) -> bool:
|
||||||
|
return self.request.user.has_perm("doorcontrol.view_hidevent")
|
44
paperwork/dashboard.py
Normal file
44
paperwork/dashboard.py
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from django.urls import reverse
|
||||||
|
|
||||||
|
import dashboard
|
||||||
|
from membershipworks.models import Member
|
||||||
|
from .models import Department
|
||||||
|
|
||||||
|
|
||||||
|
@dashboard.register
|
||||||
|
class PaperworkDashboardFragment(dashboard.DashboardFragment):
|
||||||
|
name = "Paperwork"
|
||||||
|
template = "dashboard/links_card.dj.html"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def context(self) -> Any:
|
||||||
|
links = {}
|
||||||
|
|
||||||
|
if hasattr(self.request.user, "ldap_user"):
|
||||||
|
uid = self.request.user.ldap_user.attrs["employeeNumber"][0]
|
||||||
|
links["Member Certifications"] = reverse("paperwork:member_certifications")
|
||||||
|
else:
|
||||||
|
uid = None
|
||||||
|
|
||||||
|
departments = Department.objects.prefetch_related("shop_lead_flag__members")
|
||||||
|
if self.request.user.is_superuser:
|
||||||
|
departments = departments.all()
|
||||||
|
elif uid is not None:
|
||||||
|
user_member = Member.objects.get(uid=uid)
|
||||||
|
# TODO: could be a lot simpler if membershipworks was in the same database
|
||||||
|
# TODO: should also select children
|
||||||
|
member_flags = list(user_member.flags.all().values_list("pk", flat=True))
|
||||||
|
departments = departments.filter(shop_lead_flag__in=member_flags)
|
||||||
|
|
||||||
|
if len(departments) > 0:
|
||||||
|
links["Department Certifications"] = reverse(
|
||||||
|
"paperwork:department_certifications"
|
||||||
|
)
|
||||||
|
|
||||||
|
return {"links": links}
|
||||||
|
|
||||||
|
@property
|
||||||
|
def visible(self) -> bool:
|
||||||
|
return self.request.user.is_authenticated
|
15
rentals/dashboard.py
Normal file
15
rentals/dashboard.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from django.urls import reverse
|
||||||
|
|
||||||
|
import dashboard
|
||||||
|
|
||||||
|
|
||||||
|
@dashboard.register
|
||||||
|
class RentalsDashboardFragment(dashboard.DashboardFragment):
|
||||||
|
name = "Rentals"
|
||||||
|
template = "dashboard/links_card.dj.html"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def context(self) -> Any:
|
||||||
|
return {"links": {"Locker Index": reverse("rentals:index")}}
|
@ -17,7 +17,7 @@
|
|||||||
<body>
|
<body>
|
||||||
<nav class="navbar navbar-expand-sm navbar-light bg-light">
|
<nav class="navbar navbar-expand-sm navbar-light bg-light">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<a class="navbar-brand" href="{% url 'root' %}">Claremont MakerSpace</a>
|
<a class="navbar-brand" href="{% url 'dashboard:dashboard' %}">Claremont MakerSpace</a>
|
||||||
<button class="navbar-toggler"
|
<button class="navbar-toggler"
|
||||||
type="button"
|
type="button"
|
||||||
data-bs-toggle="collapse"
|
data-bs-toggle="collapse"
|
||||||
|
Loading…
Reference in New Issue
Block a user