From fb1ca9e18c60559b1fdc56f9c9734104b9943b09 Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Fri, 17 Mar 2023 17:05:12 +0000 Subject: [PATCH 1/3] Add MultiTextField --- .../MultiTextField/MultiTextField.stories.tsx | 16 ++++ .../MultiTextField/MultiTextField.tsx | 95 +++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 site/src/components/MultiTextField/MultiTextField.stories.tsx create mode 100644 site/src/components/MultiTextField/MultiTextField.tsx diff --git a/site/src/components/MultiTextField/MultiTextField.stories.tsx b/site/src/components/MultiTextField/MultiTextField.stories.tsx new file mode 100644 index 0000000000000..9761e15f032da --- /dev/null +++ b/site/src/components/MultiTextField/MultiTextField.stories.tsx @@ -0,0 +1,16 @@ +import { Story } from "@storybook/react" +import { useState } from "react" +import { MultiTextField, MultiTextFieldProps } from "./MultiTextField" + +export default { + title: "components/MultiTextField", + component: MultiTextField, +} + +const Template: Story = (args) => { + const [values, setValues] = useState(args.values ?? ["foo", "bar"]) + return +} + +export const Example = Template.bind({}) +Example.args = {} diff --git a/site/src/components/MultiTextField/MultiTextField.tsx b/site/src/components/MultiTextField/MultiTextField.tsx new file mode 100644 index 0000000000000..7b903f4722413 --- /dev/null +++ b/site/src/components/MultiTextField/MultiTextField.tsx @@ -0,0 +1,95 @@ +import Chip from "@material-ui/core/Chip" +import { makeStyles } from "@material-ui/core/styles" +import { FC } from "react" + +export type MultiTextFieldProps = { + label: string + values: string[] + onChange: (values: string[]) => void +} + +export const MultiTextField: FC = ({ + label, + values, + onChange, +}) => { + const styles = useStyles() + + return ( + + ) +} + +const useStyles = makeStyles((theme) => ({ + root: { + border: `1px solid ${theme.palette.divider}`, + borderRadius: theme.shape.borderRadius, + minHeight: theme.spacing(5), + padding: theme.spacing(1.25, 1.75), + fontSize: theme.spacing(2), + display: "flex", + flexWrap: "wrap", + gap: theme.spacing(1), + position: "relative", + + "&:has(input:focus)": { + borderColor: theme.palette.primary.main, + borderWidth: 2, + // Compensate for the border width + top: -1, + left: -1, + }, + }, + + input: { + flexGrow: 1, + fontSize: "inherit", + padding: 0, + border: "none", + background: "none", + + "&:focus": { + outline: "none", + }, + }, +})) From 55e272a95a416fdaad02f70b22e4ddd0e79827cc Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Fri, 17 Mar 2023 17:16:24 +0000 Subject: [PATCH 2/3] Add field to reach parameters input --- .../MultiTextField/MultiTextField.tsx | 1 + .../RichParameterInput.stories.tsx | 12 +++++++++ .../RichParameterInput/RichParameterInput.tsx | 27 +++++++++++++++++++ 3 files changed, 40 insertions(+) diff --git a/site/src/components/MultiTextField/MultiTextField.tsx b/site/src/components/MultiTextField/MultiTextField.tsx index 7b903f4722413..4c185cbad06a9 100644 --- a/site/src/components/MultiTextField/MultiTextField.tsx +++ b/site/src/components/MultiTextField/MultiTextField.tsx @@ -71,6 +71,7 @@ const useStyles = makeStyles((theme) => ({ flexWrap: "wrap", gap: theme.spacing(1), position: "relative", + margin: theme.spacing(1, 0, 0.5), // Have same margin than TextField "&:has(input:focus)": { borderColor: theme.palette.primary.main, diff --git a/site/src/components/RichParameterInput/RichParameterInput.stories.tsx b/site/src/components/RichParameterInput/RichParameterInput.stories.tsx index fb6530cf8017e..3bb33f45a3de4 100644 --- a/site/src/components/RichParameterInput/RichParameterInput.stories.tsx +++ b/site/src/components/RichParameterInput/RichParameterInput.stories.tsx @@ -31,6 +31,7 @@ const createTemplateVersionParameter = ( validation_max: 0, validation_monotonic: "increasing", description_plaintext: "", + required: true, ...partial, } } @@ -99,6 +100,17 @@ OptionsType.args = { }), } +export const ListStringType = Template.bind({}) +ListStringType.args = { + initialValue: JSON.stringify(["first", "second", "third"]), + id: "list_string_parameter", + parameter: createTemplateVersionParameter({ + name: "list_string_parameter", + type: "list(string)", + description: "List string parameter", + }), +} + export const IconLabel = Template.bind({}) IconLabel.args = { initialValue: "initial-value", diff --git a/site/src/components/RichParameterInput/RichParameterInput.tsx b/site/src/components/RichParameterInput/RichParameterInput.tsx index e0fc6fef153dd..cc5043109dcde 100644 --- a/site/src/components/RichParameterInput/RichParameterInput.tsx +++ b/site/src/components/RichParameterInput/RichParameterInput.tsx @@ -8,6 +8,7 @@ import { FC, useState } from "react" import { TemplateVersionParameter } from "../../api/typesGenerated" import { colors } from "theme/colors" import { MemoizedMarkdown } from "components/Markdown/Markdown" +import { MultiTextField } from "components/MultiTextField/MultiTextField" const isBoolean = (parameter: TemplateVersionParameter) => { return parameter.type === "bool" @@ -154,6 +155,32 @@ const RichParameterField: React.FC = ({ ) } + if (parameter.type === "list(string)") { + let values: string[] = [] + + if (parameterValue) { + try { + values = JSON.parse(parameterValue) as string[] + } catch (e) { + console.error("Error parsing list(string) parameter", e) + } + } + + return ( + { + try { + onChange(JSON.stringify(values)) + } catch (e) { + console.error("Error on change of list(string) parameter", e) + } + }} + /> + ) + } + // A text field can technically handle all cases! // As other cases become more prominent (like filtering for numbers), // we should break this out into more finely scoped input fields. From 1b0d866095fa6aa4e505323e94950432a3a16e67 Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Fri, 17 Mar 2023 17:31:27 +0000 Subject: [PATCH 3/3] Minor fixes --- site/src/components/MultiTextField/MultiTextField.tsx | 1 - .../src/components/RichParameterInput/RichParameterInput.tsx | 4 +++- site/src/theme/overrides.ts | 5 +++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/site/src/components/MultiTextField/MultiTextField.tsx b/site/src/components/MultiTextField/MultiTextField.tsx index 4c185cbad06a9..c65528431f56c 100644 --- a/site/src/components/MultiTextField/MultiTextField.tsx +++ b/site/src/components/MultiTextField/MultiTextField.tsx @@ -22,7 +22,6 @@ export const MultiTextField: FC = ({ key={index} label={value} size="small" - color="primary" onDelete={() => { onChange(values.filter((oldValue) => oldValue !== value)) }} diff --git a/site/src/components/RichParameterInput/RichParameterInput.tsx b/site/src/components/RichParameterInput/RichParameterInput.tsx index cc5043109dcde..4cf8c5c82f37b 100644 --- a/site/src/components/RichParameterInput/RichParameterInput.tsx +++ b/site/src/components/RichParameterInput/RichParameterInput.tsx @@ -172,7 +172,9 @@ const RichParameterField: React.FC = ({ values={values} onChange={(values) => { try { - onChange(JSON.stringify(values)) + const value = JSON.stringify(values) + setParameterValue(value) + onChange(value) } catch (e) { console.error("Error on change of list(string) parameter", e) } diff --git a/site/src/theme/overrides.ts b/site/src/theme/overrides.ts index 65e57a2643cab..19b2947940ab2 100644 --- a/site/src/theme/overrides.ts +++ b/site/src/theme/overrides.ts @@ -229,5 +229,10 @@ export const getOverrides = ({ borderRadius: 999, }, }, + MuiChip: { + root: { + backgroundColor: colors.gray[12], + }, + }, } }