From 131c4534b55d86c60c202353f8dc639854cbd979 Mon Sep 17 00:00:00 2001 From: ValueOn AG Date: Sun, 22 Mar 2026 01:20:40 +0100 Subject: [PATCH] fixed global RAG and admin consent msft --- .../TreeNavigation/TreeNavigation.module.css | 8 ++ .../TreeNavigation/TreeNavigation.tsx | 11 +- .../UiComponents/Messages/MessagesTypes.ts | 2 + src/pages/basedata/ConnectionsPage.tsx | 32 ++++- src/pages/basedata/FilesPage.tsx | 2 +- .../automation/AutomationDefinitionsView.tsx | 2 +- .../automation/AutomationTemplatesView.tsx | 2 +- src/pages/views/workspace/ChatStream.tsx | 12 ++ src/pages/views/workspace/useWorkspace.ts | 117 ++++++++++++++++-- 9 files changed, 172 insertions(+), 16 deletions(-) diff --git a/src/components/Navigation/TreeNavigation/TreeNavigation.module.css b/src/components/Navigation/TreeNavigation/TreeNavigation.module.css index 01f0722..5e9f57c 100644 --- a/src/components/Navigation/TreeNavigation/TreeNavigation.module.css +++ b/src/components/Navigation/TreeNavigation/TreeNavigation.module.css @@ -103,6 +103,14 @@ pointer-events: none; } +/* + * Label-only row under a parent that shows an icon: indent so text lines up with the + * parent's title, not with the icon column (see .nodeIcon width + .treeNode gap). + */ +.treeNodeAlignWithParentTitle { + padding-left: calc(0.5rem + 0.875rem + 0.375rem); +} + /* ============================================ */ /* DEPTH-SPECIFIC STYLES (via data-depth) */ /* ============================================ */ diff --git a/src/components/Navigation/TreeNavigation/TreeNavigation.tsx b/src/components/Navigation/TreeNavigation/TreeNavigation.tsx index 1d38b65..babceee 100644 --- a/src/components/Navigation/TreeNavigation/TreeNavigation.tsx +++ b/src/components/Navigation/TreeNavigation/TreeNavigation.tsx @@ -125,6 +125,8 @@ function isTreeSeparator(item: TreeItem): item is TreeSeparatorItem { interface TreeNodeProps { node: TreeNodeItem; level: number; + /** True when the parent row shows an icon — used to align label-only children with the parent's title text. */ + parentHasIcon?: boolean; autoExpandActive: boolean; currentPath: string; onNodeClick?: (node: TreeNodeItem) => void; @@ -134,6 +136,7 @@ interface TreeNodeProps { const TreeNode: React.FC = ({ node, level, + parentHasIcon = false, autoExpandActive, currentPath, onNodeClick, @@ -219,8 +222,9 @@ const TreeNode: React.FC = ({ ); - // Determine if we should render as NavLink or button - const nodeClasses = `${styles.treeNode} ${isLeafActive ? styles.active : ''} ${isGroupActive ? styles.activeGroup : ''} ${node.disabled ? styles.disabled : ''} ${node.className || ''}`; + // Unterknoten ohne Icon unter einem Knoten mit Icon: Text mit Eltern-Titel ausrichten (nicht mit Icon-Spalte) + const alignLabelWithParentTitle = parentHasIcon && !node.icon; + const nodeClasses = `${styles.treeNode} ${isLeafActive ? styles.active : ''} ${isGroupActive ? styles.activeGroup : ''} ${node.disabled ? styles.disabled : ''} ${alignLabelWithParentTitle ? styles.treeNodeAlignWithParentTitle : ''} ${node.className || ''}`; const nodeElement = node.path ? ( = ({ key={child.id || `${node.id}-child-${index}`} node={child} level={level + 1} + parentHasIcon={!!node.icon} autoExpandActive={autoExpandActive} currentPath={currentPath} onNodeClick={onNodeClick} @@ -304,6 +309,7 @@ const TreeSection: React.FC = ({ key={node.id || `section-${section.title}-${index}`} node={node} level={0} + parentHasIcon={false} autoExpandActive={autoExpandActive} currentPath={currentPath} onNodeClick={onNodeClick} @@ -355,6 +361,7 @@ export const TreeNavigation: React.FC = ({ key={item.id || `node-${index}`} node={item} level={0} + parentHasIcon={false} autoExpandActive={autoExpandActive} currentPath={currentPath} onNodeClick={onNodeClick} diff --git a/src/components/UiComponents/Messages/MessagesTypes.ts b/src/components/UiComponents/Messages/MessagesTypes.ts index 9ab4d6c..7aa81b3 100644 --- a/src/components/UiComponents/Messages/MessagesTypes.ts +++ b/src/components/UiComponents/Messages/MessagesTypes.ts @@ -32,6 +32,8 @@ export interface Message { role?: string; status?: string; sequenceNr?: number; + /** ISO or number from API; workspace may use publishedAt only */ + createdAt?: number; publishedAt?: number; success?: boolean; actionId?: string; diff --git a/src/pages/basedata/ConnectionsPage.tsx b/src/pages/basedata/ConnectionsPage.tsx index 9cd0b7e..5e0b662 100644 --- a/src/pages/basedata/ConnectionsPage.tsx +++ b/src/pages/basedata/ConnectionsPage.tsx @@ -9,7 +9,8 @@ import React, { useState, useMemo, useEffect } from 'react'; import { useConnections, type Connection } from '../../hooks/useConnections'; import { FormGeneratorTable } from '../../components/FormGenerator/FormGeneratorTable'; import { FormGeneratorForm } from '../../components/FormGenerator/FormGeneratorForm'; -import { FaSync, FaPlug, FaGoogle, FaMicrosoft, FaLink, FaRedo } from 'react-icons/fa'; +import { FaSync, FaPlug, FaGoogle, FaMicrosoft, FaLink, FaRedo, FaShieldAlt } from 'react-icons/fa'; +import { getApiBaseUrl } from '../../../config/config'; import styles from '../admin/Admin.module.css'; export const ConnectionsPage: React.FC = () => { @@ -37,6 +38,7 @@ export const ConnectionsPage: React.FC = () => { const [editingConnection, setEditingConnection] = useState(null); const [deletingConnections, setDeletingConnections] = useState>(new Set()); const [refreshingConnections, setRefreshingConnections] = useState>(new Set()); + const [adminConsentPending, setAdminConsentPending] = useState(false); // Initial fetch useEffect(() => { @@ -182,6 +184,24 @@ export const ConnectionsPage: React.FC = () => { } }; + // Open Microsoft Admin Consent flow in a popup + const handleAdminConsent = () => { + setAdminConsentPending(true); + const consentUrl = `${getApiBaseUrl()}/api/msft/adminconsent`; + const popup = window.open(consentUrl, 'msft-admin-consent', 'width=600,height=700,scrollbars=yes,resizable=yes'); + if (!popup) { + setAdminConsentPending(false); + return; + } + const checkClosed = setInterval(() => { + if (popup.closed) { + clearInterval(checkClosed); + setAdminConsentPending(false); + refetch(); + } + }, 1000); + }; + // Form attributes for edit modal const formAttributes = useMemo(() => { const excludedFields = ['id', 'mandateId', 'userId', '_createdBy', '_createdAt', '_modifiedAt', 'connectedAt', 'lastChecked']; @@ -204,13 +224,21 @@ export const ConnectionsPage: React.FC = () => { } return ( -
+

Verbindungen

OAuth-Verbindungen verwalten

+