Skip to content
Snippets Groups Projects
Unverified Commit 9a3144ec authored by Ryan Laurie's avatar Ryan Laurie Committed by GitHub
Browse files

Action Creator 6: Allow user-defined options for select and radio inputs (#25404)

* allow user-defined select options

* Update frontend/src/metabase/writeback/components/ActionCreator/FormCreator/utils.ts

:face_palm:
parent 09a07a68
No related branches found
No related tags found
No related merge requests found
import styled from "@emotion/styled";
import InputBase from "metabase/core/components/Input";
import Button from "metabase/core/components/Button";
import { color } from "metabase/lib/colors";
import { space } from "metabase/styled-components/theme";
......@@ -40,3 +41,18 @@ export const EmptyFormPlaceholderWrapper = styled.div`
max-width: 20rem;
margin: 5rem auto;
`;
export const EditButton = styled(Button)`
color: ${color("brand")};
background-opacity: 0;
&:hover {
color: ${color("accent0-light")};
}
`;
export const FormSettingsPreviewContainer = styled.div`
display: flex;
flex-direction: column;
gap: ${space(1)};
min-width: 12rem;
`;
......@@ -7,6 +7,7 @@ import type { ActionFormSettings, FieldSettings } from "metabase-types/api";
import { FieldSettingsPopover } from "./FieldSettingsPopover";
import { getDefaultFormSettings, getDefaultFieldSettings } from "./utils";
import { FormField } from "./FormField";
import { OptionEditor } from "./OptionEditor";
import {
FormItemWrapper,
......@@ -14,6 +15,8 @@ import {
FormItemName,
FormSettings,
EmptyFormPlaceholderWrapper,
FormSettingsPreviewContainer,
EditButton,
} from "./FormCreator.styled";
export function FormCreator({
......@@ -74,12 +77,44 @@ function FormItem({
fieldSettings: FieldSettings;
onChange: (fieldSettings: FieldSettings) => void;
}) {
const [isEditingOptions, setIsEditingOptions] = useState(false);
const name = tag.name;
const updateOptions = (newOptions: (string | number)[]) => {
onChange({
...fieldSettings,
valueOptions: newOptions,
});
setIsEditingOptions(false);
};
const hasOptions =
fieldSettings.inputType === "dropdown" ||
fieldSettings.inputType === "inline-select";
return (
<FormItemWrapper>
<FormItemName>{name}</FormItemName>
<FormSettings>
<FormField tag={tag} fieldSettings={fieldSettings} />
<FormSettingsPreviewContainer>
{isEditingOptions && hasOptions ? (
<OptionEditor
options={fieldSettings.valueOptions ?? []}
onChange={updateOptions}
/>
) : (
<FormField tag={tag} fieldSettings={fieldSettings} />
)}
{!isEditingOptions && hasOptions && (
<EditButton
onClick={() => setIsEditingOptions(true)}
borderless
small
>
{t`Edit options`}
</EditButton>
)}
</FormSettingsPreviewContainer>
<FieldSettingsPopover
fieldSettings={fieldSettings}
onChange={onChange}
......
import styled from "@emotion/styled";
import InputBase from "metabase/core/components/Input";
import { color } from "metabase/lib/colors";
import { space } from "metabase/styled-components/theme";
export const OptionEditorContainer = styled.div`
display: flex;
flex-direction: column;
`;
export const AddMorePrompt = styled.div`
text-align: center;
font-size: 0.875rem;
margin: ${space(1)} 0;
height: 1.25rem;
color: ${color("text-light")};
transition: opacity 0.2s ease-in-out;
`;
export const StyledTextArea = styled.textarea`
resize: none;
border: none;
outline: 1px solid ${color("border")};
width: 20rem;
border-radius: ${space(1)};
padding: ${space(1)};
`;
import React, { useState } from "react";
import { t } from "ttag";
import Button from "metabase/core/components/Button";
import {
OptionEditorContainer,
AddMorePrompt,
StyledTextArea,
} from "./OptionEditor.styled";
type ValueOptions = (string | number)[];
const optionsToText = (options: ValueOptions) => options.join("\n");
const textToOptions = (text: string): ValueOptions =>
text.split("\n").map(option => option.trim());
export const OptionEditor = ({
options,
onChange,
}: {
options: ValueOptions;
onChange: (options: ValueOptions) => void;
}) => {
const [text, setText] = useState(optionsToText(options));
const save = () => {
onChange(textToOptions(text));
};
return (
<OptionEditorContainer>
<StyledTextArea
value={text}
onChange={e => setText(e.target.value)}
placeholder={t`Enter one option per line`}
/>
<AddMorePrompt style={{ opacity: text.length ? 1 : 0 }}>
{t`Press enter to add another option`}
</AddMorePrompt>
<Button onClick={save} small>
{t`Save`}
</Button>
</OptionEditorContainer>
);
};
......@@ -40,6 +40,9 @@ const getSampleOptions = () => [
{ name: t`Option Three`, value: 3 },
];
const getOptionsFromArray = (options: (number | string)[]) =>
options.map(o => ({ name: o, value: o }));
const getParameterFieldProps = (fieldSettings: FieldSettings) => {
switch (fieldSettings.inputType) {
case "string":
......@@ -56,12 +59,16 @@ const getParameterFieldProps = (fieldSettings: FieldSettings) => {
case "dropdown":
return {
type: "select",
options: fieldSettings.valueOptions ?? getSampleOptions(),
options: fieldSettings.valueOptions?.length
? getOptionsFromArray(fieldSettings.valueOptions)
: getSampleOptions(),
};
case "inline-select":
return {
type: "radio",
options: fieldSettings.valueOptions ?? getSampleOptions(),
options: fieldSettings.valueOptions?.length
? getOptionsFromArray(fieldSettings.valueOptions)
: getSampleOptions(),
};
default:
return { type: "input" };
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment