mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-16 22:50:10 +03:00
F OpenNebula/one#5422: Add zones table
This commit is contained in:
parent
ffceed0cef
commit
e25b2ad18b
@ -16,11 +16,12 @@ import {
|
||||
|
||||
ServerConnection as NetworksIcon,
|
||||
NetworkAlt as NetworkIcon,
|
||||
Combine as NetworkTemplateIcon,
|
||||
KeyframesCouple as NetworkTemplateIcon,
|
||||
|
||||
CloudSync as InfrastructureIcon,
|
||||
Server as ClusterIcon,
|
||||
HardDrive as HostIcon,
|
||||
MinusPinAlt as ZoneIcon,
|
||||
|
||||
Home as SystemIcon,
|
||||
User as UserIcon,
|
||||
@ -53,7 +54,7 @@ const VNetworkTemplates = loadable(() => import('client/containers/VNetworkTempl
|
||||
|
||||
const Clusters = loadable(() => import('client/containers/Clusters'), { ssr: false })
|
||||
const Hosts = loadable(() => import('client/containers/Hosts'), { ssr: false })
|
||||
// const Zones = loadable(() => import('client/containers/Zones'), { ssr: false })
|
||||
const Zones = loadable(() => import('client/containers/Zones'), { ssr: false })
|
||||
|
||||
const Users = loadable(() => import('client/containers/Users'), { ssr: false })
|
||||
const Groups = loadable(() => import('client/containers/Groups'), { ssr: false })
|
||||
@ -106,6 +107,9 @@ export const PATH = {
|
||||
},
|
||||
HOSTS: {
|
||||
LIST: '/hosts'
|
||||
},
|
||||
ZONES: {
|
||||
LIST: '/zones'
|
||||
}
|
||||
},
|
||||
SYSTEM: {
|
||||
@ -229,6 +233,13 @@ export const ENDPOINTS = [
|
||||
sidebar: true,
|
||||
icon: HostIcon,
|
||||
Component: Hosts
|
||||
},
|
||||
{
|
||||
label: 'Zones',
|
||||
path: PATH.INFRASTRUCTURE.ZONES.LIST,
|
||||
sidebar: true,
|
||||
icon: ZoneIcon,
|
||||
Component: Zones
|
||||
}
|
||||
]
|
||||
},
|
||||
|
26
src/fireedge/src/client/components/Tables/Zones/columns.js
Normal file
26
src/fireedge/src/client/components/Tables/Zones/columns.js
Normal file
@ -0,0 +1,26 @@
|
||||
import CategoryFilter from 'client/components/Tables/Enhanced/Utils/CategoryFilter'
|
||||
import * as ZoneModel from 'client/models/Zone'
|
||||
|
||||
export default [
|
||||
{ Header: 'ID', accessor: 'ID', sortType: 'number' },
|
||||
{ Header: 'Name', accessor: 'NAME' },
|
||||
{
|
||||
Header: 'State',
|
||||
id: 'STATE',
|
||||
accessor: row => ZoneModel.getState(row)?.name,
|
||||
disableFilters: false,
|
||||
Filter: ({ column }) => CategoryFilter({
|
||||
column,
|
||||
multiple: true,
|
||||
title: 'State'
|
||||
}),
|
||||
filter: 'includesValue'
|
||||
},
|
||||
{
|
||||
Header: 'ENDPOINT',
|
||||
id: 'ENDPOINT',
|
||||
accessor: row => row?.TEMPLATE?.ENDPOINT,
|
||||
disableSortBy: true
|
||||
}
|
||||
|
||||
]
|
36
src/fireedge/src/client/components/Tables/Zones/index.js
Normal file
36
src/fireedge/src/client/components/Tables/Zones/index.js
Normal file
@ -0,0 +1,36 @@
|
||||
import React, { useEffect } from 'react'
|
||||
|
||||
import { useFetch } from 'client/hooks'
|
||||
import { useZone, useZoneApi } from 'client/features/One'
|
||||
|
||||
import { SkeletonTable, EnhancedTable } from 'client/components/Tables'
|
||||
import ZoneColumns from 'client/components/Tables/Zones/columns'
|
||||
import ZoneRow from 'client/components/Tables/Zones/row'
|
||||
|
||||
const ZonesTable = () => {
|
||||
const columns = React.useMemo(() => ZoneColumns, [])
|
||||
|
||||
const zones = useZone()
|
||||
const { getZones } = useZoneApi()
|
||||
|
||||
const { status, fetchRequest, loading, reloading, STATUS } = useFetch(getZones)
|
||||
const { INIT, PENDING } = STATUS
|
||||
|
||||
useEffect(() => { fetchRequest() }, [])
|
||||
|
||||
if (zones?.length === 0 && [INIT, PENDING].includes(status)) {
|
||||
return <SkeletonTable />
|
||||
}
|
||||
|
||||
return (
|
||||
<EnhancedTable
|
||||
columns={columns}
|
||||
data={zones}
|
||||
isLoading={loading || reloading}
|
||||
getRowId={row => String(row.ID)}
|
||||
RowComponent={ZoneRow}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default ZonesTable
|
50
src/fireedge/src/client/components/Tables/Zones/row.js
Normal file
50
src/fireedge/src/client/components/Tables/Zones/row.js
Normal file
@ -0,0 +1,50 @@
|
||||
import * as React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import { ShieldCheck } from 'iconoir-react'
|
||||
import { Typography } from '@material-ui/core'
|
||||
|
||||
import { StatusCircle } from 'client/components/Status'
|
||||
import { rowStyles } from 'client/components/Tables/styles'
|
||||
|
||||
import * as ZoneModel from 'client/models/Zone'
|
||||
|
||||
const Row = ({ original, value, ...props }) => {
|
||||
const classes = rowStyles()
|
||||
const { ID, NAME, ENDPOINT } = value
|
||||
|
||||
const { color: stateColor, name: stateName } = ZoneModel.getState(original)
|
||||
|
||||
return (
|
||||
<div {...props}>
|
||||
<div>
|
||||
<StatusCircle color={stateColor} tooltip={stateName} />
|
||||
</div>
|
||||
<div className={classes.main}>
|
||||
<div className={classes.title}>
|
||||
<Typography className={classes.titleText} component='span'>
|
||||
{NAME}
|
||||
</Typography>
|
||||
</div>
|
||||
<div className={classes.caption}>
|
||||
<span>
|
||||
{`#${ID}`}
|
||||
</span>
|
||||
<span title={`Endpoint: ${ENDPOINT}`}>
|
||||
<ShieldCheck size={16} />
|
||||
<span>{` ${ENDPOINT}`}</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Row.propTypes = {
|
||||
original: PropTypes.object,
|
||||
value: PropTypes.object,
|
||||
isSelected: PropTypes.bool,
|
||||
handleClick: PropTypes.func
|
||||
}
|
||||
|
||||
export default Row
|
@ -13,6 +13,7 @@ import VmsTable from 'client/components/Tables/Vms'
|
||||
import VmTemplatesTable from 'client/components/Tables/VmTemplates'
|
||||
import VNetworksTable from 'client/components/Tables/VNetworks'
|
||||
import VNetworkTemplatesTable from 'client/components/Tables/VNetworkTemplates'
|
||||
import ZoneTable from 'client/components/Tables/Zones'
|
||||
|
||||
export {
|
||||
SkeletonTable,
|
||||
@ -30,5 +31,6 @@ export {
|
||||
VmsTable,
|
||||
VmTemplatesTable,
|
||||
VNetworksTable,
|
||||
VNetworkTemplatesTable
|
||||
VNetworkTemplatesTable,
|
||||
ZoneTable
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ export const DISK_SNAPSHOT_REVERT_POWEROFF = 'DISK_SNAPSHOT_REVERT_POWEROFF'
|
||||
export const DISK_SNAPSHOT_REVERT_SUSPENDED = 'DISK_SNAPSHOT_REVERT_SUSPENDED'
|
||||
export const DISK_SNAPSHOT_SUSPENDED = 'DISK_SNAPSHOT_SUSPENDED'
|
||||
export const DONE = 'DONE'
|
||||
export const ENABLED = 'ENABLED'
|
||||
export const EPILOG = 'EPILOG'
|
||||
export const EPILOG_FAILURE = 'EPILOG_FAILURE'
|
||||
export const EPILOG_STOP = 'EPILOG_STOP'
|
||||
|
22
src/fireedge/src/client/containers/Zones/index.js
Normal file
22
src/fireedge/src/client/containers/Zones/index.js
Normal file
@ -0,0 +1,22 @@
|
||||
import * as React from 'react'
|
||||
|
||||
import { Container, Box } from '@material-ui/core'
|
||||
|
||||
import * as Tables from 'client/components/Tables'
|
||||
|
||||
function Zones () {
|
||||
return (
|
||||
<Box
|
||||
height={1}
|
||||
py={2}
|
||||
overflow='auto'
|
||||
display='flex'
|
||||
flexDirection='column'
|
||||
component={Container}
|
||||
>
|
||||
<Tables.ZoneTable />
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export default Zones
|
@ -20,3 +20,4 @@ export * from 'client/features/One/vm/hooks'
|
||||
export * from 'client/features/One/vmTemplate/hooks'
|
||||
export * from 'client/features/One/vnetwork/hooks'
|
||||
export * from 'client/features/One/vnetworkTemplate/hooks'
|
||||
export * from 'client/features/One/zone/hooks'
|
||||
|
14
src/fireedge/src/client/features/One/zone/actions.js
Normal file
14
src/fireedge/src/client/features/One/zone/actions.js
Normal file
@ -0,0 +1,14 @@
|
||||
import { createAction } from 'client/features/One/utils'
|
||||
import { zoneService } from 'client/features/One/zone/services'
|
||||
import { RESOURCES } from 'client/features/One/slice'
|
||||
|
||||
export const getZone = createAction(
|
||||
'zone/detail',
|
||||
zoneService.getZone
|
||||
)
|
||||
|
||||
export const getZones = createAction(
|
||||
'zone/pool',
|
||||
zoneService.getZones,
|
||||
response => ({ [RESOURCES.zone]: response })
|
||||
)
|
24
src/fireedge/src/client/features/One/zone/hooks.js
Normal file
24
src/fireedge/src/client/features/One/zone/hooks.js
Normal file
@ -0,0 +1,24 @@
|
||||
import { useCallback } from 'react'
|
||||
import { useDispatch, useSelector } from 'react-redux'
|
||||
import { unwrapResult } from '@reduxjs/toolkit'
|
||||
|
||||
import * as actions from 'client/features/One/zone/actions'
|
||||
import { RESOURCES } from 'client/features/One/slice'
|
||||
|
||||
export const useZone = () => (
|
||||
useSelector(state => state.one[RESOURCES.zone])
|
||||
)
|
||||
|
||||
export const useZoneApi = () => {
|
||||
const dispatch = useDispatch()
|
||||
|
||||
const unwrapDispatch = useCallback(
|
||||
action => dispatch(action).then(unwrapResult)
|
||||
, [dispatch]
|
||||
)
|
||||
|
||||
return {
|
||||
getZone: id => unwrapDispatch(actions.getZone({ id })),
|
||||
getZones: () => unwrapDispatch(actions.getZones())
|
||||
}
|
||||
}
|
25
src/fireedge/src/client/features/One/zone/services.js
Normal file
25
src/fireedge/src/client/features/One/zone/services.js
Normal file
@ -0,0 +1,25 @@
|
||||
import { Actions, Commands } from 'server/utils/constants/commands/zone'
|
||||
import { httpCodes } from 'server/utils/constants'
|
||||
import { requestParams, RestClient } from 'client/utils'
|
||||
import { poolRequest } from 'client/features/One/utils'
|
||||
|
||||
export const zoneService = ({
|
||||
getZone: ({ filter, id }) => {
|
||||
const name = Actions.ZONE_INFO
|
||||
const { url, options } = requestParams(
|
||||
{ filter, id },
|
||||
{ name, ...Commands[name] }
|
||||
)
|
||||
|
||||
return RestClient.get(url, options).then(res => {
|
||||
if (!res?.id || res?.id !== httpCodes.ok.id) throw res
|
||||
|
||||
return res?.data?.ZONE ?? {}
|
||||
})
|
||||
},
|
||||
getZones: data => {
|
||||
const name = Actions.ZONE_POOL_INFO
|
||||
const command = { name, ...Commands[name] }
|
||||
return poolRequest(data, command, 'ZONE')
|
||||
}
|
||||
})
|
15
src/fireedge/src/client/models/Zone.js
Normal file
15
src/fireedge/src/client/models/Zone.js
Normal file
@ -0,0 +1,15 @@
|
||||
import * as STATES from 'client/constants/states'
|
||||
import COLOR from 'client/constants/color'
|
||||
|
||||
const ZONE_STATES = [
|
||||
{ // 0
|
||||
name: STATES.ENABLED,
|
||||
color: COLOR.success.main
|
||||
},
|
||||
{ // 1
|
||||
name: STATES.DISABLED,
|
||||
color: COLOR.debug.main
|
||||
}
|
||||
]
|
||||
|
||||
export const getState = ({ STATE = 0 } = {}) => ZONE_STATES[+STATE]
|
@ -16,15 +16,15 @@
|
||||
const {
|
||||
from: { resource, postBody, query },
|
||||
httpMethod: { GET, POST, PUT, DELETE }
|
||||
} = require('../defaults');
|
||||
} = require('../defaults')
|
||||
|
||||
const ZONE_ALLOCATE = 'zone.allocate';
|
||||
const ZONE_DELETE = 'zone.delete';
|
||||
const ZONE_UPDATE = 'zone.update';
|
||||
const ZONE_RENAME = 'zone.rename';
|
||||
const ZONE_INFO = 'zone.info';
|
||||
const ZONE_RAFTSTATUS = 'zone.raftstatus';
|
||||
const ZONEPOOL_INFO = 'zonepool.info';
|
||||
const ZONE_ALLOCATE = 'zone.allocate'
|
||||
const ZONE_DELETE = 'zone.delete'
|
||||
const ZONE_UPDATE = 'zone.update'
|
||||
const ZONE_RENAME = 'zone.rename'
|
||||
const ZONE_INFO = 'zone.info'
|
||||
const ZONE_RAFTSTATUS = 'zone.raftstatus'
|
||||
const ZONE_POOL_INFO = 'zonepool.info'
|
||||
|
||||
const Actions = {
|
||||
ZONE_ALLOCATE,
|
||||
@ -33,8 +33,8 @@ const Actions = {
|
||||
ZONE_RENAME,
|
||||
ZONE_INFO,
|
||||
ZONE_RAFTSTATUS,
|
||||
ZONEPOOL_INFO
|
||||
};
|
||||
ZONE_POOL_INFO
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
Actions,
|
||||
@ -110,10 +110,10 @@ module.exports = {
|
||||
httpMethod: GET,
|
||||
params: {}
|
||||
},
|
||||
[ZONEPOOL_INFO]: {
|
||||
[ZONE_POOL_INFO]: {
|
||||
// inspected
|
||||
httpMethod: GET,
|
||||
params: {}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user