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

Improve gui criteria filter #674

Merged
merged 20 commits into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from 17 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
4 changes: 2 additions & 2 deletions src/components/filter/expert/expertFilterConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,12 +194,12 @@ export const OPERATOR_OPTIONS = {
IS_PART_OF: {
name: OperatorType.IS_PART_OF,
customName: OperatorType.IS_PART_OF,
label: 'isPartOf',
label: 'inFilter',
},
IS_NOT_PART_OF: {
name: OperatorType.IS_NOT_PART_OF,
customName: OperatorType.IS_NOT_PART_OF,
label: 'isNotPartOf',
label: 'notInFilter',
},
};

Expand Down
9 changes: 8 additions & 1 deletion src/components/filter/expert/stylesExpertFilter.css
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,14 @@
display: none;
}

.queryBuilder-branches .rule:hover .rule-remove {
visibility: visible;
}

.queryBuilder-branches .rule .rule-remove {
visibility: hidden;
}

.queryBuilder-branches .ruleGroup .ruleGroup::before,
.queryBuilder-branches .ruleGroup .ruleGroup::after {
left: calc(calc(-0.5rem - 1px) - 1px);
Expand All @@ -110,7 +118,6 @@
}

/* Justify layout */
.queryBuilder .ruleGroup-remove,
.queryBuilder .rule-remove {
margin-left: auto;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ import { CombinatorSelectorProps } from 'react-querybuilder';
import { useCallback, useState } from 'react';
import { MaterialValueSelector } from '@react-querybuilder/material';
import { PopupConfirmationDialog } from '../../dialogs/popupConfirmationDialog/PopupConfirmationDialog';
import { useSelectAppearance } from '../../../hooks/useSelectAppearance';

export function CombinatorSelector(props: CombinatorSelectorProps) {
const { value, handleOnChange } = props;
const { options, value, handleOnChange } = props;
const [tempCombinator, setTempCombinator] = useState(value);
const [openPopup, setOpenPopup] = useState(false);

Expand All @@ -35,6 +36,7 @@ export function CombinatorSelector(props: CombinatorSelectorProps) {
setTempCombinator(newCombinator);
setOpenPopup(true);
}}
{...useSelectAppearance(options.length)}
/>
</>
);
Expand Down
4 changes: 3 additions & 1 deletion src/components/inputs/reactQueryBuilder/FieldSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import { ValueSelectorProps } from 'react-querybuilder';
import { MaterialValueSelector } from '@react-querybuilder/material';
import { useSelectAppearance } from '../../../hooks/useSelectAppearance';

const ITEM_HEIGHT = 32; // default value from React query builder defaultNativeSelectStyles that can't be accessed
const ITEM_PADDING = 4;
Expand All @@ -21,5 +22,6 @@ const MenuProps = {
};

export function FieldSelector(props: Readonly<ValueSelectorProps>) {
return <MaterialValueSelector {...props} MenuProps={MenuProps} />;
const { options } = props;
return <MaterialValueSelector {...props} MenuProps={MenuProps} {...useSelectAppearance(options.length)} />;
}
41 changes: 36 additions & 5 deletions src/components/inputs/reactQueryBuilder/PropertyValueEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import { useCallback, useEffect, useMemo } from 'react';
import Grid from '@mui/material/Grid';
import { Autocomplete, MenuItem, Select, TextField } from '@mui/material';
import { Autocomplete, createFilterOptions, FilterOptionsState, MenuItem, Select, TextField } from '@mui/material';
import { ValueEditorProps } from 'react-querybuilder';
import { useIntl } from 'react-intl';
import { useValid } from './hooks/useValid';
Expand All @@ -16,6 +16,7 @@ import { OPERATOR_OPTIONS } from '../../filter/expert/expertFilterConstants';
import { FieldConstants } from '../../../utils/constants/fieldConstants';
import { usePredefinedProperties } from '../../../hooks/usePredefinedProperties';
import { EquipmentType } from '../../../utils';
import { useSelectAppearance } from '../../../hooks/useSelectAppearance';

const PROPERTY_VALUE_OPERATORS = [OPERATOR_OPTIONS.IN];

Expand Down Expand Up @@ -70,8 +71,29 @@ export function PropertyValueEditor(props: ExpertFilterPropertyProps) {
[valueEditorProps]
);

const filter = useMemo(() => {
return createFilterOptions<string>();
}, []);

const filterList = useCallback(
(options: string[], params: FilterOptionsState<string>) => {
let filtered = filter(options, params);
const { inputValue } = params;

const isExisting = options.some((option) => inputValue === option);
if (isExisting && options.length === 1 && options[0] === inputValue) {
// exact match : nothing to show
filtered = [];
} else if (inputValue !== '' && !isExisting) {
filtered.push(inputValue);
}
return filtered;
},
[filter]
);

