Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/add-subtype-into-equipmentType' …
Browse files Browse the repository at this point in the history
…into add-subtype-into-equipmentType
  • Loading branch information
ghazwarhili committed Feb 3, 2025
2 parents 987ace1 + 8b406ec commit 721bb09
Show file tree
Hide file tree
Showing 14 changed files with 125 additions and 23 deletions.
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)} />;
}
19 changes: 15 additions & 4 deletions src/components/inputs/reactQueryBuilder/PropertyValueEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ 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';
import { useCustomFilterOptions } from '../../../hooks/useCustomFilterOptions';

const PROPERTY_VALUE_OPERATORS = [OPERATOR_OPTIONS.IN];

Expand Down Expand Up @@ -71,7 +73,7 @@ export function PropertyValueEditor(props: ExpertFilterPropertyProps) {
);

return (
<Grid container item spacing={1}>
<Grid container spacing={1} item>
<Grid item xs={5}>
<Autocomplete
value={propertyName ?? ''}
Expand All @@ -84,9 +86,10 @@ export function PropertyValueEditor(props: ExpertFilterPropertyProps) {
onChange(FieldConstants.PROPERTY_NAME, value);
}}
size="small"
filterOptions={useCustomFilterOptions()}
/>
</Grid>
<Grid item xs={2.5}>
<Grid item xs="auto">
<Select
value={propertyOperator ?? PROPERTY_VALUE_OPERATORS[0].customName}
size="small"
Expand All @@ -95,6 +98,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 +107,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={useCustomFilterOptions()}
/>
</Grid>
</Grid>
Expand Down
14 changes: 13 additions & 1 deletion src/components/inputs/reactQueryBuilder/TextValueEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
import { ValueEditorProps } from 'react-querybuilder';
import { MaterialValueEditor } from '@react-querybuilder/material';
import { Autocomplete, TextField } from '@mui/material';
import { useIntl } from 'react-intl';
import { useConvertValue } from './hooks/useConvertValue';
import { useValid } from './hooks/useValid';
import { useCustomFilterOptions } from '../../../hooks/useCustomFilterOptions';

export function TextValueEditor(props: ValueEditorProps) {
useConvertValue(props);
Expand All @@ -18,6 +20,9 @@ export function TextValueEditor(props: ValueEditorProps) {

const { value, handleOnChange, title } = props;
// The displayed component totally depends on the value type and not the operator. This way, we have smoother transition.
const customFilterOptions = useCustomFilterOptions();
const intl = useIntl();

if (!Array.isArray(value)) {
return <MaterialValueEditor {...props} />;
}
Expand All @@ -29,9 +34,16 @@ export function TextValueEditor(props: ValueEditorProps) {
onChange={(event, newValue: any) => handleOnChange(newValue)}
multiple
fullWidth
renderInput={(params) => <TextField {...params} error={!valid} />}
renderInput={(params) => (
<TextField
{...params}
error={!valid}
placeholder={value?.length > 0 ? '' : intl.formatMessage({ id: 'valuesList' })}
/>
)}
size="small"
title={title}
filterOptions={customFilterOptions}
/>
);
}
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';
31 changes: 31 additions & 0 deletions src/hooks/useCustomFilterOptions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* 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/.
*/

import { useCallback } from 'react';
import { createFilterOptions, FilterOptionsState } from '@mui/material';

/**
* Hook used to add custom filterOptions, use only when freeSolo = true
*/
export function useCustomFilterOptions() {
return useCallback((options: string[], params: FilterOptionsState<string>) => {
const filter = createFilterOptions<string>();
const filteredOptions = 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
return [];
}

if (inputValue !== '' && !isExisting) {
filteredOptions.push(inputValue);
}
return filteredOptions;
}, []);
}
32 changes: 32 additions & 0 deletions src/hooks/useSelectAppearance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* 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/.
*/

import { useMemo } from 'react';

/** 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) {
return useMemo(() => {
if (listLength === 1) {
return {
IconComponent: () => null,
sx: {
boxShadow: 'none',
'.MuiOutlinedInput-notchedOutline': { border: 'none' },
pointerEvents: 'none',
border: 'none',
},
readOnly: true,
disableUnderline: true,
};
}
return {};
}, [listLength]);
}
10 changes: 5 additions & 5 deletions src/translations/en/filterEn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
export const filterEn = {
OR: 'OR',
AND: 'AND',
rule: 'rule',
rule: 'criterion',
subGroup: 'subgroup',
is: 'is',
contains: 'contains',
Expand All @@ -18,13 +18,13 @@ 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.',
betweenRule: "Left value of 'between' rule have to be lower than the right value",
emptyGroup: 'Filter contains an empty group. Consider removing it or adding rules to this group',
betweenRule: "Left value of 'between' criterion has to be lower than the right value",
emptyGroup: 'Filter contains an empty group. Consider removing it or adding criteria to this group',
Hvdc: 'HVDC',
'filter.expert': 'Criteria based',
'filter.explicitNaming': 'Explicit naming',
Expand Down
3 changes: 2 additions & 1 deletion src/translations/en/filterExpertEn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,8 @@ export const filterExpertEn = {
YupNotTypeNumber: 'This field only accepts numeric values',
YupNotTypeDefault: 'Field value format is incorrect',
changeOperatorMessage:
'The operator will be changed and will be applied to all the rules already created in the group.',
'The operator will be changed and will be applied to all the criteria already created in the group.',
lowShortCircuitCurrentLimit: 'Low short-circuit current limit',
highShortCircuitCurrentLimit: 'High short-circuit current limit',
valuesList: 'Values list',
};
3 changes: 2 additions & 1 deletion src/translations/fr/filterExpertFr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,8 @@ export const filterExpertFr = {
lessOrEqual: '<=',
YupNotTypeNumber: "Ce champ n'accepte que des valeurs numériques",
YupNotTypeDefault: "La valeur du champ n'est pas au bon format",
changeOperatorMessage: "L'opérateur sera modifié et s'appliquera sur toutes les règles déjà créées dans le groupe.",
changeOperatorMessage: "L'opérateur sera modifié et s'appliquera sur tous les critères déjà créés dans le groupe.",
lowShortCircuitCurrentLimit: 'Limite ICC min',
highShortCircuitCurrentLimit: 'Limite ICC max',
valuesList: 'Liste de valeurs',
};
10 changes: 5 additions & 5 deletions src/translations/fr/filterFr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
export const filterFr = {
OR: 'OU',
AND: 'ET',
rule: 'règle',
rule: 'critère',
subGroup: 'sous-groupe',
is: 'est',
contains: 'contient',
Expand All @@ -18,13 +18,13 @@ 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.",
betweenRule: "La valeur de gauche d'une règle 'entre' doit être inférieure à la valeur de droite",
emptyGroup: 'Le filtre contient un groupe vide. Supprimez le ou ajoutez des règles à ce groupe',
betweenRule: "La valeur de gauche d'un critère 'entre' doit être inférieure à la valeur de droite",
emptyGroup: 'Le filtre contient un groupe vide. Supprimez le ou ajoutez des critères à ce groupe',
Hvdc: 'HVDC',
'filter.expert': 'Par critères',
'filter.explicitNaming': 'Par nommage',
Expand Down

0 comments on commit 721bb09

Please sign in to comment.