diff --git a/src/common/Api/LeCoffreApi/sdk/CustomerService.ts b/src/common/Api/LeCoffreApi/sdk/CustomerService.ts index 5bf3a3b7..de3122e7 100644 --- a/src/common/Api/LeCoffreApi/sdk/CustomerService.ts +++ b/src/common/Api/LeCoffreApi/sdk/CustomerService.ts @@ -7,6 +7,8 @@ export default class CustomerService { private static readonly messageBus: MessageBus = MessageBus.getInstance(); + private static readonly CACHE_TTL = 5 * 60 * 1000; // 5 minutes cache TTL + private constructor() { } public static createCustomer(customerData: any, validatorId: string): Promise { @@ -70,7 +72,7 @@ export default class CustomerService { 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); + this.getCustomerByUid(processCreated.processData.uid).then(resolve).catch(reject); }).catch(reject); }).catch(reject); }).catch(reject); @@ -78,16 +80,64 @@ export default class CustomerService { } public static getCustomers(): Promise { - return this.messageBus.getProcessesDecoded((publicValues: any) => publicValues['uid'] && publicValues['utype'] && publicValues['utype'] === 'customer' && publicValues['isDeleted'] && publicValues['isDeleted'] === 'false'); + // Check if we have valid cache + const cacheProcesses: any[] = []; + const now = Date.now(); + const customers: any[] = JSON.parse(sessionStorage.getItem('_customers_') || '[]'); + for (const customer of customers) { + if (now - customer.timestamp < this.CACHE_TTL) { + cacheProcesses.push(customer.process); + } + } + const cacheUids: string[] = cacheProcesses.map((process: any) => process.processData.uid); + + return this.messageBus.getProcessesDecoded((publicValues: any) => + publicValues['uid'] && + publicValues['utype'] && + publicValues['utype'] === 'customer' && + publicValues['isDeleted'] && + publicValues['isDeleted'] === 'false' && + !cacheUids.includes(publicValues['uid']) + ).then((processes: any[]) => { + if (processes.length === 0) { + return cacheProcesses; + } else { + for (const process of processes) { + // Update cache + this.setCache(process); + + cacheProcesses.push(process); + } + return cacheProcesses; + } + }); } public static getCustomerByUid(uid: string): Promise { + // Check if we have valid cache + const now = Date.now(); + const cache: any = this.getCache(uid); + if (cache && (now - cache.timestamp) < this.CACHE_TTL) { + return Promise.resolve(cache.process); + } + 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'] === 'customer' && publicValues['isDeleted'] && publicValues['isDeleted'] === 'false').then((processes: any[]) => { + this.messageBus.getProcessesDecoded((publicValues: any) => + publicValues['uid'] && + publicValues['uid'] === uid && + publicValues['utype'] && + publicValues['utype'] === 'customer' && + publicValues['isDeleted'] && + publicValues['isDeleted'] === 'false' + ).then((processes: any[]) => { if (processes.length === 0) { resolve(null); } else { const process: any = processes[0]; + + // Update cache + this.setCache(process); + resolve(process); } }).catch(reject); @@ -100,10 +150,56 @@ export default class CustomerService { const newStateId: string = processUpdated.diffs[0]?.state_id; this.messageBus.notifyUpdate(process.processId, newStateId).then(() => { this.messageBus.validateState(process.processId, newStateId).then((_stateValidated) => { - resolve(); + const customerUid: string = process.processData.uid; + this.removeCache(customerUid); + + this.getCustomerByUid(customerUid).then(resolve).catch(reject); }).catch(reject); }).catch(reject); }).catch(reject); }); } + + private static setCache(process: any): void { + const key: string = '_customers_'; + + const customers: any[] = JSON.parse(sessionStorage.getItem(key) || '[]'); + const index: number = customers.findIndex((customer: any) => customer.process.processData.uid === process.processData.uid); + if (index !== -1) { + customers[index] = { + process: process, + timestamp: Date.now() + }; + } else { + customers.push({ + process: process, + timestamp: Date.now() + }); + } + + sessionStorage.setItem(key, JSON.stringify(customers)); + } + + private static getCache(uid: string): any { + const key: string = '_customers_'; + + const customers: any[] = JSON.parse(sessionStorage.getItem(key) || '[]'); + if (customers.length === 0) { + return null; + } + + return customers.find((customer: any) => customer.process.processData.uid === uid); + } + + private static removeCache(uid: string): void { + const key: string = '_customers_'; + + const customers: any[] = JSON.parse(sessionStorage.getItem(key) || '[]'); + const index: number = customers.findIndex((customer: any) => customer.process.processData.uid === uid); + if (index !== -1) { + customers.splice(index, 1); + } + + sessionStorage.setItem(key, JSON.stringify(customers)); + } } diff --git a/src/common/Api/LeCoffreApi/sdk/DocumentService.ts b/src/common/Api/LeCoffreApi/sdk/DocumentService.ts index 987ca689..5546a386 100644 --- a/src/common/Api/LeCoffreApi/sdk/DocumentService.ts +++ b/src/common/Api/LeCoffreApi/sdk/DocumentService.ts @@ -7,6 +7,8 @@ export default class DocumentService { private static readonly messageBus: MessageBus = MessageBus.getInstance(); + private static readonly CACHE_TTL = 5 * 60 * 1000; // 5 minutes cache TTL + private constructor() { } public static createDocument(documentData: any, validatorId: string): Promise { @@ -70,7 +72,7 @@ export default class DocumentService { 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); + this.getDocumentByUid(processCreated.processData.uid).then(resolve).catch(reject); }).catch(reject); }).catch(reject); }).catch(reject); @@ -78,16 +80,64 @@ export default class DocumentService { } public static getDocuments(): Promise { - return this.messageBus.getProcessesDecoded((publicValues: any) => publicValues['uid'] && publicValues['utype'] && publicValues['utype'] === 'document' && publicValues['isDeleted'] && publicValues['isDeleted'] === 'false'); + // Check if we have valid cache + const cacheProcesses: any[] = []; + const now = Date.now(); + const customers: any[] = JSON.parse(sessionStorage.getItem('_documents') || '[]'); + for (const customer of customers) { + if (now - customer.timestamp < this.CACHE_TTL) { + cacheProcesses.push(customer.process); + } + } + const cacheUids: string[] = cacheProcesses.map((process: any) => process.processData.uid); + + return this.messageBus.getProcessesDecoded((publicValues: any) => + publicValues['uid'] && + publicValues['utype'] && + publicValues['utype'] === 'document' && + publicValues['isDeleted'] && + publicValues['isDeleted'] === 'false' && + !cacheUids.includes(publicValues['uid']) + ).then((processes: any[]) => { + if (processes.length === 0) { + return cacheProcesses; + } else { + for (const process of processes) { + // Update cache + this.setCache(process); + + cacheProcesses.push(process); + } + return cacheProcesses; + } + }); } public static getDocumentByUid(uid: string): Promise { + // Check if we have valid cache + const now = Date.now(); + const cache: any = this.getCache(uid); + if (cache && (now - cache.timestamp) < this.CACHE_TTL) { + return Promise.resolve(cache.process); + } + 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'] === 'document' && publicValues['isDeleted'] && publicValues['isDeleted'] === 'false').then((processes: any[]) => { + this.messageBus.getProcessesDecoded((publicValues: any) => + publicValues['uid'] && + publicValues['uid'] === uid && + publicValues['utype'] && + publicValues['utype'] === 'document' && + publicValues['isDeleted'] && + publicValues['isDeleted'] === 'false' + ).then((processes: any[]) => { if (processes.length === 0) { resolve(null); } else { const process: any = processes[0]; + + // Update cache + this.setCache(process); + resolve(process); } }).catch(reject); @@ -100,10 +150,56 @@ export default class DocumentService { const newStateId: string = processUpdated.diffs[0]?.state_id; this.messageBus.notifyUpdate(process.processId, newStateId).then(() => { this.messageBus.validateState(process.processId, newStateId).then((_stateValidated) => { - resolve(); + const documentUid: string = process.processData.uid; + this.removeCache(documentUid); + + this.getDocumentByUid(documentUid).then(resolve).catch(reject); }).catch(reject); }).catch(reject); }).catch(reject); }); } + + private static setCache(process: any): void { + const key: string = '_documents_'; + + const documents: any[] = JSON.parse(sessionStorage.getItem(key) || '[]'); + const index: number = documents.findIndex((document: any) => document.process.processData.uid === process.processData.uid); + if (index !== -1) { + documents[index] = { + process: process, + timestamp: Date.now() + }; + } else { + documents.push({ + process: process, + timestamp: Date.now() + }); + } + + sessionStorage.setItem(key, JSON.stringify(documents)); + } + + private static getCache(uid: string): any { + const key: string = '_documents_'; + + const documents: any[] = JSON.parse(sessionStorage.getItem(key) || '[]'); + if (documents.length === 0) { + return null; + } + + return documents.find((document: any) => document.process.processData.uid === uid); + } + + private static removeCache(uid: string): void { + const key: string = '_documents_'; + + const documents: any[] = JSON.parse(sessionStorage.getItem(key) || '[]'); + const index: number = documents.findIndex((document: any) => document.process.processData.uid === uid); + if (index !== -1) { + documents.splice(index, 1); + } + + sessionStorage.setItem(key, JSON.stringify(documents)); + } } diff --git a/src/common/Api/LeCoffreApi/sdk/FolderService.ts b/src/common/Api/LeCoffreApi/sdk/FolderService.ts index e8e49afb..c19d73ac 100644 --- a/src/common/Api/LeCoffreApi/sdk/FolderService.ts +++ b/src/common/Api/LeCoffreApi/sdk/FolderService.ts @@ -10,6 +10,8 @@ export default class FolderService { private static readonly messageBus: MessageBus = MessageBus.getInstance(); + private static readonly CACHE_TTL = 5 * 60 * 1000; // 5 minutes cache TTL + private constructor() { } public static createFolder(folderData: any, stakeholdersId: string[], customersId: string[]): Promise { @@ -79,7 +81,7 @@ export default class FolderService { 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); + this.getFolderByUid(processCreated.processData.uid).then(resolve).catch(reject); }).catch(reject); }).catch(reject); }).catch(reject); @@ -87,34 +89,66 @@ export default class FolderService { } public static getFolders(): Promise { - return this.messageBus.getProcessesDecoded((publicValues: any) => publicValues['uid'] && publicValues['utype'] && publicValues['utype'] === 'folder' && publicValues['isDeleted'] && publicValues['isDeleted'] === 'false'); + // Check if we have valid cache + const cacheProcesses: any[] = []; + const now = Date.now(); + const folders: any[] = JSON.parse(sessionStorage.getItem('_folders_') || '[]'); + for (const folder of folders) { + if (now - folder.timestamp < this.CACHE_TTL) { + cacheProcesses.push(folder.process); + } + } + const cacheUids: string[] = cacheProcesses.map((process: any) => process.processData.uid); + + return this.messageBus.getProcessesDecoded((publicValues: any) => + publicValues['uid'] && + publicValues['utype'] && + publicValues['utype'] === 'folder' && + publicValues['isDeleted'] && + publicValues['isDeleted'] === 'false' && + !cacheUids.includes(publicValues['uid']) + ).then(async (processes: any[]) => { + if (processes.length === 0) { + return cacheProcesses; + } else { + for (const process of processes) { + await this.completeFolder(process); + + // Update cache + this.setCache(process); + + cacheProcesses.push(process); + } + return cacheProcesses; + } + }); } - public static getFolderByUid(uid: string, includeCustomers: boolean = true, includeDeedType: boolean = true): Promise { + public static getFolderByUid(uid: string): Promise { + // Check if we have valid cache + const now = Date.now(); + const cache: any = this.getCache(uid); + if (cache && (now - cache.timestamp) < this.CACHE_TTL) { + return Promise.resolve(cache.process); + } + 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'] === 'folder' && publicValues['isDeleted'] && publicValues['isDeleted'] === 'false').then(async (processes: any[]) => { + this.messageBus.getProcessesDecoded((publicValues: any) => + publicValues['uid'] && + publicValues['uid'] === uid && + publicValues['utype'] && + publicValues['utype'] === 'folder' && + publicValues['isDeleted'] && + publicValues['isDeleted'] === 'false' + ).then(async (processes: any[]) => { if (processes.length === 0) { resolve(null); } else { const process: any = processes[0]; + await this.completeFolder(process); - if (includeCustomers && process.processData.customers && process.processData.customers.length > 0) { - process.processData.customers = await new Promise(async (resolve: (customers: any[]) => void) => { - const customers: any[] = []; - for (const uid of process.processData.customers) { - const p: any = await CustomerService.getCustomerByUid(uid); - customers.push(p.processData); - } - resolve(customers); - }); - } - - if (includeDeedType && process.processData.deed && process.processData.deed.deed_type) { - const p: any = await DeedTypeService.getDeedTypeByUid(process.processData.deed.deed_type.uid); - process.processData.deed.deed_type = p.processData; - // Remove duplicates - process.processData.deed.document_types = p.processData.document_types.filter((item: any, index: number) => p.processData.document_types.findIndex((t: any) => t.uid === item.uid) === index); - } + // Update cache + this.setCache(process); resolve(process); } @@ -128,10 +162,81 @@ export default class FolderService { const newStateId: string = processUpdated.diffs[0]?.state_id; this.messageBus.notifyUpdate(process.processId, newStateId).then(() => { this.messageBus.validateState(process.processId, newStateId).then((_stateValidated) => { - resolve(); + const folderUid: string = process.processData.uid; + this.removeCache(folderUid); + + this.getFolderByUid(folderUid).then(resolve).catch(reject); }).catch(reject); }).catch(reject); }).catch(reject); }); } + + private static async completeFolder(process: any): Promise { + if (process.processData.customers && process.processData.customers.length > 0) { + process.processData.customers = await new Promise(async (resolve: (customers: any[]) => void) => { + const customers: any[] = []; + for (const customer of process.processData.customers) { + const p: any = await CustomerService.getCustomerByUid(customer.uid); + customers.push(p.processData); + } + resolve(customers); + }); + } + + if (process.processData.deed && process.processData.deed.deed_type) { + const p: any = await DeedTypeService.getDeedTypeByUid(process.processData.deed.deed_type.uid); + process.processData.deed.deed_type = p.processData; + + // Remove duplicates + if (p.processData.document_types && p.processData.document_types.length > 0) { + process.processData.deed.document_types = p.processData.document_types.filter((item: any, index: number) => p.processData.document_types.findIndex((t: any) => t.uid === item.uid) === index); + } + } + + return process; + } + + private static setCache(process: any): void { + const key: string = '_folders_'; + + const folders: any[] = JSON.parse(sessionStorage.getItem(key) || '[]'); + const index: number = folders.findIndex((folder: any) => folder.process.processData.uid === process.processData.uid); + if (index !== -1) { + folders[index] = { + process: process, + timestamp: Date.now() + }; + } else { + folders.push({ + process: process, + timestamp: Date.now() + }); + } + + sessionStorage.setItem(key, JSON.stringify(folders)); + } + + private static getCache(uid: string): any { + const key: string = '_folders_'; + + const folders: any[] = JSON.parse(sessionStorage.getItem(key) || '[]'); + if (folders.length === 0) { + return null; + } + + return folders.find((folder: any) => folder.process.processData.uid === uid); + } + + private static removeCache(uid: string): void { + const key: string = '_folders_'; + + const folders: any[] = JSON.parse(sessionStorage.getItem(key) || '[]'); + const index: number = folders.findIndex((folder: any) => folder.process.processData.uid === uid); + if (index !== -1) { + folders.splice(index, 1); + } + + sessionStorage.setItem(key, JSON.stringify(folders)); + } } diff --git a/src/front/Api/Auth/IdNot/index.ts b/src/front/Api/Auth/IdNot/index.ts index 4023b179..5cd82e71 100644 --- a/src/front/Api/Auth/IdNot/index.ts +++ b/src/front/Api/Auth/IdNot/index.ts @@ -44,7 +44,7 @@ export default class Auth extends BaseApiService { // const variables = FrontendVariables.getInstance(); // TODO: review - const baseBackUrl = 'http://local.lecoffreio.4nkweb:3001'//variables.BACK_API_PROTOCOL + variables.BACK_API_HOST; + const baseBackUrl = 'http://localhost:8080';//variables.BACK_API_PROTOCOL + variables.BACK_API_HOST; const url = new URL(`${baseBackUrl}/api/v1/idnot/user/${autorizationCode}`); try { diff --git a/src/front/Components/LayoutTemplates/DefaultRoleDashboard/index.tsx b/src/front/Components/LayoutTemplates/DefaultRoleDashboard/index.tsx index aaa86b35..8e6215a4 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 { v4 as uuidv4 } from 'uuid'; + import RoleService from "src/common/Api/LeCoffreApi/sdk/RoleService"; type IProps = IPropsDashboardWithList; @@ -26,10 +28,96 @@ export default function DefaultRoleDashboard(props: IProps) { .then((roles) => setRoles(roles)); */ - RoleService.getRoles().then((processes: any[]) => { + const roles: any[] = [ + { + uid: uuidv4(), + name: 'Notaire', + office: { + name: '', + crpcen: '', + created_at: new Date(), + updated_at: new Date() + }, + rules: [ + { + uid: uuidv4(), + name: "Gestion de l'abonnement", + label: "Gestion de l'abonnement", + namespace: "Gestion de l'abonnement", + created_at: new Date(), + updated_at: new Date() + }, + { + uid: uuidv4(), + name: "Gestion des matrices d'actes et des documents", + label: "Gestion des matrices d'actes et des documents", + namespace: "Gestion des matrices d'actes et des documents", + created_at: new Date(), + updated_at: new Date() + }, + { + uid: uuidv4(), + name: "Intégration du RIB", + label: "Intégration du RIB", + namespace: "Intégration du RIB", + created_at: new Date(), + updated_at: new Date() + } + ], + created_at: new Date(), + updated_at: new Date(), + }, + { + uid: uuidv4(), + name: 'Collaborateur', + office: { + name: '', + crpcen: '', + created_at: new Date(), + updated_at: new Date() + }, + rules: [ + { + uid: uuidv4(), + name: "Gestion de l'abonnement", + label: "Gestion de l'abonnement", + namespace: "Gestion de l'abonnement", + created_at: new Date(), + updated_at: new Date() + }, + { + uid: uuidv4(), + name: "Gestion des matrices d'actes et des documents", + label: "Gestion des matrices d'actes et des documents", + namespace: "Gestion des matrices d'actes et des documents", + created_at: new Date(), + updated_at: new Date() + }, + { + uid: uuidv4(), + name: "Intégration du RIB", + label: "Intégration du RIB", + namespace: "Intégration du RIB", + created_at: new Date(), + updated_at: new Date() + } + ], + created_at: new Date(), + updated_at: new Date(), + } + ]; + + RoleService.getRoles().then(async (processes: any[]) => { if (processes.length > 0) { const roles: any[] = processes.map((process: any) => process.processData); setRoles(roles); + } else { + for (let role of roles) { + const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0'; + + await RoleService.createRole(role, validatorId); + } + setRoles(roles); } }); }, []); diff --git a/src/front/Components/Layouts/ClientDashboard/ViewDocumentsNotary/index.tsx b/src/front/Components/Layouts/ClientDashboard/ViewDocumentsNotary/index.tsx index 22cb4ba4..b9cf69df 100644 --- a/src/front/Components/Layouts/ClientDashboard/ViewDocumentsNotary/index.tsx +++ b/src/front/Components/Layouts/ClientDashboard/ViewDocumentsNotary/index.tsx @@ -30,7 +30,7 @@ type IState = { refuseText: string; selectedFileIndex: number; selectedFile: { uid: string; file_name: string; file_blob: FileBlob } | null; - documentNotary: DocumentNotary | null; + documentNotary: any | null; fileBlob: Blob | null; isLoading: boolean; }; @@ -168,7 +168,7 @@ class ViewDocumentsNotaryClass extends BasePage { private async getFilePreview(): Promise { try { - const fileBlob: Blob = new Blob([this.state.selectedFile.file_blob.data], { type: this.state.selectedFile.file_blob.type }); + const fileBlob: Blob = new Blob([this.state.selectedFile!.file_blob.data], { type: this.state.selectedFile!.file_blob.type }); this.setState({ fileBlob, }); diff --git a/src/front/Components/Layouts/DeedTypes/DeedTypesCreate/index.tsx b/src/front/Components/Layouts/DeedTypes/DeedTypesCreate/index.tsx index 96a68be9..c93c3507 100644 --- a/src/front/Components/Layouts/DeedTypes/DeedTypesCreate/index.tsx +++ b/src/front/Components/Layouts/DeedTypes/DeedTypesCreate/index.tsx @@ -60,12 +60,12 @@ export default function DeedTypesCreate(props: IProps) { title: "Succès !", description: "Type d'acte créé avec succès" }); - setTimeout(() => LoaderService.getInstance().hide(), 2000); router.push( Module.getInstance() .get() .modules.pages.DeedTypes.pages.DeedTypesInformations.props.path.replace("[uid]", processCreated.processData.uid), ); + LoaderService.getInstance().hide(); }); } catch (validationErrors: Array | any) { setValidationError(validationErrors as ValidationError[]); diff --git a/src/front/Components/Layouts/DeedTypes/DeedTypesEdit/index.tsx b/src/front/Components/Layouts/DeedTypes/DeedTypesEdit/index.tsx index 064509a3..be9d649d 100644 --- a/src/front/Components/Layouts/DeedTypes/DeedTypesEdit/index.tsx +++ b/src/front/Components/Layouts/DeedTypes/DeedTypesEdit/index.tsx @@ -36,7 +36,7 @@ export default function DeedTypesEdit() { const deedType: any = process.processData; setDeedTypeSelected(deedType); } - setTimeout(() => LoaderService.getInstance().hide(), 2000); + LoaderService.getInstance().hide(); }); } @@ -66,12 +66,12 @@ export default function DeedTypesEdit() { 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), ); + LoaderService.getInstance().hide(); }); } }); diff --git a/src/front/Components/Layouts/DeedTypes/DeedTypesInformations/index.tsx b/src/front/Components/Layouts/DeedTypes/DeedTypesInformations/index.tsx index 778758f7..f7cc77f0 100644 --- a/src/front/Components/Layouts/DeedTypes/DeedTypesInformations/index.tsx +++ b/src/front/Components/Layouts/DeedTypes/DeedTypesInformations/index.tsx @@ -55,8 +55,8 @@ export default function DeedTypesInformations(props: IProps) { 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); + LoaderService.getInstance().hide(); }); } }); @@ -119,7 +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); + LoaderService.getInstance().hide(); closeSaveModal(); }); } diff --git a/src/front/Components/Layouts/DocumentTypes/DocumentTypesCreate/index.tsx b/src/front/Components/Layouts/DocumentTypes/DocumentTypesCreate/index.tsx index eba9773d..1a8d38ce 100644 --- a/src/front/Components/Layouts/DocumentTypes/DocumentTypesCreate/index.tsx +++ b/src/front/Components/Layouts/DocumentTypes/DocumentTypesCreate/index.tsx @@ -53,12 +53,12 @@ export default function DocumentTypesCreate(props: IProps) { title: "Succès !", description: "Type de document créé avec succès" }); - setTimeout(() => LoaderService.getInstance().hide(), 2000); router.push( Module.getInstance() .get() .modules.pages.DocumentTypes.pages.DocumentTypesInformations.props.path.replace("[uid]", processCreated.processData.uid), ); + LoaderService.getInstance().hide(); }); } catch (e) { if (e instanceof Array) { diff --git a/src/front/Components/Layouts/DocumentTypes/DocumentTypesEdit/index.tsx b/src/front/Components/Layouts/DocumentTypes/DocumentTypesEdit/index.tsx index 3fe6de1b..bf17ef91 100644 --- a/src/front/Components/Layouts/DocumentTypes/DocumentTypesEdit/index.tsx +++ b/src/front/Components/Layouts/DocumentTypes/DocumentTypesEdit/index.tsx @@ -31,7 +31,7 @@ export default function DocumentTypesEdit() { const documentType: any = process.processData; setDocumentTypeSelected(documentType); } - setTimeout(() => LoaderService.getInstance().hide(), 2000); + LoaderService.getInstance().hide(); }); } @@ -56,7 +56,6 @@ export default function DocumentTypesEdit() { 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() @@ -65,6 +64,7 @@ export default function DocumentTypesEdit() { documentTypeUid as string ?? "", ) ); + LoaderService.getInstance().hide(); }); } }); diff --git a/src/front/Components/Layouts/Folder/AddClientToFolder/index.tsx b/src/front/Components/Layouts/Folder/AddClientToFolder/index.tsx index 358cc6c1..ae2f53c3 100644 --- a/src/front/Components/Layouts/Folder/AddClientToFolder/index.tsx +++ b/src/front/Components/Layouts/Folder/AddClientToFolder/index.tsx @@ -82,21 +82,21 @@ export default function AddClientToFolder(props: IProps) { LoaderService.getInstance().show(); CustomerService.createCustomer(customerData, validatorId).then((processCreated: any) => { - FolderService.getFolderByUid(folderUid as string, false, false).then((process: any) => { + FolderService.getFolderByUid(folderUid as string).then((process: any) => { if (process) { - let customers: any[] = process.processData.customers; - if (!customers) { - customers = []; + const customers: any[] = []; + for (const customerUid of process.processData.customers.map((customer: any) => customer.uid)) { + customers.push({ uid: customerUid }); } - customers.push(processCreated.processData.uid); + customers.push({ uid: processCreated.processData.uid }); FolderService.updateFolder(process, { customers: customers }).then(() => { - ToasterService.getInstance().success({ - title: "Succès !", - description: "Client ajouté avec succès au dossier" + ToasterService.getInstance().success({ + title: "Succès !", + description: "Client ajouté avec succès au dossier" }); - setTimeout(() => LoaderService.getInstance().hide(), 2000); router.push(`/folders/${folderUid}`); + LoaderService.getInstance().hide(); }); } }); @@ -108,17 +108,20 @@ export default function AddClientToFolder(props: IProps) { } } else { LoaderService.getInstance().show(); - FolderService.getFolderByUid(folderUid as string, false, false).then((process: any) => { + FolderService.getFolderByUid(folderUid as string).then((process: any) => { if (process) { - const customers: any[] = customersToLink.map((customer: any) => customer.uid); + const customers: any[] = []; + for (const customerUid of customersToLink.map((customer: any) => customer.uid)) { + customers.push({ uid: customerUid }); + } 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" + 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}`); + LoaderService.getInstance().hide(); }); } }); diff --git a/src/front/Components/Layouts/Folder/AskDocuments/index.tsx b/src/front/Components/Layouts/Folder/AskDocuments/index.tsx index 0828bfa1..5805598e 100644 --- a/src/front/Components/Layouts/Folder/AskDocuments/index.tsx +++ b/src/front/Components/Layouts/Folder/AskDocuments/index.tsx @@ -18,7 +18,6 @@ import backgroundImage from "@Assets/images/background_refonte.svg"; import FolderService from "src/common/Api/LeCoffreApi/sdk/FolderService"; import DocumentService from "src/common/Api/LeCoffreApi/sdk/DocumentService"; import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService"; -import { DocumentData } from "../FolderInformation/ClientView/DocumentTables/types"; export default function AskDocuments() { const router = useRouter(); @@ -65,7 +64,7 @@ export default function AskDocuments() { for (let i = 0; i < documentAsked.length; i++) { const documentTypeUid = documentAsked[i]; if (!documentTypeUid) continue; - + const documentData: any = { folder: { uid: folderUid as string, @@ -106,7 +105,7 @@ export default function AskDocuments() { // If those UIDs are already asked, filter them to not show them in the list and only // show the documents that are not asked yet - const documentTypes = folder.deed!.document_types!.filter((documentType) => { + const documentTypes = folder.deed?.document_types?.filter((documentType) => { if (userDocumentTypesUids.includes(documentType!.uid!)) return false; return true; }); diff --git a/src/front/Components/Layouts/Folder/CreateFolder/index.tsx b/src/front/Components/Layouts/Folder/CreateFolder/index.tsx index e41a625d..f1bdf7ba 100644 --- a/src/front/Components/Layouts/Folder/CreateFolder/index.tsx +++ b/src/front/Components/Layouts/Folder/CreateFolder/index.tsx @@ -103,9 +103,9 @@ export default function CreateFolder(): JSX.Element { title: "Succès !", description: "Dossier créé avec succès" }); - setTimeout(() => LoaderService.getInstance().hide(), 2000); const folderUid: string = processCreated.processData.uid; router.push(`/folders/${folderUid}`); + LoaderService.getInstance().hide(); }); } catch (backError) { if (!Array.isArray(backError)) return; diff --git a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/DocumentTables/index.tsx b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/DocumentTables/index.tsx index 8776d020..526420c3 100644 --- a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/DocumentTables/index.tsx +++ b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/DocumentTables/index.tsx @@ -64,12 +64,6 @@ export default function DocumentTables(props: IProps) { // FilterBy folder.uid & depositor.uid documents = documents.filter((document: any) => document.folder.uid === folderUid && document.depositor && document.depositor.uid === customerUid); - console.log('[DocumentTables] fetchDocuments: all documents for this folder/customer:', documents.map(doc => ({ - uid: doc.uid, - status: doc.document_status, - type: doc.document_type?.name - }))); - for (const document of documents) { if (document.document_type) { document.document_type = (await DocumentTypeService.getDocumentTypeByUid(document.document_type.uid)).processData; @@ -187,7 +181,6 @@ export default function DocumentTables(props: IProps) { const onDownloadCertificate = useCallback(async (doc: any) => { try { - console.log('[DocumentTables] onDownloadCertificate: doc', doc); const certificateData: CertificateData = { customer: { firstName: doc.depositor.first_name || doc.depositor.firstName || "N/A", @@ -221,14 +214,12 @@ export default function DocumentTables(props: IProps) { // Process only the files for this specific document for (const file of documentProcess.processData.files) { const fileProcess = await FileService.getFileByUid(file.uid); - console.log('[DocumentTables] onDownloadCertificate: fileProcess', fileProcess); - + const hash = fileProcess.lastUpdatedFileState.pcd_commitment.file_blob; certificateData.documentHash = hash; const proof = await MessageBus.getInstance().generateMerkleProof(fileProcess.lastUpdatedFileState, 'file_blob'); - console.log('[DocumentTables] onDownloadCertificate: proof', proof); - + const metadata: Metadata = { fileName: fileProcess.processData.file_name, isDeleted: false, @@ -241,8 +232,6 @@ export default function DocumentTables(props: IProps) { }; certificateData.metadata = metadata; } - - console.log('[DocumentTables] onDownloadCertificate: certificateData', certificateData); await PdfService.getInstance().downloadCertificate(certificateData); } catch (error) { @@ -381,7 +370,7 @@ export default function DocumentTables(props: IProps) { }; }) .filter((document) => document !== null) as IRowProps[]; - + return validated; }, [documents, folderUid, onDownload, onDownloadCertificate], diff --git a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/index.tsx b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/index.tsx index 61677356..a6de0584 100644 --- a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/index.tsx +++ b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/index.tsx @@ -64,7 +64,7 @@ export default function ClientView(props: IProps) { (customerUid: string) => { if (!folder.uid) return; LoaderService.getInstance().show(); - FolderService.getFolderByUid(folder.uid, false, false).then((process: any) => { + FolderService.getFolderByUid(folder.uid).then((process: any) => { if (process) { const folder: any = process.processData; @@ -72,7 +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); + LoaderService.getInstance().hide(); 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 ec0958e6..197325c0 100644 --- a/src/front/Components/Layouts/Folder/FolderInformation/NoClientView/DeleteFolderModal/index.tsx +++ b/src/front/Components/Layouts/Folder/FolderInformation/NoClientView/DeleteFolderModal/index.tsx @@ -29,7 +29,7 @@ export default function DeleteFolderModal(props: IProps) { FolderService.getFolderByUid(folder.uid!).then((process: any) => { if (process) { FolderService.updateFolder(process, { isDeleted: 'true' }).then(() => { - setTimeout(() => LoaderService.getInstance().hide(), 2000); + LoaderService.getInstance().hide(); resolve(); }); } diff --git a/src/front/Components/Layouts/Folder/FolderInformation/index.tsx b/src/front/Components/Layouts/Folder/FolderInformation/index.tsx index e2cb8518..dfeadf48 100644 --- a/src/front/Components/Layouts/Folder/FolderInformation/index.tsx +++ b/src/front/Components/Layouts/Folder/FolderInformation/index.tsx @@ -109,7 +109,6 @@ 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; @@ -143,7 +142,6 @@ 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 1272a6a3..2408227a 100644 --- a/src/front/Components/Layouts/Folder/UpdateClient/index.tsx +++ b/src/front/Components/Layouts/Folder/UpdateClient/index.tsx @@ -41,7 +41,7 @@ export default function UpdateClient() { if (process) { const customer: any = process.processData; setCustomer(customer); - setTimeout(() => LoaderService.getInstance().hide(), 2000); + LoaderService.getInstance().hide(); } }); } catch (error) { @@ -77,8 +77,8 @@ export default function UpdateClient() { if (process) { // TODO: review - address CustomerService.updateCustomer(process, { contact: contact }).then(() => { - setTimeout(() => LoaderService.getInstance().hide(), 2000); router.push(backwardPath); + LoaderService.getInstance().hide(); }); } }); diff --git a/src/front/Components/Layouts/Folder/UpdateFolderMetadata/index.tsx b/src/front/Components/Layouts/Folder/UpdateFolderMetadata/index.tsx index 163d7197..a995c32a 100644 --- a/src/front/Components/Layouts/Folder/UpdateFolderMetadata/index.tsx +++ b/src/front/Components/Layouts/Folder/UpdateFolderMetadata/index.tsx @@ -54,10 +54,10 @@ export default function UpdateFolderMetadata() { 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)); + LoaderService.getInstance().hide(); }); } }); @@ -75,7 +75,7 @@ export default function UpdateFolderMetadata() { if (process) { const folder: any = process.processData; setSelectedFolder(folder); - setTimeout(() => LoaderService.getInstance().hide(), 2000); + LoaderService.getInstance().hide(); } }); }, [folderUid]); diff --git a/src/front/Components/Layouts/Roles/RolesCreate/index.tsx b/src/front/Components/Layouts/Roles/RolesCreate/index.tsx index 1ed07e3a..7a7694ea 100644 --- a/src/front/Components/Layouts/Roles/RolesCreate/index.tsx +++ b/src/front/Components/Layouts/Roles/RolesCreate/index.tsx @@ -64,9 +64,9 @@ export default function RolesCreate(props: IProps) { 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!)); + LoaderService.getInstance().hide(); } }); diff --git a/src/front/Components/Layouts/Roles/RolesInformations/index.tsx b/src/front/Components/Layouts/Roles/RolesInformations/index.tsx index 490908a6..d186a6c0 100644 --- a/src/front/Components/Layouts/Roles/RolesInformations/index.tsx +++ b/src/front/Components/Layouts/Roles/RolesInformations/index.tsx @@ -57,7 +57,7 @@ export default function RolesInformations() { if (process) { const role: any = process.processData; resolve(role); - setTimeout(() => LoaderService.getInstance().hide(), 2000); + LoaderService.getInstance().hide(); } }); }) @@ -69,6 +69,8 @@ export default function RolesInformations() { }, }); */ + + /* const rulesGroups: RulesGroup[] = [ { uid: 'toto', @@ -87,12 +89,14 @@ export default function RolesInformations() { 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: any) => r.uid === rule.uid))) { @@ -106,6 +110,8 @@ export default function RolesInformations() { const selectAll = rulesCheckboxes.every((rule) => rule.checked); setSelectAll(selectAll); setRulesGroupsCheckboxes(rulesCheckboxes); + */ + setRulesGroupsCheckboxes(role.rules); } getUser(); diff --git a/src/front/Services/PdfService/index.ts b/src/front/Services/PdfService/index.ts index 24533913..fcfa0eb3 100644 --- a/src/front/Services/PdfService/index.ts +++ b/src/front/Services/PdfService/index.ts @@ -19,7 +19,7 @@ export interface Metadata { fileName: string, createdAt: Date, isDeleted: boolean, - updatedAt: Date, + updatedAt: Date, commitmentId: string, documentUid: string; documentType: string; @@ -247,14 +247,14 @@ export default class PdfService { private splitTextToFit(font: any, text: string, maxWidth: number, fontSize: number): string[] { const lines: string[] = []; let currentLine = ''; - + // Split by characters (pdf-lib doesn't have word-level text measurement) const chars = text.split(''); - + for (const char of chars) { const testLine = currentLine + char; const testWidth = font.widthOfTextAtSize(testLine, fontSize); - + if (testWidth <= maxWidth) { currentLine = testLine; } else { @@ -267,11 +267,11 @@ export default class PdfService { } } } - + if (currentLine) { lines.push(currentLine); } - + return lines; } @@ -296,12 +296,10 @@ export default class PdfService { * @param pdfBlob - The PDF file as a blob * @returns Promise<{documentHash: string, documentUid: string, commitmentId: string, merkleProof?: string}> - Extracted information */ - public async parseCertificate(certificateFile: File): Promise<{documentHash: string, commitmentId: string, merkleProof: any}> { + public async parseCertificate(certificateFile: File): Promise<{ documentHash: string, commitmentId: string, merkleProof: any }> { return new Promise((resolve, reject) => { const fileReader = new FileReader(); - console.log("certificateFile", certificateFile); - fileReader.onload = async () => { try { // Read the metadata and get the validation data from the keywords @@ -312,8 +310,6 @@ export default class PdfService { throw new Error("No keywords found in certificate"); } - console.log(keywords); - if (keywords.length !== 3) { throw new Error("Invalid keywords found in certificate"); } @@ -326,20 +322,15 @@ export default class PdfService { throw new Error("Invalid keywords found in certificate"); } - console.log("documentHash", documentHash); - console.log("commitmentId", commitmentId); - console.log("merkleProof", merkleProof); - - resolve({ documentHash, commitmentId, merkleProof }); } catch (error) { reject(error); } }; - + fileReader.onerror = () => { reject(new Error('Failed to read PDF file')); - }; + }; fileReader.readAsArrayBuffer(certificateFile); }); diff --git a/src/front/Services/WatermarkService/index.ts b/src/front/Services/WatermarkService/index.ts index b7dcf66a..ebfc8ff5 100644 --- a/src/front/Services/WatermarkService/index.ts +++ b/src/front/Services/WatermarkService/index.ts @@ -15,7 +15,7 @@ export default class WatermarkService { */ public async addWatermark(file: File): Promise { const fileType = file.type; - + try { if (fileType.startsWith('image/')) { return await this.addWatermarkToImage(file); @@ -23,7 +23,7 @@ export default class WatermarkService { return await this.addWatermarkToPdf(file); } else { // For other file types, return the original file - console.log(`Watermark not supported for file type: ${fileType}`); + console.warn(`Watermark not supported for file type: ${fileType}`); return file; } } catch (error) { @@ -49,22 +49,22 @@ export default class WatermarkService { // Create canvas const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); - + if (!ctx) { reject(new Error('Could not get canvas context')); return; } - + // Set canvas size to image size canvas.width = img.width; canvas.height = img.height; - + // Draw original image ctx.drawImage(img, 0, 0); - + // Add watermark this.addImageWatermark(ctx, img.width, img.height); - + // Convert to blob canvas.toBlob((blob) => { if (blob) { @@ -100,26 +100,26 @@ export default class WatermarkService { reader.onload = async (event) => { try { const arrayBuffer = event.target?.result as ArrayBuffer; - + // Import pdf-lib dynamically to avoid SSR issues const { PDFDocument, rgb } = await import('pdf-lib'); - + // Load the existing PDF const pdfDoc = await PDFDocument.load(arrayBuffer); - + // Get all pages const pages = pdfDoc.getPages(); - + // Add watermark to each page for (const page of pages) { this.addPdfWatermark(page, rgb(0.8, 0.2, 0.2)); // Pale red color } - + // Save the modified PDF const pdfBytes = await pdfDoc.save(); const watermarkedFile = new File([pdfBytes], file.name, { type: file.type }); resolve(watermarkedFile); - + } catch (error) { console.error('Error adding watermark to PDF:', error); // If PDF watermarking fails, return original file @@ -140,21 +140,21 @@ export default class WatermarkService { private addImageWatermark(ctx: CanvasRenderingContext2D, width: number, height: number): void { // Save current state ctx.save(); - + // Set watermark properties ctx.fillStyle = 'rgba(128, 128, 128, 0.7)'; // Semi-transparent gray ctx.font = '12px Arial'; ctx.textAlign = 'right'; ctx.textBaseline = 'bottom'; - + // Position watermark in bottom-right corner const text = 'Processed by LeCoffre'; const x = width - 10; // 10 pixels from right edge const y = height - 10; // 10 pixels from bottom - + // Add watermark text ctx.fillText(text, x, y); - + // Restore state ctx.restore(); } @@ -166,7 +166,7 @@ export default class WatermarkService { */ private addPdfWatermark(page: any, color: any): void { const { width, height } = page.getSize(); - + // Calculate watermark position (bottom-right corner) const text = 'Processed by LeCoffre'; const dateTime = new Date().toLocaleString('fr-FR', { @@ -176,20 +176,20 @@ export default class WatermarkService { hour: '2-digit', minute: '2-digit' }); - + const fontSize = 10; const lineHeight = 12; // Space between lines - + // Calculate text widths (approximate - pdf-lib doesn't have a direct method for this) // Using a conservative estimate: ~6 points per character for 10pt font const estimatedTextWidth1 = text.length * 6; const estimatedTextWidth2 = dateTime.length * 6; const maxTextWidth = Math.max(estimatedTextWidth1, estimatedTextWidth2); - + // Position watermark with proper margins (20 points from edges) const x = width - maxTextWidth - 20; // 20 points from right edge const y = 20; // 20 points from bottom - + // Add watermark text with transparency (first line) page.drawText(text, { x: x, @@ -198,7 +198,7 @@ export default class WatermarkService { color: color, opacity: 0.7 }); - + // Add date/time with transparency (second line) page.drawText(dateTime, { x: x, diff --git a/src/sdk/MessageBus.ts b/src/sdk/MessageBus.ts index 4a6ffe31..b75165d3 100644 --- a/src/sdk/MessageBus.ts +++ b/src/sdk/MessageBus.ts @@ -6,6 +6,7 @@ import EventBus from './EventBus'; import User from './User'; import MapUtils from './MapUtils'; + import { FileBlob } from '../front/Api/Entities/types'; export default class MessageBus { @@ -768,9 +769,6 @@ export default class MessageBus { console.error('[MessageBus] sendMessage: iframe not found'); return; } - if (message.type === 'VALIDATE_MERKLE_PROOF') { - console.log('[MessageBus] sendMessage:', message); - } iframe.contentWindow?.postMessage(message, targetOrigin); } @@ -807,8 +805,6 @@ export default class MessageBus { } const message = event.data; - // console.log('[MessageBus] handleMessage:', message); - switch (message.type) { case 'LISTENING': this.isListening = true;