Skip to content

apply all button poc #5918

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Expand Up @@ -66,6 +66,7 @@ export function actionsToInitializeNewDashboard(
filterContextDefinition: createDefaultFilterContext(dateFilterConfig),
attributeFilterDisplayForms: [],
}),
filterContextActions.applyFilterContext(),
layoutActions.setLayout(EmptyDashboardLayout),
insightsActions.setInsights([]),
metaActions.setMeta({}),
Expand Down Expand Up @@ -280,6 +281,7 @@ export function* actionsToInitializeExistingDashboard(
filterContextIdentity,
attributeFilterDisplayForms,
}),
filterContextActions.applyFilterContext(),
layoutActions.setLayout(dashboardLayout),
metaActions.setMeta({
dashboard: persistedDashboard ?? dashboard,
Expand Down
6 changes: 4 additions & 2 deletions libs/sdk-ui-dashboard/src/model/react/useWidgetFilters.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// (C) 2020-2024 GoodData Corporation
// (C) 2020-2025 GoodData Corporation
import { useEffect, useMemo, useState } from "react";
import {
areObjRefsEqual,
Expand All @@ -19,6 +19,7 @@ import {
selectFilterContextFilters,
selectIsInEditMode,
selectCrossFilteringFiltersLocalIdentifiersByWidgetRef,
selectAppliedFilterContextFilters,
} from "../../model/store/index.js";
import { safeSerializeObjRef } from "../../_staging/metadata/safeSerializeObjRef.js";
import { FilterableDashboardWidget } from "../types/layoutTypes.js";
Expand Down Expand Up @@ -126,7 +127,8 @@ export function useWidgetFilters(
* @param widget - widget to get the non-ignored filters for
*/
function useNonIgnoredFilters(widget: FilterableDashboardWidget | undefined | null) {
const dashboardFilters = useDashboardSelector(selectFilterContextFilters);
// TODO: make selector that takes into the account used filter mode
const dashboardFilters = useDashboardSelector(selectAppliedFilterContextFilters);
const crossFilteringLocalIdentifiersForThisWidget = useDashboardSelector(
selectCrossFilteringFiltersLocalIdentifiersByWidgetRef(widget?.ref),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ const setFilterContext: FilterContextReducer<PayloadAction<SetFilterContextPaylo
state.attributeFilterDisplayForms = attributeFilterDisplayForms;
};

const applyFilterContext: FilterContextReducer<PayloadAction<void>> = (state) => {
state.appliedFilterContextDefinition = state.filterContextDefinition;
};

//
//
//
Expand Down Expand Up @@ -687,4 +691,5 @@ export const filterContextReducers = {
changeSelectionMode,
changeLimitingItems,
setPreloadedAttributesWithReferences,
applyFilterContext,
};
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import isEmpty from "lodash/isEmpty.js";
import { selectSupportsCircularDependencyInFilters } from "../backendCapabilities/backendCapabilitiesSelectors.js";
import { selectCrossFilteringFiltersLocalIdentifiers } from "../drill/drillSelectors.js";
import { IAttributeWithReferences } from "@gooddata/sdk-backend-spi";
import isEqual from "lodash/isEqual.js";

const selectSelf = createSelector(
(state: DashboardState) => state,
Expand Down Expand Up @@ -91,6 +92,16 @@ export const selectFilterContextDefinition: DashboardSelector<IFilterContextDefi
},
);

export const selectAppliedFilterContextDefinition: DashboardSelector<IFilterContextDefinition> =
createSelector(selectSelf, (filterContextState) => {
invariant(
filterContextState.appliedFilterContextDefinition,
"attempting to access uninitialized filter context state",
);

return filterContextState.appliedFilterContextDefinition!;
});

/**
* Selects dashboard's filter context identity.
*
Expand Down Expand Up @@ -178,6 +189,19 @@ export const selectFilterContextFilters: DashboardSelector<FilterContextItem[]>
(filterContext): FilterContextItem[] => filterContext.filters,
);

export const selectAppliedFilterContextFilters: DashboardSelector<FilterContextItem[]> = createSelector(
selectAppliedFilterContextDefinition,
(filterContext): FilterContextItem[] => filterContext.filters,
);

export const selectCanApplyFilterContext: DashboardSelector<boolean> = createSelector(
selectFilterContextDefinition,
selectAppliedFilterContextDefinition,
(filterContextDefinition, appliedFilterContextDefinition) => {
return !isEqual(filterContextDefinition, appliedFilterContextDefinition);
},
);

/**
* This selector returns dashboard's filter context attribute filters.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ export interface FilterContextState {
*/
filterContextDefinition?: IFilterContextDefinition;

/**
* For "apply all" filter bar mode, this contains the filter context definition that is applied to the dashboard,
* and should be used for the executions.
* @beta
*/
appliedFilterContextDefinition?: IFilterContextDefinition;

/**
* Filter context definition contains the original dashboard filters stored on the backend.
* @beta
Expand Down Expand Up @@ -56,6 +63,7 @@ export interface FilterContextState {

export const filterContextInitialState: FilterContextState = {
filterContextDefinition: undefined,
appliedFilterContextDefinition: undefined,
filterContextIdentity: undefined,
attributeFilterDisplayForms: undefined,
attributesWithReferences: undefined,
Expand Down
3 changes: 3 additions & 0 deletions libs/sdk-ui-dashboard/src/model/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ export {
selectIsAttributeFilterDependentByLocalIdentifier,
selectFilterContextDateFilterByDataSet,
selectPreloadedAttributesWithReferences,
selectAppliedFilterContextDefinition,
selectAppliedFilterContextFilters,
selectCanApplyFilterContext,
} from "./filterContext/filterContextSelectors.js";
export type { IImplicitDrillWithPredicates } from "./widgetDrills/widgetDrillSelectors.js";
export {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// (C) 2021-2024 GoodData Corporation
import React, { useRef } from "react";
// (C) 2021-2025 GoodData Corporation
import React, { useCallback, useRef } from "react";
import DefaultMeasure from "react-measure";
import cx from "classnames";
import { createSelector } from "@reduxjs/toolkit";
Expand All @@ -14,6 +14,8 @@ import {
useDashboardSelector,
selectEnableFilterViews,
selectEnableFlexibleLayout,
selectCanApplyFilterContext,
useDashboardDispatch,
} from "../../../model/index.js";

import { ShowAllFiltersButton } from "./ShowAllFiltersButton.js";
Expand All @@ -24,6 +26,9 @@ import { FiltersConfigurationPanel } from "./FiltersConfigurationPanel.js";
import { FilterViews } from "./filterViews/FilterViews.js";
import { BulletsBar as FlexibleBulletsBar } from "../../flexibleLayout/dragAndDrop/Resize/BulletsBar/BulletsBar.js";
import { BulletsBar as FluidBulletsBar } from "../../layout/dragAndDrop/Resize/BulletsBar/BulletsBar.js";
import { UiButton } from "@gooddata/sdk-ui-kit";
// TODO: this should be proper dashboard command
import { filterContextActions } from "../../../model/store/filterContext/index.js";

const selectShowFiltersConfigurationPanel = createSelector(
selectIsInEditMode,
Expand Down Expand Up @@ -52,6 +57,12 @@ const DefaultFilterBarContainerCore: React.FC<{ children?: React.ReactNode }> =
const showFiltersConfigurationPanel = useDashboardSelector(selectShowFiltersConfigurationPanel);
const isFilterViewsFeatureFlagEnabled = useDashboardSelector(selectEnableFilterViews);
const isFlexibleLayoutEnabled = useDashboardSelector(selectEnableFlexibleLayout);
const canApplyFilterContext = useDashboardSelector(selectCanApplyFilterContext);
const dispatch = useDashboardDispatch();

const applyFilterContext = useCallback(() => {
dispatch(filterContextActions.applyFilterContext());
}, [dispatch]);

return (
<div className="dash-filters-wrapper s-gd-dashboard-filter-bar" ref={dropRef}>
Expand All @@ -65,6 +76,13 @@ const DefaultFilterBarContainerCore: React.FC<{ children?: React.ReactNode }> =
<AllFiltersContainer setCalculatedRows={setCalculatedRows}>{children}</AllFiltersContainer>
<FiltersRows rows={rows} />
<div className="filter-bar-configuration">
<UiButton
// TODO: use react-intl to translate this
label="Apply"
variant="primary"
isDisabled={!canApplyFilterContext}
onClick={applyFilterContext}
/>
{isFilterViewsFeatureFlagEnabled ? <FilterViews /> : null}
{showFiltersConfigurationPanel ? <FiltersConfigurationPanel /> : null}
</div>
Expand Down
Loading