From bc0cd778578a7167681f06ea6e682907188df887 Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Fri, 26 Jul 2024 00:18:51 +0200 Subject: [PATCH 1/7] migrate to new version --- package-lock.json | 26 +++++++++++++++++++++++--- package.json | 2 +- src/redux/slices/User.ts | 9 +++++---- src/redux/store.ts | 9 +++++---- 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index 292baf2..1745d5c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@emotion/react": "^11.11.4", "@emotion/styled": "^11.11.5", - "@gridsuite/commons-ui": "0.63.2", + "@gridsuite/commons-ui": "file:../commons-ui/gridsuite-commons-ui-0.63.2.tgz", "@hookform/resolvers": "^3.3.4", "@mui/icons-material": "^5.15.14", "@mui/lab": "5.0.0-alpha.169", @@ -2750,8 +2750,9 @@ }, "node_modules/@gridsuite/commons-ui": { "version": "0.63.2", - "resolved": "https://registry.npmjs.org/@gridsuite/commons-ui/-/commons-ui-0.63.2.tgz", - "integrity": "sha512-MxFBu8wzojgVsiMP23YzGoD8UPByXRLsCFMbrL0Rpt7y4YiPD7zKwPoMs+gA7n2lL/KGtlkYg2NdLHtwI5CYEA==", + "resolved": "file:../commons-ui/gridsuite-commons-ui-0.63.2.tgz", + "integrity": "sha512-mQLOg3A4OUCEioijw3wbiquwcDBKj/rPDtSNSDvEF4amfiUYDcl9He3RtElTJYdV3qRGnrObAWj+m1N4AWmHVw==", + "license": "MPL-2.0", "dependencies": { "@react-querybuilder/dnd": "^7.2.0", "@react-querybuilder/material": "^7.2.0", @@ -2767,6 +2768,7 @@ "react-dnd-html5-backend": "^16.0.1", "react-querybuilder": "^7.2.0", "react-virtualized": "^9.22.5", + "type-fest": "^4.21.0", "uuid": "^9.0.1" }, "engines": { @@ -2792,6 +2794,7 @@ "react-intl": "^6.6.4", "react-papaparse": "^4.1.0", "react-router-dom": "^6.22.3", + "reconnecting-websocket": "^4.4.0", "yup": "^1.4.0" } }, @@ -2803,6 +2806,17 @@ "node": ">=6" } }, + "node_modules/@gridsuite/commons-ui/node_modules/type-fest": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.23.0.tgz", + "integrity": "sha512-ZiBujro2ohr5+Z/hZWHESLz3g08BBdrdLMieYFULJO+tWc437sn8kQsWLJoZErY8alNhxre9K4p3GURAG11n+w==", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@hookform/resolvers": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.3.4.tgz", @@ -16565,6 +16579,12 @@ "node": ">=8.10.0" } }, + "node_modules/reconnecting-websocket": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/reconnecting-websocket/-/reconnecting-websocket-4.4.0.tgz", + "integrity": "sha512-D2E33ceRPga0NvTDhJmphEgJ7FUYF0v4lr1ki0csq06OdlxKfugGzN0dSkxM/NfqCxYELK4KcaTOUOjTV6Dcng==", + "peer": true + }, "node_modules/recursive-readdir": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", diff --git a/package.json b/package.json index f3edd06..5049758 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "dependencies": { "@emotion/react": "^11.11.4", "@emotion/styled": "^11.11.5", - "@gridsuite/commons-ui": "0.63.2", + "@gridsuite/commons-ui": "file:../commons-ui/gridsuite-commons-ui-0.63.2.tgz", "@hookform/resolvers": "^3.3.4", "@mui/icons-material": "^5.15.14", "@mui/lab": "5.0.0-alpha.169", diff --git a/src/redux/slices/User.ts b/src/redux/slices/User.ts index 77ee8c9..68fd320 100644 --- a/src/redux/slices/User.ts +++ b/src/redux/slices/User.ts @@ -10,9 +10,10 @@ import { PayloadAction, SliceCaseReducers, } from '@reduxjs/toolkit'; +import { User } from 'oidc-client'; import { + AuthenticationRouterErrorAction, AuthenticationRouterErrorState, - CommonStoreState, LOGOUT_ERROR, LogoutErrorAction, RESET_AUTHENTICATION_ROUTER_ERROR, @@ -27,16 +28,16 @@ import { UserAction, UserValidationErrorAction, } from '@gridsuite/commons-ui'; -import { AuthenticationRouterErrorAction } from '@gridsuite/commons-ui/dist/redux/authActions'; -export type UserState = CommonStoreState & { +export type UserState = { + user: User | undefined; signInCallbackError: Error | null; authenticationRouterError: AuthenticationRouterErrorState | null; showAuthenticationRouterLogin: boolean; }; const initialState: UserState = { - user: null, + user: undefined, signInCallbackError: null, authenticationRouterError: null, showAuthenticationRouterLogin: false, diff --git a/src/redux/store.ts b/src/redux/store.ts index 83f2453..6d6d03d 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -5,11 +5,12 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ import { configureStore } from '@reduxjs/toolkit'; -import { setCommonStore } from '@gridsuite/commons-ui'; +import { initCommonServices } from '@gridsuite/commons-ui'; import { reducer } from './reducer'; export const store = configureStore({ reducer }); export type AppDispatch = typeof store.dispatch; -setCommonStore({ - getState: () => store.getState().user, -}); +initCommonServices( + process.env.REACT_APP_NAME!, + () => store.getState().user?.user +); From 089223b1ba9b6a90adccfaa90fb99f54273dd26c Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Fri, 26 Jul 2024 00:36:28 +0200 Subject: [PATCH 2/7] migrate theme storage --- src/components/app.js | 2 +- src/redux/local-storage.js | 18 ------------- src/redux/slices/Theme.js | 38 --------------------------- src/redux/slices/Theme.ts | 53 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 57 deletions(-) delete mode 100644 src/redux/local-storage.js delete mode 100644 src/redux/slices/Theme.js create mode 100644 src/redux/slices/Theme.ts diff --git a/src/components/app.js b/src/components/app.js index e646ba5..c3041e0 100644 --- a/src/components/app.js +++ b/src/components/app.js @@ -21,13 +21,13 @@ import { StyledEngineProvider, ThemeProvider, } from '@mui/material/styles'; -import { LIGHT_THEME } from '../redux/slices/Theme'; import { AuthenticationRouter, CardErrorBoundary, getPreLoginPath, initializeAuthenticationDev, initializeAuthenticationProd, + LIGHT_THEME, logout, TopBar, } from '@gridsuite/commons-ui'; diff --git a/src/redux/local-storage.js b/src/redux/local-storage.js deleted file mode 100644 index 309296e..0000000 --- a/src/redux/local-storage.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Copyright (c) 2020, 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 { DARK_THEME } from './slices/Theme'; - -const LOCAL_STORAGE_THEME_KEY = process.env.REACT_APP_NAME + '_THEME'; - -export const getLocalStorageTheme = () => { - return localStorage.getItem(LOCAL_STORAGE_THEME_KEY) || DARK_THEME; -}; - -export const saveLocalStorageTheme = (theme) => { - localStorage.setItem(LOCAL_STORAGE_THEME_KEY, theme); -}; diff --git a/src/redux/slices/Theme.js b/src/redux/slices/Theme.js deleted file mode 100644 index dea1976..0000000 --- a/src/redux/slices/Theme.js +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Copyright (c) 2021, 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 { createSlice } from '@reduxjs/toolkit'; -import { getLocalStorageTheme, saveLocalStorageTheme } from '../local-storage'; - -export const SELECT_THEME = 'SELECT_THEME'; -export const DARK_THEME = 'Dark'; -export const LIGHT_THEME = 'Light'; - -export function selectTheme(theme) { - return { type: SELECT_THEME, theme: theme }; -} - -const initialState = getLocalStorageTheme(); - -// Selectors - -// Reducers - -const reducers = { - selectTheme: (state, action) => { - state = action.payload; - saveLocalStorageTheme(state.theme); - }, -}; - -export const ThemeSlice = createSlice({ - name: 'Theme', - initialState, - reducers, -}); - -export const ThemeReducer = ThemeSlice.reducer; diff --git a/src/redux/slices/Theme.ts b/src/redux/slices/Theme.ts new file mode 100644 index 0000000..be4a29b --- /dev/null +++ b/src/redux/slices/Theme.ts @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2021, 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 { + Action, + createSlice, + PayloadAction, + SliceCaseReducers, +} from '@reduxjs/toolkit'; +import { + getLocalStorageTheme, + GsTheme, + saveLocalStorageTheme, +} from '@gridsuite/commons-ui'; + +export const SELECT_THEME = 'SELECT_THEME'; +type SelectThemeAction = Action & { + theme: GsTheme; +}; +export function selectTheme(theme: GsTheme) { + return { type: SELECT_THEME, theme: theme }; +} + +export type ThemeState = { + theme: GsTheme; +}; + +const initialState: ThemeState = { + theme: getLocalStorageTheme(process.env.REACT_APP_NAME!), +}; + +// Selectors + +// Reducers + +const reducers: SliceCaseReducers = { + selectTheme: (state, action: PayloadAction) => { + state = action.payload; + saveLocalStorageTheme(process.env.REACT_APP_NAME!, state.theme); + }, +}; + +export const ThemeSlice = createSlice({ + name: 'Theme', + initialState, + reducers, +}); + +export const ThemeReducer = ThemeSlice.reducer; From 39af62e3d4a8f01fe512779c59baaadc5c522987 Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Fri, 26 Jul 2024 00:39:56 +0200 Subject: [PATCH 3/7] dedup some functions --- src/components/2-molecules/Header.jsx | 3 +-- src/components/2-molecules/SetGroupSelect.tsx | 4 ++-- src/components/3-organisms/Automaton.jsx | 2 +- src/components/3-organisms/Filter.jsx | 2 +- src/components/3-organisms/Rule.jsx | 2 +- src/components/3-organisms/SetEditor.jsx | 6 ++--- .../automaton/AutomatonProperties.tsx | 11 ++++----- .../3-organisms/hooks/useSetSearch.js | 14 +++++------ .../react-hook-form/form/useDataUpdate.ts | 4 ++-- src/redux/slices/Mapping.js | 24 +++++++++---------- src/redux/slices/Model.js | 12 +++++----- src/utils/functions.js | 6 ++--- 12 files changed, 42 insertions(+), 48 deletions(-) diff --git a/src/components/2-molecules/Header.jsx b/src/components/2-molecules/Header.jsx index 38c87c6..273471d 100644 --- a/src/components/2-molecules/Header.jsx +++ b/src/components/2-molecules/Header.jsx @@ -9,9 +9,8 @@ import { Grid, Tooltip, Typography } from '@mui/material'; import { AddIconButton, AttachButton, SaveButton } from '../1-atoms/buttons/'; import React from 'react'; import PropTypes from 'prop-types'; - +import { mergeSx } from '@gridsuite/commons-ui'; import { styles } from './HeaderStyles'; -import { mergeSx } from 'utils/functions'; const outdatedLabel = 'Generated elements are outdated, re-generate them to delete this warning'; diff --git a/src/components/2-molecules/SetGroupSelect.tsx b/src/components/2-molecules/SetGroupSelect.tsx index debc84e..49da773 100644 --- a/src/components/2-molecules/SetGroupSelect.tsx +++ b/src/components/2-molecules/SetGroupSelect.tsx @@ -6,13 +6,13 @@ */ import { Checkbox, Grid, Typography } from '@mui/material'; +import { mergeSx } from '@gridsuite/commons-ui'; import Select from '../1-atoms/Select'; import { styles } from './SetGroupSelectStyle'; import React, { useEffect, useState } from 'react'; import { SetType } from '../../constants/models'; import { EditButton } from '../1-atoms/buttons'; import { Group, Model } from '../../redux/types/model.type'; -import { mergeSx } from 'utils/functions'; const setLabel = 'and use parameters group'; const editGroupLabel = 'Edit the parameters group and/or the parameters sets'; @@ -117,7 +117,7 @@ const SetGroupSelect = (props: SetGroupSelectProps) => { sx={mergeSx( styles.button, styles.gridItem, - errorInParams && styles.errorButton + errorInParams ? styles.errorButton : undefined )} > { const { diff --git a/src/components/3-organisms/Filter.jsx b/src/components/3-organisms/Filter.jsx index 434d7a9..16642ac 100644 --- a/src/components/3-organisms/Filter.jsx +++ b/src/components/3-organisms/Filter.jsx @@ -12,11 +12,11 @@ import { CustomReactQueryBuilder, EXPERT_FILTER_FIELDS, EXPERT_FILTER_QUERY, + mergeSx, } from '@gridsuite/commons-ui'; import { useIntl } from 'react-intl'; import { AddIconButton, DeleteButton } from '../1-atoms/buttons'; import { styles } from './FilterStyle'; -import { mergeSx } from '../../utils/functions'; import InfoIcon from '@mui/icons-material/Info'; const filterLabel = 'Where:'; diff --git a/src/components/3-organisms/Rule.jsx b/src/components/3-organisms/Rule.jsx index 74b905f..5af6def 100644 --- a/src/components/3-organisms/Rule.jsx +++ b/src/components/3-organisms/Rule.jsx @@ -7,12 +7,12 @@ import React from 'react'; import PropTypes from 'prop-types'; +import { mergeSx } from '@gridsuite/commons-ui'; import { CopyButton, DeleteButton } from '../1-atoms/buttons'; import { Grid, Paper, Typography } from '@mui/material'; import { styles } from './RuleStyle'; import ModelSelect from '../2-molecules/ModelSelect'; import SetGroupSelect from '../2-molecules/SetGroupSelect'; -import { mergeSx } from 'utils/functions'; const equipmentLabel = 'Each'; const deleteRuleLabel = 'Delete model'; diff --git a/src/components/3-organisms/SetEditor.jsx b/src/components/3-organisms/SetEditor.jsx index c8010a1..97df2aa 100644 --- a/src/components/3-organisms/SetEditor.jsx +++ b/src/components/3-organisms/SetEditor.jsx @@ -10,7 +10,7 @@ import PropTypes from 'prop-types'; import { ParameterOrigin, ParameterType } from '../../constants/models'; import { Box, Grid, TextField, Tooltip, Typography } from '@mui/material'; import InfoIcon from '@mui/icons-material/Info'; -import * as _ from 'lodash'; +import { cloneDeep } from 'lodash'; import { isParameterValueValid } from '../../utils/parameters'; const infoTypeLabel = 'This parameter is of type '; @@ -42,7 +42,7 @@ const SetEditor = (props) => { ).type === ParameterType.DOUBLE ? newValue.replace(',', '.') : newValue; - const updatedSet = _.cloneDeep(set); + const updatedSet = cloneDeep(set); updatedSet.parameters.find( (parameter) => parameter.name === parameterChanged ).value = newValueToUse; @@ -52,7 +52,7 @@ const SetEditor = (props) => { return ( {set.name} - {_.cloneDeep(filteredDefinitions) + {cloneDeep(filteredDefinitions) .sort((a, b) => valueOrigin(a.origin) - valueOrigin(b.origin)) .map((definition) => { const correspondingParameter = set.parameters.find( diff --git a/src/components/3-organisms/automaton/AutomatonProperties.tsx b/src/components/3-organisms/automaton/AutomatonProperties.tsx index 8f41b00..ecc2276 100644 --- a/src/components/3-organisms/automaton/AutomatonProperties.tsx +++ b/src/components/3-organisms/automaton/AutomatonProperties.tsx @@ -10,7 +10,7 @@ import { Divider, Grid, Typography } from '@mui/material'; import Autocomplete from '../../1-atoms/Autocomplete'; import { styles } from './AutomatonPropertiesStyle'; import { getPossibleOptionsForProperty } from '../../../utils/automata'; -import * as _ from 'lodash'; +import { isArray, join, map, split, trim } from 'lodash'; import { Automaton } from '../../../redux/types/mapping.type'; import { AutomationDefinition } from '../../../redux/types/model.type'; import { EquipmentValues } from '../../../redux/types/network.type'; @@ -43,8 +43,8 @@ const AutomatonProperties = ({ propertyType )( // convert an array to a string content with VALUE_DELIMITER - _.isArray(propertyValue) - ? _.join(propertyValue, VALUE_DELIMITER) + isArray(propertyValue) + ? join(propertyValue, VALUE_DELIMITER) : propertyValue ); }, @@ -62,10 +62,7 @@ const AutomatonProperties = ({ // convert a string content with VALUE_DELIMITER to an array const propertyValue = propertyDefinition.multiple - ? _.map( - _.split(property?.value, VALUE_DELIMITER), - _.trim - ) + ? map(split(property?.value, VALUE_DELIMITER), trim) : property?.value ?? ''; const options = diff --git a/src/components/3-organisms/hooks/useSetSearch.js b/src/components/3-organisms/hooks/useSetSearch.js index ab461cc..1a099f9 100644 --- a/src/components/3-organisms/hooks/useSetSearch.js +++ b/src/components/3-organisms/hooks/useSetSearch.js @@ -13,7 +13,7 @@ import { makeGetSearchSets, ModelSlice, } from '../../../redux/slices/Model'; -import _ from 'lodash'; +import { cloneDeep, find, forEach, reduce } from 'lodash'; import { useDispatch } from 'react-redux'; export default function useSetSearch(currentGroup, currentSet) { @@ -49,17 +49,17 @@ export default function useSetSearch(currentGroup, currentSet) { } const updatedSets = isAll - ? _.reduce( + ? reduce( currentGroup?.sets, - (acc, set) => [...acc, _.cloneDeep(set)], + (acc, set) => [...acc, cloneDeep(set)], [] ) - : [_.cloneDeep(currentSet)]; + : [cloneDeep(currentSet)]; // fill with values in the provided sets - _.forEach(updatedSets, (updatedSet) => { - _.forEach(updatedSet?.parameters, (parameter) => { - const templateParameter = _.find( + forEach(updatedSets, (updatedSet) => { + forEach(updatedSet?.parameters, (parameter) => { + const templateParameter = find( set?.parameters, (elem) => elem.name === parameter.name ); diff --git a/src/hooks/react-hook-form/form/useDataUpdate.ts b/src/hooks/react-hook-form/form/useDataUpdate.ts index 774d785..b8f8e31 100644 --- a/src/hooks/react-hook-form/form/useDataUpdate.ts +++ b/src/hooks/react-hook-form/form/useDataUpdate.ts @@ -7,7 +7,7 @@ import { useEffect } from 'react'; import { FieldErrors, FieldValues, UseFormReturn } from 'react-hook-form'; import { usePrevious } from '@gridsuite/commons-ui'; -import _ from 'lodash'; +import { isEqual } from 'lodash'; const useDataUpdate = ( formApi: UseFormReturn, @@ -18,7 +18,7 @@ const useDataUpdate = ( const prevFormData = usePrevious(formData); useEffect(() => { - if (!_.isEqual(prevFormData, formData)) { + if (!isEqual(prevFormData, formData)) { formApi.handleSubmit(onValid, onInvalid)(); } }, [formApi, onValid, onInvalid, formData, prevFormData]); diff --git a/src/redux/slices/Mapping.js b/src/redux/slices/Mapping.js index 7f02b88..0c5374c 100644 --- a/src/redux/slices/Mapping.js +++ b/src/redux/slices/Mapping.js @@ -11,7 +11,7 @@ import { createSlice, } from '@reduxjs/toolkit'; import * as mappingsAPI from '../../rest/mappingsAPI'; -import * as _ from 'lodash'; +import { cloneDeep, isEmpty, isEqual } from 'lodash'; import RequestStatus from '../../constants/RequestStatus'; import * as networkAPI from '../../rest/networkAPI'; import { AutomatonFamily } from '../../constants/automatonDefinition'; @@ -63,7 +63,7 @@ export const DEFAULT_NAME = 'default'; const ruleMatcher = (rule1) => (rule2) => rule1?.id === rule2?.id; const transformMapping = (receivedMapping) => { - const mapping = _.cloneDeep(receivedMapping); + const mapping = cloneDeep(receivedMapping); mapping.rules = mapping.rules.map((rule) => { rule['type'] = rule.equipmentType; delete rule.equipmentType; @@ -246,7 +246,7 @@ const checkFilterValidity = (filter, isLast) => { // only last rule allows empty filter return !!isLast; } - const isQueryExist = !_.isEmpty(filter.rules); + const isQueryExist = !isEmpty(filter.rules); const isQueryValid = isQueryExist && rqbQuerySchemaValidator(yup.object()).isValidSync(filter.rules); @@ -446,7 +446,7 @@ export const isModified = createSelector( ); function ignoreInternalProperties(rule) { - const ruleToTest = _.cloneDeep(rule); + const ruleToTest = cloneDeep(rule); delete ruleToTest.matches; // ignore matches which is used for matched equipment ids delete ruleToTest.filterDirty; // ignore the derived field @@ -466,12 +466,12 @@ export const isModified = createSelector( } return !( - _.isEqual( + isEqual( activeRules.map(ignoreInternalProperties), foundMapping.rules.map(ignoreInternalProperties) ) && - _.isEqual(activeAutomata, foundMapping.automata) && - _.isEqual(controlledParameters, foundMapping.controlledParameters) + isEqual(activeAutomata, foundMapping.automata) && + isEqual(controlledParameters, foundMapping.controlledParameters) ); } ); @@ -512,7 +512,7 @@ export const postMapping = createAsyncThunk( : state?.mappings.rules; const augmentedRules = rules.map((rule) => { - let augmentedRule = _.cloneDeep(rule); + let augmentedRule = cloneDeep(rule); augmentedRule.equipmentType = rule.type.toUpperCase(); if (augmentedRule.filter) { @@ -668,7 +668,7 @@ const reducers = { }, // Rule addRule: (state) => { - const newRule = _.cloneDeep(DEFAULT_RULE); + const newRule = cloneDeep(DEFAULT_RULE); // provide an id for new rule newRule.id = uuid4(); newRule.type = state.filteredRuleType; @@ -701,7 +701,7 @@ const reducers = { }, copyRule: (state, action) => { const { index } = action.payload; - const ruleToCopy = _.cloneDeep( + const ruleToCopy = cloneDeep( filterRulesByType(state.rules, state.filteredRuleType)[index] ); @@ -772,7 +772,7 @@ const reducers = { }, // Automaton addAutomaton: (state) => { - const newAutomaton = _.cloneDeep(DEFAULT_AUTOMATON); + const newAutomaton = cloneDeep(DEFAULT_AUTOMATON); newAutomaton.family = state.filteredAutomatonFamily; state.automata.push(newAutomaton); }, @@ -834,7 +834,7 @@ const reducers = { }, copyAutomaton: (state, action) => { const { index } = action.payload; - const automatonToCopy = _.cloneDeep( + const automatonToCopy = cloneDeep( filterAutomataByFamily( state.automata, state.filteredAutomatonFamily diff --git a/src/redux/slices/Model.js b/src/redux/slices/Model.js index 48b4bc5..6ea1bd1 100644 --- a/src/redux/slices/Model.js +++ b/src/redux/slices/Model.js @@ -12,7 +12,7 @@ import { } from '@reduxjs/toolkit'; import * as modelsAPI from '../../rest/modelsAPI'; import RequestStatus from '../../constants/RequestStatus'; -import * as _ from 'lodash'; +import { cloneDeep, findIndex, forEach, uniqBy } from 'lodash'; import { SetType } from '../../constants/models'; const DEFAULT_GROUP = { @@ -152,7 +152,7 @@ const reducers = { changeGroup: (state, action) => { const { group, originalGroup, modelName, isAbsolute, matches } = action.payload; - const currentGroup = _.cloneDeep(group); + const currentGroup = cloneDeep(group); const definitions = state.parameterDefinitions; currentGroup.modelName = modelName; if (originalGroup) { @@ -180,7 +180,7 @@ const reducers = { const newSets = matches .filter( (match) => - _.findIndex( + findIndex( currentGroup.sets, (set) => set.name === @@ -225,7 +225,7 @@ const reducers = { addOrModifySet: (state, action) => { const newSets = action.payload; - _.forEach(Array.isArray(newSets) ? newSets : [newSets], (newSet) => { + forEach(Array.isArray(newSets) ? newSets : [newSets], (newSet) => { const setIndex = state.currentGroup.sets.findIndex( (setToTest) => setToTest.name === newSet.name ); @@ -253,7 +253,7 @@ const extraReducers = (builder) => { builder.addCase(getModelSets.fulfilled, (state, action) => { const receivedSets = action.payload; - state.currentGroup.sets = _.uniqBy( + state.currentGroup.sets = uniqBy( receivedSets.concat(state.currentGroup.sets), 'name' ); @@ -262,7 +262,7 @@ const extraReducers = (builder) => { builder.addCase(getSearchedModelSets.fulfilled, (state, action) => { const candidateSets = action.payload; - state.currentGroup.searchSets = _.uniqBy(candidateSets, 'name'); + state.currentGroup.searchSets = uniqBy(candidateSets, 'name'); state.status = RequestStatus.SUCCESS; }); builder.addCase(postModelSetsGroup.fulfilled, (state, action) => { diff --git a/src/utils/functions.js b/src/utils/functions.js index 5b6a4a7..75ad437 100644 --- a/src/utils/functions.js +++ b/src/utils/functions.js @@ -5,9 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -import _ from 'lodash'; - -export const mergeSx = (...allSx) => allSx.flat(); +import { pick } from 'lodash'; /** * Copy properties from corresponding objects in a source array to objects in a target array. @@ -23,7 +21,7 @@ export const assignArray = (targetArray, sourceArray, matcher, ...props) => { targetArray?.forEach((targetObj) => { const matcherOfTarget = matcher(targetObj); const sourceObj = sourceArray?.find(matcherOfTarget); - const pickObj = _.pick(sourceObj, props); + const pickObj = pick(sourceObj, props); Object.assign(targetObj, pickObj); }); From e0b41acfb11a4e55aa59d606839ea4a79ce35eed Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Fri, 26 Jul 2024 00:49:10 +0200 Subject: [PATCH 4/7] clean unused functions --- src/utils/composition.js | 95 ------------------------ src/utils/{functions.js => functions.ts} | 14 +++- src/utils/properties.js | 22 ------ 3 files changed, 11 insertions(+), 120 deletions(-) delete mode 100644 src/utils/composition.js rename src/utils/{functions.js => functions.ts} (72%) delete mode 100644 src/utils/properties.js diff --git a/src/utils/composition.js b/src/utils/composition.js deleted file mode 100644 index a041e15..0000000 --- a/src/utils/composition.js +++ /dev/null @@ -1,95 +0,0 @@ -/** - * Copyright (c) 2021, 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/. - */ - -export function convertCompositionStringToArray(compositionString) { - // Transform parentheses into arrays - const step1 = compositionString - .split(/([()])/) - .map((x) => x.trim()) - .join(' ') - .replace(/\)\s\)/g, '))') - .replace(/\(/g, '[') - .replace(/\)\s/g, '], ') - .replace(/\)/g, ']'); - - // Wrap whole string in an array - const step2 = '[' + step1 + ']'; - - // Replace whitespace separators with commas and escape values - const step3 = step2 - .replace(/[^[\],\s]+/g, '"$&"') - .replace(/" /g, '", ') - .replace(/,[\s]+]/g, ']'); - - // Parse as a JSON array - const compositionArray = JSON.parse(step3); - - // Wrap Single filters in a group - return compositionArray.map((element) => { - if (!Array.isArray(element) && element !== '||' && element !== '&&') { - return [element]; - } - return element; - }); -} - -export function convertCompositionArrayToString(compositionArray) { - const compositionStringArray = compositionArray.map((element) => { - if (Array.isArray(element)) { - if (element.length === 1) { - return element[0]; - } else { - return `(${convertCompositionArrayToString(element)})`; - } - } - return element; - }); - return compositionStringArray.join(' '); -} - -export const checkCompositionArrayValidity = ( - compositionArray, - isInner = false -) => { - let arrayOperation; - return compositionArray - .map((compositionElement, index) => { - if (index % 2 === 0) { - if (Array.isArray(compositionElement)) { - return checkCompositionArrayValidity( - compositionElement, - true - ); - } - return /filter\d+\b/.test(compositionElement); - } - if (index === 1) { - arrayOperation = compositionElement; - } - return ( - /(&&|\|\|)/.test(compositionElement) && - (!isInner || compositionElement === arrayOperation) - ); - }) - .reduce((acc, element) => acc && element); -}; - -export function getMaxDepthParentheses(logicString) { - let count = 0; - let maxCount = 0; - Array.from(logicString).forEach((char) => { - if (char === '(') { - count++; - } else if (char === ')') { - count--; - } - if (count > maxCount) { - maxCount = count; - } - }); - return maxCount; -} diff --git a/src/utils/functions.js b/src/utils/functions.ts similarity index 72% rename from src/utils/functions.js rename to src/utils/functions.ts index 75ad437..90b401f 100644 --- a/src/utils/functions.js +++ b/src/utils/functions.ts @@ -7,9 +7,12 @@ import { pick } from 'lodash'; +type GetMatcher = (target: T) => Parameters['find']>[0]; +type PickProps = Array; + /** * Copy properties from corresponding objects in a source array to objects in a target array. - * It returns the target array that contain modified objects + * It returns the target array that contains modified objects * * @param targetArray the target array to copy to inside objects * @param sourceArray the source array from which to copy properties of objects @@ -17,7 +20,12 @@ import { pick } from 'lodash'; * @param props properties names to copy, specified individually or in array * @return the target array */ -export const assignArray = (targetArray, sourceArray, matcher, ...props) => { +export function assignArray( + targetArray: T[], + sourceArray: T[], + matcher: GetMatcher, + ...props: PickProps +) { targetArray?.forEach((targetObj) => { const matcherOfTarget = matcher(targetObj); const sourceObj = sourceArray?.find(matcherOfTarget); @@ -26,4 +34,4 @@ export const assignArray = (targetArray, sourceArray, matcher, ...props) => { }); return targetArray; -}; +} diff --git a/src/utils/properties.js b/src/utils/properties.js deleted file mode 100644 index 8b8d472..0000000 --- a/src/utils/properties.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Copyright (c) 2021, 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 { EquipmentProperties } from '../constants/equipmentDefinition'; - -export function getProperty(equipmentType, propertyName) { - return EquipmentProperties[equipmentType].find( - (property) => property.name === propertyName - ); -} - -export function getValuesOption(property) { - //TODO Intl - return property?.values?.map((value) => ({ - label: value, - value, - })); -} From e979bbfceb350f97bfd20bdf4aeadd50ac9380e6 Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Fri, 26 Jul 2024 02:29:59 +0200 Subject: [PATCH 5/7] migrate api service & dedup utils --- .env | 8 +- .env.development | 8 +- src/components/app.js | 50 ++++++---- src/react-app-env.d.ts | 10 ++ src/redux/slices/Mapping.js | 23 +++-- src/redux/slices/Model.js | 18 ++-- src/redux/slices/Network.js | 11 ++- src/redux/store.ts | 8 +- src/rest/mappingsAPI.js | 100 -------------------- src/rest/modelsAPI.js | 88 ------------------ src/rest/networkAPI.js | 76 --------------- src/rest/studyAPI.js | 30 ------ src/services/app-local.ts | 19 ++++ src/services/dynamic-mapping.ts | 151 ++++++++++++++++++++++++++++++ src/services/index.ts | 65 +++++++++++++ src/setupProxy.js | 4 +- src/utils/rest-api.js | 158 -------------------------------- 17 files changed, 324 insertions(+), 503 deletions(-) delete mode 100644 src/rest/mappingsAPI.js delete mode 100644 src/rest/modelsAPI.js delete mode 100644 src/rest/networkAPI.js delete mode 100644 src/rest/studyAPI.js create mode 100644 src/services/app-local.ts create mode 100644 src/services/dynamic-mapping.ts create mode 100644 src/services/index.ts delete mode 100644 src/utils/rest-api.js diff --git a/.env b/.env index fab96a8..bcbdc28 100644 --- a/.env +++ b/.env @@ -4,8 +4,8 @@ REACT_APP_NAME=GridDynaApp EXTEND_ESLINT=true -REACT_APP_API_PREFIX=api -REACT_APP_GATEWAY_PREFIX=/gateway -REACT_APP_URI=/dynamic-mapping-server REACT_APP_WS_GATEWAY=ws/gateway -REACT_APP_STUDY_URI=/study-server +REACT_APP_API_GATEWAY=api/gateway + +REACT_APP_API_PREFIX=api/gateway +REACT_APP_DYNAMAP_SVC=dynamic-mapping diff --git a/.env.development b/.env.development index 86192d9..8f03c67 100644 --- a/.env.development +++ b/.env.development @@ -2,8 +2,8 @@ REACT_APP_USE_AUTHENTICATION=false REACT_APP_NAME=GridDynaApp -REACT_APP_API_PREFIX=api -REACT_APP_GATEWAY_PREFIX=/gateway -REACT_APP_URI=/dynamic-mapping-server REACT_APP_WS_GATEWAY=ws/gateway -REACT_APP_STUDY_URI=/study-server +REACT_APP_API_GATEWAY=api/gateway + +REACT_APP_API_PREFIX=api +REACT_APP_DYNAMAP_SVC=dynamic-mapping-server diff --git a/src/components/app.js b/src/components/app.js index c3041e0..e29af71 100644 --- a/src/components/app.js +++ b/src/components/app.js @@ -34,15 +34,14 @@ import { import { FormattedMessage } from 'react-intl'; import { ReactComponent as PowsyblLogo } from '../images/powsybl_logo.svg'; import AppPackage from '../../package.json'; -import { - fetchAppsAndUrls, - fetchIdpSettings, - fetchValidateUser, - fetchVersion, -} from '../utils/rest-api'; -import { getServersInfos } from '../rest/studyAPI'; import { UserSlice } from '../redux/slices/User'; import RootContainer from '../containers/RootContainer'; +import { + appLocalSrv, + appsMetadataSrv, + studySrv, + userAdminSrv, +} from '../services'; const lightTheme = createTheme({ palette: { @@ -87,6 +86,11 @@ const App = () => { const navigate = useNavigate(); + const onLogoClick = useCallback( + () => navigate('/', { replace: true }), + [navigate] + ); + const dispatch = useDispatch(); const authenticationDispatch = useCallback( @@ -94,6 +98,11 @@ const App = () => { [dispatch] ); + const onLogoutClick = useCallback( + () => logout(authenticationDispatch, userManager.instance), + [authenticationDispatch, userManager.instance] + ); + const location = useLocation(); // Can't use lazy initializer because useMatch is a hook @@ -121,8 +130,8 @@ const App = () => { ? initializeAuthenticationProd( authenticationDispatch, initialMatchSilentRenewCallbackUrl != null, - fetchIdpSettings, - fetchValidateUser, + appLocalSrv.fetchIdpSettings, + userAdminSrv.fetchValidateUser, initialMatchSigninCallbackUrl != null ) : initializeAuthenticationDev( @@ -148,12 +157,21 @@ const App = () => { useEffect(() => { if (user !== null) { - fetchAppsAndUrls().then((res) => { + appsMetadataSrv.fetchAppsMetadata().then((res) => { setAppsAndUrls(res); }); } }, [user]); + const additionalModulesFetcher = useCallback( + () => studySrv.getServersInfos('dyna'), + [] + ); + const globalVersionFetcher = useCallback( + () => appsMetadataSrv.fetchVersion().then((res) => res?.deployVersion), + [] + ); + return ( @@ -165,16 +183,12 @@ const App = () => { appLogo={} appVersion={AppPackage.version} appLicense={AppPackage.license} - onLogoClick={() => navigate('/', { replace: true })} - onLogoutClick={() => - logout(authenticationDispatch, userManager.instance) - } + onLogoClick={onLogoClick} + onLogoutClick={onLogoutClick} user={user} appsAndUrls={appsAndUrls} - globalVersionPromise={() => - fetchVersion().then((res) => res?.deployVersion) - } - additionalModulesPromise={getServersInfos} + globalVersionPromise={globalVersionFetcher} + additionalModulesPromise={additionalModulesFetcher} /> {user !== null ? ( diff --git a/src/react-app-env.d.ts b/src/react-app-env.d.ts index 7b288b8..49bf58a 100644 --- a/src/react-app-env.d.ts +++ b/src/react-app-env.d.ts @@ -6,3 +6,13 @@ */ /// + +namespace NodeJS { + interface ProcessEnv { + REACT_APP_API_GATEWAY: string; + REACT_APP_WS_GATEWAY: string; + + REACT_APP_API_PREFIX: string; + REACT_APP_DYNAMAP_SVC: string; + } +} diff --git a/src/redux/slices/Mapping.js b/src/redux/slices/Mapping.js index 0c5374c..c862772 100644 --- a/src/redux/slices/Mapping.js +++ b/src/redux/slices/Mapping.js @@ -10,10 +10,8 @@ import { createSelector, createSlice, } from '@reduxjs/toolkit'; -import * as mappingsAPI from '../../rest/mappingsAPI'; import { cloneDeep, isEmpty, isEqual } from 'lodash'; import RequestStatus from '../../constants/RequestStatus'; -import * as networkAPI from '../../rest/networkAPI'; import { AutomatonFamily } from '../../constants/automatonDefinition'; import { RuleEquipmentTypes } from '../../constants/equipmentType'; import { @@ -27,6 +25,7 @@ import { import { v4 as uuid4 } from 'uuid'; import { enrichIdRqbQuery } from '../../utils/rqb-utils'; import { assignArray } from '../../utils/functions'; +import { dynamicMappingSrv } from '../../services'; const initialState = { mappings: [], @@ -555,7 +554,7 @@ export const postMapping = createAsyncThunk( )?.controlledParameters : state?.mappings.controlledParameters; - return await mappingsAPI.postMapping( + return await dynamicMappingSrv.postMapping( mappingName, augmentedRules, formattedAutomata, @@ -569,7 +568,7 @@ export const getMappings = createAsyncThunk( 'mappings/get', async (_arg, { getState }) => { const token = getState()?.user.user?.id_token; - return await mappingsAPI.getMappings(token); + return await dynamicMappingSrv.getMappings(token); } ); @@ -577,7 +576,7 @@ export const deleteMapping = createAsyncThunk( 'mappings/delete', async (mappingName, { getState }) => { const token = getState()?.user.user?.id_token; - return await mappingsAPI.deleteMapping(mappingName, token); + return await dynamicMappingSrv.deleteMapping(mappingName, token); } ); @@ -585,7 +584,11 @@ export const renameMapping = createAsyncThunk( 'mappings/rename', async ({ nameToReplace, newName }, { getState }) => { const token = getState()?.user.user?.id_token; - return await mappingsAPI.renameMapping(nameToReplace, newName, token); + return await dynamicMappingSrv.renameMapping( + nameToReplace, + newName, + token + ); } ); @@ -593,7 +596,11 @@ export const copyMapping = createAsyncThunk( 'mappings/copy', async ({ originalName, copyName }, { getState }) => { const token = getState()?.user.user?.id_token; - return await mappingsAPI.copyMapping(originalName, copyName, token); + return await dynamicMappingSrv.copyMapping( + originalName, + copyName, + token + ); } ); @@ -610,7 +617,7 @@ export const getNetworkMatchesFromRule = createAsyncThunk( equipmentType: foundRule.type, filter: augmentFilter(foundRule.filter, foundRule.type), }; - return await networkAPI.getNetworkMatchesFromRule( + return await dynamicMappingSrv.getNetworkMatchesFromRule( networkId, ruleToMatch, token diff --git a/src/redux/slices/Model.js b/src/redux/slices/Model.js index 6ea1bd1..8947760 100644 --- a/src/redux/slices/Model.js +++ b/src/redux/slices/Model.js @@ -10,10 +10,10 @@ import { createSelector, createSlice, } from '@reduxjs/toolkit'; -import * as modelsAPI from '../../rest/modelsAPI'; import RequestStatus from '../../constants/RequestStatus'; import { cloneDeep, findIndex, forEach, uniqBy } from 'lodash'; import { SetType } from '../../constants/models'; +import { dynamicMappingSrv } from '../../services'; const DEFAULT_GROUP = { name: '', @@ -74,7 +74,7 @@ export const getModels = createAsyncThunk( 'models/get', async (_arg, { getState }) => { const token = getState()?.user.user?.id_token; - return await modelsAPI.getModels(token); + return await dynamicMappingSrv.getModels(token); } ); @@ -82,7 +82,7 @@ export const getModelDefinitions = createAsyncThunk( 'models/definitions', async (modelName, { getState }) => { const token = getState()?.user.user?.id_token; - return await modelsAPI.getModelDefinitions(modelName, token); + return await dynamicMappingSrv.getModelDefinitions(modelName, token); } ); @@ -91,7 +91,7 @@ export const getModelSets = createAsyncThunk( async ({ modelName, groupName, groupType }, { getState }) => { if (groupName) { const token = getState()?.user.user?.id_token; - return await modelsAPI.getModelSets( + return await dynamicMappingSrv.getModelSets( modelName, groupName, groupType !== '' ? groupType : SetType.FIXED, @@ -108,7 +108,7 @@ export const getSearchedModelSets = createAsyncThunk( async ({ modelName, groupName, groupType }, { getState }) => { if (groupName) { const token = getState()?.user.user?.id_token; - return await modelsAPI.getModelSets( + return await dynamicMappingSrv.getModelSets( modelName, groupName, groupType ?? '', @@ -125,7 +125,11 @@ export const postModelSetsGroup = createAsyncThunk( async (strict, { getState }) => { const token = getState()?.user.user?.id_token; const setGroup = getState()?.models.currentGroup; - return await modelsAPI.postModelSetsGroup(setGroup, strict, token); + return await dynamicMappingSrv.postModelSetsGroup( + setGroup, + strict, + token + ); } ); @@ -133,7 +137,7 @@ export const getAutomatonDefinitions = createAsyncThunk( 'models/automaton/get/definitions', async (_arg, { getState }) => { const token = getState()?.user.user?.id_token; - return await modelsAPI.getAutomatonDefinitions(token); + return await dynamicMappingSrv.getAutomatonDefinitions(token); } ); diff --git a/src/redux/slices/Network.js b/src/redux/slices/Network.js index 51ee5ee..9e42418 100644 --- a/src/redux/slices/Network.js +++ b/src/redux/slices/Network.js @@ -11,9 +11,9 @@ import { createSlice, } from '@reduxjs/toolkit'; import RequestStatus from '../../constants/RequestStatus'; -import * as networkAPI from '../../rest/networkAPI'; import { createParameterSelector } from '../selectorUtil'; import { PropertyType } from '../../constants/equipmentType'; +import { dynamicMappingSrv } from '../../services'; const initialState = { propertyValues: [], @@ -73,7 +73,7 @@ export const getPropertyValuesFromFile = createAsyncThunk( 'network/getValuesFromFile', async (file, { getState }) => { const token = getState()?.user.user?.id_token; - return await networkAPI.getPropertyValuesFromFile(file, token); + return await dynamicMappingSrv.getPropertyValuesFromFile(file, token); } ); @@ -81,7 +81,10 @@ export const getPropertyValuesFromNetworkId = createAsyncThunk( 'network/getValuesFromId', async (networkId, { getState }) => { const token = getState()?.user.user?.id_token; - return await networkAPI.getPropertyValuesFromId(networkId, token); + return await dynamicMappingSrv.getPropertyValuesFromId( + networkId, + token + ); } ); @@ -89,7 +92,7 @@ export const getNetworkNames = createAsyncThunk( 'network/getNetworks', async (_args, { getState }) => { const token = getState()?.user.user?.id_token; - return await networkAPI.getNetworksName(token); + return await dynamicMappingSrv.getNetworksName(token); } ); diff --git a/src/redux/store.ts b/src/redux/store.ts index 6d6d03d..301cd34 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -10,7 +10,7 @@ import { reducer } from './reducer'; export const store = configureStore({ reducer }); export type AppDispatch = typeof store.dispatch; -initCommonServices( - process.env.REACT_APP_NAME!, - () => store.getState().user?.user -); + +export function getUser() { + return store.getState().user?.user; +} diff --git a/src/rest/mappingsAPI.js b/src/rest/mappingsAPI.js deleted file mode 100644 index d055180..0000000 --- a/src/rest/mappingsAPI.js +++ /dev/null @@ -1,100 +0,0 @@ -/** - * Copyright (c) 2021, 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 { backendFetchJson, backendFetchText } from '../utils/rest-api'; - -const API_URL = - process.env.REACT_APP_API_PREFIX + - (process.env.REACT_APP_USE_AUTHENTICATION === 'true' - ? process.env.REACT_APP_GATEWAY_PREFIX + '/dynamic-mapping' - : process.env.REACT_APP_URI) + - '/mappings'; - -export function postMapping( - mappingName, - rules, - automata, - controlledParameters, - token -) { - return backendFetchJson( - `${API_URL}/${mappingName}`, - { - method: 'POST', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - }, - cache: 'default', - body: JSON.stringify({ - name: mappingName, - rules, - automata, - controlledParameters, - }), - }, - token - ); -} - -export function getMappings(token) { - return backendFetchJson( - `${API_URL}/`, - { - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - }, - cache: 'default', - }, - token - ); -} - -export function deleteMapping(mappingName, token) { - return backendFetchText( - `${API_URL}/${mappingName}`, - { - method: 'DELETE', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - }, - cache: 'default', - }, - token - ); -} - -export async function renameMapping(nameToReplace, newName, token) { - return backendFetchJson( - `${API_URL}/rename/${nameToReplace}/to/${newName}`, - { - method: 'POST', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - }, - cache: 'default', - }, - token - ); -} - -export async function copyMapping(originalName, copyName, token) { - return backendFetchJson( - `${API_URL}/copy/${originalName}/to/${copyName}`, - { - method: 'POST', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - }, - cache: 'default', - }, - token - ); -} diff --git a/src/rest/modelsAPI.js b/src/rest/modelsAPI.js deleted file mode 100644 index 6db65fb..0000000 --- a/src/rest/modelsAPI.js +++ /dev/null @@ -1,88 +0,0 @@ -/** - * Copyright (c) 2021, 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 { backendFetchJson } from '../utils/rest-api'; - -const API_URL = - process.env.REACT_APP_API_PREFIX + - (process.env.REACT_APP_USE_AUTHENTICATION === 'true' - ? process.env.REACT_APP_GATEWAY_PREFIX + '/dynamic-mapping' - : process.env.REACT_APP_URI) + - '/models'; - -export function getModels(token) { - return backendFetchJson( - `${API_URL}/`, - { - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - }, - cache: 'default', - }, - token - ); -} - -export function getModelDefinitions(modelName, token) { - return backendFetchJson( - `${API_URL}/${modelName}/parameters/definitions`, - { - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - }, - cache: 'default', - }, - token - ); -} - -export function getModelSets(modelName, groupName, groupType, token) { - return backendFetchJson( - `${API_URL}/${modelName}/parameters/sets/${groupName}/${groupType}`, - { - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - }, - cache: 'default', - }, - token - ); -} - -export function postModelSetsGroup(setGroup, strict, token) { - return backendFetchJson( - `${API_URL}/${setGroup.modelName}/parameters/sets${ - strict ? '/strict' : '' - }`, - { - method: 'POST', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - }, - cache: 'default', - body: JSON.stringify(setGroup), - }, - token - ); -} - -export function getAutomatonDefinitions(token) { - return backendFetchJson( - `${API_URL}/automaton-definitions`, - { - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - }, - cache: 'default', - }, - token - ); -} diff --git a/src/rest/networkAPI.js b/src/rest/networkAPI.js deleted file mode 100644 index 2894f04..0000000 --- a/src/rest/networkAPI.js +++ /dev/null @@ -1,76 +0,0 @@ -/** - * Copyright (c) 2021, 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 { backendFetchJson } from '../utils/rest-api'; - -const API_URL = - process.env.REACT_APP_API_PREFIX + - (process.env.REACT_APP_USE_AUTHENTICATION === 'true' - ? process.env.REACT_APP_GATEWAY_PREFIX + '/dynamic-mapping' - : process.env.REACT_APP_URI) + - '/network'; - -export function getPropertyValuesFromFile(networkFile, token) { - const formData = new FormData(); - formData.append('file', networkFile); - - return backendFetchJson( - `${API_URL}/new`, - { - method: 'POST', - headers: { - Accept: 'application/json', - }, - cache: 'default', - body: formData, - }, - token - ); -} - -export function getPropertyValuesFromId(networkId, token) { - return backendFetchJson( - `${API_URL}/${networkId}/values`, - { - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - }, - cache: 'default', - }, - token - ); -} - -export function getNetworksName(token) { - return backendFetchJson( - `${API_URL}/`, - { - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - }, - cache: 'default', - }, - token - ); -} - -export function getNetworkMatchesFromRule(networkId, ruleToMatch, token) { - return backendFetchJson( - `${API_URL}/${networkId}/matches/rule`, - { - method: 'POST', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - }, - cache: 'default', - body: JSON.stringify(ruleToMatch), - }, - token - ); -} diff --git a/src/rest/studyAPI.js b/src/rest/studyAPI.js deleted file mode 100644 index 9d62af3..0000000 --- a/src/rest/studyAPI.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) 2023, 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 { backendFetchJson } from '../utils/rest-api'; - -const API_URL = - process.env.REACT_APP_API_PREFIX + - (process.env.REACT_APP_USE_AUTHENTICATION === 'true' - ? process.env.REACT_APP_GATEWAY_PREFIX + '/study/v1' - : process.env.REACT_APP_STUDY_URI + '/v1'); - -export function getServersInfos(token) { - return backendFetchJson( - `${API_URL}/servers/about?view=dyna`, - { - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - }, - cache: 'default', - }, - token - ).catch((reason) => { - console.error('Error while fetching the servers infos : ' + reason); - return reason; - }); -} diff --git a/src/services/app-local.ts b/src/services/app-local.ts new file mode 100644 index 0000000..52ef7bf --- /dev/null +++ b/src/services/app-local.ts @@ -0,0 +1,19 @@ +/* + * Copyright © 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 { AppLocalComSvc, Env } from '@gridsuite/commons-ui'; + +export type EnvJson = Env & typeof import('../../public/env.json'); + +export default class AppLocalSvc extends AppLocalComSvc { + public constructor() { + super(); + } + public async fetchEnv(): Promise { + return (await super.fetchEnv()) as EnvJson; + } +} diff --git a/src/services/dynamic-mapping.ts b/src/services/dynamic-mapping.ts new file mode 100644 index 0000000..df333b5 --- /dev/null +++ b/src/services/dynamic-mapping.ts @@ -0,0 +1,151 @@ +/* + * Copyright © 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 { ApiService } from '@gridsuite/commons-ui'; +import { getUser } from '../redux/store'; +import { UUID } from 'crypto'; + +export default class DynamicMappingSvc extends ApiService { + public constructor() { + super( + getUser, + process.env.REACT_APP_DYNAMAP_SVC, + // If you want to use user-admin-server in dev mode you must avoid passing through gateway + // and use the user-admin-server directly. SetupProxy should allow this. + // @ts-expect-error url type incompatibility + process.env.REACT_APP_API_PREFIX + ); + } + + public async postMapping( + mappingName: string, + rules: unknown, + automata: unknown, + controlledParameters: boolean + ) { + return await this.backendFetchJson( + `${this.getPrefix(1)}/mappings/${mappingName}`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + name: mappingName, + rules, + automata, + controlledParameters, + }), + } + ); + } + + public async getMappings() { + return await this.backendFetchJson(`${this.getPrefix(1)}/mappings/`); + } + + public async deleteMapping(mappingName: string) { + return await this.backendFetchText( + `${this.getPrefix(1)}/mappings/${mappingName}`, + 'DELETE' + ); + } + + public async renameMapping(nameToReplace: string, newName: string) { + return await this.backendFetchJson( + `${this.getPrefix( + 1 + )}/mappings/rename/${nameToReplace}/to/${newName}`, + 'POST' + ); + } + + public async copyMapping(originalName: string, copyName: string) { + return await this.backendFetchJson( + `${this.getPrefix(1)}/mappings/copy/${originalName}/to/${copyName}`, + 'POST' + ); + } + + public async getPropertyValuesFromFile(networkFile: string | Blob) { + const formData = new FormData(); + formData.append('file', networkFile); + return await this.backendFetchJson(`${this.getPrefix(1)}/network/new`, { + method: 'POST', + body: formData, + }); + } + + public async getPropertyValuesFromId(networkId: UUID) { + return await this.backendFetchJson( + `${this.getPrefix(1)}/network/${networkId}/values` + ); + } + + public async getNetworksName() { + return await this.backendFetchJson(`${this.getPrefix(1)}/network/`); + } + + public async getNetworkMatchesFromRule( + networkId: UUID, + ruleToMatch: unknown + ) { + return await this.backendFetchJson( + `${this.getPrefix(1)}/network/${networkId}/matches/rule`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(ruleToMatch), + } + ); + } + + public async getModels() { + return this.backendFetchJson(`${this.getPrefix(1)}/models/`); + } + + public async getModelDefinitions(modelName: string) { + return await this.backendFetchJson( + `${this.getPrefix(1)}/models/${modelName}/parameters/definitions` + ); + } + + public async getModelSets( + modelName: string, + groupName: string, + groupType: unknown + ) { + return await this.backendFetchJson( + `${this.getPrefix( + 1 + )}/models/${modelName}/parameters/sets/${groupName}/${groupType}` + ); + } + + public async postModelSetsGroup(setGroup: any, strict: boolean) { + return await this.backendFetchJson( + `${this.getPrefix(1)}/models/${setGroup.modelName}/parameters/sets${ + strict ? '/strict' : '' + }`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(setGroup), + } + ); + } + + public async getAutomatonDefinitions() { + return await this.backendFetchJson( + `${this.getPrefix(1)}/models/automaton-definitions` + ); + } +} diff --git a/src/services/index.ts b/src/services/index.ts new file mode 100644 index 0000000..bf79cda --- /dev/null +++ b/src/services/index.ts @@ -0,0 +1,65 @@ +/* + * Copyright © 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 { getUser } from '../redux/store'; +import { + AppsMetadataComSvc, + ConfigComSvc, + ConfigNotificationComSvc, + DirectoryComSvc, + ExploreComSvc, + setCommonServices, + StudyComSvc, + UserAdminComSvc, +} from '@gridsuite/commons-ui'; +import AppLocalSvc from './app-local'; +import DynamicMappingSvc from './dynamic-mapping'; + +export type { EnvJson } from './app-local'; + +// If you want to use user-admin-server in dev mode you must avoid passing through gateway +// and use the user-admin-server directly. SetupProxy should allow this. + +export const appLocalSrv = new AppLocalSvc(), + appsMetadataSrv = new AppsMetadataComSvc(appLocalSrv), + configSrv = new ConfigComSvc( + process.env.REACT_APP_NAME!, + getUser, + // @ts-expect-error url type incompatibility + process.env.REACT_APP_API_GATEWAY + ), + configNotificationSrv = new ConfigNotificationComSvc( + getUser, + // @ts-expect-error url type incompatibility + process.env.REACT_APP_WS_GATEWAY + ), + directorySrv = new DirectoryComSvc( + getUser, + // @ts-expect-error url type incompatibility + process.env.REACT_APP_API_GATEWAY + ), + // @ts-expect-error url type incompatibility + exploreSrv = new ExploreComSvc(getUser, process.env.REACT_APP_API_GATEWAY), + // @ts-expect-error url type incompatibility + studySrv = new StudyComSvc(getUser, process.env.REACT_APP_API_PREFIX), + userAdminSrv = new UserAdminComSvc( + getUser, + // @ts-expect-error url type incompatibility + process.env.REACT_APP_API_GATEWAY + ), + dynamicMappingSrv = new DynamicMappingSvc(); + +setCommonServices( + appLocalSrv, + appsMetadataSrv, + configSrv, + configNotificationSrv, + directorySrv, + exploreSrv, + studySrv, + userAdminSrv +); diff --git a/src/setupProxy.js b/src/setupProxy.js index ceed83e..356233c 100644 --- a/src/setupProxy.js +++ b/src/setupProxy.js @@ -27,8 +27,8 @@ module.exports = function (app) { ) ); app.use( - createProxyMiddleware('http://localhost:5001/api/study-server', { - pathRewrite: { '^/api/study-server/': '/' }, + createProxyMiddleware('http://localhost:5001/api/study', { + pathRewrite: { '^/api/study/': '/' }, }) ); }; diff --git a/src/utils/rest-api.js b/src/utils/rest-api.js deleted file mode 100644 index 1157f8d..0000000 --- a/src/utils/rest-api.js +++ /dev/null @@ -1,158 +0,0 @@ -/** - * Copyright (c) 2020, 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 { store } from '../redux/store'; -const PREFIX_USER_ADMIN_SERVER_QUERIES = - process.env.REACT_APP_API_PREFIX + - process.env.REACT_APP_GATEWAY_PREFIX + - '/user-admin'; - -// If you want to use user-admin-server in dev mode you must avoid passing through gateway -// and use the user-admin-server directly. SetupProxy should allow this. -// const PREFIX_USER_ADMIN_SERVER_QUERIES = -// process.env.REACT_APP_API_PREFIX + -// (process.env.REACT_APP_USE_AUTHENTICATION === 'true' -// ? process.env.REACT_APP_API_GATEWAY + '/user-admin' -// : process.env.REACT_APP_USER_ADMIN_URI); - -function getToken() { - const state = store.getState(); - return state.user.id_token; -} - -function parseError(text) { - try { - return JSON.parse(text); - } catch (err) { - return null; - } -} - -function handleError(response) { - return response.text().then((text) => { - const errorName = 'HttpResponseError : '; - let error; - const errorJson = parseError(text); - if ( - errorJson && - errorJson.status && - errorJson.error && - errorJson.message - ) { - error = new Error( - errorName + - errorJson.status + - ' ' + - errorJson.error + - ', message : ' + - errorJson.message - ); - error.status = errorJson.status; - } else { - error = new Error( - errorName + response.status + ' ' + response.statusText - ); - error.status = response.status; - } - throw error; - }); -} - -function prepareRequest(init, token) { - if (!(typeof init == 'undefined' || typeof init == 'object')) { - throw new TypeError( - 'Argument 2 of backendFetch is not an object' + typeof init - ); - } - const initCopy = Object.assign({}, init); - initCopy.headers = new Headers(initCopy.headers || {}); - const tokenCopy = token ? token : getToken(); - initCopy.headers.append('Authorization', 'Bearer ' + tokenCopy); - return initCopy; -} - -function safeFetch(url, initCopy) { - return fetch(url, initCopy).then((response) => - response.ok ? response : handleError(response) - ); -} - -export function backendFetch(url, init, token) { - const initCopy = prepareRequest(init, token); - return safeFetch(url, initCopy); -} - -export function backendFetchText(url, init, token) { - const initCopy = prepareRequest(init, token); - return safeFetch(url, initCopy).then((safeResponse) => safeResponse.text()); -} - -export function backendFetchJson(url, init, token) { - const initCopy = prepareRequest(init, token); - return safeFetch(url, initCopy).then((safeResponse) => safeResponse.json()); -} - -export function fetchValidateUser(user) { - const sub = user?.profile?.sub; - if (!sub) { - return Promise.reject( - new Error( - 'Error : Fetching access for missing user.profile.sub : ' + user - ) - ); - } - - console.info(`Fetching access for user...`); - const CheckAccessUrl = - PREFIX_USER_ADMIN_SERVER_QUERIES + `/v1/users/${sub}`; - console.debug(CheckAccessUrl); - - return backendFetch( - CheckAccessUrl, - { - method: 'head', - }, - user?.id_token - ) - .then((response) => { - //if the response is ok, the responseCode will be either 200 or 204 otherwise it's a Http error and it will be caught - return response.status === 200; - }) - .catch((error) => { - if (error.status === 403) { - return false; - } else { - throw error; - } - }); -} - -function fetchEnv() { - return fetch('env.json').then((res) => res.json()); -} - -export function fetchIdpSettings() { - return fetch('idpSettings.json').then((res) => res.json()); -} - -export function fetchAppsAndUrls() { - console.info(`Fetching apps and urls...`); - return fetchEnv() - .then((env) => fetch(env.appsMetadataServerUrl + '/apps-metadata.json')) - .then((response) => response.json()); -} - -export function fetchVersion() { - console.info(`Fetching global metadata...`); - return fetchEnv() - .then((env) => fetch(env.appsMetadataServerUrl + '/version.json')) - .then((response) => response.json()) - .catch((reason) => { - console.error('Error while fetching the version : ' + reason); - return reason; - }); -} From a49ea219f2c226e34a677aefe9bdea227979f61c Mon Sep 17 00:00:00 2001 From: Tristan Chuine Date: Fri, 9 Aug 2024 08:48:33 +0200 Subject: [PATCH 6/7] pick 120 --- .prettierrc.json | 1 + README.md | 4 +- license-checker-config.json | 2 +- src/__mocks__/svgrMock.js | 4 +- src/components/1-atoms/Autocomplete.jsx | 33 +- src/components/1-atoms/AutocompleteStyles.js | 4 +- src/components/1-atoms/buttons/NewButton.jsx | 8 +- src/components/1-atoms/buttons/index.jsx | 58 +-- src/components/2-molecules/AttachDialog.jsx | 16 +- src/components/2-molecules/Header.jsx | 23 +- src/components/2-molecules/ModelSelect.jsx | 7 +- src/components/2-molecules/NavigationMenu.jsx | 28 +- src/components/2-molecules/RenameDialog.jsx | 15 +- src/components/2-molecules/SetGroupSelect.tsx | 51 +- src/components/2-molecules/Stepper.jsx | 18 +- .../2-molecules/VerticalStepper.jsx | 14 +- src/components/3-organisms/Automaton.jsx | 62 +-- src/components/3-organisms/Filter.jsx | 36 +- src/components/3-organisms/FiltersGroup.jsx | 21 +- src/components/3-organisms/Rule.jsx | 88 +--- src/components/3-organisms/SetEditor.jsx | 49 +- src/components/3-organisms/SetGroupEditor.jsx | 9 +- src/components/3-organisms/SetSearch.jsx | 64 +-- .../automaton/AutomatonProperties.tsx | 83 +-- .../3-organisms/hooks/useSetSearch.js | 14 +- src/components/4-templates/PageTemplate.jsx | 7 +- src/components/app.js | 80 +-- src/constants/equipmentType.ts | 6 +- src/constants/operands.js | 7 +- src/containers/AutomatonContainer.jsx | 41 +- src/containers/FilterContainer.jsx | 17 +- src/containers/MappingContainer.jsx | 54 +- src/containers/MenuContainer.jsx | 38 +- src/containers/ParametersContainer.jsx | 88 +--- src/containers/RuleContainer.jsx | 15 +- src/hooks/react-hook-form/form/useFormInit.ts | 6 +- src/index.css | 12 +- src/plugins/README.md | 8 +- src/plugins/translations/en.json | 3 +- src/plugins/translations/fr.json | 3 +- src/redux/slices/Mapping.js | 493 ++++++------------ src/redux/slices/Model.js | 112 ++-- src/redux/slices/Network.js | 93 +--- src/redux/slices/Theme.ts | 13 +- src/redux/slices/User.ts | 46 +- src/services/dynamic-mapping.ts | 96 ++-- src/setupProxy.js | 9 +- src/translations/en.json | 2 +- src/translations/fr.json | 2 +- src/utils/automata.ts | 4 +- src/utils/optionsBuilders.js | 7 +- src/utils/parameters.js | 14 +- src/utils/rqb-utils.ts | 8 +- 53 files changed, 504 insertions(+), 1492 deletions(-) diff --git a/.prettierrc.json b/.prettierrc.json index 27512b6..fda48c3 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -1,5 +1,6 @@ { "trailingComma": "es5", "tabWidth": 4, + "printWidth": 120, "singleQuote": true } diff --git a/README.md b/README.md index daa7788..8e5baea 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ Selectors are the functions called by the Containers to retrieve the data needed derived data should be obtained from a selector. A selector has for argument the state of the slice. It is possible to add other arguments to selector by using -`React.useMemo` and `RTK.createSelector` to customise the fetched data. `RTK.createSelector can also be used to combine +`React.useMemo` and `RTK.createSelector` to customise the fetched data. `RTK.createSelector can also be used to combine reducers to create a more complex one. _There is no inherent reason to not have Selectors fetching data from separate slices, however, in most cases, it is @@ -107,7 +107,7 @@ To check dependencies license compatibility with this project one locally, pleas npm run licenses-check ``` -Notes : +Notes : * Check [license-checker-config.json](license-checker-config.json) for license white list and exclusion. If you need to update this list, please inform organization's owners. * Excluded dependencies : diff --git a/license-checker-config.json b/license-checker-config.json index 94edbfb..8f50cca 100644 --- a/license-checker-config.json +++ b/license-checker-config.json @@ -1,5 +1,5 @@ { - "onlyAllow" : [ + "onlyAllow": [ "MPL-2.0", "MIT", "BSD-3-Clause", diff --git a/src/__mocks__/svgrMock.js b/src/__mocks__/svgrMock.js index 2e01553..2eecbf2 100644 --- a/src/__mocks__/svgrMock.js +++ b/src/__mocks__/svgrMock.js @@ -7,9 +7,7 @@ import React from 'react'; -const SvgrMock = React.forwardRef((props, ref) => ( - -)); +const SvgrMock = React.forwardRef((props, ref) => ); export const ReactComponent = SvgrMock; export default SvgrMock; diff --git a/src/components/1-atoms/Autocomplete.jsx b/src/components/1-atoms/Autocomplete.jsx index 9cf903b..f2273b1 100644 --- a/src/components/1-atoms/Autocomplete.jsx +++ b/src/components/1-atoms/Autocomplete.jsx @@ -7,11 +7,7 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'; import PropTypes from 'prop-types'; -import { - Autocomplete as MuiAutocomplete, - Popper, - TextField, -} from '@mui/material'; +import { Autocomplete as MuiAutocomplete, Popper, TextField } from '@mui/material'; import { styles } from './AutocompleteStyles'; const PRECISION = 10e-8; @@ -62,9 +58,7 @@ const Autocomplete = (props) => { }, [options, value, isMultiple, matchMultipleOptions] ); - const [inputValue, setInputValue] = useState( - isMultiple ? '' : value?.toString() ?? '' - ); + const [inputValue, setInputValue] = useState(isMultiple ? '' : value?.toString() ?? ''); const sxStyles = styles({ inputLength: fixedWidth ? undefined : inputValue.length, @@ -163,31 +157,16 @@ const Autocomplete = (props) => { autoHighlight={!isFree} renderOption={renderOption} sx={sxStyles.inputWidth} - renderInput={(params) => ( - - )} - isOptionEqualToValue={(option, value) => - option.value === value.value - } - PopperComponent={(props) => ( - - )} + renderInput={(params) => } + isOptionEqualToValue={(option, value) => option.value === value.value} + PopperComponent={(props) => } {...rest} /> ); }; Autocomplete.propTypes = { - value: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - PropTypes.bool, - PropTypes.array, - ]).isRequired, + value: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool, PropTypes.array]).isRequired, isFree: PropTypes.bool, isMultiple: PropTypes.bool, onChange: PropTypes.func, diff --git a/src/components/1-atoms/AutocompleteStyles.js b/src/components/1-atoms/AutocompleteStyles.js index 280bf9d..5e74403 100644 --- a/src/components/1-atoms/AutocompleteStyles.js +++ b/src/components/1-atoms/AutocompleteStyles.js @@ -10,8 +10,6 @@ const MINIMUM_WIDTH = '150px'; export const styles = ({ inputLength }) => ({ inputWidth: { minWidth: MINIMUM_WIDTH, - width: inputLength - ? `calc(${inputLength} * ${FONT_SIZE} * 16px)` - : 'auto', + width: inputLength ? `calc(${inputLength} * ${FONT_SIZE} * 16px)` : 'auto', }, }); diff --git a/src/components/1-atoms/buttons/NewButton.jsx b/src/components/1-atoms/buttons/NewButton.jsx index 4465e03..adef9fe 100644 --- a/src/components/1-atoms/buttons/NewButton.jsx +++ b/src/components/1-atoms/buttons/NewButton.jsx @@ -12,13 +12,7 @@ import AddRoundedIcon from '@mui/icons-material/AddRounded'; const NewButton = ({ onClick, sx, disabled, tooltip }) => ( - diff --git a/src/components/1-atoms/buttons/index.jsx b/src/components/1-atoms/buttons/index.jsx index aeb99bb..b05011e 100644 --- a/src/components/1-atoms/buttons/index.jsx +++ b/src/components/1-atoms/buttons/index.jsx @@ -19,43 +19,21 @@ import DoneIcon from '@mui/icons-material/Done'; import DoneAllIcon from '@mui/icons-material/DoneAll'; import SaveAsIcon from '@mui/icons-material/SaveAs'; -export const AddIconButton = (props) => ( - } {...props} /> -); - -export const ConvertButton = (props) => ( - } {...props} /> -); - -export const SaveButton = (props) => ( - } {...props} /> -); - -export const DeleteButton = (props) => ( - } {...props} /> -); - -export const CopyButton = (props) => ( - } {...props} /> -); - -export const AttachButton = (props) => ( - } {...props} /> -); - -export const ChangeButton = (props) => ( - } {...props} /> -); - -export const ResetButton = (props) => ( - } {...props} /> -); -export const ApplyOneButton = (props) => ( - } {...props} /> -); -export const ApplyAllButton = (props) => ( - } {...props} /> -); -export const EditButton = (props) => ( - } {...props} /> -); +export const AddIconButton = (props) => } {...props} />; + +export const ConvertButton = (props) => } {...props} />; + +export const SaveButton = (props) => } {...props} />; + +export const DeleteButton = (props) => } {...props} />; + +export const CopyButton = (props) => } {...props} />; + +export const AttachButton = (props) => } {...props} />; + +export const ChangeButton = (props) => } {...props} />; + +export const ResetButton = (props) => } {...props} />; +export const ApplyOneButton = (props) => } {...props} />; +export const ApplyAllButton = (props) => } {...props} />; +export const EditButton = (props) => } {...props} />; diff --git a/src/components/2-molecules/AttachDialog.jsx b/src/components/2-molecules/AttachDialog.jsx index d87b77a..0deef07 100644 --- a/src/components/2-molecules/AttachDialog.jsx +++ b/src/components/2-molecules/AttachDialog.jsx @@ -46,11 +46,7 @@ const AttachDialog = (props) => { }; return ( - + Attach a Network @@ -83,16 +79,10 @@ const AttachDialog = (props) => { )} {attachWithFile && ( - - Attach a new network using the iidm: - + Attach a new network using the iidm: - onChangeFile(e)} - /> + onChangeFile(e)} /> @@ -40,9 +30,7 @@ const Stepper = (props) => { nextButton={