feat: add storybook for /deployment/appearance page (#5582)

* wip

* wip: move appearancesettingspage

* refactor: separate page and view ApperanceSettings

* refactor: create storybook from AppearanceSettingsView

* fixup: formatting and types
This commit is contained in:
Joe Previte
2023-01-05 16:16:54 -05:00
committed by GitHub
parent 0d30a1eb72
commit bb03df8148
4 changed files with 129 additions and 66 deletions
+4 -1
View File
@@ -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"),
@@ -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<AppearanceConfig>,
preview: boolean,
) => {
const newAppearance = {
...appearance,
...newConfig,
}
if (preview) {
appearanceSend({
type: "SET_PREVIEW_APPEARANCE",
appearance: newAppearance,
})
return
}
appearanceSend({
type: "SET_APPEARANCE",
appearance: newAppearance,
})
}
return (
<>
<Helmet>
<title>{pageTitle("Appearance Settings")}</title>
</Helmet>
<AppearanceSettingsPageView
appearance={appearance}
isEntitled={isEntitled}
updateAppearance={updateAppearance}
/>
</>
)
}
export default AppearanceSettingsPage
@@ -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<typeof AppearanceSettingsPageView>
const Template: Story<AppearanceSettingsPageViewProps> = (args) => (
<AppearanceSettingsPageView {...args} />
)
export const Page = Template.bind({})
@@ -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 { 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 React, { useContext, useState } from "react"
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"
import { useTheme } from "@material-ui/core/styles"
// 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"
const updateAppearance = (
export type AppearanceSettingsPageViewProps = {
appearance: AppearanceConfig
isEntitled: boolean
updateAppearance: (
newConfig: Partial<AppearanceConfig>,
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 (
<>
<Helmet>
<title>{pageTitle("Appearance Settings")}</title>
</Helmet>
<Header
title="Appearance"
description="Customize the look and feel of your Coder deployment."
@@ -280,5 +245,3 @@ const useStyles = makeStyles((theme) => ({
},
},
}))
export default AppearanceSettingsPage