2
0
Fork 0

Populate nav with signal/context processor

This commit is contained in:
Luca 2023-04-29 11:13:43 +02:00
parent 441c1434e3
commit 77bbca4d37
37 changed files with 261 additions and 255 deletions

View File

@ -2,6 +2,7 @@ from django.db.models.signals import pre_save
from django.dispatch import receiver from django.dispatch import receiver
from django.shortcuts import reverse from django.shortcuts import reverse
from django.template import Context, Template from django.template import Context, Template
from shiftregister.core.signals import populate_nav
from .models import Message, Shift from .models import Message, Shift
@ -37,3 +38,40 @@ def notify_shift_changed(sender, **kwargs):
for reg in instance.shiftregistration_set.all() for reg in instance.shiftregistration_set.all()
) )
) )
@receiver(populate_nav, dispatch_uid="populate_app_nav")
def populate_app_nav(sender, **kwargs):
request = sender
nav_items = []
helper = request.helper
if helper is None:
nav_items.append({"link": reverse("register"), "text": "Anmelden"})
else:
if not helper.number_validated:
nav_items.append(
{
"class": "has-text-danger",
"text": "Bestätige deine Telefonnummer über den Link in der SMS",
}
)
important_shift = helper.important_shift()
if important_shift is not None:
template = Template(
'{% if is_running %}Laufende{% else %}Nächste{% endif %} Schicht ({{ start_at|date:"H:i" }})'
)
text = template.render(
Context(
{
"is_running": important_shift.is_running,
"start_at": important_shift.start_at,
}
)
)
nav_items.append(
{"link": reverse("shift", args=(important_shift.pk,)), "text": text}
)
return nav_items

View File

@ -2,22 +2,6 @@
{% block title %}Help!{% endblock %} {% block title %}Help!{% endblock %}
{% block navbar %}
<div class="navbar-start">
{% if not helper%}
<a class="navbar-item" href="{% url 'register' %}">Anmelden</a>
{% else %}
{% if not helper.number_validated %}
<p class="navbar-item has-text-danger">Bestätige deine Telefonnummer über den Link in der SMS</p>
{% endif %}
{% if helper.important_shift %}
<a class="navbar-item" href="{% url 'shift' helper.important_shift.pk %}">{%if helper.important_shift.is_running%}Laufende{% else %}Nächste{% endif %} Schicht ({{ helper.important_shift.start_at|date:"H:i" }})</a>
{% endif %}
{% endif %}
</div>
<div class="navbar-end"></div>
{% endblock %}
{% block body %} {% block body %}
<section class="section"> <section class="section">
<div class="container"> <div class="container">
@ -36,6 +20,7 @@
{% endblock %} {% endblock %}
{% block footer %} {% block footer %}
<div class="content">
{% if DEBUG %} {% if DEBUG %}
(Debug-Modus) (Debug-Modus)
{% if helper %} {% if helper %}
@ -43,4 +28,5 @@
<a href="{{ helper.logintoken_set.first.get_absolute_url }}">login url</a> <a href="{{ helper.logintoken_set.first.get_absolute_url }}">login url</a>
{% endif %} {% endif %}
{% endif %} {% endif %}
</div>
{% endblock %} {% endblock %}

View File

@ -1,6 +1,7 @@
{% extends "helper_base.html" %} {% extends "helper_base.html" %}
{% block title %}Freie Schichten{% endblock %} {% block title %}Freie Schichten{% endblock %}
{% block content %} {% block content %}
{% if current_shift %} {% if current_shift %}
<h3 class="title">Aktuelle Schicht</h3> <h3 class="title">Aktuelle Schicht</h3>

View File

@ -1,6 +1,7 @@
{% extends "helper_base.html" %} {% extends "helper_base.html" %}
{% block title %}Registrierung{% endblock %} {% block title %}Registrierung{% endblock %}
{% block content %} {% block content %}
Hallo {{ helper.name }},<br> Hallo {{ helper.name }},<br>
wir haben dir eine SMS an {{ helper.phone }} mit einem Bestätigungslink geschickt. Sobald du diesen anklickst, kann es losgehen! wir haben dir eine SMS an {{ helper.phone }} mit einem Bestätigungslink geschickt. Sobald du diesen anklickst, kann es losgehen!

