Skip to content

Commit 8f9f40a

Browse files
committed
Address feedback for MTV-1686 fixes
1 parent 3d530f4 commit 8f9f40a

File tree

10 files changed

+87
-54
lines changed

10 files changed

+87
-54
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import React, { PropsWithChildren } from 'react';
2+
3+
import { Spinner, SpinnerProps } from '@patternfly/react-core';
4+
5+
type LoadingSpinnerProps = PropsWithChildren &
6+
SpinnerProps & {
7+
isLoading: boolean;
8+
};
9+
10+
export const LoadingSpinner: React.FC<LoadingSpinnerProps> = ({
11+
isLoading,
12+
children,
13+
...spinnerProps
14+
}) => (isLoading ? <Spinner {...spinnerProps} /> : children);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { LoadingSpinner } from './LoadingSpinner';

packages/common/src/components/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export * from './FormGroupWithHelpText';
66
export * from './HelpIconPopover';
77
export * from './Icons';
88
export * from './LoadingDots';
9+
export * from './LoadingSpinner';
910
export * from './Page';
1011
export * from './QueryClientHoc';
1112
export * from './TableView';

packages/forklift-console-plugin/src/modules/Plans/actions/PlanActionsDropdownItems.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react';
1+
import React, { useMemo } from 'react';
22
import { DropdownItemLink } from 'src/components/actions/DropdownItemLink';
33
import { useModal } from 'src/modules/Providers/modals';
44
import { getResourceUrl } from 'src/modules/Providers/utils/helpers';
@@ -53,7 +53,7 @@ export const PlanActionsDropdownItems = ({ data }: PlanActionsDropdownItemsProps
5353
showModal(<PlanDeleteModal resource={plan} model={PlanModel} />);
5454
};
5555

