diff --git a/src/fireedge/src/client/components/Tabs/Common/Attribute/Attribute.js b/src/fireedge/src/client/components/Tabs/Common/Attribute/Attribute.js index 35966d942b..2fdb4db5fd 100644 --- a/src/fireedge/src/client/components/Tabs/Common/Attribute/Attribute.js +++ b/src/fireedge/src/client/components/Tabs/Common/Attribute/Attribute.js @@ -63,10 +63,10 @@ const Attribute = React.memo(({ } const handleActiveEditForm = async () => { - const response = await handleGetOptionList?.() + const response = await handleGetOptionList?.() ?? [] const isFormatValid = response?.every?.(({ text, value } = {}) => !!text && !!value) - if (isFormatValid) { + if (!handleGetOptionList || isFormatValid) { setOptions(response) setIsEditing(true) } @@ -79,25 +79,31 @@ const Attribute = React.memo(({ return ( <> - + {Tr(name)}
{isEditing ? ( <> - {handleGetOptionList && ( + {handleGetOptionList ? ( + ) : ( + )} ) : ( <> - + {value} {canEdit && ( diff --git a/src/fireedge/src/client/components/Tabs/Common/Attribute/Inputs.js b/src/fireedge/src/client/components/Tabs/Common/Attribute/Inputs.js index 56bc84e47c..838c51480f 100644 --- a/src/fireedge/src/client/components/Tabs/Common/Attribute/Inputs.js +++ b/src/fireedge/src/client/components/Tabs/Common/Attribute/Inputs.js @@ -82,4 +82,41 @@ Select.propTypes = { ) } -export { Select } +const Text = React.forwardRef( + /** + * @param {object} props - Props + * @param {string} props.name - Attribute name + * @param {string} props.value - Attribute value + * @param {React.ForwardedRef} ref - Forward reference + * @returns {React.JSXElementConstructor} Text field + */ + ({ name = '', value = '' }, ref) => { + console.log({ name, value }) + const [newValue, setNewValue] = React.useState(() => value) + + const handleChange = event => setNewValue(event.target.value) + + return ( + + ) + } +) + +Text.displayName = 'Text' + +Text.propTypes = { + name: PropTypes.string.isRequired, + value: PropTypes.string.isRequired +} + +export { Select, Text } diff --git a/src/fireedge/src/client/components/Tabs/Common/List.js b/src/fireedge/src/client/components/Tabs/Common/List.js index af592c7a93..ef5b584c6b 100644 --- a/src/fireedge/src/client/components/Tabs/Common/List.js +++ b/src/fireedge/src/client/components/Tabs/Common/List.js @@ -19,6 +19,7 @@ import PropTypes from 'prop-types' import { makeStyles, List as MList, ListItem, Typography, Paper } from '@material-ui/core' +import Attribute from 'client/components/Tabs/Common/Attribute' import { Tr } from 'client/components/HOC' const useStyles = makeStyles(theme => ({ @@ -27,7 +28,7 @@ const useStyles = makeStyles(theme => ({ borderBottom: `1px solid ${theme.palette.divider}` }, item: { - '& > $typo': { + '& > *': { width: '50%' } }, @@ -49,18 +50,12 @@ const List = ({ title, list = [], ...props }) => { )} {/* LIST */} - {list.map(({ key, value }, idx) => ( - - - {Tr(key)} - - - {value} - + {list.map((attribute, idx) => ( + + ))} @@ -71,8 +66,14 @@ const List = ({ title, list = [], ...props }) => { List.propTypes = { title: PropTypes.string, list: PropTypes.arrayOf(PropTypes.shape({ - key: PropTypes.string, - value: PropTypes.any + canDelete: PropTypes.bool, + canEdit: PropTypes.bool, + handleEdit: PropTypes.func, + handleDelete: PropTypes.func, + handleGetOptionList: PropTypes.func, + name: PropTypes.string.isRequired, + value: PropTypes.any.isRequired, + valueInOptionList: PropTypes.string.isRequired })) } diff --git a/src/fireedge/src/client/components/Tabs/Common/Ownership.js b/src/fireedge/src/client/components/Tabs/Common/Ownership.js index 3371213549..2694922ce1 100644 --- a/src/fireedge/src/client/components/Tabs/Common/Ownership.js +++ b/src/fireedge/src/client/components/Tabs/Common/Ownership.js @@ -64,35 +64,25 @@ const Ownership = React.memo(({ ) } + const ownership = [ + { + key: T.Owner, + value: userName, + valueInOptionList: userId, + handleGetOptionList: getUserOptions, + handleEdit: user => handleEdit?.({ user }) + }, + { + key: T.Group, + value: groupName, + valueInOptionList: groupId, + handleGetOptionList: getGroupOptions, + handleEdit: group => handleEdit?.({ group }) + } + ] + return ( - - - - {Tr(T.Ownership)} - - - - handleEdit?.({ user })} - /> - - - handleEdit?.({ group })} - /> - - - + ) }) diff --git a/src/fireedge/src/client/components/Tabs/TabProvider.js b/src/fireedge/src/client/components/Tabs/TabProvider.js new file mode 100644 index 0000000000..e5285c977e --- /dev/null +++ b/src/fireedge/src/client/components/Tabs/TabProvider.js @@ -0,0 +1,45 @@ +/* ------------------------------------------------------------------------- * + * Copyright 2002-2021, OpenNebula Project, OpenNebula Systems * + * * + * Licensed under the Apache License, Version 2.0 (the "License"); you may * + * not use this file except in compliance with the License. You may obtain * + * a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, software * + * distributed under the License is distributed on an "AS IS" BASIS, * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * + * See the License for the specific language governing permissions and * + * limitations under the License. * + * ------------------------------------------------------------------------- */ +/* eslint-disable jsdoc/require-jsdoc */ +import React, { createContext, useState } from 'react' +import PropTypes from 'prop-types' + +export const TabContext = createContext(null) + +const TabProvider = ({ initialState = {}, children }) => { + const [information, setTabInformation] = useState(() => initialState) + const { data } = initialState + + React.useEffect(() => { + data && setTabInformation(prev => ({ ...prev, data })) + }, [data]) + + return ( + + {children} + + ) +} + +TabProvider.propTypes = { + initialState: PropTypes.object, + children: PropTypes.oneOfType([ + PropTypes.node, + PropTypes.arrayOf(PropTypes.node) + ]) +} + +export default TabProvider diff --git a/src/fireedge/src/client/components/Tabs/Vm/Capacity.js b/src/fireedge/src/client/components/Tabs/Vm/Capacity.js index ec63c47d15..1aac0a146b 100644 --- a/src/fireedge/src/client/components/Tabs/Vm/Capacity.js +++ b/src/fireedge/src/client/components/Tabs/Vm/Capacity.js @@ -17,6 +17,7 @@ import * as React from 'react' import { makeStyles, Paper, Typography } from '@material-ui/core' +import { TabContext } from 'client/components/Tabs/TabProvider' import { Action } from 'client/components/Cards/SelectCard' import * as VirtualMachine from 'client/models/VirtualMachine' import { prettyBytes } from 'client/utils' @@ -56,12 +57,13 @@ const useStyles = makeStyles(theme => ({ } })) -const VmCapacityTab = data => { +const VmCapacityTab = () => { const classes = useStyles() - const { TEMPLATE } = data + const { data: vm = {} } = React.useContext(TabContext) + const { TEMPLATE } = vm - const isVCenter = VirtualMachine.isVCenter(data) + const isVCenter = VirtualMachine.isVCenter(vm) const capacity = [ { key: 'Physical CPU', value: TEMPLATE?.CPU }, diff --git a/src/fireedge/src/client/components/Tabs/Vm/Configuration.js b/src/fireedge/src/client/components/Tabs/Vm/Configuration.js index cb9e0b7872..03749ebcf4 100644 --- a/src/fireedge/src/client/components/Tabs/Vm/Configuration.js +++ b/src/fireedge/src/client/components/Tabs/Vm/Configuration.js @@ -17,10 +17,12 @@ import * as React from 'react' import { Accordion, AccordionSummary, AccordionDetails } from '@material-ui/core' +import { TabContext } from 'client/components/Tabs/TabProvider' + const NavArrowDown = {'>'} const VmConfigurationTab = data => { - const { TEMPLATE, USER_TEMPLATE } = data + const { data: { TEMPLATE, USER_TEMPLATE } = {} } = React.useContext(TabContext) return (
diff --git a/src/fireedge/src/client/components/Tabs/Vm/Info/index.js b/src/fireedge/src/client/components/Tabs/Vm/Info/index.js index ed85a22d35..94d3d06b7e 100644 --- a/src/fireedge/src/client/components/Tabs/Vm/Info/index.js +++ b/src/fireedge/src/client/components/Tabs/Vm/Info/index.js @@ -19,11 +19,13 @@ import PropTypes from 'prop-types' import { useVmApi } from 'client/features/One' import { Permissions, Ownership } from 'client/components/Tabs/Common' +import { TabContext } from 'client/components/Tabs/TabProvider' import Information from 'client/components/Tabs/Vm/Info/information' -const VmInfoTab = ({ tabProps, handleRefetch, ...data }) => { - const { ID, UNAME, UID, GNAME, GID, PERMISSIONS } = data +const VmInfoTab = ({ tabProps }) => { const { changeOwnership } = useVmApi() + const { handleRefetch, data } = React.useContext(TabContext) + const { ID, UNAME, UID, GNAME, GID, PERMISSIONS } = data const handleChangeOwnership = async newOwnership => { const response = await changeOwnership(ID, newOwnership) @@ -58,8 +60,7 @@ const VmInfoTab = ({ tabProps, handleRefetch, ...data }) => { } VmInfoTab.propTypes = { - tabProps: PropTypes.object, - handleRefetch: PropTypes.func + tabProps: PropTypes.object } VmInfoTab.displayName = 'VmInfoTab' diff --git a/src/fireedge/src/client/components/Tabs/Vm/Info/information.js b/src/fireedge/src/client/components/Tabs/Vm/Info/information.js index 2078aa214f..3596b7d29c 100644 --- a/src/fireedge/src/client/components/Tabs/Vm/Info/information.js +++ b/src/fireedge/src/client/components/Tabs/Vm/Info/information.js @@ -35,42 +35,49 @@ const InformationPanel = data => { const ips = VirtualMachine.getIps(data) const info = [ - { key: T.ID, value: ID }, - { key: T.Name, value: NAME }, + { name: T.ID, value: ID }, { - key: T.State, + name: T.Name, + value: NAME, + canEdit: true, + handleEdit: newName => { + + } + }, + { + name: T.State, value: }, { - key: T.Reschedule, + name: T.Reschedule, value: Helper.booleanToString(+RESCHED) }, { - key: T.Locked, + name: T.Locked, value: Helper.levelLockToString(LOCK?.LOCKED) }, { - key: T.IP, + name: T.IP, value: ips?.length ? : '--' }, { - key: T.StartTime, + name: T.StartTime, value: Helper.timeToString(STIME) }, { - key: T.EndTime, + name: T.EndTime, value: Helper.timeToString(ETIME) }, { - key: T.Host, + name: T.Host, value: hostId ? `#${hostId} ${hostname}` : '' }, { - key: T.Cluster, + name: T.Cluster, value: clusterId ? `#${clusterId} ${clusterName}` : '' }, { - key: T.DeployID, + name: T.DeployID, value: DEPLOY_ID } ] diff --git a/src/fireedge/src/client/components/Tabs/Vm/Network/Item.js b/src/fireedge/src/client/components/Tabs/Vm/Network/Item.js index afa2cc3da4..4ee56211ab 100644 --- a/src/fireedge/src/client/components/Tabs/Vm/Network/Item.js +++ b/src/fireedge/src/client/components/Tabs/Vm/Network/Item.js @@ -32,6 +32,7 @@ import { import { useVmApi } from 'client/features/One' import { Action } from 'client/components/Cards/SelectCard' import Multiple from 'client/components/Tables/Vms/multiple' +import { TabContext } from 'client/components/Tabs/TabProvider' import { T, VM_ACTIONS } from 'client/constants' import { Tr } from 'client/components/HOC' @@ -84,9 +85,11 @@ const useStyles = makeStyles(({ } })) -const NetworkItem = ({ vmId, handleRefetch, nic = {}, actions }) => { +const NetworkItem = ({ nic = {}, actions }) => { const classes = useStyles() const isMobile = useMediaQuery(theme => theme.breakpoints.down('sm')) + + const { handleRefetch, data: vm } = React.useContext(TabContext) const { detachNic } = useVmApi() const { NIC_ID, NETWORK = '-', BRIDGE, IP, MAC, PCI_ID, ALIAS, SECURITY_GROUPS } = nic @@ -96,15 +99,15 @@ const NetworkItem = ({ vmId, handleRefetch, nic = {}, actions }) => { [ALIAS.length, SECURITY_GROUPS?.length] ) - const detachAction = () => actions.includes(VM_ACTIONS.DETACH_NIC) && ( + const detachAction = () => actions?.includes?.(VM_ACTIONS.DETACH_NIC) && ( } stopPropagation handleClick={async () => { - const response = await detachNic(vmId, NIC_ID) + const response = await detachNic(vm.ID, NIC_ID) - String(response) === String(vmId) && handleRefetch?.(vmId) + String(response) === String(vm.ID) && handleRefetch?.(vm.ID) }} /> ) @@ -169,8 +172,6 @@ const NetworkItem = ({ vmId, handleRefetch, nic = {}, actions }) => { NetworkItem.propTypes = { actions: PropTypes.arrayOf(PropTypes.string), - handleRefetch: PropTypes.func, - vmId: PropTypes.string, nic: PropTypes.object } diff --git a/src/fireedge/src/client/components/Tabs/Vm/Network/List.js b/src/fireedge/src/client/components/Tabs/Vm/Network/List.js index e21316c571..aceab21d8f 100644 --- a/src/fireedge/src/client/components/Tabs/Vm/Network/List.js +++ b/src/fireedge/src/client/components/Tabs/Vm/Network/List.js @@ -19,7 +19,7 @@ import PropTypes from 'prop-types' import NetworkItem from 'client/components/Tabs/Vm/Network/Item' -const NetworkList = ({ vmId, handleRefetch, nics, actions }) => ( +const NetworkList = ({ nics, actions }) => (
( paddingBlock: '0.8em' }}> {nics.map((nic, idx) => ( - + ))}
) NetworkList.propTypes = { actions: PropTypes.arrayOf(PropTypes.string), - handleRefetch: PropTypes.func, - vmId: PropTypes.string, nics: PropTypes.array } diff --git a/src/fireedge/src/client/components/Tabs/Vm/Network/index.js b/src/fireedge/src/client/components/Tabs/Vm/Network/index.js index c6b8f1b8cf..e07d2ced22 100644 --- a/src/fireedge/src/client/components/Tabs/Vm/Network/index.js +++ b/src/fireedge/src/client/components/Tabs/Vm/Network/index.js @@ -18,11 +18,12 @@ import * as React from 'react' import PropTypes from 'prop-types' import NetworkList from 'client/components/Tabs/Vm/Network/List' - +import { TabContext } from 'client/components/Tabs/TabProvider' import * as VirtualMachine from 'client/models/VirtualMachine' import * as Helper from 'client/models/Helper' -const VmNetworkTab = ({ tabProps, handleRefetch, ...vm }) => { +const VmNetworkTab = ({ tabProps }) => { + const { data: vm } = React.useContext(TabContext) const { actions = [] } = tabProps const nics = VirtualMachine.getNics(vm, { @@ -34,18 +35,12 @@ const VmNetworkTab = ({ tabProps, handleRefetch, ...vm }) => { const actionsAvailable = Helper.getActionsAvailable(actions, hypervisor) return ( - + ) } VmNetworkTab.propTypes = { - tabProps: PropTypes.object, - handleRefetch: PropTypes.func + tabProps: PropTypes.object } VmNetworkTab.displayName = 'VmNetworkTab' diff --git a/src/fireedge/src/client/components/Tabs/Vm/Storage/List.js b/src/fireedge/src/client/components/Tabs/Vm/Storage/List.js index 3765b657a6..78efdd4560 100644 --- a/src/fireedge/src/client/components/Tabs/Vm/Storage/List.js +++ b/src/fireedge/src/client/components/Tabs/Vm/Storage/List.js @@ -22,11 +22,7 @@ import StorageItem from 'client/components/Tabs/Vm/Storage/Item' const StorageList = ({ disks, actions }) => (
{disks.map((disk, idx) => ( - + ))}
) diff --git a/src/fireedge/src/client/components/Tabs/Vm/Storage/index.js b/src/fireedge/src/client/components/Tabs/Vm/Storage/index.js index 0e7264d3aa..5d1027ac18 100644 --- a/src/fireedge/src/client/components/Tabs/Vm/Storage/index.js +++ b/src/fireedge/src/client/components/Tabs/Vm/Storage/index.js @@ -18,15 +18,17 @@ import * as React from 'react' import PropTypes from 'prop-types' import StorageList from 'client/components/Tabs/Vm/Storage/List' - +import { TabContext } from 'client/components/Tabs/TabProvider' import * as VirtualMachine from 'client/models/VirtualMachine' import * as Helper from 'client/models/Helper' -const VmStorageTab = ({ tabProps, ...data }) => { +const VmStorageTab = ({ tabProps = {} }) => { + const { data: vm } = React.useContext(TabContext) const { actions = [] } = tabProps - const disks = VirtualMachine.getDisks(data) - const hypervisor = VirtualMachine.getHypervisor(data) + const disks = VirtualMachine.getDisks(vm) + + const hypervisor = VirtualMachine.getHypervisor(vm) const actionsAvailable = Helper.getActionsAvailable(actions, hypervisor) return ( @@ -35,10 +37,7 @@ const VmStorageTab = ({ tabProps, ...data }) => { } VmStorageTab.propTypes = { - tabProps: PropTypes.shape({ - actions: PropTypes.object - }), - actions: PropTypes.array + tabProps: PropTypes.object } VmStorageTab.displayName = 'VmStorageTab' diff --git a/src/fireedge/src/client/components/Tabs/Vm/index.js b/src/fireedge/src/client/components/Tabs/Vm/index.js index e93755f20c..e42a540c8e 100644 --- a/src/fireedge/src/client/components/Tabs/Vm/index.js +++ b/src/fireedge/src/client/components/Tabs/Vm/index.js @@ -22,6 +22,7 @@ import { useAuth } from 'client/features/Auth' import Tabs from 'client/components/Tabs' import { stringToCamelCase, stringToCamelSpace } from 'client/utils' +import TabProvider from 'client/components/Tabs/TabProvider' import Capacity from 'client/components/Tabs/Vm/Capacity' import Configuration from 'client/components/Tabs/Vm/Configuration' import Info from 'client/components/Tabs/Vm/Info' @@ -59,14 +60,17 @@ const VmTabs = ({ data, handleRefetch }) => { return TabContent && { name: stringToCamelSpace(nameSanitize), - renderContent: - props => TabContent({ ...props, tabProps, handleRefetch }) + renderContent: props => TabContent({ ...props, tabProps }) } }) ?.filter(Boolean)) }, [view]) - return + return ( + + + + ) } VmTabs.propTypes = { diff --git a/src/fireedge/src/client/components/Tabs/index.js b/src/fireedge/src/client/components/Tabs/index.js index 43a7b20b3a..82a0561c83 100644 --- a/src/fireedge/src/client/components/Tabs/index.js +++ b/src/fireedge/src/client/components/Tabs/index.js @@ -19,7 +19,7 @@ import PropTypes from 'prop-types' import { Tabs as MTabs, Tab as MTab } from '@material-ui/core' -const Content = ({ name, renderContent: Content, hidden, data }) => ( +const Content = ({ name, renderContent: Content, hidden }) => (
( display: hidden ? 'none' : 'block' }} > - {typeof Content === 'function' ? : Content} + {typeof Content === 'function' ? : Content}
) -const Tabs = ({ tabs = [], renderHiddenTabs = false, data }) => { +const Tabs = ({ tabs = [], renderHiddenTabs = false }) => { const [tabSelected, setTab] = useState(0) const renderTabs = useMemo(() => ( @@ -68,7 +68,7 @@ const Tabs = ({ tabs = [], renderHiddenTabs = false, data }) => { {renderHiddenTabs ? ( renderAllHiddenTabContents ) : ( - (value ?? idx) === tabSelected)} /> + (value ?? idx) === tabSelected)} /> )} ) @@ -79,8 +79,7 @@ Content.displayName = 'Content' Tabs.propTypes = { tabs: PropTypes.array, - renderHiddenTabs: PropTypes.bool, - data: PropTypes.object + renderHiddenTabs: PropTypes.bool } Content.propTypes = { @@ -89,8 +88,7 @@ Content.propTypes = { PropTypes.object, PropTypes.func ]), - hidden: PropTypes.bool, - data: PropTypes.object + hidden: PropTypes.bool } export default Tabs