diff --git a/.env.example b/.env.example index c16bf61..4de72c4 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,5 @@ VITE_SERVER_ADDRESS = backend_url #ohne pfad +VITE_APP_NAME_OVERWRITE = Mitgliederverwaltung # overwrites FF Admin VITE_IMPRINT_LINK = https://mywebsite-imprint-url VITE_PRIVACY_LINK = https://mywebsite-privacy-url VITE_CUSTOM_LOGIN_MESSAGE = betrieben von xy diff --git a/.env.production b/.env.production index 5ecf896..6696bbd 100644 --- a/.env.production +++ b/.env.production @@ -1,4 +1,5 @@ VITE_SERVER_ADDRESS = __SERVERADDRESS__ +VITE_APP_NAME_OVERWRITE = __APPNAMEOVERWRITE__ VITE_IMPRINT_LINK = __IMPRINTLINK__ VITE_PRIVACY_LINK = __PRIVACYLINK__ VITE_CUSTOM_LOGIN_MESSAGE = __CUSTOMLOGINMESSAGE__ \ No newline at end of file diff --git a/README.md b/README.md index 7619e76..08b6aaf 100644 --- a/README.md +++ b/README.md @@ -31,12 +31,14 @@ services: restart: unless-stopped #environment: - # - SERVERADDRESS= # wichtig: ohne pfad + # - SERVERADDRESS= # wichtig: ohne Pfad + # - APPNAMEOVERWRITE=Mitgliederverwaltung # ersetzt den Namen FF-Admin auf der Login-Seite und sonstigen Positionen in der Oberfläche # - IMPRINTLINK=https://mywebsite-imprint-url # - PRIVACYLINK=https://mywebsite-privacy-url # - CUSTOMLOGINMESSAGE=betrieben von xy #volumes: - # - /myfavicon.png:/usr/share/nginx/html/favicon.png + # - /myfavicon.ico:/usr/share/nginx/html/favicon.ico # 48x48 px Auflösung + # - /myfavicon.png:/usr/share/nginx/html/favicon.png # 512x512 px Auflösung - wird als pwa Icon genutzt # - /mylogo.png:/usr/share/nginx/html/Logo.png ``` @@ -62,7 +64,7 @@ npm run start ### Konfiguration -Ein eigenes favicon und Logo kann über ein volume ausgetauscht werden. +Ein eigenes Favicon und Logo kann über das verwenden Volume ausgetauscht werden. Es dürfen jedoch nur einzelne Dateien ausgetauscht werden. ## Einrichtung diff --git a/docs/ff-admin.md b/docs/ff-admin.md index 4d370ca..c52cde2 100644 --- a/docs/ff-admin.md +++ b/docs/ff-admin.md @@ -1,6 +1,6 @@ # FF Admin -## FF Admin ist eine Verwaltungsoberfläche für die Feuerwehr: +## FF Admin ist eine Verwaltungsoberfläche für die Feuerwehr oder andere Vereine: FF Admin bietet folgende Module: - Mitgliederverwaltung @@ -23,3 +23,6 @@ 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. + +## Verwendung +Damit FF Admin auch für andere Vereine genutzt werden kann, muss keine erweiterte Konfiguration vorgenommen werden. Am besten ist es alle nicht benötigten Module in der Berechtigungsverwaltung zu deaktivieren. So wird normalerweise der Abschnitt Wehr nicht außerhalb der Feuerwehr benötigt. So müssen hier lediglich keine Berechtigungen vergeben werden und das Modul ist außer für Administratoren oder Owner nicht sichtbar. diff --git a/entrypoint.sh b/entrypoint.sh index 7c29fdb..f84cb83 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,9 +1,10 @@ #!/bin/sh -keys="SERVERADDRESS IMPRINTLINK PRIVACYLINK CUSTOMLOGINMESSAGE" +keys="SERVERADDRESS APPNAMEOVERWRITE IMPRINTLINK PRIVACYLINK CUSTOMLOGINMESSAGE" +files="/usr/share/nginx/html/assets/config-*.js /usr/share/nginx/html/manifest.webmanifest" # Replace env vars in files served by NGINX -for file in /usr/share/nginx/html/assets/config-*.js +for file in $files do echo "Processing $file ..."; for key in $keys diff --git a/index.html b/index.html index c8331c5..35046b4 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,6 @@ - Mitgliederverwaltung
diff --git a/package.json b/package.json index 447a638..220c24e 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore", "format": "prettier --write src/", "bnp": "npm run build-only && npm run preview", - "generate-pwa-assets": "pwa-assets-generator --preset minimal-2023 public/CM.svg" + "generate-pwa-assets": "pwa-assets-generator --preset minimal-2023 public/fw-wappen.png" }, "repository": { "type": "git", diff --git a/public/ChartDB(administration-db).json b/public/ChartDB(administration-db).json index 9310a77..2bc4c00 100644 --- a/public/ChartDB(administration-db).json +++ b/public/ChartDB(administration-db).json @@ -1,8 +1,8 @@ { "id": "0", "name": "administration-db", - "createdAt": "2025-01-08T15:50:20.331Z", - "updatedAt": "2025-01-08T15:50:20.331Z", + "createdAt": "2025-01-12T13:30:56.612Z", + "updatedAt": "2025-01-12T13:30:56.612Z", "databaseType": "mariadb", "tables": [ { @@ -1291,6 +1291,18 @@ }, { "id": "101", + "name": "postalCode", + "type": { + "name": "varchar", + "id": "varchar" + }, + "unique": false, + "nullable": true, + "primaryKey": false, + "createdAt": 1736688552836 + }, + { + "id": "102", "name": "city", "type": { "id": "varchar", @@ -1305,7 +1317,7 @@ "createdAt": 1734524896260 }, { - "id": "102", + "id": "103", "name": "street", "type": { "id": "varchar", @@ -1320,7 +1332,7 @@ "createdAt": 1734524896260 }, { - "id": "103", + "id": "104", "name": "streetNumber", "type": { "id": "int", @@ -1333,7 +1345,7 @@ "createdAt": 1734524896260 }, { - "id": "104", + "id": "105", "name": "streetNumberAddition", "type": { "id": "varchar", @@ -1348,7 +1360,7 @@ "createdAt": 1734524896260 }, { - "id": "105", + "id": "106", "name": "typeId", "type": { "id": "int", @@ -1360,7 +1372,7 @@ "createdAt": 1734524896260 }, { - "id": "106", + "id": "107", "name": "memberId", "type": { "id": "int", @@ -1372,7 +1384,7 @@ "createdAt": 1734524896260 }, { - "id": "107", + "id": "108", "name": "isSMSAlarming", "type": { "id": "tinyint", @@ -1387,7 +1399,7 @@ ], "indexes": [ { - "id": "108", + "id": "109", "name": "PRIMARY", "unique": true, "fieldIds": [ @@ -1396,20 +1408,20 @@ "createdAt": 1734524896260 }, { - "id": "109", + "id": "110", "name": "FK_21994db635b47e07f45b2686a51", "unique": false, "fieldIds": [ - "105" + "106" ], "createdAt": 1734524896260 }, { - "id": "110", + "id": "111", "name": "FK_fc5f59e5c9aafdedd25ed8ed36e", "unique": false, "fieldIds": [ - "106" + "107" ], "createdAt": 1734524896260 } @@ -1421,14 +1433,14 @@ "diagramId": "7gb18czobyir" }, { - "id": "111", + "id": "112", "name": "member_qualifications", "schema": "administration", "x": -250.37357560579426, "y": 82.72883357238302, "fields": [ { - "id": "112", + "id": "113", "name": "id", "type": { "id": "int", @@ -1440,7 +1452,7 @@ "createdAt": 1734524896259 }, { - "id": "113", + "id": "114", "name": "note", "type": { "id": "varchar", @@ -1455,7 +1467,7 @@ "createdAt": 1734524896259 }, { - "id": "114", + "id": "115", "name": "start", "type": { "id": "date", @@ -1467,7 +1479,7 @@ "createdAt": 1734524896259 }, { - "id": "115", + "id": "116", "name": "end", "type": { "id": "date", @@ -1480,7 +1492,7 @@ "createdAt": 1734524896259 }, { - "id": "116", + "id": "117", "name": "terminationReason", "type": { "id": "varchar", @@ -1495,7 +1507,7 @@ "createdAt": 1734524896259 }, { - "id": "117", + "id": "118", "name": "memberId", "type": { "id": "int", @@ -1507,7 +1519,7 @@ "createdAt": 1734524896259 }, { - "id": "118", + "id": "119", "name": "qualificationId", "type": { "id": "int", @@ -1521,31 +1533,31 @@ ], "indexes": [ { - "id": "119", + "id": "120", "name": "PRIMARY", "unique": true, "fieldIds": [ - "112" - ], - "createdAt": 1734524896259 - }, - { - "id": "120", - "name": "FK_98b70e687c35709d2f01b3d7d74", - "unique": false, - "fieldIds": [ - "117" + "113" ], "createdAt": 1734524896259 }, { "id": "121", - "name": "FK_dbebe53df1caa0b6715a220b0ea", + "name": "FK_98b70e687c35709d2f01b3d7d74", "unique": false, "fieldIds": [ "118" ], "createdAt": 1734524896259 + }, + { + "id": "122", + "name": "FK_dbebe53df1caa0b6715a220b0ea", + "unique": false, + "fieldIds": [ + "119" + ], + "createdAt": 1734524896259 } ], "color": "#ff6b8a", @@ -1555,14 +1567,14 @@ "diagramId": "7gb18czobyir" }, { - "id": "122", + "id": "123", "name": "executive_position", "schema": "administration", "x": -542.0601569820527, "y": 474.7348899814151, "fields": [ { - "id": "123", + "id": "124", "name": "id", "type": { "id": "int", @@ -1574,7 +1586,7 @@ "createdAt": 1734524896260 }, { - "id": "124", + "id": "125", "name": "position", "type": { "id": "varchar", @@ -1590,11 +1602,11 @@ ], "indexes": [ { - "id": "125", + "id": "126", "name": "PRIMARY", "unique": true, "fieldIds": [ - "123" + "124" ], "createdAt": 1734524896260 } @@ -1606,14 +1618,14 @@ "diagramId": "7gb18czobyir" }, { - "id": "126", + "id": "127", "name": "qualification", "schema": "administration", "x": -568.0578068648438, "y": 192.56221408776412, "fields": [ { - "id": "127", + "id": "128", "name": "id", "type": { "id": "int", @@ -1625,7 +1637,7 @@ "createdAt": 1734524896260 }, { - "id": "128", + "id": "129", "name": "qualification", "type": { "id": "varchar", @@ -1639,7 +1651,7 @@ "createdAt": 1734524896260 }, { - "id": "129", + "id": "130", "name": "description", "type": { "id": "varchar", @@ -1656,11 +1668,11 @@ ], "indexes": [ { - "id": "130", + "id": "131", "name": "PRIMARY", "unique": true, "fieldIds": [ - "127" + "128" ], "createdAt": 1734524896260 } @@ -1674,28 +1686,14 @@ ], "relationships": [ { - "id": "131", + "id": "132", "name": "FK_1fd52c8f109123e5a2c67dc2c83", "sourceSchema": "administration", "targetSchema": "administration", "sourceTableId": "1", - "targetTableId": "122", + "targetTableId": "123", "sourceFieldId": "7", - "targetFieldId": "123", - "sourceCardinality": "many", - "targetCardinality": "one", - "createdAt": 1734524896262, - "diagramId": "7gb18czobyir" - }, - { - "id": "132", - "name": "FK_21994db635b47e07f45b2686a51", - "sourceSchema": "administration", - "targetSchema": "administration", - "sourceTableId": "96", - "targetTableId": "71", - "sourceFieldId": "105", - "targetFieldId": "72", + "targetFieldId": "124", "sourceCardinality": "many", "targetCardinality": "one", "createdAt": 1734524896262, @@ -1703,6 +1701,20 @@ }, { "id": "133", + "name": "FK_21994db635b47e07f45b2686a51", + "sourceSchema": "administration", + "targetSchema": "administration", + "sourceTableId": "96", + "targetTableId": "71", + "sourceFieldId": "106", + "targetFieldId": "72", + "sourceCardinality": "many", + "targetCardinality": "one", + "createdAt": 1734524896262, + "diagramId": "7gb18czobyir" + }, + { + "id": "134", "name": "FK_2912b056a5d0b7977360a986164", "sourceSchema": "administration", "targetSchema": "administration", @@ -1716,7 +1728,7 @@ "diagramId": "7gb18czobyir" }, { - "id": "134", + "id": "135", "name": "FK_3b4b41597707b13086e71727422", "sourceSchema": "administration", "targetSchema": "administration", @@ -1730,13 +1742,13 @@ "diagramId": "7gb18czobyir" }, { - "id": "135", + "id": "136", "name": "FK_98b70e687c35709d2f01b3d7d74", "sourceSchema": "administration", "targetSchema": "administration", - "sourceTableId": "111", + "sourceTableId": "112", "targetTableId": "60", - "sourceFieldId": "117", + "sourceFieldId": "118", "targetFieldId": "61", "sourceCardinality": "many", "targetCardinality": "one", @@ -1744,7 +1756,7 @@ "diagramId": "7gb18czobyir" }, { - "id": "136", + "id": "137", "name": "FK_a47e04bfd3671d8a375d1896d25", "sourceSchema": "administration", "targetSchema": "administration", @@ -1758,7 +1770,7 @@ "diagramId": "7gb18czobyir" }, { - "id": "137", + "id": "138", "name": "FK_ba47b44c2ddf34c1bcc75df6675", "sourceSchema": "administration", "targetSchema": "administration", @@ -1772,21 +1784,21 @@ "diagramId": "7gb18czobyir" }, { - "id": "138", + "id": "139", "name": "FK_dbebe53df1caa0b6715a220b0ea", "sourceSchema": "administration", "targetSchema": "administration", - "sourceTableId": "111", - "targetTableId": "126", - "sourceFieldId": "118", - "targetFieldId": "127", + "sourceTableId": "112", + "targetTableId": "127", + "sourceFieldId": "119", + "targetFieldId": "128", "sourceCardinality": "many", "targetCardinality": "one", "createdAt": 1734524896262, "diagramId": "7gb18czobyir" }, { - "id": "139", + "id": "140", "name": "FK_e9fd4d37c4ac0fb08bd6eeeda3c", "sourceSchema": "administration", "targetSchema": "administration", @@ -1800,13 +1812,13 @@ "diagramId": "7gb18czobyir" }, { - "id": "140", + "id": "141", "name": "FK_fc5f59e5c9aafdedd25ed8ed36e", "sourceSchema": "administration", "targetSchema": "administration", "sourceTableId": "96", "targetTableId": "60", - "sourceFieldId": "106", + "sourceFieldId": "107", "targetFieldId": "61", "sourceCardinality": "many", "targetCardinality": "one", @@ -1816,7 +1828,7 @@ ], "dependencies": [ { - "id": "141", + "id": "142", "schema": "administration", "tableId": "60", "dependentSchema": "administration", @@ -1825,36 +1837,27 @@ "diagramId": "7gb18czobyir" }, { - "id": "142", + "id": "143", "schema": "administration", - "tableId": "126", + "tableId": "127", "dependentSchema": "administration", "dependentTableId": "86", "createdAt": 1734524897266, "diagramId": "7gb18czobyir" }, { - "id": "143", + "id": "144", "schema": "administration", - "tableId": "111", + "tableId": "112", "dependentSchema": "administration", "dependentTableId": "86", "createdAt": 1734524897267, "diagramId": "7gb18czobyir" }, - { - "id": "144", - "schema": "administration", - "tableId": "60", - "dependentSchema": "administration", - "dependentTableId": "11", - "createdAt": 1734524897283, - "diagramId": "7gb18czobyir" - }, { "id": "145", "schema": "administration", - "tableId": "1", + "tableId": "60", "dependentSchema": "administration", "dependentTableId": "11", "createdAt": 1734524897283, @@ -1863,6 +1866,15 @@ { "id": "146", "schema": "administration", + "tableId": "1", + "dependentSchema": "administration", + "dependentTableId": "11", + "createdAt": 1734524897283, + "diagramId": "7gb18czobyir" + }, + { + "id": "147", + "schema": "administration", "tableId": "60", "dependentSchema": "administration", "dependentTableId": "21", @@ -1870,7 +1882,7 @@ "diagramId": "7gb18czobyir" }, { - "id": "147", + "id": "148", "schema": "administration", "tableId": "56", "dependentSchema": "administration", @@ -1879,7 +1891,7 @@ "diagramId": "7gb18czobyir" }, { - "id": "148", + "id": "149", "schema": "administration", "tableId": "35", "dependentSchema": "administration", @@ -1888,16 +1900,16 @@ "diagramId": "7gb18czobyir" }, { - "id": "149", + "id": "150", "schema": "administration", - "tableId": "122", + "tableId": "123", "dependentSchema": "administration", "dependentTableId": "11", "createdAt": 1734524897283, "diagramId": "7gb18czobyir" }, { - "id": "150", + "id": "151", "schema": "administration", "tableId": "60", "dependentSchema": "administration", diff --git a/public/administration-db.png b/public/administration-db.png index 6c4bd2a..d150de5 100644 Binary files a/public/administration-db.png and b/public/administration-db.png differ diff --git a/public/administration-db.svg b/public/administration-db.svg index b29954e..13fcea8 100644 --- a/public/administration-db.svg +++ b/public/administration-db.svg @@ -1 +1 @@ -
id
int
note
varchar?
start
date
end
date?
memberId
int
executivePositionId
int
positionId
int?
position
varchar?
memberId
int?
memberSalutation
varchar?
memberFirstname
varchar?
memberLastname
varchar?
memberNameaffix
varchar?
memberBirthdate
date?
durationInDays
decimal?
member_id
int
member_salutation
varchar
member_firstname
varchar
member_lastname
varchar
member_nameaffix
varchar
member_birthdate
date
member_sendNewsletterId
int?
todayAge
bigint?
ageThisYear
int?
id
int
award
varchar
id
int
start
date
end
date?
terminationReason
varchar?
memberId
int
statusId
int
id
int
given
tinyint
note
varchar?
date
date
memberId
int
awardId
int
id
int
status
varchar
id
int
salutation
varchar
firstname
varchar
lastname
varchar
nameaffix
varchar
birthdate
date
internalId
varchar?
sendNewsletterId
int?
id
int
type
varchar
useColumns
varchar
statusId
int?
status
varchar?
memberId
int?
memberSalutation
varchar?
memberFirstname
varchar?
memberLastname
varchar?
memberNameaffix
varchar?
memberBirthdate
date?
durationInDays
decimal?
qualificationId
int?
qualification
varchar?
memberId
int?
memberSalutation
varchar?
memberFirstname
varchar?
memberLastname
varchar?
memberNameaffix
varchar?
memberBirthdate
date?
durationInDays
decimal?
id
int
preferred
tinyint
mobile
varchar?
email
varchar?
city
varchar?
street
varchar?
streetNumber
int?
streetNumberAddition
varchar?
typeId
int
memberId
int
isSMSAlarming
tinyint
Mehr anzeigen
id
int
note
varchar?
start
date
end
date?
terminationReason
varchar?
memberId
int
qualificationId
int
id
int
position
varchar
id
int
qualification
varchar
description
varchar?
\ No newline at end of file +
id
int
note
varchar?
start
date
end
date?
memberId
int
executivePositionId
int
positionId
int?
position
varchar?
memberId
int?
memberSalutation
varchar?
memberFirstname
varchar?
memberLastname
varchar?
memberNameaffix
varchar?
memberBirthdate
date?
durationInDays
decimal?
member_id
int
member_salutation
varchar
member_firstname
varchar
member_lastname
varchar
member_nameaffix
varchar
member_birthdate
date
member_sendNewsletterId
int?
todayAge
bigint?
ageThisYear
int?
id
int
award
varchar
id
int
start
date
end
date?
terminationReason
varchar?
memberId
int
statusId
int
id
int
given
tinyint
note
varchar?
date
date
memberId
int
awardId
int
id
int
status
varchar
id
int
salutation
varchar
firstname
varchar
lastname
varchar
nameaffix
varchar
birthdate
date
internalId
varchar?
sendNewsletterId
int?
id
int
type
varchar
useColumns
varchar
statusId
int?
status
varchar?
memberId
int?
memberSalutation
varchar?
memberFirstname
varchar?
memberLastname
varchar?
memberNameaffix
varchar?
memberBirthdate
date?
durationInDays
decimal?
qualificationId
int?
qualification
varchar?
memberId
int?
memberSalutation
varchar?
memberFirstname
varchar?
memberLastname
varchar?
memberNameaffix
varchar?
memberBirthdate
date?
durationInDays
decimal?
id
int
preferred
tinyint
mobile
varchar?
email
varchar?
postalCode
varchar?
city
varchar?
street
varchar?
streetNumber
int?
streetNumberAddition
varchar?
typeId
int
memberId
int
isSMSAlarming
tinyint
Weniger anzeigen
id
int
note
varchar?
start
date
end
date?
terminationReason
varchar?
memberId
int
qualificationId
int
id
int
position
varchar
id
int
qualification
varchar
description
varchar?
\ No newline at end of file diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..cabbec8 Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/favicon.png b/public/favicon.png index 5e07171..4d193a3 100644 Binary files a/public/favicon.png and b/public/favicon.png differ diff --git a/public/fw-wappen.png b/public/fw-wappen.png new file mode 100644 index 0000000..5e07171 Binary files /dev/null and b/public/fw-wappen.png differ diff --git a/src/components/FormBottomBar.vue b/src/components/FormBottomBar.vue index 6d46114..8854d97 100644 --- a/src/components/FormBottomBar.vue +++ b/src/components/FormBottomBar.vue @@ -5,10 +5,16 @@ Impressum

