Skip to content

refactor(site): Highlight immutable parameters and do a few tweaks #6490

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions site/src/components/HorizontalForm/HorizontalForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
} from "components/FormFooter/FormFooter"
import { Stack } from "components/Stack/Stack"
import { FC, HTMLProps, PropsWithChildren } from "react"
import { combineClasses } from "util/combineClasses"

export const HorizontalForm: FC<
PropsWithChildren & HTMLProps<HTMLFormElement>
Expand All @@ -21,12 +22,16 @@ export const HorizontalForm: FC<
}

export const FormSection: FC<
PropsWithChildren & { title: string; description: string | JSX.Element }
> = ({ children, title, description }) => {
PropsWithChildren & {
title: string
description: string | JSX.Element
className?: string
}
> = ({ children, title, description, className }) => {
const styles = useStyles()

return (
<div className={styles.formSection}>
<div className={combineClasses([styles.formSection, className])}>
<div className={styles.formSectionInfo}>
<h2 className={styles.formSectionInfoTitle}>{title}</h2>
<div className={styles.formSectionInfoDescription}>{description}</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,16 @@ const createTemplateVersionParameter = (
validation_regex: "",
validation_min: 0,
validation_max: 0,
validation_monotonic: "",

validation_monotonic: "increasing",
description_plaintext: "",
...partial,
}
}

export const Basic = Template.bind({})
Basic.args = {
initialValue: "initial-value",
id: "project_name",
parameter: createTemplateVersionParameter({
name: "project_name",
description:
Expand All @@ -48,6 +49,7 @@ Basic.args = {
export const NumberType = Template.bind({})
NumberType.args = {
initialValue: "4",
id: "number_parameter",
parameter: createTemplateVersionParameter({
name: "number_parameter",
type: "number",
Expand All @@ -58,6 +60,7 @@ NumberType.args = {
export const BooleanType = Template.bind({})
BooleanType.args = {
initialValue: "false",
id: "bool_parameter",
parameter: createTemplateVersionParameter({
name: "bool_parameter",
type: "bool",
Expand All @@ -68,6 +71,7 @@ BooleanType.args = {
export const OptionsType = Template.bind({})
OptionsType.args = {
initialValue: "first_option",
id: "options_parameter",
parameter: createTemplateVersionParameter({
name: "options_parameter",
type: "string",
Expand All @@ -94,3 +98,68 @@ OptionsType.args = {
],
}),
}

export const IconLabel = Template.bind({})
IconLabel.args = {
initialValue: "initial-value",
id: "project_name",
parameter: createTemplateVersionParameter({
name: "project_name",
description:
"Customize the name of a Google Cloud project that will be created!",
icon: "/emojis/1f30e.png",
}),
}

export const NoDescription = Template.bind({})
NoDescription.args = {
initialValue: "",
id: "region",
parameter: createTemplateVersionParameter({
name: "Region",
description: "",
description_plaintext: "",
type: "string",
mutable: false,
default_value: "",
icon: "/emojis/1f30e.png",
options: [
{
name: "Pittsburgh",
description: "",
value: "us-pittsburgh",
icon: "/emojis/1f1fa-1f1f8.png",
},
{
name: "Helsinki",
description: "",
value: "eu-helsinki",
icon: "/emojis/1f1eb-1f1ee.png",
},
{
name: "Sydney",
description: "",
value: "ap-sydney",
icon: "/emojis/1f1e6-1f1fa.png",
},
],
}),
}

export const DescriptionWithLinks = Template.bind({})
DescriptionWithLinks.args = {
initialValue: "",
id: "coder-repository-directory",
parameter: createTemplateVersionParameter({
name: "Coder Repository Directory",
description:
"The directory specified will be created and [coder/coder](https://github.com/coder/coder) will be automatically cloned into it 🪄.",
description_plaintext:
"The directory specified will be created and coder/coder (https://github.com/coder/coder) will be automatically cloned into it 🪄.",
type: "string",
mutable: true,
default_value: "~/coder",
icon: "",
options: [],
}),
}
102 changes: 51 additions & 51 deletions site/src/components/RichParameterInput/RichParameterInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import FormControlLabel from "@material-ui/core/FormControlLabel"
import Radio from "@material-ui/core/Radio"
import RadioGroup from "@material-ui/core/RadioGroup"
import { makeStyles } from "@material-ui/core/styles"
import TextField from "@material-ui/core/TextField"
import TextField, { TextFieldProps } from "@material-ui/core/TextField"
import { Stack } from "components/Stack/Stack"
import { FC, useState } from "react"
import { TemplateVersionParameter } from "../../api/typesGenerated"
Expand All @@ -14,54 +14,48 @@ const isBoolean = (parameter: TemplateVersionParameter) => {
}

export interface ParameterLabelProps {
index: number
id: string
parameter: TemplateVersionParameter
}

const ParameterLabel: FC<ParameterLabelProps> = ({ index, parameter }) => {
const ParameterLabel: FC<ParameterLabelProps> = ({ id, parameter }) => {
const styles = useStyles()
const hasDescription = parameter.description && parameter.description !== ""

return (
<span>
<span className={styles.labelNameWithIcon}>
<label htmlFor={id}>
<Stack direction="row" alignItems="center">
{parameter.icon && (
<span className={styles.iconWrapper}>
<span className={styles.labelIconWrapper}>
<img
className={styles.icon}
className={styles.labelIcon}
alt="Parameter icon"
src={parameter.icon}
style={{
pointerEvents: "none",
}}
/>
</span>
)}
<span className={styles.labelName}>
<label htmlFor={`rich_parameter_values[${index}].value`}>
{parameter.name}
</label>
</span>
</span>
{parameter.description && (
<span className={styles.labelDescription}>
<MemoizedMarkdown>{parameter.description}</MemoizedMarkdown>
</span>
)}
{!parameter.mutable && (
<div className={styles.labelImmutable}>
This parameter cannot be changed after creating workspace.
</div>
)}
</span>

{hasDescription ? (
<Stack spacing={0.5}>
<span className={styles.labelCaption}>{parameter.name}</span>
<span className={styles.labelPrimary}>
<MemoizedMarkdown>{parameter.description}</MemoizedMarkdown>
</span>
</Stack>
) : (
<span className={styles.labelPrimary}>{parameter.name}</span>
)}
</Stack>
</label>
)
}

export interface RichParameterInputProps {
export type RichParameterInputProps = TextFieldProps & {
index: number
disabled?: boolean
parameter: TemplateVersionParameter
onChange: (value: string) => void
initialValue?: string
id: string
}

export const RichParameterInput: FC<RichParameterInputProps> = ({
Expand All @@ -70,16 +64,16 @@ export const RichParameterInput: FC<RichParameterInputProps> = ({
onChange,
parameter,
initialValue,
...props
...fieldProps
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why spread this? Isn't it just id?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nops, it passes other props. I probably should fix the types to make it clear... Going to make that.

}) => {
const styles = useStyles()

return (
<Stack direction="column" spacing={0.75}>
<ParameterLabel index={index} parameter={parameter} />
<ParameterLabel id={fieldProps.id} parameter={parameter} />
<div className={styles.input}>
<RichParameterField
{...props}
{...fieldProps}
index={index}
disabled={disabled}
onChange={onChange}
Expand Down Expand Up @@ -140,7 +134,7 @@ const RichParameterField: React.FC<RichParameterInputProps> = ({
value={option.value}
control={<Radio color="primary" size="small" disableRipple />}
label={
<span>
<span className={styles.radioOption}>
{option.icon && (
<img
className={styles.optionIcon}
Expand Down Expand Up @@ -179,24 +173,25 @@ const RichParameterField: React.FC<RichParameterInputProps> = ({
)
}

const iconSize = 20
const optionIconSize = 24
const optionIconSize = 20

const useStyles = makeStyles((theme) => ({
labelName: {
label: {
marginBottom: theme.spacing(0.5),
},
labelCaption: {
fontSize: 14,
color: theme.palette.text.secondary,
display: "block",
marginBottom: theme.spacing(1.0),
},
labelNameWithIcon: {
marginBottom: theme.spacing(0.5),
},
labelDescription: {
labelPrimary: {
fontSize: 16,
color: theme.palette.text.primary,
display: "block",
fontWeight: 600,

"& p": {
margin: 0,
lineHeight: "20px", // Keep the same as ParameterInput
},
},
labelImmutable: {
marginTop: theme.spacing(0.5),
Expand All @@ -212,18 +207,23 @@ const useStyles = makeStyles((theme) => ({
alignItems: "center",
gap: theme.spacing(1),
},
iconWrapper: {
float: "left",
labelIconWrapper: {
width: theme.spacing(2.5),
height: theme.spacing(2.5),
display: "block",
},
icon: {
maxHeight: iconSize,
width: iconSize,
marginRight: theme.spacing(1.0),
labelIcon: {
width: "100%",
height: "100%",
objectFit: "contain",
},
radioOption: {
display: "flex",
alignItems: "center",
gap: theme.spacing(1.5),
},
optionIcon: {
maxHeight: optionIconSize,
width: optionIconSize,
marginRight: theme.spacing(1.0),
float: "left",
},
}))
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ describe("CreateWorkspacePage", () => {

const secondParameterField = await screen.findByLabelText(
MockTemplateVersionParameter2.name,
{ exact: false },
)
expect(secondParameterField).toBeDefined()

Expand Down Expand Up @@ -212,6 +213,7 @@ describe("CreateWorkspacePage", () => {

const thirdParameterField = await screen.findByLabelText(
MockTemplateVersionParameter3.name,
{ exact: false },
)
expect(thirdParameterField).toBeDefined()
fireEvent.change(thirdParameterField, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,35 @@ RichParameters.args = {
MockTemplateVersionParameter1,
MockTemplateVersionParameter2,
MockTemplateVersionParameter3,
{
name: "Region",
description: "",
description_plaintext: "",
type: "string",
mutable: false,
default_value: "",
icon: "/emojis/1f30e.png",
options: [
{
name: "Pittsburgh",
description: "",
value: "us-pittsburgh",
icon: "/emojis/1f1fa-1f1f8.png",
},
{
name: "Helsinki",
description: "",
value: "eu-helsinki",
icon: "/emojis/1f1eb-1f1ee.png",
},
{
name: "Sydney",
description: "",
value: "ap-sydney",
icon: "/emojis/1f1e6-1f1fa.png",
},
],
},
],
createWorkspaceErrors: {},
}
Expand Down
Loading