From c14a4b92ed81a2a0dcfa607c10883e73748e50f2 Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Fri, 19 Aug 2022 13:09:07 -0300 Subject: [PATCH] feat: Display and edit template icons in the UI (#3598) --- .../TemplateSettingsForm.tsx | 36 +++++++++++++++++++ .../TemplateSettingsPage.test.tsx | 7 +++- .../TemplatesPageView.stories.tsx | 2 ++ .../pages/TemplatesPage/TemplatesPageView.tsx | 15 ++++++++ 4 files changed, 59 insertions(+), 1 deletion(-) diff --git a/site/src/pages/TemplateSettingsPage/TemplateSettingsForm.tsx b/site/src/pages/TemplateSettingsPage/TemplateSettingsForm.tsx index 0598d0d87b..8693709d7a 100644 --- a/site/src/pages/TemplateSettingsPage/TemplateSettingsForm.tsx +++ b/site/src/pages/TemplateSettingsPage/TemplateSettingsForm.tsx @@ -1,3 +1,5 @@ +import InputAdornment from "@material-ui/core/InputAdornment" +import { makeStyles } from "@material-ui/core/styles" import TextField from "@material-ui/core/TextField" import { Template, UpdateTemplateMeta } from "api/typesGenerated" import { FormFooter } from "components/FormFooter/FormFooter" @@ -10,6 +12,7 @@ import * as Yup from "yup" export const Language = { nameLabel: "Name", descriptionLabel: "Description", + iconLabel: "Icon", maxTtlLabel: "Max TTL", // This is the same from the CLI on https://github.com/coder/coder/blob/546157b63ef9204658acf58cb653aa9936b70c49/cli/templateedit.go#L59 maxTtlHelperText: "Edit the template maximum time before shutdown in milliseconds", @@ -45,6 +48,7 @@ export const TemplateSettingsForm: FC = ({ name: template.name, description: template.description, max_ttl_ms: template.max_ttl_ms, + icon: template.icon, }, validationSchema, onSubmit: (data) => { @@ -53,6 +57,8 @@ export const TemplateSettingsForm: FC = ({ initialTouched, }) const getFieldHelpers = getFormHelpersWithError(form, error) + const styles = useStyles() + const hasIcon = form.values.icon && form.values.icon !== "" return (
@@ -77,6 +83,29 @@ export const TemplateSettingsForm: FC = ({ rows={2} /> + + (e.currentTarget.style.display = "none")} + onLoad={(e) => (e.currentTarget.style.display = "inline")} + /> + + ) : undefined, + }} + /> + = ({ ) } + +const useStyles = makeStyles((theme) => ({ + adornment: { + width: theme.spacing(3), + height: theme.spacing(3), + }, +})) diff --git a/site/src/pages/TemplateSettingsPage/TemplateSettingsPage.test.tsx b/site/src/pages/TemplateSettingsPage/TemplateSettingsPage.test.tsx index d28d5aa01b..78554885f8 100644 --- a/site/src/pages/TemplateSettingsPage/TemplateSettingsPage.test.tsx +++ b/site/src/pages/TemplateSettingsPage/TemplateSettingsPage.test.tsx @@ -23,6 +23,7 @@ const fillAndSubmitForm = async ({ name, description, max_ttl_ms, + icon, }: Omit, "min_autostart_interval_ms">) => { const nameField = await screen.findByLabelText(FormLanguage.nameLabel) await userEvent.clear(nameField) @@ -32,6 +33,10 @@ const fillAndSubmitForm = async ({ await userEvent.clear(descriptionField) await userEvent.type(descriptionField, description) + const iconField = await screen.findByLabelText(FormLanguage.iconLabel) + await userEvent.clear(iconField) + await userEvent.type(iconField, icon) + const maxTtlField = await screen.findByLabelText(FormLanguage.maxTtlLabel) await userEvent.clear(maxTtlField) await userEvent.type(maxTtlField, max_ttl_ms.toString()) @@ -54,7 +59,7 @@ describe("TemplateSettingsPage", () => { name: "edited-template-name", description: "Edited description", max_ttl_ms: 4000, - icon: "/icons/new-icon.png", + icon: "/icon/code.svg", } jest.spyOn(API, "updateTemplateMeta").mockResolvedValueOnce({ ...MockTemplate, diff --git a/site/src/pages/TemplatesPage/TemplatesPageView.stories.tsx b/site/src/pages/TemplatesPage/TemplatesPageView.stories.tsx index a72c802450..f97e94456a 100644 --- a/site/src/pages/TemplatesPage/TemplatesPageView.stories.tsx +++ b/site/src/pages/TemplatesPage/TemplatesPageView.stories.tsx @@ -17,11 +17,13 @@ AllStates.args = { { ...MockTemplate, description: "🚀 Some magical template that does some magical things!", + icon: "/icon/goland.svg", }, { ...MockTemplate, workspace_owner_count: 150, description: "😮 Wow, this one has a bunch of usage!", + icon: "", }, ], } diff --git a/site/src/pages/TemplatesPage/TemplatesPageView.tsx b/site/src/pages/TemplatesPage/TemplatesPageView.tsx index 948b511dfb..4127c72fe9 100644 --- a/site/src/pages/TemplatesPage/TemplatesPageView.tsx +++ b/site/src/pages/TemplatesPage/TemplatesPageView.tsx @@ -142,6 +142,8 @@ export const TemplatesPageView: FC = (props) => { )} {props.templates?.map((template) => { const templatePageLink = `/templates/${template.name}` + const hasIcon = template.icon && template.icon !== "" + return ( = (props) => { title={template.name} subtitle={template.description} highlightTitle + avatar={ + hasIcon ? ( +
+ +
+ ) : undefined + } /> @@ -211,4 +220,10 @@ const useStyles = makeStyles((theme) => ({ arrowCell: { display: "flex", }, + templateIconWrapper: { + // Same size then the avatar component + width: 36, + height: 36, + padding: 2, + }, }))