From 784e274f5fb3c87834b8130a0de86c6e6c521cfb Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Wed, 4 Jan 2023 22:30:06 +0000 Subject: [PATCH 1/5] wip From e0946ce577c8cf80fa44d35e93599b608c045569 Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Wed, 4 Jan 2023 23:03:35 +0000 Subject: [PATCH 2/5] wip: move appearancesettingspage --- .../AppearanceSettingsPage.stories.tsx | 12 ++++++++++++ .../AppearanceSettingsPage.tsx | 0 2 files changed, 12 insertions(+) create mode 100644 site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPage.stories.tsx rename site/src/pages/DeploySettingsPage/{ => AppearanceSettingsPage}/AppearanceSettingsPage.tsx (100%) diff --git a/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPage.stories.tsx b/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPage.stories.tsx new file mode 100644 index 0000000000000..579a4bffb2e4d --- /dev/null +++ b/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPage.stories.tsx @@ -0,0 +1,12 @@ +import { ComponentMeta, Story } from "@storybook/react" +import AppearanceSettingsPage from "./AppearanceSettingsPage" + +export default { + title: "pages/AppearanceSettingsPage", + component: AppearanceSettingsPage, +} as ComponentMeta + +const Template: Story = (args) => + +export const Default = Template.bind({}) +Default.args = {} diff --git a/site/src/pages/DeploySettingsPage/AppearanceSettingsPage.tsx b/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPage.tsx similarity index 100% rename from site/src/pages/DeploySettingsPage/AppearanceSettingsPage.tsx rename to site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPage.tsx From 8da68992f2d0865dfc4dd2685053f30a8fd4023a Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Thu, 5 Jan 2023 17:34:07 +0000 Subject: [PATCH 3/5] refactor: separate page and view ApperanceSettings --- .../AppearanceSettingsPage.tsx | 234 +---------------- .../AppearanceSettingsPageView.tsx | 244 ++++++++++++++++++ 2 files changed, 250 insertions(+), 228 deletions(-) create mode 100644 site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx diff --git a/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPage.tsx b/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPage.tsx index 5689e433b8c3b..81bcfe2c1554c 100644 --- a/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPage.tsx +++ b/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPage.tsx @@ -1,31 +1,11 @@ -import Button from "@material-ui/core/Button" -import FormControlLabel from "@material-ui/core/FormControlLabel" -import FormHelperText from "@material-ui/core/FormHelperText" -import InputAdornment from "@material-ui/core/InputAdornment" -import { useTheme } from "@material-ui/core/styles" -import makeStyles from "@material-ui/core/styles/makeStyles" -import Switch from "@material-ui/core/Switch" -import TextField from "@material-ui/core/TextField" import { useActor } from "@xstate/react" import { FeatureNames } from "api/types" import { AppearanceConfig } from "api/typesGenerated" -import { - Badges, - DisabledBadge, - EnterpriseBadge, - EntitledBadge, -} from "components/DeploySettingsLayout/Badges" -import { Fieldset } from "components/DeploySettingsLayout/Fieldset" -import { Header } from "components/DeploySettingsLayout/Header" -import { Stack } from "components/Stack/Stack" -import { useFormik } from "formik" -import React, { useContext, useState } from "react" -import { BlockPicker } from "react-color" +import React, { useContext } from "react" import { Helmet } from "react-helmet-async" -import { useTranslation } from "react-i18next" -import { getFormHelpers } from "util/formUtils" import { pageTitle } from "util/page" import { XServiceContext } from "xServices/StateContext" +import { AppearanceSettingsPageView } from "./AppearanceSettingsPageView" // ServiceBanner is unlike the other Deployment Settings pages because it // implements a form, whereas the others are read-only. We make this @@ -38,7 +18,6 @@ const AppearanceSettingsPage: React.FC = () => { ) const [entitlementsState] = useActor(xServices.entitlementsXService) const appearance = appearanceXService.context.appearance - const styles = useStyles() const isEntitled = entitlementsState.context.entitlements.features[FeatureNames.Appearance] @@ -65,220 +44,19 @@ const AppearanceSettingsPage: React.FC = () => { }) } - const logoForm = useFormik<{ - logo_url: string - }>({ - initialValues: { - logo_url: appearance.logo_url, - }, - onSubmit: (values) => updateAppearance(values, false), - }) - const logoFieldHelpers = getFormHelpers(logoForm) - - const serviceBannerForm = useFormik({ - initialValues: { - message: appearance.service_banner.message, - enabled: appearance.service_banner.enabled, - background_color: appearance.service_banner.background_color, - }, - onSubmit: (values) => - updateAppearance( - { - service_banner: values, - }, - false, - ), - }) - const serviceBannerFieldHelpers = getFormHelpers(serviceBannerForm) - const [backgroundColor, setBackgroundColor] = useState( - serviceBannerForm.values.background_color, - ) - - const theme = useTheme() - const [t] = useTranslation("appearanceSettings") - return ( <> {pageTitle("Appearance Settings")} -
- - - {isEntitled ? : } - - - -
Submit} - > -

