From da1865ba33528b34825e2fb121dbe7d9460bd71b Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Mon, 27 Jan 2025 15:24:26 +0100 Subject: [PATCH 1/9] change: member overview rename newsletter --- src/views/admin/club/members/MemberOverview.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/admin/club/members/MemberOverview.vue b/src/views/admin/club/members/MemberOverview.vue index db2726c..c92deab 100644 --- a/src/views/admin/club/members/MemberOverview.vue +++ b/src/views/admin/club/members/MemberOverview.vue @@ -111,7 +111,7 @@
-

Newsletter Kommunikationswege

+

sende Newsletter an:

From 4c5d132de809926b4d629bdfd0c12651d8af072b Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Wed, 29 Jan 2025 08:53:42 +0100 Subject: [PATCH 2/9] change user to uuid --- src/components/Pagination.vue | 21 +++--- src/components/admin/MemberSearchSelect.vue | 6 +- src/components/admin/Permission.vue | 4 +- src/stores/admin/club/member/member.ts | 8 +-- .../club/newsletter/newsletterRecipients.ts | 4 +- .../admin/club/protocol/protocolPresence.ts | 4 +- src/stores/admin/user/user.ts | 66 ++++++++----------- .../admin/club/member/member.models.ts | 6 +- .../newsletter/newsletterRecipients.models.ts | 4 +- .../club/protocol/protocolPresence.models.ts | 4 +- src/viewmodels/admin/user/user.models.ts | 4 +- .../club/newsletter/NewsletterRecipients.vue | 2 +- .../admin/club/protocol/ProtocolPresence.vue | 6 +- src/views/admin/user/user/UserEdit.vue | 2 +- .../admin/user/user/UserEditPermission.vue | 2 +- src/views/admin/user/user/UserEditRoles.vue | 2 +- src/views/docs/DocPage.vue | 34 +++++----- 17 files changed, 86 insertions(+), 93 deletions(-) diff --git a/src/components/Pagination.vue b/src/components/Pagination.vue index 28084c6..83210a7 100644 --- a/src/components/Pagination.vue +++ b/src/components/Pagination.vue @@ -1,7 +1,7 @@ \ No newline at end of file + From 5a8d858918d9e49c3d7664e543fde4e7c78462c3 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Wed, 29 Jan 2025 10:06:09 +0100 Subject: [PATCH 3/9] fix: member update salutation read --- src/views/admin/club/members/MemberEdit.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/admin/club/members/MemberEdit.vue b/src/views/admin/club/members/MemberEdit.vue index 6053966..9e71a03 100644 --- a/src/views/admin/club/members/MemberEdit.vue +++ b/src/views/admin/club/members/MemberEdit.vue @@ -157,7 +157,7 @@ export default defineComponent({ let formData = e.target.elements; let updateMember: UpdateMemberViewModel = { id: this.member.id, - salutationId: formData.salutation.value, + salutationId: formData["salutation[id]"].value, firstname: formData.firstname.value, lastname: formData.lastname.value, nameaffix: formData.nameaffix.value, From e5cb8fecc60bd08d5b1652986b97033697c829ca Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Sun, 2 Feb 2025 11:10:11 +0100 Subject: [PATCH 4/9] change permission --- src/components/admin/user/user/UserListItem.vue | 2 +- src/viewmodels/admin/club/member/membership.models.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/admin/user/user/UserListItem.vue b/src/components/admin/user/user/UserListItem.vue index 241a60e..f705262 100644 --- a/src/components/admin/user/user/UserListItem.vue +++ b/src/components/admin/user/user/UserListItem.vue @@ -7,7 +7,7 @@

diff --git a/src/viewmodels/admin/club/member/membership.models.ts b/src/viewmodels/admin/club/member/membership.models.ts index 6051ec9..0bbdb92 100644 --- a/src/viewmodels/admin/club/member/membership.models.ts +++ b/src/viewmodels/admin/club/member/membership.models.ts @@ -12,7 +12,7 @@ export interface MembershipStatisticsViewModel { durationInYears: string; status: string; statusId: number; - memberId: number; + memberId: string; memberSalutation: string; memberFirstname: string; memberLastname: string; From f8fb222ebbdf6bcb3ac041762f3c6acef421bb04 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Sun, 2 Feb 2025 16:37:46 +0100 Subject: [PATCH 5/9] backup read, upload and restore --- package-lock.json | 81 +++++++++++++- package.json | 2 +- .../admin/user/backup/BackupListItem.vue | 58 ++++++++++ .../admin/user/backup/CreateBackupModal.vue | 67 ++++++++++++ .../admin/user/backup/RestoreBackupModal.vue | 101 ++++++++++++++++++ .../admin/user/backup/UploadBackupModal.vue | 93 ++++++++++++++++ src/router/index.ts | 7 ++ src/stores/admin/navigation.ts | 1 + src/stores/admin/user/backup.ts | 56 ++++++++++ src/types/backupTypes.ts | 24 +++++ src/types/permissionTypes.ts | 6 +- src/viewmodels/admin/user/backup.models.ts | 7 ++ src/views/admin/user/backup/Backup.vue | 60 +++++++++++ 13 files changed, 555 insertions(+), 8 deletions(-) create mode 100644 src/components/admin/user/backup/BackupListItem.vue create mode 100644 src/components/admin/user/backup/CreateBackupModal.vue create mode 100644 src/components/admin/user/backup/RestoreBackupModal.vue create mode 100644 src/components/admin/user/backup/UploadBackupModal.vue create mode 100644 src/stores/admin/user/backup.ts create mode 100644 src/types/backupTypes.ts create mode 100644 src/viewmodels/admin/user/backup.models.ts create mode 100644 src/views/admin/user/backup/Backup.vue diff --git a/package-lock.json b/package-lock.json index 10f4839..9748c4c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,7 @@ "@headlessui/vue": "^1.7.13", "@heroicons/vue": "^2.1.5", "@vueup/vue-quill": "^1.2.0", - "axios": "^0.26.1", + "axios": "^1.7.9", "event-source-polyfill": "^1.0.31", "grapesjs": "^0.22.4", "grapesjs-preset-newsletter": "^1.0.2", @@ -3951,6 +3951,12 @@ "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", "dev": true }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, "node_modules/at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", @@ -4013,11 +4019,14 @@ } }, "node_modules/axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", + "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", + "license": "MIT", "dependencies": { - "follow-redirects": "^1.14.8" + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, "node_modules/b4a": { @@ -4515,6 +4524,18 @@ "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", "dev": true }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -4875,6 +4896,15 @@ "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", "dev": true }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/detect-libc": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", @@ -5714,6 +5744,20 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -7172,6 +7216,27 @@ "node": ">=8.6" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/mimic-response": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", @@ -8115,6 +8180,12 @@ "integrity": "sha512-H5oELycFml5yto/atYqmjyigJoAo3+OXwolYiH7OfQuYlAqhxNvTfiNMbV9hsC6Yp83yE5r2KTVmtrG6R9i6Pg==", "license": "MIT" }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", diff --git a/package.json b/package.json index 922267f..c76f49a 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "@headlessui/vue": "^1.7.13", "@heroicons/vue": "^2.1.5", "@vueup/vue-quill": "^1.2.0", - "axios": "^0.26.1", + "axios": "^1.7.9", "event-source-polyfill": "^1.0.31", "grapesjs": "^0.22.4", "grapesjs-preset-newsletter": "^1.0.2", diff --git a/src/components/admin/user/backup/BackupListItem.vue b/src/components/admin/user/backup/BackupListItem.vue new file mode 100644 index 0000000..18e2b06 --- /dev/null +++ b/src/components/admin/user/backup/BackupListItem.vue @@ -0,0 +1,58 @@ + + + + + diff --git a/src/components/admin/user/backup/CreateBackupModal.vue b/src/components/admin/user/backup/CreateBackupModal.vue new file mode 100644 index 0000000..0c205ef --- /dev/null +++ b/src/components/admin/user/backup/CreateBackupModal.vue @@ -0,0 +1,67 @@ + + + + + diff --git a/src/components/admin/user/backup/RestoreBackupModal.vue b/src/components/admin/user/backup/RestoreBackupModal.vue new file mode 100644 index 0000000..e50a398 --- /dev/null +++ b/src/components/admin/user/backup/RestoreBackupModal.vue @@ -0,0 +1,101 @@ + + + + + diff --git a/src/components/admin/user/backup/UploadBackupModal.vue b/src/components/admin/user/backup/UploadBackupModal.vue new file mode 100644 index 0000000..d65db5f --- /dev/null +++ b/src/components/admin/user/backup/UploadBackupModal.vue @@ -0,0 +1,93 @@ + + + + + diff --git a/src/router/index.ts b/src/router/index.ts index 4d46b2b..8011d2a 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -634,6 +634,13 @@ const router = createRouter({ }, ], }, + { + path: "backup", + name: "admin-user-backup", + component: () => import("@/views/admin/user/backup/Backup.vue"), + meta: { type: "read", section: "user", module: "backup" }, + beforeEnter: [abilityAndNavUpdate], + }, ], }, { diff --git a/src/stores/admin/navigation.ts b/src/stores/admin/navigation.ts index 003f868..07a7532 100644 --- a/src/stores/admin/navigation.ts +++ b/src/stores/admin/navigation.ts @@ -133,6 +133,7 @@ export const useNavigationStore = defineStore("navigation", { ...(abilityStore.can("read", "user", "user") ? [{ key: "user", title: "Benutzer" }] : []), ...(abilityStore.can("read", "user", "role") ? [{ key: "role", title: "Rollen" }] : []), ...(abilityStore.can("read", "user", "webapi") ? [{ key: "webapi", title: "Webapi-Token" }] : []), + ...(abilityStore.can("read", "user", "backup") ? [{ key: "backup", title: "Backups" }] : []), ], }, } as navigationModel; diff --git a/src/stores/admin/user/backup.ts b/src/stores/admin/user/backup.ts new file mode 100644 index 0000000..1f29cf8 --- /dev/null +++ b/src/stores/admin/user/backup.ts @@ -0,0 +1,56 @@ +import { defineStore } from "pinia"; +import { http } from "@/serverCom"; +import type { AxiosResponse, AxiosProgressEvent } from "axios"; +import type { BackupRestoreViewModel } from "../../../viewmodels/admin/user/backup.models"; + +export const useBackupStore = defineStore("backup", { + state: () => { + return { + backups: [] as Array, + loading: null as null | "loading" | "success" | "failed", + }; + }, + actions: { + fetchBackups() { + this.loading = "loading"; + http + .get("/admin/backup") + .then((result) => { + this.backups = result.data; + this.loading = "success"; + }) + .catch((err) => { + this.loading = "failed"; + }); + }, + fetchBackupById(filename: string): Promise> { + return http.get(`/admin/backup/${filename}`); + }, + async triggerBackupCreate(): Promise> { + const result = await http.post("/admin/backup"); + this.fetchBackups(); + return result; + }, + async restoreBackup(backup: BackupRestoreViewModel): Promise> { + return await http.post("/admin/backup/restore", backup); + }, + async uploadBackup(file: File): Promise> { + const formData = new FormData(); + formData.append("file", file); + + const options = { + headers: { + "Content-Type": "multipart/form-data", + }, + onUploadProgress: (progressEvent: AxiosProgressEvent) => { + const { loaded, total = 1 } = progressEvent; + console.log("progress", Math.floor((loaded * 100) / total)); + }, + }; + + const result = await http.post("/admin/backup/upload", formData, options); + this.fetchBackups(); + return result; + }, + }, +}); diff --git a/src/types/backupTypes.ts b/src/types/backupTypes.ts new file mode 100644 index 0000000..744ddc4 --- /dev/null +++ b/src/types/backupTypes.ts @@ -0,0 +1,24 @@ +export type BackupSection = + | "member" + | "memberBase" + | "protocol" + | "newsletter" + | "newsletter_config" + | "calendar" + | "query" + | "template" + | "user" + | "webapi"; + +export const backupSections: Array = [ + "member", + "memberBase", + "protocol", + "newsletter", + "newsletter_config", + "calendar", + "query", + "template", + "user", + "webapi", +]; diff --git a/src/types/permissionTypes.ts b/src/types/permissionTypes.ts index cd37e49..e3d3105 100644 --- a/src/types/permissionTypes.ts +++ b/src/types/permissionTypes.ts @@ -19,7 +19,8 @@ export type PermissionModule = | "query" | "query_store" | "template" - | "template_usage"; + | "template_usage" + | "backup"; export type PermissionType = "read" | "create" | "update" | "delete"; @@ -63,6 +64,7 @@ export const permissionModules: Array = [ "query_store", "template", "template_usage", + "backup", ]; export const permissionTypes: Array = ["read", "create", "update", "delete"]; export const sectionsAndModules: SectionsAndModulesObject = { @@ -80,5 +82,5 @@ export const sectionsAndModules: SectionsAndModulesObject = { "template_usage", "newsletter_config", ], - user: ["user", "role", "webapi"], + user: ["user", "role", "webapi", "backup"], }; diff --git a/src/viewmodels/admin/user/backup.models.ts b/src/viewmodels/admin/user/backup.models.ts new file mode 100644 index 0000000..1d552dc --- /dev/null +++ b/src/viewmodels/admin/user/backup.models.ts @@ -0,0 +1,7 @@ +import type { BackupSection } from "../../../types/backupTypes"; + +export interface BackupRestoreViewModel { + filename: string; + partial: boolean; + include: Array; +} diff --git a/src/views/admin/user/backup/Backup.vue b/src/views/admin/user/backup/Backup.vue new file mode 100644 index 0000000..b238994 --- /dev/null +++ b/src/views/admin/user/backup/Backup.vue @@ -0,0 +1,60 @@ + + + + + From 5cb68d92ce3f66a6bc3caaccba020e1e24d84c9f Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Mon, 3 Feb 2025 11:03:38 +0100 Subject: [PATCH 6/9] split uploaded and generated backups --- .../admin/user/backup/RestoreBackupModal.vue | 6 +++ .../admin/user/backup/UploadBackupModal.vue | 7 ++- src/router/backupGuard.ts | 19 ++++++++ src/router/index.ts | 24 +++++++++- src/stores/admin/user/backup.ts | 11 +++-- .../admin/club/member/membership.models.ts | 3 +- src/viewmodels/admin/user/backup.models.ts | 1 + .../admin/club/members/MemberOverview.vue | 2 +- .../backup/{Backup.vue => BackupRouting.vue} | 40 +++++++++++----- .../admin/user/backup/GeneratedBackup.vue | 48 +++++++++++++++++++ .../admin/user/backup/UploadedBackup.vue | 48 +++++++++++++++++++ 11 files changed, 188 insertions(+), 21 deletions(-) create mode 100644 src/router/backupGuard.ts rename src/views/admin/user/backup/{Backup.vue => BackupRouting.vue} (57%) create mode 100644 src/views/admin/user/backup/GeneratedBackup.vue create mode 100644 src/views/admin/user/backup/UploadedBackup.vue diff --git a/src/components/admin/user/backup/RestoreBackupModal.vue b/src/components/admin/user/backup/RestoreBackupModal.vue index e50a398..c80e026 100644 --- a/src/components/admin/user/backup/RestoreBackupModal.vue +++ b/src/components/admin/user/backup/RestoreBackupModal.vue @@ -15,12 +15,17 @@
+
+ + +

