diff --git a/frontend/src/metabase-types/api/actions.ts b/frontend/src/metabase-types/api/actions.ts index cf69fdf94657925ce3c2a2e878c7832f4196b5f2..193458b91f342b5271fb58920fe54a13e88b953d 100644 --- a/frontend/src/metabase-types/api/actions.ts +++ b/frontend/src/metabase-types/api/actions.ts @@ -18,7 +18,7 @@ export interface WritebackActionBase { model_id: CardId; name: string; description: string | null; - parameters: WritebackParameter[]; + parameters?: WritebackParameter[]; visualization_settings?: ActionFormSettings; archived: boolean; creator_id: UserId; diff --git a/frontend/src/metabase-types/api/mocks/actions.ts b/frontend/src/metabase-types/api/mocks/actions.ts index daba99ef685b3bf29c424b50e6d48bdb928f3f57..5b62571d294ac1fa1b6c6953fbccb2076966725b 100644 --- a/frontend/src/metabase-types/api/mocks/actions.ts +++ b/frontend/src/metabase-types/api/mocks/actions.ts @@ -41,7 +41,7 @@ export const createMockQueryAction = ({ description: null, model_id: 1, database_id: 1, - parameters: [], + parameters: undefined, creator_id: creator.id, creator, archived: false, @@ -66,7 +66,7 @@ export const createMockImplicitQueryAction = ({ description: "", model_id: 1, database_id: 1, - parameters: [], + parameters: undefined, visualization_settings: undefined, creator_id: creator.id, creator, diff --git a/frontend/src/metabase/actions/components/ActionViz/ActionDashcardSettings.tsx b/frontend/src/metabase/actions/components/ActionViz/ActionDashcardSettings.tsx index 56056b3ed9baf3c8e5d8b036e00f84c7d6ed8617..30c79093cd5706f1d4c8e407f898e179ac3a4482 100644 --- a/frontend/src/metabase/actions/components/ActionViz/ActionDashcardSettings.tsx +++ b/frontend/src/metabase/actions/components/ActionViz/ActionDashcardSettings.tsx @@ -71,8 +71,8 @@ export function ActionDashcardSettings({ ); const isFormInvalid = - !!action && - action.parameters.some(actionParameter => { + action != null && + action.parameters?.some(actionParameter => { const isHidden = isParameterHidden(action, actionParameter); const isRequired = isParameterRequired(action, actionParameter); const isParameterMapped = diff --git a/frontend/src/metabase/actions/components/ActionViz/ActionDashcardSettings.unit.spec.tsx b/frontend/src/metabase/actions/components/ActionViz/ActionDashcardSettings.unit.spec.tsx index 27b4ff6e4c43893c14054ecbf2c2e6d89523f71c..440c7e1f21fd2755d89693a62dd878a7535721a2 100644 --- a/frontend/src/metabase/actions/components/ActionViz/ActionDashcardSettings.unit.spec.tsx +++ b/frontend/src/metabase/actions/components/ActionViz/ActionDashcardSettings.unit.spec.tsx @@ -456,6 +456,16 @@ describe("ActionViz > ActionDashcardSettings", () => { ).toBeInTheDocument(); }); + it("should be valid and not crash when the action does not have parameters (metabase#32665)", async () => { + const { closeSpy } = setup({ + dashcard: createMockActionDashboardCard({ + action: createMockQueryAction(), + }), + }); + await userEvent.click(screen.getByRole("button", { name: "Done" })); + expect(closeSpy).toHaveBeenCalled(); + }); + it("shows parameters for an action", async () => { setup({ dashcard: actionDashcardWithAction, diff --git a/frontend/src/metabase/actions/hooks/use-action-form/use-action-form.ts b/frontend/src/metabase/actions/hooks/use-action-form/use-action-form.ts index cef659923055556166f88380879a5c517336020f..95f904d3cfc7b218621d40f26f94cc85bc6af80b 100644 --- a/frontend/src/metabase/actions/hooks/use-action-form/use-action-form.ts +++ b/frontend/src/metabase/actions/hooks/use-action-form/use-action-form.ts @@ -6,6 +6,7 @@ import type { ActionFormInitialValues, ParametersForActionExecution, WritebackAction, + WritebackParameter, } from "metabase-types/api"; import { @@ -22,27 +23,28 @@ type Opts = { }; const INITIAL_VALUES = {}; +const DEFAULT_PARAMETERS: WritebackParameter[] = []; function useActionForm({ - action, + action: { parameters = DEFAULT_PARAMETERS, visualization_settings }, initialValues = INITIAL_VALUES, prefetchesInitialValues, }: Opts) { const fieldSettings = useMemo(() => { return getOrGenerateFieldSettings( - action.parameters, - action.visualization_settings?.fields, + parameters, + visualization_settings?.fields, ); - }, [action]); + }, [parameters, visualization_settings]); const form = useMemo( - () => getForm(action.parameters, fieldSettings), - [action.parameters, fieldSettings], + () => getForm(parameters, fieldSettings), + [parameters, fieldSettings], ); const validationSchema = useMemo( - () => getFormValidationSchema(action.parameters, fieldSettings), - [action.parameters, fieldSettings], + () => getFormValidationSchema(parameters, fieldSettings), + [parameters, fieldSettings], ); const cleanedInitialValues = useMemo(() => {