import { useState, memo } from 'react'; import './ProcessesViewer.css'; import { isFileBlob, type FileBlob } from '../sdk/models/Data'; import MessageBus from '../sdk/MessageBus'; import { iframeUrl } from '../App'; interface BlockState { commited_in: string; state_id: string; pcd_commitment: Record; public_data: Record; // Autres propriétés disponibles si nécessaires } interface Block { states: BlockState[]; } interface Processes { [key: string]: Block; } interface ProcessesViewerProps { processes: Processes | null; myProcesses: string[]; onProcessesUpdate?: (processes: Processes) => void; } const compareStates = ( currentState: BlockState, index: number, previousState?: BlockState, currentPrivateData?: Record, previousPrivateData?: Record ) => { const result: Record = {}; // Ajouter toutes les données publiques de l'état actuel Object.keys(currentState.public_data).forEach(key => { const currentValue = currentState.public_data[key]; const previousValue = previousState?.public_data[key]; const isModified = index > 0 && previousValue !== undefined && JSON.stringify(currentValue) !== JSON.stringify(previousValue); result[key] = { value: currentValue, status: isModified ? 'modified' : 'unchanged', hash: currentState.pcd_commitment[key], isPrivate: false, stateId: currentState.state_id }; }); // Gérer les données privées if (index === 0) { // Pour le premier état, on ajoute simplement les données privées actuelles if (currentPrivateData) { Object.entries(currentPrivateData).forEach(([key, value]) => { result[key] = { value, status: 'unchanged', hash: currentState.pcd_commitment[key], isPrivate: true, stateId: currentState.state_id }; }); } } else if (previousPrivateData) { // Pour les états suivants, on commence par les données privées de l'état précédent Object.entries(previousPrivateData).forEach(([key, value]) => { result[key] = { value, status: 'unchanged', hash: previousState?.pcd_commitment[key], isPrivate: true, stateId: previousState!.state_id }; }); // Puis on met à jour les données privées qui ont changé if (currentPrivateData) { Object.entries(currentPrivateData).forEach(([key, value]) => { result[key] = { value, status: 'modified', hash: currentState.pcd_commitment[key], isPrivate: true, stateId: currentState.state_id }; }); } } return result; }; function ProcessesViewer({ processes, myProcesses, onProcessesUpdate }: ProcessesViewerProps) { const [expandedBlocks, setExpandedBlocks] = useState([]); const [isFiltered, setIsFiltered] = useState(false); const [privateData, setPrivateData] = useState>>({}); const [editingField, setEditingField] = useState<{ processId: string; stateId: string; key: string; value: any; } | null>(null); const [tempValue, setTempValue] = useState(null); const handleFilterClick = () => { setIsFiltered(prev => !prev); }; // Si pas de données, afficher un message if (!processes || Object.keys(processes).length === 0) { return (

Aucun processus disponible

Connectez-vous

); } const toggleBlock = (blockId: string) => { setExpandedBlocks(prev => prev.includes(blockId) ? prev.filter(id => id !== blockId) : [...prev, blockId] ); }; const fetchPrivateData = async (processId: string, stateId: string) => { if (!expandedBlocks.includes(processId) || !myProcesses.includes(processId)) { return; } try { const messageBus = MessageBus.getInstance(iframeUrl); await messageBus.isReady(); const data = await messageBus.getData(processId, stateId); setPrivateData(prev => ({ ...prev, [stateId]: data })); } catch (error) { console.error('Error fetching private data:', error); } }; const handleDownload = (name: string | undefined, fileBlob: FileBlob) => { const blob = new Blob([fileBlob.data], { type: fileBlob.type }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = name || 'download'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); }; const formatValue = (key: string, value: string | number[] | FileBlob) => { if (isFileBlob(value)) { return ( ); } return JSON.stringify(value || ''); }; const getDataIcon = (value: any) => { if (isFileBlob(value)) return '📄'; if (typeof value === 'string') return '📝'; if (typeof value === 'number') return '🔢'; if (Array.isArray(value)) return '📋'; if (typeof value === 'boolean') return '✅'; return '📦'; // object }; const handleFieldUpdate = async (processId: string, stateId: string, key: string, value: any) => { try { const messageBus = MessageBus.getInstance(iframeUrl); await messageBus.isReady(); const updateData = { [key]: value }; // First update the process const updatedProcess = await messageBus.updateProcess(processId, stateId, updateData, [], null); if (!updatedProcess) { throw new Error('No updated process found'); } const newStateId = updatedProcess.diffs[0]?.state_id; if (!newStateId) { throw new Error('No new state id found'); } // Then notify about the update await messageBus.notifyProcessUpdate(processId, newStateId); // Finally validate the state await messageBus.validateState(processId, newStateId); // Refresh the processes data const updatedProcesses = await messageBus.getProcesses(); if (onProcessesUpdate) { onProcessesUpdate(updatedProcesses); } console.log('Process updated successfully'); } catch (error) { console.error('Error updating field:', error); // You might want to show an error message to the user here } }; const renderEditForm = (key: string, value: any, onSave: (newValue: any) => void, onCancel: () => void) => { // Initialize tempValue when editing starts if (tempValue === null) { setTempValue(value); } const handleFormClick = (e: React.MouseEvent) => { e.stopPropagation(); e.preventDefault(); }; if (isFileBlob(value)) { return (
{ e.stopPropagation(); const file = e.target.files?.[0]; if (file) { const reader = new FileReader(); reader.onload = (event) => { if (event.target?.result) { const arrayBuffer = event.target.result as ArrayBuffer; const uint8Array = new Uint8Array(arrayBuffer); setTempValue({ type: file.type, data: uint8Array }); } }; reader.readAsArrayBuffer(file); } }} />
); } if (typeof value === 'boolean') { return (
); } if (Array.isArray(value)) { return (