From 059442b5a8351f9ab267d404e7247d5fb9acb2c1 Mon Sep 17 00:00:00 2001 From: Alessandro Date: Wed, 11 Mar 2026 11:39:03 +0100 Subject: [PATCH 1/3] feat: add collapsible arrows for plugin cards --- .../create-job/plugins/PluginsSection.tsx | 54 +++++++++++++------ 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/src/components/create-job/plugins/PluginsSection.tsx b/src/components/create-job/plugins/PluginsSection.tsx index 0763c33..d0dd17b 100644 --- a/src/components/create-job/plugins/PluginsSection.tsx +++ b/src/components/create-job/plugins/PluginsSection.tsx @@ -5,12 +5,13 @@ import { POLICY_TYPES } from '@data/policyTypes'; import { InteractionContextType, useInteractionContext } from '@lib/contexts/interaction'; import { generatePluginName, getPluginName } from '@lib/pluginNames'; import { SlateCard } from '@shared/cards/SlateCard'; +import Expander from '@shared/Expander'; import DeeployErrorAlert from '@shared/jobs/DeeployErrorAlert'; import AddJobCard from '@shared/projects/AddJobCard'; import { SmallTag } from '@shared/SmallTag'; import { computeDependencyTree } from '@lib/dependencyTree'; import { BasePluginType, GenericPlugin, Plugin, PluginType } from '@typedefs/steps/deploymentStepTypes'; -import { useEffect, useMemo, useRef } from 'react'; +import { useEffect, useMemo, useRef, useState } from 'react'; import { useFieldArray, useFormContext, useWatch } from 'react-hook-form'; import toast from 'react-hot-toast'; import { RiBox3Line, RiDeleteBin2Line, RiTerminalBoxLine } from 'react-icons/ri'; @@ -81,6 +82,7 @@ export default function PluginsSection() { }); const plugins = fields as PluginWithId[]; + const [expandedPlugins, setExpandedPlugins] = useState>({}); const previousPluginsLengthRef = useRef(plugins.length); @@ -265,11 +267,25 @@ export default function PluginsSection() {
{plugins.map((plugin, index) => { const { title, element } = getPluginAlias(plugin, index); + const isExpanded = expandedPlugins[plugin.id] ?? true; return (
+ + setExpandedPlugins((previous) => ({ + ...previous, + [plugin.id]: !(previous[plugin.id] ?? true), + })) + } + /> + {element} +
+ } label={
} > - <> - {plugin.basePluginType === BasePluginType.Generic ? ( - <> - {(plugin as GenericPlugin).deploymentType.pluginType === PluginType.Container ? ( - - ) : ( - - )} - - ) : ( - - )} - + {isExpanded ? ( + <> + {plugin.basePluginType === BasePluginType.Generic ? ( + <> + {(plugin as GenericPlugin).deploymentType.pluginType === PluginType.Container ? ( + + ) : ( + + )} + + ) : ( + + )} + + ) : null}
); From 49069f925beff3cd11e913b33bae072aefd6ddbe Mon Sep 17 00:00:00 2001 From: Alessandro Date: Wed, 11 Mar 2026 11:46:11 +0100 Subject: [PATCH 2/3] fix: prune plugin expansion state on remove --- .../create-job/plugins/PluginsSection.tsx | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/components/create-job/plugins/PluginsSection.tsx b/src/components/create-job/plugins/PluginsSection.tsx index d0dd17b..0e44b94 100644 --- a/src/components/create-job/plugins/PluginsSection.tsx +++ b/src/components/create-job/plugins/PluginsSection.tsx @@ -114,7 +114,20 @@ export default function PluginsSection() { // Clean stale shmem references when a plugin is removed const handleRemovePlugin = (indexToRemove: number) => { + const removedPluginId = plugins[indexToRemove]?.id; const removedName = watchedPlugins[indexToRemove]?.pluginName; + + if (removedPluginId) { + setExpandedPlugins((previous) => { + if (!(removedPluginId in previous)) { + return previous; + } + + const { [removedPluginId]: _removed, ...next } = previous; + return next; + }); + } + remove(indexToRemove); if (!removedName) return; @@ -254,6 +267,20 @@ export default function PluginsSection() { previousPluginsLengthRef.current = plugins.length; }, [plugins]); + useEffect(() => { + const pluginIds = new Set(plugins.map((plugin) => plugin.id)); + + setExpandedPlugins((previous) => { + const next = Object.fromEntries(Object.entries(previous).filter(([id]) => pluginIds.has(id))); + + if (Object.keys(next).length === Object.keys(previous).length) { + return previous; + } + + return next; + }); + }, [plugins]); + return (
{fields.length < 5 && ( From 2afb2017e618214049a6ab5109fcd2406860d622 Mon Sep 17 00:00:00 2001 From: Alessandro Date: Wed, 11 Mar 2026 11:47:19 +0100 Subject: [PATCH 3/3] fix: remove empty slate card body spacing --- src/shared/cards/SlateCard.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/shared/cards/SlateCard.tsx b/src/shared/cards/SlateCard.tsx index a503900..ba20f8d 100644 --- a/src/shared/cards/SlateCard.tsx +++ b/src/shared/cards/SlateCard.tsx @@ -1,4 +1,4 @@ -import { FunctionComponent, PropsWithChildren } from 'react'; +import { Children, FunctionComponent, PropsWithChildren } from 'react'; interface Props { title?: string; @@ -7,6 +7,8 @@ interface Props { } export const SlateCard: FunctionComponent> = ({ children, title, titleElement, label }) => { + const hasChildren = Children.count(children) > 0; + return (
{(!!title || !!titleElement || !!label) && ( @@ -17,7 +19,7 @@ export const SlateCard: FunctionComponent> = ({ childre
)} -
{children}
+ {hasChildren &&
{children}
}
); };