56-
const startActionDescription = React.useMemo(() => {
56+
const startActionDescription = useMemo(() => {
5757
if (isPlanValidating) {
5858
return t('The plan is being validated');
5959
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { V1beta1Plan } from '@kubev2v/types';
2+
3+
import { PlanConditionStatus } from '../types/PlanCondition';
4+
5+
/**
6+
* Gets a record of plan types with truthful ('True') statuses
7+
* @param plan V1beta1Plan
8+
* @returns Record<string, boolean>
9+
*/
10+
export const getConditionTypes = (plan: V1beta1Plan): Record<string, boolean> =>
11+
plan?.status?.conditions?.reduce((acc, condition) => {
12+
if (condition.status === PlanConditionStatus.True) {
13+
acc[condition.type] = true;
14+
}
15+
16+
return acc;
17+
}, {});

packages/forklift-console-plugin/src/modules/Plans/utils/helpers/getPlanPhase.ts

+22-22
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,43 @@
11
import { V1beta1Plan } from '@kubev2v/types';
22

33
import { PlanData, PlanPhase } from '../types';
4+
import { PlanConditionType } from '../types/PlanCondition';
5+
6+
import { getConditionTypes } from './getConditionTypes';
47

58
export const getPlanPhase = (data: PlanData): PlanPhase => {
69
const plan = data?.obj;
710

811
if (!plan) return PlanPhase.Unknown;
912

1013
// Check condition type
11-
const conditions = getConditions(plan);
14+
const conditionTypes = getConditionTypes(plan);
1215

13-
if (!conditions || conditions?.length < 1) {
16+
if (!Object.keys(conditionTypes).length) {
1417
return PlanPhase.Unknown;
1518
}
1619

1720
// Check for Archived
18-
if (plan?.spec?.archived && !conditions.includes('Archived')) {
21+
if (plan?.spec?.archived && !conditionTypes[PlanConditionType.Archived]) {
1922
return PlanPhase.Archiving;
2023
}
2124

22-
if (conditions.includes('Archived')) {
25+
if (conditionTypes[PlanConditionType.Archived]) {
2326
return PlanPhase.Archived;
2427
}
2528

2629
// Check for Succeeded
27-
if (conditions.includes('Succeeded')) {
30+
if (conditionTypes[PlanConditionType.Succeeded]) {
2831
return PlanPhase.Succeeded;
2932
}
3033

3134
// Check for Canceled
32-
if (conditions.includes('Canceled')) {
35+
if (conditionTypes[PlanConditionType.Canceled]) {
3336
return PlanPhase.Canceled;
3437
}
3538

3639
// CHeck for Running
37-
if (conditions.includes('Executing')) {
40+
if (conditionTypes[PlanConditionType.Executing]) {
3841
return PlanPhase.Running;
3942
}
4043

@@ -50,7 +53,7 @@ export const getPlanPhase = (data: PlanData): PlanPhase => {
5053
// Check for vm errors
5154
const vmError = plan?.status?.migration?.vms?.find((vm) => vm?.error);
5255

53-
if (conditions.includes('Failed')) {
56+
if (conditionTypes[PlanConditionType.Failed]) {
5457
return PlanPhase.Failed;
5558
}
5659

@@ -67,40 +70,40 @@ export const getPlanPhase = (data: PlanData): PlanPhase => {
6770
return PlanPhase.Warning;
6871
}
6972

70-
if (conditions.includes('Ready')) {
73+
if (conditionTypes[PlanConditionType.Ready]) {
7174
return PlanPhase.Ready;
7275
}
7376

7477
return PlanPhase.NotReady;
7578
};
7679

7780
export const canPlanStart = (plan: V1beta1Plan) => {
78-
const conditions = getConditions(plan);
81+
const conditionTypes = getConditionTypes(plan);
7982

8083
return (
81-
conditions?.includes('Ready') &&
82-
!conditions?.includes('Executing') &&
83-
!conditions?.includes('Succeeded') &&
84+
conditionTypes[PlanConditionType.Ready] &&
85+
!conditionTypes[PlanConditionType.Executing] &&
86+
!conditionTypes[PlanConditionType.Succeeded] &&
8487
!plan?.spec?.archived
8588
);
8689
};
8790

8891
export const canPlanReStart = (plan: V1beta1Plan) => {
89-
const conditions = getConditions(plan);
92+
const conditionTypes = getConditionTypes(plan);
9093

91-
return conditions?.includes('Failed') || conditions?.includes('Canceled');
94+
return conditionTypes[PlanConditionType.Failed] || conditionTypes[PlanConditionType.Canceled];
9295
};
9396

9497
export const isPlanExecuting = (plan: V1beta1Plan) => {
95-
const conditions = getConditions(plan);
98+
const conditionTypes = getConditionTypes(plan);
9699

97-
return conditions?.includes('Executing');
100+
return conditionTypes[PlanConditionType.Executing];
98101
};
99102

100103
export const isPlanSucceeded = (plan: V1beta1Plan) => {
101-
const conditions = getConditions(plan);
104+
const conditionTypes = getConditionTypes(plan);
102105

103-
return conditions?.includes('Succeeded');
106+
return conditionTypes[PlanConditionType.Succeeded];
104107
};
105108

106109
export const isPlanEditable = (plan: V1beta1Plan) => {
@@ -122,6 +125,3 @@ export const isPlanArchived = (plan: V1beta1Plan) => {
122125

123126
return planStatus === PlanPhase.Archiving || planStatus === PlanPhase.Archived;
124127
};
125-
126-
const getConditions = (obj: V1beta1Plan) =>
127-
obj?.status?.conditions?.filter((c) => c.status === 'True').map((c) => c.type);

packages/forklift-console-plugin/src/modules/Plans/utils/helpers/getPlanSummaryStatus.ts

+20-19
Original file line numberDiff line numberDiff line change
@@ -5,44 +5,45 @@ import {
55
PlanConditionType,
66
} from '../types/PlanCondition';
77

8+
import { getConditionTypes } from './getConditionTypes';
9+
810
export const getPlanSummaryStatus = (data: PlanData): PlanSummaryStatus => {
911
const plan = data?.obj;
10-
const conditionTypes = plan?.status?.conditions?.reduce((acc, condition) => {
11-
if (condition.status === PlanConditionStatus.True) {
12-
acc.push(condition.type);
13-
}
14-
15-
return acc;
16-
}, []);
12+
const conditionTypes = getConditionTypes(plan);
1713

18-
if (!conditionTypes?.length) {
14+
if (!Object.keys(conditionTypes)?.length) {
1915
return;
2016
}
2117

22-
const isArchiving = plan?.spec?.archived && !conditionTypes.includes(PlanConditionType.Archived);
18+
const {
19+
[PlanConditionType.Archived]: isArchived,
20+
[PlanConditionType.Canceled]: isCanceled,
21+
[PlanConditionType.Executing]: isExecuting,
22+
[PlanConditionType.Running]: isRunning,
23+
[PlanConditionType.Failed]: isFailed,
24+
[PlanConditionType.Succeeded]: isSucceeded,
25+
[PlanConditionType.Ready]: isReady,
26+
} = conditionTypes;
2327

2428
// Archived
25-
if (isArchiving || conditionTypes.includes(PlanConditionType.Archived)) {
29+
if ((plan?.spec?.archived && !isArchived) || isArchived) {
2630
return PlanSummaryStatus.Archived;
2731
}
2832

2933
// Canceled
30-
if (conditionTypes.includes(PlanConditionType.Canceled)) {
34+
if (isCanceled) {
3135
return PlanSummaryStatus.Canceled;
3236
}
3337

3438
// Running
35-
if (
36-
conditionTypes.includes(PlanConditionType.Executing) ||
37-
conditionTypes.includes(PlanConditionType.Running)
38-
) {
39+
if (isExecuting || isRunning) {
3940
return PlanSummaryStatus.Running;
4041
}
4142

4243
// Incomplete
43-
const vmError = plan?.status?.migration?.vms?.find((vm) => vm?.error);
44+
const hasVmError = !!plan?.status?.migration?.vms?.find((vm) => vm?.error);
4445

45-
if (conditionTypes.includes(PlanConditionType.Failed) || vmError) {
46+
if (isFailed || hasVmError) {
4647
return PlanSummaryStatus.Incomplete;
4748
}
4849

@@ -63,12 +64,12 @@ export const getPlanSummaryStatus = (data: PlanData): PlanSummaryStatus => {
6364
}
6465

6566
// Complete
66-
if (conditionTypes.includes(PlanConditionType.Succeeded)) {
67+
if (isSucceeded) {
6768
return PlanSummaryStatus.Complete;
6869
}
6970

7071
// Ready to start
71-
if (conditionTypes.includes(PlanConditionType.Ready)) {
72+
if (isReady) {
7273
return PlanSummaryStatus.ReadyToStart;
7374
}
7475
};

packages/forklift-console-plugin/src/modules/Plans/utils/helpers/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// @index(['./*', /style/g], f => `export * from '${f.path}';`)
2+
export * from './getConditionTypes';
23
export * from './getMigrationPhase';
34
export * from './getMigrationVmsCounts';
45
export * from './getPlanPhase';

packages/forklift-console-plugin/src/modules/Plans/views/list/components/PlanStatusCell/PlanStatusCell.tsx

+5-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ import { useModal } from 'src/modules/Providers/modals';
1212
import { getResourceUrl } from 'src/modules/Providers/utils';
1313
import { useForkliftTranslation } from 'src/utils/i18n';
1414

15+
import { LoadingSpinner } from '@kubev2v/common';
1516
import { PlanModel, PlanModelRef } from '@kubev2v/types';
16-
import { Button, Flex, FlexItem, Split, SplitItem } from '@patternfly/react-core';
17+
import { Button, Flex, FlexItem, spinnerSize, Split, SplitItem } from '@patternfly/react-core';
1718
import StartIcon from '@patternfly/react-icons/dist/esm/icons/play-icon';
1819

1920
import { CellProps } from '../CellProps';
@@ -95,7 +96,9 @@ export const PlanStatusCell: React.FC<CellProps> = ({ data }) => {
9596
className="plan-status-cell-label-section"
9697
>
9798
<FlexItem>
98-
<PlanStatusCellLabel status={planStatus} isLoading={isPlanLoading} />
99+
<LoadingSpinner isLoading={isPlanLoading} size={spinnerSize.md}>
100+
<PlanStatusCellLabel status={planStatus} />
101+
</LoadingSpinner>
99102
</FlexItem>
100103

101104
{progressValue !== 0 && isPlanLoading && (

packages/forklift-console-plugin/src/modules/Plans/views/list/components/PlanStatusCell/PlanStatusCellLabel.tsx

+4-9
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,15 @@ import React from 'react';
22
import { PlanSummaryStatus } from 'src/modules/Plans/utils';
33
import { useForkliftTranslation } from 'src/utils';
44

5-
import { Label, Spinner } from '@patternfly/react-core';
5+
import { Label } from '@patternfly/react-core';
66

7-
interface PlanStatusCellLabelProps {
7+
type PlanStatusCellLabelProps = {
88
status: PlanSummaryStatus;
9-
isLoading: boolean;
10-
}
9+
};
1110

12-
export const PlanStatusCellLabel: React.FC<PlanStatusCellLabelProps> = ({ status, isLoading }) => {
11+
export const PlanStatusCellLabel: React.FC<PlanStatusCellLabelProps> = ({ status }) => {
1312
const { t } = useForkliftTranslation();
1413

15-
if (isLoading) {
16-
return <Spinner size="md" />;
17-
}
18-
1914
if (!status) {
2015
return t('Validating...');
2116
}

0 commit comments

Comments
 (0)