deps: migrate fec/notifications
The frontend component library decoupled notifications from redux.
Dispatching notifications via the notifications middleware was replaced
by a new `useAddNotifications` hook.
We mostly used the notifications middleware outside of React Components
in our `enhancedImageBuilderApi` store for mutation events. I created a
wrapper around the RTK hooks that uses the `useAddNotification` hook
and created a directory for the new hooks.
In other places, where we were using the notification dispatcher inside
React components, I replaced the call with the new hook.
[1] b1d4973144/packages/notifications/doc/migration.md
bump @redhat-cloud-services/frontend-components-notifications
---
updated-dependencies:
- dependency-name: "@redhat-cloud-services/frontend-components-notifications"
dependency-version: 6.0.2
dependency-type: direct:production
update-type: version-update:semver-major
...
Co-authored-by: dependabot[bot] <support@github.com>
Assisted-by: cursor ide for generalizing the `useMutationWithNotification`
hook.
This commit is contained in:
parent
77e0f5d6bf
commit
e8d46dd716
32 changed files with 412 additions and 473 deletions
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useEffect } from 'react';
|
||||
|
||||
import { useChrome } from '@redhat-cloud-services/frontend-components/useChrome';
|
||||
import NotificationsPortal from '@redhat-cloud-services/frontend-components-notifications/NotificationPortal';
|
||||
import NotificationsProvider from '@redhat-cloud-services/frontend-components-notifications/NotificationsProvider';
|
||||
import '@patternfly/patternfly/patternfly-addons.css';
|
||||
|
||||
import { Router } from './Router';
|
||||
|
|
@ -26,8 +26,9 @@ const App = () => {
|
|||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<NotificationsPortal />
|
||||
<Router />
|
||||
<NotificationsProvider>
|
||||
<Router />
|
||||
</NotificationsProvider>
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import React from 'react';
|
|||
|
||||
import 'cockpit-dark-theme';
|
||||
import { Page, PageSection } from '@patternfly/react-core';
|
||||
import NotificationsPortal from '@redhat-cloud-services/frontend-components-notifications/NotificationPortal';
|
||||
import NotificationsProvider from '@redhat-cloud-services/frontend-components-notifications/NotificationsProvider';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import { Provider } from 'react-redux';
|
||||
import { HashRouter } from 'react-router-dom';
|
||||
|
|
@ -31,10 +31,11 @@ const Application = () => {
|
|||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<NotificationsPortal />
|
||||
<HashRouter>
|
||||
<Router />
|
||||
</HashRouter>
|
||||
<NotificationsProvider>
|
||||
<HashRouter>
|
||||
<Router />
|
||||
</HashRouter>
|
||||
</NotificationsProvider>
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -10,15 +10,13 @@ import {
|
|||
Spinner,
|
||||
} from '@patternfly/react-core';
|
||||
|
||||
import { useDeleteBPWithNotification as useDeleteBlueprintMutation } from '../../Hooks';
|
||||
import {
|
||||
selectSelectedBlueprintId,
|
||||
setBlueprintId,
|
||||
} from '../../store/BlueprintSlice';
|
||||
import { useAppDispatch, useAppSelector } from '../../store/hooks';
|
||||
import {
|
||||
BlueprintItem,
|
||||
useDeleteBlueprintMutation,
|
||||
} from '../../store/imageBuilderApi';
|
||||
import { BlueprintItem } from '../../store/imageBuilderApi';
|
||||
|
||||
type blueprintProps = {
|
||||
blueprint: BlueprintItem;
|
||||
|
|
@ -28,7 +26,7 @@ const BlueprintCard = ({ blueprint }: blueprintProps) => {
|
|||
const selectedBlueprintId = useAppSelector(selectSelectedBlueprintId);
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const [, { isLoading }] = useDeleteBlueprintMutation({
|
||||
const { isLoading } = useDeleteBlueprintMutation({
|
||||
fixedCacheKey: 'delete-blueprint',
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -16,17 +16,14 @@ import {
|
|||
} from '@patternfly/react-core';
|
||||
import { MenuToggleElement } from '@patternfly/react-core/dist/esm/components/MenuToggle/MenuToggle';
|
||||
import useChrome from '@redhat-cloud-services/frontend-components/useChrome';
|
||||
import { addNotification } from '@redhat-cloud-services/frontend-components-notifications/redux';
|
||||
import { ChromeUser } from '@redhat-cloud-services/types';
|
||||
import { skipToken } from '@reduxjs/toolkit/query';
|
||||
|
||||
import { AMPLITUDE_MODULE_NAME, targetOptions } from '../../constants';
|
||||
import {
|
||||
useGetBlueprintQuery,
|
||||
useComposeBlueprintMutation,
|
||||
} from '../../store/backendApi';
|
||||
import { useComposeBPWithNotification as useComposeBlueprintMutation } from '../../Hooks';
|
||||
import { useGetBlueprintQuery } from '../../store/backendApi';
|
||||
import { selectSelectedBlueprintId } from '../../store/BlueprintSlice';
|
||||
import { useAppDispatch, useAppSelector } from '../../store/hooks';
|
||||
import { useAppSelector } from '../../store/hooks';
|
||||
import { ImageTypes } from '../../store/imageBuilderApi';
|
||||
|
||||
type BuildImagesButtonPropTypes = {
|
||||
|
|
@ -37,9 +34,8 @@ type BuildImagesButtonPropTypes = {
|
|||
export const BuildImagesButton = ({ children }: BuildImagesButtonPropTypes) => {
|
||||
const selectedBlueprintId = useAppSelector(selectSelectedBlueprintId);
|
||||
const [deselectedTargets, setDeselectedTargets] = useState<ImageTypes[]>([]);
|
||||
const [buildBlueprint, { isLoading: imageBuildLoading }] =
|
||||
const { trigger: buildBlueprint, isLoading: imageBuildLoading } =
|
||||
useComposeBlueprintMutation();
|
||||
const dispatch = useAppDispatch();
|
||||
const { analytics, auth } = useChrome();
|
||||
|
||||
const [userData, setUserData] = useState<ChromeUser | void>(undefined);
|
||||
|
|
@ -53,29 +49,19 @@ export const BuildImagesButton = ({ children }: BuildImagesButtonPropTypes) => {
|
|||
|
||||
const onBuildHandler = async () => {
|
||||
if (selectedBlueprintId) {
|
||||
try {
|
||||
await buildBlueprint({
|
||||
id: selectedBlueprintId,
|
||||
body: {
|
||||
image_types: blueprintImageType?.filter(
|
||||
(target) => !deselectedTargets.includes(target)
|
||||
),
|
||||
},
|
||||
});
|
||||
analytics.track(`${AMPLITUDE_MODULE_NAME} - Image Requested`, {
|
||||
module: AMPLITUDE_MODULE_NAME,
|
||||
trigger: 'synchronize images',
|
||||
account_id: userData?.identity.internal?.account_id || 'Not found',
|
||||
});
|
||||
} catch (imageBuildError) {
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'warning',
|
||||
title: 'No blueprint was build',
|
||||
description: imageBuildError?.data?.error?.message,
|
||||
})
|
||||
);
|
||||
}
|
||||
await buildBlueprint({
|
||||
id: selectedBlueprintId,
|
||||
body: {
|
||||
image_types: blueprintImageType?.filter(
|
||||
(target) => !deselectedTargets.includes(target)
|
||||
),
|
||||
},
|
||||
});
|
||||
analytics.track(`${AMPLITUDE_MODULE_NAME} - Image Requested`, {
|
||||
module: AMPLITUDE_MODULE_NAME,
|
||||
trigger: 'synchronize images',
|
||||
account_id: userData?.identity.internal?.account_id || 'Not found',
|
||||
});
|
||||
}
|
||||
};
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
|
@ -180,7 +166,7 @@ export const BuildImagesButtonEmptyState = ({
|
|||
children,
|
||||
}: BuildImagesButtonEmptyStatePropTypes) => {
|
||||
const selectedBlueprintId = useAppSelector(selectSelectedBlueprintId);
|
||||
const [buildBlueprint, { isLoading: imageBuildLoading }] =
|
||||
const { trigger: buildBlueprint, isLoading: imageBuildLoading } =
|
||||
useComposeBlueprintMutation();
|
||||
const onBuildHandler = async () => {
|
||||
if (selectedBlueprintId) {
|
||||
|
|
|
|||
|
|
@ -10,11 +10,8 @@ import {
|
|||
PAGINATION_LIMIT,
|
||||
PAGINATION_OFFSET,
|
||||
} from '../../constants';
|
||||
import {
|
||||
backendApi,
|
||||
useDeleteBlueprintMutation,
|
||||
useGetBlueprintsQuery,
|
||||
} from '../../store/backendApi';
|
||||
import { useDeleteBPWithNotification as useDeleteBlueprintMutation } from '../../Hooks';
|
||||
import { backendApi, useGetBlueprintsQuery } from '../../store/backendApi';
|
||||
import {
|
||||
selectBlueprintSearchInput,
|
||||
selectLimit,
|
||||
|
|
@ -65,7 +62,7 @@ export const DeleteBlueprintModal: React.FunctionComponent<
|
|||
)?.name,
|
||||
}),
|
||||
});
|
||||
const [deleteBlueprint] = useDeleteBlueprintMutation({
|
||||
const { trigger: deleteBlueprint } = useDeleteBlueprintMutation({
|
||||
fixedCacheKey: 'delete-blueprint',
|
||||
});
|
||||
const handleDelete = async () => {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import {
|
|||
import { Modal, ModalVariant } from '@patternfly/react-core/deprecated';
|
||||
import { DropEvent } from '@patternfly/react-core/dist/esm/helpers';
|
||||
import { HelpIcon } from '@patternfly/react-icons';
|
||||
import { addNotification } from '@redhat-cloud-services/frontend-components-notifications/redux';
|
||||
import { useAddNotification } from '@redhat-cloud-services/frontend-components-notifications/hooks';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { mapOnPremToHosted } from './helpers/onPremToHostedBlueprintMapper';
|
||||
|
|
@ -26,7 +26,6 @@ import {
|
|||
ApiRepositoryRequest,
|
||||
useBulkImportRepositoriesMutation,
|
||||
} from '../../store/contentSourcesApi';
|
||||
import { useAppDispatch } from '../../store/hooks';
|
||||
import {
|
||||
BlueprintExportResponse,
|
||||
BlueprintItem,
|
||||
|
|
@ -64,7 +63,7 @@ export const ImportBlueprintModal: React.FunctionComponent<
|
|||
const [isRejected, setIsRejected] = React.useState(false);
|
||||
const [isOnPrem, setIsOnPrem] = React.useState(false);
|
||||
const [isCheckedImportRepos, setIsCheckedImportRepos] = React.useState(true);
|
||||
const dispatch = useAppDispatch();
|
||||
const addNotification = useAddNotification();
|
||||
const [importRepositories] = useBulkImportRepositoriesMutation();
|
||||
|
||||
const handleFileInputChange = (
|
||||
|
|
@ -103,33 +102,27 @@ export const ImportBlueprintModal: React.FunctionComponent<
|
|||
importedRepositoryNames.push(repository.url);
|
||||
return;
|
||||
}
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'warning',
|
||||
title: 'Failed to import custom repositories',
|
||||
description: JSON.stringify(repository.warnings),
|
||||
})
|
||||
);
|
||||
addNotification({
|
||||
variant: 'warning',
|
||||
title: 'Failed to import custom repositories',
|
||||
description: JSON.stringify(repository.warnings),
|
||||
});
|
||||
});
|
||||
|
||||
if (importedRepositoryNames.length !== 0) {
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'info',
|
||||
title: 'Successfully imported custom repositories',
|
||||
description: importedRepositoryNames.join(', '),
|
||||
})
|
||||
);
|
||||
addNotification({
|
||||
variant: 'info',
|
||||
title: 'Successfully imported custom repositories',
|
||||
description: importedRepositoryNames.join(', '),
|
||||
});
|
||||
}
|
||||
return newCustomRepos;
|
||||
}
|
||||
} catch {
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'danger',
|
||||
title: 'Custom repositories import failed',
|
||||
})
|
||||
);
|
||||
addNotification({
|
||||
variant: 'danger',
|
||||
title: 'Custom repositories import failed',
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -197,13 +190,11 @@ export const ImportBlueprintModal: React.FunctionComponent<
|
|||
}
|
||||
} catch (error) {
|
||||
setIsInvalidFormat(true);
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'warning',
|
||||
title: 'File is not a valid blueprint',
|
||||
description: error?.data?.error?.message,
|
||||
})
|
||||
);
|
||||
addNotification({
|
||||
variant: 'warning',
|
||||
title: 'File is not a valid blueprint',
|
||||
description: error?.data?.error?.message,
|
||||
});
|
||||
}
|
||||
};
|
||||
parseAndImport();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useEffect } from 'react';
|
||||
|
||||
import { addNotification } from '@redhat-cloud-services/frontend-components-notifications/redux';
|
||||
import { useAddNotification } from '@redhat-cloud-services/frontend-components-notifications/hooks';
|
||||
import { useLocation, useNavigate } from 'react-router-dom';
|
||||
|
||||
import CreateImageWizard from './CreateImageWizard';
|
||||
|
|
@ -13,6 +13,7 @@ const ImportImageWizard = () => {
|
|||
const dispatch = useAppDispatch();
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const addNotification = useAddNotification();
|
||||
const locationState = location.state as { blueprint?: wizardState };
|
||||
const blueprint = locationState?.blueprint;
|
||||
useEffect(() => {
|
||||
|
|
@ -20,12 +21,10 @@ const ImportImageWizard = () => {
|
|||
dispatch(loadWizardState(blueprint));
|
||||
} else {
|
||||
navigate(resolveRelPath(''));
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'warning',
|
||||
title: 'No blueprint was imported',
|
||||
})
|
||||
);
|
||||
addNotification({
|
||||
variant: 'warning',
|
||||
title: 'No blueprint was imported',
|
||||
});
|
||||
}
|
||||
}, [blueprint, dispatch]);
|
||||
return <CreateImageWizard />;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import {
|
|||
TextInputGroup,
|
||||
TextInputGroupMain,
|
||||
} from '@patternfly/react-core';
|
||||
import { addNotification } from '@redhat-cloud-services/frontend-components-notifications/redux';
|
||||
import { useAddNotification } from '@redhat-cloud-services/frontend-components-notifications/hooks';
|
||||
|
||||
import ManageKeysButton from './ManageKeysButton';
|
||||
import PopoverActivation from './PopoverActivation';
|
||||
|
|
@ -37,6 +37,7 @@ import { generateRandomId } from '../../../utilities/generateRandomId';
|
|||
|
||||
const ActivationKeysList = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const addNotification = useAddNotification();
|
||||
|
||||
const activationKey = useAppSelector(selectActivationKey);
|
||||
const registrationType = useAppSelector(selectRegistrationType);
|
||||
|
|
@ -138,13 +139,11 @@ const ActivationKeysList = () => {
|
|||
);
|
||||
dispatch(changeActivationKey(defaultActivationKeyName));
|
||||
} catch (error) {
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'danger',
|
||||
title: 'Error creating activation key',
|
||||
description: error?.data?.error?.message,
|
||||
})
|
||||
);
|
||||
addNotification({
|
||||
variant: 'danger',
|
||||
title: 'Error creating activation key',
|
||||
description: error?.data?.error?.message,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -14,12 +14,15 @@ import useChrome from '@redhat-cloud-services/frontend-components/useChrome';
|
|||
import { ChromeUser } from '@redhat-cloud-services/types';
|
||||
|
||||
import { AMPLITUDE_MODULE_NAME } from '../../../../../constants';
|
||||
import { useCreateBlueprintMutation } from '../../../../../store/backendApi';
|
||||
import {
|
||||
useComposeBPWithNotification as useComposeBlueprintMutation,
|
||||
useCreateBPWithNotification as useCreateBlueprintMutation,
|
||||
} from '../../../../../Hooks';
|
||||
import { setBlueprintId } from '../../../../../store/BlueprintSlice';
|
||||
import { useAppDispatch, useAppSelector } from '../../../../../store/hooks';
|
||||
import {
|
||||
CreateBlueprintRequest,
|
||||
useComposeBlueprintMutation,
|
||||
CreateBlueprintResponse,
|
||||
} from '../../../../../store/imageBuilderApi';
|
||||
import { selectPackages } from '../../../../../store/wizardSlice';
|
||||
import { createAnalytics } from '../../../../../Utilities/analytics';
|
||||
|
|
@ -46,8 +49,8 @@ export const CreateSaveAndBuildBtn = ({
|
|||
}, [auth]);
|
||||
const packages = useAppSelector(selectPackages);
|
||||
|
||||
const [buildBlueprint] = useComposeBlueprintMutation();
|
||||
const [createBlueprint] = useCreateBlueprintMutation({
|
||||
const { trigger: buildBlueprint } = useComposeBlueprintMutation();
|
||||
const { trigger: createBlueprint } = useCreateBlueprintMutation({
|
||||
fixedCacheKey: 'createBlueprintKey',
|
||||
});
|
||||
const dispatch = useAppDispatch();
|
||||
|
|
@ -70,13 +73,11 @@ export const CreateSaveAndBuildBtn = ({
|
|||
),
|
||||
});
|
||||
}
|
||||
const blueprint =
|
||||
requestBody &&
|
||||
(await createBlueprint({
|
||||
if (requestBody) {
|
||||
const blueprint = (await createBlueprint({
|
||||
createBlueprintRequest: requestBody,
|
||||
}).unwrap()); // unwrap - access the success payload immediately after a mutation
|
||||
})) as CreateBlueprintResponse;
|
||||
|
||||
if (blueprint) {
|
||||
buildBlueprint({ id: blueprint.id, body: {} });
|
||||
dispatch(setBlueprintId(blueprint.id));
|
||||
}
|
||||
|
|
@ -107,7 +108,7 @@ export const CreateSaveButton = ({
|
|||
}, [auth]);
|
||||
const packages = useAppSelector(selectPackages);
|
||||
|
||||
const [createBlueprint, { isLoading }] = useCreateBlueprintMutation({
|
||||
const { trigger: createBlueprint, isLoading } = useCreateBlueprintMutation({
|
||||
fixedCacheKey: 'createBlueprintKey',
|
||||
});
|
||||
const dispatch = useAppDispatch();
|
||||
|
|
@ -166,15 +167,11 @@ export const CreateSaveButton = ({
|
|||
account_id: userData?.identity.internal?.account_id || 'Not found',
|
||||
});
|
||||
}
|
||||
|
||||
const blueprint =
|
||||
requestBody &&
|
||||
(await createBlueprint({
|
||||
if (requestBody) {
|
||||
const blueprint = (await createBlueprint({
|
||||
createBlueprintRequest: requestBody,
|
||||
}).unwrap());
|
||||
|
||||
if (blueprint) {
|
||||
dispatch(setBlueprintId(blueprint?.id));
|
||||
})) as CreateBlueprintResponse;
|
||||
dispatch(setBlueprintId(blueprint.id));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -12,12 +12,12 @@ import useChrome from '@redhat-cloud-services/frontend-components/useChrome';
|
|||
import { ChromeUser } from '@redhat-cloud-services/types';
|
||||
|
||||
import { AMPLITUDE_MODULE_NAME } from '../../../../../constants';
|
||||
import { useUpdateBlueprintMutation } from '../../../../../store/backendApi';
|
||||
import { useAppSelector } from '../../../../../store/hooks';
|
||||
import {
|
||||
CreateBlueprintRequest,
|
||||
useComposeBlueprintMutation,
|
||||
} from '../../../../../store/imageBuilderApi';
|
||||
useComposeBPWithNotification as useComposeBlueprintMutation,
|
||||
useUpdateBPWithNotification as useUpdateBlueprintMutation,
|
||||
} from '../../../../../Hooks';
|
||||
import { useAppSelector } from '../../../../../store/hooks';
|
||||
import { CreateBlueprintRequest } from '../../../../../store/imageBuilderApi';
|
||||
import { selectPackages } from '../../../../../store/wizardSlice';
|
||||
import { createAnalytics } from '../../../../../Utilities/analytics';
|
||||
|
||||
|
|
@ -43,10 +43,10 @@ export const EditSaveAndBuildBtn = ({
|
|||
setUserData(data);
|
||||
})();
|
||||
}, [auth]);
|
||||
const [buildBlueprint] = useComposeBlueprintMutation();
|
||||
const { trigger: buildBlueprint } = useComposeBlueprintMutation();
|
||||
const packages = useAppSelector(selectPackages);
|
||||
|
||||
const [updateBlueprint] = useUpdateBlueprintMutation({
|
||||
const { trigger: updateBlueprint } = useUpdateBlueprintMutation({
|
||||
fixedCacheKey: 'updateBlueprintKey',
|
||||
});
|
||||
|
||||
|
|
@ -104,7 +104,7 @@ export const EditSaveButton = ({
|
|||
}, [auth]);
|
||||
const packages = useAppSelector(selectPackages);
|
||||
|
||||
const [updateBlueprint, { isLoading }] = useUpdateBlueprintMutation({
|
||||
const { trigger: updateBlueprint, isLoading } = useUpdateBlueprintMutation({
|
||||
fixedCacheKey: 'updateBlueprintKey',
|
||||
});
|
||||
const onSave = async () => {
|
||||
|
|
|
|||
|
|
@ -17,20 +17,20 @@ import { CreateSaveAndBuildBtn, CreateSaveButton } from './CreateDropdown';
|
|||
import { EditSaveAndBuildBtn, EditSaveButton } from './EditDropdown';
|
||||
|
||||
import {
|
||||
useCreateBlueprintMutation,
|
||||
useUpdateBlueprintMutation,
|
||||
} from '../../../../../store/backendApi';
|
||||
useCreateBPWithNotification as useCreateBlueprintMutation,
|
||||
useUpdateBPWithNotification as useUpdateBlueprintMutation,
|
||||
} from '../../../../../Hooks';
|
||||
import { resolveRelPath } from '../../../../../Utilities/path';
|
||||
import { mapRequestFromState } from '../../../utilities/requestMapper';
|
||||
import { useIsBlueprintValid } from '../../../utilities/useValidation';
|
||||
|
||||
const ReviewWizardFooter = () => {
|
||||
const { goToPrevStep, close } = useWizardContext();
|
||||
const [, { isSuccess: isCreateSuccess, reset: resetCreate }] =
|
||||
const { isSuccess: isCreateSuccess, reset: resetCreate } =
|
||||
useCreateBlueprintMutation({ fixedCacheKey: 'createBlueprintKey' });
|
||||
|
||||
// initialize the server store with the data from RTK query
|
||||
const [, { isSuccess: isUpdateSuccess, reset: resetUpdate }] =
|
||||
const { isSuccess: isUpdateSuccess, reset: resetUpdate } =
|
||||
useUpdateBlueprintMutation({ fixedCacheKey: 'updateBlueprintKey' });
|
||||
const { auth } = useChrome();
|
||||
const { composeId } = useParams();
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import {
|
|||
Title,
|
||||
} from '@patternfly/react-core';
|
||||
|
||||
import { useFixupBPWithNotification as useFixupBlueprintMutation } from '../../Hooks';
|
||||
import {
|
||||
useGetBlueprintsQuery,
|
||||
useGetBlueprintQuery,
|
||||
|
|
@ -28,7 +29,6 @@ import {
|
|||
useGetBlueprintComposesQuery,
|
||||
Distributions,
|
||||
GetBlueprintComposesApiArg,
|
||||
useFixupBlueprintMutation,
|
||||
} from '../../store/imageBuilderApi';
|
||||
import { BlueprintActionsMenu } from '../Blueprints/BlueprintActionsMenu';
|
||||
import BlueprintDiffModal from '../Blueprints/BlueprintDiffModal';
|
||||
|
|
@ -128,7 +128,7 @@ const ImagesTableToolbar: React.FC<imagesTableToolbarProps> = ({
|
|||
{ skip: !selectedBlueprintId }
|
||||
);
|
||||
|
||||
const [fixupBlueprint] = useFixupBlueprintMutation();
|
||||
const { trigger: fixupBlueprint } = useFixupBlueprintMutation();
|
||||
const hasErrors =
|
||||
blueprintDetails?.lint?.errors && blueprintDetails?.lint?.errors.length > 0;
|
||||
const [isLintExp, setIsLintExp] = React.useState(true);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import './LandingPage.scss';
|
|||
import { NewAlert } from './NewAlert';
|
||||
|
||||
import { MANAGING_WITH_DNF_URL, OSTREE_URL } from '../../constants';
|
||||
import { manageEdgeImagesUrlName } from '../../Utilities/edge';
|
||||
import { manageEdgeImagesUrlName } from '../../Hooks/Edge/useGetNotificationProp';
|
||||
import { resolveRelPath } from '../../Utilities/path';
|
||||
import { useFlag } from '../../Utilities/useGetEnvironment';
|
||||
import BlueprintsSidebar from '../Blueprints/BlueprintsSideBar';
|
||||
|
|
|
|||
|
|
@ -29,9 +29,9 @@ import {
|
|||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { AWS_REGIONS } from '../../constants';
|
||||
import { useCloneComposeWithNotification as useCloneComposeMutation } from '../../Hooks';
|
||||
import {
|
||||
ComposeStatus,
|
||||
useCloneComposeMutation,
|
||||
useGetComposeStatusQuery,
|
||||
} from '../../store/imageBuilderApi';
|
||||
import { resolveRelPath } from '../../Utilities/path';
|
||||
|
|
@ -130,7 +130,7 @@ const RegionsSelect = ({ composeId, handleClose }: RegionsSelectPropTypes) => {
|
|||
}
|
||||
};
|
||||
|
||||
const [cloneCompose] = useCloneComposeMutation();
|
||||
const { trigger: cloneCompose } = useCloneComposeMutation();
|
||||
|
||||
const { data: composeStatus, isSuccess } = useGetComposeStatusQuery({
|
||||
composeId,
|
||||
|
|
|
|||
|
|
@ -3,19 +3,17 @@ import React from 'react';
|
|||
import AsyncComponent from '@redhat-cloud-services/frontend-components/AsyncComponent';
|
||||
import ErrorState from '@redhat-cloud-services/frontend-components/ErrorState';
|
||||
import Unavailable from '@redhat-cloud-services/frontend-components/Unavailable';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { useNavigate, useLocation, useParams } from 'react-router-dom';
|
||||
|
||||
import {
|
||||
getNotificationProp,
|
||||
useGetNotificationProp,
|
||||
manageEdgeImagesUrlName,
|
||||
} from '../../Utilities/edge';
|
||||
} from '../../Hooks/Edge/useGetNotificationProp';
|
||||
import { resolveRelPath } from '../../Utilities/path';
|
||||
import { useFlag } from '../../Utilities/useGetEnvironment';
|
||||
|
||||
const ImageDetail = () => {
|
||||
const dispatch = useDispatch();
|
||||
const notificationProp = getNotificationProp(dispatch);
|
||||
const notificationProp = useGetNotificationProp();
|
||||
// Feature flag for the federated modules
|
||||
const edgeParityFlag = useFlag('edgeParity.image-list');
|
||||
// Feature flag to access the 'local' images table list
|
||||
|
|
|
|||
|
|
@ -3,20 +3,18 @@ import React from 'react';
|
|||
import AsyncComponent from '@redhat-cloud-services/frontend-components/AsyncComponent';
|
||||
import ErrorState from '@redhat-cloud-services/frontend-components/ErrorState';
|
||||
import Unavailable from '@redhat-cloud-services/frontend-components/Unavailable';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { useNavigate, useLocation } from 'react-router-dom';
|
||||
|
||||
import { CREATING_IMAGES_WITH_IB_URL } from '../../constants';
|
||||
import {
|
||||
getNotificationProp,
|
||||
useGetNotificationProp,
|
||||
manageEdgeImagesUrlName,
|
||||
} from '../../Utilities/edge';
|
||||
} from '../../Hooks/Edge/useGetNotificationProp';
|
||||
import { resolveRelPath } from '../../Utilities/path';
|
||||
import { useFlag } from '../../Utilities/useGetEnvironment';
|
||||
|
||||
const ImagesTable = () => {
|
||||
const dispatch = useDispatch();
|
||||
const notificationProp = getNotificationProp(dispatch);
|
||||
const notificationProp = useGetNotificationProp();
|
||||
// Feature flag for the federated modules
|
||||
const edgeParityFlag = useFlag('edgeParity.image-list');
|
||||
// Feature flag to access the 'local' images table list
|
||||
|
|
|
|||
34
src/Hooks/Edge/useGetNotificationProp.ts
Normal file
34
src/Hooks/Edge/useGetNotificationProp.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import { useAddNotification } from '@redhat-cloud-services/frontend-components-notifications/hooks';
|
||||
|
||||
const manageEdgeImagesUrlName = 'manage-edge-images';
|
||||
|
||||
const useGetNotificationProp = () => {
|
||||
const addNotification = useAddNotification();
|
||||
return {
|
||||
hasInfo: (hasInfoMessage: Notification) => {
|
||||
addNotification({
|
||||
variant: 'info',
|
||||
...hasInfoMessage,
|
||||
});
|
||||
},
|
||||
hasSuccess: (hasSuccessMessage: Notification) => {
|
||||
addNotification({
|
||||
variant: 'success',
|
||||
...hasSuccessMessage,
|
||||
});
|
||||
},
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
err: (errMessage: any, err: any) => {
|
||||
addNotification({
|
||||
variant: 'danger',
|
||||
...errMessage,
|
||||
// Add error message from API, if present
|
||||
description: err?.Title
|
||||
? `${errMessage.description}: ${err.Title}`
|
||||
: errMessage.description,
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export { useGetNotificationProp, manageEdgeImagesUrlName };
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import { useMutationWithNotification } from './useMutationWithNotification';
|
||||
|
||||
import {
|
||||
CloneComposeApiArg,
|
||||
useCloneComposeMutation,
|
||||
} from '../../store/service/imageBuilderApi';
|
||||
|
||||
export const useCloneComposeWithNotification = () => {
|
||||
const { trigger: cloneCompose, ...rest } = useMutationWithNotification(
|
||||
useCloneComposeMutation,
|
||||
{
|
||||
messages: {
|
||||
success: ({ cloneRequest }: CloneComposeApiArg) =>
|
||||
`Your image is being shared to ${cloneRequest.region} region`,
|
||||
error: () => 'Your image could not be shared',
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
trigger: cloneCompose,
|
||||
...rest,
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
import { useMutationWithNotification } from './useMutationWithNotification';
|
||||
|
||||
import { useComposeBlueprintMutation } from '../../store/backendApi';
|
||||
|
||||
export const useComposeBPWithNotification = () => {
|
||||
const { trigger: composeBlueprint, ...rest } = useMutationWithNotification(
|
||||
useComposeBlueprintMutation,
|
||||
{
|
||||
messages: {
|
||||
success: () => 'Image is being built',
|
||||
error: () => 'Image could not be built',
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
trigger: composeBlueprint,
|
||||
...rest,
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import {
|
||||
HookOptions,
|
||||
useMutationWithNotification,
|
||||
} from './useMutationWithNotification';
|
||||
|
||||
import { useCreateBlueprintMutation } from '../../store/backendApi';
|
||||
|
||||
export const useCreateBPWithNotification = (options?: HookOptions) => {
|
||||
const { trigger: createBlueprint, ...rest } = useMutationWithNotification(
|
||||
useCreateBlueprintMutation,
|
||||
{
|
||||
options,
|
||||
messages: {
|
||||
success: () => 'Blueprint was created',
|
||||
error: () => 'Blueprint could not be created',
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
trigger: createBlueprint,
|
||||
...rest,
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import {
|
||||
HookOptions,
|
||||
useMutationWithNotification,
|
||||
} from './useMutationWithNotification';
|
||||
|
||||
import { useDeleteBlueprintMutation } from '../../store/backendApi';
|
||||
|
||||
export const useDeleteBPWithNotification = (options?: HookOptions) => {
|
||||
const { trigger: deleteBlueprint, ...rest } = useMutationWithNotification(
|
||||
useDeleteBlueprintMutation,
|
||||
{
|
||||
options,
|
||||
messages: {
|
||||
success: () => 'Blueprint was deleted',
|
||||
error: () => 'Blueprint could not be deleted',
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
trigger: deleteBlueprint,
|
||||
...rest,
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import {
|
||||
HookOptions,
|
||||
useMutationWithNotification,
|
||||
} from './useMutationWithNotification';
|
||||
|
||||
import { useFixupBlueprintMutation } from '../../store/imageBuilderApi';
|
||||
|
||||
export const useFixupBPWithNotification = (options?: HookOptions) => {
|
||||
const { trigger: fixupBlueprint, ...rest } = useMutationWithNotification(
|
||||
useFixupBlueprintMutation,
|
||||
{
|
||||
options,
|
||||
messages: {
|
||||
success: () => 'Blueprint was fixed',
|
||||
error: () => 'Blueprint could not be fixed',
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
trigger: fixupBlueprint,
|
||||
...rest,
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
import { useAddNotification } from '@redhat-cloud-services/frontend-components-notifications/hooks';
|
||||
import {
|
||||
BaseQueryFn,
|
||||
TypedMutationTrigger,
|
||||
} from '@reduxjs/toolkit/dist/query/react';
|
||||
|
||||
import { errorMessage } from '../../store/service/enhancedImageBuilderApi';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const getErrorDescription = (err: any) => {
|
||||
if (process.env.IS_ON_PREMISE) {
|
||||
// If details are present, assume it's coming from composer
|
||||
if (err.error?.body?.details) {
|
||||
return `${err.error.message}: ${err.error.body.details}`;
|
||||
}
|
||||
|
||||
return JSON.stringify(err);
|
||||
}
|
||||
|
||||
if (err.error?.status) {
|
||||
return `Status code ${err.error.status}: ${errorMessage(err)}`;
|
||||
}
|
||||
|
||||
return err as string;
|
||||
};
|
||||
|
||||
type NotificationMessages<TArgs> = {
|
||||
success: (args: TArgs) => string;
|
||||
error?: (args: TArgs, error: unknown) => string;
|
||||
};
|
||||
|
||||
export type HookOptions = {
|
||||
fixedCacheKey?: string | string;
|
||||
};
|
||||
|
||||
type MutationOptions<Arg> = {
|
||||
options?: HookOptions | undefined;
|
||||
messages: NotificationMessages<Arg>;
|
||||
};
|
||||
|
||||
// cursor ide was used to make this hook more generic
|
||||
// and re-usable. Specifically for extending the complicated
|
||||
// types to pass in other mutation hooks with using `any`
|
||||
export function useMutationWithNotification<
|
||||
Arg,
|
||||
Result,
|
||||
State extends {
|
||||
isLoading: boolean;
|
||||
isSuccess: boolean;
|
||||
isError: boolean;
|
||||
error?: unknown;
|
||||
reset: () => void;
|
||||
}
|
||||
>(
|
||||
mutationHook: (
|
||||
options?: HookOptions
|
||||
) => readonly [TypedMutationTrigger<Result, Arg, BaseQueryFn>, State],
|
||||
{ options, messages }: MutationOptions<Arg>
|
||||
) {
|
||||
const [trigger, state] = mutationHook(options);
|
||||
const addNotification = useAddNotification();
|
||||
|
||||
const handler = async (args: Arg): Promise<Result> => {
|
||||
try {
|
||||
const result = await trigger(args).unwrap();
|
||||
addNotification({
|
||||
variant: 'success',
|
||||
title: messages.success(args),
|
||||
});
|
||||
return result;
|
||||
} catch (err) {
|
||||
const description = getErrorDescription(err);
|
||||
if (messages.error) {
|
||||
addNotification({
|
||||
variant: 'danger',
|
||||
title: messages.error(args, err),
|
||||
description,
|
||||
});
|
||||
}
|
||||
return err;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
trigger: handler,
|
||||
...state,
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
import {
|
||||
HookOptions,
|
||||
useMutationWithNotification,
|
||||
} from './useMutationWithNotification';
|
||||
|
||||
import { useUpdateBlueprintMutation } from '../../store/backendApi';
|
||||
|
||||
export const useUpdateBPWithNotification = (options?: HookOptions) => {
|
||||
const { trigger: updateBlueprint, ...rest } = useMutationWithNotification(
|
||||
useUpdateBlueprintMutation,
|
||||
{
|
||||
options,
|
||||
messages: {
|
||||
success: () => 'Blueprint was updated',
|
||||
error: () => 'Blueprint could not be updated',
|
||||
},
|
||||
}
|
||||
);
|
||||
return {
|
||||
trigger: updateBlueprint,
|
||||
...rest,
|
||||
};
|
||||
};
|
||||
6
src/Hooks/index.tsx
Normal file
6
src/Hooks/index.tsx
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
export { useCreateBPWithNotification } from './MutationNotifications/useCreateBPWithNotification';
|
||||
export { useUpdateBPWithNotification } from './MutationNotifications/useUpdateBPWithNotification';
|
||||
export { useDeleteBPWithNotification } from './MutationNotifications/useDeleteBPWithNotification';
|
||||
export { useFixupBPWithNotification } from './MutationNotifications/useFixupBPWithNotification';
|
||||
export { useComposeBPWithNotification } from './MutationNotifications/useComposeBPWithNotification';
|
||||
export { useCloneComposeWithNotification } from './MutationNotifications/useCloneComposeWithNotification';
|
||||
|
|
@ -4,7 +4,7 @@ import { Route, Routes } from 'react-router-dom';
|
|||
|
||||
import EdgeImageDetail from './Components/edge/ImageDetails';
|
||||
import ShareImageModal from './Components/ShareImageModal/ShareImageModal';
|
||||
import { manageEdgeImagesUrlName } from './Utilities/edge';
|
||||
import { manageEdgeImagesUrlName } from './Hooks/Edge/useGetNotificationProp';
|
||||
import {
|
||||
useFlag,
|
||||
useFlagWithEphemDefault,
|
||||
|
|
|
|||
|
|
@ -1,40 +0,0 @@
|
|||
import { addNotification } from '@redhat-cloud-services/frontend-components-notifications/redux';
|
||||
import { Dispatch } from 'redux';
|
||||
|
||||
const manageEdgeImagesUrlName = 'manage-edge-images';
|
||||
|
||||
const getNotificationProp = (dispatch: Dispatch) => {
|
||||
return {
|
||||
hasInfo: (hasInfoMessage: Notification) => {
|
||||
dispatch({
|
||||
...addNotification({
|
||||
variant: 'info',
|
||||
...hasInfoMessage,
|
||||
}),
|
||||
});
|
||||
},
|
||||
hasSuccess: (hasSuccessMessage: Notification) => {
|
||||
dispatch({
|
||||
...addNotification({
|
||||
variant: 'success',
|
||||
...hasSuccessMessage,
|
||||
}),
|
||||
});
|
||||
},
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
err: (errMessage: any, err: any) => {
|
||||
dispatch({
|
||||
...addNotification({
|
||||
variant: 'danger',
|
||||
...errMessage,
|
||||
// Add error message from API, if present
|
||||
description: err?.Title
|
||||
? `${errMessage.description}: ${err.Title}`
|
||||
: errMessage.description,
|
||||
}),
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export { getNotificationProp, manageEdgeImagesUrlName };
|
||||
|
|
@ -1,5 +1,3 @@
|
|||
import { addNotification } from '@redhat-cloud-services/frontend-components-notifications/redux';
|
||||
|
||||
import { cockpitApi } from './cockpitApi';
|
||||
|
||||
const enhancedApi = cockpitApi.enhanceEndpoints({
|
||||
|
|
@ -17,98 +15,15 @@ const enhancedApi = cockpitApi.enhanceEndpoints({
|
|||
},
|
||||
createBlueprint: {
|
||||
invalidatesTags: [{ type: 'Blueprints' }],
|
||||
onQueryStarted: async (_, { dispatch, queryFulfilled }) => {
|
||||
queryFulfilled
|
||||
.then(() => {
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'success',
|
||||
title: 'Blueprint was created',
|
||||
})
|
||||
);
|
||||
})
|
||||
.catch((err) => {
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'danger',
|
||||
title: 'Unable to create blueprint',
|
||||
description: `Error: ${JSON.stringify(err)}`,
|
||||
})
|
||||
);
|
||||
});
|
||||
},
|
||||
},
|
||||
updateBlueprint: {
|
||||
invalidatesTags: [{ type: 'Blueprint' }, { type: 'Blueprints' }],
|
||||
onQueryStarted: async (_, { dispatch, queryFulfilled }) => {
|
||||
queryFulfilled
|
||||
.then(() => {
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'success',
|
||||
title: 'Blueprint was created',
|
||||
})
|
||||
);
|
||||
})
|
||||
.catch((err) => {
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'danger',
|
||||
title: 'Unable to update blueprint',
|
||||
description: `Error: ${JSON.stringify(err)}`,
|
||||
})
|
||||
);
|
||||
});
|
||||
},
|
||||
},
|
||||
deleteBlueprint: {
|
||||
invalidatesTags: [{ type: 'Blueprints' }, { type: 'Composes' }],
|
||||
onQueryStarted: async (_, { dispatch, queryFulfilled }) => {
|
||||
queryFulfilled
|
||||
.then(() => {
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'success',
|
||||
title: 'Blueprint was deleted',
|
||||
})
|
||||
);
|
||||
})
|
||||
.catch((err) => {
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'danger',
|
||||
title: 'Blueprint could not be deleted',
|
||||
description: `Error: ${JSON.stringify(err)}`,
|
||||
})
|
||||
);
|
||||
});
|
||||
},
|
||||
},
|
||||
composeBlueprint: {
|
||||
invalidatesTags: [{ type: 'Composes' }],
|
||||
onQueryStarted: async (_, { dispatch, queryFulfilled }) => {
|
||||
queryFulfilled
|
||||
.then(() => {
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'success',
|
||||
title: 'Build was queued',
|
||||
})
|
||||
);
|
||||
})
|
||||
.catch((err) => {
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'danger',
|
||||
title: 'Unable to build blueprint',
|
||||
// If details are present, assume it's coming from composer
|
||||
description: err.error?.body?.details
|
||||
? `${err.error.message}: ${err.error.body.details}`
|
||||
: `Error: ${JSON.stringify(err)}`,
|
||||
})
|
||||
);
|
||||
});
|
||||
},
|
||||
},
|
||||
getComposes: {
|
||||
providesTags: [{ type: 'Composes' }],
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { notificationsReducer } from '@redhat-cloud-services/frontend-components-notifications/redux';
|
||||
import { combineReducers, configureStore } from '@reduxjs/toolkit';
|
||||
import promiseMiddleware from 'redux-promise-middleware';
|
||||
|
||||
|
|
@ -27,7 +26,6 @@ export const serviceReducer = combineReducers({
|
|||
[rhsmApi.reducerPath]: rhsmApi.reducer,
|
||||
[provisioningApi.reducerPath]: provisioningApi.reducer,
|
||||
[complianceApi.reducerPath]: complianceApi.reducer,
|
||||
notifications: notificationsReducer,
|
||||
wizard: wizardSlice,
|
||||
blueprints: blueprintsSlice.reducer,
|
||||
});
|
||||
|
|
@ -41,7 +39,6 @@ export const onPremReducer = combineReducers({
|
|||
// TODO: add other endpoints so we can remove this.
|
||||
// It's still needed to get things to work.
|
||||
[imageBuilderApi.reducerPath]: imageBuilderApi.reducer,
|
||||
notifications: notificationsReducer,
|
||||
wizard: wizardSlice,
|
||||
blueprints: blueprintsSlice.reducer,
|
||||
});
|
||||
|
|
@ -64,7 +61,7 @@ startAppListening({
|
|||
distribution: distribution,
|
||||
})(state as serviceState);
|
||||
|
||||
const allowedImageTypes = architecturesResponse?.data?.find(
|
||||
const allowedImageTypes = architecturesResponse.data?.find(
|
||||
(elem) => elem.arch === architecture
|
||||
)?.image_types;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import { addNotification } from '@redhat-cloud-services/frontend-components-notifications/redux';
|
||||
|
||||
import { imageBuilderApi } from '../imageBuilderApi';
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
|
|
@ -51,146 +49,45 @@ const enhancedApi = imageBuilderApi.enhanceEndpoints({
|
|||
},
|
||||
updateBlueprint: {
|
||||
onQueryStarted: async (_, { dispatch, queryFulfilled }) => {
|
||||
queryFulfilled
|
||||
.then(() => {
|
||||
dispatch(
|
||||
// @ts-expect-error Typescript is unaware of tag types being defined concurrently in enhanceEndpoints()
|
||||
imageBuilderApi.util.invalidateTags(['Blueprints', 'Blueprint'])
|
||||
);
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'success',
|
||||
title: 'Changes saved to blueprint',
|
||||
})
|
||||
);
|
||||
})
|
||||
.catch((err) => {
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'danger',
|
||||
title: 'Blueprint could not be updated',
|
||||
description: `Status code ${err.error.status}: ${errorMessage(
|
||||
err
|
||||
)}`,
|
||||
})
|
||||
);
|
||||
});
|
||||
queryFulfilled.then(() => {
|
||||
dispatch(
|
||||
// @ts-expect-error Typescript is unaware of tag types being defined concurrently in enhanceEndpoints()
|
||||
imageBuilderApi.util.invalidateTags(['Blueprints', 'Blueprint'])
|
||||
);
|
||||
});
|
||||
},
|
||||
},
|
||||
createBlueprint: {
|
||||
onQueryStarted: async (_, { dispatch, queryFulfilled }) => {
|
||||
queryFulfilled
|
||||
.then(() => {
|
||||
// @ts-expect-error Typescript is unaware of tag types being defined concurrently in enhanceEndpoints()
|
||||
dispatch(imageBuilderApi.util.invalidateTags(['Blueprints']));
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'success',
|
||||
title: 'Blueprint is being created',
|
||||
})
|
||||
);
|
||||
})
|
||||
.catch((err) => {
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'danger',
|
||||
title: 'Blueprint could not be created',
|
||||
description: `Status code ${err.error.status}: ${errorMessage(
|
||||
err
|
||||
)}`,
|
||||
})
|
||||
);
|
||||
});
|
||||
queryFulfilled.then(() => {
|
||||
// @ts-expect-error Typescript is unaware of tag types being defined concurrently in enhanceEndpoints()
|
||||
dispatch(imageBuilderApi.util.invalidateTags(['Blueprints']));
|
||||
});
|
||||
},
|
||||
},
|
||||
cloneCompose: {
|
||||
onQueryStarted: async (
|
||||
{ composeId, cloneRequest },
|
||||
{ dispatch, queryFulfilled }
|
||||
) => {
|
||||
queryFulfilled
|
||||
.then(() => {
|
||||
dispatch(
|
||||
imageBuilderApi.util.invalidateTags([
|
||||
// @ts-expect-error Typescript is unaware of tag types being defined concurrently in enhanceEndpoints()
|
||||
{ type: 'Clone', id: composeId },
|
||||
])
|
||||
);
|
||||
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'success',
|
||||
title:
|
||||
'Your image is being shared to ' +
|
||||
cloneRequest.region +
|
||||
' region',
|
||||
})
|
||||
);
|
||||
})
|
||||
.catch((err) => {
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'danger',
|
||||
title: 'Your image could not be shared',
|
||||
description: `Status code ${err.error.status}: ${errorMessage(
|
||||
err
|
||||
)}`,
|
||||
})
|
||||
);
|
||||
});
|
||||
onQueryStarted: async ({ composeId }, { dispatch, queryFulfilled }) => {
|
||||
queryFulfilled.then(() => {
|
||||
dispatch(
|
||||
imageBuilderApi.util.invalidateTags([
|
||||
// @ts-expect-error Typescript is unaware of tag types being defined concurrently in enhanceEndpoints()
|
||||
{ type: 'Clone', id: composeId },
|
||||
])
|
||||
);
|
||||
});
|
||||
},
|
||||
},
|
||||
composeBlueprint: {
|
||||
invalidatesTags: [{ type: 'Compose' }, { type: 'BlueprintComposes' }],
|
||||
onQueryStarted: async (_, { dispatch, queryFulfilled }) => {
|
||||
queryFulfilled
|
||||
.then(() => {
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'success',
|
||||
title: 'Image is being built',
|
||||
})
|
||||
);
|
||||
})
|
||||
.catch((err) => {
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'danger',
|
||||
title: 'Image could not be built',
|
||||
description: `Status code ${err.error.status}: ${errorMessage(
|
||||
err
|
||||
)}`,
|
||||
})
|
||||
);
|
||||
});
|
||||
},
|
||||
},
|
||||
composeImage: {
|
||||
onQueryStarted: async (_, { dispatch, queryFulfilled }) => {
|
||||
queryFulfilled
|
||||
.then(() => {
|
||||
dispatch(
|
||||
// @ts-expect-error Typescript is unaware of tag types being defined concurrently in enhanceEndpoints()
|
||||
imageBuilderApi.util.invalidateTags(['Blueprints', 'Compose'])
|
||||
);
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'success',
|
||||
title: 'Your image is being created',
|
||||
})
|
||||
);
|
||||
})
|
||||
.catch((err) => {
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'danger',
|
||||
title: 'Your image could not be created',
|
||||
description: `Status code ${err.error.status}: ${errorMessage(
|
||||
err
|
||||
)}`,
|
||||
})
|
||||
);
|
||||
});
|
||||
queryFulfilled.then(() => {
|
||||
dispatch(
|
||||
// @ts-expect-error Typescript is unaware of tag types being defined concurrently in enhanceEndpoints()
|
||||
imageBuilderApi.util.invalidateTags(['Blueprints', 'Compose'])
|
||||
);
|
||||
});
|
||||
},
|
||||
},
|
||||
deleteBlueprint: {
|
||||
|
|
@ -199,53 +96,9 @@ const enhancedApi = imageBuilderApi.enhanceEndpoints({
|
|||
{ type: 'BlueprintComposes' },
|
||||
{ type: 'Compose' },
|
||||
],
|
||||
onQueryStarted: async (_, { dispatch, queryFulfilled }) => {
|
||||
queryFulfilled
|
||||
.then(() => {
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'success',
|
||||
title: 'Blueprint was deleted',
|
||||
})
|
||||
);
|
||||
})
|
||||
.catch((err) => {
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'danger',
|
||||
title: 'Blueprint could not be deleted',
|
||||
description: `Status code ${err.error.status}: ${errorMessage(
|
||||
err
|
||||
)}`,
|
||||
})
|
||||
);
|
||||
});
|
||||
},
|
||||
},
|
||||
fixupBlueprint: {
|
||||
invalidatesTags: [{ type: 'Blueprint' }],
|
||||
onQueryStarted: async (_, { dispatch, queryFulfilled }) => {
|
||||
queryFulfilled
|
||||
.then(() => {
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'success',
|
||||
title: 'Blueprint was fixed',
|
||||
})
|
||||
);
|
||||
})
|
||||
.catch((err) => {
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'danger',
|
||||
title: 'Blueprint could not be fixed',
|
||||
description: `Status code ${err.error.status}: ${errorMessage(
|
||||
err
|
||||
)}`,
|
||||
})
|
||||
);
|
||||
});
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue