mirror of
https://github.com/OpenNebula/one.git
synced 2025-03-16 22:50:10 +03:00
F OpenNebula/one#5422: Add sunstone app
This commit is contained in:
parent
1cc50546ca
commit
09bd5cbf7c
@ -28,7 +28,7 @@ import { _APPS } from 'client/constants'
|
||||
const APP_NAME = _APPS.provision.name
|
||||
|
||||
const ProvisionApp = () => {
|
||||
const { jwt, firstRender } = useAuth()
|
||||
const { isLogged, jwt, firstRender } = useAuth()
|
||||
const { getAuthUser, logout } = useAuthApi()
|
||||
|
||||
const provisionTemplate = useProvisionTemplate()
|
||||
@ -39,6 +39,7 @@ const ProvisionApp = () => {
|
||||
(async () => {
|
||||
try {
|
||||
if (jwt) {
|
||||
changeTitle(APP_NAME)
|
||||
getAuthUser()
|
||||
!provisionTemplate?.length && await getProvisionsTemplates()
|
||||
}
|
||||
@ -48,15 +49,11 @@ const ProvisionApp = () => {
|
||||
})()
|
||||
}, [jwt])
|
||||
|
||||
React.useEffect(() => {
|
||||
changeTitle(APP_NAME)
|
||||
}, [])
|
||||
|
||||
if (jwt && firstRender) {
|
||||
return <LoadingScreen />
|
||||
}
|
||||
|
||||
return <Router routes={routes} />
|
||||
return <Router isLogged={isLogged} routes={routes} />
|
||||
}
|
||||
|
||||
ProvisionApp.displayName = '_ProvisionApp'
|
||||
|
@ -29,8 +29,7 @@ export const PATH = {
|
||||
CREATE: '/provisions/create',
|
||||
EDIT: '/provisions/edit/:id'
|
||||
},
|
||||
SETTINGS: '/settings',
|
||||
TEST_API: '/test-api'
|
||||
SETTINGS: '/settings'
|
||||
}
|
||||
|
||||
export const ENDPOINTS = [
|
||||
|
@ -16,45 +16,37 @@
|
||||
import * as React from 'react'
|
||||
|
||||
import Router from 'client/router'
|
||||
import routes from 'client/apps/flow/routes'
|
||||
import routes from 'client/apps/sunstone/routes'
|
||||
|
||||
import { useGeneralApi } from 'client/features/General'
|
||||
import { useAuth, useAuthApi } from 'client/features/Auth'
|
||||
|
||||
import LoadingScreen from 'client/components/LoadingScreen'
|
||||
import { fakeDelay } from 'client/utils'
|
||||
import { _APPS, TIME_HIDE_LOGO } from 'client/constants'
|
||||
import { _APPS } from 'client/constants'
|
||||
|
||||
const APP_NAME = _APPS.sunstone.name
|
||||
|
||||
const SunstoneApp = () => {
|
||||
const [firstRender, setFirstRender] = React.useState(() => true)
|
||||
|
||||
const { jwt } = useAuth()
|
||||
const { getAuthUser } = useAuthApi()
|
||||
const { isLogged, jwt, firstRender } = useAuth()
|
||||
const { getAuthUser, logout } = useAuthApi()
|
||||
const { changeTitle } = useGeneralApi()
|
||||
|
||||
React.useEffect(() => {
|
||||
if (firstRender) {
|
||||
jwt && (async () => {
|
||||
await getAuthUser()
|
||||
})()
|
||||
(async () => {
|
||||
try {
|
||||
jwt && changeTitle(APP_NAME)
|
||||
jwt && getAuthUser()
|
||||
} catch {
|
||||
logout()
|
||||
}
|
||||
})()
|
||||
}, [jwt])
|
||||
|
||||
fakeDelay(TIME_HIDE_LOGO).then(() => setFirstRender(false))
|
||||
}
|
||||
}, [firstRender, jwt])
|
||||
|
||||
React.useEffect(() => {
|
||||
changeTitle(APP_NAME)
|
||||
}, [])
|
||||
|
||||
if (firstRender) {
|
||||
if (jwt && firstRender) {
|
||||
return <LoadingScreen />
|
||||
}
|
||||
|
||||
return (
|
||||
<Router routes={routes} />
|
||||
)
|
||||
return <Router isLogged={isLogged} routes={routes} />
|
||||
}
|
||||
|
||||
SunstoneApp.displayName = '_SunstoneApp'
|
@ -23,24 +23,24 @@ import MuiProvider from 'client/providers/muiProvider'
|
||||
import NotistackProvider from 'client/providers/notistackProvider'
|
||||
import { TranslateProvider } from 'client/components/HOC'
|
||||
|
||||
import App from 'client/apps/flow/_app'
|
||||
import theme from 'client/apps/flow/theme'
|
||||
import App from 'client/apps/sunstone/_app'
|
||||
import theme from 'client/apps/sunstone/theme'
|
||||
import { _APPS, APP_URL } from 'client/constants'
|
||||
|
||||
const APP_NAME = _APPS.sunstone.name
|
||||
|
||||
const Sunstone = ({ store, location, context }) => (
|
||||
const Provision = ({ store, location, context }) => (
|
||||
<ReduxProvider store={store}>
|
||||
<TranslateProvider>
|
||||
<MuiProvider theme={theme}>
|
||||
<NotistackProvider>
|
||||
{location && context ? (
|
||||
// server build
|
||||
// server build
|
||||
<StaticRouter location={location} context={context}>
|
||||
<App />
|
||||
</StaticRouter>
|
||||
) : (
|
||||
// browser build
|
||||
// browser build
|
||||
<BrowserRouter basename={`${APP_URL}/${APP_NAME}`}>
|
||||
<App />
|
||||
</BrowserRouter>
|
||||
@ -51,18 +51,18 @@ const Sunstone = ({ store, location, context }) => (
|
||||
</ReduxProvider>
|
||||
)
|
||||
|
||||
Sunstone.propTypes = {
|
||||
Provision.propTypes = {
|
||||
location: PropTypes.string,
|
||||
context: PropTypes.shape({}),
|
||||
store: PropTypes.shape({})
|
||||
}
|
||||
|
||||
Sunstone.defaultProps = {
|
||||
Provision.defaultProps = {
|
||||
location: '',
|
||||
context: {},
|
||||
store: {}
|
||||
}
|
||||
|
||||
Sunstone.displayName = 'SunstoneApp'
|
||||
Provision.displayName = 'SunstoneApp'
|
||||
|
||||
export default Sunstone
|
||||
export default Provision
|
@ -1,21 +1,10 @@
|
||||
import {
|
||||
ReportColumns as DashboardIcon,
|
||||
List as TemplatesIcons,
|
||||
Cell4x4 as InstancesIcons
|
||||
} from 'iconoir-react'
|
||||
|
||||
import loadable from '@loadable/component'
|
||||
|
||||
const Dashboard = loadable(
|
||||
() => import('client/containers/Dashboard'),
|
||||
{ ssr: false }
|
||||
)
|
||||
|
||||
const Settings = loadable(
|
||||
() => import('client/containers/Settings'),
|
||||
{ ssr: false }
|
||||
)
|
||||
|
||||
const ApplicationsTemplates = loadable(
|
||||
() => import('client/containers/ApplicationsTemplates'),
|
||||
{ ssr: false }
|
||||
@ -32,7 +21,6 @@ const ApplicationsTemplatesFormCreate = loadable(
|
||||
)
|
||||
|
||||
export const PATH = {
|
||||
DASHBOARD: '/dashboard',
|
||||
APPLICATIONS_TEMPLATES: {
|
||||
LIST: '/applications-templates',
|
||||
CREATE: '/applications-templates/create',
|
||||
@ -40,26 +28,12 @@ export const PATH = {
|
||||
},
|
||||
APPLICATIONS: {
|
||||
LIST: '/applications'
|
||||
},
|
||||
SETTINGS: '/settings'
|
||||
}
|
||||
}
|
||||
|
||||
export const ENDPOINTS = [
|
||||
{
|
||||
label: 'Dashboard',
|
||||
path: PATH.DASHBOARD,
|
||||
sidebar: true,
|
||||
icon: DashboardIcon,
|
||||
Component: Dashboard
|
||||
},
|
||||
{
|
||||
label: 'Settings',
|
||||
path: PATH.SETTINGS,
|
||||
header: true,
|
||||
Component: Settings
|
||||
},
|
||||
{
|
||||
label: 'Templates',
|
||||
label: 'Service Templates',
|
||||
path: PATH.APPLICATIONS_TEMPLATES.LIST,
|
||||
sidebar: true,
|
||||
icon: TemplatesIcons,
|
||||
@ -76,7 +50,7 @@ export const ENDPOINTS = [
|
||||
Component: ApplicationsTemplatesFormCreate
|
||||
},
|
||||
{
|
||||
label: 'Instances',
|
||||
label: 'Service Instances',
|
||||
path: PATH.APPLICATIONS.LIST,
|
||||
sidebar: true,
|
||||
icon: InstancesIcons,
|
225
src/fireedge/src/client/apps/sunstone/routes.js
Normal file
225
src/fireedge/src/client/apps/sunstone/routes.js
Normal file
@ -0,0 +1,225 @@
|
||||
import {
|
||||
ReportColumns as DashboardIcon,
|
||||
Settings as SettingsIcon,
|
||||
Cell4x4 as InstancesIcons,
|
||||
User as UserIcon,
|
||||
SimpleCart as MarketplaceIcon,
|
||||
CloudDownload as MarketplaceAppIcon,
|
||||
EmptyPage as TemplateIcon,
|
||||
Server as ClusterIcon,
|
||||
HardDrive as HostIcon,
|
||||
Folder as DatastoreIcon,
|
||||
Group as GroupIcon,
|
||||
Archive as ImageIcon,
|
||||
NetworkAlt as NetworkIcon
|
||||
} from 'iconoir-react'
|
||||
|
||||
import loadable from '@loadable/component'
|
||||
|
||||
const Dashboard = loadable(() => import('client/containers/Dashboard/Sunstone'), { ssr: false })
|
||||
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 VmTemplates = loadable(() => import('client/containers/VmTemplates'), { ssr: false })
|
||||
// const VrTemplates = loadable(() => import('client/containers/VrTemplates'), { ssr: false })
|
||||
// const VmGroups = loadable(() => import('client/containers/VmGroups'), { ssr: false })
|
||||
|
||||
const Datastores = loadable(() => import('client/containers/Datastores'), { ssr: false })
|
||||
const Images = loadable(() => import('client/containers/Images'), { ssr: false })
|
||||
// const Files = loadable(() => import('client/containers/Files'), { ssr: false })
|
||||
const Marketplaces = loadable(() => import('client/containers/Marketplaces'), { ssr: false })
|
||||
const MarketplaceApps = loadable(() => import('client/containers/MarketplaceApps'), { ssr: false })
|
||||
|
||||
// const VirtualNetworks = loadable(() => import('client/containers/VirtualNetworks'), { ssr: false })
|
||||
// const NetworkTemplates = loadable(() => import('client/containers/NetworkTemplates'), { ssr: false })
|
||||
// const NetworkTopologies = loadable(() => import('client/containers/NetworkTopologies'), { ssr: false })
|
||||
// const SecurityGroups = loadable(() => import('client/containers/SecurityGroups'), { ssr: false })
|
||||
|
||||
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 Users = loadable(() => import('client/containers/Users'), { ssr: false })
|
||||
const Groups = loadable(() => import('client/containers/Groups'), { ssr: false })
|
||||
// const VDCs = loadable(() => import('client/containers/VDCs'), { ssr: false })
|
||||
// const ACLs = loadable(() => import('client/containers/ACLs'), { ssr: false })
|
||||
|
||||
export const PATH = {
|
||||
DASHBOARD: '/dashboard',
|
||||
INSTANCE: {
|
||||
VMS: {
|
||||
LIST: '/vms'
|
||||
}
|
||||
},
|
||||
TEMPLATE: {
|
||||
VMS: {
|
||||
LIST: '/vm-templates'
|
||||
}
|
||||
},
|
||||
STORAGE: {
|
||||
DATASTORES: {
|
||||
LIST: '/datastores'
|
||||
},
|
||||
IMAGES: {
|
||||
LIST: '/images'
|
||||
},
|
||||
FILES: {
|
||||
LIST: '/files'
|
||||
},
|
||||
MARKETPLACES: {
|
||||
LIST: '/marketplaces'
|
||||
},
|
||||
MARKETPLACE_APPS: {
|
||||
LIST: '/marketplaces-apps'
|
||||
}
|
||||
},
|
||||
NETWORK: {
|
||||
VNETS: {
|
||||
LIST: '/virtual-networks'
|
||||
},
|
||||
VN_TEMPLATES: {
|
||||
LIST: '/network-templates'
|
||||
},
|
||||
SEC_GROUPS: {
|
||||
LIST: '/security-groups'
|
||||
}
|
||||
},
|
||||
INFRASTRUCTURE: {
|
||||
CLUSTERS: {
|
||||
LIST: '/clusters'
|
||||
},
|
||||
HOSTS: {
|
||||
LIST: '/hosts'
|
||||
}
|
||||
},
|
||||
SYSTEM: {
|
||||
USERS: {
|
||||
LIST: '/users'
|
||||
},
|
||||
GROUPS: {
|
||||
LIST: '/groups'
|
||||
}
|
||||
},
|
||||
SETTINGS: '/settings'
|
||||
}
|
||||
|
||||
export const ENDPOINTS = [
|
||||
{
|
||||
label: 'Dashboard',
|
||||
path: PATH.DASHBOARD,
|
||||
sidebar: true,
|
||||
icon: DashboardIcon,
|
||||
Component: Dashboard
|
||||
},
|
||||
{
|
||||
label: 'Instances',
|
||||
sidebar: true,
|
||||
routes: [
|
||||
{
|
||||
label: 'VMs',
|
||||
path: PATH.INSTANCE.VMS.LIST,
|
||||
sidebar: true,
|
||||
icon: InstancesIcons,
|
||||
Component: VirtualMachines
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Templates',
|
||||
sidebar: true,
|
||||
routes: [
|
||||
{
|
||||
label: 'VMs',
|
||||
path: PATH.TEMPLATE.VMS.LIST,
|
||||
sidebar: true,
|
||||
icon: TemplateIcon,
|
||||
Component: VmTemplates
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Storage',
|
||||
sidebar: true,
|
||||
routes: [
|
||||
{
|
||||
label: 'Datastores',
|
||||
path: PATH.STORAGE.DATASTORES.LIST,
|
||||
sidebar: true,
|
||||
icon: DatastoreIcon,
|
||||
Component: Datastores
|
||||
},
|
||||
{
|
||||
label: 'Images',
|
||||
path: PATH.STORAGE.IMAGES.LIST,
|
||||
sidebar: true,
|
||||
icon: ImageIcon,
|
||||
Component: Images
|
||||
},
|
||||
{
|
||||
label: 'Marketplaces',
|
||||
path: PATH.STORAGE.MARKETPLACES.LIST,
|
||||
sidebar: true,
|
||||
icon: MarketplaceIcon,
|
||||
Component: Marketplaces
|
||||
},
|
||||
{
|
||||
label: 'Apps',
|
||||
path: PATH.STORAGE.MARKETPLACE_APPS.LIST,
|
||||
sidebar: true,
|
||||
icon: MarketplaceAppIcon,
|
||||
Component: MarketplaceApps
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Infrastructure',
|
||||
sidebar: true,
|
||||
routes: [
|
||||
{
|
||||
label: 'Clusters',
|
||||
path: PATH.INFRASTRUCTURE.CLUSTERS.LIST,
|
||||
sidebar: true,
|
||||
icon: ClusterIcon,
|
||||
Component: Clusters
|
||||
},
|
||||
{
|
||||
label: 'Hosts',
|
||||
path: PATH.INFRASTRUCTURE.HOSTS.LIST,
|
||||
sidebar: true,
|
||||
icon: HostIcon,
|
||||
Component: Hosts
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'System',
|
||||
sidebar: true,
|
||||
routes: [
|
||||
{
|
||||
label: 'Users',
|
||||
path: PATH.SYSTEM.USERS.LIST,
|
||||
sidebar: true,
|
||||
icon: UserIcon,
|
||||
Component: Users
|
||||
},
|
||||
{
|
||||
label: 'Groups',
|
||||
path: PATH.SYSTEM.GROUPS.LIST,
|
||||
sidebar: true,
|
||||
icon: GroupIcon,
|
||||
Component: Groups
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Settings',
|
||||
path: PATH.SETTINGS,
|
||||
sidebar: true,
|
||||
icon: SettingsIcon,
|
||||
Component: Settings
|
||||
}
|
||||
]
|
||||
|
||||
export default { PATH, ENDPOINTS }
|
@ -4,6 +4,7 @@ import clsx from 'clsx'
|
||||
|
||||
import {
|
||||
List,
|
||||
Icon as MIcon,
|
||||
Collapse,
|
||||
ListItem,
|
||||
ListItemText,
|
||||
@ -32,26 +33,24 @@ const SidebarCollapseItem = ({ label, routes, icon: Icon }) => {
|
||||
<Icon />
|
||||
</ListItemIcon>
|
||||
)}
|
||||
<ListItemText primary={label} />
|
||||
{expanded ? (
|
||||
<CollapseIcon
|
||||
className={clsx({ [classes.expandIcon]: isUpLg && !isFixMenu })}
|
||||
/>
|
||||
) : (
|
||||
<ExpandMoreIcon
|
||||
className={clsx({ [classes.expandIcon]: isUpLg && !isFixMenu })}
|
||||
/>
|
||||
)}
|
||||
<ListItemText
|
||||
className={classes.itemText}
|
||||
data-max-label={label}
|
||||
data-min-label={label.slice(0, 3)}
|
||||
/>
|
||||
<MIcon className={clsx({ [classes.expandIcon]: isUpLg && !isFixMenu })}>
|
||||
{expanded ? <CollapseIcon /> : <ExpandMoreIcon />}
|
||||
</MIcon>
|
||||
</ListItem>
|
||||
{routes?.map((subItem, index) => (
|
||||
<Collapse
|
||||
key={`subitem-${index}`}
|
||||
in={expanded}
|
||||
timeout="auto"
|
||||
timeout='auto'
|
||||
unmountOnExit
|
||||
className={clsx({ [classes.subItemWrapper]: isUpLg && !isFixMenu })}
|
||||
>
|
||||
<List component="div" disablePadding>
|
||||
<List component='div' disablePadding>
|
||||
<SidebarLink {...subItem} isSubItem />
|
||||
</List>
|
||||
</Collapse>
|
||||
|
@ -36,11 +36,11 @@ export default makeStyles(theme => ({
|
||||
'& #logo__text': {
|
||||
visibility: 'hidden'
|
||||
},
|
||||
'& $menu': {
|
||||
overflowY: 'hidden'
|
||||
},
|
||||
'& $expandIcon, & $subItemWrapper': {
|
||||
display: 'none'
|
||||
},
|
||||
'& $itemText::before': {
|
||||
content: 'attr(data-min-label)'
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -62,6 +62,9 @@ export default makeStyles(theme => ({
|
||||
},
|
||||
'& $expandIcon, & $subItemWrapper': {
|
||||
display: 'block !important'
|
||||
},
|
||||
'& $itemText::before': {
|
||||
content: 'attr(data-max-label) !important'
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -114,6 +117,14 @@ export default makeStyles(theme => ({
|
||||
list: {
|
||||
color: theme.palette.text.primary
|
||||
},
|
||||
itemText: {
|
||||
'&::before': {
|
||||
...theme.typography.body1,
|
||||
display: 'block',
|
||||
minWidth: 100,
|
||||
content: 'attr(data-max-label)'
|
||||
}
|
||||
},
|
||||
expandIcon: {},
|
||||
subItemWrapper: {},
|
||||
subItem: {
|
||||
|
12
src/fireedge/src/client/components/Tables/Groups/columns.js
Normal file
12
src/fireedge/src/client/components/Tables/Groups/columns.js
Normal file
@ -0,0 +1,12 @@
|
||||
const getTotalOfResources = resources => [resources?.ID ?? []].flat().length || 0
|
||||
|
||||
export default [
|
||||
{ Header: 'ID', accessor: 'ID', sortType: 'number' },
|
||||
{ Header: 'Name', accessor: 'NAME' },
|
||||
{
|
||||
Header: 'Total Users',
|
||||
id: 'TOTAL_USERS',
|
||||
accessor: row => getTotalOfResources(row?.USERS),
|
||||
sortType: 'number'
|
||||
}
|
||||
]
|
31
src/fireedge/src/client/components/Tables/Groups/index.js
Normal file
31
src/fireedge/src/client/components/Tables/Groups/index.js
Normal file
@ -0,0 +1,31 @@
|
||||
import React, { useEffect } from 'react'
|
||||
|
||||
import { useFetch } from 'client/hooks'
|
||||
import { useGroup, useGroupApi } from 'client/features/One'
|
||||
|
||||
import { EnhancedTable } from 'client/components/Tables'
|
||||
import GroupColumns from 'client/components/Tables/Groups/columns'
|
||||
import GroupRow from 'client/components/Tables/Groups/row'
|
||||
|
||||
const GroupsTable = () => {
|
||||
const columns = React.useMemo(() => GroupColumns, [])
|
||||
|
||||
const groups = useGroup()
|
||||
const { getGroups } = useGroupApi()
|
||||
|
||||
const { fetchRequest, loading, reloading } = useFetch(getGroups)
|
||||
|
||||
useEffect(() => { fetchRequest() }, [])
|
||||
|
||||
return (
|
||||
<EnhancedTable
|
||||
columns={columns}
|
||||
data={groups}
|
||||
isLoading={loading || reloading}
|
||||
getRowId={row => String(row.ID)}
|
||||
RowComponent={GroupRow}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default GroupsTable
|
42
src/fireedge/src/client/components/Tables/Groups/row.js
Normal file
42
src/fireedge/src/client/components/Tables/Groups/row.js
Normal file
@ -0,0 +1,42 @@
|
||||
import * as React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import { Group } 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, TOTAL_USERS } = 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={`Total Users: ${TOTAL_USERS}`}>
|
||||
<Group size={16} />
|
||||
<span>{` ${TOTAL_USERS}`}</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Row.propTypes = {
|
||||
original: PropTypes.object,
|
||||
value: PropTypes.object,
|
||||
isSelected: PropTypes.bool,
|
||||
handleClick: PropTypes.func
|
||||
}
|
||||
|
||||
export default Row
|
@ -0,0 +1,7 @@
|
||||
export default [
|
||||
{ Header: 'ID', accessor: 'ID', sortType: 'number' },
|
||||
{ Header: 'Name', accessor: 'NAME' },
|
||||
{ Header: 'Group', accessor: 'GNAME' },
|
||||
{ Header: 'Enabled', accessor: 'ENABLED' },
|
||||
{ Header: 'Auth driver', accessor: 'AUTH_DRIVER' }
|
||||
]
|
31
src/fireedge/src/client/components/Tables/Users/index.js
Normal file
31
src/fireedge/src/client/components/Tables/Users/index.js
Normal file
@ -0,0 +1,31 @@
|
||||
import React, { useEffect } from 'react'
|
||||
|
||||
import { useFetch } from 'client/hooks'
|
||||
import { useUser, useUserApi } from 'client/features/One'
|
||||
|
||||
import { EnhancedTable } from 'client/components/Tables'
|
||||
import UserColumns from 'client/components/Tables/Users/columns'
|
||||
import UserRow from 'client/components/Tables/Users/row'
|
||||
|
||||
const UsersTable = () => {
|
||||
const columns = React.useMemo(() => UserColumns, [])
|
||||
|
||||
const users = useUser()
|
||||
const { getUsers } = useUserApi()
|
||||
|
||||
const { fetchRequest, loading, reloading } = useFetch(getUsers)
|
||||
|
||||
useEffect(() => { fetchRequest() }, [])
|
||||
|
||||
return (
|
||||
<EnhancedTable
|
||||
columns={columns}
|
||||
data={users}
|
||||
isLoading={loading || reloading}
|
||||
getRowId={row => String(row.ID)}
|
||||
RowComponent={UserRow}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default UsersTable
|
49
src/fireedge/src/client/components/Tables/Users/row.js
Normal file
49
src/fireedge/src/client/components/Tables/Users/row.js
Normal file
@ -0,0 +1,49 @@
|
||||
import * as React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import { Group, Lock, LockKey } 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, GNAME, ENABLED, AUTH_DRIVER } = value
|
||||
|
||||
return (
|
||||
<div {...props}>
|
||||
<div className={classes.main}>
|
||||
<div className={classes.title}>
|
||||
<Typography className={classes.titleText} component='span'>
|
||||
{NAME}
|
||||
</Typography>
|
||||
<span className={classes.labels}>
|
||||
{!+ENABLED && <Lock size={20} />}
|
||||
</span>
|
||||
</div>
|
||||
<div className={classes.caption}>
|
||||
<span>
|
||||
{`#${ID}`}
|
||||
</span>
|
||||
<span title={`Group: ${GNAME}`}>
|
||||
<Group size={16} />
|
||||
<span>{` ${GNAME}`}</span>
|
||||
</span>
|
||||
<span title={`Auth Driver: ${AUTH_DRIVER}`}>
|
||||
<LockKey size={16} />
|
||||
<span>{` ${AUTH_DRIVER}`}</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Row.propTypes = {
|
||||
original: PropTypes.object,
|
||||
value: PropTypes.object,
|
||||
isSelected: PropTypes.bool,
|
||||
handleClick: PropTypes.func
|
||||
}
|
||||
|
||||
export default Row
|
@ -0,0 +1,8 @@
|
||||
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' }
|
||||
]
|
@ -0,0 +1,70 @@
|
||||
import React, { useEffect } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { LinearProgress } from '@material-ui/core'
|
||||
|
||||
import Tabs from 'client/components/Tabs'
|
||||
|
||||
import { useFetch } from 'client/hooks'
|
||||
import { useVmTemplateApi } from 'client/features/One'
|
||||
|
||||
import * as Helper from 'client/models/Helper'
|
||||
|
||||
const VmTemplateDetail = ({ id }) => {
|
||||
const { getVmTemplate } = useVmTemplateApi()
|
||||
const { data, fetchRequest, loading, error } = useFetch(getVmTemplate)
|
||||
|
||||
useEffect(() => {
|
||||
fetchRequest(id)
|
||||
}, [id])
|
||||
|
||||
if ((!data && !error) || loading) {
|
||||
return <LinearProgress color='secondary' style={{ width: '100%' }} />
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return <div>{error}</div>
|
||||
}
|
||||
|
||||
const { ID, NAME, UNAME, GNAME, REGTIME, LOCK, TEMPLATE } = data
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
name: 'info',
|
||||
renderContent: (
|
||||
<div>
|
||||
<span>
|
||||
{`#${ID} - ${NAME}`}
|
||||
</span>
|
||||
<div>
|
||||
<p>Owner: {UNAME}</p>
|
||||
<p>Group: {GNAME}</p>
|
||||
<p>Locked: {Helper.levelLockToString(LOCK?.LOCKED)}</p>
|
||||
<p>Register time: {Helper.timeToString(REGTIME)}</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
{
|
||||
name: 'template',
|
||||
renderContent: (
|
||||
<div>
|
||||
<pre>
|
||||
<code>
|
||||
{JSON.stringify(TEMPLATE, null, 2)}
|
||||
</code>
|
||||
</pre>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
]
|
||||
|
||||
return (
|
||||
<Tabs tabs={tabs} />
|
||||
)
|
||||
}
|
||||
|
||||
VmTemplateDetail.propTypes = {
|
||||
id: PropTypes.string.isRequired
|
||||
}
|
||||
|
||||
export default VmTemplateDetail
|
@ -0,0 +1,33 @@
|
||||
import React, { useEffect } from 'react'
|
||||
|
||||
import { useFetch } from 'client/hooks'
|
||||
import { useVmTemplate, useVmTemplateApi } from 'client/features/One'
|
||||
|
||||
import { EnhancedTable } from 'client/components/Tables'
|
||||
import VmTemplateColumns from 'client/components/Tables/VmTemplates/columns'
|
||||
import VmTemplateRow from 'client/components/Tables/VmTemplates/row'
|
||||
import VmTemplateDetail from 'client/components/Tables/VmTemplates/detail'
|
||||
|
||||
const VmTemplatesTable = () => {
|
||||
const columns = React.useMemo(() => VmTemplateColumns, [])
|
||||
|
||||
const vmTemplates = useVmTemplate()
|
||||
const { getVmTemplates } = useVmTemplateApi()
|
||||
|
||||
const { fetchRequest, loading, reloading } = useFetch(getVmTemplates)
|
||||
|
||||
useEffect(() => { fetchRequest() }, [])
|
||||
|
||||
return (
|
||||
<EnhancedTable
|
||||
columns={columns}
|
||||
data={vmTemplates}
|
||||
isLoading={loading || reloading}
|
||||
getRowId={row => String(row.ID)}
|
||||
RowComponent={VmTemplateRow}
|
||||
renderDetail={row => <VmTemplateDetail id={row.ID} />}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default VmTemplatesTable
|
54
src/fireedge/src/client/components/Tables/VmTemplates/row.js
Normal file
54
src/fireedge/src/client/components/Tables/VmTemplates/row.js
Normal file
@ -0,0 +1,54 @@
|
||||
import * as React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import { User, Group, Lock } from 'iconoir-react'
|
||||
import { Typography } from '@material-ui/core'
|
||||
|
||||
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 time = Helper.timeFromMilliseconds(+REGTIME)
|
||||
const timeAgo = `registered ${time.toRelative()}`
|
||||
|
||||
return (
|
||||
<div {...props}>
|
||||
<div className={classes.main}>
|
||||
<div className={classes.title}>
|
||||
<Typography className={classes.titleText} component='span'>
|
||||
{NAME}
|
||||
</Typography>
|
||||
<span className={classes.labels}>
|
||||
{LOCK && <Lock size={20} />}
|
||||
</span>
|
||||
</div>
|
||||
<div className={classes.caption}>
|
||||
<span title={time.toFormat('ff')}>
|
||||
{`#${ID} ${timeAgo}`}
|
||||
</span>
|
||||
<span title={`Owner: ${UNAME}`}>
|
||||
<User size={16} />
|
||||
<span>{` ${UNAME}`}</span>
|
||||
</span>
|
||||
<span title={`Group: ${GNAME}`}>
|
||||
<Group size={16} />
|
||||
<span>{` ${GNAME}`}</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Row.propTypes = {
|
||||
original: PropTypes.object,
|
||||
value: PropTypes.object,
|
||||
isSelected: PropTypes.bool,
|
||||
handleClick: PropTypes.func
|
||||
}
|
||||
|
||||
export default Row
|
@ -17,7 +17,11 @@ const Multiple = ({ tags, limitTags = 1 }) => {
|
||||
))
|
||||
|
||||
return (
|
||||
<div style={{ display: 'flex', flexWrap: 'wrap' }}>
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
flexWrap: 'wrap',
|
||||
justifyContent: 'end'
|
||||
}}>
|
||||
{Tags}
|
||||
{more > 0 && (
|
||||
<Tooltip arrow
|
||||
|
@ -1,12 +1,15 @@
|
||||
import ClustersTable from 'client/components/Tables/Clusters'
|
||||
import DatastoresTable from 'client/components/Tables/Datastores'
|
||||
import EnhancedTable from 'client/components/Tables/Enhanced'
|
||||
import GroupsTable from 'client/components/Tables/Groups'
|
||||
import HostsTable from 'client/components/Tables/Hosts'
|
||||
import ImagesTable from 'client/components/Tables/Images'
|
||||
import MarketplaceAppsTable from 'client/components/Tables/MarketplaceApps'
|
||||
import MarketplacesTable from 'client/components/Tables/Marketplaces'
|
||||
import UsersTable from 'client/components/Tables/Users'
|
||||
import VirtualizedTable from 'client/components/Tables/Virtualized'
|
||||
import VmsTable from 'client/components/Tables/Vms'
|
||||
import VmTemplatesTable from 'client/components/Tables/VmTemplates'
|
||||
|
||||
export {
|
||||
EnhancedTable,
|
||||
@ -14,9 +17,12 @@ export {
|
||||
|
||||
ClustersTable,
|
||||
DatastoresTable,
|
||||
GroupsTable,
|
||||
HostsTable,
|
||||
ImagesTable,
|
||||
MarketplaceAppsTable,
|
||||
MarketplacesTable,
|
||||
VmsTable
|
||||
UsersTable,
|
||||
VmsTable,
|
||||
VmTemplatesTable
|
||||
}
|
||||
|
@ -0,0 +1,66 @@
|
||||
import * as React from 'react'
|
||||
|
||||
import {
|
||||
User as UserIcon,
|
||||
Group as GroupIcon,
|
||||
Archive as ImageIcon,
|
||||
NetworkAlt as NetworkIcon
|
||||
} from 'iconoir-react'
|
||||
import { makeStyles } from '@material-ui/core'
|
||||
|
||||
import { useUser, useGroup, useImage, useVNetwork } from 'client/features/One'
|
||||
import Count from 'client/components/Count'
|
||||
import { WavesCard } from 'client/components/Cards'
|
||||
import { T } from 'client/constants'
|
||||
|
||||
const useStyles = makeStyles({
|
||||
root: {
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))',
|
||||
gridGap: '2em'
|
||||
}
|
||||
})
|
||||
|
||||
const TotalProvisionInfrastructures = () => {
|
||||
const classes = useStyles()
|
||||
const users = useUser()
|
||||
const groups = useGroup()
|
||||
const images = useImage()
|
||||
const vnetworks = useVNetwork()
|
||||
|
||||
return React.useMemo(() => (
|
||||
<div
|
||||
data-cy='dashboard-widget-total-sunstone-resources'
|
||||
className={classes.root}
|
||||
>
|
||||
<WavesCard
|
||||
text={T.Users}
|
||||
value={<Count number={`${users.length}`} />}
|
||||
bgColor='#fa7892'
|
||||
icon={UserIcon}
|
||||
/>
|
||||
<WavesCard
|
||||
text={T.Groups}
|
||||
value={<Count number={`${groups.length}`} />}
|
||||
bgColor='#b25aff'
|
||||
icon={GroupIcon}
|
||||
/>
|
||||
<WavesCard
|
||||
text={T.Images}
|
||||
value={<Count number={`${images.length}`} />}
|
||||
bgColor='#1fbbc6'
|
||||
icon={ImageIcon}
|
||||
/>
|
||||
<WavesCard
|
||||
text={T.VirtualNetwork}
|
||||
value={<Count number={`${vnetworks.length}`} />}
|
||||
bgColor='#f09d42'
|
||||
icon={NetworkIcon}
|
||||
/>
|
||||
</div>
|
||||
), [users.length, groups.length, images.length, vnetworks.length])
|
||||
}
|
||||
|
||||
TotalProvisionInfrastructures.displayName = 'TotalProvisionInfrastructures'
|
||||
|
||||
export default TotalProvisionInfrastructures
|
@ -1,9 +1,11 @@
|
||||
import TotalProviders from 'client/components/Widgets/TotalProviders'
|
||||
import TotalProvisionsByState from 'client/components/Widgets/TotalProvisionsByState'
|
||||
import TotalProvisionInfrastructures from 'client/components/Widgets/TotalProvisionInfrastructures'
|
||||
import TotalSunstoneResources from 'client/components/Widgets/TotalSunstoneResources'
|
||||
|
||||
export {
|
||||
TotalProviders,
|
||||
TotalProvisionInfrastructures,
|
||||
TotalProvisionsByState
|
||||
TotalProvisionsByState,
|
||||
TotalSunstoneResources
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import { yupResolver } from '@hookform/resolvers'
|
||||
import FormStepper from 'client/components/FormStepper'
|
||||
import Steps from 'client/containers/ApplicationsTemplates/Form/Create/Steps'
|
||||
|
||||
import { PATH } from 'client/apps/flow/routes'
|
||||
import { PATH } from 'client/apps/sunstone/routes-flow'
|
||||
import { useFetch } from 'client/hooks'
|
||||
import { useApplicationTemplateApi } from 'client/features/One'
|
||||
import { parseApplicationToForm, parseFormToApplication } from 'client/utils'
|
||||
|
@ -3,7 +3,7 @@ import React, { useEffect, useState } from 'react'
|
||||
import { useHistory } from 'react-router-dom'
|
||||
import { Container, Box } from '@material-ui/core'
|
||||
|
||||
import { PATH } from 'client/apps/flow/routes'
|
||||
import { PATH } from 'client/apps/sunstone/routes-flow'
|
||||
import { useFetch } from 'client/hooks'
|
||||
import { useApplicationTemplate, useApplicationTemplateApi } from 'client/features/One'
|
||||
|
||||
|
23
src/fireedge/src/client/containers/Clusters/index.js
Normal file
23
src/fireedge/src/client/containers/Clusters/index.js
Normal file
@ -0,0 +1,23 @@
|
||||
import * as React from 'react'
|
||||
|
||||
import { styled, Container as MContainer, Box } from '@material-ui/core'
|
||||
|
||||
import * as Tables from 'client/components/Tables'
|
||||
|
||||
const Container = styled(MContainer)`
|
||||
display: flex;
|
||||
flexDirection: column;
|
||||
height: 100%
|
||||
`
|
||||
|
||||
function Clusters () {
|
||||
return (
|
||||
<Container disableGutters>
|
||||
<Box py={2} overflow='auto'>
|
||||
<Tables.ClustersTable />
|
||||
</Box>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
export default Clusters
|
@ -0,0 +1,45 @@
|
||||
import * as React from 'react'
|
||||
|
||||
import clsx from 'clsx'
|
||||
import { Container, Box, Grid } from '@material-ui/core'
|
||||
|
||||
import { useAuth } from 'client/features/Auth'
|
||||
import { useUserApi, useGroupApi, useImageApi, useVNetworkApi } from 'client/features/One'
|
||||
import * as Widgets from 'client/components/Widgets'
|
||||
import dashboardStyles from 'client/containers/Dashboard/Provision/styles'
|
||||
|
||||
function Dashboard () {
|
||||
const { getUsers } = useUserApi()
|
||||
const { getGroups } = useGroupApi()
|
||||
const { getImages } = useImageApi()
|
||||
const { getVNetworks } = useVNetworkApi()
|
||||
|
||||
const { settings: { disableanimations } = {} } = useAuth()
|
||||
const classes = dashboardStyles({ disableanimations })
|
||||
|
||||
React.useEffect(() => {
|
||||
getUsers()
|
||||
getGroups()
|
||||
getImages()
|
||||
getVNetworks()
|
||||
}, [])
|
||||
|
||||
const withoutAnimations = String(disableanimations).toUpperCase() === 'YES'
|
||||
|
||||
return (
|
||||
<Container
|
||||
disableGutters
|
||||
className={clsx({ [classes.withoutAnimations]: withoutAnimations })}
|
||||
>
|
||||
<Box py={3}>
|
||||
<Grid container spacing={3}>
|
||||
<Grid item xs={12}>
|
||||
<Widgets.TotalSunstoneResources />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
export default Dashboard
|
@ -0,0 +1,9 @@
|
||||
import { makeStyles } from '@material-ui/core'
|
||||
|
||||
export default makeStyles({
|
||||
withoutAnimations: {
|
||||
'& *, & *::before, & *::after': {
|
||||
animation: 'none !important'
|
||||
}
|
||||
}
|
||||
})
|
@ -1,40 +0,0 @@
|
||||
/* 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. */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
import * as React from 'react'
|
||||
|
||||
import { Box, Typography } from '@material-ui/core'
|
||||
|
||||
import dashboardStyles from 'client/containers/Dashboard/styles'
|
||||
import { Tr } from 'client/components/HOC/Translate'
|
||||
import { T } from 'client/constants'
|
||||
|
||||
function Dashboard () {
|
||||
const classes = dashboardStyles()
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Typography
|
||||
variant="h2"
|
||||
className={classes.title}
|
||||
data-cy="dashboard-title"
|
||||
>
|
||||
{Tr(T.Dashboard)}
|
||||
</Typography>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export default Dashboard
|
@ -1,8 +0,0 @@
|
||||
import { makeStyles } from '@material-ui/core'
|
||||
|
||||
export default makeStyles(theme => ({
|
||||
root: {},
|
||||
title: {
|
||||
color: theme.palette.common.black
|
||||
}
|
||||
}))
|
23
src/fireedge/src/client/containers/Datastores/index.js
Normal file
23
src/fireedge/src/client/containers/Datastores/index.js
Normal file
@ -0,0 +1,23 @@
|
||||
import * as React from 'react'
|
||||
|
||||
import { styled, Container as MContainer, Box } from '@material-ui/core'
|
||||
|
||||
import * as Tables from 'client/components/Tables'
|
||||
|
||||
const Container = styled(MContainer)`
|
||||
display: flex;
|
||||
flexDirection: column;
|
||||
height: 100%
|
||||
`
|
||||
|
||||
function Datastores () {
|
||||
return (
|
||||
<Container disableGutters>
|
||||
<Box py={2} overflow='auto'>
|
||||
<Tables.DatastoresTable />
|
||||
</Box>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
export default Datastores
|
23
src/fireedge/src/client/containers/Groups/index.js
Normal file
23
src/fireedge/src/client/containers/Groups/index.js
Normal file
@ -0,0 +1,23 @@
|
||||
import * as React from 'react'
|
||||
|
||||
import { styled, Container as MContainer, Box } from '@material-ui/core'
|
||||
|
||||
import * as Tables from 'client/components/Tables'
|
||||
|
||||
const Container = styled(MContainer)`
|
||||
display: flex;
|
||||
flexDirection: column;
|
||||
height: 100%
|
||||
`
|
||||
|
||||
function Groups () {
|
||||
return (
|
||||
<Container disableGutters>
|
||||
<Box py={2} overflow='auto'>
|
||||
<Tables.GroupsTable />
|
||||
</Box>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
export default Groups
|
23
src/fireedge/src/client/containers/Hosts/index.js
Normal file
23
src/fireedge/src/client/containers/Hosts/index.js
Normal file
@ -0,0 +1,23 @@
|
||||
import * as React from 'react'
|
||||
|
||||
import { styled, Container as MContainer, Box } from '@material-ui/core'
|
||||
|
||||
import * as Tables from 'client/components/Tables'
|
||||
|
||||
const Container = styled(MContainer)`
|
||||
display: flex;
|
||||
flexDirection: column;
|
||||
height: 100%
|
||||
`
|
||||
|
||||
function Hosts () {
|
||||
return (
|
||||
<Container disableGutters>
|
||||
<Box py={2} overflow='auto'>
|
||||
<Tables.HostsTable />
|
||||
</Box>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
export default Hosts
|
23
src/fireedge/src/client/containers/Images/index.js
Normal file
23
src/fireedge/src/client/containers/Images/index.js
Normal file
@ -0,0 +1,23 @@
|
||||
import * as React from 'react'
|
||||
|
||||
import { styled, Container as MContainer, Box } from '@material-ui/core'
|
||||
|
||||
import * as Tables from 'client/components/Tables'
|
||||
|
||||
const Container = styled(MContainer)`
|
||||
display: flex;
|
||||
flexDirection: column;
|
||||
height: 100%
|
||||
`
|
||||
|
||||
function Images () {
|
||||
return (
|
||||
<Container disableGutters>
|
||||
<Box py={2} overflow='auto'>
|
||||
<Tables.ImagesTable />
|
||||
</Box>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
export default Images
|
23
src/fireedge/src/client/containers/MarketplaceApps/index.js
Normal file
23
src/fireedge/src/client/containers/MarketplaceApps/index.js
Normal file
@ -0,0 +1,23 @@
|
||||
import * as React from 'react'
|
||||
|
||||
import { styled, Container as MContainer, Box } from '@material-ui/core'
|
||||
|
||||
import * as Tables from 'client/components/Tables'
|
||||
|
||||
const Container = styled(MContainer)`
|
||||
display: flex;
|
||||
flexDirection: column;
|
||||
height: 100%
|
||||
`
|
||||
|
||||
function MarketplaceApps () {
|
||||
return (
|
||||
<Container disableGutters>
|
||||
<Box py={2} overflow='auto'>
|
||||
<Tables.MarketplaceAppsTable />
|
||||
</Box>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
export default MarketplaceApps
|
23
src/fireedge/src/client/containers/Marketplaces/index.js
Normal file
23
src/fireedge/src/client/containers/Marketplaces/index.js
Normal file
@ -0,0 +1,23 @@
|
||||
import * as React from 'react'
|
||||
|
||||
import { styled, Container as MContainer, Box } from '@material-ui/core'
|
||||
|
||||
import * as Tables from 'client/components/Tables'
|
||||
|
||||
const Container = styled(MContainer)`
|
||||
display: flex;
|
||||
flexDirection: column;
|
||||
height: 100%
|
||||
`
|
||||
|
||||
function Marketplaces () {
|
||||
return (
|
||||
<Container disableGutters>
|
||||
<Box py={2} overflow='auto'>
|
||||
<Tables.MarketplacesTable />
|
||||
</Box>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
export default Marketplaces
|
@ -58,9 +58,9 @@ const Newstone = () => {
|
||||
<Route exact path={TABS.hosts} component={Tables.HostsTable} />
|
||||
<Route exact path={TABS.images} component={Tables.ImagesTable} />
|
||||
<Route exact path={TABS.marketplaces} component={Tables.MarketplacesTable} />
|
||||
<Route exact path={TABS.vms} component={Tables.VmsTable} />
|
||||
<Route exact path={PATH.INSTANCES_VMS} component={Tables.VmsTable} />
|
||||
|
||||
<Route component={() => <Redirect to={TABS.vms} />} />
|
||||
<Route component={() => <Redirect to={PATH.INSTANCES_VMS} />} />
|
||||
</Switch>
|
||||
</Box>
|
||||
</Container>
|
23
src/fireedge/src/client/containers/Users/index.js
Normal file
23
src/fireedge/src/client/containers/Users/index.js
Normal file
@ -0,0 +1,23 @@
|
||||
import * as React from 'react'
|
||||
|
||||
import { styled, Container as MContainer, Box } from '@material-ui/core'
|
||||
|
||||
import * as Tables from 'client/components/Tables'
|
||||
|
||||
const Container = styled(MContainer)`
|
||||
display: flex;
|
||||
flexDirection: column;
|
||||
height: 100%
|
||||
`
|
||||
|
||||
function Users () {
|
||||
return (
|
||||
<Container disableGutters>
|
||||
<Box py={2} overflow='auto'>
|
||||
<Tables.UsersTable />
|
||||
</Box>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
export default Users
|
23
src/fireedge/src/client/containers/VirtualMachines/index.js
Normal file
23
src/fireedge/src/client/containers/VirtualMachines/index.js
Normal file
@ -0,0 +1,23 @@
|
||||
import * as React from 'react'
|
||||
|
||||
import { styled, Container as MContainer, Box } from '@material-ui/core'
|
||||
|
||||
import * as Tables from 'client/components/Tables'
|
||||
|
||||
const Container = styled(MContainer)`
|
||||
display: flex;
|
||||
flexDirection: column;
|
||||
height: 100%
|
||||
`
|
||||
|
||||
function VirtualMachines () {
|
||||
return (
|
||||
<Container disableGutters>
|
||||
<Box py={2} overflow='auto'>
|
||||
<Tables.VmsTable />
|
||||
</Box>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
export default VirtualMachines
|
23
src/fireedge/src/client/containers/VmTemplates/index.js
Normal file
23
src/fireedge/src/client/containers/VmTemplates/index.js
Normal file
@ -0,0 +1,23 @@
|
||||
import * as React from 'react'
|
||||
|
||||
import { styled, Container as MContainer, Box } from '@material-ui/core'
|
||||
|
||||
import * as Tables from 'client/components/Tables'
|
||||
|
||||
const Container = styled(MContainer)`
|
||||
display: flex;
|
||||
flexDirection: column;
|
||||
height: 100%
|
||||
`
|
||||
|
||||
function VmTemplates () {
|
||||
return (
|
||||
<Container disableGutters>
|
||||
<Box py={2} overflow='auto'>
|
||||
<Tables.VmTemplatesTable />
|
||||
</Box>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
export default VmTemplates
|
@ -15,7 +15,7 @@
|
||||
|
||||
import * as React from 'react'
|
||||
|
||||
import FlowApp from 'client/apps/flow'
|
||||
import SunstoneApp from 'client/apps/sunstone'
|
||||
import ProvisionApp from 'client/apps/provision'
|
||||
|
||||
import { isDevelopment, isBackend } from 'client/utils'
|
||||
@ -39,7 +39,7 @@ const DevelopmentApp = props => {
|
||||
return (
|
||||
<>
|
||||
{appName === _APPS.provision.name && <ProvisionApp {...props} />}
|
||||
{appName === _APPS.sunstone.name && <FlowApp {...props} />}
|
||||
{appName === _APPS.sunstone.name && <SunstoneApp {...props} />}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { Actions, Commands } from 'server/utils/constants/commands/template'
|
||||
import { httpCodes } from 'server/utils/constants'
|
||||
import { requestParams, RestClient } from 'client/utils'
|
||||
import { poolRequest } from 'client/features/One/utils'
|
||||
|
||||
export const vmTemplateService = ({
|
||||
getVNetwork: ({ filter, id }) => {
|
||||
getVmTemplate: ({ filter, id }) => {
|
||||
const name = Actions.TEMPLATE_INFO
|
||||
const { url, options } = requestParams(
|
||||
{ filter, id },
|
||||
@ -15,5 +16,10 @@ export const vmTemplateService = ({
|
||||
|
||||
return res?.data?.VMTEMPLATE ?? {}
|
||||
})
|
||||
},
|
||||
getVmTemplates: data => {
|
||||
const name = Actions.TEMPLATE_POOL_INFO
|
||||
const command = { name, ...Commands[name] }
|
||||
return poolRequest(data, command, 'VMTEMPLATE')
|
||||
}
|
||||
})
|
||||
|
@ -69,7 +69,7 @@ const useFetch = (request, socket) => {
|
||||
}, [])
|
||||
|
||||
const doFetch = useCallback(async (payload, reload = false) => {
|
||||
dispatch({ type: ACTIONS.REQUEST, reload })
|
||||
!cancelRequest.current && dispatch({ type: ACTIONS.REQUEST, reload })
|
||||
|
||||
try {
|
||||
const response = await request(payload)
|
||||
|
@ -1,25 +1,13 @@
|
||||
import loadable from '@loadable/component'
|
||||
import {
|
||||
Code as DevIcon,
|
||||
ViewGrid as NewstoneIcon
|
||||
} from 'iconoir-react'
|
||||
import { Code as DevIcon } from 'iconoir-react'
|
||||
|
||||
const Newstone = loadable(() => import('client/containers/Newstone'), { ssr: false })
|
||||
const TestApi = loadable(() => import('client/containers/TestApi'), { ssr: false })
|
||||
|
||||
export const PATH = {
|
||||
NEWSTONE: '/newstone/:resource',
|
||||
TEST_API: '/test-api'
|
||||
}
|
||||
|
||||
export const ENDPOINTS = [
|
||||
{
|
||||
label: 'Newstone',
|
||||
path: PATH.NEWSTONE,
|
||||
sidebar: true,
|
||||
icon: NewstoneIcon,
|
||||
Component: Newstone
|
||||
},
|
||||
{
|
||||
label: 'Test API',
|
||||
path: PATH.TEST_API,
|
||||
|
@ -18,6 +18,7 @@ import PropTypes from 'prop-types'
|
||||
|
||||
import { Redirect, Route, Switch } from 'react-router-dom'
|
||||
import { TransitionGroup } from 'react-transition-group'
|
||||
import { LinearProgress } from '@material-ui/core'
|
||||
|
||||
import devRoutes from 'client/router/dev'
|
||||
import commonRoutes from 'client/router/common'
|
||||
@ -28,51 +29,67 @@ import Sidebar from 'client/components/Sidebar'
|
||||
import Notifier from 'client/components/Notifier'
|
||||
import { isDevelopment } from 'client/utils'
|
||||
|
||||
const Router = ({ routes }) => {
|
||||
const Router = ({ isLogged, routes }) => {
|
||||
const ENDPOINTS = React.useMemo(() => [
|
||||
...routes.ENDPOINTS,
|
||||
...(isDevelopment() ? devRoutes.ENDPOINTS : [])
|
||||
], [])
|
||||
|
||||
const renderRoute = React.useCallback(
|
||||
({ Component, ...rest }, index) => (
|
||||
<ProtectedRoute key={index} exact {...rest}>
|
||||
<InternalLayout>
|
||||
<Component fallback={<LinearProgress color='secondary' />} />
|
||||
</InternalLayout>
|
||||
</ProtectedRoute>
|
||||
), [])
|
||||
|
||||
return (
|
||||
<TransitionGroup>
|
||||
<Switch>
|
||||
{ENDPOINTS?.map(({ Component, ...rest }, index, endpoints) =>
|
||||
<ProtectedRoute key={index} exact {...rest}>
|
||||
<Sidebar endpoints={endpoints} />
|
||||
<Notifier />
|
||||
<InternalLayout>
|
||||
<>
|
||||
{isLogged && (
|
||||
<>
|
||||
<Sidebar endpoints={ENDPOINTS} />
|
||||
<Notifier />
|
||||
</>
|
||||
)}
|
||||
<TransitionGroup>
|
||||
<Switch>
|
||||
{ENDPOINTS?.map(({ routes: subRoutes, ...rest }, index) =>
|
||||
Array.isArray(subRoutes)
|
||||
? subRoutes?.map(renderRoute)
|
||||
: renderRoute(rest, index)
|
||||
)}
|
||||
{commonRoutes.ENDPOINTS?.map(({ Component, ...rest }, index) =>
|
||||
<NoAuthRoute key={index} exact {...rest}>
|
||||
<Component />
|
||||
</InternalLayout>
|
||||
</ProtectedRoute>
|
||||
)}
|
||||
{commonRoutes.ENDPOINTS?.map(({ Component, ...rest }, index) =>
|
||||
<NoAuthRoute key={index} exact {...rest}>
|
||||
<Component />
|
||||
</NoAuthRoute>
|
||||
)}
|
||||
<Route component={() => <Redirect to={commonRoutes.PATH.LOGIN} />} />
|
||||
</Switch>
|
||||
</TransitionGroup>
|
||||
</NoAuthRoute>
|
||||
)}
|
||||
<Route component={() => <Redirect to={commonRoutes.PATH.LOGIN} />} />
|
||||
</Switch>
|
||||
</TransitionGroup>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
Router.propTypes = {
|
||||
isLogged: PropTypes.bool,
|
||||
routes: PropTypes.shape({
|
||||
PATH: PropTypes.object,
|
||||
ENDPOINTS: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
Component: PropTypes.object.isRequired,
|
||||
Component: PropTypes.object,
|
||||
icon: PropTypes.object,
|
||||
label: PropTypes.string.isRequired,
|
||||
path: PropTypes.string.isRequired,
|
||||
sidebar: PropTypes.bool
|
||||
path: PropTypes.string,
|
||||
sidebar: PropTypes.bool,
|
||||
routes: PropTypes.array
|
||||
})
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
Router.defaultProps = {
|
||||
isLogged: false,
|
||||
routes: {
|
||||
PATH: {},
|
||||
ENDPOINTS: []
|
||||
|
@ -17,7 +17,7 @@ import * as React from 'react'
|
||||
import { hydrate, render } from 'react-dom'
|
||||
|
||||
import { createStore } from 'client/store'
|
||||
import App from 'client/apps/flow'
|
||||
import App from 'client/apps/sunstone'
|
||||
|
||||
const { store } = createStore({ initState: window.REDUX_DATA })
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user