From 1812faf5dcbe859569802aa047d98618d668a34a Mon Sep 17 00:00:00 2001 From: andreizdrali-uipath Date: Thu, 22 Oct 2026 16:57:01 +0300 Subject: [PATCH] feat(apollo-react): hide the log severity select on request [AL-667] Add hideLogSeverity to GuardrailActionSection and GuardrailBuilder, which forwards it. With it on, a log action shows only the action type select. Flow's Guardrail node needs it: it relabels log as Fail, and Fail has no severity. The action keeps its severityLevel. A new guardrail still saves 'Info', an edited one its stored value, and the host overwrites it on save if it needs another. Off by default, so Agents and the other Flow editors are unchanged. Co-Authored-By: Claude Opus 5.5 --- .../canvas/components/Guardrails/README.md | 5 ++ .../guardrail-action-section.stories.tsx | 8 +++ .../guardrail-action-section.test.tsx | 46 +++++++++++++ .../components/guardrail-action-section.tsx | 8 ++- .../Guardrails/guardrail-builder.stories.tsx | 14 ++++ .../Guardrails/guardrail-builder.test.tsx | 69 +++++++++++++++++++ .../Guardrails/guardrail-builder.tsx | 8 +++ 7 files changed, 157 insertions(+), 1 deletion(-) diff --git a/packages/apollo-react/src/canvas/components/Guardrails/README.md b/packages/apollo-react/src/canvas/components/Guardrails/README.md index 9f021549e2..6b7a687175 100644 --- a/packages/apollo-react/src/canvas/components/Guardrails/README.md +++ b/packages/apollo-react/src/canvas/components/Guardrails/README.md @@ -954,6 +954,11 @@ const [action, setAction] = useState({ action outside the list never blanks the select. Both builders forward it, and start a new guardrail on the first allowed type when log is not among them. `GuardrailBuilder`'s takes no `filter`, which it has no field picker for. +- **`hideLogSeverity` drops the severity select** for a host whose log action has no severity + (Flow's Guardrail node, where log is relabelled Fail). The type select keeps its column, so + it does not move when the user switches to block. `severityLevel` is left as it is: a new + guardrail saves `'Info'`, an edited one its stored value, and the host overwrites it on save + if it needs another. `GuardrailBuilder` forwards it. - **Asset recipients round-trip.** Types 4 and 6 display as their static siblings (3 and 5) in the type select, so a value written by a host asset editor never blanks the selection. - **Recipient types outside 1-6 pass through.** Agents' argument (7, 8) and diff --git a/packages/apollo-react/src/canvas/components/Guardrails/components/guardrail-action-section.stories.tsx b/packages/apollo-react/src/canvas/components/Guardrails/components/guardrail-action-section.stories.tsx index 639473ef0c..660eeda950 100644 --- a/packages/apollo-react/src/canvas/components/Guardrails/components/guardrail-action-section.stories.tsx +++ b/packages/apollo-react/src/canvas/components/Guardrails/components/guardrail-action-section.stories.tsx @@ -183,6 +183,14 @@ export const AllowedActionTypes: Story = { render: () => , }; +/** hideLogSeverity drops the severity select; the action keeps its severityLevel. */ +export const LogWithoutSeverity: Story = { + args: { action: logAction, onActionChange: () => {} }, + render: () => ( + + ), +}; + /** Filter appears only with showFilter, and its field picker is host content. */ export const FilterWithHostFieldPicker: Story = { args: { action: { $actionType: 'filter', fields: [] }, onActionChange: () => {} }, diff --git a/packages/apollo-react/src/canvas/components/Guardrails/components/guardrail-action-section.test.tsx b/packages/apollo-react/src/canvas/components/Guardrails/components/guardrail-action-section.test.tsx index 242a2ca43f..faca29305b 100644 --- a/packages/apollo-react/src/canvas/components/Guardrails/components/guardrail-action-section.test.tsx +++ b/packages/apollo-react/src/canvas/components/Guardrails/components/guardrail-action-section.test.tsx @@ -117,6 +117,52 @@ describe('GuardrailActionSection', () => { expect(onActionChange).toHaveBeenCalledWith({ $actionType: 'log', severityLevel: 'Warning' }); }); + describe('hideLogSeverity', () => { + it('shows the severity select by default', () => { + render(); + + expect(screen.getByRole('combobox', { name: /severity level/i })).toBeInTheDocument(); + }); + + it('hides the severity select for log actions', () => { + render( + + ); + + expect(screen.getByRole('combobox', { name: /action type/i })).toHaveTextContent('Log'); + expect(screen.queryByRole('combobox', { name: /severity level/i })).not.toBeInTheDocument(); + expect(screen.queryByText('Severity level')).not.toBeInTheDocument(); + }); + + it('still emits a severity level when switching to log', async () => { + const onActionChange = vi.fn(); + render( + + ); + + fireEvent.click(screen.getByRole('combobox', { name: /action type/i })); + fireEvent.click(await screen.findByRole('option', { name: 'Log' })); + + expect(onActionChange).toHaveBeenCalledWith({ $actionType: 'log', severityLevel: 'Info' }); + }); + + it('leaves the other action types alone', () => { + render( + + ); + + expect(screen.getByLabelText(/blocking reason/i)).toBeInTheDocument(); + }); + }); + it('renders the blocking reason input with its error for block actions', () => { const onActionChange = vi.fn(); render( diff --git a/packages/apollo-react/src/canvas/components/Guardrails/components/guardrail-action-section.tsx b/packages/apollo-react/src/canvas/components/Guardrails/components/guardrail-action-section.tsx index 030b616e5a..f977213bf9 100644 --- a/packages/apollo-react/src/canvas/components/Guardrails/components/guardrail-action-section.tsx +++ b/packages/apollo-react/src/canvas/components/Guardrails/components/guardrail-action-section.tsx @@ -39,6 +39,11 @@ export interface GuardrailActionSectionProps { * action outside the list never blanks the select. */ allowedActionTypes?: readonly GuardrailActionType[]; + /** + * Hide the severity level select for a log action, for a host whose log action has no + * severity. The action's `severityLevel` is left as it is, for the host to set. + */ + hideLogSeverity?: boolean; /** Content rendered as the second grid column when $actionType === 'filter' */ filterContent?: ReactNode; /** Validation messages; each renders as soon as it is present. */ @@ -72,6 +77,7 @@ export function GuardrailActionSection({ onActionChange, showFilter = false, allowedActionTypes, + hideLogSeverity = false, filterContent, errors, recipientTypeDisabled, @@ -150,7 +156,7 @@ export function GuardrailActionSection({
{actionTypeSelect} - {action.$actionType === 'log' && ( + {action.$actionType === 'log' && !hideLogSeverity && (