diff --git a/packages/apollo-react/src/canvas/components/Guardrails/README.md b/packages/apollo-react/src/canvas/components/Guardrails/README.md index 9f021549e..6b7a68717 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 639473ef0..660eeda95 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 242a2ca43..faca29305 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 030b616e5..f977213bf 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 && (