Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Apply filters follow up #6034

Merged
merged 16 commits into from
Mar 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@gooddata/sdk-ui-all",
"comment": "Support of new filter mode Apply all at once in Dashboard",
"type": "none"
}
],
"packageName": "@gooddata/sdk-ui-all"
}
19 changes: 17 additions & 2 deletions libs/sdk-ui-dashboard/api/sdk-ui-dashboard.api.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
addAttributeFilter,
changeAttributeFilterSelection,
removeAttributeFilters,
resetFilterContextWorkingSelection,
} from "../../commands/filters.js";
import { CrossFiltering } from "../../commands/drill.js";
import { crossFilteringRequested, crossFilteringResolved } from "../../events/drill.js";
Expand All @@ -24,6 +25,7 @@ import { removeAttributeFiltersHandler } from "../filterContext/attributeFilter/
import isEmpty from "lodash/isEmpty.js";
import {
selectEnableCrossFilteringAliasTitles,
selectEnableDashboardFiltersApplyModes,
selectEnableDuplicatedLabelValuesInAttributeFilter,
} from "../../store/config/configSelectors.js";
import { selectAttributeFilterConfigsDisplayAsLabelMap } from "../../store/attributeFilterConfigs/attributeFilterConfigsSelectors.js";
Expand Down Expand Up @@ -125,6 +127,12 @@ export function* crossFilteringHandler(ctx: DashboardContext, cmd: CrossFilterin

const correlation = `crossFiltering_${uuid()}`;

const enableDashboardFiltersApplyModes: ReturnType<typeof selectEnableDashboardFiltersApplyModes> =
yield select(selectEnableDashboardFiltersApplyModes);
if (enableDashboardFiltersApplyModes) {
yield put(resetFilterContextWorkingSelection());
}

// Cleanup of previous cross-filtering state
if (!shouldUpdateExistingCrossFiltering) {
yield call(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,15 +98,13 @@ export function* changeAttributeDisplayFormHandler(
]),
);

if (!isWorkingSelectionChange || !enableDashboardFiltersApplyModes) {
const changedFilter: ReturnType<ReturnType<typeof selectFilterContextAttributeFilterByLocalId>> =
yield select(selectFilterContextAttributeFilterByLocalId(filterLocalId));
const changedFilter: ReturnType<ReturnType<typeof selectFilterContextAttributeFilterByLocalId>> =
yield select(selectFilterContextAttributeFilterByLocalId(filterLocalId));

invariant(
changedFilter,
"Inconsistent state in changeAttributeDisplayFormHandler, cannot update attribute filter for given local identifier.",
);
yield dispatchDashboardEvent(attributeDisplayFormChanged(ctx, changedFilter, cmd.correlationId));
yield call(dispatchFilterContextChanged, ctx, cmd);
}
invariant(
changedFilter,
"Inconsistent state in changeAttributeDisplayFormHandler, cannot update attribute filter for given local identifier.",
);
yield dispatchDashboardEvent(attributeDisplayFormChanged(ctx, changedFilter, cmd.correlationId));
yield call(dispatchFilterContextChanged, ctx, cmd);
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,6 @@ export function* changeAttributeFilterSelectionHandler(
yield call(resetCrossFiltering, cmd);
}

if (!isWorkingSelectionChange || !enableDashboardFiltersApplyModes) {
yield dispatchDashboardEvent(attributeFilterSelectionChanged(ctx, changedFilter, cmd.correlationId));
yield call(dispatchFilterContextChanged, ctx, cmd);
}
yield dispatchDashboardEvent(attributeFilterSelectionChanged(ctx, changedFilter, cmd.correlationId));
yield call(dispatchFilterContextChanged, ctx, cmd);
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ import { selectEffectiveDateFilterOptions } from "../../store/dateFilterConfig/d
import { findDateFilterOptionByValue } from "../../../_staging/dateFilterConfig/dateFilterOptionMapping.js";
import { selectAttributeFilterConfigsOverrides } from "../../store/attributeFilterConfigs/attributeFilterConfigsSelectors.js";
import { removeAttributeFilters } from "../../commands/filters.js";
import { selectCrossFilteringFiltersLocalIdentifiers } from "../../store/drill/drillSelectors.js";
import {
selectCrossFilteringFiltersLocalIdentifiers,
selectIsCrossFiltering,
} from "../../store/drill/drillSelectors.js";
import { drillActions } from "../../store/drill/index.js";
import { filterContextActions } from "../../store/filterContext/index.js";
import { selectEnableImmediateAttributeFilterDisplayAsLabelMigration } from "../../store/config/configSelectors.js";
Expand Down Expand Up @@ -74,5 +77,14 @@ export function* applyWorkingSelectionHandler(ctx: DashboardContext, cmd: IDashb
yield put(
filterContextActions.applyWorkingSelection({ enableImmediateAttributeFilterDisplayAsLabelMigration }),
);
const isCrossFiltering: ReturnType<typeof selectIsCrossFiltering> = yield select(selectIsCrossFiltering);

if (isCrossFiltering) {
yield call(resetCrossFiltering, cmd);
}
yield call(dispatchFilterContextChanged, ctx, cmd);
}

export function* resetWorkingSelectionHandler() {
yield put(filterContextActions.resetWorkingSelection());
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,21 +63,21 @@ export function* changeDateFilterSelectionHandler(
);

if (!isWorkingSelectionChange) {
const affectedFilter: ReturnType<typeof selectFilterContextDateFilter> = cmd.payload.dataSet
? yield select(selectFilterContextDateFilterByDataSet(cmd.payload.dataSet))
: yield select(selectFilterContextDateFilter);

const isCrossFiltering = yield select(selectIsCrossFiltering);
if (isCrossFiltering) {
yield call(resetCrossFiltering, cmd);
}
}

yield dispatchDashboardEvent(
dateFilterChanged(ctx, affectedFilter, cmd.payload.dateFilterOptionLocalId, cmd.correlationId),
);
const affectedFilter: ReturnType<typeof selectFilterContextDateFilter> = cmd.payload.dataSet
? yield select(selectFilterContextDateFilterByDataSet(cmd.payload.dataSet))
: yield select(selectFilterContextDateFilter);

yield call(dispatchFilterContextChanged, ctx, cmd);
}
yield dispatchDashboardEvent(
dateFilterChanged(ctx, affectedFilter, cmd.payload.dateFilterOptionLocalId, cmd.correlationId),
);

yield call(dispatchFilterContextChanged, ctx, cmd);
}

