From 669e3c07e3faf1932b0d3b11d0664ca9dd080256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anna=20V=C3=ADtov=C3=A1?= Date: Thu, 4 Apr 2024 14:39:44 +0200 Subject: [PATCH] feat(HMS-3687): Add blueprints exporting --- api/config/imageBuilder.ts | 2 +- .../Blueprints/BlueprintActionsMenu.tsx | 37 ++++++++++++++++++- src/store/imageBuilderApi.ts | 11 ++++++ 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/api/config/imageBuilder.ts b/api/config/imageBuilder.ts index 1f430c8a..34fb2f15 100644 --- a/api/config/imageBuilder.ts +++ b/api/config/imageBuilder.ts @@ -6,7 +6,7 @@ const config: ConfigFile = { apiImport: 'emptyImageBuilderApi', outputFile: '../../src/store/imageBuilderApi.ts', exportName: 'imageBuilderApi', - hooks: true, + hooks: { queries: true, lazyQueries: true, mutations: true }, filterEndpoints: [ 'cloneCompose', 'composeImage', diff --git a/src/Components/Blueprints/BlueprintActionsMenu.tsx b/src/Components/Blueprints/BlueprintActionsMenu.tsx index d4e64bce..ea9dbed4 100644 --- a/src/Components/Blueprints/BlueprintActionsMenu.tsx +++ b/src/Components/Blueprints/BlueprintActionsMenu.tsx @@ -13,7 +13,12 @@ import { useNavigate } from 'react-router-dom'; import { selectSelectedBlueprintId } from '../../store/BlueprintSlice'; import { useAppSelector } from '../../store/hooks'; +import { + BlueprintResponse, + useLazyGetBlueprintQuery, +} from '../../store/imageBuilderApi'; import { resolveRelPath } from '../../Utilities/path'; +import BetaLabel from '../sharedComponents/BetaLabel'; interface BlueprintActionsMenuProps { setShowDeleteModal: React.Dispatch>; @@ -27,10 +32,21 @@ export const BlueprintActionsMenu: React.FunctionComponent< const onSelect = () => { setShowBlueprintActionsMenu(!showBlueprintActionsMenu); }; - const selectedBlueprintId = useAppSelector(selectSelectedBlueprintId); const navigate = useNavigate(); const importExportFlag = useFlag('image-builder.import.enabled'); + const [trigger] = useLazyGetBlueprintQuery(); + const selectedBlueprintId = useAppSelector(selectSelectedBlueprintId); + if (selectedBlueprintId === undefined) { + return null; + } + const handleClick = () => { + trigger({ id: selectedBlueprintId }) + .unwrap() + .then((response: BlueprintResponse) => { + handleExportBlueprint(response.name, response); + }); + }; return ( {importExportFlag && ( - Download blueprint (.json) + + Download blueprint (.json) + )} setShowDeleteModal(true)}> Delete blueprint @@ -72,3 +90,18 @@ export const BlueprintActionsMenu: React.FunctionComponent< ); }; + +async function handleExportBlueprint( + blueprintName: string, + blueprint: BlueprintResponse +) { + const jsonData = JSON.stringify(blueprint, null, 2); + const blob = new Blob([jsonData], { type: 'application/json' }); + + const url = URL.createObjectURL(blob); + const link = document.createElement('a'); + link.href = url; + link.download = blueprintName.replace(/\s/g, '_').toLowerCase() + '.json'; + link.click(); + URL.revokeObjectURL(url); +} diff --git a/src/store/imageBuilderApi.ts b/src/store/imageBuilderApi.ts index 0d261574..698d3d91 100644 --- a/src/store/imageBuilderApi.ts +++ b/src/store/imageBuilderApi.ts @@ -806,20 +806,31 @@ export type BlueprintResponse = { }; export const { useGetArchitecturesQuery, + useLazyGetArchitecturesQuery, useGetComposesQuery, + useLazyGetComposesQuery, useGetComposeStatusQuery, + useLazyGetComposeStatusQuery, useCloneComposeMutation, useGetComposeClonesQuery, + useLazyGetComposeClonesQuery, useGetCloneStatusQuery, + useLazyGetCloneStatusQuery, useComposeImageMutation, useGetPackagesQuery, + useLazyGetPackagesQuery, useGetOscapProfilesQuery, + useLazyGetOscapProfilesQuery, useGetOscapCustomizationsQuery, + useLazyGetOscapCustomizationsQuery, useGetBlueprintsQuery, + useLazyGetBlueprintsQuery, useCreateBlueprintMutation, useUpdateBlueprintMutation, useGetBlueprintQuery, + useLazyGetBlueprintQuery, useDeleteBlueprintMutation, useComposeBlueprintMutation, useGetBlueprintComposesQuery, + useLazyGetBlueprintComposesQuery, } = injectedRtkApi;