mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-16 22:50:10 +03:00
F OpenNebula/one#5422: Add view condition to vm detail
This commit is contained in:
parent
5feacf8d56
commit
d5b2e8a286
@ -1,10 +1,6 @@
|
||||
import { CategoryFilter } from 'client/components/Tables/Enhanced/Utils'
|
||||
|
||||
export const createColumns = ({ view, resource, columns }) => {
|
||||
const filters = view
|
||||
?.find(({ resource_name: name }) => name === resource)
|
||||
?.filters ?? {}
|
||||
|
||||
export const createColumns = ({ filters = {}, columns = [] }) => {
|
||||
if (Object.keys(filters).length === 0) return columns
|
||||
|
||||
return columns.map(column => {
|
||||
|
@ -1,27 +1,24 @@
|
||||
import React, { useEffect } from 'react'
|
||||
import * as React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { LinearProgress, Accordion, AccordionSummary, AccordionDetails } from '@material-ui/core'
|
||||
|
||||
import Tabs from 'client/components/Tabs'
|
||||
import { StatusBadge } from 'client/components/Status'
|
||||
import { LinearProgress } from '@material-ui/core'
|
||||
|
||||
import { useFetch, useSocket } from 'client/hooks'
|
||||
import { useVmApi } from 'client/features/One'
|
||||
|
||||
import * as VirtualMachine from 'client/models/VirtualMachine'
|
||||
import * as Helper from 'client/models/Helper'
|
||||
import { prettyBytes } from 'client/utils'
|
||||
import VmTabs from 'client/components/Tabs/Vm'
|
||||
|
||||
const NavArrowDown = <span style={{ writingMode: 'vertical-rl' }}>{'>'}</span>
|
||||
|
||||
const VmDetail = ({ id }) => {
|
||||
const VmDetail = React.memo(({ id, view = {} }) => {
|
||||
const { getHooksSocket } = useSocket()
|
||||
const socket = getHooksSocket({ resource: 'vm', id })
|
||||
|
||||
const { getVm } = useVmApi()
|
||||
const { data, fetchRequest, loading, error } = useFetch(getVm, socket)
|
||||
|
||||
useEffect(() => {
|
||||
const {
|
||||
data,
|
||||
fetchRequest,
|
||||
loading,
|
||||
error
|
||||
} = useFetch(getVm, getHooksSocket({ resource: 'vm', id }))
|
||||
|
||||
React.useEffect(() => {
|
||||
fetchRequest(id)
|
||||
}, [id])
|
||||
|
||||
@ -33,168 +30,20 @@ const VmDetail = ({ id }) => {
|
||||
return <div>{error}</div>
|
||||
}
|
||||
|
||||
const { ID, NAME, UNAME, GNAME, RESCHED, STIME, ETIME, LOCK, DEPLOY_ID, TEMPLATE, USER_TEMPLATE } = data
|
||||
|
||||
const isVCenter = VirtualMachine.isVCenter(data)
|
||||
const { name: stateName, color: stateColor } = VirtualMachine.getState(data)
|
||||
|
||||
const { HID: hostId, HOSTNAME: hostname = '--', CID: clusterId } = VirtualMachine.getLastHistory(data)
|
||||
const clusterName = clusterId === '-1' ? 'default' : '--' // TODO: get from cluster list
|
||||
|
||||
const ips = VirtualMachine.getIps(data)
|
||||
const { nics, alias } = VirtualMachine.splitNicAlias(data)
|
||||
|
||||
const disks = VirtualMachine.getDisks(data)
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
name: 'info',
|
||||
renderContent: (
|
||||
<div>
|
||||
<div>
|
||||
<StatusBadge
|
||||
title={stateName}
|
||||
stateColor={stateColor}
|
||||
customTransform='translate(150%, 50%)'
|
||||
/>
|
||||
<span style={{ marginLeft: 20 }}>
|
||||
{`#${ID} - ${NAME}`}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<p>Owner: {UNAME}</p>
|
||||
<p>Group: {GNAME}</p>
|
||||
<p>Reschedule: {Helper.booleanToString(+RESCHED)}</p>
|
||||
<p>Locked: {Helper.levelLockToString(LOCK?.LOCKED)}</p>
|
||||
<p>IP: {ips.join(', ') || '--'}</p>
|
||||
<p>Start time: {Helper.timeToString(STIME)}</p>
|
||||
<p>End time: {Helper.timeToString(ETIME)}</p>
|
||||
<p>Host: {hostId ? `#${hostId} ${hostname}` : ''}</p>
|
||||
<p>Cluster: {clusterId ? `#${clusterId} ${clusterName}` : ''}</p>
|
||||
<p>Deploy ID: {DEPLOY_ID}</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
name: 'capacity',
|
||||
renderContent: (
|
||||
<div>
|
||||
<p>Physical CPU: {TEMPLATE?.CPU}</p>
|
||||
<p>Virtual CPU: {TEMPLATE?.VCPU ?? '-'}</p>
|
||||
{isVCenter && (
|
||||
<p>Virtual Cores: {`
|
||||
Cores x ${TEMPLATE?.TOPOLOGY?.CORES || '-'} |
|
||||
Sockets ${TEMPLATE?.TOPOLOGY?.SOCKETS || '-'}
|
||||
`}</p>
|
||||
)}
|
||||
<p>Memory: {prettyBytes(+TEMPLATE?.MEMORY, 'MB')}</p>
|
||||
<p>Cost / CPU: {TEMPLATE?.CPU_COST}</p>
|
||||
<p>Cost / MByte: {TEMPLATE?.MEMORY_COST}</p>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
name: 'storage',
|
||||
renderContent: (
|
||||
<div>
|
||||
<p>VM DISKS</p>
|
||||
{disks.map(({
|
||||
DISK_ID,
|
||||
DATASTORE = '-',
|
||||
TARGET = '-',
|
||||
IMAGE,
|
||||
TYPE,
|
||||
FORMAT,
|
||||
SIZE,
|
||||
MONITOR_SIZE,
|
||||
READONLY,
|
||||
SAVE = 'No',
|
||||
CLONE
|
||||
}) => {
|
||||
const size = +SIZE ? prettyBytes(+SIZE, 'MB') : '-'
|
||||
const monitorSize = +MONITOR_SIZE ? prettyBytes(+MONITOR_SIZE, 'MB') : '-'
|
||||
|
||||
const type = String(TYPE).toLowerCase()
|
||||
|
||||
const image = IMAGE ?? ({
|
||||
fs: `${FORMAT} - ${size}`,
|
||||
swap: size
|
||||
}[type])
|
||||
|
||||
return (
|
||||
<p key={DISK_ID}>
|
||||
{`${DISK_ID} | ${DATASTORE} | ${TARGET} | ${image} | ${monitorSize}/${size} | ${type} | ${READONLY} | ${SAVE} | ${CLONE}`}
|
||||
</p>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
name: 'network',
|
||||
renderContent: (
|
||||
<div>
|
||||
<div>
|
||||
<p>VM NICS</p>
|
||||
{nics.map(({ NIC_ID, NETWORK = '-', BRIDGE = '-', IP = '-', MAC = '-', PCI_ID = '' }) => (
|
||||
<p key={NIC_ID}>
|
||||
{`${NIC_ID} | ${NETWORK} | ${BRIDGE} | ${IP} | ${MAC} | ${PCI_ID}`}
|
||||
</p>
|
||||
))}
|
||||
</div>
|
||||
<hr />
|
||||
<div>
|
||||
<p>VM ALIAS</p>
|
||||
{alias.map(({ NIC_ID, NETWORK = '-', BRIDGE = '-', IP = '-', MAC = '-' }) => (
|
||||
<p key={NIC_ID}>
|
||||
{`${NIC_ID} | ${NETWORK} | ${BRIDGE} | ${IP} | ${MAC}`}
|
||||
</p>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
name: 'template',
|
||||
renderContent: (
|
||||
<div>
|
||||
<Accordion TransitionProps={{ unmountOnExit: true }}>
|
||||
<AccordionSummary expandIcon={NavArrowDown}>
|
||||
User Template
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<pre>
|
||||
<code>
|
||||
{JSON.stringify(USER_TEMPLATE, null, 2)}
|
||||
</code>
|
||||
</pre>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
<Accordion TransitionProps={{ unmountOnExit: true }}>
|
||||
<AccordionSummary expandIcon={NavArrowDown}>
|
||||
Template
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<pre>
|
||||
<code>
|
||||
{JSON.stringify(TEMPLATE, null, 2)}
|
||||
</code>
|
||||
</pre>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
]
|
||||
const tabs = Object.entries(view['info-tabs'] ?? {})
|
||||
?.map(([tabName, { enabled } = {}]) => !!enabled && tabName)
|
||||
?.filter(Boolean)
|
||||
|
||||
return (
|
||||
<Tabs tabs={tabs} />
|
||||
<VmTabs data={data} tabs={tabs} view={view} />
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
VmDetail.propTypes = {
|
||||
id: PropTypes.string.isRequired
|
||||
id: PropTypes.string.isRequired,
|
||||
view: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
VmDetail.displayName = 'VmDetail'
|
||||
|
||||
export default VmDetail
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useEffect } from 'react'
|
||||
import * as React from 'react'
|
||||
|
||||
import { useAuth } from 'client/features/Auth'
|
||||
import { useFetch } from 'client/hooks'
|
||||
@ -18,16 +18,19 @@ const VmsTable = () => {
|
||||
const { getVms } = useVmApi()
|
||||
const { view, views, filterPool } = useAuth()
|
||||
|
||||
const viewSelected = React.useMemo(() => views[view], [view])
|
||||
|
||||
const resourceView = viewSelected?.find(({ resource_name: name }) => name === 'VM')
|
||||
|
||||
const columns = React.useMemo(() => createColumns({
|
||||
view: views[view],
|
||||
resource: 'VM',
|
||||
filters: resourceView?.filters,
|
||||
columns: VmColumns
|
||||
}), [view])
|
||||
|
||||
const { status, data, fetchRequest, loading, reloading, error, STATUS } = useFetch(getVms)
|
||||
const { INIT, PENDING } = STATUS
|
||||
|
||||
useEffect(() => {
|
||||
React.useEffect(() => {
|
||||
const requests = {
|
||||
INIT: () => fetchRequest({
|
||||
start: INITIAL_ELEMENT,
|
||||
@ -60,7 +63,7 @@ const VmsTable = () => {
|
||||
isLoading={loading || reloading}
|
||||
getRowId={row => String(row.ID)}
|
||||
RowComponent={VmRow}
|
||||
renderDetail={row => <VmDetail id={row.ID} />}
|
||||
renderDetail={row => <VmDetail id={row.ID} view={resourceView} />}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
30
src/fireedge/src/client/components/Tabs/Vm/capacity.js
Normal file
30
src/fireedge/src/client/components/Tabs/Vm/capacity.js
Normal file
@ -0,0 +1,30 @@
|
||||
import * as React from 'react'
|
||||
|
||||
import * as VirtualMachine from 'client/models/VirtualMachine'
|
||||
import { prettyBytes } from 'client/utils'
|
||||
|
||||
const VmCapacityTab = data => {
|
||||
const { TEMPLATE } = data
|
||||
|
||||
const isVCenter = VirtualMachine.isVCenter(data)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<p>Physical CPU: {TEMPLATE?.CPU}</p>
|
||||
<p>Virtual CPU: {TEMPLATE?.VCPU ?? '-'}</p>
|
||||
{isVCenter && (
|
||||
<p>Virtual Cores: {`
|
||||
Cores x ${TEMPLATE?.TOPOLOGY?.CORES || '-'} |
|
||||
Sockets ${TEMPLATE?.TOPOLOGY?.SOCKETS || '-'}
|
||||
`}</p>
|
||||
)}
|
||||
<p>Memory: {prettyBytes(+TEMPLATE?.MEMORY, 'MB')}</p>
|
||||
<p>Cost / CPU: {TEMPLATE?.CPU_COST}</p>
|
||||
<p>Cost / MByte: {TEMPLATE?.MEMORY_COST}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
VmCapacityTab.displayName = 'VmCapacityTab'
|
||||
|
||||
export default VmCapacityTab
|
41
src/fireedge/src/client/components/Tabs/Vm/configuration.js
Normal file
41
src/fireedge/src/client/components/Tabs/Vm/configuration.js
Normal file
@ -0,0 +1,41 @@
|
||||
import * as React from 'react'
|
||||
import { Accordion, AccordionSummary, AccordionDetails } from '@material-ui/core'
|
||||
|
||||
const NavArrowDown = <span style={{ writingMode: 'vertical-rl' }}>{'>'}</span>
|
||||
|
||||
const VmConfigurationTab = data => {
|
||||
const { TEMPLATE, USER_TEMPLATE } = data
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Accordion TransitionProps={{ unmountOnExit: true }}>
|
||||
<AccordionSummary expandIcon={NavArrowDown}>
|
||||
{'User Template'}
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<pre>
|
||||
<code>
|
||||
{JSON.stringify(USER_TEMPLATE, null, 2)}
|
||||
</code>
|
||||
</pre>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
<Accordion TransitionProps={{ unmountOnExit: true }}>
|
||||
<AccordionSummary expandIcon={NavArrowDown}>
|
||||
{'Template'}
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<pre>
|
||||
<code>
|
||||
{JSON.stringify(TEMPLATE, null, 2)}
|
||||
</code>
|
||||
</pre>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
VmConfigurationTab.displayName = 'VmConfigurationTab'
|
||||
|
||||
export default VmConfigurationTab
|
52
src/fireedge/src/client/components/Tabs/Vm/index.js
Normal file
52
src/fireedge/src/client/components/Tabs/Vm/index.js
Normal file
@ -0,0 +1,52 @@
|
||||
import * as React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import Tabs from 'client/components/Tabs'
|
||||
|
||||
const stringToCamelCase = s =>
|
||||
s.replace(
|
||||
/([-_][a-z])/ig,
|
||||
$1 => $1.toUpperCase()
|
||||
.replace('-', '')
|
||||
.replace('_', '')
|
||||
)
|
||||
|
||||
const stringToCamelSpace = s => s.replace(/([a-z])([A-Z])/g, '$1 $2')
|
||||
|
||||
const VmTabs = ({ data, tabs }) => {
|
||||
const [renderTabs, setTabs] = React.useState(() => [])
|
||||
|
||||
React.useEffect(() => {
|
||||
const loadTab = async tabKey => {
|
||||
try {
|
||||
const camelCaseKey = stringToCamelCase(tabKey)
|
||||
|
||||
// dynamic import => client/components/Tabs/Vm
|
||||
const tabComponent = await import(`./${camelCaseKey}`)
|
||||
|
||||
setTabs(prev => prev.concat([{
|
||||
name: stringToCamelSpace(camelCaseKey),
|
||||
renderContent: tabComponent.default(data)
|
||||
}]))
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
// reset
|
||||
setTabs([])
|
||||
|
||||
tabs?.forEach(loadTab)
|
||||
}, [tabs?.length])
|
||||
|
||||
return <Tabs tabs={renderTabs} />
|
||||
}
|
||||
|
||||
VmTabs.propTypes = {
|
||||
data: PropTypes.object.isRequired,
|
||||
tabs: PropTypes.arrayOf(
|
||||
PropTypes.string
|
||||
).isRequired
|
||||
}
|
||||
|
||||
VmTabs.displayName = 'VmTabs'
|
||||
|
||||
export default VmTabs
|
47
src/fireedge/src/client/components/Tabs/Vm/info.js
Normal file
47
src/fireedge/src/client/components/Tabs/Vm/info.js
Normal file
@ -0,0 +1,47 @@
|
||||
import * as React from 'react'
|
||||
import { StatusBadge } from 'client/components/Status'
|
||||
|
||||
import * as VirtualMachine from 'client/models/VirtualMachine'
|
||||
import * as Helper from 'client/models/Helper'
|
||||
|
||||
const VmInfoTab = data => {
|
||||
const { ID, NAME, UNAME, GNAME, RESCHED, STIME, ETIME, LOCK, DEPLOY_ID } = data
|
||||
|
||||
const { name: stateName, color: stateColor } = VirtualMachine.getState(data)
|
||||
|
||||
const { HID: hostId, HOSTNAME: hostname = '--', CID: clusterId } = VirtualMachine.getLastHistory(data)
|
||||
const clusterName = clusterId === '-1' ? 'default' : '--' // TODO: get from cluster list
|
||||
|
||||
const ips = VirtualMachine.getIps(data)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<p>
|
||||
<StatusBadge
|
||||
title={stateName}
|
||||
stateColor={stateColor}
|
||||
customTransform='translate(150%, 50%)'
|
||||
/>
|
||||
<span style={{ marginLeft: 20 }}>
|
||||
{`#${ID} - ${NAME}`}
|
||||
</span>
|
||||
</p>
|
||||
<div>
|
||||
<p>Owner: {UNAME}</p>
|
||||
<p>Group: {GNAME}</p>
|
||||
<p>Reschedule: {Helper.booleanToString(+RESCHED)}</p>
|
||||
<p>Locked: {Helper.levelLockToString(LOCK?.LOCKED)}</p>
|
||||
<p>IP: {ips.join(', ') || '--'}</p>
|
||||
<p>Start time: {Helper.timeToString(STIME)}</p>
|
||||
<p>End time: {Helper.timeToString(ETIME)}</p>
|
||||
<p>Host: {hostId ? `#${hostId} ${hostname}` : ''}</p>
|
||||
<p>Cluster: {clusterId ? `#${clusterId} ${clusterName}` : ''}</p>
|
||||
<p>Deploy ID: {DEPLOY_ID}</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
VmInfoTab.displayName = 'VmInfoTab'
|
||||
|
||||
export default VmInfoTab
|
13
src/fireedge/src/client/components/Tabs/Vm/log.js
Normal file
13
src/fireedge/src/client/components/Tabs/Vm/log.js
Normal file
@ -0,0 +1,13 @@
|
||||
import * as React from 'react'
|
||||
|
||||
const VmLogTab = data => {
|
||||
return (
|
||||
<div>
|
||||
<p>WIP - LOG</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
VmLogTab.displayName = 'VmLogTab'
|
||||
|
||||
export default VmLogTab
|
33
src/fireedge/src/client/components/Tabs/Vm/network.js
Normal file
33
src/fireedge/src/client/components/Tabs/Vm/network.js
Normal file
@ -0,0 +1,33 @@
|
||||
import * as React from 'react'
|
||||
|
||||
import * as VirtualMachine from 'client/models/VirtualMachine'
|
||||
|
||||
const VmNetworkTab = data => {
|
||||
const { nics, alias } = VirtualMachine.splitNicAlias(data)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
<p>VM NICS</p>
|
||||
{nics.map(({ NIC_ID, NETWORK = '-', BRIDGE = '-', IP = '-', MAC = '-', PCI_ID = '' }) => (
|
||||
<p key={NIC_ID}>
|
||||
{`${NIC_ID} | ${NETWORK} | ${BRIDGE} | ${IP} | ${MAC} | ${PCI_ID}`}
|
||||
</p>
|
||||
))}
|
||||
</div>
|
||||
<hr />
|
||||
<div>
|
||||
<p>VM ALIAS</p>
|
||||
{alias.map(({ NIC_ID, NETWORK = '-', BRIDGE = '-', IP = '-', MAC = '-' }) => (
|
||||
<p key={NIC_ID}>
|
||||
{`${NIC_ID} | ${NETWORK} | ${BRIDGE} | ${IP} | ${MAC}`}
|
||||
</p>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
VmNetworkTab.displayName = 'VmNetworkTab'
|
||||
|
||||
export default VmNetworkTab
|
13
src/fireedge/src/client/components/Tabs/Vm/placement.js
Normal file
13
src/fireedge/src/client/components/Tabs/Vm/placement.js
Normal file
@ -0,0 +1,13 @@
|
||||
import * as React from 'react'
|
||||
|
||||
const VmPlacementTab = data => {
|
||||
return (
|
||||
<div>
|
||||
<p>WIP - PLACEMENT</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
VmPlacementTab.displayName = 'VmPlacementTab'
|
||||
|
||||
export default VmPlacementTab
|
13
src/fireedge/src/client/components/Tabs/Vm/schedActions.js
Normal file
13
src/fireedge/src/client/components/Tabs/Vm/schedActions.js
Normal file
@ -0,0 +1,13 @@
|
||||
import * as React from 'react'
|
||||
|
||||
const VmSchedulingTab = data => {
|
||||
return (
|
||||
<div>
|
||||
<p>WIP - SCHED ACTIONS</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
VmSchedulingTab.displayName = 'VmSchedulingTab'
|
||||
|
||||
export default VmSchedulingTab
|
13
src/fireedge/src/client/components/Tabs/Vm/snapshot.js
Normal file
13
src/fireedge/src/client/components/Tabs/Vm/snapshot.js
Normal file
@ -0,0 +1,13 @@
|
||||
import * as React from 'react'
|
||||
|
||||
const VmSnapshotTab = data => {
|
||||
return (
|
||||
<div>
|
||||
<p>WIP - SNAPSHOT</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
VmSnapshotTab.displayName = 'VmSnapshotTab'
|
||||
|
||||
export default VmSnapshotTab
|
55
src/fireedge/src/client/components/Tabs/Vm/storage.js
Normal file
55
src/fireedge/src/client/components/Tabs/Vm/storage.js
Normal file
@ -0,0 +1,55 @@
|
||||
import * as React from 'react'
|
||||
|
||||
import * as VirtualMachine from 'client/models/VirtualMachine'
|
||||
import { prettyBytes } from 'client/utils'
|
||||
|
||||
const VmStorageTab = data => {
|
||||
const disks = VirtualMachine.getDisks(data)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<p>VM DISKS</p>
|
||||
{disks.map(({
|
||||
DISK_ID,
|
||||
DATASTORE = '-',
|
||||
TARGET = '-',
|
||||
IMAGE,
|
||||
TYPE,
|
||||
FORMAT,
|
||||
SIZE,
|
||||
MONITOR_SIZE,
|
||||
READONLY,
|
||||
SAVE = 'No',
|
||||
CLONE
|
||||
}) => {
|
||||
const size = +SIZE ? prettyBytes(+SIZE, 'MB') : '-'
|
||||
const monitorSize = +MONITOR_SIZE ? prettyBytes(+MONITOR_SIZE, 'MB') : '-'
|
||||
|
||||
const type = String(TYPE).toLowerCase()
|
||||
|
||||
const image = IMAGE ?? ({
|
||||
fs: `${FORMAT} - ${size}`,
|
||||
swap: size
|
||||
}[type])
|
||||
|
||||
return (
|
||||
<p key={DISK_ID}>
|
||||
{`${DISK_ID} |
|
||||
${DATASTORE} |
|
||||
${TARGET} |
|
||||
${image} |
|
||||
${monitorSize}/${size} |
|
||||
${type} |
|
||||
${READONLY} |
|
||||
${SAVE} |
|
||||
${CLONE}`}
|
||||
</p>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
VmStorageTab.displayName = 'VmStorageTab'
|
||||
|
||||
export default VmStorageTab
|
@ -36,7 +36,7 @@ const Tabs = ({ tabs = [], renderHiddenTabs = false }) => {
|
||||
/>
|
||||
)}
|
||||
</MTabs>
|
||||
), [tabSelected])
|
||||
), [tabs.length, tabSelected])
|
||||
|
||||
const renderAllHiddenTabContents = useMemo(() =>
|
||||
tabs.map((tabProps, idx) => {
|
||||
|
@ -5,7 +5,7 @@ import { Container, Box, Grid } from '@material-ui/core'
|
||||
|
||||
import { useAuth } from 'client/features/Auth'
|
||||
import { useFetchAll } from 'client/hooks'
|
||||
import { useVmApi, useUserApi, useImageApi, useVNetworkApi } from 'client/features/One'
|
||||
import { useUserApi, useImageApi, useVNetworkApi } from 'client/features/One'
|
||||
|
||||
import * as Widgets from 'client/components/Widgets'
|
||||
import dashboardStyles from 'client/containers/Dashboard/Provision/styles'
|
||||
@ -14,7 +14,6 @@ function Dashboard () {
|
||||
const { status, fetchRequestAll, STATUS } = useFetchAll()
|
||||
const { INIT, PENDING } = STATUS
|
||||
|
||||
const { getVms } = useVmApi()
|
||||
const { getUsers } = useUserApi()
|
||||
const { getImages } = useImageApi()
|
||||
const { getVNetworks } = useVNetworkApi()
|
||||
@ -26,7 +25,6 @@ function Dashboard () {
|
||||
|
||||
React.useEffect(() => {
|
||||
fetchRequestAll([
|
||||
getVms(),
|
||||
getUsers(),
|
||||
getImages(),
|
||||
getVNetworks()
|
||||
|
Loading…
x
Reference in New Issue
Block a user