Merge pull request 'notification-badge' (#409) from notification-badge into staging
All checks were successful
CI/CD Pipeline / test (push) Successful in 21m20s
CI/CD Pipeline / deploy-staging (push) Successful in 18m13s
CI/CD Pipeline / deploy-main (push) Has been skipped

Reviewed-on: #409
This commit is contained in:
philipp 2024-04-19 15:54:58 +02:00
commit c122dea6a9
6 changed files with 60 additions and 32 deletions

View File

@ -72,5 +72,6 @@ export default defineConfig({
webServer: { webServer: {
timeout: 15 * 60 * 1000, timeout: 15 * 60 * 1000,
command: 'cd .. && ./test_db.sh && cargo r', command: 'cd .. && ./test_db.sh && cargo r',
url: 'http://127.0.0.1:8000'
}, },
}); });

View File

@ -13,3 +13,4 @@
@import 'components/search'; @import 'components/search';
@import 'components/important'; @import 'components/important';
@import 'components/searchable-table'; @import 'components/searchable-table';
@import 'components/notification';

View File

@ -0,0 +1,5 @@
.notification {
right: -.2rem;
top: -.1rem;
font-size: .5rem;
}

View File

@ -8,7 +8,7 @@ test("cox can create and delete trip", async ({ page }) => {
await page.getByPlaceholder("Passwort").fill("cox"); await page.getByPlaceholder("Passwort").fill("cox");
await page.getByPlaceholder("Passwort").press("Enter"); await page.getByPlaceholder("Passwort").press("Enter");
await page.locator('li').filter({ hasText: 'Geplante Ausfahrten' }).getByRole('link').click(); await page.locator('li').filter({ hasText: 'Geplante Ausfahrten' }).getByRole('link').click();
await page.locator(".relative").first().click(); await page.locator('a[href="#"]:has-text("Ausfahrt")').first().click();
await page.locator("#sidebar #planned_starting_time").click(); await page.locator("#sidebar #planned_starting_time").click();
await page.locator("#sidebar #planned_starting_time").fill("18:00"); await page.locator("#sidebar #planned_starting_time").fill("18:00");
await page.locator("#sidebar #planned_starting_time").press("Tab"); await page.locator("#sidebar #planned_starting_time").press("Tab");
@ -38,8 +38,8 @@ test.describe("cox can edit trips", () => {
await page.getByPlaceholder("Name").press("Tab"); await page.getByPlaceholder("Name").press("Tab");
await page.getByPlaceholder("Passwort").fill("cox"); await page.getByPlaceholder("Passwort").fill("cox");
await page.getByPlaceholder("Passwort").press("Enter"); await page.getByPlaceholder("Passwort").press("Enter");
await page.locator('li').filter({ hasText: 'Geplante Ausfahrten' }).getByRole('link').click(); await page.locator('li').filter({ hasText: 'Geplante Ausfahrten' }).getByRole('link').click();
await page.locator(".relative").first().click(); await page.locator('a[href="#"]:has-text("Ausfahrt")').first().click();
await page.locator("#sidebar #planned_starting_time").click(); await page.locator("#sidebar #planned_starting_time").click();
await page.locator("#sidebar #planned_starting_time").fill("18:00"); await page.locator("#sidebar #planned_starting_time").fill("18:00");
await page.locator("#sidebar #planned_starting_time").press("Tab"); await page.locator("#sidebar #planned_starting_time").press("Tab");

View File

@ -31,21 +31,26 @@
<a href="/"> <a href="/">
{{ loggedin_user.name }} {{ loggedin_user.name }}
{% if loggedin_user.amount_unread_notifications > 0 %}
<span class="bg-red-100 text-red-800 text-sm font-medium me-2 px-2.5 py-0.5 rounded-full dark:bg-red-900 dark:text-red-300 inline-flex items-center">
<svg class="w-3 h-3 me-1.5"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 20 20">
<path d="M1.5 8.67v8.58a3 3 0 0 0 3 3h15a3 3 0 0 0 3-3V8.67l-8.928 5.493a3 3 0 0 1-3.144 0L1.5 8.67Z" />
<path d="M22.5 6.908V6.75a3 3 0 0 0-3-3h-15a3 3 0 0 0-3 3v.158l9.714 5.978a1.5 1.5 0 0 0 1.572 0L22.5 6.908Z" />
</svg>
{{ loggedin_user.amount_unread_notifications }}</span>
{% endif %}
</a> </a>
</div> </div>
<div> <div class="flex items-center">
{% if loggedin_user.amount_unread_notifications > 0 %}
<a href="/#notification"
class="relative inline-flex items-end ms-2 me-3">
<svg height="20"
width="24"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 20 24">
<path d="M1.5 8.67v8.58a3 3 0 0 0 3 3h15a3 3 0 0 0 3-3V8.67l-8.928 5.493a3 3 0 0 1-3.144 0L1.5 8.67Z" />
<path d="M22.5 6.908V6.75a3 3 0 0 0-3-3h-15a3 3 0 0 0-3 3v.158l9.714 5.978a1.5 1.5 0 0 0 1.572 0L22.5 6.908Z" />
</svg>
<small class="bg-red-500 rounded-full w-3 h-3 inline-flex justify-center items-center absolute p-1 notification">
{{ loggedin_user.amount_unread_notifications }}
</small>
</a>
{% endif %}
<a href="#" <a href="#"
class="inline-flex justify-center rounded-md bg-primary-600 mx-1 px-3 py-2 text-sm font-semibold text-white hover:bg-primary-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600 cursor-pointer" class="inline-flex justify-center rounded-md bg-primary-600 mx-1 px-3 py-2 text-sm font-semibold text-white hover:bg-primary-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-600 cursor-pointer"
data-sidebar="true" data-sidebar="true"
@ -175,18 +180,24 @@
<div class="p-2 border border-t-0 border-{{ bg }} mb-4 rounded-b-md"> <div class="p-2 border border-t-0 border-{{ bg }} mb-4 rounded-b-md">
{% if participants | length > 0 %} {% if participants | length > 0 %}
{% for rower in participants %} {% for rower in participants %}
{{ rower.name }} <div class="relative">
{% if rower.is_guest %}<small class="text-gray-600 dark:text-gray-100">(Scheckbuch)</small>{% endif %} {{ rower.name }}
{% if rower.is_real_guest %} {% if rower.is_guest %}<small class="text-gray-600 dark:text-gray-100">(Scheckbuch)</small>{% endif %}
<small class="text-gray-600 dark:text-gray-100">(Gast)</small> {% if rower.is_real_guest %}
{% if allow_removing %} <small class="text-gray-600 dark:text-gray-100">(Gast)</small>
<a href="/planned/remove/{{ trip_details_id }}/{{ rower.name }}" {% if allow_removing %}
class="btn btn-attention btn-fw">Abmelden</a> <a href="/planned/remove/{{ trip_details_id }}/{{ rower.name }}"
class="absolute r-0 bg-red-500 w-5 h-5 text-white rounded-full flex items-center justify-center transform rotate-45 top-0 right-0">
<svg class="inline h-5 w-5" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
<path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z"></path>
</svg>
<span class="sr-only">Abmelden</span>
</a>
{% endif %}
{% endif %} {% endif %}
{% endif %} <span class="hidden">(angemeldet seit
<span class="hidden">(angemeldet seit {{ rower.registered_at }})</span>
{{ rower.registered_at }})</span> </div>
<br />
{% endfor %} {% endfor %}
{% else %} {% else %}
{{ text }} {{ text }}

View File

@ -2,7 +2,11 @@
{% extends "base" %} {% extends "base" %}
{% block content %} {% block content %}
<div class="max-w-screen-lg w-full"> <div class="max-w-screen-lg w-full">
<h1 class="h1">Ruderassistent</h1> <h1 class="h1">
Ruder
<wbr />
assistent
</h1>
<div class="grid gap-3 my-5"> <div class="grid gap-3 my-5">
<div class="m-auto"> <div class="m-auto">
<a href="/planned" <a href="/planned"
@ -11,9 +15,15 @@
<span class="text-xl px-3">Geplante Ausfahrten</span> <span class="text-xl px-3">Geplante Ausfahrten</span>
</a> </a>
</div> </div>
<div class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow mt-5" <div id="notification"
class="bg-white dark:bg-primary-900 text-black dark:text-white rounded-md block shadow mt-5"
role="alert"> role="alert">
<h2 class="h2">Nachrichten</h2> <h2 class="h2">Nachrichten</h2>
{% if loggedin_user.amount_unread_notifications > 10 %}
<div class="text-primary-950 dark:text-white bg-gray-200 dark:bg-primary-950 bg-opacity-80 text-center pb-3 px-3">
Du hast viele ungelesene Benachrichtigungen. Um deine Oberfläche übersichtlich zu halten und wichtige Updates nicht zu verpassen, nimm dir bitte einen Moment Zeit sie zu überprüfen und als gelesen zu markieren (&#10003;).
</div>
{% endif %}
<div class="divide-y"> <div class="divide-y">
{% for notification in notifications %} {% for notification in notifications %}
{% if not notification.read_at %} {% if not notification.read_at %}
@ -27,7 +37,7 @@
<div> <div>
{% if not notification.read_at %} {% if not notification.read_at %}
<a href="/notification/{{ notification.id }}/read" class="inline-block"> <a href="/notification/{{ notification.id }}/read" class="inline-block">
<button class="btn btn-alert bg-red-100 dark:bg-red-900" type="button"> <button class="btn btn-primary" type="button">
&#10003; &#10003;
<span class="sr-only">Notification gelesen</span> <span class="sr-only">Notification gelesen</span>
</button> </button>
@ -38,8 +48,8 @@
{% endif %} {% endif %}
{% endfor %} {% endfor %}
</div> </div>
<details class="py-3 bg-gray-200 dark:bg-primary-950 rounded-b-md"> <details class="py-3 border-t rounded-b-md">
<summary class="px-3">Vergangene Nachrichten (14 Tage)</summary> <summary class="px-3 cursor-pointer">Vergangene Nachrichten (14 Tage)</summary>
<div class="divide-y text-sm"> <div class="divide-y text-sm">
{% for notification in notifications %} {% for notification in notifications %}
{% if notification.read_at %} {% if notification.read_at %}