Skip to content

Commit 19a72e3

Browse files
authored
New deployment forms: add json-schema-based table (#5412)
* Remove unused deps Signed-off-by: Antonio Gamez Diaz <[email protected]> * Refactor schema/yaml util functions Signed-off-by: Antonio Gamez Diaz <[email protected]> * Delete no longer used components Signed-off-by: Antonio Gamez Diaz <[email protected]> * Add some required changes in files Signed-off-by: Antonio Gamez Diaz <[email protected]> * Add new json-schema tabular view Signed-off-by: Antonio Gamez Diaz <[email protected]> * Add basic form components Signed-off-by: Antonio Gamez Diaz <[email protected]> * Fix some tests Signed-off-by: Antonio Gamez Diaz <[email protected]> * Fix linter issues Signed-off-by: Antonio Gamez Diaz <[email protected]> * Add test files (still WIP) Signed-off-by: Antonio Gamez Diaz <[email protected]> * Fix e2e test Signed-off-by: Antonio Gamez Diaz <[email protected]> * Fix booleanParam test Signed-off-by: Antonio Gamez Diaz <[email protected]> * Fix textParam tests Signed-off-by: Antonio Gamez Diaz <[email protected]> * Fix sliderParam tests Signed-off-by: Antonio Gamez Diaz <[email protected]> * Add remaining unit tests Signed-off-by: Antonio Gamez Diaz <[email protected]> * Fix e2e test Signed-off-by: Antonio Gamez Diaz <[email protected]> * Add wait in e2e test to prevent deboucing Signed-off-by: Antonio Gamez Diaz <[email protected]> * remove leftover Signed-off-by: Antonio Gamez Diaz <[email protected]> * remove unused useEffect Signed-off-by: Antonio Gamez Diaz <[email protected]> * move leftover file Signed-off-by: Antonio Gamez Diaz <[email protected]> * add simple validation Signed-off-by: Antonio Gamez Diaz <[email protected]> * Fix issue with duplicate key indexes Signed-off-by: Antonio Gamez Diaz <[email protected]> * Validate schema before installing/upgrading Signed-off-by: Antonio Gamez Diaz <[email protected]> * fix linter issue Signed-off-by: Antonio Gamez Diaz <[email protected]> * Remove max/min in the input of the SliderParam Signed-off-by: Antonio Gamez Diaz <[email protected]> * add comments in some types Signed-off-by: Antonio Gamez Diaz <[email protected]> * Make replicas selector more specific in e2e test Signed-off-by: Antonio Gamez Diaz <[email protected]> Signed-off-by: Antonio Gamez Diaz <[email protected]>
1 parent 75452ce commit 19a72e3

File tree

78 files changed

+4254
-6197
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+4254
-6197
lines changed

dashboard/package.json

+2-5
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,7 @@
5050
"protobufjs": "^7.1.2",
5151
"qs": "^6.11.0",
5252
"react": "^17.0.2",
53-
"react-compound-slider": "^3.4.0",
5453
"react-copy-to-clipboard": "^5.1.0",
55-
"react-dom": "^17.0.2",
5654
"react-helmet": "^6.1.0",
5755
"react-intl": "^6.1.1",
5856
"react-markdown": "^8.0.3",
@@ -61,9 +59,6 @@
6159
"react-redux": "^7.2.9",
6260
"react-router-dom": "^5.3.0",
6361
"react-router-hash-link": "^2.4.3",
64-
"react-switch": "^7.0.0",
65-
"react-tabs": "^5.1.0",
66-
"react-test-renderer": "^17.0.2",
6762
"react-tooltip": "^4.2.21",
6863
"react-transition-group": "^4.4.5",
6964
"redux": "^4.2.0",
@@ -113,7 +108,9 @@
113108
"postcss": "^8.4.16",
114109
"postcss-scss": "^4.0.5",
115110
"prettier": "^2.7.1",
111+
"react-dom": "^17.0.2",
116112
"react-scripts": "^5.0.1",
113+
"react-test-renderer": "^17.0.2",
117114
"redux-mock-store": "^1.5.4",
118115
"sass": "^1.55.0",
119116
"shx": "^0.3.4",

dashboard/src/actions/installedpackages.ts

+27-9
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import {
2727
import { getPluginsSupportingRollback } from "shared/utils";
2828
import { ActionType, deprecated } from "typesafe-actions";
2929
import { InstalledPackage } from "../shared/InstalledPackage";
30-
import { validate } from "../shared/schema";
30+
import { validateSchema, validateValuesSchema } from "../shared/schema";
3131
import { handleErrorAction } from "./auth";
3232

3333
const { createAction } = deprecated;
@@ -234,11 +234,20 @@ export function installPackage(
234234
dispatch(requestInstallPackage());
235235
try {
236236
if (values && schema) {
237-
const validation = validate(values, schema);
237+
const schemaValidation = validateSchema(schema);
238+
if (!schemaValidation.valid) {
239+
const errorText = schemaValidation?.errors
240+
?.map(e => ` - ${e.instancePath}: ${e.message}`)
241+
.join("\n");
242+
throw new UnprocessableEntityError(
243+
`The schema for this package is not valid. Please contact the package author. The following errors were found:\n${errorText}`,
244+
);
245+
}
246+
const validation = validateValuesSchema(values, schema);
238247
if (!validation.valid) {
239-
const errorText =
240-
validation.errors &&
241-
validation.errors.map(e => ` - ${e.instancePath}: ${e.message}`).join("\n");
248+
const errorText = validation?.errors
249+
?.map(e => ` - ${e.instancePath}: ${e.message}`)
250+
.join("\n");
242251
throw new UnprocessableEntityError(
243252
`The given values don't match the required format. The following errors were found:\n${errorText}`,
244253
);
@@ -283,11 +292,20 @@ export function updateInstalledPackage(
283292
dispatch(requestUpdateInstalledPackage());
284293
try {
285294
if (values && schema) {
286-
const validation = validate(values, schema);
295+
const schemaValidation = validateSchema(schema);
296+
if (!schemaValidation.valid) {
297+
const errorText = schemaValidation?.errors
298+
?.map(e => ` - ${e.instancePath}: ${e.message}`)
299+
.join("\n");
300+
throw new UnprocessableEntityError(
301+
`The schema for this package is not valid. Please contact the package author. The following errors were found:\n${errorText}`,
302+
);
303+
}
304+
const validation = validateValuesSchema(values, schema);
287305
if (!validation.valid) {
288-
const errorText =
289-
validation.errors &&
290-
validation.errors.map(e => ` - ${e.instancePath}: ${e.message}`).join("\n");
306+
const errorText = validation?.errors
307+
?.map(e => ` - ${e.instancePath}: ${e.message}`)
308+
.join("\n");
291309
throw new UnprocessableEntityError(
292310
`The given values don't match the required format. The following errors were found:\n${errorText}`,
293311
);

dashboard/src/components/AppUpgrade/AppUpgrade.test.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ beforeEach(() => {
131131
})),
132132
});
133133

134-
// mock the window.ResizeObserver, required by the MonacoEditor for the layout
134+
// mock the window.ResizeObserver, required by the MonacoDiffEditor for the layout
135135
Object.defineProperty(window, "ResizeObserver", {
136136
writable: true,
137137
configurable: true,
@@ -142,7 +142,7 @@ beforeEach(() => {
142142
})),
143143
});
144144

145-
// mock the window.HTMLCanvasElement.getContext(), required by the MonacoEditor for the layout
145+
// mock the window.HTMLCanvasElement.getContext(), required by the MonacoDiffEditor for the layout
146146
Object.defineProperty(HTMLCanvasElement.prototype, "getContext", {
147147
writable: true,
148148
configurable: true,

dashboard/src/components/AppView/AppView.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,7 @@ export default function AppView() {
404404
<div className="appview-separator">
405405
<AppValues
406406
values={
407+
//TODO(agamez): check if using this yaml.dump/load is really needed
407408
selectedInstalledPkg?.valuesApplied
408409
? yaml.dump(yaml.load(selectedInstalledPkg.valuesApplied))
409410
: ""

dashboard/src/components/DeploymentForm/DeploymentForm.test.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ import { MemoryRouter, Route, Router } from "react-router-dom";
2222
import { Kube } from "shared/Kube";
2323
import { getStore, mountWrapper } from "shared/specs/mountWrapper";
2424
import { FetchError, IStoreState, PluginNames } from "shared/types";
25-
import DeploymentFormBody from "../DeploymentFormBody/DeploymentFormBody";
2625
import DeploymentForm from "./DeploymentForm";
26+
import DeploymentFormBody from "./DeploymentFormBody";
2727

2828
const defaultProps = {
2929
pkgName: "foo",
@@ -79,7 +79,7 @@ beforeEach(() => {
7979
})),
8080
});
8181

82-
// mock the window.ResizeObserver, required by the MonacoEditor for the layout
82+
// mock the window.ResizeObserver, required by the MonacoDiffEditor for the layout
8383
Object.defineProperty(window, "ResizeObserver", {
8484
writable: true,
8585
configurable: true,
@@ -90,7 +90,7 @@ beforeEach(() => {
9090
})),
9191
});
9292

93-
// mock the window.HTMLCanvasElement.getContext(), required by the MonacoEditor for the layout
93+
// mock the window.HTMLCanvasElement.getContext(), required by the MonacoDiffEditor for the layout
9494
Object.defineProperty(HTMLCanvasElement.prototype, "getContext", {
9595
writable: true,
9696
configurable: true,

dashboard/src/components/DeploymentForm/DeploymentForm.tsx

+6-5
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,24 @@ import AvailablePackageDetailExcerpt from "components/Catalog/AvailablePackageDe
1010
import Alert from "components/js/Alert";
1111
import Column from "components/js/Column";
1212
import Row from "components/js/Row";
13+
import LoadingWrapper from "components/LoadingWrapper";
1314
import PackageHeader from "components/PackageHeader/PackageHeader";
1415
import { push } from "connected-react-router";
1516
import {
1617
AvailablePackageReference,
1718
ReconciliationOptions,
1819
} from "gen/kubeappsapis/core/packages/v1alpha1/packages";
1920
import { Plugin } from "gen/kubeappsapis/core/plugins/v1alpha1/plugins";
20-
import { useEffect, useState } from "react";
21+
import { useEffect, useRef, useState } from "react";
2122
import { useDispatch, useSelector } from "react-redux";
2223
import * as ReactRouter from "react-router-dom";
23-
import "react-tabs/style/react-tabs.css";
2424
import { Action } from "redux";
2525
import { ThunkDispatch } from "redux-thunk";
2626
import { Kube } from "shared/Kube";
2727
import { FetchError, IStoreState } from "shared/types";
2828
import * as url from "shared/url";
2929
import { getPluginsRequiringSA, k8sObjectNameRegex } from "shared/utils";
30-
import DeploymentFormBody from "../DeploymentFormBody/DeploymentFormBody";
31-
import LoadingWrapper from "../LoadingWrapper/LoadingWrapper";
30+
import DeploymentFormBody from "./DeploymentFormBody";
3231
interface IRouteParams {
3332
cluster: string;
3433
namespace: string;
@@ -63,6 +62,7 @@ export default function DeploymentForm() {
6362
const [valuesModified, setValuesModified] = useState(false);
6463
const [serviceAccountList, setServiceAccountList] = useState([] as string[]);
6564
const [reconciliationOptions, setReconciliationOptions] = useState({} as ReconciliationOptions);
65+
const formRef = useRef<HTMLFormElement>(null);
6666

6767
const error = apps.error || selectedPackage.error;
6868

@@ -209,7 +209,7 @@ export default function DeploymentForm() {
209209
</Column>
210210
<Column span={9}>
211211
{error && <Alert theme="danger">An error occurred: {error.message}</Alert>}
212-
<form onSubmit={handleDeploy}>
212+
<form onSubmit={handleDeploy} ref={formRef}>
213213
<CdsFormGroup
214214
validate={true}
215215
className="deployment-form"
@@ -267,6 +267,7 @@ export default function DeploymentForm() {
267267
setValues={handleValuesChange}
268268
appValues={appValues}
269269
setValuesModified={setValuesModifiedTrue}
270+
formRef={formRef}
270271
/>
271272
</form>
272273
</Column>

dashboard/src/components/DeploymentFormBody/AdvancedDeploymentForm.test.tsx dashboard/src/components/DeploymentForm/DeploymentFormBody/AdvancedDeploymentForm/AdvancedDeploymentForm.test.tsx

+11-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// Copyright 2021-2022 the Kubeapps contributors.
22
// SPDX-License-Identifier: Apache-2.0
33

4-
import MonacoEditor from "react-monaco-editor";
54
import { SupportedThemes } from "shared/Config";
65
import { defaultStore, getStore, mountWrapper } from "shared/specs/mountWrapper";
76
import { IStoreState } from "shared/types";
@@ -24,7 +23,7 @@ beforeEach(() => {
2423
})),
2524
});
2625

27-
// mock the window.ResizeObserver, required by the MonacoEditor for the layout
26+
// mock the window.ResizeObserver, required by the MonacoDiffEditor for the layout
2827
Object.defineProperty(window, "ResizeObserver", {
2928
writable: true,
3029
configurable: true,
@@ -35,7 +34,7 @@ beforeEach(() => {
3534
})),
3635
});
3736

38-
// mock the window.HTMLCanvasElement.getContext(), required by the MonacoEditor for the layout
37+
// mock the window.HTMLCanvasElement.getContext(), required by the MonacoDiffEditor for the layout
3938
Object.defineProperty(HTMLCanvasElement.prototype, "getContext", {
4039
writable: true,
4140
configurable: true,
@@ -51,25 +50,30 @@ afterEach(() => {
5150

5251
const defaultProps = {
5352
handleValuesChange: jest.fn(),
53+
valuesFromTheDeployedPackage: "",
54+
valuesFromTheAvailablePackage: "",
55+
deploymentEvent: "",
56+
valuesFromTheParentContainer: "",
5457
};
5558

59+
// eslint-disable-next-line jest/no-focused-tests
5660
it("includes values", () => {
5761
const wrapper = mountWrapper(
5862
defaultStore,
59-
<AdvancedDeploymentForm {...defaultProps} appValues="foo: bar" />,
63+
<AdvancedDeploymentForm {...defaultProps} valuesFromTheParentContainer="foo: bar" />,
6064
);
61-
expect(wrapper.find(MonacoEditor).prop("value")).toBe("foo: bar");
65+
expect(wrapper.find("MonacoDiffEditor").prop("value")).toBe("foo: bar");
6266
});
6367

6468
it("sets light theme by default", () => {
6569
const wrapper = mountWrapper(defaultStore, <AdvancedDeploymentForm {...defaultProps} />);
66-
expect(wrapper.find(MonacoEditor).prop("theme")).toBe("light");
70+
expect(wrapper.find("MonacoDiffEditor").prop("theme")).toBe("light");
6771
});
6872

6973
it("changes theme", () => {
7074
const wrapper = mountWrapper(
7175
getStore({ config: { theme: SupportedThemes.dark } } as Partial<IStoreState>),
7276
<AdvancedDeploymentForm {...defaultProps} />,
7377
);
74-
expect(wrapper.find(MonacoEditor).prop("theme")).toBe("vs-dark");
78+
expect(wrapper.find("MonacoDiffEditor").prop("theme")).toBe("vs-dark");
7579
});

0 commit comments

Comments
 (0)