From df2cf0eeb99e20f1669d22652170039b7ad573a0 Mon Sep 17 00:00:00 2001 From: hackerstanislav Date: Mon, 24 Jun 2024 09:08:55 +0200 Subject: [PATCH] feat: allow to disable local saving and reset filter Query params to handle - Disable cross filtering - Disable reset button - Disable save filters risk: low JIRA: F1-427 --- .../api/sdk-ui-dashboard.api.md | 8 +++++++ .../resolveDashboardConfig.ts | 4 +++- .../tests/__snapshots__/handler.test.ts.snap | 2 ++ .../src/model/store/config/configSelectors.ts | 24 +++++++++++++++++++ .../sdk-ui-dashboard/src/model/store/index.ts | 2 ++ .../widgetDrills/widgetDrillSelectors.ts | 10 +++++++- .../src/model/types/commonTypes.ts | 20 +++++++++++++++- .../filterBar/hooks/useResetFiltersButton.ts | 15 ++++++++++-- 8 files changed, 80 insertions(+), 5 deletions(-) diff --git a/libs/sdk-ui-dashboard/api/sdk-ui-dashboard.api.md b/libs/sdk-ui-dashboard/api/sdk-ui-dashboard.api.md index 8d2c0982749..8974c9aa7f1 100644 --- a/libs/sdk-ui-dashboard/api/sdk-ui-dashboard.api.md +++ b/libs/sdk-ui-dashboard/api/sdk-ui-dashboard.api.md @@ -1424,7 +1424,9 @@ export interface DashboardConfig { allowUnfinishedFeatures?: boolean; colorPalette?: IColorPalette; dateFilterConfig?: IDateFilterConfig; + disableCrossFiltering?: boolean; disableDefaultDrills?: boolean; + disableUserFilterReset?: boolean; enableFilterValuesResolutionInDrillEvents?: boolean; // @internal exportId?: string; @@ -6993,6 +6995,12 @@ export const selectIsDeleteDialogOpen: DashboardSelector; // @internal export const selectIsDeleteFilterButtonEnabled: DashboardSelector; +// @internal +export const selectIsDisabledCrossFiltering: DashboardSelector; + +// @internal +export const selectIsDisableUserFilterReset: DashboardSelector; + // @internal (undocumented) export const selectIsDraggingWidget: DashboardSelector; diff --git a/libs/sdk-ui-dashboard/src/model/commandHandlers/dashboard/initializeDashboardHandler/resolveDashboardConfig.ts b/libs/sdk-ui-dashboard/src/model/commandHandlers/dashboard/initializeDashboardHandler/resolveDashboardConfig.ts index da45a931ebc..1e46927eb10 100644 --- a/libs/sdk-ui-dashboard/src/model/commandHandlers/dashboard/initializeDashboardHandler/resolveDashboardConfig.ts +++ b/libs/sdk-ui-dashboard/src/model/commandHandlers/dashboard/initializeDashboardHandler/resolveDashboardConfig.ts @@ -1,4 +1,4 @@ -// (C) 2021-2023 GoodData Corporation +// (C) 2021-2024 GoodData Corporation import { SagaIterator } from "redux-saga"; import { all, call, put } from "redux-saga/effects"; import { IDateFilterConfigsQueryResult, IUserWorkspaceSettings } from "@gooddata/sdk-backend-spi"; @@ -187,6 +187,8 @@ function applyConfigDefaults(config: T) { initialRenderMode: config.initialRenderMode ?? "view", hideSaveAsNewButton: config.hideSaveAsNewButton ?? false, hideShareButton: config.hideShareButton ?? false, + disableCrossFiltering: config.disableCrossFiltering ?? false, + disableUserFilterReset: config.disableUserFilterReset ?? false, widgetsOverlay: config.widgetsOverlay ?? {}, }; } diff --git a/libs/sdk-ui-dashboard/src/model/commandHandlers/dashboard/initializeDashboardHandler/tests/__snapshots__/handler.test.ts.snap b/libs/sdk-ui-dashboard/src/model/commandHandlers/dashboard/initializeDashboardHandler/tests/__snapshots__/handler.test.ts.snap index 65179e77875..4d880cd8687 100644 --- a/libs/sdk-ui-dashboard/src/model/commandHandlers/dashboard/initializeDashboardHandler/tests/__snapshots__/handler.test.ts.snap +++ b/libs/sdk-ui-dashboard/src/model/commandHandlers/dashboard/initializeDashboardHandler/tests/__snapshots__/handler.test.ts.snap @@ -178,7 +178,9 @@ exports[`initialize dashboard handler > for any dashboard > should resolve confi ], "selectedOption": "THIS_MONTH", }, + "disableCrossFiltering": false, "disableDefaultDrills": false, + "disableUserFilterReset": false, "enableFilterValuesResolutionInDrillEvents": false, "hideSaveAsNewButton": false, "hideShareButton": false, diff --git a/libs/sdk-ui-dashboard/src/model/store/config/configSelectors.ts b/libs/sdk-ui-dashboard/src/model/store/config/configSelectors.ts index 42578e7a898..c8ddad39117 100644 --- a/libs/sdk-ui-dashboard/src/model/store/config/configSelectors.ts +++ b/libs/sdk-ui-dashboard/src/model/store/config/configSelectors.ts @@ -554,6 +554,30 @@ export const selectIsShareButtonHidden: DashboardSelector = createSelec return state.hideShareButton ?? false; }); +/** + * Returns whether cross filtering is disabled by config + * + * @internal + */ +export const selectIsDisabledCrossFiltering: DashboardSelector = createSelector( + selectConfig, + (state) => { + return state.disableCrossFiltering ?? false; + }, +); + +/** + * Returns whether user filter reset is disabled by config + * + * @internal + */ +export const selectIsDisableUserFilterReset: DashboardSelector = createSelector( + selectConfig, + (state) => { + return state.disableUserFilterReset ?? false; + }, +); + /** * Returns whether drill down is enabled. * diff --git a/libs/sdk-ui-dashboard/src/model/store/index.ts b/libs/sdk-ui-dashboard/src/model/store/index.ts index 08c9e732dd5..5ac674a57a7 100644 --- a/libs/sdk-ui-dashboard/src/model/store/index.ts +++ b/libs/sdk-ui-dashboard/src/model/store/index.ts @@ -80,6 +80,8 @@ export { selectEnableKDAttributeFilterDatesValidation, selectEnableDuplicatedLabelValuesInAttributeFilter, selectEnableRichTextDescriptions, + selectIsDisabledCrossFiltering, + selectIsDisableUserFilterReset, } from "./config/configSelectors.js"; export { EntitlementsState } from "./entitlements/entitlementsState.js"; export { selectEntitlementExportPdf } from "./entitlements/entitlementsSelectors.js"; diff --git a/libs/sdk-ui-dashboard/src/model/store/widgetDrills/widgetDrillSelectors.ts b/libs/sdk-ui-dashboard/src/model/store/widgetDrills/widgetDrillSelectors.ts index 1363a242160..2947675b391 100644 --- a/libs/sdk-ui-dashboard/src/model/store/widgetDrills/widgetDrillSelectors.ts +++ b/libs/sdk-ui-dashboard/src/model/store/widgetDrills/widgetDrillSelectors.ts @@ -56,6 +56,7 @@ import { selectHideKpiDrillInEmbedded, selectIsEmbedded, selectEnableKDCrossFiltering, + selectIsDisabledCrossFiltering, } from "../config/configSelectors.js"; import flatMap from "lodash/flatMap.js"; import { selectAccessibleDashboardsMap } from "../accessibleDashboards/accessibleDashboardsSelectors.js"; @@ -345,18 +346,21 @@ const selectCrossFilteringByWidgetRef: ( selectSupportsCrossFiltering, selectDrillTargetsByWidgetRef(ref), selectDisableDashboardCrossFiltering, + selectIsDisabledCrossFiltering, selectDrillableItems, ( isCrossFilteringEnabled, isCrossFilteringSupported, availableDrillTargets, disableCrossFiltering, + disableCrossFilteringByConfig, drillableItems, ) => { if ( !isCrossFilteringEnabled || !isCrossFilteringSupported || disableCrossFiltering || + disableCrossFilteringByConfig || // When some drillable items are present, we need to disable // cross filtering so that drill events are still possible to do. drillableItems.length > 0 @@ -474,6 +478,7 @@ export const selectConfiguredDrillsByWidgetRef: ( selectHideKpiDrillInEmbedded, selectIsEmbedded, selectDisableDashboardCrossFiltering, + selectIsDisabledCrossFiltering, ( drills = [], disableDefaultDrills, @@ -485,6 +490,7 @@ export const selectConfiguredDrillsByWidgetRef: ( hideKpiDrillInEmbedded, isEmbedded, disableCrossFiltering, + disableCrossFilteringByConfig, ) => { if (disableDefaultDrills) { return []; @@ -509,7 +515,9 @@ export const selectConfiguredDrillsByWidgetRef: ( return !(isEmbedded && hideKpiDrillInEmbedded); } case "crossFiltering": { - return enableKDCrossFiltering && !disableCrossFiltering; + return ( + enableKDCrossFiltering && !disableCrossFiltering && !disableCrossFilteringByConfig + ); } default: { const unhandledType: never = drillType; diff --git a/libs/sdk-ui-dashboard/src/model/types/commonTypes.ts b/libs/sdk-ui-dashboard/src/model/types/commonTypes.ts index f668b8ca6bc..8e5a5ee0c67 100644 --- a/libs/sdk-ui-dashboard/src/model/types/commonTypes.ts +++ b/libs/sdk-ui-dashboard/src/model/types/commonTypes.ts @@ -1,4 +1,4 @@ -// (C) 2021-2023 GoodData Corporation +// (C) 2021-2024 GoodData Corporation import { IAnalyticalBackend } from "@gooddata/sdk-backend-spi"; import { IColorPalette, @@ -212,6 +212,24 @@ export interface DashboardConfig { * priority over other stored or supplied filter context. */ exportId?: string; + + /** + * Disable cross filtering + * + * @remarks + * If set to true, cross filtering will be forced disabled even if the dashboard is configured to support it. + * If set to false or not set, cross filtering will be enabled if the dashboard is configured to support it. + */ + disableCrossFiltering?: boolean; + + /** + * Disable user filter reset + * + * @remarks + * If set to true, user filter reset will be disabled even if the dashboard is configured to support it. + * If set to false or not set, user filter reset will be enabled if the dashboard is configured to support it. + */ + disableUserFilterReset?: boolean; } /** diff --git a/libs/sdk-ui-dashboard/src/presentation/filterBar/filterBar/hooks/useResetFiltersButton.ts b/libs/sdk-ui-dashboard/src/presentation/filterBar/filterBar/hooks/useResetFiltersButton.ts index d57f230cc68..ecc1db3622e 100644 --- a/libs/sdk-ui-dashboard/src/presentation/filterBar/filterBar/hooks/useResetFiltersButton.ts +++ b/libs/sdk-ui-dashboard/src/presentation/filterBar/filterBar/hooks/useResetFiltersButton.ts @@ -25,6 +25,8 @@ import { useDashboardUserInteraction, selectDisableDashboardCrossFiltering, selectDisableDashboardUserFilterReset, + selectIsDisabledCrossFiltering, + selectIsDisableUserFilterReset, } from "../../../../model/index.js"; /** @@ -44,7 +46,9 @@ export const useResetFiltersButton = (): { const currentFilters = useDashboardSelector(selectFilterContextFilters); const enableKDCrossFiltering = useDashboardSelector(selectEnableKDCrossFiltering); const supportsCrossFiltering = useDashboardSelector(selectSupportsCrossFiltering); + const disableCrossFilteringByConfig = useDashboardSelector(selectIsDisabledCrossFiltering); const disableCrossFiltering = useDashboardSelector(selectDisableDashboardCrossFiltering); + const disableUserFilterResetByConfig = useDashboardSelector(selectIsDisableUserFilterReset); const disableUserFilterReset = useDashboardSelector(selectDisableDashboardUserFilterReset); const dispatch = useDashboardDispatch(); @@ -65,13 +69,15 @@ export const useResetFiltersButton = (): { !isEditMode && !isEqual(currentFilters, originalFilters) && // If the cross filter add some filters, we should allow the reset - (!disableUserFilterReset || newlyAddedFiltersLocalIds.length > 0) + ((!disableUserFilterReset && !disableUserFilterResetByConfig) || + newlyAddedFiltersLocalIds.length > 0) ); }, [ isEditMode, currentFilters, originalFilters, disableUserFilterReset, + disableUserFilterResetByConfig, newlyAddedFiltersLocalIds.length, ]); @@ -98,7 +104,12 @@ export const useResetFiltersButton = (): { } // If cross filtering is enabled, we need to remove all attribute filters that were added by cross filtering - if (enableKDCrossFiltering && supportsCrossFiltering && !disableCrossFiltering) { + if ( + enableKDCrossFiltering && + supportsCrossFiltering && + !disableCrossFiltering && + !disableCrossFilteringByConfig + ) { dispatch(removeAttributeFilters(newlyAddedFiltersLocalIds)); dispatch(drillActions.resetCrossFiltering()); }