{{ config.custom_login_message }}

- © Admin-Portal by JK Effects +

+ © + Admin-Portal + by + JK Effects +

+ \ No newline at end of file diff --git a/src/components/Header.vue b/src/components/Header.vue index 78a3897..6f7b03c 100644 --- a/src/components/Header.vue +++ b/src/components/Header.vue @@ -2,7 +2,7 @@
LOGO -

FF Admin

+

{{config.app_name_overwrite || "FF Admin"}}

@@ -57,6 +59,7 @@ export default defineComponent({ let createAward: CreateAwardViewModel = { award: formData.award.value, }; + this.status = "loading"; this.createAward(createAward) .then(() => { this.status = { status: "success" }; diff --git a/src/components/admin/settings/award/DeleteAwardModal.vue b/src/components/admin/settings/award/DeleteAwardModal.vue index c3a1e6a..2f59002 100644 --- a/src/components/admin/settings/award/DeleteAwardModal.vue +++ b/src/components/admin/settings/award/DeleteAwardModal.vue @@ -16,7 +16,9 @@
- +
@@ -57,6 +59,7 @@ export default defineComponent({ ...mapActions(useModalStore, ["closeModal"]), ...mapActions(useAwardStore, ["deleteAward"]), triggerDelete() { + this.status = "loading"; this.deleteAward(this.data) .then(() => { this.status = { status: "success" }; diff --git a/src/components/admin/settings/calendarType/CreateCalendarTypeModal.vue b/src/components/admin/settings/calendarType/CreateCalendarTypeModal.vue index b35a897..4e83c1b 100644 --- a/src/components/admin/settings/calendarType/CreateCalendarTypeModal.vue +++ b/src/components/admin/settings/calendarType/CreateCalendarTypeModal.vue @@ -32,11 +32,7 @@
-
@@ -82,6 +78,7 @@ export default defineComponent({ nscdr: formData.nscdr.checked, passphrase: formData.passphrase.value, }; + this.status = "loading"; this.createCalendarType(createCalendarType) .then(() => { this.status = { status: "success" }; diff --git a/src/components/admin/settings/calendarType/DeleteCalendarTypeModal.vue b/src/components/admin/settings/calendarType/DeleteCalendarTypeModal.vue index 46642ec..04186d6 100644 --- a/src/components/admin/settings/calendarType/DeleteCalendarTypeModal.vue +++ b/src/components/admin/settings/calendarType/DeleteCalendarTypeModal.vue @@ -16,7 +16,9 @@
- +
@@ -56,6 +58,7 @@ export default defineComponent({ ...mapActions(useModalStore, ["closeModal"]), ...mapActions(useCalendarTypeStore, ["deleteCalendarType"]), triggerDelete() { + this.status = "loading"; this.deleteCalendarType(this.data) .then(() => { this.status = { status: "success" }; diff --git a/src/components/admin/settings/communicationType/CreateCommunicationTypeModal.vue b/src/components/admin/settings/communicationType/CreateCommunicationTypeModal.vue index c9cf750..32929dc 100644 --- a/src/components/admin/settings/communicationType/CreateCommunicationTypeModal.vue +++ b/src/components/admin/settings/communicationType/CreateCommunicationTypeModal.vue @@ -65,7 +65,9 @@
- +
@@ -114,6 +116,7 @@ export default defineComponent({ type: formData.communicationType.value, fields: this.selectedFields, }; + this.status = "loading"; this.createCommunicationType(createCommunicationType) .then(() => { this.status = { status: "success" }; diff --git a/src/components/admin/settings/communicationType/DeleteCommunicationTypeModal.vue b/src/components/admin/settings/communicationType/DeleteCommunicationTypeModal.vue index f9a18a3..d04aa14 100644 --- a/src/components/admin/settings/communicationType/DeleteCommunicationTypeModal.vue +++ b/src/components/admin/settings/communicationType/DeleteCommunicationTypeModal.vue @@ -16,7 +16,9 @@
- +
@@ -56,6 +58,7 @@ export default defineComponent({ ...mapActions(useModalStore, ["closeModal"]), ...mapActions(useCommunicationTypeStore, ["deleteCommunicationType"]), triggerDelete() { + this.status = "loading"; this.deleteCommunicationType(this.data) .then(() => { this.status = { status: "success" }; diff --git a/src/components/admin/settings/executivePosition/CreateExecutivePositionModal.vue b/src/components/admin/settings/executivePosition/CreateExecutivePositionModal.vue index c01cc47..411fd55 100644 --- a/src/components/admin/settings/executivePosition/CreateExecutivePositionModal.vue +++ b/src/components/admin/settings/executivePosition/CreateExecutivePositionModal.vue @@ -19,7 +19,9 @@
- +
@@ -57,6 +59,7 @@ export default defineComponent({ let createExecutivePosition: CreateExecutivePositionViewModel = { position: formData.executivePosition.value, }; + this.status = "loading"; this.createExecutivePosition(createExecutivePosition) .then(() => { this.status = { status: "success" }; diff --git a/src/components/admin/settings/executivePosition/DeleteExecutivePositionModal.vue b/src/components/admin/settings/executivePosition/DeleteExecutivePositionModal.vue index 399bdcd..7099608 100644 --- a/src/components/admin/settings/executivePosition/DeleteExecutivePositionModal.vue +++ b/src/components/admin/settings/executivePosition/DeleteExecutivePositionModal.vue @@ -16,7 +16,9 @@
- +
@@ -57,6 +59,7 @@ export default defineComponent({ ...mapActions(useModalStore, ["closeModal"]), ...mapActions(useExecutivePositionStore, ["deleteExecutivePosition"]), triggerDelete() { + this.status = "loading"; this.deleteExecutivePosition(this.data) .then(() => { this.status = { status: "success" }; diff --git a/src/components/admin/settings/membershipStatus/CreateMembershipStatusModal.vue b/src/components/admin/settings/membershipStatus/CreateMembershipStatusModal.vue index 8bbe3af..dffdf5c 100644 --- a/src/components/admin/settings/membershipStatus/CreateMembershipStatusModal.vue +++ b/src/components/admin/settings/membershipStatus/CreateMembershipStatusModal.vue @@ -19,7 +19,9 @@
- +
@@ -57,6 +59,7 @@ export default defineComponent({ let createMembershipStatus: CreateMembershipStatusViewModel = { status: formData.membershipStatus.value, }; + this.status = "loading"; this.createMembershipStatus(createMembershipStatus) .then(() => { this.status = { status: "success" }; diff --git a/src/components/admin/settings/membershipStatus/DeleteMembershipStatusModal.vue b/src/components/admin/settings/membershipStatus/DeleteMembershipStatusModal.vue index 081727a..5868a8a 100644 --- a/src/components/admin/settings/membershipStatus/DeleteMembershipStatusModal.vue +++ b/src/components/admin/settings/membershipStatus/DeleteMembershipStatusModal.vue @@ -16,7 +16,9 @@
- +
@@ -57,6 +59,7 @@ export default defineComponent({ ...mapActions(useModalStore, ["closeModal"]), ...mapActions(useMembershipStatusStore, ["deleteMembershipStatus"]), triggerDelete() { + this.status = "loading"; this.deleteMembershipStatus(this.data) .then(() => { this.status = { status: "success" }; diff --git a/src/components/admin/settings/qualification/CreateQualificationModal.vue b/src/components/admin/settings/qualification/CreateQualificationModal.vue index a70a710..c2ac0ab 100644 --- a/src/components/admin/settings/qualification/CreateQualificationModal.vue +++ b/src/components/admin/settings/qualification/CreateQualificationModal.vue @@ -23,7 +23,9 @@
- +
@@ -62,6 +64,7 @@ export default defineComponent({ qualification: formData.qualification.value, description: formData.description.value, }; + this.status = "loading"; this.createQualification(createQualification) .then(() => { this.status = { status: "success" }; diff --git a/src/components/admin/settings/qualification/DeleteQualificationModal.vue b/src/components/admin/settings/qualification/DeleteQualificationModal.vue index ffdb77b..011b132 100644 --- a/src/components/admin/settings/qualification/DeleteQualificationModal.vue +++ b/src/components/admin/settings/qualification/DeleteQualificationModal.vue @@ -16,7 +16,9 @@
- +
@@ -57,6 +59,7 @@ export default defineComponent({ ...mapActions(useModalStore, ["closeModal"]), ...mapActions(useQualificationStore, ["deleteQualification"]), triggerDelete() { + this.status = "loading"; this.deleteQualification(this.data) .then(() => { this.status = { status: "success" }; diff --git a/src/components/admin/settings/queryStore/CreateQueryStoreModal.vue b/src/components/admin/settings/queryStore/CreateQueryStoreModal.vue index 485381a..7f27a9e 100644 --- a/src/components/admin/settings/queryStore/CreateQueryStoreModal.vue +++ b/src/components/admin/settings/queryStore/CreateQueryStoreModal.vue @@ -19,7 +19,9 @@
- +
@@ -62,6 +64,7 @@ export default defineComponent({ title: formData.title.value, query: this.query ?? "", }; + this.status = "loading"; this.createQueryStore(createAward) .then(() => { this.status = { status: "success" }; diff --git a/src/components/admin/settings/queryStore/DeleteQueryStoreModal.vue b/src/components/admin/settings/queryStore/DeleteQueryStoreModal.vue index eb50139..a623deb 100644 --- a/src/components/admin/settings/queryStore/DeleteQueryStoreModal.vue +++ b/src/components/admin/settings/queryStore/DeleteQueryStoreModal.vue @@ -16,7 +16,9 @@
- +
@@ -56,6 +58,7 @@ export default defineComponent({ ...mapActions(useModalStore, ["closeModal"]), ...mapActions(useQueryStoreStore, ["deleteQueryStore"]), triggerDelete() { + this.status = "loading"; this.deleteQueryStore(this.data) .then(() => { this.status = { status: "success" }; diff --git a/src/components/admin/settings/queryStore/UpdateQueryStoreModal.vue b/src/components/admin/settings/queryStore/UpdateQueryStoreModal.vue index a60b8b7..82b10f4 100644 --- a/src/components/admin/settings/queryStore/UpdateQueryStoreModal.vue +++ b/src/components/admin/settings/queryStore/UpdateQueryStoreModal.vue @@ -21,7 +21,9 @@
- +
@@ -73,6 +75,7 @@ export default defineComponent({ id: this.data, query: this.query ?? "", }; + this.status = "loading"; this.updateActiveQueryStore(updateQuery) .then(() => { this.status = { status: "success" }; diff --git a/src/components/admin/settings/template/CreateTemplateModal.vue b/src/components/admin/settings/template/CreateTemplateModal.vue index 14ddbdd..5319e57 100644 --- a/src/components/admin/settings/template/CreateTemplateModal.vue +++ b/src/components/admin/settings/template/CreateTemplateModal.vue @@ -23,7 +23,9 @@
- +
@@ -62,6 +64,7 @@ export default defineComponent({ template: formData.template.value, description: formData.description.value, }; + this.status = "loading"; this.createTemplate(createTemplate) .then((res) => { this.status = { status: "success" }; diff --git a/src/components/admin/settings/template/DeleteTemplateModal.vue b/src/components/admin/settings/template/DeleteTemplateModal.vue index 8bbf2ba..29ad5fa 100644 --- a/src/components/admin/settings/template/DeleteTemplateModal.vue +++ b/src/components/admin/settings/template/DeleteTemplateModal.vue @@ -16,7 +16,9 @@
- +
@@ -57,6 +59,7 @@ export default defineComponent({ ...mapActions(useModalStore, ["closeModal"]), ...mapActions(useTemplateStore, ["deleteTemplate"]), triggerDelete() { + this.status = "loading"; this.deleteTemplate(this.data) .then(() => { this.status = { status: "success" }; diff --git a/src/components/admin/user/role/CreateRoleModal.vue b/src/components/admin/user/role/CreateRoleModal.vue index 87d9573..9699f9c 100644 --- a/src/components/admin/user/role/CreateRoleModal.vue +++ b/src/components/admin/user/role/CreateRoleModal.vue @@ -19,7 +19,9 @@
- +
@@ -53,6 +55,7 @@ export default defineComponent({ ...mapActions(useRoleStore, ["createRole"]), triggerCreateRole(e: any) { let formData = e.target.elements; + this.status = "loading"; this.createRole(formData.role.value) .then(() => { this.status = { status: "success" }; diff --git a/src/components/admin/user/role/DeleteRoleModal.vue b/src/components/admin/user/role/DeleteRoleModal.vue index 764c487..eda8907 100644 --- a/src/components/admin/user/role/DeleteRoleModal.vue +++ b/src/components/admin/user/role/DeleteRoleModal.vue @@ -16,7 +16,9 @@
- +
@@ -56,6 +58,7 @@ export default defineComponent({ ...mapActions(useModalStore, ["closeModal"]), ...mapActions(useRoleStore, ["deleteRole"]), triggerDeleteRole() { + this.status = "loading"; this.deleteRole(this.data) .then(() => { this.status = { status: "success" }; diff --git a/src/components/admin/user/user/DeleteUserModal.vue b/src/components/admin/user/user/DeleteUserModal.vue index 720a06f..fcd155a 100644 --- a/src/components/admin/user/user/DeleteUserModal.vue +++ b/src/components/admin/user/user/DeleteUserModal.vue @@ -16,7 +16,9 @@
- +
@@ -56,6 +58,7 @@ export default defineComponent({ ...mapActions(useModalStore, ["closeModal"]), ...mapActions(useUserStore, ["deleteUser"]), triggerDeleteUser() { + this.status = "loading"; this.deleteUser(this.data) .then(() => { this.status = { status: "success" }; diff --git a/src/components/admin/user/user/InviteUserModal.vue b/src/components/admin/user/user/InviteUserModal.vue index 9ea6d9f..7e46698 100644 --- a/src/components/admin/user/user/InviteUserModal.vue +++ b/src/components/admin/user/user/InviteUserModal.vue @@ -32,7 +32,9 @@
- +
@@ -70,13 +72,13 @@ export default defineComponent({ ...mapActions(useInviteStore, ["createInvite"]), invite(e: any) { let formData = e.target.elements; - this.status = "loading"; let createInvite: CreateInviteViewModel = { username: formData.username.value, mail: formData.mail.value, firstname: formData.firstname.value, lastname: formData.lastname.value, }; + this.status = "loading"; this.createInvite(createInvite) .then((result) => { this.status = { status: "success" }; @@ -86,7 +88,7 @@ export default defineComponent({ }) .catch((err) => { this.status = { status: "failed", reason: err.response.data }; - }) + }); }, }, }); diff --git a/src/config.ts b/src/config.ts index 856263a..1351e98 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,5 +1,6 @@ export interface Config { server_address: string; + app_name_overwrite: string; imprint_link: string; privacy_link: string; custom_login_message: string; @@ -7,6 +8,7 @@ export interface Config { export const config: Config = { server_address: import.meta.env.VITE_SERVER_ADDRESS, + app_name_overwrite: import.meta.env.VITE_APP_NAME_OVERWRITE, imprint_link: import.meta.env.VITE_IMPRINT_LINK, privacy_link: import.meta.env.VITE_PRIVACY_LINK, custom_login_message: import.meta.env.VITE_CUSTOM_LOGIN_MESSAGE, diff --git a/src/helpers/queryFormatter.ts b/src/helpers/queryFormatter.ts index fe8cc6e..f934c6a 100644 --- a/src/helpers/queryFormatter.ts +++ b/src/helpers/queryFormatter.ts @@ -14,7 +14,6 @@ export function flattenQueryResult(result: Array): Array<{ [key: st const newKey = prefix ? `${prefix}_${key}` : key; if (Array.isArray(value) && value.every((item) => typeof item === "object" && item !== null)) { - console.log(value, newKey); const arrayResults: Array<{ [key: string]: FieldType }> = []; value.forEach((item) => { const flattenedItems = flatten(item, newKey); @@ -29,7 +28,6 @@ export function flattenQueryResult(result: Array): Array<{ [key: st }); results = tempResults; } else if (value && typeof value === "object" && !Array.isArray(value)) { - console.log(value, newKey); const objResults = flatten(value as QueryResult, newKey); const tempResults: Array<{ [key: string]: FieldType }> = []; results.forEach((res) => { diff --git a/src/router/index.ts b/src/router/index.ts index ec0156e..335f7fa 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -9,6 +9,7 @@ import type { PermissionType, PermissionSection, PermissionModule } from "@/type import { resetMemberStores, setMemberId } from "./memberGuard"; import { resetProtocolStores, setProtocolId } from "./protocolGuard"; import { resetNewsletterStores, setNewsletterId } from "./newsletterGuard"; +import { config } from "../config"; const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), @@ -683,6 +684,10 @@ const router = createRouter({ ], }); +router.afterEach((to, from) => { + document.title = config.app_name_overwrite || "FF Admin"; +}); + export default router; declare module "vue-router" { diff --git a/src/router/newsletterGuard.ts b/src/router/newsletterGuard.ts index d96cb8e..5d96cf9 100644 --- a/src/router/newsletterGuard.ts +++ b/src/router/newsletterGuard.ts @@ -9,8 +9,6 @@ export async function setNewsletterId(to: any, from: any, next: any) { useNewsletterDatesStore().$reset(); useNewsletterRecipientsStore().$reset(); - useNewsletterPrintoutStore().unsubscribePdfPrintingProgress(); - useNewsletterPrintoutStore().unsubscribeMailSendingProgress(); useNewsletterPrintoutStore().$reset(); next(); @@ -23,8 +21,6 @@ export async function resetNewsletterStores(to: any, from: any, next: any) { useNewsletterDatesStore().$reset(); useNewsletterRecipientsStore().$reset(); - useNewsletterPrintoutStore().unsubscribePdfPrintingProgress(); - useNewsletterPrintoutStore().unsubscribeMailSendingProgress(); useNewsletterPrintoutStore().$reset(); next(); diff --git a/src/serverCom.ts b/src/serverCom.ts index 210406e..45afab9 100644 --- a/src/serverCom.ts +++ b/src/serverCom.ts @@ -28,6 +28,15 @@ http.interceptors.request.use( } } + const isPWA = + window.matchMedia("(display-mode: standalone)").matches || + window.matchMedia("(display-mode: fullscreen)").matches; + if (isPWA) { + if (config.headers) { + config.headers["X-PWA-Client"] = isPWA ? "true" : "false"; + } + } + return config; }, (error) => { @@ -53,11 +62,15 @@ http.interceptors.response.use( .then(() => { return http(originalRequest); }) - .catch(); + .catch(() => {}); } const notificationStore = useNotificationStore(); - notificationStore.push("Fehler", error.response.data, "error"); + if (error.toString().includes("Network Error")) { + notificationStore.push("Netzwerkfehler", "Server nicht erreichbar!", "error"); + } else { + notificationStore.push("Fehler", error.response.data, "error"); + } return Promise.reject(error); } @@ -99,4 +112,25 @@ function newEventSource(path: string) { }); } -export { http, newEventSource, host }; +async function* streamingFetch(path: string, abort?: AbortController) { + await refreshToken() + .then(() => {}) + .catch(() => {}); + + const token = localStorage.getItem("accessToken"); + const response = await fetch(url + "/api" + path, { + signal: abort?.signal, + headers: { + Authorization: `Bearer ${token}`, + }, + }); + + const reader = response.body?.getReader(); + while (true && reader) { + const { done, value } = await reader.read(); + if (done) break; + yield new TextDecoder().decode(value); + } +} + +export { http, newEventSource, streamingFetch, host }; diff --git a/src/stores/admin/club/newsletter/newsletterPrintout.ts b/src/stores/admin/club/newsletter/newsletterPrintout.ts index 0a12ef6..945ac24 100644 --- a/src/stores/admin/club/newsletter/newsletterPrintout.ts +++ b/src/stores/admin/club/newsletter/newsletterPrintout.ts @@ -1,8 +1,9 @@ import { defineStore } from "pinia"; -import { http, newEventSource } from "@/serverCom"; +import { http, newEventSource, streamingFetch } from "@/serverCom"; import { useNewsletterStore } from "./newsletter"; import type { AxiosResponse } from "axios"; import type { EventSourcePolyfill } from "event-source-polyfill"; +import { useNotificationStore, type NotificationType } from "../../../notification"; export const useNewsletterPrintoutStore = defineStore("newsletterPrintout", { state: () => { @@ -12,10 +13,10 @@ export const useNewsletterPrintoutStore = defineStore("newsletterPrintout", { printing: undefined as undefined | "loading" | "success" | "failed", sending: undefined as undefined | "loading" | "success" | "failed", sendingPreview: undefined as undefined | "loading" | "success" | "failed", - pdfProgessSource: undefined as undefined | EventSourcePolyfill, - mailProgessSource: undefined as undefined | EventSourcePolyfill, - pdfSourceMessages: [] as Array, - mailSourceMessages: [] as Array, + pdfSourceMessages: [] as Array<{ kind: string; factor: string; [key: string]: string }>, + mailSourceMessages: [] as Array<{ kind: string; factor: string; [key: string]: string }>, + pdfPrintingAbort: undefined as undefined | AbortController, + mailSendingAbort: undefined as undefined | AbortController, }; }, actions: { @@ -63,6 +64,7 @@ export const useNewsletterPrintoutStore = defineStore("newsletterPrintout", { }); }, createNewsletterPrintout() { + this.subscribePdfPrintingProgress(); this.printing = "loading"; const newsletterId = useNewsletterStore().activeNewsletter; if (newsletterId == null) return; @@ -78,10 +80,12 @@ export const useNewsletterPrintoutStore = defineStore("newsletterPrintout", { .finally(() => { setTimeout(() => { this.printing = undefined; + this.pdfPrintingAbort?.abort(); }, 1500); }); }, createNewsletterSend() { + this.subscribeMailSendingProgress(); this.sending = "loading"; const newsletterId = useNewsletterStore().activeNewsletter; if (newsletterId == null) return; @@ -96,32 +100,55 @@ export const useNewsletterPrintoutStore = defineStore("newsletterPrintout", { .finally(() => { setTimeout(() => { this.sending = undefined; + this.mailSendingAbort?.abort(); }, 1500); }); }, - subscribePdfPrintingProgress() { - // const newsletterId = useNewsletterStore().activeNewsletter; - // if (this.pdfProgessSource != undefined) return; - // this.pdfProgessSource = newEventSource(`/admin/newsletter/${newsletterId}/printoutprogress`); - // this.pdfProgessSource.onmessage = (event) => { - // console.log("pdf", event); - // }; + async subscribePdfPrintingProgress() { + this.pdfSourceMessages = []; + const newsletterId = useNewsletterStore().activeNewsletter; + const notificationStore = useNotificationStore(); + this.pdfPrintingAbort = new AbortController(); + for await (let chunk of streamingFetch( + `/admin/newsletter/${newsletterId}/printoutprogress`, + this.pdfPrintingAbort + )) { + chunk.split("//").forEach((r) => { + if (r.trim() != "") { + let data = JSON.parse(r); + this.pdfSourceMessages.push(data); + let type: NotificationType = "info"; + let timeout = undefined; + if (data.factor == "failed") { + type = "error"; + timeout = 0; + } + notificationStore.push(`Druck: ${data.iteration}/${data.total}`, `${data.msg}`, type, timeout); + } + }); + this.fetchNewsletterPrintout(); + } }, - subscribeMailSendingProgress() { - // const newsletterId = useNewsletterStore().activeNewsletter; - // if (this.mailProgessSource != undefined) return; - // this.mailProgessSource = newEventSource(`/admin/newsletter/${newsletterId}/sendprogress`); - // this.mailProgessSource.onmessage = (event) => { - // console.log("mail", event); - // }; - }, - unsubscribePdfPrintingProgress() { - this.pdfProgessSource?.close(); - this.pdfProgessSource = undefined; - }, - unsubscribeMailSendingProgress() { - this.mailProgessSource?.close(); - this.mailProgessSource = undefined; + async subscribeMailSendingProgress() { + this.mailSourceMessages = []; + const newsletterId = useNewsletterStore().activeNewsletter; + const notificationStore = useNotificationStore(); + this.mailSendingAbort = new AbortController(); + for await (let chunk of streamingFetch(`/admin/newsletter/${newsletterId}/sendprogress`, this.mailSendingAbort)) { + chunk.split("//").forEach((r) => { + if (r.trim() != "") { + let data = JSON.parse(r); + this.mailSourceMessages.push(data); + let type: NotificationType = "info"; + let timeout = undefined; + if (data.factor == "failed") { + type = "error"; + timeout = 0; + } + notificationStore.push(`Mailversand: ${data.iteration}/${data.total}`, `${data.msg}`, type, timeout); + } + }); + } }, }, }); diff --git a/src/stores/admin/club/protocol/protocolDecision.ts b/src/stores/admin/club/protocol/protocolDecision.ts index 8ff0fcb..069cd74 100644 --- a/src/stores/admin/club/protocol/protocolDecision.ts +++ b/src/stores/admin/club/protocol/protocolDecision.ts @@ -38,7 +38,6 @@ export const useProtocolDecisionStore = defineStore("protocolDecision", { this.loading = "fetched"; }) .catch((err) => { - console.log(err); this.loading = "failed"; }); }, diff --git a/src/stores/admin/navigation.ts b/src/stores/admin/navigation.ts index b0af149..a3f6eeb 100644 --- a/src/stores/admin/navigation.ts +++ b/src/stores/admin/navigation.ts @@ -98,30 +98,32 @@ export const useNavigationStore = defineStore("navigation", { settings: { mainTitle: "Einstellungen", main: [ - ...(abilityStore.can("read", "settings", "qualification") - ? [{ key: "qualification", title: "Qualifikationen" }] - : []), + { key: "divider1", title: "Mitgliederdaten" }, ...(abilityStore.can("read", "settings", "award") ? [{ key: "award", title: "Auszeichnungen" }] : []), - ...(abilityStore.can("read", "settings", "executive_position") - ? [{ key: "executive_position", title: "Vereinsämter" }] - : []), ...(abilityStore.can("read", "settings", "communication_type") ? [{ key: "communication_type", title: "Kommunikationsarten" }] : []), ...(abilityStore.can("read", "settings", "membership_status") ? [{ key: "membership_status", title: "Mitgliedsstatus" }] : []), - ...(abilityStore.can("read", "settings", "calendar_type") - ? [{ key: "calendar_type", title: "Terminarten" }] + ...(abilityStore.can("read", "settings", "qualification") + ? [{ key: "qualification", title: "Qualifikationen" }] + : []), + ...(abilityStore.can("read", "settings", "executive_position") + ? [{ key: "executive_position", title: "Vereinsämter" }] + : []), + { key: "divider2", title: "Einstellungen" }, + ...(abilityStore.can("read", "settings", "newsletter_config") + ? [{ key: "newsletter_config", title: "Newsletter Konfiguration" }] : []), - ...(abilityStore.can("read", "settings", "query") ? [{ key: "query_store", title: "Query Store" }] : []), ...(abilityStore.can("read", "settings", "template") ? [{ key: "template", title: "Templates" }] : []), ...(abilityStore.can("read", "settings", "template_usage") ? [{ key: "template_usage", title: "Template-Verwendung" }] : []), - ...(abilityStore.can("read", "settings", "newsletter_config") - ? [{ key: "newsletter_config", title: "Newsletter Konfiguration" }] + ...(abilityStore.can("read", "settings", "calendar_type") + ? [{ key: "calendar_type", title: "Terminarten" }] : []), + ...(abilityStore.can("read", "settings", "query") ? [{ key: "query_store", title: "Query Store" }] : []), ], }, user: { diff --git a/src/stores/notification.ts b/src/stores/notification.ts index 249f2c0..872b108 100644 --- a/src/stores/notification.ts +++ b/src/stores/notification.ts @@ -1,7 +1,7 @@ import { defineStore } from "pinia"; export interface Notification { - id: number; + id: string; title: string; text: string; type: NotificationType; @@ -19,7 +19,7 @@ export const useNotificationStore = defineStore("notification", { }, actions: { push(title: string, text: string, type: NotificationType, timeout: number = 5000) { - let id = Date.now(); + let id = `${Date.now()}_${Math.random()}`; this.notifications.push({ id, title, @@ -27,14 +27,16 @@ export const useNotificationStore = defineStore("notification", { type, indicator: false, }); - setTimeout(() => { - this.notifications[this.notifications.findIndex((n) => n.id === id)].indicator = true; - }, 100); - this.timeouts[id] = setTimeout(() => { - this.revoke(id); - }, timeout); + if (timeout != 0) { + setTimeout(() => { + this.notifications[this.notifications.findIndex((n) => n.id === id)].indicator = true; + }, 100); + this.timeouts[id] = setTimeout(() => { + this.revoke(id); + }, timeout); + } }, - revoke(id: number) { + revoke(id: string) { this.notifications.splice( this.notifications.findIndex((n) => n.id === id), 1 diff --git a/src/views/Login.vue b/src/views/Login.vue index 3e5f764..d33ad0e 100644 --- a/src/views/Login.vue +++ b/src/views/Login.vue @@ -3,7 +3,7 @@
LOGO -

FF Admin

+

{{config.app_name_overwrite || "FF Admin"}}

@@ -48,6 +48,7 @@ import SuccessCheckmark from "@/components/SuccessCheckmark.vue"; import FailureXMark from "@/components/FailureXMark.vue"; import { resetAllPiniaStores } from "@/helpers/piniaReset"; import FormBottomBar from "@/components/FormBottomBar.vue"; +import { config } from "@/config" diff --git a/src/views/admin/settings/template/TemplateEdit.vue b/src/views/admin/settings/template/TemplateEdit.vue index 4317717..a8d7e8a 100644 --- a/src/views/admin/settings/template/TemplateEdit.vue +++ b/src/views/admin/settings/template/TemplateEdit.vue @@ -139,7 +139,6 @@ export default defineComponent({ if (!fromSave) this.loadDesign(); }) .catch((err) => { - console.log(err); this.loading = "failed"; }); }, diff --git a/src/views/docs/View.vue b/src/views/docs/View.vue index a5f6ec1..05ce05c 100644 --- a/src/views/docs/View.vue +++ b/src/views/docs/View.vue @@ -3,7 +3,7 @@