Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions locales/en/plugin__nmstate-console-plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
127 changes: 77 additions & 50 deletions src/utils/components/PolicyForm/PolicyWizard/PolicyWizard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -27,9 +33,11 @@ import './PolicyWizard.scss';
type PolicyWizardProps = {
policy: V1NodeNetworkConfigurationPolicy;
setPolicy: Updater<V1NodeNetworkConfigurationPolicy>;
onSubmit: () => void | Promise<void>;
onSubmit: (createAnother: boolean) => void | Promise<void>;
onClose: () => void;
onStepChange?: (stepId: string | number) => void;
lastCreatedPolicyName?: string;
clearSuccessMessage?: () => void;
};

const PolicyWizard: FC<PolicyWizardProps> = ({
Expand All @@ -38,10 +46,13 @@ const PolicyWizard: FC<PolicyWizardProps> = ({
onSubmit,
onClose,
onStepChange,
lastCreatedPolicyName,
clearSuccessMessage,
}) => {
const { t } = useNMStateTranslation();
const [loading, setLoading] = useState(false);
const [error, setError] = useState<Error>(null);
const [createAnother, setCreateAnother] = useState(false);

const onFormSubmit: MouseEventHandler<HTMLButtonElement> = useCallback(async () => {
const error = ensureNoEmptyBridgeMapping(policy);
Expand All @@ -50,63 +61,79 @@ const PolicyWizard: FC<PolicyWizardProps> = ({

setLoading(true);
try {
await onSubmit();
await onSubmit(createAnother);
} catch (error) {
setError(error);
} finally {
setLoading(false);
}
}, [onSubmit, policy, t]);
}, [onSubmit, policy, t, createAnother]);

return (
<Wizard
onSave={onFormSubmit}
onClose={onClose}
onStepChange={(_, currentStep) => {
onStepChange?.(currentStep.id);
}}
className="nmstate-policy-wizard policy-form-content"
>
<WizardStep
footer={{ isNextDisabled: isEmpty(getOVNLocalnet(policy)) }}
id="policy-wizard-network-identity"
name={t('Network identity')}
>
<NetworkIdentity policy={policy} setPolicy={setPolicy} />
</WizardStep>
<WizardStep
footer={{ isNextDisabled: isEmpty(getName(policy)) }}
id="policy-wizard-basic-info"
name={t('Nodes configuration')}
>
<NodesConfigurationStep policy={policy} setPolicy={setPolicy} />
</WizardStep>
<WizardStep
id="policy-wizard-uplink-connection"
name={t('Uplink connection')}
footer={{ isNextDisabled: !uplinkSettingsValid(policy) }}
>
<UplinkConnectionStep policy={policy} setPolicy={setPolicy} />
</WizardStep>
<WizardStep
name={t('Settings')}
id="policy-wizard-configuration"
isDisabled={getUplinkConnectionOption(policy) === ConnectionOption.BREX}
>
<SettingsStep policy={policy} setPolicy={setPolicy} />
</WizardStep>
<WizardStep
footer={{
isNextDisabled: isEmpty(getName(policy)),
nextButtonProps: { isLoading: loading },
nextButtonText: t('Create network'),
<>
{lastCreatedPolicyName && (
<Alert
isInline
variant={AlertVariant.success}
title={t('{{name}} created successfully', { name: lastCreatedPolicyName })}
actionClose={<AlertActionCloseButton onClose={clearSuccessMessage} />}
/>
)}
<Wizard
onSave={onFormSubmit}
onClose={onClose}
onStepChange={(_, currentStep) => {
onStepChange?.(currentStep.id);
}}
id="policy-wizard-review"
name={t('Review and create')}
className="nmstate-policy-wizard policy-form-content"
>
<ReviewStep policy={policy} creationError={error} setPolicy={setPolicy} />
</WizardStep>
</Wizard>
<WizardStep
footer={{ isNextDisabled: isEmpty(getOVNLocalnet(policy)) }}
id="policy-wizard-network-identity"
name={t('Network identity')}
>
<NetworkIdentity policy={policy} setPolicy={setPolicy} />
</WizardStep>
<WizardStep
footer={{ isNextDisabled: isEmpty(getName(policy)) }}
id="policy-wizard-basic-info"
name={t('Nodes configuration')}
>
<NodesConfigurationStep policy={policy} setPolicy={setPolicy} />
</WizardStep>
<WizardStep
id="policy-wizard-uplink-connection"
name={t('Uplink connection')}
footer={{ isNextDisabled: !uplinkSettingsValid(policy) }}
>
<UplinkConnectionStep policy={policy} setPolicy={setPolicy} />
</WizardStep>
<WizardStep
name={t('Settings')}
id="policy-wizard-configuration"
isDisabled={getUplinkConnectionOption(policy) === ConnectionOption.BREX}
>
<SettingsStep policy={policy} setPolicy={setPolicy} />
</WizardStep>
<WizardStep
footer={{
isNextDisabled: isEmpty(getName(policy)),
nextButtonProps: { isLoading: loading },
nextButtonText: t('Create network'),
}}
id="policy-wizard-review"
name={t('Review and create')}
>
<ReviewStep
policy={policy}
creationError={error}
setPolicy={setPolicy}
createAnother={createAnother}
setCreateAnother={setCreateAnother}
/>
</WizardStep>
</Wizard>
</>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,19 @@ type ReviewStepProps = {
policy: V1NodeNetworkConfigurationPolicy;
creationError?: Error;
setPolicy: Updater<V1NodeNetworkConfigurationPolicy>;
createAnother: boolean;
setCreateAnother: (value: boolean) => void;
};

const ReviewStep: FC<ReviewStepProps> = ({ policy, creationError, setPolicy }) => {
const ReviewStep: FC<ReviewStepProps> = ({
policy,
creationError,
setPolicy,
createAnother,
setCreateAnother,
}) => {
const { t } = useNMStateTranslation();
const [openInVMNetworksPage, setOpenInVMNetworksPage] = useState<boolean>(false);
//const [openInVMNetworksPage, setOpenInVMNetworksPage] = useState<boolean>(false);
const [error, setError] = useState<Error | null>(null);

const handleUpdate = (updatedPolicy: V1NodeNetworkConfigurationPolicy) => {
Expand Down Expand Up @@ -140,8 +148,8 @@ const ReviewStep: FC<ReviewStepProps> = ({ policy, creationError, setPolicy }) =
<Checkbox
label={t('Create another node network configuration')}
id="create-new-vm-network"
isChecked={openInVMNetworksPage}
onChange={(_, newValue) => setOpenInVMNetworksPage(newValue)}
isChecked={createAnother}
onChange={(_, newValue) => setCreateAnother(newValue)}
/>
</StackItem>
</Stack>
Expand Down
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -25,6 +25,8 @@ const CreatePolicyDrawer: FC<CreatePolicyDrawerProps> = ({ onClose }) => {
const [policy, setPolicy] = useImmer(initialPolicy);
const completed = useRef(false);
const currentStepId = useRef<string | number>('policy-wizard-basicinfo');
const [wizardKey, setWizardKey] = useState(0);
const [lastCreatedPolicyName, setLastCreatedPolicyName] = useState<string>('');
const history = useHistory();

creatingPolicySignal.value = policy;
Expand All @@ -41,7 +43,7 @@ const CreatePolicyDrawer: FC<CreatePolicyDrawerProps> = ({ onClose }) => {
};
}, []);

const onSubmit = async () => {
const onSubmit = async (createAnother: boolean) => {
try {
const createdPolicy = await k8sCreate({
model: NodeNetworkConfigurationPolicyModel,
Expand All @@ -51,8 +53,16 @@ const CreatePolicyDrawer: FC<CreatePolicyDrawerProps> = ({ 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 }),
);
Expand All @@ -70,13 +80,16 @@ const CreatePolicyDrawer: FC<CreatePolicyDrawerProps> = ({ onClose }) => {

return (
<PolicyWizard
key={wizardKey}
policy={policy}
setPolicy={setPolicy}
onSubmit={onSubmit}
onClose={closeDrawer}
onStepChange={(stepId) => {
currentStepId.current = stepId;
}}
lastCreatedPolicyName={lastCreatedPolicyName}
clearSuccessMessage={() => setLastCreatedPolicyName('')}
/>
);
};
Expand Down