From 6b09941e2893baf00fceb44e7218e664eb446818 Mon Sep 17 00:00:00 2001 From: Anthony Janin Date: Wed, 23 Jul 2025 12:10:10 +0200 Subject: [PATCH] Fix some issues --- .../LeCoffreApi/sdk/CollaboratorService.ts | 57 ++++- .../Api/LeCoffreApi/sdk/CustomerService.ts | 4 +- src/common/Api/LeCoffreApi/sdk/FileService.ts | 1 + .../Api/LeCoffreApi/sdk/FolderService.ts | 38 ++- .../Api/LeCoffreApi/sdk/OfficeRibService.ts | 98 ++++++++ .../Api/LeCoffreApi/sdk/OfficeRoleService.ts | 179 ++++++++++++++ src/common/Api/LeCoffreApi/sdk/RoleService.ts | 10 +- .../Api/LeCoffreApi/sdk/RuleGroupService.ts | 171 +++++++++++++ src/front/Api/BaseApiService.ts | 2 +- .../LeCoffreApi/Notary/Customers/Customers.ts | 9 +- .../DepositOtherDocument/index.tsx | 7 +- src/front/Components/Elements/Rules/index.tsx | 6 + .../DefaultRoleDashboard/index.tsx | 16 +- .../ClientDashboard/ContactBox/index.tsx | 34 +-- .../DepositDocumentComponent/index.tsx | 13 +- .../CollaboratorInformations/index.tsx | 139 ++++------- .../Layouts/Folder/AskDocuments/index.tsx | 14 +- .../Layouts/Folder/CreateFolder/index.tsx | 40 ++- .../ClientView/DocumentTables/index.tsx | 19 +- .../Layouts/Folder/SendDocuments/index.tsx | 6 +- .../Layouts/Folder/ViewDocuments/index.tsx | 59 ++--- .../Layouts/LoginCallback/index.tsx | 233 +++++++++++++++--- src/front/Components/Layouts/Rib/index.tsx | 81 +++++- .../Layouts/Roles/RolesInformations/index.tsx | 162 +++++------- src/sdk/MessageBus.ts | 110 ++++++++- 25 files changed, 1139 insertions(+), 369 deletions(-) create mode 100644 src/common/Api/LeCoffreApi/sdk/OfficeRibService.ts create mode 100644 src/common/Api/LeCoffreApi/sdk/OfficeRoleService.ts create mode 100644 src/common/Api/LeCoffreApi/sdk/RuleGroupService.ts diff --git a/src/common/Api/LeCoffreApi/sdk/CollaboratorService.ts b/src/common/Api/LeCoffreApi/sdk/CollaboratorService.ts index a071141d..76fed7b9 100644 --- a/src/common/Api/LeCoffreApi/sdk/CollaboratorService.ts +++ b/src/common/Api/LeCoffreApi/sdk/CollaboratorService.ts @@ -4,6 +4,10 @@ import User from 'src/sdk/User'; import AbstractService from './AbstractService'; +import OfficeService from './OfficeService'; +import RoleService from './RoleService'; +import OfficeRoleService from './OfficeRoleService'; + export default class CollaboratorService extends AbstractService { private constructor() { @@ -89,11 +93,13 @@ export default class CollaboratorService extends AbstractService { publicValues['isDeleted'] && publicValues['isDeleted'] === 'false' && !items.map((item: any) => item.processData.uid).includes(publicValues['uid']) - ).then((processes: any[]) => { + ).then(async (processes: any[]) => { if (processes.length === 0) { return items; } else { - for (const process of processes) { + for (let process of processes) { + process = await this.completeCollaborator(process); + // Update cache this.setItem('_collaborators_', process); @@ -104,10 +110,10 @@ export default class CollaboratorService extends AbstractService { }); } - public static getCollaboratorByUid(uid: string): Promise { + public static getCollaboratorByUid(uid: string, forceRefresh: boolean = false): Promise { // Check if we have valid cache const item: any = this.getItem('_collaborators_', uid); - if (item) { + if (item && !forceRefresh) { return Promise.resolve(item); } @@ -119,11 +125,12 @@ export default class CollaboratorService extends AbstractService { publicValues['utype'] === 'collaborator' && publicValues['isDeleted'] && publicValues['isDeleted'] === 'false' - ).then((processes: any[]) => { + ).then(async (processes: any[]) => { if (processes.length === 0) { resolve(null); } else { - const process: any = processes[0]; + let process: any = processes[0]; + process = await this.completeCollaborator(process); // Update cache this.setItem('_collaborators_', process); @@ -143,10 +150,46 @@ export default class CollaboratorService extends AbstractService { const collaboratorUid: string = process.processData.uid; this.removeItem('_collaborators_', collaboratorUid); - this.getCollaboratorByUid(collaboratorUid).then(resolve).catch(reject); + this.getCollaboratorByUid(collaboratorUid, true).then(resolve).catch(reject); }).catch(reject); }).catch(reject); }).catch(reject); }); } + + private static async completeCollaborator(process: any): Promise { + if (process.processData.office) { + const office: any = (await OfficeService.getOfficeByUid(process.processData.office.uid)).processData; + process.processData.office = { + uid: office.uid, + idNot: office.idNot, + crpcen: office.crpcen, + office_status: office.office_status + }; + } + + if (process.processData.role) { + const role: any = (await RoleService.getRoleByUid(process.processData.role.uid)).processData; + process.processData.role = { + uid: role.uid, + name: role.name + }; + } + + if (process.processData.office_role) { + const officeRole: any = (await OfficeRoleService.getOfficeRoleByUid(process.processData.office_role.uid)).processData; + process.processData.office_role = { + uid: officeRole.uid, + name: officeRole.name, + rules: officeRole.rules.map((rule: any) => { + return { + uid: rule.uid, + name: rule.name + }; + }) + }; + } + + return process; + } } diff --git a/src/common/Api/LeCoffreApi/sdk/CustomerService.ts b/src/common/Api/LeCoffreApi/sdk/CustomerService.ts index f8841b3c..5fecb25f 100644 --- a/src/common/Api/LeCoffreApi/sdk/CustomerService.ts +++ b/src/common/Api/LeCoffreApi/sdk/CustomerService.ts @@ -80,7 +80,7 @@ export default class CustomerService extends AbstractService { public static getCustomers(): Promise { // Check if we have valid cache - const items: any[] = [];//this.getItems('_customers_'); + const items: any[] = this.getItems('_customers_'); return this.messageBus.getProcessesDecoded((publicValues: any) => publicValues['uid'] && @@ -108,7 +108,7 @@ export default class CustomerService extends AbstractService { // Check if we have valid cache const item: any = this.getItem('_customers_', uid); if (item) { - //return Promise.resolve(item); + return Promise.resolve(item); } return new Promise((resolve: (process: any) => void, reject: (error: string) => void) => { diff --git a/src/common/Api/LeCoffreApi/sdk/FileService.ts b/src/common/Api/LeCoffreApi/sdk/FileService.ts index b6dff078..448f2522 100644 --- a/src/common/Api/LeCoffreApi/sdk/FileService.ts +++ b/src/common/Api/LeCoffreApi/sdk/FileService.ts @@ -2,6 +2,7 @@ import { v4 as uuidv4 } from 'uuid'; import MessageBus from 'src/sdk/MessageBus'; import User from 'src/sdk/User'; + import { FileData } from '../../../../front/Api/Entities/types'; export default class FileService { diff --git a/src/common/Api/LeCoffreApi/sdk/FolderService.ts b/src/common/Api/LeCoffreApi/sdk/FolderService.ts index 458408e8..e5a21fbd 100644 --- a/src/common/Api/LeCoffreApi/sdk/FolderService.ts +++ b/src/common/Api/LeCoffreApi/sdk/FolderService.ts @@ -4,6 +4,7 @@ import User from 'src/sdk/User'; import AbstractService from './AbstractService'; import CustomerService from './CustomerService'; +import CollaboratorService from './CollaboratorService'; import DeedTypeService from './DeedTypeService'; import DocumentTypeService from './DocumentTypeService'; import DocumentService from './DocumentService'; @@ -16,10 +17,6 @@ export default class FolderService extends AbstractService { super(); } - public static invalidateCache(uid: string): void { - this.removeItem('_folders_', uid); - } - public static createFolder(folderData: any, stakeholdersId: string[], customersId: string[]): Promise { const ownerId = User.getInstance().getPairingId()!; @@ -96,7 +93,7 @@ export default class FolderService extends AbstractService { public static getFolders(): Promise { // Check if we have valid cache - const items: any[] = [];//this.getItems('_folders_'); + const items: any[] = this.getItems('_folders_'); return this.messageBus.getProcessesDecoded((publicValues: any) => publicValues['uid'] && @@ -113,7 +110,7 @@ export default class FolderService extends AbstractService { process = await this.completeFolder(process); // Update cache - //this.setItem('_folders_', process); + this.setItem('_folders_', process); items.push(process); } @@ -126,7 +123,7 @@ export default class FolderService extends AbstractService { // Check if we have valid cache const item: any = this.getItem('_folders_', uid); if (item) { - //return Promise.resolve(item); + return Promise.resolve(item); } return new Promise((resolve: (process: any) => void, reject: (error: string) => void) => { @@ -145,7 +142,7 @@ export default class FolderService extends AbstractService { process = await this.completeFolder(process); // Update cache - //this.setItem('_folders_', process); + this.setItem('_folders_', process); resolve(process); } @@ -160,15 +157,23 @@ export default class FolderService extends AbstractService { this.messageBus.notifyUpdate(process.processId, newStateId).then(() => { this.messageBus.validateState(process.processId, newStateId).then((_stateValidated) => { const folderUid: string = process.processData.uid; - //this.removeItem('_folders_', folderUid); + this.removeItem('_folders_', folderUid); - //this.getFolderByUid(folderUid).then(resolve).catch(reject); + this.getFolderByUid(folderUid).then(resolve).catch(reject); }).catch(reject); }).catch(reject); }).catch(reject); }); } + public static refreshFolderByUid(uid: string): Promise { + return new Promise((resolve: () => void, reject: (error: string) => void) => { + this.getFolderByUid(uid).then((process: any) => { + this.updateFolder(process, {}).then(resolve).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) => { @@ -192,8 +197,7 @@ export default class FolderService extends AbstractService { if (document.files && document.files.length > 0) { const files: any[] = []; for (const file of document.files) { - const p: any = await FileService.getFileByUid(file.uid); - files.push({ uid: p.processData.uid, file_name: p.processData.file_name }); + files.push({ uid: file.uid, file_name: (await FileService.getFileByUid(file.uid)).processData.file_name }); } document.files = files; } @@ -202,6 +206,16 @@ export default class FolderService extends AbstractService { } } + if (process.processData.stakeholders && process.processData.stakeholders.length > 0) { + process.processData.stakeholders = await new Promise(async (resolve: (stakeholders: any[]) => void) => { + const stakeholders: any[] = []; + for (const stakeholder of process.processData.stakeholders) { + stakeholders.push((await CollaboratorService.getCollaboratorByUid(stakeholder.uid)).processData); + } + resolve(stakeholders); + }); + } + if (process.processData.deed && process.processData.deed.deed_type) { const deed_type: any = (await DeedTypeService.getDeedTypeByUid(process.processData.deed.deed_type.uid)).processData; process.processData.deed.deed_type = deed_type; diff --git a/src/common/Api/LeCoffreApi/sdk/OfficeRibService.ts b/src/common/Api/LeCoffreApi/sdk/OfficeRibService.ts new file mode 100644 index 00000000..b5475c68 --- /dev/null +++ b/src/common/Api/LeCoffreApi/sdk/OfficeRibService.ts @@ -0,0 +1,98 @@ +import { v4 as uuidv4 } from 'uuid'; + +import MessageBus from 'src/sdk/MessageBus'; +import User from 'src/sdk/User'; + +import { FileData } from '../../../../front/Api/Entities/types'; + +export default class OfficeRibService { + + private static readonly messageBus: MessageBus = MessageBus.getInstance(); + + private constructor() { } + + public static createOfficeRib(fileData: FileData, validatorId: string): Promise { + const ownerId = User.getInstance().getPairingId()!; + + const processData: any = { + uid: uuidv4(), + utype: 'officeRib', + isDeleted: 'false', + created_at: new Date().toISOString(), + updated_at: new Date().toISOString(), + ...fileData, + }; + + 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 getOfficeRib(): Promise { + return this.messageBus.getFileByUtype('officeRib'); + } + + public static updateOfficeRib(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/common/Api/LeCoffreApi/sdk/OfficeRoleService.ts b/src/common/Api/LeCoffreApi/sdk/OfficeRoleService.ts new file mode 100644 index 00000000..d34a5bd1 --- /dev/null +++ b/src/common/Api/LeCoffreApi/sdk/OfficeRoleService.ts @@ -0,0 +1,179 @@ +import { v4 as uuidv4 } from 'uuid'; + +import User from 'src/sdk/User'; + +import AbstractService from './AbstractService'; + +import OfficeService from './OfficeService'; +import RuleService from './RuleService'; + +export default class OfficeRoleService extends AbstractService { + + private constructor() { + super(); + } + + public static createOfficeRole(roleData: any, validatorId: string): Promise { + const ownerId = User.getInstance().getPairingId()!; + + const processData: any = { + uid: uuidv4(), + utype: 'officeRole', + 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) => { + this.getOfficeRoleByUid(processCreated.processData.uid).then(resolve).catch(reject); + }).catch(reject); + }).catch(reject); + }).catch(reject); + }); + } + + public static getOfficeRoles(): Promise { + // Check if we have valid cache + const items: any[] = this.getItems('_office_roles_'); + + return this.messageBus.getProcessesDecoded((publicValues: any) => + publicValues['uid'] && + publicValues['utype'] && + publicValues['utype'] === 'officeRole' && + publicValues['isDeleted'] && + publicValues['isDeleted'] === 'false' && + !items.map((item: any) => item.processData.uid).includes(publicValues['uid']) + ).then(async (processes: any[]) => { + if (processes.length === 0) { + return items; + } else { + for (let process of processes) { + process = await this.completeOfficeRole(process); + + // Update cache + this.setItem('_office_roles_', process); + + items.push(process); + } + return items; + } + }); + } + + public static getOfficeRoleByUid(uid: string): Promise { + // Check if we have valid cache + const item: any = this.getItem('_office_roles_', uid); + if (item) { + return Promise.resolve(item); + } + + 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'] === 'officeRole' && + publicValues['isDeleted'] && + publicValues['isDeleted'] === 'false' + ).then(async (processes: any[]) => { + if (processes.length === 0) { + resolve(null); + } else { + let process: any = processes[0]; + process = await this.completeOfficeRole(process); + + // Update cache + this.setItem('_office_roles_', process); + + resolve(process); + } + }).catch(reject); + }); + } + + public static updateOfficeRole(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) => { + const roleUid: string = process.processData.uid; + this.removeItem('_office_roles_', roleUid); + + this.getOfficeRoleByUid(roleUid).then(resolve).catch(reject); + }).catch(reject); + }).catch(reject); + }).catch(reject); + }); + } + + private static async completeOfficeRole(process: any): Promise { + if (process.processData.office) { + process.processData.office = await new Promise(async (resolve: (office: any) => void) => { + const office: any = (await OfficeService.getOfficeByUid(process.processData.office.uid)).processData; + resolve(office); + }); + } + + if (process.processData.rules && process.processData.rules.length > 0) { + process.processData.rules = await new Promise(async (resolve: (rules: any[]) => void) => { + const rules: any[] = []; + for (const rule of process.processData.rules) { + rules.push((await RuleService.getRuleByUid(rule.uid)).processData); + } + resolve(rules); + }); + } + + return process; + } +} diff --git a/src/common/Api/LeCoffreApi/sdk/RoleService.ts b/src/common/Api/LeCoffreApi/sdk/RoleService.ts index 588c3df6..4593f383 100644 --- a/src/common/Api/LeCoffreApi/sdk/RoleService.ts +++ b/src/common/Api/LeCoffreApi/sdk/RoleService.ts @@ -4,7 +4,6 @@ import User from 'src/sdk/User'; import AbstractService from './AbstractService'; -import OfficeService from './OfficeService'; import RuleService from './RuleService'; export default class RoleService extends AbstractService { @@ -157,13 +156,7 @@ export default class RoleService extends AbstractService { } private static async completeRole(process: any): Promise { - if (process.processData.office) { - process.processData.office = await new Promise(async (resolve: (office: any) => void) => { - const office: any = (await OfficeService.getOfficeByUid(process.processData.office.uid)).processData; - resolve(office); - }); - } - + /* if (process.processData.rules && process.processData.rules.length > 0) { process.processData.rules = await new Promise(async (resolve: (rules: any[]) => void) => { const rules: any[] = []; @@ -173,6 +166,7 @@ export default class RoleService extends AbstractService { resolve(rules); }); } + */ return process; } diff --git a/src/common/Api/LeCoffreApi/sdk/RuleGroupService.ts b/src/common/Api/LeCoffreApi/sdk/RuleGroupService.ts new file mode 100644 index 00000000..aeb47afe --- /dev/null +++ b/src/common/Api/LeCoffreApi/sdk/RuleGroupService.ts @@ -0,0 +1,171 @@ +import { v4 as uuidv4 } from 'uuid'; + +import User from 'src/sdk/User'; + +import AbstractService from './AbstractService'; + +import RuleService from './RuleService'; + +export default class RuleGroupService extends AbstractService { + + private constructor() { + super(); + } + + public static createRuleGroup(ruleGroupData: any, validatorId: string): Promise { + const ownerId = User.getInstance().getPairingId()!; + + const processData: any = { + uid: uuidv4(), + utype: 'ruleGroup', + isDeleted: 'false', + created_at: new Date().toISOString(), + updated_at: new Date().toISOString(), + ...ruleGroupData, + }; + + 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) => { + this.getRuleGroupByUid(processCreated.processData.uid).then(resolve).catch(reject); + }).catch(reject); + }).catch(reject); + }).catch(reject); + }); + } + + public static getRuleGroups(): Promise { + // Check if we have valid cache + const items: any[] = this.getItems('_rule_groups_'); + + return this.messageBus.getProcessesDecoded((publicValues: any) => + publicValues['uid'] && + publicValues['utype'] && + publicValues['utype'] === 'ruleGroup' && + publicValues['isDeleted'] && + publicValues['isDeleted'] === 'false' && + !items.map((item: any) => item.processData.uid).includes(publicValues['uid']) + ).then(async (processes: any[]) => { + if (processes.length === 0) { + return items; + } else { + for (let process of processes) { + process = await this.completeRuleGroup(process); + + // Update cache + this.setItem('_rule_groups_', process); + + items.push(process); + } + return items; + } + }); + } + + public static getRuleGroupByUid(uid: string): Promise { + // Check if we have valid cache + const item: any = this.getItem('_rule_groups_', uid); + if (item) { + return Promise.resolve(item); + } + + 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'] === 'ruleGroup' && + publicValues['isDeleted'] && + publicValues['isDeleted'] === 'false' + ).then(async (processes: any[]) => { + if (processes.length === 0) { + resolve(null); + } else { + let process: any = processes[0]; + process = await this.completeRuleGroup(process); + + // Update cache + this.setItem('_rule_groups_', process); + + resolve(process); + } + }).catch(reject); + }); + } + + public static updateRuleGroup(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) => { + const ruleUid: string = process.processData.uid; + this.removeItem('_rule_groups_', ruleUid); + + this.getRuleGroupByUid(ruleUid).then(resolve).catch(reject); + }).catch(reject); + }).catch(reject); + }).catch(reject); + }); + } + + private static async completeRuleGroup(process: any): Promise { + if (process.processData.rules && process.processData.rules.length > 0) { + process.processData.rules = await new Promise(async (resolve: (rules: any[]) => void) => { + const rules: any[] = []; + for (const rule of process.processData.rules) { + rules.push((await RuleService.getRuleByUid(rule.uid)).processData); + } + resolve(rules); + }); + } + + return process; + } +} diff --git a/src/front/Api/BaseApiService.ts b/src/front/Api/BaseApiService.ts index 01ad7443..6541d135 100644 --- a/src/front/Api/BaseApiService.ts +++ b/src/front/Api/BaseApiService.ts @@ -56,7 +56,7 @@ export default abstract class BaseApiService { } protected async postRequest(url: URL, body: { [key: string]: unknown } = {}, token?: string) { - await this.checkJwtToken(); + //await this.checkJwtToken(); return this.sendRequest( async () => await fetch(url, { diff --git a/src/front/Api/LeCoffreApi/Notary/Customers/Customers.ts b/src/front/Api/LeCoffreApi/Notary/Customers/Customers.ts index f9378372..36b113d8 100644 --- a/src/front/Api/LeCoffreApi/Notary/Customers/Customers.ts +++ b/src/front/Api/LeCoffreApi/Notary/Customers/Customers.ts @@ -89,9 +89,14 @@ export default class Customers extends BaseNotary { } public async sendReminder(uid: string, documentsUid: string[]): Promise { - const url = new URL(this.baseURl.concat(`/${uid}/send_reminder`)); + // TODO: review + const baseBackUrl = 'http://localhost:8080';//variables.BACK_API_PROTOCOL + variables.BACK_API_HOST; + + const url = new URL(`${baseBackUrl}/api/${uid}/send_reminder`); + + //const url = new URL(this.baseURl.concat(`/${uid}/send_reminder`)); try { - await this.postRequest(url, { documentsUid }); + await this.postRequest(url, { email: 'ja.janin.anthony@gmail.com', documentsUid }); } catch (err) { this.onError(err); return Promise.reject(err); diff --git a/src/front/Components/DesignSystem/DepositOtherDocument/index.tsx b/src/front/Components/DesignSystem/DepositOtherDocument/index.tsx index 39caebc7..d6b39eb9 100644 --- a/src/front/Components/DesignSystem/DepositOtherDocument/index.tsx +++ b/src/front/Components/DesignSystem/DepositOtherDocument/index.tsx @@ -20,6 +20,7 @@ import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService"; import DocumentService from "src/common/Api/LeCoffreApi/sdk/DocumentService"; import FileService from "src/common/Api/LeCoffreApi/sdk/FileService"; import CustomerService from "src/common/Api/LeCoffreApi/sdk/CustomerService"; +import FolderService from "src/common/Api/LeCoffreApi/sdk/FolderService"; type IProps = { onChange?: (files: File[]) => void; @@ -257,7 +258,7 @@ export default class DepositOtherDocument extends React.Component resolve()); + DocumentService.updateDocument(process, { files: files, document_status: EDocumentStatus.DEPOSITED }).then(() => { + FolderService.refreshFolderByUid(document.folder.uid).then(() => resolve()); + }); } }); }); diff --git a/src/front/Components/Elements/Rules/index.tsx b/src/front/Components/Elements/Rules/index.tsx index df347680..235a01b2 100644 --- a/src/front/Components/Elements/Rules/index.tsx +++ b/src/front/Components/Elements/Rules/index.tsx @@ -4,6 +4,8 @@ import { IAppRule } from "@Front/Api/Entities/rule"; import { useRouter } from "next/router"; import Module from "@Front/Config/Module"; +import UserStore from "@Front/Stores/UserStore"; + export enum RulesMode { OPTIONAL = "optional", NECESSARY = "necessary", @@ -23,9 +25,13 @@ export default function Rules(props: IProps) { // const [hasJwt, setHasJwt] = React.useState(false); const getShowValue = useCallback(() => { + //const user: any = UserStore.instance.getUser(); if (props.mode === RulesMode.NECESSARY) { + //return user.isAdmin && user.isAdmin === 'true'; return props.rules.every((rule) => JwtService.getInstance().hasRule(rule.name, rule.action)); } + //const ruleNames: string[] = props.rules.map((rule: any) => rule.name); + //return user.role.rules.map((rule: any) => rule.name).filter((ruleName: string) => ruleNames.includes(ruleName)).length > 0; return props.rules.length === 0 || !!props.rules.find((rule) => JwtService.getInstance().hasRule(rule.name, rule.action)); }, [props.mode, props.rules]); diff --git a/src/front/Components/LayoutTemplates/DefaultRoleDashboard/index.tsx b/src/front/Components/LayoutTemplates/DefaultRoleDashboard/index.tsx index aa5295a3..c08cb70d 100644 --- a/src/front/Components/LayoutTemplates/DefaultRoleDashboard/index.tsx +++ b/src/front/Components/LayoutTemplates/DefaultRoleDashboard/index.tsx @@ -7,7 +7,7 @@ import DefaultDashboardWithList, { IPropsDashboardWithList } from "../DefaultDas import UserStore from "@Front/Stores/UserStore"; -import RoleService from "src/common/Api/LeCoffreApi/sdk/RoleService"; +import OfficeRoleService from "src/common/Api/LeCoffreApi/sdk/OfficeRoleService"; type IProps = IPropsDashboardWithList; @@ -28,17 +28,17 @@ export default function DefaultRoleDashboard(props: IProps) { return; } - RoleService.getRoles().then(async (processes: any[]) => { + OfficeRoleService.getOfficeRoles().then(async (processes: any[]) => { if (processes.length > 0) { - let roles: any[] = processes.map((process: any) => process.processData); + let officeRoles: any[] = processes.map((process: any) => process.processData); // FilterBy office.uid - roles = roles.filter((role: any) => role.office.uid === office.uid); + officeRoles = officeRoles.filter((officeRole: any) => officeRole.office.uid === office.uid); - // OrderBy label - roles = roles.sort((a: any, b: any) => a.label.localeCompare(b.label)); + // OrderBy name + officeRoles = officeRoles.sort((a: any, b: any) => a.name.localeCompare(b.name)); - setRoles(roles); + setRoles(officeRoles); } }); }, []); @@ -55,7 +55,7 @@ export default function DefaultRoleDashboard(props: IProps) { roles ? roles.map((role) => ({ id: role.uid!, - primaryText: role.label, + primaryText: role.name, isActive: role.uid === roleUid, })) : [] diff --git a/src/front/Components/Layouts/ClientDashboard/ContactBox/index.tsx b/src/front/Components/Layouts/ClientDashboard/ContactBox/index.tsx index 9947c5c4..fcfb51d6 100644 --- a/src/front/Components/Layouts/ClientDashboard/ContactBox/index.tsx +++ b/src/front/Components/Layouts/ClientDashboard/ContactBox/index.tsx @@ -3,10 +3,11 @@ import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Ty import { ArrowDownTrayIcon } from "@heroicons/react/24/outline"; import Customer from "le-coffre-resources/dist/Customer"; import { OfficeFolder as OfficeFolderNotary } from "le-coffre-resources/dist/Notary"; -import { useCallback, useEffect, useMemo } from "react"; +import { useCallback, useEffect, useMemo, useState } from "react"; import classes from "./classes.module.scss"; -// import OfficeRib from "@Front/Api/LeCoffreApi/Customer/OfficeRib/OfficeRib"; + +import OfficeRibService from "src/common/Api/LeCoffreApi/sdk/OfficeRibService"; type IProps = { folder: OfficeFolderNotary; @@ -16,23 +17,10 @@ type IProps = { export default function ContactBox(props: IProps) { const { folder, customer } = props; - // const [ribUrl, setRibUrl] = useState(null); - const ribUrl = null; - - // TODO: review - const stakeholder = { - cell_phone_number: "0606060606", - phone_number: "0606060606", - email: "test@lecoffre.fr", - }; + const [ribUrl, setRibUrl] = useState(null); const notaryContact = useMemo( - () => - /*folder?.stakeholders!.find((stakeholder) => stakeholder.office_role?.name === "Notaire")?.contact ?? - folder?.stakeholders![0]!.contact*/ - - // TODO: review - stakeholder, + () => folder?.stakeholders!.find((stakeholder) => stakeholder.office_role?.name === "Notaire")?.contact ?? folder?.stakeholders![0]!.contact, [folder], ); @@ -48,11 +36,13 @@ export default function ContactBox(props: IProps) { useEffect(() => { if (!folder?.office?.uid) return; - /* TODO: review - OfficeRib.getInstance() - .getRibStream(folder.office.uid) - .then((blob) => setRibUrl(URL.createObjectURL(blob))); - */ + OfficeRibService.getOfficeRib().then((process: any) => { + if (process) { + const officeRib: any = process.processData; + const fileBlob: Blob = new Blob([officeRib.file_blob.data], { type: officeRib.file_blob.type }); + setRibUrl(URL.createObjectURL(fileBlob)); + } + }); }, [folder]); const downloadRib = useCallback(async () => { diff --git a/src/front/Components/Layouts/ClientDashboard/DepositDocumentComponent/index.tsx b/src/front/Components/Layouts/ClientDashboard/DepositDocumentComponent/index.tsx index 6c0d5796..3cc24447 100644 --- a/src/front/Components/Layouts/ClientDashboard/DepositDocumentComponent/index.tsx +++ b/src/front/Components/Layouts/ClientDashboard/DepositDocumentComponent/index.tsx @@ -48,7 +48,7 @@ export default function DepositDocumentComponent(props: IProps) { const date: Date = new Date(); const strDate: string = `${date.getDate().toString().padStart(2, '0')}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getFullYear()}`; - const fileName: string = `${document.document_type.name}-${customer.contact.last_name}-${strDate}.${file.name.split('.').pop()}`; + const fileName: string = `${document.document_type.name}-${customer.contact.last_name}_${strDate}.${file.name.split('.').pop()}`; const arrayBuffer: ArrayBuffer = event.target.result as ArrayBuffer; const uint8Array: Uint8Array = new Uint8Array(arrayBuffer); @@ -70,7 +70,6 @@ export default function DepositDocumentComponent(props: IProps) { DocumentService.getDocumentByUid(document.uid!).then((process: any) => { if (process) { const document: any = process.processData; - FolderService.invalidateCache(document.folder.uid); let files: any[] = document.files; if (!files) { @@ -78,7 +77,9 @@ export default function DepositDocumentComponent(props: IProps) { } files.push({ uid: fileUid }); - DocumentService.updateDocument(process, { files: files, document_status: EDocumentStatus.DEPOSITED }).then(() => resolve()); + DocumentService.updateDocument(process, { files: files, document_status: EDocumentStatus.DEPOSITED }).then(() => { + FolderService.refreshFolderByUid(document.folder.uid).then(() => resolve()); + }); } }); }); @@ -100,7 +101,7 @@ export default function DepositDocumentComponent(props: IProps) { const date: Date = new Date(); const strDate: string = `${date.getDate().toString().padStart(2, '0')}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getFullYear()}`; - const fileName: string = `${document.document_type.name}-${customer.contact.last_name}-${strDate}.${file.name.split('.').pop()}`; + const fileName: string = `${document.document_type.name}-${customer.contact.last_name}_${strDate}.${file.name.split('.').pop()}`; const arrayBuffer: ArrayBuffer = event.target.result as ArrayBuffer; const uint8Array: Uint8Array = new Uint8Array(arrayBuffer); @@ -129,7 +130,9 @@ export default function DepositDocumentComponent(props: IProps) { } files.push({ uid: fileUid }); - DocumentService.updateDocument(process, { files: files, document_status: EDocumentStatus.DEPOSITED }).then(() => resolve()); + DocumentService.updateDocument(process, { files: files, document_status: EDocumentStatus.DEPOSITED }).then(() => { + FolderService.refreshFolderByUid(document.folder.uid).then(() => resolve()); + }); } }); }); diff --git a/src/front/Components/Layouts/Collaborators/CollaboratorInformations/index.tsx b/src/front/Components/Layouts/Collaborators/CollaboratorInformations/index.tsx index 4babe364..98724800 100644 --- a/src/front/Components/Layouts/Collaborators/CollaboratorInformations/index.tsx +++ b/src/front/Components/Layouts/Collaborators/CollaboratorInformations/index.tsx @@ -1,14 +1,10 @@ import { ChevronLeftIcon } from "@heroicons/react/24/solid"; -import OfficeRoles from "@Front/Api/LeCoffreApi/Admin/OfficeRoles/OfficeRoles"; -import Roles from "@Front/Api/LeCoffreApi/Admin/Roles/Roles"; -import Users from "@Front/Api/LeCoffreApi/Admin/Users/Users"; import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button"; import Confirm from "@Front/Components/DesignSystem/OldModal/Confirm"; import Switch from "@Front/Components/DesignSystem/Switch"; import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography"; import DefaultCollaboratorDashboard from "@Front/Components/LayoutTemplates/DefaultCollaboratorDashboard"; import Module from "@Front/Config/Module"; -import User, { OfficeRole } from "le-coffre-resources/dist/Admin"; import Link from "next/link"; import { useRouter } from "next/router"; import { useCallback, useEffect, useState } from "react"; @@ -18,7 +14,9 @@ import { IOption } from "@Front/Components/DesignSystem/Dropdown/DropdownMenu/Dr import { getLabel } from "@Front/Components/DesignSystem/Dropdown"; import SelectField from "@Front/Components/DesignSystem/Form/SelectField"; +import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService"; import CollaboratorService from "src/common/Api/LeCoffreApi/sdk/CollaboratorService"; +import OfficeRoleService from "src/common/Api/LeCoffreApi/sdk/OfficeRoleService"; import RoleService from "src/common/Api/LeCoffreApi/sdk/RoleService"; type IProps = {}; @@ -26,7 +24,7 @@ export default function CollaboratorInformations(props: IProps) { const router = useRouter(); let { collaboratorUid } = router.query; - const [userSelected, setUserSelected] = useState(null); + const [userSelected, setUserSelected] = useState(null); const [availableRoles, setAvailableRoles] = useState([]); const [roleModalOpened, setRoleModalOpened] = useState(false); @@ -38,7 +36,7 @@ export default function CollaboratorInformations(props: IProps) { useEffect(() => { if (!userSelected) return; - setIsAdminChecked(userSelected.role?.name === "admin"); + setIsAdminChecked(userSelected.role.name === "admin"); }, [userSelected]); const handleRoleChange = useCallback((option: IOption) => { @@ -49,60 +47,54 @@ export default function CollaboratorInformations(props: IProps) { const closeRoleModal = useCallback(() => { setRoleModalOpened(false); setSelectedOption({ - id: (userSelected?.office_role ? userSelected?.office_role?.uid : userSelected?.role?.uid) ?? "", - label: userSelected?.office_role ? userSelected?.office_role?.name : "Utilisateur restreint", + id: userSelected?.role?.uid ?? "", + label: userSelected?.role?.name ?? "Utilisateur restreint" }); - }, [userSelected?.office_role, userSelected?.role?.uid]); + }, [userSelected?.role]); const changeRole = useCallback(async () => { - await Users.getInstance().put( - userSelected?.uid as string, - User.hydrate({ - uid: userSelected?.uid as string, - office_role: OfficeRole.hydrate({ - uid: selectedOption?.id as string, - }), - }), - ); - setRoleModalOpened(false); + LoaderService.getInstance().show(); + CollaboratorService.getCollaboratorByUid(collaboratorUid as string).then((process: any) => { + if (process) { + CollaboratorService.updateCollaborator(process, { office_role: { uid: selectedOption?.id as string } }).then(() => { + LoaderService.getInstance().hide(); + setRoleModalOpened(false); + }); + } + }); }, [selectedOption, userSelected]); const changeAdmin = useCallback(async () => { try { if (adminRoleType === "add") { - const adminRole = await Roles.getInstance().getOne({ - where: { - name: "admin", - }, - }); + LoaderService.getInstance().show(); + CollaboratorService.getCollaboratorByUid(collaboratorUid as string).then(async (process: any) => { + if (process) { + const role: any = (await RoleService.getRoles()) + .map((process: any) => process.processData) + .filter((role: any) => role.name === "admin")[0]; - if (!adminRole) return; - await Users.getInstance().put( - userSelected?.uid as string, - User.hydrate({ - uid: userSelected?.uid as string, - office_role: undefined, - role: adminRole, - }), - ); + CollaboratorService.updateCollaborator(process, { role: { uid: role.uid } }).then(() => { + LoaderService.getInstance().hide(); + setAdminModalOpened(false); + }); + } + }); } else { - const defaultRole = await Roles.getInstance().getOne({ - where: { - name: "default", - }, - }); + LoaderService.getInstance().show(); + CollaboratorService.getCollaboratorByUid(collaboratorUid as string).then(async (process: any) => { + if (process) { + const role: any = (await RoleService.getRoles()) + .map((process: any) => process.processData) + .filter((role: any) => role.name === "default")[0]; - if (!defaultRole) return; - await Users.getInstance().put( - userSelected?.uid as string, - User.hydrate({ - uid: userSelected?.uid as string, - office_role: undefined, - role: defaultRole, - }), - ); + CollaboratorService.updateCollaborator(process, { role: { uid: role.uid } }).then(() => { + LoaderService.getInstance().hide(); + setAdminModalOpened(false); + }); + } + }); } - setAdminModalOpened(false); } catch (e) { console.error(e); } @@ -116,62 +108,29 @@ export default function CollaboratorInformations(props: IProps) { }, []); const closeAdminModal = useCallback(() => { - setIsAdminChecked(userSelected?.role?.name === "admin" && !userSelected.office_role); + setIsAdminChecked(userSelected?.role.name === "admin"); setAdminModalOpened(false); }, [userSelected]); useEffect(() => { async function getUser() { if (!collaboratorUid) return; - + LoaderService.getInstance().show(); CollaboratorService.getCollaboratorByUid(collaboratorUid as string).then(async (process: any) => { if (process) { const collaborator: any = process.processData; - const roles: any[] = await new Promise((resolve: (roles: any[]) => void) => { - RoleService.getRoles().then((processes: any[]) => { - if (processes.length > 0) { - const roles: any[] = processes.map((process: any) => process.processData); - resolve(roles); - } - }); - }); - setAvailableRoles(roles.map((role) => ({ id: role.uid ?? "", label: role.label }))); + const officeRoles: any[] = (await OfficeRoleService.getOfficeRoles()) + .map((process: any) => process.processData); setUserSelected(collaborator); - setSelectedOption({ - id: (collaborator?.office_role ? collaborator?.office_role?.uid : collaborator?.role?.uid) ?? "", - label: collaborator?.office_role ? collaborator?.office_role?.label : "Utilisateur restreint", - }); + setAvailableRoles(officeRoles.map((officeRole: any) => ({ id: officeRole.uid, label: officeRole.name }))); + setSelectedOption({ id: collaborator.office_role.uid, label: collaborator.office_role.name }); + + LoaderService.getInstance().hide(); } }); - - /* - const user = await Users.getInstance().getByUid(collaboratorUid as string, { - q: { - contact: true, - office_role: true, - role: true, - seats: { - include: { - subscription: true, - }, - }, - }, - }); - if (!user) return; - - const roles = await OfficeRoles.getInstance().get(); - if (!roles) return; - setAvailableRoles(roles.map((role) => ({ id: role.uid ?? "", label: role.name }))); - setUserSelected(user); - setSelectedOption({ - id: (user?.office_role ? user?.office_role?.uid : user?.role?.uid) ?? "", - label: user?.office_role ? user?.office_role?.name : "Utilisateur restreint", - }); - */ } - getUser(); }, [collaboratorUid]); @@ -182,7 +141,7 @@ export default function CollaboratorInformations(props: IProps) { {userSelected?.contact?.first_name + " " + userSelected?.contact?.last_name} - {userSelected && userSelected.seats?.some((seat) => new Date(seat.subscription!.end_date) >= new Date()) && ( + {userSelected && userSelected.seats?.some((seat: any) => new Date(seat.subscription!.end_date) >= new Date()) && (
diff --git a/src/front/Components/Layouts/Folder/AskDocuments/index.tsx b/src/front/Components/Layouts/Folder/AskDocuments/index.tsx index 5805598e..9b9e7f30 100644 --- a/src/front/Components/Layouts/Folder/AskDocuments/index.tsx +++ b/src/front/Components/Layouts/Folder/AskDocuments/index.tsx @@ -82,11 +82,15 @@ export default function AskDocuments() { await DocumentService.createDocument(documentData, validatorId); } - router.push( - Module.getInstance() - .get() - .modules.pages.Folder.pages.FolderInformation.props.path.replace("[folderUid]", folderUid as string), - ); + + FolderService.refreshFolderByUid(folderUid as string).then(() => { + LoaderService.getInstance().hide(); + router.push( + Module.getInstance() + .get() + .modules.pages.Folder.pages.FolderInformation.props.path.replace("[folderUid]", folderUid as string), + ); + }); } catch (e) { console.error(e); } diff --git a/src/front/Components/Layouts/Folder/CreateFolder/index.tsx b/src/front/Components/Layouts/Folder/CreateFolder/index.tsx index f1bdf7ba..0df0fa45 100644 --- a/src/front/Components/Layouts/Folder/CreateFolder/index.tsx +++ b/src/front/Components/Layouts/Folder/CreateFolder/index.tsx @@ -11,7 +11,6 @@ import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Ty 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"; import { ValidationError } from "class-validator/types/validation/ValidationError"; import { Deed, Office, OfficeFolder } from "le-coffre-resources/dist/Notary"; import User from "le-coffre-resources/dist/Notary"; @@ -21,9 +20,12 @@ import { useRouter } from "next/router"; import React, { useCallback, useEffect, useState } from "react"; import classes from "./classes.module.scss"; +import UserStore from "@Front/Stores/UserStore"; + 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"; +import CollaboratorService from "src/common/Api/LeCoffreApi/sdk/CollaboratorService"; export default function CreateFolder(): JSX.Element { /** @@ -50,9 +52,8 @@ export default function CreateFolder(): JSX.Element { [key: string]: any; }, ) => { - // TODO: review - console.log(JwtService.getInstance().decodeJwt()); - const officeId = 'demo_notary_office_id'; //JwtService.getInstance().decodeJwt()?.office_Id; + const user: any = UserStore.instance.getUser(); + const officeId: string = user.office.uid; const officeFolderModel = OfficeFolder.hydrate({ folder_number: values["folder_number"], @@ -93,7 +94,7 @@ export default function CreateFolder(): JSX.Element { customers: [], documents: [], notes: [], - stakeholders: folderAccessType === "whole_office" ? availableCollaborators : selectedCollaborators, + stakeholders: (folderAccessType === "whole_office" ? availableCollaborators : selectedCollaborators).map((collaborator: any) => ({ uid: collaborator.uid })), status: EFolderStatus.LIVE }; @@ -132,32 +133,23 @@ export default function CreateFolder(): JSX.Element { useEffect(() => { DeedTypeService.getDeedTypes().then((processes: any[]) => { if (processes.length > 0) { - let deedTypes: any[] = processes.map((process: any) => process.processData); - - // FilterBy archived_at = null or not defined - deedTypes = deedTypes.filter((deedType: any) => !deedType.archived_at); - + const deedTypes: any[] = processes.map((process: any) => process.processData); setAvailableDeedTypes(deedTypes); } }); - /* TODO: review - // no need to pass query 'where' param here, default query for notaries include only users which are in the same office as the caller - Users.getInstance() - .get({ - include: { contact: true }, - }) - .then((users) => { - setAvailableCollaborators(users); - / * - // set default selected collaborators to the connected user - const currentUser = users.find((user) => user.uid === JwtService.getInstance().decodeJwt()?.userId); + CollaboratorService.getCollaborators().then((processes: any[]) => { + if (processes.length > 0) { + const collaborators: any[] = processes.map((process: any) => process.processData); + setAvailableCollaborators(collaborators); + + const user: any = UserStore.instance.getUser(); + const currentUser: any = collaborators.find((collaborator: any) => collaborator.uid === user.uid); if (currentUser) { setSelectedCollaborators([currentUser]); } - * / - }); - */ + } + }); }, []); /** 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 fa7e0e37..afe5eff6 100644 --- a/src/front/Components/Layouts/Folder/FolderInformation/ClientView/DocumentTables/index.tsx +++ b/src/front/Components/Layouts/Folder/FolderInformation/ClientView/DocumentTables/index.tsx @@ -23,8 +23,11 @@ import DocumentService from "src/common/Api/LeCoffreApi/sdk/DocumentService"; import FileService from "src/common/Api/LeCoffreApi/sdk/FileService"; import PdfService, { CertificateData, Metadata } from "@Front/Services/PdfService"; + import MessageBus from "src/sdk/MessageBus"; +import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService"; + type IProps = { customerUid: string; folderUid: string; @@ -122,7 +125,13 @@ export default function DocumentTables(props: IProps) { const file = doc.files?.[0]; if (!file) return; - return new Promise((resolve: () => void) => { + return new Promise(async (resolve: () => void) => { + if (!file.file_blob) { + LoaderService.getInstance().show(); + file.file_blob = (await FileService.getFileByUid(file.uid)).processData.file_blob; + LoaderService.getInstance().hide(); + } + const blob = new Blob([file.file_blob.data], { type: file.file_blob.type }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); @@ -223,7 +232,7 @@ export default function DocumentTables(props: IProps) { if (document.document_status !== EDocumentStatus.ASKED) return null; return { key: document.uid, - document_type: { sx: { width: 300 }, content: document.document_type?.name ?? "_" }, + document_type: { sx: { width: 300 }, content: document.document_type?.name ?? "Autre document" }, document_status: { sx: { width: 107 }, content: ( @@ -263,7 +272,7 @@ export default function DocumentTables(props: IProps) { if (document.document_status !== EDocumentStatus.DEPOSITED) return null; return { key: document.uid, - document_type: { sx: { width: 300 }, content: document.document_type?.name ?? "_" }, + document_type: { sx: { width: 300 }, content: document.document_type?.name ?? "Autre document" }, document_status: { sx: { width: 107 }, content: ( @@ -309,7 +318,7 @@ export default function DocumentTables(props: IProps) { if (document.document_status !== EDocumentStatus.VALIDATED) return null; return { key: document.uid, - document_type: { sx: { width: 300 }, content: document.document_type?.name ?? "_" }, + document_type: { sx: { width: 300 }, content: document.document_type?.name ?? "Autre document" }, document_status: { sx: { width: 107 }, content: ( @@ -360,7 +369,7 @@ export default function DocumentTables(props: IProps) { if (document.document_status !== EDocumentStatus.REFUSED) return null; return { key: document.uid, - document_type: { sx: { width: 300 }, content: document.document_type?.name ?? "_" }, + document_type: { sx: { width: 300 }, content: document.document_type?.name ?? "Autre document" }, document_status: { sx: { width: 107 }, content: ( diff --git a/src/front/Components/Layouts/Folder/SendDocuments/index.tsx b/src/front/Components/Layouts/Folder/SendDocuments/index.tsx index af91b368..2a2f27e4 100644 --- a/src/front/Components/Layouts/Folder/SendDocuments/index.tsx +++ b/src/front/Components/Layouts/Folder/SendDocuments/index.tsx @@ -83,7 +83,7 @@ export default function SendDocuments() { const date: Date = new Date(); const strDate: string = `${date.getDate().toString().padStart(2, '0')}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getFullYear()}`; - const fileName: string = `${customer.contact.last_name}-${strDate}.${file.name.split('.').pop()}`; + const fileName: string = `${customer.contact.last_name}_${strDate}.${file.name.split('.').pop()}`; const arrayBuffer: ArrayBuffer = event.target.result as ArrayBuffer; const uint8Array: Uint8Array = new Uint8Array(arrayBuffer); @@ -117,7 +117,9 @@ export default function SendDocuments() { document_status: EDocumentNotaryStatus.SENT }; - DocumentService.createDocument(documentData, validatorId).then(() => resolve()); + DocumentService.createDocument(documentData, validatorId).then(() => { + FolderService.refreshFolderByUid(folderUid as string).then(() => resolve()); + }); }); } }; diff --git a/src/front/Components/Layouts/Folder/ViewDocuments/index.tsx b/src/front/Components/Layouts/Folder/ViewDocuments/index.tsx index 834b2586..f194b511 100644 --- a/src/front/Components/Layouts/Folder/ViewDocuments/index.tsx +++ b/src/front/Components/Layouts/Folder/ViewDocuments/index.tsx @@ -6,7 +6,6 @@ import Confirm from "@Front/Components/DesignSystem/OldModal/Confirm"; import Typography, { ETypo, ETypoColor } from "@Front/Components/DesignSystem/Typography"; import DefaultNotaryDashboard from "@Front/Components/LayoutTemplates/DefaultNotaryDashboard"; import Module from "@Front/Config/Module"; -import { Document } from "le-coffre-resources/dist/Notary"; import { EDocumentStatus } from "le-coffre-resources/dist/Notary/Document"; import Image from "next/image"; import { NextRouter, useRouter } from "next/router"; @@ -19,8 +18,10 @@ import MessageBox from "@Front/Components/Elements/MessageBox"; import { FileBlob } from "@Front/Api/Entities/types"; +import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService"; import DocumentService from "src/common/Api/LeCoffreApi/sdk/DocumentService"; import FileService from "src/common/Api/LeCoffreApi/sdk/FileService"; +import FolderService from "src/common/Api/LeCoffreApi/sdk/FolderService"; type IProps = {}; type IPropsClass = { @@ -323,16 +324,20 @@ class ViewDocumentsClass extends BasePage { private async refuseDocument() { try { + LoaderService.getInstance().show(); DocumentService.getDocumentByUid(this.props.documentUid).then((process: any) => { if (process) { DocumentService.updateDocument(process, { document_status: EDocumentStatus.REFUSED, refused_reason: this.state.refuseText }).then(() => { - this.props.router.push( - Module.getInstance() - .get() - .modules.pages.Folder.pages.FolderInformation.props.path.replace("[folderUid]", this.props.folderUid) + - "?customerUid=" + - this.state.document?.depositor?.uid, - ); + FolderService.refreshFolderByUid(this.props.folderUid).then(() => { + LoaderService.getInstance().hide(); + this.props.router.push( + Module.getInstance() + .get() + .modules.pages.Folder.pages.FolderInformation.props.path.replace("[folderUid]", this.props.folderUid) + + "?customerUid=" + + this.state.document?.depositor?.uid, + ); + }); }); } }); @@ -343,36 +348,34 @@ class ViewDocumentsClass extends BasePage { private async validateDocument() { try { + LoaderService.getInstance().show(); DocumentService.getDocumentByUid(this.props.documentUid).then(async (process: any) => { if (process) { await new Promise((resolve: () => void) => { FileService.getFileByUid(process.processData.files[0].uid).then((p) => { if (p) { - FileService.updateFile(p, { - file_name: `aplc-${p.processData.file_name}` - }).then(resolve); + const date: Date = new Date(); + const strDate: string = `${date.getDate().toString().padStart(2, '0')}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getFullYear()}`; + + const fileName: string = p.processData.file_name; + const extension: string = fileName.substring(fileName.lastIndexOf('.')); + + FileService.updateFile(p, { file_name: `aplc_${fileName.substring(0, fileName.lastIndexOf('_'))}_${strDate}${extension}` }).then(resolve); } }); }); - /* - this.props.router.push( - Module.getInstance() - .get() - .modules.pages.Folder.pages.FolderInformation.props.path.replace("[folderUid]", this.props.folderUid) + - "?customerUid=" + - this.state.document?.depositor?.uid, - ); - */ - DocumentService.updateDocument(process, { document_status: EDocumentStatus.VALIDATED }).then(() => { - this.props.router.push( - Module.getInstance() - .get() - .modules.pages.Folder.pages.FolderInformation.props.path.replace("[folderUid]", this.props.folderUid) + - "?customerUid=" + - this.state.document?.depositor?.uid, - ); + FolderService.refreshFolderByUid(this.props.folderUid).then(() => { + LoaderService.getInstance().hide(); + this.props.router.push( + Module.getInstance() + .get() + .modules.pages.Folder.pages.FolderInformation.props.path.replace("[folderUid]", this.props.folderUid) + + "?customerUid=" + + this.state.document?.depositor?.uid, + ); + }); }); } }); diff --git a/src/front/Components/Layouts/LoginCallback/index.tsx b/src/front/Components/Layouts/LoginCallback/index.tsx index 41bff8a6..e3bd56be 100644 --- a/src/front/Components/Layouts/LoginCallback/index.tsx +++ b/src/front/Components/Layouts/LoginCallback/index.tsx @@ -17,10 +17,13 @@ import AuthModal from "src/sdk/AuthModal"; import MessageBus from "src/sdk/MessageBus"; import Iframe from "src/sdk/Iframe"; +import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService"; import RuleService from "src/common/Api/LeCoffreApi/sdk/RuleService"; +import RuleGroupService from "src/common/Api/LeCoffreApi/sdk/RuleGroupService"; import RoleService from "src/common/Api/LeCoffreApi/sdk/RoleService"; import OfficeService from "src/common/Api/LeCoffreApi/sdk/OfficeService"; import CollaboratorService from "src/common/Api/LeCoffreApi/sdk/CollaboratorService"; +import OfficeRoleService from "src/common/Api/LeCoffreApi/sdk/OfficeRoleService"; export default function LoginCallBack() { const router = useRouter(); @@ -60,23 +63,111 @@ export default function LoginCallBack() { }); }; - const getRoles = async (office: any) => { + const initDefaultData = async (office: any) => { const rules: any[] = await new Promise((resolve: (rules: any[]) => void) => { const defaultRules: any[] = [ + // Actes et documents { - name: "subscription", - label: "Gestion de l'abonnement", - namespace: "Gestion de l'abonnement" + name: "POST deeds", + label: "Créer un template de type d'acte", + namespace: "collaborator" }, { - name: "document_types", - label: "Gestion des matrices d'actes et des documents", - namespace: "Gestion des matrices d'actes et des documents" + name: "PUT deeds", + label: "Modifier un type d'acte", + namespace: "collaborator" }, { - name: "rib", - label: "Intégration du RIB", - namespace: "Intégration du RIB" + name: "DELETE deeds", + label: "Supprimer des types d'actes", + namespace: "collaborator" + }, + { + name: "GET deed-types", + label: "Lecture des types d'actes", + namespace: "collaborator" + }, + { + name: "POST deed-types", + label: "Création des types d'actes", + namespace: "collaborator" + }, + { + name: "PUT deed-types", + label: "Modification des types d'actes", + namespace: "collaborator" + }, + { + name: "DELETE deed-types", + label: "Suppression des types d'actes", + namespace: "collaborator" + }, + { + name: "GET document-types", + label: "Lecture des types de documents", + namespace: "collaborator" + }, + { + name: "POST document-types", + label: "Création des types de documents", + namespace: "collaborator" + }, + { + name: "PUT document-types", + label: "Modification des types de documents", + namespace: "collaborator" + }, + { + name: "DELETE document-types", + label: "Suppression des types de documents", + namespace: "collaborator" + }, + // RIB + { + name: "GET rib", + label: "Lire le RIB de l'office", + namespace: "collaborator" + }, + { + name: "POST rib", + label: "Déposer le RIB de l'office", + namespace: "collaborator" + }, + { + name: "PUT rib", + label: "Editer le RIB de l'office", + namespace: "collaborator" + }, + { + name: "DELETE rib", + label: "Supprimer le RIB de l'office", + namespace: "collaborator" + }, + // Abonnements + { + name: "GET subscriptions", + label: "Récupérer les abonnements", + namespace: "collaborator" + }, + { + name: "POST subscriptions", + label: "Inviter un collaborateur à l'abonnement", + namespace: "collaborator" + }, + { + name: "PUT subscriptions", + label: "Modifier l'abonnement", + namespace: "collaborator" + }, + { + name: "GET stripe", + label: "Gérer l'abonnement de l'office", + namespace: "collaborator" + }, + { + name: "POST stripe", + label: "Payer un abonnement", + namespace: "collaborator" } ]; RuleService.getRules().then(async (processes: any[]) => { @@ -91,23 +182,56 @@ export default function LoginCallBack() { }); }); - const roles: any[] = await new Promise((resolve: (roles: any[]) => void) => { - const defaultRoles: any[] = [ + await new Promise((resolve: () => void) => { + const defaultRuleGroups: any[] = [ { - name: 'notary', - label: 'Notaire', - office: { - uid: office.uid - }, - rules: rules.map((rule: any) => ({ uid: rule.uid })) + name: "Gestion des matrices d'actes et des documents", + rules: rules + .filter((rule: any) => rule.name.includes("deeds") || rule.name.includes("deed-types") || rule.name.includes("document-types")) + .map((rule: any) => ({ uid: rule.uid })) }, { - name: 'collaborator', - label: 'Collaborateur', - office: { - uid: office.uid - }, - rules: rules.map((rule: any) => ({ uid: rule.uid })) + name: "Intégration du RIB", + rules: rules + .filter((rule: any) => rule.name.includes("rib")) + .map((rule: any) => ({ uid: rule.uid })) + }, + { + name: "Gestion de l'abonnement", + rules: rules + .filter((rule: any) => rule.name.includes("subscriptions") || rule.name.includes("stripe")) + .map((rule: any) => ({ uid: rule.uid })) + } + ]; + RuleGroupService.getRuleGroups().then(async (processes: any[]) => { + const ruleGroups: any[] = processes.map((process: any) => process.processData); + if (ruleGroups.length === 0) { + for (let ruleGroupData of defaultRuleGroups) { + const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0'; + ruleGroups.push((await RuleGroupService.createRuleGroup(ruleGroupData, validatorId)).processData); + } + } + resolve(); + }); + }); + + await new Promise((resolve: () => void) => { + const defaultRoles: any[] = [ + { + name: 'super-admin', + label: 'Super administrateur' + }, + { + name: 'admin', + label: 'Administrateur' + }, + { + name: 'notary', + label: 'Notaire' + }, + { + name: 'default', + label: 'Utilisateur' } ]; RoleService.getRoles().then(async (processes: any[]) => { @@ -118,11 +242,36 @@ export default function LoginCallBack() { roles.push((await RoleService.createRole(roleData, validatorId)).processData); } } - resolve(roles); + resolve(); }); }); - return roles; + await new Promise((resolve: () => void) => { + const defaultOfficeRoles: any[] = [ + { + name: 'Notaire', + office: { + uid: office.uid + } + }, + { + name: 'Collaborateur', + office: { + uid: office.uid + } + } + ]; + OfficeRoleService.getOfficeRoles().then(async (processes: any[]) => { + const roles: any[] = processes.map((process: any) => process.processData); + if (roles.length === 0) { + for (let officeRoleData of defaultOfficeRoles) { + const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0'; + roles.push((await OfficeRoleService.createOfficeRole(officeRoleData, validatorId)).processData); + } + } + resolve(); + }); + }); }; const getCollaborator = async (collaboratorData: any) => { @@ -159,8 +308,14 @@ export default function LoginCallBack() { const code = router.query["code"]; if (code) { try { - const idNotUser: any = await Auth.getInstance().getIdNotUser(code as string); - setIdNotUser(idNotUser); + // Nettoyer l'URL pour ne garder que la racine + const rootUrl = window.location.origin; + if (window.location.href !== rootUrl) { + window.history.replaceState({}, document.title, rootUrl); + } + + const user: any = await Auth.getInstance().getIdNotUser(code as string); + setIdNotUser(user.idNotUser); setIsAuthModalOpen(true); /* const token: any = null; @@ -228,12 +383,20 @@ export default function LoginCallBack() { setIsAuthModalOpen(false); setIsConnected(true); setTimeout(() => { + LoaderService.getInstance().show(); MessageBus.getInstance().initMessageListener(); MessageBus.getInstance().isReady().then(async () => { const office: any = await getOffice(idNotUser); + await initDefaultData(office); - const roles: any[] = await getRoles(office); - const role: any = roles.find((role: any) => role.name === idNotUser.role.name); + const role: any = (await RoleService.getRoles()) + .map((process: any) => process.processData) + .find((role: any) => role.name === idNotUser.role.name); + + const officeRole: any = (await OfficeRoleService.getOfficeRoles()) + .map((process: any) => process.processData) + .filter((officeRole: any) => officeRole.office.uid === office.uid) + .find((officeRole: any) => officeRole.name === idNotUser.office_role.name); const collaboratorData: any = { idNot: idNotUser.idNot, @@ -243,20 +406,24 @@ export default function LoginCallBack() { }, role: { uid: role.uid + }, + office_role: { + uid: officeRole.uid } }; const collaborator: any = await getCollaborator(collaboratorData); - collaborator.office = office; - collaborator.role = role; UserStore.instance.connect(collaborator); MessageBus.getInstance().destroyMessageListener(); + LoaderService.getInstance().hide(); + /* if (jwt.rules && !jwt.rules.includes("GET folders")) { router.push(Module.getInstance().get().modules.pages.Subscription.pages.New.props.path); } */ - router.push(Module.getInstance().get().modules.pages.Folder.props.path); + + window.location.href = Module.getInstance().get().modules.pages.Folder.props.path; }); }, 100); }} diff --git a/src/front/Components/Layouts/Rib/index.tsx b/src/front/Components/Layouts/Rib/index.tsx index 44f78205..66a6c3b0 100644 --- a/src/front/Components/Layouts/Rib/index.tsx +++ b/src/front/Components/Layouts/Rib/index.tsx @@ -5,11 +5,13 @@ import DefaultTemplate from "@Front/Components/LayoutTemplates/DefaultTemplate"; import FilePreview from "@Front/Components/DesignSystem/FilePreview"; import Button, { EButtonstyletype, EButtonVariant } from "@Front/Components/DesignSystem/Button"; import { useRouter } from "next/router"; -import OfficeRib from "@Front/Api/LeCoffreApi/Notary/OfficeRib/OfficeRib"; import DepositRib from "@Front/Components/DesignSystem/DepositRib"; import Confirm from "@Front/Components/DesignSystem/OldModal/Confirm"; import Loader from "@Front/Components/DesignSystem/Loader"; +import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService"; +import OfficeRibService from "src/common/Api/LeCoffreApi/sdk/OfficeRibService"; + export default function Rib() { const [documentList, setDocumentList] = useState([]); const router = useRouter(); @@ -24,10 +26,11 @@ export default function Rib() { const fetchData = useCallback(async () => { try { - const blob = await OfficeRib.getInstance().getRibStream(); - setFileBlob(blob.blob); + const officeRib: any = (await OfficeRibService.getOfficeRib()).processData; + const fileBlob: Blob = new Blob([officeRib.file_blob.data], { type: officeRib.file_blob.type }); + setFileBlob(fileBlob); setKey(key); - setFileName(blob.fileName); + setFileName(officeRib.file_name); } catch (error) { setFileBlob(undefined); setFileName(""); @@ -54,13 +57,41 @@ export default function Rib() { async function onRibModalAccepted() { // Send documents to the backend for validation if (documentList.length === 0) return; - const formData = new FormData(); - formData.append("file", documentList[0]!, documentList[0]!.name); + const file = documentList[0]!; - await OfficeRib.getInstance().post(formData); + LoaderService.getInstance().show(); + const reader = new FileReader(); + reader.onload = (event) => { + if (event.target?.result) { + const date: Date = new Date(); + const strDate: string = `${date.getDate().toString().padStart(2, '0')}-${(date.getMonth() + 1).toString().padStart(2, '0')}-${date.getFullYear()}`; - onCloseRibModal(); - fetchData(); + const fileName: string = `aplc_${file.name.split('.')[0]}_${strDate}.${file.name.split('.').pop()}`; + + const arrayBuffer: ArrayBuffer = event.target.result as ArrayBuffer; + const uint8Array: Uint8Array = new Uint8Array(arrayBuffer); + + const fileBlob: any = { + type: file.type, + data: uint8Array + }; + + const fileData: any = { + file_blob: fileBlob, + file_name: fileName + }; + const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0'; + + OfficeRibService.createOfficeRib(fileData, validatorId).then(() => { + LoaderService.getInstance().hide(); + onCloseRibModal(); + + setIsLoading(true); + setTimeout(() => fetchData(), 2000); + }); + } + }; + reader.readAsArrayBuffer(file); } function openRibModal(): void { @@ -73,10 +104,18 @@ export default function Rib() { } async function onDeleteModalAccepted() { - await OfficeRib.getInstance().delete(); + LoaderService.getInstance().show(); + OfficeRibService.getOfficeRib().then((process: any) => { + if (process) { + OfficeRibService.updateOfficeRib(process, { isDeleted: 'true', archived_at: new Date().toISOString() }).then(() => { + LoaderService.getInstance().hide(); + onCloseDeleteModal(); - onCloseDeleteModal(); - fetchData(); + setIsLoading(true); + setTimeout(() => fetchData(), 2000); + }); + } + }); } function openDeleteModal(): void { @@ -88,7 +127,23 @@ export default function Rib() { } const onDocumentChange = (documentList: File[]) => { - setDocumentList(documentList); + if (documentList.length === 0) return; + if (fileBlob) { + LoaderService.getInstance().show(); + OfficeRibService.getOfficeRib().then((process: any) => { + if (process) { + OfficeRibService.updateOfficeRib(process, { isDeleted: 'true', archived_at: new Date().toISOString() }).then(() => { + LoaderService.getInstance().hide(); + onCloseDeleteModal(); + + setIsLoading(true); + setDocumentList(documentList); + }); + } + }); + } else { + setDocumentList(documentList); + } }; return ( diff --git a/src/front/Components/Layouts/Roles/RolesInformations/index.tsx b/src/front/Components/Layouts/Roles/RolesInformations/index.tsx index ef40d023..24525a7f 100644 --- a/src/front/Components/Layouts/Roles/RolesInformations/index.tsx +++ b/src/front/Components/Layouts/Roles/RolesInformations/index.tsx @@ -1,31 +1,25 @@ -import OfficeRoles from "@Front/Api/LeCoffreApi/Admin/OfficeRoles/OfficeRoles"; import Button from "@Front/Components/DesignSystem/Button"; import CheckBox from "@Front/Components/DesignSystem/CheckBox"; import Form from "@Front/Components/DesignSystem/Form"; import Confirm from "@Front/Components/DesignSystem/OldModal/Confirm"; import Typography, { ETypo } from "@Front/Components/DesignSystem/Typography"; import DefaultRoleDashboard from "@Front/Components/LayoutTemplates/DefaultRoleDashboard"; -import { OfficeRole, Rule, RulesGroup } from "le-coffre-resources/dist/Admin"; import { useRouter } from "next/router"; import { useCallback, useEffect, useState } from "react"; 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; -}; +import OfficeRoleService from "src/common/Api/LeCoffreApi/sdk/OfficeRoleService"; +import RuleGroupService from "src/common/Api/LeCoffreApi/sdk/RuleGroupService"; export default function RolesInformations() { const router = useRouter(); let { roleUid } = router.query; const [roleSelected, setRoleSelected] = useState(null); - const [rulesGroupsCheckboxes, setRulesGroupsCheckboxes] = useState([]); + const [rulesCheckboxes, setRulesCheckboxes] = useState([]); const [selectAll, setSelectAll] = useState(false); const [isConfirmModalOpened, setIsConfirmModalOpened] = useState(false); @@ -43,77 +37,28 @@ export default function RolesInformations() { 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); - LoaderService.getInstance().hide(); - } - }); - }) - /* TODO: review - const rulesGroups = await RulesGroups.getInstance().get({ - include: { - rules: true, - }, - }); - */ + const officeRole: any = (await OfficeRoleService.getOfficeRoleByUid(roleUid as string)).processData; + const ruleGroups: any[] = (await RuleGroupService.getRuleGroups()) + .map((process: any) => process.processData); - /* - 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(), - } - ]; - */ + const rulesCheckboxes: any[] = officeRole.rules ? ruleGroups.map((ruleGroup: any) => { + const isChecked: boolean = officeRole.rules.find((r1: any) => ruleGroup.rules.find((r2: any) => r2.uid === r1.uid)) !== undefined; + return { + ...ruleGroup, + checked: isChecked + }; + }) : ruleGroups; - if (!role) return; - setRoleSelected(role); + setRoleSelected(officeRole); + setRulesCheckboxes(rulesCheckboxes); - // 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))) { - return { ...ruleGroup, checked: true }; - } - return { ...ruleGroup, checked: false }; - }) - .sort((ruleA, ruleB) => (ruleA.name! < ruleB.name! ? 1 : -1)) - .sort((rule) => (rule.checked ? -1 : 1)); - - const selectAll = rulesCheckboxes.every((rule) => rule.checked); + const selectAll: boolean = rulesCheckboxes.every((ruleCheckbox: any) => ruleCheckbox.checked); setSelectAll(selectAll); - setRulesGroupsCheckboxes(rulesCheckboxes); - */ - setRulesGroupsCheckboxes(role.rules); - } + LoaderService.getInstance().hide(); + } getUser(); }, [roleUid]); @@ -121,45 +66,64 @@ export default function RolesInformations() { (e: React.ChangeEvent) => { setSelectAll(e.target.checked); const checked = e.target.checked; - rulesGroupsCheckboxes.forEach((rule) => (rule.checked = checked)); - setRulesGroupsCheckboxes([...rulesGroupsCheckboxes]); + rulesCheckboxes.forEach((rule) => (rule.checked = checked)); + setRulesCheckboxes([...rulesCheckboxes]); }, - [rulesGroupsCheckboxes], + [rulesCheckboxes], ); const modifyRules = useCallback(async () => { if (!roleSelected || !roleSelected.uid) return; - const rulesGroupsChecked = rulesGroupsCheckboxes.filter((rule) => rule.checked); - let newRules: Rule[] = []; + LoaderService.getInstance().show(); - for (let ruleGroup of rulesGroupsChecked) { - if (!ruleGroup.rules) continue; - newRules = [...newRules, ...ruleGroup.rules]; - } - await OfficeRoles.getInstance().put(roleSelected.uid, { - uid: roleSelected.uid, - rules: newRules, + const ruleGroups: any[] = (await RuleGroupService.getRuleGroups()) + .map((process: any) => process.processData); + + const newRules: any[] = rulesCheckboxes + .filter((ruleCheckbox: any) => ruleCheckbox.checked) + .map((ruleCheckbox: any) => ruleCheckbox.rules) + .reduce((acc: any, curr: any) => [...acc, ...curr], []) + .map((ruleCheckbox: any) => ({ uid: ruleCheckbox.uid })); + + await new Promise(async (resolve: () => void) => { + OfficeRoleService.getOfficeRoleByUid(roleSelected.uid).then((process: any) => { + if (process) { + OfficeRoleService.updateOfficeRole(process, { rules: newRules }).then(resolve); + } + }); }); - const roleUpdated = await OfficeRoles.getInstance().getByUid(roleSelected.uid, { - q: { - rules: true, - }, - }); - setRoleSelected(roleUpdated); + const officeRoleUpdated: any = (await OfficeRoleService.getOfficeRoleByUid(roleSelected.uid)).processData; + + const rulesCheckboxesUpdated: any[] = officeRoleUpdated.rules ? ruleGroups.map((ruleGroup: any) => { + const isChecked: boolean = officeRoleUpdated.rules.find((r1: any) => ruleGroup.rules.find((r2: any) => r2.uid === r1.uid)) !== undefined; + return { + ...ruleGroup, + checked: isChecked + }; + }) : ruleGroups; + + setRoleSelected(officeRoleUpdated); + setRulesCheckboxes(rulesCheckboxesUpdated); + + const selectAllUpdated = rulesCheckboxesUpdated.every((ruleCheckbox: any) => ruleCheckbox.checked); + setSelectAll(selectAllUpdated); + + LoaderService.getInstance().hide(); + closeConfirmModal(); - }, [closeConfirmModal, roleSelected, rulesGroupsCheckboxes]); + }, [closeConfirmModal, roleSelected, rulesCheckboxes]); const handleRuleChange = useCallback( (e: React.ChangeEvent) => { const ruleUid = e.target.value; - const rule = rulesGroupsCheckboxes.find((rule) => rule.uid === ruleUid); + const rule = rulesCheckboxes.find((rule) => rule.uid === ruleUid); if (!rule) return; rule.checked = e.target.checked; - setRulesGroupsCheckboxes([...rulesGroupsCheckboxes]); + setRulesCheckboxes([...rulesCheckboxes]); }, - [rulesGroupsCheckboxes], + [rulesCheckboxes], ); return ( @@ -187,11 +151,11 @@ export default function RolesInformations() {
- {rulesGroupsCheckboxes.map((ruleGroup) => ( -
+ {rulesCheckboxes.map((rule) => ( +
diff --git a/src/sdk/MessageBus.ts b/src/sdk/MessageBus.ts index 12dabda7..c524e5e3 100644 --- a/src/sdk/MessageBus.ts +++ b/src/sdk/MessageBus.ts @@ -132,10 +132,118 @@ export default class MessageBus { publicDataDecoded[key] = await this.getPublicData(publicDataEncoded[key]); } - if (!(publicDataDecoded['uid'] && publicDataDecoded['uid'] === uid && publicDataDecoded['utype'] && publicDataDecoded['utype'] === 'file')) { + if (!(publicDataDecoded['uid'] && publicDataDecoded['uid'] === uid && publicDataDecoded['utype'] && publicDataDecoded['utype'] === 'file' && publicDataDecoded['isDeleted'] === 'false')) { continue; } + try { + const lastArchivedAtFileState = process.states.findLast((state: any) => state.pcd_commitment['archived_at']); + if (lastArchivedAtFileState) { + const archivedAt = (await this.getPublicData(lastArchivedAtFileState.public_data['archived_at'])); + if (archivedAt) { + continue; + } + } + } catch (error) { } + + // We take the file in it's latest commited state + let file: any; + + // Which is the last state that updated file_blob? + const lastUpdatedFileNameState = process.states.findLast((state: any) => state.pcd_commitment['file_name']); + const lastUpdatedFileState = process.states.findLast((state: any) => state.pcd_commitment['file_blob']); + if (!lastUpdatedFileNameState || !lastUpdatedFileState) { + continue; + } + + try { + const fileName: string = (await this.getData(processId, lastUpdatedFileNameState.state_id)).file_name; + + const processData = await this.getData(processId, lastUpdatedFileState.state_id); + const isEmpty = Object.keys(processData).length === 0; + if (isEmpty) { + continue; + } + + const publicDataEncoded = lastUpdatedFileState.public_data; + if (!publicDataEncoded) { + continue; + } + + if (!file) { + file = { + processId, + lastUpdatedFileState, + processData, + publicDataDecoded, + }; + } else { + for (const key of Object.keys(processData)) { + file.processData[key] = processData[key]; + } + file.lastUpdatedFileState = lastUpdatedFileState; + for (const key of Object.keys(publicDataDecoded)) { + file.publicDataDecoded[key] = publicDataDecoded[key]; + } + } + file.processData.file_name = fileName; + } catch (error) { + console.error(error); + } + + files.push(file); + break; + } + + resolve(files[0]); + }).catch(reject); + }); + } + + public getFileByUtype(utype: string): Promise { + return new Promise((resolve: (files: any[]) => void, reject: (error: string) => void) => { + this.getProcesses().then(async (processes: any) => { + const files: any[] = []; + + for (const processId of Object.keys(processes)) { + const process = processes[processId]; + if (!process.states) { + continue; + } + + const publicDataDecoded: { [key: string]: any } = {}; + + // We only care about the public data as they are in the last commited state + const processTip = process.states[process.states.length - 1].commited_in; + const lastCommitedState = process.states.findLast((state: any) => state.commited_in !== processTip); + + if (!lastCommitedState) { + continue; + } + + const publicDataEncoded = lastCommitedState.public_data; + if (!publicDataEncoded) { + continue; + } + + for (const key of Object.keys(publicDataEncoded)) { + publicDataDecoded[key] = await this.getPublicData(publicDataEncoded[key]); + } + + if (!(publicDataDecoded['uid'] && publicDataDecoded['utype'] && publicDataDecoded['utype'] === utype && publicDataDecoded['isDeleted'] === 'false')) { + continue; + } + + try { + const lastArchivedAtFileState = process.states.findLast((state: any) => state.pcd_commitment['archived_at']); + if (lastArchivedAtFileState) { + const archivedAt = (await this.getPublicData(lastArchivedAtFileState.public_data['archived_at'])); + if (archivedAt) { + continue; + } + } + } catch (error) { } + // We take the file in it's latest commited state let file: any; -- 2.39.5