Compare commits

..

2 Commits

Author SHA1 Message Date
8eec5b3455 Filter my processes in processes viewer 2025-06-11 20:37:52 +02:00
09e8530c6a Add getMyProcesses logic 2025-06-11 20:37:00 +02:00
3 changed files with 116 additions and 58 deletions

View File

@ -23,6 +23,7 @@ function App() {
const [showAuthModal, setShowAuthModal] = useState(false) const [showAuthModal, setShowAuthModal] = useState(false)
const [showFolderModal, setShowFolderModal] = useState(false) const [showFolderModal, setShowFolderModal] = useState(false)
const [processes, setProcesses] = useState<any>(null) const [processes, setProcesses] = useState<any>(null)
const [myProcesses, setMyProcesses] = useState<string[]>([])
const [userPairingId, setUserPairingId] = useState<string | null>(null) const [userPairingId, setUserPairingId] = useState<string | null>(null)
useEffect(() => { useEffect(() => {
@ -39,28 +40,22 @@ function App() {
messageBus.isReady().then(() => { messageBus.isReady().then(() => {
messageBus.getProcesses().then((processes: any) => { messageBus.getProcesses().then((processes: any) => {
setProcesses(processes); setProcesses(processes);
for (const key of Object.keys(processes)) {
try {
const process = processes[key];
if (Object.keys(process.states?.[0]?.keys).length === 0) {
continue;
}
console.log(key);
console.log(process);
} catch (error) {
console.error('Failed to retrieve data:', error);
}
}
}); });
}); });
} }
}, [isConnected, iframeUrl]); }, [isConnected, iframeUrl]);
useEffect(() => {
if (isConnected && processes !== null) {
const messageBus = MessageBus.getInstance(iframeUrl);
messageBus.isReady().then(() => {
messageBus.getMyProcesses().then((res: string[]) => {
setMyProcesses(res);
})
});
}
}, [isConnected, processes]);
useEffect(() => { useEffect(() => {
if (isConnected && userPairingId === null) { if (isConnected && userPairingId === null) {
const messageBus = MessageBus.getInstance(iframeUrl); const messageBus = MessageBus.getInstance(iframeUrl);
@ -174,7 +169,7 @@ function App() {
{/* Espace pour contenu supplémentaire à droite */} {/* Espace pour contenu supplémentaire à droite */}
<div className="content-area"> <div className="content-area">
{/* Affichage des blocs de la blockchain */} {/* Affichage des blocs de la blockchain */}
<BlockchainViewer processes={processes} /> <BlockchainViewer processes={processes} myProcesses={myProcesses}/>
</div> </div>
</div> </div>

View File

@ -21,10 +21,16 @@ interface Processes {
interface ProcessesViewerProps { interface ProcessesViewerProps {
processes: Processes | null; processes: Processes | null;
myProcesses: string[];
} }
function ProcessesViewer({ processes }: ProcessesViewerProps) { function ProcessesViewer({ processes, myProcesses }: ProcessesViewerProps) {
const [expandedBlocks, setExpandedBlocks] = useState<string[]>([]); const [expandedBlocks, setExpandedBlocks] = useState<string[]>([]);
const [isFiltered, setIsFiltered] = useState<boolean>(false);
const handleFilterClick = () => {
setIsFiltered(prev => !prev);
};
// Si pas de données, afficher un message // Si pas de données, afficher un message
if (!processes || Object.keys(processes).length === 0) { if (!processes || Object.keys(processes).length === 0) {
@ -87,21 +93,30 @@ function ProcessesViewer({ processes }: ProcessesViewerProps) {
return ( return (
<div className="processes-viewer"> <div className="processes-viewer">
<h2>Processus</h2> <h2>Processus</h2>
<button onClick = {handleFilterClick}>
{isFiltered ? 'Show All Processes' : 'Filter Processes'}
</button>
<p className="block-count">{Object.keys(processes).length} processus disponible(s)</p> <p className="block-count">{Object.keys(processes).length} processus disponible(s)</p>
<div className="block-list"> <div className="block-list">
{Object.entries(processes).map(([blockId, block]) => { {Object.entries(processes).map(([processId, process]) => {
const isExpanded = expandedBlocks.includes(blockId); if (isFiltered) {
const stateCount = block.states.length; // skip processes that are not in myProcesses
if (!myProcesses.includes(processId)) {
return;
}
}
const isExpanded = expandedBlocks.includes(processId);
const stateCount = process.states.length - 1; // We just ignore the last state, which is always empty
// Le premier état est le plus récent // Le premier état est le plus récent
return ( return (
<div key={blockId} className="block-item"> <div key={processId} className="block-item">
<div <div
className={`block-header ${isExpanded ? 'expanded' : ''}`} className={`block-header ${isExpanded ? 'expanded' : ''}`}
onClick={() => toggleBlock(blockId)} onClick={() => toggleBlock(processId)}
> >
<div className="block-id">{blockId.substring(0, 8)}...{blockId.substring(blockId.length - 4)}</div> <div className="block-id">{processId.substring(0, 8)}...{processId.substring(processId.length - 4)}</div>
<div className="block-state-count">{stateCount} état(s)</div> <div className="block-state-count">{stateCount} état(s)</div>
<div className="block-toggle">{isExpanded ? '▼' : '▶'}</div> <div className="block-toggle">{isExpanded ? '▼' : '▶'}</div>
</div> </div>
@ -109,45 +124,48 @@ function ProcessesViewer({ processes }: ProcessesViewerProps) {
{isExpanded && ( {isExpanded && (
<div className="block-details"> <div className="block-details">
<div className="block-complete-id"> <div className="block-complete-id">
<strong>ID complet:</strong> {blockId} <strong>ID complet:</strong> {processId}
</div> </div>
{block.states.map((state, index) => ( {process.states.map((state, index) => {
<div key={`${blockId}-state-${index}`} className="state-item"> if (index === stateCount - 1) return null;
<h4>État {index + 1}</h4> return (
<div className="state-detail"> <div key={`${processId}-state-${index}`} className="state-item">
<strong>State ID:</strong> {state.state_id} <h4>État {index + 1}</h4>
</div> <div className="state-detail">
<div className="state-detail"> <strong>State ID:</strong> {state.state_id}
<strong>Commited dans:</strong> {state.commited_in}
</div>
<div className="state-public-data">
<h5>Données publiques</h5>
<div className="public-data-item">
<strong>Nom:</strong> {formatName(state.public_data.memberPublicName)}
</div> </div>
{state.public_data.pairedAddresses && ( <div className="state-detail">
<strong>Commited dans:</strong> {state.commited_in}
</div>
<div className="state-public-data">
<h5>Données publiques</h5>
<div className="public-data-item"> <div className="public-data-item">
<strong>Adresses associées:</strong> <strong>Nom:</strong> {formatName(state.public_data.memberPublicName)}
<ul className="address-list">
{Array.isArray(state.public_data.pairedAddresses) ?
(typeof state.public_data.pairedAddresses[0] === 'string' ? (
(state.public_data.pairedAddresses as string[]).map((addr, i) => (
<li key={i}>{addr}</li>
))
) : (
<li>{formatAddress(state.public_data.pairedAddresses as number[])}</li>
)) : (
<li>{String(state.public_data.pairedAddresses || '')}</li>
)
}
</ul>
</div> </div>
)} {state.public_data.pairedAddresses && (
<div className="public-data-item">
<strong>Adresses associées:</strong>
<ul className="address-list">
{Array.isArray(state.public_data.pairedAddresses) ?
(typeof state.public_data.pairedAddresses[0] === 'string' ? (
(state.public_data.pairedAddresses as string[]).map((addr, i) => (
<li key={i}>{addr}</li>
))
) : (
<li>{formatAddress(state.public_data.pairedAddresses as number[])}</li>
)) : (
<li>{String(state.public_data.pairedAddresses || '')}</li>
)
}
</ul>
</div>
)}
</div>
</div> </div>
</div> );
))} })}
</div> </div>
)} )}
</div> </div>

View File

@ -228,6 +228,41 @@ export default class MessageBus {
}); });
} }
public getMyProcesses(): Promise<string[]> {
return new Promise<string[]>((resolve: (myProcesses: string[]) => 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('GET_MY_PROCESSES', (responseId: string, myProcesses: string[]) => {
if (responseId !== correlationId) {
return;
}
unsubscribe();
this.destroyMessageListener();
resolve(myProcesses);
});
const unsubscribeError = EventBus.getInstance().on('ERROR_GET_MY_PROCESSES', (responseId: string, error: string) => {
if (responseId !== correlationId) {
return;
}
unsubscribeError();
this.destroyMessageListener();
reject(error);
});
this.sendMessage({
type: 'GET_MY_PROCESSES',
accessToken,
});
}).catch(console.error);
});
}
public getData(processId: string, stateId: string): Promise<any> { public getData(processId: string, stateId: string): Promise<any> {
return new Promise<any>((resolve: (data: any) => void, reject: (error: string) => void) => { return new Promise<any>((resolve: (data: any) => void, reject: (error: string) => void) => {
this.checkToken().then(() => { this.checkToken().then(() => {
@ -444,6 +479,16 @@ export default class MessageBus {
EventBus.getInstance().emit('PROCESSES_RETRIEVED', correlationId, message.processes); EventBus.getInstance().emit('PROCESSES_RETRIEVED', correlationId, message.processes);
break; break;
case 'GET_MY_PROCESSES':
if (this.errors[correlationId]) {
const error = this.errors[correlationId];
delete this.errors[correlationId];
EventBus.getInstance().emit('ERROR_GET_MY_PROCESSES', correlationId, error);
return;
}
EventBus.getInstance().emit('GET_MY_PROCESSES', correlationId, message.myProcesses);
break;
case 'PROFILE_CREATED': // CREATE_PROFILE case 'PROFILE_CREATED': // CREATE_PROFILE
if (this.errors[correlationId]) { if (this.errors[correlationId]) {
const error = this.errors[correlationId]; const error = this.errors[correlationId];