Compare commits
19 Commits
a6a67d4b7c
...
2213168f8e
Author | SHA1 | Date | |
---|---|---|---|
![]() |
2213168f8e | ||
![]() |
6ec7d8318e | ||
![]() |
cfad52c5ec | ||
![]() |
4c67ac5986 | ||
![]() |
3f413a885f | ||
![]() |
cf51fff97a | ||
![]() |
429d3243a4 | ||
![]() |
6f1f542dd2 | ||
![]() |
c8f7c3e08e | ||
![]() |
e4d8064abc | ||
![]() |
87483af243 | ||
![]() |
e081585fd9 | ||
![]() |
58d421ae57 | ||
![]() |
371ff69a35 | ||
![]() |
108419b381 | ||
![]() |
b97bbcd087 | ||
![]() |
0536b98ea8 | ||
![]() |
0986d60974 | ||
![]() |
a78666b4a9 |
1
.github/workflows/dev.yml
vendored
1
.github/workflows/dev.yml
vendored
@ -38,4 +38,5 @@ jobs:
|
||||
ssh: default
|
||||
tags: |
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:dev
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ gitea.sha }}
|
@ -9,6 +9,7 @@ const nextConfig = {
|
||||
// Will be available on both server and client
|
||||
NEXT_PUBLIC_BACK_API_PROTOCOL: process.env.NEXT_PUBLIC_BACK_API_PROTOCOL,
|
||||
NEXT_PUBLIC_BACK_API_HOST: process.env.NEXT_PUBLIC_BACK_API_HOST,
|
||||
NEXT_PUBLIC_BACK_API_PORT: process.env.NEXT_PUBLIC_BACK_API_PORT,
|
||||
NEXT_PUBLIC_BACK_API_ROOT_URL: process.env.NEXT_PUBLIC_BACK_API_ROOT_URL,
|
||||
NEXT_PUBLIC_BACK_API_VERSION: process.env.NEXT_PUBLIC_BACK_API_VERSION,
|
||||
NEXT_PUBLIC_FRONT_APP_HOST: process.env.NEXT_PUBLIC_FRONT_APP_HOST,
|
||||
@ -26,6 +27,7 @@ const nextConfig = {
|
||||
serverRuntimeConfig: {
|
||||
NEXT_PUBLIC_BACK_API_PROTOCOL: process.env.NEXT_PUBLIC_BACK_API_PROTOCOL,
|
||||
NEXT_PUBLIC_BACK_API_HOST: process.env.NEXT_PUBLIC_BACK_API_HOST,
|
||||
NEXT_PUBLIC_BACK_API_PORT: process.env.NEXT_PUBLIC_BACK_API_PORT,
|
||||
NEXT_PUBLIC_BACK_API_ROOT_URL: process.env.NEXT_PUBLIC_BACK_API_ROOT_URL,
|
||||
NEXT_PUBLIC_BACK_API_VERSION: process.env.NEXT_PUBLIC_BACK_API_VERSION,
|
||||
NEXT_PUBLIC_FRONT_APP_HOST: process.env.NEXT_PUBLIC_FRONT_APP_HOST,
|
||||
@ -43,6 +45,7 @@ const nextConfig = {
|
||||
env: {
|
||||
NEXT_PUBLIC_BACK_API_PROTOCOL: process.env.NEXT_PUBLIC_BACK_API_PROTOCOL,
|
||||
NEXT_PUBLIC_BACK_API_HOST: process.env.NEXT_PUBLIC_BACK_API_HOST,
|
||||
NEXT_PUBLIC_BACK_API_PORT: process.env.NEXT_PUBLIC_BACK_API_PORT,
|
||||
NEXT_PUBLIC_BACK_API_ROOT_URL: process.env.NEXT_PUBLIC_BACK_API_ROOT_URL,
|
||||
NEXT_PUBLIC_BACK_API_VERSION: process.env.NEXT_PUBLIC_BACK_API_VERSION,
|
||||
NEXT_PUBLIC_FRONT_APP_HOST: process.env.NEXT_PUBLIC_FRONT_APP_HOST,
|
||||
|
@ -7,6 +7,7 @@ import AbstractService from './AbstractService';
|
||||
import OfficeService from './OfficeService';
|
||||
import RoleService from './RoleService';
|
||||
import OfficeRoleService from './OfficeRoleService';
|
||||
import { DEFAULT_STORAGE_URLS } from '@Front/Config/AppConstants';
|
||||
|
||||
export default class CollaboratorService extends AbstractService {
|
||||
|
||||
@ -33,7 +34,7 @@ export default class CollaboratorService extends AbstractService {
|
||||
|
||||
const roles: any = {
|
||||
demiurge: {
|
||||
members: [...[ownerId], validatorId],
|
||||
members: [ownerId],
|
||||
validation_rules: [],
|
||||
storages: []
|
||||
},
|
||||
@ -41,28 +42,23 @@ export default class CollaboratorService extends AbstractService {
|
||||
members: [ownerId],
|
||||
validation_rules: [
|
||||
{
|
||||
quorum: 0.5,
|
||||
fields: [...privateFields, 'roles', 'uid', 'utype'],
|
||||
quorum: 1,
|
||||
fields: [...privateFields, 'roles', 'uid', 'utype', 'isDeleted'],
|
||||
min_sig_member: 1,
|
||||
},
|
||||
],
|
||||
storages: []
|
||||
storages: [...DEFAULT_STORAGE_URLS]
|
||||
},
|
||||
validator: {
|
||||
members: [validatorId],
|
||||
validation_rules: [
|
||||
{
|
||||
quorum: 0.5,
|
||||
fields: ['idCertified', 'roles'],
|
||||
quorum: 1,
|
||||
fields: [...privateFields, 'roles', 'uid', 'utype', 'isDeleted'],
|
||||
min_sig_member: 1,
|
||||
},
|
||||
{
|
||||
quorum: 0.0,
|
||||
fields: [...privateFields],
|
||||
min_sig_member: 0,
|
||||
},
|
||||
],
|
||||
storages: []
|
||||
storages: [...DEFAULT_STORAGE_URLS]
|
||||
},
|
||||
apophis: {
|
||||
members: [ownerId],
|
||||
@ -265,6 +261,7 @@ export default class CollaboratorService extends AbstractService {
|
||||
|
||||
if (process.processData.office) {
|
||||
const office: any = (await OfficeService.getOfficeByUid(process.processData.office.uid)).processData;
|
||||
if (office) {
|
||||
process.processData.office = {
|
||||
uid: office.uid,
|
||||
idNot: office.idNot,
|
||||
@ -277,14 +274,21 @@ export default class CollaboratorService extends AbstractService {
|
||||
progressiveProcess.processData.office = process.processData.office;
|
||||
progressCallback(JSON.parse(JSON.stringify(progressiveProcess)));
|
||||
}
|
||||
} else {
|
||||
console.error('Office not found');
|
||||
}
|
||||
}
|
||||
|
||||
if (process.processData.role) {
|
||||
const role: any = (await RoleService.getRoleByUid(process.processData.role.uid)).processData;
|
||||
if (!role) {
|
||||
console.error('Role not found');
|
||||
} else {
|
||||
process.processData.role = {
|
||||
uid: role.uid,
|
||||
name: role.name
|
||||
};
|
||||
}
|
||||
|
||||
if (progressCallback) {
|
||||
progressiveProcess.processData.role = process.processData.role;
|
||||
@ -294,6 +298,9 @@ export default class CollaboratorService extends AbstractService {
|
||||
|
||||
if (process.processData.office_role) {
|
||||
const officeRole: any = (await OfficeRoleService.getOfficeRoleByUid(process.processData.office_role.uid)).processData;
|
||||
if (!officeRole) {
|
||||
console.error('Office role not found');
|
||||
} else {
|
||||
process.processData.office_role = {
|
||||
uid: officeRole.uid,
|
||||
name: officeRole.name,
|
||||
@ -304,6 +311,7 @@ export default class CollaboratorService extends AbstractService {
|
||||
};
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
if (progressCallback) {
|
||||
progressiveProcess.processData.office_role = process.processData.office_role;
|
||||
|
@ -27,7 +27,8 @@ export default class DatabaseService {
|
||||
|
||||
try {
|
||||
// Construction de l'URL avec paramètres de pagination
|
||||
const url = `${publicRuntimeConfig.NEXT_PUBLIC_API_URL}/db/${tableName}?page=${page}&limit=${limit}`;
|
||||
const baseUrl = DatabaseService.buildBaseUrl();
|
||||
const url = `${baseUrl}/db/${tableName}?page=${page}&limit=${limit}`;
|
||||
|
||||
// Appel à l'API REST
|
||||
const response = await fetch(url, {
|
||||
@ -49,4 +50,28 @@ export default class DatabaseService {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construit l'URL de base en utilisant les variables d'environnement
|
||||
* @returns URL de base de l'API
|
||||
*/
|
||||
private static buildBaseUrl(): string {
|
||||
// Vérification des variables d'environnement requises
|
||||
const requiredVars = [
|
||||
'NEXT_PUBLIC_BACK_API_PROTOCOL',
|
||||
'NEXT_PUBLIC_BACK_API_HOST',
|
||||
'NEXT_PUBLIC_BACK_API_PORT',
|
||||
'NEXT_PUBLIC_BACK_API_ROOT_URL',
|
||||
'NEXT_PUBLIC_BACK_API_VERSION'
|
||||
];
|
||||
|
||||
for (const varName of requiredVars) {
|
||||
if (!publicRuntimeConfig[varName]) {
|
||||
throw new Error(`${varName} is not defined in environment variables`);
|
||||
}
|
||||
}
|
||||
|
||||
// Construction de l'URL de base
|
||||
return `${publicRuntimeConfig.NEXT_PUBLIC_BACK_API_PROTOCOL}${publicRuntimeConfig.NEXT_PUBLIC_BACK_API_HOST}:${publicRuntimeConfig.NEXT_PUBLIC_BACK_API_PORT}${publicRuntimeConfig.NEXT_PUBLIC_BACK_API_ROOT_URL}${publicRuntimeConfig.NEXT_PUBLIC_BACK_API_VERSION}`;
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import User from 'src/sdk/User';
|
||||
|
||||
import AbstractService from './AbstractService';
|
||||
|
||||
import DocumentTypeService from './DocumentTypeService';
|
||||
import { DEFAULT_STORAGE_URLS } from '@Front/Config/AppConstants';
|
||||
|
||||
export default class DeedTypeService extends AbstractService {
|
||||
|
||||
@ -12,7 +12,7 @@ export default class DeedTypeService extends AbstractService {
|
||||
super();
|
||||
}
|
||||
|
||||
public static createDeedType(deedTypeData: any, validatorId: string): Promise<any> {
|
||||
public static async createDeedType(deedTypeData: any, validatorId: string): Promise<{ processId: string, processData: any }> {
|
||||
const ownerId: string = User.getInstance().getPairingId()!;
|
||||
|
||||
const processData: any = {
|
||||
@ -25,104 +25,64 @@ export default class DeedTypeService extends AbstractService {
|
||||
};
|
||||
|
||||
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 allFields: string[] = [...privateFields, 'roles'];
|
||||
|
||||
const roles: any = {
|
||||
demiurge: {
|
||||
members: [...[ownerId], validatorId],
|
||||
members: [ownerId],
|
||||
validation_rules: [],
|
||||
storages: []
|
||||
},
|
||||
owner: {
|
||||
members: [ownerId],
|
||||
members: [ownerId, validatorId],
|
||||
validation_rules: [
|
||||
{
|
||||
quorum: 0.5,
|
||||
fields: [...privateFields, 'roles', 'uid', 'utype'],
|
||||
min_sig_member: 1,
|
||||
quorum: 0.01,
|
||||
fields: allFields,
|
||||
min_sig_member: 0.01,
|
||||
},
|
||||
],
|
||||
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: []
|
||||
storages: [...DEFAULT_STORAGE_URLS]
|
||||
},
|
||||
apophis: {
|
||||
members: [ownerId],
|
||||
members: [ownerId, validatorId],
|
||||
validation_rules: [],
|
||||
storages: []
|
||||
}
|
||||
};
|
||||
|
||||
return new Promise<any>((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.getDeedTypeByUid(processCreated.processData.uid).then(resolve).catch(reject);
|
||||
}).catch(reject);
|
||||
}).catch(reject);
|
||||
}).catch(reject);
|
||||
});
|
||||
try {
|
||||
const processCreated = await this.messageBus.createProcess(processData, privateFields, roles);
|
||||
await this.messageBus.notifyUpdate(processCreated.processId, processCreated.process.states[0].state_id);
|
||||
await this.messageBus.validateState(processCreated.processId, processCreated.process.states[0].state_id);
|
||||
const finalProcessData = await this.messageBus.getProcessData(processCreated.processId);
|
||||
|
||||
return { processId: processCreated.processId, processData: finalProcessData };
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
public static getDeedTypes(callback: (processes: any[]) => void, waitForAll: boolean = false): void {
|
||||
public static getDeedTypes(callback: (processes: any[]) => void): void {
|
||||
// Check if we have valid cache
|
||||
const items: any[] = this.getItems('_deed_types_');
|
||||
if (items.length > 0 && !waitForAll) {
|
||||
if (items.length > 0) {
|
||||
setTimeout(() => callback([...items]), 0);
|
||||
}
|
||||
|
||||
this.messageBus.getProcessesDecoded((publicValues: any) =>
|
||||
publicValues['uid'] &&
|
||||
publicValues['utype'] &&
|
||||
publicValues['utype'] === 'deedType' &&
|
||||
publicValues['isDeleted'] &&
|
||||
publicValues['isDeleted'] === 'false' &&
|
||||
!items.map((item: any) => item.processData.uid).includes(publicValues['uid'])
|
||||
).then(async (processes: any[]) => {
|
||||
this.messageBus.getProcessesDecoded((values: any) => {
|
||||
return values['utype'] === 'deedType'
|
||||
&& values['isDeleted'] === 'false';
|
||||
}).then(async (processes: any) => {
|
||||
if (processes.length === 0) {
|
||||
if (waitForAll) {
|
||||
callback([...items]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const updatedItems: any[] = [...items];
|
||||
|
||||
for (let processIndex = 0; processIndex < processes.length; processIndex++) {
|
||||
let process = processes[processIndex];
|
||||
|
||||
if (!waitForAll) {
|
||||
process = await this.completeDeedType(process, (processInProgress: any) => {
|
||||
const currentItems: any[] = [...updatedItems];
|
||||
|
||||
const existingIndex: number = currentItems.findIndex(item => item.processData?.uid === processInProgress.processData?.uid);
|
||||
if (existingIndex >= 0) {
|
||||
currentItems[existingIndex] = processInProgress;
|
||||
} else {
|
||||
currentItems.push(processInProgress);
|
||||
}
|
||||
|
||||
callback(currentItems);
|
||||
});
|
||||
} else {
|
||||
process = await this.completeDeedType(process);
|
||||
}
|
||||
const process = processes[processIndex];
|
||||
|
||||
// Update cache
|
||||
this.setItem('_deed_types_', process);
|
||||
@ -133,90 +93,33 @@ export default class DeedTypeService extends AbstractService {
|
||||
} else {
|
||||
updatedItems.push(process);
|
||||
}
|
||||
|
||||
if (!waitForAll) {
|
||||
callback([...updatedItems]);
|
||||
}
|
||||
}
|
||||
|
||||
if (waitForAll) {
|
||||
callback([...updatedItems]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static getDeedTypeByUid(uid: string): Promise<any> {
|
||||
// Check if we have valid cache
|
||||
const item: any = this.getItem('_deed_types_', uid);
|
||||
if (item) {
|
||||
return Promise.resolve(item);
|
||||
}
|
||||
public static async updateDeedType(processId: string, newData: any): Promise<void> {
|
||||
try {
|
||||
const processUpdated = await this.messageBus.updateProcess(
|
||||
processId,
|
||||
{ updated_at: new Date().toISOString(), ...newData },
|
||||
[],
|
||||
null
|
||||
);
|
||||
|
||||
return new Promise<any>((resolve: (process: any) => void, reject: (error: string) => void) => {
|
||||
this.messageBus.getProcessesDecoded((publicValues: any) =>
|
||||
publicValues['uid'] &&
|
||||
publicValues['uid'] === uid &&
|
||||
publicValues['utype'] &&
|
||||
publicValues['utype'] === 'deedType' &&
|
||||
publicValues['isDeleted'] &&
|
||||
publicValues['isDeleted'] === 'false'
|
||||
).then(async (processes: any[]) => {
|
||||
if (processes.length === 0) {
|
||||
resolve(null);
|
||||
} else {
|
||||
let process: any = processes[0];
|
||||
process = await this.completeDeedType(process);
|
||||
|
||||
// Update cache
|
||||
this.setItem('_deed_types_', process);
|
||||
|
||||
resolve(process);
|
||||
}
|
||||
}).catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
public static updateDeedType(process: any, newData: any): Promise<void> {
|
||||
return new Promise<void>((resolve: () => 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(() => {
|
||||
await this.messageBus.notifyUpdate(processId, newStateId);
|
||||
await this.messageBus.validateState(processId, newStateId);
|
||||
|
||||
const processData = await this.messageBus.getProcessData(processId);
|
||||
|
||||
// Update cache
|
||||
this.setItem('_deed_types_', process);
|
||||
|
||||
resolve();
|
||||
}).catch((error) => console.error('Failed to validate state', error));
|
||||
}).catch((error) => console.error('Failed to notify update', error));
|
||||
}).catch((error) => console.error('Failed to update', error));
|
||||
});
|
||||
}
|
||||
|
||||
private static async completeDeedType(process: any, progressCallback?: (processInProgress: any) => void): Promise<any> {
|
||||
const progressiveProcess: any = JSON.parse(JSON.stringify(process));
|
||||
|
||||
if (process.processData.document_types && process.processData.document_types.length > 0) {
|
||||
progressiveProcess.processData.document_types = [];
|
||||
if (progressCallback) {
|
||||
progressCallback(progressiveProcess);
|
||||
}
|
||||
|
||||
for (const document_type of process.processData.document_types) {
|
||||
const documentTypeData = (await DocumentTypeService.getDocumentTypeByUid(document_type.uid)).processData;
|
||||
progressiveProcess.processData.document_types.push(documentTypeData);
|
||||
|
||||
// Remove duplicates
|
||||
progressiveProcess.processData.document_types = progressiveProcess.processData.document_types
|
||||
.filter((item: any, index: number) => progressiveProcess.processData.document_types.findIndex((t: any) => t.uid === item.uid) === index);
|
||||
|
||||
if (progressCallback) {
|
||||
progressCallback(JSON.parse(JSON.stringify(progressiveProcess)));
|
||||
this.setItem('_deed_types_', processData);
|
||||
} catch (error) {
|
||||
console.error('Failed to update deed type:', error);
|
||||
throw error; // Re-throw to allow caller to handle
|
||||
}
|
||||
}
|
||||
|
||||
process.processData.document_types = progressiveProcess.processData.document_types;
|
||||
}
|
||||
|
||||
return process;
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import { v4 as uuidv4 } from 'uuid';
|
||||
import User from 'src/sdk/User';
|
||||
|
||||
import AbstractService from './AbstractService';
|
||||
import { DEFAULT_STORAGE_URLS } from '@Front/Config/AppConstants';
|
||||
|
||||
export default class DocumentTypeService extends AbstractService {
|
||||
|
||||
@ -10,7 +11,7 @@ export default class DocumentTypeService extends AbstractService {
|
||||
super();
|
||||
}
|
||||
|
||||
public static createDocumentType(documentTypeData: any, validatorId: string): Promise<any> {
|
||||
public static createDocumentType(documentTypeData: any, validatorId: string): Promise<{ processId: string, processData: any }> {
|
||||
const ownerId: string = User.getInstance().getPairingId()!;
|
||||
|
||||
const processData: any = {
|
||||
@ -23,45 +24,27 @@ export default class DocumentTypeService extends AbstractService {
|
||||
};
|
||||
|
||||
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 allFields: string[] = [...privateFields, 'roles'];
|
||||
|
||||
const roles: any = {
|
||||
demiurge: {
|
||||
members: [...[ownerId], validatorId],
|
||||
members: [ownerId],
|
||||
validation_rules: [],
|
||||
storages: []
|
||||
},
|
||||
owner: {
|
||||
members: [ownerId],
|
||||
members: [ownerId, validatorId],
|
||||
validation_rules: [
|
||||
{
|
||||
quorum: 0.5,
|
||||
fields: [...privateFields, 'roles', 'uid', 'utype'],
|
||||
min_sig_member: 1,
|
||||
quorum: 0.01,
|
||||
fields: allFields,
|
||||
min_sig_member: 0.01,
|
||||
},
|
||||
],
|
||||
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: []
|
||||
storages: [...DEFAULT_STORAGE_URLS]
|
||||
},
|
||||
apophis: {
|
||||
members: [ownerId],
|
||||
members: [ownerId, validatorId],
|
||||
validation_rules: [],
|
||||
storages: []
|
||||
}
|
||||
@ -71,39 +54,80 @@ export default class DocumentTypeService extends AbstractService {
|
||||
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.getDocumentTypeByUid(processCreated.processData.uid).then(resolve).catch(reject);
|
||||
this.messageBus.getProcessData(processCreated.processId).then((processData: any) => {
|
||||
resolve({ processId: processCreated.processId, processData: processData });
|
||||
}).catch(reject);
|
||||
}).catch(reject);
|
||||
}).catch(reject);
|
||||
}).catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
public static getDocumentTypes(): Promise<any[]> {
|
||||
public static getDocumentTypes(callback: (processes: any[]) => void): void {
|
||||
// Check if we have valid cache
|
||||
const items: any[] = this.getItems('_document_types_');
|
||||
if (items.length > 0) {
|
||||
setTimeout(() => callback([...items]), 0);
|
||||
}
|
||||
|
||||
return this.messageBus.getProcessesDecoded((publicValues: any) =>
|
||||
publicValues['uid'] &&
|
||||
publicValues['utype'] &&
|
||||
publicValues['utype'] === 'documentType' &&
|
||||
publicValues['isDeleted'] &&
|
||||
publicValues['isDeleted'] === 'false' &&
|
||||
!items.map((item: any) => item.processData.uid).includes(publicValues['uid'])
|
||||
).then(async (processes: any[]) => {
|
||||
this.messageBus.getProcessesDecoded((values: any) => {
|
||||
return values['utype'] === 'documentType'
|
||||
&& values['isDeleted'] === 'false';
|
||||
}).then(async (processes: any) => {
|
||||
if (processes.length === 0) {
|
||||
return items;
|
||||
} else {
|
||||
for (const process of processes) {
|
||||
callback([...items]);
|
||||
return;
|
||||
}
|
||||
|
||||
const updatedItems: any[] = [...items];
|
||||
|
||||
for (let processIndex = 0; processIndex < processes.length; processIndex++) {
|
||||
const process = processes[processIndex];
|
||||
|
||||
// Update cache
|
||||
this.setItem('_document_types_', process);
|
||||
|
||||
items.push(process);
|
||||
const existingIndex: number = updatedItems.findIndex(item => item.processId === process.processId);
|
||||
if (existingIndex >= 0) {
|
||||
updatedItems[existingIndex] = process;
|
||||
} else {
|
||||
updatedItems.push(process);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
callback([...updatedItems]);
|
||||
});
|
||||
}
|
||||
|
||||
public static getDocumentTypeByProcessId(processId: string): Promise<any> {
|
||||
// Check if we have valid cache
|
||||
const item: any = this.getItem('_document_types_', processId);
|
||||
if (item) {
|
||||
return Promise.resolve(item);
|
||||
}
|
||||
|
||||
return new Promise<any>((resolve: (process: any) => void, reject: (error: string) => void) => {
|
||||
this.messageBus.getProcessesDecoded((publicValues: any) => {
|
||||
return publicValues['utype'] === 'documentType' && publicValues['isDeleted'] === 'false';
|
||||
}).then((processes: any[]) => {
|
||||
// Find the process with matching processId
|
||||
const process = processes.find((p: any) => p.processId === processId);
|
||||
|
||||
if (!process) {
|
||||
resolve(null);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update cache
|
||||
this.setItem('_document_types_', process);
|
||||
|
||||
resolve(process);
|
||||
}).catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
// Keep the old method for backward compatibility but mark as deprecated
|
||||
/** @deprecated Use getDocumentTypeByProcessId instead */
|
||||
public static getDocumentTypeByUid(uid: string): Promise<any> {
|
||||
// Check if we have valid cache
|
||||
const item: any = this.getItem('_document_types_', uid);
|
||||
@ -133,10 +157,9 @@ export default class DocumentTypeService extends AbstractService {
|
||||
const newStateId: string = processUpdated.diffs[0]?.state_id;
|
||||
this.messageBus.notifyUpdate(process.processId, newStateId).then(() => {
|
||||
this.messageBus.validateState(process.processId, newStateId).then((_stateValidated) => {
|
||||
const documentTypeUid: string = process.processData.uid;
|
||||
this.removeItem('_document_types_', documentTypeUid);
|
||||
this.removeItem('_document_types_', process.processId);
|
||||
|
||||
this.getDocumentTypeByUid(documentTypeUid).then(resolve).catch(reject);
|
||||
this.getDocumentTypeByProcessId(process.processId).then(resolve).catch(reject);
|
||||
}).catch(reject);
|
||||
}).catch(reject);
|
||||
}).catch(reject);
|
||||
|
@ -8,6 +8,9 @@ import RuleService from './RuleService';
|
||||
import RuleGroupService from './RuleGroupService';
|
||||
import RoleService from './RoleService';
|
||||
import OfficeRoleService from './OfficeRoleService';
|
||||
import { DEFAULT_VALIDATOR_ID } from '@Front/Config/AppConstants';
|
||||
|
||||
const mandatoryRoles = ['Notaire', 'Collaborateur'];
|
||||
|
||||
/**
|
||||
* Type pour le callback de progression
|
||||
@ -85,9 +88,13 @@ export default class ImportData {
|
||||
|
||||
// Exécuter l'étape et stocker le résultat si nécessaire
|
||||
const result = await step.function(stepProgressCallback, results);
|
||||
if (result) {
|
||||
if (result !== undefined) {
|
||||
results.push(result);
|
||||
} else {
|
||||
// Push empty array to maintain consistent indexing
|
||||
results.push([]);
|
||||
}
|
||||
console.log(`Step ${i} (${step.name}): ${result?.length || 0} items`);
|
||||
}
|
||||
|
||||
if (!await this.isDone()) {
|
||||
@ -122,7 +129,7 @@ export default class ImportData {
|
||||
|
||||
const roles: any = {
|
||||
demiurge: {
|
||||
members: [...[ownerId], validatorId],
|
||||
members: [ownerId],
|
||||
validation_rules: [],
|
||||
storages: []
|
||||
},
|
||||
@ -172,6 +179,7 @@ export default class ImportData {
|
||||
}
|
||||
|
||||
private static async importRules(onProgress?: (progress: number, description?: string) => void): Promise<any[]> {
|
||||
console.log('Importing rules');
|
||||
const rules: any[] = [];
|
||||
|
||||
const INIT_PROGRESS = 0;
|
||||
@ -201,10 +209,14 @@ export default class ImportData {
|
||||
const existingRules: any[] = (await RuleService.getRules()).map((process: any) => process.processData);
|
||||
const filteredRules: any[] = result.data.filter((rule: any) => !existingRules.some((existingRule: any) => existingRule.uid === rule.uid));
|
||||
|
||||
if (filteredRules.length === 0) {
|
||||
console.debug('All rules already imported');
|
||||
}
|
||||
|
||||
const totalFilteredRules = filteredRules.length;
|
||||
for (let i = 0; i < totalFilteredRules; i++) {
|
||||
const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';
|
||||
rules.push((await RuleService.createRule(filteredRules[i], validatorId)).processData);
|
||||
console.log(`Adding rule ${filteredRules[i].name}`);
|
||||
rules.push((await RuleService.createRule(filteredRules[i], DEFAULT_VALIDATOR_ID)).processData);
|
||||
|
||||
const progressRange = CREATE_END_PROGRESS - CREATE_START_PROGRESS;
|
||||
const ruleProgressIncrement = progressRange / (totalFilteredRules * totalPages);
|
||||
@ -225,6 +237,7 @@ export default class ImportData {
|
||||
}
|
||||
|
||||
private static async importRuleGroups(onProgress?: (progress: number, description?: string) => void): Promise<any[]> {
|
||||
console.log('Importing rule groups');
|
||||
const ruleGroups: any[] = [];
|
||||
|
||||
const INIT_PROGRESS = 0;
|
||||
@ -256,8 +269,8 @@ export default class ImportData {
|
||||
|
||||
const totalFilteredRuleGroups = filteredRuleGroups.length;
|
||||
for (let i = 0; i < totalFilteredRuleGroups; i++) {
|
||||
const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';
|
||||
ruleGroups.push((await RuleGroupService.createRuleGroup(filteredRuleGroups[i], validatorId)).processData);
|
||||
console.log(`Adding rule group ${filteredRuleGroups[i].name}`);
|
||||
ruleGroups.push((await RuleGroupService.createRuleGroup(filteredRuleGroups[i], DEFAULT_VALIDATOR_ID)).processData);
|
||||
|
||||
const progressRange = CREATE_END_PROGRESS - CREATE_START_PROGRESS;
|
||||
const ruleProgressIncrement = progressRange / (totalFilteredRuleGroups * totalPages);
|
||||
@ -278,6 +291,7 @@ export default class ImportData {
|
||||
}
|
||||
|
||||
private static async importRoles(onProgress?: (progress: number, description?: string) => void): Promise<any[]> {
|
||||
console.log('Importing roles');
|
||||
// Constantes de progression - pourraient être paramétrées
|
||||
const INIT_PROGRESS = 0;
|
||||
const FETCH_PROGRESS = 30;
|
||||
@ -309,10 +323,14 @@ export default class ImportData {
|
||||
onProgress?.(FETCH_PROGRESS, 'Récupération des rôles existants');
|
||||
const roles: any[] = processes.map((process: any) => process.processData);
|
||||
if (roles.length === 0) {
|
||||
const defaultRolesNames: string[] = defaultRoles.map((role: any) => role.name);
|
||||
const totalRoles = defaultRoles.length;
|
||||
for (let i = 0; i < totalRoles; i++) {
|
||||
const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';
|
||||
roles.push((await RoleService.createRole(defaultRoles[i], validatorId)).processData);
|
||||
if (!defaultRolesNames.includes(roles[i].name)) {
|
||||
roles.push((await RoleService.createRole(defaultRoles[i], DEFAULT_VALIDATOR_ID)).processData);
|
||||
} else {
|
||||
console.log(`Role ${defaultRoles[i].name} already exists`);
|
||||
}
|
||||
|
||||
// Progression dynamique pendant la création des rôles
|
||||
const progressRange = CREATE_END_PROGRESS - CREATE_START_PROGRESS;
|
||||
@ -326,54 +344,166 @@ export default class ImportData {
|
||||
});
|
||||
}
|
||||
|
||||
private static async importOfficeRoles(office: any, ruleGroups: any[], onProgress?: (progress: number, description?: string) => void): Promise<any[]> {
|
||||
// Constantes de progression - pourraient être paramétrées
|
||||
const INIT_PROGRESS = 0;
|
||||
const FETCH_PROGRESS = 30;
|
||||
const CREATE_START_PROGRESS = FETCH_PROGRESS;
|
||||
const CREATE_END_PROGRESS = 90;
|
||||
const FINAL_PROGRESS = 100;
|
||||
private static async importDefaultRoles(officeUid: string, ruleGroups: any[], onProgress?: (progress: number, description?: string) => void): Promise<any[]> {
|
||||
console.log('Importing default roles');
|
||||
let officeRoles: any[] = [];
|
||||
|
||||
onProgress?.(INIT_PROGRESS, 'Initialisation');
|
||||
return await new Promise<any[]>((resolve: (roles: any[]) => void) => {
|
||||
const CREATE_START_PROGRESS = 60;
|
||||
const CREATE_END_PROGRESS = 90;
|
||||
|
||||
onProgress?.(CREATE_START_PROGRESS, 'Création des rôles par défaut');
|
||||
|
||||
// Prepare the collaborator rules from rule groups
|
||||
const collaboratorRules: any[] = ruleGroups
|
||||
.map((ruleGroup: any) => ruleGroup.rules)
|
||||
.map((ruleGroup: any) => ruleGroup.rules || [])
|
||||
.reduce((acc: any, curr: any) => [...acc, ...curr], [])
|
||||
.map((rule: any) => ({ uid: rule.uid }));
|
||||
|
||||
const defaultOfficeRoles: any[] = [
|
||||
{
|
||||
name: 'Notaire',
|
||||
office: {
|
||||
uid: office.uid
|
||||
},
|
||||
rules: collaboratorRules
|
||||
},
|
||||
{
|
||||
name: 'Collaborateur',
|
||||
office: {
|
||||
uid: office.uid
|
||||
}
|
||||
}
|
||||
];
|
||||
OfficeRoleService.getOfficeRoles().then(async (processes: any[]) => {
|
||||
onProgress?.(FETCH_PROGRESS, 'Récupération des rôles d\'office existants');
|
||||
const officeRoles: any[] = processes.map((process: any) => process.processData);
|
||||
if (officeRoles.length === 0) {
|
||||
const totalOfficeRoles = defaultOfficeRoles.length;
|
||||
for (let i = 0; i < totalOfficeRoles; i++) {
|
||||
const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';
|
||||
officeRoles.push((await OfficeRoleService.createOfficeRole(defaultOfficeRoles[i], validatorId)).processData);
|
||||
console.log(`Found ${collaboratorRules.length} collaborator rules from ${ruleGroups.length} rule groups`);
|
||||
|
||||
// Get fresh list of existing roles (including ones we just created)
|
||||
const updatedExistingRoles = await OfficeRoleService.getOfficeRoles();
|
||||
const existingRoles = updatedExistingRoles
|
||||
.map((role: any) => role.processData)
|
||||
.filter((roleData: any) => roleData.office?.uid === officeUid);
|
||||
|
||||
const existingRoleNames = existingRoles.map((role: any) => role.name);
|
||||
|
||||
const missingMandatoryRoles = mandatoryRoles.filter(roleName =>
|
||||
!existingRoleNames.includes(roleName)
|
||||
);
|
||||
|
||||
console.log(`Found ${existingRoleNames.length} existing roles, ${missingMandatoryRoles.length} mandatory roles missing`);
|
||||
|
||||
if (missingMandatoryRoles.length === 0) {
|
||||
onProgress?.(CREATE_END_PROGRESS, 'Tous les rôles obligatoires existent déjà');
|
||||
return officeRoles;
|
||||
}
|
||||
|
||||
for (let i = 0; i < missingMandatoryRoles.length; i++) {
|
||||
const roleName = missingMandatoryRoles[i];
|
||||
const fallbackRole = {
|
||||
name: roleName,
|
||||
office: { uid: officeUid },
|
||||
// Only Notaire gets rules, Collaborateur gets none
|
||||
...(roleName === 'Notaire' && { rules: collaboratorRules })
|
||||
};
|
||||
|
||||
console.log(`Creating missing mandatory role: ${roleName}`);
|
||||
|
||||
officeRoles.push((await OfficeRoleService.createOfficeRole(fallbackRole, DEFAULT_VALIDATOR_ID)).processData);
|
||||
|
||||
// Progression dynamique pendant la création des rôles d'office
|
||||
const progressRange = CREATE_END_PROGRESS - CREATE_START_PROGRESS;
|
||||
const progress = CREATE_START_PROGRESS + ((i + 1) / totalOfficeRoles) * progressRange;
|
||||
onProgress?.(progress, `Création du rôle d'office ${i + 1}/${totalOfficeRoles} : ${defaultOfficeRoles[i].name}`);
|
||||
const progress = CREATE_START_PROGRESS + ((i + 1) / missingMandatoryRoles.length) * progressRange;
|
||||
onProgress?.(progress, `Création rôle obligatoire ${i + 1}/${missingMandatoryRoles.length} - ${roleName}`);
|
||||
}
|
||||
|
||||
return officeRoles;
|
||||
}
|
||||
|
||||
private static async importOfficeRoles(office: any, ruleGroups: any[], onProgress?: (progress: number, description?: string) => void): Promise<any[]> {
|
||||
console.log('Importing office roles');
|
||||
let officeRoles: any[] = [];
|
||||
const officeUid = office.processData?.uid;
|
||||
if (!officeUid) {
|
||||
console.error('Office UID is not set');
|
||||
return officeRoles;
|
||||
}
|
||||
console.log(`Processing ${ruleGroups.length} rule groups for office ${officeUid}`);
|
||||
|
||||
const INIT_PROGRESS = 0;
|
||||
const FETCH_PROGRESS = 30;
|
||||
const CREATE_END_PROGRESS = 90;
|
||||
const FINAL_PROGRESS = 100;
|
||||
onProgress?.(INIT_PROGRESS, 'Initialisation');
|
||||
|
||||
let page = 1;
|
||||
let limit = 10;
|
||||
let totalPages = 1;
|
||||
|
||||
onProgress?.(FETCH_PROGRESS, 'Récupération des rôles d\'office existants');
|
||||
let result = await DatabaseService.getTableData('office_roles', page, limit);
|
||||
if (result && result.success && result.pagination) {
|
||||
totalPages = result.pagination.totalPages || 1;
|
||||
}
|
||||
|
||||
const FETCH_PAGE_PROGRESS_START = FETCH_PROGRESS;
|
||||
const FETCH_PAGE_PROGRESS_END = 60;
|
||||
const CREATE_START_PROGRESS = 60;
|
||||
|
||||
// Collect all office roles for this office from all pages
|
||||
const allOfficeRolesForThisOffice: any[] = [];
|
||||
while (result && result.success) {
|
||||
const fetchPageProgress = FETCH_PAGE_PROGRESS_START + ((page / totalPages) * (FETCH_PAGE_PROGRESS_END - FETCH_PAGE_PROGRESS_START));
|
||||
onProgress?.(fetchPageProgress, `Page ${page}/${totalPages} : Récupération des rôles d'office`);
|
||||
|
||||
// Collect office roles for this office from current page
|
||||
const officeRolesFromPage = result.data.filter((officeRole: any) =>
|
||||
officeRole.office?.uid === officeUid
|
||||
);
|
||||
allOfficeRolesForThisOffice.push(...officeRolesFromPage);
|
||||
|
||||
if (!result.pagination.hasNextPage) {
|
||||
break;
|
||||
}
|
||||
page++;
|
||||
result = await DatabaseService.getTableData('office_roles', page, limit);
|
||||
}
|
||||
|
||||
console.log(`Found ${allOfficeRolesForThisOffice.length} office roles in database for this office`);
|
||||
|
||||
if (allOfficeRolesForThisOffice.length === 0) {
|
||||
console.log('No office roles found in database, creating defaults');
|
||||
return await this.importDefaultRoles(officeUid, ruleGroups, onProgress);
|
||||
}
|
||||
|
||||
// Get all existing office role processes (to avoid duplicates)
|
||||
const existingOfficeRoles: any[] = await OfficeRoleService.getOfficeRoles();
|
||||
const existingOfficeRoleUids = existingOfficeRoles.map((existingRole: any) =>
|
||||
existingRole.processData.uid
|
||||
);
|
||||
|
||||
console.log(`Found ${existingOfficeRoles.length} existing office role processes`);
|
||||
|
||||
// Import all office roles found in database (if not already imported)
|
||||
const dbRolesToImport = allOfficeRolesForThisOffice.filter((dbRole: any) =>
|
||||
!existingOfficeRoleUids.includes(dbRole.uid)
|
||||
);
|
||||
|
||||
console.log(`Importing ${dbRolesToImport.length} new office roles from database`);
|
||||
|
||||
for (let i = 0; i < dbRolesToImport.length; i++) {
|
||||
const roleData = dbRolesToImport[i];
|
||||
|
||||
// Ensure office UID is set correctly
|
||||
if (!roleData.office) {
|
||||
roleData.office = { uid: officeUid };
|
||||
} else if (!roleData.office.uid) {
|
||||
roleData.office.uid = officeUid;
|
||||
}
|
||||
|
||||
console.log(`Importing office role: ${roleData.name}`);
|
||||
|
||||
officeRoles.push((await OfficeRoleService.createOfficeRole(roleData, DEFAULT_VALIDATOR_ID)).processData);
|
||||
|
||||
const progressRange = (CREATE_END_PROGRESS - CREATE_START_PROGRESS) * 0.7; // 70% for db imports
|
||||
const progress = CREATE_START_PROGRESS + ((i + 1) / dbRolesToImport.length) * progressRange;
|
||||
onProgress?.(progress, `Import base de données ${i + 1}/${dbRolesToImport.length} - ${roleData.name}`);
|
||||
}
|
||||
|
||||
// Now check for mandatory roles and create any missing ones
|
||||
const mandatoryRolesProgress = CREATE_START_PROGRESS + (CREATE_END_PROGRESS - CREATE_START_PROGRESS) * 0.7;
|
||||
onProgress?.(mandatoryRolesProgress, 'Vérification des rôles obligatoires');
|
||||
|
||||
const defaultRolesCreated = await this.importDefaultRoles(officeUid, ruleGroups, (subProgress, description) => {
|
||||
// Map sub-progress to remaining 20% of total progress
|
||||
const mappedProgress = mandatoryRolesProgress + (subProgress - 60) * 0.3 / 30; // Scale 60-90 to remaining 30%
|
||||
onProgress?.(mappedProgress, description);
|
||||
});
|
||||
|
||||
officeRoles.push(...defaultRolesCreated);
|
||||
|
||||
onProgress?.(FINAL_PROGRESS, 'Importation des rôles d\'office terminée');
|
||||
resolve(officeRoles);
|
||||
});
|
||||
});
|
||||
return officeRoles;
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import AbstractService from './AbstractService';
|
||||
|
||||
import OfficeService from './OfficeService';
|
||||
import RuleService from './RuleService';
|
||||
import { DEFAULT_STORAGE_URLS } from '@Front/Config/AppConstants';
|
||||
|
||||
export default class OfficeRoleService extends AbstractService {
|
||||
|
||||
@ -32,7 +33,7 @@ export default class OfficeRoleService extends AbstractService {
|
||||
|
||||
const roles: any = {
|
||||
demiurge: {
|
||||
members: [...[ownerId], validatorId],
|
||||
members: [ownerId],
|
||||
validation_rules: [],
|
||||
storages: []
|
||||
},
|
||||
@ -40,31 +41,26 @@ export default class OfficeRoleService extends AbstractService {
|
||||
members: [ownerId],
|
||||
validation_rules: [
|
||||
{
|
||||
quorum: 0.5,
|
||||
fields: [...privateFields, 'roles', 'uid', 'utype'],
|
||||
min_sig_member: 1,
|
||||
quorum: 0.01,
|
||||
fields: [...privateFields, 'roles', 'uid', 'utype', 'isDeleted'],
|
||||
min_sig_member: 0.01,
|
||||
},
|
||||
],
|
||||
storages: []
|
||||
storages: [...DEFAULT_STORAGE_URLS]
|
||||
},
|
||||
validator: {
|
||||
members: [validatorId],
|
||||
validation_rules: [
|
||||
{
|
||||
quorum: 0.5,
|
||||
fields: ['idCertified', 'roles'],
|
||||
quorum: 1,
|
||||
fields: [...privateFields, 'roles', 'uid', 'utype', 'isDeleted'],
|
||||
min_sig_member: 1,
|
||||
},
|
||||
{
|
||||
quorum: 0.0,
|
||||
fields: [...privateFields],
|
||||
min_sig_member: 0,
|
||||
},
|
||||
],
|
||||
storages: []
|
||||
storages: [...DEFAULT_STORAGE_URLS]
|
||||
},
|
||||
apophis: {
|
||||
members: [ownerId],
|
||||
members: [ownerId, validatorId],
|
||||
validation_rules: [],
|
||||
storages: []
|
||||
}
|
||||
@ -97,8 +93,6 @@ export default class OfficeRoleService extends AbstractService {
|
||||
return items;
|
||||
} else {
|
||||
for (let process of processes) {
|
||||
process = await this.completeOfficeRole(process);
|
||||
|
||||
// Update cache
|
||||
this.setItem('_office_roles_', process);
|
||||
|
||||
@ -125,14 +119,11 @@ export default class OfficeRoleService extends AbstractService {
|
||||
publicValues['isDeleted'] &&
|
||||
publicValues['isDeleted'] === 'false'
|
||||
).then(async (processes: any[]) => {
|
||||
if (processes.length === 0) {
|
||||
if (processes.length !== 1) {
|
||||
resolve(null);
|
||||
} else {
|
||||
let process: any = processes[0];
|
||||
process = await this.completeOfficeRole(process);
|
||||
|
||||
// Update cache
|
||||
this.setItem('_office_roles_', process);
|
||||
this.setItem('_office_roles_', processes[0]);
|
||||
|
||||
resolve(process);
|
||||
}
|
||||
@ -156,24 +147,4 @@ export default class OfficeRoleService extends AbstractService {
|
||||
});
|
||||
}
|
||||
|
||||
private static async completeOfficeRole(process: any): Promise<any> {
|
||||
if (process.processData.office) {
|
||||
process.processData.office = await new Promise<any>(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<any[]>(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;
|
||||
}
|
||||
}
|
||||
|
@ -10,9 +10,12 @@ export default class OfficeService extends AbstractService {
|
||||
super();
|
||||
}
|
||||
|
||||
public static createOffice(officeData: any, validatorId: string): Promise<any> {
|
||||
public static createOffice(officeData: any, owners: string[], validatorId: string, storageUrls: string[]): Promise<any> {
|
||||
const ownerId: string = User.getInstance().getPairingId()!;
|
||||
|
||||
// Create a set for all owners to avoid duplicates
|
||||
const ownersSet: Set<string> = new Set([...owners, ownerId]);
|
||||
|
||||
const processData: any = {
|
||||
uid: uuidv4(),
|
||||
utype: 'office',
|
||||
@ -29,39 +32,34 @@ export default class OfficeService extends AbstractService {
|
||||
|
||||
const roles: any = {
|
||||
demiurge: {
|
||||
members: [...[ownerId], validatorId],
|
||||
members: Array.from(ownersSet),
|
||||
validation_rules: [],
|
||||
storages: []
|
||||
},
|
||||
owner: {
|
||||
members: [ownerId],
|
||||
members: Array.from(ownersSet),
|
||||
validation_rules: [
|
||||
{
|
||||
quorum: 0.5,
|
||||
fields: [...privateFields, 'roles', 'uid', 'utype'],
|
||||
min_sig_member: 1,
|
||||
quorum: 0.01, // effectively any owner can make any change
|
||||
fields: [...privateFields, 'roles', 'uid', 'utype', 'isDeleted'],
|
||||
min_sig_member: 0.01, // need to sign with at least one device
|
||||
},
|
||||
],
|
||||
storages: []
|
||||
storages: storageUrls
|
||||
},
|
||||
validator: {
|
||||
members: [validatorId],
|
||||
validation_rules: [
|
||||
{
|
||||
quorum: 0.5,
|
||||
fields: ['idCertified', 'roles'],
|
||||
quorum: 1, // validator can do anything alone
|
||||
fields: [...privateFields, 'roles', 'uid', 'utype', 'isDeleted'],
|
||||
min_sig_member: 1,
|
||||
},
|
||||
{
|
||||
quorum: 0.0,
|
||||
fields: [...privateFields],
|
||||
min_sig_member: 0,
|
||||
},
|
||||
],
|
||||
storages: []
|
||||
storages: storageUrls
|
||||
},
|
||||
apophis: {
|
||||
members: [ownerId],
|
||||
members: Array.from(ownersSet), // any owner can terminate the office
|
||||
validation_rules: [],
|
||||
storages: []
|
||||
}
|
||||
@ -149,4 +147,43 @@ export default class OfficeService extends AbstractService {
|
||||
}).catch(reject);
|
||||
});
|
||||
}
|
||||
public static addCollaborators(process: any, existingRoles: any, collaborators: any[]): Promise<void> {
|
||||
return new Promise<void>((resolve: () => void, reject: (error: string) => void) => {
|
||||
const newRoles: any = existingRoles;
|
||||
const owners: string[] = newRoles['owner'].members;
|
||||
if (!owners) {
|
||||
console.error('[addCollaborators] owner role not found');
|
||||
return;
|
||||
}
|
||||
|
||||
const previousOwnersLength: number = owners.length;
|
||||
for (const collaborator of collaborators) {
|
||||
if (owners.includes(collaborator)) {
|
||||
console.debug('[addCollaborators] collaborator already in owner role');
|
||||
continue;
|
||||
} else {
|
||||
owners.push(collaborator);
|
||||
}
|
||||
}
|
||||
|
||||
if (previousOwnersLength === owners.length) {
|
||||
console.error('[addCollaborators] no new collaborators added');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('newRoles : ', newRoles);
|
||||
this.messageBus.updateProcess(process.processId, { updated_at: new Date().toISOString() }, [], newRoles).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 officeUid: string = process.processData.uid;
|
||||
this.removeItem('_offices_', officeUid);
|
||||
|
||||
this.getOfficeByUid(officeUid).then(resolve).catch(reject);
|
||||
}).catch(reject);
|
||||
}).catch(reject);
|
||||
}).catch(reject);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import { v4 as uuidv4 } from 'uuid';
|
||||
import User from 'src/sdk/User';
|
||||
|
||||
import AbstractService from './AbstractService';
|
||||
import { DEFAULT_STORAGE_URLS } from '@Front/Config/AppConstants';
|
||||
|
||||
export default class RoleService extends AbstractService {
|
||||
|
||||
@ -29,7 +30,7 @@ export default class RoleService extends AbstractService {
|
||||
|
||||
const roles: any = {
|
||||
demiurge: {
|
||||
members: [...[ownerId], validatorId],
|
||||
members: [ownerId],
|
||||
validation_rules: [],
|
||||
storages: []
|
||||
},
|
||||
@ -37,31 +38,26 @@ export default class RoleService extends AbstractService {
|
||||
members: [ownerId],
|
||||
validation_rules: [
|
||||
{
|
||||
quorum: 0.5,
|
||||
fields: [...privateFields, 'roles', 'uid', 'utype'],
|
||||
min_sig_member: 1,
|
||||
quorum: 0.01,
|
||||
fields: [...privateFields, 'roles', 'uid', 'utype', 'isDeleted'],
|
||||
min_sig_member: 0.01,
|
||||
},
|
||||
],
|
||||
storages: []
|
||||
storages: [...DEFAULT_STORAGE_URLS]
|
||||
},
|
||||
validator: {
|
||||
members: [validatorId],
|
||||
validation_rules: [
|
||||
{
|
||||
quorum: 0.5,
|
||||
fields: ['idCertified', 'roles'],
|
||||
quorum: 1,
|
||||
fields: [...privateFields, 'roles', 'uid', 'utype', 'isDeleted'],
|
||||
min_sig_member: 1,
|
||||
},
|
||||
{
|
||||
quorum: 0.0,
|
||||
fields: [...privateFields],
|
||||
min_sig_member: 0,
|
||||
},
|
||||
],
|
||||
storages: []
|
||||
storages: [...DEFAULT_STORAGE_URLS]
|
||||
},
|
||||
apophis: {
|
||||
members: [ownerId],
|
||||
members: [ownerId, validatorId],
|
||||
validation_rules: [],
|
||||
storages: []
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import User from 'src/sdk/User';
|
||||
import AbstractService from './AbstractService';
|
||||
|
||||
import RuleService from './RuleService';
|
||||
import { DEFAULT_STORAGE_URLS } from '@Front/Config/AppConstants';
|
||||
|
||||
export default class RuleGroupService extends AbstractService {
|
||||
|
||||
@ -31,7 +32,7 @@ export default class RuleGroupService extends AbstractService {
|
||||
|
||||
const roles: any = {
|
||||
demiurge: {
|
||||
members: [...[ownerId], validatorId],
|
||||
members: [ownerId],
|
||||
validation_rules: [],
|
||||
storages: []
|
||||
},
|
||||
@ -39,31 +40,26 @@ export default class RuleGroupService extends AbstractService {
|
||||
members: [ownerId],
|
||||
validation_rules: [
|
||||
{
|
||||
quorum: 0.5,
|
||||
fields: [...privateFields, 'roles', 'uid', 'utype'],
|
||||
min_sig_member: 1,
|
||||
quorum: 0.01,
|
||||
fields: [...privateFields, 'roles', 'uid', 'utype', 'isDeleted'],
|
||||
min_sig_member: 0.01,
|
||||
},
|
||||
],
|
||||
storages: []
|
||||
storages: [...DEFAULT_STORAGE_URLS]
|
||||
},
|
||||
validator: {
|
||||
members: [validatorId],
|
||||
validation_rules: [
|
||||
{
|
||||
quorum: 0.5,
|
||||
fields: ['idCertified', 'roles'],
|
||||
quorum: 1,
|
||||
fields: [...privateFields, 'roles', 'uid', 'utype', 'isDeleted'],
|
||||
min_sig_member: 1,
|
||||
},
|
||||
{
|
||||
quorum: 0.0,
|
||||
fields: [...privateFields],
|
||||
min_sig_member: 0,
|
||||
},
|
||||
],
|
||||
storages: []
|
||||
storages: [...DEFAULT_STORAGE_URLS]
|
||||
},
|
||||
apophis: {
|
||||
members: [ownerId],
|
||||
members: [ownerId, validatorId],
|
||||
validation_rules: [],
|
||||
storages: []
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import { v4 as uuidv4 } from 'uuid';
|
||||
import User from 'src/sdk/User';
|
||||
|
||||
import AbstractService from './AbstractService';
|
||||
import { DEFAULT_STORAGE_URLS } from '@Front/Config/AppConstants';
|
||||
|
||||
export default class RuleService extends AbstractService {
|
||||
|
||||
@ -29,7 +30,7 @@ export default class RuleService extends AbstractService {
|
||||
|
||||
const roles: any = {
|
||||
demiurge: {
|
||||
members: [...[ownerId], validatorId],
|
||||
members: [ownerId],
|
||||
validation_rules: [],
|
||||
storages: []
|
||||
},
|
||||
@ -37,31 +38,26 @@ export default class RuleService extends AbstractService {
|
||||
members: [ownerId],
|
||||
validation_rules: [
|
||||
{
|
||||
quorum: 0.5,
|
||||
fields: [...privateFields, 'roles', 'uid', 'utype'],
|
||||
min_sig_member: 1,
|
||||
quorum: 0.01,
|
||||
fields: [...privateFields, 'roles', 'uid', 'utype', 'isDeleted'],
|
||||
min_sig_member: 0.01,
|
||||
},
|
||||
],
|
||||
storages: []
|
||||
storages: [...DEFAULT_STORAGE_URLS]
|
||||
},
|
||||
validator: {
|
||||
members: [validatorId],
|
||||
validation_rules: [
|
||||
{
|
||||
quorum: 0.5,
|
||||
fields: ['idCertified', 'roles'],
|
||||
quorum: 1,
|
||||
fields: [...privateFields, 'roles', 'isDeleted', 'uid', 'utype'],
|
||||
min_sig_member: 1,
|
||||
},
|
||||
{
|
||||
quorum: 0.0,
|
||||
fields: [...privateFields],
|
||||
min_sig_member: 0,
|
||||
},
|
||||
],
|
||||
storages: []
|
||||
storages: [...DEFAULT_STORAGE_URLS]
|
||||
},
|
||||
apophis: {
|
||||
members: [ownerId],
|
||||
members: [ownerId, validatorId],
|
||||
validation_rules: [],
|
||||
storages: []
|
||||
}
|
||||
|
@ -54,4 +54,17 @@ export default class Auth extends BaseApiService {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
}
|
||||
|
||||
public async getIdNotUserForOffice(officeId: string): Promise<any[]> {
|
||||
const baseBackUrl = 'http://localhost:8080';//variables.BACK_API_PROTOCOL + variables.BACK_API_HOST;
|
||||
|
||||
const url = new URL(`${baseBackUrl}/api/v1/idnot/office/rattachements`);
|
||||
url.searchParams.set('idNot', officeId);
|
||||
try {
|
||||
return await this.getRequest(url);
|
||||
} catch (err) {
|
||||
this.onError(err);
|
||||
return Promise.reject(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ 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";
|
||||
import { DEFAULT_VALIDATOR_ID } from "@Front/Config/AppConstants";
|
||||
|
||||
type IProps = {
|
||||
onChange?: (files: File[]) => void;
|
||||
@ -226,9 +227,8 @@ export default class DepositOtherDocument extends React.Component<IProps, IState
|
||||
uid: this.props.customer_uid,
|
||||
}
|
||||
};
|
||||
const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';
|
||||
|
||||
DocumentService.createDocument(documentTypeData, validatorId).then((processCreated: any) => {
|
||||
DocumentService.createDocument(documentTypeData, DEFAULT_VALIDATOR_ID).then((processCreated: any) => {
|
||||
if (processCreated) {
|
||||
const document: any = processCreated.processData;
|
||||
resolve(document);
|
||||
@ -272,9 +272,8 @@ export default class DepositOtherDocument extends React.Component<IProps, IState
|
||||
file_blob: fileBlob,
|
||||
file_name: fileName
|
||||
};
|
||||
const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';
|
||||
|
||||
FileService.createFile(fileData, validatorId).then((processCreated: any) => {
|
||||
FileService.createFile(fileData, DEFAULT_VALIDATOR_ID).then((processCreated: any) => {
|
||||
const fileUid: string = processCreated.processData.uid;
|
||||
|
||||
DocumentService.getDocumentByUid(documentCreated.uid).then((process: any) => {
|
||||
|
@ -28,6 +28,8 @@ export default function DefaultDeedTypeDashboard(props: IProps) {
|
||||
deedTypes.sort((a: any, b: any) => a.name.localeCompare(b.name));
|
||||
|
||||
setDeedTypes(deedTypes);
|
||||
} else {
|
||||
console.log('[DefaultDeedTypeDashboard] No deed types found');
|
||||
}
|
||||
});
|
||||
}, []);
|
||||
@ -51,7 +53,7 @@ export default function DefaultDeedTypeDashboard(props: IProps) {
|
||||
}
|
||||
bottomButton={{
|
||||
link: Module.getInstance().get().modules.pages.DeedTypes.pages.Create.props.path,
|
||||
text: "Créer une liste de pièces",
|
||||
text: "Créer une liste de pièces", // TODO I think this is misleading, should be "Créer un type d'acte"
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
@ -13,6 +13,7 @@ import FileService from "src/common/Api/LeCoffreApi/sdk/FileService";
|
||||
|
||||
import { FileBlob, FileData } from "@Front/Api/Entities/types";
|
||||
import WatermarkService from "@Front/Services/WatermarkService";
|
||||
import { DEFAULT_VALIDATOR_ID } from "@Front/Config/AppConstants";
|
||||
|
||||
type IProps = {
|
||||
document: any;
|
||||
@ -62,9 +63,8 @@ export default function DepositDocumentComponent(props: IProps) {
|
||||
file_blob: fileBlob,
|
||||
file_name: fileName
|
||||
};
|
||||
const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';
|
||||
|
||||
FileService.createFile(fileData, validatorId).then((processCreated: any) => {
|
||||
FileService.createFile(fileData, DEFAULT_VALIDATOR_ID).then((processCreated: any) => {
|
||||
const fileUid: string = processCreated.processData.uid;
|
||||
|
||||
DocumentService.getDocumentByUid(document.uid!).then((process: any) => {
|
||||
@ -115,9 +115,8 @@ export default function DepositDocumentComponent(props: IProps) {
|
||||
file_blob: fileBlob,
|
||||
file_name: fileName
|
||||
};
|
||||
const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';
|
||||
|
||||
FileService.createFile(fileData, validatorId).then((processCreated: any) => {
|
||||
FileService.createFile(fileData, DEFAULT_VALIDATOR_ID).then((processCreated: any) => {
|
||||
const fileUid: string = processCreated.processData.uid;
|
||||
|
||||
DocumentService.getDocumentByUid(document.uid!).then((process: any) => {
|
||||
|
@ -18,6 +18,7 @@ import UserStore from "@Front/Stores/UserStore";
|
||||
|
||||
import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService";
|
||||
import DeedTypeService from "src/common/Api/LeCoffreApi/sdk/DeedTypeService";
|
||||
import { DEFAULT_VALIDATOR_ID } from "@Front/Config/AppConstants";
|
||||
|
||||
type IProps = {};
|
||||
export default function DeedTypesCreate(props: IProps) {
|
||||
@ -53,10 +54,9 @@ export default function DeedTypesCreate(props: IProps) {
|
||||
uid: officeId,
|
||||
}
|
||||
};
|
||||
const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';
|
||||
|
||||
LoaderService.getInstance().show();
|
||||
DeedTypeService.createDeedType(deedTypeData, validatorId).then((processCreated: any) => {
|
||||
DeedTypeService.createDeedType(deedTypeData, DEFAULT_VALIDATOR_ID).then((processCreated: any) => {
|
||||
ToasterService.getInstance().success({
|
||||
title: "Succès !",
|
||||
description: "Type d'acte créé avec succès"
|
||||
|
@ -17,51 +17,81 @@ import classes from "./classes.module.scss";
|
||||
import DocumentTypeService from "src/common/Api/LeCoffreApi/sdk/DocumentTypeService";
|
||||
import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService";
|
||||
import UserStore from "@Front/Stores/UserStore";
|
||||
import { DEFAULT_VALIDATOR_ID } from "@Front/Config/AppConstants";
|
||||
|
||||
type IProps = {};
|
||||
export default function DocumentTypesCreate(props: IProps) {
|
||||
const [validationError, setValidationError] = useState<ValidationError[]>([]);
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const handleCancel = useCallback(() => {
|
||||
router.push(Module.getInstance().get().modules.pages.DocumentTypes.props.path);
|
||||
}, [router]);
|
||||
|
||||
const onSubmitHandler = useCallback(
|
||||
async (e: React.FormEvent<HTMLFormElement> | null, values: { [key: string]: string }) => {
|
||||
try {
|
||||
const user: any = UserStore.instance.getUser();
|
||||
const officeId: string = user.office.uid;
|
||||
if (!user) {
|
||||
console.error("DocumentTypesCreate: User not found - user is null or undefined");
|
||||
return;
|
||||
}
|
||||
const office = UserStore.instance.getOffice();
|
||||
if (!office) {
|
||||
console.error("DocumentTypesCreate: office not found - office is undefined or null");
|
||||
return;
|
||||
}
|
||||
const officeId = office.processId;
|
||||
const officeIdNot = office.processData.idNot;
|
||||
|
||||
const documentFormModel = DocumentType.hydrate<DocumentType>({
|
||||
...values,
|
||||
office: Office.hydrate<Office>({
|
||||
uid: officeId,
|
||||
})
|
||||
});
|
||||
await validateOrReject(documentFormModel, { groups: ["createDocumentType"] });
|
||||
// const documentFormModel = DocumentType.hydrate<DocumentType>({
|
||||
// ...values,
|
||||
// office: Office.hydrate<Office>({
|
||||
// uid: officeId,
|
||||
// })
|
||||
// });
|
||||
// await validateOrReject(documentFormModel, { groups: ["createDocumentType"] });
|
||||
|
||||
const documentTypeData: any = {
|
||||
...values,
|
||||
office: {
|
||||
uid: officeId,
|
||||
idNot: officeIdNot,
|
||||
}
|
||||
};
|
||||
const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';
|
||||
|
||||
LoaderService.getInstance().show();
|
||||
DocumentTypeService.createDocumentType(documentTypeData, validatorId).then((processCreated: any) => {
|
||||
try {
|
||||
const processCreated = await DocumentTypeService.createDocumentType(documentTypeData, DEFAULT_VALIDATOR_ID);
|
||||
ToasterService.getInstance().success({
|
||||
title: "Succès !",
|
||||
description: "Type de document créé avec succès"
|
||||
});
|
||||
const documentTypeUid = processCreated.processId.split(':')[0];
|
||||
if (!documentTypeUid) {
|
||||
console.error("DocumentTypesCreate: documentTypeUid is undefined - processCreated.processId is missing");
|
||||
return;
|
||||
}
|
||||
router.push(
|
||||
Module.getInstance()
|
||||
.get()
|
||||
.modules.pages.DocumentTypes.pages.DocumentTypesInformations.props.path.replace("[uid]", processCreated.processData.uid),
|
||||
.modules.pages.DocumentTypes.pages.DocumentTypesInformations.props.path.replace("[uid]", documentTypeUid),
|
||||
);
|
||||
LoaderService.getInstance().hide();
|
||||
} catch (apiError) {
|
||||
ToasterService.getInstance().error({
|
||||
title: "Erreur !",
|
||||
description: "Une erreur est survenue lors de la création du type de document"
|
||||
});
|
||||
console.error("Document type creation error:", apiError);
|
||||
} finally {
|
||||
LoaderService.getInstance().hide();
|
||||
}
|
||||
} catch (e) {
|
||||
if (e instanceof Array) {
|
||||
setValidationError(e);
|
||||
}
|
||||
LoaderService.getInstance().hide();
|
||||
}
|
||||
},
|
||||
[router],
|
||||
@ -90,7 +120,7 @@ export default function DocumentTypesCreate(props: IProps) {
|
||||
validationError={validationError.find((error) => error.property === "public_description")}
|
||||
/>
|
||||
<div className={classes["buttons-container"]}>
|
||||
<Button variant={EButtonVariant.PRIMARY} styletype={EButtonstyletype.OUTLINED}>
|
||||
<Button variant={EButtonVariant.PRIMARY} styletype={EButtonstyletype.OUTLINED} onClick={handleCancel}>
|
||||
Annuler
|
||||
</Button>
|
||||
<Button type="submit">Créer le document</Button>
|
||||
|
@ -26,9 +26,12 @@ export default function DocumentTypesEdit() {
|
||||
async function getDocumentType() {
|
||||
if (!documentTypeUid) return;
|
||||
LoaderService.getInstance().show();
|
||||
DocumentTypeService.getDocumentTypeByUid(documentTypeUid as string).then((process: any) => {
|
||||
DocumentTypeService.getDocumentTypeByProcessId(documentTypeUid as string).then((process: any) => {
|
||||
if (process) {
|
||||
const documentType: any = process.processData;
|
||||
const documentType: any = {
|
||||
...process.processData,
|
||||
processId: process.processId
|
||||
};
|
||||
setDocumentTypeSelected(documentType);
|
||||
}
|
||||
LoaderService.getInstance().hide();
|
||||
@ -53,7 +56,7 @@ export default function DocumentTypesEdit() {
|
||||
return;
|
||||
}
|
||||
LoaderService.getInstance().show();
|
||||
DocumentTypeService.getDocumentTypeByUid(documentTypeUid as string).then((process: any) => {
|
||||
DocumentTypeService.getDocumentTypeByProcessId(documentTypeUid as string).then((process: any) => {
|
||||
if (process) {
|
||||
DocumentTypeService.updateDocumentType(process, values).then(() => {
|
||||
router.push(
|
||||
|
@ -22,13 +22,23 @@ export default function DocumentTypesInformations() {
|
||||
|
||||
useEffect(() => {
|
||||
async function getDocument() {
|
||||
if (!documentTypeUid) return;
|
||||
|
||||
DocumentTypeService.getDocumentTypeByUid(documentTypeUid as string).then((process: any) => {
|
||||
if (process) {
|
||||
const document: any = process.processData;
|
||||
setDocumentSelected(document);
|
||||
if (!documentTypeUid) {
|
||||
console.log('DocumentTypesInformations: documentTypeUid is not available yet');
|
||||
return;
|
||||
}
|
||||
|
||||
DocumentTypeService.getDocumentTypeByProcessId(documentTypeUid as string).then((process: any) => {
|
||||
if (process) {
|
||||
const document: any = {
|
||||
...process.processData,
|
||||
processId: process.processId
|
||||
};
|
||||
setDocumentSelected(document);
|
||||
} else {
|
||||
console.log('DocumentTypesInformations: No process found for processId:', documentTypeUid);
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.error('DocumentTypesInformations: Error fetching document:', error);
|
||||
});
|
||||
}
|
||||
|
||||
@ -69,13 +79,15 @@ export default function DocumentTypesInformations() {
|
||||
</div>
|
||||
</div>
|
||||
<div className={classes["right"]}>
|
||||
{(documentSelected as any)?.processId && (
|
||||
<Link
|
||||
href={Module.getInstance()
|
||||
.get()
|
||||
.modules.pages.DocumentTypes.pages.Edit.props.path.replace("[uid]", documentSelected?.uid ?? "")}
|
||||
.modules.pages.DocumentTypes.pages.Edit.props.path.replace("[uid]", (documentSelected as any).processId)}
|
||||
className={classes["edit-icon-container"]}>
|
||||
<Image src={PenICon} alt="edit informations" />
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -21,6 +21,7 @@ import DefaultDoubleSidePage from "@Front/Components/LayoutTemplates/DefaultDoub
|
||||
import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService";
|
||||
import CustomerService from "src/common/Api/LeCoffreApi/sdk/CustomerService";
|
||||
import FolderService from "src/common/Api/LeCoffreApi/sdk/FolderService";
|
||||
import { DEFAULT_VALIDATOR_ID } from "../../../../Config/AppConstants";
|
||||
|
||||
enum ESelectedOption {
|
||||
EXISTING_CUSTOMER = "existing_customer",
|
||||
@ -78,10 +79,9 @@ export default function AddClientToFolder(props: IProps) {
|
||||
const customerData: any = {
|
||||
contact: values
|
||||
};
|
||||
const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';
|
||||
|
||||
LoaderService.getInstance().show();
|
||||
CustomerService.createCustomer(customerData, validatorId).then((processCreated: any) => {
|
||||
CustomerService.createCustomer(customerData, DEFAULT_VALIDATOR_ID).then((processCreated: any) => {
|
||||
FolderService.getFolderByUid(folderUid as string).then((process: any) => {
|
||||
if (process) {
|
||||
const customers: any[] = [];
|
||||
|
@ -13,6 +13,7 @@ import classes from "./classes.module.scss";
|
||||
import DocumentTypeService from "src/common/Api/LeCoffreApi/sdk/DocumentTypeService";
|
||||
import DeedTypeService from "src/common/Api/LeCoffreApi/sdk/DeedTypeService";
|
||||
import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService";
|
||||
import { DEFAULT_VALIDATOR_ID } from "@Front/Config/AppConstants";
|
||||
|
||||
type IProps = {
|
||||
isCreateDocumentModalVisible: boolean;
|
||||
@ -85,10 +86,9 @@ export default function ParameterDocuments(props: IProps) {
|
||||
},
|
||||
public_description: visibleDescription,
|
||||
};
|
||||
const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';
|
||||
|
||||
const documentType: any = await new Promise<any>((resolve: (documentType: any) => void) => {
|
||||
DocumentTypeService.createDocumentType(documentTypeData, validatorId).then((processCreated: any) => {
|
||||
DocumentTypeService.createDocumentType(documentTypeData, DEFAULT_VALIDATOR_ID).then((processCreated: any) => {
|
||||
const documentType: any = processCreated.processData;
|
||||
resolve(documentType);
|
||||
});
|
||||
|
@ -18,6 +18,7 @@ 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 { DEFAULT_VALIDATOR_ID } from "@Front/Config/AppConstants";
|
||||
|
||||
export default function AskDocuments() {
|
||||
const router = useRouter();
|
||||
@ -78,9 +79,8 @@ export default function AskDocuments() {
|
||||
document_status: EDocumentStatus.ASKED,
|
||||
file_uid: null,
|
||||
};
|
||||
const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';
|
||||
|
||||
await DocumentService.createDocument(documentData, validatorId);
|
||||
await DocumentService.createDocument(documentData, DEFAULT_VALIDATOR_ID);
|
||||
}
|
||||
|
||||
FolderService.refreshFolderByUid(folderUid as string).then(() => {
|
||||
|
@ -18,6 +18,7 @@ import FolderService from "src/common/Api/LeCoffreApi/sdk/FolderService";
|
||||
import CustomerService from "src/common/Api/LeCoffreApi/sdk/CustomerService";
|
||||
import NoteService from "src/common/Api/LeCoffreApi/sdk/NoteService";
|
||||
import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService";
|
||||
import { DEFAULT_VALIDATOR_ID } from "@Front/Config/AppConstants";
|
||||
|
||||
type IProps = {};
|
||||
|
||||
@ -124,10 +125,8 @@ class CreateCustomerNoteClass extends BasePage<IPropsClass, IState> {
|
||||
uid: this.state.customer.uid
|
||||
}
|
||||
};
|
||||
const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';
|
||||
|
||||
LoaderService.getInstance().show();
|
||||
NoteService.createNote(noteData, validatorId).then(() => {
|
||||
NoteService.createNote(noteData, DEFAULT_VALIDATOR_ID).then(() => {
|
||||
this.props.router.push(this.backwardPath);
|
||||
});
|
||||
} catch (error) {
|
||||
|
@ -23,6 +23,7 @@ import FolderService from "src/common/Api/LeCoffreApi/sdk/FolderService";
|
||||
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 { DEFAULT_VALIDATOR_ID } from "@Front/Config/AppConstants";
|
||||
|
||||
enum EClientSelection {
|
||||
ALL_CLIENTS = "all_clients",
|
||||
@ -97,9 +98,8 @@ export default function SendDocuments() {
|
||||
file_blob: fileBlob,
|
||||
file_name: fileName
|
||||
};
|
||||
const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';
|
||||
|
||||
FileService.createFile(fileData, validatorId).then((processCreated: any) => {
|
||||
FileService.createFile(fileData, DEFAULT_VALIDATOR_ID).then((processCreated: any) => {
|
||||
const fileUid: string = processCreated.processData.uid;
|
||||
|
||||
const documentData: any = {
|
||||
@ -117,7 +117,7 @@ export default function SendDocuments() {
|
||||
document_status: EDocumentNotaryStatus.SENT
|
||||
};
|
||||
|
||||
DocumentService.createDocument(documentData, validatorId).then(() => {
|
||||
DocumentService.createDocument(documentData, DEFAULT_VALIDATOR_ID).then(() => {
|
||||
FolderService.refreshFolderByUid(folderUid as string).then(() => resolve());
|
||||
});
|
||||
});
|
||||
|
@ -51,7 +51,7 @@ export default function StepEmail(props: IProps) {
|
||||
);
|
||||
*/
|
||||
router.push(
|
||||
`https://qual-connexion.idnot.fr/user/IdPOAuth2/authorize/idnot_idp_v1?client_id=B3CE56353EDB15A9&redirect_uri=http://local.lecoffreio.4nkweb:3000/authorized-client&scope=openid,profile&response_type=code`,
|
||||
`https://qual-connexion.idnot.fr/user/IdPOAuth2/authorize/idnot_idp_v1?client_id=B3CE56353EDB15A9&redirect_uri=http://127.0.0.1:3000/authorized-client&scope=openid,profile&response_type=code`,
|
||||
);
|
||||
}, [router]);
|
||||
|
||||
|
@ -21,6 +21,8 @@ import UserStore from "@Front/Stores/UserStore";
|
||||
|
||||
import AuthModal from "src/sdk/AuthModal";
|
||||
import CustomerService from "src/common/Api/LeCoffreApi/sdk/CustomerService";
|
||||
import MessageBus from "src/sdk/MessageBus";
|
||||
import { resolve } from "path";
|
||||
|
||||
export enum LoginStep {
|
||||
EMAIL,
|
||||
@ -41,6 +43,7 @@ export default function Login() {
|
||||
const [totpCode, setTotpCode] = useState<string>("");
|
||||
const [email, setEmail] = useState<string>("");
|
||||
const [partialPhoneNumber, setPartialPhoneNumber] = useState<string>("");
|
||||
const [sessionId, setSessionId] = useState<string>("");
|
||||
const [validationErrors, setValidationErrors] = useState<ValidationError[]>([]);
|
||||
const [isAuthModalOpen, setIsAuthModalOpen] = useState(false);
|
||||
|
||||
@ -92,10 +95,13 @@ export default function Login() {
|
||||
// If the code is valid setting it in state
|
||||
if (res.validCode) {
|
||||
setTotpCode(values["totpCode"]);
|
||||
setSessionId(res.sessionId); // Store the session ID
|
||||
}
|
||||
*/
|
||||
if ('1234' === values["totpCode"]) {
|
||||
setTotpCode(values["totpCode"]);
|
||||
// For testing, set a mock session ID
|
||||
setSessionId("mock-session-id-123");
|
||||
}
|
||||
|
||||
setValidationErrors([]);
|
||||
@ -265,17 +271,43 @@ export default function Login() {
|
||||
{isAuthModalOpen && <AuthModal
|
||||
isOpen={isAuthModalOpen}
|
||||
onClose={() => {
|
||||
CustomerService.getCustomers().then((processes: any[]) => {
|
||||
if (processes.length > 0) {
|
||||
const customers: any[] = processes.map((process: any) => process.processData);
|
||||
const customer: any = customers.find((customer: any) => customer.contact.email === email);
|
||||
if (customer) {
|
||||
UserStore.instance.connect(customer);
|
||||
// After 4nk authentication is complete, get the process for the pairing ID
|
||||
MessageBus.getInstance().initMessageListener();
|
||||
MessageBus.getInstance().isReady().then(async () => {
|
||||
try {
|
||||
// Find the customer
|
||||
const customer: any = (await CustomerService.getCustomers())
|
||||
.map((process: any) => process.processData)
|
||||
.find((customer: any) => customer.contact.email === email);
|
||||
|
||||
// Get the pairing ID
|
||||
const pairingId = await MessageBus.getInstance().getPairingId();
|
||||
console.log('[Login] Got pairing ID:', pairingId);
|
||||
|
||||
// Get all processes
|
||||
const processes = await MessageBus.getInstance().getProcesses();
|
||||
console.log('[Login] Got processes:', Object.keys(processes));
|
||||
|
||||
const targetProcess = processes[pairingId];
|
||||
|
||||
if (targetProcess) {
|
||||
console.log('[Login] Found target process:', targetProcess);
|
||||
// Connect the user with the process data
|
||||
UserStore.instance.connect(customer /*targetProcess*/);
|
||||
router.push(Module.getInstance().get().modules.pages.Folder.pages.Select.props.path);
|
||||
} else {
|
||||
console.error('[Login] No process found for pairing ID:', pairingId);
|
||||
// Handle the case where no process is found
|
||||
}
|
||||
|
||||
MessageBus.getInstance().destroyMessageListener();
|
||||
} catch (error) {
|
||||
console.error('[Login] Error getting process:', error);
|
||||
MessageBus.getInstance().destroyMessageListener();
|
||||
}
|
||||
setIsAuthModalOpen(false);
|
||||
});
|
||||
|
||||
setIsAuthModalOpen(false);
|
||||
}}
|
||||
/>}
|
||||
</div>
|
||||
|
@ -26,6 +26,7 @@ import RoleService from "src/common/Api/LeCoffreApi/sdk/RoleService";
|
||||
import OfficeService from "src/common/Api/LeCoffreApi/sdk/OfficeService";
|
||||
import OfficeRoleService from "src/common/Api/LeCoffreApi/sdk/OfficeRoleService";
|
||||
import CollaboratorService from "src/common/Api/LeCoffreApi/sdk/CollaboratorService";
|
||||
import { DEFAULT_STORAGE_URLS, DEFAULT_VALIDATOR_ID } from "@Front/Config/AppConstants";
|
||||
|
||||
export default function LoginCallBack() {
|
||||
const router = useRouter();
|
||||
@ -45,10 +46,23 @@ export default function LoginCallBack() {
|
||||
const getOffice = async (idNotUser: any) => {
|
||||
return await new Promise<any>((resolve: (office: any) => void) => {
|
||||
OfficeService.getOffices().then((processes: any[]) => {
|
||||
const officeFound: any = processes.length > 0 ? processes.map((process: any) => process.processData).find((office: any) => office.idNot === idNotUser.office.idNot) : null;
|
||||
const officeFound: any = processes.length > 0 ? processes.find((office: any) => office.processData.idNot === idNotUser.office.idNot) : null;
|
||||
if (officeFound) {
|
||||
resolve(officeFound);
|
||||
} else {
|
||||
// Some info must be here or have some value, just to be sure
|
||||
if (!idNotUser.office.office_status || idNotUser.office.office_status !== 'ACTIVATED') {
|
||||
console.error(`[LoginCallback] office_status is not ACTIVATED for idNot ${idNotUser.office.idNot}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// I guess if we don't have crpcen that's also a big problem
|
||||
if (!idNotUser.office.crpcen) {
|
||||
console.error(`[LoginCallback] crpcen is not set for idNot ${idNotUser.office.idNot}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// We create office
|
||||
const officeData: any = {
|
||||
idNot: idNotUser.office.idNot,
|
||||
name: idNotUser.office.name,
|
||||
@ -60,17 +74,29 @@ export default function LoginCallBack() {
|
||||
city: idNotUser.office.address.city
|
||||
}
|
||||
},
|
||||
office_status: 'ACTIVATED'
|
||||
office_status: idNotUser.office.office_status // must be ACTIVATED though
|
||||
};
|
||||
const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';
|
||||
|
||||
OfficeService.createOffice(officeData, validatorId).then((process: any) => {
|
||||
Auth.getInstance().getIdNotUserForOffice(idNotUser.office.idNot).then((users: any) => {
|
||||
console.log('users : ', users);
|
||||
const activeUsers = users.result.filter((user: any) => user.activite === 'En exercice');
|
||||
let officeCollaborators: any[] = [];
|
||||
for (const user of activeUsers) {
|
||||
CollaboratorService.getCollaboratorByUid(user.uid).then((collaborator: any) => {
|
||||
console.log('collaborator : ', collaborator);
|
||||
officeCollaborators.push(collaborator);
|
||||
});
|
||||
}
|
||||
|
||||
OfficeService.createOffice(officeData, officeCollaborators, DEFAULT_VALIDATOR_ID, [...DEFAULT_STORAGE_URLS]).then((process: any) => {
|
||||
if (process) {
|
||||
const office: any = process.processData;
|
||||
resolve(office);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
return;
|
||||
});
|
||||
});
|
||||
};
|
||||
@ -79,22 +105,36 @@ export default function LoginCallBack() {
|
||||
return await new Promise<any>(async (resolve: (role: any) => void) => {
|
||||
const processFound: any | null = await CollaboratorService.getCollaboratorBy({ idNot: idNotUser.idNot });
|
||||
if (processFound) {
|
||||
resolve(processFound.processData);
|
||||
} else {
|
||||
const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';
|
||||
console.log('Found a collaborator for idNot', idNotUser.idNot);
|
||||
// TODO: check if the collaborator is in the office process
|
||||
const office: any = await getOffice(idNotUser);
|
||||
|
||||
if (!await ImportData.isDone()) {
|
||||
LoaderService.getInstance().hide();
|
||||
setShowProgress(true);
|
||||
|
||||
await ImportData.import(office, validatorId, (info: ProgressInfo) => {
|
||||
setProgressInfo(info);
|
||||
});
|
||||
|
||||
setShowProgress(false);
|
||||
LoaderService.getInstance().show();
|
||||
// Take the role of the collaborator
|
||||
MessageBus.getInstance().getRolesForProcess(processFound.processId).then((roles: any) => {
|
||||
console.log('roles : ', roles);
|
||||
// We should find one pairing id in the role 'owner'
|
||||
const owners = roles['owner'].members;
|
||||
if (owners.length !== 1) {
|
||||
console.error('[LoginCallback] owner should have 1 member');
|
||||
return;
|
||||
}
|
||||
const ownerPairingId = owners[0];
|
||||
// Now we can check if the owner pairing id is in the office roles
|
||||
MessageBus.getInstance().getRolesForProcess(office.processId).then((officeRoles: any) => {
|
||||
const officeOwners = officeRoles['owner'].members;
|
||||
if (!officeOwners.includes(ownerPairingId)) {
|
||||
// We add the newly created collaborator to the office roles
|
||||
OfficeService.addCollaborators(office, officeRoles, [ownerPairingId]).then((process: any) => {
|
||||
resolve(processFound);
|
||||
});
|
||||
} else {
|
||||
// Nothing to do
|
||||
resolve(processFound);
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
console.log('No collaborator found for idNot', idNotUser.idNot);
|
||||
const office: any = await getOffice(idNotUser);
|
||||
|
||||
const role: any = (await RoleService.getRoles())
|
||||
.map((process: any) => process.processData)
|
||||
@ -102,9 +142,21 @@ export default function LoginCallBack() {
|
||||
|
||||
const officeRole: any = (await OfficeRoleService.getOfficeRoles())
|
||||
.map((process: any) => process.processData)
|
||||
.filter((officeRole: any) => officeRole.office.uid === office.uid)
|
||||
.filter((officeRole: any) => officeRole.office.uid === office.processData.uid)
|
||||
.find((officeRole: any) => officeRole.name === idNotUser.office_role.name);
|
||||
|
||||
if (!office || !role || !officeRole) {
|
||||
LoaderService.getInstance().hide();
|
||||
setShowProgress(true);
|
||||
|
||||
await ImportData.import(office, DEFAULT_VALIDATOR_ID, (info: ProgressInfo) => {
|
||||
setProgressInfo(info);
|
||||
});
|
||||
|
||||
setShowProgress(false);
|
||||
LoaderService.getInstance().show();
|
||||
}
|
||||
|
||||
const collaboratorData: any = {
|
||||
idNot: idNotUser.idNot,
|
||||
contact: idNotUser.contact,
|
||||
@ -119,10 +171,38 @@ export default function LoginCallBack() {
|
||||
}
|
||||
};
|
||||
|
||||
CollaboratorService.createCollaborator(collaboratorData, validatorId).then((process: any) => {
|
||||
if (process) {
|
||||
const collaborator: any = process.processData;
|
||||
resolve(collaborator);
|
||||
CollaboratorService.createCollaborator(collaboratorData, DEFAULT_VALIDATOR_ID).then((newCollaborator: any) => {
|
||||
if (newCollaborator) {
|
||||
// Now that we created the collaborator, we must check that it's in the office roles (probably not)
|
||||
MessageBus.getInstance().getRolesForProcess(newCollaborator.processId).then((roles: any) => {
|
||||
console.log('roles : ', roles);
|
||||
// We should have our own pairing id in roles['owner']
|
||||
const owner = roles['owner'].members;
|
||||
if (owner.length !== 1) {
|
||||
console.error('[LoginCallback] owner should have 1 member');
|
||||
return;
|
||||
}
|
||||
const ownerPairingId = owner[0];
|
||||
if (ownerPairingId !== newCollaborator.processData.uid) {
|
||||
console.error('[LoginCallback] owner pairing id is not the same as the collaborator uid');
|
||||
return;
|
||||
}
|
||||
|
||||
// is ownerPairingId in roles for the office process?
|
||||
MessageBus.getInstance().getRolesForProcess(office.processId).then((officeRoles: any) => {
|
||||
const officeOwners = officeRoles['owner'].members;
|
||||
if (!officeOwners.includes(ownerPairingId)) {
|
||||
// We add the newly created collaborator to the office roles
|
||||
OfficeService.addCollaborators(office, officeRoles, [ownerPairingId]).then((process: any) => {
|
||||
resolve(newCollaborator);
|
||||
});
|
||||
} else {
|
||||
// Nothing to do
|
||||
resolve(newCollaborator);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -153,6 +233,7 @@ export default function LoginCallBack() {
|
||||
const user: any = await Auth.getInstance().getIdNotUser(code as string);
|
||||
setIdNotUser(user.idNotUser);
|
||||
setIsAuthModalOpen(true);
|
||||
console.log('[LoginCallback] idNotUser', idNotUser);
|
||||
/*
|
||||
const token: any = null;
|
||||
if (!token) return router.push(Module.getInstance().get().modules.pages.Login.props.path);
|
||||
@ -274,7 +355,11 @@ export default function LoginCallBack() {
|
||||
MessageBus.getInstance().initMessageListener();
|
||||
MessageBus.getInstance().isReady().then(async () => {
|
||||
const collaborator: any = await getCollaborator(idNotUser);
|
||||
UserStore.instance.connect(collaborator);
|
||||
if (!UserStore.instance.connect(collaborator)) {
|
||||
console.error('[LoginCallback] collaborator not connected');
|
||||
router.push(Module.getInstance().get().modules.pages.Login.props.path + "?error=1");
|
||||
return;
|
||||
}
|
||||
|
||||
MessageBus.getInstance().destroyMessageListener();
|
||||
LoaderService.getInstance().hide();
|
||||
|
@ -11,6 +11,7 @@ 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";
|
||||
import { DEFAULT_VALIDATOR_ID } from "../../../Config/AppConstants";
|
||||
|
||||
export default function Rib() {
|
||||
const [documentList, setDocumentList] = useState<File[]>([]);
|
||||
@ -80,9 +81,8 @@ export default function Rib() {
|
||||
file_blob: fileBlob,
|
||||
file_name: fileName
|
||||
};
|
||||
const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';
|
||||
|
||||
OfficeRibService.createOfficeRib(fileData, validatorId).then(() => {
|
||||
OfficeRibService.createOfficeRib(fileData, DEFAULT_VALIDATOR_ID).then(() => {
|
||||
LoaderService.getInstance().hide();
|
||||
onCloseRibModal();
|
||||
|
||||
|
@ -20,6 +20,7 @@ import { ValidationError } from "class-validator";
|
||||
import RoleService from "src/common/Api/LeCoffreApi/sdk/RoleService";
|
||||
import LoaderService from "src/common/Api/LeCoffreApi/sdk/Loader/LoaderService";
|
||||
import UserStore from "@Front/Stores/UserStore";
|
||||
import { DEFAULT_VALIDATOR_ID } from "@Front/Config/AppConstants";
|
||||
|
||||
type IProps = {};
|
||||
export default function RolesCreate(props: IProps) {
|
||||
@ -54,10 +55,9 @@ export default function RolesCreate(props: IProps) {
|
||||
uid: officeId,
|
||||
}
|
||||
};
|
||||
const validatorId: string = '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0';
|
||||
|
||||
LoaderService.getInstance().show();
|
||||
RoleService.createRole(roleData, validatorId).then((processCreated: any) => {
|
||||
RoleService.createRole(roleData, DEFAULT_VALIDATOR_ID).then((processCreated: any) => {
|
||||
if (processCreated) {
|
||||
ToasterService.getInstance().success({
|
||||
title: "Succès !",
|
||||
|
20
src/front/Config/AppConstants.ts
Normal file
20
src/front/Config/AppConstants.ts
Normal file
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Application-wide constants
|
||||
* This file contains constants that are used across multiple components and services
|
||||
*/
|
||||
|
||||
export const APP_CONSTANTS = {
|
||||
/**
|
||||
* Default validator ID used for creating various entities (customers, documents, roles, etc.)
|
||||
* This is a system-level validator that has permissions to create and manage entities
|
||||
*/
|
||||
DEFAULT_VALIDATOR_ID: 'c87bbb4873fd4c8427655b083b098c4b3f3a8ebf436d286b69c8036db4a2a029:0',
|
||||
} as const;
|
||||
|
||||
// Export individual constants for easier imports
|
||||
export const DEFAULT_VALIDATOR_ID = APP_CONSTANTS.DEFAULT_VALIDATOR_ID;
|
||||
|
||||
// Define
|
||||
export const DEFAULT_STORAGE_URLS = [
|
||||
'https://dev3.4nkweb.com/storage'
|
||||
] as const;
|
@ -5,6 +5,8 @@ export class FrontendVariables {
|
||||
|
||||
public BACK_API_HOST!: string;
|
||||
|
||||
public BACK_API_PORT!: string;
|
||||
|
||||
public BACK_API_ROOT_URL!: string;
|
||||
|
||||
public BACK_API_VERSION!: string;
|
||||
|
@ -24,6 +24,7 @@ type AppPropsWithLayout = AppProps & {
|
||||
} & {
|
||||
backApiProtocol: string;
|
||||
backApiHost: string;
|
||||
backApiPort: string;
|
||||
backApiRootUrl: string;
|
||||
backApiVersion: string;
|
||||
frontAppHost: string;
|
||||
@ -46,6 +47,7 @@ const MyApp = (({
|
||||
pageProps,
|
||||
backApiProtocol,
|
||||
backApiHost,
|
||||
backApiPort,
|
||||
backApiRootUrl,
|
||||
backApiVersion,
|
||||
frontAppHost,
|
||||
@ -65,6 +67,7 @@ const MyApp = (({
|
||||
const instance = FrontendVariables.getInstance();
|
||||
instance.BACK_API_PROTOCOL = backApiProtocol;
|
||||
instance.BACK_API_HOST = backApiHost;
|
||||
instance.BACK_API_PORT = backApiPort;
|
||||
instance.BACK_API_ROOT_URL = backApiRootUrl;
|
||||
instance.BACK_API_VERSION = backApiVersion;
|
||||
instance.FRONT_APP_HOST = frontAppHost;
|
||||
@ -129,6 +132,7 @@ MyApp.getInitialProps = async () => {
|
||||
return {
|
||||
backApiProtocol: publicRuntimeConfig.NEXT_PUBLIC_BACK_API_PROTOCOL,
|
||||
backApiHost: publicRuntimeConfig.NEXT_PUBLIC_BACK_API_HOST,
|
||||
backApiPort: publicRuntimeConfig.NEXT_PUBLIC_BACK_API_PORT,
|
||||
backApiRootUrl: publicRuntimeConfig.NEXT_PUBLIC_BACK_API_ROOT_URL,
|
||||
backApiVersion: publicRuntimeConfig.NEXT_PUBLIC_BACK_API_VERSION,
|
||||
frontAppHost: publicRuntimeConfig.NEXT_PUBLIC_FRONT_APP_HOST,
|
||||
|
@ -71,6 +71,20 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
||||
break;
|
||||
}
|
||||
|
||||
case 'PAIRING_CREATED': {
|
||||
console.log('[AuthModal] PAIRING_CREATED:', message);
|
||||
User.getInstance().setPairingId(message.userPairingId);
|
||||
setAuthSuccess(true);
|
||||
|
||||
setTimeout(() => {
|
||||
setShowIframe(false);
|
||||
setIsIframeReady(false);
|
||||
setAuthSuccess(false);
|
||||
onClose();
|
||||
}, 500);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'GET_PAIRING_ID': {
|
||||
User.getInstance().setPairingId(message.userPairingId);
|
||||
setAuthSuccess(true);
|
||||
@ -83,6 +97,36 @@ export default function AuthModal({ isOpen, onClose }: AuthModalProps) {
|
||||
}, 500);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'ERROR': {
|
||||
console.error('[AuthModal] handleMessage: error', message);
|
||||
if (message.messageId.includes('GET_PAIRING_ID')) {
|
||||
// We are not paired yet
|
||||
const accessToken = User.getInstance().getAccessToken();
|
||||
if (accessToken) {
|
||||
// create a new pairing
|
||||
const messageId = `CREATE_PAIRING_${uuidv4()}`;
|
||||
iframeRef.current.contentWindow!.postMessage({ type: 'CREATE_PAIRING', accessToken, messageId }, targetOrigin);
|
||||
} else {
|
||||
// We don't have an access token
|
||||
// Shouldn't happen
|
||||
console.error('[AuthModal] handleMessage: error: we don\'t have an access token');
|
||||
setShowIframe(false);
|
||||
setIsIframeReady(false);
|
||||
setAuthSuccess(false);
|
||||
onClose();
|
||||
}
|
||||
} else if (message.messageId.includes('CREATE_PAIRING')) {
|
||||
// Something went wrong while creating a pairing
|
||||
// show stopper for now
|
||||
console.error('[AuthModal] CREATE_PAIRING error:', message.error);
|
||||
setShowIframe(false);
|
||||
setIsIframeReady(false);
|
||||
setAuthSuccess(false);
|
||||
onClose();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
window.addEventListener('message', handleMessage);
|
||||
|
@ -11,8 +11,8 @@ import { FileBlob } from '../front/Api/Entities/types';
|
||||
|
||||
export default class MessageBus {
|
||||
private static instance: MessageBus;
|
||||
private errors: { [key: string]: string } = {};
|
||||
private isListening: boolean = false;
|
||||
private messagesSent: Set<string> = new Set();
|
||||
|
||||
public static getInstance(): MessageBus {
|
||||
if (!MessageBus.instance) {
|
||||
@ -27,6 +27,11 @@ export default class MessageBus {
|
||||
|
||||
public destroyMessageListener(): void {
|
||||
window.removeEventListener('message', this.handleMessage.bind(this));
|
||||
this.isListening = false; // Reset the flag when destroying listener
|
||||
}
|
||||
|
||||
public resetListeningState(): void {
|
||||
this.isListening = false; // Allow external components to reset listening state
|
||||
}
|
||||
|
||||
public isReady(): Promise<void> {
|
||||
@ -41,20 +46,61 @@ export default class MessageBus {
|
||||
});
|
||||
}
|
||||
|
||||
public isWaitingForMessage(): boolean {
|
||||
return this.messagesSent.size > 0;
|
||||
}
|
||||
|
||||
public requestLink(): Promise<void> {
|
||||
return new Promise<void>((resolve: () => void, reject: (error: string) => void) => {
|
||||
const messageId = `REQUEST_LINK_${uuidv4()}`;
|
||||
console.log('[MessageBus] requestLink - waiting for messageId:', messageId);
|
||||
|
||||
const unsubscribe = EventBus.getInstance().on('LINK_ACCEPTED', (responseId: string, message: { accessToken: string, refreshToken: string }) => {
|
||||
console.log('[MessageBus] LINK_ACCEPTED received with responseId:', responseId, 'expected:', messageId);
|
||||
if (responseId !== messageId) {
|
||||
return;
|
||||
}
|
||||
console.log('[MessageBus] LINK_ACCEPTED matched - resolving');
|
||||
unsubscribe();
|
||||
unsubscribeError();
|
||||
User.getInstance().setTokens(message.accessToken, message.refreshToken);
|
||||
resolve();
|
||||
});
|
||||
|
||||
const unsubscribeError = EventBus.getInstance().on('ERROR_LINK_ACCEPTED', (responseId: string, error: string) => {
|
||||
console.log('[MessageBus] ERROR_LINK_ACCEPTED received with responseId:', responseId, 'expected:', messageId);
|
||||
if (responseId !== messageId) {
|
||||
return;
|
||||
}
|
||||
console.log('[MessageBus] ERROR_LINK_ACCEPTED matched - rejecting with error:', error);
|
||||
unsubscribe();
|
||||
unsubscribeError();
|
||||
reject(error);
|
||||
});
|
||||
|
||||
console.log('[MessageBus] requestLink - sending REQUEST_LINK message');
|
||||
this.sendMessage({
|
||||
type: 'REQUEST_LINK',
|
||||
messageId
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public createPairing(): Promise<void> {
|
||||
return new Promise<void>((resolve: () => void, reject: (error: string) => void) => {
|
||||
this.checkToken().then(() => {
|
||||
const messageId = `CREATE_PAIRING_${uuidv4()}`;
|
||||
|
||||
const unsubscribe = EventBus.getInstance().on('PAIRING_CREATED', (responseId: string, pairingId: string) => {
|
||||
if (responseId !== messageId) {
|
||||
return;
|
||||
}
|
||||
unsubscribe();
|
||||
User.getInstance().setPairingId(pairingId);
|
||||
resolve();
|
||||
});
|
||||
|
||||
const unsubscribeError = EventBus.getInstance().on('ERROR_CREATE_PAIRING', (responseId: string, error: string) => {
|
||||
if (responseId !== messageId) {
|
||||
return;
|
||||
}
|
||||
@ -62,10 +108,15 @@ export default class MessageBus {
|
||||
reject(error);
|
||||
});
|
||||
|
||||
const user = User.getInstance();
|
||||
const accessToken = user.getAccessToken()!;
|
||||
|
||||
this.sendMessage({
|
||||
type: 'REQUEST_LINK',
|
||||
type: 'CREATE_PAIRING',
|
||||
accessToken,
|
||||
messageId
|
||||
});
|
||||
}).catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
@ -98,7 +149,7 @@ export default class MessageBus {
|
||||
accessToken,
|
||||
messageId
|
||||
});
|
||||
}).catch(console.error);
|
||||
}).catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
@ -298,6 +349,114 @@ export default class MessageBus {
|
||||
});
|
||||
}
|
||||
|
||||
public getRolesForProcess(processId: string): Promise<any> {
|
||||
return new Promise<any>((resolve: (roles: any[]) => void, reject: (error: string) => void) => {
|
||||
this.getAllProcesses().then((processes: any) => {
|
||||
const process = processes[processId];
|
||||
|
||||
if (!process.states || process.states.length < 2) {
|
||||
reject('No states found for process');
|
||||
}
|
||||
|
||||
const roles = process.states[process.states.length - 2].roles;
|
||||
if (!roles) {
|
||||
reject('No roles found for process');
|
||||
}
|
||||
|
||||
resolve(roles);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Returns all processes details, including processes we only have public data for
|
||||
public getAllProcessesDecoded(filterPublicValues: (publicValues: { [key: string]: any }) => boolean): Promise<any[]> {
|
||||
return new Promise<any[]>((resolve: (processesDecoded: any[]) => void, reject: (error: string) => void) => {
|
||||
this.getAllProcesses().then(async (processes: any) => {
|
||||
const processesDecoded: any[] = [];
|
||||
|
||||
for (const processId of Object.keys(processes)) {
|
||||
const process = processes[processId];
|
||||
if (!process.states) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const publicDataDecoded: { [key: string]: any } = {};
|
||||
|
||||
for (let stateId = 0; stateId < process.states.length - 1; stateId++) {
|
||||
const state = process.states[stateId];
|
||||
if (!state) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const publicDataEncoded = state.public_data;
|
||||
if (!publicDataEncoded) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const key of Object.keys(publicDataEncoded)) {
|
||||
publicDataDecoded[key] = await this.getPublicData(publicDataEncoded[key]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!filterPublicValues(publicDataDecoded)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let processDecoded: any;
|
||||
|
||||
for (let stateId = 0; stateId < process.states.length - 1; stateId++) {
|
||||
const lastState = process.states[stateId];
|
||||
if (!lastState) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const lastStateId = lastState.state_id;
|
||||
if (!lastStateId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
let processData = await this.getData(processId, lastStateId);
|
||||
if (!processData) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const isEmpty = Object.keys(processData).length === 0;
|
||||
if (isEmpty) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const key of Object.keys(publicDataDecoded)) {
|
||||
processData[key] = publicDataDecoded[key];
|
||||
}
|
||||
processData = MapUtils.toJson(processData);
|
||||
|
||||
if (!processDecoded) {
|
||||
processDecoded = {
|
||||
processId,
|
||||
lastStateId,
|
||||
processData,
|
||||
};
|
||||
} else {
|
||||
for (const key of Object.keys(processData)) {
|
||||
processDecoded.processData[key] = processData[key];
|
||||
}
|
||||
processDecoded.lastStateId = lastStateId;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
processesDecoded.push(processDecoded);
|
||||
}
|
||||
|
||||
resolve(processesDecoded);
|
||||
}).catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
// Returns details about processes that we are involved in
|
||||
public getProcessesDecoded(filterPublicValues: (publicValues: { [key: string]: any }) => boolean): Promise<any[]> {
|
||||
return new Promise<any[]>((resolve: (processesDecoded: any[]) => void, reject: (error: string) => void) => {
|
||||
this.getProcesses().then(async (processes: any) => {
|
||||
@ -417,7 +576,7 @@ export default class MessageBus {
|
||||
accessToken,
|
||||
messageId
|
||||
});
|
||||
}).catch(console.error);
|
||||
}).catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
@ -454,12 +613,48 @@ export default class MessageBus {
|
||||
accessToken,
|
||||
messageId
|
||||
});
|
||||
}).catch(console.error);
|
||||
}).catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
public getProcesses(): Promise<any> {
|
||||
return new Promise<any>((resolve: (processes: any) => void, reject: (error: string) => void) => {
|
||||
// Returns all processes, including processes that have nothing to do with us
|
||||
public getAllProcesses(): Promise<{ [processId: string]: any }> {
|
||||
return new Promise<{ [processId: string]: any }>((resolve: (processes: { [processId: string]: any }) => void, reject: (error: string) => void) => {
|
||||
this.checkToken().then(() => {
|
||||
const messageId = `GET_PROCESSES_${uuidv4()}`;
|
||||
|
||||
const unsubscribe = EventBus.getInstance().on('PROCESSES_RETRIEVED', (responseId: string, processes: any) => {
|
||||
if (responseId !== messageId) {
|
||||
return;
|
||||
}
|
||||
unsubscribe();
|
||||
|
||||
resolve(processes);
|
||||
});
|
||||
|
||||
const unsubscribeError = EventBus.getInstance().on('ERROR_PROCESSES_RETRIEVED', (responseId: string, error: string) => {
|
||||
if (responseId !== messageId) {
|
||||
return;
|
||||
}
|
||||
unsubscribeError();
|
||||
reject(error);
|
||||
});
|
||||
|
||||
const user = User.getInstance();
|
||||
const accessToken = user.getAccessToken()!;
|
||||
|
||||
this.sendMessage({
|
||||
type: 'GET_PROCESSES',
|
||||
accessToken,
|
||||
messageId
|
||||
});
|
||||
}).catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
// Returns processes that we are involved in
|
||||
public getProcesses(): Promise<{ [processId: string]: any }> {
|
||||
return new Promise<{ [processId: string]: any }>((resolve: (processes: { [processId: string]: any }) => void, reject: (error: string) => void) => {
|
||||
this.checkToken().then(() => {
|
||||
const messageId = `GET_PROCESSES_${uuidv4()}`;
|
||||
|
||||
@ -471,7 +666,7 @@ export default class MessageBus {
|
||||
|
||||
// Filter processes by my processes
|
||||
setTimeout(() => {
|
||||
this.getMyProcesses().then((myProcesses: any) => {
|
||||
this.getMyProcesses().then((myProcesses: string[]) => {
|
||||
const processesFiltered: { [processId: string]: any } = {};
|
||||
for (const processId of myProcesses) {
|
||||
const process = processes[processId];
|
||||
@ -500,16 +695,18 @@ export default class MessageBus {
|
||||
accessToken,
|
||||
messageId
|
||||
});
|
||||
}).catch(console.error);
|
||||
}).catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
public getMyProcesses(): Promise<any> {
|
||||
return new Promise<any>((resolve: (processes: any) => void, reject: (error: string) => void) => {
|
||||
// Returns the processes id of processes we are involved in
|
||||
// It's meant to be used to filter processes in the getProcesses() method
|
||||
public getMyProcesses(): Promise<string[]> {
|
||||
return new Promise<string[]>((resolve: (processes: string[]) => void, reject: (error: string) => void) => {
|
||||
this.checkToken().then(() => {
|
||||
const messageId = `GET_MY_PROCESSES_${uuidv4()}`;
|
||||
|
||||
const unsubscribe = EventBus.getInstance().on('GET_MY_PROCESSES', (responseId: string, processes: any) => {
|
||||
const unsubscribe = EventBus.getInstance().on('GET_MY_PROCESSES', (responseId: string, processes: string[]) => {
|
||||
if (responseId !== messageId) {
|
||||
return;
|
||||
}
|
||||
@ -533,7 +730,7 @@ export default class MessageBus {
|
||||
accessToken,
|
||||
messageId
|
||||
});
|
||||
}).catch(console.error);
|
||||
}).catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
@ -568,7 +765,7 @@ export default class MessageBus {
|
||||
accessToken,
|
||||
messageId
|
||||
});
|
||||
}).catch(console.error);
|
||||
}).catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
@ -603,7 +800,7 @@ export default class MessageBus {
|
||||
accessToken,
|
||||
messageId
|
||||
});
|
||||
}).catch(console.error);
|
||||
}).catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
@ -638,7 +835,7 @@ export default class MessageBus {
|
||||
accessToken,
|
||||
messageId
|
||||
});
|
||||
}).catch(console.error);
|
||||
}).catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
@ -672,7 +869,7 @@ export default class MessageBus {
|
||||
accessToken,
|
||||
messageId
|
||||
});
|
||||
}).catch(console.error);
|
||||
}).catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
@ -874,6 +1071,7 @@ export default class MessageBus {
|
||||
const targetOrigin = IframeReference.getTargetOrigin();
|
||||
const iframe = IframeReference.getIframe();
|
||||
iframe.contentWindow?.postMessage(message, targetOrigin);
|
||||
this.messagesSent.add(message.messageId);
|
||||
} catch (error) {
|
||||
console.error('[MessageBus] sendMessage: error', error);
|
||||
}
|
||||
@ -975,19 +1173,26 @@ export default class MessageBus {
|
||||
|
||||
case 'ERROR':
|
||||
console.error('Error:', message);
|
||||
this.errors[message.messageId] = message.error;
|
||||
// Extract operation type from messageId by splitting on last underscore
|
||||
const operationType = this.extractOperationTypeFromMessageId(message.messageId);
|
||||
EventBus.getInstance().emit(`ERROR_${operationType}`, message.messageId, message.error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private doHandleMessage(messageId: string, messageType: string, message: any, callback: (message: any) => any) {
|
||||
if (this.errors[messageId]) {
|
||||
const error = this.errors[messageId];
|
||||
delete this.errors[messageId];
|
||||
EventBus.getInstance().emit(`ERROR_${messageType}`, messageId, error);
|
||||
return;
|
||||
private extractOperationTypeFromMessageId(messageId: string): string {
|
||||
// Split on last underscore to extract operation type
|
||||
// e.g., "GET_PAIRING_ID_abc123" -> "GET_PAIRING_ID"
|
||||
const lastUnderscoreIndex = messageId.lastIndexOf('_');
|
||||
if (lastUnderscoreIndex === -1) {
|
||||
return messageId; // No underscore found, return as-is
|
||||
}
|
||||
return messageId.substring(0, lastUnderscoreIndex);
|
||||
}
|
||||
|
||||
private doHandleMessage(messageId: string, messageType: string, message: any, callback: (message: any) => any) {
|
||||
EventBus.getInstance().emit('MESSAGE_RECEIVED', message);
|
||||
EventBus.getInstance().emit(messageType, messageId, callback(message));
|
||||
this.messagesSent.delete(messageId);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user