- Specify a custom URL for your logo to be displayed in the top left - corner of the dashboard. -

- - (e.currentTarget.style.display = "none")} - onLoad={(e) => (e.currentTarget.style.display = "inline")} - /> - - ), - }} - /> -
- -
{ - updateAppearance( - { - service_banner: { - message: - "👋 **This** is a service banner. The banner's color and text are editable.", - background_color: "#004852", - enabled: true, - }, - }, - true, - ) - }} - > - {t("showPreviewLabel")} - - ) - } - validation={ - !isEntitled && ( -

- Your license does not include Service Banners.{" "} - Contact sales to learn more. -

- ) - } - > -

Configure a banner that displays a message to all users.

- - {isEntitled && ( - - { - const newState = !serviceBannerForm.values.enabled - const newBanner = { - ...serviceBannerForm.values, - enabled: newState, - } - updateAppearance( - { - service_banner: newBanner, - }, - false, - ) - await serviceBannerForm.setFieldValue("enabled", newState) - }} - /> - } - label="Enabled" - /> - - - {t("messageHelperText")} - - - -

{"Background Color"}

- { - setBackgroundColor(color.hex) - await serviceBannerForm.setFieldValue( - "background_color", - color.hex, - ) - updateAppearance( - { - service_banner: { - ...serviceBannerForm.values, - background_color: color.hex, - }, - }, - true, - ) - }} - triangle="hide" - colors={["#004852", "#D65D0F", "#4CD473", "#D94A5D", "#5A00CF"]} - styles={{ - default: { - input: { - color: "white", - backgroundColor: theme.palette.background.default, - }, - body: { - backgroundColor: "black", - color: "white", - }, - card: { - backgroundColor: "black", - }, - }, - }} - /> -
-
- )} -
) } -const useStyles = makeStyles((theme) => ({ - form: { - maxWidth: "500px", - }, - logoAdornment: { - width: theme.spacing(3), - height: theme.spacing(3), - - "& img": { - maxWidth: "100%", - }, - }, -})) - export default AppearanceSettingsPage diff --git a/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx b/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx new file mode 100644 index 0000000000000..ac684b73a587c --- /dev/null +++ b/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx @@ -0,0 +1,244 @@ +import React, { useState } from "react" +import { Header } from "components/DeploySettingsLayout/Header" +import { + Badges, + DisabledBadge, + EnterpriseBadge, + EntitledBadge, +} from "components/DeploySettingsLayout/Badges" +import InputAdornment from "@material-ui/core/InputAdornment" +import { Fieldset } from "components/DeploySettingsLayout/Fieldset" +import { getFormHelpers } from "util/formUtils" +import Button from "@material-ui/core/Button" +import FormControlLabel from "@material-ui/core/FormControlLabel" +import FormHelperText from "@material-ui/core/FormHelperText" +import { BlockPicker } from "react-color" +import { useTranslation } from "react-i18next" +import makeStyles from "@material-ui/core/styles/makeStyles" +import Switch from "@material-ui/core/Switch" +import TextField from "@material-ui/core/TextField" +import { AppearanceConfig } from "api/typesGenerated" +import { Stack } from "components/Stack/Stack" +import { useFormik } from "formik" +import { useTheme } from "@material-ui/core/styles" + +export type AppearanceSettingsPageViewProps = { + appearance: AppearanceConfig + isEntitled: boolean + updateAppearance: any +} +export const AppearanceSettingsPageView = ({ + appearance, + isEntitled, + updateAppearance, +}: AppearanceSettingsPageViewProps) => { + const styles = useStyles() + const theme = useTheme() + const [t] = useTranslation("appearanceSettings") + const logoForm = useFormik<{ + logo_url: string + }>({ + initialValues: { + logo_url: appearance.logo_url, + }, + onSubmit: (values) => updateAppearance(values, false), + }) + const logoFieldHelpers = getFormHelpers(logoForm) + + const serviceBannerForm = useFormik({ + initialValues: { + message: appearance.service_banner.message, + enabled: appearance.service_banner.enabled, + background_color: appearance.service_banner.background_color, + }, + onSubmit: (values) => + updateAppearance( + { + service_banner: values, + }, + false, + ), + }) + const serviceBannerFieldHelpers = getFormHelpers(serviceBannerForm) + const [backgroundColor, setBackgroundColor] = useState( + serviceBannerForm.values.background_color, + ) + return ( + <> +
+ + + {isEntitled ? : } + + + +
Submit} + > +

+ Specify a custom URL for your logo to be displayed in the top left + corner of the dashboard. +

+ + (e.currentTarget.style.display = "none")} + onLoad={(e) => (e.currentTarget.style.display = "inline")} + /> + + ), + }} + /> +
+ +
{ + updateAppearance( + { + service_banner: { + message: + "👋 **This** is a service banner. The banner's color and text are editable.", + background_color: "#004852", + enabled: true, + }, + }, + true, + ) + }} + > + {t("showPreviewLabel")} + + ) + } + validation={ + !isEntitled && ( +

+ Your license does not include Service Banners.{" "} + Contact sales to learn more. +

+ ) + } + > +

