#23-cleanup-&-enhancements #28

Merged
jkeffects merged 3 commits from #23-cleanup-&-enhancements into main 2025-01-05 15:12:32 +00:00
16 changed files with 320 additions and 14 deletions
Showing only changes of commit 5050011f29 - Show all commits

26
docs/calendar.md Normal file
View file

@ -0,0 +1,26 @@
# Kalender
Der Kalender bietet eine Möglichkeit der Organisation von Terminen in unterschiedlichen Kategorien.
Die Kategorien können in den Einstellungen gesetzt werden. Dabei gibt es folgende Einstellungsmöglichkeiten:
- Bezeichnung
- Farbe
- Standard Kalender Auslieferung
- Passphrase
Die Standard Kalender Auslieferung gibt immer Termine dieser Art in der Öffentlichen Ansicht, als auch in der externen Kalendern an, sofern der Link nicht weiter spezifiziert ist.
Die Passphrase kann zugangsbeschränkend für Termintypen angewandt werden.
## öffentlicher Kalender
Der öffentliche Kalender ist unter dem Pfad `/public/calendar` erreichbar. Dieser Kalender zeigt immer alle Termine an, welche einem Typ mit Standard-Auslieferung zugewiesen sind.
## WebCal
Der Kalender kann auch in den Kalender von zum Beispiel Google, Apple und co eingebunden werden, damit die Termine auch direkt im Kalender des Smartphones oder Outlook... verfügbar sind.
Hierfür kann der Link konfiguriert werden. Der Link kann dann so eingestellt werden, dass passwort-geschützte oder nicht standard Typen ausgeliefert werden. Zusätzlich können unter diesen Links auch die Standard-Typen hinzugefügt werden.
Genutzt werden kann das zum Beispiel, dass Vorstands-Interne Termine oder Mitglieds-Spezifische Termine über einen personalisierten Link ausgegeben werden können.
Wird der erstellte Link in einem Browser geöffnet, sollte automatisch eine ICS-Datei mit den Terminen heruntergeladen werden, oder die Möglichkeit vorgeschlagen werden, den Link in einen Kalender zu integrieren.

View file

@ -1 +1,25 @@
# FF Admin
## FF Admin ist eine Verwaltungsoberfläche für die Feuerwehr:
FF Admin bietet folgende Module:
- Mitgliederverwaltung
- Kalender
- Newsletter-Versand
- Protokolle
- Datenabfrage
- Templating-Engine
- Benutzerverwaltung
- Rollenverwaltung
<br>
-------
<br>
## Struktur
FF Admin ist in Verein, Wehr, Einstellungen und Nutzerverwaltung getrennt.
Die den Modulen zugrunde liegenden Daten können in den Einstellungen gesetzt werden.
Fast alle Daten lassen sich einstellen, damit es keine Einschränkungen in der Auswahl von Werten... gibt. Diese Modularität muss allerdings bei einigen Modulen gesondert eingestellt werden.

51
docs/member.md Normal file
View file