return (
<Grid container item spacing={1}>
<Grid container spacing={1} item>
<Grid item xs={5}>
<Autocomplete
value={propertyName ?? ''}
Expand All @@ -84,9 +106,10 @@ export function PropertyValueEditor(props: ExpertFilterPropertyProps) {
onChange(FieldConstants.PROPERTY_NAME, value);
}}
size="small"
filterOptions={(options, params) => filterList(options, params)}
/>
</Grid>
<Grid item xs={2.5}>
<Grid item xs="auto">
<Select
value={propertyOperator ?? PROPERTY_VALUE_OPERATORS[0].customName}
size="small"
Expand All @@ -95,6 +118,7 @@ export function PropertyValueEditor(props: ExpertFilterPropertyProps) {
onChange={(event, value) => {
onChange(FieldConstants.PROPERTY_OPERATOR, value);
}}
{...useSelectAppearance(PROPERTY_VALUE_OPERATORS.length)}
>
{PROPERTY_VALUE_OPERATORS.map((operator) => (
<MenuItem key={operator.customName} value={operator.customName}>
Expand All @@ -103,19 +127,26 @@ export function PropertyValueEditor(props: ExpertFilterPropertyProps) {
))}
</Select>
</Grid>
<Grid item xs={4.5}>
<Grid item xs>
<Autocomplete
value={propertyValues ?? []}
options={predefinedValues ?? []}
title={valueEditorProps?.title}
multiple
renderInput={(params) => <TextField {...params} error={!valid} />}
renderInput={(params) => (
<TextField
{...params}
error={!valid}
placeholder={propertyValues?.length > 0 ? '' : intl.formatMessage({ id: 'valuesList' })}
/>
)}
freeSolo
autoSelect
onChange={(event, value) => {
onChange(FieldConstants.PROPERTY_VALUES, value);
}}
size="small"
filterOptions={(options, params) => filterList(options, params)}
/>
</Grid>
</Grid>
Expand Down
4 changes: 3 additions & 1 deletion src/components/inputs/reactQueryBuilder/ValueSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@

import { ValueSelectorProps } from 'react-querybuilder';
import { MaterialValueSelector } from '@react-querybuilder/material';
import { useSelectAppearance } from '../../../hooks/useSelectAppearance';

export function ValueSelector(props: ValueSelectorProps) {
return <MaterialValueSelector {...props} />;
const { options } = props;
return <MaterialValueSelector {...props} {...useSelectAppearance(options.length)} sx={{ border: 'none' }} />;
}
1 change: 1 addition & 0 deletions src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ export * from './usePredefinedProperties';
export * from './usePrevious';
export * from './useSnackMessage';
export * from './useFormatLabelWithUnit';
export * from './useSelectAppearance';
28 changes: 28 additions & 0 deletions src/hooks/useSelectAppearance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* Copyright (c) 2025, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

/** Hook used to modify the appearance of Select into a readonly TextField,
by hiding display button and setting readOnly prop to true
if options list is only one element long.
P.S : Do not use on AutoComplete.
*/
export function useSelectAppearance(listLength: number) {
if (listLength === 1) {
return {
IconComponent: () => null,
sx: {
boxShadow: 'none',
'.MuiOutlinedInput-notchedOutline': { border: 'none' },
pointerEvents: 'none',
border: 'none',
},
readOnly: true,
disableUnderline: true,
};
}
return {};
}
4 changes: 2 additions & 2 deletions src/translations/en/filterEn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ export const filterEn = {
not_exists: 'not exists',
between: 'between',
in: 'in',
isPartOf: 'is part of',
isNotPartOf: 'is not part of',
inFilter: 'in filter',
notInFilter: 'not in filter',
emptyRule: 'Filter contains an empty field',
incorrectRule: 'Filter contains an incorrect field',
obsoleteFilter: 'This filter is no longer supported. Please remove it or change its equipment type.',
Expand Down
1 change: 1 addition & 0 deletions src/translations/en/filterExpertEn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,4 +189,5 @@ export const filterExpertEn = {
'The operator will be changed and will be applied to all the rules already created in the group.',
lowShortCircuitCurrentLimit: 'Low short-circuit current limit',
highShortCircuitCurrentLimit: 'High short-circuit current limit',
valuesList: 'Values list',
};
1 change: 1 addition & 0 deletions src/translations/fr/filterExpertFr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,4 +188,5 @@ export const filterExpertFr = {
changeOperatorMessage: "L'opérateur sera modifié et s'appliquera sur toutes les règles déjà créées dans le groupe.",
lowShortCircuitCurrentLimit: 'Limite ICC min',
highShortCircuitCurrentLimit: 'Limite ICC max',
valuesList: 'Liste de valeurs',
};
4 changes: 2 additions & 2 deletions src/translations/fr/filterFr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ export const filterFr = {
not_exists: "n'existe pas",
between: 'entre',
in: 'dans',
isPartOf: 'fait partie de',
isNotPartOf: 'ne fait pas partie de',
inFilter: 'dans le filtre',
notInFilter: 'pas dans le filtre',
emptyRule: 'Le filtre contient un champ vide',
incorrectRule: 'Le filtre contient un champ incorrect',
obsoleteFilter: "Ce filtre n'est plus supporté. Veuillez le supprimer ou changer son type d'équipement.",
Expand Down
Loading