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/AppearanceSettingsPage.tsx b/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPage.tsx new file mode 100644 index 0000000000000..81bcfe2c1554c --- /dev/null +++ b/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPage.tsx @@ -0,0 +1,62 @@ +import { useActor } from "@xstate/react" +import { FeatureNames } from "api/types" +import { AppearanceConfig } from "api/typesGenerated" +import React, { useContext } from "react" +import { Helmet } from "react-helmet-async" +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 +// exception because the Service Banner is visual, and configuring it from +// the command line would be a significantly worse user experience. +const AppearanceSettingsPage: React.FC = () => { + const xServices = useContext(XServiceContext) + const [appearanceXService, appearanceSend] = useActor( + xServices.appearanceXService, + ) + const [entitlementsState] = useActor(xServices.entitlementsXService) + const appearance = appearanceXService.context.appearance + + const isEntitled = + entitlementsState.context.entitlements.features[FeatureNames.Appearance] + .entitlement !== "not_entitled" + + const updateAppearance = ( + newConfig: Partial, + preview: boolean, + ) => { + const newAppearance = { + ...appearance, + ...newConfig, + } + if (preview) { + appearanceSend({ + type: "SET_PREVIEW_APPEARANCE", + appearance: newAppearance, + }) + return + } + appearanceSend({ + type: "SET_APPEARANCE", + appearance: newAppearance, + }) + } + + return ( + <> + + {pageTitle("Appearance Settings")} + + + + + ) +} + +export default AppearanceSettingsPage 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..0bad75dedaf95 --- /dev/null +++ b/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.stories.tsx @@ -0,0 +1,35 @@ +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: () => { + return undefined + }, + }, + }, +} as ComponentMeta + +const Template: Story = (args) => ( + +) +export const Page = Template.bind({}) diff --git a/site/src/pages/DeploySettingsPage/AppearanceSettingsPage.tsx b/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx similarity index 83% rename from site/src/pages/DeploySettingsPage/AppearanceSettingsPage.tsx rename to site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx index 5689e433b8c3b..14b4bad0827a0 100644 --- a/site/src/pages/DeploySettingsPage/AppearanceSettingsPage.tsx +++ b/site/src/pages/DeploySettingsPage/AppearanceSettingsPage/AppearanceSettingsPageView.tsx @@ -1,70 +1,43 @@ -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 { 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 { Header } from "components/DeploySettingsLayout/Header" -import { Stack } from "components/Stack/Stack" -import { useFormik } from "formik" -import React, { useContext, useState } from "react" +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 { 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" - -// ServiceBanner is unlike the other Deployment Settings pages because it -// implements a form, whereas the others are read-only. We make this -// exception because the Service Banner is visual, and configuring it from -// the command line would be a significantly worse user experience. -const AppearanceSettingsPage: React.FC = () => { - const xServices = useContext(XServiceContext) - const [appearanceXService, appearanceSend] = useActor( - xServices.appearanceXService, - ) - const [entitlementsState] = useActor(xServices.entitlementsXService) - const appearance = appearanceXService.context.appearance - const styles = useStyles() - - const isEntitled = - entitlementsState.context.entitlements.features[FeatureNames.Appearance] - .entitlement !== "not_entitled" +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" - const updateAppearance = ( +export type AppearanceSettingsPageViewProps = { + appearance: AppearanceConfig + isEntitled: boolean + updateAppearance: ( newConfig: Partial, preview: boolean, - ) => { - const newAppearance = { - ...appearance, - ...newConfig, - } - if (preview) { - appearanceSend({ - type: "SET_PREVIEW_APPEARANCE", - appearance: newAppearance, - }) - return - } - appearanceSend({ - type: "SET_APPEARANCE", - appearance: newAppearance, - }) - } - + ) => void +} +export const AppearanceSettingsPageView = ({ + appearance, + isEntitled, + updateAppearance, +}: AppearanceSettingsPageViewProps): JSX.Element => { + const styles = useStyles() + const theme = useTheme() + const [t] = useTranslation("appearanceSettings") const logoForm = useFormik<{ logo_url: string }>({ @@ -93,16 +66,8 @@ const AppearanceSettingsPage: React.FC = () => { const [backgroundColor, setBackgroundColor] = useState( serviceBannerForm.values.background_color, ) - - const theme = useTheme() - const [t] = useTranslation("appearanceSettings") - return ( <> - - {pageTitle("Appearance Settings")} - -
({ }, }, })) - -export default AppearanceSettingsPage