Compare commits
2 Commits
32f11a56ef
...
c6f42e893b
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c6f42e893b | ||
![]() |
02a490d3e3 |
22
src/App.tsx
22
src/App.tsx
@ -12,7 +12,7 @@ import Iframe from './sdk/Iframe'
|
|||||||
import BlockchainViewer from './components/ProcessesViewer';
|
import BlockchainViewer from './components/ProcessesViewer';
|
||||||
import FolderModal from './components/FolderModal';
|
import FolderModal from './components/FolderModal';
|
||||||
import type { ProfileCreated, ProfileData } from './sdk/models/ProfileData'
|
import type { ProfileCreated, ProfileData } from './sdk/models/ProfileData'
|
||||||
import type { FolderCreated, FolderData } from './sdk/models/FolderData'
|
import { FolderPrivateFields, setDefaultFolderRoles, type FolderCreated, type FolderData } from './sdk/models/FolderData'
|
||||||
|
|
||||||
const iframeUrl = 'https://dev3.4nkweb.com'
|
const iframeUrl = 'https://dev3.4nkweb.com'
|
||||||
|
|
||||||
@ -126,14 +126,22 @@ function App() {
|
|||||||
|
|
||||||
// Gestionnaire pour soumettre les données du dossier
|
// Gestionnaire pour soumettre les données du dossier
|
||||||
const handleFolderSubmit = useCallback((folderData: FolderData) => {
|
const handleFolderSubmit = useCallback((folderData: FolderData) => {
|
||||||
MessageBus.getInstance(iframeUrl).createFolder(folderData).then((_folderCreated: FolderCreated) => {
|
if (userPairingId !== null) {
|
||||||
MessageBus.getInstance(iframeUrl).getProcesses().then((processes: any) => {
|
const roles = setDefaultFolderRoles(userPairingId, [], []);
|
||||||
setProcesses(processes);
|
const folderPrivateFields = FolderPrivateFields;
|
||||||
|
MessageBus.getInstance(iframeUrl).createFolder(folderData, folderPrivateFields, roles).then((_folderCreated: FolderCreated) => {
|
||||||
|
MessageBus.getInstance(iframeUrl).notifyProcessUpdate(_folderCreated.processId, _folderCreated.process.states[0].state_id).then(() => {
|
||||||
|
MessageBus.getInstance(iframeUrl).validateState(_folderCreated.processId, _folderCreated.process.states[0].state_id).then((_updatedProcess: any) => {
|
||||||
|
MessageBus.getInstance(iframeUrl).getProcesses().then((processes: any) => {
|
||||||
|
setProcesses(processes);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
setShowFolderModal(false);
|
setShowFolderModal(false);
|
||||||
}, []);
|
}
|
||||||
|
}, [userPairingId]);
|
||||||
|
|
||||||
// Gestionnaire du clic sur le bouton Vider les messages
|
// Gestionnaire du clic sur le bouton Vider les messages
|
||||||
const handleClearMessages = useCallback(() => {
|
const handleClearMessages = useCallback(() => {
|
||||||
|
@ -2,8 +2,9 @@ import IframeReference from './IframeReference';
|
|||||||
import EventBus from './EventBus';
|
import EventBus from './EventBus';
|
||||||
import UserStore from './UserStrore';
|
import UserStore from './UserStrore';
|
||||||
import type { ProfileCreated, ProfileData } from './models/ProfileData';
|
import type { ProfileCreated, ProfileData } from './models/ProfileData';
|
||||||
import type { FolderCreated, FolderData } from './models/FolderData';
|
import { isFolderData, type FolderCreated, type FolderData } from './models/FolderData';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
import type { RoleDefinition } from './models/Roles';
|
||||||
|
|
||||||
export default class MessageBus {
|
export default class MessageBus {
|
||||||
private static instance: MessageBus;
|
private static instance: MessageBus;
|
||||||
@ -336,7 +337,7 @@ export default class MessageBus {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public createFolder(folderData: FolderData): Promise<FolderCreated> {
|
public createFolder(folderData: FolderData, folderPrivateData: string[], roles: Record<string, RoleDefinition>): Promise<FolderCreated> {
|
||||||
return new Promise<FolderCreated>((resolve: (folderData: FolderCreated) => void, reject: (error: string) => void) => {
|
return new Promise<FolderCreated>((resolve: (folderData: FolderCreated) => void, reject: (error: string) => void) => {
|
||||||
this.checkToken().then(() => {
|
this.checkToken().then(() => {
|
||||||
const userStore = UserStore.getInstance();
|
const userStore = UserStore.getInstance();
|
||||||
@ -345,16 +346,29 @@ export default class MessageBus {
|
|||||||
const correlationId = uuidv4();
|
const correlationId = uuidv4();
|
||||||
this.initMessageListener(correlationId);
|
this.initMessageListener(correlationId);
|
||||||
|
|
||||||
const unsubscribe = EventBus.getInstance().on('FOLDER_CREATED', (responseId: string, folderCreated: FolderCreated) => {
|
const unsubscribe = EventBus.getInstance().on('PROCESS_CREATED', (responseId: string, processCreated: any) => {
|
||||||
|
console.log(processCreated);
|
||||||
if (responseId !== correlationId) {
|
if (responseId !== correlationId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
unsubscribe();
|
unsubscribe();
|
||||||
this.destroyMessageListener();
|
this.destroyMessageListener();
|
||||||
|
// Return value must contain the data commited in the new process
|
||||||
|
const folderData = processCreated.folderCreated;
|
||||||
|
if (!folderData || !isFolderData(folderData)) reject('Returned invalid process data');
|
||||||
|
if (!processCreated.processId || typeof processCreated.processId !== 'string') reject('Returned invalid process id');
|
||||||
|
// TODO check that process is of type Process
|
||||||
|
|
||||||
|
const folderCreated: FolderCreated = {
|
||||||
|
processId: processCreated.processId,
|
||||||
|
process: processCreated.process,
|
||||||
|
folderData
|
||||||
|
};
|
||||||
|
|
||||||
resolve(folderCreated);
|
resolve(folderCreated);
|
||||||
});
|
});
|
||||||
|
|
||||||
const unsubscribeError = EventBus.getInstance().on('ERROR_FOLDER_CREATED', (responseId: string, error: string) => {
|
const unsubscribeError = EventBus.getInstance().on('ERROR_PROCESS_CREATED', (responseId: string, error: string) => {
|
||||||
if (responseId !== correlationId) {
|
if (responseId !== correlationId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -364,9 +378,86 @@ export default class MessageBus {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.sendMessage({
|
this.sendMessage({
|
||||||
type: 'CREATE_FOLDER',
|
type: 'CREATE_PROCESS',
|
||||||
folderData,
|
processData: folderData,
|
||||||
token: accessToken
|
privateFields: folderPrivateData,
|
||||||
|
roles,
|
||||||
|
accessToken
|
||||||
|
});
|
||||||
|
}).catch(console.error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public notifyProcessUpdate(processId: string, stateId: string): Promise<void> {
|
||||||
|
return new Promise<void>((resolve: () => void, reject: (error: string) => void) => {
|
||||||
|
this.checkToken().then(() => {
|
||||||
|
const userStore = UserStore.getInstance();
|
||||||
|
const accessToken = userStore.getAccessToken()!;
|
||||||
|
|
||||||
|
const correlationId = uuidv4();
|
||||||
|
this.initMessageListener(correlationId);
|
||||||
|
|
||||||
|
const unsubscribe = EventBus.getInstance().on('UPDATE_NOTIFIED', (responseId: string) => {
|
||||||
|
if (responseId !== correlationId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unsubscribe();
|
||||||
|
this.destroyMessageListener();
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
const unsubscribeError = EventBus.getInstance().on('ERROR_UPDATE_NOTIFIED', (responseId: string, error: string) => {
|
||||||
|
if (responseId !== correlationId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unsubscribeError();
|
||||||
|
this.destroyMessageListener();
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.sendMessage({
|
||||||
|
type: 'NOTIFY_UPDATE',
|
||||||
|
processId,
|
||||||
|
stateId,
|
||||||
|
accessToken
|
||||||
|
});
|
||||||
|
}).catch(console.error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public validateState(processId: string, stateId: string): Promise<any> {
|
||||||
|
return new Promise<any>((resolve: (updatedProcess: any) => void, reject: (error: string) => void) => {
|
||||||
|
this.checkToken().then(() => {
|
||||||
|
const userStore = UserStore.getInstance();
|
||||||
|
const accessToken = userStore.getAccessToken()!;
|
||||||
|
|
||||||
|
const correlationId = uuidv4();
|
||||||
|
this.initMessageListener(correlationId);
|
||||||
|
|
||||||
|
const unsubscribe = EventBus.getInstance().on('STATE_VALIDATED', (responseId: string, updatedProcess: any) => {
|
||||||
|
console.log(updatedProcess);
|
||||||
|
if (responseId !== correlationId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unsubscribe();
|
||||||
|
this.destroyMessageListener();
|
||||||
|
resolve(updatedProcess);
|
||||||
|
});
|
||||||
|
|
||||||
|
const unsubscribeError = EventBus.getInstance().on('ERROR_STATE_VALIDATED', (responseId: string, error: string) => {
|
||||||
|
if (responseId !== correlationId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unsubscribeError();
|
||||||
|
this.destroyMessageListener();
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.sendMessage({
|
||||||
|
type: 'VALIDATE_STATE',
|
||||||
|
processId,
|
||||||
|
stateId,
|
||||||
|
accessToken
|
||||||
});
|
});
|
||||||
}).catch(console.error);
|
}).catch(console.error);
|
||||||
});
|
});
|
||||||
@ -520,6 +611,39 @@ export default class MessageBus {
|
|||||||
EventBus.getInstance().emit('DATA_RETRIEVED', correlationId, message.data);
|
EventBus.getInstance().emit('DATA_RETRIEVED', correlationId, message.data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'PROCESS_CREATED':
|
||||||
|
if (this.errors[correlationId]) {
|
||||||
|
const error = this.errors[correlationId];
|
||||||
|
delete this.errors[correlationId];
|
||||||
|
EventBus.getInstance().emit('ERROR_PROCESS_CREATED', correlationId, error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
EventBus.getInstance().emit('MESSAGE_RECEIVED', message);
|
||||||
|
EventBus.getInstance().emit('PROCESS_CREATED', correlationId, message.processCreated);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'UPDATE_NOTIFIED':
|
||||||
|
if (this.errors[correlationId]) {
|
||||||
|
const error = this.errors[correlationId];
|
||||||
|
delete this.errors[correlationId];
|
||||||
|
EventBus.getInstance().emit('ERROR_UPDATE_NOTIFIED', correlationId, error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
EventBus.getInstance().emit('MESSAGE_RECEIVED', message);
|
||||||
|
EventBus.getInstance().emit('UPDATE_NOTIFIED', correlationId);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'STATE_VALIDATED':
|
||||||
|
if (this.errors[correlationId]) {
|
||||||
|
const error = this.errors[correlationId];
|
||||||
|
delete this.errors[correlationId];
|
||||||
|
EventBus.getInstance().emit('ERROR_STATE_VALIDATED', correlationId, error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
EventBus.getInstance().emit('MESSAGE_RECEIVED', message);
|
||||||
|
EventBus.getInstance().emit('STATE_VALIDATED', correlationId, message.validatedProcess);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'ERROR':
|
case 'ERROR':
|
||||||
console.error('Error:', message);
|
console.error('Error:', message);
|
||||||
this.errors[correlationId] = message.error;
|
this.errors[correlationId] = message.error;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import type { RoleDefinition } from "./Roles";
|
||||||
|
|
||||||
export interface FolderData {
|
export interface FolderData {
|
||||||
folderNumber: string;
|
folderNumber: string;
|
||||||
name: string;
|
name: string;
|
||||||
@ -13,8 +15,109 @@ export interface FolderData {
|
|||||||
stakeholders: string[];
|
stakeholders: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isFolderData(data: any): data is FolderData {
|
||||||
|
if (typeof data !== 'object' || data === null) return false;
|
||||||
|
|
||||||
|
const requiredStringFields = [
|
||||||
|
'folderNumber',
|
||||||
|
'name',
|
||||||
|
'deedType',
|
||||||
|
'description',
|
||||||
|
'archived_description',
|
||||||
|
'status',
|
||||||
|
'created_at',
|
||||||
|
'updated_at'
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const field of requiredStringFields) {
|
||||||
|
if (typeof data[field] !== 'string') return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const requiredArrayFields = [
|
||||||
|
'customers',
|
||||||
|
'documents',
|
||||||
|
'motes',
|
||||||
|
'stakeholders'
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const field of requiredArrayFields) {
|
||||||
|
if (!Array.isArray(data[field]) || !data[field].every((item: any) => typeof item === 'string')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const emptyFolderData: FolderData = {
|
||||||
|
folderNumber: '',
|
||||||
|
name: '',
|
||||||
|
deedType: '',
|
||||||
|
description: '',
|
||||||
|
archived_description: '',
|
||||||
|
status: '',
|
||||||
|
created_at: '',
|
||||||
|
updated_at: '',
|
||||||
|
customers: [],
|
||||||
|
documents: [],
|
||||||
|
motes: [],
|
||||||
|
stakeholders: []
|
||||||
|
};
|
||||||
|
|
||||||
|
const folderDataFields: string[] = Object.keys(emptyFolderData);
|
||||||
|
|
||||||
|
const FolderPublicFields: string[] = [];
|
||||||
|
|
||||||
|
// All the attributes are private in that case
|
||||||
|
export const FolderPrivateFields = [
|
||||||
|
...folderDataFields.filter(key => !FolderPublicFields.includes(key))
|
||||||
|
];
|
||||||
|
|
||||||
export interface FolderCreated {
|
export interface FolderCreated {
|
||||||
processId: string,
|
processId: string,
|
||||||
process: any, // Process
|
process: any, // Process
|
||||||
folderData: FolderData,
|
folderData: FolderData,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function setDefaultFolderRoles(ownerId: string, stakeholdersId: string[], customersId: string[]): Record<string, RoleDefinition> {
|
||||||
|
return {
|
||||||
|
owner: {
|
||||||
|
members: [ownerId],
|
||||||
|
validation_rules: [
|
||||||
|
{
|
||||||
|
quorum: 0.5,
|
||||||
|
fields: [...folderDataFields, 'roles'],
|
||||||
|
min_sig_member: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
storages: []
|
||||||
|
},
|
||||||
|
stakeholders: {
|
||||||
|
members: stakeholdersId,
|
||||||
|
validation_rules: [
|
||||||
|
{
|
||||||
|
quorum: 0.5,
|
||||||
|
fields: ['documents', 'motes'],
|
||||||
|
min_sig_member: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
storages: []
|
||||||
|
},
|
||||||
|
customers: {
|
||||||
|
members: customersId,
|
||||||
|
validation_rules: [
|
||||||
|
{
|
||||||
|
quorum: 0.0,
|
||||||
|
fields: folderDataFields,
|
||||||
|
min_sig_member: 0.0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
storages: []
|
||||||
|
},
|
||||||
|
apophis: {
|
||||||
|
members: [ownerId],
|
||||||
|
validation_rules: [],
|
||||||
|
storages: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
11
src/sdk/models/Roles.ts
Normal file
11
src/sdk/models/Roles.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
export interface ValidationRule {
|
||||||
|
quorum: number,
|
||||||
|
fields: string[],
|
||||||
|
min_sig_member: number,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RoleDefinition {
|
||||||
|
members: string[],
|
||||||
|
validation_rules: ValidationRule[],
|
||||||
|
storages: string[]
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user