@ -0,0 +1,51 @@
# Mitgliederverwaltung
Die Mitgliederverwaltung bietet eine Startansicht, in welcher alle Mitglieder durch Pagination angezeigt werden. Die Suche ermöglicht eine Full-Text-Suche nach Vor- und Nachnamen.
Ist ein Mitglied ausgewählt, lassen sich innerhalb dessen alle Daten zu einem Mitglied verwalten.
- Allgemeine Daten des Mitglieds
- Mitgliedschaft
- Adressen bzw. Kommunikationswege
- Auszeichnungen
- Qualifikationen
- Vereinsämter
Jedes dieser Verwaltungsmöglichkeiten benötigt vorher eingestellte Werte, welche dann einem Mitglied hinzugefügt werden können.
## Allgemeine Daten des Mitglieds
Die allgemeinen Daten des Mitglieds umfassen die interne Id, Anrede, Vorname, Nachname, Nameaffix und das Geburtsdatum. Diese Daten können über den Stift oben rechts im Eck geändert werden.
Weiterhin zeigt die Übersicht des Mitglieds auch Informationen zu den Einträgen der übrigen Kategorien.
## Mitgliedschaft
Die auswählbaren Mitgliedsarten können in den Einstellungen gesetzt werden.
Im Mitglied können dann Zeiträume einer bestimmten Mitgliedschafts-Art angelegt werden. Wird ein neuer Zeitraum hinzugefügt, wird ein aktuell laufender Zeitraum mit dem Vortag des neuen Startdatums beendet.
Weiterhin kann bei manuellem setzen des Enddatums ein Grund angegeben werden.
## Adressen bzw. Kommunikationswege
Die auswählbaren Kommunikationsarten können in den Einstellungen erstellt werden. Hierfür muss zu jeder Kommunikationsart ausgewählt werden, welche Felder ausgefüllt werden sollen.
Im Miglied kann dann bei jedem kommunikationstyp gesetzt werden, ob dieser bevorzugt wird, und ob der Newsletter dorthin versandt werden soll.
Ist eine Telefonnummer in der Auswahl enthalten, besteht zusätzlich die Möglichkeit, diesen Kommunikationsweg für den Versand der SMS Alarmierung auszuwählen.
## Auszeichnungen
Die auswählbaren Auszeichnungen können in den Einstellungen erstellt werden.
Im Mitglied können Auszeichnungen mit dem Vergabedatum hinzugefügt werden. Wird eine Annahme verweigert oder Ausgabe verwehrt, kann ein Grund hierfür angegeben werden.
## Qualifikation
Die auswählbaren Qualifikationen können in den Einstellungen erstellt werden.
Im Mitglied können Qualifikationen mit einem Start und Enddatum hinzugefügt werden. Eine Notiz kann auch hinzugefügt werden. Zusätzlich zum Enddatum kann ein Grund für das Ende gesetzt werden.
## Vereinsämter
Die auswählbaren Vereinsämter können in den Einstellungen erstellt werden.
Im Mitglied können Qualifikationen mit einem Start und Enddatum hinzugefügt werden. Eine Notiz kann auch hinzugefügt werden.

143
docs/newsletter.md Normal file
View file

@ -0,0 +1,143 @@
# Newsletter
Das Newsletter erlaubt den Druck und Versand von Inhalten zum Verein. Zu einem Newsletter können öffentliche Kalendereinträge hinzugefügt werden.
## Newsletter erstellen
Ein Newsletter besteht aus Titel und Zusammenfassung, um einen schnelleren Überblick in der Pagination zu erhalten.
Im Newsletter können Überschrift, Einleitung/Text und Signatur hinzugefügt werden.
Es können Daten ausgewählt werden, welche dann automatisch nach dem Text und vor der Signatur im Standard-Template angezeigt.
Und es können Empfänger über eine Vordefinierte Datenabfrage oder manuelles hinzufügen festgelegt werden.
Im Tab Druck und Versand wird eine Datei mit allen Hinzugefügten Kalendereinträgen angezeigt, wie auch alle erstellten pdfs wie auch eine pdf, die alle anderen pdfs enthält.
## Versand
In den Einstellungen kann festgelegt werden, welcher Kommunikationstyp wie versandt werden soll. Dies wird zusätzlich nochmals vor dem finalen Versand geprüft.
Es wird beim Druck unterschieden in Ausgaben mit und ohne Adresse. In der Fußzeile wird dann entweder nur der Name oder auch mit Adresse gedruckt.
Die Auswahl des Typs Mail versendet nur den Hauptteil des pdfs mit einer ics-Datei im Anhang.
## Template
Über die Templating-Engine können für den Newsletter abweichende Kopf- und Fußzeilen und ein abweichender Hauptteil festgelegt werden.
Ein Newsletter-Template erhält folgende Daten:
``` ts
// interface:
{
title: string;
description: string;
newsletterTitle: string;
newsletterText: string;
newsletterSignatur: string;
dates: Array<
{
title: string; // enthält alternativen Titel bzw. Titel des Kalendereintrags
content: string; // enthält alternative Beschreibung bzw. Beschreibung des Kalendereintrags
starttime: string;
endtime: string;
location: string;
formattedStarttime: string;
formattedFullStarttime: string;
formattedEndtime: string;
formattedFullEndtime: string;
}
>;
recipient: {
firstname: string;
lastname: string;
salutation: Salutation; // (sir | madam | divers | none)
nameaffix: string;
street: string;
streetNumber: string;
streetNumberAdd: string
};
}
// beispieldaten
{
title: "Beispiel Newsletter Daten",
description: "Zusammenfassung der Demodaten.",
newsletterTitle: "<h1>Sehr geehrtes Feuerwehrmitglied</h1>",
newsletterText: "<p>zu folgenden Terminen möchten wir recht herzlich zur Teilnahme einladen:</p>",
newsletterSignatur: "<p>Mit freundlichen Grüßen</p><p>...</p>",
dates: [
{
title: "Termin 1",
content: "<p>Beschreibung eines Termins</p>",
starttime: new Date(),
formattedStarttime: "Montag 20. Januar",
formattedFullStarttime: "Montag 20. Januar um 19:00",
endtime: new Date(),
formattedEndtime: "Montag 20. Januar",
formattedFullEndtime: "Montag 20. Januar um 21:00",
location: "Feuerwehrhaus",
},
],
recipient: {
firstname: "Julian",
lastname: "Krauser",
salutation: "sir",
nameaffix: "",
street: "Straße",
streetNumber: "Hausnummer",
streetNumberAdd: "Adresszusatz",
},
}
```
Das Template ist als HTML definiert und beinhaltet Platzhalter, welche durch `handlebarsjs` ausgetauscht werden.
``` html
<!-- Standard-Template -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Newsletter</title>
</head>
<body>
<h1>{{{newsletterTitle}}}</h1>
<p>{{{newsletterText}}}</p>
<br />
{{#each dates}}
<div>
<h2><b>{{this.formattedStarttime}}: {{this.title}}</b></h2>
<span>{{{this.content}}}</span>
</div>
<br />
{{/each}}
<br />
<br />
<p>{{{newsletterSignatur}}}</p>
</body>
<style>
h2,
h3,
p,
span,
ul,
li {
padding: 0;
margin: 0;
}
h1,
h2 {
color: #990b00;
}
h2 {
margin-bottom: 5px;
}
</style>
</html>
<!--Footer Template-->
<div style="font-size: 10pt; width: 100%; margin: 0 20px; padding-top: 5px; color: #888; border-top: 0.5px solid black">
{{recipient.lastname}}, {{recipient.firstname}}{{#if recipient.street}},{{/if}} {{recipient.street}}
{{recipient.streetNumber}} {{recipient.streetNumberAdd}}
</div>
```

