mirror of
https://github.com/coder/coder.git
synced 2026-09-22 05:05:20 +08:00
chore: miscellaneous cleanup (#11027)
This commit is contained in:
@@ -21,7 +21,7 @@ export const Alert: FC<AlertProps> = ({
|
||||
children,
|
||||
actions,
|
||||
dismissible,
|
||||
severity,
|
||||
severity = "info",
|
||||
onDismiss,
|
||||
...alertProps
|
||||
}) => {
|
||||
|
||||
@@ -17,9 +17,7 @@ export const BuildAvatar: FC<BuildAvatarProps> = ({ build, size }) => {
|
||||
const theme = useTheme();
|
||||
const { status, type } = getDisplayWorkspaceBuildStatus(theme, build);
|
||||
const badgeType = useClassName(
|
||||
(css, theme) => css`
|
||||
background-color: ${theme.palette[type].light};
|
||||
`,
|
||||
(css, theme) => css({ backgroundColor: theme.palette[type].light }),
|
||||
[type],
|
||||
);
|
||||
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
import {
|
||||
type FC,
|
||||
type FormEvent,
|
||||
type PropsWithChildren,
|
||||
useId,
|
||||
useState,
|
||||
} from "react";
|
||||
|
||||
import { useTheme } from "@emotion/react";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import { type Interpolation, type Theme } from "@emotion/react";
|
||||
import { type FC, type FormEvent, useId, useState } from "react";
|
||||
import { Stack } from "../../Stack/Stack";
|
||||
import { ConfirmDialog } from "../ConfirmDialog/ConfirmDialog";
|
||||
|
||||
export interface DeleteDialogProps {
|
||||
@@ -24,7 +18,7 @@ export interface DeleteDialogProps {
|
||||
confirmText?: string;
|
||||
}
|
||||
|
||||
export const DeleteDialog: FC<PropsWithChildren<DeleteDialogProps>> = ({
|
||||
export const DeleteDialog: FC<DeleteDialogProps> = ({
|
||||
isOpen,
|
||||
onCancel,
|
||||
onConfirm,
|
||||
@@ -39,7 +33,6 @@ export const DeleteDialog: FC<PropsWithChildren<DeleteDialogProps>> = ({
|
||||
confirmText,
|
||||
}) => {
|
||||
const hookId = useId();
|
||||
const theme = useTheme();
|
||||
|
||||
const [userConfirmationText, setUserConfirmationText] = useState("");
|
||||
const [isFocused, setIsFocused] = useState(false);
|
||||
@@ -69,19 +62,17 @@ export const DeleteDialog: FC<PropsWithChildren<DeleteDialogProps>> = ({
|
||||
confirmText={confirmText}
|
||||
description={
|
||||
<>
|
||||
<p>
|
||||
{verb ?? "Deleting"} this {entity} is irreversible!
|
||||
</p>
|
||||
<Stack spacing={1.5}>
|
||||
<p>
|
||||
{verb ?? "Deleting"} this {entity} is irreversible!
|
||||
</p>
|
||||
|
||||
{Boolean(info) && (
|
||||
<p css={{ color: theme.palette.warning.light }}>{info}</p>
|
||||
)}
|
||||
{Boolean(info) && <div css={styles.callout}>{info}</div>}
|
||||
|
||||
<p>Are you sure you want to proceed?</p>
|
||||
|
||||
<p>
|
||||
Type “<strong>{name}</strong>” below to confirm.
|
||||
</p>
|
||||
<p>
|
||||
Type <strong>{name}</strong> below to confirm.
|
||||
</p>
|
||||
</Stack>
|
||||
|
||||
<form onSubmit={onSubmit}>
|
||||
<TextField
|
||||
@@ -114,3 +105,13 @@ export const DeleteDialog: FC<PropsWithChildren<DeleteDialogProps>> = ({
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = {
|
||||
callout: (theme) => ({
|
||||
backgroundColor: theme.experimental.roles.danger.background,
|
||||
border: `1px solid ${theme.experimental.roles.danger.outline}`,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
color: theme.experimental.roles.danger.text,
|
||||
padding: "8px 16px",
|
||||
}),
|
||||
} satisfies Record<string, Interpolation<Theme>>;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import MuiDialog, { DialogProps as MuiDialogProps } from "@mui/material/Dialog";
|
||||
import LoadingButton, { LoadingButtonProps } from "@mui/lab/LoadingButton";
|
||||
import { type Interpolation, type Theme } from "@emotion/react";
|
||||
import { type FC, type ReactNode } from "react";
|
||||
import { ConfirmDialogType } from "./types";
|
||||
import { type Interpolation, type Theme } from "@emotion/react";
|
||||
import LoadingButton, { LoadingButtonProps } from "@mui/lab/LoadingButton";
|
||||
|
||||
export interface DialogActionButtonsProps {
|
||||
/** Text to display in the cancel button */
|
||||
|
||||
@@ -7,11 +7,11 @@ import {
|
||||
HelpTooltipTitle,
|
||||
HelpTooltipTrigger,
|
||||
} from "components/HelpTooltip/HelpTooltip";
|
||||
import { Interpolation, Theme, css, useTheme } from "@emotion/react";
|
||||
import { css, type Interpolation, type Theme, useTheme } from "@emotion/react";
|
||||
import type { ThemeRole } from "theme/experimental";
|
||||
|
||||
interface InfoTooltipProps {
|
||||
// TODO: use a `ThemeRole` type or something
|
||||
type?: "warning" | "notice" | "info";
|
||||
type?: ThemeRole;
|
||||
title: ReactNode;
|
||||
message: ReactNode;
|
||||
}
|
||||
@@ -22,13 +22,12 @@ export const InfoTooltip: FC<InfoTooltipProps> = ({
|
||||
type = "info",
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const iconColor = theme.experimental.roles[type].outline;
|
||||
|
||||
return (
|
||||
<HelpTooltip>
|
||||
<HelpTooltipTrigger size="small" css={styles.button}>
|
||||
<HelpTooltipIcon
|
||||
css={{ color: theme.experimental.roles[type].outline }}
|
||||
/>
|
||||
<HelpTooltipIcon css={{ color: iconColor }} />
|
||||
</HelpTooltipTrigger>
|
||||
<HelpTooltipContent>
|
||||
<HelpTooltipTitle>{title}</HelpTooltipTitle>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { useTheme } from "@emotion/react";
|
||||
import HelpOutline from "@mui/icons-material/HelpOutline";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import { type FC } from "react";
|
||||
import { getLatencyColor } from "utils/latency";
|
||||
import CircularProgress from "@mui/material/CircularProgress";
|
||||
import { visuallyHidden } from "@mui/utils";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { type FC } from "react";
|
||||
import { getLatencyColor } from "utils/latency";
|
||||
import { Abbr } from "components/Abbr/Abbr";
|
||||
|
||||
interface ProxyStatusLatencyProps {
|
||||
@@ -17,18 +17,16 @@ export const ProxyStatusLatency: FC<ProxyStatusLatencyProps> = ({
|
||||
isLoading,
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const color = getLatencyColor(theme, latency);
|
||||
// Always use the no latency color for loading.
|
||||
const color = getLatencyColor(theme, isLoading ? undefined : latency);
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<Tooltip title="Loading latency...">
|
||||
<CircularProgress
|
||||
size={14}
|
||||
css={{
|
||||
// Always use the no latency color for loading.
|
||||
color: getLatencyColor(theme, undefined),
|
||||
marginLeft: "auto",
|
||||
}}
|
||||
css={{ marginLeft: "auto" }}
|
||||
style={{ color }}
|
||||
/>
|
||||
</Tooltip>
|
||||
);
|
||||
@@ -45,8 +43,8 @@ export const ProxyStatusLatency: FC<ProxyStatusLatencyProps> = ({
|
||||
css={{
|
||||
marginLeft: "auto",
|
||||
fontSize: "14px !important",
|
||||
color,
|
||||
}}
|
||||
style={{ color }}
|
||||
/>
|
||||
</>
|
||||
</Tooltip>
|
||||
@@ -54,7 +52,7 @@ export const ProxyStatusLatency: FC<ProxyStatusLatencyProps> = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<p css={{ color, fontSize: 13, margin: "0 0 0 auto" }}>
|
||||
<p css={{ fontSize: 13, margin: "0 0 0 auto" }} style={{ color }}>
|
||||
<span css={{ ...visuallyHidden }}>Latency: </span>
|
||||
{latency.toFixed(0)}
|
||||
<Abbr title="milliseconds">ms</Abbr>
|
||||
|
||||
@@ -2,7 +2,7 @@ import { type CSSObject, type Interpolation, type Theme } from "@emotion/react";
|
||||
import Button from "@mui/material/Button";
|
||||
import Paper from "@mui/material/Paper";
|
||||
import dayjs from "dayjs";
|
||||
import { useState } from "react";
|
||||
import { type FC, useState } from "react";
|
||||
import { compareAsc } from "date-fns";
|
||||
import { type GetLicensesResponse } from "api/api";
|
||||
import { ConfirmDialog } from "components/Dialogs/ConfirmDialog/ConfirmDialog";
|
||||
@@ -17,13 +17,13 @@ type LicenseCardProps = {
|
||||
isRemoving: boolean;
|
||||
};
|
||||
|
||||
export const LicenseCard = ({
|
||||
export const LicenseCard: FC<LicenseCardProps> = ({
|
||||
license,
|
||||
userLimitActual,
|
||||
userLimitLimit,
|
||||
onRemove,
|
||||
isRemoving,
|
||||
}: LicenseCardProps) => {
|
||||
}) => {
|
||||
const [licenseIDMarkedForRemoval, setLicenseIDMarkedForRemoval] = useState<
|
||||
number | undefined
|
||||
>(undefined);
|
||||
|
||||
@@ -508,9 +508,9 @@ export const TemplateVersionEditor: FC<TemplateVersionEditorProps> = ({
|
||||
ref={buildLogsRef}
|
||||
css={{
|
||||
display: selectedTab !== "logs" ? "none" : "flex",
|
||||
height: selectedTab ? 280 : 0,
|
||||
flexDirection: "column",
|
||||
overflowY: "auto",
|
||||
height: selectedTab ? 280 : 0,
|
||||
}}
|
||||
>
|
||||
{templateVersion.job.error && (
|
||||
@@ -536,33 +536,7 @@ export const TemplateVersionEditor: FC<TemplateVersionEditorProps> = ({
|
||||
|
||||
{buildLogs && buildLogs.length > 0 && (
|
||||
<WorkspaceBuildLogs
|
||||
css={{
|
||||
borderRadius: 0,
|
||||
border: 0,
|
||||
|
||||
// Hack to update logs header and lines
|
||||
"& .logs-header": {
|
||||
border: 0,
|
||||
padding: "0 16px",
|
||||
fontFamily: MONOSPACE_FONT_FAMILY,
|
||||
|
||||
"&:first-child": {
|
||||
paddingTop: 16,
|
||||
},
|
||||
|
||||
"&:last-child": {
|
||||
paddingBottom: 16,
|
||||
},
|
||||
},
|
||||
|
||||
"& .logs-line": {
|
||||
paddingLeft: 16,
|
||||
},
|
||||
|
||||
"& .logs-container": {
|
||||
border: "0 !important",
|
||||
},
|
||||
}}
|
||||
css={styles.buildLogs}
|
||||
hideTimestamps
|
||||
logs={buildLogs}
|
||||
/>
|
||||
@@ -570,25 +544,13 @@ export const TemplateVersionEditor: FC<TemplateVersionEditorProps> = ({
|
||||
</div>
|
||||
|
||||
<div
|
||||
css={{
|
||||
display: selectedTab !== "resources" ? "none" : undefined,
|
||||
overflowY: "auto",
|
||||
height: selectedTab ? 280 : 0,
|
||||
|
||||
// Hack to access customize resource-card from here
|
||||
"& .resource-card": {
|
||||
borderLeft: 0,
|
||||
borderRight: 0,
|
||||
|
||||
"&:first-child": {
|
||||
borderTop: 0,
|
||||
},
|
||||
|
||||
"&:last-child": {
|
||||
borderBottom: 0,
|
||||
},
|
||||
css={[
|
||||
{
|
||||
display: selectedTab !== "resources" ? "none" : undefined,
|
||||
height: selectedTab ? 280 : 0,
|
||||
},
|
||||
}}
|
||||
styles.resources,
|
||||
]}
|
||||
>
|
||||
{resources && (
|
||||
<TemplateResourcesTable
|
||||
@@ -670,6 +632,7 @@ const styles = {
|
||||
color: theme.palette.text.disabled,
|
||||
},
|
||||
}),
|
||||
|
||||
tabBar: (theme) => ({
|
||||
padding: "8px 16px",
|
||||
position: "sticky",
|
||||
@@ -684,4 +647,50 @@ const styles = {
|
||||
borderTop: `1px solid ${theme.palette.divider}`,
|
||||
},
|
||||
}),
|
||||
|
||||
buildLogs: {
|
||||
borderRadius: 0,
|
||||
border: 0,
|
||||
|
||||
// Hack to update logs header and lines
|
||||
"& .logs-header": {
|
||||
border: 0,
|
||||
padding: "0 16px",
|
||||
fontFamily: MONOSPACE_FONT_FAMILY,
|
||||
|
||||
"&:first-child": {
|
||||
paddingTop: 16,
|
||||
},
|
||||
|
||||
"&:last-child": {
|
||||
paddingBottom: 16,
|
||||
},
|
||||
},
|
||||
|
||||
"& .logs-line": {
|
||||
paddingLeft: 16,
|
||||
},
|
||||
|
||||
"& .logs-container": {
|
||||
border: "0 !important",
|
||||
},
|
||||
},
|
||||
|
||||
resources: {
|
||||
overflowY: "auto",
|
||||
|
||||
// Hack to access customize resource-card from here
|
||||
"& .resource-card": {
|
||||
borderLeft: 0,
|
||||
borderRight: 0,
|
||||
|
||||
"&:first-child": {
|
||||
borderTop: 0,
|
||||
},
|
||||
|
||||
"&:last-child": {
|
||||
borderBottom: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
} satisfies Record<string, Interpolation<Theme>>;
|
||||
|
||||
@@ -4,18 +4,18 @@ import TableCell from "@mui/material/TableCell";
|
||||
import TableContainer from "@mui/material/TableContainer";
|
||||
import TableHead from "@mui/material/TableHead";
|
||||
import TableRow from "@mui/material/TableRow";
|
||||
import { ChooseOne, Cond } from "components/Conditionals/ChooseOne";
|
||||
import { Stack } from "components/Stack/Stack";
|
||||
import { TableEmpty } from "components/TableEmpty/TableEmpty";
|
||||
import { TableLoader } from "components/TableLoader/TableLoader";
|
||||
import IconButton from "@mui/material/IconButton";
|
||||
import DeleteOutlineIcon from "@mui/icons-material/DeleteOutline";
|
||||
import dayjs from "dayjs";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { type FC, type ReactNode } from "react";
|
||||
import IconButton from "@mui/material/IconButton/IconButton";
|
||||
import type { APIKeyWithOwner } from "api/typesGenerated";
|
||||
import relativeTime from "dayjs/plugin/relativeTime";
|
||||
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||
import { ChooseOne, Cond } from "components/Conditionals/ChooseOne";
|
||||
import { Stack } from "components/Stack/Stack";
|
||||
import { TableEmpty } from "components/TableEmpty/TableEmpty";
|
||||
import { TableLoader } from "components/TableLoader/TableLoader";
|
||||
|
||||
dayjs.extend(relativeTime);
|
||||
|
||||
|
||||
@@ -49,10 +49,6 @@ const deleteUser = async () => {
|
||||
const deleteButton = screen.getByText(/Delete/);
|
||||
await user.click(deleteButton);
|
||||
|
||||
// Check if the confirm message is displayed
|
||||
const confirmDialog = await screen.findByRole("dialog");
|
||||
expect(confirmDialog).toHaveTextContent(`Are you sure you want to proceed?`);
|
||||
|
||||
// Confirm with text input
|
||||
const textField = screen.getByLabelText("Name of the user to delete");
|
||||
const dialog = screen.getByRole("dialog");
|
||||
|
||||
@@ -136,6 +136,7 @@ export const BatchDeleteConfirmation: FC<BatchDeleteConfirmationProps> = ({
|
||||
|
||||
return (
|
||||
<ConfirmDialog
|
||||
type="delete"
|
||||
open={open}
|
||||
onClose={() => {
|
||||
setStage("consequences");
|
||||
@@ -146,7 +147,6 @@ export const BatchDeleteConfirmation: FC<BatchDeleteConfirmationProps> = ({
|
||||
confirmLoading={isLoading}
|
||||
confirmText={confirmText}
|
||||
onConfirm={onProceed}
|
||||
type="delete"
|
||||
description={
|
||||
<>
|
||||
{stage === "consequences" && <Consequences />}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import ArrowForwardOutlined from "@mui/icons-material/ArrowForwardOutlined";
|
||||
import Button from "@mui/material/Button";
|
||||
import { Template } from "api/typesGenerated";
|
||||
import type { Template } from "api/typesGenerated";
|
||||
import { Avatar } from "components/Avatar/Avatar";
|
||||
import { TableEmpty } from "components/TableEmpty/TableEmpty";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import ErrorIcon from "@mui/icons-material/ErrorOutline";
|
||||
import StopIcon from "@mui/icons-material/StopOutlined";
|
||||
import PlayIcon from "@mui/icons-material/PlayArrowOutlined";
|
||||
import QueuedIcon from "@mui/icons-material/HourglassEmpty";
|
||||
import dayjs from "dayjs";
|
||||
import duration from "dayjs/plugin/duration";
|
||||
import minMax from "dayjs/plugin/minMax";
|
||||
import utc from "dayjs/plugin/utc";
|
||||
import ErrorIcon from "@mui/icons-material/ErrorOutline";
|
||||
import StopIcon from "@mui/icons-material/StopOutlined";
|
||||
import PlayIcon from "@mui/icons-material/PlayArrowOutlined";
|
||||
import QueuedIcon from "@mui/icons-material/HourglassEmpty";
|
||||
import { type Theme } from "@emotion/react";
|
||||
import semver from "semver";
|
||||
import type * as TypesGen from "api/typesGenerated";
|
||||
@@ -36,19 +36,19 @@ export const getDisplayWorkspaceBuildStatus = (
|
||||
case "succeeded":
|
||||
return {
|
||||
type: "success",
|
||||
color: theme.palette.success.light,
|
||||
color: theme.experimental.roles.success.text,
|
||||
status: DisplayWorkspaceBuildStatusLanguage.succeeded,
|
||||
} as const;
|
||||
case "pending":
|
||||
return {
|
||||
type: "secondary",
|
||||
color: theme.palette.text.secondary,
|
||||
color: theme.experimental.roles.active.text,
|
||||
status: DisplayWorkspaceBuildStatusLanguage.pending,
|
||||
} as const;
|
||||
case "running":
|
||||
return {
|
||||
type: "info",
|
||||
color: theme.palette.primary.main,
|
||||
color: theme.experimental.roles.active.text,
|
||||
status: DisplayWorkspaceBuildStatusLanguage.running,
|
||||
} as const;
|
||||
// Just handle unknown as failed
|
||||
@@ -56,19 +56,19 @@ export const getDisplayWorkspaceBuildStatus = (
|
||||
case "failed":
|
||||
return {
|
||||
type: "error",
|
||||
color: theme.palette.text.secondary,
|
||||
color: theme.experimental.roles.error.text,
|
||||
status: DisplayWorkspaceBuildStatusLanguage.failed,
|
||||
} as const;
|
||||
case "canceling":
|
||||
return {
|
||||
type: "warning",
|
||||
color: theme.palette.warning.light,
|
||||
color: theme.experimental.roles.warning.text,
|
||||
status: DisplayWorkspaceBuildStatusLanguage.canceling,
|
||||
} as const;
|
||||
case "canceled":
|
||||
return {
|
||||
type: "secondary",
|
||||
color: theme.palette.text.secondary,
|
||||
color: theme.experimental.roles.warning.text,
|
||||
status: DisplayWorkspaceBuildStatusLanguage.canceled,
|
||||
} as const;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user