From e883cdfffcc80241777dccf366839eba82c6e4af Mon Sep 17 00:00:00 2001 From: Oisin Coveney <oisin@metabase.com> Date: Wed, 16 Oct 2024 17:07:55 +0300 Subject: [PATCH] Convert `dashcardData` dashboard reducers to TS (#48679) --- .../src/metabase-types/api/mocks/revision.ts | 35 ++++---- frontend/src/metabase-types/api/revision.ts | 3 + .../src/metabase/dashboard/reducers-typed.ts | 82 +++++++++++++------ frontend/src/metabase/dashboard/reducers.js | 30 +------ 4 files changed, 80 insertions(+), 70 deletions(-) diff --git a/frontend/src/metabase-types/api/mocks/revision.ts b/frontend/src/metabase-types/api/mocks/revision.ts index 12833b5c1c7..f9f3783786a 100644 --- a/frontend/src/metabase-types/api/mocks/revision.ts +++ b/frontend/src/metabase-types/api/mocks/revision.ts @@ -1,21 +1,20 @@ import type { Revision } from "metabase-types/api"; -export const createMockRevision = (opts?: Partial<Revision>): Revision => { - return { +export const createMockRevision = (opts?: Partial<Revision>): Revision => ({ + model_id: 1, + id: 1, + description: "created this", + message: null, + timestamp: "2023-05-16T13:33:30.198622-07:00", + is_creation: true, + is_reversion: false, + has_multiple_changes: false, + user: { id: 1, - description: "created this", - message: null, - timestamp: "2023-05-16T13:33:30.198622-07:00", - is_creation: true, - is_reversion: false, - has_multiple_changes: false, - user: { - id: 1, - first_name: "Admin", - last_name: "Test", - common_name: "Admin Test", - }, - diff: null, - ...opts, - }; -}; + first_name: "Admin", + last_name: "Test", + common_name: "Admin Test", + }, + diff: null, + ...opts, +}); diff --git a/frontend/src/metabase-types/api/revision.ts b/frontend/src/metabase-types/api/revision.ts index 10e6b962068..f0536bc65a6 100644 --- a/frontend/src/metabase-types/api/revision.ts +++ b/frontend/src/metabase-types/api/revision.ts @@ -1,3 +1,5 @@ +import type { CardId } from "metabase-types/api"; + export interface Revision { id: number; description: string; @@ -13,6 +15,7 @@ export interface Revision { last_name: string; common_name: string; }; + model_id: CardId; } export interface RevisionListQuery { diff --git a/frontend/src/metabase/dashboard/reducers-typed.ts b/frontend/src/metabase/dashboard/reducers-typed.ts index 22d8513c70d..d48f831835d 100644 --- a/frontend/src/metabase/dashboard/reducers-typed.ts +++ b/frontend/src/metabase/dashboard/reducers-typed.ts @@ -1,5 +1,5 @@ import { createReducer } from "@reduxjs/toolkit"; -import { assocIn } from "icepick"; +import { assocIn, dissocIn } from "icepick"; import { omit } from "underscore"; import { @@ -9,14 +9,18 @@ import { updateDashboardEnableEmbedding, } from "metabase/api"; import Dashboards from "metabase/entities/dashboards"; +import Questions from "metabase/entities/questions"; +import Revisions from "metabase/entities/revisions"; import { handleActions } from "metabase/lib/redux"; import { NAVIGATE_BACK_TO_DASHBOARD } from "metabase/query_builder/actions"; import type { UiParameter } from "metabase-lib/v1/parameters/types"; import type { + Card, DashCardId, Dashboard, ParameterId, ParameterValueOrArray, + Revision, } from "metabase-types/api"; import type { DashboardSidebarName, @@ -40,6 +44,7 @@ import { addDashcardIdsToLoadingQueue, addManyCardsToDash, cancelFetchCardData, + clearCardData, fetchCardDataAction, fetchDashboard, fetchDashboardCardDataAction, @@ -204,17 +209,12 @@ export const sidebar = createReducer( export const parameterValues = createReducer( INITIAL_DASHBOARD_STATE.parameterValues, builder => { - builder.addCase< - string, - { - type: string; - payload: { - clearCache?: boolean; - }; - } - >(INITIALIZE, (state, { payload: { clearCache = true } = {} }) => { - return clearCache ? {} : state; - }); + builder.addCase( + initialize, + (state, { payload: { clearCache = true } = {} }) => { + return clearCache ? {} : state; + }, + ); builder.addCase(fetchDashboard.fulfilled, (_state, { payload }) => { return payload.parameterValues; @@ -259,17 +259,12 @@ export const parameterValues = createReducer( } }); - builder.addCase< - string, - { - type: string; - payload: { - id: ParameterId; - }; - } - >(REMOVE_PARAMETER, (state, { payload: { id } }) => { - delete state[id]; - }); + builder.addCase<string, { type: string; payload: { id: ParameterId } }>( + REMOVE_PARAMETER, + (state, { payload: { id } }) => { + delete state[id]; + }, + ); }, ); @@ -413,3 +408,44 @@ export const loadingDashCards = createReducer( })); }, ); + +export const dashcardData = createReducer( + INITIAL_DASHBOARD_STATE.dashcardData, + builder => { + builder + .addCase(initialize, (state, action) => { + const { clearCache = true } = action.payload ?? {}; + return clearCache ? {} : state; + }) + .addCase(fetchCardDataAction.fulfilled, (state, action) => { + const { dashcard_id, card_id, result } = action.payload ?? {}; + if (dashcard_id && card_id) { + return assocIn(state, [dashcard_id, card_id], result); + } + }) + .addCase(clearCardData, (state, action) => { + const { cardId, dashcardId } = action.payload; + return dissocIn(state, [dashcardId, cardId]); + }) + .addCase<string, { type: string; payload: { object: Card } }>( + Questions.actionTypes.UPDATE, + (state, action) => { + const id = action.payload.object.id; + for (const dashcardId in state) { + delete state[dashcardId][id]; + } + }, + ) + .addCase<string, { type: string; payload: Revision }>( + Revisions.actionTypes.REVERT, + (state, action) => { + const { model_id } = action.payload; + if (model_id) { + for (const dashcardId in state) { + delete state[dashcardId][model_id]; + } + } + }, + ); + }, +); diff --git a/frontend/src/metabase/dashboard/reducers.js b/frontend/src/metabase/dashboard/reducers.js index fe5bf641438..3b3f35cdf3e 100644 --- a/frontend/src/metabase/dashboard/reducers.js +++ b/frontend/src/metabase/dashboard/reducers.js @@ -4,13 +4,11 @@ import _ from "underscore"; import Actions from "metabase/entities/actions"; import Questions from "metabase/entities/questions"; -import Revisions from "metabase/entities/revisions"; import { combineReducers, handleActions } from "metabase/lib/redux"; import { ADD_CARD_TO_DASH, ADD_MANY_CARDS_TO_DASH, - CLEAR_CARD_DATA, INITIALIZE, MARK_NEW_CARD_SEEN, REMOVE_CARD_FROM_DASH, @@ -24,7 +22,6 @@ import { UNDO_REMOVE_CARD_FROM_DASH, UPDATE_DASHCARD_VISUALIZATION_SETTINGS, UPDATE_DASHCARD_VISUALIZATION_SETTINGS_FOR_COLUMN, - fetchCardDataAction, fetchDashboard, tabsReducer, } from "./actions"; @@ -33,6 +30,7 @@ import { autoApplyFilters, dashboardId, dashboards, + dashcardData, editingDashboard, isAddParameterPopoverOpen, isNavigatingBackToDashboard, @@ -162,32 +160,6 @@ const dashcards = handleActions( INITIAL_DASHBOARD_STATE.dashcards, ); -// Many of these slices are also updated by `tabsReducer` in `frontend/src/metabase/dashboard/actions/tabs.ts` -const dashcardData = handleActions( - { - // clear existing dashboard data when loading a dashboard - [INITIALIZE]: { - next: (state, { payload: { clearCache = true } = {} }) => - clearCache ? {} : state, - }, - [fetchCardDataAction.fulfilled]: { - next: (state, { payload: { dashcard_id, card_id, result } }) => - assocIn(state, [dashcard_id, card_id], result), - }, - [CLEAR_CARD_DATA]: { - next: (state, { payload: { cardId, dashcardId } }) => - assocIn(state, [dashcardId, cardId]), - }, - [Questions.actionTypes.UPDATE]: (state, { payload: { object: card } }) => - _.mapObject(state, dashboardData => dissoc(dashboardData, card.id)), - [Revisions.actionTypes.REVERT]: (state, { payload: revision }) => - _.mapObject(state, dashboardData => - dissoc(dashboardData, revision.model_id), - ), - }, - INITIAL_DASHBOARD_STATE.dashcardData, -); - const draftParameterValues = handleActions( { [INITIALIZE]: { -- GitLab