function dateFilterSelectionToDateFilter(dateFilterSelection: DateFilterSelection): IDashboardDateFilter {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ import {
reloadFilterViews,
changeFilterContextSelectionByParams,
} from "../../commands/index.js";
import { selectFilterContextDefinition } from "../../store/filterContext/filterContextSelectors.js";
import {
selectFilterContextDefinition,
selectWorkingFilterContextDefinition,
} from "../../store/filterContext/filterContextSelectors.js";
import { selectCrossFilteringFiltersLocalIdentifiers } from "../../store/drill/drillSelectors.js";
import { selectFilterViews, filterViewsActions } from "../../store/filterViews/index.js";
import {
Expand All @@ -39,6 +42,11 @@ import { loadFilterViews } from "../dashboard/initializeDashboardHandler/loadFil
import { PromiseFnReturnType } from "../../types/sagas.js";
import { resetCrossFiltering } from "./common.js";
import { selectAttributeFilterConfigsOverrides } from "../../store/attributeFilterConfigs/attributeFilterConfigsSelectors.js";
import { filterContextActions } from "../../store/filterContext/index.js";
import {
selectDashboardFiltersApplyMode,
selectEnableDashboardFiltersApplyModes,
} from "../../store/config/configSelectors.js";

function createFilterView(
ctx: DashboardContext,
Expand All @@ -53,9 +61,21 @@ export function* saveFilterViewHandler(ctx: DashboardContext, cmd: SaveFilterVie
throw Error("Dashboard ref must be provided.");
}

const filterContext: ReturnType<typeof selectFilterContextDefinition> = yield select(
const appliedFilterContext: ReturnType<typeof selectFilterContextDefinition> = yield select(
selectFilterContextDefinition,
);
const workingFilterContext: ReturnType<typeof selectWorkingFilterContextDefinition> = yield select(
selectWorkingFilterContextDefinition,
);
const filtersApplyMode: ReturnType<typeof selectDashboardFiltersApplyMode> = yield select(
selectDashboardFiltersApplyMode,
);
const enableDashboardFiltersApplyModes: ReturnType<typeof selectEnableDashboardFiltersApplyModes> =
yield select(selectEnableDashboardFiltersApplyModes);
const filterContext =
filtersApplyMode.mode === "ALL_AT_ONCE" && enableDashboardFiltersApplyModes
? workingFilterContext
: appliedFilterContext;

const virtualFilters: ReturnType<typeof selectCrossFilteringFiltersLocalIdentifiers> = yield select(
selectCrossFilteringFiltersLocalIdentifiers,
Expand Down Expand Up @@ -133,6 +153,11 @@ export function* applyFilterViewHandler(ctx: DashboardContext, cmd: ApplyFilterV

if (filterView) {
yield call(resetCrossFiltering, cmd);
const enableDashboardFiltersApplyModes: ReturnType<typeof selectEnableDashboardFiltersApplyModes> =
yield select(selectEnableDashboardFiltersApplyModes);
if (enableDashboardFiltersApplyModes) {
yield put(filterContextActions.resetWorkingSelection());
}
yield put(
changeFilterContextSelectionByParams({
filters: filterView.filterContext.filters,
Expand Down
3 changes: 2 additions & 1 deletion libs/sdk-ui-dashboard/src/model/commandHandlers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ import { attributeHierarchyModifiedHandler } from "./widgets/attributeHierarchyM
import { addDateFilterHandler } from "./filterContext/dateFilter/addDateFilterHandler.js";
import { removeDateFiltersHandler } from "./filterContext/dateFilter/removeDateFiltersHandler.js";
import { moveDateFilterHandler } from "./filterContext/dateFilter/moveDateFilterHandler.js";
import { applyWorkingSelectionHandler } from "./filterContext/common.js";
import { applyWorkingSelectionHandler, resetWorkingSelectionHandler } from "./filterContext/common.js";
import { changeDateFilterWithDimensionModeHandler } from "./dashboard/changeDateFilterWithDimensionModeHandler.js";
import { changeDateFilterTitleHandler } from "./dashboard/changeDateFilterTitleHandler.js";
import { changeAttributeFilterLimitingItemsHandler } from "./dashboard/changeAttributeFilterLimitingItemsHandler.js";
Expand Down Expand Up @@ -146,6 +146,7 @@ export const DefaultCommandHandlers: {
"GDC.DASH/CMD.FILTER_CONTEXT.DATE_FILTER.REMOVE": removeDateFiltersHandler,
"GDC.DASH/CMD.FILTER_CONTEXT.DATE_FILTER.MOVE": moveDateFilterHandler,
"GDC.DASH/CMD.FILTER_CONTEXT.APPLY_WORKING_SELECTION": applyWorkingSelectionHandler,
"GDC.DASH/CMD.FILTER_CONTEXT.RESET_WORKING_SELECTION": resetWorkingSelectionHandler,
"GDC.DASH/CMD.ATTRIBUTE_FILTER_CONFIG.SET_MODE": changeAttributeFilterModeHandler,
"GDC.DASH/CMD.ATTRIBUTE_FILTER_CONFIG.SET_DISPLAY_AS_LABEL": changeAttributeFilterDisplayAsLabelHandler,
"GDC.DASH/CMD.ATTRIBUTE_FILTER_CONFIG.SET_LIMITING_ITEMS": changeAttributeFilterLimitingItemsHandler,
Expand Down
1 change: 1 addition & 0 deletions libs/sdk-ui-dashboard/src/model/commands/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ export type DashboardCommandType =
| "GDC.DASH/CMD.FILTER_CONTEXT.FILTER_VIEW.CHANGE_DEFAULT_STATUS"
| "GDC.DASH/CMD.FILTER_CONTEXT.FILTER_VIEW.RELOAD"
| "GDC.DASH/CMD.FILTER_CONTEXT.APPLY_WORKING_SELECTION"
| "GDC.DASH/CMD.FILTER_CONTEXT.RESET_WORKING_SELECTION"
// @internal
| "GDC.DASH/CMD.USERS.LOAD_ALL"
| "GDC.DASH/CMD.INSIGHT_WIDGET.EXPORT_RAW"
Expand Down
35 changes: 35 additions & 0 deletions libs/sdk-ui-dashboard/src/model/commands/filters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1413,3 +1413,38 @@ export function applyFilterContextWorkingSelection(
correlationId,
};
}

/**
* Command for reseting all working filters.
* It resets the working filters in to same state as applied filters.
*
* @remarks
* This command ot usually used with setting dashboardApplyFiltersMode: ALL_AT_ONCE
*
* If you want to reset applied filters too, you may use {@link changeFilterContextSelection} and pass all available filters to it.
*
* @remarks
* See {@link applyFilterContextWorkingSelection} for a factory function that will help you create this command.
*
* @alpha
*/
export interface ResetFilterContextWorkingSelection extends IDashboardCommand {
readonly type: "GDC.DASH/CMD.FILTER_CONTEXT.RESET_WORKING_SELECTION";
}

/**
* Creates the {@link ResetFilterContextWorkingSelection} command.
*
* @param correlationId - specify correlation id. It will be included in all events that will be emitted during the command processing.
* @returns apply reset working filters command
*
* @alpha
*/
export function resetFilterContextWorkingSelection(
correlationId?: string,
): ResetFilterContextWorkingSelection {
return {
type: "GDC.DASH/CMD.FILTER_CONTEXT.RESET_WORKING_SELECTION",
correlationId,
};
}
4 changes: 4 additions & 0 deletions libs/sdk-ui-dashboard/src/model/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import {
SetFilterViewAsDefault,
ReloadFilterViews,
ApplyFilterContextWorkingSelection,
ResetFilterContextWorkingSelection,
} from "./filters.js";
import {
ChangeInsightWidgetFilterSettings,
Expand Down Expand Up @@ -215,6 +216,7 @@ export type {
SetFilterViewAsDefaultPayload,
ReloadFilterViews,
ApplyFilterContextWorkingSelection,
ResetFilterContextWorkingSelection,
} from "./filters.js";
export {
changeDateFilterSelection,
Expand Down Expand Up @@ -244,6 +246,7 @@ export {
setFilterViewAsDefault,
reloadFilterViews,
applyFilterContextWorkingSelection,
resetFilterContextWorkingSelection,
} from "./filters.js";

export type {
Expand Down Expand Up @@ -619,6 +622,7 @@ export type DashboardCommands =
| ReloadFilterViews
| ToggleLayoutSectionHeaders
| ApplyFilterContextWorkingSelection
| ResetFilterContextWorkingSelection
//internal
| SetScreenSize
| LoadAllWorkspaceUsers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,15 @@ const applyWorkingSelection: FilterContextReducer<PayloadAction<IApplyWorkingSel
//
//

const resetWorkingSelection: FilterContextReducer<PayloadAction> = (state) => {
invariant(state.workingFilterContextDefinition, "Attempt to edit uninitialized working filter context");
state.workingFilterContextDefinition = { filters: [] };
};

//
//
//

export const filterContextReducers = {
setFilterContext,
updateFilterContextIdentity,
Expand All @@ -772,4 +781,5 @@ export const filterContextReducers = {
changeLimitingItems,
setPreloadedAttributesWithReferences,
applyWorkingSelection,
resetWorkingSelection,
};
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ import {
isDashboardDateFilterWithDimension,
isObjRef,
isDashboardCommonDateFilter,
isDashboardDateFilter,
objRefToString,
getAttributeElementsItems,
} from "@gooddata/sdk-model";
import { ObjRefMap, newDisplayFormMap } from "../../../_staging/metadata/objRefMap.js";
Expand All @@ -34,7 +32,7 @@ import keyBy from "lodash/keyBy.js";
import keys from "lodash/keys.js";
import sortBy from "lodash/sortBy.js";
import { selectEnableImmediateAttributeFilterDisplayAsLabelMigration } from "../config/configSelectors.js";
import { applyFilterContext } from "./filterContextUtils.js";
import { applyFilterContext, getFilterIdentifier } from "./filterContextUtils.js";

const selectSelf = createSelector(
(state: DashboardState) => state,
Expand Down Expand Up @@ -140,33 +138,13 @@ export const selectIsWorkingFilterContextChanged: DashboardSelector<boolean | un
selectEnableImmediateAttributeFilterDisplayAsLabelMigration,
(filterContext, workingFilterContext, enableImmediateAttributeFilterDisplayAsLabelMigration) => {
if (filterContext.filters.length !== workingFilterContext.filters.length) {
return false;
}

function getFilterIdentifier(filter: FilterContextItem): string {
if (isDashboardAttributeFilter(filter)) {
const localIdentifier = filter.attributeFilter.localIdentifier;
if (!localIdentifier) {
console.warn(
"Attribute filter without localIdentifier found. Using displayForm as fallback which may not be reliable.",
);
return objRefToString(filter.attributeFilter.displayForm);
}
return localIdentifier;
}
if (isDashboardDateFilter(filter)) {
return (
(filter.dateFilter.dataSet && objRefToString(filter.dateFilter.dataSet)) ??
"default_date_filter"
);
}
throw new Error("Unknown filter type");
return true;
}

const appliedFilters = keyBy(filterContext.filters, getFilterIdentifier);
const workingFilters = keyBy(workingFilterContext.filters, getFilterIdentifier);

return keys(appliedFilters)
return !keys(appliedFilters)
.map((key): boolean => {
const appliedFilter = appliedFilters[key];
const workingFilter = workingFilters[key];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
IDashboardAttributeFilter,
IDashboardDateFilter,
IFilterContextDefinition,
objRefToString,
} from "@gooddata/sdk-model";
import type { IWorkingFilterContextDefinition } from "./filterContextState.js";

Expand Down Expand Up @@ -97,3 +98,25 @@ export function applyFilterContext(
filters: [workingCommonDateFilter, ...filters],
};
}

/**
* @internal
*/
export function getFilterIdentifier(filter: FilterContextItem): string {
if (isDashboardAttributeFilter(filter)) {
const localIdentifier = filter.attributeFilter.localIdentifier;
if (!localIdentifier) {
console.warn(
"Attribute filter without localIdentifier found. Using displayForm as fallback which may not be reliable.",
);
return objRefToString(filter.attributeFilter.displayForm);
}
return localIdentifier;
}
if (isDashboardDateFilter(filter)) {
return (
(filter.dateFilter.dataSet && objRefToString(filter.dateFilter.dataSet)) ?? "default_date_filter"
);
}
throw new Error("Unknown filter type");
}
Loading
Loading