Skip to content

Comments

Refactor global filters: simplify state management#3744

Open
flomillot wants to merge 21 commits intomainfrom
refactor-global-filters
Open

Refactor global filters: simplify state management#3744
flomillot wants to merge 21 commits intomainfrom
refactor-global-filters

Conversation

@flomillot
Copy link
Contributor

@flomillot flomillot commented Feb 18, 2026

PR Summary

The goal of this pull request is to refactor the global filters management, by simplifying and clarifying the storage and the update.
It also resolves some bugs and performance issues.
All the global filter definitions / options are now stored in only one list in Redux.
For each table we have a list with the selected global filters ID.
Redux is now the source of truth. And every update to the backend are now done asynchronously and automatically via a Redux middleware.
Some cleaning, renaming and other simplification have also been done.

  - Rework global filter redux state and middleware
  - Simplify GlobalFilterProvider, GlobalFilterSelector and related hooks
  - Simplify spreadsheet global filter component
  - Update computation result tabs (loadflow, security analysis, sensitivity
    analysis, shortcircuit, pcc-min, voltage-init) to use refactored filters
  - Adjust column filter hooks and utilities

Signed-off-by: Florent MILLOT <75525996+flomillot@users.noreply.github.com>
… improved performance and readability

Signed-off-by: Florent MILLOT <75525996+flomillot@users.noreply.github.com>
# Conflicts:
#	src/components/results/common/column-filter/update-computation-columns-filters.ts
#	src/components/results/common/column-filter/use-computation-column-filters.ts
#	src/components/results/loadflow/load-flow-result-tab.tsx
#	src/components/results/loadflow/load-flow-result-utils.ts
#	src/components/results/pccmin/pcc-min-result.tsx
#	src/components/results/securityanalysis/security-analysis-result-tab.tsx
#	src/components/results/sensitivity-analysis/paged-sensitivity-analysis-result.tsx
#	src/components/results/shortcircuit/shortcircuit-analysis-result.tsx
Signed-off-by: Florent MILLOT <75525996+flomillot@users.noreply.github.com>
Signed-off-by: Florent MILLOT <75525996+flomillot@users.noreply.github.com>
This reverts commit 954d475.
@ghazwarhili ghazwarhili self-requested a review February 19, 2026 11:11
Signed-off-by: Florent MILLOT <75525996+flomillot@users.noreply.github.com>
Signed-off-by: Florent MILLOT <75525996+flomillot@users.noreply.github.com>
Signed-off-by: Florent MILLOT <75525996+flomillot@users.noreply.github.com>
@basseche basseche self-requested a review February 19, 2026 15:48
Signed-off-by: Florent MILLOT <75525996+flomillot@users.noreply.github.com>
Signed-off-by: Florent MILLOT <75525996+flomillot@users.noreply.github.com>
* joins them with the global filter options, and returns the resolved `GlobalFilter[]`.
* Use this when you need the selected filters at a T time, e.g. when fetching the data.
*/
export function getSelectedGlobalFilters(tableKey: string): GlobalFilter[] {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this function from this hook and move it to the global-filter-utils.ts

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to keep it alongside the hook so that people can read the descriptions and choose which one to use
But ok its legit I will move it

const globalFilterSpreadsheetState = useSelector(
(state: AppState) => state.globalFilterSpreadsheetState[tableDefinition.uuid]
);
const globalFilterSpreadsheetState = useSelectedGlobalFilters(tableDefinition.uuid);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

selectedGlobalFilters

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kept the previous variable name to keep the history clean.
It's also coherent with the columns filter variable name.

const globalFilterSpreadsheetState = useSelectedGlobalFilters(tableDefinition.uuid);
const spreadsheetColumnsFiltersState = useSelector(
(state: AppState) => state.spreadsheetFilter[tableDefinition?.uuid]
);

Maybe refactor them later in another pull request ?

uuid: UUID;
export const REMOVE_FROM_GLOBAL_FILTER_OPTIONS = 'REMOVE_FROM_GLOBAL_FILTER_OPTIONS';
export type RemoveFromGlobalFilterOptionsAction = Readonly<Action<typeof REMOVE_FROM_GLOBAL_FILTER_OPTIONS>> & {
id: string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

id: UUID

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not always an UUID

builder.addCase(SAVE_SPREADSHEET_GS_FILTER, (state, action: SaveSpreadSheetGlobalFilterAction) => {
state.globalFilterSpreadsheetState[action.tabUuid] = action.filters;
builder.addCase(INIT_SPREADSHEET_GLOBAL_FILTER, (state, action: InitSpreadSheetGlobalFilterAction) => {
console.log('Reducer INIT_SPREADSHEET_GLOBAL_FILTER:', action);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to be removed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I saw it, I cleaned it.

…ver.

Signed-off-by: Florent MILLOT <75525996+flomillot@users.noreply.github.com>
* This ensures that the server state remains in sync with the client-side filter state from Redux.
*/
export const globalFiltersMiddleware: Middleware<{}, AppState> = (store) => (next) => (action) => {
const result = next(action); // Let Redux update the state first
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice !

addFilterForNewSpreadsheet,
addSortForNewSpreadsheet,
saveSpreadsheetGlobalFilters,
initOrUpdateSpreadsheetGlobalFilters,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or we can simply keep saveSpreadsheetGlobalFilters

Copy link
Contributor Author

@flomillot flomillot Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Save is really a database operation. I can use set if you prefer, but I prefer init or update Because it describes precisely what the action do

);
}
delete debouncedSyncTimers[index];
}, 2000);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use debounce from '@mui/material' is better than manual setTimeout

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is outside React and MUI. I prefer manual JavaScript here. Why do you think it's better ?

: option.filterType === filterGroupSelected
)
.filter((option: GlobalFilter) =>
genericFiltersStrictMode && option.filterType === FilterType.GENERIC_FILTER
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why genericFiltersStrictMode is removed from here ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved below where it belongs

disableCloseOnSelect
options={options}
onChange={(_e, value) => onChange(value)}
groupBy={(option: GlobalFilter): string =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't need anymore groupBy here ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope it's deprecated code, we discussed about with @Mathieu-Deharbe

element.specificMetadata?.equipmentType === EQUIPMENT_TYPES.SUBSTATION ||
element.specificMetadata?.equipmentType === EQUIPMENT_TYPES.VOLTAGE_LEVEL;
newlySelectedFilters.push({
id: element.elementUuid,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

id and uuid ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes because uuid has another signification here.

| UpdateColumnFiltersAction
| UpdateGlobalFiltersAction;
| AddGlobalFiltersAction
| ClearGlobalFiltersAction;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and RemoveGlobalFiltersAction; ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yes thanks didnt notice that

…perations and improve performance.

Signed-off-by: Florent MILLOT <75525996+flomillot@users.noreply.github.com>
… to `global-filter-utils` and updating imports across components.

Signed-off-by: Florent MILLOT <75525996+flomillot@users.noreply.github.com>
@sonarqubecloud
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants