Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modified wizard flow with 4.15 specific changes #1100

Merged
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
17 changes: 15 additions & 2 deletions locales/en/plugin__odf-console.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@
"Data policies": "Data policies",
"Disaster recovery": "Disaster recovery",
"Validated": "Validated",
"Not Validated": "Not Validated",
"Not validated": "Not validated",
"{{async}}, interval: {{syncInterval}}": "{{async}}, interval: {{syncInterval}}",
"Application": "Application",
"Applications": "Applications",
"DRPolicies": "DRPolicies",
Expand Down Expand Up @@ -245,6 +246,19 @@
"Use PVC label selectors to effortlessly specify the application resources that need protection.": "Use PVC label selectors to effortlessly specify the application resources that need protection.",
"Application resource": "Application resource",
"Add application resource": "Add application resource",
"{{count}} placements_one": "{{count}} placements",
"{{count}} placements_other": "{{count}} placements",
"Data policy": "Data policy",
"Policy name:": "Policy name:",
"Clusters:": "Clusters:",
"Replication type:": "Replication type:",
"Sync interval:": "Sync interval:",
"PVC details": "PVC details",
"Application resource:": "Application resource:",
"PVC label selector:": "PVC label selector:",
"Replication type: {{type}}, Interval: {{interval}}, Clusters: {{clusters}}": "Replication type: {{type}}, Interval: {{interval}}, Clusters: {{clusters}}",
"Replication type: {{type}}, Clusters: {{clusters}}": "Replication type: {{type}}, Clusters: {{clusters}}",
"Status: {{status}}": "Status: {{status}}",
"Select a policy": "Select a policy",
"Search": "Search",
"Search input": "Search input",
Expand Down Expand Up @@ -274,7 +288,6 @@
"Policy": "Policy",
"PersistentVolumeClaim": "PersistentVolumeClaim",
"Review and assign": "Review and assign",
"{{async}}, interval: {{interval}}": "{{async}}, interval: {{interval}}",
"In use: {{targetClusters}}": "In use: {{targetClusters}}",
"Used: {{targetClusters}}": "Used: {{targetClusters}}",
"View documentation": "View documentation",
Expand Down
13 changes: 10 additions & 3 deletions packages/mco/components/drpolicy-list-page/drpolicy-list-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
} from '@openshift-console/dynamic-plugin-sdk';
import { Trans } from 'react-i18next';
import { useHistory, useLocation } from 'react-router';
import { HUB_CLUSTER_NAME } from '../../constants';
import { HUB_CLUSTER_NAME, REPLICATION_TYPE } from '../../constants';
import {
ApplicationRefKind,
getDRPolicyResourceObj,
Expand Down Expand Up @@ -56,6 +56,8 @@ const DRPolicyRow: React.FC<RowProps<DRPolicyKind, RowData>> = ({
));
const filteredApps = findAppsUsingDRPolicy(applicationRefs, obj);
const appCount = filteredApps?.length;
const syncInterval = obj?.spec?.schedulingInterval;
const replicationType = getReplicationType(syncInterval);

const onClick = () => {
openModal(true);
Expand All @@ -68,13 +70,18 @@ const DRPolicyRow: React.FC<RowProps<DRPolicyKind, RowData>> = ({
{obj?.metadata?.name}
</TableData>
<TableData {...tableColumnInfo[1]} activeColumnIDs={activeColumnIDs}>
{isDRPolicyValidated(obj) ? t('Validated') : t('Not Validated')}
{isDRPolicyValidated(obj) ? t('Validated') : t('Not validated')}
</TableData>
<TableData {...tableColumnInfo[2]} activeColumnIDs={activeColumnIDs}>
{clusterNames}
</TableData>
<TableData {...tableColumnInfo[3]} activeColumnIDs={activeColumnIDs}>
{getReplicationType(obj?.spec?.schedulingInterval, t)}
{replicationType === REPLICATION_TYPE.ASYNC
? t('{{async}}, interval: {{syncInterval}}', {
async: REPLICATION_TYPE.ASYNC,
syncInterval,
})
: REPLICATION_TYPE.SYNC}
</TableData>
<TableData {...tableColumnInfo[4]} activeColumnIDs={activeColumnIDs}>
{appCount > 0 ? (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import * as React from 'react';
import { AssignPolicySteps, AssignPolicyStepsNames } from '@odf/mco/constants';
import { createRefFromK8Resource } from '@odf/mco/utils';
import { ModalBody } from '@odf/shared/modals/Modal';
import {
APPLICATION_TYPE,
AssignPolicySteps,
AssignPolicyStepsNames,
} from '@odf/mco/constants';
import { ModalBody } from '@odf/shared/modals';
import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook';
import { getErrorMessage } from '@odf/shared/utils';
import { TFunction } from 'i18next';
import { Wizard, WizardStep, AlertVariant } from '@patternfly/react-core';
import { AssignPolicyViewFooter } from './helper/assign-policy-view-footer';
import { PolicyConfigViewer } from './helper/policy-config-viewer';
import { PVCDetailsWizardContent } from './helper/pvc-details-wizard-content';
import { ReviewAndAssign } from './helper/review-and-assign';
import { SelectPolicyWizardContent } from './helper/select-policy-wizard-content';
import { assignPromises } from './utils/k8s-utils';
import {
Expand All @@ -21,59 +24,76 @@ import {
} from './utils/reducer';
import {
ApplicationType,
DRPlacementControlType,
DRPolicyType,
DataPolicyType,
PlacementType,
} from './utils/types';

export const createSteps = (
appType: APPLICATION_TYPE,
workloadNamespace: string,
unProtectedPlacements: PlacementType[],
matchingPolicies: DRPolicyType[],
state: AssignPolicyViewState,
stepIdReached: number,
isValidationEnabled: boolean,
t: TFunction,
setPolicy: (policy?: DataPolicyType) => void,
setDRPlacementControls: (
drPlacementControls: DRPlacementControlType[]
) => void
): WizardStep[] => [
{
id: 1,
name: AssignPolicyStepsNames(t)[AssignPolicySteps.Policy],
component: (
<SelectPolicyWizardContent
matchingPolicies={matchingPolicies}
policy={state.policy}
isValidationEnabled={isValidationEnabled}
setPolicy={setPolicy}
/>
),
},
{
id: 2,
name: AssignPolicyStepsNames(t)[AssignPolicySteps.PersistentVolumeClaim],
component: (
<PVCDetailsWizardContent
placementControInfo={state.policy?.placementControlInfo}
unProtectedPlacements={unProtectedPlacements}
workloadNamespace={workloadNamespace}
isValidationEnabled={isValidationEnabled}
policyRef={createRefFromK8Resource(state.policy)}
setDRPlacementControls={setDRPlacementControls}
/>
),
canJumpTo: stepIdReached >= 2,
},
{
id: 3,
name: AssignPolicyStepsNames(t)[AssignPolicySteps.ReviewAndAssign],
component: <PolicyConfigViewer policy={state.policy} hideSelector={true} />,
canJumpTo: stepIdReached >= 3,
},
];
dispatch: React.Dispatch<ManagePolicyStateAction>
): WizardStep[] => {
const commonSteps = {
policy: {
name: AssignPolicyStepsNames(t)[AssignPolicySteps.Policy],
component: (
<SelectPolicyWizardContent
matchingPolicies={matchingPolicies}
policy={state.policy}
isValidationEnabled={isValidationEnabled}
dispatch={dispatch}
/>
),
},
persistentVolumeClaim: {
name: AssignPolicyStepsNames(t)[AssignPolicySteps.PersistentVolumeClaim],
component: (
<PVCDetailsWizardContent
pvcSelectors={state.persistentVolumeClaim.pvcSelectors}
unProtectedPlacements={unProtectedPlacements}
workloadNamespace={workloadNamespace}
isValidationEnabled={isValidationEnabled}
dispatch={dispatch}
/>
),
},
reviewAndAssign: {
name: AssignPolicyStepsNames(t)[AssignPolicySteps.ReviewAndAssign],
component: <ReviewAndAssign state={state} />,
},
};

switch (appType) {
case APPLICATION_TYPE.APPSET:
case APPLICATION_TYPE.SUBSCRIPTION:
return [
{
id: 1,
...commonSteps.policy,
canJumpTo: stepIdReached >= 1,
},
{
id: 2,
...commonSteps.persistentVolumeClaim,
canJumpTo: stepIdReached >= 2,
},
{
id: 3,
...commonSteps.reviewAndAssign,
canJumpTo: stepIdReached >= 3,
},
];
default:
return [];
}
};

export const AssignPolicyView: React.FC<AssignPolicyViewProps> = ({
state,
Expand All @@ -88,20 +108,12 @@ export const AssignPolicyView: React.FC<AssignPolicyViewProps> = ({
const [stepIdReached, setStepIdReached] = React.useState(1);
const [isValidationEnabled, setIsValidationEnabled] = React.useState(false);

const setPolicy = (policy: DataPolicyType = null) =>
dispatch({
type: ManagePolicyStateType.SET_SELECTED_POLICY,
context: ModalViewContext.ASSIGN_POLICY_VIEW,
payload: policy,
});
const { type: appType, workloadNamespace, placements } = applicaitonInfo;

const setDRPlacementControls = (
drPlacementControls: DRPlacementControlType[]
) =>
const resetAssignState = () =>
dispatch({
type: ManagePolicyStateType.SET_PLACEMENT_CONTROLS,
type: ManagePolicyStateType.RESET_ASSIGN_POLICY_STATE,
context: ModalViewContext.ASSIGN_POLICY_VIEW,
payload: drPlacementControls,
});

const onSubmit = async () => {
Expand All @@ -123,11 +135,11 @@ export const AssignPolicyView: React.FC<AssignPolicyViewProps> = ({
setModalActionContext(actionContext, ModalViewContext.POLICY_LIST_VIEW);
// switch to list policy view
setModalContext(ModalViewContext.POLICY_LIST_VIEW);
// reset policy info
setPolicy();
// reset info
resetAssignState();
};
// assign DRPolicy
const promises = assignPromises(state.policy);
const promises = assignPromises(state, applicaitonInfo.placements);
await Promise.all(promises)
.then(() => {
updateContext(
Expand All @@ -149,8 +161,8 @@ export const AssignPolicyView: React.FC<AssignPolicyViewProps> = ({

const onClose = () => {
setModalContext(ModalViewContext.POLICY_LIST_VIEW);
// reset policy info
setPolicy();
// reset info
resetAssignState();
};

return (
Expand All @@ -159,19 +171,20 @@ export const AssignPolicyView: React.FC<AssignPolicyViewProps> = ({
navAriaLabel={t('Assign policy nav')}
mainAriaLabel={t('Assign policy content')}
steps={createSteps(
applicaitonInfo.workloadNamespace,
applicaitonInfo.placements,
appType,
workloadNamespace,
placements,
matchingPolicies,
state,
stepIdReached,
isValidationEnabled,
t,
setPolicy,
setDRPlacementControls
dispatch
)}
footer={
<AssignPolicyViewFooter
dataPolicy={state.policy}
state={state}
appType={appType}
stepIdReached={stepIdReached}
isValidationEnabled={isValidationEnabled}
setStepIdReached={setStepIdReached}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import * as React from 'react';
import { AssignPolicySteps, AssignPolicyStepsNames } from '@odf/mco/constants';
import {
APPLICATION_TYPE,
AssignPolicySteps,
AssignPolicyStepsNames,
} from '@odf/mco/constants';
import { getName } from '@odf/shared/selectors';
import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook';
import { TFunction } from 'i18next';
Expand All @@ -11,33 +15,34 @@ import {
Alert,
AlertVariant,
} from '@patternfly/react-core';
import { DRPolicyType, DataPolicyType } from '../utils/types';
import { AssignPolicyViewState, PVCSelectorType } from '../utils/reducer';
import { DRPolicyType } from '../utils/types';
import '../../../../style.scss';
import '../style.scss';

const isPVCSelectorFound = (dataPolicy: DRPolicyType) =>
!!dataPolicy?.placementControlInfo?.length &&
!!dataPolicy.placementControlInfo.every((drpc) => !!drpc.pvcSelector?.length);
const isPVCSelectorFound = (pvcSelectors: PVCSelectorType[]) =>
!!pvcSelectors.length &&
!!pvcSelectors.every((pvcSelector) => !!pvcSelector.labels?.length);

const isDRPolicySelected = (dataPolicy: DRPolicyType) => !!getName(dataPolicy);

const canJumpToNextStep = (
stepName: string,
dataPolicy: DataPolicyType,
state: AssignPolicyViewState,
t: TFunction
) => {
switch (stepName) {
case AssignPolicyStepsNames(t)[AssignPolicySteps.Policy]:
return isDRPolicySelected(dataPolicy);
return isDRPolicySelected(state.policy);
case AssignPolicyStepsNames(t)[AssignPolicySteps.PersistentVolumeClaim]:
return isPVCSelectorFound(dataPolicy);
return isPVCSelectorFound(state.persistentVolumeClaim.pvcSelectors);
default:
return false;
}
};

export const AssignPolicyViewFooter: React.FC<AssignPolicyViewFooterProps> = ({
dataPolicy,
state,
stepIdReached,
isValidationEnabled,
setStepIdReached,
Expand All @@ -53,7 +58,7 @@ export const AssignPolicyViewFooter: React.FC<AssignPolicyViewFooterProps> = ({
const stepId = activeStep.id as number;
const stepName = activeStep.name as string;

const canJumpToNext = canJumpToNextStep(stepName, dataPolicy, t);
const canJumpToNext = canJumpToNextStep(stepName, state, t);
const validationError = isValidationEnabled && !canJumpToNext;

const moveToNextStep = () => {
Expand Down Expand Up @@ -127,7 +132,8 @@ export const AssignPolicyViewFooter: React.FC<AssignPolicyViewFooterProps> = ({
};

type AssignPolicyViewFooterProps = {
dataPolicy: DataPolicyType;
state: AssignPolicyViewState;
appType: APPLICATION_TYPE;
stepIdReached: number;
isValidationEnabled: boolean;
setStepIdReached: React.Dispatch<React.SetStateAction<number>>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export const DataPolicyStatus: React.FC<DataPolicyStatusProps> = ({
{...(isValidated
? { title: t('Validated'), icon: <GreenCheckCircleIcon /> }
: {
title: t('Not Validated'),
title: t('Not validated'),
icon: <RedExclamationCircleIcon />,
})}
/>
Expand Down Expand Up @@ -199,7 +199,7 @@ export const PolicyConfigViewer: React.FC<PolicyConfigViewerProps> = ({
)}
<DescriptionListItem
term={t('PVC label selector')}
description={<Labels numLabels={3} labels={labels} />}
description={<Labels numLabels={5} labels={labels} />}
/>
</DescriptionList>
</div>
Expand Down
Loading