1
0
mirror of https://github.com/OpenNebula/one.git synced 2024-12-23 17:33:56 +03:00

F #3951: Add configure action to provision (#668)

This commit is contained in:
Sergio Betanzos 2021-01-19 10:15:57 +01:00 committed by GitHub
parent 5e09101b92
commit 8b03aae0fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 97 additions and 38 deletions

View File

@ -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 = {

View File

@ -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 = {

View File

@ -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 = {

View File

@ -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

View File

@ -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
} }

View File

@ -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>

View File

@ -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 }}
/> />

View File

@ -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,

View File

@ -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,

View File

@ -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: {