Skip to content
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 @@ -26,7 +26,7 @@ import { useIntl } from 'react-intl';
import { useLocalizedCountries } from 'components/utils/localized-countries-hook';
import { useSelector } from 'react-redux';
import { AppState } from '../../../../redux/reducer';
import { FilterType } from '../utils';
import { FilterType, isGenericFilter } from '../utils';
import { OverflowableText, OverflowableChip } from '@gridsuite/commons-ui';
import { EQUIPMENT_TYPES } from '../../../utils/equipment-types';
import { GlobalFilter } from './global-filter-types';
Expand Down Expand Up @@ -125,7 +125,7 @@ function GlobalFilterAutocomplete({
const intl = useIntl();
const { translate } = useLocalizedCountries();
const recentGlobalFilters: GlobalFilter[] = useSelector((state: AppState) => state.recentGlobalFilters);
const autocompleteRef = useRef<HTMLDivElement>(null);
const autocompleteRef = useRef<HTMLDivElement | null>(null);

// checks the generic filter to see if they are applicable to the current tab
const warningEquipmentTypeMessage: string = useMemo(() => {
Expand Down Expand Up @@ -178,7 +178,7 @@ function GlobalFilterAutocomplete({
: option.filterType === filterGroupSelected
)
.filter((option: GlobalFilter) =>
genericFiltersStrictMode && option.filterType === FilterType.GENERIC_FILTER
genericFiltersStrictMode && isGenericFilter(option)
? filterableEquipmentTypes.includes(option.equipmentType as EQUIPMENT_TYPES)
: true
)
Expand All @@ -196,7 +196,7 @@ function GlobalFilterAutocomplete({
}),
// recent generic filters are displayed 2 times : once in the recent filters (see above) and also in the generic filters :
...recentGlobalFilters
.filter((filter) => filter.filterType === FilterType.GENERIC_FILTER)
.filter((filter) => isGenericFilter(filter))
.map((filter) => {
return { ...filter, recent: false };
}),
Expand Down Expand Up @@ -243,7 +243,7 @@ function GlobalFilterAutocomplete({
);

const isOptionEqualToValue = useCallback((option: GlobalFilter, value: GlobalFilter) => {
if (option.filterType === FilterType.GENERIC_FILTER) {
if (isGenericFilter(option)) {
return (
option.label === value.label &&
option.filterType === value.filterType &&
Expand Down
125 changes: 74 additions & 51 deletions src/components/results/common/global-filter/global-filter-paper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,33 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import { Box, Button, Grid, ListItem, ListItemButton, Paper, Typography } from '@mui/material';
import {
getResultsGlobalFiltersChipStyle,
GLOBAL_FILTERS_CELL_HEIGHT,
IMPORT_FILTER_HEIGHT,
resultsGlobalFilterStyles,
} from './global-filter-styles';
import { Box, Button, Grid, ListItemButton, Paper, Typography } from '@mui/material';
import { GLOBAL_FILTERS_CELL_HEIGHT, IMPORT_FILTER_HEIGHT, resultsGlobalFilterStyles } from './global-filter-styles';
import { FormattedMessage, useIntl } from 'react-intl';
import FileUploadIcon from '@mui/icons-material/FileUpload';
import { PropsWithChildren, RefObject, useCallback, useContext, useEffect, useMemo, useState } from 'react';
import ListItemText from '@mui/material/ListItemText';
import List from '@mui/material/List';
import { FilterType } from '../utils';
import { FilterType, isGenericFilterType } from '../utils';
import { GlobalFilter } from './global-filter-types';
import { fetchSubstationPropertiesGlobalFilters, getOptionLabel, RECENT_FILTER } from './global-filter-utils';
import { useLocalizedCountries } from '../../../utils/localized-countries-hook';
import { fetchSubstationPropertiesGlobalFilters, RECENT_FILTER } from './global-filter-utils';
import ClickAwayListener from '@mui/material/ClickAwayListener';
import {
DirectoryItemSelector,
ElementAttributes,
ElementType,
fetchElementsInfos,
mergeSx,
OverflowableChip,
TreeViewFinderNodeProps,
} from '@gridsuite/commons-ui';
import { GlobalFilterContext } from './global-filter-context';
import SelectedGlobalFilters from './selected-global-filters';
import { EQUIPMENT_TYPES } from '../../../utils/equipment-types';
import { TextWithToolTip } from './text-with-tooltip';

const XS_COLUMN1: number = 3.5;
const XS_COLUMN1: number = 3;
const XS_COLUMN2: number = 4;
const XS_COLUMN3: number = 4.5;
const XS_COLUMN3: number = 5;

type GlobalFilterPaperProps = PropsWithChildren<{
autocompleteRef?: RefObject<HTMLElement | null>;
Expand All @@ -49,13 +45,11 @@ function GlobalFilterPaper({ children, autocompleteRef }: Readonly<GlobalFilterP
filterGroupSelected,
setFilterGroupSelected,
selectedGlobalFilters,
setSelectedGlobalFilters,
onChange,
filterCategories,
genericFiltersStrictMode,
equipmentTypes,
} = useContext(GlobalFilterContext);
const { translate } = useLocalizedCountries();
const intl = useIntl();
const [categories, setCategories] = useState<string[]>([]);

Expand All @@ -76,6 +70,13 @@ function GlobalFilterPaper({ children, autocompleteRef }: Readonly<GlobalFilterP
...(substationPropertiesGlobalFilters ? Array.from(substationPropertiesGlobalFilters.keys()) : []),
];
// generic filters always at the end of the menus
const substationCategory: string[] = sortedCategories.splice(
sortedCategories.indexOf(FilterType.SUBSTATION_OR_VL),
1
);
if (substationCategory.length > 0) {
sortedCategories.push(substationCategory[0]);
}
const genericFilterCategory: string[] = sortedCategories.splice(
sortedCategories.indexOf(FilterType.GENERIC_FILTER),
1
Expand Down Expand Up @@ -115,14 +116,29 @@ function GlobalFilterPaper({ children, autocompleteRef }: Readonly<GlobalFilterP
// ignore already selected filters and non-generic filters :
if (!selectedGlobalFilters.find((filter) => filter.uuid && filter.uuid === element.elementUuid)) {
// add the others
newlySelectedFilters.push({
uuid: element.elementUuid,
equipmentType: element.specificMetadata?.equipmentType,
label: element.elementName,
filterType: FilterType.GENERIC_FILTER,
filterTypeFromMetadata: element.specificMetadata?.type,
recent: true,
});
const equipmentType = element.specificMetadata?.equipmentType;
if (
equipmentType === EQUIPMENT_TYPES.SUBSTATION ||
equipmentType === EQUIPMENT_TYPES.VOLTAGE_LEVEL
) {
newlySelectedFilters.push({
uuid: element.elementUuid,
equipmentType: element.specificMetadata?.equipmentType,
label: element.elementName,
filterType: FilterType.SUBSTATION_OR_VL,
filterTypeFromMetadata: element.specificMetadata?.type,
recent: true,
});
} else {
newlySelectedFilters.push({
uuid: element.elementUuid,
equipmentType: element.specificMetadata?.equipmentType,
label: element.elementName,
filterType: FilterType.GENERIC_FILTER,
filterTypeFromMetadata: element.specificMetadata?.type,
recent: true,
});
}
}
});

Expand All @@ -132,10 +148,22 @@ function GlobalFilterPaper({ children, autocompleteRef }: Readonly<GlobalFilterP
[onChange, selectedGlobalFilters, setDirectoryItemSelectorOpen, setOpenedDropdown]
);

const allowedEquipmentTypes = useMemo(
() => (genericFiltersStrictMode ? equipmentTypes : undefined),
[equipmentTypes, genericFiltersStrictMode]
);
/**
* substations and voltage levels filters are not part of the regular selectable elements filters.
* They are selected through their specific filter category (FilterType.SUBSTATION_OR_VL)
*/
const allowedEquipmentTypes = useMemo(() => {
if (filterGroupSelected === FilterType.SUBSTATION_OR_VL) {
return [EQUIPMENT_TYPES.SUBSTATION, EQUIPMENT_TYPES.VOLTAGE_LEVEL];
}

return genericFiltersStrictMode
? equipmentTypes
: Object.values(EQUIPMENT_TYPES.toString()).filter(
(equipmentType) =>
equipmentType !== EQUIPMENT_TYPES.SUBSTATION && equipmentType !== EQUIPMENT_TYPES.VOLTAGE_LEVEL
);
}, [equipmentTypes, genericFiltersStrictMode, filterGroupSelected]);

return (
<>
Expand All @@ -156,7 +184,10 @@ function GlobalFilterPaper({ children, autocompleteRef }: Readonly<GlobalFilterP
<Paper sx={resultsGlobalFilterStyles.dropdown}>
<Grid container>
<Grid item xs={XS_COLUMN1} sx={resultsGlobalFilterStyles.cellHeader}>
<FormattedMessage id={'results.globalFilter.categories'} />
<TextWithToolTip
text="results.globalFilter.categories"
tooltipMessage="results.globalFilter.categoriesHelp"
/>
</Grid>
<Grid item xs={XS_COLUMN2} sx={resultsGlobalFilterStyles.cellHeader} />
<Grid item xs={XS_COLUMN3} sx={resultsGlobalFilterStyles.cellHeader}>
Expand All @@ -179,7 +210,16 @@ function GlobalFilterPaper({ children, autocompleteRef }: Readonly<GlobalFilterP
selected={category === filterGroupSelected}
>
<ListItemText
primary={<FormattedMessage id={'results.globalFilter.' + category} />}
primary={
category === 'genericFilter' ? (
<TextWithToolTip
text="results.globalFilter.genericFilter"
tooltipMessage="results.globalFilter.elementsHelp"
/>
) : (
<FormattedMessage id={'results.globalFilter.' + category} />
)
}
/>
</ListItemButton>
);
Expand All @@ -189,15 +229,14 @@ function GlobalFilterPaper({ children, autocompleteRef }: Readonly<GlobalFilterP
<Grid item xs={XS_COLUMN2} sx={resultsGlobalFilterStyles.cell}>
<Box
sx={mergeSx(resultsGlobalFilterStyles.list, {
height:
filterGroupSelected === FilterType.GENERIC_FILTER
? `${GLOBAL_FILTERS_CELL_HEIGHT - IMPORT_FILTER_HEIGHT}px`
: `${GLOBAL_FILTERS_CELL_HEIGHT}px`,
height: isGenericFilterType(filterGroupSelected)
? `${GLOBAL_FILTERS_CELL_HEIGHT - IMPORT_FILTER_HEIGHT}px`
: `${GLOBAL_FILTERS_CELL_HEIGHT}px`,
})}
>
{children}
</Box>
{filterGroupSelected === FilterType.GENERIC_FILTER && (
{isGenericFilterType(filterGroupSelected) && (
<Button
startIcon={<FileUploadIcon />}
fullWidth={true}
Expand All @@ -211,23 +250,7 @@ function GlobalFilterPaper({ children, autocompleteRef }: Readonly<GlobalFilterP
)}
</Grid>
<Grid item xs={XS_COLUMN3} sx={resultsGlobalFilterStyles.cell}>
<List sx={mergeSx(resultsGlobalFilterStyles.list, { overflowY: 'auto' })}>
{selectedGlobalFilters.map((element: GlobalFilter) => (
<ListItem key={element.label} sx={{ height: '1.8em' }}>
<OverflowableChip
label={getOptionLabel(element, translate)}
sx={getResultsGlobalFiltersChipStyle(element.filterType)}
onDelete={() => {
const newSelectedGlobalFilters = selectedGlobalFilters.filter(
(filter) => filter !== element
);
setSelectedGlobalFilters(newSelectedGlobalFilters);
onChange(newSelectedGlobalFilters);
}}
/>
</ListItem>
))}
</List>
<SelectedGlobalFilters />
</Grid>
</Grid>
</Paper>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import { PropsWithChildren, useCallback, useEffect, useMemo, useState } from 'react';
import { GlobalFilter } from './global-filter-types';
import { FilterType } from '../utils';
import { FilterType, isGenericFilter } from '../utils';
import type { UUID } from 'node:crypto';
import {
ElementAttributes,
Expand Down Expand Up @@ -58,7 +58,7 @@ export default function GlobalFilterProvider({

const notFoundGenericFilterUuids: UUID[] = [];
const genericFiltersUuids: UUID[] = mutableFilters
.filter((globalFilter) => globalFilter.filterType === FilterType.GENERIC_FILTER)
.filter((globalFilter) => isGenericFilter(globalFilter))
.map((globalFilter) => globalFilter.uuid)
.filter((globalFilterUUID) => globalFilterUUID !== undefined);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ export default function GlobalFilterSelector({
if (!categories.includes(FilterType.GENERIC_FILTER) && !disableGenericFilters) {
categories.push(FilterType.GENERIC_FILTER);
}
if (!categories.includes(FilterType.SUBSTATION_OR_VL) && !disableGenericFilters) {
categories.push(FilterType.SUBSTATION_OR_VL);
}
return categories;
}, [filters, disableGenericFilters]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import { cyan } from '@mui/material/colors';
import { cyan, lime } from '@mui/material/colors';
import { FilterType } from '../utils';
import { mergeSx, type MuiStyles } from '@gridsuite/commons-ui';

Expand All @@ -21,6 +21,9 @@ export const getResultsGlobalFiltersChipStyle = (filterType: string) => {
case FilterType.GENERIC_FILTER:
chipStyle = resultsGlobalFilterStyles.chipGenericFilter;
break;
case FilterType.SUBSTATION_OR_VL:
chipStyle = resultsGlobalFilterStyles.chipSubstationOrVoltageLevel;
break;
case FilterType.SUBSTATION_PROPERTY:
chipStyle = resultsGlobalFilterStyles.chipSubstationProperty;
break;
Expand All @@ -29,7 +32,7 @@ export const getResultsGlobalFiltersChipStyle = (filterType: string) => {
};

const AUTOCOMPLETE_WIDTH: number = 520;
const POPPER_EXTRA_WIDTH: number = 250;
const POPPER_EXTRA_WIDTH: number = 300;
export const GLOBAL_FILTERS_CELL_HEIGHT: number = 400;
export const IMPORT_FILTER_HEIGHT: number = 40;

Expand Down Expand Up @@ -68,6 +71,9 @@ export const resultsGlobalFilterStyles = {
border: '1px solid',
borderColor: theme.palette.divider,
}),
cellTooltip: (theme) => ({
paddingLeft: theme.spacing(1),
}),
cell: (theme) => ({
borderLeft: '1px solid',
borderColor: theme.palette.divider,
Expand All @@ -80,6 +86,20 @@ export const resultsGlobalFilterStyles = {
width: '100%',
maxHeight: `${GLOBAL_FILTERS_CELL_HEIGHT}px`,
}),
selectedFiltersPanel: () => ({
overflowY: 'auto',
paddingLeft: 1,
paddingTop: 1,
maxHeight: `${GLOBAL_FILTERS_CELL_HEIGHT}px`,
}),
selectedFiltersSubGroup: (theme) => ({
display: 'flex',
flexDirection: 'row',
flexWrap: 'wrap',
color: theme.palette.text.secondary,
fontSize: '1em',
paddingBottom: 1,
}),
importFilterButton: (theme) => ({
color: theme.palette.text.secondary,
fontSize: '0.8em',
Expand All @@ -103,7 +123,7 @@ export const resultsGlobalFilterStyles = {
chip: {
'&.MuiChip-root': {
borderRadius: '100px solid',
margin: '4px 2px 4px 2px',
margin: '1px 2px 1px 2px',
padding: '0',
color: 'white',
},
Expand Down Expand Up @@ -145,6 +165,14 @@ export const resultsGlobalFilterStyles = {
backgroundColor: `${cyan['700']}!important`,
},
},
chipSubstationOrVoltageLevel: {
'&.MuiChip-root, &.MuiChip-root[aria-selected="true"]': {
backgroundColor: `${lime['800']}!important`,
},
'&.MuiChip-root:hover, &.MuiChip-root:focus': {
backgroundColor: `${lime['900']}!important`,
},
},
chipSubstationProperty: (theme) => ({
'&.MuiChip-root, &.MuiChip-root[aria-selected="true"]': {
backgroundColor: `${theme.palette.success.main}!important`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const getOptionLabel = (option: GlobalFilter, translate: (arg: string) =>
case FilterType.VOLTAGE_LEVEL:
return option.label + ' kV';
case FilterType.GENERIC_FILTER:
case FilterType.SUBSTATION_OR_VL:
case FilterType.SUBSTATION_PROPERTY:
return option.label;
}
Expand Down
Loading
Loading