1
docs/protocol.md Normal file
View file

@ -0,0 +1 @@
# Protokoll

1
docs/query.md Normal file
View file

@ -0,0 +1 @@
# Query Builder & Query Store

1
docs/role.md Normal file
View file

@ -0,0 +1 @@
# Rollenverwaltung

1
docs/templating.md Normal file
View file

@ -0,0 +1 @@
# Templating Engine

1
docs/user.md Normal file
View file

@ -0,0 +1 @@
# Benutzerverwaltung

View file

@ -1,6 +1,6 @@
<template>
<footer
v-if="authCheck && (routeName.includes('admin-') || routeName.includes('account-'))"
v-if="authCheck && (routeName.includes('admin-') || routeName.includes('account-') || routeName.includes('docs-'))"
class="md:hidden flex flex-row h-16 min-h-16 justify-center md:justify-normal p-1 bg-white"
>
<div class="w-full flex flex-row gap-2 h-full align-middle">
@ -12,7 +12,7 @@
:disableSubLink="true"
/>
<TopLevelLink
v-else-if="routeName == 'account' || routeName.includes('account-')"
v-else-if="routeName == 'account' || routeName.includes('account-') || routeName == 'docs' || routeName.includes('docs-')"
:link="{ key: 'club', title: 'Zur Verwaltung', levelDefault: '' }"
:disableSubLink="true"
/>

View file

@ -13,7 +13,7 @@
:link="item"
/>
<TopLevelLink
v-else-if="routeName == 'account' || routeName.includes('account-')"
v-else-if="routeName == 'account' || routeName.includes('account-') || routeName == 'docs' || routeName.includes('docs-')"
:link="{ key: 'club', title: 'Zur Verwaltung', levelDefault: '' }"
:disable-sub-link="true"
/>

View file

@ -13,7 +13,7 @@
leave-to-class="transform scale-95 opacity-0"
>
<MenuItems
class="absolute right-0 mt-2 w-56 z-10 origin-top-right divide-y divide-gray-100 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
class="absolute right-0 mt-2 w-56 z-20 origin-top-right divide-y divide-gray-100 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
>
<div class="px-3 py-1 pt-2">
<p class="text-xs">Angemeldet als</p>
@ -25,6 +25,11 @@
<button button primary @click="close">Mein Account</button>
</RouterLink>
</MenuItem>
<MenuItem v-slot="{ close }">
<RouterLink to="/docs">
<button button primary @click="close">Dokumentation</button>
</RouterLink>
</MenuItem>
<MenuItem>
<span>
<button primary-outline @click="logoutAccount">ausloggen</button>

View file

@ -45,7 +45,6 @@ const router = createRouter({
path: "/reset",
name: "reset",
component: () => import("@/views/RouterView.vue"),
children: [
{
path: "",
@ -655,6 +654,7 @@ const router = createRouter({
path: "/docs",
name: "docs",
component: () => import("@/views/docs/View.vue"),
beforeEnter: [isAuthenticated],
props: true,
children: [
{

View file

@ -1,6 +1,10 @@
<template>
<div class="flex flex-col gap-2 h-full w-full overflow-y-auto">
<div v-if="activeMemberObj != null" class="flex flex-col gap-2 w-full">
<div>
<label for="id">Interne Id</label>
<input type="text" id="id" :value="activeMemberObj.internalId" readonly />
</div>
<div>
<label for="salutation">Anrede</label>
<input type="text" id="salutation" :value="activeMemberObj.salutation" readonly />

View file

@ -1,15 +1,17 @@
<template>
<MainTemplate :useStagedOverviewLink="false">
<template #topBar>
<!-- <template #topBar>
<div class="flex flex-row items-center justify-between pt-5 pb-3 px-7">
<h1 class="font-bold text-xl h-8">{{page}}</h1>
</div>
</template>
<template #main>
<div class="markdown-container">
</template> -->
<template #diffMain>
<div class="flex flex-col gap-2 h-full px-4 overflow-hidden">
<div class="markdown-container overflow-y-scroll">
<component v-if="markdownComponent" :is="markdownComponent" />
<p v-else>Diese Seite existiert nicht.</p>
</div>
</div>
</template>
</MainTemplate>
</template>
@ -40,8 +42,46 @@ export default defineComponent({
},
methods:{
loadPage(){
this.markdownComponent = null
this.markdownComponent = markRaw(defineAsyncComponent(() => import(`$/${this.page?.toLowerCase()}.md`)));
}
}
});
</script>
<style>
.markdown-container {
font-family: 'Open Sans', sans-serif;
color: #555;
background-color: #f8f8f8;
border: 2px solid gray;
padding: 20px;
border-radius: 5px;
height: 100%
}
.markdown-container h1 {
font-size: 2rem !important;
color: #222;
}
.markdown-container h2 {
font-size: 1.25rem !important;
color: #222;
}
.markdown-container hr {
background-color: #222;
margin: 8px 0;
padding: 1px;
}
.markdown-container p {
margin: 10px 0;
}
.markdown-container ul {
list-style-type: disc;
margin-left: 20px;
}
</style>

View file

@ -4,6 +4,14 @@
<SidebarTemplate mainTitle="Dokumentation">
<template #list>
<RoutingLink title="FF Admin" :link="{ name: 'docs-page', params: { page: 'ff-admin' } }" :active="page == 'ff-admin'" />
<RoutingLink title="Mitgliederverwaltung" :link="{ name: 'docs-page', params: { page: 'member' } }" :active="page == 'member'" />
<RoutingLink title="Kalendar" :link="{ name: 'docs-page', params: { page: 'calendar' } }" :active="page == 'calendar'" />
<RoutingLink title="Newsletter-Versand" :link="{ name: 'docs-page', params: { page: 'newsletter' } }" :active="page == 'newsletter'" />
<RoutingLink title="Protokolle" :link="{ name: 'docs-page', params: { page: 'protocol' } }" :active="page == 'protocol'" />
<RoutingLink title="Datenabfrage" :link="{ name: 'docs-page', params: { page: 'query' } }" :active="page == 'query'" />
<RoutingLink title="Templating-Engine" :link="{ name: 'docs-page', params: { page: 'templating' } }" :active="page == 'templating'" />
<RoutingLink title="Benutzerverwaltung" :link="{ name: 'docs-page', params: { page: 'user' } }" :active="page == 'user'" />
<RoutingLink title="Rollenverwaltung" :link="{ name: 'docs-page', params: { page: 'role' } }" :active="page == 'role'" />
</template>
</SidebarTemplate>
</template>