Skip to content

Commit

Permalink
Review feedback, remove reloading warnings, move selector functions t…
Browse files Browse the repository at this point in the history
…o separate TSX file
  • Loading branch information
jscheffl committed Jan 4, 2025
1 parent 7ddb8f6 commit 313d868
Show file tree
Hide file tree
Showing 16 changed files with 127 additions and 119 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,9 @@ import { githubLight, githubDark } from "@uiw/codemirror-themes-all";
import CodeMirror from "@uiw/react-codemirror";

import { useColorMode } from "src/context/colorMode";
import type { ParamSchema } from "src/queries/useDagParams";

import type { FlexibleFormElementProps } from ".";

export const isFieldAdvancedArray = (fieldType: string, fieldSchema: ParamSchema) =>
fieldType === "array" && fieldSchema.items?.type !== "string";

export const FlexibleFormFieldAdvancedArray = ({ name, param }: FlexibleFormElementProps) => {
const { colorMode } = useColorMode();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
import type { FlexibleFormElementProps } from ".";
import { Switch } from "../ui";

export const isFieldBool = (fieldType: string) => fieldType === "boolean";

export const FlexibleFormFieldBool = ({ name, param }: FlexibleFormElementProps) => (
<Switch
colorPalette="blue"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,8 @@
*/
import { Input } from "@chakra-ui/react";

import type { ParamSchema } from "src/queries/useDagParams";

import type { FlexibleFormElementProps } from ".";

export const isFieldDate = (fieldType: string, fieldSchema: ParamSchema) =>
fieldType === "string" && fieldSchema.format === "date";

export const FlexibleFormFieldDate = ({ name, param }: FlexibleFormElementProps) => (
<Input
defaultValue={typeof param.value === "string" ? param.value : undefined}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,8 @@
*/
import { Input } from "@chakra-ui/react";

import type { ParamSchema } from "src/queries/useDagParams";

import type { FlexibleFormElementProps } from ".";

export const isFieldDateTime = (fieldType: string, fieldSchema: ParamSchema) =>
fieldType === "string" && fieldSchema.format === "date-time";

export const FlexibleFormFieldDateTime = ({ name, param }: FlexibleFormElementProps) => (
<Input
defaultValue={typeof param.value === "string" ? param.value : undefined}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,9 @@ import { createListCollection } from "@chakra-ui/react/collection";
import { useRef } from "react";

import { Select } from "src/components/ui";
import type { ParamSchema } from "src/queries/useDagParams";

import type { FlexibleFormElementProps } from ".";

const enumTypes = ["string", "number", "integer"];

export const isFieldDropdown = (fieldType: string, fieldSchema: ParamSchema) =>
enumTypes.includes(fieldType) && Array.isArray(fieldSchema.enum);

const labelLookup = (key: string, valuesDisplay: Record<string, string> | null): string => {
if (valuesDisplay && typeof valuesDisplay === "object") {
return valuesDisplay[key] ?? key;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,8 @@
import { Select as ReactSelect } from "chakra-react-select";
import { useState } from "react";

import type { ParamSchema } from "src/queries/useDagParams";

import type { FlexibleFormElementProps } from ".";

export const isFieldMultiSelect = (fieldType: string, fieldSchema: ParamSchema) =>
fieldType === "array" && Array.isArray(fieldSchema.examples);

const labelLookup = (key: string, valuesDisplay: Record<string, string> | null): string => {
if (valuesDisplay && typeof valuesDisplay === "object") {
return valuesDisplay[key] ?? key;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,8 @@
*/
import { Textarea } from "@chakra-ui/react";

import type { ParamSchema } from "src/queries/useDagParams";

import type { FlexibleFormElementProps } from ".";

export const isFieldMultilineText = (fieldType: string, fieldSchema: ParamSchema) =>
fieldType === "string" && fieldSchema.format === "multiline";

export const FlexibleFormFieldMultilineText = ({ name, param }: FlexibleFormElementProps) => (
<Textarea
defaultValue={typeof param.value === "string" ? param.value : String(param.value)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,6 @@
import type { FlexibleFormElementProps } from ".";
import { NumberInputField, NumberInputRoot } from "../ui/NumberInput";

export const isFieldNumber = (fieldType: string) => {
const numberTypes = ["integer", "number"];

return numberTypes.includes(fieldType);
};

export const FlexibleFormFieldNumber = ({ name, param }: FlexibleFormElementProps) => (
<NumberInputRoot
allowMouseWheel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ import { useColorMode } from "src/context/colorMode";

import type { FlexibleFormElementProps } from ".";

export const isFieldObject = (fieldType: string) => fieldType === "object";

export const FlexibleFormFieldObject = ({ name, param }: FlexibleFormElementProps) => {
const { colorMode } = useColorMode();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,8 @@
*/
import { Textarea } from "@chakra-ui/react";

import type { ParamSchema } from "src/queries/useDagParams";

import type { FlexibleFormElementProps } from ".";

export const isFieldStringArray = (fieldType: string, fieldSchema: ParamSchema) =>
fieldType === "array" &&
(!fieldSchema.items || fieldSchema.items.type === undefined || fieldSchema.items.type === "string");

export const FlexibleFormFieldStringArray = ({ name, param }: FlexibleFormElementProps) => (
<Textarea
defaultValue={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,8 @@
*/
import { Input } from "@chakra-ui/react";

import type { ParamSchema } from "src/queries/useDagParams";

import type { FlexibleFormElementProps } from ".";

export const isFieldTime = (fieldType: string, fieldSchema: ParamSchema) =>
fieldType === "string" && fieldSchema.format === "date";

export const FlexibleFormFieldTime = ({ name, param }: FlexibleFormElementProps) => (
<Input
defaultValue={typeof param.value === "string" ? param.value : undefined}
Expand Down
4 changes: 0 additions & 4 deletions airflow/ui/src/components/FlexibleForm/FlexibleFormHidden.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,8 @@
*/
import { VisuallyHidden } from "@chakra-ui/react";

import type { ParamSchema } from "src/queries/useDagParams";

import type { FlexibleFormElementProps } from ".";

export const isHidden = (fieldSchema: ParamSchema) => Boolean(fieldSchema.const);

/** Render a "const" field where user can not change data as hidden */
export const FlexibleFormHidden = ({ name, param }: FlexibleFormElementProps) => (
<VisuallyHidden asChild>
Expand Down
63 changes: 1 addition & 62 deletions airflow/ui/src/components/FlexibleForm/FlexibleFormNormalRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,75 +23,14 @@ import remarkGfm from "remark-gfm";
import type { ParamSpec } from "src/queries/useDagParams";

import type { FlexibleFormElementProps } from ".";
import { FlexibleFormFieldAdvancedArray, isFieldAdvancedArray } from "./FlexibleFormFieldAdvancedArray";
import { FlexibleFormFieldBool, isFieldBool } from "./FlexibleFormFieldBool";
import { FlexibleFormFieldDate, isFieldDate } from "./FlexibleFormFieldDate";
import { FlexibleFormFieldDateTime, isFieldDateTime } from "./FlexibleFormFieldDateTime";
import { FlexibleFormFieldDropdown, isFieldDropdown } from "./FlexibleFormFieldDropdown";
import { FlexibleFormFieldMultiSelect, isFieldMultiSelect } from "./FlexibleFormFieldMultiSelect";
import { FlexibleFormFieldMultilineText, isFieldMultilineText } from "./FlexibleFormFieldMultilineText";
import { FlexibleFormFieldNumber, isFieldNumber } from "./FlexibleFormFieldNumber";
import { FlexibleFormFieldObject, isFieldObject } from "./FlexibleFormFieldObject";
import { FlexibleFormFieldString } from "./FlexibleFormFieldString";
import { FlexibleFormFieldStringArray, isFieldStringArray } from "./FlexibleFormFieldStringArray";
import { FlexibleFormFieldTime, isFieldTime } from "./FlexibleFormFieldTime";
import { FlexibleFormSelectElement } from "./FlexibleFormSelectElement";

const isRequired = (param: ParamSpec) =>
// The field is required if the schema type is defined.
// But if the type "null" is included, then the field is not required.
// We assume that "null" is only defined if the type is an array.
Boolean(param.schema.type) && (!Array.isArray(param.schema.type) || !param.schema.type.includes("null"));

const inferType = (param: ParamSpec) => {
if (Boolean(param.schema.type)) {
// If there are multiple types, we assume that the first one is the correct one that is not "null".
// "null" is only used to signal the value is optional.
if (Array.isArray(param.schema.type)) {
return param.schema.type.find((type) => type !== "null") ?? "string";
}

return param.schema.type ?? "string";
}

// If the type is not defined, we infer it from the value.
if (Array.isArray(param.value)) {
return "array";
}

return typeof param.value;
};

export const FlexibleFormSelectElement = ({ key, name, param }: FlexibleFormElementProps) => {
// FUTURE: Add support for other types as described in AIP-68 via Plugins
const fieldType = inferType(param);

if (isFieldBool(fieldType)) {
return <FlexibleFormFieldBool key={key} name={name} param={param} />;
} else if (isFieldDateTime(fieldType, param.schema)) {
return <FlexibleFormFieldDateTime key={key} name={name} param={param} />;
} else if (isFieldDate(fieldType, param.schema)) {
return <FlexibleFormFieldDate key={key} name={name} param={param} />;
} else if (isFieldTime(fieldType, param.schema)) {
return <FlexibleFormFieldTime key={key} name={name} param={param} />;
} else if (isFieldDropdown(fieldType, param.schema)) {
return <FlexibleFormFieldDropdown key={key} name={name} param={param} />;
} else if (isFieldMultiSelect(fieldType, param.schema)) {
return <FlexibleFormFieldMultiSelect key={key} name={name} param={param} />;
} else if (isFieldStringArray(fieldType, param.schema)) {
return <FlexibleFormFieldStringArray key={key} name={name} param={param} />;
} else if (isFieldAdvancedArray(fieldType, param.schema)) {
return <FlexibleFormFieldAdvancedArray key={key} name={name} param={param} />;
} else if (isFieldObject(fieldType)) {
return <FlexibleFormFieldObject key={key} name={name} param={param} />;
} else if (isFieldNumber(fieldType)) {
return <FlexibleFormFieldNumber key={key} name={name} param={param} />;
} else if (isFieldMultilineText(fieldType, param.schema)) {
return <FlexibleFormFieldMultilineText key={key} name={name} param={param} />;
} else {
return <FlexibleFormFieldString key={key} name={name} param={param} />;
}
};

/** Render a normal form row with a field that is auto-selected */
export const FlexibleFormNormalRow = ({ key, name, param }: FlexibleFormElementProps) => (
<Field.Root orientation="horizontal" required={isRequired(param)}>
Expand Down
6 changes: 5 additions & 1 deletion airflow/ui/src/components/FlexibleForm/FlexibleFormRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
import type { ParamSchema } from "src/queries/useDagParams";

import type { FlexibleFormElementProps } from ".";
import { FlexibleFormHidden, isHidden } from "./FlexibleFormHidden";
import { FlexibleFormHidden } from "./FlexibleFormHidden";
import { FlexibleFormNormalRow } from "./FlexibleFormNormalRow";

const isHidden = (fieldSchema: ParamSchema) => Boolean(fieldSchema.const);

/** Generates a form row */
export const FlexibleFormRow = ({ key, name, param }: FlexibleFormElementProps) =>
isHidden(param.schema) ? (
Expand Down
120 changes: 120 additions & 0 deletions airflow/ui/src/components/FlexibleForm/FlexibleFormSelectElement.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*!
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import type { ParamSchema, ParamSpec } from "src/queries/useDagParams";

import type { FlexibleFormElementProps } from ".";
import { FlexibleFormFieldAdvancedArray } from "./FlexibleFormFieldAdvancedArray";
import { FlexibleFormFieldBool } from "./FlexibleFormFieldBool";
import { FlexibleFormFieldDate } from "./FlexibleFormFieldDate";
import { FlexibleFormFieldDateTime } from "./FlexibleFormFieldDateTime";
import { FlexibleFormFieldDropdown } from "./FlexibleFormFieldDropdown";
import { FlexibleFormFieldMultiSelect } from "./FlexibleFormFieldMultiSelect";
import { FlexibleFormFieldMultilineText } from "./FlexibleFormFieldMultilineText";
import { FlexibleFormFieldNumber } from "./FlexibleFormFieldNumber";
import { FlexibleFormFieldObject } from "./FlexibleFormFieldObject";
import { FlexibleFormFieldString } from "./FlexibleFormFieldString";
import { FlexibleFormFieldStringArray } from "./FlexibleFormFieldStringArray";
import { FlexibleFormFieldTime } from "./FlexibleFormFieldTime";

const inferType = (param: ParamSpec) => {
if (Boolean(param.schema.type)) {
// If there are multiple types, we assume that the first one is the correct one that is not "null".
// "null" is only used to signal the value is optional.
if (Array.isArray(param.schema.type)) {
return param.schema.type.find((type) => type !== "null") ?? "string";
}

return param.schema.type ?? "string";
}

// If the type is not defined, we infer it from the value.
if (Array.isArray(param.value)) {
return "array";
}

return typeof param.value;
};

const isFieldAdvancedArray = (fieldType: string, fieldSchema: ParamSchema) =>
fieldType === "array" && fieldSchema.items?.type !== "string";

const isFieldBool = (fieldType: string) => fieldType === "boolean";

const isFieldDate = (fieldType: string, fieldSchema: ParamSchema) =>
fieldType === "string" && fieldSchema.format === "date";

const isFieldDateTime = (fieldType: string, fieldSchema: ParamSchema) =>
fieldType === "string" && fieldSchema.format === "date-time";

const enumTypes = ["string", "number", "integer"];

const isFieldDropdown = (fieldType: string, fieldSchema: ParamSchema) =>
enumTypes.includes(fieldType) && Array.isArray(fieldSchema.enum);

const isFieldMultilineText = (fieldType: string, fieldSchema: ParamSchema) =>
fieldType === "string" && fieldSchema.format === "multiline";

const isFieldMultiSelect = (fieldType: string, fieldSchema: ParamSchema) =>
fieldType === "array" && Array.isArray(fieldSchema.examples);

const isFieldNumber = (fieldType: string) => {
const numberTypes = ["integer", "number"];

return numberTypes.includes(fieldType);
};

const isFieldObject = (fieldType: string) => fieldType === "object";

const isFieldStringArray = (fieldType: string, fieldSchema: ParamSchema) =>
fieldType === "array" &&
(!fieldSchema.items || fieldSchema.items.type === undefined || fieldSchema.items.type === "string");

const isFieldTime = (fieldType: string, fieldSchema: ParamSchema) =>
fieldType === "string" && fieldSchema.format === "date";

export const FlexibleFormSelectElement = ({ key, name, param }: FlexibleFormElementProps) => {
// FUTURE: Add support for other types as described in AIP-68 via Plugins
const fieldType = inferType(param);

if (isFieldBool(fieldType)) {
return <FlexibleFormFieldBool key={key} name={name} param={param} />;
} else if (isFieldDateTime(fieldType, param.schema)) {
return <FlexibleFormFieldDateTime key={key} name={name} param={param} />;
} else if (isFieldDate(fieldType, param.schema)) {
return <FlexibleFormFieldDate key={key} name={name} param={param} />;
} else if (isFieldTime(fieldType, param.schema)) {
return <FlexibleFormFieldTime key={key} name={name} param={param} />;
} else if (isFieldDropdown(fieldType, param.schema)) {
return <FlexibleFormFieldDropdown key={key} name={name} param={param} />;
} else if (isFieldMultiSelect(fieldType, param.schema)) {
return <FlexibleFormFieldMultiSelect key={key} name={name} param={param} />;
} else if (isFieldStringArray(fieldType, param.schema)) {
return <FlexibleFormFieldStringArray key={key} name={name} param={param} />;
} else if (isFieldAdvancedArray(fieldType, param.schema)) {
return <FlexibleFormFieldAdvancedArray key={key} name={name} param={param} />;
} else if (isFieldObject(fieldType)) {
return <FlexibleFormFieldObject key={key} name={name} param={param} />;
} else if (isFieldNumber(fieldType)) {
return <FlexibleFormFieldNumber key={key} name={name} param={param} />;
} else if (isFieldMultilineText(fieldType, param.schema)) {
return <FlexibleFormFieldMultilineText key={key} name={name} param={param} />;
} else {
return <FlexibleFormFieldString key={key} name={name} param={param} />;
}
};
2 changes: 1 addition & 1 deletion airflow/ui/src/components/FlexibleForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const FlexibleForm = ({ params }: FlexibleFormProps) => {
const currentSection = secParam.schema.section;

if (processedSections.has(currentSection)) {
return null;
return undefined;
} else {
processedSections.set(currentSection, true);

Expand Down

0 comments on commit 313d868

Please sign in to comment.