Je nach Auswahl, werden die entsprechenden Bestandsdaten ersetzt. Dadurch können Daten, die seit diesem Backup erstellt wurden, verloren gehen.

+

Das Laden eines vollständigen Backups wird zur Vermeidung von Inkonsistenzen empfohlen.

diff --git a/src/router/backupGuard.ts b/src/router/backupGuard.ts new file mode 100644 index 0000000..a9e6302 --- /dev/null +++ b/src/router/backupGuard.ts @@ -0,0 +1,19 @@ +import { useBackupStore } from "../stores/admin/user/backup"; + +export async function setBackupPage(to: any, from: any, next: any) { + const backup = useBackupStore(); + + let uploadPage = to.name.includes("uploaded"); + + if (uploadPage) { + backup.page = "uploaded"; + backup.backups = []; + } else { + backup.page = "generated"; + backup.backups = []; + } + + backup.fetchBackups(); + + next(); +} diff --git a/src/router/index.ts b/src/router/index.ts index 8011d2a..2d39254 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -10,6 +10,7 @@ import { resetMemberStores, setMemberId } from "./memberGuard"; import { resetProtocolStores, setProtocolId } from "./protocolGuard"; import { resetNewsletterStores, setNewsletterId } from "./newsletterGuard"; import { config } from "../config"; +import { setBackupPage } from "./backupGuard"; const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), @@ -636,10 +637,29 @@ const router = createRouter({ }, { path: "backup", - name: "admin-user-backup", - component: () => import("@/views/admin/user/backup/Backup.vue"), + name: "admin-user-backup-route", + component: () => import("@/views/admin/user/backup/BackupRouting.vue"), meta: { type: "read", section: "user", module: "backup" }, beforeEnter: [abilityAndNavUpdate], + children: [ + { + path: "", + name: "admin-user-backup", + redirect: { name: "admin-user-backup-generated" }, + }, + { + path: "generated", + name: "admin-user-backup-generated", + component: () => import("@/views/admin/user/backup/GeneratedBackup.vue"), + beforeEnter: [setBackupPage], + }, + { + path: "uploads", + name: "admin-user-backup-uploaded", + component: () => import("@/views/admin/user/backup/UploadedBackup.vue"), + beforeEnter: [setBackupPage], + }, + ], }, ], }, diff --git a/src/stores/admin/user/backup.ts b/src/stores/admin/user/backup.ts index 1f29cf8..1f87652 100644 --- a/src/stores/admin/user/backup.ts +++ b/src/stores/admin/user/backup.ts @@ -8,13 +8,14 @@ export const useBackupStore = defineStore("backup", { return { backups: [] as Array, loading: null as null | "loading" | "success" | "failed", + page: "generated" as "generated" | "uploaded", }; }, actions: { fetchBackups() { this.loading = "loading"; http - .get("/admin/backup") + .get(`/admin/backup/${this.page}`) .then((result) => { this.backups = result.data; this.loading = "success"; @@ -24,16 +25,16 @@ export const useBackupStore = defineStore("backup", { }); }, fetchBackupById(filename: string): Promise> { - return http.get(`/admin/backup/${filename}`); + return http.get(`/admin/backup/${this.page}/${filename}`); + }, + async restoreBackup(backup: BackupRestoreViewModel): Promise> { + return await http.post(`/admin/backup/${this.page}/restore`, backup); }, async triggerBackupCreate(): Promise> { const result = await http.post("/admin/backup"); this.fetchBackups(); return result; }, - async restoreBackup(backup: BackupRestoreViewModel): Promise> { - return await http.post("/admin/backup/restore", backup); - }, async uploadBackup(file: File): Promise> { const formData = new FormData(); formData.append("file", file); diff --git a/src/viewmodels/admin/club/member/membership.models.ts b/src/viewmodels/admin/club/member/membership.models.ts index 0bbdb92..ccf8105 100644 --- a/src/viewmodels/admin/club/member/membership.models.ts +++ b/src/viewmodels/admin/club/member/membership.models.ts @@ -9,7 +9,8 @@ export interface MembershipViewModel { export interface MembershipStatisticsViewModel { durationInDays: number; - durationInYears: string; + durationInYears: number; + exactDuration: string; status: string; statusId: number; memberId: string; diff --git a/src/viewmodels/admin/user/backup.models.ts b/src/viewmodels/admin/user/backup.models.ts index 1d552dc..522c0ff 100644 --- a/src/viewmodels/admin/user/backup.models.ts +++ b/src/viewmodels/admin/user/backup.models.ts @@ -4,4 +4,5 @@ export interface BackupRestoreViewModel { filename: string; partial: boolean; include: Array; + overwrite: boolean; } diff --git a/src/views/admin/club/members/MemberOverview.vue b/src/views/admin/club/members/MemberOverview.vue index db2726c..5bb4ad1 100644 --- a/src/views/admin/club/members/MemberOverview.vue +++ b/src/views/admin/club/members/MemberOverview.vue @@ -34,7 +34,7 @@ >

{{ stat.status }} für gesamt {{ stat.durationInDays }} Tage - ~> {{ stat.durationInYears.replace("_", "") }} Jahre + ~> {{ stat.exactDuration }}

diff --git a/src/views/admin/user/backup/Backup.vue b/src/views/admin/user/backup/BackupRouting.vue similarity index 57% rename from src/views/admin/user/backup/Backup.vue rename to src/views/admin/user/backup/BackupRouting.vue index b238994..477398e 100644 --- a/src/views/admin/user/backup/Backup.vue +++ b/src/views/admin/user/backup/BackupRouting.vue @@ -6,17 +6,27 @@
@@ -35,6 +45,14 @@ import { useAbilityStore } from "@/stores/ability"; + + diff --git a/src/views/admin/user/backup/UploadedBackup.vue b/src/views/admin/user/backup/UploadedBackup.vue new file mode 100644 index 0000000..b5f975c --- /dev/null +++ b/src/views/admin/user/backup/UploadedBackup.vue @@ -0,0 +1,48 @@ + + + + + From 9446fd87ebee79e6093ea9a8633c94d68173523c Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Mon, 3 Feb 2025 11:30:12 +0100 Subject: [PATCH 7/9] get members by ids update --- src/components/admin/user/backup/UploadBackupModal.vue | 2 +- src/stores/admin/club/member/member.ts | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/components/admin/user/backup/UploadBackupModal.vue b/src/components/admin/user/backup/UploadBackupModal.vue index c14fdbb..8b194b1 100644 --- a/src/components/admin/user/backup/UploadBackupModal.vue +++ b/src/components/admin/user/backup/UploadBackupModal.vue @@ -21,7 +21,7 @@ @change=" (e) => { uploadFile((e.target as HTMLInputElement)?.files?.[0]); - e.target.value = null; + (e.target as HTMLInputElement).value = ''; } " multiple diff --git a/src/stores/admin/club/member/member.ts b/src/stores/admin/club/member/member.ts index 29fc075..3f48547 100644 --- a/src/stores/admin/club/member/member.ts +++ b/src/stores/admin/club/member/member.ts @@ -51,9 +51,13 @@ export const useMemberStore = defineStore("member", { }); }, async getMembersByIds(ids: Array): Promise> { - return await http.get(`/admin/member?ids=${ids.join(",")}&noLimit=true`).then((res) => { - return { ...res, data: res.data.members }; - }); + return await http + .post(`/admin/member/ids`, { + ids, + }) + .then((res) => { + return { ...res, data: res.data.members }; + }); }, async searchMembers(search: string): Promise> { return await http.get(`/admin/member?search=${search}&noLimit=true`).then((res) => { From a24f8b7153aafa366cdb1dfed17a855d96a78910 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Mon, 3 Feb 2025 11:37:51 +0100 Subject: [PATCH 8/9] deactivate partial restore --- .../admin/user/backup/RestoreBackupModal.vue | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/components/admin/user/backup/RestoreBackupModal.vue b/src/components/admin/user/backup/RestoreBackupModal.vue index c80e026..9f373da 100644 --- a/src/components/admin/user/backup/RestoreBackupModal.vue +++ b/src/components/admin/user/backup/RestoreBackupModal.vue @@ -5,7 +5,7 @@

-
+ + +

Backups ersetzen den aktuellen Stand vollständig.


-

+