before refactory workflowAutomation
All checks were successful
Deploy Nyla Frontend to Integration / deploy (push) Successful in 1m23s

This commit is contained in:
ValueOn AG 2026-06-07 22:26:22 +02:00
parent 49c3cf7290
commit d398907edc
10 changed files with 1623 additions and 1594 deletions

View file

@ -44,6 +44,7 @@ import { AdminMandateWizardPage, AdminInvitationWizardPage } from './pages/admin
import { PromptsPage, FilesPage, ConnectionsPage } from './pages/basedata'; import { PromptsPage, FilesPage, ConnectionsPage } from './pages/basedata';
import { BillingDataView, BillingAdmin, BillingMandateView, AdminSubscriptionsPage } from './pages/billing'; import { BillingDataView, BillingAdmin, BillingMandateView, AdminSubscriptionsPage } from './pages/billing';
import { AutomationsDashboardPage } from './pages/AutomationsDashboardPage'; import { AutomationsDashboardPage } from './pages/AutomationsDashboardPage';
import { WorkflowAutomationPage } from './pages/WorkflowAutomationPage';
import { RagInventoryPage } from './pages/RagInventoryPage'; import { RagInventoryPage } from './pages/RagInventoryPage';
import { ComplianceAuditPage } from './pages/ComplianceAuditPage'; import { ComplianceAuditPage } from './pages/ComplianceAuditPage';
function App() { function App() {
@ -128,6 +129,11 @@ function App() {
{/* ============================================== */} {/* ============================================== */}
<Route path="automations" element={<AutomationsDashboardPage />} /> <Route path="automations" element={<AutomationsDashboardPage />} />
{/* ============================================== */}
{/* WORKFLOW AUTOMATION (System-Komponente) */}
{/* ============================================== */}
<Route path="workflow-automation" element={<WorkflowAutomationPage />} />
{/* ============================================== */} {/* ============================================== */}
{/* RAG INVENTORY */} {/* RAG INVENTORY */}
{/* ============================================== */} {/* ============================================== */}
@ -170,13 +176,9 @@ function App() {
<Route path="templates" element={<FeatureViewPage view="templates" />} /> <Route path="templates" element={<FeatureViewPage view="templates" />} />
<Route path="logs" element={<FeatureViewPage view="logs" />} /> <Route path="logs" element={<FeatureViewPage view="logs" />} />
{/* Workspace + Automation2 Editor */} {/* Workspace Editor */}
<Route path="editor" element={<FeatureViewPage view="editor" />} /> <Route path="editor" element={<FeatureViewPage view="editor" />} />
{/* Automation2: legacy workflows URL → editor */}
<Route path="workflows" element={<Navigate to="../editor" replace />} />
<Route path="workflows-tasks" element={<FeatureViewPage view="workflows-tasks" />} />
{/* Teams Bot Feature Views */} {/* Teams Bot Feature Views */}
<Route path="sessions" element={<FeatureViewPage view="sessions" />} /> <Route path="sessions" element={<FeatureViewPage view="sessions" />} />
<Route path="settings" element={<FeatureViewPage view="settings" />} /> <Route path="settings" element={<FeatureViewPage view="settings" />} />

View file

@ -228,6 +228,7 @@ export const MandateNavigation: React.FC = () => {
let systemBlock: { title: string; items: NavigationItem[]; subgroups?: NavSubgroup[] } | null = null; let systemBlock: { title: string; items: NavigationItem[]; subgroups?: NavSubgroup[] } | null = null;
let adminBlock: { title: string; items: NavigationItem[]; subgroups: NavSubgroup[] } | null = null; let adminBlock: { title: string; items: NavigationItem[]; subgroups: NavSubgroup[] } | null = null;
const extraStaticBlocks: { id: string; title: string; items: NavigationItem[]; order: number }[] = [];
for (const block of blocks) { for (const block of blocks) {
if (block.type === 'static') { if (block.type === 'static') {
@ -236,8 +237,7 @@ export const MandateNavigation: React.FC = () => {
} else if (block.id === 'system') { } else if (block.id === 'system') {
systemBlock = { title: block.title, items: block.items || [], subgroups: block.subgroups }; systemBlock = { title: block.title, items: block.items || [], subgroups: block.subgroups };
} else if (block.items.length > 0) { } else if (block.items.length > 0) {
if (!systemBlock) systemBlock = { title: block.title, items: [], subgroups: [] }; extraStaticBlocks.push({ id: block.id, title: block.title, items: block.items, order: block.order ?? 50 });
systemBlock.items.push(...block.items);
} }
} }
} }
@ -267,6 +267,19 @@ export const MandateNavigation: React.FC = () => {
} }
} }
for (const extra of extraStaticBlocks.sort((a, b) => a.order - b.order)) {
const extraChildren = extra.items.map(i => _navigationItemToTreeNode(i));
if (extraChildren.length > 0) {
if (items.length > 0) items.push({ type: 'separator' });
items.push({
id: extra.id,
label: extra.title,
children: extraChildren,
defaultExpanded: true,
});
}
}
for (const block of blocks) { for (const block of blocks) {
if (block.type === 'dynamic') { if (block.type === 'dynamic') {
const mandateNodes = _dynamicBlockToTreeNodes(block, _handleRename, t); const mandateNodes = _dynamicBlockToTreeNodes(block, _handleRename, t);

View file

@ -2,7 +2,6 @@ import type { KeepAliveEntry } from '../types/keepAlive.types';
import { AdminDatabaseHealthPage } from '../pages/admin/AdminDatabaseHealthPage'; import { AdminDatabaseHealthPage } from '../pages/admin/AdminDatabaseHealthPage';
import { AdminLanguagesPage } from '../pages/admin/AdminLanguagesPage'; import { AdminLanguagesPage } from '../pages/admin/AdminLanguagesPage';
import { CommcoachSessionView } from '../pages/views/commcoach'; import { CommcoachSessionView } from '../pages/views/commcoach';
import { GraphicalEditorPage } from '../pages/views/graphicalEditor/GraphicalEditorPage';
import { WorkspacePage } from '../pages/views/workspace/WorkspacePage'; import { WorkspacePage } from '../pages/views/workspace/WorkspacePage';
export const KEEP_ALIVE_ROUTES: KeepAliveEntry[] = [ export const KEEP_ALIVE_ROUTES: KeepAliveEntry[] = [
@ -22,18 +21,6 @@ export const KEEP_ALIVE_ROUTES: KeepAliveEntry[] = [
shellOverflowHidden: false, shellOverflowHidden: false,
render: ({ scopeKey }) => <CommcoachSessionView key={scopeKey} />, render: ({ scopeKey }) => <CommcoachSessionView key={scopeKey} />,
}, },
{
id: 'graphical-editor',
pathRegex: /\/mandates\/[^/]+\/graphicalEditor\/[^/]+\/editor/,
scopeRegex: /\/mandates\/([^/]+)\/graphicalEditor\/([^/]+)\/editor/,
render: ({ mandateId, instanceId, scopeKey }) => (
<GraphicalEditorPage
key={scopeKey}
persistentInstanceId={instanceId}
persistentMandateId={mandateId}
/>
),
},
{ {
id: 'admin-languages', id: 'admin-languages',
pathRegex: /\/admin\/languages(?:$|\/)/, pathRegex: /\/admin\/languages(?:$|\/)/,

View file

@ -23,6 +23,7 @@ import {
FaProjectDiagram, FaMapMarkedAlt, FaWallet, FaMoneyBillAlt, FaClock, FaProjectDiagram, FaMapMarkedAlt, FaWallet, FaMoneyBillAlt, FaClock,
FaHeadset, FaVideo, FaHatWizard, FaStore, FaUserTie, FaClipboardList, FaHeadset, FaVideo, FaHatWizard, FaStore, FaUserTie, FaClipboardList,
FaFileContract, FaRobot, FaGlobe, FaClipboardCheck, FaFileContract, FaRobot, FaGlobe, FaClipboardCheck,
FaSitemap, FaCopy, FaTasks,
} from 'react-icons/fa'; } from 'react-icons/fa';
// ============================================================================= // =============================================================================
@ -55,6 +56,13 @@ export const PAGE_ICONS: Record<string, React.ReactNode> = {
'page.system.automations': <FaRobot />, 'page.system.automations': <FaRobot />,
'page.system.ragInventory': <FaDatabase />, 'page.system.ragInventory': <FaDatabase />,
// System pages - Workflow Automation
'page.system.workflowAutomation.workflows': <FaSitemap />,
'page.system.workflowAutomation.editor': <FaProjectDiagram />,
'page.system.workflowAutomation.templates': <FaCopy />,
'page.system.workflowAutomation.runs': <FaPlay />,
'page.system.workflowAutomation.tasks': <FaTasks />,
// Billing pages (legacy compat) // Billing pages (legacy compat)
'page.billing.dashboard': <FaWallet />, 'page.billing.dashboard': <FaWallet />,
'page.billing.transactions': <FaListAlt />, 'page.billing.transactions': <FaListAlt />,
@ -132,9 +140,6 @@ export const PAGE_ICONS: Record<string, React.ReactNode> = {
'feature.trustee': <FaBriefcase />, 'feature.trustee': <FaBriefcase />,
'feature.realestate': <FaBuilding />, 'feature.realestate': <FaBuilding />,
'feature.chatworkflow': <FaPlay />, 'feature.chatworkflow': <FaPlay />,
'feature.graphicalEditor': <FaProjectDiagram />,
'page.feature.graphicalEditor.editor': <FaProjectDiagram />,
'page.feature.graphicalEditor.workflows-tasks': <FaClipboardList />,
'feature.teamsbot': <FaHeadset />, 'feature.teamsbot': <FaHeadset />,
// Feature pages - Workspace // Feature pages - Workspace

File diff suppressed because it is too large Load diff

View file

@ -25,10 +25,6 @@ import { TrusteeDataTablesView } from './views/trustee/TrusteeDataTablesView';
// RealEstate Views // RealEstate Views
import { RealEstatePekView, RealEstateInstanceRolesPlaceholder } from './views/realestate'; import { RealEstatePekView, RealEstateInstanceRolesPlaceholder } from './views/realestate';
// GraphicalEditor Views
import { GraphicalEditorPage } from './views/graphicalEditor/GraphicalEditorPage';
import { GraphicalEditorWorkflowsTasksPage } from './views/graphicalEditor/GraphicalEditorWorkflowsTasksPage';
import { GraphicalEditorTemplatesPage } from './views/graphicalEditor/GraphicalEditorTemplatesPage';
// Workspace Views // Workspace Views
import { WorkspacePage } from './views/workspace/WorkspacePage'; import { WorkspacePage } from './views/workspace/WorkspacePage';
import { WorkspaceEditorPage } from './views/workspace/WorkspaceEditorPage'; import { WorkspaceEditorPage } from './views/workspace/WorkspaceEditorPage';
@ -129,11 +125,6 @@ const VIEW_COMPONENTS: Record<string, Record<string, ViewComponent>> = {
dashboard: RealEstatePekView, dashboard: RealEstatePekView,
'instance-roles': RealEstateInstanceRolesPlaceholder, 'instance-roles': RealEstateInstanceRolesPlaceholder,
}, },
graphicalEditor: {
editor: GraphicalEditorPage,
'workflows-tasks': GraphicalEditorWorkflowsTasksPage,
templates: GraphicalEditorTemplatesPage,
},
workspace: { workspace: {
dashboard: WorkspacePage, dashboard: WorkspacePage,
editor: WorkspaceEditorPage, editor: WorkspaceEditorPage,

View file

@ -5,7 +5,7 @@
*/ */
import React from 'react'; import React from 'react';
import { FaCogs, FaComments, FaHeadset, FaProjectDiagram, FaShieldAlt } from 'react-icons/fa'; import { FaCogs, FaComments, FaHeadset, FaShieldAlt } from 'react-icons/fa';
import { useLanguage } from '../providers/language/LanguageContext'; import { useLanguage } from '../providers/language/LanguageContext';
import { mandateDisplayLabel } from '../utils/mandateDisplayUtils'; import { mandateDisplayLabel } from '../utils/mandateDisplayUtils';
import { useStore, _storeActionKey } from '../hooks/useStore'; import { useStore, _storeActionKey } from '../hooks/useStore';
@ -15,7 +15,6 @@ import styles from './Store.module.css';
const FEATURE_ICONS: Record<string, React.ReactNode> = { const FEATURE_ICONS: Record<string, React.ReactNode> = {
automation: <FaCogs />, automation: <FaCogs />,
graphicalEditor: <FaProjectDiagram />,
teamsbot: <FaHeadset />, teamsbot: <FaHeadset />,
workspace: <FaComments />, workspace: <FaComments />,
commcoach: <FaComments />, commcoach: <FaComments />,
@ -25,7 +24,6 @@ const FEATURE_ICONS: Record<string, React.ReactNode> = {
/** Fallback when GET /store/features omits description (German i18n keys). */ /** Fallback when GET /store/features omits description (German i18n keys). */
const STORE_FEATURE_DESCRIPTION_FALLBACK: Record<string, string> = { const STORE_FEATURE_DESCRIPTION_FALLBACK: Record<string, string> = {
automation: 'Erstelle und verwalte Automatisierungen, um wiederkehrende Aufgaben effizient zu erledigen.', automation: 'Erstelle und verwalte Automatisierungen, um wiederkehrende Aufgaben effizient zu erledigen.',
graphicalEditor: 'n8n-style Flow-Automatisierung mit grafischem Editor, RAG und Tools.',
teamsbot: 'Integriere einen AI-Bot in deine Microsoft Teams Meetings und Channels.', teamsbot: 'Integriere einen AI-Bot in deine Microsoft Teams Meetings und Channels.',
workspace: 'Nutze den gemeinsamen AI Workspace: Chats, Tools und Kontext pro Instanz.', workspace: 'Nutze den gemeinsamen AI Workspace: Chats, Tools und Kontext pro Instanz.',
commcoach: 'CommCoach: Kommunikation trainieren mit KI-gestütztem Coaching und Feedback.', commcoach: 'CommCoach: Kommunikation trainieren mit KI-gestütztem Coaching und Feedback.',

File diff suppressed because it is too large Load diff

View file

@ -44,7 +44,15 @@ function _formatTs(ts?: number): string {
return time; return time;
} }
export const GraphicalEditorTemplatesPage: React.FC = () => { interface GraphicalEditorTemplatesPageProps {
persistentInstanceId?: string;
persistentMandateId?: string;
}
export const GraphicalEditorTemplatesPage: React.FC<GraphicalEditorTemplatesPageProps> = ({
persistentInstanceId,
persistentMandateId,
}) => {
const { t } = useLanguage(); const { t } = useLanguage();
const scopeLabels = useMemo( const scopeLabels = useMemo(
@ -57,8 +65,10 @@ export const GraphicalEditorTemplatesPage: React.FC = () => {
[t], [t],
); );
const instanceId = useInstanceId(); const urlInstanceId = useInstanceId();
const { mandateId } = useParams<{ mandateId: string }>(); const { mandateId: urlMandateId } = useParams<{ mandateId: string }>();
const instanceId = persistentInstanceId || urlInstanceId;
const mandateId = persistentMandateId || urlMandateId;
const { request } = useApiRequest(); const { request } = useApiRequest();
const navigate = useNavigate(); const navigate = useNavigate();
const { showSuccess, showError } = useToast(); const { showSuccess, showError } = useToast();

View file

@ -182,113 +182,9 @@ export interface FeatureConfig {
deprecated?: boolean; deprecated?: boolean;
} }
// ============================================================================= // FEATURE_REGISTRY removed (2026-06-07).
// FEATURE REGISTRY (DEPRECATED) // Navigation is provided by the backend via GET /api/navigation.
// ============================================================================= // Icon mapping is handled by src/config/pageRegistry.ts using uiComponent codes.
/**
* @deprecated Since Navigation-API-Konzept implementation.
*
* Navigation is now provided by the backend via GET /api/navigation.
* The backend is the Single Source of Truth for navigation structure.
*
* Icon mapping is now handled by src/config/pageRegistry.ts using uiComponent codes.
*
* This registry is kept for backward compatibility with existing code that may
* still reference it. It will be removed in a future version.
*
* TODO: Remove after all references are migrated to use backend navigation.
*/
export const FEATURE_REGISTRY: Record<string, FeatureConfig> = {
trustee: {
code: 'trustee',
label: 'Treuhand',
icon: 'briefcase',
views: [
{ code: 'dashboard', label: 'Übersicht', path: 'dashboard' },
{ code: 'data-tables', label: 'Daten-Tabellen', path: 'data-tables' },
{ code: 'position-documents', label: 'Zuordnungen', path: 'position-documents' },
{ code: 'import-process', label: 'Import & Verarbeitung', path: 'import-process' },
{ code: 'instance-roles', label: 'Rollen & Rechte', path: 'instance-roles', adminOnly: true },
{ code: 'settings', label: 'Buchhaltungseinstellungen', path: 'settings' },
]
},
chatworkflow: {
code: 'chatworkflow',
label: 'Workflow',
icon: 'play_circle',
views: [
{ code: 'dashboard', label: 'Übersicht', path: 'dashboard' },
{ code: 'runs', label: 'Runs', path: 'runs' },
{ code: 'files', label: 'Dateien', path: 'files' },
]
},
realestate: {
code: 'realestate',
label: 'Immobilien',
icon: 'home',
views: [
{ code: 'dashboard', label: 'Karte', path: 'dashboard' },
{ code: 'instance-roles', label: 'Rollen & Rechte', path: 'instance-roles', adminOnly: true },
]
},
teamsbot: {
code: 'teamsbot',
label: 'Teams Bot',
icon: 'headset_mic',
views: [
{ code: 'dashboard', label: 'Dashboard', path: 'dashboard' },
{ code: 'assistant', label: 'Assistent', path: 'assistant' },
{ code: 'modules', label: 'Module', path: 'modules' },
{ code: 'sessions', label: 'Live-Session', path: 'sessions' },
{ code: 'settings', label: 'Einstellungen', path: 'settings' },
]
},
graphicalEditor: {
code: 'graphicalEditor',
label: 'Grafischer Editor',
icon: 'sitemap',
views: [
{ code: 'editor', label: 'Editor', path: 'editor' },
{ code: 'templates', label: 'Vorlagen', path: 'templates' },
{ code: 'workflows-tasks', label: 'Tasks', path: 'workflows-tasks' },
{ code: 'dashboard', label: 'Dashboard', path: 'dashboard' },
]
},
neutralization: {
code: 'neutralization',
label: 'Neutralisierung',
icon: 'shield_check',
views: [
{ code: 'dashboard', label: 'Neutralisierung testen', path: 'playground' },
{ code: 'playground', label: 'Neutralisierung testen', path: 'playground' },
{ code: 'config', label: 'Einstellungen', path: 'config' },
{ code: 'attributes', label: 'Attribute', path: 'attributes' },
]
},
commcoach: {
code: 'commcoach',
label: 'Kommunikations-Coach',
icon: 'account_voice',
views: [
{ code: 'dashboard', label: 'Dashboard', path: 'dashboard' },
{ code: 'assistant', label: 'Assistent', path: 'assistant' },
{ code: 'modules', label: 'Module', path: 'modules' },
{ code: 'session', label: 'Session', path: 'session' },
{ code: 'settings', label: 'Einstellungen', path: 'settings' },
]
},
workspace: {
code: 'workspace',
label: 'AI Workspace',
icon: 'psychology',
views: [
{ code: 'dashboard', label: 'Dashboard', path: 'dashboard' },
{ code: 'editor', label: 'Editor', path: 'editor' },
{ code: 'settings', label: 'Einstellungen', path: 'settings' },
]
},
};
// ============================================================================= // =============================================================================
// HELPERS // HELPERS