From b0ea9d13e7cc7689a7da1939ed471c6ddb5630b8 Mon Sep 17 00:00:00 2001 From: Julian Krauser Date: Sun, 15 Sep 2024 13:52:54 +0200 Subject: [PATCH] form state rewrite --- package-lock.json | 18 ++- package.json | 2 + src/components/admin/Permission.vue | 29 ++--- .../admin/settings/award/CreateAwardModal.vue | 45 +++---- .../admin/settings/award/DeleteAwardModal.vue | 38 +++--- .../CreateCommunicationTypeModal.vue | 42 ++++--- .../DeleteCommunicationTypeModal.vue | 38 +++--- .../CreateExecutivePositionModal.vue | 45 +++---- .../DeleteExecutivePositionModal.vue | 38 +++--- .../CreateMembershipStatusModal.vue | 45 +++---- .../DeleteMembershipStatusModal.vue | 44 ++++--- .../CreateQualificationModal.vue | 45 +++---- .../DeleteQualificationModal.vue | 38 +++--- .../admin/user/role/CreateRoleModal.vue | 41 +++---- .../admin/user/role/DeleteRoleModal.vue | 42 +++---- .../admin/user/user/DeleteUserModal.vue | 42 +++---- src/stores/admin/award.ts | 91 ++++---------- src/stores/admin/communicationType.ts | 100 +++++----------- src/stores/admin/executivePosition.ts | 94 +++++---------- src/stores/admin/membershipStatus.ts | 100 +++++----------- src/stores/admin/qualification.ts | 96 +++++---------- src/stores/admin/role.ts | 111 +++++------------- src/stores/admin/user.ts | 96 ++++----------- src/viewmodels/admin/award.models.ts | 7 +- .../admin/communicationType.models.ts | 8 +- .../admin/executivePosition.models.ts | 7 +- .../admin/membershipStatus.models.ts | 7 +- src/viewmodels/admin/qualification.models.ts | 8 +- src/viewmodels/admin/user.models.ts | 14 ++- src/views/admin/settings/AwardEdit.vue | 86 ++++++++++---- .../admin/settings/CommunicationTypeEdit.vue | 106 +++++++++++------ .../admin/settings/ExecutivePositionEdit.vue | 99 +++++++++++----- src/views/admin/settings/MembershipStatus.vue | 12 +- .../admin/settings/MembershipStatusEdit.vue | 97 ++++++++++----- .../admin/settings/QualificationEdit.vue | 88 ++++++++++---- src/views/admin/user/RoleEdit.vue | 82 +++++++++---- src/views/admin/user/RoleEditPermission.vue | 61 +++++++--- src/views/admin/user/UserEdit.vue | 92 +++++++++++---- src/views/admin/user/UserEditPermission.vue | 61 +++++++--- src/views/admin/user/UserEditRoles.vue | 78 ++++++++---- 40 files changed, 1123 insertions(+), 1070 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6ff430b..5565e10 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,9 +11,11 @@ "dependencies": { "@headlessui/vue": "^1.7.13", "@heroicons/vue": "^2.1.5", + "@types/lodash.isequal": "^4.5.8", "axios": "^0.26.1", "jwt-decode": "^4.0.0", "lodash.clonedeep": "^4.5.0", + "lodash.isequal": "^4.5.0", "nprogress": "^0.2.0", "pdf-dist": "^1.0.0", "pinia": "^2.1.7", @@ -3068,7 +3070,6 @@ "version": "4.17.7", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz", "integrity": "sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==", - "dev": true, "license": "MIT" }, "node_modules/@types/lodash.clonedeep": { @@ -3081,6 +3082,15 @@ "@types/lodash": "*" } }, + "node_modules/@types/lodash.isequal": { + "version": "4.5.8", + "resolved": "https://registry.npmjs.org/@types/lodash.isequal/-/lodash.isequal-4.5.8.tgz", + "integrity": "sha512-uput6pg4E/tj2LGxCZo9+y27JNyB2OZuuI/T5F+ylVDYuqICLG2/ktjxx0v6GvVntAf8TvEzeQLcV0ffRirXuA==", + "license": "MIT", + "dependencies": { + "@types/lodash": "*" + } + }, "node_modules/@types/node": { "version": "20.14.15", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.15.tgz", @@ -6624,6 +6634,12 @@ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", "dev": true }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", diff --git a/package.json b/package.json index 1b2c737..6a65d22 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "axios": "^0.26.1", "jwt-decode": "^4.0.0", "lodash.clonedeep": "^4.5.0", + "lodash.isequal": "^4.5.0", "nprogress": "^0.2.0", "pdf-dist": "^1.0.0", "pinia": "^2.1.7", @@ -44,6 +45,7 @@ "@tsconfig/node20": "^20.1.4", "@types/eslint": "~9.6.0", "@types/lodash.clonedeep": "^4.5.9", + "@types/lodash.isequal": "^4.5.8", "@types/node": "^20.14.5", "@types/nprogress": "^0.2.0", "@types/qrcode": "^1.5.5", diff --git a/src/components/admin/Permission.vue b/src/components/admin/Permission.vue index 3fa54e1..359ac18 100644 --- a/src/components/admin/Permission.vue +++ b/src/components/admin/Permission.vue @@ -66,8 +66,10 @@
- - + + @@ -89,7 +91,8 @@ import { sectionsAndModules, permissionSections, permissionTypes } from "@/types import { mapState, mapActions } from "pinia"; import { EyeIcon, PencilIcon, PlusIcon, TrashIcon } from "@heroicons/vue/24/outline"; import { useAbilityStore } from "@/stores/ability"; -import _cloneDeep from "lodash.clonedeep"; +import cloneDeep from "lodash.clonedeep"; +import isEqual from "lodash.isEqual"; import Spinner from "@/components/Spinner.vue"; import SuccessCheckmark from "@/components/SuccessCheckmark.vue"; import FailureXMark from "@/components/FailureXMark.vue"; @@ -111,39 +114,35 @@ export default defineComponent({ default: null, }, }, - emits: ["savePermissions", "resetStatus"], + emits: ["savePermissions"], data() { return { isAdmin: false, sections: [] as Array, permissionStructure: {} as SectionsAndModulesObject, permissionUpdate: {} as PermissionObject, - detect_change: false as boolean, }; }, computed: { ...mapState(useAbilityStore, ["_can"]), + canSaveOrReset(): boolean { + return isEqual(this.permissions, this.permissionUpdate); + }, }, mounted() { this.sections = permissionSections; this.permissionStructure = sectionsAndModules; - this.permissionUpdate = _cloneDeep(this.permissions); + this.permissionUpdate = cloneDeep(this.permissions); this.isAdmin = this.permissions.admin ?? false; }, methods: { toggleAdmin(e: Event) { - this.detect_change = true; - this.$emit("resetStatus"); - const target = e.target as HTMLInputElement; this.isAdmin = target.checked ?? false; this.permissionUpdate.admin = this.isAdmin; }, togglePermission(type: PermissionType, section: PermissionSection, modul?: PermissionModule) { - this.detect_change = true; - this.$emit("resetStatus"); - let permissions = [] as Array | "*"; if (!modul) { permissions = this.permissionUpdate[section]?.all ?? []; @@ -177,15 +176,11 @@ export default defineComponent({ } }, reset() { - this.detect_change = false; - - this.permissionUpdate = _cloneDeep(this.permissions); + this.permissionUpdate = cloneDeep(this.permissions); this.isAdmin = this.permissions.admin ?? false; }, submit() { this.$emit("savePermissions", this.permissionUpdate); - - this.detect_change = false; }, }, }); diff --git a/src/components/admin/settings/award/CreateAwardModal.vue b/src/components/admin/settings/award/CreateAwardModal.vue index 54fc5a8..5da402a 100644 --- a/src/components/admin/settings/award/CreateAwardModal.vue +++ b/src/components/admin/settings/award/CreateAwardModal.vue @@ -10,18 +10,16 @@
- - - - + + + +
- +
@@ -35,45 +33,40 @@ import Spinner from "@/components/Spinner.vue"; import SuccessCheckmark from "@/components/SuccessCheckmark.vue"; import FailureXMark from "@/components/FailureXMark.vue"; import { useAwardStore } from "@/stores/admin/award"; -import type { CreateOrUpdateAwardViewModel } from "@/viewmodels/admin/award.models"; +import type { CreateAwardViewModel } from "@/viewmodels/admin/award.models"; @@ -90,21 +88,12 @@ import { CheckIcon, ChevronUpDownIcon } from "@heroicons/vue/20/solid"; export default defineComponent({ data() { return { + status: null as null | "loading" | { status: "success" | "failed"; reason?: string }, timeout: undefined as any, selectedFields: [] as Array, }; }, - watch: { - createStatus() { - if (this.createStatus != "loading" && this.createStatus?.status == "success") { - this.timeout = setTimeout(() => { - this.closeModal(); - }, 1500); - } - }, - }, mounted() { - this.resetStatus(); this.fetchAvailableFields(); }, beforeUnmount() { @@ -113,18 +102,27 @@ export default defineComponent({ } catch (error) {} }, computed: { - ...mapState(useCommunicationTypeStore, ["createStatus", "availableFields"]), + ...mapState(useCommunicationTypeStore, ["availableFields"]), }, methods: { ...mapActions(useModalStore, ["closeModal"]), - ...mapActions(useCommunicationTypeStore, ["createCommunicationType", "fetchAvailableFields", "resetStatus"]), + ...mapActions(useCommunicationTypeStore, ["createCommunicationType", "fetchAvailableFields"]), triggerCreate(e: any) { let formData = e.target.elements; - let createCommunicationType: CreateOrUpdateCommunicationTypeViewModel = { + let createCommunicationType: CreateCommunicationTypeViewModel = { type: formData.communicationType.value, fields: this.selectedFields, }; - this.createCommunicationType(createCommunicationType); + this.createCommunicationType(createCommunicationType) + .then(() => { + this.status = { status: "success" }; + this.timeout = setTimeout(() => { + this.closeModal(); + }, 1500); + }) + .catch(() => { + this.status = { status: "failed" }; + }); }, }, }); diff --git a/src/components/admin/settings/communicationType/DeleteCommunicationTypeModal.vue b/src/components/admin/settings/communicationType/DeleteCommunicationTypeModal.vue index 27049a6..d371e5e 100644 --- a/src/components/admin/settings/communicationType/DeleteCommunicationTypeModal.vue +++ b/src/components/admin/settings/communicationType/DeleteCommunicationTypeModal.vue @@ -6,17 +6,17 @@
- - - - + + +
- +
@@ -36,21 +36,10 @@ import { useCommunicationTypeStore } from "@/stores/admin/communicationType"; export default defineComponent({ data() { return { + status: null as null | "loading" | { status: "success" | "failed"; reason?: string }, timeout: undefined as any, }; }, - watch: { - deleteStatus() { - if (this.deleteStatus != "loading" && this.deleteStatus?.status == "success") { - this.timeout = setTimeout(() => { - this.closeModal(); - }, 1500); - } - }, - }, - mounted() { - this.resetStatus(); - }, beforeUnmount() { try { clearTimeout(this.timeout); @@ -58,16 +47,25 @@ export default defineComponent({ }, computed: { ...mapState(useModalStore, ["data"]), - ...mapState(useCommunicationTypeStore, ["communicationTypes", "deleteStatus"]), + ...mapState(useCommunicationTypeStore, ["communicationTypes"]), communicationType() { return this.communicationTypes.find((r) => r.id == this.data); }, }, methods: { ...mapActions(useModalStore, ["closeModal"]), - ...mapActions(useCommunicationTypeStore, ["deleteCommunicationType", "resetStatus"]), + ...mapActions(useCommunicationTypeStore, ["deleteCommunicationType"]), triggerDelete() { - this.deleteCommunicationType(this.data); + this.deleteCommunicationType(this.data) + .then(() => { + this.status = { status: "success" }; + this.timeout = setTimeout(() => { + this.closeModal(); + }, 1500); + }) + .catch(() => { + this.status = { status: "failed" }; + }); }, }, }); diff --git a/src/components/admin/settings/executivePosition/CreateExecutivePositionModal.vue b/src/components/admin/settings/executivePosition/CreateExecutivePositionModal.vue index 12b1e50..9c4bf5c 100644 --- a/src/components/admin/settings/executivePosition/CreateExecutivePositionModal.vue +++ b/src/components/admin/settings/executivePosition/CreateExecutivePositionModal.vue @@ -10,18 +10,16 @@
- - - - + + + +
- +
@@ -35,45 +33,40 @@ import Spinner from "@/components/Spinner.vue"; import SuccessCheckmark from "@/components/SuccessCheckmark.vue"; import FailureXMark from "@/components/FailureXMark.vue"; import { useExecutivePositionStore } from "@/stores/admin/executivePosition"; -import type { CreateOrUpdateExecutivePositionViewModel } from "@/viewmodels/admin/executivePosition.models"; +import type { CreateExecutivePositionViewModel } from "@/viewmodels/admin/executivePosition.models";