Compare commits

..

No commits in common. "e6b9f58ceaf4d60a6db24135d20d7c0cde4b3fb2" and "24a8be727c6c72e361dd5a09256d08e63b422339" have entirely different histories.

6 changed files with 37 additions and 161 deletions

View File

@ -11,7 +11,7 @@ import UserStore from './sdk/UserStrore';
import Iframe from './sdk/Iframe' 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 { ProfilePrivateFields, setDefaultProfileRoles, type ProfileCreated, type ProfileData } from './sdk/models/ProfileData' import type { ProfileCreated, ProfileData } from './sdk/models/ProfileData'
import { FolderPrivateFields, setDefaultFolderRoles, type FolderCreated, type 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'
@ -66,7 +66,7 @@ function App() {
}) })
}); });
} }
}, [isConnected, userPairingId, processes]); }, [isConnected, userPairingId]);
// Gestionnaire pour afficher la modale de connexion // Gestionnaire pour afficher la modale de connexion
const handleLogin = useCallback(() => { const handleLogin = useCallback(() => {
@ -108,33 +108,21 @@ function App() {
}, []); }, []);
// Gestionnaire pour soumettre les données du profil // Gestionnaire pour soumettre les données du profil
const handleProfileSubmit = useCallback((profileData: ProfileData, validatorId: string | null, ownerId: string | null) => { const handleProfileSubmit = useCallback((profileData: ProfileData) => {
if (userPairingId !== null) { // Ajouter le validator fixe aux données du profil
if (validatorId === null && ownerId === null) { const completeProfileData = {
console.error("No validator or owner ID provided"); ...profileData,
return; validator: '884cb36a346a79af8697559f16940141f068bdf1656f88fa0df0e9ecd7311fb8:0'
} };
const messageBus = MessageBus.getInstance(iframeUrl);
if (validatorId === null) {
validatorId = userPairingId;
} else if (ownerId === null) {
ownerId = userPairingId;
}
const roles = setDefaultProfileRoles([ownerId!], validatorId!);
const profilePrivateFields = ProfilePrivateFields;
messageBus.createProfile(profileData, profilePrivateFields, roles).then((_profileCreated: ProfileCreated) => {
messageBus.notifyProcessUpdate(_profileCreated.processId, _profileCreated.process.states[0].state_id).then(() => {
messageBus.validateState(_profileCreated.processId, _profileCreated.process.states[0].state_id).then((_updatedProcess: any) => {
messageBus.getProcesses().then((processes: any) => {
setProcesses(processes);
});
});
})
});
setShowProfileModal(false); MessageBus.getInstance(iframeUrl).createProfile(completeProfileData).then((_profileCreated: ProfileCreated) => {
} MessageBus.getInstance(iframeUrl).getProcesses().then((processes: any) => {
}, [userPairingId]); setProcesses(processes);
});
});
setShowProfileModal(false);
}, []);
// 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) => {
@ -209,7 +197,7 @@ function App() {
<ProfileModal <ProfileModal
isOpen={showProfileModal} isOpen={showProfileModal}
onClose={handleCloseProfileModal} onClose={handleCloseProfileModal}
onSubmit={(profileData: ProfileData, validatorId: string | null, ownerId: string | null) => handleProfileSubmit(profileData, validatorId, ownerId)} onSubmit={handleProfileSubmit}
/> />
)} )}
{showFolderModal && ( {showFolderModal && (

View File

@ -165,21 +165,6 @@
box-shadow: 0 2px 4px rgba(103, 58, 183, 0.2); box-shadow: 0 2px 4px rgba(103, 58, 183, 0.2);
} }
.error-message {
color: red;
background-color: #ffebee; /* Light red background */
padding: 10px;
border-radius: 4px;
margin-top: 10px;
border-left: 4px solid red; /* Left border for emphasis */
font-weight: bold;
animation: fadeIn 0.5s ease-in-out;
}
.error-message::before {
content: "⚠️ "; /* Unicode for warning emoji */
}
/* Styles adaptatifs pour les écrans plus petits */ /* Styles adaptatifs pour les écrans plus petits */
@media (max-width: 768px) { @media (max-width: 768px) {
.form-row { .form-row {
@ -187,8 +172,3 @@
gap: 0.5rem; gap: 0.5rem;
} }
} }
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}

View File

@ -6,7 +6,7 @@ import type { ProfileData } from '../sdk/models/ProfileData';
interface ProfileModalProps { interface ProfileModalProps {
isOpen: boolean; isOpen: boolean;
onClose: () => void; onClose: () => void;
onSubmit: (profileData: ProfileData, validatorId: string | null, ownerId: string | null) => void; onSubmit: (profileData: ProfileData) => void;
initialData?: Partial<ProfileData>; initialData?: Partial<ProfileData>;
} }
@ -23,10 +23,6 @@ function ProfileModal({ isOpen, onClose, onSubmit, initialData = {} }: ProfileMo
idDocument: initialData.idDocument || null, idDocument: initialData.idDocument || null,
idCertified: false, idCertified: false,
}); });
const [validatorId, setValidatorId] = useState<string | null>(null);
const [ownerId, setOwnerId] = useState<string | null>(null);
const [isOwnProfile, setIsOwnProfile] = useState<boolean>(false);
const [errorMessage, setErrorMessage] = useState<string | null>(null);
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, type, files, value } = e.target; const { name, type, files, value } = e.target;
@ -48,12 +44,7 @@ function ProfileModal({ isOpen, onClose, onSubmit, initialData = {} }: ProfileMo
const handleSubmit = (e: React.FormEvent) => { const handleSubmit = (e: React.FormEvent) => {
e.preventDefault(); e.preventDefault();
if (!validatorId && !ownerId) { onSubmit(profileData);
setErrorMessage("Please set either a Validator ID or an Owner ID.");
return;
}
setErrorMessage(null);
onSubmit(profileData, validatorId, ownerId);
}; };
return ( return (
@ -185,45 +176,6 @@ function ProfileModal({ isOpen, onClose, onSubmit, initialData = {} }: ProfileMo
</div> </div>
</div> </div>
<div className="form-section">
<h3 className="section-title">Profil</h3>
<button type="button" onClick={() => setIsOwnProfile(!isOwnProfile)}>
{isOwnProfile ? "Je veux faire valider mon profil" : "Je valide le profil d'un utilisateur"}</button>
{isOwnProfile ? (
<div className="form-field">
<label htmlFor="validatorId">ID du validateur</label>
<input
type="text"
id="validatorId"
name="validatorId"
value={validatorId || ''}
onChange={(e) => {
setValidatorId(e.target.value);
setOwnerId(null);
}}
placeholder="ID du validateur"
/>
</div>
) : (
<div className="form-field">
<label htmlFor="ownerId">ID de l'utilisateur</label>
<input
type="text"
id="ownerId"
name="ownerId"
value={ownerId || ''}
onChange={(e) => {
setOwnerId(e.target.value);
setValidatorId(null);
}}
placeholder="ID de l'utilisateur"
/>
</div>
)}
</div>
{errorMessage && <div className="error-message">{errorMessage}</div>}
<div className="form-actions"> <div className="form-actions">
<button type="button" className="btn-cancel" onClick={onClose}>Annuler</button> <button type="button" className="btn-cancel" onClick={onClose}>Annuler</button>
<button type="submit" className="btn-submit">Créer le profil</button> <button type="submit" className="btn-submit">Créer le profil</button>

View File

@ -1,7 +1,7 @@
import IframeReference from './IframeReference'; import IframeReference from './IframeReference';
import EventBus from './EventBus'; import EventBus from './EventBus';
import UserStore from './UserStrore'; import UserStore from './UserStrore';
import { isProfileData, type ProfileCreated, type ProfileData } from './models/ProfileData'; import type { ProfileCreated, ProfileData } from './models/ProfileData';
import { isFolderData, type FolderCreated, type 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'; import type { RoleDefinition } from './models/Roles';
@ -301,7 +301,7 @@ export default class MessageBus {
}); });
} }
public createProfile(profileData: ProfileData, profilePrivateData: string[], roles: Record<string, RoleDefinition>): Promise<ProfileCreated> { public createProfile(profileData: ProfileData): Promise<ProfileCreated> {
return new Promise<ProfileCreated>((resolve: (profileCreated: ProfileCreated) => void, reject: (error: string) => void) => { return new Promise<ProfileCreated>((resolve: (profileCreated: ProfileCreated) => void, reject: (error: string) => void) => {
this.checkToken().then(() => { this.checkToken().then(() => {
const userStore = UserStore.getInstance(); const userStore = UserStore.getInstance();
@ -310,33 +310,16 @@ export default class MessageBus {
const correlationId = uuidv4(); const correlationId = uuidv4();
this.initMessageListener(correlationId); this.initMessageListener(correlationId);
const unsubscribe = EventBus.getInstance().on('PROCESS_CREATED', (responseId: string, processCreated: any) => { const unsubscribe = EventBus.getInstance().on('PROFILE_CREATED', (responseId: string, profileCreated: ProfileCreated) => {
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 profileData = processCreated.processData;
if (!profileData || !isProfileData(profileData)) {
reject('Returned invalid profile data');
}
if (!processCreated.processId || typeof processCreated.processId !== 'string') {
console.error('Returned invalid process id');
reject('Returned invalid process id');
}
// TODO check that process is of type Process
const profileCreated: ProfileCreated = {
processId: processCreated.processId,
process: processCreated.process,
profileData
};
resolve(profileCreated); resolve(profileCreated);
}); });
const unsubscribeError = EventBus.getInstance().on('ERROR_PROCESS_CREATED', (responseId: string, error: string) => { const unsubscribeError = EventBus.getInstance().on('ERROR_PROFILE_CREATED', (responseId: string, error: string) => {
if (responseId !== correlationId) { if (responseId !== correlationId) {
return; return;
} }
@ -346,11 +329,9 @@ export default class MessageBus {
}); });
this.sendMessage({ this.sendMessage({
type: 'CREATE_PROCESS', type: 'CREATE_PROFILE',
processData: profileData, profileData,
privateFields: profilePrivateData, accessToken,
roles,
accessToken
}); });
}).catch(console.error); }).catch(console.error);
}); });
@ -366,13 +347,14 @@ export default class MessageBus {
this.initMessageListener(correlationId); this.initMessageListener(correlationId);
const unsubscribe = EventBus.getInstance().on('PROCESS_CREATED', (responseId: string, processCreated: any) => { 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 // Return value must contain the data commited in the new process
const folderData = processCreated.processData; const folderData = processCreated.folderCreated;
if (!folderData || !isFolderData(folderData)) reject('Returned invalid process data'); if (!folderData || !isFolderData(folderData)) reject('Returned invalid process data');
if (!processCreated.processId || typeof processCreated.processId !== 'string') reject('Returned invalid process id'); if (!processCreated.processId || typeof processCreated.processId !== 'string') reject('Returned invalid process id');
// TODO check that process is of type Process // TODO check that process is of type Process

View File

@ -90,11 +90,6 @@ export interface FolderCreated {
export function setDefaultFolderRoles(ownerId: string, stakeholdersId: string[], customersId: string[]): Record<string, RoleDefinition> { export function setDefaultFolderRoles(ownerId: string, stakeholdersId: string[], customersId: string[]): Record<string, RoleDefinition> {
return { return {
demiurge: {
members: [ownerId],
validation_rules: [],
storages: []
},
owner: { owner: {
members: [ownerId], members: [ownerId],
validation_rules: [ validation_rules: [

View File

@ -1,4 +1,4 @@
import { isFileBlob, type FileBlob } from "./Data"; import type { FileBlob } from "./Data";
import type { RoleDefinition } from "./Roles"; import type { RoleDefinition } from "./Roles";
export interface ProfileData { export interface ProfileData {
@ -18,36 +18,20 @@ export function isProfileData(data: any): data is ProfileData{
if (typeof data !== 'object' || data === null) return false; if (typeof data !== 'object' || data === null) return false;
const requiredStringFields = [ const requiredStringFields = [
'folderNumber',
'name', 'name',
'surname', 'deedType',
'email', 'description',
'phone', 'archived_description',
'address', 'status',
'postalCode', 'created_at',
'city', 'updated_at'
'country',
]; ];
for (const field of requiredStringFields) { for (const field of requiredStringFields) {
if (typeof data[field] !== 'string') return false; if (typeof data[field] !== 'string') return false;
} }
const requiredBooleanFields = [
'idCertified',
];
for (const field of requiredBooleanFields) {
if (typeof data[field] !== 'boolean') return false;
}
const requiredFileFields = [
'idDocument',
];
for (const field of requiredFileFields) {
if (!isFileBlob(data[field]) && data[field] !== null) return false;
}
return true; return true;
} }
@ -80,11 +64,6 @@ export interface ProfileCreated {
export function setDefaultProfileRoles(ownerId: string[], validatorId: string): Record<string, RoleDefinition> { export function setDefaultProfileRoles(ownerId: string[], validatorId: string): Record<string, RoleDefinition> {
return { return {
demiurge: {
members: [...ownerId, validatorId],
validation_rules: [],
storages: []
},
owner: { owner: {
members: ownerId, members: ownerId,
validation_rules: [ validation_rules: [