From 17ba0e63b0b7099d454c4e737171a65fdfdd75cf Mon Sep 17 00:00:00 2001 From: Sergio Betanzos Date: Fri, 11 Sep 2020 14:32:56 +0200 Subject: [PATCH] F #3951: Add stepper role form (#208) --- src/fireedge/jsconfig.json | 4 +- src/fireedge/package.json | 3 +- src/fireedge/src/public/actions/pool.js | 4 +- .../public/components/Cards/ClusterCard.js | 4 +- .../public/components/Cards/NetworkCard.js | 4 +- .../public/components/Dialogs/DialogForm.js | 83 +++++++ .../components/Dialogs/NetworkDialog.js | 234 ------------------ .../public/components/Dialogs/RoleDialog.js | 96 ------- .../src/public/components/Dialogs/index.js | 5 +- .../public/components/Flows/FlowWithFAB.js | 101 ++++++++ .../{FormDialog.js => FormList.js} | 84 ++----- .../components/FormStepper/FormListSelect.js | 4 +- .../public/components/FormStepper/FormStep.js | 36 ++- .../components/FormStepper/MobileStepper.js | 13 +- .../public/components/FormStepper/Stepper.js | 27 +- .../public/components/Forms/FormWithSchema.js | 27 +- .../src/public/components/List/ListCards.js | 70 ++++++ .../Create/Steps/BasicConfiguration/index.js | 22 ++ .../{ => Steps/BasicConfiguration}/schema.js | 37 ++- .../Create/Steps/Clusters/index.js | 29 +++ .../Create/Steps/Clusters/schema.js | 9 + .../Create/Steps/Networks/index.js | 52 ++++ .../Create/Steps/Networks/schema.js | 110 ++++++++ .../Roles/Steps/BasicConfiguration/index.js | 22 ++ .../Roles/Steps/BasicConfiguration/schema.js | 31 +++ .../Steps/Roles/Steps/Template/index.js | 19 ++ .../Steps/Roles/Steps/Template/schema.js | 21 ++ .../Create/Steps/Roles/Steps/index.js | 25 ++ .../Application/Create/Steps/Roles/index.js | 54 ++++ .../Application/Create/Steps/index.js | 28 +++ .../containers/Application/Create/index.js | 9 +- .../containers/Application/Create/steps.js | 148 ----------- .../src/public/hooks/useOpennebula.js | 11 + .../src/public/reducers/opennebula.js | 2 +- src/fireedge/src/public/services/pool.js | 16 ++ src/fireedge/src/public/utils/helpers.js | 9 + 36 files changed, 854 insertions(+), 599 deletions(-) create mode 100644 src/fireedge/src/public/components/Dialogs/DialogForm.js delete mode 100644 src/fireedge/src/public/components/Dialogs/NetworkDialog.js delete mode 100644 src/fireedge/src/public/components/Dialogs/RoleDialog.js create mode 100644 src/fireedge/src/public/components/Flows/FlowWithFAB.js rename src/fireedge/src/public/components/FormStepper/{FormDialog.js => FormList.js} (50%) create mode 100644 src/fireedge/src/public/components/List/ListCards.js create mode 100644 src/fireedge/src/public/containers/Application/Create/Steps/BasicConfiguration/index.js rename src/fireedge/src/public/containers/Application/Create/{ => Steps/BasicConfiguration}/schema.js (51%) create mode 100644 src/fireedge/src/public/containers/Application/Create/Steps/Clusters/index.js create mode 100644 src/fireedge/src/public/containers/Application/Create/Steps/Clusters/schema.js create mode 100644 src/fireedge/src/public/containers/Application/Create/Steps/Networks/index.js create mode 100644 src/fireedge/src/public/containers/Application/Create/Steps/Networks/schema.js create mode 100644 src/fireedge/src/public/containers/Application/Create/Steps/Roles/Steps/BasicConfiguration/index.js create mode 100644 src/fireedge/src/public/containers/Application/Create/Steps/Roles/Steps/BasicConfiguration/schema.js create mode 100644 src/fireedge/src/public/containers/Application/Create/Steps/Roles/Steps/Template/index.js create mode 100644 src/fireedge/src/public/containers/Application/Create/Steps/Roles/Steps/Template/schema.js create mode 100644 src/fireedge/src/public/containers/Application/Create/Steps/Roles/Steps/index.js create mode 100644 src/fireedge/src/public/containers/Application/Create/Steps/Roles/index.js create mode 100644 src/fireedge/src/public/containers/Application/Create/Steps/index.js delete mode 100644 src/fireedge/src/public/containers/Application/Create/steps.js diff --git a/src/fireedge/jsconfig.json b/src/fireedge/jsconfig.json index 1af04c46bb..295dda0d43 100644 --- a/src/fireedge/jsconfig.json +++ b/src/fireedge/jsconfig.json @@ -5,5 +5,7 @@ "client/*": ["public/*"], "server/*": ["*"] } - } + }, + "include": ["./src/*"], + "exclude": ["node_modules"] } \ No newline at end of file diff --git a/src/fireedge/package.json b/src/fireedge/package.json index 0c17b1e941..d0cb278fc9 100644 --- a/src/fireedge/package.json +++ b/src/fireedge/package.json @@ -8,7 +8,7 @@ "build-node": "webpack --mode=production --env.node --env.ssr", "build-front": "npm run copy_static_assets && concurrently \"webpack --mode=production --env.front\"", "dev": "npm run copy_static_assets && concurrently \"nodemon --inspect dist\" \"webpack --mode=development --env.node --env.front --env.ssr --env.hotreload --watch\"", - "dev-front": "npm run copy_static_assets && concurrently \"nodemon --inspect dist\" \"webpack --mode=development --env.node --env.hotreload\" \"webpack --mode=development --env.front --env.hotreload --watch\"" , + "dev-front": "npm run copy_static_assets && concurrently \"nodemon --inspect dist\" \"webpack --mode=development --env.node --env.hotreload\" \"webpack --mode=development --env.front --env.hotreload --watch\"", "start": "node dist/index", "cypress:open": "cypress open", "cypress:run": "cypress run --headless --browser chrome --spec \"cypress/integration/**/*.spec.js\"", @@ -58,6 +58,7 @@ "react": "^16.8.6", "react-ace": "^9.1.1", "react-dom": "^16.8.6", + "react-flow-renderer": "^5.7.1", "react-hook-form": "^6.0.0", "react-json-pretty": "^2.2.0", "react-redux": "^7.2.0", diff --git a/src/fireedge/src/public/actions/pool.js b/src/fireedge/src/public/actions/pool.js index b4bc73bd55..ae3c7b23e8 100644 --- a/src/fireedge/src/public/actions/pool.js +++ b/src/fireedge/src/public/actions/pool.js @@ -42,9 +42,9 @@ module.exports = { type: SUCCESS_ONE_REQUEST, payload: { files } }), - setMarketplaces: marketPlaces => ({ + setMarketplaces: marketplaces => ({ type: SUCCESS_ONE_REQUEST, - payload: { marketPlaces } + payload: { marketplaces } }), setApps: apps => ({ type: SUCCESS_ONE_REQUEST, diff --git a/src/fireedge/src/public/components/Cards/ClusterCard.js b/src/fireedge/src/public/components/Cards/ClusterCard.js index 7d31f4c3c9..b75170eaf6 100644 --- a/src/fireedge/src/public/components/Cards/ClusterCard.js +++ b/src/fireedge/src/public/components/Cards/ClusterCard.js @@ -57,9 +57,9 @@ const useStyles = makeStyles(theme => ({ })); const ClusterCard = React.memo( - ({ info, isSelected, handleSelect, handleUnselect }) => { + ({ value, isSelected, handleSelect, handleUnselect }) => { const classes = useStyles(); - const { ID, NAME, HOSTS, VNETS, DATASTORES } = info; + const { ID, NAME, HOSTS, VNETS, DATASTORES } = value; const hosts = [HOSTS?.ID ?? []].flat(); const vnets = [VNETS?.ID ?? []].flat(); diff --git a/src/fireedge/src/public/components/Cards/NetworkCard.js b/src/fireedge/src/public/components/Cards/NetworkCard.js index 00e8c320ec..0d7018e140 100644 --- a/src/fireedge/src/public/components/Cards/NetworkCard.js +++ b/src/fireedge/src/public/components/Cards/NetworkCard.js @@ -36,9 +36,9 @@ const useStyles = makeStyles(theme => ({ })); const NetworkCard = React.memo( - ({ info, handleEdit, handleClone, handleRemove }) => { + ({ value, handleEdit, handleClone, handleRemove }) => { const classes = useStyles(); - const { mandatory, name, description, type, id, extra } = info; + const { mandatory, name, description, type, id, extra } = value; return ( diff --git a/src/fireedge/src/public/components/Dialogs/DialogForm.js b/src/fireedge/src/public/components/Dialogs/DialogForm.js new file mode 100644 index 0000000000..e1088e0642 --- /dev/null +++ b/src/fireedge/src/public/components/Dialogs/DialogForm.js @@ -0,0 +1,83 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +import { + useMediaQuery, + Button, + Dialog, + DialogTitle, + DialogContent, + DialogActions +} from '@material-ui/core'; +import { useForm, FormProvider } from 'react-hook-form'; +import { yupResolver } from '@hookform/resolvers'; + +import { Tr } from 'client/components/HOC'; + +const DialogForm = React.memo( + ({ open, title, values, resolver, onSubmit, onCancel, children }) => { + const isMobile = useMediaQuery(theme => theme.breakpoints.only('xs')); + + const { handleSubmit, ...methods } = useForm({ + reValidateMode: 'onSubmit', + defaultValues: values, + resolver: yupResolver(resolver) + }); + + return ( + + {title} + + {children} + + + + + + + ); + } +); + +DialogForm.propTypes = { + open: PropTypes.bool.isRequired, + title: PropTypes.string.isRequired, + values: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.any), + PropTypes.objectOf(PropTypes.any) + ]), + resolver: PropTypes.oneOfType([PropTypes.func, PropTypes.object]).isRequired, + onSubmit: PropTypes.func, + onCancel: PropTypes.func, + children: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.node), + PropTypes.node + ]) +}; + +DialogForm.defaultProps = { + open: true, + title: 'Title dialog form', + values: {}, + resolver: {}, + onSubmit: () => undefined, + onCancel: () => undefined, + children: null +}; + +export default DialogForm; diff --git a/src/fireedge/src/public/components/Dialogs/NetworkDialog.js b/src/fireedge/src/public/components/Dialogs/NetworkDialog.js deleted file mode 100644 index f49c35000d..0000000000 --- a/src/fireedge/src/public/components/Dialogs/NetworkDialog.js +++ /dev/null @@ -1,234 +0,0 @@ -import React from 'react'; - -import { - makeStyles, - useMediaQuery, - Button, - Dialog, - DialogTitle, - DialogContent, - DialogActions, - Grid, - FormControlLabel, - Checkbox, - TextField, - MenuItem -} from '@material-ui/core'; -import { useForm, Controller } from 'react-hook-form'; -import { yupResolver } from '@hookform/resolvers'; -import * as yup from 'yup'; - -import useOpennebula from 'client/hooks/useOpennebula'; -import ErrorHelper from 'client/components/FormControl/ErrorHelper'; -import { Tr } from 'client/components/HOC'; - -const useStyles = makeStyles(theme => ({})); - -const SELECT = { - template: 'template', - network: 'network' -}; - -const TYPES_NETWORKS = { - template_id: { text: 'Create', select: SELECT.template, extra: true }, - reserve_from: { text: 'Reserve', select: SELECT.network, extra: true }, - id: { text: 'Existing', select: SELECT.network, extra: false } -}; - -const ID_CY = 'form-network'; - -const NetworkDialog = React.memo( - ({ open, info: network, onSubmit, onCancel }) => { - const classes = useStyles(); - const { vNetworks, vNetworksTemplates } = useOpennebula(); - const isMobile = useMediaQuery(theme => theme.breakpoints.only('xs')); - - const { register, handleSubmit, errors, control, watch } = useForm({ - reValidateMode: 'onSubmit', - defaultValues: { - type: Object.keys(TYPES_NETWORKS)[0], - ...network - }, - resolver: yupResolver( - yup.object().shape({ - mandatory: yup.boolean().required(), - name: yup.string().required('Name is a required field'), - description: yup.string(), - type: yup - .string() - .oneOf(Object.keys(TYPES_NETWORKS)) - .required('Type is required field'), - id: yup - .string() - .when('type', { - is: type => - Object.entries(TYPES_NETWORKS)?.some( - ([key, { select }]) => - type === key && select === SELECT.network - ), - then: yup.string().required('Network is required field'), - otherwise: yup - .string() - .required('Network template is required field') - }) - .required(), - extra: yup.string() - }) - ) - }); - - const { type } = watch(); - const typeSelected = TYPES_NETWORKS[type]?.select; - - const selectType = - typeSelected === SELECT.network ? vNetworks : vNetworksTemplates; - - return ( - - - {network?.name ? 'Edit network' : 'New network'} - - - - - - } - label={Tr('Mandatory')} - labelPlacement="end" - /> - - - - } - FormHelperTextProps={{ 'data-cy': `${ID_CY}-name-error` }} - /> - - - - ) - } - FormHelperTextProps={{ - 'data-cy': `${ID_CY}-description-error` - }} - /> - - - - ) - } - FormHelperTextProps={{ - 'data-cy': `${ID_CY}-type-error` - }} - > - {Object.entries(TYPES_NETWORKS).map(([key, { text }]) => ( - - {text} - - ))} - - } - name="type" - control={control} - /> - - - - } - FormHelperTextProps={{ - 'data-cy': `${ID_CY}-id-error` - }} - > - {selectType?.map(({ ID, NAME }) => ( - - {NAME} - - ))} - - } - name="id" - control={control} - /> - - - - } - FormHelperTextProps={{ - 'data-cy': `${ID_CY}-extra-error` - }} - /> - - - - - - - - - ); - } -); - -export default NetworkDialog; diff --git a/src/fireedge/src/public/components/Dialogs/RoleDialog.js b/src/fireedge/src/public/components/Dialogs/RoleDialog.js deleted file mode 100644 index 68ffbaed45..0000000000 --- a/src/fireedge/src/public/components/Dialogs/RoleDialog.js +++ /dev/null @@ -1,96 +0,0 @@ -import React, { useMemo, useEffect } from 'react'; - -import { - makeStyles, - useMediaQuery, - Button, - Dialog, - DialogTitle, - DialogContent, - DialogActions, - Grid, - FormControlLabel, - Checkbox, - TextField, - MenuItem -} from '@material-ui/core'; -import { useForm, Controller } from 'react-hook-form'; -import { yupResolver } from '@hookform/resolvers'; -import * as yup from 'yup'; - -import useOpennebula from 'client/hooks/useOpennebula'; -import ErrorHelper from 'client/components/FormControl/ErrorHelper'; -import { Tr } from 'client/components/HOC'; - -const useStyles = makeStyles(theme => ({})); - -const ID_CY = 'form-role'; - -const NetworkDialog = React.memo(({ open, info: role, onSubmit, onCancel }) => { - // const classes = useStyles(); - const { templates } = useOpennebula(); - const isMobile = useMediaQuery(theme => theme.breakpoints.only('xs')); - - const { register, handleSubmit, errors, control } = useForm({ - reValidateMode: 'onSubmit', - defaultValues: role - // resolver: yupResolver(yup.object().shape({})) - }); - - return ( - - - {role?.name ? 'Edit role' : 'New role'} - - - - - {'ROLE FORM'} - {/* - ) - } - FormHelperTextProps={{ - 'data-cy': `${ID_CY}-id-error` - }} - > - {templates?.map(({ ID, NAME }) => ( - - {NAME} - - ))} - - } - name="template" - control={control} - /> */} - - - - - - - - - ); -}); - -export default NetworkDialog; diff --git a/src/fireedge/src/public/components/Dialogs/index.js b/src/fireedge/src/public/components/Dialogs/index.js index 25126df23d..8fff21000d 100644 --- a/src/fireedge/src/public/components/Dialogs/index.js +++ b/src/fireedge/src/public/components/Dialogs/index.js @@ -1,4 +1,3 @@ -import NetworkDialog from 'client/components/Dialogs/NetworkDialog'; -import RoleDialog from 'client/components/Dialogs/RoleDialog'; +import DialogForm from 'client/components/Dialogs/DialogForm'; -export { NetworkDialog, RoleDialog }; +export { DialogForm }; diff --git a/src/fireedge/src/public/components/Flows/FlowWithFAB.js b/src/fireedge/src/public/components/Flows/FlowWithFAB.js new file mode 100644 index 0000000000..b0c71bd1c2 --- /dev/null +++ b/src/fireedge/src/public/components/Flows/FlowWithFAB.js @@ -0,0 +1,101 @@ +import React, { useState } from 'react'; +import PropTypes from 'prop-types'; + +import { Fab, Box, Card } from '@material-ui/core'; +import AddIcon from '@material-ui/icons/Add'; + +import ReactFlow, { + removeElements, + addEdge, + MiniMap, + Background, + isNode +} from 'react-flow-renderer'; + +const initialElements = []; + +const onNodeDragStart = (event, node) => console.log('drag start', node); +const onNodeDragStop = (event, node) => console.log('drag stop', node); +const onSelectionDrag = (event, nodes) => console.log('selection drag', nodes); +const onSelectionDragStart = (event, nodes) => + console.log('selection drag start', nodes); +const onSelectionDragStop = (event, nodes) => + console.log('selection drag stop', nodes); +const onElementClick = (event, element) => + console.log(`${isNode(element) ? 'node' : 'edge'} click:`, element); +const onSelectionChange = elements => console.log('selection change', elements); +const onLoad = reactFlowInstance => { + console.log('flow loaded:', reactFlowInstance); + reactFlowInstance.fitView(); +}; + +const onMoveEnd = transform => console.log('zoom/move end', transform); + +const connectionLineStyle = { stroke: '#ddd' }; +const snapGrid = [16, 16]; + +const CustomNode = React.memo(({ data }) => ( + +
Custom node
+
+)); + +const FlowWithFAB = ({ handleClick }) => { + const [elements, setElements] = useState(initialElements); + const onElementsRemove = elementsToRemove => + setElements(els => removeElements(elementsToRemove, els)); + const onConnect = params => setElements(els => addEdge(params, els)); + + return ( + + + { + if (n.style?.background) return n.style.background; + if (n.type === 'input') return '#9999ff'; + if (n.type === 'output') return '#79c9b7'; + if (n.type === 'default') return '#ff6060'; + + return '#eee'; + }} + /> + + + + + + + ); +}; + +FlowWithFAB.propTypes = { + handleClick: PropTypes.func +}; + +FlowWithFAB.defaultProps = { + handleClick: evt => evt +}; + +export default FlowWithFAB; diff --git a/src/fireedge/src/public/components/FormStepper/FormDialog.js b/src/fireedge/src/public/components/FormStepper/FormList.js similarity index 50% rename from src/fireedge/src/public/components/FormStepper/FormDialog.js rename to src/fireedge/src/public/components/FormStepper/FormList.js index 9151fa5a96..1ac76f28b1 100644 --- a/src/fireedge/src/public/components/FormStepper/FormDialog.js +++ b/src/fireedge/src/public/components/FormStepper/FormList.js @@ -1,42 +1,17 @@ import React, { useEffect, useState } from 'react'; import PropTypes from 'prop-types'; -import { - makeStyles, - Box, - CardActionArea, - CardContent, - Card, - Grid -} from '@material-ui/core'; -import { Add } from '@material-ui/icons'; +import { Box } from '@material-ui/core'; import { useFormContext } from 'react-hook-form'; import ErrorHelper from 'client/components/FormControl/ErrorHelper'; -const useStyles = makeStyles(() => ({ - cardPlus: { - height: '100%', - minHeight: 140, - display: 'flex', - textAlign: 'center' - } -})); - -function FormDialog({ step, data, setFormData }) { - const classes = useStyles(); +function FormList({ step, data, setFormData }) { const { errors } = useFormContext(); const [dialogFormData, setDialogFormData] = useState({}); const [showDialog, setShowDialog] = useState(false); - const { - id, - addCardAction, - preRender, - InfoComponent, - DialogComponent, - DEFAULT_DATA - } = step; + const { id, preRender, ListComponent, DialogComponent, DEFAULT_DATA } = step; useEffect(() => { preRender && preRender(); @@ -81,43 +56,22 @@ function FormDialog({ step, data, setFormData }) { return ( - - {typeof errors[id]?.message === 'string' && ( - - - - )} - {addCardAction && - React.useMemo( - () => ( - - - handleOpen()}> - - - - - - - ), - [handleOpen, classes] - )} - {Array.isArray(data) && - data?.map((info, index) => ( - - handleOpen(index)} - handleClone={() => handleClone(index)} - handleRemove={() => handleRemove(index)} - /> - - ))} - + {typeof errors[id]?.message === 'string' && ( + + )} + handleOpen()} + itemsProps={({ index }) => ({ + handleEdit: () => handleOpen(index), + handleClone: () => handleClone(index), + handleRemove: () => handleRemove(index) + })} + /> {showDialog && DialogComponent && ( @@ -126,16 +80,16 @@ function FormDialog({ step, data, setFormData }) { ); } -FormDialog.propTypes = { +FormList.propTypes = { step: PropTypes.objectOf(PropTypes.any).isRequired, data: PropTypes.arrayOf(PropTypes.object).isRequired, setFormData: PropTypes.func.isRequired }; -FormDialog.defaultProps = { +FormList.defaultProps = { step: {}, data: [], setFormData: data => data }; -export default FormDialog; +export default FormList; diff --git a/src/fireedge/src/public/components/FormStepper/FormListSelect.js b/src/fireedge/src/public/components/FormStepper/FormListSelect.js index 6e6b18f9b7..99c8195625 100644 --- a/src/fireedge/src/public/components/FormStepper/FormListSelect.js +++ b/src/fireedge/src/public/components/FormStepper/FormListSelect.js @@ -8,7 +8,7 @@ import ErrorHelper from '../FormControl/ErrorHelper'; function FormListSelect({ step, data, setFormData }) { const { errors } = useFormContext(); - const { id, onlyOneSelect, preRender, list, InfoComponent } = step; + const { id, onlyOneSelect, preRender, list, ItemComponent } = step; useEffect(() => { preRender && preRender(); @@ -37,7 +37,7 @@ function FormListSelect({ step, data, setFormData }) { {Array.isArray(list) && list?.map((info, index) => ( - selected === info?.ID)} handleSelect={handleSelect} diff --git a/src/fireedge/src/public/components/FormStepper/FormStep.js b/src/fireedge/src/public/components/FormStepper/FormStep.js index 34cd93631d..d6aa1ca80d 100644 --- a/src/fireedge/src/public/components/FormStepper/FormStep.js +++ b/src/fireedge/src/public/components/FormStepper/FormStep.js @@ -1,18 +1,44 @@ -import React, { useEffect } from 'react'; +import React, { useEffect, useState } from 'react'; import PropTypes from 'prop-types'; import { useFormContext } from 'react-hook-form'; +import ErrorHelper from 'client/components/FormControl/ErrorHelper'; + function FormStep({ step, data, setFormData }) { - const { reset, errors } = useFormContext(); - const { id, preRender, FormComponent } = step; + const { errors } = useFormContext(); + const [showDialog, setShowDialog] = useState(false); + const { id, preRender, FormComponent, DialogComponent } = step; useEffect(() => { preRender && preRender(); - reset({ [id]: data }, { errors: true }); }, []); - return React.useMemo(() => , [id]); + const handleOpen = () => setShowDialog(true); + const handleClose = () => setShowDialog(false); + const handleSubmit = d => console.log(d); + + return ( + <> + {typeof errors[id]?.message === 'string' && ( + + )} + {React.useMemo( + () => ( + + ), + [id, handleOpen] + )} + {showDialog && DialogComponent && ( + + )} + + ); } FormStep.propTypes = { diff --git a/src/fireedge/src/public/components/FormStepper/MobileStepper.js b/src/fireedge/src/public/components/FormStepper/MobileStepper.js index f4a23fd197..500ae2bc0e 100644 --- a/src/fireedge/src/public/components/FormStepper/MobileStepper.js +++ b/src/fireedge/src/public/components/FormStepper/MobileStepper.js @@ -1,11 +1,19 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { Button, MobileStepper } from '@material-ui/core'; +import { styled, Button, MobileStepper } from '@material-ui/core'; import { KeyboardArrowLeft, KeyboardArrowRight } from '@material-ui/icons'; import { Tr } from 'client/components/HOC'; +const StickyMobileStepper = styled(MobileStepper)({ + position: 'sticky', + top: -15, + backdropFilter: 'blur(5px)', + background: '#fafafa9c', + zIndex: 1 +}); + const CustomMobileStepper = ({ totalSteps, activeStep, @@ -14,12 +22,11 @@ const CustomMobileStepper = ({ handleNext, handleBack }) => ( - {Tr('Back')} diff --git a/src/fireedge/src/public/components/FormStepper/Stepper.js b/src/fireedge/src/public/components/FormStepper/Stepper.js index e8872195fe..2708d51f47 100644 --- a/src/fireedge/src/public/components/FormStepper/Stepper.js +++ b/src/fireedge/src/public/components/FormStepper/Stepper.js @@ -1,17 +1,24 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { Button, Stepper, Step, StepLabel, Box } from '@material-ui/core'; +import { + styled, + Button, + Stepper, + Step, + StepLabel, + Box +} from '@material-ui/core'; import { Tr } from 'client/components/HOC'; -/* -position: sticky; -top: 0; -backdrop-filter: blur(5px); -background: #000000aa; -z-index: 1; -*/ +const StickyStepper = styled(Stepper)({ + position: 'sticky', + top: -15, + backdropFilter: 'blur(5px)', + background: '#fafafa9c', + zIndex: 1 +}); const CustomStepper = ({ steps, @@ -22,13 +29,13 @@ const CustomStepper = ({ handleBack }) => ( <> - + {steps?.map(({ label }) => ( {label} ))} - +