chore(site): move components close to where they are used (#9552)

* Move AppLink

* Move AuditLogRow

* Move UserDropdown

* Move BuildsTable

* Remove CodeBlock

* Move CreateUserForm

* Move DeploymentBanner

* Move ResetPassworDialog

* Move EditRolesButton

* Move EnterpriseSnackbar

* Move GitAuth

* Move LicenseBanner

* Move Logs

* Move MultiTextField

* Move Navbar

* Remove PasswordField

* Move RuntimeErrorState

* Remove Section

* Move SectionAction

* Move ServiceBanner

* Move SettingsAccountForm

* Move LicenseCard

* Move SettingsSecurityForm

* Move SignInForm

* Remove TabPanel and TabSidebar

* Move TemplateStats and TemplateVariableField

* Move TemplateEditor

* Move TerminalLink

* Move SSH Button

* Move many tooltips

* Move UsersTable

* Move VersionsTable

* Move VSCodeDesktopButton

* Remove WarningAlert

* Move Workspace

* Move WorkspaceActions

* Move WorkspaceBuildProgress

* Move WorkspaceDeletedBanner

* Move WorkspaceScheduleForm

* Move WorkspaceSection

* Move WorkspaceStats

* Fix imports

* Flat CreateUserForm

* Flat GitAuth

* Transform WorkspaceSection into ChartSection

* Flat AccountForm

* Flat ConfirmDeleteDialog

* Flat ResetPasswordDialog

* Flat BuildsTable
This commit is contained in:
Bruno Quaresma
2023-09-06 15:06:08 -03:00
committed by GitHub
parent 75139d1d06
commit b15bfa41c2
193 changed files with 289 additions and 1007 deletions

View File

@ -1,7 +1,7 @@
import { test, expect } from "@playwright/test"
import * as constants from "./constants"
import { STORAGE_STATE } from "./playwright.config"
import { Language } from "../src/components/CreateUserForm/CreateUserForm"
import { Language } from "../src/pages/CreateUserPage/CreateUserForm"
test("create first user", async ({ page }) => {
await page.goto("/", { waitUntil: "domcontentloaded" })

View File

@ -43,7 +43,7 @@ const WorkspaceProxyPage = lazy(
import("./pages/UserSettingsPage/WorkspaceProxyPage/WorkspaceProxyPage"),
)
const CreateUserPage = lazy(
() => import("./pages/UsersPage/CreateUserPage/CreateUserPage"),
() => import("./pages/CreateUserPage/CreateUserPage"),
)
const WorkspaceBuildPage = lazy(
() => import("./pages/WorkspaceBuildPage/WorkspaceBuildPage"),
@ -120,10 +120,7 @@ const TemplateVersionPage = lazy(
() => import("./pages/TemplateVersionPage/TemplateVersionPage"),
)
const TemplateVersionEditorPage = lazy(
() =>
import(
"./pages/TemplateVersionPage/TemplateVersionEditorPage/TemplateVersionEditorPage"
),
() => import("./pages/TemplateVersionEditorPage/TemplateVersionEditorPage"),
)
const StarterTemplatesPage = lazy(
() => import("./pages/StarterTemplatesPage/StarterTemplatesPage"),

View File

@ -1,25 +0,0 @@
import { Story } from "@storybook/react"
import { CodeBlock, CodeBlockProps } from "./CodeBlock"
const sampleLines = `Successfully assigned coder/image-jcws7 to cluster-1
Container image "gcr.io/coder-dogfood/master/coder-dev-ubuntu@sha256" already present on machine
Created container user
Started container user
Using user 'coder' with shell '/bin/bash'`.split("\n")
export default {
title: "components/CodeBlock",
component: CodeBlock,
argTypes: {
lines: { control: "text", defaultValue: sampleLines },
},
}
const Template: Story<CodeBlockProps> = (args: CodeBlockProps) => (
<CodeBlock {...args} />
)
export const Example = Template.bind({})
Example.args = {
lines: sampleLines,
}

View File

@ -1,15 +0,0 @@
import { screen } from "@testing-library/react"
import { render } from "../../testHelpers/renderHelpers"
import { CodeBlock } from "./CodeBlock"
describe("CodeBlock", () => {
it("renders lines)", async () => {
// When
render(<CodeBlock lines={["line1", "line2"]} />)
// Then
// Both lines should be rendered
await screen.findByText("line1")
await screen.findByText("line2")
})
})

View File

@ -1,59 +0,0 @@
import { makeStyles } from "@mui/styles"
import { FC, Fragment, ReactElement } from "react"
import { MONOSPACE_FONT_FAMILY } from "../../theme/constants"
import { combineClasses } from "../../utils/combineClasses"
export interface CodeBlockProps {
lines: string[]
ctas?: ReactElement[]
className?: string
}
export const CodeBlock: FC<React.PropsWithChildren<CodeBlockProps>> = ({
lines,
ctas,
className = "",
}) => {
const styles = useStyles()
return (
<>
<div className={combineClasses([styles.root, className])}>
{lines.map((line, idx) => (
<div className={styles.line} key={idx}>
{line}
</div>
))}
</div>
{ctas && ctas.length > 0 && (
<div className={styles.ctaBar}>
{ctas.map((cta, i) => {
return <Fragment key={i}>{cta}</Fragment>
})}
</div>
)}
</>
)
}
const useStyles = makeStyles((theme) => ({
root: {
minHeight: 156,
maxHeight: 240,
overflowY: "scroll",
background: theme.palette.background.default,
color: theme.palette.text.primary,
fontFamily: MONOSPACE_FONT_FAMILY,
fontSize: 13,
wordBreak: "break-all",
padding: theme.spacing(2),
borderRadius: theme.shape.borderRadius,
},
line: {
whiteSpace: "pre-wrap",
},
ctaBar: {
display: "flex",
justifyContent: "space-between",
},
}))

View File

@ -19,7 +19,7 @@ import {
HelpTooltip,
HelpTooltipTitle,
HelpTooltipText,
} from "components/Tooltips/HelpTooltip"
} from "components/HelpTooltip/HelpTooltip"
import dayjs from "dayjs"
import { FC } from "react"
import { Bar } from "react-chartjs-2"

View File

@ -1,15 +1,15 @@
import { makeStyles } from "@mui/styles"
import { useMachine } from "@xstate/react"
import { DeploymentBanner } from "components/DeploymentBanner/DeploymentBanner"
import { LicenseBanner } from "components/LicenseBanner/LicenseBanner"
import { DeploymentBanner } from "./DeploymentBanner/DeploymentBanner"
import { LicenseBanner } from "components/Dashboard/LicenseBanner/LicenseBanner"
import { Loader } from "components/Loader/Loader"
import { ServiceBanner } from "components/ServiceBanner/ServiceBanner"
import { ServiceBanner } from "components/Dashboard/ServiceBanner/ServiceBanner"
import { usePermissions } from "hooks/usePermissions"
import { FC, Suspense } from "react"
import { Outlet } from "react-router-dom"
import { dashboardContentBottomPadding } from "theme/constants"
import { updateCheckMachine } from "xServices/updateCheck/updateCheckXService"
import { Navbar } from "../Navbar/Navbar"
import { Navbar } from "./Navbar/Navbar"
import Snackbar from "@mui/material/Snackbar"
import Link from "@mui/material/Link"
import Box, { BoxProps } from "@mui/material/Box"

View File

@ -1,7 +1,7 @@
import { useMachine } from "@xstate/react"
import { usePermissions } from "hooks/usePermissions"
import { DeploymentBannerView } from "./DeploymentBannerView"
import { deploymentStatsMachine } from "../../xServices/deploymentStats/deploymentStatsMachine"
import { deploymentStatsMachine } from "xServices/deploymentStats/deploymentStatsMachine"
export const DeploymentBanner: React.FC = () => {
const permissions = usePermissions()

View File

@ -1,5 +1,5 @@
import { Story } from "@storybook/react"
import { MockUser, MockUser2 } from "../../testHelpers/entities"
import { MockUser, MockUser2 } from "../../../testHelpers/entities"
import { NavbarView, NavbarViewProps } from "./NavbarView"
export default {

View File

@ -3,8 +3,8 @@ import {
MockPrimaryWorkspaceProxy,
MockUser,
MockUser2,
} from "../../testHelpers/entities"
import { renderWithAuth } from "../../testHelpers/renderHelpers"
} from "../../../testHelpers/entities"
import { renderWithAuth } from "../../../testHelpers/renderHelpers"
import { Language as navLanguage, NavbarView } from "./NavbarView"
import { ProxyContextValue } from "contexts/ProxyContext"
import { action } from "@storybook/addon-actions"

View File

@ -8,10 +8,10 @@ import { CoderIcon } from "components/Icons/CoderIcon"
import { FC, useRef, useState } from "react"
import { NavLink, useLocation, useNavigate } from "react-router-dom"
import { colors } from "theme/colors"
import * as TypesGen from "../../api/typesGenerated"
import { navHeight } from "../../theme/constants"
import { combineClasses } from "../../utils/combineClasses"
import { UserDropdown } from "../UserDropdown/UserDropdown"
import * as TypesGen from "../../../api/typesGenerated"
import { navHeight } from "../../../theme/constants"
import { combineClasses } from "../../../utils/combineClasses"
import { UserDropdown } from "./UserDropdown/UserDropdown"
import Box from "@mui/material/Box"
import Menu from "@mui/material/Menu"
import Button from "@mui/material/Button"

View File

@ -3,8 +3,8 @@ import { makeStyles } from "@mui/styles"
import CheckIcon from "@mui/icons-material/Check"
import { FC } from "react"
import { NavLink } from "react-router-dom"
import { ellipsizeText } from "../../utils/ellipsizeText"
import { Typography } from "../Typography/Typography"
import { ellipsizeText } from "../../../../../utils/ellipsizeText"
import { Typography } from "../../../../Typography/Typography"
type BorderedMenuRowVariant = "narrow" | "wide"

View File

@ -1,6 +1,6 @@
import Box from "@mui/material/Box"
import { Story } from "@storybook/react"
import { MockUser } from "../../testHelpers/entities"
import { MockUser } from "../../../../testHelpers/entities"
import { UserDropdown, UserDropdownProps } from "./UserDropdown"
export default {

View File

@ -1,7 +1,7 @@
import { fireEvent, screen } from "@testing-library/react"
import { MockSupportLinks, MockUser } from "../../testHelpers/entities"
import { render } from "../../testHelpers/renderHelpers"
import { Language } from "../UserDropdownContent/UserDropdownContent"
import { MockSupportLinks, MockUser } from "../../../../testHelpers/entities"
import { render } from "../../../../testHelpers/renderHelpers"
import { Language } from "./UserDropdownContent/UserDropdownContent"
import { UserDropdown, UserDropdownProps } from "./UserDropdown"
const renderAndClick = async (props: Partial<UserDropdownProps> = {}) => {

View File

@ -3,12 +3,15 @@ import MenuItem from "@mui/material/MenuItem"
import { makeStyles } from "@mui/styles"
import { useState, FC, PropsWithChildren, MouseEvent } from "react"
import { colors } from "theme/colors"
import * as TypesGen from "../../api/typesGenerated"
import { navHeight } from "../../theme/constants"
import { BorderedMenu } from "../BorderedMenu/BorderedMenu"
import { CloseDropdown, OpenDropdown } from "../DropdownArrows/DropdownArrows"
import { UserAvatar } from "../UserAvatar/UserAvatar"
import { UserDropdownContent } from "../UserDropdownContent/UserDropdownContent"
import * as TypesGen from "../../../../api/typesGenerated"
import { navHeight } from "../../../../theme/constants"
import { BorderedMenu } from "./BorderedMenu/BorderedMenu"
import {
CloseDropdown,
OpenDropdown,
} from "../../../DropdownArrows/DropdownArrows"
import { UserAvatar } from "../../../UserAvatar/UserAvatar"
import { UserDropdownContent } from "./UserDropdownContent/UserDropdownContent"
import { BUTTON_SM_HEIGHT } from "theme/theme"
export interface UserDropdownProps {

View File

@ -1,5 +1,5 @@
import { Story } from "@storybook/react"
import { MockUser } from "../../testHelpers/entities"
import { MockUser } from "../../../../../testHelpers/entities"
import {
UserDropdownContent,
UserDropdownContentProps,

View File

@ -3,8 +3,8 @@ import {
MockBuildInfo,
MockSupportLinks,
MockUser,
} from "../../testHelpers/entities"
import { render } from "../../testHelpers/renderHelpers"
} from "../../../../../testHelpers/entities"
import { render } from "../../../../../testHelpers/renderHelpers"
import { Language, UserDropdownContent } from "./UserDropdownContent"
describe("UserDropdownContent", () => {

View File

@ -8,7 +8,7 @@ import LaunchIcon from "@mui/icons-material/LaunchOutlined"
import { Stack } from "components/Stack/Stack"
import { FC } from "react"
import { Link } from "react-router-dom"
import * as TypesGen from "../../api/typesGenerated"
import * as TypesGen from "../../../../../api/typesGenerated"
import DocsIcon from "@mui/icons-material/MenuBook"
import LogoutIcon from "@mui/icons-material/ExitToAppOutlined"
import { combineClasses } from "utils/combineClasses"

View File

@ -1,5 +1,5 @@
import { Component, ReactNode, PropsWithChildren } from "react"
import { RuntimeErrorState } from "../RuntimeErrorState/RuntimeErrorState"
import { RuntimeErrorState } from "./RuntimeErrorState/RuntimeErrorState"
type ErrorBoundaryProps = PropsWithChildren<unknown>

View File

@ -9,7 +9,7 @@ import { FullScreenLoader } from "components/Loader/FullScreenLoader"
import { Stack } from "components/Stack/Stack"
import { FC, useEffect, useState } from "react"
import { Helmet } from "react-helmet-async"
import { Margins } from "../Margins/Margins"
import { Margins } from "../../Margins/Margins"
const fetchDynamicallyImportedModuleError =
"Failed to fetch dynamically imported module"

View File

@ -5,7 +5,7 @@ import Snackbar, {
import { makeStyles } from "@mui/styles"
import CloseIcon from "@mui/icons-material/Close"
import { FC } from "react"
import { combineClasses } from "../../utils/combineClasses"
import { combineClasses } from "../../../utils/combineClasses"
type EnterpriseSnackbarVariant = "error" | "info" | "success"

View File

@ -2,7 +2,7 @@ import { makeStyles } from "@mui/styles"
import { useCallback, useState, FC } from "react"
import { useCustomEvent } from "../../hooks/events"
import { CustomEventListener } from "../../utils/events"
import { EnterpriseSnackbar } from "../EnterpriseSnackbar/EnterpriseSnackbar"
import { EnterpriseSnackbar } from "./EnterpriseSnackbar/EnterpriseSnackbar"
import { ErrorIcon } from "../Icons/ErrorIcon"
import { Typography } from "../Typography/Typography"
import {

View File

@ -12,7 +12,7 @@ import {
PropsWithChildren,
} from "react"
import { combineClasses } from "utils/combineClasses"
import { Stack } from "../../Stack/Stack"
import { Stack } from "components/Stack/Stack"
import Box, { BoxProps } from "@mui/material/Box"
type Icon = typeof HelpIcon

View File

@ -1,13 +0,0 @@
import { render, screen } from "@testing-library/react"
import { PasswordField } from "./PasswordField"
describe("PasswordField", () => {
it("renders", async () => {
// When
render(<PasswordField helperText="Enter password" />)
// Then
const element = await screen.findByText("Enter password")
expect(element).toBeDefined()
})
})

View File

@ -1,52 +0,0 @@
import IconButton from "@mui/material/IconButton"
import InputAdornment from "@mui/material/InputAdornment"
import { makeStyles } from "@mui/styles"
import TextField, { TextFieldProps } from "@mui/material/TextField"
import VisibilityOffOutlined from "@mui/icons-material/VisibilityOffOutlined"
import VisibilityOutlined from "@mui/icons-material/VisibilityOutlined"
import { useCallback, useState, FC, PropsWithChildren } from "react"
type PasswordFieldProps = Omit<TextFieldProps, "InputProps" | "type">
export const PasswordField: FC<PropsWithChildren<PasswordFieldProps>> = ({
variant = "outlined",
...rest
}) => {
const styles = useStyles()
const [showPassword, setShowPassword] = useState<boolean>(false)
const handleVisibilityChange = useCallback(
() => setShowPassword((showPassword) => !showPassword),
[],
)
const VisibilityIcon = showPassword
? VisibilityOffOutlined
: VisibilityOutlined
return (
<TextField
{...rest}
type={showPassword ? "text" : "password"}
variant={variant}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton
aria-label="toggle password visibility"
onClick={handleVisibilityChange}
size="small"
>
<VisibilityIcon className={styles.visibilityIcon} />
</IconButton>
</InputAdornment>
),
}}
/>
)
}
const useStyles = makeStyles({
visibilityIcon: {
fontSize: 20,
},
})

View File

@ -5,7 +5,7 @@ import {
HelpTooltipText,
HelpPopover,
HelpTooltipTitle,
} from "components/Tooltips/HelpTooltip"
} from "components/HelpTooltip/HelpTooltip"
import { Stack } from "components/Stack/Stack"
import { WorkspaceAgent, DERPRegion } from "api/typesGenerated"
import { getLatencyColor } from "utils/latency"

View File

@ -8,7 +8,7 @@ import {
HelpTooltipAction,
HelpTooltipLinksGroup,
HelpTooltipContext,
} from "components/Tooltips/HelpTooltip"
} from "components/HelpTooltip/HelpTooltip"
import { WorkspaceAgent } from "api/typesGenerated"
import { Stack } from "components/Stack/Stack"
import { useTranslation } from "react-i18next"

View File

@ -7,9 +7,9 @@ import {
CloseDropdown,
OpenDropdown,
} from "components/DropdownArrows/DropdownArrows"
import { LogLine, logLineHeight } from "components/Logs/Logs"
import { LogLine, logLineHeight } from "components/WorkspaceBuildLogs/Logs/Logs"
import { PortForwardButton } from "./PortForwardButton"
import { VSCodeDesktopButton } from "components/VSCodeDesktopButton/VSCodeDesktopButton"
import { VSCodeDesktopButton } from "components/Resources/VSCodeDesktopButton/VSCodeDesktopButton"
import {
FC,
useCallback,
@ -34,10 +34,10 @@ import {
WorkspaceAgent,
WorkspaceAgentMetadata,
} from "../../api/typesGenerated"
import { AppLink } from "../AppLink/AppLink"
import { SSHButton } from "../SSHButton/SSHButton"
import { AppLink } from "./AppLink/AppLink"
import { SSHButton } from "./SSHButton/SSHButton"
import { Stack } from "../Stack/Stack"
import { TerminalLink } from "../TerminalLink/TerminalLink"
import { TerminalLink } from "./TerminalLink/TerminalLink"
import { AgentLatency } from "./AgentLatency"
import { AgentMetadata } from "./AgentMetadata"
import { AgentVersion } from "./AgentVersion"

View File

@ -1,5 +1,5 @@
import { makeStyles } from "@mui/styles"
import { AppPreviewLink } from "components/AppLink/AppPreviewLink"
import { AppPreviewLink } from "components/Resources/AppLink/AppPreviewLink"
import { Maybe } from "components/Conditionals/Maybe"
import { FC } from "react"
import { useTranslation } from "react-i18next"

View File

@ -9,7 +9,7 @@ import {
HelpPopover,
HelpTooltipText,
HelpTooltipTitle,
} from "components/Tooltips/HelpTooltip"
} from "components/HelpTooltip/HelpTooltip"
import { useRef, useState } from "react"
import Link from "@mui/material/Link"

View File

@ -2,7 +2,7 @@ import { useRef, useState, FC } from "react"
import { makeStyles } from "@mui/styles"
import { WorkspaceAgent } from "api/typesGenerated"
import { getDisplayVersionStatus } from "utils/workspace"
import { AgentOutdatedTooltip } from "components/Tooltips/AgentOutdatedTooltip"
import { AgentOutdatedTooltip } from "./AgentOutdatedTooltip"
export const AgentVersion: FC<{
agent: WorkspaceAgent

View File

@ -6,8 +6,8 @@ import ErrorOutlineIcon from "@mui/icons-material/ErrorOutline"
import { PrimaryAgentButton } from "components/Resources/AgentButton"
import { FC } from "react"
import { combineClasses } from "utils/combineClasses"
import * as TypesGen from "../../api/typesGenerated"
import { generateRandomString } from "../../utils/random"
import * as TypesGen from "../../../api/typesGenerated"
import { generateRandomString } from "../../../utils/random"
import { BaseIcon } from "./BaseIcon"
import { ShareIcon } from "./ShareIcon"
import { useProxy } from "contexts/ProxyContext"

View File

@ -1,7 +1,7 @@
import PublicOutlinedIcon from "@mui/icons-material/PublicOutlined"
import GroupOutlinedIcon from "@mui/icons-material/GroupOutlined"
import LaunchOutlinedIcon from "@mui/icons-material/LaunchOutlined"
import * as TypesGen from "../../api/typesGenerated"
import * as TypesGen from "../../../api/typesGenerated"
import Tooltip from "@mui/material/Tooltip"
import { useTranslation } from "react-i18next"

View File

@ -8,7 +8,7 @@ import {
HelpTooltipLinksGroup,
HelpTooltipText,
HelpTooltipTitle,
} from "../Tooltips/HelpTooltip"
} from "components/HelpTooltip"
import { SecondaryAgentButton } from "components/Resources/AgentButton"
import { docs } from "utils/docs"
import Box from "@mui/material/Box"

View File

@ -2,13 +2,13 @@ import Popover from "@mui/material/Popover"
import { makeStyles } from "@mui/styles"
import { SecondaryAgentButton } from "components/Resources/AgentButton"
import { useRef, useState } from "react"
import { CodeExample } from "../CodeExample/CodeExample"
import { Stack } from "../Stack/Stack"
import { CodeExample } from "../../CodeExample/CodeExample"
import { Stack } from "../../Stack/Stack"
import {
HelpTooltipLink,
HelpTooltipLinksGroup,
HelpTooltipText,
} from "../Tooltips/HelpTooltip"
} from "components/HelpTooltip/HelpTooltip"
import { docs } from "utils/docs"
export interface SSHButtonProps {

View File

@ -1,8 +1,8 @@
import Link from "@mui/material/Link"
import { SecondaryAgentButton } from "components/Resources/AgentButton"
import { FC } from "react"
import * as TypesGen from "../../api/typesGenerated"
import { generateRandomString } from "../../utils/random"
import * as TypesGen from "../../../api/typesGenerated"
import { generateRandomString } from "../../../utils/random"
export const Language = {
linkText: "Terminal",

View File

@ -8,7 +8,7 @@ import { FC } from "react"
import { TemplateVersionParameter } from "../../api/typesGenerated"
import { colors } from "theme/colors"
import { MemoizedMarkdown } from "components/Markdown/Markdown"
import { MultiTextField } from "components/MultiTextField/MultiTextField"
import { MultiTextField } from "components/RichParameterInput/MultiTextField/MultiTextField"
import Box from "@mui/material/Box"
import { Theme } from "@mui/material/styles"

View File

@ -1,38 +0,0 @@
import Button from "@mui/material/Button"
import TextField from "@mui/material/TextField"
import { Story } from "@storybook/react"
import { Section, SectionProps } from "./Section"
export default {
title: "components/Section",
component: Section,
argTypes: {
title: { type: "string" },
description: { type: "string" },
children: { control: { disable: true } },
},
}
const Template: Story<SectionProps> = (args: SectionProps) => (
<Section {...args} />
)
export const Example = Template.bind({})
Example.args = {
title: "User Settings",
description: "Add your personal info",
children: (
<>
<form style={{ display: "grid", gridAutoFlow: "row", gap: 12 }}>
<TextField label="Name" variant="filled" fullWidth />
<TextField label="Email" variant="filled" fullWidth />
</form>
<Section.Action>
<Button variant="contained" color="primary">
Submit
</Button>
</Section.Action>
</>
),
}

View File

@ -1,92 +0,0 @@
import { makeStyles } from "@mui/styles"
import Typography from "@mui/material/Typography"
import { FC } from "react"
import { combineClasses } from "../../utils/combineClasses"
import { SectionAction } from "../SectionAction/SectionAction"
type SectionLayout = "fixed" | "fluid"
export interface SectionProps {
title?: React.ReactNode | string
description?: React.ReactNode
toolbar?: React.ReactNode
alert?: React.ReactNode
layout?: SectionLayout
className?: string
children?: React.ReactNode
}
type SectionFC = FC<React.PropsWithChildren<SectionProps>> & {
Action: typeof SectionAction
}
export const Section: SectionFC = ({
title,
description,
toolbar,
alert,
className = "",
children,
layout = "fixed",
}) => {
const styles = useStyles({ layout })
return (
<section className={combineClasses([styles.root, className])}>
<div className={styles.inner}>
{(title || description) && (
<div className={styles.header}>
<div>
{title && <Typography variant="h4">{title}</Typography>}
{description && typeof description === "string" && (
<Typography className={styles.description}>
{description}
</Typography>
)}
{description && typeof description !== "string" && (
<div className={styles.description}>{description}</div>
)}
</div>
{toolbar && <div>{toolbar}</div>}
</div>
)}
{alert && <div className={styles.alert}>{alert}</div>}
{children}
</div>
</section>
)
}
// Sub-components
Section.Action = SectionAction
const useStyles = makeStyles((theme) => ({
root: {
backgroundColor: theme.palette.background.paper,
boxShadow: theme.shadows[6],
marginBottom: theme.spacing(1),
padding: theme.spacing(6),
borderRadius: theme.shape.borderRadius,
border: `1px solid ${theme.palette.divider}`,
[theme.breakpoints.down("md")]: {
padding: theme.spacing(4, 3, 4, 3),
},
},
inner: ({ layout }: { layout: SectionLayout }) => ({
maxWidth: layout === "fluid" ? "100%" : 500,
}),
alert: {
marginBottom: theme.spacing(1),
},
header: {
marginBottom: theme.spacing(4),
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
},
description: {
color: theme.palette.text.secondary,
fontSize: 16,
marginTop: theme.spacing(2),
},
}))

View File

@ -1,7 +1,7 @@
import { makeStyles } from "@mui/styles"
import Typography from "@mui/material/Typography"
import { FC, ReactNode, PropsWithChildren } from "react"
import { SectionAction } from "../SectionAction/SectionAction"
import { SectionAction } from "./SectionAction"
type SectionLayout = "fixed" | "fluid"

View File

@ -1,21 +0,0 @@
import { Story } from "@storybook/react"
import { TabPanel, TabPanelProps } from "./TabPanel"
export default {
title: "components/TabPanel",
component: TabPanel,
}
const Template: Story<TabPanelProps> = (args: TabPanelProps) => (
<TabPanel {...args} />
)
export const Example = Template.bind({})
Example.args = {
title: "Title",
menuItems: [
{ label: "OAuth Settings", path: "oauthSettings" },
{ label: "Security", path: "oauthSettings", hasChanges: true },
{ label: "Hardware", path: "oauthSettings" },
],
}

View File

@ -1,99 +0,0 @@
import { makeStyles } from "@mui/styles"
import { FC } from "react"
import { TabSidebar, TabSidebarItem } from "../TabSidebar/TabSidebar"
export interface TabPanelProps {
title: string
menuItems: TabSidebarItem[]
}
export const TabPanel: FC<React.PropsWithChildren<TabPanelProps>> = ({
children,
title,
menuItems,
}) => {
const styles = useStyles()
return (
<div className={styles.root}>
<div className={styles.inner}>
<div className={styles.menuPanel}>
<div className={styles.title}>{title}</div>
<TabSidebar menuItems={menuItems} />
</div>
<div className={styles.contentPanel}>{children}</div>
</div>
</div>
)
}
const useStyles = makeStyles((theme) => ({
root: {
minHeight: 400,
marginBottom: theme.spacing(2),
},
inner: {
display: "flex",
maxWidth: 1920,
padding: theme.spacing(5, 3.5, 0, 4),
[theme.breakpoints.down("md")]: {
flexDirection: "column",
padding: 0,
},
},
icon: {
fontSize: 100,
position: "absolute",
left: -50,
top: 31,
color: theme.palette.text.secondary,
transition: "transform 0.3s ease",
zIndex: -1,
},
menuPanel: {
paddingRight: 40,
[theme.breakpoints.down("md")]: {
padding: 0,
},
},
title: {
marginTop: theme.spacing(6),
fontSize: 32,
},
contentPanel: {
display: "flex",
flexDirection: "column",
width: "100%",
maxWidth: 930,
},
[theme.breakpoints.up("lg")]: {
icon: {
position: "relative",
top: -11,
left: 30,
},
contentPanel: {
width: 930,
},
},
[theme.breakpoints.down("xl")]: {
contentPanel: {
width: 890,
},
},
[theme.breakpoints.down("md")]: {
contentPanel: {
width: "auto",
},
},
}))

View File

@ -1,20 +0,0 @@
import { Story } from "@storybook/react"
import { TabSidebar, TabSidebarProps } from "./TabSidebar"
export default {
title: "components/TabSidebar",
component: TabSidebar,
}
const Template: Story<TabSidebarProps> = (args: TabSidebarProps) => (
<TabSidebar {...args} />
)
export const Example = Template.bind({})
Example.args = {
menuItems: [
{ label: "OAuth Settings", path: "oauthSettings" },
{ label: "Security", path: "security", hasChanges: true },
{ label: "Hardware", path: "hardware" },
],
}

View File

@ -1,134 +0,0 @@
import List from "@mui/material/List"
import ListItem from "@mui/material/ListItem"
import { makeStyles } from "@mui/styles"
import { FC } from "react"
import { NavLink } from "react-router-dom"
import { sidePadding } from "theme/constants"
import { combineClasses } from "../../utils/combineClasses"
export interface TabSidebarItem {
path: string
label: string
hasChanges?: boolean
}
export interface TabSidebarProps {
menuItems: TabSidebarItem[]
}
export const TabSidebar: FC<React.PropsWithChildren<TabSidebarProps>> = ({
menuItems,
}) => {
const styles = useStyles()
return (
<List className={styles.menu}>
{menuItems.map(({ hasChanges, ...tab }) => {
return (
<NavLink to={tab.path} key={tab.path} className={styles.link}>
{({ isActive }) => (
<ListItem
button
className={styles.menuItem}
disableRipple
focusRipple={false}
component="li"
>
<span
className={combineClasses({
[styles.menuItemSpan]: true,
active: isActive,
})}
>
{hasChanges ? `${tab.label}*` : tab.label}
</span>
</ListItem>
)}
</NavLink>
)
})}
</List>
)
}
const useStyles = makeStyles((theme) => ({
menu: {
minWidth: 160,
marginTop: theme.spacing(5),
[theme.breakpoints.down("md")]: {
display: "flex",
borderBottom: `1px solid ${theme.palette.divider}`,
marginBottom: theme.spacing(2),
// Fit all the width
width: `calc(100% + ${sidePadding * 2}px)`,
marginLeft: -sidePadding,
marginTop: sidePadding,
},
},
link: {
textDecoration: "none",
flex: 1,
},
menuItem: {
letterSpacing: theme.spacing(-0.0375),
padding: 0,
fontSize: 18,
color: theme.palette.text.secondary,
"&.MuiListItem-button:hover": {
backgroundColor: "transparent",
},
},
menuItemSpan: {
paddingTop: theme.spacing(1.5),
paddingBottom: theme.spacing(1),
transition: "300ms all ease",
position: "relative",
"&:hover": {
color: theme.palette.text.primary,
},
"&.active": {
color: theme.palette.secondary.dark,
},
"&.active, &:hover": {
"&::before": {
opacity: 1,
},
"&::after": {
opacity: 1,
},
},
[theme.breakpoints.down("md")]: {
textAlign: "center",
width: "100%",
paddingTop: theme.spacing(2),
paddingBottom: theme.spacing(2),
},
},
[theme.breakpoints.up("lg")]: {
menuItemSpan: {
"&::before": {
content: "'{'",
position: "absolute",
left: -15,
opacity: 0,
transition: "inherit",
},
"&::after": {
content: "'}'",
position: "absolute",
right: -15,
opacity: 0,
transition: "inherit",
},
},
},
}))

View File

@ -1,4 +0,0 @@
export { AuditHelpTooltip } from "./AuditHelpTooltip"
export { WorkspaceOutdatedTooltip } from "./WorkspaceOutdatedTooltip"
export { UserRoleHelpTooltip } from "./UserRoleHelpTooltip"
export { WorkspaceHelpTooltip } from "./WorkspaceHelpTooltip"

View File

@ -3,7 +3,7 @@ import Link from "@mui/material/Link"
import { makeStyles } from "@mui/styles"
import GroupAdd from "@mui/icons-material/GroupAddOutlined"
import PersonAdd from "@mui/icons-material/PersonAddOutlined"
import { USERS_LINK } from "components/Navbar/NavbarView"
import { USERS_LINK } from "components/Dashboard/Navbar/NavbarView"
import { PageHeader, PageHeaderTitle } from "components/PageHeader/PageHeader"
import { useFeatureVisibility } from "hooks/useFeatureVisibility"
import { usePermissions } from "hooks/usePermissions"

View File

@ -1,40 +0,0 @@
import { Meta, StoryObj } from "@storybook/react"
import { WarningAlert } from "./WarningAlert"
import Button from "@mui/material/Button"
const meta: Meta<typeof WarningAlert> = {
title: "components/WarningAlert",
component: WarningAlert,
}
export default meta
type Story = StoryObj<typeof WarningAlert>
export const ExampleWithDismiss: Story = {
args: {
text: "This is a warning",
dismissible: true,
},
}
const ExampleAction = (
<Button onClick={() => null} size="small" variant="text">
Button
</Button>
)
export const ExampleWithAction = {
args: {
text: "This is a warning",
actions: [ExampleAction],
},
}
export const ExampleWithActionAndDismiss = {
args: {
text: "This is a warning",
actions: [ExampleAction],
dismissible: true,
},
}

View File

@ -1,65 +0,0 @@
import { useState, FC, ReactElement } from "react"
import Collapse from "@mui/material/Collapse"
import { Stack } from "components/Stack/Stack"
import { makeStyles } from "@mui/styles"
import { colors } from "theme/colors"
import ReportProblemOutlinedIcon from "@mui/icons-material/ReportProblemOutlined"
import Button from "@mui/material/Button"
import { useTranslation } from "react-i18next"
export interface WarningAlertProps {
text: string
dismissible?: boolean
actions?: ReactElement[]
}
export const WarningAlert: FC<WarningAlertProps> = ({
text,
dismissible = false,
actions = [],
}) => {
const { t } = useTranslation("common")
const [open, setOpen] = useState(true)
const classes = useStyles()
return (
<Collapse in={open}>
<Stack
className={classes.alertContainer}
direction="row"
alignItems="center"
spacing={0}
justifyContent="space-between"
>
<Stack direction="row" spacing={1}>
<ReportProblemOutlinedIcon
fontSize="small"
className={classes.alertIcon}
/>
{text}
</Stack>
<Stack direction="row">
{actions.length > 0 &&
actions.map((action) => <div key={String(action)}>{action}</div>)}
{dismissible && (
<Button size="small" onClick={() => setOpen(false)}>
{t("ctas.dismissCta")}
</Button>
)}
</Stack>
</Stack>
</Collapse>
)
}
const useStyles = makeStyles((theme) => ({
alertContainer: {
border: `1px solid ${colors.orange[7]}`,
borderRadius: theme.shape.borderRadius,
padding: `${theme.spacing(1)} ${theme.spacing(2)}`,
backgroundColor: `${colors.gray[16]}`,
},
alertIcon: {
color: `${colors.orange[7]}`,
},
}))

View File

@ -1,6 +1,6 @@
import { ComponentMeta, Story } from "@storybook/react"
import { LogLevel } from "api/typesGenerated"
import { MockWorkspaceBuildLogs } from "../../testHelpers/entities"
import { MockWorkspaceBuildLogs } from "../../../testHelpers/entities"
import { Logs, LogsProps } from "./Logs"
export default {

View File

@ -2,8 +2,8 @@ import { makeStyles } from "@mui/styles"
import { LogLevel } from "api/typesGenerated"
import dayjs from "dayjs"
import { FC, useMemo } from "react"
import { MONOSPACE_FONT_FAMILY } from "../../theme/constants"
import { combineClasses } from "../../utils/combineClasses"
import { MONOSPACE_FONT_FAMILY } from "../../../theme/constants"
import { combineClasses } from "../../../utils/combineClasses"
import AnsiToHTML from "ansi-to-html"
import { Theme } from "@mui/material/styles"

View File

@ -3,7 +3,7 @@ import dayjs from "dayjs"
import { ComponentProps, FC, Fragment } from "react"
import { ProvisionerJobLog } from "../../api/typesGenerated"
import { MONOSPACE_FONT_FAMILY } from "../../theme/constants"
import { Logs } from "../Logs/Logs"
import { Logs } from "./Logs/Logs"
import Box from "@mui/material/Box"
import { combineClasses } from "utils/combineClasses"

View File

@ -6,7 +6,7 @@ import {
HelpTooltipLinksGroup,
HelpTooltipText,
HelpTooltipTitle,
} from "./HelpTooltip"
} from "components/HelpTooltip/HelpTooltip"
import InfoIcon from "@mui/icons-material/InfoOutlined"
import { makeStyles } from "@mui/styles"
import { colors } from "theme/colors"

View File

@ -1,29 +0,0 @@
import IconButton from "@mui/material/IconButton"
import EditIcon from "@mui/icons-material/Edit"
import { action } from "@storybook/addon-actions"
import { Story } from "@storybook/react"
import { WorkspaceSection, WorkspaceSectionProps } from "./WorkspaceSection"
export default {
title: "components/WorkspaceSection",
component: WorkspaceSection,
}
const Template: Story<WorkspaceSectionProps> = (args) => (
<WorkspaceSection {...args}>Content</WorkspaceSection>
)
export const NoAction = Template.bind({})
NoAction.args = {
title: "A Workspace Section",
}
export const Action = Template.bind({})
Action.args = {
action: (
<IconButton onClick={action("edit")} size="large">
<EditIcon />
</IconButton>
),
title: "Action Section",
}

View File

@ -5,7 +5,7 @@ import {
HelpTooltipLinksGroup,
HelpTooltipText,
HelpTooltipTitle,
} from "./HelpTooltip"
} from "components/HelpTooltip/HelpTooltip"
import { docs } from "utils/docs"
export const Language = {

View File

@ -4,7 +4,7 @@ import TableCell from "@mui/material/TableCell"
import TableContainer from "@mui/material/TableContainer"
import TableRow from "@mui/material/TableRow"
import { AuditLog } from "api/typesGenerated"
import { AuditLogRow } from "components/AuditLogRow/AuditLogRow"
import { AuditLogRow } from "pages/AuditPage/AuditLogRow/AuditLogRow"
import { ChooseOne, Cond } from "components/Conditionals/ChooseOne"
import { EmptyState } from "components/EmptyState/EmptyState"
import { Margins } from "components/Margins/Margins"
@ -16,7 +16,7 @@ import {
import { Stack } from "components/Stack/Stack"
import { TableLoader } from "components/TableLoader/TableLoader"
import { Timeline } from "components/Timeline/Timeline"
import { AuditHelpTooltip } from "components/Tooltips"
import { AuditHelpTooltip } from "./AuditHelpTooltip"
import { ComponentProps, FC } from "react"
import { useTranslation } from "react-i18next"
import { AuditPaywall } from "./AuditPaywall"

View File

@ -25,7 +25,10 @@ import {
import { CreateTemplateData } from "xServices/createTemplate/createTemplateXService"
import * as Yup from "yup"
import { WorkspaceBuildLogs } from "components/WorkspaceBuildLogs/WorkspaceBuildLogs"
import { HelpTooltip, HelpTooltipText } from "components/Tooltips/HelpTooltip"
import {
HelpTooltip,
HelpTooltipText,
} from "components/HelpTooltip/HelpTooltip"
import { LazyIconField } from "components/IconField/LazyIconField"
import { Maybe } from "components/Conditionals/Maybe"
import i18next from "i18next"

View File

@ -2,15 +2,11 @@ import TextField from "@mui/material/TextField"
import { FormikContextType, useFormik } from "formik"
import { FC } from "react"
import * as Yup from "yup"
import * as TypesGen from "../../api/typesGenerated"
import {
getFormHelpers,
nameValidator,
onChangeTrimmed,
} from "../../utils/formUtils"
import { FormFooter } from "../FormFooter/FormFooter"
import { FullPageForm } from "../FullPageForm/FullPageForm"
import { Stack } from "../Stack/Stack"
import * as TypesGen from "api/typesGenerated"
import { getFormHelpers, nameValidator, onChangeTrimmed } from "utils/formUtils"
import { FormFooter } from "components/FormFooter/FormFooter"
import { FullPageForm } from "components/FullPageForm/FullPageForm"
import { Stack } from "components/Stack/Stack"
import { ErrorAlert } from "components/Alert/ErrorAlert"
import { hasApiFieldErrors, isApiError } from "api/errors"
import MenuItem from "@mui/material/MenuItem"

View File

@ -1,14 +1,14 @@
import { fireEvent, screen } from "@testing-library/react"
import userEvent from "@testing-library/user-event"
import { rest } from "msw"
import { Language as FormLanguage } from "../../../components/CreateUserForm/CreateUserForm"
import { Language as FooterLanguage } from "../../../components/FormFooter/FormFooter"
import { Language as FormLanguage } from "./CreateUserForm"
import { Language as FooterLanguage } from "components/FormFooter/FormFooter"
import {
renderWithAuth,
waitForLoaderToBeRemoved,
} from "../../../testHelpers/renderHelpers"
import { server } from "../../../testHelpers/server"
import { Language as CreateUserLanguage } from "../../../xServices/users/createUserXService"
} from "testHelpers/renderHelpers"
import { server } from "testHelpers/server"
import { Language as CreateUserLanguage } from "xServices/users/createUserXService"
import { CreateUserPage } from "./CreateUserPage"
const renderCreateUserPage = async () => {

View File

@ -4,10 +4,10 @@ import { FC } from "react"
import { Helmet } from "react-helmet-async"
import { useNavigate } from "react-router-dom"
import { createUserMachine } from "xServices/users/createUserXService"
import * as TypesGen from "../../../api/typesGenerated"
import { CreateUserForm } from "../../../components/CreateUserForm/CreateUserForm"
import { Margins } from "../../../components/Margins/Margins"
import { pageTitle } from "../../../utils/page"
import * as TypesGen from "api/typesGenerated"
import { CreateUserForm } from "./CreateUserForm"
import { Margins } from "components/Margins/Margins"
import { pageTitle } from "utils/page"
import { getAuthMethods } from "api/api"
import { useQuery } from "@tanstack/react-query"

View File

@ -24,7 +24,7 @@ import {
MutableTemplateParametersSection,
} from "components/TemplateParameters/TemplateParameters"
import { CreateWSPermissions } from "xServices/createWorkspace/createWorkspaceXService"
import { GitAuth } from "components/GitAuth/GitAuth"
import { GitAuth } from "./GitAuth"
import { ErrorAlert } from "components/Alert/ErrorAlert"
export interface CreateWorkspacePageViewProps {

View File

@ -1,9 +1,9 @@
import Paper from "@mui/material/Paper"
import { makeStyles } from "@mui/styles"
import { HTMLProps, ReactNode, FC, PropsWithChildren } from "react"
import { combineClasses } from "../../utils/combineClasses"
import { combineClasses } from "utils/combineClasses"
export interface WorkspaceSectionProps {
export interface ChartSectionProps {
/**
* action appears in the top right of the section card
*/
@ -12,7 +12,7 @@ export interface WorkspaceSectionProps {
title?: string | JSX.Element
}
export const WorkspaceSection: FC<PropsWithChildren<WorkspaceSectionProps>> = ({
export const ChartSection: FC<PropsWithChildren<ChartSectionProps>> = ({
action,
children,
contentsProps,

Some files were not shown because too many files have changed in this diff Show More