126 lines
4.7 KiB
TypeScript
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>
|
|
);
|
|
};
|