From f7ae585a29ce56f1c5031fffe843bfa888ee87ae Mon Sep 17 00:00:00 2001 From: Marcel Wege Date: Mon, 8 Jun 2026 07:24:29 +0200 Subject: [PATCH] fix(operator-agents): redesign plugin DnD for visibility + fix host-list overflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add min-w-0 to the tile content column so the truncate on metadata actually shrinks instead of forcing the card to grow — root cause of the horizontal overflow on plugins with large network_outbound lists (e.g. Dynamics 365 CRM). - Replace the inline comma-joined host dump with a compact 'N hosts' chip (Globe icon, full list in the title tooltip). - Larger, scannable tiles: dedicated drag-handle rail, clearer name/id hierarchy, rounded-lg cards with hover elevation. - Column redesign: status dot + count pill, emerald accent for the Attached column, dashed drop-zone hint with active highlight. - Disabled (inactive) plugins dim; active toggle uses an accent checkbox. - Match DragOverlay to the new tile style. - New i18n keys: networkHosts (plural), networkHostsTitle (en + de). --- .../agents/_components/PluginsDnd.tsx | 198 +++++++++++------- web-ui/messages/de.json | 2 + web-ui/messages/en.json | 2 + 3 files changed, 128 insertions(+), 74 deletions(-) diff --git a/web-ui/app/operator/agents/_components/PluginsDnd.tsx b/web-ui/app/operator/agents/_components/PluginsDnd.tsx index bdccd9b4..65c387db 100644 --- a/web-ui/app/operator/agents/_components/PluginsDnd.tsx +++ b/web-ui/app/operator/agents/_components/PluginsDnd.tsx @@ -19,7 +19,7 @@ import { verticalListSortingStrategy, } from '@dnd-kit/sortable'; import { CSS } from '@dnd-kit/utilities'; -import { GripVertical } from 'lucide-react'; +import { Globe, GripVertical } from 'lucide-react'; import { useMemo, useState } from 'react'; import { useTranslations } from 'next-intl'; @@ -286,24 +286,26 @@ export function PluginsDnd(props: PluginsDndProps): React.ReactElement { return (
-

- {t('pluginsHeading')} +
+

+ {t('pluginsHeading')} +

-

+
-
+
{activeEntry ? ( -
- {activeEntry.name} - - {activeEntry.id} - +
+ + + {activeEntry.name} + +
) : null} @@ -498,29 +501,57 @@ function Column(props: { return [props.id]; }, [props.id]); + const accent = props.id === ENABLED_ID; + return (
-
- - {props.title} +
+
+ + + {props.title} + +
+ + {props.count} - {props.count}
-
+
{props.count === 0 ? ( -

+

{props.emptyLabel}

) : ( @@ -575,26 +606,32 @@ function DraggablePluginTile(props: { return (
-
-
- -
-
- +
+
+ +
+
+
+ {entry.name} - - {entry.id} - {!entry.multi_instance && ( )} - {attached && ( - - )}
+ + {entry.id} + {(entry.memory_reads.length > 0 || - entry.memory_writes.length > 0) && ( -
+ entry.memory_writes.length > 0 || + entry.network_outbound.length > 0) && ( +
{entry.memory_reads.map((s) => ( r:{s} @@ -650,24 +680,28 @@ function DraggablePluginTile(props: { w:{s} ))} + {entry.network_outbound.length > 0 && ( + + + {t('networkHosts', { count: entry.network_outbound.length })} + + )}
)} - {entry.network_outbound.length > 0 && ( -

- {t('networkLabel')} {entry.network_outbound.join(', ')} -

- )}
-
+
{!attached ? ( ) : ( <> - {hasFields && ( + +
+ {hasFields && ( + + )} - )} - +
)}
- {attached && props.expanded && hasFields && ( +
+ {attached && props.expanded && hasFields && (