Skip to content

Commit 129dd13

Browse files
[ITEP-27174] Cluster Edit: Fix Cluster Label Metadata (#88)
1 parent 8903b25 commit 129dd13

7 files changed

Lines changed: 156 additions & 228 deletions

File tree

apps/cluster-orch/src/components/organism/ClusterEdit/MetadataLabels/MetadataLabels.cy.tsx

Lines changed: 33 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,41 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6-
import { Provider } from "react-redux";
7-
import { store } from "../../../../store";
8-
import { updateClusterLabels } from "../../../../store/reducers/cluster";
6+
import { clusterA, ObjectKeyValue, objectToMetadataPair } from "@orch-ui/utils";
7+
import { setupStore } from "../../../../store";
8+
import { useAppSelector } from "../../../../store/hooks";
99
import MetadataLabels from "./MetadataLabels";
1010
import MetadataLabelsPom from "./MetadataLabels.pom";
1111

12+
const TestComponent = () => {
13+
const clusterLabels = useAppSelector((state) => state.cluster.labels);
14+
return (
15+
<MetadataLabels
16+
inheritedMetadata={[
17+
{ key: "region", value: "region1", type: "region" },
18+
{ key: "site", value: "site1", type: "site" },
19+
]}
20+
clusterLabels={objectToMetadataPair(clusterLabels as ObjectKeyValue)}
21+
/>
22+
);
23+
};
24+
1225
const pom = new MetadataLabelsPom();
1326
describe("<MetadataLabels/> should", () => {
1427
beforeEach(() => {
15-
store.dispatch(
16-
updateClusterLabels({
17-
"customer-one": "value-one",
18-
"customer-two": "value-two",
19-
"customer-three": "value-three",
28+
const labels = {
29+
"customer-one": "value-one",
30+
"customer-two": "value-two",
31+
"customer-three": "value-three",
32+
};
33+
cy.mount(<TestComponent />, {
34+
reduxStore: setupStore({
35+
cluster: {
36+
...clusterA,
37+
labels,
38+
},
2039
}),
21-
);
22-
23-
cy.mount(
24-
<Provider store={store}>
25-
<MetadataLabels
26-
regionMeta={[{ key: "region", value: "region1" }]}
27-
siteMeta={[{ key: "site", value: "site1", type: "site" }]}
28-
clusterLabels={{ "customer-one": "value-one" }}
29-
getUserDefinedMeta={(value) => cy.stub(value)}
30-
getInheritedMeta={(value) => cy.stub(value)}
31-
/>
32-
</Provider>,
33-
);
40+
});
3441
});
3542

3643
it("render component", () => {
@@ -41,34 +48,19 @@ describe("<MetadataLabels/> should", () => {
4148

4249
pom.metadataDisplay.getByIndex(1).should("contain", "site = site1");
4350
pom.metadataDisplay.getTagByIndex(1).should("have.text", "S");
44-
// TODO: 22694 labels design to be updated
45-
// pom.metadataForm.el.pair
46-
// .eq(0)
47-
// .children()
48-
// .eq(0)
49-
// .find("input")
50-
// .invoke("attr", "value")
51-
// .should("equal", "customer-one");
52-
// pom.metadataForm.el.pair
53-
// .eq(0)
54-
// .children()
55-
// .eq(1)
56-
// .find("input")
57-
// .invoke("attr", "value")
58-
// .should("equal", "value-one");
5951
});
6052

61-
it("edit labels", () => {
62-
pom.root.should("exist");
63-
53+
it("should see inherited metadata", () => {
6454
pom.metadataDisplay.getByIndex(0).should("contain", "region = region1");
6555
pom.metadataDisplay.getTagByIndex(0).should("have.text", "R");
6656

6757
pom.metadataDisplay.getByIndex(1).should("contain", "site = site1");
6858
pom.metadataDisplay.getTagByIndex(1).should("have.text", "S");
59+
});
6960

61+
it("should delete labels", () => {
62+
pom.getMetadataKeyInput(0).should("contain.value", "customer-one");
7063
pom.metadataForm.el.delete.eq(0).click();
71-
72-
pom.metadataForm.el.pair.should("not.exist");
64+
pom.getMetadataKeyInput(0).should("not.contain.value", "customer-one");
7365
});
7466
});

apps/cluster-orch/src/components/organism/ClusterEdit/MetadataLabels/MetadataLabels.pom.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,12 @@ class MetadataLabelsPom extends CyPom<Selectors> {
1818
constructor(public rootCy: string = "metadataLabels") {
1919
super(rootCy, [...dataCySelectors]);
2020
}
21+
22+
getMetadataKeyInput(index: number) {
23+
return this.metadataForm.el.pair
24+
.eq(index)
25+
.find("[data-cy='metadataKey'] input")
26+
.first();
27+
}
2128
}
2229
export default MetadataLabelsPom;

apps/cluster-orch/src/components/organism/ClusterEdit/MetadataLabels/MetadataLabels.tsx

Lines changed: 9 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -10,108 +10,23 @@ import {
1010
MetadataPair,
1111
TypedMetadata,
1212
} from "@orch-ui/components";
13+
import { metadataPairToObject } from "@orch-ui/utils";
1314
import { Heading, MessageBanner } from "@spark-design/react";
14-
import { useEffect, useState } from "react";
1515
import { useAppDispatch } from "../../../../store/hooks";
1616
import { updateClusterLabels } from "../../../../store/reducers/cluster";
1717

1818
const dataCy = "metadataLabels";
19-
2019
interface MetadataLabelsProps {
21-
regionMeta: TypedMetadata[];
22-
siteMeta: TypedMetadata[];
23-
clusterLabels: object;
24-
getInheritedMeta: (label: MetadataPair[]) => void;
25-
getUserDefinedMeta: (metadata: MetadataPair[]) => void;
20+
inheritedMetadata: TypedMetadata[];
21+
clusterLabels: MetadataPair[];
2622
}
2723

2824
const MetadataLabels = ({
29-
regionMeta,
30-
siteMeta,
25+
inheritedMetadata,
3126
clusterLabels,
32-
getInheritedMeta,
3327
}: MetadataLabelsProps) => {
34-
const dispatch = useAppDispatch();
35-
3628
const cy = { "data-cy": dataCy };
37-
38-
const [userLabels, setUserLabels] = useState<MetadataPair[]>();
39-
const [hiddenLabels, setHiddenLabels] = useState<MetadataPair[]>();
40-
const [inheritedMetadata, setInheritedMetadata] = useState<TypedMetadata[]>(
41-
[],
42-
);
43-
44-
// Inherited metadata array for metadata display
45-
useEffect(() => {
46-
let combinedMetadata: TypedMetadata[] = [];
47-
48-
combinedMetadata = [
49-
...combinedMetadata,
50-
...regionMeta.map(({ key, value }) => ({
51-
key,
52-
value,
53-
type: "region",
54-
})),
55-
];
56-
57-
combinedMetadata = [
58-
...combinedMetadata,
59-
...siteMeta.map(({ key, value }) => ({
60-
key,
61-
value,
62-
type: "site",
63-
})),
64-
];
65-
setInheritedMetadata(combinedMetadata);
66-
getInheritedMeta(typedToMeta(combinedMetadata));
67-
}, [regionMeta, clusterLabels]);
68-
69-
// Filter to only show user defined labels
70-
useEffect(() => {
71-
const userDefinedLabels: { [key: string]: string } = {};
72-
const hidLabels: { [key: string]: string } = {};
73-
Object.entries(clusterLabels).forEach((label) => {
74-
hidLabels[label[0]] = label[1];
75-
});
76-
setUserLabels(labelsToPair(userDefinedLabels));
77-
setHiddenLabels(labelsToPair(hidLabels));
78-
}, [clusterLabels]);
79-
80-
// Typed to meta
81-
const typedToMeta = (pairs: TypedMetadata[]) => {
82-
const newArray: MetadataPair[] = [];
83-
pairs.forEach((label) => {
84-
newArray.push({
85-
key: label.key,
86-
value: label.value,
87-
});
88-
});
89-
return newArray;
90-
};
91-
92-
// Label conversion
93-
const labelsToPair = (data: any) => {
94-
const labelPair: MetadataPair[] = [];
95-
Object.keys(data).map(function (index) {
96-
if (data) {
97-
const label = {
98-
key: index,
99-
value: data[index],
100-
};
101-
labelPair.push(label);
102-
return data[index];
103-
}
104-
});
105-
return labelPair;
106-
};
107-
108-
const labelsToObject = (pairs: MetadataPair[]) => {
109-
const labelObject: any = {};
110-
pairs.forEach((tags) => {
111-
labelObject[tags.key] = tags.value;
112-
});
113-
return labelObject;
114-
};
29+
const dispatch = useAppDispatch();
11530

11631
return (
11732
<>
@@ -133,18 +48,13 @@ const MetadataLabels = ({
13348

13449
<Flex cols={[6, 6]}>
13550
<MetadataForm
136-
pairs={userLabels ?? []}
51+
pairs={clusterLabels}
13752
leftLabelText="Key"
13853
rightLabelText="Value"
13954
buttonText="+"
140-
onUpdate={(kv) => {
141-
setUserLabels(kv);
142-
143-
dispatch(
144-
updateClusterLabels(
145-
labelsToObject(kv.concat(hiddenLabels ?? [])),
146-
),
147-
);
55+
onUpdate={(metadata) => {
56+
// Update the cluster labels in the redux store
57+
dispatch(updateClusterLabels(metadataPairToObject(metadata)));
14858
}}
14959
/>
15060
</Flex>

apps/cluster-orch/src/components/pages/ClusterEdit/ClusterEdit.tsx

Lines changed: 37 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@ import {
1010
setActiveNavItem,
1111
setBreadcrumb as setClusterBreadcrumb,
1212
} from "@orch-ui/components";
13-
import { SharedStorage } from "@orch-ui/utils";
13+
import {
14+
ObjectKeyValue,
15+
objectToMetadataPair,
16+
SharedStorage,
17+
} from "@orch-ui/utils";
1418
import { Button, ButtonGroup, Heading, Toast } from "@spark-design/react";
1519
import {
1620
ButtonSize,
@@ -58,13 +62,13 @@ const ClusterEdit = ({ setBreadcrumb, HostsTableRemote }: ClusterEditProps) => {
5862
{},
5963
);
6064
const currentCluster = useAppSelector(getCluster);
65+
// Labels is of type `object` in API. This is not recognized as ObjectKeyValue `{[key: string]: string}`
66+
const currentClusterLabel = (currentCluster.labels ?? {}) as ObjectKeyValue;
6167

6268
const [clusterTemplateName, setClusterTemplateName] = useState<string>("");
6369
const [clusterTemplateVersion, setClusterTemplateVersion] =
6470
useState<string>("");
65-
6671
const [inheritedMeta, setInheritedMeta] = useState<MetadataPair[]>([]); // Set Inherited Data
67-
const [userDefinedMeta, setUserDefinedMeta] = useState<MetadataPair[]>([]); // Set Custom Input data
6872
const [firstHostId, setFirstHostId] = useState<string>();
6973
const [siteId, setSiteId] = useState<string>();
7074

@@ -112,6 +116,29 @@ const ClusterEdit = ({ setBreadcrumb, HostsTableRemote }: ClusterEditProps) => {
112116
},
113117
{ skip: !siteId || !SharedStorage.project?.name },
114118
);
119+
120+
// Inherited metadata array for metadata display
121+
useEffect(() => {
122+
if (siteData) {
123+
const regionMeta = siteData?.inheritedMetadata?.location ?? [];
124+
const siteMeta = siteData?.metadata ?? [];
125+
/** Combine Region and Site Metadata (a.k.a Inherited Metadata) */
126+
const combinedMetadata = [
127+
...regionMeta.map(({ key, value }) => ({
128+
key,
129+
value,
130+
type: "region",
131+
})),
132+
...siteMeta.map(({ key, value }) => ({
133+
key,
134+
value,
135+
type: "site",
136+
})),
137+
];
138+
setInheritedMeta(combinedMetadata);
139+
}
140+
}, [siteData]);
141+
115142
const [
116143
editClusterByTemplateName,
117144
{ isSuccess: isEditTemplateSuccess, isError: isEditTemplateError },
@@ -267,30 +294,6 @@ const ClusterEdit = ({ setBreadcrumb, HostsTableRemote }: ClusterEditProps) => {
267294

268295
return newNodes;
269296
};
270-
// labels to object
271-
const labelsToObject = (pairs: MetadataPair[]) => {
272-
const labelObject: any = {};
273-
pairs.forEach((tags) => {
274-
labelObject[tags.key] = tags.value;
275-
});
276-
return labelObject;
277-
};
278-
279-
// object to labels
280-
const objectToLabels = (data: any) => {
281-
const labelPair: MetadataPair[] = [];
282-
Object.keys(data).map(function (personNamedIndex) {
283-
if (data) {
284-
const label = {
285-
key: personNamedIndex,
286-
value: data[personNamedIndex],
287-
};
288-
labelPair.push(label);
289-
return data[personNamedIndex];
290-
}
291-
});
292-
return labelPair;
293-
};
294297

295298
/**
296299
* editHandler checks for all the required updates and creates a list of promises
@@ -313,15 +316,18 @@ const ClusterEdit = ({ setBreadcrumb, HostsTableRemote }: ClusterEditProps) => {
313316
projectName: SharedStorage.project?.name ?? "",
314317
name: currentCluster.name ?? "",
315318
clusterLabels: {
316-
labels: labelsToObject(objectToLabels(currentCluster.labels)),
319+
labels: currentClusterLabel,
317320
},
318321
}).unwrap();
319322
promises.push(p);
320323

321324
const metadataP = updateMetadata({
322325
projectName: SharedStorage.project?.name ?? "",
323326
metadataList: {
324-
metadata: [...userDefinedMeta, ...inheritedMeta],
327+
metadata: [
328+
...objectToMetadataPair(currentClusterLabel),
329+
...inheritedMeta,
330+
],
325331
},
326332
}).unwrap();
327333
promises.push(metadataP);
@@ -347,13 +353,9 @@ const ClusterEdit = ({ setBreadcrumb, HostsTableRemote }: ClusterEditProps) => {
347353
clusterName={clusterName}
348354
/>
349355

350-
{/** TODO: MetadataLabel needs to be refactored. This causing a performance issue with rerendering in circle. */}
351356
<MetadataLabels
352-
regionMeta={siteData?.inheritedMetadata?.location ?? []}
353-
siteMeta={siteData?.metadata ?? []}
354-
clusterLabels={currentCluster.labels ?? {}}
355-
getInheritedMeta={(meta) => setInheritedMeta(meta)}
356-
getUserDefinedMeta={(meta) => setUserDefinedMeta(meta)}
357+
inheritedMetadata={inheritedMeta}
358+
clusterLabels={objectToMetadataPair(currentClusterLabel)}
357359
/>
358360

359361
{siteData && siteData.region && (

0 commit comments

Comments
 (0)