diff --git a/frontend/src/metabase/actions/components/ActionViz/Action.tsx b/frontend/src/metabase/actions/components/ActionViz/Action.tsx index bb689f38b3d64d3c2c352a2164b5d2c684fe1f69..514126c5381b04dde557d26fe075a84190ce3b02 100644 --- a/frontend/src/metabase/actions/components/ActionViz/Action.tsx +++ b/frontend/src/metabase/actions/components/ActionViz/Action.tsx @@ -1,4 +1,5 @@ import React, { useMemo, useCallback } from "react"; +import _ from "underscore"; import { t } from "ttag"; import { connect } from "react-redux"; @@ -10,6 +11,7 @@ import type { WritebackQueryAction, Dashboard, } from "metabase-types/api"; + import type { VisualizationProps } from "metabase-types/types/Visualization"; import type { Dispatch, State } from "metabase-types/store"; import type { ParameterValueOrArray } from "metabase-types/types/Parameter"; @@ -20,8 +22,9 @@ import { } from "metabase/actions/utils"; import { getEditingDashcardId } from "metabase/dashboard/selectors"; -import { getMetadata } from "metabase/selectors/metadata"; -import type Metadata from "metabase-lib/metadata/Metadata"; +import Databases from "metabase/entities/databases"; + +import type Database from "metabase-lib/metadata/Database"; import { getDashcardParamValues, @@ -37,7 +40,7 @@ export interface ActionProps extends VisualizationProps { dispatch: Dispatch; parameterValues: { [id: string]: ParameterValueOrArray }; isEditingDashcard: boolean; - metadata: Metadata; + database: Database; } export function ActionComponent({ @@ -120,20 +123,18 @@ const ConnectedActionComponent = connect()(ActionComponent); function mapStateToProps(state: State, props: ActionProps) { return { isEditingDashcard: getEditingDashcardId(state) === props.dashcard.id, - metadata: getMetadata(state), }; } export function ActionFn(props: ActionProps) { const { - metadata, + database, dashcard: { action }, } = props; - const actionsEnabled = !!metadata - ?.database(action?.database_id) - ?.hasActionsEnabled?.(); - if (!props.dashcard?.action || !actionsEnabled) { + const hasActionsEnabled = database?.hasActionsEnabled?.(); + + if (!action || !hasActionsEnabled) { const tooltip = !action ? t`No action assigned` : t`Actions are not enabled for this database`; @@ -152,4 +153,10 @@ export function ActionFn(props: ActionProps) { return <ConnectedActionComponent {...props} />; } -export default connect(mapStateToProps)(ActionFn); +export default _.compose( + Databases.load({ + id: (state: State, props: ActionProps) => + props.dashcard?.action?.database_id, + }), + connect(mapStateToProps), +)(ActionFn); diff --git a/frontend/src/metabase/actions/components/ActionViz/Action.unit.spec.tsx b/frontend/src/metabase/actions/components/ActionViz/Action.unit.spec.tsx index 45d86836f3ef0dab5a5902491bfb5b02367c8abe..f1f25d208e3216b5ac80d1af0ef3c6205760d70c 100644 --- a/frontend/src/metabase/actions/components/ActionViz/Action.unit.spec.tsx +++ b/frontend/src/metabase/actions/components/ActionViz/Action.unit.spec.tsx @@ -60,6 +60,14 @@ const defaultProps = { parameterValues: {}, } as unknown as ActionProps; +const databases: Record<number, any> = { + 1: createMockDatabase({ id: 1 }), + 2: createMockDatabase({ + id: 2, + settings: { "database-enable-actions": true }, + }), +}; + async function setup(options?: Partial<ActionProps>) { return renderWithProviders( <ActionComponent {...defaultProps} {...options} />, @@ -67,17 +75,17 @@ async function setup(options?: Partial<ActionProps>) { } async function setupActionWrapper(options?: Partial<ActionProps>) { + const dbId = options?.dashcard?.action?.database_id ?? 0; + + nock(location.origin) + .get(`/api/database/${dbId}`) + .reply(200, databases[dbId] ?? null); + return renderWithProviders(<Action {...defaultProps} {...options} />, { withSampleDatabase: true, storeInitialState: { entities: { - databases: { - 1: createMockDatabase({ id: 1 }), - 2: createMockDatabase({ - id: 2, - settings: { "database-enable-actions": true }, - }), - }, + databases, }, }, }); @@ -120,10 +128,10 @@ describe("Actions > ActionViz > ActionComponent", () => { }), }, }); - expect(screen.getByLabelText("bolt icon")).toBeInTheDocument(); - expect(screen.getByRole("button")).toBeDisabled(); + expect(await screen.findByLabelText("bolt icon")).toBeInTheDocument(); + expect(await screen.findByRole("button")).toBeDisabled(); expect( - screen.getByLabelText(/actions are not enabled/i), + await screen.findByLabelText(/actions are not enabled/i), ).toBeInTheDocument(); }); @@ -137,7 +145,7 @@ describe("Actions > ActionViz > ActionComponent", () => { }), }, }); - expect(screen.getByRole("button")).toBeEnabled(); + expect(await screen.findByRole("button")).toBeEnabled(); }); it("should render a button with default text", async () => {