diff --git a/locales/en/plugin__nmstate-console-plugin.json b/locales/en/plugin__nmstate-console-plugin.json index 8446bcf..028bba8 100644 --- a/locales/en/plugin__nmstate-console-plugin.json +++ b/locales/en/plugin__nmstate-console-plugin.json @@ -151,6 +151,7 @@ "Must have at least two interfaces.": "Must have at least two interfaces.", "Name": "Name", "Name already in use by another interface": "Name already in use by another interface", + "{{name}} created successfully": "{{name}} created successfully", "Neighbors": "Neighbors", "Network description": "Network description", "Network details": "Network details", diff --git a/src/utils/components/PolicyForm/PolicyWizard/PolicyWizard.tsx b/src/utils/components/PolicyForm/PolicyWizard/PolicyWizard.tsx index 28b8cfe..4405253 100644 --- a/src/utils/components/PolicyForm/PolicyWizard/PolicyWizard.tsx +++ b/src/utils/components/PolicyForm/PolicyWizard/PolicyWizard.tsx @@ -3,7 +3,13 @@ import { useNMStateTranslation } from 'src/utils/hooks/useNMStateTranslation'; import { Updater } from 'use-immer'; import { V1NodeNetworkConfigurationPolicy } from '@kubevirt-ui/kubevirt-api/nmstate'; -import { Wizard, WizardStep } from '@patternfly/react-core'; +import { + Alert, + AlertActionCloseButton, + AlertVariant, + Wizard, + WizardStep, +} from '@patternfly/react-core'; import NodesConfigurationStep from '@utils/components/PolicyForm/PolicyWizard/steps/NodesConfigurationStep/NodesConfigurationStep'; import SettingsStep from '@utils/components/PolicyForm/PolicyWizard/steps/SettingsStep/SettingsStep'; import { getOVNLocalnet } from '@utils/components/PolicyForm/PolicyWizard/utils/selectors'; @@ -27,9 +33,11 @@ import './PolicyWizard.scss'; type PolicyWizardProps = { policy: V1NodeNetworkConfigurationPolicy; setPolicy: Updater; - onSubmit: () => void | Promise; + onSubmit: (createAnother: boolean) => void | Promise; onClose: () => void; onStepChange?: (stepId: string | number) => void; + lastCreatedPolicyName?: string; + clearSuccessMessage?: () => void; }; const PolicyWizard: FC = ({ @@ -38,10 +46,13 @@ const PolicyWizard: FC = ({ onSubmit, onClose, onStepChange, + lastCreatedPolicyName, + clearSuccessMessage, }) => { const { t } = useNMStateTranslation(); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); + const [createAnother, setCreateAnother] = useState(false); const onFormSubmit: MouseEventHandler = useCallback(async () => { const error = ensureNoEmptyBridgeMapping(policy); @@ -50,63 +61,79 @@ const PolicyWizard: FC = ({ setLoading(true); try { - await onSubmit(); + await onSubmit(createAnother); } catch (error) { setError(error); } finally { setLoading(false); } - }, [onSubmit, policy, t]); + }, [onSubmit, policy, t, createAnother]); return ( - { - onStepChange?.(currentStep.id); - }} - className="nmstate-policy-wizard policy-form-content" - > - - - - - - - - - - - - - + {lastCreatedPolicyName && ( + } + /> + )} + { + onStepChange?.(currentStep.id); }} - id="policy-wizard-review" - name={t('Review and create')} + className="nmstate-policy-wizard policy-form-content" > - - - + + + + + + + + + + + + + + + + + ); }; diff --git a/src/utils/components/PolicyForm/PolicyWizard/steps/ReviewStep/ReviewStep.tsx b/src/utils/components/PolicyForm/PolicyWizard/steps/ReviewStep/ReviewStep.tsx index 54a9587..602b6ef 100644 --- a/src/utils/components/PolicyForm/PolicyWizard/steps/ReviewStep/ReviewStep.tsx +++ b/src/utils/components/PolicyForm/PolicyWizard/steps/ReviewStep/ReviewStep.tsx @@ -38,11 +38,19 @@ type ReviewStepProps = { policy: V1NodeNetworkConfigurationPolicy; creationError?: Error; setPolicy: Updater; + createAnother: boolean; + setCreateAnother: (value: boolean) => void; }; -const ReviewStep: FC = ({ policy, creationError, setPolicy }) => { +const ReviewStep: FC = ({ + policy, + creationError, + setPolicy, + createAnother, + setCreateAnother, +}) => { const { t } = useNMStateTranslation(); - const [openInVMNetworksPage, setOpenInVMNetworksPage] = useState(false); + //const [openInVMNetworksPage, setOpenInVMNetworksPage] = useState(false); const [error, setError] = useState(null); const handleUpdate = (updatedPolicy: V1NodeNetworkConfigurationPolicy) => { @@ -140,8 +148,8 @@ const ReviewStep: FC = ({ policy, creationError, setPolicy }) = setOpenInVMNetworksPage(newValue)} + isChecked={createAnother} + onChange={(_, newValue) => setCreateAnother(newValue)} /> diff --git a/src/views/nodenetworkconfiguration/components/TopologySidebar/CreatePolicyDrawer.tsx b/src/views/nodenetworkconfiguration/components/TopologySidebar/CreatePolicyDrawer.tsx index d38c1b4..0f6a049 100644 --- a/src/views/nodenetworkconfiguration/components/TopologySidebar/CreatePolicyDrawer.tsx +++ b/src/views/nodenetworkconfiguration/components/TopologySidebar/CreatePolicyDrawer.tsx @@ -1,4 +1,4 @@ -import React, { FC, useEffect, useRef } from 'react'; +import React, { FC, useEffect, useRef, useState } from 'react'; import { useHistory } from 'react-router'; import NodeNetworkConfigurationPolicyModel from 'src/console-models/NodeNetworkConfigurationPolicyModel'; import { useImmer } from 'use-immer'; @@ -25,6 +25,8 @@ const CreatePolicyDrawer: FC = ({ onClose }) => { const [policy, setPolicy] = useImmer(initialPolicy); const completed = useRef(false); const currentStepId = useRef('policy-wizard-basicinfo'); + const [wizardKey, setWizardKey] = useState(0); + const [lastCreatedPolicyName, setLastCreatedPolicyName] = useState(''); const history = useHistory(); creatingPolicySignal.value = policy; @@ -41,7 +43,7 @@ const CreatePolicyDrawer: FC = ({ onClose }) => { }; }, []); - const onSubmit = async () => { + const onSubmit = async (createAnother: boolean) => { try { const createdPolicy = await k8sCreate({ model: NodeNetworkConfigurationPolicyModel, @@ -51,8 +53,16 @@ const CreatePolicyDrawer: FC = ({ onClose }) => { completed.current = true; logNNCPCreated(createdPolicy); - creatingPolicySignal.value = null; + if (createAnother) { + setPolicy(initialPolicy); + creatingPolicySignal.value = initialPolicy; + completed.current = false; + setWizardKey((prev) => prev + 1); + setLastCreatedPolicyName(createdPolicy.metadata.name); + return; + } + creatingPolicySignal.value = null; history.push( getResourceUrl({ model: NodeNetworkConfigurationPolicyModel, resource: createdPolicy }), ); @@ -70,6 +80,7 @@ const CreatePolicyDrawer: FC = ({ onClose }) => { return ( = ({ onClose }) => { onStepChange={(stepId) => { currentStepId.current = stepId; }} + lastCreatedPolicyName={lastCreatedPolicyName} + clearSuccessMessage={() => setLastCreatedPolicyName('')} /> ); };