diff --git a/src/fireedge/src/client/components/Tabs/Host/Info/index.js b/src/fireedge/src/client/components/Tabs/Host/Info/index.js index 08f7d6c5c5..eadcc4eccc 100644 --- a/src/fireedge/src/client/components/Tabs/Host/Info/index.js +++ b/src/fireedge/src/client/components/Tabs/Host/Info/index.js @@ -55,7 +55,7 @@ const HostInfoTab = ({ tabProps = {}, id }) => { } = tabProps const [updateUserTemplate] = useUpdateHostMutation() - const { data: host = {} } = useGetHostQuery(id) + const { data: host = {} } = useGetHostQuery({ id }) const { TEMPLATE } = host const handleAttributeInXml = async (path, newValue) => { diff --git a/src/fireedge/src/client/components/Tabs/Host/Numa/index.js b/src/fireedge/src/client/components/Tabs/Host/Numa/index.js index ee6c6bde75..12dc536ebe 100644 --- a/src/fireedge/src/client/components/Tabs/Host/Numa/index.js +++ b/src/fireedge/src/client/components/Tabs/Host/Numa/index.js @@ -33,7 +33,7 @@ import UpdateIsolatedCPUSForm from 'client/components/Tabs/Host/Numa/UpdateIsola * @returns {ReactElement} Information tab */ const NumaInfoTab = ({ id }) => { - const { data: host = {} } = useGetHostQuery(id) + const { data: host = {} } = useGetHostQuery({ id }) const numa = getHostNuma(host) return ( diff --git a/src/fireedge/src/client/components/Tabs/Host/Vms.js b/src/fireedge/src/client/components/Tabs/Host/Vms.js index e1ede0d14f..de72826b14 100644 --- a/src/fireedge/src/client/components/Tabs/Host/Vms.js +++ b/src/fireedge/src/client/components/Tabs/Host/Vms.js @@ -31,7 +31,7 @@ import { VmsTable } from 'client/components/Tables' * @returns {ReactElement} Information tab */ const VmsInfoTab = ({ id }) => { - const { data: host = {} } = useGetHostQuery(id) + const { data: host = {} } = useGetHostQuery({ id }) const path = PATH.INSTANCE.VMS.DETAIL const history = useHistory() diff --git a/src/fireedge/src/client/components/Tabs/Host/Wilds.js b/src/fireedge/src/client/components/Tabs/Host/Wilds.js index d7d60a2b16..b45441becf 100644 --- a/src/fireedge/src/client/components/Tabs/Host/Wilds.js +++ b/src/fireedge/src/client/components/Tabs/Host/Wilds.js @@ -30,7 +30,7 @@ import WildsTable from 'client/components/Tables/Wilds' * @returns {ReactElement} - Wild information tab */ const WildsInfoTab = ({ id }) => { - const { data: host = {} } = useGetHostQuery(id) + const { data: host = {} } = useGetHostQuery({ id }) const wilds = getHostWilds(host) return ( diff --git a/src/fireedge/src/client/components/Tabs/Host/Zombies.js b/src/fireedge/src/client/components/Tabs/Host/Zombies.js index 35a62c7166..8ba1c5444b 100644 --- a/src/fireedge/src/client/components/Tabs/Host/Zombies.js +++ b/src/fireedge/src/client/components/Tabs/Host/Zombies.js @@ -30,7 +30,7 @@ import ZombiesTable from 'client/components/Tables/Zombies' * @returns {ReactElement} - Zombies information tab */ const ZombiesInfoTab = ({ id }) => { - const { data: host = {} } = useGetHostQuery(id) + const { data: host = {} } = useGetHostQuery({ id }) const zombies = getHostZombies(host) return ( diff --git a/src/fireedge/src/client/components/Tabs/Host/index.js b/src/fireedge/src/client/components/Tabs/Host/index.js index 29797f1f6c..c800e4b3f9 100644 --- a/src/fireedge/src/client/components/Tabs/Host/index.js +++ b/src/fireedge/src/client/components/Tabs/Host/index.js @@ -40,7 +40,10 @@ const getTabComponent = (tabName) => const HostTabs = memo(({ id }) => { const { view, getResourceView } = useViews() - const { isLoading, isError, error } = useGetHostQuery(id) + const { isLoading, isError, error } = useGetHostQuery( + { id }, + { refetchOnMountOrArgChange: 10 } + ) const tabsAvailable = useMemo(() => { const resource = RESOURCE_NAMES.HOST diff --git a/src/fireedge/src/client/components/Tabs/MarketplaceApp/Info/index.js b/src/fireedge/src/client/components/Tabs/MarketplaceApp/Info/index.js index bd42db72ff..f7b87e086d 100644 --- a/src/fireedge/src/client/components/Tabs/MarketplaceApp/Info/index.js +++ b/src/fireedge/src/client/components/Tabs/MarketplaceApp/Info/index.js @@ -60,7 +60,7 @@ const MarketplaceAppInfoTab = ({ tabProps = {}, id }) => { const [changeOwnership] = useChangeAppOwnershipMutation() const [changePermissions] = useChangeAppPermissionsMutation() const [updateTemplate] = useUpdateAppMutation() - const { data: app = {} } = useGetMarketplaceAppQuery(id) + const { data: app = {} } = useGetMarketplaceAppQuery({ id }) const { UNAME, UID, GNAME, GID, PERMISSIONS, TEMPLATE } = app const handleChangeOwnership = async (newOwnership) => { diff --git a/src/fireedge/src/client/components/Tabs/MarketplaceApp/Template.js b/src/fireedge/src/client/components/Tabs/MarketplaceApp/Template.js index 0cae876fab..56fa315939 100644 --- a/src/fireedge/src/client/components/Tabs/MarketplaceApp/Template.js +++ b/src/fireedge/src/client/components/Tabs/MarketplaceApp/Template.js @@ -31,7 +31,7 @@ import { T } from 'client/constants' * @returns {ReactElement} App Template tab */ const AppTemplateTab = ({ id }) => { - const { data: marketplaceApp = {} } = useGetMarketplaceAppQuery(id) + const { data: marketplaceApp = {} } = useGetMarketplaceAppQuery({ id }) const { APPTEMPLATE64, VMTEMPLATE64 } = marketplaceApp?.TEMPLATE const appTemplate = useMemo( diff --git a/src/fireedge/src/client/components/Tabs/MarketplaceApp/index.js b/src/fireedge/src/client/components/Tabs/MarketplaceApp/index.js index b1ab972b23..671be9cffa 100644 --- a/src/fireedge/src/client/components/Tabs/MarketplaceApp/index.js +++ b/src/fireedge/src/client/components/Tabs/MarketplaceApp/index.js @@ -34,7 +34,10 @@ const getTabComponent = (tabName) => const MarketplaceAppTabs = memo(({ id }) => { const { view, getResourceView } = useViews() - const { isLoading, isError, error } = useGetMarketplaceAppQuery(id) + const { isLoading, isError, error } = useGetMarketplaceAppQuery( + { id }, + { refetchOnMountOrArgChange: 10 } + ) const tabsAvailable = useMemo(() => { const resource = RESOURCE_NAMES.APP diff --git a/src/fireedge/src/client/components/Tabs/VNetwork/Info/information.js b/src/fireedge/src/client/components/Tabs/VNetwork/Info/information.js index ecc001f229..b79edcf7b8 100644 --- a/src/fireedge/src/client/components/Tabs/VNetwork/Info/information.js +++ b/src/fireedge/src/client/components/Tabs/VNetwork/Info/information.js @@ -16,7 +16,7 @@ import { ReactElement } from 'react' import PropTypes from 'prop-types' -import { useRenameVNTemplateMutation } from 'client/features/OneApi/networkTemplate' +import { useRenameVNetMutation } from 'client/features/OneApi/network' import { StatusChip } from 'client/components/Status' import { List } from 'client/components/Tabs/Common' @@ -33,7 +33,7 @@ import { T, VNetwork, VN_ACTIONS } from 'client/constants' * @returns {ReactElement} Information tab */ const InformationPanel = ({ vnet = {}, actions }) => { - const [rename] = useRenameVNTemplateMutation() + const [rename] = useRenameVNetMutation() const { ID, NAME } = vnet const { name: stateName, color: stateColor } = getState(vnet) diff --git a/src/fireedge/src/client/features/OneApi/common.js b/src/fireedge/src/client/features/OneApi/common.js index 97799f239e..81d734aa97 100644 --- a/src/fireedge/src/client/features/OneApi/common.js +++ b/src/fireedge/src/client/features/OneApi/common.js @@ -233,7 +233,7 @@ export const updateOwnershipOnResource = ( } /** - * Update the template or user template of a resource in the store. + * Update the resource template in the store. * * @param {object} params - Request params * @param {number|string} params.id - The id of the resource @@ -242,13 +242,13 @@ export const updateOwnershipOnResource = ( * - Update type: * ``0``: Replace the whole template. * ``1``: Merge new template with the existing one. - * @param {string} [userTemplateAttribute] - The attribute name of the user template. By default is `USER_TEMPLATE`. + * @param {string} [templateAttribute] - The attribute name of the resource template. By default is `TEMPLATE`. * @returns {function(Draft):ThunkAction} - Dispatches the action */ -export const updateUserTemplateOnResource = +export const updateTemplateOnResource = ( { id: resourceId, template: xml, replace = 0 }, - userTemplateAttribute = 'USER_TEMPLATE' + templateAttribute = 'TEMPLATE' ) => (draft) => { const updatePool = isUpdateOnPool(draft, resourceId) @@ -260,10 +260,10 @@ export const updateUserTemplateOnResource = if (updatePool && !resource) return - resource[userTemplateAttribute] = + resource[templateAttribute] = +replace === 0 ? newTemplateJson - : { ...resource[userTemplateAttribute], ...newTemplateJson } + : { ...resource[templateAttribute], ...newTemplateJson } } /** diff --git a/src/fireedge/src/client/features/OneApi/host.js b/src/fireedge/src/client/features/OneApi/host.js index 5ccbbae4ac..332993c899 100644 --- a/src/fireedge/src/client/features/OneApi/host.js +++ b/src/fireedge/src/client/features/OneApi/host.js @@ -14,11 +14,18 @@ * limitations under the License. * * ------------------------------------------------------------------------- */ import { Actions, Commands } from 'server/utils/constants/commands/host' + import { oneApi, ONE_RESOURCES, ONE_RESOURCES_POOL, } from 'client/features/OneApi' +import { + updateResourceOnPool, + removeResourceOnPool, + updateNameOnResource, + updateTemplateOnResource, +} from 'client/features/OneApi/common' import { UpdateFromSocket } from 'client/features/OneApi/socket' import { Host } from 'client/constants' @@ -53,34 +60,45 @@ const hostApi = oneApi.injectEndpoints({ /** * Retrieves information for the host. * - * @param {string} id - Host id + * @param {object} params - Request params + * @param {string} params.id - Host id * @returns {Host} Get host identified by id * @throws Fails when response isn't code 200 */ - query: (id) => { + query: (params) => { const name = Actions.HOST_INFO const command = { name, ...Commands[name] } - return { params: { id }, command } + return { params, command } }, transformResponse: (data) => data?.HOST ?? {}, - providesTags: (_, __, id) => [{ type: HOST, id }], - async onQueryStarted(id, { dispatch, queryFulfilled }) { + providesTags: (_, __, { id }) => [{ type: HOST, id }], + async onQueryStarted({ id }, { dispatch, queryFulfilled }) { try { - const { data: queryVm } = await queryFulfilled + const { data: resourceFromQuery } = await queryFulfilled dispatch( - hostApi.util.updateQueryData('getHosts', undefined, (draft) => { - const index = draft.findIndex(({ ID }) => +ID === +id) - index !== -1 && (draft[index] = queryVm) - }) + hostApi.util.updateQueryData( + 'getHosts', + undefined, + updateResourceOnPool({ id, resourceFromQuery }) + ) ) - } catch {} + } catch { + // if the query fails, we want to remove the resource from the pool + dispatch( + hostApi.util.updateQueryData( + 'getHosts', + undefined, + removeResourceOnPool({ id }) + ) + ) + } }, onCacheEntryAdded: UpdateFromSocket({ updateQueryData: (updateFn) => hostApi.util.updateQueryData('getHosts', undefined, updateFn), - resource: HOST.toLowerCase(), + resource: 'HOST', }), }), allocateHost: builder.mutation({ @@ -105,7 +123,6 @@ const hostApi = oneApi.injectEndpoints({ return { params, command } }, - invalidatesTags: [HOST_POOL], }), updateHost: builder.mutation({ /** @@ -128,6 +145,30 @@ const hostApi = oneApi.injectEndpoints({ return { params, command } }, invalidatesTags: (_, __, { id }) => [{ type: HOST, id }], + async onQueryStarted(params, { dispatch, queryFulfilled }) { + try { + const patchHost = dispatch( + hostApi.util.updateQueryData( + 'getHost', + { id: params.id }, + updateTemplateOnResource(params) + ) + ) + + const patchHosts = dispatch( + hostApi.util.updateQueryData( + 'getHosts', + undefined, + updateTemplateOnResource(params) + ) + ) + + queryFulfilled.catch(() => { + patchHost.undo() + patchHosts.undo() + }) + } catch {} + }, }), removeHost: builder.mutation({ /** @@ -211,16 +252,28 @@ const hostApi = oneApi.injectEndpoints({ return { params, command } }, invalidatesTags: (_, __, { id }) => [{ type: HOST, id }], - async onQueryStarted({ id, name }, { dispatch, queryFulfilled }) { + async onQueryStarted(params, { dispatch, queryFulfilled }) { try { - await queryFulfilled - - dispatch( - hostApi.util.updateQueryData('getHosts', undefined, (draft) => { - const host = draft.find(({ ID }) => +ID === +id) - host && (host.NAME = name) - }) + const patchHost = dispatch( + hostApi.util.updateQueryData( + 'getHost', + { id: params.id }, + updateNameOnResource(params) + ) ) + + const patchHosts = dispatch( + hostApi.util.updateQueryData( + 'getHosts', + undefined, + updateNameOnResource(params) + ) + ) + + queryFulfilled.catch(() => { + patchHost.undo() + patchHosts.undo() + }) } catch {} }, }), diff --git a/src/fireedge/src/client/features/OneApi/image.js b/src/fireedge/src/client/features/OneApi/image.js index 6ae16bcdc9..764a986253 100644 --- a/src/fireedge/src/client/features/OneApi/image.js +++ b/src/fireedge/src/client/features/OneApi/image.js @@ -76,12 +76,11 @@ const imageApi = oneApi.injectEndpoints({ }, transformResponse: (data) => data?.IMAGE ?? {}, providesTags: (_, __, { id }) => [{ type: IMAGE, id }], - onCacheEntryAdded: ({ id }, endpointProps) => - UpdateFromSocket({ - updateQueryData: (updateFn) => - imageApi.util.updateQueryData('getImages', undefined, updateFn), - resource: IMAGE.toLowerCase(), - })(id, endpointProps), + onCacheEntryAdded: UpdateFromSocket({ + updateQueryData: (updateFn) => + imageApi.util.updateQueryData('getImages', undefined, updateFn), + resource: 'IMAGE', + }), }), allocateImage: builder.mutation({ /** diff --git a/src/fireedge/src/client/features/OneApi/marketplaceApp.js b/src/fireedge/src/client/features/OneApi/marketplaceApp.js index 92034bf510..e6dc6341ad 100644 --- a/src/fireedge/src/client/features/OneApi/marketplaceApp.js +++ b/src/fireedge/src/client/features/OneApi/marketplaceApp.js @@ -24,8 +24,23 @@ import { ONE_RESOURCES, ONE_RESOURCES_POOL, } from 'client/features/OneApi' +import { + updateResourceOnPool, + removeResourceOnPool, + updateNameOnResource, + updateLockLevelOnResource, + removeLockLevelOnResource, + updatePermissionOnResource, + updateOwnershipOnResource, + updateTemplateOnResource, +} from 'client/features/OneApi/common' import { requestConfig } from 'client/utils' -import { FilterFlag, Permission, MarketplaceApp } from 'client/constants' +import { + LockLevel, + FilterFlag, + Permission, + MarketplaceApp, +} from 'client/constants' const { APP } = ONE_RESOURCES const { APP_POOL } = ONE_RESOURCES_POOL @@ -64,18 +79,41 @@ const marketAppApi = oneApi.injectEndpoints({ /** * Retrieves information for the marketplace app. * - * @param {string} id - Marketplace apps id + * @param {object} params - Request parameters + * @param {string} params.id - Marketplace apps id * @returns {MarketplaceApp} Get marketplace app identified by id * @throws Fails when response isn't code 200 */ - query: (id) => { + query: (params) => { const name = Actions.MARKETAPP_INFO const command = { name, ...Commands[name] } - return { params: { id }, command } + return { params, command } }, transformResponse: (data) => data?.MARKETPLACEAPP ?? {}, - providesTags: (_, __, id) => [{ type: APP, id }], + providesTags: (_, __, { id }) => [{ type: APP, id }], + async onQueryStarted({ id }, { dispatch, queryFulfilled }) { + try { + const { data: resourceFromQuery } = await queryFulfilled + + dispatch( + marketAppApi.util.updateQueryData( + 'getMarketplaceApps', + undefined, + updateResourceOnPool({ id, resourceFromQuery }) + ) + ) + } catch { + // if the query fails, we want to remove the resource from the pool + dispatch( + marketAppApi.util.updateQueryData( + 'getMarketplaceApps', + undefined, + removeResourceOnPool({ id }) + ) + ) + } + }, }), getDockerHubTags: builder.query({ /** @@ -110,7 +148,6 @@ const marketAppApi = oneApi.injectEndpoints({ return { params, command } }, - invalidatesTags: [APP_POOL], }), updateApp: builder.mutation({ /** @@ -133,6 +170,30 @@ const marketAppApi = oneApi.injectEndpoints({ return { params, command } }, invalidatesTags: (_, __, { id }) => [{ type: APP, id }], + async onQueryStarted(params, { dispatch, queryFulfilled }) { + try { + const patchApp = dispatch( + marketAppApi.util.updateQueryData( + 'getMarketplaceApp', + { id: params.id }, + updateTemplateOnResource(params) + ) + ) + + const patchApps = dispatch( + marketAppApi.util.updateQueryData( + 'getMarketplaceApps', + undefined, + updateTemplateOnResource(params) + ) + ) + + queryFulfilled.catch(() => { + patchApp.undo() + patchApps.undo() + }) + } catch {} + }, }), removeApp: builder.mutation({ /** @@ -208,6 +269,30 @@ const marketAppApi = oneApi.injectEndpoints({ return { params, command } }, invalidatesTags: (_, __, { id }) => [{ type: APP, id }], + async onQueryStarted(params, { dispatch, queryFulfilled }) { + try { + const patchApp = dispatch( + marketAppApi.util.updateQueryData( + 'getMarketplaceApp', + { id: params.id }, + updatePermissionOnResource(params) + ) + ) + + const patchApps = dispatch( + marketAppApi.util.updateQueryData( + 'getMarketplaceApps', + undefined, + updatePermissionOnResource(params) + ) + ) + + queryFulfilled.catch(() => { + patchApp.undo() + patchApps.undo() + }) + } catch {} + }, }), changeAppOwnership: builder.mutation({ /** @@ -216,8 +301,8 @@ const marketAppApi = oneApi.injectEndpoints({ * * @param {object} params - Request parameters * @param {string} params.id - Marketplace app id - * @param {string|'-1'} [params.userId] - User id - * @param {string|'-1'} [params.groupId] - Group id + * @param {number} params.user - The user id + * @param {number} params.group - The group id * @returns {number} Marketplace app id * @throws Fails when response isn't code 200 */ @@ -227,7 +312,31 @@ const marketAppApi = oneApi.injectEndpoints({ return { params, command } }, - invalidatesTags: (_, __, { id }) => [{ type: APP, id }, APP_POOL], + invalidatesTags: (_, __, { id }) => [{ type: APP, id }], + async onQueryStarted(params, { getState, dispatch, queryFulfilled }) { + try { + const patchApp = dispatch( + marketAppApi.util.updateQueryData( + 'getMarketplaceApp', + { id: params.id }, + updateOwnershipOnResource(getState(), params) + ) + ) + + const patchApps = dispatch( + marketAppApi.util.updateQueryData( + 'getMarketplaceApps', + undefined, + updateOwnershipOnResource(getState(), params) + ) + ) + + queryFulfilled.catch(() => { + patchApp.undo() + patchApps.undo() + }) + } catch {} + }, }), renameApp: builder.mutation({ /** @@ -245,19 +354,39 @@ const marketAppApi = oneApi.injectEndpoints({ return { params, command } }, - invalidatesTags: (_, __, { id }) => [{ type: APP, id }, APP_POOL], + invalidatesTags: (_, __, { id }) => [{ type: APP, id }], + async onQueryStarted(params, { dispatch, queryFulfilled }) { + try { + const patchApp = dispatch( + marketAppApi.util.updateQueryData( + 'getMarketplaceApp', + { id: params.id }, + updateNameOnResource(params) + ) + ) + + const patchApps = dispatch( + marketAppApi.util.updateQueryData( + 'getMarketplaceApps', + undefined, + updateNameOnResource(params) + ) + ) + + queryFulfilled.catch(() => { + patchApp.undo() + patchApps.undo() + }) + } catch {} + }, }), lockApp: builder.mutation({ /** * Locks a MarketPlaceApp. Lock certain actions depending on blocking level. - * - `USE` (1): locks Admin, Manage and Use actions. - * - `MANAGE` (2): locks Manage and Use actions. - * - `ADMIN` (3): locks only Admin actions. - * - `ALL` (4): locks all actions. * * @param {object} params - Request parameters * @param {string} params.id - Marketplace app id - * @param {'1'|'2'|'3'|'4'} params.lock - Lock level + * @param {LockLevel} params.lock - Lock level * @returns {number} Marketplace app id * @throws Fails when response isn't code 200 */ @@ -267,23 +396,72 @@ const marketAppApi = oneApi.injectEndpoints({ return { params, command } }, - invalidatesTags: (_, __, { id }) => [{ type: APP, id }, APP_POOL], + invalidatesTags: (_, __, { id }) => [{ type: APP, id }], + async onQueryStarted(params, { dispatch, queryFulfilled }) { + try { + const patchApp = dispatch( + marketAppApi.util.updateQueryData( + 'getMarketplaceApp', + { id: params.id }, + updateLockLevelOnResource(params) + ) + ) + + const patchApps = dispatch( + marketAppApi.util.updateQueryData( + 'getMarketplaceApps', + undefined, + updateLockLevelOnResource(params) + ) + ) + + queryFulfilled.catch(() => { + patchApp.undo() + patchApps.undo() + }) + } catch {} + }, }), unlockApp: builder.mutation({ /** * Unlocks a MarketPlaceApp. * - * @param {string} id - Marketplace app id + * @param {object} params - Request parameters + * @param {string} params.id - Marketplace app id * @returns {number} Marketplace app id * @throws Fails when response isn't code 200 */ - query: (id) => { + query: (params) => { const name = Actions.MARKETAPP_UNLOCK const command = { name, ...Commands[name] } - return { params: { id }, command } + return { params, command } + }, + invalidatesTags: (_, __, { id }) => [{ type: APP, id }], + async onQueryStarted(params, { dispatch, queryFulfilled }) { + try { + const patchApp = dispatch( + marketAppApi.util.updateQueryData( + 'getMarketplaceApp', + { id: params.id }, + removeLockLevelOnResource(params) + ) + ) + + const patchApps = dispatch( + marketAppApi.util.updateQueryData( + 'getMarketplaceApps', + undefined, + removeLockLevelOnResource(params) + ) + ) + + queryFulfilled.catch(() => { + patchApp.undo() + patchApps.undo() + }) + } catch {} }, - invalidatesTags: (_, __, id) => [{ type: APP, id }, APP_POOL], }), importApp: builder.mutation({ /** diff --git a/src/fireedge/src/client/features/OneApi/socket.js b/src/fireedge/src/client/features/OneApi/socket.js index a4e8ed5a36..7df0feb747 100644 --- a/src/fireedge/src/client/features/OneApi/socket.js +++ b/src/fireedge/src/client/features/OneApi/socket.js @@ -13,19 +13,24 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -import { ThunkDispatch } from 'redux-thunk' +import { ThunkDispatch, ThunkAction } from 'redux-thunk' import socketIO, { Socket } from 'socket.io-client' import { WEBSOCKET_URL, SOCKETS } from 'client/constants' /** - * @typedef {object} HookStateData - Event data from hook event STATE + * @typedef {'VM'|'HOST'|'IMAGE'|'VNET'} HookObjectName + * - Hook object name to update from socket + */ + +/** + * @typedef HookStateData - Event data from hook event STATE * @property {HookStateMessage} HOOK_MESSAGE - Hook message from OpenNebula API */ /** - * @typedef {object} HookStateMessage - Hook message from OpenNebula API + * @typedef HookStateMessage - Hook message from OpenNebula API * @property {'STATE'} HOOK_TYPE - Type of event API - * @property {('VM'|'HOST'|'IMAGE'|'NET')} HOOK_OBJECT - Type name of the resource + * @property {HookObjectName} HOOK_OBJECT - Type name of the resource * @property {string} STATE - The state that triggers the hook. * @property {string} [LCM_STATE] * - The LCM state that triggers the hook (Only for VM hooks) @@ -58,30 +63,22 @@ const createWebsocket = (path, query) => /** * @param {HookStateData} data - Event data from hook event STATE - * @returns {{name: ('vm'|'host'|'image'|'net'), value: object}} - * - Name and new value of resource + * @returns {object} - New value of resource from socket */ -const getResourceFromEventState = (data) => { - const { HOOK_OBJECT: name } = data?.HOOK_MESSAGE ?? {} +const getResourceValueFromEventState = (data) => { + const { HOOK_OBJECT: name, [name]: value } = data?.HOOK_MESSAGE ?? {} - const ensuredValue = - data?.HOOK_MESSAGE?.[name] ?? - data?.HOOK_MESSAGE?.VM ?? - data?.HOOK_MESSAGE?.HOST ?? - data?.HOOK_MESSAGE?.IMAGE ?? - data?.HOOK_MESSAGE?.VNET - - return { name: String(name).toLowerCase(), value: ensuredValue } + return value } /** * Creates a function to update the data from socket. * * @param {object} params - Parameters - * @param {Function(Function)} params.updateQueryData - Api - * @param {string} params.resource - Resource name + * @param {function(Function):ThunkAction} params.updateQueryData - Api + * @param {HookObjectName} params.resource - Resource name to subscribe * @returns {function( - * string, + * { id: string }, * { dispatch: ThunkDispatch } * ):Promise} Function to update data from socket */ @@ -94,14 +91,15 @@ const UpdateFromSocket = const { zone } = getState().general const { jwt: token } = getState().auth - const query = { token, zone, resource: resource.toLowerCase(), id } + const query = { token, zone, resource, id } const socket = createWebsocket(SOCKETS.HOOKS, query) try { await cacheDataLoaded const listener = ({ data } = {}) => { - const { value } = getResourceFromEventState(data) + const value = getResourceValueFromEventState(data) + if (!value) return dispatch( diff --git a/src/fireedge/src/client/features/OneApi/vm.js b/src/fireedge/src/client/features/OneApi/vm.js index 8d14e60237..3d850914b0 100644 --- a/src/fireedge/src/client/features/OneApi/vm.js +++ b/src/fireedge/src/client/features/OneApi/vm.js @@ -32,7 +32,7 @@ import { removeLockLevelOnResource, updatePermissionOnResource, updateOwnershipOnResource, - updateUserTemplateOnResource, + updateTemplateOnResource, } from 'client/features/OneApi/common' import { actions as guacamoleActions } from 'client/features/Guacamole/slice' import { UpdateFromSocket } from 'client/features/OneApi/socket' @@ -133,7 +133,7 @@ const vmApi = oneApi.injectEndpoints({ onCacheEntryAdded: UpdateFromSocket({ updateQueryData: (updateFn) => vmApi.util.updateQueryData('getVms', undefined, updateFn), - resource: VM.toLowerCase(), + resource: 'VM', }), }), getGuacamoleSession: builder.query({ @@ -641,6 +641,7 @@ const vmApi = oneApi.injectEndpoints({ changeVmOwnership: builder.mutation({ /** * Changes the ownership bits of a virtual machine. + * If set to `-1`, the user or group aren't changed. * * @param {object} params - Request parameters * @param {string} params.id - Virtual machine id @@ -666,7 +667,7 @@ const vmApi = oneApi.injectEndpoints({ ) ) - queryFulfilled.catch(patchVm.undo()) + queryFulfilled.catch(patchVm.undo) } catch {} }, }), @@ -812,7 +813,7 @@ const vmApi = oneApi.injectEndpoints({ vmApi.util.updateQueryData( 'getVm', { id: params.id }, - updateUserTemplateOnResource(params) + updateTemplateOnResource(params, 'USER_TEMPLATE') ) ) @@ -820,7 +821,7 @@ const vmApi = oneApi.injectEndpoints({ vmApi.util.updateQueryData( 'getVms', undefined, - updateUserTemplateOnResource(params) + updateTemplateOnResource(params, 'USER_TEMPLATE') ) ) diff --git a/src/fireedge/src/client/features/OneApi/vmTemplate.js b/src/fireedge/src/client/features/OneApi/vmTemplate.js index 7c1b5762c6..2e3bd6a229 100644 --- a/src/fireedge/src/client/features/OneApi/vmTemplate.js +++ b/src/fireedge/src/client/features/OneApi/vmTemplate.js @@ -28,7 +28,7 @@ import { removeLockLevelOnResource, updatePermissionOnResource, updateOwnershipOnResource, - updateUserTemplateOnResource, + updateTemplateOnResource, } from 'client/features/OneApi/common' import { LockLevel, FilterFlag, Permission, VmTemplate } from 'client/constants' @@ -211,7 +211,7 @@ const vmTemplateApi = oneApi.injectEndpoints({ vmTemplateApi.util.updateQueryData( 'getTemplate', { id: params.id }, - updateUserTemplateOnResource(params, 'TEMPLATE') + updateTemplateOnResource(params) ) ) @@ -219,7 +219,7 @@ const vmTemplateApi = oneApi.injectEndpoints({ vmTemplateApi.util.updateQueryData( 'getTemplates', undefined, - updateUserTemplateOnResource(params, 'TEMPLATE') + updateTemplateOnResource(params) ) ) @@ -289,8 +289,8 @@ const vmTemplateApi = oneApi.injectEndpoints({ * * @param {object} params - Request parameters * @param {string|number} params.id - VM Template id - * @param {number|'-1'} params.user - The user id - * @param {number|'-1'} params.group - The group id + * @param {number} params.user - The user id + * @param {number} params.group - The group id * @returns {number} VM Template id * @throws Fails when response isn't code 200 */