From c064adf99c0c0205df9bb1a02fa0fb9b103a3883 Mon Sep 17 00:00:00 2001 From: David Date: Thu, 30 May 2024 12:59:14 +0200 Subject: [PATCH 001/124] M #-: Add switches to bridge and physical device (#3086) on vnet and vnet templates Signed-off-by: David Carracedo --- .../configuration/schema.js | 63 ++++++++++++++++--- .../Steps/ExtraConfiguration/schema.js | 2 + .../VNTemplate/CreateForm/Steps/index.js | 17 ++++- .../CreateForm/Steps/General/commonFields.js | 50 +++++++++++++-- .../Forms/VNetwork/CreateForm/Steps/index.js | 14 ++++- .../src/client/constants/translates.js | 12 +++- 6 files changed, 141 insertions(+), 17 deletions(-) diff --git a/src/fireedge/src/client/components/Forms/VNTemplate/CreateForm/Steps/ExtraConfiguration/configuration/schema.js b/src/fireedge/src/client/components/Forms/VNTemplate/CreateForm/Steps/ExtraConfiguration/configuration/schema.js index 696bffe1055..576642085d6 100644 --- a/src/fireedge/src/client/components/Forms/VNTemplate/CreateForm/Steps/ExtraConfiguration/configuration/schema.js +++ b/src/fireedge/src/client/components/Forms/VNTemplate/CreateForm/Steps/ExtraConfiguration/configuration/schema.js @@ -59,16 +59,46 @@ const DRIVER_FIELD = { notNull: true, } +/** @type {Field} Bridge switch linux field */ +const BRIDGE_SWITCH = { + name: 'bridgeSwitch', + label: T.BridgeSwitch, + tooltip: T.BridgeSwitchConcept, + type: INPUT_TYPES.SWITCH, + validation: boolean().default(() => false), + grid: { md: 12 }, +} + /** @type {Field} Bridge linux field */ const BRIDGE_FIELD = { name: 'BRIDGE', label: T.Bridge, tooltip: T.BridgeConcept, + dependOf: BRIDGE_SWITCH.name, + htmlType: (bridgeSwitch) => !bridgeSwitch && INPUT_TYPES.HIDDEN, type: INPUT_TYPES.TEXT, validation: string() .trim() .notRequired() - .default(() => undefined), + .default(() => undefined) + .when(BRIDGE_SWITCH.name, { + is: (bridgeSwitch) => bridgeSwitch, + then: (schema) => schema.required(), + }), + grid: { md: 6 }, +} + +/** @type {Field} Bridge switch linux field */ +const PHYDEV_SWITCH = { + name: 'phyDevSwitch', + label: T.PhysicalDeviceSwitch, + tooltip: T.PhysicalDeviceSwitchConcept, + dependOf: DRIVER_FIELD.name, + htmlType: (driver) => + [dot1Q, vxlan, openVSwitchVXLAN].includes(driver) && INPUT_TYPES.HIDDEN, + type: INPUT_TYPES.SWITCH, + validation: boolean().default(() => false), + grid: { md: 12 }, } /** @type {Field} Physical device field */ @@ -76,14 +106,22 @@ const PHYDEV_FIELD = { name: 'PHYDEV', label: T.PhysicalDevice, tooltip: T.PhysicalDeviceConcept, + dependOf: [PHYDEV_SWITCH.name, DRIVER_FIELD.name], + htmlType: ([phyDevSwitch, driver] = []) => + phyDevSwitch && + ![dot1Q, vxlan, openVSwitchVXLAN].includes(driver) && + INPUT_TYPES.HIDDEN, type: INPUT_TYPES.TEXT, validation: string() .trim() .default(() => undefined) - .when(DRIVER_FIELD.name, { - is: (driver) => [dot1Q, vxlan, openVSwitchVXLAN].includes(driver), + .when([DRIVER_FIELD.name, PHYDEV_SWITCH.name], { + is: (driver, phyDevSwitch) => + [dot1Q, vxlan, openVSwitchVXLAN].includes(driver) || !phyDevSwitch, then: (schema) => schema.required(), + otherwise: (schema) => schema.notRequired(), }), + grid: { md: 6 }, } /** @type {Field} Filter MAC spoofing field */ @@ -169,9 +207,12 @@ const VLAN_ID_FIELD = { validation: string() .trim() .default(() => undefined) - .when(AUTOMATIC_VLAN_FIELD.name, { - is: (automatic) => !automatic, + .when([DRIVER_FIELD.name, AUTOMATIC_VLAN_FIELD.name], { + is: (driver, automatic) => + [dot1Q, vxlan, ovswitch, openVSwitchVXLAN].includes(driver) && + !automatic, then: (schema) => schema.required(), + otherwise: (schema) => schema.notRequired(), }), grid: { sm: 6 }, } @@ -212,9 +253,11 @@ const OUTER_VLAN_ID_FIELD = { validation: string() .trim() .default(() => undefined) - .when(AUTOMATIC_OUTER_VLAN_ID_FIELD.name, { - is: (oAutomatic) => !oAutomatic, + .when([DRIVER_FIELD.name, AUTOMATIC_OUTER_VLAN_ID_FIELD.name], { + is: (driver, oAutomatic) => + [openVSwitchVXLAN].includes(driver) && !oAutomatic, then: (schema) => schema.required(), + otherwise: (schema) => schema.notRequired(), }), grid: { sm: 6 }, } @@ -240,8 +283,12 @@ const FIELDS = (oneConfig, adminGroup) => disableFields( [ DRIVER_FIELD, - BRIDGE_FIELD, + + PHYDEV_SWITCH, PHYDEV_FIELD, + BRIDGE_SWITCH, + BRIDGE_FIELD, + FILTER_MAC_SPOOFING_FIELD, FILTER_IP_SPOOFING_FIELD, AUTOMATIC_VLAN_FIELD, diff --git a/src/fireedge/src/client/components/Forms/VNTemplate/CreateForm/Steps/ExtraConfiguration/schema.js b/src/fireedge/src/client/components/Forms/VNTemplate/CreateForm/Steps/ExtraConfiguration/schema.js index d2a2b3b14f6..0ea72a6d8a0 100644 --- a/src/fireedge/src/client/components/Forms/VNTemplate/CreateForm/Steps/ExtraConfiguration/schema.js +++ b/src/fireedge/src/client/components/Forms/VNTemplate/CreateForm/Steps/ExtraConfiguration/schema.js @@ -17,6 +17,7 @@ import { array, object, ObjectSchema } from 'yup' import { SCHEMA as CONTEXT_SCHEMA } from 'client/components/Forms/VNTemplate/CreateForm/Steps/ExtraConfiguration/context/schema' import { SCHEMA as QOS_SCHEMA } from 'client/components/Forms/VNTemplate/CreateForm/Steps/ExtraConfiguration/qos/schema' +import { SCHEMA as CONFIGURATION_SCHEMA } from 'client/components/Forms/VNTemplate/CreateForm/Steps/ExtraConfiguration/configuration/schema' /** * Map name attribute if not exists. @@ -46,6 +47,7 @@ const AR_SCHEMA = object({ */ export const SCHEMA = (isUpdate, oneConfig, adminGroup) => { const schema = object({ SECURITY_GROUPS: array().ensure() }) + .concat(CONFIGURATION_SCHEMA(oneConfig, adminGroup)) .concat(CONTEXT_SCHEMA(oneConfig, adminGroup)) .concat(QOS_SCHEMA(oneConfig, adminGroup)) diff --git a/src/fireedge/src/client/components/Forms/VNTemplate/CreateForm/Steps/index.js b/src/fireedge/src/client/components/Forms/VNTemplate/CreateForm/Steps/index.js index 78e7455bd22..114865e0161 100644 --- a/src/fireedge/src/client/components/Forms/VNTemplate/CreateForm/Steps/index.js +++ b/src/fireedge/src/client/components/Forms/VNTemplate/CreateForm/Steps/index.js @@ -59,10 +59,17 @@ export const getUnknownVars = (fromAttributes = {}, schema) => { const Steps = createSteps([General, ExtraConfiguration], { transformInitialValue: ({ TEMPLATE, ...vnet } = {}, schema) => { const { AR = {}, DESCRIPTION = '' } = TEMPLATE + + // Init switches of physical device and bridge + const phyDevSwitch = !TEMPLATE.PHYDEV + const bridgeSwitch = !!( + TEMPLATE.BRIDGE && !TEMPLATE.BRIDGE.startsWith('onebr') + ) + const initialValue = schema.cast( { [GENERAL_ID]: { ...vnet, DESCRIPTION }, - [EXTRA_ID]: { ...TEMPLATE, AR, ...vnet }, + [EXTRA_ID]: { ...TEMPLATE, AR, ...vnet, phyDevSwitch, bridgeSwitch }, }, { stripUnknown: true, context: vnet } ) @@ -78,6 +85,14 @@ const Steps = createSteps([General, ExtraConfiguration], { const { [GENERAL_ID]: general = {}, [EXTRA_ID]: extra = {} } = formData ?? {} + // Delete values of physical device and bridge depending of the value of their switches + extra.phyDevSwitch && delete extra.PHYDEV + !extra.bridgeSwitch && delete extra.BRIDGE + + // Ensure that switches of physical device and bridge are not sent to the API + delete extra.phyDevSwitch + delete extra.bridgeSwitch + return jsonToXml({ ...extra, ...general }) }, }) diff --git a/src/fireedge/src/client/components/Forms/VNetwork/CreateForm/Steps/General/commonFields.js b/src/fireedge/src/client/components/Forms/VNetwork/CreateForm/Steps/General/commonFields.js index 72eff0257df..95705c1e4dc 100644 --- a/src/fireedge/src/client/components/Forms/VNetwork/CreateForm/Steps/General/commonFields.js +++ b/src/fireedge/src/client/components/Forms/VNetwork/CreateForm/Steps/General/commonFields.js @@ -27,16 +27,46 @@ const { ovswitch_vxlan: openVSwitchVXLAN, } = VN_DRIVERS +/** @type {Field} Bridge switch linux field */ +const BRIDGE_SWITCH = { + name: 'bridgeSwitch', + label: T.BridgeSwitch, + tooltip: T.BridgeSwitchConcept, + type: INPUT_TYPES.SWITCH, + validation: boolean().default(() => false), + grid: { md: 12 }, +} + /** @type {Field} Bridge linux field */ const BRIDGE_FIELD = { name: 'BRIDGE', label: T.Bridge, tooltip: T.BridgeConcept, + dependOf: BRIDGE_SWITCH.name, + htmlType: (bridgeSwitch) => !bridgeSwitch && INPUT_TYPES.HIDDEN, type: INPUT_TYPES.TEXT, validation: string() .trim() .notRequired() - .default(() => undefined), + .default(() => undefined) + .when(BRIDGE_SWITCH.name, { + is: (bridgeSwitch) => bridgeSwitch, + then: (schema) => schema.required(), + }), + grid: { md: 6 }, +} + +/** @type {Field} Bridge switch linux field */ +const PHYDEV_SWITCH = { + name: 'phyDevSwitch', + label: T.PhysicalDeviceSwitch, + tooltip: T.PhysicalDeviceSwitchConcept, + dependOf: DRIVER_FIELD.name, + htmlType: (driver) => + [dot1Q, vxlan, openVSwitchVXLAN].includes(driver) && INPUT_TYPES.HIDDEN, + type: INPUT_TYPES.SWITCH, + validation: boolean().default(() => false), + grid: { md: 12 }, } /** @type {Field} Physical device field */ @@ -44,14 +74,22 @@ const PHYDEV_FIELD = { name: 'PHYDEV', label: T.PhysicalDevice, tooltip: T.PhysicalDeviceConcept, + dependOf: [PHYDEV_SWITCH.name, DRIVER_FIELD.name], + htmlType: ([phyDevSwitch, driver] = []) => + phyDevSwitch && + ![dot1Q, vxlan, openVSwitchVXLAN].includes(driver) && + INPUT_TYPES.HIDDEN, type: INPUT_TYPES.TEXT, validation: string() .trim() .default(() => undefined) - .when(DRIVER_FIELD.name, { - is: (driver) => [dot1Q, vxlan, openVSwitchVXLAN].includes(driver), + .when([DRIVER_FIELD.name, PHYDEV_SWITCH.name], { + is: (driver, phyDevSwitch) => + [dot1Q, vxlan, openVSwitchVXLAN].includes(driver) || !phyDevSwitch, then: (schema) => schema.required(), + otherwise: (schema) => schema.notRequired(), }), + grid: { md: 6 }, } /** @type {Field} Filter MAC spoofing field */ @@ -98,7 +136,7 @@ const AUTOMATIC_VLAN_FIELD = { .yesOrNo() .default(() => context?.AUTOMATIC_VLAN_ID === '1') ), - grid: (self) => (self ? { md: 12 } : { sm: 6 }), + grid: { md: 12 }, } /** @type {Field} VLAN ID field */ @@ -204,8 +242,10 @@ const VXLAN_MC_FIELD = { /** @type {Field[]} List of common fields */ export const FIELDS = [ - BRIDGE_FIELD, + PHYDEV_SWITCH, PHYDEV_FIELD, + BRIDGE_SWITCH, + BRIDGE_FIELD, FILTER_MAC_SPOOFING_FIELD, FILTER_IP_SPOOFING_FIELD, diff --git a/src/fireedge/src/client/components/Forms/VNetwork/CreateForm/Steps/index.js b/src/fireedge/src/client/components/Forms/VNetwork/CreateForm/Steps/index.js index 164c5382ed1..f003853e541 100644 --- a/src/fireedge/src/client/components/Forms/VNetwork/CreateForm/Steps/index.js +++ b/src/fireedge/src/client/components/Forms/VNetwork/CreateForm/Steps/index.js @@ -58,9 +58,13 @@ export const getUnknownVars = (fromAttributes = {}, schema) => { const Steps = createSteps([General, ExtraConfiguration], { transformInitialValue: ({ TEMPLATE, AR_POOL, ...vnet } = {}, schema) => { + // Init switches of physical device and bridge + const phyDevSwitch = !vnet.PHYDEV + const bridgeSwitch = !!(vnet.BRIDGE && !vnet.BRIDGE.startsWith('onebr')) + const initialValue = schema.cast( { - [GENERAL_ID]: { ...vnet }, + [GENERAL_ID]: { ...vnet, phyDevSwitch, bridgeSwitch }, [EXTRA_ID]: { ...TEMPLATE, AR: AR_POOL.AR, ...vnet }, }, { stripUnknown: true, context: vnet } @@ -77,6 +81,14 @@ const Steps = createSteps([General, ExtraConfiguration], { const { [GENERAL_ID]: general = {}, [EXTRA_ID]: extra = {} } = formData ?? {} + // Delete values of physical device and bridge depending of the value of their switches + general.phyDevSwitch && delete general.PHYDEV + !general.bridgeSwitch && delete general.BRIDGE + + // Ensure that switches of physical device and bridge are not sent to the API + delete general.phyDevSwitch + delete general.bridgeSwitch + return jsonToXml({ ...extra, ...general }) }, }) diff --git a/src/fireedge/src/client/constants/translates.js b/src/fireedge/src/client/constants/translates.js index c5791d4aa3e..31e1b27ce83 100644 --- a/src/fireedge/src/client/constants/translates.js +++ b/src/fireedge/src/client/constants/translates.js @@ -1431,9 +1431,17 @@ module.exports = { /* Virtual Network schema - driver configuration */ NetworkMode: 'Network mode', Bridge: 'Bridge', - BridgeConcept: 'Name of the physical bridge in the nodes to attach VM NICs', + BridgeConcept: + 'This lets you specify the name of the bridge to be created in the hosts.', + BridgeSwitch: 'Custom name for bridge', + BridgeSwitchConcept: + 'If enabled, you have to define the name of the bridge. Otherwise, OpenNebula will create the name of the bridge with the "onebr" prefix.', PhysicalDevice: 'Physical device', - PhysicalDeviceConcept: 'Node NIC to send/receive virtual network traffic', + PhysicalDeviceConcept: + 'Device name of the physical network card in the host to route traffic to. Example: eth0', + PhysicalDeviceSwitch: 'Use only private host networking', + PhysicalDeviceSwitchConcept: + 'If enabled, the Virtual Network will not connect to any physical device and hence the Virtual Machines will be able to communicate only with other Virtual Machines in the same virtual network and in the same host.', MacSpoofingFilter: ' MAC spoofing filter', IpSpoofingFilter: ' IP spoofing filter', MTU: 'MTU of the interface', From 168bd86983563e816fb614ca8078d1cf375012f0 Mon Sep 17 00:00:00 2001 From: David Date: Fri, 31 May 2024 14:24:51 +0200 Subject: [PATCH 002/124] B OpenNebula/one#6471: Change password in Settings tab (#3090) Signed-off-by: David Carracedo --- .../components/FormControl/SubmitButton.js | 62 +++++++++---- .../Settings/ChangePasswordForm/index.js | 24 ++++++ .../Settings/ChangePasswordForm/schema.js | 55 ++++++++++++ .../client/components/Forms/Settings/index.js | 27 ++++++ .../User/CreateForm/Steps/General/schema.js | 58 +++++++------ .../Forms/User/CreateForm/Steps/index.js | 5 +- .../src/client/constants/translates.js | 27 ++++-- src/fireedge/src/client/constants/user.js | 11 +++ .../containers/Login/Opennebula/index.js | 12 ++- .../Settings/ConfigurationUI/index.js | 86 +++++++++++++++++-- .../src/client/features/Auth/hooks.js | 1 + .../src/client/features/Auth/slice.js | 3 + 12 files changed, 309 insertions(+), 62 deletions(-) create mode 100644 src/fireedge/src/client/components/Forms/Settings/ChangePasswordForm/index.js create mode 100644 src/fireedge/src/client/components/Forms/Settings/ChangePasswordForm/schema.js create mode 100644 src/fireedge/src/client/components/Forms/Settings/index.js diff --git a/src/fireedge/src/client/components/FormControl/SubmitButton.js b/src/fireedge/src/client/components/FormControl/SubmitButton.js index a802cfd0774..a5da9d76209 100644 --- a/src/fireedge/src/client/components/FormControl/SubmitButton.js +++ b/src/fireedge/src/client/components/FormControl/SubmitButton.js @@ -39,6 +39,13 @@ const useStyles = makeStyles((theme) => ({ color: theme.palette.action.disabled, }, }, + tooltipLink: { + color: theme.palette.secondary.main, + textDecoration: 'none', + '&:hover': { + color: theme.palette.secondary.dark, + }, + }, })) const ButtonComponent = forwardRef( @@ -63,23 +70,43 @@ const ButtonComponent = forwardRef( ) ) -const TooltipComponent = ({ tooltip, tooltipprops, children }) => ( - ( - {tooltip}} - {...tooltipprops} - > - {wrapperChildren} - - )} - > - {children} - -) +const TooltipComponent = ({ tooltip, tooltipLink, tooltipprops, children }) => { + const classes = useStyles() + + return ( + ( + + {tooltip}{' '} + + {tooltipLink.text} + + + ) : ( + {tooltip} + ) + } + {...tooltipprops} + > + {wrapperChildren} + + )} + > + {children} + + ) +} const SubmitButton = memo( ({ isSubmitting, disabled, label, icon, className, ...props }) => { @@ -118,6 +145,7 @@ export const SubmitButtonPropTypes = { endicon: PropTypes.node, label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), tooltip: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), + tooltipLink: PropTypes.object, tooltipprops: PropTypes.object, isSubmitting: PropTypes.bool, disabled: PropTypes.bool, diff --git a/src/fireedge/src/client/components/Forms/Settings/ChangePasswordForm/index.js b/src/fireedge/src/client/components/Forms/Settings/ChangePasswordForm/index.js new file mode 100644 index 00000000000..2d64f77a686 --- /dev/null +++ b/src/fireedge/src/client/components/Forms/Settings/ChangePasswordForm/index.js @@ -0,0 +1,24 @@ +/* ------------------------------------------------------------------------- * + * Copyright 2002-2023, 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 { createForm } from 'client/utils' +import { CHANGE_PASSWORD_SCHEMA, CHANGE_PASSWORD_FIELDS } from './schema' + +const ChangePasswordForm = createForm( + CHANGE_PASSWORD_SCHEMA, + CHANGE_PASSWORD_FIELDS +) + +export default ChangePasswordForm diff --git a/src/fireedge/src/client/components/Forms/Settings/ChangePasswordForm/schema.js b/src/fireedge/src/client/components/Forms/Settings/ChangePasswordForm/schema.js new file mode 100644 index 00000000000..0b83ae73ac7 --- /dev/null +++ b/src/fireedge/src/client/components/Forms/Settings/ChangePasswordForm/schema.js @@ -0,0 +1,55 @@ +/* ------------------------------------------------------------------------- * + * Copyright 2002-2023, 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 { ObjectSchema, string } from 'yup' +import { Field, getObjectSchemaFromFields } from 'client/utils' +import { T, INPUT_TYPES } from 'client/constants' + +/** @type {Field} Password field */ +const PASSWORD_FIELD = { + name: 'password', + label: T.Password, + type: INPUT_TYPES.PASSWORD, + validation: string() + .trim() + .required() + .default(() => undefined), + grid: { md: 12 }, +} + +/** @type {Field} Confirm Password field */ +const CONFIRM_PASSWORD_FIELD = { + name: 'confirmPassword', + label: T.ConfirmPassword, + type: INPUT_TYPES.PASSWORD, + validation: string() + .trim() + .required() + .test('passwords-match', T.PasswordsMustMatch, function (value) { + return this.parent.password === value + }) + .default(() => undefined), + grid: { md: 12 }, +} + +/** + * @returns {Field[]} List of change password form inputs fields + */ +export const CHANGE_PASSWORD_FIELDS = [PASSWORD_FIELD, CONFIRM_PASSWORD_FIELD] + +/** @type {ObjectSchema} Change password form object schema */ +export const CHANGE_PASSWORD_SCHEMA = getObjectSchemaFromFields( + CHANGE_PASSWORD_FIELDS +) diff --git a/src/fireedge/src/client/components/Forms/Settings/index.js b/src/fireedge/src/client/components/Forms/Settings/index.js new file mode 100644 index 00000000000..69da9028ff0 --- /dev/null +++ b/src/fireedge/src/client/components/Forms/Settings/index.js @@ -0,0 +1,27 @@ +/* ------------------------------------------------------------------------- * + * Copyright 2002-2023, 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 { ReactElement } from 'react' +import { AsyncLoadForm, ConfigurationProps } from 'client/components/HOC' +import { CreateStepsCallback } from 'client/utils/schema' + +/** + * @param {ConfigurationProps} configProps - Configuration + * @returns {ReactElement|CreateStepsCallback} Asynchronous loaded form + */ +const ChangePasswordForm = (configProps) => + AsyncLoadForm({ formPath: 'Settings/ChangePasswordForm' }, configProps) + +export { ChangePasswordForm } diff --git a/src/fireedge/src/client/components/Forms/User/CreateForm/Steps/General/schema.js b/src/fireedge/src/client/components/Forms/User/CreateForm/Steps/General/schema.js index a026fc977f7..76762733ac3 100644 --- a/src/fireedge/src/client/components/Forms/User/CreateForm/Steps/General/schema.js +++ b/src/fireedge/src/client/components/Forms/User/CreateForm/Steps/General/schema.js @@ -13,8 +13,8 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { INPUT_TYPES, T } from 'client/constants' -import { Field, getObjectSchemaFromFields } from 'client/utils' +import { INPUT_TYPES, T, AUTH_DRIVER } from 'client/constants' +import { Field, getObjectSchemaFromFields, arrayToOptions } from 'client/utils' import { string } from 'yup' /** @type {Field} Username field */ @@ -29,14 +29,37 @@ const USERNAME_FIELD = { grid: { md: 12 }, } +/** @type {Field} Authentication Type field */ +const AUTH_TYPE_FIELD = { + name: 'authType', + label: T.AuthType, + type: INPUT_TYPES.SELECT, + values: () => + arrayToOptions(Object.keys(AUTH_DRIVER), { + addEmpty: false, + getText: (key) => AUTH_DRIVER[key], + getValue: (key) => AUTH_DRIVER[key], + }), + validation: string() + .trim() + .required() + .default(() => 'core'), + grid: { md: 12 }, +} + /** @type {Field} Password field */ const PASSWORD_FIELD = { name: 'password', label: T.Password, type: INPUT_TYPES.PASSWORD, + dependOf: AUTH_TYPE_FIELD.name, + htmlType: (authType) => + authType && authType === AUTH_DRIVER.LDAP && INPUT_TYPES.HIDDEN, validation: string() .trim() - .required() + .when(AUTH_TYPE_FIELD.name, (authType, schema) => + authType === AUTH_DRIVER.LDAP ? schema.strip() : schema.required() + ) .default(() => undefined), grid: { md: 12 }, } @@ -46,9 +69,14 @@ const CONFIRM_PASSWORD_FIELD = { name: 'confirmPassword', label: T.ConfirmPassword, type: INPUT_TYPES.PASSWORD, + dependOf: AUTH_TYPE_FIELD.name, + htmlType: (authType) => + authType && authType === AUTH_DRIVER.LDAP && INPUT_TYPES.HIDDEN, validation: string() .trim() - .required() + .when(AUTH_TYPE_FIELD.name, (authType, schema) => + authType === AUTH_DRIVER.LDAP ? schema.strip() : schema.required() + ) .test('passwords-match', T.PasswordsMustMatch, function (value) { return this.parent.password === value }) @@ -56,28 +84,6 @@ const CONFIRM_PASSWORD_FIELD = { grid: { md: 12 }, } -/** @type {Field} Authentication Type field */ -const AUTH_TYPE_FIELD = { - name: 'authType', - label: T.AuthType, - type: INPUT_TYPES.SELECT, - values: [ - { text: 'core', value: 'core' }, - { text: 'public', value: 'public' }, - { text: 'ssh', value: 'ssh' }, - { text: 'x509', value: 'x509' }, - { text: 'ldap', value: 'ldap' }, - { text: 'server_cipher', value: 'server_cipher' }, - { text: 'server_x509', value: 'server_x509' }, - { text: 'custom', value: 'custom' }, - ], - validation: string() - .trim() - .required() - .default(() => 'core'), - grid: { md: 12 }, -} - const SCHEMA = getObjectSchemaFromFields([ USERNAME_FIELD, AUTH_TYPE_FIELD, diff --git a/src/fireedge/src/client/components/Forms/User/CreateForm/Steps/index.js b/src/fireedge/src/client/components/Forms/User/CreateForm/Steps/index.js index 2eb7ac876e1..0582186122a 100644 --- a/src/fireedge/src/client/components/Forms/User/CreateForm/Steps/index.js +++ b/src/fireedge/src/client/components/Forms/User/CreateForm/Steps/index.js @@ -22,6 +22,7 @@ import SecondaryGroups, { import PrimaryGroup, { STEP_ID as PRIMARY_GROUP_ID, } from 'client/components/Forms/User/CreateForm/Steps/PrimaryGroup' +import { AUTH_DRIVER } from 'client/constants' import { createSteps } from 'client/utils' const Steps = createSteps([General, PrimaryGroup, SecondaryGroups], { @@ -32,9 +33,11 @@ const Steps = createSteps([General, PrimaryGroup, SecondaryGroups], { [SECONDARY_GROUPS_ID]: secondaryGroupsData, } = formData + // LDAP driver needs to set passwort to '-' return { username: generalData.username, - password: generalData.password, + password: + generalData.authType === AUTH_DRIVER.LDAP ? '-' : generalData.password, driver: generalData.authType, group: [primaryGroupsData, ...secondaryGroupsData], } diff --git a/src/fireedge/src/client/constants/translates.js b/src/fireedge/src/client/constants/translates.js index 31e1b27ce83..05b5ace114b 100644 --- a/src/fireedge/src/client/constants/translates.js +++ b/src/fireedge/src/client/constants/translates.js @@ -304,6 +304,14 @@ module.exports = { Password: 'Password', ConfirmPassword: 'Confirm Password', PasswordsMustMatch: 'Passwords must match', + ChangePassword: 'Change password', + ChangePasswordSuccess: 'Succesfully changed password', + ChangePasswordAdminWarning: + 'Users oneadmin and serveradmin can not change theirs passwords using Sunstone.', + ChangePasswordAdminWarningLink: + 'See OpenNebula documentation to get more details.', + ChangePasswordLdapWarning: + 'Users with authentication driver LDAP can not change theirs passwords using Sunstone.', Token2FA: '2FA Token', GetAuthenticatorApp: 'Get authenticator app: ', ScanThisQr: 'Scan this Qr', @@ -332,6 +340,7 @@ module.exports = { Reserved: 'Reserved', Vrouter: 'Vrouter', SessionExpired: 'Sorry, your session has expired', + WrongUsernamePassword: 'Wrong username or password', OnlyForOneadminGroup: 'Only members of the oneadmin group can access OneProvision functionality', SomethingWrong: 'Something go wrong', @@ -508,7 +517,7 @@ module.exports = { 'cluster.form.create.general.help.paragraph.2': 'Please, select a name for the cluster', 'cluster.form.create.help.link': - 'See Open Nebula documentation to get more details about clusters.', + 'See OpenNebula documentation to get more details about clusters.', 'cluster.form.create.hosts.help.title': 'Hosts', 'cluster.form.create.hosts.help.paragraph.1': 'Please, select one or more hosts in the hosts table. Hosts are not mandatory, so you can skip this step.', @@ -1547,7 +1556,7 @@ module.exports = { 'marketplace.form.create.general.description': 'Description', 'marketplace.form.create.general.type': 'Storage backend', 'marketplace.form.create.help.link': - 'See Open Nebula documentation to get more details about marketplaces.', + 'See OpenNebula documentation to get more details about marketplaces.', 'marketplace.general.help.title': 'Marketplace', 'marketplace.general.help.paragraph.1': 'OpenNebula Marketplaces provide a simple way to integrate your cloud with popular application/image providers. Think of them as external datastores. A Marketplace can be:', @@ -1566,7 +1575,7 @@ module.exports = { 'marketplace.form.configuration.one.help.paragraph.2': 'Please, fill the configuration attributes for Markeplace OpenNebula Systems.', 'marketplace.form.configuration.one.help.link': - 'See Open Nebula documentation to get more details about OpenNebula Systems marketplaces.', + 'See OpenNebula documentation to get more details about OpenNebula Systems marketplaces.', 'marketplace.form.configuration.http.url': 'Base URL of the Marketplace HTTP endpoint', @@ -1581,7 +1590,7 @@ module.exports = { 'marketplace.form.configuration.http.help.paragraph.2': 'Please, fill the configuration attributes for HTTP Marketplace.', 'marketplace.form.configuration.http.help.link': - 'See Open Nebula documentation to get more details about HTTP marketplaces.', + 'See OpenNebula documentation to get more details about HTTP marketplaces.', 'marketplace.form.configuration.s3.accessKey': 'Access Key Id', 'marketplace.form.configuration.s3.accessKey.tooltip': @@ -1612,7 +1621,7 @@ module.exports = { 'marketplace.form.configuration.s3.help.paragraph.2': 'Please, fill the configuration attributes for S3 Marketplace.', 'marketplace.form.configuration.s3.help.link': - 'See Open Nebula documentation to get more details about S3 marketplaces.', + 'See OpenNebula documentation to get more details about S3 marketplaces.', 'marketplace.form.configuration.dockerhub.info': 'No configuration attributes are needed for Dockerhub.', @@ -1621,7 +1630,7 @@ module.exports = { 'marketplace.form.configuration.dockerhub.help.paragraph.2': 'Please, fill the configuration attributes for DockerHub Marketplace.', 'marketplace.form.configuration.dockerhub.help.link': - 'See Open Nebula documentation to get more details about DockerHub marketplaces.', + 'See OpenNebula documentation to get more details about DockerHub marketplaces.', 'marketplace.form.configuration.dockerRegistry.url': 'Marketplace Docker registry url', @@ -1635,7 +1644,7 @@ module.exports = { 'marketplace.form.configuration.dockerRegistry.help.paragraph.2': 'Please, fill the configuration attributes for Docker Registry Marketplace.', 'marketplace.form.configuration.dockerRegistry.help.link': - 'See Open Nebula documentation to get more details about Docker Registry marketplaces.', + 'See OpenNebula documentation to get more details about Docker Registry marketplaces.', 'marketplace.types.one': 'OpenNebula Systems', 'marketplace.types.http': 'HTTP', @@ -1850,7 +1859,7 @@ module.exports = { 'groups.permissions.help.paragraph.3': 'On "Permissions - View" select if the users could or not view resources that other users of the group have created.', 'groups.permissions.help.paragraph.link': - 'See Open Nebula documentation to get more details about groups and permissions.', + 'See OpenNebula documentation to get more details about groups and permissions.', 'groups.views.group.section': 'Views - Groups', 'groups.views.group.tooltip': 'Select the default view and the views that any user on the group could use', @@ -1866,7 +1875,7 @@ module.exports = { 'groups.views.help.paragraph.3': 'On "Views - Admin" select the views and the default view for an admin user of the group.', 'groups.views.help.paragraph.link': - 'See Open Nebula documentation to get more details about views on Fireedge Sunstone.', + 'See OpenNebula documentation to get more details about views on Fireedge Sunstone.', 'groups.actions.edit.admins': 'Edit administrators', 'groups.actions.edit.admins.form': 'Select the administrators', 'groups.actions.edit.admins.success': 'Administrators updated', diff --git a/src/fireedge/src/client/constants/user.js b/src/fireedge/src/client/constants/user.js index 8c69cf0266c..beb9f1bd2e5 100644 --- a/src/fireedge/src/client/constants/user.js +++ b/src/fireedge/src/client/constants/user.js @@ -78,3 +78,14 @@ export const USER_ACTIONS = { ENABLE: 'enable', DISABLE: 'disable', } + +export const AUTH_DRIVER = { + CORE: 'core', + PUBLIC: 'public', + SSH: 'ssh', + X509: 'x509', + LDAP: 'ldap', + SERVER_CIPHER: 'server_cipher', + SERVER_X509: 'server_x509', + CUSTOM: 'custom', +} diff --git a/src/fireedge/src/client/containers/Login/Opennebula/index.js b/src/fireedge/src/client/containers/Login/Opennebula/index.js index 6e08b8f37e1..257c4204773 100644 --- a/src/fireedge/src/client/containers/Login/Opennebula/index.js +++ b/src/fireedge/src/client/containers/Login/Opennebula/index.js @@ -30,7 +30,7 @@ import { useLoginMutation, } from 'client/features/OneApi/auth' -import { Translate } from 'client/components/HOC' +import { Translate, Tr } from 'client/components/HOC' import { OpenNebulaLogo } from 'client/components/Icons' import { APPS, APPS_WITH_ONE_PREFIX, APP_URL, T } from 'client/constants' import Form from 'client/containers/Login/Opennebula/Form' @@ -51,7 +51,7 @@ const STEPS = { function OpenNebula() { const isMobile = useMediaQuery((theme) => theme.breakpoints.only('xs')) - const { logout } = useAuthApi() + const { logout, setErrorMessage } = useAuthApi() const { error: authError, isLoginInProgress: needGroupToContinue } = useAuth() const [changeAuthGroup, changeAuthGroupState] = useChangeAuthGroupMutation() @@ -64,6 +64,9 @@ function OpenNebula() { needGroupToContinue ? STEPS.GROUP_FORM : STEPS.USER_FORM ) + // Wrong username and password message + const wrongUsernamePassword = Tr(T.WrongUsernamePassword) + const handleSubmitUser = async (dataForm) => { try { const response = await login({ ...dataUserForm, ...dataForm }).unwrap() @@ -75,7 +78,10 @@ function OpenNebula() { setStep(STEPS.FA2_FORM) setDataUserForm(dataForm) } - } catch {} + } catch (error) { + // If login request returns 401, show error message about username and password + error?.status === 401 && setErrorMessage(wrongUsernamePassword) + } } const handleSubmitGroup = (dataForm) => { diff --git a/src/fireedge/src/client/containers/Settings/ConfigurationUI/index.js b/src/fireedge/src/client/containers/Settings/ConfigurationUI/index.js index 0a16f11b039..cf97f37a78f 100644 --- a/src/fireedge/src/client/containers/Settings/ConfigurationUI/index.js +++ b/src/fireedge/src/client/containers/Settings/ConfigurationUI/index.js @@ -16,18 +16,22 @@ import { Box, Link, Paper, debounce } from '@mui/material' import { ReactElement, useCallback, useEffect, useMemo } from 'react' import { FormProvider, useForm } from 'react-hook-form' - +import ButtonToTriggerForm from 'client/components/Forms/ButtonToTriggerForm' import { useAuth, useAuthApi, useViews } from 'client/features/Auth' import makeStyles from '@mui/styles/makeStyles' import { useGeneralApi } from 'client/features/General' -import { useUpdateUserMutation } from 'client/features/OneApi/user' +import { + useUpdateUserMutation, + useChangePasswordMutation, +} from 'client/features/OneApi/user' import { useGetZonesQuery } from 'client/features/OneApi/zone' import { PATH } from 'client/apps/sunstone/routesOne' import { FormWithSchema } from 'client/components/Forms' -import { Translate } from 'client/components/HOC' -import { T } from 'client/constants' +import { Translate, Tr } from 'client/components/HOC' +import { T, ONEADMIN_ID, SERVERADMIN_ID, AUTH_DRIVER } from 'client/constants' + import { FIELDS, SCHEMA, @@ -35,9 +39,15 @@ import { import { jsonToXml } from 'client/models/Helper' import { Link as RouterLink, generatePath } from 'react-router-dom' +import { ChangePasswordForm } from 'client/components/Forms/Settings' +import { generateDocLink } from 'client/utils' +import systemApi from 'client/features/OneApi/system' + const useStyles = makeStyles((theme) => ({ content: { - textAlign: 'right', + display: 'flex', + justifyContent: 'space-between', + width: '100%', }, })) @@ -49,10 +59,13 @@ const useStyles = makeStyles((theme) => ({ const Settings = () => { const { user, settings: { FIREEDGE: fireedge = {} } = {} } = useAuth() const { data: zones = [], isLoading } = useGetZonesQuery() + const { data: version } = systemApi.useGetOneVersionQuery() const { changeAuthUser } = useAuthApi() - const { enqueueError } = useGeneralApi() + const { enqueueError, enqueueSuccess } = useGeneralApi() const [updateUser] = useUpdateUserMutation() + const [changePassword, { isSuccess: isSuccessChangePassword }] = + useChangePasswordMutation() const { views, view: userView } = useViews() const classes = useStyles() @@ -80,6 +93,26 @@ const Settings = () => { [updateUser] ) + // Success messages + const successMessageChangePassword = `${Tr(T.ChangePasswordSuccess)}` + useEffect( + () => + isSuccessChangePassword && enqueueSuccess(successMessageChangePassword), + [isSuccessChangePassword] + ) + + /** + * Change the user's password. + * + * @param {object} formData - Password data + */ + const handleChangePassword = async (formData) => { + await changePassword({ + id: user.ID, + password: formData.password, + }) + } + useEffect(() => { const subscription = watch((formData) => { // update user settings before submit @@ -109,6 +142,47 @@ const Settings = () => { )} + {/* + Oneadmin and serveradmin users cannot change their passwords -> management_and_operations/users_groups_management/manage_users.html#change-credentials-for-oneadmin-or-serveradmin + LDAP users cannot change their passwords (the password is stored on the LDAP server) + */} + + ChangePasswordForm(), + onSubmit: handleChangePassword, + }, + ]} + /> { changeView: (view) => dispatch(actions.changeView(view)), changeJwt: (jwt) => dispatch(actions.changeJwt(jwt)), changeAuthUser: (user) => dispatch(actions.changeAuthUser(user)), + setErrorMessage: (message) => dispatch(actions.setErrorMessage(message)), } } diff --git a/src/fireedge/src/client/features/Auth/slice.js b/src/fireedge/src/client/features/Auth/slice.js index 4fcf108dd9d..1f99b581389 100644 --- a/src/fireedge/src/client/features/Auth/slice.js +++ b/src/fireedge/src/client/features/Auth/slice.js @@ -51,6 +51,9 @@ const slice = createSlice({ stopFirstRender: (state) => { state.firstRender = false }, + setErrorMessage: (state, { payload }) => { + state.error = payload + }, }, extraReducers: (builder) => { builder.addCase(logout, (_, { payload }) => { From 4f8e837fd9f311a4e25798a42bf5903fa9eb2cbf Mon Sep 17 00:00:00 2001 From: Jorge Miguel Lobo Escalona Date: Mon, 3 Jun 2024 11:00:09 +0200 Subject: [PATCH 003/124] F OpenNebula/one#6092: Add full screen info tab (#3087) --- .../ResourcesBackButton/BackButton.js | 45 ++++ .../components/ResourcesBackButton/index.js | 200 ++++++++++++++++++ .../Enhanced/Utils/GlobalActions/index.js | 19 +- .../components/Tables/Enhanced/index.js | 18 +- .../src/client/components/Tables/Hosts/row.js | 2 +- .../src/client/constants/translates.js | 4 + .../src/client/containers/ACLs/index.js | 98 +++++---- .../src/client/containers/BackupJobs/index.js | 108 ++++++---- .../src/client/containers/Backups/index.js | 110 ++++++---- .../src/client/containers/Clusters/index.js | 138 ++++++------ .../src/client/containers/Datastores/index.js | 110 ++++++---- .../src/client/containers/Files/index.js | 123 ++++++----- .../src/client/containers/Groups/index.js | 127 ++++++----- .../src/client/containers/Hosts/Detail.js | 10 +- .../src/client/containers/Hosts/index.js | 107 ++++++---- .../src/client/containers/Images/index.js | 112 ++++++---- .../containers/MarketplaceApps/index.js | 130 +++++++----- .../client/containers/Marketplaces/index.js | 127 ++++++----- .../client/containers/SecurityGroups/index.js | 130 +++++++----- .../containers/ServiceTemplates/index.js | 122 ++++++----- .../src/client/containers/Services/index.js | 121 ++++++----- .../Settings/ConfigurationUI/schema.js | 9 + .../src/client/containers/Settings/index.js | 2 +- .../src/client/containers/Users/index.js | 128 ++++++----- .../src/client/containers/VDCs/index.js | 108 ++++++---- .../containers/VNetworkTemplates/index.js | 107 ++++++---- .../containers/VirtualMachines/index.js | 110 ++++++---- .../containers/VirtualNetworks/index.js | 128 ++++++----- .../VirtualRouterTemplates/index.js | 126 ++++++----- .../client/containers/VirtualRouters/index.js | 117 +++++----- .../src/client/containers/VmGroups/index.js | 128 ++++++----- .../client/containers/VmTemplates/index.js | 126 ++++++----- .../src/client/containers/Zones/index.js | 112 +++++----- 33 files changed, 1956 insertions(+), 1206 deletions(-) create mode 100644 src/fireedge/src/client/components/ResourcesBackButton/BackButton.js create mode 100644 src/fireedge/src/client/components/ResourcesBackButton/index.js diff --git a/src/fireedge/src/client/components/ResourcesBackButton/BackButton.js b/src/fireedge/src/client/components/ResourcesBackButton/BackButton.js new file mode 100644 index 00000000000..1015b3589bd --- /dev/null +++ b/src/fireedge/src/client/components/ResourcesBackButton/BackButton.js @@ -0,0 +1,45 @@ +/* ------------------------------------------------------------------------- * + * Copyright 2002-2023, 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 { Grid, IconButton } from '@mui/material' +import NavArrowLeft from 'iconoir-react/dist/NavArrowLeft' +import { ReactElement, useCallback } from 'react' +import { useHistory } from 'react-router-dom' + +/** + * Back Button. + * + * @returns {ReactElement} BackButton rendered + */ +const BackButton = () => { + const history = useHistory() + + const handleBackClick = useCallback(() => { + history.goBack() + }) + + return ( + + + + + + + + ) +} + +export default BackButton diff --git a/src/fireedge/src/client/components/ResourcesBackButton/index.js b/src/fireedge/src/client/components/ResourcesBackButton/index.js new file mode 100644 index 00000000000..4d778be9946 --- /dev/null +++ b/src/fireedge/src/client/components/ResourcesBackButton/index.js @@ -0,0 +1,200 @@ +/* ------------------------------------------------------------------------- * + * Copyright 2002-2023, 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 { Box, Grid, IconButton, styled } from '@mui/material' +import { Tr } from 'client/components/HOC' +import SplitPane from 'client/components/SplitPane' +import { GlobalActions } from 'client/components/Tables/Enhanced/Utils' +import Pagination from 'client/components/Tables/Enhanced/pagination' +import EnhancedTableStyles from 'client/components/Tables/Enhanced/styles' +import { T } from 'client/constants' +import { useAuth } from 'client/features/Auth' +import NavArrowLeft from 'iconoir-react/dist/NavArrowLeft' +import OpenInWindow from 'iconoir-react/dist/OpenInWindow' +import OpenNewWindow from 'iconoir-react/dist/OpenNewWindow' +import PropTypes from 'prop-types' +import { memo, useCallback, useEffect, useMemo, useState } from 'react' + +const StyledWindowButtons = styled(Grid)(() => ({ + '&': { + textAlign: 'right', + }, +})) + +const StyledRowButtons = styled(Grid)(() => ({ + '&': { + marginBottom: '.5rem', + }, +})) + +const defaultPropsResize = 'auto 1fr auto 1fr' + +const ResourcesBackButton = memo( + ({ + selectedRows = [], + table = () => undefined, + info = () => undefined, + simpleGroupsTags = () => undefined, + setSelectedRows = () => undefined, + actions = [], + ...restProps + }) => { + const styles = EnhancedTableStyles({ + readOnly: false, + }) + + const { settings: { FIREEDGE: fireedge = {} } = {} } = useAuth() + const { FULL_SCREEN_INFO } = fireedge + + const [divided, setDivided] = useState(() => false) + const [propsResize, setPropsResize] = useState(() => defaultPropsResize) + const [pageIndex, setPageIndex] = useState(() => 0) + + useEffect(() => { + divided + ? setPropsResize('auto auto auto 1fr') + : setPropsResize(defaultPropsResize) + + !divided && setPageIndex(0) + }, [divided]) + + useEffect(() => { + FULL_SCREEN_INFO === 'true' && setDivided(true) + }, []) + + const countSelectedRows = selectedRows?.length + const moreThanOneSelected = countSelectedRows > 1 + const hasSelectedRows = countSelectedRows > 0 + + const selectedRowsTable = useMemo( + () => + selectedRows?.reduce((res, { id }) => ({ ...res, [id]: true }), {}) || + [], + [selectedRows] + ) + const handleUnselectRow = useCallback( + (id) => { + const newRows = selectedRows.filter((item) => item?.id !== id) + setSelectedRows(newRows) + }, + [selectedRows] + ) + + const props = { + ...restProps, + actions, + moreThanOneSelected, + selectedRows, + selectedRowsTable, + setSelectedRows, + handleElement: !divided, + gotoPage: !divided && selectedRows?.[0]?.gotoPage, + unselect: !divided && (() => selectedRows?.[0]?.toggleRowSelected(false)), + handleUnselectRow, + } + + return ( + + {({ getGridProps, GutterComponent }) => ( + + + + {hasSelectedRows && divided && ( + setSelectedRows([])} + title={Tr(T.Back)} + > + + + )} + + + + {!divided && ( + setDivided(true)} + title={Tr(T.DivideWindow)} + > + + + )} + {divided && ( + setDivided(false)} + title={Tr(T.UnDivideWindow)} + > + + + )} + + + {divided ? !hasSelectedRows && table(props) : table(props)} + {!divided && } + {hasSelectedRows && divided && ( +
+ + {moreThanOneSelected && ( + setPageIndex(index)} + count={countSelectedRows} + showPageCount={true} + useTableProps={{ + state: { + pageIndex, + pageSize: 1, + }, + }} + /> + )} +
+ )} + {moreThanOneSelected + ? divided + ? info({ + ...props, + selectedRows: [selectedRows[pageIndex]], + }) + : simpleGroupsTags(props) + : hasSelectedRows && info(props)} +
+ )} +
+ ) + } +) + +ResourcesBackButton.propTypes = { + selectedRows: PropTypes.array, + table: PropTypes.func, + info: PropTypes.func, + simpleGroupsTags: PropTypes.func, + setSelectedRows: PropTypes.func, + actions: PropTypes.array, +} +ResourcesBackButton.displayName = 'ResourcesBackButton' + +export default ResourcesBackButton diff --git a/src/fireedge/src/client/components/Tables/Enhanced/Utils/GlobalActions/index.js b/src/fireedge/src/client/components/Tables/Enhanced/Utils/GlobalActions/index.js index 45a352a3913..065e6f81b7d 100644 --- a/src/fireedge/src/client/components/Tables/Enhanced/Utils/GlobalActions/index.js +++ b/src/fireedge/src/client/components/Tables/Enhanced/Utils/GlobalActions/index.js @@ -75,14 +75,17 @@ const GlobalActions = ({ onClick={refetch} /> )} - {!singleSelect && !disableRowSelect && ( - - )} + {!singleSelect && + !disableRowSelect && + getToggleAllPageRowsSelectedProps && + getToggleAllRowsSelectedProps && ( + + )} {globalActions?.map((item, idx) => { if ((singleSelect || disableRowSelect) && item.selected) return null diff --git a/src/fireedge/src/client/components/Tables/Enhanced/index.js b/src/fireedge/src/client/components/Tables/Enhanced/index.js index b28bea2c6de..57438ab74ec 100644 --- a/src/fireedge/src/client/components/Tables/Enhanced/index.js +++ b/src/fireedge/src/client/components/Tables/Enhanced/index.js @@ -48,6 +48,9 @@ import EnhancedTableStyles from 'client/components/Tables/Enhanced/styles' import { Translate } from 'client/components/HOC' import { T } from 'client/constants' +import _ from 'lodash' + +const RELOAD_STATE = 'RELOAD_STATE' const EnhancedTable = ({ columns, @@ -103,7 +106,7 @@ const EnhancedTable = ({ ) const stateReducer = (newState, action, prevState) => { switch (action.type) { - case 'RELOAD_STATE': { + case RELOAD_STATE: { const updatedState = { ...prevState, selectedRowIds: action.value, @@ -169,6 +172,7 @@ const EnhancedTable = ({ setGlobalFilter, state, toggleRowSelected: propsToggleRow, + dispatch, } = useTableProps const [stateData, setStateData] = useState(data) @@ -220,6 +224,15 @@ const EnhancedTable = ({ })) }, [state.selectedRowIds, selectedRowStates]) + useEffect(() => { + initialState?.selectedRowIds && + !_.isEqual(state.selectedRowIds, initialState.selectedRowIds) && + dispatch({ + type: RELOAD_STATE, + value: initialState.selectedRowIds, + }) + }, [initialState?.selectedRowIds]) + useEffect(() => { if ( dataDepend && @@ -423,7 +436,6 @@ const EnhancedTable = ({ ) { toggleAllRowsSelected?.(false) } - toggleRowSelected?.(!isSelected) } }} @@ -477,7 +489,7 @@ EnhancedTable.propTypes = { dataDepend: PropTypes.oneOfType([PropTypes.array, PropTypes.string]), readOnly: PropTypes.bool, tableViews: PropTypes.object, - zoneId: PropTypes.string, + zoneId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), } export * from 'client/components/Tables/Enhanced/Utils' diff --git a/src/fireedge/src/client/components/Tables/Hosts/row.js b/src/fireedge/src/client/components/Tables/Hosts/row.js index 1bcc03b4a1d..7e6a1d11685 100644 --- a/src/fireedge/src/client/components/Tables/Hosts/row.js +++ b/src/fireedge/src/client/components/Tables/Hosts/row.js @@ -70,7 +70,7 @@ Row.propTypes = { className: PropTypes.string, handleClick: PropTypes.func, onClickLabel: PropTypes.func, - zone: PropTypes.string, + zone: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), } Row.displayName = 'HostRow' diff --git a/src/fireedge/src/client/constants/translates.js b/src/fireedge/src/client/constants/translates.js index 05b5ace114b..bc5e4aabd9b 100644 --- a/src/fireedge/src/client/constants/translates.js +++ b/src/fireedge/src/client/constants/translates.js @@ -17,6 +17,8 @@ module.exports = { /* pagination / stepper */ Back: 'Back', Previous: 'Previous', + DivideWindow: 'Divide Window', + UnDivideWindow: 'Undivide Window', Next: 'Next', Sort: 'Sort', SortBy: 'Sort by', @@ -116,6 +118,7 @@ module.exports = { DetachRestricted: 'You cannot delete this resource because it has restricted attributes on this template. Please, contact with your administrator.', DetachSomething: 'Detach: %s', + Disable: 'Disable', Dismiss: 'Dismiss', DiskSnapshotCreate: 'Disk snapshot create', @@ -830,6 +833,7 @@ module.exports = { CtrlAltDel: 'Ctrl-Alt-Del', Reconnect: 'Reconnect', FullScreen: 'Full screen', + FullScreenInfo: 'Full screen information in datatables', Screenshot: 'Screenshot', LastConnection: 'Last connection', VmIsNotOnVCenter: '%s is not located on vCenter Host', diff --git a/src/fireedge/src/client/containers/ACLs/index.js b/src/fireedge/src/client/containers/ACLs/index.js index abf12900020..7a5496f3269 100644 --- a/src/fireedge/src/client/containers/ACLs/index.js +++ b/src/fireedge/src/client/containers/ACLs/index.js @@ -13,14 +13,16 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { ReactElement, useState, memo } from 'react' -import PropTypes from 'prop-types' -import { Box, Stack, Chip } from '@mui/material' -import { Row } from 'react-table' -import SplitPane from 'client/components/SplitPane' +/* eslint-disable react/prop-types */ +import { Chip, Stack } from '@mui/material' import MultipleTags from 'client/components/MultipleTags' -import ACLActions from 'client/components/Tables/ACLs/actions' +import ResourcesBackButton from 'client/components/ResourcesBackButton' import { ACLsTable } from 'client/components/Tables' +import ACLActions from 'client/components/Tables/ACLs/actions' +import { useGeneral } from 'client/features/General' +import PropTypes from 'prop-types' +import { ReactElement, useState } from 'react' +import { Row } from 'react-table' /** * Displays a list of Groups with a split pane between the list and selected row(s). @@ -28,30 +30,41 @@ import { ACLsTable } from 'client/components/Tables' * @returns {ReactElement} Groups list and selected row(s) */ function ACLs() { - const [selectedRows, onSelectedRowsChange] = useState(() => []) - - const hasSelectedRows = selectedRows?.length > 0 - + const [selectedRows, setSelectedRows] = useState(() => []) + const { zone } = useGeneral() const actions = ACLActions() return ( - - {({ getGridProps, GutterComponent }) => ( - - - - {hasSelectedRows && ( - <> - - - - )} - + ( + + )} + simpleGroupsTags={(props) => ( + + )} + info={(props) => ( + )} - + /> ) } @@ -61,23 +74,34 @@ function ACLs() { * @param {Row[]} tags - Row(s) to display as tags * @returns {ReactElement} List of tags */ -const GroupedTags = memo(({ tags = [] }) => ( +const GroupedTags = ({ + tags = [], + handleElement = true, + onDelete = () => undefined, +}) => ( ( - toggleRowSelected(false)} - /> - ))} + tags={tags?.map((props) => { + const { original, id, toggleRowSelected, gotoPage } = props + const clickElement = handleElement + ? { + onClick: gotoPage, + onDelete: () => onDelete(id) || toggleRowSelected(false), + } + : {} + + return + })} /> -)) +) -GroupedTags.propTypes = { tags: PropTypes.array } +GroupedTags.propTypes = { + tags: PropTypes.array, + handleElement: PropTypes.bool, + onDelete: PropTypes.func, +} GroupedTags.displayName = 'GroupedTags' export default ACLs diff --git a/src/fireedge/src/client/containers/BackupJobs/index.js b/src/fireedge/src/client/containers/BackupJobs/index.js index 2ed020fd326..e583e1d62c2 100644 --- a/src/fireedge/src/client/containers/BackupJobs/index.js +++ b/src/fireedge/src/client/containers/BackupJobs/index.js @@ -13,7 +13,8 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { Box, Chip, Stack, Typography } from '@mui/material' +/* eslint-disable react/prop-types */ +import { Chip, Stack, Typography } from '@mui/material' import { Cancel, Pin as GotoIcon, RefreshDouble } from 'iconoir-react' import PropTypes from 'prop-types' import { ReactElement, memo, useState } from 'react' @@ -22,12 +23,13 @@ import { Row } from 'react-table' import { SubmitButton } from 'client/components/FormControl' import { Tr } from 'client/components/HOC' import MultipleTags from 'client/components/MultipleTags' -import SplitPane from 'client/components/SplitPane' +import ResourcesBackButton from 'client/components/ResourcesBackButton' import { BackupJobsTable } from 'client/components/Tables' import BackupJobActions from 'client/components/Tables/BackupJobs/actions' import BackupJobsTabs from 'client/components/Tabs/BackupJobs' import { T } from 'client/constants' +import { useGeneral } from 'client/features/General' import { useLazyGetBackupJobQuery, useUpdateBackupJobMutation, @@ -39,39 +41,46 @@ import { * @returns {ReactElement} Backup Jobs list and selected row(s) */ function BackupJobs() { - const [selectedRows, onSelectedRowsChange] = useState(() => []) + const [selectedRows, setSelectedRows] = useState(() => []) const actions = BackupJobActions() - - const hasSelectedRows = selectedRows?.length > 0 - const moreThanOneSelected = selectedRows?.length > 1 + const { zone } = useGeneral() return ( - - {({ getGridProps, GutterComponent }) => ( - - - - {hasSelectedRows && ( - <> - - {moreThanOneSelected ? ( - - ) : ( - selectedRows[0]?.toggleRowSelected(false)} - /> - )} - - )} - + ( + + )} + simpleGroupsTags={(props) => ( + )} - + info={(props) => { + const propsInfo = { + template: props?.selectedRows?.[0]?.original, + selectedRows: props?.selectedRows, + } + props?.gotoPage && (propsInfo.gotoPage = props.gotoPage) + props?.unselect && (propsInfo.unselect = props.unselect) + + return + }} + /> ) } @@ -85,8 +94,8 @@ function BackupJobs() { */ const InfoTabs = memo(({ template, gotoPage, unselect }) => { const [getBackupJob, { data, isFetching }] = useLazyGetBackupJobQuery() - const id = data?.ID ?? template.ID - const name = data?.NAME ?? template.NAME + const id = data?.ID ?? template?.ID + const name = data?.NAME ?? template?.NAME return ( @@ -140,23 +149,34 @@ InfoTabs.displayName = 'InfoTabs' * @param {Row[]} tags - Row(s) to display as tags * @returns {ReactElement} List of tags */ -const GroupedTags = memo(({ tags = [] }) => ( +const GroupedTags = ({ + tags = [], + handleElement = true, + onDelete = () => undefined, +}) => ( ( - toggleRowSelected(false)} - /> - ))} + tags={tags?.map((props) => { + const { original, id, toggleRowSelected, gotoPage } = props + const clickElement = handleElement + ? { + onClick: gotoPage, + onDelete: () => onDelete(id) || toggleRowSelected(false), + } + : {} + + return + })} /> -)) +) -GroupedTags.propTypes = { tags: PropTypes.array } +GroupedTags.propTypes = { + tags: PropTypes.array, + handleElement: PropTypes.bool, + onDelete: PropTypes.func, +} GroupedTags.displayName = 'GroupedTags' export default BackupJobs diff --git a/src/fireedge/src/client/containers/Backups/index.js b/src/fireedge/src/client/containers/Backups/index.js index 7a781772856..463096e4791 100644 --- a/src/fireedge/src/client/containers/Backups/index.js +++ b/src/fireedge/src/client/containers/Backups/index.js @@ -13,7 +13,8 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { Box, Chip, Stack, Typography } from '@mui/material' +/* eslint-disable react/prop-types */ +import { Chip, Stack, Typography } from '@mui/material' import Cancel from 'iconoir-react/dist/Cancel' import GotoIcon from 'iconoir-react/dist/Pin' import RefreshDouble from 'iconoir-react/dist/RefreshDouble' @@ -24,11 +25,12 @@ import { Row } from 'react-table' import { SubmitButton } from 'client/components/FormControl' import { Tr } from 'client/components/HOC' import MultipleTags from 'client/components/MultipleTags' -import SplitPane from 'client/components/SplitPane' +import ResourcesBackButton from 'client/components/ResourcesBackButton' import { BackupsTable } from 'client/components/Tables' import BackupActions from 'client/components/Tables/Backups/actions' import BackupTabs from 'client/components/Tabs/Backup' import { Image, T } from 'client/constants' +import { useGeneral } from 'client/features/General' import { useLazyGetImageQuery, useUpdateImageMutation, @@ -40,39 +42,46 @@ import { * @returns {ReactElement} Backups list and selected row(s) */ function Backups() { - const [selectedRows, onSelectedRowsChange] = useState(() => []) + const [selectedRows, setSelectedRows] = useState(() => []) const actions = BackupActions(selectedRows) - - const hasSelectedRows = selectedRows?.length > 0 - const moreThanOneSelected = selectedRows?.length > 1 + const { zone } = useGeneral() return ( - - {({ getGridProps, GutterComponent }) => ( - - - - {hasSelectedRows && ( - <> - - {moreThanOneSelected ? ( - - ) : ( - selectedRows[0]?.toggleRowSelected(false)} - /> - )} - - )} - + ( + + )} + simpleGroupsTags={(props) => ( + )} - + info={(props) => { + const propsInfo = { + image: props?.selectedRows?.[0]?.original, + selectedRows: props?.selectedRows, + } + props?.gotoPage && (propsInfo.gotoPage = props.gotoPage) + props?.unselect && (propsInfo.unselect = props.unselect) + + return + }} + /> ) } @@ -86,8 +95,8 @@ function Backups() { */ const InfoTabs = memo(({ image, gotoPage, unselect }) => { const [getImage, { data: lazyData, isFetching }] = useLazyGetImageQuery() - const id = lazyData?.ID ?? image.ID - const name = lazyData?.NAME ?? image.NAME + const id = lazyData?.ID ?? image?.ID + const name = lazyData?.NAME ?? image?.NAME return ( @@ -119,7 +128,7 @@ const InfoTabs = memo(({ image, gotoPage, unselect }) => { /> )} - + ) }) @@ -138,23 +147,34 @@ InfoTabs.displayName = 'InfoTabs' * @param {Row[]} tags - Row(s) to display as tags * @returns {ReactElement} List of tags */ -const GroupedTags = memo(({ tags = [] }) => ( +const GroupedTags = ({ + tags = [], + handleElement = true, + onDelete = () => undefined, +}) => ( ( - toggleRowSelected(false)} - /> - ))} + tags={tags?.map((props) => { + const { original, id, toggleRowSelected, gotoPage } = props + const clickElement = handleElement + ? { + onClick: gotoPage, + onDelete: () => onDelete(id) || toggleRowSelected(false), + } + : {} + + return + })} /> -)) +) -GroupedTags.propTypes = { tags: PropTypes.array } +GroupedTags.propTypes = { + tags: PropTypes.array, + handleElement: PropTypes.bool, + onDelete: PropTypes.func, +} GroupedTags.displayName = 'GroupedTags' export default Backups diff --git a/src/fireedge/src/client/containers/Clusters/index.js b/src/fireedge/src/client/containers/Clusters/index.js index 7718fcb112b..2b9dbe5fdc1 100644 --- a/src/fireedge/src/client/containers/Clusters/index.js +++ b/src/fireedge/src/client/containers/Clusters/index.js @@ -13,26 +13,28 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { ReactElement, useState, memo } from 'react' -import PropTypes from 'prop-types' +/* eslint-disable react/prop-types */ +import { Chip, Stack, Typography } from '@mui/material' +import Cancel from 'iconoir-react/dist/Cancel' import GotoIcon from 'iconoir-react/dist/Pin' import RefreshDouble from 'iconoir-react/dist/RefreshDouble' -import Cancel from 'iconoir-react/dist/Cancel' -import { Typography, Box, Stack, Chip } from '@mui/material' +import PropTypes from 'prop-types' +import { ReactElement, memo, useState } from 'react' import { Row } from 'react-table' +import { SubmitButton } from 'client/components/FormControl' +import { Tr } from 'client/components/HOC' +import MultipleTags from 'client/components/MultipleTags' +import ResourcesBackButton from 'client/components/ResourcesBackButton' +import { ClustersTable } from 'client/components/Tables' +import ClusterActions from 'client/components/Tables/Clusters/actions' +import ClusterTabs from 'client/components/Tabs/Cluster' +import { Cluster, T } from 'client/constants' +import { useGeneral } from 'client/features/General' import { useLazyGetClustersQuery, useUpdateClusterMutation, } from 'client/features/OneApi/cluster' -import { ClustersTable } from 'client/components/Tables' -import ClusterTabs from 'client/components/Tabs/Cluster' -import SplitPane from 'client/components/SplitPane' -import MultipleTags from 'client/components/MultipleTags' -import { SubmitButton } from 'client/components/FormControl' -import { Tr } from 'client/components/HOC' -import { T, Cluster } from 'client/constants' -import ClusterActions from 'client/components/Tables/Clusters/actions' /** * Displays a list of Clusters with a split pane between the list and selected row(s). @@ -40,40 +42,47 @@ import ClusterActions from 'client/components/Tables/Clusters/actions' * @returns {ReactElement} Clusters list and selected row(s) */ function Clusters() { - const [selectedRows, onSelectedRowsChange] = useState(() => []) - - const hasSelectedRows = selectedRows?.length > 0 - const moreThanOneSelected = selectedRows?.length > 1 + const [selectedRows, setSelectedRows] = useState(() => []) const actions = ClusterActions() + const { zone } = useGeneral() return ( - - {({ getGridProps, GutterComponent }) => ( - - - - {hasSelectedRows && ( - <> - - {moreThanOneSelected ? ( - - ) : ( - selectedRows[0]?.toggleRowSelected(false)} - /> - )} - - )} - + ( + + )} + simpleGroupsTags={(props) => ( + )} - + info={(props) => { + const propsInfo = { + cluster: props?.selectedRows?.[0]?.original, + selectedRows: props?.selectedRows, + } + props?.gotoPage && (propsInfo.gotoPage = props.gotoPage) + props?.unselect && (propsInfo.unselect = props.unselect) + + return + }} + /> ) } @@ -87,8 +96,8 @@ function Clusters() { */ const InfoTabs = memo(({ cluster, gotoPage, unselect }) => { const [get, { data: lazyData, isFetching }] = useLazyGetClustersQuery() - const id = lazyData?.ID ?? cluster.ID - const name = lazyData?.NAME ?? cluster.NAME + const id = lazyData?.ID ?? cluster?.ID + const name = lazyData?.NAME ?? cluster?.NAME return ( @@ -142,23 +151,34 @@ InfoTabs.displayName = 'InfoTabs' * @param {Row[]} tags - Row(s) to display as tags * @returns {ReactElement} List of tags */ -const GroupedTags = memo(({ tags = [] }) => ( - - ( - toggleRowSelected(false)} - /> - ))} - /> - -)) +const GroupedTags = memo( + ({ tags = [], handleElement = true, onDelete = () => undefined }) => ( + + { + const { original, id, toggleRowSelected, gotoPage } = props + const clickElement = handleElement + ? { + onClick: gotoPage, + onDelete: () => onDelete(id) || toggleRowSelected(false), + } + : {} -GroupedTags.propTypes = { tags: PropTypes.array } + return ( + + ) + })} + /> + + ) +) + +GroupedTags.propTypes = { + tags: PropTypes.array, + handleElement: PropTypes.bool, + onDelete: PropTypes.func, +} GroupedTags.displayName = 'GroupedTags' export default Clusters diff --git a/src/fireedge/src/client/containers/Datastores/index.js b/src/fireedge/src/client/containers/Datastores/index.js index 27ae2379ff7..0314477d064 100644 --- a/src/fireedge/src/client/containers/Datastores/index.js +++ b/src/fireedge/src/client/containers/Datastores/index.js @@ -13,7 +13,8 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { Box, Chip, Stack, Typography } from '@mui/material' +/* eslint-disable react/prop-types */ +import { Chip, Stack, Typography } from '@mui/material' import Cancel from 'iconoir-react/dist/Cancel' import GotoIcon from 'iconoir-react/dist/Pin' import RefreshDouble from 'iconoir-react/dist/RefreshDouble' @@ -24,11 +25,12 @@ import { Row } from 'react-table' import { SubmitButton } from 'client/components/FormControl' import { Tr } from 'client/components/HOC' import MultipleTags from 'client/components/MultipleTags' -import SplitPane from 'client/components/SplitPane' +import ResourcesBackButton from 'client/components/ResourcesBackButton' import { DatastoresTable } from 'client/components/Tables' import DatastoreActions from 'client/components/Tables/Datastores/actions' import DatastoreTabs from 'client/components/Tabs/Datastore' import { Datastore, T } from 'client/constants' +import { useGeneral } from 'client/features/General' import { useLazyGetDatastoreQuery, useUpdateDatastoreMutation, @@ -40,39 +42,46 @@ import { * @returns {ReactElement} Datastores list and selected row(s) */ function Datastores() { - const [selectedRows, onSelectedRowsChange] = useState(() => []) + const [selectedRows, setSelectedRows] = useState(() => []) const actions = DatastoreActions() - - const hasSelectedRows = selectedRows?.length > 0 - const moreThanOneSelected = selectedRows?.length > 1 + const { zone } = useGeneral() return ( - - {({ getGridProps, GutterComponent }) => ( - - - - {hasSelectedRows && ( - <> - - {moreThanOneSelected ? ( - - ) : ( - selectedRows[0]?.toggleRowSelected(false)} - /> - )} - - )} - + ( + + )} + simpleGroupsTags={(props) => ( + )} - + info={(props) => { + const propsInfo = { + datastore: props?.selectedRows?.[0]?.original, + selectedRows: props?.selectedRows, + } + props?.gotoPage && (propsInfo.gotoPage = props.gotoPage) + props?.unselect && (propsInfo.unselect = props.unselect) + + return + }} + /> ) } @@ -87,8 +96,8 @@ function Datastores() { const InfoTabs = memo(({ datastore, gotoPage, unselect }) => { const [getDatastore, { data: lazyData, isFetching }] = useLazyGetDatastoreQuery() - const id = lazyData?.ID ?? datastore.ID - const name = lazyData?.NAME ?? datastore.NAME + const id = lazyData?.ID ?? datastore?.ID + const name = lazyData?.NAME ?? datastore?.NAME return ( @@ -120,7 +129,7 @@ const InfoTabs = memo(({ datastore, gotoPage, unselect }) => { /> )} - + ) }) @@ -139,23 +148,34 @@ InfoTabs.displayName = 'InfoTabs' * @param {Row[]} tags - Row(s) to display as tags * @returns {ReactElement} List of tags */ -const GroupedTags = memo(({ tags = [] }) => ( +const GroupedTags = ({ + tags = [], + handleElement = true, + onDelete = () => undefined, +}) => ( ( - toggleRowSelected(false)} - /> - ))} + tags={tags?.map((props) => { + const { original, id, toggleRowSelected, gotoPage } = props + const clickElement = handleElement + ? { + onClick: gotoPage, + onDelete: () => onDelete(id) || toggleRowSelected(false), + } + : {} + + return + })} /> -)) +) -GroupedTags.propTypes = { tags: PropTypes.array } +GroupedTags.propTypes = { + tags: PropTypes.array, + handleElement: PropTypes.bool, + onDelete: PropTypes.func, +} GroupedTags.displayName = 'GroupedTags' export default Datastores diff --git a/src/fireedge/src/client/containers/Files/index.js b/src/fireedge/src/client/containers/Files/index.js index 76e92bc1081..60b86b77a7e 100644 --- a/src/fireedge/src/client/containers/Files/index.js +++ b/src/fireedge/src/client/containers/Files/index.js @@ -13,23 +13,25 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { ReactElement, useState, memo } from 'react' -import PropTypes from 'prop-types' +/* eslint-disable react/prop-types */ +import { Chip, Stack, Typography } from '@mui/material' +import Cancel from 'iconoir-react/dist/Cancel' import GotoIcon from 'iconoir-react/dist/Pin' import RefreshDouble from 'iconoir-react/dist/RefreshDouble' -import Cancel from 'iconoir-react/dist/Cancel' -import { Typography, Box, Stack, Chip } from '@mui/material' +import PropTypes from 'prop-types' +import { ReactElement, memo, useState } from 'react' import { Row } from 'react-table' -import { useLazyGetImageQuery } from 'client/features/OneApi/image' +import { SubmitButton } from 'client/components/FormControl' +import { Tr } from 'client/components/HOC' +import MultipleTags from 'client/components/MultipleTags' +import ResourcesBackButton from 'client/components/ResourcesBackButton' import { FilesTable } from 'client/components/Tables' import fileActions from 'client/components/Tables/Files/actions' import FileTabs from 'client/components/Tabs/File' -import SplitPane from 'client/components/SplitPane' -import MultipleTags from 'client/components/MultipleTags' -import { SubmitButton } from 'client/components/FormControl' -import { Tr } from 'client/components/HOC' -import { T, Image } from 'client/constants' +import { Image, T } from 'client/constants' +import { useGeneral } from 'client/features/General' +import { useLazyGetImageQuery } from 'client/features/OneApi/image' /** * Displays a list of Files with a split pane between the list and selected row(s). @@ -37,38 +39,44 @@ import { T, Image } from 'client/constants' * @returns {ReactElement} Files list and selected row(s) */ function Files() { - const [selectedRows, onSelectedRowsChange] = useState(() => []) + const [selectedRows, setSelectedRows] = useState(() => []) const actions = fileActions() - - const hasSelectedRows = selectedRows?.length > 0 - const moreThanOneSelected = selectedRows?.length > 1 + const { zone } = useGeneral() return ( - - {({ getGridProps, GutterComponent }) => ( - - - - {hasSelectedRows && ( - <> - - {moreThanOneSelected ? ( - - ) : ( - selectedRows[0]?.toggleRowSelected(false)} - /> - )} - - )} - + ( + + )} + simpleGroupsTags={(props) => ( + )} - + info={(props) => { + const propsInfo = { + file: props?.selectedRows?.[0]?.original, + selectedRows: props?.selectedRows, + } + props?.gotoPage && (propsInfo.gotoPage = props.gotoPage) + props?.unselect && (propsInfo.unselect = props.unselect) + + return + }} + /> ) } @@ -82,8 +90,8 @@ function Files() { */ const InfoTabs = memo(({ file, gotoPage, unselect }) => { const [getImage, { data: lazyData, isFetching }] = useLazyGetImageQuery() - const id = lazyData?.ID ?? file.ID - const name = lazyData?.NAME ?? file.NAME + const id = lazyData?.ID ?? file?.ID + const name = lazyData?.NAME ?? file?.NAME return ( @@ -115,7 +123,7 @@ const InfoTabs = memo(({ file, gotoPage, unselect }) => { /> )} - + ) }) @@ -134,23 +142,34 @@ InfoTabs.displayName = 'InfoTabs' * @param {Row[]} tags - Row(s) to display as tags * @returns {ReactElement} List of tags */ -const GroupedTags = memo(({ tags = [] }) => ( +const GroupedTags = ({ + tags = [], + handleElement = true, + onDelete = () => undefined, +}) => ( ( - toggleRowSelected(false)} - /> - ))} + tags={tags?.map((props) => { + const { original, id, toggleRowSelected, gotoPage } = props + const clickElement = handleElement + ? { + onClick: gotoPage, + onDelete: () => onDelete(id) || toggleRowSelected(false), + } + : {} + + return + })} /> -)) +) -GroupedTags.propTypes = { tags: PropTypes.array } +GroupedTags.propTypes = { + tags: PropTypes.array, + handleElement: PropTypes.bool, + onDelete: PropTypes.func, +} GroupedTags.displayName = 'GroupedTags' export default Files diff --git a/src/fireedge/src/client/containers/Groups/index.js b/src/fireedge/src/client/containers/Groups/index.js index c6e46cf5be6..fb738ddb951 100644 --- a/src/fireedge/src/client/containers/Groups/index.js +++ b/src/fireedge/src/client/containers/Groups/index.js @@ -13,25 +13,27 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { ReactElement, useState, memo } from 'react' -import PropTypes from 'prop-types' +/* eslint-disable react/prop-types */ +import { Chip, Stack, Typography } from '@mui/material' +import Cancel from 'iconoir-react/dist/Cancel' import GotoIcon from 'iconoir-react/dist/Pin' import RefreshDouble from 'iconoir-react/dist/RefreshDouble' -import Cancel from 'iconoir-react/dist/Cancel' -import { Typography, Box, Stack, Chip } from '@mui/material' +import PropTypes from 'prop-types' +import { ReactElement, memo, useState } from 'react' import { Row } from 'react-table' +import { SubmitButton } from 'client/components/FormControl' +import { Tr } from 'client/components/HOC' +import MultipleTags from 'client/components/MultipleTags' +import ResourcesBackButton from 'client/components/ResourcesBackButton' +import { GroupsTable } from 'client/components/Tables' +import GroupTabs from 'client/components/Tabs/Group' +import { Group, T } from 'client/constants' +import { useGeneral } from 'client/features/General' import { useLazyGetGroupQuery, useUpdateGroupMutation, } from 'client/features/OneApi/group' -import { GroupsTable } from 'client/components/Tables' -import GroupTabs from 'client/components/Tabs/Group' -import SplitPane from 'client/components/SplitPane' -import MultipleTags from 'client/components/MultipleTags' -import { SubmitButton } from 'client/components/FormControl' -import { Tr } from 'client/components/HOC' -import { T, Group } from 'client/constants' import GroupActions from 'client/components/Tables/Groups/actions' @@ -41,40 +43,46 @@ import GroupActions from 'client/components/Tables/Groups/actions' * @returns {ReactElement} Groups list and selected row(s) */ function Groups() { - const [selectedRows, onSelectedRowsChange] = useState(() => []) - - const hasSelectedRows = selectedRows?.length > 0 - const moreThanOneSelected = selectedRows?.length > 1 - + const [selectedRows, setSelectedRows] = useState(() => []) const actions = GroupActions() + const { zone } = useGeneral() return ( - - {({ getGridProps, GutterComponent }) => ( - - - - {hasSelectedRows && ( - <> - - {moreThanOneSelected ? ( - - ) : ( - selectedRows[0]?.toggleRowSelected(false)} - /> - )} - - )} - + ( + )} - + simpleGroupsTags={(props) => ( + + )} + info={(props) => { + const propsInfo = { + group: props?.selectedRows?.[0]?.original, + selectedRows: props?.selectedRows, + } + props?.gotoPage && (propsInfo.gotoPage = props.gotoPage) + props?.unselect && (propsInfo.unselect = props.unselect) + + return + }} + /> ) } @@ -88,8 +96,8 @@ function Groups() { */ const InfoTabs = memo(({ group, gotoPage, unselect }) => { const [get, { data: lazyData, isFetching }] = useLazyGetGroupQuery() - const id = lazyData?.ID ?? group.ID - const name = lazyData?.NAME ?? group.NAME + const id = lazyData?.ID ?? group?.ID + const name = lazyData?.NAME ?? group?.NAME return ( @@ -143,23 +151,34 @@ InfoTabs.displayName = 'InfoTabs' * @param {Row[]} tags - Row(s) to display as tags * @returns {ReactElement} List of tags */ -const GroupedTags = memo(({ tags = [] }) => ( +const GroupedTags = ({ + tags = [], + handleElement = true, + onDelete = () => undefined, +}) => ( ( - toggleRowSelected(false)} - /> - ))} + tags={tags?.map((props) => { + const { original, id, toggleRowSelected, gotoPage } = props + const clickElement = handleElement + ? { + onClick: gotoPage, + onDelete: () => onDelete(id) || toggleRowSelected(false), + } + : {} + + return + })} /> -)) +) -GroupedTags.propTypes = { tags: PropTypes.array } +GroupedTags.propTypes = { + tags: PropTypes.array, + handleElement: PropTypes.bool, + onDelete: PropTypes.func, +} GroupedTags.displayName = 'GroupedTags' export default Groups diff --git a/src/fireedge/src/client/containers/Hosts/Detail.js b/src/fireedge/src/client/containers/Hosts/Detail.js index 3033b723aeb..b46110d4d86 100644 --- a/src/fireedge/src/client/containers/Hosts/Detail.js +++ b/src/fireedge/src/client/containers/Hosts/Detail.js @@ -14,8 +14,9 @@ * limitations under the License. * * ------------------------------------------------------------------------- */ import { ReactElement } from 'react' -import { useParams, Redirect } from 'react-router-dom' +import { Redirect, useParams } from 'react-router-dom' +import BackButton from 'client/components/ResourcesBackButton/BackButton' import HostTabs from 'client/components/Tabs/Host' /** @@ -30,7 +31,12 @@ function HostDetail() { return } - return + return ( + <> + + + + ) } export default HostDetail diff --git a/src/fireedge/src/client/containers/Hosts/index.js b/src/fireedge/src/client/containers/Hosts/index.js index 50fc2f4aeaf..fab309d1321 100644 --- a/src/fireedge/src/client/containers/Hosts/index.js +++ b/src/fireedge/src/client/containers/Hosts/index.js @@ -13,7 +13,8 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { Box, Chip, Stack, Typography } from '@mui/material' +/* eslint-disable react/prop-types */ +import { Chip, Stack, Typography } from '@mui/material' import Cancel from 'iconoir-react/dist/Cancel' import GotoIcon from 'iconoir-react/dist/Pin' import RefreshDouble from 'iconoir-react/dist/RefreshDouble' @@ -24,7 +25,7 @@ import { Row } from 'react-table' import { SubmitButton } from 'client/components/FormControl' import { Tr } from 'client/components/HOC' import MultipleTags from 'client/components/MultipleTags' -import SplitPane from 'client/components/SplitPane' +import ResourcesBackButton from 'client/components/ResourcesBackButton' import { HostsTable } from 'client/components/Tables' import HostActions from 'client/components/Tables/Hosts/actions' import HostTabs from 'client/components/Tabs/Host' @@ -41,41 +42,46 @@ import { * @returns {ReactElement} Hosts list and selected row(s) */ function Hosts() { - const [selectedRows, onSelectedRowsChange] = useState(() => []) + const [selectedRows, setSelectedRows] = useState(() => []) const actions = HostActions() const { zone } = useGeneral() - const hasSelectedRows = selectedRows?.length > 0 - const moreThanOneSelected = selectedRows?.length > 1 - return ( - - {({ getGridProps, GutterComponent }) => ( - - - - {hasSelectedRows && ( - <> - - {moreThanOneSelected ? ( - - ) : ( - selectedRows[0]?.toggleRowSelected(false)} - /> - )} - - )} - + ( + + )} + simpleGroupsTags={(props) => ( + )} - + info={(props) => { + const propsInfo = { + host: props?.selectedRows?.[0]?.original, + selectedRows: props?.selectedRows, + } + props?.gotoPage && (propsInfo.gotoPage = props.gotoPage) + props?.unselect && (propsInfo.unselect = props.unselect) + + return + }} + /> ) } @@ -89,8 +95,8 @@ function Hosts() { */ const InfoTabs = memo(({ host, gotoPage, unselect }) => { const [getVm, { data: lazyData, isFetching }] = useLazyGetHostQuery() - const id = lazyData?.ID ?? host.ID - const name = lazyData?.NAME ?? host.NAME + const id = lazyData?.ID ?? host?.ID + const name = lazyData?.NAME ?? host?.NAME return ( @@ -144,23 +150,34 @@ InfoTabs.displayName = 'InfoTabs' * @param {Row[]} tags - Row(s) to display as tags * @returns {ReactElement} List of tags */ -const GroupedTags = memo(({ tags = [] }) => ( +const GroupedTags = ({ + tags = [], + handleElement = true, + onDelete = () => undefined, +}) => ( ( - toggleRowSelected(false)} - /> - ))} + tags={tags?.map((props) => { + const { original, id, toggleRowSelected, gotoPage } = props + const clickElement = handleElement + ? { + onClick: gotoPage, + onDelete: () => onDelete(id) || toggleRowSelected(false), + } + : {} + + return + })} /> -)) +) -GroupedTags.propTypes = { tags: PropTypes.array } +GroupedTags.propTypes = { + tags: PropTypes.array, + handleElement: PropTypes.bool, + onDelete: PropTypes.func, +} GroupedTags.displayName = 'GroupedTags' export default Hosts diff --git a/src/fireedge/src/client/containers/Images/index.js b/src/fireedge/src/client/containers/Images/index.js index 4701f69d0f5..8d6740ad811 100644 --- a/src/fireedge/src/client/containers/Images/index.js +++ b/src/fireedge/src/client/containers/Images/index.js @@ -13,7 +13,8 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { Box, Chip, Stack, Typography } from '@mui/material' +/* eslint-disable react/prop-types */ +import { Chip, Stack, Typography } from '@mui/material' import Cancel from 'iconoir-react/dist/Cancel' import GotoIcon from 'iconoir-react/dist/Pin' import RefreshDouble from 'iconoir-react/dist/RefreshDouble' @@ -24,14 +25,15 @@ import { Row } from 'react-table' import { SubmitButton } from 'client/components/FormControl' import { Tr } from 'client/components/HOC' import MultipleTags from 'client/components/MultipleTags' -import SplitPane from 'client/components/SplitPane' +import ResourcesBackButton from 'client/components/ResourcesBackButton' import { ImagesTable } from 'client/components/Tables' import ImageActions from 'client/components/Tables/Images/actions' import ImageTabs from 'client/components/Tabs/Image' import { Image, T } from 'client/constants' +import { useGeneral } from 'client/features/General' import { - useUpdateImageMutation, useLazyGetImageQuery, + useUpdateImageMutation, } from 'client/features/OneApi/image' /** @@ -40,39 +42,46 @@ import { * @returns {ReactElement} Images list and selected row(s) */ function Images() { - const [selectedRows, onSelectedRowsChange] = useState(() => []) + const [selectedRows, setSelectedRows] = useState(() => []) const actions = ImageActions() - - const hasSelectedRows = selectedRows?.length > 0 - const moreThanOneSelected = selectedRows?.length > 1 + const { zone } = useGeneral() return ( - - {({ getGridProps, GutterComponent }) => ( - - - - {hasSelectedRows && ( - <> - - {moreThanOneSelected ? ( - - ) : ( - selectedRows[0]?.toggleRowSelected(false)} - /> - )} - - )} - + ( + )} - + simpleGroupsTags={(props) => ( + + )} + info={(props) => { + const propsInfo = { + image: props?.selectedRows?.[0]?.original, + selectedRows: props?.selectedRows, + } + props?.gotoPage && (propsInfo.gotoPage = props.gotoPage) + props?.unselect && (propsInfo.unselect = props.unselect) + + return + }} + /> ) } @@ -86,8 +95,8 @@ function Images() { */ const InfoTabs = memo(({ image, gotoPage, unselect }) => { const [getImage, { data: lazyData, isFetching }] = useLazyGetImageQuery() - const id = lazyData?.ID ?? image.ID - const name = lazyData?.NAME ?? image.NAME + const id = lazyData?.ID ?? image?.ID + const name = lazyData?.NAME ?? image?.NAME return ( @@ -119,7 +128,7 @@ const InfoTabs = memo(({ image, gotoPage, unselect }) => { /> )} - + ) }) @@ -138,23 +147,34 @@ InfoTabs.displayName = 'InfoTabs' * @param {Row[]} tags - Row(s) to display as tags * @returns {ReactElement} List of tags */ -const GroupedTags = memo(({ tags = [] }) => ( +const GroupedTags = ({ + tags = [], + handleElement = true, + onDelete = () => undefined, +}) => ( ( - toggleRowSelected(false)} - /> - ))} + tags={tags?.map((props) => { + const { original, id, toggleRowSelected, gotoPage } = props + const clickElement = handleElement + ? { + onClick: gotoPage, + onDelete: () => onDelete(id) || toggleRowSelected(false), + } + : {} + + return + })} /> -)) +) -GroupedTags.propTypes = { tags: PropTypes.array } +GroupedTags.propTypes = { + tags: PropTypes.array, + handleElement: PropTypes.bool, + onDelete: PropTypes.func, +} GroupedTags.displayName = 'GroupedTags' export default Images diff --git a/src/fireedge/src/client/containers/MarketplaceApps/index.js b/src/fireedge/src/client/containers/MarketplaceApps/index.js index 55bec9495e3..c960a6149f1 100644 --- a/src/fireedge/src/client/containers/MarketplaceApps/index.js +++ b/src/fireedge/src/client/containers/MarketplaceApps/index.js @@ -13,26 +13,28 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { ReactElement, useState, memo } from 'react' -import PropTypes from 'prop-types' +/* eslint-disable react/prop-types */ +import { Chip, Stack, Typography } from '@mui/material' +import Cancel from 'iconoir-react/dist/Cancel' import GotoIcon from 'iconoir-react/dist/Pin' import RefreshDouble from 'iconoir-react/dist/RefreshDouble' -import Cancel from 'iconoir-react/dist/Cancel' -import { Typography, Box, Stack, Chip } from '@mui/material' +import PropTypes from 'prop-types' +import { ReactElement, memo, useState } from 'react' import { Row } from 'react-table' -import { - useUpdateAppMutation, - useLazyGetMarketplaceAppQuery, -} from 'client/features/OneApi/marketplaceApp' +import { SubmitButton } from 'client/components/FormControl' +import { Tr } from 'client/components/HOC' +import MultipleTags from 'client/components/MultipleTags' +import ResourcesBackButton from 'client/components/ResourcesBackButton' import { MarketplaceAppsTable } from 'client/components/Tables' import MarketplaceAppActions from 'client/components/Tables/MarketplaceApps/actions' import MarketplaceAppsTabs from 'client/components/Tabs/MarketplaceApp' -import SplitPane from 'client/components/SplitPane' -import MultipleTags from 'client/components/MultipleTags' -import { SubmitButton } from 'client/components/FormControl' -import { Tr } from 'client/components/HOC' -import { T, MarketplaceApp } from 'client/constants' +import { MarketplaceApp, T } from 'client/constants' +import { useGeneral } from 'client/features/General' +import { + useLazyGetMarketplaceAppQuery, + useUpdateAppMutation, +} from 'client/features/OneApi/marketplaceApp' /** * Displays a list of Marketplace Apps with a split pane between the list and selected row(s). @@ -40,39 +42,46 @@ import { T, MarketplaceApp } from 'client/constants' * @returns {ReactElement} Marketplace Apps list and selected row(s) */ function MarketplaceApps() { - const [selectedRows, onSelectedRowsChange] = useState(() => []) + const [selectedRows, setSelectedRows] = useState(() => []) const actions = MarketplaceAppActions() - - const hasSelectedRows = selectedRows?.length > 0 - const moreThanOneSelected = selectedRows?.length > 1 + const { zone } = useGeneral() return ( - - {({ getGridProps, GutterComponent }) => ( - - - - {hasSelectedRows && ( - <> - - {moreThanOneSelected ? ( - - ) : ( - selectedRows[0]?.toggleRowSelected(false)} - /> - )} - - )} - + ( + )} - + simpleGroupsTags={(props) => ( + + )} + info={(props) => { + const propsInfo = { + app: props?.selectedRows?.[0]?.original, + selectedRows: props?.selectedRows, + } + props?.gotoPage && (propsInfo.gotoPage = props.gotoPage) + props?.unselect && (propsInfo.unselect = props.unselect) + + return + }} + /> ) } @@ -88,8 +97,8 @@ const InfoTabs = memo(({ app, gotoPage, unselect }) => { const [get, queryState] = useLazyGetMarketplaceAppQuery() const { data: lazyData, isFetching } = queryState - const id = lazyData?.ID ?? app.ID - const name = lazyData?.NAME ?? app.NAME + const id = lazyData?.ID ?? app?.ID + const name = lazyData?.NAME ?? app?.NAME return ( @@ -143,23 +152,34 @@ InfoTabs.displayName = 'InfoTabs' * @param {Row[]} tags - Row(s) to display as tags * @returns {ReactElement} List of tags */ -const GroupedTags = memo(({ tags = [] }) => ( +const GroupedTags = ({ + tags = [], + handleElement = true, + onDelete = () => undefined, +}) => ( ( - toggleRowSelected(false)} - /> - ))} + tags={tags?.map((props) => { + const { original, id, toggleRowSelected, gotoPage } = props + const clickElement = handleElement + ? { + onClick: gotoPage, + onDelete: () => onDelete(id) || toggleRowSelected(false), + } + : {} + + return + })} /> -)) +) -GroupedTags.propTypes = { tags: PropTypes.array } +GroupedTags.propTypes = { + tags: PropTypes.array, + handleElement: PropTypes.bool, + onDelete: PropTypes.func, +} GroupedTags.displayName = 'GroupedTags' export default MarketplaceApps diff --git a/src/fireedge/src/client/containers/Marketplaces/index.js b/src/fireedge/src/client/containers/Marketplaces/index.js index aa050578f7a..fd7f33dcf4d 100644 --- a/src/fireedge/src/client/containers/Marketplaces/index.js +++ b/src/fireedge/src/client/containers/Marketplaces/index.js @@ -13,25 +13,27 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { ReactElement, useState, memo } from 'react' -import PropTypes from 'prop-types' +/* eslint-disable react/prop-types */ +import { Chip, Stack, Typography } from '@mui/material' +import Cancel from 'iconoir-react/dist/Cancel' import GotoIcon from 'iconoir-react/dist/Pin' import RefreshDouble from 'iconoir-react/dist/RefreshDouble' -import Cancel from 'iconoir-react/dist/Cancel' -import { Typography, Box, Stack, Chip } from '@mui/material' +import PropTypes from 'prop-types' +import { ReactElement, memo, useState } from 'react' import { Row } from 'react-table' +import { SubmitButton } from 'client/components/FormControl' +import { Tr } from 'client/components/HOC' +import MultipleTags from 'client/components/MultipleTags' +import ResourcesBackButton from 'client/components/ResourcesBackButton' +import { MarketplacesTable } from 'client/components/Tables' +import MarketplaceTabs from 'client/components/Tabs/Marketplace' +import { Marketplace, T } from 'client/constants' +import { useGeneral } from 'client/features/General' import { useLazyGetMarketplaceQuery, useUpdateMarketplaceMutation, } from 'client/features/OneApi/marketplace' -import { MarketplacesTable } from 'client/components/Tables' -import MarketplaceTabs from 'client/components/Tabs/Marketplace' -import SplitPane from 'client/components/SplitPane' -import MultipleTags from 'client/components/MultipleTags' -import { SubmitButton } from 'client/components/FormControl' -import { Tr } from 'client/components/HOC' -import { T, Marketplace } from 'client/constants' import MarketplaceActions from 'client/components/Tables/Marketplaces/actions' @@ -41,40 +43,46 @@ import MarketplaceActions from 'client/components/Tables/Marketplaces/actions' * @returns {ReactElement} Marketplaces list and selected row(s) */ function Marketplaces() { - const [selectedRows, onSelectedRowsChange] = useState(() => []) - - const hasSelectedRows = selectedRows?.length > 0 - const moreThanOneSelected = selectedRows?.length > 1 - + const [selectedRows, setSelectedRows] = useState(() => []) const actions = MarketplaceActions() + const { zone } = useGeneral() return ( - - {({ getGridProps, GutterComponent }) => ( - - - - {hasSelectedRows && ( - <> - - {moreThanOneSelected ? ( - - ) : ( - selectedRows[0]?.toggleRowSelected(false)} - /> - )} - - )} - + ( + )} - + simpleGroupsTags={(props) => ( + + )} + info={(props) => { + const propsInfo = { + market: props?.selectedRows?.[0]?.original, + selectedRows: props?.selectedRows, + } + props?.gotoPage && (propsInfo.gotoPage = props.gotoPage) + props?.unselect && (propsInfo.unselect = props.unselect) + + return + }} + /> ) } @@ -88,8 +96,8 @@ function Marketplaces() { */ const InfoTabs = memo(({ market, gotoPage, unselect }) => { const [get, { data: lazyData, isFetching }] = useLazyGetMarketplaceQuery() - const id = lazyData?.ID ?? market.ID - const name = lazyData?.NAME ?? market.NAME + const id = lazyData?.ID ?? market?.ID + const name = lazyData?.NAME ?? market?.NAME return ( @@ -143,23 +151,34 @@ InfoTabs.displayName = 'InfoTabs' * @param {Row[]} tags - Row(s) to display as tags * @returns {ReactElement} List of tags */ -const GroupedTags = memo(({ tags = [] }) => ( +const GroupedTags = ({ + tags = [], + handleElement = true, + onDelete = () => undefined, +}) => ( ( - toggleRowSelected(false)} - /> - ))} + tags={tags?.map((props) => { + const { original, id, toggleRowSelected, gotoPage } = props + const clickElement = handleElement + ? { + onClick: gotoPage, + onDelete: () => onDelete(id) || toggleRowSelected(false), + } + : {} + + return + })} /> -)) +) -GroupedTags.propTypes = { tags: PropTypes.array } +GroupedTags.propTypes = { + tags: PropTypes.array, + handleElement: PropTypes.bool, + onDelete: PropTypes.func, +} GroupedTags.displayName = 'GroupedTags' export default Marketplaces diff --git a/src/fireedge/src/client/containers/SecurityGroups/index.js b/src/fireedge/src/client/containers/SecurityGroups/index.js index cccbe17e742..4bed34f505a 100644 --- a/src/fireedge/src/client/containers/SecurityGroups/index.js +++ b/src/fireedge/src/client/containers/SecurityGroups/index.js @@ -13,26 +13,28 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { ReactElement, useState, memo } from 'react' -import PropTypes from 'prop-types' +/* eslint-disable react/prop-types */ +import { Chip, Stack, Typography } from '@mui/material' +import Cancel from 'iconoir-react/dist/Cancel' import GotoIcon from 'iconoir-react/dist/Pin' import RefreshDouble from 'iconoir-react/dist/RefreshDouble' -import Cancel from 'iconoir-react/dist/Cancel' -import { Typography, Box, Stack, Chip } from '@mui/material' +import PropTypes from 'prop-types' +import { ReactElement, memo, useState } from 'react' import { Row } from 'react-table' +import { SubmitButton } from 'client/components/FormControl' +import { Tr } from 'client/components/HOC' +import MultipleTags from 'client/components/MultipleTags' +import ResourcesBackButton from 'client/components/ResourcesBackButton' +import { SecurityGroupsTable } from 'client/components/Tables' +import SecurityGroupsActions from 'client/components/Tables/SecurityGroups/actions' +import SecurityGroupsTabs from 'client/components/Tabs/SecurityGroup' +import { Image, T } from 'client/constants' +import { useGeneral } from 'client/features/General' import { useLazyGetSecGroupQuery, useUpdateSecGroupMutation, } from 'client/features/OneApi/securityGroup' -import { SecurityGroupsTable } from 'client/components/Tables' -import SecurityGroupsActions from 'client/components/Tables/SecurityGroups/actions' -import SecurityGroupsTabs from 'client/components/Tabs/SecurityGroup' -import SplitPane from 'client/components/SplitPane' -import MultipleTags from 'client/components/MultipleTags' -import { SubmitButton } from 'client/components/FormControl' -import { Tr } from 'client/components/HOC' -import { T, Image } from 'client/constants' /** * Displays a list of Security Groups with a split pane between the list and selected row(s). @@ -40,39 +42,46 @@ import { T, Image } from 'client/constants' * @returns {ReactElement} Security Groups list and selected row(s) */ function SecurityGroups() { - const [selectedRows, onSelectedRowsChange] = useState(() => []) + const [selectedRows, setSelectedRows] = useState(() => []) const actions = SecurityGroupsActions() - - const hasSelectedRows = selectedRows?.length > 0 - const moreThanOneSelected = selectedRows?.length > 1 + const { zone } = useGeneral() return ( - - {({ getGridProps, GutterComponent }) => ( - - - - {hasSelectedRows && ( - <> - - {moreThanOneSelected ? ( - - ) : ( - selectedRows[0]?.toggleRowSelected(false)} - /> - )} - - )} - + ( + )} - + simpleGroupsTags={(props) => ( + + )} + info={(props) => { + const propsInfo = { + securityGroup: props?.selectedRows?.[0]?.original, + selectedRows: props?.selectedRows, + } + props?.gotoPage && (propsInfo.gotoPage = props.gotoPage) + props?.unselect && (propsInfo.unselect = props.unselect) + + return + }} + /> ) } @@ -87,8 +96,8 @@ function SecurityGroups() { const InfoTabs = memo(({ securityGroup, gotoPage, unselect }) => { const [getSecurityGroup, { data: lazyData, isFetching }] = useLazyGetSecGroupQuery() - const id = lazyData?.ID ?? securityGroup.ID - const name = lazyData?.NAME ?? securityGroup.NAME + const id = lazyData?.ID ?? securityGroup?.ID + const name = lazyData?.NAME ?? securityGroup?.NAME return ( @@ -120,7 +129,7 @@ const InfoTabs = memo(({ securityGroup, gotoPage, unselect }) => { /> )} - + ) }) @@ -139,23 +148,34 @@ InfoTabs.displayName = 'InfoTabs' * @param {Row[]} tags - Row(s) to display as tags * @returns {ReactElement} List of tags */ -const GroupedTags = memo(({ tags = [] }) => ( +const GroupedTags = ({ + tags = [], + handleElement = true, + onDelete = () => undefined, +}) => ( ( - toggleRowSelected(false)} - /> - ))} + tags={tags?.map((props) => { + const { original, id, toggleRowSelected, gotoPage } = props + const clickElement = handleElement + ? { + onClick: gotoPage, + onDelete: () => onDelete(id) || toggleRowSelected(false), + } + : {} + + return + })} /> -)) +) -GroupedTags.propTypes = { tags: PropTypes.array } +GroupedTags.propTypes = { + tags: PropTypes.array, + handleElement: PropTypes.bool, + onDelete: PropTypes.func, +} GroupedTags.displayName = 'GroupedTags' export default SecurityGroups diff --git a/src/fireedge/src/client/containers/ServiceTemplates/index.js b/src/fireedge/src/client/containers/ServiceTemplates/index.js index 63af1242eb4..5a1669ffa0a 100644 --- a/src/fireedge/src/client/containers/ServiceTemplates/index.js +++ b/src/fireedge/src/client/containers/ServiceTemplates/index.js @@ -13,23 +13,25 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { ReactElement, useState, memo } from 'react' -import PropTypes from 'prop-types' +/* eslint-disable react/prop-types */ +import { Chip, Stack, Typography } from '@mui/material' +import Cancel from 'iconoir-react/dist/Cancel' import GotoIcon from 'iconoir-react/dist/Pin' import RefreshDouble from 'iconoir-react/dist/RefreshDouble' -import Cancel from 'iconoir-react/dist/Cancel' -import { Typography, Box, Stack, Chip } from '@mui/material' +import PropTypes from 'prop-types' +import { ReactElement, memo, useState } from 'react' import { Row } from 'react-table' -import { useLazyGetServiceTemplateQuery } from 'client/features/OneApi/serviceTemplate' -import { ServiceTemplatesTable } from 'client/components/Tables' -import ServiceTemplateTabs from 'client/components/Tabs/ServiceTemplate' -import SplitPane from 'client/components/SplitPane' -import MultipleTags from 'client/components/MultipleTags' -import ServiceTemplateActions from 'client/components/Tables/ServiceTemplates/actions' import { SubmitButton } from 'client/components/FormControl' import { Tr } from 'client/components/HOC' +import MultipleTags from 'client/components/MultipleTags' +import ResourcesBackButton from 'client/components/ResourcesBackButton' +import { ServiceTemplatesTable } from 'client/components/Tables' +import ServiceTemplateActions from 'client/components/Tables/ServiceTemplates/actions' +import ServiceTemplateTabs from 'client/components/Tabs/ServiceTemplate' import { T } from 'client/constants' +import { useGeneral } from 'client/features/General' +import { useLazyGetServiceTemplateQuery } from 'client/features/OneApi/serviceTemplate' /** * Displays a list of Service Templates with a split pane between @@ -38,39 +40,44 @@ import { T } from 'client/constants' * @returns {ReactElement} Service Templates list and selected row(s) */ function ServiceTemplates() { - const [selectedRows, onSelectedRowsChange] = useState(() => []) + const [selectedRows, setSelectedRows] = useState(() => []) const actions = ServiceTemplateActions() - - const hasSelectedRows = selectedRows?.length > 0 - const moreThanOneSelected = selectedRows?.length > 1 + const { zone } = useGeneral() return ( - - {({ getGridProps, GutterComponent }) => ( - - - - {hasSelectedRows && ( - <> - - {moreThanOneSelected ? ( - - ) : ( - selectedRows[0]?.toggleRowSelected(false)} - /> - )} - - )} - + ( + + )} + simpleGroupsTags={(props) => ( + )} - + info={(props) => { + const propsInfo = { + template: props?.selectedRows?.[0]?.original, + selectedRows: props?.selectedRows, + } + props?.gotoPage && (propsInfo.gotoPage = props.gotoPage) + props?.unselect && (propsInfo.unselect = props.unselect) + + return + }} + /> ) } @@ -84,8 +91,8 @@ function ServiceTemplates() { */ const InfoTabs = memo(({ template, gotoPage, unselect }) => { const [get, { data: lazyData, isFetching }] = useLazyGetServiceTemplateQuery() - const id = lazyData?.ID ?? template.ID - const name = lazyData?.NAME ?? template.NAME + const id = lazyData?.ID ?? template?.ID + const name = lazyData?.NAME ?? template?.NAME return ( @@ -139,23 +146,34 @@ InfoTabs.displayName = 'InfoTabs' * @param {Row[]} tags - Row(s) to display as tags * @returns {ReactElement} List of tags */ -const GroupedTags = memo(({ tags = [] }) => ( +const GroupedTags = ({ + tags = [], + handleElement = true, + onDelete = () => undefined, +}) => ( ( - toggleRowSelected(false)} - /> - ))} + tags={tags?.map((props) => { + const { original, id, toggleRowSelected, gotoPage } = props + const clickElement = handleElement + ? { + onClick: gotoPage, + onDelete: () => onDelete(id) || toggleRowSelected(false), + } + : {} + + return + })} /> -)) +) -GroupedTags.propTypes = { tags: PropTypes.array } +GroupedTags.propTypes = { + tags: PropTypes.array, + handleElement: PropTypes.bool, + onDelete: PropTypes.func, +} GroupedTags.displayName = 'GroupedTags' export default ServiceTemplates diff --git a/src/fireedge/src/client/containers/Services/index.js b/src/fireedge/src/client/containers/Services/index.js index 955231b30de..2096ba44dd7 100644 --- a/src/fireedge/src/client/containers/Services/index.js +++ b/src/fireedge/src/client/containers/Services/index.js @@ -13,23 +13,25 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { ReactElement, useState, memo } from 'react' -import PropTypes from 'prop-types' +/* eslint-disable react/prop-types */ +import { Chip, Stack, Typography } from '@mui/material' +import Cancel from 'iconoir-react/dist/Cancel' import GotoIcon from 'iconoir-react/dist/Pin' import RefreshDouble from 'iconoir-react/dist/RefreshDouble' -import Cancel from 'iconoir-react/dist/Cancel' -import { Typography, Box, Stack, Chip } from '@mui/material' +import PropTypes from 'prop-types' +import { ReactElement, memo, useState } from 'react' import { Row } from 'react-table' -import { useLazyGetServiceQuery } from 'client/features/OneApi/service' -import { ServicesTable } from 'client/components/Tables' -import ServiceTabs from 'client/components/Tabs/Service' -import SplitPane from 'client/components/SplitPane' -import MultipleTags from 'client/components/MultipleTags' -import ServiceActions from 'client/components/Tables/Services/actions' import { SubmitButton } from 'client/components/FormControl' import { Tr } from 'client/components/HOC' +import MultipleTags from 'client/components/MultipleTags' +import ResourcesBackButton from 'client/components/ResourcesBackButton' +import { ServicesTable } from 'client/components/Tables' +import ServiceActions from 'client/components/Tables/Services/actions' +import ServiceTabs from 'client/components/Tabs/Service' import { T } from 'client/constants' +import { useGeneral } from 'client/features/General' +import { useLazyGetServiceQuery } from 'client/features/OneApi/service' /** * Displays a list of Service with a split pane between @@ -38,38 +40,44 @@ import { T } from 'client/constants' * @returns {ReactElement} Service list and selected row(s) */ function Services() { - const [selectedRows, onSelectedRowsChange] = useState(() => []) + const [selectedRows, setSelectedRows] = useState(() => []) const actions = ServiceActions() - - const hasSelectedRows = selectedRows?.length > 0 - const moreThanOneSelected = selectedRows?.length > 1 + const { zone } = useGeneral() return ( - - {({ getGridProps, GutterComponent }) => ( - - - - {hasSelectedRows && ( - <> - - {moreThanOneSelected ? ( - - ) : ( - selectedRows[0]?.toggleRowSelected(false)} - /> - )} - - )} - + ( + + )} + simpleGroupsTags={(props) => ( + )} - + info={(props) => { + const propsInfo = { + service: props?.selectedRows?.[0]?.original, + selectedRows: props?.selectedRows, + } + props?.gotoPage && (propsInfo.gotoPage = props.gotoPage) + props?.unselect && (propsInfo.unselect = props.unselect) + + return + }} + /> ) } @@ -83,8 +91,8 @@ function Services() { */ const InfoTabs = memo(({ service, gotoPage, unselect }) => { const [get, { data: lazyData, isFetching }] = useLazyGetServiceQuery() - const id = lazyData?.ID ?? service.ID - const name = lazyData?.NAME ?? service.NAME + const id = lazyData?.ID ?? service?.ID + const name = lazyData?.NAME ?? service?.NAME return ( @@ -138,23 +146,34 @@ InfoTabs.displayName = 'InfoTabs' * @param {Row[]} tags - Row(s) to display as tags * @returns {ReactElement} List of tags */ -const GroupedTags = memo(({ tags = [] }) => ( +const GroupedTags = ({ + tags = [], + handleElement = true, + onDelete = () => undefined, +}) => ( ( - toggleRowSelected(false)} - /> - ))} + tags={tags?.map((props) => { + const { original, id, toggleRowSelected, gotoPage } = props + const clickElement = handleElement + ? { + onClick: gotoPage, + onDelete: () => onDelete(id) || toggleRowSelected(false), + } + : {} + + return + })} /> -)) +) -GroupedTags.propTypes = { tags: PropTypes.array } +GroupedTags.propTypes = { + tags: PropTypes.array, + handleElement: PropTypes.bool, + onDelete: PropTypes.func, +} GroupedTags.displayName = 'GroupedTags' export default Services diff --git a/src/fireedge/src/client/containers/Settings/ConfigurationUI/schema.js b/src/fireedge/src/client/containers/Settings/ConfigurationUI/schema.js index 5901ebb6d7b..579d140f35c 100644 --- a/src/fireedge/src/client/containers/Settings/ConfigurationUI/schema.js +++ b/src/fireedge/src/client/containers/Settings/ConfigurationUI/schema.js @@ -107,6 +107,14 @@ const ZONE_ENDPOINT_FIELD = ({ zones = [] }) => ({ grid: { md: 12 }, }) +const FULL_SCREEN_INFO_FIELD = { + name: 'FULL_SCREEN_INFO', + label: T.FullScreenInfo, + type: INPUT_TYPES.CHECKBOX, + validation: boolean().yesOrNo(), + grid: { md: 12 }, +} + /** * @param {object} props - Props * @param {object} props.views - views. @@ -120,6 +128,7 @@ export const FIELDS = (props) => [ VIEW_FIELD(props), ZONE_ENDPOINT_FIELD(props), DISABLE_ANIMATIONS_FIELD, + FULL_SCREEN_INFO_FIELD, ] /** diff --git a/src/fireedge/src/client/containers/Settings/index.js b/src/fireedge/src/client/containers/Settings/index.js index 6b2dbe24255..b7cc382ae76 100644 --- a/src/fireedge/src/client/containers/Settings/index.js +++ b/src/fireedge/src/client/containers/Settings/index.js @@ -43,7 +43,7 @@ const Settings = () => { diff --git a/src/fireedge/src/client/containers/Users/index.js b/src/fireedge/src/client/containers/Users/index.js index cd728101a37..fe07f81abea 100644 --- a/src/fireedge/src/client/containers/Users/index.js +++ b/src/fireedge/src/client/containers/Users/index.js @@ -13,26 +13,28 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { ReactElement, useState, memo } from 'react' -import PropTypes from 'prop-types' +/* eslint-disable react/prop-types */ +import { Chip, Stack, Typography } from '@mui/material' +import Cancel from 'iconoir-react/dist/Cancel' import GotoIcon from 'iconoir-react/dist/Pin' import RefreshDouble from 'iconoir-react/dist/RefreshDouble' -import Cancel from 'iconoir-react/dist/Cancel' -import { Typography, Box, Stack, Chip } from '@mui/material' +import PropTypes from 'prop-types' +import { ReactElement, memo, useState } from 'react' import { Row } from 'react-table' +import { SubmitButton } from 'client/components/FormControl' +import { Tr } from 'client/components/HOC' +import MultipleTags from 'client/components/MultipleTags' +import ResourcesBackButton from 'client/components/ResourcesBackButton' +import { UsersTable } from 'client/components/Tables' +import UserActions from 'client/components/Tables/Users/actions' +import UserTabs from 'client/components/Tabs/User' +import { T, User } from 'client/constants' +import { useGeneral } from 'client/features/General' import { useLazyGetUserQuery, useUpdateUserMutation, } from 'client/features/OneApi/user' -import { UsersTable } from 'client/components/Tables' -import UserTabs from 'client/components/Tabs/User' -import UserActions from 'client/components/Tables/Users/actions' -import SplitPane from 'client/components/SplitPane' -import MultipleTags from 'client/components/MultipleTags' -import { SubmitButton } from 'client/components/FormControl' -import { Tr } from 'client/components/HOC' -import { T, User } from 'client/constants' /** * Displays a list of Users with a split pane between the list and selected row(s). @@ -40,39 +42,46 @@ import { T, User } from 'client/constants' * @returns {ReactElement} Users list and selected row(s) */ function Users() { - const [selectedRows, onSelectedRowsChange] = useState(() => []) + const [selectedRows, setSelectedRows] = useState(() => []) const actions = UserActions() - - const hasSelectedRows = selectedRows?.length > 0 - const moreThanOneSelected = selectedRows?.length > 1 + const { zone } = useGeneral() return ( - - {({ getGridProps, GutterComponent }) => ( - - - - {hasSelectedRows && ( - <> - - {moreThanOneSelected ? ( - - ) : ( - selectedRows[0]?.toggleRowSelected(false)} - /> - )} - - )} - + ( + )} - + simpleGroupsTags={(props) => ( + + )} + info={(props) => { + const propsInfo = { + user: props?.selectedRows?.[0]?.original, + selectedRows: props?.selectedRows, + } + props?.gotoPage && (propsInfo.gotoPage = props.gotoPage) + props?.unselect && (propsInfo.unselect = props.unselect) + + return + }} + /> ) } @@ -86,8 +95,8 @@ function Users() { */ const InfoTabs = memo(({ user, gotoPage, unselect }) => { const [get, { data: lazyData, isFetching }] = useLazyGetUserQuery() - const id = lazyData?.ID ?? user.ID - const name = lazyData?.NAME ?? user.NAME + const id = lazyData?.ID ?? user?.ID + const name = lazyData?.NAME ?? user?.NAME return ( @@ -141,23 +150,34 @@ InfoTabs.displayName = 'InfoTabs' * @param {Row[]} tags - Row(s) to display as tags * @returns {ReactElement} List of tags */ -const GroupedTags = memo(({ tags = [] }) => ( +const GroupedTags = ({ + tags = [], + handleElement = true, + onDelete = () => undefined, +}) => ( ( - toggleRowSelected(false)} - /> - ))} + tags={tags?.map((props) => { + const { original, id, toggleRowSelected, gotoPage } = props + const clickElement = handleElement + ? { + onClick: gotoPage, + onDelete: () => onDelete(id) || toggleRowSelected(false), + } + : {} + + return + })} /> -)) +) -GroupedTags.propTypes = { tags: PropTypes.array } +GroupedTags.propTypes = { + tags: PropTypes.array, + handleElement: PropTypes.bool, + onDelete: PropTypes.func, +} GroupedTags.displayName = 'GroupedTags' export default Users diff --git a/src/fireedge/src/client/containers/VDCs/index.js b/src/fireedge/src/client/containers/VDCs/index.js index 7e53d9694c9..bf8d4ea1a17 100644 --- a/src/fireedge/src/client/containers/VDCs/index.js +++ b/src/fireedge/src/client/containers/VDCs/index.js @@ -13,7 +13,8 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { Box, Chip, Stack, Typography } from '@mui/material' +/* eslint-disable react/prop-types */ +import { Chip, Stack, Typography } from '@mui/material' import { Cancel, Pin as GotoIcon, RefreshDouble } from 'iconoir-react' import PropTypes from 'prop-types' import { ReactElement, memo, useState } from 'react' @@ -22,11 +23,12 @@ import { Row } from 'react-table' import { SubmitButton } from 'client/components/FormControl' import { Tr } from 'client/components/HOC' import MultipleTags from 'client/components/MultipleTags' -import SplitPane from 'client/components/SplitPane' +import ResourcesBackButton from 'client/components/ResourcesBackButton' import { VDCsTable } from 'client/components/Tables' import VDCActions from 'client/components/Tables/VirtualDataCenters/actions' import VDCTabs from 'client/components/Tabs/Vdc' import { T, VmTemplate as VdcTemplate } from 'client/constants' +import { useGeneral } from 'client/features/General' import { useLazyGetVDCQuery, useUpdateVDCMutation, @@ -38,39 +40,46 @@ import { * @returns {ReactElement} VDCs list and selected row(s) */ function VirtualDataCenters() { - const [selectedRows, onSelectedRowsChange] = useState(() => []) + const [selectedRows, setSelectedRows] = useState(() => []) const actions = VDCActions() - - const hasSelectedRows = selectedRows?.length > 0 - const moreThanOneSelected = selectedRows?.length > 1 + const { zone } = useGeneral() return ( - - {({ getGridProps, GutterComponent }) => ( - - - - {hasSelectedRows && ( - <> - - {moreThanOneSelected ? ( - - ) : ( - selectedRows[0]?.toggleRowSelected(false)} - /> - )} - - )} - + ( + + )} + simpleGroupsTags={(props) => ( + )} - + info={(props) => { + const propsInfo = { + template: props?.selectedRows?.[0]?.original, + selectedRows: props?.selectedRows, + } + props?.gotoPage && (propsInfo.gotoPage = props.gotoPage) + props?.unselect && (propsInfo.unselect = props.unselect) + + return + }} + /> ) } @@ -84,8 +93,8 @@ function VirtualDataCenters() { */ const InfoTabs = memo(({ template, gotoPage, unselect }) => { const [getVDC, { data, isFetching }] = useLazyGetVDCQuery() - const id = data?.ID ?? template.ID - const name = data?.NAME ?? template.NAME + const id = data?.ID ?? template?.ID + const name = data?.NAME ?? template?.NAME return ( @@ -139,23 +148,34 @@ InfoTabs.displayName = 'InfoTabs' * @param {Row[]} tags - Row(s) to display as tags * @returns {ReactElement} List of tags */ -const GroupedTags = memo(({ tags = [] }) => ( +const GroupedTags = ({ + tags = [], + handleElement = true, + onDelete = () => undefined, +}) => ( ( - toggleRowSelected(false)} - /> - ))} + tags={tags?.map((props) => { + const { original, id, toggleRowSelected, gotoPage } = props + const clickElement = handleElement + ? { + onClick: gotoPage, + onDelete: () => onDelete(id) || toggleRowSelected(false), + } + : {} + + return + })} /> -)) +) -GroupedTags.propTypes = { tags: PropTypes.array } +GroupedTags.propTypes = { + tags: PropTypes.array, + handleElement: PropTypes.bool, + onDelete: PropTypes.func, +} GroupedTags.displayName = 'GroupedTags' export default VirtualDataCenters diff --git a/src/fireedge/src/client/containers/VNetworkTemplates/index.js b/src/fireedge/src/client/containers/VNetworkTemplates/index.js index 8591f0e4d61..88324e5aad9 100644 --- a/src/fireedge/src/client/containers/VNetworkTemplates/index.js +++ b/src/fireedge/src/client/containers/VNetworkTemplates/index.js @@ -13,7 +13,8 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { Box, Chip, Stack, Typography } from '@mui/material' +/* eslint-disable react/prop-types */ +import { Chip, Stack, Typography } from '@mui/material' import Cancel from 'iconoir-react/dist/Cancel' import GotoIcon from 'iconoir-react/dist/Pin' import RefreshDouble from 'iconoir-react/dist/RefreshDouble' @@ -24,11 +25,12 @@ import { Row } from 'react-table' import { SubmitButton } from 'client/components/FormControl' import { Tr } from 'client/components/HOC' import MultipleTags from 'client/components/MultipleTags' -import SplitPane from 'client/components/SplitPane' +import ResourcesBackButton from 'client/components/ResourcesBackButton' import { VNetworkTemplatesTable } from 'client/components/Tables' import VNetworkTemplateActions from 'client/components/Tables/VNetworkTemplates/actions' import VNetworkTemplateTabs from 'client/components/Tabs/VNetworkTemplate' import { T, VNetworkTemplate } from 'client/constants' +import { useGeneral } from 'client/features/General' import { useLazyGetVNTemplateQuery, useUpdateVNTemplateMutation, @@ -40,38 +42,46 @@ import { * @returns {ReactElement} VNet Templates list and selected row(s) */ function VNetworkTemplates() { - const [selectedRows, onSelectedRowsChange] = useState(() => []) + const [selectedRows, setSelectedRows] = useState(() => []) const actions = VNetworkTemplateActions() - const hasSelectedRows = selectedRows?.length > 0 - const moreThanOneSelected = selectedRows?.length > 1 + const { zone } = useGeneral() return ( - - {({ getGridProps, GutterComponent }) => ( - - - - {hasSelectedRows && ( - <> - - {moreThanOneSelected ? ( - - ) : ( - selectedRows[0]?.toggleRowSelected(false)} - /> - )} - - )} - + ( + + )} + simpleGroupsTags={(props) => ( + )} - + info={(props) => { + const propsInfo = { + vnTemplate: props?.selectedRows?.[0]?.original, + selectedRows: props?.selectedRows, + } + props?.gotoPage && (propsInfo.gotoPage = props.gotoPage) + props?.unselect && (propsInfo.unselect = props.unselect) + + return + }} + /> ) } @@ -85,8 +95,8 @@ function VNetworkTemplates() { */ const InfoTabs = memo(({ vnTemplate, gotoPage, unselect }) => { const [get, { data: lazyData, isFetching }] = useLazyGetVNTemplateQuery() - const id = lazyData?.ID ?? vnTemplate.ID - const name = lazyData?.NAME ?? vnTemplate.NAME + const id = lazyData?.ID ?? vnTemplate?.ID + const name = lazyData?.NAME ?? vnTemplate?.NAME return ( @@ -140,23 +150,34 @@ InfoTabs.displayName = 'InfoTabs' * @param {Row[]} tags - Row(s) to display as tags * @returns {ReactElement} List of tags */ -const GroupedTags = memo(({ tags = [] }) => ( +const GroupedTags = ({ + tags = [], + handleElement = true, + onDelete = () => undefined, +}) => ( ( - toggleRowSelected(false)} - /> - ))} + tags={tags?.map((props) => { + const { original, id, toggleRowSelected, gotoPage } = props + const clickElement = handleElement + ? { + onClick: gotoPage, + onDelete: () => onDelete(id) || toggleRowSelected(false), + } + : {} + + return + })} /> -)) +) -GroupedTags.propTypes = { tags: PropTypes.array } +GroupedTags.propTypes = { + tags: PropTypes.array, + handleElement: PropTypes.bool, + onDelete: PropTypes.func, +} GroupedTags.displayName = 'GroupedTags' export default VNetworkTemplates diff --git a/src/fireedge/src/client/containers/VirtualMachines/index.js b/src/fireedge/src/client/containers/VirtualMachines/index.js index d18c95c249e..6e42b41b7d0 100644 --- a/src/fireedge/src/client/containers/VirtualMachines/index.js +++ b/src/fireedge/src/client/containers/VirtualMachines/index.js @@ -13,27 +13,28 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { Box, Chip, Stack, Typography } from '@mui/material' +/* eslint-disable react/prop-types */ +import { Chip, Stack, Typography } from '@mui/material' import Cancel from 'iconoir-react/dist/Cancel' import GotoIcon from 'iconoir-react/dist/Pin' import RefreshDouble from 'iconoir-react/dist/RefreshDouble' import PropTypes from 'prop-types' -import { ReactElement, memo, useState, useEffect } from 'react' +import { ReactElement, memo, useEffect, useState } from 'react' import { Row } from 'react-table' import { SubmitButton } from 'client/components/FormControl' import { Tr } from 'client/components/HOC' import MultipleTags from 'client/components/MultipleTags' -import SplitPane from 'client/components/SplitPane' +import ResourcesBackButton from 'client/components/ResourcesBackButton' import { VmsTable } from 'client/components/Tables' import VmActions from 'client/components/Tables/Vms/actions' import VmTabs from 'client/components/Tabs/Vm' import { T, VM } from 'client/constants' +import { setSelectedIds, useGeneral } from 'client/features/General' import { useLazyGetVmQuery, useUpdateUserTemplateMutation, } from 'client/features/OneApi/vm' -import { setSelectedIds } from 'client/features/General' import { useDispatch } from 'react-redux' /** @@ -43,11 +44,9 @@ import { useDispatch } from 'react-redux' */ function VirtualMachines() { const dispatch = useDispatch() - const [selectedRows, onSelectedRowsChange] = useState(() => []) + const [selectedRows, setSelectedRows] = useState(() => []) const actions = VmActions(selectedRows) - - const hasSelectedRows = selectedRows?.length > 0 - const moreThanOneSelected = selectedRows?.length > 1 + const { zone } = useGeneral() useEffect(() => { const selectedIds = selectedRows.map((row) => row.original.ID) @@ -55,31 +54,41 @@ function VirtualMachines() { }, [selectedRows, dispatch]) return ( - - {({ getGridProps, GutterComponent }) => ( - - - {hasSelectedRows && ( - <> - - {moreThanOneSelected ? ( - - ) : ( - selectedRows[0]?.toggleRowSelected(false)} - /> - )} - - )} - + ( + + )} + simpleGroupsTags={(props) => ( + )} - + info={(props) => { + const propsInfo = { + vm: props?.selectedRows?.[0]?.original, + selectedRows: props?.selectedRows, + } + props?.gotoPage && (propsInfo.gotoPage = props.gotoPage) + props?.unselect && (propsInfo.unselect = props.unselect) + + return + }} + /> ) } @@ -93,8 +102,8 @@ function VirtualMachines() { */ const InfoTabs = memo(({ vm, gotoPage, unselect }) => { const [getVm, { data: lazyData, isFetching }] = useLazyGetVmQuery() - const id = lazyData?.ID ?? vm.ID - const name = lazyData?.NAME ?? vm.NAME + const id = lazyData?.ID ?? vm?.ID + const name = lazyData?.NAME ?? vm?.NAME return ( @@ -148,23 +157,34 @@ InfoTabs.displayName = 'InfoTabs' * @param {Row[]} tags - Row(s) to display as tags * @returns {ReactElement} List of tags */ -const GroupedTags = memo(({ tags = [] }) => ( +const GroupedTags = ({ + tags = [], + handleElement = true, + onDelete = () => undefined, +}) => ( ( - toggleRowSelected(false)} - /> - ))} + tags={tags?.map((props) => { + const { original, id, toggleRowSelected, gotoPage } = props + const clickElement = handleElement + ? { + onClick: gotoPage, + onDelete: () => onDelete(id) || toggleRowSelected(false), + } + : {} + + return + })} /> -)) +) -GroupedTags.propTypes = { tags: PropTypes.array } +GroupedTags.propTypes = { + tags: PropTypes.array, + handleElement: PropTypes.bool, + onDelete: PropTypes.func, +} GroupedTags.displayName = 'GroupedTags' export default VirtualMachines diff --git a/src/fireedge/src/client/containers/VirtualNetworks/index.js b/src/fireedge/src/client/containers/VirtualNetworks/index.js index d1a44534743..992ef84af54 100644 --- a/src/fireedge/src/client/containers/VirtualNetworks/index.js +++ b/src/fireedge/src/client/containers/VirtualNetworks/index.js @@ -13,26 +13,28 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { ReactElement, useState, memo } from 'react' -import PropTypes from 'prop-types' +/* eslint-disable react/prop-types */ +import { Chip, Stack, Typography } from '@mui/material' +import Cancel from 'iconoir-react/dist/Cancel' import GotoIcon from 'iconoir-react/dist/Pin' import RefreshDouble from 'iconoir-react/dist/RefreshDouble' -import Cancel from 'iconoir-react/dist/Cancel' -import { Typography, Box, Stack, Chip } from '@mui/material' +import PropTypes from 'prop-types' +import { ReactElement, memo, useState } from 'react' import { Row } from 'react-table' -import { - useLazyGetVNetworkQuery, - useUpdateVNetMutation, -} from 'client/features/OneApi/network' +import { SubmitButton } from 'client/components/FormControl' +import { Tr } from 'client/components/HOC' +import MultipleTags from 'client/components/MultipleTags' +import ResourcesBackButton from 'client/components/ResourcesBackButton' import { VNetworksTable } from 'client/components/Tables' import VNetworkActions from 'client/components/Tables/VNetworks/actions' import VNetworkTabs from 'client/components/Tabs/VNetwork' -import SplitPane from 'client/components/SplitPane' -import MultipleTags from 'client/components/MultipleTags' -import { SubmitButton } from 'client/components/FormControl' -import { Tr } from 'client/components/HOC' import { T, VirtualNetwork } from 'client/constants' +import { useGeneral } from 'client/features/General' +import { + useLazyGetVNetworkQuery, + useUpdateVNetMutation, +} from 'client/features/OneApi/network' /** * Displays a list of Virtual Networks with a split pane between the list and selected row(s). @@ -40,39 +42,46 @@ import { T, VirtualNetwork } from 'client/constants' * @returns {ReactElement} Virtual Networks list and selected row(s) */ function VirtualNetworks() { - const [selectedRows, onSelectedRowsChange] = useState(() => []) + const [selectedRows, setSelectedRows] = useState(() => []) const actions = VNetworkActions() - - const hasSelectedRows = selectedRows?.length > 0 - const moreThanOneSelected = selectedRows?.length > 1 + const { zone } = useGeneral() return ( - - {({ getGridProps, GutterComponent }) => ( - - - - {hasSelectedRows && ( - <> - - {moreThanOneSelected ? ( - - ) : ( - selectedRows[0]?.toggleRowSelected(false)} - /> - )} - - )} - + ( + )} - + simpleGroupsTags={(props) => ( + + )} + info={(props) => { + const propsInfo = { + vnet: props?.selectedRows?.[0]?.original, + selectedRows: props?.selectedRows, + } + props?.gotoPage && (propsInfo.gotoPage = props.gotoPage) + props?.unselect && (propsInfo.unselect = props.unselect) + + return + }} + /> ) } @@ -86,8 +95,8 @@ function VirtualNetworks() { */ const InfoTabs = memo(({ vnet, gotoPage, unselect }) => { const [get, { data: lazyData, isFetching }] = useLazyGetVNetworkQuery() - const id = lazyData?.ID ?? vnet.ID - const name = lazyData?.NAME ?? vnet.NAME + const id = lazyData?.ID ?? vnet?.ID + const name = lazyData?.NAME ?? vnet?.NAME return ( @@ -141,23 +150,34 @@ InfoTabs.displayName = 'InfoTabs' * @param {Row[]} tags - Row(s) to display as tags * @returns {ReactElement} List of tags */ -const GroupedTags = memo(({ tags = [] }) => ( +const GroupedTags = ({ + tags = [], + handleElement = true, + onDelete = () => undefined, +}) => ( ( - toggleRowSelected(false)} - /> - ))} + tags={tags?.map((props) => { + const { original, id, toggleRowSelected, gotoPage } = props + const clickElement = handleElement + ? { + onClick: gotoPage, + onDelete: () => onDelete(id) || toggleRowSelected(false), + } + : {} + + return + })} /> -)) +) -GroupedTags.propTypes = { tags: PropTypes.array } +GroupedTags.propTypes = { + tags: PropTypes.array, + handleElement: PropTypes.bool, + onDelete: PropTypes.func, +} GroupedTags.displayName = 'GroupedTags' export default VirtualNetworks diff --git a/src/fireedge/src/client/containers/VirtualRouterTemplates/index.js b/src/fireedge/src/client/containers/VirtualRouterTemplates/index.js index b890afec210..8744f9aba8a 100644 --- a/src/fireedge/src/client/containers/VirtualRouterTemplates/index.js +++ b/src/fireedge/src/client/containers/VirtualRouterTemplates/index.js @@ -13,24 +13,26 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { ReactElement, useState, memo } from 'react' +/* eslint-disable react/prop-types */ +import { Chip, Stack, Typography } from '@mui/material' +import { Cancel, Pin as GotoIcon, RefreshDouble } from 'iconoir-react' import PropTypes from 'prop-types' -import { Pin as GotoIcon, RefreshDouble, Cancel } from 'iconoir-react' -import { Typography, Box, Stack, Chip } from '@mui/material' +import { ReactElement, memo, useState } from 'react' import { Row } from 'react-table' -import { - useLazyGetVRouterTemplateQuery, - useUpdateVRouterTemplateMutation, -} from 'client/features/OneApi/vrouterTemplate' +import { SubmitButton } from 'client/components/FormControl' +import { Tr } from 'client/components/HOC' +import MultipleTags from 'client/components/MultipleTags' +import ResourcesBackButton from 'client/components/ResourcesBackButton' import { VRouterTemplatesTable } from 'client/components/Tables' import VRouterTemplateActions from 'client/components/Tables/VRouterTemplates/actions' import VmTemplateTabs from 'client/components/Tabs/VmTemplate' -import SplitPane from 'client/components/SplitPane' -import MultipleTags from 'client/components/MultipleTags' -import { SubmitButton } from 'client/components/FormControl' -import { Tr } from 'client/components/HOC' import { T, VmTemplate } from 'client/constants' +import { useGeneral } from 'client/features/General' +import { + useLazyGetVRouterTemplateQuery, + useUpdateVRouterTemplateMutation, +} from 'client/features/OneApi/vrouterTemplate' /** * Displays a list of VM Templates with a split pane between the list and selected row(s). @@ -38,39 +40,46 @@ import { T, VmTemplate } from 'client/constants' * @returns {ReactElement} VM Templates list and selected row(s) */ function VRouterTemplates() { - const [selectedRows, onSelectedRowsChange] = useState(() => []) + const [selectedRows, setSelectedRows] = useState(() => []) const actions = VRouterTemplateActions() - - const hasSelectedRows = selectedRows?.length > 0 - const moreThanOneSelected = selectedRows?.length > 1 + const { zone } = useGeneral() return ( - - {({ getGridProps, GutterComponent }) => ( - - - - {hasSelectedRows && ( - <> - - {moreThanOneSelected ? ( - - ) : ( - selectedRows[0]?.toggleRowSelected(false)} - /> - )} - - )} - + ( + + )} + simpleGroupsTags={(props) => ( + )} - + info={(props) => { + const propsInfo = { + template: props?.selectedRows?.[0]?.original, + selectedRows: props?.selectedRows, + } + props?.gotoPage && (propsInfo.gotoPage = props.gotoPage) + props?.unselect && (propsInfo.unselect = props.unselect) + + return + }} + /> ) } @@ -84,8 +93,8 @@ function VRouterTemplates() { */ const InfoTabs = memo(({ template, gotoPage, unselect }) => { const [getTemplate, { data, isFetching }] = useLazyGetVRouterTemplateQuery() - const id = data?.ID ?? template.ID - const name = data?.NAME ?? template.NAME + const id = data?.ID ?? template?.ID + const name = data?.NAME ?? template?.NAME return ( @@ -139,23 +148,34 @@ InfoTabs.displayName = 'InfoTabs' * @param {Row[]} tags - Row(s) to display as tags * @returns {ReactElement} List of tags */ -const GroupedTags = memo(({ tags = [] }) => ( +const GroupedTags = ({ + tags = [], + handleElement = true, + onDelete = () => undefined, +}) => ( ( - toggleRowSelected(false)} - /> - ))} + tags={tags?.map((props) => { + const { original, id, toggleRowSelected, gotoPage } = props + const clickElement = handleElement + ? { + onClick: gotoPage, + onDelete: () => onDelete(id) || toggleRowSelected(false), + } + : {} + + return + })} /> -)) +) -GroupedTags.propTypes = { tags: PropTypes.array } +GroupedTags.propTypes = { + tags: PropTypes.array, + handleElement: PropTypes.bool, + onDelete: PropTypes.func, +} GroupedTags.displayName = 'GroupedTags' export default VRouterTemplates diff --git a/src/fireedge/src/client/containers/VirtualRouters/index.js b/src/fireedge/src/client/containers/VirtualRouters/index.js index a2843dd7489..c22ded4004a 100644 --- a/src/fireedge/src/client/containers/VirtualRouters/index.js +++ b/src/fireedge/src/client/containers/VirtualRouters/index.js @@ -13,21 +13,23 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { ReactElement, useState, memo } from 'react' +/* eslint-disable react/prop-types */ +import { Chip, Stack, Typography } from '@mui/material' +import { Cancel, Pin as GotoIcon, RefreshDouble } from 'iconoir-react' import PropTypes from 'prop-types' -import { Pin as GotoIcon, RefreshDouble, Cancel } from 'iconoir-react' -import { Typography, Box, Stack, Chip } from '@mui/material' +import { ReactElement, memo, useState } from 'react' import { Row } from 'react-table' -import { useLazyGetVRouterQuery } from 'client/features/OneApi/vrouter' +import { SubmitButton } from 'client/components/FormControl' +import { Tr } from 'client/components/HOC' +import MultipleTags from 'client/components/MultipleTags' +import ResourcesBackButton from 'client/components/ResourcesBackButton' import { VRoutersTable } from 'client/components/Tables' import VRouterActions from 'client/components/Tables/VRouters/actions' import VirtualRouterTabs from 'client/components/Tabs/VirtualRouter' -import SplitPane from 'client/components/SplitPane' -import MultipleTags from 'client/components/MultipleTags' -import { SubmitButton } from 'client/components/FormControl' -import { Tr } from 'client/components/HOC' import { T, VmTemplate } from 'client/constants' +import { useGeneral } from 'client/features/General' +import { useLazyGetVRouterQuery } from 'client/features/OneApi/vrouter' /** * Displays a list of VM Templates with a split pane between the list and selected row(s). @@ -35,38 +37,44 @@ import { T, VmTemplate } from 'client/constants' * @returns {ReactElement} VM Templates list and selected row(s) */ function VRouters() { - const [selectedRows, onSelectedRowsChange] = useState(() => []) + const [selectedRows, setSelectedRows] = useState(() => []) const actions = VRouterActions() - - const hasSelectedRows = selectedRows?.length > 0 - const moreThanOneSelected = selectedRows?.length > 1 + const { zone } = useGeneral() return ( - - {({ getGridProps, GutterComponent }) => ( - - - - {hasSelectedRows && ( - <> - - {moreThanOneSelected ? ( - - ) : ( - selectedRows[0]?.toggleRowSelected(false)} - /> - )} - - )} - + ( + )} - + simpleGroupsTags={(props) => ( + + )} + info={(props) => { + const propsInfo = { + template: props?.selectedRows?.[0]?.original, + selectedRows: props?.selectedRows, + } + props?.gotoPage && (propsInfo.gotoPage = props.gotoPage) + props?.unselect && (propsInfo.unselect = props.unselect) + + return + }} + /> ) } @@ -80,8 +88,8 @@ function VRouters() { */ const InfoTabs = memo(({ template, gotoPage, unselect }) => { const [getTemplate, { data, isFetching }] = useLazyGetVRouterQuery() - const id = data?.ID ?? template.ID - const name = data?.NAME ?? template.NAME + const id = data?.ID ?? template?.ID + const name = data?.NAME ?? template?.NAME return ( @@ -135,23 +143,34 @@ InfoTabs.displayName = 'InfoTabs' * @param {Row[]} tags - Row(s) to display as tags * @returns {ReactElement} List of tags */ -const GroupedTags = memo(({ tags = [] }) => ( +const GroupedTags = ({ + tags = [], + handleElement = true, + onDelete = () => undefined, +}) => ( ( - toggleRowSelected(false)} - /> - ))} + tags={tags?.map((props) => { + const { original, id, toggleRowSelected, gotoPage } = props + const clickElement = handleElement + ? { + onClick: gotoPage, + onDelete: () => onDelete(id) || toggleRowSelected(false), + } + : {} + + return + })} /> -)) +) -GroupedTags.propTypes = { tags: PropTypes.array } +GroupedTags.propTypes = { + tags: PropTypes.array, + handleElement: PropTypes.bool, + onDelete: PropTypes.func, +} GroupedTags.displayName = 'GroupedTags' export default VRouters diff --git a/src/fireedge/src/client/containers/VmGroups/index.js b/src/fireedge/src/client/containers/VmGroups/index.js index b51c11b79c2..cb3e6b84bf6 100644 --- a/src/fireedge/src/client/containers/VmGroups/index.js +++ b/src/fireedge/src/client/containers/VmGroups/index.js @@ -13,26 +13,28 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { ReactElement, useState, memo } from 'react' -import PropTypes from 'prop-types' +/* eslint-disable react/prop-types */ +import { Chip, Stack, Typography } from '@mui/material' +import Cancel from 'iconoir-react/dist/Cancel' import GotoIcon from 'iconoir-react/dist/Pin' import RefreshDouble from 'iconoir-react/dist/RefreshDouble' -import Cancel from 'iconoir-react/dist/Cancel' -import { Typography, Box, Stack, Chip } from '@mui/material' +import PropTypes from 'prop-types' +import { ReactElement, memo, useState } from 'react' import { Row } from 'react-table' +import { SubmitButton } from 'client/components/FormControl' +import { Tr } from 'client/components/HOC' +import MultipleTags from 'client/components/MultipleTags' +import ResourcesBackButton from 'client/components/ResourcesBackButton' +import { VmGroupsTable } from 'client/components/Tables' +import VmGroupActions from 'client/components/Tables/VmGroups/actions' +import VmGroupTabs from 'client/components/Tabs/VmGroup' +import { T, VmGroup } from 'client/constants' +import { useGeneral } from 'client/features/General' import { useLazyGetVMGroupQuery, useUpdateVMGroupMutation, } from 'client/features/OneApi/vmGroup' -import { VmGroupsTable } from 'client/components/Tables' -import VmGroupTabs from 'client/components/Tabs/VmGroup' -import VmGroupActions from 'client/components/Tables/VmGroups/actions' -import SplitPane from 'client/components/SplitPane' -import MultipleTags from 'client/components/MultipleTags' -import { SubmitButton } from 'client/components/FormControl' -import { Tr } from 'client/components/HOC' -import { T, VmGroup } from 'client/constants' /** * Displays a list of VmGroups with a split pane between the list and selected row(s). @@ -40,39 +42,46 @@ import { T, VmGroup } from 'client/constants' * @returns {ReactElement} VmGroups list and selected row(s) */ function VmGroups() { - const [selectedRows, onSelectedRowsChange] = useState(() => []) + const [selectedRows, setSelectedRows] = useState(() => []) const actions = VmGroupActions() - - const hasSelectedRows = selectedRows?.length > 0 - const moreThanOneSelected = selectedRows?.length > 1 + const { zone } = useGeneral() return ( - - {({ getGridProps, GutterComponent }) => ( - - - - {hasSelectedRows && ( - <> - - {moreThanOneSelected ? ( - - ) : ( - selectedRows[0]?.toggleRowSelected(false)} - /> - )} - - )} - + ( + )} - + simpleGroupsTags={(props) => ( + + )} + info={(props) => { + const propsInfo = { + user: props?.selectedRows?.[0]?.original, + selectedRows: props?.selectedRows, + } + props?.gotoPage && (propsInfo.gotoPage = props.gotoPage) + props?.unselect && (propsInfo.unselect = props.unselect) + + return + }} + /> ) } @@ -86,8 +95,8 @@ function VmGroups() { */ const InfoTabs = memo(({ user, gotoPage, unselect }) => { const [get, { data: lazyData, isFetching }] = useLazyGetVMGroupQuery() - const id = lazyData?.ID ?? user.ID - const name = lazyData?.NAME ?? user.NAME + const id = lazyData?.ID ?? user?.ID + const name = lazyData?.NAME ?? user?.NAME return ( @@ -139,23 +148,34 @@ InfoTabs.displayName = 'InfoTabs' * @param {Row[]} tags - Row(s) to display as tags * @returns {ReactElement} List of tags */ -const GroupedTags = memo(({ tags = [] }) => ( +const GroupedTags = ({ + tags = [], + handleElement = true, + onDelete = () => undefined, +}) => ( ( - toggleRowSelected(false)} - /> - ))} + tags={tags?.map((props) => { + const { original, id, toggleRowSelected, gotoPage } = props + const clickElement = handleElement + ? { + onClick: gotoPage, + onDelete: () => onDelete(id) || toggleRowSelected(false), + } + : {} + + return + })} /> -)) +) -GroupedTags.propTypes = { tags: PropTypes.array } +GroupedTags.propTypes = { + tags: PropTypes.array, + handleElement: PropTypes.bool, + onDelete: PropTypes.func, +} GroupedTags.displayName = 'GroupedTags' export default VmGroups diff --git a/src/fireedge/src/client/containers/VmTemplates/index.js b/src/fireedge/src/client/containers/VmTemplates/index.js index 6e21c05bbe5..dacee146d3a 100644 --- a/src/fireedge/src/client/containers/VmTemplates/index.js +++ b/src/fireedge/src/client/containers/VmTemplates/index.js @@ -13,24 +13,26 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { ReactElement, useState, memo } from 'react' +/* eslint-disable react/prop-types */ +import { Chip, Stack, Typography } from '@mui/material' +import { Cancel, Pin as GotoIcon, RefreshDouble } from 'iconoir-react' import PropTypes from 'prop-types' -import { Pin as GotoIcon, RefreshDouble, Cancel } from 'iconoir-react' -import { Typography, Box, Stack, Chip } from '@mui/material' +import { ReactElement, memo, useState } from 'react' import { Row } from 'react-table' -import { - useLazyGetTemplateQuery, - useUpdateTemplateMutation, -} from 'client/features/OneApi/vmTemplate' +import { SubmitButton } from 'client/components/FormControl' +import { Tr } from 'client/components/HOC' +import MultipleTags from 'client/components/MultipleTags' +import ResourcesBackButton from 'client/components/ResourcesBackButton' import { VmTemplatesTable } from 'client/components/Tables' import VmTemplateActions from 'client/components/Tables/VmTemplates/actions' import VmTemplateTabs from 'client/components/Tabs/VmTemplate' -import SplitPane from 'client/components/SplitPane' -import MultipleTags from 'client/components/MultipleTags' -import { SubmitButton } from 'client/components/FormControl' -import { Tr } from 'client/components/HOC' import { T, VmTemplate } from 'client/constants' +import { useGeneral } from 'client/features/General' +import { + useLazyGetTemplateQuery, + useUpdateTemplateMutation, +} from 'client/features/OneApi/vmTemplate' /** * Displays a list of VM Templates with a split pane between the list and selected row(s). @@ -38,39 +40,46 @@ import { T, VmTemplate } from 'client/constants' * @returns {ReactElement} VM Templates list and selected row(s) */ function VmTemplates() { - const [selectedRows, onSelectedRowsChange] = useState(() => []) + const [selectedRows, setSelectedRows] = useState(() => []) const actions = VmTemplateActions() - - const hasSelectedRows = selectedRows?.length > 0 - const moreThanOneSelected = selectedRows?.length > 1 + const { zone } = useGeneral() return ( - - {({ getGridProps, GutterComponent }) => ( - - - - {hasSelectedRows && ( - <> - - {moreThanOneSelected ? ( - - ) : ( - selectedRows[0]?.toggleRowSelected(false)} - /> - )} - - )} - + ( + + )} + simpleGroupsTags={(props) => ( + )} - + info={(props) => { + const propsInfo = { + template: props?.selectedRows?.[0]?.original, + selectedRows: props?.selectedRows, + } + props?.gotoPage && (propsInfo.gotoPage = props.gotoPage) + props?.unselect && (propsInfo.unselect = props.unselect) + + return + }} + /> ) } @@ -84,8 +93,8 @@ function VmTemplates() { */ const InfoTabs = memo(({ template, gotoPage, unselect }) => { const [getTemplate, { data, isFetching }] = useLazyGetTemplateQuery() - const id = data?.ID ?? template.ID - const name = data?.NAME ?? template.NAME + const id = data?.ID ?? template?.ID + const name = data?.NAME ?? template?.NAME return ( @@ -139,23 +148,34 @@ InfoTabs.displayName = 'InfoTabs' * @param {Row[]} tags - Row(s) to display as tags * @returns {ReactElement} List of tags */ -const GroupedTags = memo(({ tags = [] }) => ( +const GroupedTags = ({ + tags = [], + handleElement = true, + onDelete = () => undefined, +}) => ( ( - toggleRowSelected(false)} - /> - ))} + tags={tags?.map((props) => { + const { original, id, toggleRowSelected, gotoPage } = props + const clickElement = handleElement + ? { + onClick: gotoPage, + onDelete: () => onDelete(id) || toggleRowSelected(false), + } + : {} + + return + })} /> -)) +) -GroupedTags.propTypes = { tags: PropTypes.array } +GroupedTags.propTypes = { + tags: PropTypes.array, + handleElement: PropTypes.bool, + onDelete: PropTypes.func, +} GroupedTags.displayName = 'GroupedTags' export default VmTemplates diff --git a/src/fireedge/src/client/containers/Zones/index.js b/src/fireedge/src/client/containers/Zones/index.js index f71268d3a2c..5f63a2c6fb1 100644 --- a/src/fireedge/src/client/containers/Zones/index.js +++ b/src/fireedge/src/client/containers/Zones/index.js @@ -13,7 +13,8 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { Box, Chip, Stack, Typography } from '@mui/material' +/* eslint-disable react/prop-types */ +import { Chip, Stack, Typography } from '@mui/material' import Cancel from 'iconoir-react/dist/Cancel' import GotoIcon from 'iconoir-react/dist/Pin' import RefreshDouble from 'iconoir-react/dist/RefreshDouble' @@ -24,7 +25,7 @@ import { Row } from 'react-table' import { SubmitButton } from 'client/components/FormControl' import { Tr } from 'client/components/HOC' import MultipleTags from 'client/components/MultipleTags' -import SplitPane from 'client/components/SplitPane' +import ResourcesBackButton from 'client/components/ResourcesBackButton' import { ZonesTable } from 'client/components/Tables' import ZoneTabs from 'client/components/Tabs/Zone' import { T, Zone } from 'client/constants' @@ -39,37 +40,41 @@ import { * @returns {ReactElement} Zones list and selected row(s) */ function Zones() { - const [selectedRows, onSelectedRowsChange] = useState(() => []) - - const hasSelectedRows = selectedRows?.length > 0 - const moreThanOneSelected = selectedRows?.length > 1 + const [selectedRows, setSelectedRows] = useState(() => []) return ( - - {({ getGridProps, GutterComponent }) => ( - - - - {hasSelectedRows && ( - <> - - {moreThanOneSelected ? ( - - ) : ( - selectedRows[0]?.toggleRowSelected(false)} - /> - )} - - )} - + ( + )} - + simpleGroupsTags={(props) => ( + + )} + info={(props) => { + const propsInfo = { + zone: props?.selectedRows?.[0]?.original, + selectedRows: props?.selectedRows, + } + props?.gotoPage && (propsInfo.gotoPage = props.gotoPage) + props?.unselect && (propsInfo.unselect = props.unselect) + + return + }} + /> ) } @@ -83,8 +88,8 @@ function Zones() { */ const InfoTabs = memo(({ zone, gotoPage, unselect }) => { const [get, { data: lazyData, isFetching }] = useLazyGetZoneQuery() - const id = lazyData?.ID ?? zone.ID - const name = lazyData?.NAME ?? zone.NAME + const id = lazyData?.ID ?? zone?.ID + const name = lazyData?.NAME ?? zone?.NAME return ( @@ -138,23 +143,34 @@ InfoTabs.displayName = 'InfoTabs' * @param {Row[]} tags - Row(s) to display as tags * @returns {ReactElement} List of tags */ -const GroupedTags = memo(({ tags = [] }) => ( - - ( - toggleRowSelected(false)} - /> - ))} - /> - -)) +const GroupedTags = memo( + ({ tags = [], handleElement = true, onDelete = () => undefined }) => ( + + { + const { original, id, toggleRowSelected, gotoPage } = props + const clickElement = handleElement + ? { + onClick: gotoPage, + onDelete: () => onDelete(id) || toggleRowSelected(false), + } + : {} -GroupedTags.propTypes = { tags: PropTypes.array } + return ( + + ) + })} + /> + + ) +) + +GroupedTags.propTypes = { + tags: PropTypes.array, + handleElement: PropTypes.bool, + onDelete: PropTypes.func, +} GroupedTags.displayName = 'GroupedTags' export default Zones From 2fe396ae15921c497e86b2cc1ddac84a267085e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Czern=C3=BD?= Date: Mon, 3 Jun 2024 11:40:24 +0200 Subject: [PATCH 004/124] L #-: Add Astyle linting * Add AStyle to smoke tests * Format C++ files using AStyle --- .github/workflows/smoke_tests.yml | 2 + include/AclManager.h | 2 +- include/AclRule.h | 10 +- include/ActionSet.h | 4 +- include/AddressRange.h | 42 +- include/AddressRangeIPAM.h | 4 +- include/AddressRangeInternal.h | 4 +- include/AddressRangePool.h | 22 +- include/Attribute.h | 26 +- include/AuthManager.h | 20 +- include/AuthRequest.h | 12 +- include/BackupIncrements.h | 16 +- include/BackupJob.h | 10 +- include/BackupJobPool.h | 18 +- include/BitMap.h | 6 +- include/Callbackable.h | 14 +- include/Client.h | 20 +- include/Cluster.h | 20 +- include/ClusterPool.h | 10 +- include/ClusterTemplate.h | 6 +- include/Clusterable.h | 4 +- include/ClusterableSingle.h | 4 +- include/Datastore.h | 8 +- include/DatastorePool.h | 30 +- include/DatastoreTemplate.h | 6 +- include/DefaultQuotas.h | 6 +- include/DispatchManager.h | 62 +- include/DocumentPool.h | 15 +- include/DocumentTemplate.h | 8 +- include/Driver.h | 53 +- include/DriverManager.h | 13 +- include/EnumString.h | 8 +- include/ExecuteHook.h | 2 +- include/ExtendedAttribute.h | 22 +- include/FedReplicaManager.h | 8 +- include/GroupPool.h | 4 +- include/History.h | 28 +- include/HookAPI.h | 2 +- include/HookManager.h | 2 +- include/HookPool.h | 6 +- include/HookStateHost.h | 2 +- include/HookStateImage.h | 2 +- include/HookStateVM.h | 2 +- include/HookStateVirtualNetwork.h | 2 +- include/Host.h | 29 +- include/HostPool.h | 24 +- include/HostShare.h | 2 +- include/HostShareDatastore.h | 4 +- include/HostShareNUMA.h | 14 +- include/HostSharePCI.h | 6 +- include/HostTemplate.h | 6 +- include/IPAMManager.h | 4 +- include/IPAMRequest.h | 6 +- include/Image.h | 12 +- include/ImageManager.h | 128 +- include/ImagePool.h | 42 +- include/ImageTemplate.h | 6 +- include/InformationManager.h | 12 +- include/LifeCycleManager.h | 2 +- include/Listener.h | 16 +- include/Log.h | 49 +- include/LogDB.h | 18 +- include/LoginToken.h | 16 +- include/MarketPlace.h | 7 +- include/MarketPlaceAppPool.h | 8 +- include/MarketPlaceAppTemplate.h | 4 +- include/MarketPlaceManager.h | 22 +- include/MarketPlacePool.h | 14 +- include/MarketPlaceTemplate.h | 4 +- include/Message.h | 18 +- include/MySqlDB.h | 5 +- include/Nebula.h | 48 +- include/NebulaLog.h | 41 +- include/NebulaService.h | 12 +- include/NebulaTemplate.h | 9 +- include/NebulaUtil.h | 36 +- include/ObjectCollection.h | 9 +- include/ObjectSQL.h | 10 +- include/ObjectXML.h | 2 +- include/OpenNebulaTemplate.h | 4 +- include/PoolObjectSQL.h | 52 +- include/PoolSQL.h | 32 +- include/PostgreSqlDB.h | 29 +- include/Quota.h | 88 +- include/QuotaDatastore.h | 6 +- include/QuotaImage.h | 6 +- include/QuotaNetwork.h | 14 +- include/QuotaVirtualMachine.h | 8 +- include/Quotas.h | 181 +- include/QuotasSQL.h | 26 +- include/RaftManager.h | 15 +- include/RankScheduler.h | 2 +- include/ReplicaManager.h | 10 +- include/ReplicaRequest.h | 4 +- include/ReplicaThread.h | 6 +- include/Request.h | 37 +- include/RequestManagerAcl.h | 10 +- include/RequestManagerAllocate.h | 140 +- include/RequestManagerAllocateDB.h | 8 +- include/RequestManagerChmod.h | 72 +- include/RequestManagerChown.h | 34 +- include/RequestManagerClone.h | 44 +- include/RequestManagerCluster.h | 84 +- include/RequestManagerConnection.h | 6 +- include/RequestManagerDatastore.h | 8 +- include/RequestManagerDelete.h | 4 +- include/RequestManagerDropDB.h | 6 +- include/RequestManagerGroup.h | 20 +- include/RequestManagerHook.h | 4 +- include/RequestManagerHost.h | 12 +- include/RequestManagerImage.h | 36 +- include/RequestManagerInfo.h | 8 +- include/RequestManagerMarketPlaceApp.h | 6 +- include/RequestManagerPoolInfoFilter.h | 36 +- include/RequestManagerProxy.h | 2 +- include/RequestManagerRename.h | 10 +- include/RequestManagerSystem.h | 44 +- include/RequestManagerUpdateDB.h | 16 +- include/RequestManagerUpdateTemplate.h | 38 +- include/RequestManagerUser.h | 38 +- include/RequestManagerVMGroup.h | 2 +- include/RequestManagerVMTemplate.h | 14 +- include/RequestManagerVNTemplate.h | 6 +- include/RequestManagerVdc.h | 38 +- include/RequestManagerVirtualMachine.h | 208 +- include/RequestManagerVirtualNetwork.h | 48 +- include/RequestManagerVirtualRouter.h | 10 +- include/RequestManagerZone.h | 34 +- include/SSLUtil.h | 12 +- include/ScheduledAction.h | 6 +- include/ScheduledActionManager.h | 2 +- include/ScheduledActionPool.h | 4 +- include/SecurityGroup.h | 16 +- include/SecurityGroupPool.h | 8 +- include/Snapshots.h | 2 +- include/SqlDB.h | 19 +- include/StreamManager.h | 15 +- include/StringBuffer.h | 3 +- include/SystemDB.h | 16 +- include/Template.h | 36 +- include/TransferManager.h | 22 +- include/User.h | 8 +- include/UserPool.h | 26 +- include/UserTemplate.h | 2 +- include/VMActions.h | 5 +- include/VMGroup.h | 8 +- include/VMGroupPool.h | 16 +- include/VMGroupRole.h | 10 +- include/VMGroupRule.h | 2 +- include/VMTemplatePool.h | 10 +- include/VNTemplatePool.h | 8 +- include/Vdc.h | 10 +- include/VdcPool.h | 14 +- include/VirtualMachine.h | 58 +- include/VirtualMachineAttribute.h | 10 +- include/VirtualMachineDisk.h | 44 +- include/VirtualMachineManager.h | 48 +- include/VirtualMachineManagerDriver.h | 102 +- include/VirtualMachineMonitorInfo.h | 2 +- include/VirtualMachineNic.h | 28 +- include/VirtualMachinePool.h | 50 +- include/VirtualMachineTemplate.h | 10 +- include/VirtualNetwork.h | 38 +- include/VirtualNetworkPool.h | 60 +- include/VirtualNetworkTemplate.h | 6 +- include/VirtualRouter.h | 2 +- include/VirtualRouterPool.h | 14 +- include/XMLDriver.h | 4 +- include/XenDriver.h | 4 +- include/Zone.h | 11 +- include/ZonePool.h | 8 +- include/ZoneServer.h | 10 +- share/linters/.astylerc | 27 + share/smoke_tests/tests/05-astyle.sh | 26 + src/acl/AclManager.cc | 166 +- src/acl/AclRule.cc | 58 +- src/authm/AuthManager.cc | 22 +- src/client/Client.cc | 18 +- src/cluster/Cluster.cc | 16 +- src/cluster/ClusterPool.cc | 14 +- src/common/Attribute.cc | 22 +- src/common/ExtendedAttribute.cc | 2 +- src/common/NebulaUtil.cc | 29 +- src/common/SSLUtil.cc | 12 +- src/datastore/Datastore.cc | 38 +- src/datastore/DatastorePool.cc | 52 +- src/dm/DispatchManager.cc | 2 +- src/dm/DispatchManagerActions.cc | 227 +- src/dm/DispatchManagerStates.cc | 60 +- src/document/Document.cc | 24 +- src/group/Group.cc | 218 +- src/group/GroupPool.cc | 24 +- src/hm/ExecuteHook.cc | 7 +- src/hm/Hook.cc | 2 +- src/hm/HookAPI.cc | 23 +- src/hm/HookManager.cc | 28 +- src/hm/HookStateVM.cc | 4 +- src/host/Host.cc | 56 +- src/host/HostMonitoringTemplate.cc | 6 +- src/host/HostPool.cc | 16 +- src/host/HostShare.cc | 46 +- src/host/HostShareNUMA.cc | 36 +- src/host/HostSharePCI.cc | 28 +- src/im/InformationManager.cc | 40 +- src/image/BackupIncrements.cc | 4 +- src/image/Image.cc | 157 +- src/image/ImageManager.cc | 38 +- src/image/ImageManagerActions.cc | 184 +- src/image/ImageManagerProtocol.cc | 10 +- src/image/ImagePool.cc | 8 +- src/ipamm/IPAMManager.cc | 37 +- src/ipamm/IPAMManagerProtocol.cc | 16 +- src/lcm/LifeCycleActions.cc | 468 +- src/lcm/LifeCycleManager.cc | 2 +- src/lcm/LifeCycleStates.cc | 291 +- src/log/Log.cc | 34 +- src/market/MarketPlace.cc | 80 +- src/market/MarketPlaceApp.cc | 102 +- src/market/MarketPlaceAppPool.cc | 36 +- src/market/MarketPlaceManager.cc | 38 +- src/market/MarketPlaceManagerActions.cc | 58 +- src/market/MarketPlaceManagerProtocol.cc | 8 +- src/market/MarketPlacePool.cc | 52 +- src/monitor/include/HostMonitorManager.h | 8 +- src/monitor/include/MonitorConfigTemplate.h | 2 +- src/monitor/include/MonitorDriver.h | 14 +- src/monitor/include/RPCPool.h | 4 +- src/monitor/include/TCPMonitorDriver.h | 14 +- src/monitor/include/TCPStream.h | 12 +- src/monitor/include/UDPMonitorDriver.h | 14 +- src/monitor/include/UDPStream.h | 9 +- src/monitor/include/VirtualMachineBase.h | 2 +- src/monitor/src/data_model/HostRPCPool.cc | 7 +- src/monitor/src/data_model/VMRPCPool.cc | 4 +- .../src/data_model/VirtualMachineBase.cc | 2 +- src/monitor/src/monitor/HostMonitorManager.cc | 21 +- src/monitor/src/monitor/Monitor.cc | 18 +- .../src/monitor/MonitorConfigTemplate.cc | 22 +- .../src/monitor/MonitorDriverProtocol.cc | 47 +- src/monitor/src/monitor/OneMonitorDriver.cc | 18 +- src/monitor/src/monitor/onemonitord.cc | 7 +- src/nebula/Nebula.cc | 84 +- src/nebula/SystemDB.cc | 18 +- src/nebula/oned.cc | 10 +- src/pool/ObjectCollection.cc | 52 +- src/pool/PoolObjectSQL.cc | 48 +- src/pool/PoolSQL.cc | 14 +- src/protocol/Message.cc | 27 +- src/raft/FedReplicaManager.cc | 10 +- src/raft/RaftManager.cc | 41 +- src/raft/ReplicaManager.cc | 3 +- src/raft/ReplicaThread.cc | 22 +- src/rm/Request.cc | 62 +- src/rm/RequestManager.cc | 99 +- src/rm/RequestManagerAcl.cc | 16 +- src/rm/RequestManagerAllocate.cc | 58 +- src/rm/RequestManagerBackupJob.cc | 2 +- src/rm/RequestManagerChmod.cc | 40 +- src/rm/RequestManagerChown.cc | 28 +- src/rm/RequestManagerClone.cc | 14 +- src/rm/RequestManagerCluster.cc | 4 +- src/rm/RequestManagerDatastore.cc | 2 +- src/rm/RequestManagerDelete.cc | 48 +- src/rm/RequestManagerGroup.cc | 8 +- src/rm/RequestManagerHook.cc | 2 +- src/rm/RequestManagerImage.cc | 36 +- src/rm/RequestManagerInfo.cc | 12 +- src/rm/RequestManagerLock.cc | 4 +- src/rm/RequestManagerMarketPlace.cc | 4 +- src/rm/RequestManagerMarketPlaceApp.cc | 4 +- src/rm/RequestManagerPoolInfoFilter.cc | 50 +- src/rm/RequestManagerProxy.cc | 2 +- src/rm/RequestManagerRename.cc | 2 +- src/rm/RequestManagerSchedAction.cc | 2 +- src/rm/RequestManagerSecurityGroup.cc | 2 +- src/rm/RequestManagerSystem.cc | 18 +- src/rm/RequestManagerUpdateTemplate.cc | 8 +- src/rm/RequestManagerUser.cc | 40 +- src/rm/RequestManagerVMTemplate.cc | 52 +- src/rm/RequestManagerVNTemplate.cc | 14 +- src/rm/RequestManagerVdc.cc | 6 +- src/rm/RequestManagerVirtualMachine.cc | 171 +- src/rm/RequestManagerVirtualNetwork.cc | 56 +- src/rm/RequestManagerVirtualRouter.cc | 2 +- src/rm/RequestManagerZone.cc | 38 +- src/sam/ScheduledAction.cc | 23 +- src/sam/ScheduledActionManager.cc | 10 +- src/sam/ScheduledActionPool.cc | 4 +- src/scheduler/include/AclXML.h | 2 +- src/scheduler/include/ClusterPoolXML.h | 4 +- src/scheduler/include/DatastorePoolXML.h | 8 +- src/scheduler/include/HostPoolXML.h | 2 +- src/scheduler/include/HostXML.h | 4 +- src/scheduler/include/MonitorXML.h | 6 +- src/scheduler/include/PoolXML.h | 8 +- src/scheduler/include/RankPolicy.h | 26 +- src/scheduler/include/Resource.h | 9 +- src/scheduler/include/Scheduler.h | 2 +- src/scheduler/include/SchedulerPolicy.h | 10 +- src/scheduler/include/SchedulerTemplate.h | 4 +- src/scheduler/include/UserPoolXML.h | 4 +- src/scheduler/include/UserPriorityPolicy.h | 4 +- src/scheduler/include/UserXML.h | 2 +- src/scheduler/include/VMGroupPoolXML.h | 4 +- src/scheduler/include/VMGroupXML.h | 6 +- src/scheduler/include/VirtualMachinePoolXML.h | 8 +- src/scheduler/include/VirtualMachineXML.h | 6 +- src/scheduler/include/VirtualNetworkPoolXML.h | 2 +- src/scheduler/src/pool/AclXML.cc | 6 +- src/scheduler/src/pool/ClusterPoolXML.cc | 4 +- src/scheduler/src/pool/DatastorePoolXML.cc | 4 +- src/scheduler/src/pool/DatastoreXML.cc | 3 +- src/scheduler/src/pool/HostPoolXML.cc | 6 +- src/scheduler/src/pool/HostXML.cc | 6 +- src/scheduler/src/pool/UserPoolXML.cc | 4 +- src/scheduler/src/pool/VMGroupPoolXML.cc | 4 +- src/scheduler/src/pool/VMGroupXML.cc | 12 +- .../src/pool/VirtualMachinePoolXML.cc | 16 +- src/scheduler/src/pool/VirtualMachineXML.cc | 64 +- .../src/pool/VirtualNetworkPoolXML.cc | 6 +- src/scheduler/src/pool/VirtualNetworkXML.cc | 7 +- src/scheduler/src/sched/Scheduler.cc | 95 +- src/scheduler/src/sched/SchedulerTemplate.cc | 90 +- src/secgroup/SecurityGroup.cc | 27 +- src/secgroup/SecurityGroupPool.cc | 18 +- src/sql/LogDB.cc | 16 +- src/sql/MySqlDB.cc | 29 +- src/sql/OneDB.cc | 240 +- src/sql/PostgreSqlDB.cc | 15 +- src/sql/SqlDB.cc | 2 +- src/sql/SqliteDB.cc | 15 +- src/svncterm_server/glyphs.h | 143826 ++++++++------- src/svncterm_server/svncterm.h | 430 +- src/template/NebulaTemplate.cc | 6 +- src/template/OpenNebulaTemplate.cc | 468 +- src/template/Template.cc | 32 +- src/tm/TransferManager.cc | 553 +- src/um/Quota.cc | 10 +- src/um/QuotaImage.cc | 10 +- src/um/QuotaNetwork.cc | 6 +- src/um/QuotaVirtualMachine.cc | 9 +- src/um/Quotas.cc | 20 +- src/um/QuotasSQL.cc | 6 +- src/um/User.cc | 30 +- src/um/UserPool.cc | 153 +- src/vdc/Vdc.cc | 62 +- src/vdc/VdcPool.cc | 20 +- src/vm/BackupJob.cc | 53 +- src/vm/Backups.cc | 2 +- src/vm/History.cc | 244 +- src/vm/Snapshots.cc | 2 +- src/vm/VMActions.cc | 114 +- src/vm/VirtualMachine.cc | 495 +- src/vm/VirtualMachineContext.cc | 28 +- src/vm/VirtualMachineDisk.cc | 71 +- src/vm/VirtualMachineNic.cc | 26 +- src/vm/VirtualMachineParser.cc | 50 +- src/vm/VirtualMachinePool.cc | 120 +- src/vm/VirtualMachineSystemSnapshot.cc | 2 +- src/vm/VirtualMachineTemplate.cc | 127 +- src/vm_group/VMGroup.cc | 14 +- src/vm_group/VMGroupPool.cc | 8 +- src/vm_group/VMGroupRole.cc | 4 +- src/vm_group/VMGroupRule.cc | 2 +- src/vm_template/VMTemplate.cc | 24 +- src/vmm/LibVirtDriverKVM.cc | 121 +- src/vmm/VirtualMachineManager.cc | 1383 +- src/vmm/VirtualMachineManagerDriver.cc | 30 +- src/vmm/VirtualMachineManagerProtocol.cc | 56 +- src/vmm/XMLDriver.cc | 4 +- src/vmm/XenDriver.cc | 36 +- src/vn_template/VNTemplate.cc | 26 +- src/vnm/AddressRange.cc | 142 +- src/vnm/AddressRangeIPAM.cc | 4 +- src/vnm/AddressRangeInternal.cc | 2 +- src/vnm/AddressRangePool.cc | 60 +- src/vnm/VirtualNetwork.cc | 133 +- src/vnm/VirtualNetworkPool.cc | 48 +- src/vrouter/VirtualRouter.cc | 44 +- src/xml/ObjectXML.cc | 26 +- src/zone/Zone.cc | 14 +- src/zone/ZonePool.cc | 26 +- 382 files changed, 79249 insertions(+), 78779 deletions(-) create mode 100644 share/linters/.astylerc create mode 100755 share/smoke_tests/tests/05-astyle.sh diff --git a/.github/workflows/smoke_tests.yml b/.github/workflows/smoke_tests.yml index a7491079b8d..b069eb80090 100644 --- a/.github/workflows/smoke_tests.yml +++ b/.github/workflows/smoke_tests.yml @@ -19,6 +19,8 @@ jobs: run: gem install rubocop - name: Install CppCheck run: sudo apt install -y cppcheck + - name: Install AStyle + run: sudo apt install -y astyle # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v4 diff --git a/include/AclManager.h b/include/AclManager.h index eb665666e95..7e96e8bf1f5 100644 --- a/include/AclManager.h +++ b/include/AclManager.h @@ -90,7 +90,7 @@ class AclManager : public Callbackable * @return true if the authorization is granted for oneadmin */ bool oneadmin_authorize(const PoolObjectAuth& obj_perms, - AuthRequest::Operation op) const; + AuthRequest::Operation op) const; /** * Adds a new rule to the ACL rule set diff --git a/include/AclRule.h b/include/AclRule.h index 50cfd057055..b848bda18fc 100644 --- a/include/AclRule.h +++ b/include/AclRule.h @@ -64,11 +64,11 @@ class AclRule /** * Set the fields of the ACL, and updates its representation */ - void set(int _oid, - long long _user, - long long _resource, - long long _rights, - long long _zone) + void set(int _oid, + long long _user, + long long _resource, + long long _rights, + long long _zone) { oid = _oid; user = _user; diff --git a/include/ActionSet.h b/include/ActionSet.h index c9a56f22f38..683c9c269c4 100644 --- a/include/ActionSet.h +++ b/include/ActionSet.h @@ -28,7 +28,7 @@ template class ActionSet { public: - ActionSet():action_set(0UL){}; + ActionSet():action_set(0UL) {}; ActionSet(const T * actions, int actions_len):action_set(0) { for (int i=0; i& vms, - const std::vector& vnets, const std::vector& vrs) const; + const std::vector& vnets, const std::vector& vrs) const; /** * Same as above but without the LEASES section @@ -194,7 +194,7 @@ class AddressRange * @return 0 if success */ int allocate_addr(PoolObjectSQL::ObjectType ot, int obid, - VectorAttribute * nic, const std::set &inherit); + VectorAttribute * nic, const std::set &inherit); /** * Returns the specific address by mac/ip if is not allocated. The NIC attr @@ -207,13 +207,13 @@ class AddressRange * @return 0 if success */ int allocate_by_mac(const std::string& mac, PoolObjectSQL::ObjectType ot, - int obid, VectorAttribute * nic, const std::set &inherit); + int obid, VectorAttribute * nic, const std::set &inherit); int allocate_by_ip(const std::string& ip, PoolObjectSQL::ObjectType ot, - int obid, VectorAttribute * nic, const std::set &inherit); + int obid, VectorAttribute * nic, const std::set &inherit); int allocate_by_ip6(const std::string& ip6, PoolObjectSQL::ObjectType ot, - int obid, VectorAttribute * nic, const std::set &inherit); + int obid, VectorAttribute * nic, const std::set &inherit); /** * Sets the given ip/mac on hold, the address is associated to a VM of @@ -237,7 +237,7 @@ class AddressRange int free_addr_by_ip(PoolObjectSQL::ObjectType ot, int id, const std::string& ip); - int free_addr_by_ip6(PoolObjectSQL::ObjectType ot, int id,const std::string& ip); + int free_addr_by_ip6(PoolObjectSQL::ObjectType ot, int id, const std::string& ip); /** * Frees all previous allocated address to the given object @@ -257,7 +257,7 @@ class AddressRange * @return the number of addresses freed */ int free_addr_by_range(PoolObjectSQL::ObjectType ot, int obid, - const std::string& mac, unsigned int rsize); + const std::string& mac, unsigned int rsize); /** * Adds the relevant AR definition attributes to the Security Group rule @@ -288,13 +288,13 @@ class AddressRange * @return 0 on success */ int reserve_addr_by_mac(int vid, unsigned int rsize, const std::string& mac, - AddressRange *rar); + AddressRange *rar); int reserve_addr_by_ip(int vid, unsigned int rsize, const std::string& ip, - AddressRange *rar); + AddressRange *rar); int reserve_addr_by_ip6(int vid, unsigned int rsize, const std::string& ip, - AddressRange *rar); + AddressRange *rar); // ************************************************************************* // Helpers @@ -437,7 +437,7 @@ class AddressRange * Base constructor it cannot be called directly but from the * AddressRange factory constructor. */ - AddressRange(unsigned int _id):id(_id){}; + AddressRange(unsigned int _id):id(_id) {}; /* ---------------------------------------------------------------------- */ /* Address/AR helper functions to build/parse driver messages */ @@ -462,7 +462,7 @@ class AddressRange * @param oss string stream to write the request to */ void addr_to_xml(unsigned int index, unsigned int size, - std::ostringstream& oss) const; + std::ostringstream& oss) const; /** * Check if the given MAC is valid for this address range by verifying: @@ -611,7 +611,7 @@ class AddressRange * @return 0 on success */ static int ip6_to_s(const unsigned int prefix[], const unsigned int mac[], - std::string& ip6_s); + std::string& ip6_s); static int ip6_to_s(const unsigned int ip6_i[], std::string& ip6_s); @@ -686,7 +686,7 @@ class AddressRange * Adds a new allocated address to the map. Updates the ALLOCATED attribute */ void set_allocated_addr(PoolObjectSQL::ObjectType ot, int obid, - unsigned int addr_index); + unsigned int addr_index); /** * Sets the address lease as used and fills a NIC attribute with the @@ -699,16 +699,16 @@ class AddressRange * @return 0 if success */ void allocate_by_index(unsigned int index, - PoolObjectSQL::ObjectType ot, - int obid, - VectorAttribute* nic, - const std::set& inherit); + PoolObjectSQL::ObjectType ot, + int obid, + VectorAttribute* nic, + const std::set& inherit); /** * Frees an address from the map. Updates the ALLOCATED attribute */ int free_allocated_addr(PoolObjectSQL::ObjectType ot, int obid, - unsigned int addr_index); + unsigned int addr_index); /** * Reserve a set of addresses from an starting one @@ -719,7 +719,7 @@ class AddressRange * @return 0 on success */ int reserve_addr_by_index(int vid, unsigned int rsize, unsigned int sindex, - AddressRange *rar); + AddressRange *rar); /* ---------------------------------------------------------------------- */ /* Restricted Attributes functions */ diff --git a/include/AddressRangeIPAM.h b/include/AddressRangeIPAM.h index 2ef740833e7..e2b3e5cef03 100644 --- a/include/AddressRangeIPAM.h +++ b/include/AddressRangeIPAM.h @@ -26,9 +26,9 @@ class VectorAttribute; class AddressRangeIPAM : public AddressRange { public: - AddressRangeIPAM(unsigned int _id):AddressRange(_id){}; + AddressRangeIPAM(unsigned int _id):AddressRange(_id) {}; - virtual ~AddressRangeIPAM(){}; + virtual ~AddressRangeIPAM() {}; /* ---------------------------------------------------------------------- */ /* AddressRange Interface */ diff --git a/include/AddressRangeInternal.h b/include/AddressRangeInternal.h index 5d138019a90..07d3c2f4add 100644 --- a/include/AddressRangeInternal.h +++ b/include/AddressRangeInternal.h @@ -26,9 +26,9 @@ class VectorAttribute; class AddressRangeInternal : public AddressRange { public: - AddressRangeInternal(unsigned int _id):AddressRange(_id), next(0){}; + AddressRangeInternal(unsigned int _id):AddressRange(_id), next(0) {}; - virtual ~AddressRangeInternal(){}; + virtual ~AddressRangeInternal() {}; /* ---------------------------------------------------------------------- */ /* AddressRange Interface */ diff --git a/include/AddressRangePool.h b/include/AddressRangePool.h index 9e0a0036cd2..671e7173f5f 100644 --- a/include/AddressRangePool.h +++ b/include/AddressRangePool.h @@ -89,8 +89,8 @@ class AddressRangePool * @return 0 on success */ int update_ar(std::vector ars, bool keep_restricted, - std::set& update_ids, std::unique_ptr& update_attr, - std::string& error_msg); + std::set& update_ids, std::unique_ptr& update_attr, + std::string& error_msg); /** * Allocates a new *empty* address range. It is not added to the pool as it * needs to be initialized. Only the AR_ID is set. @@ -121,7 +121,7 @@ class AddressRangePool * @return 0 if success */ int allocate_addr(PoolObjectSQL::ObjectType ot, int obid, - VectorAttribute * nic, const std::set &inherit); + VectorAttribute * nic, const std::set &inherit); /** * Allocates an address in a suitable address range from the pool by mac/ip @@ -175,13 +175,13 @@ class AddressRangePool * @param mac/ip the specific MAC/IP address requested */ void free_addr(unsigned int arid, PoolObjectSQL::ObjectType ot, int obid, - const std::string& mac); + const std::string& mac); void free_addr_by_ip(unsigned int arid, PoolObjectSQL::ObjectType ot, - int obid, const std::string& ip); + int obid, const std::string& ip); void free_addr_by_ip6(unsigned int arid, PoolObjectSQL::ObjectType ot, - int obid, const std::string& ip); + int obid, const std::string& ip); /** * Frees the given address by MAC/IP from all address ranges containing @@ -216,7 +216,7 @@ class AddressRangePool * @param rsize size of the address range */ int free_addr_by_range(unsigned int arid, PoolObjectSQL::ObjectType ot, - int obid, const std::string& mac, unsigned int rsize); + int obid, const std::string& mac, unsigned int rsize); /** * From a Security Group rule that uses this vnet, creates a new rule @@ -253,7 +253,7 @@ class AddressRangePool * @return 0 on success */ int reserve_addr(int vid, unsigned int rsize, unsigned int ar_id, - AddressRange *rar); + AddressRange *rar); /** * Reserve a number of addresses from an address range from a given ip/mac @@ -265,13 +265,13 @@ class AddressRangePool * @return 0 on success */ int reserve_addr_by_mac(int vid, unsigned int rsize, unsigned int ar_id, - const std::string& mac, AddressRange *rar); + const std::string& mac, AddressRange *rar); int reserve_addr_by_ip(int vid, unsigned int rsize, unsigned int ar_id, - const std::string& ip, AddressRange *rar); + const std::string& ip, AddressRange *rar); int reserve_addr_by_ip6(int vid, unsigned int rsize, unsigned int ar_id, - const std::string& ip, AddressRange *rar); + const std::string& ip, AddressRange *rar); // ************************************************************************* diff --git a/include/Attribute.h b/include/Attribute.h index dc44ecc93f0..59beaa71f9e 100644 --- a/include/Attribute.h +++ b/include/Attribute.h @@ -45,11 +45,11 @@ class Attribute if ((size >0 && !(isalpha(aname[0]) || aname[0] == '_')) || (size >=3 && (aname[0]=='X' && aname[1]=='M' && aname[2]=='L'))) { - attribute_name.insert(0,"ONE_"); + attribute_name.insert(0, "ONE_"); } }; - virtual ~Attribute(){}; + virtual ~Attribute() {}; enum AttributeType { @@ -82,7 +82,7 @@ class Attribute virtual void to_token(std::ostringstream& s) const = 0; virtual void to_xml(std::ostringstream& s, - const std::map> &hidden) const = 0; + const std::map> &hidden) const = 0; /** * Builds a new attribute from a string. @@ -145,7 +145,7 @@ class SingleAttribute : public Attribute , attribute_value(sa.attribute_value) {} - ~SingleAttribute(){}; + ~SingleAttribute() {}; /** * Returns the attribute value, a string. @@ -182,17 +182,17 @@ class SingleAttribute : public Attribute } void to_xml(std::ostringstream& s, - const std::map> &hidden) const override + const std::map> &hidden) const override { s << "<" << attribute_name << ">"; if (hidden.find(attribute_name) != hidden.end() ) { - s << "***"; + s << "***"; } else { - s << one_util::escape_xml(attribute_value); + s << one_util::escape_xml(attribute_value); } s << ""; @@ -282,7 +282,7 @@ class VectorAttribute : public Attribute {} VectorAttribute(const std::string& name, - const std::map& value) + const std::map& value) : Attribute(name) , attribute_value(value) {} @@ -296,12 +296,12 @@ class VectorAttribute : public Attribute VectorAttribute& operator=(const VectorAttribute& va) = default; - ~VectorAttribute(){}; + ~VectorAttribute() {}; /** * Returns the attribute value, a string. */ - const std::map& value() const + const std::map& value() const { return attribute_value; }; @@ -452,7 +452,7 @@ class VectorAttribute : public Attribute void to_xml(std::ostringstream& s) const override; void to_xml(std::ostringstream& s, - const std::map> &hidden) const override; + const std::map> &hidden) const override; void to_json(std::ostringstream& s) const override; @@ -467,7 +467,7 @@ class VectorAttribute : public Attribute /** * Replace the value of the given attribute with the provided map */ - void replace(const std::map& attr); + void replace(const std::map& attr); /** * The attributes from vattr will be copied to this vector @@ -560,7 +560,7 @@ class VectorAttribute : public Attribute static const int magic_sep_size; - std::map attribute_value; + std::map attribute_value; }; #endif /*ATTRIBUTE_H_*/ diff --git a/include/AuthManager.h b/include/AuthManager.h index 68dc136bf36..2c3142210a0 100644 --- a/include/AuthManager.h +++ b/include/AuthManager.h @@ -29,17 +29,17 @@ class AuthRequest; class AuthManager : public DriverManager>, - public Listener + public Listener { public: AuthManager( - time_t timer, - const std::string& mads_location) - : DriverManager(mads_location) - , Listener("Authorization Manager") - , timer_thread(timer, [this](){timer_action();}) - , authz_enabled(false) + time_t timer, + const std::string& mads_location) + : DriverManager(mads_location) + , Listener("Authorization Manager") + , timer_thread(timer, [this]() {timer_action();}) + , authz_enabled(false) { } @@ -88,9 +88,9 @@ class AuthManager : */ static const char * auth_driver_name; - /** - * True if there is an authorization driver enabled - */ + /** + * True if there is an authorization driver enabled + */ bool authz_enabled; /** diff --git a/include/AuthRequest.h b/include/AuthRequest.h index 0e2bbe4f4d3..53619a6952b 100644 --- a/include/AuthRequest.h +++ b/include/AuthRequest.h @@ -40,7 +40,7 @@ class AuthRequest : public SyncRequest , self_authorize(true) {} - ~AuthRequest(){}; + ~AuthRequest() {}; /** * Authorization Request Type @@ -78,11 +78,11 @@ class AuthRequest : public SyncRequest static Operation str_to_operation(const std::string& str) { - if (str == "USE") return USE; - else if (str == "MANAGE") return MANAGE; - else if (str == "ADMIN") return ADMIN; - else if (str == "CREATE") return CREATE; - else return NONE; + if (str == "USE") return USE; + else if (str == "MANAGE") return MANAGE; + else if (str == "ADMIN") return ADMIN; + else if (str == "CREATE") return CREATE; + else return NONE; }; /** diff --git a/include/BackupIncrements.h b/include/BackupIncrements.h index fe13f051864..f846821b16f 100644 --- a/include/BackupIncrements.h +++ b/include/BackupIncrements.h @@ -36,7 +36,7 @@ class Increment : public ExtendedAttribute { public: - Increment(VectorAttribute *va, int id): ExtendedAttribute(va, id){}; + Increment(VectorAttribute *va, int id): ExtendedAttribute(va, id) {}; ~Increment() = default; @@ -90,7 +90,7 @@ class Increment : public ExtendedAttribute case FULL: replace("TYPE", "FULL"); break; - case INCREMENT: + case INCREMENT: replace("TYPE", "INCREMENT"); break; } @@ -121,7 +121,7 @@ class Increment : public ExtendedAttribute class IncrementSet : public ExtendedAttributeSet { public: - IncrementSet(): ExtendedAttributeSet(false){}; + IncrementSet(): ExtendedAttributeSet(false) {}; ~IncrementSet() = default; @@ -146,7 +146,7 @@ class IncrementSet : public ExtendedAttributeSet * @return Pointer to the new attribute */ VectorAttribute * new_increment(const std::string& source, long long sz, - Increment::Type type); + Increment::Type type); Increment * last_increment() { @@ -182,10 +182,10 @@ class IncrementSet : public ExtendedAttributeSet class IncIterator : public AttributeIterator { public: - IncIterator():AttributeIterator(){}; - IncIterator(const AttributeIterator& dit):AttributeIterator(dit){}; + IncIterator():AttributeIterator() {}; + IncIterator(const AttributeIterator& dit):AttributeIterator(dit) {}; - virtual ~IncIterator(){}; + virtual ~IncIterator() {}; Increment * operator*() const { @@ -229,7 +229,7 @@ class IncrementSet : public ExtendedAttributeSet class BackupIncrements { public: - BackupIncrements():_template(false,'=',"BACKUP_INCREMENTS"){}; + BackupIncrements():_template(false, '=', "BACKUP_INCREMENTS") {}; ~BackupIncrements() = default; diff --git a/include/BackupJob.h b/include/BackupJob.h index 94b5ef44835..7db6cae0106 100644 --- a/include/BackupJob.h +++ b/include/BackupJob.h @@ -242,8 +242,8 @@ class BackupJob : public PoolObjectSQL * @return 0 on success */ int replace_template(const std::string& tmpl_str, - bool keep_restricted, - std::string& error) override; + bool keep_restricted, + std::string& error) override; /** * Append new attributes to the *user template*. @@ -254,7 +254,7 @@ class BackupJob : public PoolObjectSQL * @return 0 on success */ int append_template(const std::string& tmpl_str, bool keep_restricted, - std::string& error) override; + std::string& error) override; friend class BackupJobPool; friend class PoolSQL; @@ -296,7 +296,7 @@ class BackupJob : public PoolObjectSQL * @param db pointer to the database. * @return 0 on success. */ - int update(SqlDB * db) override; + int update(SqlDB * db) override; /** * Execute an INSERT or REPLACE Sql query. @@ -394,7 +394,7 @@ class BackupJob : public PoolObjectSQL */ int process_backup_vms(const std::string& vms_new_str, const std::string& vms_old_str, - std::string& error); + std::string& error); /** * Remove Backup Job ID from Virtual Machines listed in BACKUP_VMS attribute diff --git a/include/BackupJobPool.h b/include/BackupJobPool.h index 0bee58927a9..030c3e1c59a 100644 --- a/include/BackupJobPool.h +++ b/include/BackupJobPool.h @@ -47,14 +47,14 @@ class BackupJobPool : public PoolSQL * -2 in case of template parse failure */ int allocate ( - int uid, - int gid, - const std::string& uname, - const std::string& gname, - int umask, - std::unique_ptr