diff --git a/src/components/dialogs/customMuiDialog/CustomMuiDialog.tsx b/src/components/dialogs/customMuiDialog/CustomMuiDialog.tsx index 044bf984..0d0a1b31 100644 --- a/src/components/dialogs/customMuiDialog/CustomMuiDialog.tsx +++ b/src/components/dialogs/customMuiDialog/CustomMuiDialog.tsx @@ -30,6 +30,7 @@ export interface CustomMuiDialogProps { isDataFetching?: boolean; language?: string; confirmationMessageKey?: string; + unscrollableFullHeight?: boolean; } const styles = { @@ -40,6 +41,20 @@ const styles = { margin: 'auto', }, }, + dialogPaperFullHeight: { + '.MuiDialog-paper': { + width: 'auto', + minWidth: '1000px', + margin: 'auto', + height: '95vh', + overflowY: 'hidden', + }, + }, + unscrollable: { + display: 'flex', + flexDirection: 'column', + overflowY: 'hidden', + }, }; export function CustomMuiDialog({ @@ -57,6 +72,7 @@ export function CustomMuiDialog({ children, language, confirmationMessageKey, + unscrollableFullHeight = false, }: Readonly) { const [openConfirmationPopup, setOpenConfirmationPopup] = useState(false); const [validatedData, setValidatedData] = useState(undefined); @@ -113,14 +129,19 @@ export function CustomMuiDialog({ removeOptional={removeOptional} language={language} > - + {isDataFetching && } - {children} + {children} ) { const filterType = useWatch({ name: FieldConstants.FILTER_TYPE }); - // We do this because setValue don't set the field dirty - const handleChange = (_event: React.ChangeEvent, value: string) => { - setValue(FieldConstants.FILTER_TYPE, value); - }; - - useEffect(() => { - if (sourceFilterForExplicitNamingConversion) { - setValue(FieldConstants.FILTER_TYPE, FilterType.EXPLICIT_NAMING.id); - } - }, [sourceFilterForExplicitNamingConversion, setValue]); - return ( - - - + + - - {creation && ( - <> - - - - {!sourceFilterForExplicitNamingConversion && ( - - - - )} - - )} + {filterType === FilterType.CRITERIA_BASED.id && } {filterType === FilterType.EXPLICIT_NAMING.id && ( )} {filterType === FilterType.EXPERT.id && } - + ); } diff --git a/src/components/filter/HeaderFilterForm.tsx b/src/components/filter/HeaderFilterForm.tsx new file mode 100644 index 00000000..5a07364c --- /dev/null +++ b/src/components/filter/HeaderFilterForm.tsx @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2024, 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 { useFormContext } from 'react-hook-form'; +import React, { useEffect } from 'react'; +import { Grid } from '@mui/material'; +import { UUID } from 'crypto'; +import { FieldConstants } from '../../utils/constants/fieldConstants'; +import { FilterType } from './constants/FilterConstants'; +import { UniqueNameInput } from '../inputs/reactHookForm/text/UniqueNameInput'; +import { ElementExistsType, ElementType } from '../../utils/types/elementType'; +import { DescriptionField } from '../inputs/reactHookForm/text/DescriptionField'; +import { RadioInput } from '../inputs/reactHookForm/booleans/RadioInput'; + +export interface FilterFormProps { + creation?: boolean; + activeDirectory?: UUID; + elementExists?: ElementExistsType; + sourceFilterForExplicitNamingConversion?: { + id: UUID; + equipmentType: string; + }; +} + +export function HeaderFilterForm({ + sourceFilterForExplicitNamingConversion, + creation, + activeDirectory, + elementExists, +}: Readonly) { + const { setValue } = useFormContext(); + + useEffect(() => { + if (sourceFilterForExplicitNamingConversion) { + setValue(FieldConstants.FILTER_TYPE, FilterType.EXPLICIT_NAMING.id); + } + }, [sourceFilterForExplicitNamingConversion, setValue]); + + // We do this because setValue don't set the field dirty + const handleChange = (_event: React.ChangeEvent, value: string) => { + setValue(FieldConstants.FILTER_TYPE, value); + }; + + return ( + + + + + {creation && ( + <> + + + + {!sourceFilterForExplicitNamingConversion && ( + + + + )} + + )} + + ); +} diff --git a/src/components/filter/criteriaBased/CriteriaBasedFilterEditionDialog.tsx b/src/components/filter/criteriaBased/CriteriaBasedFilterEditionDialog.tsx index 7ccb87ea..fe4f7a91 100644 --- a/src/components/filter/criteriaBased/CriteriaBasedFilterEditionDialog.tsx +++ b/src/components/filter/criteriaBased/CriteriaBasedFilterEditionDialog.tsx @@ -134,6 +134,7 @@ export function CriteriaBasedFilterEditionDialog({ disabledSave={!!nameError || !!isValidating} isDataFetching={dataFetchStatus === FetchStatus.FETCHING} language={language} + unscrollableFullHeight > {isDataReady && } diff --git a/src/components/filter/criteriaBased/CriteriaBasedFilterForm.tsx b/src/components/filter/criteriaBased/CriteriaBasedFilterForm.tsx index 8a4e57da..dcae3624 100644 --- a/src/components/filter/criteriaBased/CriteriaBasedFilterForm.tsx +++ b/src/components/filter/criteriaBased/CriteriaBasedFilterForm.tsx @@ -4,7 +4,6 @@ * 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 Grid from '@mui/material/Grid'; import { FilterProperties, filterPropertiesYupSchema } from './FilterProperties'; import { FieldConstants } from '../../../utils/constants/fieldConstants'; import yup from '../../../utils/yupConfig'; @@ -26,12 +25,11 @@ export const criteriaBasedFilterEmptyFormData = getCriteriaBasedFormData(null, { export function CriteriaBasedFilterForm() { return ( - - + - + ); } diff --git a/src/components/filter/criteriaBased/CriteriaBasedForm.tsx b/src/components/filter/criteriaBased/CriteriaBasedForm.tsx index 20667caa..e67f89f3 100644 --- a/src/components/filter/criteriaBased/CriteriaBasedForm.tsx +++ b/src/components/filter/criteriaBased/CriteriaBasedForm.tsx @@ -6,8 +6,8 @@ */ import { useFormContext, useWatch } from 'react-hook-form'; -import { Grid } from '@mui/material'; -import { useEffect } from 'react'; +import { Box, Grid } from '@mui/material'; +import { ReactElement, useEffect } from 'react'; import { FieldConstants } from '../../../utils/constants/fieldConstants'; import { SelectInput } from '../../inputs/reactHookForm/selectInputs/SelectInput'; import { InputWithPopupConfirmation } from '../../inputs/reactHookForm/selectInputs/InputWithPopupConfirmation'; @@ -17,9 +17,10 @@ import { useSnackMessage } from '../../../hooks/useSnackMessage'; export interface CriteriaBasedFormProps { equipments: Record; defaultValues: Record; + children?: ReactElement; } -export function CriteriaBasedForm({ equipments, defaultValues }: CriteriaBasedFormProps) { +export function CriteriaBasedForm({ equipments, defaultValues, children }: CriteriaBasedFormProps) { const { getValues, setValue } = useFormContext(); const { snackError } = useSnackMessage(); @@ -46,8 +47,13 @@ export function CriteriaBasedForm({ equipments, defaultValues }: CriteriaBasedFo }; return ( - - + <> + - - {watchEquipmentType && - equipments[watchEquipmentType] && - equipments[watchEquipmentType].fields.map((equipment: any, index: number) => { - const EquipmentForm = equipment.renderer; - const uniqueKey = `${watchEquipmentType}-${index}`; - return ( - - - - ); - })} - + + + + {watchEquipmentType && + equipments[watchEquipmentType] && + equipments[watchEquipmentType].fields.map((equipment: any, index: number) => { + const EquipmentForm = equipment.renderer; + const uniqueKey = `${watchEquipmentType}-${index}`; + return ( + + + + ); + })} + {children} + + + ); } diff --git a/src/components/filter/expert/ExpertFilterEditionDialog.tsx b/src/components/filter/expert/ExpertFilterEditionDialog.tsx index ceb09d19..61de0a36 100644 --- a/src/components/filter/expert/ExpertFilterEditionDialog.tsx +++ b/src/components/filter/expert/ExpertFilterEditionDialog.tsx @@ -143,6 +143,7 @@ export function ExpertFilterEditionDialog({ disabledSave={!!nameError || !!isValidating} isDataFetching={dataFetchStatus === FetchStatus.FETCHING} language={language} + unscrollableFullHeight > {isDataReady && } diff --git a/src/components/filter/expert/ExpertFilterForm.tsx b/src/components/filter/expert/ExpertFilterForm.tsx index 3cbdb8c3..25f31664 100644 --- a/src/components/filter/expert/ExpertFilterForm.tsx +++ b/src/components/filter/expert/ExpertFilterForm.tsx @@ -7,7 +7,6 @@ import { useCallback, useMemo } from 'react'; -import Grid from '@mui/material/Grid'; import type { RuleGroupTypeAny } from 'react-querybuilder'; import { formatQuery } from 'react-querybuilder'; import './stylesExpertFilter.css'; @@ -15,6 +14,7 @@ import { useFormContext, useWatch } from 'react-hook-form'; import * as yup from 'yup'; import { v4 as uuid4 } from 'uuid'; import { useIntl } from 'react-intl'; +import { Box } from '@mui/material'; import { testQuery } from './expertFilterUtils'; import { COMBINATOR_OPTIONS, @@ -43,6 +43,24 @@ yup.setLocale({ }, }); +const styles = { + ScrollableContainer: { + position: 'relative', + '&::after': { + content: '""', + clear: 'both', + display: 'block', + }, + }, + ScrollableContent: { + position: 'absolute', + width: '100%', + height: '100%', + maxHeight: '100%', + overflow: 'auto', + }, +}; + export const EXPERT_FILTER_QUERY = 'rules'; function isSupportedEquipmentType(equipmentType: string): boolean { @@ -125,8 +143,8 @@ export function ExpertFilterForm() { }, [intl, watchEquipmentType]); return ( - - + <> + - - {watchEquipmentType && isSupportedEquipmentType(watchEquipmentType) && ( - - )} - + + + + {watchEquipmentType && isSupportedEquipmentType(watchEquipmentType) && ( + + )} + + + ); } diff --git a/src/components/filter/expert/stylesExpertFilter.css b/src/components/filter/expert/stylesExpertFilter.css index 6b57ecd7..d0630750 100644 --- a/src/components/filter/expert/stylesExpertFilter.css +++ b/src/components/filter/expert/stylesExpertFilter.css @@ -129,11 +129,6 @@ border-bottom: 2px solid #ba000d; } -.queryBuilder { - overflow: auto; - max-height: 600px; -} - /* DnD section, copied from original, just 'border-bottom-color: lightgrey' change */ [data-inlinecombinators='disabled'] .dndOver.rule, [data-inlinecombinators='disabled'] .dndOver.ruleGroup-header { diff --git a/src/components/filter/explicitNaming/ExplicitNamingFilterEditionDialog.tsx b/src/components/filter/explicitNaming/ExplicitNamingFilterEditionDialog.tsx index a1df6f0c..60eea448 100644 --- a/src/components/filter/explicitNaming/ExplicitNamingFilterEditionDialog.tsx +++ b/src/components/filter/explicitNaming/ExplicitNamingFilterEditionDialog.tsx @@ -145,6 +145,7 @@ export function ExplicitNamingFilterEditionDialog({ disabledSave={!!nameError || !!isValidating} isDataFetching={dataFetchStatus === FetchStatus.FETCHING} language={language} + unscrollableFullHeight > {isDataReady && } diff --git a/src/components/filter/explicitNaming/ExplicitNamingFilterForm.tsx b/src/components/filter/explicitNaming/ExplicitNamingFilterForm.tsx index 332d0f23..237d0c6a 100644 --- a/src/components/filter/explicitNaming/ExplicitNamingFilterForm.tsx +++ b/src/components/filter/explicitNaming/ExplicitNamingFilterForm.tsx @@ -7,7 +7,7 @@ import { useCallback, useEffect, useMemo } from 'react'; import { useIntl } from 'react-intl'; import { useFormContext, useWatch } from 'react-hook-form'; -import Grid from '@mui/material/Grid'; +import { Box } from '@mui/material'; import { ValueParserParams } from 'ag-grid-community'; import { v4 as uuid4 } from 'uuid'; import { UUID } from 'crypto'; @@ -32,6 +32,24 @@ import { EquipmentType } from '../../../utils/types/equipmentType'; export const FILTER_EQUIPMENTS_ATTRIBUTES = 'filterEquipmentsAttributes'; +const styles = { + ScrollableContainer: { + position: 'relative', + '&::after': { + content: '""', + clear: 'both', + display: 'block', + }, + }, + ScrollableContent: { + paddingTop: '10px', + position: 'absolute', + width: '100%', + height: '100%', + overflow: 'auto', + }, +}; + function isGeneratorOrLoad(equipmentType: string): boolean { return equipmentType === Generator.type || equipmentType === Load.type; } @@ -213,8 +231,8 @@ export function ExplicitNamingFilterForm({ sourceFilterForExplicitNamingConversi }; return ( - - + <> + )} - + {watchEquipmentType && ( - - - + + + + + )} - + ); } + +export default ExplicitNamingFilterForm; diff --git a/src/components/filter/utils/filterFormUtils.ts b/src/components/filter/utils/filterFormUtils.ts index 81502717..01626094 100644 --- a/src/components/filter/utils/filterFormUtils.ts +++ b/src/components/filter/utils/filterFormUtils.ts @@ -75,7 +75,7 @@ const energySource = { ], }, }; -type FormField = { +export type FormField = { renderer: FunctionComponent; props: { label: string; diff --git a/src/components/inputs/reactQueryBuilder/CustomReactQueryBuilder.tsx b/src/components/inputs/reactQueryBuilder/CustomReactQueryBuilder.tsx index 28af9ad9..da2b57f0 100644 --- a/src/components/inputs/reactQueryBuilder/CustomReactQueryBuilder.tsx +++ b/src/components/inputs/reactQueryBuilder/CustomReactQueryBuilder.tsx @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import Grid from '@mui/material/Grid'; +import { Box } from '@mui/material'; import { QueryBuilderDnD } from '@react-querybuilder/dnd'; import * as ReactDnD from 'react-dnd'; import * as ReactDndHtml5Backend from 'react-dnd-html5-backend'; @@ -77,39 +77,37 @@ export function CustomReactQueryBuilder(props: Readonly - - - - getOperators(fieldName, intl)} - validator={queryValidator} - controlClassnames={{ - queryBuilder: 'queryBuilder-branches', - }} - controlElements={{ - addRuleAction: RuleAddButton, - addGroupAction: GroupAddButton, - combinatorSelector: CombinatorSelector, - removeRuleAction: RemoveButton, - removeGroupAction: RemoveButton, - valueEditor: ValueEditor, - operatorSelector: ValueSelector, - fieldSelector: FieldSelector, - valueSourceSelector: ValueSelector, - }} - listsAsArrays - /> - - - - + + + getOperators(fieldName, intl)} + validator={queryValidator} + controlClassnames={{ + queryBuilder: 'queryBuilder-branches', + }} + controlElements={{ + addRuleAction: RuleAddButton, + addGroupAction: GroupAddButton, + combinatorSelector: CombinatorSelector, + removeRuleAction: RemoveButton, + removeGroupAction: RemoveButton, + valueEditor: ValueEditor, + operatorSelector: ValueSelector, + fieldSelector: FieldSelector, + valueSourceSelector: ValueSelector, + }} + listsAsArrays + /> + + + - + ); }