Populate nav with signal/context processor

pull/1/head
Luca 2 years ago
parent 441c1434e3
commit 77bbca4d37

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -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",
], ],
}, },
}, },

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -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 %}
Loading…
Cancel
Save