View File

View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class CoreConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "shiftregister.core"

View File

@ -0,0 +1,14 @@
from .signals import populate_nav
def nav(request):
nav_items = [
item
for _, items in populate_nav.send(sender=request)
if isinstance(items, list)
for item in items
]
return {
"nav_items": nav_items,
}

View File

@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

View File

@ -0,0 +1,3 @@
from django.dispatch import Signal
populate_nav = Signal()

View File

@ -0,0 +1 @@
{% extends "error.html" %}

View File

@ -0,0 +1,5 @@
{% extends "error.html" %}
{% block error_message %}Seite nicht gefunden{% endblock %}
{% block error_text %}{% endblock %}

View File

@ -0,0 +1,5 @@
{% extends "error.html" %}
{% block error_message %}Es ist ein Fehler aufgetreten{% endblock %}
{% block error_text %}Wir arbeiten dran. Bei dringenden Problemen wende dich bitte an den Infopoint.{% endblock %}

View File

@ -33,6 +33,7 @@
} }
} }
</style> </style>
{% block head %}{% endblock %}
</head> </head>
<body class="is-flex is-flex-direction-column"> <body class="is-flex is-flex-direction-column">
<nav class="navbar"> <nav class="navbar">
@ -46,8 +47,14 @@
</a> </a>
</div> </div>
<div class="navbar-menu" id="main-nav"> <div class="navbar-menu" id="main-nav">
{% block navbar %} <div class="navbar-start">
{% endblock navbar %} {% for item in nav_items %}
<{% if item.link %}a{% else %}p{% endif %} class="navbar-item{% if item.class %} {{ item.class }}{% endif %}"{% if item.link %} href="{{ item.link }}"{% endif %}>
{{ item.text }}
</{% if item.link %}a{% else %}p{% endif %}>
{% endfor %}
</div>
<div class="navbar-end"></div>
</div> </div>
</div> </div>
</nav> </nav>
@ -55,14 +62,16 @@
<section class="section"> <section class="section">
<div class="container"> <div class="container">
{% include 'notifications.html' %} {% include 'notifications.html' %}
{% block content %}{% endblock %}
</div> </div>
</section> </section>
{% endblock %} {% endblock %}
<footer class="footer"> <footer class="footer">
<div class="container"> <div class="container is-flex is-flex-wrap-wrap is-justify-content-space-between">
{% block footer %} {% block footer %}
<div class="content"><a href="https://git.as42.net/kontakt/shiftregister">shiftregister</a> by flo, Luca &amp; xAndy</div>
{% endblock %} {% endblock %}
<div class="breadcrumb has-dot-separator is-right"> <div class="breadcrumb has-dot-separator is-flex-grow-1 is-right ml-5">
<ul> <ul>
<li><a href="{% url 'pages:view' 'map' %}">Karte</a></li> <li><a href="{% url 'pages:view' 'map' %}">Karte</a></li>
<li><a href="{% url 'pages:view' 'faq' %}">Häufig gestellte Fragen</a></li> <li><a href="{% url 'pages:view' 'faq' %}">Häufig gestellte Fragen</a></li>

View File

@ -0,0 +1,20 @@
{% extends "base.html" %}
{% block title %}Fehler{% endblock %}
{% block body %}
<section class="section">
<div class="container">
<div class="content">
<h1 class="title">{% block error_message %}Fehler{% endblock %}</h1>
{% block error_text %}
<p class="is-family-monospace">¯\_(ツ)_/¯</p>
{% endblock %}
</div>
<a class="button" href="{% url 'index' %}">Zurück zur Schichtübersicht</a>
{% if user.is_authenticated %}
<a class="button" href="{% url 'team:index' %}">Zurück zur Teamansicht</a>
{% endif %}
</div>
</section>
{% endblock %}

