chore: move some components into pages/ (#11536)

This commit is contained in:
Kayla Washburn-Love
2024-01-11 11:30:15 -07:00
committed by GitHub
parent e3ad9580e9
commit 8c3a4f2d7f
33 changed files with 169 additions and 107 deletions
+3 -3
View File
@@ -1,4 +1,4 @@
import { FC, lazy, Suspense } from "react";
import { type FC, lazy, Suspense } from "react";
import {
Route,
Routes,
@@ -6,10 +6,10 @@ import {
Navigate,
} from "react-router-dom";
import { DashboardLayout } from "./components/Dashboard/DashboardLayout";
import { DeploySettingsLayout } from "./components/DeploySettingsLayout/DeploySettingsLayout";
import { DeploySettingsLayout } from "./pages/DeploySettingsPage/DeploySettingsLayout";
import { FullScreenLoader } from "./components/Loader/FullScreenLoader";
import { RequireAuth } from "./components/RequireAuth/RequireAuth";
import { UsersLayout } from "./components/UsersLayout/UsersLayout";
import { UsersLayout } from "./pages/UsersPage/UsersLayout";
import AuditPage from "./pages/AuditPage/AuditPage";
import LoginPage from "./pages/LoginPage/LoginPage";
import { SetupPage } from "./pages/SetupPage/SetupPage";
@@ -0,0 +1,54 @@
import type { Meta, StoryObj } from "@storybook/react";
import dayjs from "dayjs";
import { LastSeen } from "./LastSeen";
const meta: Meta<typeof LastSeen> = {
title: "components/LastSeen",
component: LastSeen,
args: {
// We typically want this component to be excluded from Chromatic's snapshots,
// because it creates a lot of noise when a static dates roles over from eg.
// "2 months ago" to "3 months ago", but these stories use relative dates,
// and test specific cases that we want to be validated.
"data-chromatic": "",
},
};
export default meta;
type Story = StoryObj<typeof LastSeen>;
export const Now: Story = {
args: {
at: dayjs(),
},
};
export const OneDayAgo: Story = {
args: {
at: dayjs().subtract(1, "day"),
},
};
export const OneWeekAgo: Story = {
args: {
at: dayjs().subtract(1, "week"),
},
};
export const OneMonthAgo: Story = {
args: {
at: dayjs().subtract(1, "month"),
},
};
export const OneYearAgo: Story = {
args: {
at: dayjs().subtract(1, "year"),
},
};
export const Never: Story = {
args: {
at: dayjs().subtract(101, "year"),
},
};
+13 -8
View File
@@ -1,30 +1,35 @@
import { useTheme } from "@emotion/react";
import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
import { type FC, type HTMLAttributes } from "react";
interface LastSeenProps extends HTMLAttributes<HTMLSpanElement> {
value: string;
dayjs.extend(relativeTime);
interface LastSeenProps
extends Omit<HTMLAttributes<HTMLSpanElement>, "children"> {
at: dayjs.ConfigType;
"data-chromatic"?: string; // prevents a type error in the stories
}
export const LastSeen: FC<LastSeenProps> = ({ value, ...attrs }) => {
export const LastSeen: FC<LastSeenProps> = ({ at, ...attrs }) => {
const theme = useTheme();
const t = dayjs(value);
const t = dayjs(at);
const now = dayjs();
let message = t.fromNow();
let color = theme.palette.text.secondary;
if (t.isAfter(now.subtract(1, "hour"))) {
color = theme.palette.success.light;
// Since the agent reports on a 10m interval,
// the last_used_at can be inaccurate when recent.
message = "Now";
color = theme.experimental.roles.success.fill;
} else if (t.isAfter(now.subtract(3, "day"))) {
color = theme.palette.text.secondary;
color = theme.experimental.l2.text;
} else if (t.isAfter(now.subtract(1, "month"))) {
color = theme.palette.warning.light;
color = theme.experimental.roles.warning.fill;
} else if (t.isAfter(now.subtract(100, "year"))) {
color = theme.palette.error.light;
color = theme.experimental.roles.error.fill;
} else {
message = "Never";
}
@@ -9,17 +9,17 @@ import { type FC, useState } from "react";
import { BlockPicker } from "react-color";
import { useFormik } from "formik";
import type { UpdateAppearanceConfig } from "api/typesGenerated";
import { Header } from "components/DeploySettingsLayout/Header";
import {
Badges,
DisabledBadge,
EnterpriseBadge,
EntitledBadge,
} from "components/Badges/Badges";
import { Fieldset } from "components/DeploySettingsLayout/Fieldset";
import { Stack } from "components/Stack/Stack";
import { getFormHelpers } from "utils/formUtils";
import colors from "theme/tailwindColors";
import { Header } from "../Header";
import { Fieldset } from "../Fieldset";
export type AppearanceSettingsPageViewProps = {
appearance: UpdateAppearanceConfig;
@@ -1,7 +1,7 @@
import { useDeploySettings } from "components/DeploySettingsLayout/DeploySettingsLayout";
import { FC } from "react";
import { type FC } from "react";
import { Helmet } from "react-helmet-async";
import { pageTitle } from "utils/page";
import { useDeploySettings } from "../DeploySettingsLayout";
import { ExternalAuthSettingsPageView } from "./ExternalAuthSettingsPageView";
const ExternalAuthSettingsPage: FC = () => {
@@ -1,4 +1,5 @@
import { css } from "@emotion/react";
import { type FC } from "react";
import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableCell from "@mui/material/TableCell";
@@ -8,16 +9,16 @@ import TableRow from "@mui/material/TableRow";
import type { DeploymentValues, ExternalAuthConfig } from "api/typesGenerated";
import { Alert } from "components/Alert/Alert";
import { EnterpriseBadge } from "components/Badges/Badges";
import { Header } from "components/DeploySettingsLayout/Header";
import { Header } from "../Header";
import { docs } from "utils/docs";
export type ExternalAuthSettingsPageViewProps = {
config: DeploymentValues;
};
export const ExternalAuthSettingsPageView = ({
config,
}: ExternalAuthSettingsPageViewProps): JSX.Element => {
export const ExternalAuthSettingsPageView: FC<
ExternalAuthSettingsPageViewProps
> = ({ config }) => {
return (
<>
<Header
@@ -5,7 +5,7 @@ import { pageTitle } from "utils/page";
import { deploymentDAUs } from "api/queries/deployment";
import { entitlements } from "api/queries/entitlements";
import { availableExperiments } from "api/queries/experiments";
import { useDeploySettings } from "components/DeploySettingsLayout/DeploySettingsLayout";
import { useDeploySettings } from "../DeploySettingsLayout";
import { GeneralSettingsPageView } from "./GeneralSettingsPageView";
const GeneralSettingsPage: FC = () => {
@@ -10,9 +10,9 @@ import {
ActiveUserChart,
ActiveUsersTitle,
} from "components/ActiveUserChart/ActiveUserChart";
import { Header } from "components/DeploySettingsLayout/Header";
import OptionsTable from "components/DeploySettingsLayout/OptionsTable";
import { Stack } from "components/Stack/Stack";
import { Header } from "../Header";
import OptionsTable from "../OptionsTable";
import { ChartSection } from "./ChartSection";
import { useDeploymentOptions } from "utils/deployOptions";
import { docs } from "utils/docs";
@@ -3,13 +3,13 @@ import TextField from "@mui/material/TextField";
import KeyboardArrowLeft from "@mui/icons-material/KeyboardArrowLeft";
import { type FC } from "react";
import { Link as RouterLink } from "react-router-dom";
import { Fieldset } from "components/DeploySettingsLayout/Fieldset";
import { Header } from "components/DeploySettingsLayout/Header";
import { FileUpload } from "components/FileUpload/FileUpload";
import { displayError } from "components/GlobalSnackbar/utils";
import { Stack } from "components/Stack/Stack";
import { ErrorAlert } from "components/Alert/ErrorAlert";
import { DividerWithText } from "pages/DeploySettingsPage/LicensesSettingsPage/DividerWithText";
import { DividerWithText } from "./DividerWithText";
import { Fieldset } from "../Fieldset";
import { Header } from "../Header";
type AddNewLicenseProps = {
onSaveLicenseKey: (license: string) => void;
@@ -3,17 +3,17 @@ import Button from "@mui/material/Button";
import Skeleton from "@mui/material/Skeleton";
import AddIcon from "@mui/icons-material/AddOutlined";
import RefreshIcon from "@mui/icons-material/Refresh";
import type { GetLicensesResponse } from "api/api";
import { Header } from "components/DeploySettingsLayout/Header";
import { LicenseCard } from "./LicenseCard";
import { Stack } from "components/Stack/Stack";
import MuiLink from "@mui/material/Link";
import Tooltip from "@mui/material/Tooltip";
import LoadingButton from "@mui/lab/LoadingButton";
import { type FC } from "react";
import Confetti from "react-confetti";
import { Link } from "react-router-dom";
import useWindowSize from "react-use/lib/useWindowSize";
import MuiLink from "@mui/material/Link";
import Tooltip from "@mui/material/Tooltip";
import LoadingButton from "@mui/lab/LoadingButton";
import type { GetLicensesResponse } from "api/api";
import { Stack } from "components/Stack/Stack";
import { LicenseCard } from "./LicenseCard";
import { Header } from "../Header";
type Props = {
showConfetti: boolean;
@@ -1,7 +1,7 @@
import { useDeploySettings } from "components/DeploySettingsLayout/DeploySettingsLayout";
import { FC } from "react";
import { type FC } from "react";
import { Helmet } from "react-helmet-async";
import { pageTitle } from "utils/page";
import { useDeploySettings } from "../DeploySettingsLayout";
import { NetworkSettingsPageView } from "./NetworkSettingsPageView";
const NetworkSettingsPage: FC = () => {
@@ -1,21 +1,22 @@
import { type FC } from "react";
import type { ClibaseOption } from "api/typesGenerated";
import { Badges, EnabledBadge, DisabledBadge } from "components/Badges/Badges";
import { Header } from "components/DeploySettingsLayout/Header";
import OptionsTable from "components/DeploySettingsLayout/OptionsTable";
import { Stack } from "components/Stack/Stack";
import {
deploymentGroupHasParent,
useDeploymentOptions,
} from "utils/deployOptions";
import { docs } from "utils/docs";
import { Header } from "../Header";
import OptionsTable from "../OptionsTable";
export type NetworkSettingsPageViewProps = {
options: ClibaseOption[];
};
export const NetworkSettingsPageView = ({
export const NetworkSettingsPageView: FC<NetworkSettingsPageViewProps> = ({
options: options,
}: NetworkSettingsPageViewProps): JSX.Element => (
}) => (
<Stack direction="column" spacing={6}>
<div>
<Header
@@ -4,9 +4,9 @@ import { type FC } from "react";
import { Link } from "react-router-dom";
import type * as TypesGen from "api/typesGenerated";
import { ErrorAlert } from "components/Alert/ErrorAlert";
import { Header } from "components/DeploySettingsLayout/Header";
import { Stack } from "components/Stack/Stack";
import { OAuth2AppForm } from "./OAuth2AppForm";
import { Header } from "../Header";
type CreateOAuth2AppProps = {
isUpdating: boolean;
@@ -17,7 +17,6 @@ import { Alert } from "components/Alert/Alert";
import { ErrorAlert } from "components/Alert/ErrorAlert";
import { CodeExample } from "components/CodeExample/CodeExample";
import { CopyableValue } from "components/CopyableValue/CopyableValue";
import { Header } from "components/DeploySettingsLayout/Header";
import { ConfirmDialog } from "components/Dialogs/ConfirmDialog/ConfirmDialog";
import { DeleteDialog } from "components/Dialogs/DeleteDialog/DeleteDialog";
import { Loader } from "components/Loader/Loader";
@@ -25,6 +24,7 @@ import { Stack } from "components/Stack/Stack";
import { TableLoader } from "components/TableLoader/TableLoader";
import { createDayString } from "utils/createDayString";
import { OAuth2AppForm } from "./OAuth2AppForm";
import { Header } from "../Header";
export type MutatingResource = {
updateApp: boolean;
@@ -19,10 +19,10 @@ import {
EnterpriseBadge,
EntitledBadge,
} from "components/Badges/Badges";
import { Header } from "components/DeploySettingsLayout/Header";
import { TableLoader } from "components/TableLoader/TableLoader";
import { Stack } from "components/Stack/Stack";
import { useClickableTableRow } from "hooks/useClickableTableRow";
import { Header } from "../Header";
type OAuth2AppsSettingsProps = {
apps?: TypesGen.OAuth2ProviderApp[];
@@ -1,8 +1,8 @@
import { useDashboard } from "components/Dashboard/DashboardProvider";
import { useDeploySettings } from "components/DeploySettingsLayout/DeploySettingsLayout";
import { FC } from "react";
import { type FC } from "react";
import { Helmet } from "react-helmet-async";
import { pageTitle } from "utils/page";
import { useDashboard } from "components/Dashboard/DashboardProvider";
import { useDeploySettings } from "../DeploySettingsLayout";
import { ObservabilitySettingsPageView } from "./ObservabilitySettingsPageView";
const ObservabilitySettingsPage: FC = () => {
@@ -1,24 +1,25 @@
import { type FC } from "react";
import type { ClibaseOption } from "api/typesGenerated";
import { deploymentGroupHasParent } from "utils/deployOptions";
import { docs } from "utils/docs";
import {
Badges,
DisabledBadge,
EnabledBadge,
EnterpriseBadge,
} from "components/Badges/Badges";
import { Header } from "components/DeploySettingsLayout/Header";
import OptionsTable from "components/DeploySettingsLayout/OptionsTable";
import { Stack } from "components/Stack/Stack";
import { deploymentGroupHasParent } from "utils/deployOptions";
import { docs } from "utils/docs";
import { Header } from "../Header";
import OptionsTable from "../OptionsTable";
export type ObservabilitySettingsPageViewProps = {
options: ClibaseOption[];
featureAuditLogEnabled: boolean;
};
export const ObservabilitySettingsPageView = ({
options: options,
featureAuditLogEnabled,
}: ObservabilitySettingsPageViewProps): JSX.Element => {
export const ObservabilitySettingsPageView: FC<
ObservabilitySettingsPageViewProps
> = ({ options: options, featureAuditLogEnabled }) => {
return (
<>
<Stack direction="column" spacing={6}>
@@ -2,7 +2,7 @@ import CheckCircleOutlined from "@mui/icons-material/CheckCircleOutlined";
import { css, useTheme } from "@emotion/react";
import { type HTMLAttributes, type PropsWithChildren, type FC } from "react";
import { MONOSPACE_FONT_FAMILY } from "theme/constants";
import { DisabledBadge, EnabledBadge } from "../Badges/Badges";
import { DisabledBadge, EnabledBadge } from "components/Badges/Badges";
export const OptionName: FC<PropsWithChildren> = ({ children }) => {
return <span css={{ display: "block" }}>{children}</span>;
@@ -13,7 +13,7 @@ import {
OptionDescription,
OptionName,
OptionValue,
} from "components/DeploySettingsLayout/Option";
} from "./Option";
import { optionValue } from "./optionValue";
interface OptionsTableProps {
@@ -1,9 +1,9 @@
import { useDashboard } from "components/Dashboard/DashboardProvider";
import { useDeploySettings } from "components/DeploySettingsLayout/DeploySettingsLayout";
import { FC } from "react";
import { type FC } from "react";
import { Helmet } from "react-helmet-async";
import { pageTitle } from "utils/page";
import { useDashboard } from "components/Dashboard/DashboardProvider";
import { SecuritySettingsPageView } from "./SecuritySettingsPageView";
import { useDeploySettings } from "../DeploySettingsLayout";
const SecuritySettingsPage: FC = () => {
const { deploymentValues: deploymentValues } = useDeploySettings();
@@ -1,3 +1,4 @@
import { type FC } from "react";
import type { ClibaseOption } from "api/typesGenerated";
import {
Badges,
@@ -5,72 +6,71 @@ import {
EnabledBadge,
EnterpriseBadge,
} from "components/Badges/Badges";
import { Header } from "components/DeploySettingsLayout/Header";
import OptionsTable from "components/DeploySettingsLayout/OptionsTable";
import { Stack } from "components/Stack/Stack";
import {
deploymentGroupHasParent,
useDeploymentOptions,
} from "utils/deployOptions";
import { docs } from "utils/docs";
import { Header } from "../Header";
import OptionsTable from "../OptionsTable";
export type SecuritySettingsPageViewProps = {
options: ClibaseOption[];
featureBrowserOnlyEnabled: boolean;
};
export const SecuritySettingsPageView = ({
export const SecuritySettingsPageView: FC<SecuritySettingsPageViewProps> = ({
options: options,
featureBrowserOnlyEnabled,
}: SecuritySettingsPageViewProps): JSX.Element => {
}) => {
const tlsOptions = options.filter((o) =>
deploymentGroupHasParent(o.group, "TLS"),
);
return (
<>
<Stack direction="column" spacing={6}>
<Stack direction="column" spacing={6}>
<div>
<Header
title="Security"
description="Ensure your Coder deployment is secure."
/>
<OptionsTable
options={useDeploymentOptions(
options,
"SSH Keygen Algorithm",
"Secure Auth Cookie",
"Disable Owner Workspace Access",
)}
/>
</div>
<div>
<Header
title="Browser Only Connections"
secondary
description="Block all workspace access via SSH, port forward, and other non-browser connections."
docsHref={docs("/networking#browser-only-connections-enterprise")}
/>
<Badges>
{featureBrowserOnlyEnabled ? <EnabledBadge /> : <DisabledBadge />}
<EnterpriseBadge />
</Badges>
</div>
{tlsOptions.length > 0 && (
<div>
<Header
title="Security"
description="Ensure your Coder deployment is secure."
/>
<OptionsTable
options={useDeploymentOptions(
options,
"SSH Keygen Algorithm",
"Secure Auth Cookie",
"Disable Owner Workspace Access",
)}
/>
</div>
<div>
<Header
title="Browser Only Connections"
title="TLS"
secondary
description="Block all workspace access via SSH, port forward, and other non-browser connections."
docsHref={docs("/networking#browser-only-connections-enterprise")}
description="Ensure TLS is properly configured for your Coder deployment."
/>
<Badges>
{featureBrowserOnlyEnabled ? <EnabledBadge /> : <DisabledBadge />}
<EnterpriseBadge />
</Badges>
<OptionsTable options={tlsOptions} />
</div>
{tlsOptions.length > 0 && (
<div>
<Header
title="TLS"
secondary
description="Ensure TLS is properly configured for your Coder deployment."
/>
<OptionsTable options={tlsOptions} />
</div>
)}
</Stack>
</>
)}
</Stack>
);
};
@@ -1,7 +1,7 @@
import { useDeploySettings } from "components/DeploySettingsLayout/DeploySettingsLayout";
import { FC } from "react";
import { type FC } from "react";
import { Helmet } from "react-helmet-async";
import { pageTitle } from "utils/page";
import { useDeploySettings } from "../DeploySettingsLayout";
import { UserAuthSettingsPageView } from "./UserAuthSettingsPageView";
const UserAuthSettingsPage: FC = () => {
@@ -1,8 +1,8 @@
import type { ClibaseOption } from "api/typesGenerated";
import { Badges, DisabledBadge, EnabledBadge } from "components/Badges/Badges";
import { Header } from "components/DeploySettingsLayout/Header";
import OptionsTable from "components/DeploySettingsLayout/OptionsTable";
import { Stack } from "components/Stack/Stack";
import { Header } from "../Header";
import OptionsTable from "../OptionsTable";
import {
deploymentGroupHasParent,
useDeploymentOptions,
@@ -68,7 +68,7 @@ const ExternalAuthPageView: FC<ExternalAuthPageViewProps> = ({
</Welcome>
<p css={styles.text}>
{externalAuth.user?.login && `Hey @${externalAuth.user?.login}! 👋 `}
{externalAuth.user?.login && `Hey @${externalAuth.user?.login}! 👋`}
{(!externalAuth.app_installable ||
externalAuth.installations.length > 0) &&
"You are now authenticated. Feel free to close this window!"}
+1 -1
View File
@@ -289,7 +289,7 @@ const GroupMemberRow: FC<GroupMemberRowProps> = ({
css={[styles.status, member.status === "suspended" && styles.suspended]}
>
<div>{member.status}</div>
<LastSeen value={member.last_seen_at} css={{ fontSize: 12 }} />
<LastSeen at={member.last_seen_at} css={{ fontSize: 12 }} />
</TableCell>
<TableCell width="1%">
{canUpdate && (
@@ -177,7 +177,7 @@ export const UsersTableBody: FC<
]}
>
<div>{user.status}</div>
<LastSeen value={user.last_seen_at} css={{ fontSize: 12 }} />
<LastSeen at={user.last_seen_at} css={{ fontSize: 12 }} />
</TableCell>
{canEditUsers && (