From c939065562cdf9d01beb14ca012179fdeedfd624 Mon Sep 17 00:00:00 2001 From: Anthony Janin Date: Tue, 1 Jul 2025 16:16:55 +0200 Subject: [PATCH 1/5] Fix somes issues --- .../Api/LeCoffreApi/sdk/CustomerService.ts | 1 - .../Api/LeCoffreApi/sdk/DeedTypeService.ts | 1 - .../Api/LeCoffreApi/sdk/DocumentService.ts | 1 - .../LeCoffreApi/sdk/DocumentTypeService.ts | 1 - src/common/Api/LeCoffreApi/sdk/FileService.ts | 1 - .../Api/LeCoffreApi/sdk/FolderService.ts | 1 - .../LeCoffreApi/sdk/Loader/LoaderService.ts | 45 ++++++++ .../sdk/Loader/classes.module.scss | 38 ++++++ .../Api/LeCoffreApi/sdk/Loader/index.tsx | 37 ++++++ src/common/Api/LeCoffreApi/sdk/NoteService.ts | 1 - src/common/Api/LeCoffreApi/sdk/RoleService.ts | 109 ++++++++++++++++++ .../DesignSystem/Header/Navigation/index.tsx | 2 + .../DefaultRoleDashboard/index.tsx | 18 ++- .../DeedTypes/DeedTypesCreate/index.tsx | 8 ++ .../Layouts/DeedTypes/DeedTypesEdit/index.tsx | 41 ++++--- .../DeedTypes/DeedTypesInformations/index.tsx | 5 + .../DocumentTypesCreate/index.tsx | 8 ++ .../DocumentTypes/DocumentTypesEdit/index.tsx | 40 ++++--- .../Folder/AddClientToFolder/index.tsx | 14 +++ .../Layouts/Folder/CreateFolder/index.tsx | 8 ++ .../ClientView/ClientBox/index.tsx | 2 + .../FolderInformation/ClientView/index.tsx | 4 +- .../NoClientView/DeleteFolderModal/index.tsx | 7 +- .../Folder/FolderInformation/index.tsx | 3 + .../Layouts/Folder/UpdateClient/index.tsx | 10 +- .../Folder/UpdateFolderMetadata/index.tsx | 34 +++--- .../Layouts/Roles/RolesCreate/index.tsx | 35 +++++- .../Layouts/Roles/RolesInformations/index.tsx | 41 ++++++- src/pages/_app.tsx | 3 + 29 files changed, 448 insertions(+), 71 deletions(-) create mode 100644 src/common/Api/LeCoffreApi/sdk/Loader/LoaderService.ts create mode 100644 src/common/Api/LeCoffreApi/sdk/Loader/classes.module.scss create mode 100644 src/common/Api/LeCoffreApi/sdk/Loader/index.tsx create mode 100644 src/common/Api/LeCoffreApi/sdk/RoleService.ts diff --git a/src/common/Api/LeCoffreApi/sdk/CustomerService.ts b/src/common/Api/LeCoffreApi/sdk/CustomerService.ts index 37d9051e..5bf3a3b7 100644 --- a/src/common/Api/LeCoffreApi/sdk/CustomerService.ts +++ b/src/common/Api/LeCoffreApi/sdk/CustomerService.ts @@ -1,4 +1,3 @@ - import { v4 as uuidv4 } from 'uuid'; import MessageBus from 'src/sdk/MessageBus'; diff --git a/src/common/Api/LeCoffreApi/sdk/DeedTypeService.ts b/src/common/Api/LeCoffreApi/sdk/DeedTypeService.ts index 2e9a32ab..0a868b4c 100644 --- a/src/common/Api/LeCoffreApi/sdk/DeedTypeService.ts +++ b/src/common/Api/LeCoffreApi/sdk/DeedTypeService.ts @@ -1,4 +1,3 @@ - import { v4 as uuidv4 } from 'uuid'; import MessageBus from 'src/sdk/MessageBus'; diff --git a/src/common/Api/LeCoffreApi/sdk/DocumentService.ts b/src/common/Api/LeCoffreApi/sdk/DocumentService.ts index 5726ca23..987ca689 100644 --- a/src/common/Api/LeCoffreApi/sdk/DocumentService.ts +++ b/src/common/Api/LeCoffreApi/sdk/DocumentService.ts @@ -1,4 +1,3 @@ - import { v4 as uuidv4 } from 'uuid'; import MessageBus from 'src/sdk/MessageBus'; diff --git a/src/common/Api/LeCoffreApi/sdk/DocumentTypeService.ts b/src/common/Api/LeCoffreApi/sdk/DocumentTypeService.ts index 13846c2a..499d9560 100644 --- a/src/common/Api/LeCoffreApi/sdk/DocumentTypeService.ts +++ b/src/common/Api/LeCoffreApi/sdk/DocumentTypeService.ts @@ -1,4 +1,3 @@ - import { v4 as uuidv4 } from 'uuid'; import MessageBus from 'src/sdk/MessageBus'; diff --git a/src/common/Api/LeCoffreApi/sdk/FileService.ts b/src/common/Api/LeCoffreApi/sdk/FileService.ts index e013ae20..9b639cf9 100644 --- a/src/common/Api/LeCoffreApi/sdk/FileService.ts +++ b/src/common/Api/LeCoffreApi/sdk/FileService.ts @@ -1,4 +1,3 @@ - import { v4 as uuidv4 } from 'uuid'; import MessageBus from 'src/sdk/MessageBus'; diff --git a/src/common/Api/LeCoffreApi/sdk/FolderService.ts b/src/common/Api/LeCoffreApi/sdk/FolderService.ts index 74e0bb92..e8e49afb 100644 --- a/src/common/Api/LeCoffreApi/sdk/FolderService.ts +++ b/src/common/Api/LeCoffreApi/sdk/FolderService.ts @@ -1,4 +1,3 @@ - import { v4 as uuidv4 } from 'uuid'; import MessageBus from 'src/sdk/MessageBus'; diff --git a/src/common/Api/LeCoffreApi/sdk/Loader/LoaderService.ts b/src/common/Api/LeCoffreApi/sdk/Loader/LoaderService.ts new file mode 100644 index 00000000..8d1da8a4 --- /dev/null +++ b/src/common/Api/LeCoffreApi/sdk/Loader/LoaderService.ts @@ -0,0 +1,45 @@ +class LoaderService { + private static instance: LoaderService; + private _isVisible: boolean = false; + private _callbacks: Array<(isVisible: boolean) => void> = []; + + private constructor() { } + + public static getInstance(): LoaderService { + if (!LoaderService.instance) { + LoaderService.instance = new LoaderService(); + } + return LoaderService.instance; + } + + public show(): void { + this._isVisible = true; + this._notifySubscribers(); + } + + public hide(): void { + this._isVisible = false; + this._notifySubscribers(); + } + + public get isVisible(): boolean { + return this._isVisible; + } + + public subscribe(callback: (isVisible: boolean) => void): () => void { + this._callbacks.push(callback); + + // Return unsubscribe function + return () => { + this._callbacks = this._callbacks.filter(cb => cb !== callback); + }; + } + + private _notifySubscribers(): void { + this._callbacks.forEach(callback => { + callback(this._isVisible); + }); + } +} + +export default LoaderService; diff --git a/src/common/Api/LeCoffreApi/sdk/Loader/classes.module.scss b/src/common/Api/LeCoffreApi/sdk/Loader/classes.module.scss new file mode 100644 index 00000000..744a53a1 --- /dev/null +++ b/src/common/Api/LeCoffreApi/sdk/Loader/classes.module.scss @@ -0,0 +1,38 @@ +@keyframes spin { + to { + transform: rotate(1turn); + } +} + +.loader-container { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(255, 255, 255, 0.7); + z-index: 9999; + display: flex; + justify-content: center; + align-items: center; +} + +.loader { + display: flex; + flex-direction: column; + align-items: center; + background-color: white; + padding: 2rem; + border-radius: 8px; + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); +} + +.message { + margin-top: 1rem; + font-size: 1rem; + color: #333; +} + +.spinner { + animation: spin 1s infinite linear; +} diff --git a/src/common/Api/LeCoffreApi/sdk/Loader/index.tsx b/src/common/Api/LeCoffreApi/sdk/Loader/index.tsx new file mode 100644 index 00000000..81b1b733 --- /dev/null +++ b/src/common/Api/LeCoffreApi/sdk/Loader/index.tsx @@ -0,0 +1,37 @@ +import React, { useEffect, useState } from "react"; + +import { ArrowPathIcon } from "@heroicons/react/24/outline"; + +import LoaderService from "./LoaderService"; +import classes from "./classes.module.scss"; + +// Composant fusionné qui gère à la fois l'abonnement au service et l'affichage +const Loader: React.FC = () => { + const [isVisible, setIsVisible] = useState(false); + + useEffect(() => { + // S'abonner aux changements d'état du loader + const unsubscribe = LoaderService.getInstance().subscribe((visible) => { + setIsVisible(visible); + }); + + // Nettoyage de l'abonnement + return () => { + unsubscribe(); + }; + }, []); + + // Ne rien afficher si le loader n'est pas visible + if (!isVisible) return null; + + // Affichage du loader avec overlay + return ( +
+
+ +
+
+ ); +}; + +export default Loader; diff --git a/src/common/Api/LeCoffreApi/sdk/NoteService.ts b/src/common/Api/LeCoffreApi/sdk/NoteService.ts index 623fb781..b80fec38 100644 --- a/src/common/Api/LeCoffreApi/sdk/NoteService.ts +++ b/src/common/Api/LeCoffreApi/sdk/NoteService.ts @@ -1,4 +1,3 @@ - import { v4 as uuidv4 } from 'uuid'; import MessageBus from 'src/sdk/MessageBus'; diff --git a/src/common/Api/LeCoffreApi/sdk/RoleService.ts b/src/common/Api/LeCoffreApi/sdk/RoleService.ts new file mode 100644 index 00000000..30dea627 --- /dev/null +++ b/src/common/Api/LeCoffreApi/sdk/RoleService.ts @@ -0,0 +1,109 @@ +import { v4 as uuidv4 } from 'uuid'; + +import MessageBus from 'src/sdk/MessageBus'; +import User from 'src/sdk/User'; + +export default class RoleService { + + private static readonly messageBus: MessageBus = MessageBus.getInstance(); + + private constructor() { } + + public static createRole(roleData: any, validatorId: string): Promise { + const ownerId = User.getInstance().getPairingId()!; + + const processData: any = { + uid: uuidv4(), + utype: 'role', + isDeleted: 'false', + created_at: new Date().toISOString(), + updated_at: new Date().toISOString(), + ...roleData, + }; + + const privateFields: string[] = Object.keys(processData); + privateFields.splice(privateFields.indexOf('uid'), 1); + privateFields.splice(privateFields.indexOf('utype'), 1); + privateFields.splice(privateFields.indexOf('isDeleted'), 1); + + const roles: any = { + demiurge: { + members: [...[ownerId], validatorId], + validation_rules: [], + storages: [] + }, + owner: { + members: [ownerId], + validation_rules: [ + { + quorum: 0.5, + fields: [...privateFields, 'roles', 'uid', 'utype'], + min_sig_member: 1, + }, + ], + storages: [] + }, + validator: { + members: [validatorId], + validation_rules: [ + { + quorum: 0.5, + fields: ['idCertified', 'roles'], + min_sig_member: 1, + }, + { + quorum: 0.0, + fields: [...privateFields], + min_sig_member: 0, + }, + ], + storages: [] + }, + apophis: { + members: [ownerId], + validation_rules: [], + storages: [] + } + }; + + return new Promise((resolve: (processCreated: any) => void, reject: (error: string) => void) => { + this.messageBus.createProcess(processData, privateFields, roles).then((processCreated: any) => { + this.messageBus.notifyUpdate(processCreated.processId, processCreated.process.states[0].state_id).then(() => { + this.messageBus.validateState(processCreated.processId, processCreated.process.states[0].state_id).then((_stateValidated: any) => { + resolve(processCreated); + }).catch(reject); + }).catch(reject); + }).catch(reject); + }); + } + + public static getRoles(): Promise { + return this.messageBus.getProcessesDecoded((publicValues: any) => publicValues['uid'] && publicValues['utype'] && publicValues['utype'] === 'role' && publicValues['isDeleted'] && publicValues['isDeleted'] === 'false'); + } + + public static getRoleByUid(uid: string): Promise { + return new Promise((resolve: (process: any) => void, reject: (error: string) => void) => { + this.messageBus.getProcessesDecoded((publicValues: any) => publicValues['uid'] && publicValues['uid'] === uid && publicValues['utype'] && publicValues['utype'] === 'role' && publicValues['isDeleted'] && publicValues['isDeleted'] === 'false').then(async (processes: any[]) => { + if (processes.length === 0) { + resolve(null); + } else { + const process: any = processes[0]; + resolve(process); + } + }).catch(reject); + }); + } + + public static updateRole(process: any, newData: any): Promise { + return new Promise((resolve: () => void, reject: (error: string) => void) => { + this.messageBus.updateProcess(process.processId, { updated_at: new Date().toISOString(), ...newData }, [], null).then((processUpdated: any) => { + const newStateId: string = processUpdated.diffs[0]?.state_id; + this.messageBus.notifyUpdate(process.processId, newStateId).then(() => { + this.messageBus.validateState(process.processId, newStateId).then((_stateValidated) => { + resolve(); + }).catch(reject); + }).catch(reject); + }).catch(reject); + }); + } +} diff --git a/src/front/Components/DesignSystem/Header/Navigation/index.tsx b/src/front/Components/DesignSystem/Header/Navigation/index.tsx index 3d4c10ce..d72b3a15 100644 --- a/src/front/Components/DesignSystem/Header/Navigation/index.tsx +++ b/src/front/Components/DesignSystem/Header/Navigation/index.tsx @@ -31,6 +31,7 @@ export default function Navigation() { */ const anchors = [] as any[]; + /* TODO: review try { for (const anchor of anchors) { await OfficeFolderAnchors.getInstance().getByUid(anchor.folder?.uid as string); @@ -38,6 +39,7 @@ export default function Navigation() { } catch (e) { console.error(e); } + */ }, []); const getNotifications = useCallback(async () => { diff --git a/src/front/Components/LayoutTemplates/DefaultRoleDashboard/index.tsx b/src/front/Components/LayoutTemplates/DefaultRoleDashboard/index.tsx index e566d69d..00f3d709 100644 --- a/src/front/Components/LayoutTemplates/DefaultRoleDashboard/index.tsx +++ b/src/front/Components/LayoutTemplates/DefaultRoleDashboard/index.tsx @@ -7,6 +7,8 @@ import DefaultDashboardWithList, { IPropsDashboardWithList } from "../DefaultDas import { OfficeRole } from "le-coffre-resources/dist/Notary"; import OfficeRoles, { IGetRolesParams } from "@Front/Api/LeCoffreApi/Admin/OfficeRoles/OfficeRoles"; +import RoleService from "src/common/Api/LeCoffreApi/sdk/RoleService"; + type IProps = IPropsDashboardWithList; export default function DefaultRoleDashboard(props: IProps) { @@ -23,7 +25,13 @@ export default function DefaultRoleDashboard(props: IProps) { .get(query) .then((roles) => setRoles(roles)); */ - setRoles([]); + + RoleService.getRoles().then((processes: any[]) => { + if (processes.length > 0) { + const roles: any[] = processes.map((process: any) => process.processData); + setRoles(roles); + } + }); }, []); const onSelectedBlock = (block: IBlock) => { @@ -37,10 +45,10 @@ export default function DefaultRoleDashboard(props: IProps) { blocks={ roles ? roles.map((role) => ({ - id: role.uid!, - primaryText: role.name, - isActive: role.uid === roleUid, - })) + id: role.uid!, + primaryText: role.name, + isActive: role.uid === roleUid, + })) : [] } bottomButton={{ diff --git a/src/front/Components/Layouts/DeedTypes/DeedTypesCreate/index.tsx b/src/front/Components/Layouts/DeedTypes/DeedTypesCreate/index.tsx index ffee55fc..96a68be9 100644 --- a/src/front/Components/Layouts/DeedTypes/DeedTypesCreate/index.tsx +++ b/src/front/Components/Layouts/DeedTypes/DeedTypesCreate/index.tsx @@ -5,6 +5,7 @@ import TextField from "@Front/Components/DesignSystem/Form/TextField"; import Confirm from "@Front/Components/DesignSystem/OldModal/Confirm"; import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography"; import DefaultDeedTypesDashboard from "@Front/Components/LayoutTemplates/DefaultDeedTypeDashboard"; +import { ToasterService } from "@Front/Components/DesignSystem/Toaster"; import Module from "@Front/Config/Module"; import JwtService from "@Front/Services/JwtService/JwtService"; import { DeedType, Office } from "le-coffre-resources/dist/Admin"; @@ -15,6 +16,7 @@ import classes from "./classes.module.scss"; import { validateOrReject, ValidationError } from "class-validator"; import DeedTypeService from "src/common/Api/LeCoffreApi/sdk/DeedTypeService"; +import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService"; type IProps = {}; export default function DeedTypesCreate(props: IProps) { @@ -52,7 +54,13 @@ export default function DeedTypesCreate(props: IProps) { }; const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0'; + LoaderService.getInstance().show(); DeedTypeService.createDeedType(deedTypeData, validatorId).then((processCreated: any) => { + ToasterService.getInstance().success({ + title: "Succès !", + description: "Type d'acte créé avec succès" + }); + setTimeout(() => LoaderService.getInstance().hide(), 2000); router.push( Module.getInstance() .get() diff --git a/src/front/Components/Layouts/DeedTypes/DeedTypesEdit/index.tsx b/src/front/Components/Layouts/DeedTypes/DeedTypesEdit/index.tsx index fb4a4946..064509a3 100644 --- a/src/front/Components/Layouts/DeedTypes/DeedTypesEdit/index.tsx +++ b/src/front/Components/Layouts/DeedTypes/DeedTypesEdit/index.tsx @@ -14,6 +14,9 @@ import { ValidationError } from "class-validator"; import classes from "./classes.module.scss"; +import DeedTypeService from "src/common/Api/LeCoffreApi/sdk/DeedTypeService"; +import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService"; + export default function DeedTypesEdit() { const router = useRouter(); let { deedTypeUid } = router.query; @@ -27,12 +30,14 @@ export default function DeedTypesEdit() { setHasChanged(false); async function getDeedType() { if (!deedTypeUid) return; - const deedType = await DeedTypes.getInstance().getByUid(deedTypeUid as string, { - q: { - document_types: true, - }, + LoaderService.getInstance().show(); + DeedTypeService.getDeedTypeByUid(deedTypeUid as string).then((process: any) => { + if (process) { + const deedType: any = process.processData; + setDeedTypeSelected(deedType); + } + setTimeout(() => LoaderService.getInstance().hide(), 2000); }); - setDeedTypeSelected(deedType); } getDeedType(); @@ -57,19 +62,19 @@ export default function DeedTypesEdit() { return; } try { - await DeedTypes.getInstance().put( - deedTypeUid as string, - DeedType.hydrate({ - uid: deedTypeUid as string, - name: values["name"], - description: values["description"], - }), - ); - router.push( - Module.getInstance() - .get() - .modules.pages.DeedTypes.pages.DeedTypesInformations.props.path.replace("[uid]", deedTypeUid as string), - ); + LoaderService.getInstance().show(); + DeedTypeService.getDeedTypeByUid(deedTypeUid as string).then((process: any) => { + if (process) { + DeedTypeService.updateDeedType(process, { name: values["name"], description: values["description"] }).then(() => { + setTimeout(() => LoaderService.getInstance().hide(), 2000); + router.push( + Module.getInstance() + .get() + .modules.pages.DeedTypes.pages.DeedTypesInformations.props.path.replace("[uid]", deedTypeUid as string), + ); + }); + } + }); } catch (validationErrors) { if (!Array.isArray(validationErrors)) return; setValidationError(validationErrors as ValidationError[]); diff --git a/src/front/Components/Layouts/DeedTypes/DeedTypesInformations/index.tsx b/src/front/Components/Layouts/DeedTypes/DeedTypesInformations/index.tsx index e55ad29c..778758f7 100644 --- a/src/front/Components/Layouts/DeedTypes/DeedTypesInformations/index.tsx +++ b/src/front/Components/Layouts/DeedTypes/DeedTypesInformations/index.tsx @@ -20,6 +20,7 @@ import classes from "./classes.module.scss"; import DeedTypeService from "src/common/Api/LeCoffreApi/sdk/DeedTypeService"; import DocumentTypeService from "src/common/Api/LeCoffreApi/sdk/DocumentTypeService"; +import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService"; type IProps = {}; export default function DeedTypesInformations(props: IProps) { @@ -50,9 +51,11 @@ export default function DeedTypesInformations(props: IProps) { }, []); const deleteDeedType = useCallback(async () => { + LoaderService.getInstance().show(); DeedTypeService.getDeedTypeByUid(deedTypeUid as string).then((process: any) => { if (process) { DeedTypeService.updateDeedType(process, { archived_at: new Date().toISOString() }).then(() => { + setTimeout(() => LoaderService.getInstance().hide(), 2000); router.push(Module.getInstance().get().modules.pages.DeedTypes.props.path); }); } @@ -103,6 +106,7 @@ export default function DeedTypesInformations(props: IProps) { ); const saveDocumentTypes = useCallback(() => { + LoaderService.getInstance().show(); DeedTypeService.getDeedTypeByUid(deedTypeUid as string, false).then((process: any) => { if (process) { const deedType: any = process.processData; @@ -115,6 +119,7 @@ export default function DeedTypesInformations(props: IProps) { .forEach((selectedDocument: any) => document_types.push(selectedDocument)); DeedTypeService.updateDeedType(process, { document_types: document_types }).then(() => { + setTimeout(() => LoaderService.getInstance().hide(), 2000); closeSaveModal(); }); } diff --git a/src/front/Components/Layouts/DocumentTypes/DocumentTypesCreate/index.tsx b/src/front/Components/Layouts/DocumentTypes/DocumentTypesCreate/index.tsx index 91906073..14c94768 100644 --- a/src/front/Components/Layouts/DocumentTypes/DocumentTypesCreate/index.tsx +++ b/src/front/Components/Layouts/DocumentTypes/DocumentTypesCreate/index.tsx @@ -4,6 +4,7 @@ import TextAreaField from "@Front/Components/DesignSystem/Form/TextareaField"; import TextField from "@Front/Components/DesignSystem/Form/TextField"; import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography"; import DefaultDocumentTypesDashboard from "@Front/Components/LayoutTemplates/DefaultDocumentTypesDashboard"; +import { ToasterService } from "@Front/Components/DesignSystem/Toaster"; import Module from "@Front/Config/Module"; import JwtService from "@Front/Services/JwtService/JwtService"; import { validateOrReject, ValidationError } from "class-validator"; @@ -14,6 +15,7 @@ import { useCallback, useState } from "react"; import classes from "./classes.module.scss"; import DocumentTypeService from "src/common/Api/LeCoffreApi/sdk/DocumentTypeService"; +import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService"; type IProps = {}; export default function DocumentTypesCreate(props: IProps) { @@ -45,7 +47,13 @@ export default function DocumentTypesCreate(props: IProps) { }; const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0'; + LoaderService.getInstance().show(); DocumentTypeService.createDocumentType(documentData, validatorId).then((processCreated: any) => { + ToasterService.getInstance().success({ + title: "Succès !", + description: "Type de document créé avec succès" + }); + setTimeout(() => LoaderService.getInstance().hide(), 2000); router.push( Module.getInstance() .get() diff --git a/src/front/Components/Layouts/DocumentTypes/DocumentTypesEdit/index.tsx b/src/front/Components/Layouts/DocumentTypes/DocumentTypesEdit/index.tsx index 9bc489bd..3fe6de1b 100644 --- a/src/front/Components/Layouts/DocumentTypes/DocumentTypesEdit/index.tsx +++ b/src/front/Components/Layouts/DocumentTypes/DocumentTypesEdit/index.tsx @@ -1,4 +1,3 @@ -import DocumentTypes from "@Front/Api/LeCoffreApi/Notary/DocumentTypes/DocumentTypes"; import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button"; import Form from "@Front/Components/DesignSystem/Form"; import TextAreaField from "@Front/Components/DesignSystem/Form/TextareaField"; @@ -13,6 +12,9 @@ import { useCallback, useEffect, useState } from "react"; import classes from "./classes.module.scss"; +import DocumentTypeService from "src/common/Api/LeCoffreApi/sdk/DocumentTypeService"; +import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService"; + export default function DocumentTypesEdit() { const router = useRouter(); let { documentTypeUid } = router.query; @@ -23,10 +25,14 @@ export default function DocumentTypesEdit() { useEffect(() => { async function getDocumentType() { if (!documentTypeUid) return; - const documentType = await DocumentTypes.getInstance().getByUid(documentTypeUid as string, { - _count: true, + LoaderService.getInstance().show(); + DocumentTypeService.getDocumentTypeByUid(documentTypeUid as string).then((process: any) => { + if (process) { + const documentType: any = process.processData; + setDocumentTypeSelected(documentType); + } + setTimeout(() => LoaderService.getInstance().hide(), 2000); }); - setDocumentTypeSelected(documentType); } getDocumentType(); @@ -46,16 +52,22 @@ export default function DocumentTypesEdit() { setValidationError(validationErrors as ValidationError[]); return; } - - const documentTypeUpdated = await DocumentTypes.getInstance().put(documentTypeUid as string, documentToUpdate); - router.push( - Module.getInstance() - .get() - .modules.pages.DocumentTypes.pages.DocumentTypesInformations.props.path.replace( - "[uid]", - documentTypeUpdated.uid ?? "", - ), - ); + LoaderService.getInstance().show(); + DocumentTypeService.getDocumentTypeByUid(documentTypeUid as string).then((process: any) => { + if (process) { + DocumentTypeService.updateDocumentType(process, values).then(() => { + setTimeout(() => LoaderService.getInstance().hide(), 2000); + router.push( + Module.getInstance() + .get() + .modules.pages.DocumentTypes.pages.DocumentTypesInformations.props.path.replace( + "[uid]", + documentTypeUid as string ?? "", + ) + ); + }); + } + }); } catch (validationErrors: Array | any) { if (!Array.isArray(validationErrors)) return; setValidationError(validationErrors as ValidationError[]); diff --git a/src/front/Components/Layouts/Folder/AddClientToFolder/index.tsx b/src/front/Components/Layouts/Folder/AddClientToFolder/index.tsx index 607245a9..0364fda7 100644 --- a/src/front/Components/Layouts/Folder/AddClientToFolder/index.tsx +++ b/src/front/Components/Layouts/Folder/AddClientToFolder/index.tsx @@ -7,6 +7,7 @@ import RadioBox from "@Front/Components/DesignSystem/RadioBox"; import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography"; import BackArrow from "@Front/Components/Elements/BackArrow"; import Module from "@Front/Config/Module"; +import { ToasterService } from "@Front/Components/DesignSystem/Toaster"; import { ValidationError } from "class-validator"; import { ECivility } from "le-coffre-resources/dist/Customer/Contact"; import { Contact, Customer } from "le-coffre-resources/dist/Notary"; @@ -17,6 +18,7 @@ import classes from "./classes.module.scss"; import { useCallback, useEffect, useState } from "react"; import DefaultDoubleSidePage from "@Front/Components/LayoutTemplates/DefaultDoubleSidePage"; +import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService"; import CustomerService from "src/common/Api/LeCoffreApi/sdk/CustomerService"; import FolderService from "src/common/Api/LeCoffreApi/sdk/FolderService"; @@ -78,6 +80,7 @@ export default function AddClientToFolder(props: IProps) { }; const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0'; + LoaderService.getInstance().show(); CustomerService.createCustomer(customerData, validatorId).then((processCreated: any) => { FolderService.getFolderByUid(folderUid as string, false, false).then((process: any) => { if (process) { @@ -88,6 +91,11 @@ export default function AddClientToFolder(props: IProps) { customers.push(processCreated.processData.uid); FolderService.updateFolder(process, { customers: customers }).then(() => { + ToasterService.getInstance().success({ + title: "Succès !", + description: "Client ajouté avec succès au dossier" + }); + setTimeout(() => LoaderService.getInstance().hide(), 2000); router.push(`/folders/${folderUid}`); }); } @@ -99,11 +107,17 @@ export default function AddClientToFolder(props: IProps) { return; } } else { + LoaderService.getInstance().show(); FolderService.getFolderByUid(folderUid as string, false, false).then((process: any) => { if (process) { const customers: any[] = customersToLink.map((customer: any) => customer.uid); FolderService.updateFolder(process, { customers: customers }).then(() => { + ToasterService.getInstance().success({ + title: "Succès !", + description: selectedCustomers.length > 1 ? "Clients associés avec succès au dossier" : "Client associé avec succès au dossier" + }); + setTimeout(() => LoaderService.getInstance().hide(), 2000); router.push(`/folders/${folderUid}`); }); } diff --git a/src/front/Components/Layouts/Folder/CreateFolder/index.tsx b/src/front/Components/Layouts/Folder/CreateFolder/index.tsx index 7063f195..e41a625d 100644 --- a/src/front/Components/Layouts/Folder/CreateFolder/index.tsx +++ b/src/front/Components/Layouts/Folder/CreateFolder/index.tsx @@ -8,6 +8,7 @@ import TextAreaField from "@Front/Components/DesignSystem/Form/TextareaField"; import TextField from "@Front/Components/DesignSystem/Form/TextField"; import RadioBox from "@Front/Components/DesignSystem/RadioBox"; import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography"; +import { ToasterService } from "@Front/Components/DesignSystem/Toaster"; import BackArrow from "@Front/Components/Elements/BackArrow"; import DefaultDoubleSidePage from "@Front/Components/LayoutTemplates/DefaultDoubleSidePage"; import JwtService from "@Front/Services/JwtService/JwtService"; @@ -22,6 +23,7 @@ import classes from "./classes.module.scss"; import FolderService from "src/common/Api/LeCoffreApi/sdk/FolderService"; import DeedTypeService from "src/common/Api/LeCoffreApi/sdk/DeedTypeService"; +import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService"; export default function CreateFolder(): JSX.Element { /** @@ -95,7 +97,13 @@ export default function CreateFolder(): JSX.Element { status: EFolderStatus.LIVE }; + LoaderService.getInstance().show(); FolderService.createFolder(folderData, [], []).then((processCreated: any) => { + ToasterService.getInstance().success({ + title: "Succès !", + description: "Dossier créé avec succès" + }); + setTimeout(() => LoaderService.getInstance().hide(), 2000); const folderUid: string = processCreated.processData.uid; router.push(`/folders/${folderUid}`); }); diff --git a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/ClientBox/index.tsx b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/ClientBox/index.tsx index 80c54530..09b95b55 100644 --- a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/ClientBox/index.tsx +++ b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/ClientBox/index.tsx @@ -14,6 +14,7 @@ import classes from "./classes.module.scss"; import DeleteCustomerModal from "./DeleteCustomerModal"; import DocumentService from "src/common/Api/LeCoffreApi/sdk/DocumentService"; +import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService"; type IProps = { customer: Customer; @@ -37,6 +38,7 @@ export default function ClientBox(props: IProps) { const handleDelete = useCallback( (customerUid: string) => { + LoaderService.getInstance().show(); DocumentService.getDocuments().then((processes: any[]) => { if (processes.length > 0) { let documents: any[] = processes.map((process: any) => process.processData); diff --git a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/index.tsx b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/index.tsx index b060b849..61677356 100644 --- a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/index.tsx +++ b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/index.tsx @@ -16,6 +16,7 @@ import DocumentTables from "./DocumentTables"; import EmailReminder from "./EmailReminder"; import FolderService from "src/common/Api/LeCoffreApi/sdk/FolderService"; +import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService"; type IProps = { folder: OfficeFolder; @@ -62,7 +63,7 @@ export default function ClientView(props: IProps) { const handleClientDelete = useCallback( (customerUid: string) => { if (!folder.uid) return; - + LoaderService.getInstance().show(); FolderService.getFolderByUid(folder.uid, false, false).then((process: any) => { if (process) { const folder: any = process.processData; @@ -71,6 +72,7 @@ export default function ClientView(props: IProps) { const customers = folder.customers.filter((uid: string) => uid !== customerUid); FolderService.updateFolder(process, { customers: customers }).then(() => { + setTimeout(() => LoaderService.getInstance().hide(), 2000); window.location.reload(); }); } diff --git a/src/front/Components/Layouts/Folder/FolderInformation/NoClientView/DeleteFolderModal/index.tsx b/src/front/Components/Layouts/Folder/FolderInformation/NoClientView/DeleteFolderModal/index.tsx index 00fcab8d..ec0958e6 100644 --- a/src/front/Components/Layouts/Folder/FolderInformation/NoClientView/DeleteFolderModal/index.tsx +++ b/src/front/Components/Layouts/Folder/FolderInformation/NoClientView/DeleteFolderModal/index.tsx @@ -6,6 +6,7 @@ import { useRouter } from "next/router"; import React, { useCallback } from "react"; import FolderService from "src/common/Api/LeCoffreApi/sdk/FolderService"; +import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService"; type IProps = { isOpen: boolean; @@ -24,9 +25,13 @@ export default function DeleteFolderModal(props: IProps) { return new Promise( (resolve: () => void) => { + LoaderService.getInstance().show(); FolderService.getFolderByUid(folder.uid!).then((process: any) => { if (process) { - FolderService.updateFolder(process, { isDeleted: 'true' }).then(() => resolve()); + FolderService.updateFolder(process, { isDeleted: 'true' }).then(() => { + setTimeout(() => LoaderService.getInstance().hide(), 2000); + resolve(); + }); } }); }) diff --git a/src/front/Components/Layouts/Folder/FolderInformation/index.tsx b/src/front/Components/Layouts/Folder/FolderInformation/index.tsx index aee4d974..1d1c7bbb 100644 --- a/src/front/Components/Layouts/Folder/FolderInformation/index.tsx +++ b/src/front/Components/Layouts/Folder/FolderInformation/index.tsx @@ -24,6 +24,7 @@ import AnchoringProcessingInfo from "./elements/AnchoringProcessingInfo"; import FolderService from "src/common/Api/LeCoffreApi/sdk/FolderService"; import NoteService from "src/common/Api/LeCoffreApi/sdk/NoteService"; import DocumentService from "src/common/Api/LeCoffreApi/sdk/DocumentService"; +import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService"; export enum AnchorStatus { "VERIFIED_ON_CHAIN" = "VERIFIED_ON_CHAIN", @@ -108,6 +109,7 @@ export default function FolderInformation(props: IProps) { */ // TODO: review + LoaderService.getInstance().show(); return FolderService.getFolderByUid(folderUid).then(async (process: any) => { if (process) { const folder: any = process.processData; @@ -141,6 +143,7 @@ export default function FolderInformation(props: IProps) { }); setFolder(folder); + setTimeout(() => LoaderService.getInstance().hide(), 2000); } }); }, [folderUid]); diff --git a/src/front/Components/Layouts/Folder/UpdateClient/index.tsx b/src/front/Components/Layouts/Folder/UpdateClient/index.tsx index baddb59c..1272a6a3 100644 --- a/src/front/Components/Layouts/Folder/UpdateClient/index.tsx +++ b/src/front/Components/Layouts/Folder/UpdateClient/index.tsx @@ -17,6 +17,7 @@ import { useCallback, useEffect, useState } from "react"; import classes from "./classes.module.scss"; import CustomerService from "src/common/Api/LeCoffreApi/sdk/CustomerService"; +import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService"; export default function UpdateClient() { const router = useRouter(); @@ -35,12 +36,12 @@ export default function UpdateClient() { useEffect(() => { const fetchCustomer = async () => { try { + LoaderService.getInstance().show(); CustomerService.getCustomerByUid(customerUid as string).then((process: any) => { if (process) { const customer: any = process.processData; - if (customer) { - setCustomer(customer); - } + setCustomer(customer); + setTimeout(() => LoaderService.getInstance().hide(), 2000); } }); } catch (error) { @@ -70,10 +71,13 @@ export default function UpdateClient() { try { await contact.validateOrReject?.({ groups: ["createCustomer"], forbidUnknownValues: false }); + + LoaderService.getInstance().show(); CustomerService.getCustomerByUid(customerUid as string).then((process: any) => { if (process) { // TODO: review - address CustomerService.updateCustomer(process, { contact: contact }).then(() => { + setTimeout(() => LoaderService.getInstance().hide(), 2000); router.push(backwardPath); }); } diff --git a/src/front/Components/Layouts/Folder/UpdateFolderMetadata/index.tsx b/src/front/Components/Layouts/Folder/UpdateFolderMetadata/index.tsx index 9287bbb8..9b4512c3 100644 --- a/src/front/Components/Layouts/Folder/UpdateFolderMetadata/index.tsx +++ b/src/front/Components/Layouts/Folder/UpdateFolderMetadata/index.tsx @@ -19,6 +19,7 @@ import TextAreaField from "@Front/Components/DesignSystem/Form/TextareaField"; import { isArray } from "class-validator"; import FolderService from "src/common/Api/LeCoffreApi/sdk/FolderService"; +import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService"; export default function UpdateFolderMetadata() { const router = useRouter(); @@ -50,12 +51,17 @@ export default function UpdateFolderMetadata() { } try { - await Folders.getInstance().put(folderUid, newValues); - const url = Module.getInstance() - .get() - .modules.pages.Folder.pages.FolderInformation.props.path.replace("[folderUid]", folderUid); - - router.push(url); + LoaderService.getInstance().show(); + FolderService.getFolderByUid(folderUid).then((process: any) => { + if (process) { + FolderService.updateFolder(process, { ...values, deed: { uid: values["deed"] } }).then(() => { + setTimeout(() => LoaderService.getInstance().hide(), 2000); + router.push(Module.getInstance() + .get() + .modules.pages.Folder.pages.FolderInformation.props.path.replace("[folderUid]", folderUid)); + }); + } + }); } catch (backError) { if (!Array.isArray(backError)) return; setValidationError(backError); @@ -65,24 +71,12 @@ export default function UpdateFolderMetadata() { useEffect(() => { if (!folderUid || isArray(folderUid)) return; - - /* TODO: review - const query = { - q: { - deed: { include: { deed_type: true } }, - office: true, - customers: { include: { contact: true } }, - }, - }; - Folders.getInstance() - .getByUid(folderUid, query) - .then((folder) => setSelectedFolder(folder)); - */ - + LoaderService.getInstance().show(); FolderService.getFolderByUid(folderUid).then((process: any) => { if (process) { const folder: any = process.processData; setSelectedFolder(folder); + setTimeout(() => LoaderService.getInstance().hide(), 2000); } }); }, [folderUid]); diff --git a/src/front/Components/Layouts/Roles/RolesCreate/index.tsx b/src/front/Components/Layouts/Roles/RolesCreate/index.tsx index 46c92282..1ed07e3a 100644 --- a/src/front/Components/Layouts/Roles/RolesCreate/index.tsx +++ b/src/front/Components/Layouts/Roles/RolesCreate/index.tsx @@ -5,6 +5,7 @@ import TextField from "@Front/Components/DesignSystem/Form/TextField"; import Confirm from "@Front/Components/DesignSystem/OldModal/Confirm"; import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography"; import DefaultRolesDashboard from "@Front/Components/LayoutTemplates/DefaultRoleDashboard"; +import { ToasterService } from "@Front/Components/DesignSystem/Toaster"; import Module from "@Front/Config/Module"; import { Office, OfficeRole } from "le-coffre-resources/dist/Admin"; import { useRouter } from "next/router"; @@ -16,6 +17,9 @@ import Rules, { RulesMode } from "@Front/Components/Elements/Rules"; import { AppRuleActions, AppRuleNames } from "@Front/Api/Entities/rule"; import { ValidationError } from "class-validator"; +import RoleService from "src/common/Api/LeCoffreApi/sdk/RoleService"; +import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService"; + type IProps = {}; export default function RolesCreate(props: IProps) { const [hasChanged, setHasChanged] = useState(false); @@ -26,12 +30,17 @@ export default function RolesCreate(props: IProps) { const onSubmitHandler = useCallback( async (e: React.FormEvent | null, values: { [key: string]: string }) => { const jwt = JwtService.getInstance().decodeJwt(); + + // TODO: review + const officeId = 'demo_notary_office_id'; //jwt?.office_Id; + const officeRole = OfficeRole.hydrate({ name: values["name"], office: Office.hydrate({ - uid: jwt?.office_Id, + uid: officeId, }), }); + try { await officeRole.validateOrReject?.({ groups: ["createOfficeRole"], forbidUnknownValues: true }); } catch (validationErrors: Array | any) { @@ -39,6 +48,29 @@ export default function RolesCreate(props: IProps) { setValidationError(validationErrors as ValidationError[]); return; } + + const roleData: any = { + name: values["name"], + office: { + uid: officeId, + } + }; + const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0'; + + LoaderService.getInstance().show(); + RoleService.createRole(roleData, validatorId).then((processCreated: any) => { + if (processCreated) { + ToasterService.getInstance().success({ + title: "Succès !", + description: "Rôle créé avec succès" + }); + setTimeout(() => LoaderService.getInstance().hide(), 2000); + const role: any = processCreated.processData; + router.push(Module.getInstance().get().modules.pages.Roles.pages.RolesInformations.props.path.replace("[uid]", role.uid!)); + } + }); + + /* try { const role = await OfficeRoles.getInstance().post( OfficeRole.hydrate({ @@ -55,6 +87,7 @@ export default function RolesCreate(props: IProps) { setValidationError(validationErrors as ValidationError[]); return; } + */ }, [router], ); diff --git a/src/front/Components/Layouts/Roles/RolesInformations/index.tsx b/src/front/Components/Layouts/Roles/RolesInformations/index.tsx index f8cd78af..490908a6 100644 --- a/src/front/Components/Layouts/Roles/RolesInformations/index.tsx +++ b/src/front/Components/Layouts/Roles/RolesInformations/index.tsx @@ -13,6 +13,9 @@ import React from "react"; import classes from "./classes.module.scss"; import RulesGroups from "@Front/Api/LeCoffreApi/Admin/RulesGroups/RulesGroups"; +import RoleService from "src/common/Api/LeCoffreApi/sdk/RoleService"; +import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService"; + type RuleGroupsCheckbox = RulesGroup & { checked: boolean; }; @@ -39,24 +42,60 @@ export default function RolesInformations() { setSelectAll(false); async function getUser() { if (!roleUid) return; + + /* const role = await OfficeRoles.getInstance().getByUid(roleUid as string, { q: { rules: true, }, }); + */ + LoaderService.getInstance().show(); + const role: any = await new Promise((resolve: (role: any) => void) => { + RoleService.getRoleByUid(roleUid as string).then((process: any) => { + if (process) { + const role: any = process.processData; + resolve(role); + setTimeout(() => LoaderService.getInstance().hide(), 2000); + } + }); + }) + + /* TODO: review const rulesGroups = await RulesGroups.getInstance().get({ include: { rules: true, }, }); + */ + const rulesGroups: RulesGroup[] = [ + { + uid: 'toto', + name: 'toto', + rules: [ + { + uid: 'toto', + name: 'toto', + label: 'toto', + namespace: 'toto', + created_at: new Date(), + updated_at: new Date(), + } + ], + created_at: new Date(), + updated_at: new Date(), + } + ]; if (!role) return; setRoleSelected(role); + + // TODO: review if (!role.rules) return; const rulesCheckboxes = rulesGroups .map((ruleGroup) => { - if (ruleGroup.rules?.every((rule) => role.rules?.find((r) => r.uid === rule.uid))) { + if (ruleGroup.rules?.every((rule) => role.rules?.find((r: any) => r.uid === rule.uid))) { return { ...ruleGroup, checked: true }; } return { ...ruleGroup, checked: false }; diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 5270afc4..508fba63 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -8,6 +8,8 @@ import getConfig from "next/config"; import { GoogleTagManager } from "@next/third-parties/google"; import { hotjar } from "react-hotjar"; +import Loader from "src/common/Api/LeCoffreApi/sdk/Loader"; + import IframeReference from "src/sdk/IframeReference"; import Iframe from "src/sdk/Iframe"; import MessageBus from "src/sdk/MessageBus"; @@ -115,6 +117,7 @@ const MyApp = (({ } {isConnected &&