Configure a banner that displays a message to all users.

+ + {isEntitled && ( + + { + const newState = !serviceBannerForm.values.enabled + const newBanner = { + ...serviceBannerForm.values, + enabled: newState, + } + updateAppearance( + { + service_banner: newBanner, + }, + false, + ) + await serviceBannerForm.setFieldValue("enabled", newState) + }} + /> + } + label="Enabled" + /> + + + {t("messageHelperText")} + + + +

{"Background Color"}

+ { + setBackgroundColor(color.hex) + await serviceBannerForm.setFieldValue( + "background_color", + color.hex, + ) + updateAppearance( + { + service_banner: { + ...serviceBannerForm.values, + background_color: color.hex, + }, + }, + true, + ) + }} + triangle="hide" + colors={["#004852", "#D65D0F", "#4CD473", "#D94A5D", "#5A00CF"]} + styles={{ + default: { + input: { + color: "white", + backgroundColor: theme.palette.background.default, + }, + body: { + backgroundColor: "black", + color: "white", + }, + card: { + backgroundColor: "black", + }, + }, + }} + /> +
+
+ )} +
+ + ) +} + +const useStyles = makeStyles((theme) => ({ + form: { + maxWidth: "500px", + }, + logoAdornment: { + width: theme.spacing(3), + height: theme.spacing(3), + + "& img": { + maxWidth: "100%", + }, + }, +})) From 9f2f9a5e0a62f3e6df789ee7284237e2e0af6a6f Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Thu, 5 Jan 2023 17:34:23 +0000 Subject: [PATCH 4/5] refactor: create storybook from AppearanceSettingsView --- .../AppearanceSettingsPage.stories.tsx | 12 ------- .../AppearanceSettingsPageView.stories.tsx | 33 +++++++++++++++++++ 2 files changed, 33 insertions(+), 12 deletions(-) delete mode 100644 site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPage.stories.tsx create mode 100644 site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.stories.tsx diff --git a/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPage.stories.tsx b/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPage.stories.tsx deleted file mode 100644 index 579a4bffb2e4d..0000000000000 --- a/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPage.stories.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { ComponentMeta, Story } from "@storybook/react" -import AppearanceSettingsPage from "./AppearanceSettingsPage" - -export default { - title: "pages/AppearanceSettingsPage", - component: AppearanceSettingsPage, -} as ComponentMeta - -const Template: Story = (args) => - -export const Default = Template.bind({}) -Default.args = {} diff --git a/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.stories.tsx b/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.stories.tsx new file mode 100644 index 0000000000000..b69d7a6b7176b --- /dev/null +++ b/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.stories.tsx @@ -0,0 +1,33 @@ +import { ComponentMeta, Story } from "@storybook/react" +import { + AppearanceSettingsPageView, + AppearanceSettingsPageViewProps, +} from "./AppearanceSettingsPageView" + +export default { + title: "pages/AppearanceSettingsPageView", + component: AppearanceSettingsPageView, + argTypes: { + appearance: { + defaultValue: { + logo_url: "https://github.com/coder.png", + service_banner: { + enabled: true, + message: "hello world", + background_color: "white", + }, + }, + }, + isEntitled: { + defaultValue: false, + }, + updateAppearance: { + defaultValue: () => {}, + }, + }, +} as ComponentMeta + +const Template: Story = (args) => ( + +) +export const Page = Template.bind({}) From 1c9deaa2d581529e5a867c6bd0617baa7fbf8fae Mon Sep 17 00:00:00 2001 From: Joe Previte Date: Thu, 5 Jan 2023 18:29:01 +0000 Subject: [PATCH 5/5] fixup: formatting and types --- site/src/AppRouter.tsx | 5 ++++- .../AppearanceSettingsPageView.stories.tsx | 4 +++- .../AppearanceSettingsPageView.tsx | 9 ++++++--- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/site/src/AppRouter.tsx b/site/src/AppRouter.tsx index 58d32623649b0..715beaea3af47 100644 --- a/site/src/AppRouter.tsx +++ b/site/src/AppRouter.tsx @@ -77,7 +77,10 @@ const SecuritySettingsPage = lazy( () => import("./pages/DeploySettingsPage/SecuritySettingsPage"), ) const AppearanceSettingsPage = lazy( - () => import("./pages/DeploySettingsPage/AppearanceSettingsPage"), + () => + import( + "./pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPage" + ), ) const UserAuthSettingsPage = lazy( () => import("./pages/DeploySettingsPage/UserAuthSettingsPage"), diff --git a/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.stories.tsx b/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.stories.tsx index b69d7a6b7176b..0bad75dedaf95 100644 --- a/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.stories.tsx +++ b/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.stories.tsx @@ -22,7 +22,9 @@ export default { defaultValue: false, }, updateAppearance: { - defaultValue: () => {}, + defaultValue: () => { + return undefined + }, }, }, } as ComponentMeta diff --git a/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx b/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx index ac684b73a587c..14b4bad0827a0 100644 --- a/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx +++ b/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react" +import { useState } from "react" import { Header } from "components/DeploySettingsLayout/Header" import { Badges, @@ -25,13 +25,16 @@ import { useTheme } from "@material-ui/core/styles" export type AppearanceSettingsPageViewProps = { appearance: AppearanceConfig isEntitled: boolean - updateAppearance: any + updateAppearance: ( + newConfig: Partial, + preview: boolean, + ) => void } export const AppearanceSettingsPageView = ({ appearance, isEntitled, updateAppearance, -}: AppearanceSettingsPageViewProps) => { +}: AppearanceSettingsPageViewProps): JSX.Element => { const styles = useStyles() const theme = useTheme() const [t] = useTranslation("appearanceSettings")