mirror of
https://github.com/OpenNebula/one.git
synced 2024-12-23 17:33:56 +03:00
parent
5e09101b92
commit
8b03aae0fa
@ -44,7 +44,10 @@ const DatastoreCard = memo(
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
(prev, next) => prev.isSelected === next.isSelected
|
(prev, next) => (
|
||||||
|
prev.isSelected === next.isSelected &&
|
||||||
|
prev.value?.STATE === next.value?.STATE
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
DatastoreCard.propTypes = {
|
DatastoreCard.propTypes = {
|
||||||
|
@ -26,7 +26,7 @@ const HostCard = memo(
|
|||||||
stylesProps={{ minHeight: 160 }}
|
stylesProps={{ minHeight: 160 }}
|
||||||
cardProps={{ className: classes.card, elevation: 2 }}
|
cardProps={{ className: classes.card, elevation: 2 }}
|
||||||
icon={
|
icon={
|
||||||
<StatusBadge stateColor={state.color}>
|
<StatusBadge title={state?.name} stateColor={state.color}>
|
||||||
<HostIcon />
|
<HostIcon />
|
||||||
</StatusBadge>
|
</StatusBadge>
|
||||||
}
|
}
|
||||||
@ -46,7 +46,10 @@ const HostCard = memo(
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
(prev, next) => prev.isSelected === next.isSelected
|
(prev, next) => (
|
||||||
|
prev.isSelected === next.isSelected &&
|
||||||
|
prev.value?.STATE === next.value?.STATE
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
HostCard.propTypes = {
|
HostCard.propTypes = {
|
||||||
|
@ -49,7 +49,7 @@ const ProvisionCard = memo(
|
|||||||
isProvider ? (
|
isProvider ? (
|
||||||
<ProviderIcon />
|
<ProviderIcon />
|
||||||
) : (
|
) : (
|
||||||
<StatusBadge stateColor={stateInfo?.color}>
|
<StatusBadge title={stateInfo?.name} stateColor={stateInfo?.color}>
|
||||||
<ProvisionIcon />
|
<ProvisionIcon />
|
||||||
</StatusBadge>
|
</StatusBadge>
|
||||||
)
|
)
|
||||||
@ -62,7 +62,12 @@ const ProvisionCard = memo(
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}, (prev, next) => prev.isSelected === next.isSelected
|
}, (prev, next) => (
|
||||||
|
prev.isSelected === next.isSelected &&
|
||||||
|
!prev.isProvider &&
|
||||||
|
!next.isProvider &&
|
||||||
|
prev.value?.BODY?.state === next.value?.BODY?.state
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
ProvisionCard.propTypes = {
|
ProvisionCard.propTypes = {
|
||||||
|
@ -96,7 +96,7 @@ ansiHTML.setColors = function (colors) {
|
|||||||
|
|
||||||
var _finalColors = {}
|
var _finalColors = {}
|
||||||
for (var key in _defColors) {
|
for (var key in _defColors) {
|
||||||
var hex = colors.hasOwnProperty(key) ? colors[key] : null
|
var hex = Object.prototype.hasOwnProperty.call(colors, key) ? colors[key] : null
|
||||||
if (!hex) {
|
if (!hex) {
|
||||||
_finalColors[key] = _defColors[key]
|
_finalColors[key] = _defColors[key]
|
||||||
continue
|
continue
|
||||||
|
@ -4,6 +4,7 @@ import clsx from 'clsx'
|
|||||||
|
|
||||||
import { makeStyles } from '@material-ui/core'
|
import { makeStyles } from '@material-ui/core'
|
||||||
import ChevronRightIcon from '@material-ui/icons/ChevronRight'
|
import ChevronRightIcon from '@material-ui/icons/ChevronRight'
|
||||||
|
import ExpandMoreIcon from '@material-ui/icons/ExpandMore'
|
||||||
|
|
||||||
import { DEBUG_LEVEL } from 'client/constants'
|
import { DEBUG_LEVEL } from 'client/constants'
|
||||||
import AnsiHtml from 'client/components/DebugLog/ansiHtml'
|
import AnsiHtml from 'client/components/DebugLog/ansiHtml'
|
||||||
@ -16,7 +17,7 @@ const useStyles = makeStyles(theme => ({
|
|||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
marginBottom: '0.3em',
|
marginBottom: '0.3em',
|
||||||
padding: '0.5em 0',
|
padding: '0.5em 0',
|
||||||
cursor: ({ isCollapsed }) => isCollapsed ? 'pointer' : 'default',
|
cursor: ({ isMoreThanMaxChars }) => isMoreThanMaxChars ? 'pointer' : 'default',
|
||||||
fontFamily: 'monospace',
|
fontFamily: 'monospace',
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
background: '#333537'
|
background: '#333537'
|
||||||
@ -43,29 +44,35 @@ const useStyles = makeStyles(theme => ({
|
|||||||
// --------------------------------------------
|
// --------------------------------------------
|
||||||
|
|
||||||
const Message = memo(({ timestamp, severity, message }) => {
|
const Message = memo(({ timestamp, severity, message }) => {
|
||||||
const [isCollapsed, setCollapse] = useState(() => message?.length >= MAX_CHARS)
|
const isMoreThanMaxChars = message?.length >= MAX_CHARS
|
||||||
const classes = useStyles({ isCollapsed })
|
const [isCollapsed, setCollapse] = useState(() => isMoreThanMaxChars)
|
||||||
const sanitize = AnsiHtml(message)
|
const classes = useStyles({ isMoreThanMaxChars })
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(classes.root, classes[severity])}
|
className={clsx(classes.root, classes[severity])}
|
||||||
onClick={() => setCollapse(false)}
|
onClick={() => setCollapse(prev => !prev)}
|
||||||
>
|
>
|
||||||
<div className={classes.arrow}>
|
<div className={classes.arrow}>
|
||||||
{isCollapsed && <ChevronRightIcon fontSize='small' />}
|
{isMoreThanMaxChars && (isCollapsed ? (
|
||||||
|
<ChevronRightIcon fontSize='small' />
|
||||||
|
) : (
|
||||||
|
<ExpandMoreIcon fontSize='small' />
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.time}>{timestamp}</div>
|
<div className={classes.time}>{timestamp}</div>
|
||||||
<div className={classes.message}>
|
{(isCollapsed && isMoreThanMaxChars) ? (
|
||||||
{isCollapsed ? `${sanitize.slice(0, MAX_CHARS)}...` : sanitize}
|
<div className={classes.message}>{`${message?.slice(0, MAX_CHARS)}…`}</div>
|
||||||
</div>
|
) : (
|
||||||
|
<div className={classes.message} dangerouslySetInnerHTML={{ __html: AnsiHtml(message) }} />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
Message.propTypes = {
|
Message.propTypes = {
|
||||||
timestamp: PropTypes.string,
|
timestamp: PropTypes.string,
|
||||||
severity: PropTypes.oneOf([Object.keys(DEBUG_LEVEL)]),
|
severity: PropTypes.oneOf(Object.keys(DEBUG_LEVEL)),
|
||||||
message: PropTypes.string
|
message: PropTypes.string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ const useStyles = makeStyles(theme => ({
|
|||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const StatusBadge = memo(({ stateColor, children }) => {
|
const StatusBadge = memo(({ stateColor, children, ...props }) => {
|
||||||
const classes = useStyles({ stateColor })
|
const classes = useStyles({ stateColor })
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -41,6 +41,7 @@ const StatusBadge = memo(({ stateColor, children }) => {
|
|||||||
classes={{ badge: classes.badge }}
|
classes={{ badge: classes.badge }}
|
||||||
overlap="circle"
|
overlap="circle"
|
||||||
variant="dot"
|
variant="dot"
|
||||||
|
{...props}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</Badge>
|
</Badge>
|
||||||
|
@ -2,6 +2,7 @@ import React, { useState, useEffect, createElement } from 'react'
|
|||||||
|
|
||||||
import { useHistory } from 'react-router-dom'
|
import { useHistory } from 'react-router-dom'
|
||||||
import { Container, Box } from '@material-ui/core'
|
import { Container, Box } from '@material-ui/core'
|
||||||
|
import EditIcon from '@material-ui/icons/Settings'
|
||||||
import DeleteIcon from '@material-ui/icons/Delete'
|
import DeleteIcon from '@material-ui/icons/Delete'
|
||||||
|
|
||||||
import { PATH } from 'client/router/provision'
|
import { PATH } from 'client/router/provision'
|
||||||
@ -18,7 +19,13 @@ function Provisions () {
|
|||||||
const history = useHistory()
|
const history = useHistory()
|
||||||
const [showDialog, setShowDialog] = useState(false)
|
const [showDialog, setShowDialog] = useState(false)
|
||||||
|
|
||||||
const { provisions, getProvisions, getProvision, deleteProvision } = useProvision()
|
const {
|
||||||
|
provisions,
|
||||||
|
getProvisions,
|
||||||
|
getProvision,
|
||||||
|
configureProvision,
|
||||||
|
deleteProvision
|
||||||
|
} = useProvision()
|
||||||
|
|
||||||
const { error, fetchRequest, loading, reloading } = useFetch(getProvisions)
|
const { error, fetchRequest, loading, reloading } = useFetch(getProvisions)
|
||||||
const { result, handleChange } = useSearch({
|
const { result, handleChange } = useSearch({
|
||||||
@ -56,7 +63,13 @@ function Provisions () {
|
|||||||
subheader: `#${ID}`,
|
subheader: `#${ID}`,
|
||||||
content: DialogInfo
|
content: DialogInfo
|
||||||
}),
|
}),
|
||||||
actions: [{
|
actions: [
|
||||||
|
{
|
||||||
|
handleClick: () => configureProvision({ id: ID }),
|
||||||
|
icon: <EditIcon />,
|
||||||
|
cy: `provision-configure-${ID}`
|
||||||
|
},
|
||||||
|
{
|
||||||
handleClick: () => setShowDialog({
|
handleClick: () => setShowDialog({
|
||||||
id: ID,
|
id: ID,
|
||||||
title: `DELETE provision - #${ID} - ${NAME}`,
|
title: `DELETE provision - #${ID} - ${NAME}`,
|
||||||
@ -68,7 +81,8 @@ function Provisions () {
|
|||||||
}),
|
}),
|
||||||
icon: <DeleteIcon color='error' />,
|
icon: <DeleteIcon color='error' />,
|
||||||
cy: `provision-delete-${ID}`
|
cy: `provision-delete-${ID}`
|
||||||
}]
|
}
|
||||||
|
]
|
||||||
})}
|
})}
|
||||||
breakpoints={{ xs: 12, sm: 6, md: 4 }}
|
breakpoints={{ xs: 12, sm: 6, md: 4 }}
|
||||||
/>
|
/>
|
||||||
|
@ -142,6 +142,18 @@ export default function useProvision () {
|
|||||||
[dispatch]
|
[dispatch]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const configureProvision = useCallback(
|
||||||
|
({ id }) =>
|
||||||
|
serviceProvision
|
||||||
|
.configureProvision({ id })
|
||||||
|
.then(doc => {
|
||||||
|
dispatch(enqueueSuccess(`Provision configuring - ID: ${id}`))
|
||||||
|
return doc
|
||||||
|
})
|
||||||
|
.catch(err => dispatch(enqueueError(err ?? 'Error CONFIGURE provision')))
|
||||||
|
, [dispatch]
|
||||||
|
)
|
||||||
|
|
||||||
const deleteProvision = useCallback(
|
const deleteProvision = useCallback(
|
||||||
({ id }) =>
|
({ id }) =>
|
||||||
serviceProvision
|
serviceProvision
|
||||||
@ -227,6 +239,7 @@ export default function useProvision () {
|
|||||||
getProvision,
|
getProvision,
|
||||||
getProvisions,
|
getProvisions,
|
||||||
createProvision,
|
createProvision,
|
||||||
|
configureProvision,
|
||||||
deleteProvision,
|
deleteProvision,
|
||||||
getProvisionLog,
|
getProvisionLog,
|
||||||
|
|
||||||
|
@ -62,6 +62,19 @@ export const createProvision = ({ data = {} }) =>
|
|||||||
return res?.data ?? {}
|
return res?.data ?? {}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const configureProvision = ({ id }) =>
|
||||||
|
requestData(`/api/${PROVISION}/configure/${id}`, {
|
||||||
|
method: PUT,
|
||||||
|
error: err => err?.message
|
||||||
|
}).then(res => {
|
||||||
|
if (!res?.id || res?.id !== httpCodes.ok.id) {
|
||||||
|
if (res?.id === httpCodes.accepted.id) return res
|
||||||
|
throw res
|
||||||
|
}
|
||||||
|
|
||||||
|
return res?.data ?? {}
|
||||||
|
})
|
||||||
|
|
||||||
export const deleteProvision = ({ id }) =>
|
export const deleteProvision = ({ id }) =>
|
||||||
requestData(`/api/${PROVISION}/delete/${id}`, {
|
requestData(`/api/${PROVISION}/delete/${id}`, {
|
||||||
method: DELETE,
|
method: DELETE,
|
||||||
|
@ -105,13 +105,6 @@ const routes = {
|
|||||||
resource: { from: fromData.postBody, front: true }
|
resource: { from: fromData.postBody, front: true }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
configure: {
|
|
||||||
action: configureProvision,
|
|
||||||
params: {
|
|
||||||
resource: { from: fromData.resource, name: 'method' }
|
|
||||||
},
|
|
||||||
websocket: true
|
|
||||||
},
|
|
||||||
host: {
|
host: {
|
||||||
poweroff: {
|
poweroff: {
|
||||||
action: hostCommand,
|
action: hostCommand,
|
||||||
@ -210,6 +203,13 @@ const routes = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
[PUT]: {
|
[PUT]: {
|
||||||
|
configure: {
|
||||||
|
action: configureProvision,
|
||||||
|
params: {
|
||||||
|
id: { from: fromData.resource, name: 'id' }
|
||||||
|
},
|
||||||
|
websocket: true
|
||||||
|
},
|
||||||
host: {
|
host: {
|
||||||
action: configureHost,
|
action: configureHost,
|
||||||
params: {
|
params: {
|
||||||
|
Loading…
Reference in New Issue
Block a user