View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

View File

@ -0,0 +1,3 @@
from django.shortcuts import render
# Create your views here.

View File

@ -2,22 +2,6 @@
{% block title %}{{ page.title }}{% endblock %} {% block title %}{{ page.title }}{% endblock %}
{% block navbar %}
<div class="navbar-start">
{% if not helper%}
<a class="navbar-item" href="{% url 'register' %}">Anmelden</a>
{% else %}
{% if not helper.number_validated %}
<p class="navbar-item has-text-danger">Bestätige deine Telefonnummer über den Link in der SMS</p>
{% endif %}
{% if helper.important_shift %}
<a class="navbar-item" href="{% url 'shift' helper.important_shift.pk %}">{% if helper.important_shift.is_running %}Laufende{% else %}Nächste{% endif %} Schicht ({{ helper.important_shift.start_at|date:"H:i" }})</a>
{% endif %}
{% endif %}
</div>
<div class="navbar-end"></div>
{% endblock %}
{% block body %} {% block body %}
<section class="section"> <section class="section">
<div class="container"> <div class="container">

View File

@ -40,11 +40,12 @@ ALLOWED_HOSTS = list(filter(lambda s: s != "", getenv("ALLOWED_HOSTS", "").split
INSTALLED_APPS = [ INSTALLED_APPS = [
"dynamic_preferences", "dynamic_preferences",
"shiftregister.app.apps.AppConfig", "shiftregister.app.apps.AppConfig",
"shiftregister.core.apps.CoreConfig",
"shiftregister.importer.apps.ImporterConfig", "shiftregister.importer.apps.ImporterConfig",
"shiftregister.team.apps.TeamConfig",
"shiftregister.pages.apps.PagesConfig",
"shiftregister.metrics.apps.MetricsConfig", "shiftregister.metrics.apps.MetricsConfig",
"shiftregister.pages.apps.PagesConfig",
"shiftregister.signage.apps.SignageConfig", "shiftregister.signage.apps.SignageConfig",
"shiftregister.team.apps.TeamConfig",
"django.contrib.admin", "django.contrib.admin",
"django.contrib.auth", "django.contrib.auth",
"django.contrib.contenttypes", "django.contrib.contenttypes",
@ -72,7 +73,7 @@ LOGIN_URL = "/admin/login/"
TEMPLATES = [ TEMPLATES = [
{ {
"BACKEND": "django.template.backends.django.DjangoTemplates", "BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [BASE_DIR / "templates"], "DIRS": [],
"APP_DIRS": True, "APP_DIRS": True,
"OPTIONS": { "OPTIONS": {
"context_processors": [ "context_processors": [
@ -81,6 +82,7 @@ TEMPLATES = [
"django.contrib.auth.context_processors.auth", "django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages", "django.contrib.messages.context_processors.messages",
"shiftregister.app.context_processors.proc", "shiftregister.app.context_processors.proc",
"shiftregister.core.context_processors.nav",
], ],
}, },
}, },

View File

@ -1,41 +1,40 @@
<div class="column is-one-quarter"> <div class="column is-one-quarter">
<div class="box {%if not shift.teambackup_set.all%} has-background-warning{%endif%}"> <div class="box{% if not shift.teambackup_set.all %} has-background-warning{% endif %}">
<div class="content"> <div class="content">
<strong>Ort:</strong> {{ shift.room.name }}<br> <strong>Ort:</strong> {{ shift.room.name }}<br>
<strong>Beginn:</strong> {{ shift.start_at }}<br> <strong>Beginn:</strong> {{ shift.start_at }}<br>
<strong>Dauer:</strong> {{ shift.duration }}<br> <strong>Dauer:</strong> {{ shift.duration }}<br>
<strong>Belegung:</strong> {{ shift.shiftregistration_set.count }}/{{ shift.required_helpers|default:shift.room.required_helpers }} <strong>Belegung:</strong> {{ shift.shiftregistration_set.count }}/{{ shift.required_helpers|default:shift.room.required_helpers }}
<hr> <hr>
<ul> <ul>
{% for item in shift.teambackup_set.all%} {% for item in shift.teambackup_set.all %}
<li>{{item.name}}</li> <li>{{ item.name }}</li>
{%endfor%} {% endfor %}
</ul> </ul>
<form action="{%url 'signage:work_add' shift.pk%}" method="post"> <form action="{% url 'signage:work_add' shift.pk %}" method="post">
{% csrf_token %} {% csrf_token %}
{% for field in form %} {% for field in form %}
<div class="field"> <div class="field">
{% if field.widget_type == 'checkbox' %} {% if field.widget_type == 'checkbox' %}
<div class="control"> <div class="control">
<label class="checkbox" for="{{ field.id_for_label }}">{{ field }} {{ field.label }}</label> <label class="checkbox" for="{{ field.id_for_label }}">{{ field }} {{ field.label }}</label>
</div>
{% else %}
<label class="label" for="{{ field.id_for_label }}">{{ field.label }}</label>
<div class="control">
{{ field }}
</div>
{% endif %}
{% for error in field.errors %}
<p class="help is-danger">{{ error }}</p>
{% endfor %}
{% if field.help_text %}
<p class="help">{{ field.help_text }}</p>
{% endif %}
</div> </div>
{% else %} {% endfor %}
<label class="label" for="{{ field.id_for_label }}">{{ field.label }}</label> <button class="button is-link" type="submit">Team hinzufügen</button>
<div class="control"> </form>
{{ field }} </div>
</div>
{% endif %}
{% for error in field.errors %}
<p class="help is-danger">{{ error }}</p>
{% endfor %}
{% if field.help_text %}
<p class="help">{{ field.help_text }}</p>
{% endif %}
</div>
{% endfor %}
<button class="button is-link" type="submit">Team hinzufuegen</button>
</form>
</div> </div>
</div> </div>
</div>

View File

@ -1,23 +0,0 @@
{% extends "base.html" %}
{% block title %}Team{% endblock %}
{% block navbar %}
<div class="navbar-start">
<a class="navbar-item" href="{% url 'team:shift_overview' %}">Schichtübersicht</a>
<a class="navbar-item" href="{% url 'team:shift_free' %}">Freie Schichten</a>
<a class="navbar-item" href="{% url 'team:shift_all' %}">Alle Schichten</a>
<a class="navbar-item" href="{% url 'team:bulk_message' %}">Massen-Nachricht</a>
</div>
<div class="navbar-end"></div>
{% endblock %}
{% block body %}
<section class="section">
<div class="container">
{% include 'notifications.html' %}
{% block content %}{% endblock %}
</div>
</section>
{% endblock %}

View File

@ -1,90 +1,63 @@
{% load static %} {% extends "base.html" %}
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>{% block title %}Help!{% endblock %} &ndash; Helfer*innen</title>
<link rel="icon" href="{% static 'tonkakt.svg' %}" sizes="any" type="image/svg+xml">
<link rel="stylesheet" href="{% static 'bulma.min.css' %}">
<link rel="stylesheet" href="{% static 'bulma-prefers-dark.min.css' %}">
<style>
@font-face {
font-family: "Maven Pro";
src: url("{% static 'MavenPro-VariableFont:wght.ttf' %}");
}
* { {% block head %}
font-family: "Maven Pro", sans-serif !important; <script>
} window.addEventListener('load', () => {
const max = document.body.scrollHeight - window.innerHeight;
let current = 0;
let interval;
let interacted = false;
:root { window.addEventListener('click', () => interacted = true);
--background: #fff; window.addEventListener('touchstart', () => interacted = true);
}
@media (prefers-color-scheme: dark) { setTimeout(() => {
:root { window.scrollTo({top: 0});
--background: #17181c; }, 10);
}
}
</style>
<script>
window.addEventListener('load', () => {
const max = document.body.scrollHeight - window.innerHeight;
let current = 0;
let interval;
let interacted = false;
window.addEventListener('click', () => interacted = true); if (max > 0) {
window.addEventListener('touchstart', () => interacted = true); setTimeout(() => {
if (interacted) return;
setTimeout(() => { interval = setInterval(() => {
window.scrollTo({top: 0});
}, 10);
if (max > 0) {
setTimeout(() => {
if (interacted) return;
interval = setInterval(() => {
if (interacted) return;
current += 1;
window.scrollTo({top: current});
if (window.scrollY >= max) {
if (interacted) return;
clearInterval(interval);
setTimeout(() => {
window.location.reload();
}, 5000)
}
}, 20);
}, 5000)
}
setTimeout(() => {
if (interacted) return; if (interacted) return;
window.location.reload(); current += 1;
}, 120 * 1000)
}); window.scrollTo({top: current});
</script>
</head> if (window.scrollY >= max) {
<body> if (interacted) return;
<section class="section"> clearInterval(interval);
<div class="container"> setTimeout(() => {
<table class="table"> window.location.reload();
<tbody> }, 5000)
{% for shift in shifts %} }
<tr> }, 20);
<td>{{shift.start_at}}</td> }, 5000)
<td>{{ shift.registration_count }}/{{ shift.required_helpers|default:shift.room.required_helpers }}</td> }
<td>{{shift.room.name}} </td>
<td><b>{%for item in shift.teambackup_set.all%}{{item.name}}{% if not forloop.last %}, {% endif %}{%empty%}</b> <div class="has-text-danger">unbesetzt</div> <b>{%endfor%}</b></td> setTimeout(() => {
</tr> if (interacted) return;
{% endfor %} window.location.reload();
</tbody> }, 120 * 1000)
</table> });
</div> </script>
</section> {% endblock %}
</body>
</html> {% block body %}
<section class="section">
<div class="container">
<table class="table">
<tbody>
{% for shift in shifts %}
<tr>
<td>{{shift.start_at}}</td>
<td>{{ shift.registration_count }}/{{ shift.required_helpers|default:shift.room.required_helpers }}</td>
<td>{{shift.room.name}} </td>
<td><b>{%for item in shift.teambackup_set.all%}{{item.name}}{% if not forloop.last %}, {% endif %}{%empty%}</b> <div class="has-text-danger">unbesetzt</div> <b>{%endfor%}</b></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</section>
{% endblock %}

View File

@ -1,10 +1,13 @@
{% extends "signage_base.html" %} {% extends "base.html" %}
{% block title %}Team{% endblock %}
{% block body %} {% block body %}
<section class="section"> <section class="section">
<div class="columns is-multiline"> <div class="columns is-multiline">
{% for shift in shifts %} {% for shift in shifts %}
{%include 'partials/worklist_shift.html'%} {% include 'partials/worklist_shift.html' %}
{% endfor %} {% endfor %}
</div> </div>
</section> </section>
{% endblock %} {% endblock %}

View File

@ -4,3 +4,6 @@ from django.apps import AppConfig
class TeamConfig(AppConfig): class TeamConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField" default_auto_field = "django.db.models.BigAutoField"
name = "shiftregister.team" name = "shiftregister.team"
def ready(self):
from . import signals

View File

@ -0,0 +1,23 @@
from django.dispatch import receiver
from django.shortcuts import reverse
from shiftregister.core.signals import populate_nav
@receiver(populate_nav, dispatch_uid="populate_team_nav")
def populate_team_nav(sender, **kwargs):
request = sender
nav_items = []
if request.user.is_authenticated:
nav_items.append(
{"link": reverse("team:shift_overview"), "text": "Schichtübersicht"}
)
nav_items.append(
{"link": reverse("team:shift_free"), "text": "Freie Schichten"}
)
nav_items.append({"link": reverse("team:shift_all"), "text": "Alle Schichten"})
nav_items.append(
{"link": reverse("team:bulk_message"), "text": "Massen-Nachricht"}
)
return nav_items

View File

@ -1,6 +1,7 @@
{% extends "team_base.html" %} {% extends "base.html" %}
{% block title %}Massen-Nachricht{% endblock %} {% block title %}Massen-Nachricht{% endblock %}
{% block content %} {% block content %}
<h3 class="title">Massen-Nachricht versenden</h3> <h3 class="title">Massen-Nachricht versenden</h3>
<form action="" method="post"> <form action="" method="post">

View File

@ -1,6 +1,7 @@
{% extends "team_base.html" %} {% extends "base.html" %}
{% block title %}Helferdetails{% endblock %} {% block title %}Helferdetails{% endblock %}
{% block content %} {% block content %}
<h3 class="title">{{ helper.name }}</h3> <h3 class="title">{{ helper.name }}</h3>
<div class="content"> <div class="content">

View File

@ -1,4 +1,4 @@
{% extends "team_base.html" %} {% extends "base.html" %}
{% block title %}Schichtdetails{% endblock %} {% block title %}Schichtdetails{% endblock %}

View File

@ -1,4 +1,4 @@
{% extends "team_base.html" %} {% extends "base.html" %}
{% block title %}{{ title }}{% endblock %} {% block title %}{{ title }}{% endblock %}

View File

@ -1,4 +1,4 @@
{% extends "team_base.html" %} {% extends "base.html" %}
{% block title %}Schichtübersicht{% endblock %} {% block title %}Schichtübersicht{% endblock %}

View File

@ -1,22 +0,0 @@
{% extends "base.html" %}
{% block title %}Team{% endblock %}
{% block navbar %}
<div class="navbar-start">
<a class="navbar-item" href="{% url 'team:shift_overview' %}">Schichtübersicht</a>
<a class="navbar-item" href="{% url 'team:shift_free' %}">Freie Schichten</a>
<a class="navbar-item" href="{% url 'team:shift_all' %}">Alle Schichten</a>
<a class="navbar-item" href="{% url 'team:bulk_message' %}">Massen-Nachricht</a>
</div>
<div class="navbar-end"></div>
{% endblock %}
{% block body %}
<section class="section">
<div class="container">
{% include 'notifications.html' %}
{% block content %}{% endblock %}
</div>
</section>
{% endblock %}

View File

@ -1 +0,0 @@
{% extends "error_base.html" %}

View File

@ -1,3 +0,0 @@
{% extends "error_base.html" %}
<h3 class="title">{% block error_message%}Seite nicht gefunden{% endblock %}</h3>
{% block error_text%}{% endblock %}

View File

@ -1,3 +0,0 @@
{% extends "error_base.html" %}
<h3 class="title">{% block error_message%}Es ist ein Fehler aufgetreten{% endblock %}</h3>
{% block error_text%}Wir arbeiten dran. Bei dringenden Problemen kannst du dich an den Infopoint wenden.{% endblock %}

View File

@ -1,32 +0,0 @@
{% extends "base.html" %}
{% block title %}Fehler{% endblock %}
{% block navbar %}
<div class="navbar-start">
{% if not helper%}
<a class="navbar-item" href="{% url 'register' %}">Anmelden</a>
{% else %}
{% if not helper.number_validated %}
<p class="navbar-item has-text-danger">Bestätige deine Telefonnummer über den Link in der SMS</p>
{% endif %}
{% if helper.important_shift %}
<a class="navbar-item" href="{% url 'shift' helper.important_shift.pk %}">{%if helper.important_shift.is_running%}Laufende{% else %}Nächste{% endif %} Schicht ({{ helper.important_shift.start_at|date:"H:i" }})</a>
{% endif %}
{% endif %}
</div>
<div class="navbar-end"></div>
{% endblock %}
{% block body %}
<section class="section">
<div class="container">
<h3 class="title">{% block error_message%}Fehler{% endblock %}</h3>
{% block error_text%}<pre>¯\_(ツ)_/¯</pre>{% endblock %}<br>
<a href="{% url 'index' %}" class="button">Zurück zur Schichtübersicht</a>
{% if user.is_authenticated %}
<a href="{% url 'team:index' %}" class="button">Zurück zur Teamansicht</a>
{% endif %}
</div>
</section>
{% endblock %}