Skip to content

Commit 68274db

Browse files
fix(ui) Stop showing validation errors and enable "Next" when in YAML editor (#15783)
1 parent a80e803 commit 68274db

File tree

5 files changed

+54
-35
lines changed

5 files changed

+54
-35
lines changed

datahub-web-react/src/app/ingestV2/source/multiStepBuilder/steps/step2ConnectionDetails/sections/recipeSection/RecipeSection.tsx

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { message } from 'antd';
1+
import { Form, message } from 'antd';
22
import React, { useCallback, useEffect, useMemo, useState } from 'react';
33
import YAML from 'yamljs';
44

@@ -28,16 +28,31 @@ export function RecipeSection({ state, displayRecipe, sourceConfigs, setStagedRe
2828
setIsRecipeValid?.(!hasForm || isEditing || !!state.isConnectionDetailsValid);
2929
}, [hasForm, isEditing, setIsRecipeValid, state.isConnectionDetailsValid]);
3030

31+
const [form] = Form.useForm();
32+
const runFormValidation = useCallback(() => {
33+
form.validateFields()
34+
.then(() => {
35+
setIsRecipeValid?.(true);
36+
})
37+
.catch((error) => {
38+
// FYI: `error` could be triggered with empty list of `errorFields` when form is valid
39+
const hasErrors = (error.errorFields?.length ?? 0) > 0;
40+
setIsRecipeValid?.(!hasErrors);
41+
});
42+
}, [form, setIsRecipeValid]);
43+
3144
const onTabClick = useCallback(
3245
(activeKey) => {
3346
if (activeKey !== 'form') {
3447
setSelectedTabKey(activeKey);
48+
setIsRecipeValid?.(true); // no field validation when in yaml editor
3549
return;
3650
}
3751

3852
// Validate yaml content when switching from yaml tab to form
3953
try {
4054
YAML.parse(displayRecipe);
55+
setTimeout(runFormValidation, 0); // let form remount and then run validation
4156
setSelectedTabKey(activeKey);
4257
} catch (e) {
4358
message.destroy();
@@ -47,7 +62,7 @@ export function RecipeSection({ state, displayRecipe, sourceConfigs, setStagedRe
4762
message.warn(`Found invalid YAML. ${messageText} in order to switch views.`);
4863
}
4964
},
50-
[displayRecipe],
65+
[displayRecipe, setIsRecipeValid, runFormValidation],
5166
);
5267

5368
const tabs: Tab[] = useMemo(
@@ -58,10 +73,11 @@ export function RecipeSection({ state, displayRecipe, sourceConfigs, setStagedRe
5873
component: (
5974
<RecipeForm
6075
state={state}
76+
form={form}
77+
runFormValidation={runFormValidation}
6178
displayRecipe={displayRecipe}
6279
sourceConfigs={sourceConfigs}
6380
setStagedRecipe={setStagedRecipe}
64-
setIsRecipeValid={setIsRecipeValid}
6581
/>
6682
),
6783
},
@@ -71,7 +87,7 @@ export function RecipeSection({ state, displayRecipe, sourceConfigs, setStagedRe
7187
component: <YamlEditor value={displayRecipe} onChange={setStagedRecipe} />,
7288
},
7389
],
74-
[displayRecipe, state, sourceConfigs, setStagedRecipe, setIsRecipeValid],
90+
[displayRecipe, state, sourceConfigs, setStagedRecipe, form, runFormValidation],
7591
);
7692

7793
if (hasForm) {

datahub-web-react/src/app/ingestV2/source/multiStepBuilder/steps/step2ConnectionDetails/sections/recipeSection/recipeForm/RecipeForm.tsx

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { spacing } from '@components';
2-
import { Form, message } from 'antd';
2+
import { Form, FormInstance, message } from 'antd';
33
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
44
import styled from 'styled-components/macro';
55
import YAML from 'yamljs';
@@ -56,14 +56,22 @@ function getInitialValues(displayRecipe: string, allFields: RecipeField[]) {
5656
interface Props {
5757
state: MultiStepSourceBuilderState;
5858
displayRecipe: string;
59+
form: FormInstance<any>;
60+
runFormValidation: () => void;
5961
sourceConfigs?: SourceConfig;
6062
setStagedRecipe: (recipe: string) => void;
6163
selectedSource?: IngestionSource;
62-
setIsRecipeValid?: (isValid: boolean) => void;
6364
}
6465

65-
function RecipeForm({ state, displayRecipe, sourceConfigs, setStagedRecipe, selectedSource, setIsRecipeValid }: Props) {
66-
const [form] = Form.useForm();
66+
function RecipeForm({
67+
state,
68+
displayRecipe,
69+
form,
70+
runFormValidation,
71+
sourceConfigs,
72+
setStagedRecipe,
73+
selectedSource,
74+
}: Props) {
6775
const areFormValuesChangedRef = useRef<boolean>(false);
6876

6977
const formValues = Form.useWatch([], form);
@@ -79,18 +87,6 @@ function RecipeForm({ state, displayRecipe, sourceConfigs, setStagedRecipe, sele
7987
};
8088
}, [recipeFields, formValues]);
8189

82-
const runFormValidation = useCallback(() => {
83-
form.validateFields()
84-
.then(() => {
85-
setIsRecipeValid?.(true);
86-
})
87-
.catch((error) => {
88-
// FYI: `error` could be triggered with empty list of `errorFields` when form is valid
89-
const hasErrors = (error.errorFields?.length ?? 0) > 0;
90-
setIsRecipeValid?.(!hasErrors);
91-
});
92-
}, [form, setIsRecipeValid]);
93-
9490
// Run validation when fields changed. Required to revalidate hidden/shown fields
9591
useEffect(() => {
9692
// Run validation when form values were changed

datahub-web-react/src/app/ingestV2/source/multiStepBuilder/steps/step2ConnectionDetails/sections/recipeSection/recipeForm/components/CustomFormItem.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,7 @@ import styled from 'styled-components';
55

66
import { FieldLabel } from '@app/sharedV2/forms/FieldLabel';
77

8-
export const StyledFormItem = styled(Form.Item)<{
9-
$alignLeft?: boolean;
10-
$removeMargin?: boolean;
11-
$isSecretField?: boolean;
12-
}>`
8+
const StyledFormItem = styled(Form.Item)<{ $showError: boolean }>`
139
margin-bottom: 0;
1410
1511
.ant-form-item-label > label {
@@ -23,6 +19,8 @@ export const StyledFormItem = styled(Form.Item)<{
2319
2420
.ant-form-item-explain-error {
2521
color: ${colors.red[500]}; // Color of error message
22+
display: none;
23+
${({ $showError }) => !$showError && 'display: none;'}
2624
}
2725
2826
.ant-form-item-control {
@@ -34,17 +32,20 @@ export interface CustomLabelFormItemProps extends Omit<FormItemProps, 'label'> {
3432
label?: string;
3533
tooltip?: React.ReactNode;
3634
labelHelper?: React.ReactNode;
35+
showError?: boolean;
3736
}
3837

3938
export const CustomLabelFormItem: React.FC<CustomLabelFormItemProps> = ({
4039
label,
4140
tooltip,
4241
required,
4342
labelHelper,
43+
showError = true,
4444
...formItemProps
4545
}) => {
4646
return (
4747
<StyledFormItem
48+
$showError={showError}
4849
label={
4950
label ? (
5051
<FieldLabel label={label} required={required} tooltip={tooltip} labelHelper={labelHelper} />

datahub-web-react/src/app/ingestV2/source/multiStepBuilder/steps/step2ConnectionDetails/sections/recipeSection/recipeForm/fields/RecipeFormItem.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export function RecipeFormItem({
5151
name={recipeField?.name}
5252
tooltip={showTooltip ? (recipeField?.tooltip ?? tooltip) : undefined}
5353
rules={rules}
54+
showError={false}
5455
{...props}
5556
>
5657
{children}

datahub-web-react/src/app/sharedV2/forms/multiStepForm/MultiStepFormBottomPanel.tsx

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Button, Text } from '@components';
1+
import { Button, Text, Tooltip } from '@components';
22
import React, { useCallback, useMemo, useState } from 'react';
33
import styled from 'styled-components';
44

@@ -90,16 +90,21 @@ export function MultiStepFormBottomPanel<TState, TStep extends Step>({
9090
);
9191

9292
if (canGoToNext()) {
93-
buttons.push(
94-
<Button
95-
key="next"
96-
size="sm"
97-
disabled={!isCurrentStepCompleted()}
98-
onClick={goToNext}
99-
data-testid="next-button"
100-
>
93+
const isDisabled = !isCurrentStepCompleted();
94+
const nextButton = (
95+
<Button key="next" size="sm" disabled={isDisabled} onClick={goToNext} data-testid="next-button">
10196
Next
102-
</Button>,
97+
</Button>
98+
);
99+
100+
buttons.push(
101+
isDisabled ? (
102+
<Tooltip key="next" title="Please complete all required fields before moving to the next step">
103+
<span>{nextButton}</span>
104+
</Tooltip>
105+
) : (
106+
nextButton
107+
),
103108
);
104109
}
105110

0 commit comments

Comments
 (0)