frontend_nyla/src/pages/views/graphicalEditor/GraphicalEditorPage.tsx
2026-04-11 00:07:30 +02:00

126 lines
4.7 KiB
TypeScript

/**
* GraphicalEditorPage
*
* Thin wrapper: passes instance context to FlowEditor which now owns the full layout
* including the Workspace panel (Chats/Dateien/Quellen) on the left.
*/
import React, { useState, useCallback, useEffect, useRef } from 'react';
import { useSearchParams } from 'react-router-dom';
import { useInstanceId, useMandateId } from '../../../hooks/useCurrentInstance';
import { useLanguage } from '../../../providers/language/LanguageContext';
import { Automation2FlowEditor as FlowEditor } from '../../../components/FlowEditor';
import type { PendingFile, EditorDataSource, EditorFeatureDataSource } from '../../../components/FlowEditor';
import api from '../../../api';
interface GraphicalEditorPageProps {
persistentInstanceId?: string;
persistentMandateId?: string;
}
export const GraphicalEditorPage: React.FC<GraphicalEditorPageProps> = ({
persistentInstanceId,
persistentMandateId,
}) => {
const urlInstanceId = useInstanceId();
const urlMandateId = useMandateId();
const instanceId = persistentInstanceId || urlInstanceId;
const mandateId = persistentMandateId || urlMandateId;
const [searchParams] = useSearchParams();
const workflowIdFromUrl = searchParams.get('workflowId');
const [activeWorkflowId, setActiveWorkflowId] = useState<string | null>(workflowIdFromUrl);
const prevWorkflowIdRef = useRef(workflowIdFromUrl);
useEffect(() => {
if (workflowIdFromUrl && workflowIdFromUrl !== prevWorkflowIdRef.current) {
prevWorkflowIdRef.current = workflowIdFromUrl;
setActiveWorkflowId(workflowIdFromUrl);
}
}, [workflowIdFromUrl]);
const { t, currentLanguage } = useLanguage();
const language = (currentLanguage?.slice(0, 2) || 'de') as string;
const [pendingFiles, setPendingFiles] = useState<PendingFile[]>([]);
const [dataSources, setDataSources] = useState<EditorDataSource[]>([]);
const [featureDataSources, setFeatureDataSources] = useState<EditorFeatureDataSource[]>([]);
useEffect(() => {
if (!instanceId) return;
api.get(`/api/workspace/${instanceId}/datasources`)
.then(res => {
const list = (res.data.dataSources || res.data || []).map((d: any) => ({
id: d.id, label: d.label || d.path || d.id, path: d.path, sourceType: d.sourceType,
}));
setDataSources(list);
})
.catch(() => setDataSources([]));
}, [instanceId]);
useEffect(() => {
if (!instanceId) return;
api.get(`/api/workspace/${instanceId}/feature-datasources`)
.then(res => {
const list = (res.data.featureDataSources || res.data || []).map((d: any) => ({
id: d.id, featureInstanceId: d.featureInstanceId, featureCode: d.featureCode,
tableName: d.tableName, label: d.label || d.tableName,
}));
setFeatureDataSources(list);
})
.catch(() => setFeatureDataSources([]));
}, [instanceId]);
const _handleFileSelect = useCallback((fileId: string, fileName?: string) => {
setPendingFiles(prev => {
if (prev.some(f => f.fileId === fileId)) return prev;
return [...prev, { fileId, fileName: fileName || fileId.slice(0, 12) }];
});
}, []);
const _handleRemovePendingFile = useCallback((fileId: string) => {
setPendingFiles(prev => prev.filter(f => f.fileId !== fileId));
}, []);
const _handleSourcesChanged = useCallback(() => {
if (!instanceId) return;
api.get(`/api/workspace/${instanceId}/datasources`)
.then(res => {
setDataSources((res.data.dataSources || res.data || []).map((d: any) => ({
id: d.id, label: d.label || d.path || d.id, path: d.path, sourceType: d.sourceType,
})));
})
.catch(() => {});
api.get(`/api/workspace/${instanceId}/feature-datasources`)
.then(res => {
setFeatureDataSources((res.data.featureDataSources || res.data || []).map((d: any) => ({
id: d.id, featureInstanceId: d.featureInstanceId, featureCode: d.featureCode,
tableName: d.tableName, label: d.label || d.tableName,
})));
})
.catch(() => {});
}, [instanceId]);
if (!instanceId) {
return (
<div style={{ padding: '2rem', textAlign: 'center' }}>
<p>{t('Keine Feature-Instanz gefunden')}</p>
</div>
);
}
return (
<div style={{ flex: 1, minHeight: 0, display: 'flex' }}>
<FlowEditor
instanceId={instanceId}
mandateId={mandateId || undefined}
language={language}
initialWorkflowId={activeWorkflowId}
pendingFiles={pendingFiles}
onRemovePendingFile={_handleRemovePendingFile}
dataSources={dataSources}
featureDataSources={featureDataSources}
onFileSelect={_handleFileSelect}
onSourcesChanged={_handleSourcesChanged}
/>
</div>
);
};