diff --git a/src/fireedge/src/client/components/Cards/VirtualMachineCard.js b/src/fireedge/src/client/components/Cards/VirtualMachineCard.js index bee591af08..53c33a97e8 100644 --- a/src/fireedge/src/client/components/Cards/VirtualMachineCard.js +++ b/src/fireedge/src/client/components/Cards/VirtualMachineCard.js @@ -13,35 +13,35 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { ReactElement, memo, useMemo } from 'react' import PropTypes from 'prop-types' +import { ReactElement, memo, useMemo } from 'react' +import { Box, Stack, Tooltip, Typography } from '@mui/material' import { - Lock, - HardDrive, Cpu, + HardDrive, + Lock, Network, WarningCircledOutline as WarningIcon, } from 'iconoir-react' -import { Box, Stack, Typography, Tooltip } from '@mui/material' -import { useViews } from 'client/features/Auth' -import MultipleTags from 'client/components/MultipleTags' -import Timer from 'client/components/Timer' -import { MemoryIcon } from 'client/components/Icons' -import { StatusCircle, StatusChip } from 'client/components/Status' import { Tr } from 'client/components/HOC' +import { MemoryIcon } from 'client/components/Icons' +import MultipleTags from 'client/components/MultipleTags' +import { StatusChip, StatusCircle } from 'client/components/Status' import { rowStyles } from 'client/components/Tables/styles' +import Timer from 'client/components/Timer' +import { useViews } from 'client/features/Auth' -import { getState, getLastHistory, getIps } from 'client/models/VirtualMachine' +import { ACTIONS, RESOURCE_NAMES, T, VM } from 'client/constants' import { - timeFromMilliseconds, - getUniqueLabels, - getErrorMessage, getColorFromString, + getErrorMessage, + getUniqueLabels, + timeFromMilliseconds, } from 'client/models/Helper' +import { getIps, getLastHistory, getState } from 'client/models/VirtualMachine' import { prettyBytes } from 'client/utils' -import { T, VM, ACTIONS, RESOURCE_NAMES } from 'client/constants' const VirtualMachineCard = memo( /** @@ -51,9 +51,17 @@ const VirtualMachineCard = memo( * @param {function(string):Promise} [props.onClickLabel] - Callback to click label * @param {function(string):Promise} [props.onDeleteLabel] - Callback to delete label * @param {ReactElement} [props.actions] - Actions + * @param {object[]} [props.globalErrors] - Errors globals * @returns {ReactElement} - Card */ - ({ vm, rootProps, actions, onClickLabel, onDeleteLabel }) => { + ({ + vm, + rootProps, + actions, + onClickLabel, + onDeleteLabel, + globalErrors = [], + }) => { const classes = rowStyles() const { [RESOURCE_NAMES.VM]: vmView } = useViews() @@ -86,6 +94,31 @@ const VirtualMachineCard = memo( name: stateName, displayName: stateDisplayName, } = getState(vm) + + const errorRows = globalErrors.filter( + (errorRow) => errorRow?.rows?.length && errorRow?.rows?.includes(ID) + ) + const IconsError = () => ( + <> + {errorRows.map((value, index) => ( + + {value?.message || ''} + + } + > + + {value?.icon || ''} + + + ))} + + ) + const error = useMemo(() => getErrorMessage(vm), [vm]) const ips = useMemo(() => getIps(vm), [vm]) const memValue = useMemo(() => prettyBytes(+MEMORY, 'MB'), [MEMORY]) @@ -112,6 +145,7 @@ const VirtualMachineCard = memo( {NAME} + {error && ( { const styles = EnhancedTableStyles() @@ -186,6 +187,26 @@ const EnhancedTable = ({ const canResetFilter = state.filters?.length > 0 || state.sortBy?.length > 0 + const messageValues = messages.filter( + (messageValue) => messageValue?.rows?.length + ) + const MessagesRowsAlerts = () => { + let grid = 12 + messageValues.length && (grid = grid / messageValues.length) + + return ( + + {messageValues.map((value, index) => ( + + + {value?.message || ''} + + + ))} + + ) + } + return ( {!disableGlobalSort && } - {/* SELECTED ROWS */} {displaySelectedRows && (
@@ -259,6 +279,7 @@ const EnhancedTable = ({ />
+ {messages && } {/* NO DATA MESSAGE */} {!isLoading && !isUninitialized && @@ -290,6 +311,9 @@ const EnhancedTable = ({ key={key} original={original} value={values} + {...(messageValues.length && { + globalErrors: messageValues, + })} className={isSelected ? 'selected' : ''} {...(!cannotFilterByLabel && { onClickLabel: (label) => { @@ -358,6 +382,7 @@ EnhancedTable.propTypes = { PropTypes.node, PropTypes.bool, ]), + messages: PropTypes.array, } export * from 'client/components/Tables/Enhanced/Utils' diff --git a/src/fireedge/src/client/components/Tables/Vms/index.js b/src/fireedge/src/client/components/Tables/Vms/index.js index a7cb621e32..8c8dd83004 100644 --- a/src/fireedge/src/client/components/Tables/Vms/index.js +++ b/src/fireedge/src/client/components/Tables/Vms/index.js @@ -52,9 +52,27 @@ const VmsTable = (props) => { ...result, data: result?.data - ?.filter((vm) => - host?.ID ? [host?.VMS?.ID ?? []].flat().includes(vm.ID) : true - ) + ?.filter((vm) => { + if (host?.ID) { + if ( + host?.ERROR_VMS?.ID || + host?.UPDATED_VMS?.ID || + host?.UPDATING_VMS?.ID + ) { + return [ + host?.ERROR_VMS.ID ?? [], + host?.UPDATED_VMS.ID ?? [], + host?.UPDATING_VMS.ID ?? [], + ] + .flat() + .includes(vm.ID) + } + + return [host?.VMS?.ID ?? []].flat().includes(vm.ID) + } + + return true + }) ?.filter(({ STATE }) => VM_STATES[STATE]?.name !== STATES.DONE) ?? [], }), }) diff --git a/src/fireedge/src/client/components/Tables/Vms/row.js b/src/fireedge/src/client/components/Tables/Vms/row.js index ac4e8286fc..97ebe7029f 100644 --- a/src/fireedge/src/client/components/Tables/Vms/row.js +++ b/src/fireedge/src/client/components/Tables/Vms/row.js @@ -13,20 +13,20 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { memo, useMemo, useCallback } from 'react' import PropTypes from 'prop-types' +import { memo, useCallback, useMemo } from 'react' -import vmApi, { useUpdateUserTemplateMutation } from 'client/features/OneApi/vm' -import { VirtualMachineCard } from 'client/components/Cards' import { ConsoleButton } from 'client/components/Buttons' -import { jsonToXml } from 'client/models/Helper' +import { VirtualMachineCard } from 'client/components/Cards' import { VM_ACTIONS } from 'client/constants' +import vmApi, { useUpdateUserTemplateMutation } from 'client/features/OneApi/vm' +import { jsonToXml } from 'client/models/Helper' const { VNC, RDP, SSH, VMRC } = VM_ACTIONS const CONNECTION_TYPES = [VNC, RDP, SSH, VMRC] const Row = memo( - ({ original, value, onClickLabel, ...props }) => { + ({ original, value, onClickLabel, globalErrors, ...props }) => { const [update] = useUpdateUserTemplateMutation() const state = vmApi.endpoints.getVms.useQueryState(undefined, { @@ -54,6 +54,7 @@ const Row = memo( rootProps={props} onClickLabel={onClickLabel} onDeleteLabel={handleDeleteLabel} + globalErrors={globalErrors} actions={ <> {CONNECTION_TYPES.map((connectionType) => ( @@ -78,6 +79,7 @@ Row.propTypes = { className: PropTypes.string, onClick: PropTypes.func, onClickLabel: PropTypes.func, + globalErrors: PropTypes.array, } Row.displayName = 'VirtualMachineRow' diff --git a/src/fireedge/src/client/components/Tabs/SecurityGroup/Vms/index.js b/src/fireedge/src/client/components/Tabs/SecurityGroup/Vms/index.js index 8b62070b19..3fa0a28afb 100644 --- a/src/fireedge/src/client/components/Tabs/SecurityGroup/Vms/index.js +++ b/src/fireedge/src/client/components/Tabs/SecurityGroup/Vms/index.js @@ -13,14 +13,15 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { ReactElement } from 'react' -import PropTypes from 'prop-types' -import { T } from 'client/constants' -import EmptyTab from 'client/components/Tabs/EmptyTab' -import { useHistory, generatePath } from 'react-router-dom' import { PATH } from 'client/apps/sunstone/routesOne' -import { useGetSecGroupQuery } from 'client/features/OneApi/securityGroup' import { VmsTable } from 'client/components/Tables' +import EmptyTab from 'client/components/Tabs/EmptyTab' +import { T } from 'client/constants' +import { useGetSecGroupQuery } from 'client/features/OneApi/securityGroup' +import { CloudDesync, WarningTriangleOutline } from 'iconoir-react' +import PropTypes from 'prop-types' +import { ReactElement } from 'react' +import { generatePath, useHistory } from 'react-router-dom' /** * Renders mainly Vms tab. @@ -43,6 +44,20 @@ const VmsTab = ({ id }) => { disableGlobalSort displaySelectedRows host={secGroup} + messages={[ + { + rows: [secGroup?.ERROR_VMS.ID ?? []].flat(), + message: T.ErrorUpdatingSecGroups, + icon: , + type: 'error', + }, + { + rows: [secGroup?.UPDATING_VMS.ID ?? []].flat(), + message: T.PendingUpdatingSecGroups, + icon: , + type: 'info', + }, + ]} onRowClick={(row) => handleRowClick(row.ID)} noDataMessage={} /> diff --git a/src/fireedge/src/client/constants/translates.js b/src/fireedge/src/client/constants/translates.js index 36eafe48af..99593b2479 100644 --- a/src/fireedge/src/client/constants/translates.js +++ b/src/fireedge/src/client/constants/translates.js @@ -290,6 +290,8 @@ module.exports = { NoDataAvailable: 'There is no data available', ErrorsOcurred: '%s error(s) occurred', UpdatedNic: 'Updated nic', + ErrorUpdatingSecGroups: 'VMs in error. The Update to the latest rules failed', + PendingUpdatingSecGroups: 'VMs waiting to be updated with the latest rules', /* steps form */ AdvancedOptions: 'Advanced options',