Skip to content

Commit deba9bd

Browse files
committed
Add hooks/todo linting
1 parent 0bf5a22 commit deba9bd

7 files changed

Lines changed: 63 additions & 50 deletions

File tree

airflow-core/src/airflow/ui/rules/react.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,9 @@ export const reactRules = /** @type {const} @satisfies {FlatConfig.Config} */ ({
344344
*/
345345
[`${reactHooksNamespace}/rules-of-hooks`]: ERROR,
346346

347+
// https://github.com/facebook/react/blob/3640f38/compiler/packages/babel-plugin-react-compiler/src/CompilerError.ts#L807-L1111
348+
[`${reactHooksNamespace}/todo`]: ERROR,
349+
347350
/**
348351
* Prevent usage of button elements without an explicit type attribute.
349352
*

airflow-core/src/airflow/ui/src/components/FlexibleForm/FieldAdvancedArray.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,24 @@ export const FieldAdvancedArray = ({ name, namespace = "default", onUpdate }: Fl
4343
const parsedValue = JSON.parse(value) as unknown;
4444

4545
if (!Array.isArray(parsedValue)) {
46-
throw new TypeError(translate("flexibleForm.validationErrorArrayNotArray"));
46+
onUpdate(undefined, translate("flexibleForm.validationErrorArrayNotArray"));
47+
48+
return;
4749
}
4850

4951
if (expectedType === "number" && !parsedValue.every((item) => typeof item === "number")) {
5052
// Ensure all elements in the array are numbers
51-
throw new TypeError(translate("flexibleForm.validationErrorArrayNotNumbers"));
53+
onUpdate(undefined, translate("flexibleForm.validationErrorArrayNotNumbers"));
54+
55+
return;
5256
} else if (
5357
expectedType === "object" &&
5458
!parsedValue.every((item) => typeof item === "object" && item !== null)
5559
) {
5660
// Ensure all elements in the array are objects
57-
throw new TypeError(translate("flexibleForm.validationErrorArrayNotObject"));
61+
onUpdate(undefined, translate("flexibleForm.validationErrorArrayNotObject"));
62+
63+
return;
5864
}
5965

6066
if (paramsDict[name]) {

airflow-core/src/airflow/ui/src/pages/Connections/ConnectionForm.tsx

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -111,18 +111,13 @@ const ConnectionForm = ({
111111

112112
const validateAndPrettifyJson = (value: string) => {
113113
try {
114-
if (value.trim() === "") {
115-
setErrors((prev) => ({ ...prev, conf: undefined }));
114+
setErrors((prev) => ({ ...prev, conf: undefined }));
116115

116+
if (value.trim() === "") {
117117
return value;
118118
}
119-
const parsedJson = JSON.parse(value) as Record<string, unknown>;
120-
121-
if (typeof parsedJson !== "object" || Array.isArray(parsedJson)) {
122-
throw new TypeError('extra fields must be a valid JSON object (e.g., {"key": "value"})');
123-
}
124119

125-
setErrors((prev) => ({ ...prev, conf: undefined }));
120+
const parsedJson = JSON.parse(value) as Record<string, unknown>;
126121
const formattedJson = JSON.stringify(parsedJson, undefined, 2);
127122

128123
if (formattedJson !== extra) {

airflow-core/src/airflow/ui/src/pages/HITLTaskInstances/HITLResponseForm.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,9 @@ export const HITLResponseForm = ({ hitlDetail }: HITLResponseFormProps) => {
8888
updateHITLResponse(formData);
8989
} catch {
9090
setErrors(true);
91-
} finally {
92-
setIsSubmitting(false);
9391
}
92+
93+
setIsSubmitting(false);
9494
};
9595

9696
return (

airflow-core/src/airflow/ui/src/pages/ReactPlugin.tsx

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -24,46 +24,50 @@ import type { ReactAppResponse } from "openapi/requests/types.gen";
2424

2525
import { ErrorPage } from "./Error";
2626

27-
type PluginComponentType = FC<{
27+
export type PluginProps = {
2828
dagId?: string;
2929
mapIndex?: string;
3030
runId?: string;
3131
taskId?: string;
32-
}>;
32+
};
3333

34-
export const ReactPlugin = ({ reactApp }: { readonly reactApp: ReactAppResponse }) => {
35-
const { dagId, mapIndex, runId, taskId } = useParams();
34+
type PluginComponentType = FC<PluginProps>;
3635

37-
const Plugin = lazy(() =>
38-
// We are assuming the plugin manager is trusted and the bundle_url is safe
39-
import(/* @vite-ignore */ reactApp.bundle_url)
40-
.then(() => {
41-
// Store components in globalThis[reactApp.name] to avoid conflicts with the shared globalThis.AirflowPlugin
42-
// global variable.
43-
let pluginComponent = (globalThis as Record<string, unknown>)[reactApp.name] as
44-
| PluginComponentType
45-
| undefined;
36+
const loadPlugin = (reactApp: ReactAppResponse): Promise<{ default: PluginComponentType }> =>
37+
// We are assuming the plugin manager is trusted and the bundle_url is safe
38+
import(/* @vite-ignore */ reactApp.bundle_url)
39+
.then(() => {
40+
// Store components in globalThis[reactApp.name] to avoid conflicts with the shared globalThis.AirflowPlugin
41+
// global variable.
42+
let pluginComponent = (globalThis as Record<string, unknown>)[reactApp.name] as
43+
| PluginComponentType
44+
| undefined;
4645

47-
if (pluginComponent === undefined) {
48-
pluginComponent = (globalThis as Record<string, unknown>).AirflowPlugin as PluginComponentType;
46+
if (pluginComponent === undefined) {
47+
pluginComponent = (globalThis as Record<string, unknown>).AirflowPlugin as PluginComponentType;
4948

50-
(globalThis as Record<string, unknown>)[reactApp.name] = pluginComponent;
51-
}
49+
(globalThis as Record<string, unknown>)[reactApp.name] = pluginComponent;
50+
}
5251

53-
if (typeof pluginComponent !== "function") {
54-
throw new TypeError(`Expected function, got ${typeof pluginComponent} for plugin ${reactApp.name}`);
55-
}
52+
if (typeof pluginComponent !== "function") {
53+
throw new TypeError(`Expected function, got ${typeof pluginComponent} for plugin ${reactApp.name}`);
54+
}
5655

57-
return { default: pluginComponent };
58-
})
59-
.catch((error: unknown) => {
60-
console.error("Component Failed Loading:", error);
56+
return { default: pluginComponent };
57+
})
58+
.catch((error: unknown) => {
59+
// eslint-disable-next-line no-console
60+
console.error("Component failed to load:", error);
6161

62-
return {
63-
default: ErrorPage,
64-
};
65-
}),
66-
);
62+
return {
63+
default: ErrorPage,
64+
};
65+
});
66+
67+
export const ReactPlugin = ({ reactApp }: { readonly reactApp: ReactAppResponse }) => {
68+
const { dagId, mapIndex, runId, taskId } = useParams();
69+
70+
const Plugin = lazy(() => loadPlugin(reactApp));
6771

6872
return (
6973
<Suspense fallback={<Spinner />}>

airflow-core/src/airflow/ui/src/pages/Variables/ImportVariablesForm.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,9 @@ const ImportVariablesForm = ({ onClose }: ImportVariablesFormProps) => {
6565
const reader = new FileReader();
6666

6767
reader.addEventListener("load", (event) => {
68+
const text = event.target?.result as string;
69+
6870
try {
69-
const text = event.target?.result as string;
7071
const parsedContent = JSON.parse(text) as Record<string, unknown>;
7172

7273
setFileContent(parsedContent);
@@ -77,9 +78,9 @@ const ImportVariablesForm = ({ onClose }: ImportVariablesFormProps) => {
7778
},
7879
});
7980
setFileContent(undefined);
80-
} finally {
81-
setIsParsing(false);
8281
}
82+
83+
setIsParsing(false);
8384
});
8485

8586
reader.readAsText(file);

airflow-core/src/airflow/ui/src/queries/useUpdateHITLDetail.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,19 @@ export const useUpdateHITLDetail = ({
7878
});
7979

8080
const updateHITLResponse = (updateHITLResponseRequestBody: HITLResponseParams) => {
81+
const mapIndexValue = mapIndex ?? -1;
82+
83+
const requestBody = {
84+
chosen_options: updateHITLResponseRequestBody.chosen_options ?? [],
85+
params_input: updateHITLResponseRequestBody.params_input ?? {},
86+
};
87+
8188
try {
8289
mutate({
8390
dagId,
8491
dagRunId,
85-
mapIndex: mapIndex ?? -1,
86-
requestBody: {
87-
chosen_options: updateHITLResponseRequestBody.chosen_options ?? [],
88-
params_input: updateHITLResponseRequestBody.params_input ?? {},
89-
},
92+
mapIndex: mapIndexValue,
93+
requestBody,
9094
taskId,
9195
});
9296
} catch (parseError) {

0 commit comments

Comments
 (0)