mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-16 22:50:10 +03:00
F OpenNebula/one#5422: Add vrouters table
This commit is contained in:
parent
e25b2ad18b
commit
bda9ecedcc
@ -4,6 +4,7 @@ import {
|
||||
|
||||
Cell4x4 as InstancesIcons,
|
||||
ModernTv as VmsIcons,
|
||||
Shuffle as VRoutersIcons,
|
||||
|
||||
Archive as TemplatesIcon,
|
||||
GoogleDocs as TemplateIcon,
|
||||
@ -35,7 +36,7 @@ const Dashboard = loadable(() => import('client/containers/Dashboard/Sunstone'),
|
||||
const Settings = loadable(() => import('client/containers/Settings'), { ssr: false })
|
||||
|
||||
const VirtualMachines = loadable(() => import('client/containers/VirtualMachines'), { ssr: false })
|
||||
// const VirtualRouters = loadable(() => import('client/containers/VirtualRouters'), { ssr: false })
|
||||
const VirtualRouters = loadable(() => import('client/containers/VirtualRouters'), { ssr: false })
|
||||
|
||||
const VmTemplates = loadable(() => import('client/containers/VmTemplates'), { ssr: false })
|
||||
// const VrTemplates = loadable(() => import('client/containers/VrTemplates'), { ssr: false })
|
||||
@ -66,6 +67,9 @@ export const PATH = {
|
||||
INSTANCE: {
|
||||
VMS: {
|
||||
LIST: '/vms'
|
||||
},
|
||||
VROUTERS: {
|
||||
LIST: '/virtual-routers'
|
||||
}
|
||||
},
|
||||
TEMPLATE: {
|
||||
@ -142,6 +146,13 @@ export const ENDPOINTS = [
|
||||
sidebar: true,
|
||||
icon: VmsIcons,
|
||||
Component: VirtualMachines
|
||||
},
|
||||
{
|
||||
label: 'Virtual Routers',
|
||||
path: PATH.INSTANCE.VROUTERS.LIST,
|
||||
sidebar: true,
|
||||
icon: VRoutersIcons,
|
||||
Component: VirtualRouters
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -60,7 +60,7 @@ const CategoryFilter = ({ title, column, accessorOption, multiple }) => {
|
||||
>
|
||||
{Tr(title)}
|
||||
{isFiltered && (
|
||||
<IconButton disableRipple disablePadding size='small' onClick={handleClear}>
|
||||
<IconButton disableRipple size='small' onClick={handleClear}>
|
||||
<Cancel/>
|
||||
</IconButton>
|
||||
)}
|
||||
|
@ -0,0 +1,19 @@
|
||||
const getTotalOfResources = resources => [resources?.ID ?? []].flat().length || 0
|
||||
|
||||
export default [
|
||||
{ Header: 'ID', accessor: 'ID', sortType: 'number' },
|
||||
{ Header: 'Name', accessor: 'NAME' },
|
||||
{ Header: 'Owner', accessor: 'UNAME' },
|
||||
{ Header: 'Group', accessor: 'GNAME' },
|
||||
{
|
||||
Header: 'Total VMs',
|
||||
id: 'VMS',
|
||||
accessor: row => getTotalOfResources(row?.VMS),
|
||||
sortType: 'number'
|
||||
},
|
||||
{
|
||||
Header: 'Group',
|
||||
id: 'TEMPLATE_ID',
|
||||
accessor: row => row?.TEMPLATE?.TEMPLATE_ID
|
||||
}
|
||||
]
|
36
src/fireedge/src/client/components/Tables/VRouters/index.js
Normal file
36
src/fireedge/src/client/components/Tables/VRouters/index.js
Normal file
@ -0,0 +1,36 @@
|
||||
import React, { useEffect } from 'react'
|
||||
|
||||
import { useFetch } from 'client/hooks'
|
||||
import { useVRouter, useVRouterApi } from 'client/features/One'
|
||||
|
||||
import { SkeletonTable, EnhancedTable } from 'client/components/Tables'
|
||||
import VRouterColumns from 'client/components/Tables/VRouters/columns'
|
||||
import VRouterRow from 'client/components/Tables/VRouters/row'
|
||||
|
||||
const VRoutersTable = () => {
|
||||
const columns = React.useMemo(() => VRouterColumns, [])
|
||||
|
||||
const vRouters = useVRouter()
|
||||
const { getVRouters } = useVRouterApi()
|
||||
|
||||
const { status, fetchRequest, loading, reloading, STATUS } = useFetch(getVRouters)
|
||||
const { INIT, PENDING } = STATUS
|
||||
|
||||
useEffect(() => { fetchRequest() }, [])
|
||||
|
||||
if (vRouters?.length === 0 && [INIT, PENDING].includes(status)) {
|
||||
return <SkeletonTable />
|
||||
}
|
||||
|
||||
return (
|
||||
<EnhancedTable
|
||||
columns={columns}
|
||||
data={vRouters}
|
||||
isLoading={loading || reloading}
|
||||
getRowId={row => String(row.ID)}
|
||||
RowComponent={VRouterRow}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default VRoutersTable
|
54
src/fireedge/src/client/components/Tables/VRouters/row.js
Normal file
54
src/fireedge/src/client/components/Tables/VRouters/row.js
Normal file
@ -0,0 +1,54 @@
|
||||
import * as React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import { User, Group, EmptyPage, ModernTv } from 'iconoir-react'
|
||||
import { Typography } from '@material-ui/core'
|
||||
|
||||
import { rowStyles } from 'client/components/Tables/styles'
|
||||
|
||||
const Row = ({ original, value, ...props }) => {
|
||||
const classes = rowStyles()
|
||||
const { ID, NAME, UNAME, GNAME, VMS, TEMPLATE_ID } = value
|
||||
|
||||
return (
|
||||
<div {...props}>
|
||||
<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={`Owner: ${UNAME}`}>
|
||||
<User size={16} />
|
||||
<span>{` ${UNAME}`}</span>
|
||||
</span>
|
||||
<span title={`Group: ${GNAME}`}>
|
||||
<Group size={16} />
|
||||
<span>{` ${GNAME}`}</span>
|
||||
</span>
|
||||
<span title={`Template ID: ${TEMPLATE_ID}`}>
|
||||
<EmptyPage size={16} />
|
||||
<span>{` ${TEMPLATE_ID}`}</span>
|
||||
</span>
|
||||
<span title={`Total VMs: ${VMS}`}>
|
||||
<ModernTv size={16} />
|
||||
<span>{` ${VMS}`}</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Row.propTypes = {
|
||||
original: PropTypes.object,
|
||||
value: PropTypes.object,
|
||||
isSelected: PropTypes.bool,
|
||||
handleClick: PropTypes.func
|
||||
}
|
||||
|
||||
export default Row
|
@ -1,8 +1,23 @@
|
||||
import CategoryFilter from 'client/components/Tables/Enhanced/Utils/CategoryFilter'
|
||||
import * as Helper from 'client/models/Helper'
|
||||
|
||||
export default [
|
||||
{ Header: 'ID', accessor: 'ID', sortType: 'number' },
|
||||
{ Header: 'Name', accessor: 'NAME' },
|
||||
{ Header: 'Owner', accessor: 'UNAME' },
|
||||
{ Header: 'Group', accessor: 'GNAME' },
|
||||
{ Header: 'Start Time', accessor: 'REGTIME' },
|
||||
{ Header: 'Locked', accessor: 'LOCK' }
|
||||
{ Header: 'Locked', accessor: 'LOCK' },
|
||||
{
|
||||
Header: 'Virtual Router',
|
||||
id: 'VROUTER',
|
||||
accessor: row =>
|
||||
Helper.stringToBoolean(row?.TEMPLATE?.VROUTER) && 'VROUTER',
|
||||
disableFilters: false,
|
||||
Filter: ({ column }) => CategoryFilter({
|
||||
column,
|
||||
title: 'Virtual Router'
|
||||
}),
|
||||
filter: 'exact'
|
||||
}
|
||||
]
|
||||
|
@ -4,13 +4,14 @@ import PropTypes from 'prop-types'
|
||||
import { User, Group, Lock } from 'iconoir-react'
|
||||
import { Typography } from '@material-ui/core'
|
||||
|
||||
import { StatusChip } from 'client/components/Status'
|
||||
import { rowStyles } from 'client/components/Tables/styles'
|
||||
|
||||
import * as Helper from 'client/models/Helper'
|
||||
|
||||
const Row = ({ original, value, ...props }) => {
|
||||
const classes = rowStyles()
|
||||
const { ID, NAME, UNAME, GNAME, REGTIME, LOCK } = value
|
||||
const { ID, NAME, UNAME, GNAME, REGTIME, LOCK, VROUTER } = value
|
||||
|
||||
const time = Helper.timeFromMilliseconds(+REGTIME)
|
||||
const timeAgo = `registered ${time.toRelative()}`
|
||||
@ -24,6 +25,7 @@ const Row = ({ original, value, ...props }) => {
|
||||
</Typography>
|
||||
<span className={classes.labels}>
|
||||
{LOCK && <Lock size={20} />}
|
||||
{VROUTER && <StatusChip stateColor={'#c6c6c6'} text={VROUTER} />}
|
||||
</span>
|
||||
</div>
|
||||
<div className={classes.caption}>
|
||||
|
@ -13,7 +13,8 @@ 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'
|
||||
import VRoutersTable from 'client/components/Tables/VRouters'
|
||||
import ZonesTable from 'client/components/Tables/Zones'
|
||||
|
||||
export {
|
||||
SkeletonTable,
|
||||
@ -32,5 +33,6 @@ export {
|
||||
VmTemplatesTable,
|
||||
VNetworksTable,
|
||||
VNetworkTemplatesTable,
|
||||
ZoneTable
|
||||
VRoutersTable,
|
||||
ZonesTable
|
||||
}
|
||||
|
22
src/fireedge/src/client/containers/VirtualRouters/index.js
Normal file
22
src/fireedge/src/client/containers/VirtualRouters/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 VirtualRouters () {
|
||||
return (
|
||||
<Box
|
||||
height={1}
|
||||
py={2}
|
||||
overflow='auto'
|
||||
display='flex'
|
||||
flexDirection='column'
|
||||
component={Container}
|
||||
>
|
||||
<Tables.VRoutersTable />
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export default VirtualRouters
|
@ -14,7 +14,7 @@ function Zones () {
|
||||
flexDirection='column'
|
||||
component={Container}
|
||||
>
|
||||
<Tables.ZoneTable />
|
||||
<Tables.ZonesTable />
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
@ -20,4 +20,5 @@ 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/vrouter/hooks'
|
||||
export * from 'client/features/One/zone/hooks'
|
||||
|
@ -27,6 +27,7 @@ const RESOURCES = {
|
||||
vmgroup: 'vmGroups',
|
||||
vn: 'vNetworks',
|
||||
vntemplate: 'vNetworksTemplates',
|
||||
vrouter: 'vRouters',
|
||||
zone: 'zones',
|
||||
document: {
|
||||
100: 'applications',
|
||||
@ -58,6 +59,7 @@ const initial = {
|
||||
[RESOURCES.vmgroup]: [],
|
||||
[RESOURCES.vn]: [],
|
||||
[RESOURCES.vntemplate]: [],
|
||||
[RESOURCES.vrouter]: [],
|
||||
[RESOURCES.zone]: [],
|
||||
[RESOURCES.document[100]]: [],
|
||||
[RESOURCES.document[101]]: [],
|
||||
|
14
src/fireedge/src/client/features/One/vrouter/actions.js
Normal file
14
src/fireedge/src/client/features/One/vrouter/actions.js
Normal file
@ -0,0 +1,14 @@
|
||||
import { createAction } from 'client/features/One/utils'
|
||||
import { vRouterService } from 'client/features/One/vrouter/services'
|
||||
import { RESOURCES } from 'client/features/One/slice'
|
||||
|
||||
export const getVRouter = createAction(
|
||||
'vrouter/detail',
|
||||
vRouterService.getVRouter
|
||||
)
|
||||
|
||||
export const getVRouters = createAction(
|
||||
'vrouter/pool',
|
||||
vRouterService.getVRouters,
|
||||
response => ({ [RESOURCES.vrouter]: response })
|
||||
)
|
24
src/fireedge/src/client/features/One/vrouter/hooks.js
Normal file
24
src/fireedge/src/client/features/One/vrouter/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/vrouter/actions'
|
||||
import { RESOURCES } from 'client/features/One/slice'
|
||||
|
||||
export const useVRouter = () => (
|
||||
useSelector(state => state.one[RESOURCES.vrouter])
|
||||
)
|
||||
|
||||
export const useVRouterApi = () => {
|
||||
const dispatch = useDispatch()
|
||||
|
||||
const unwrapDispatch = useCallback(
|
||||
action => dispatch(action).then(unwrapResult)
|
||||
, [dispatch]
|
||||
)
|
||||
|
||||
return {
|
||||
getVRouter: id => unwrapDispatch(actions.getVRouter({ id })),
|
||||
getVRouters: () => unwrapDispatch(actions.getVRouters())
|
||||
}
|
||||
}
|
25
src/fireedge/src/client/features/One/vrouter/services.js
Normal file
25
src/fireedge/src/client/features/One/vrouter/services.js
Normal file
@ -0,0 +1,25 @@
|
||||
import { Actions, Commands } from 'server/utils/constants/commands/vrouter'
|
||||
import { httpCodes } from 'server/utils/constants'
|
||||
import { requestParams, RestClient } from 'client/utils'
|
||||
import { poolRequest } from 'client/features/One/utils'
|
||||
|
||||
export const vRouterService = ({
|
||||
getVRouter: ({ filter, id }) => {
|
||||
const name = Actions.VROUTER_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?.VROUTER ?? {}
|
||||
})
|
||||
},
|
||||
getVRouters: data => {
|
||||
const name = Actions.VROUTER_POOL_INFO
|
||||
const command = { name, ...Commands[name] }
|
||||
return poolRequest(data, command, 'VROUTER')
|
||||
}
|
||||
})
|
@ -2,6 +2,9 @@ import { DateTime } from 'luxon'
|
||||
|
||||
export const booleanToString = bool => bool ? 'Yes' : 'No'
|
||||
|
||||
export const stringToBoolean = str =>
|
||||
String(str).toLowerCase() === 'yes' || +str === 1
|
||||
|
||||
export const timeToString = time =>
|
||||
+time ? new Date(+time * 1000).toLocaleString() : '-'
|
||||
|
||||
|
@ -16,21 +16,21 @@
|
||||
const {
|
||||
from: { resource, postBody, query },
|
||||
httpMethod: { GET, POST, PUT, DELETE }
|
||||
} = require('../defaults');
|
||||
} = require('../defaults')
|
||||
|
||||
const VROUTER_ALLOCATE = 'vrouter.allocate';
|
||||
const VROUTER_DELETE = 'vrouter.delete';
|
||||
const VROUTER_INSTANTIATE = 'vrouter.instantiate';
|
||||
const VROUTER_NIC_ATTACH = 'vrouter.attachnic';
|
||||
const VROUTER_NIC_DETACH = 'vrouter.detachnic';
|
||||
const VROUTER_UPDATE = 'vrouter.update';
|
||||
const VROUTER_CHMOD = 'vrouter.chmod';
|
||||
const VROUTER_CHOWN = 'vrouter.chown';
|
||||
const VROUTER_RENAME = 'vrouter.rename';
|
||||
const VROUTER_INFO = 'vrouter.info';
|
||||
const VROUTER_LOCK = 'vrouter.lock';
|
||||
const VROUTER_UNLOCK = 'vrouter.unlock';
|
||||
const VROUTER_POOL_INFO = 'vrouterpool.info';
|
||||
const VROUTER_ALLOCATE = 'vrouter.allocate'
|
||||
const VROUTER_DELETE = 'vrouter.delete'
|
||||
const VROUTER_INSTANTIATE = 'vrouter.instantiate'
|
||||
const VROUTER_NIC_ATTACH = 'vrouter.attachnic'
|
||||
const VROUTER_NIC_DETACH = 'vrouter.detachnic'
|
||||
const VROUTER_UPDATE = 'vrouter.update'
|
||||
const VROUTER_CHMOD = 'vrouter.chmod'
|
||||
const VROUTER_CHOWN = 'vrouter.chown'
|
||||
const VROUTER_RENAME = 'vrouter.rename'
|
||||
const VROUTER_INFO = 'vrouter.info'
|
||||
const VROUTER_LOCK = 'vrouter.lock'
|
||||
const VROUTER_UNLOCK = 'vrouter.unlock'
|
||||
const VROUTER_POOL_INFO = 'vrouterpool.info'
|
||||
|
||||
const Actions = {
|
||||
VROUTER_ALLOCATE,
|
||||
@ -46,7 +46,7 @@ const Actions = {
|
||||
VROUTER_LOCK,
|
||||
VROUTER_UNLOCK,
|
||||
VROUTER_POOL_INFO
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
Actions,
|
||||
@ -286,4 +286,4 @@ module.exports = {
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user