mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
refactor(site): remove Stack component (#24503)
## Summary Remove the deprecated `Stack` component and replace all usages with Tailwind flex utility classes. - Replaced `<Stack>` → `<div className="flex flex-col gap-4">` (and variants per props) - Updated `StackLabel` and `FormFields` to no longer depend on `Stack` - Deleted `Stack.tsx` and `Stack.stories.tsx` 74 files changed, -226 lines net. > 🤖 Generated by Coder Agents --------- Co-authored-by: Jake Howell <jacob@coder.com>
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
import { Badge } from "#/components/Badge/Badge";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
|
||||
export const EnabledBadge: React.FC = () => {
|
||||
return (
|
||||
@@ -51,8 +50,6 @@ export const DeprecatedBadge: React.FC = () => {
|
||||
|
||||
export const Badges: React.FC<React.PropsWithChildren> = ({ children }) => {
|
||||
return (
|
||||
<Stack className="mb-4" direction="row" alignItems="center" spacing={1}>
|
||||
{children}
|
||||
</Stack>
|
||||
<div className="flex flex-row items-center gap-2 mb-4">{children}</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import type { Interpolation, Theme } from "@emotion/react";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import { type FC, type FormEvent, useId, useState } from "react";
|
||||
import { Stack } from "../../Stack/Stack";
|
||||
import { ConfirmDialog } from "../ConfirmDialog/ConfirmDialog";
|
||||
|
||||
interface DeleteDialogProps {
|
||||
@@ -62,17 +61,15 @@ export const DeleteDialog: FC<DeleteDialogProps> = ({
|
||||
confirmText={confirmText}
|
||||
description={
|
||||
<>
|
||||
<Stack spacing={1.5}>
|
||||
<div className="flex flex-col gap-3">
|
||||
<p>
|
||||
{verb ?? "Deleting"} this {entity} is irreversible!
|
||||
</p>
|
||||
|
||||
{Boolean(info) && <div css={styles.callout}>{info}</div>}
|
||||
|
||||
<p>
|
||||
Type <strong>{name}</strong> below to confirm.
|
||||
</p>
|
||||
</Stack>
|
||||
</div>
|
||||
|
||||
<form onSubmit={onSubmit}>
|
||||
<TextField
|
||||
|
||||
@@ -3,7 +3,6 @@ import CircularProgress from "@mui/material/CircularProgress";
|
||||
import { CloudUploadIcon, FolderIcon, TrashIcon } from "lucide-react";
|
||||
import { type DragEvent, type FC, type ReactNode, useRef } from "react";
|
||||
import { Button } from "#/components/Button/Button";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { useClickable } from "#/hooks/useClickable";
|
||||
|
||||
interface FileUploadProps {
|
||||
@@ -35,16 +34,14 @@ export const FileUpload: FC<FileUploadProps> = ({
|
||||
|
||||
if (!isUploading && file) {
|
||||
return (
|
||||
<Stack
|
||||
<div
|
||||
css={styles.file}
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
alignItems="center"
|
||||
className="flex flex-row justify-between items-center gap-4"
|
||||
>
|
||||
<Stack direction="row" alignItems="center">
|
||||
<div className="flex flex-row items-center gap-4">
|
||||
<FolderIcon className="size-icon-sm" />
|
||||
<span>{file.name}</span>
|
||||
</Stack>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
variant="subtle"
|
||||
@@ -54,7 +51,7 @@ export const FileUpload: FC<FileUploadProps> = ({
|
||||
>
|
||||
<TrashIcon className="size-icon-sm" />
|
||||
</Button>
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -66,7 +63,7 @@ export const FileUpload: FC<FileUploadProps> = ({
|
||||
{...clickable}
|
||||
{...fileDrop}
|
||||
>
|
||||
<Stack alignItems="center" spacing={1}>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<div css={styles.iconWrapper}>
|
||||
{isUploading ? (
|
||||
<CircularProgress size={32} />
|
||||
@@ -75,11 +72,11 @@ export const FileUpload: FC<FileUploadProps> = ({
|
||||
)}
|
||||
</div>
|
||||
|
||||
<Stack alignItems="center" spacing={0.5}>
|
||||
<div className="flex flex-col items-center gap-1">
|
||||
<span css={styles.title}>{title}</span>
|
||||
<span css={styles.description}>{description}</span>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input
|
||||
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
useContext,
|
||||
} from "react";
|
||||
import { AlphaBadge, DeprecatedBadge } from "#/components/Badges/Badges";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { cn } from "#/utils/cn";
|
||||
|
||||
type FormContextValue = { direction?: "horizontal" | "vertical" };
|
||||
@@ -120,11 +119,13 @@ export const FormSection: FC<FormSectionProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
export const FormFields: FC<ComponentProps<typeof Stack>> = (props) => {
|
||||
export const FormFields: FC<ComponentProps<"div">> = ({
|
||||
className,
|
||||
...props
|
||||
}) => {
|
||||
return (
|
||||
<Stack
|
||||
direction="column"
|
||||
spacing={3}
|
||||
<div
|
||||
className={cn("flex flex-col gap-6", className)}
|
||||
{...props}
|
||||
css={styles.formSectionFields}
|
||||
/>
|
||||
|
||||
@@ -3,7 +3,6 @@ import type { Meta, StoryObj } from "@storybook/react-vite";
|
||||
import type { FC } from "react";
|
||||
import { Button } from "#/components/Button/Button";
|
||||
import { FormFooter } from "#/components/Form/Form";
|
||||
import { Stack } from "../Stack/Stack";
|
||||
import { FullPageForm, type FullPageFormProps } from "./FullPageForm";
|
||||
|
||||
const Template: FC<FullPageFormProps> = (props) => (
|
||||
@@ -13,14 +12,14 @@ const Template: FC<FullPageFormProps> = (props) => (
|
||||
e.preventDefault();
|
||||
}}
|
||||
>
|
||||
<Stack>
|
||||
<div className="flex flex-col gap-4">
|
||||
<TextField fullWidth label="Field 1" name="field1" />
|
||||
<TextField fullWidth label="Field 2" name="field2" />
|
||||
<FormFooter>
|
||||
<Button variant="outline">Cancel</Button>
|
||||
<Button type="submit">Save</Button>
|
||||
</FormFooter>
|
||||
</Stack>
|
||||
</div>
|
||||
</form>
|
||||
</FullPageForm>
|
||||
);
|
||||
|
||||
@@ -12,12 +12,12 @@ import { Button } from "#/components/Button/Button";
|
||||
import { ExternalImage } from "#/components/ExternalImage/ExternalImage";
|
||||
import { MemoizedMarkdown } from "#/components/Markdown/Markdown";
|
||||
import { Pill } from "#/components/Pill/Pill";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "#/components/Tooltip/Tooltip";
|
||||
import { cn } from "#/utils/cn";
|
||||
import type {
|
||||
AutofillBuildParameter,
|
||||
AutofillSource,
|
||||
@@ -182,7 +182,7 @@ const ParameterLabel: FC<ParameterLabelProps> = ({ parameter, isPreset }) => {
|
||||
|
||||
return (
|
||||
<label htmlFor={parameter.name}>
|
||||
<Stack direction="row" alignItems="center">
|
||||
<div className="flex flex-row items-center gap-4">
|
||||
{parameter.icon && (
|
||||
<span css={styles.labelIconWrapper}>
|
||||
<ExternalImage
|
||||
@@ -194,16 +194,16 @@ const ParameterLabel: FC<ParameterLabelProps> = ({ parameter, isPreset }) => {
|
||||
)}
|
||||
|
||||
{hasDescription ? (
|
||||
<Stack spacing={0}>
|
||||
<div className="flex flex-col gap-0">
|
||||
{labelPrimary}
|
||||
<MemoizedMarkdown css={styles.labelCaption}>
|
||||
{parameter.description}
|
||||
</MemoizedMarkdown>
|
||||
</Stack>
|
||||
</div>
|
||||
) : (
|
||||
labelPrimary
|
||||
)}
|
||||
</Stack>
|
||||
</div>
|
||||
</label>
|
||||
);
|
||||
};
|
||||
@@ -235,10 +235,12 @@ export const RichParameterInput: FC<RichParameterInputProps> = ({
|
||||
const [hideSuggestion, setHideSuggestion] = useState(false);
|
||||
|
||||
return (
|
||||
<Stack
|
||||
direction="column"
|
||||
spacing={size === "small" ? 1.25 : 2}
|
||||
className={size}
|
||||
<div
|
||||
className={cn(
|
||||
"flex flex-col",
|
||||
size === "small" ? "gap-2.5" : "gap-4",
|
||||
size,
|
||||
)}
|
||||
data-testid={`parameter-field-${parameter.name}`}
|
||||
>
|
||||
<ParameterLabel parameter={parameter} isPreset={isPreset} />
|
||||
@@ -276,7 +278,7 @@ export const RichParameterInput: FC<RichParameterInputProps> = ({
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -332,7 +334,7 @@ const RichParameterField: FC<RichParameterInputProps> = ({
|
||||
value={option.value}
|
||||
control={<Radio size="small" />}
|
||||
label={
|
||||
<Stack direction="row" alignItems="center">
|
||||
<div className="flex flex-row items-center gap-4">
|
||||
{option.icon && (
|
||||
<ExternalImage
|
||||
css={styles.optionIcon}
|
||||
@@ -341,11 +343,13 @@ const RichParameterField: FC<RichParameterInputProps> = ({
|
||||
/>
|
||||
)}
|
||||
{option.description ? (
|
||||
<Stack
|
||||
spacing={small ? 1 : 0}
|
||||
alignItems={small ? "center" : undefined}
|
||||
direction={small ? "row" : "column"}
|
||||
className={small ? undefined : "py-1"}
|
||||
<div
|
||||
className={cn(
|
||||
"flex",
|
||||
small
|
||||
? "flex-row gap-2 items-center"
|
||||
: "flex-col gap-0 py-1",
|
||||
)}
|
||||
>
|
||||
{small ? (
|
||||
<Tooltip>
|
||||
@@ -366,11 +370,11 @@ const RichParameterField: FC<RichParameterInputProps> = ({
|
||||
</MemoizedMarkdown>
|
||||
</>
|
||||
)}
|
||||
</Stack>
|
||||
</div>
|
||||
) : (
|
||||
option.name
|
||||
)}
|
||||
</Stack>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
))}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { ElementType, FC, ReactNode } from "react";
|
||||
import { Link, NavLink } from "react-router";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { cn } from "#/utils/cn";
|
||||
|
||||
interface SidebarProps {
|
||||
@@ -31,7 +30,7 @@ export const SidebarHeader: FC<SidebarHeaderProps> = ({
|
||||
linkTo,
|
||||
}) => {
|
||||
return (
|
||||
<Stack direction="row" spacing={1} className="mb-4">
|
||||
<div className="flex flex-row gap-2 mb-4">
|
||||
{avatar}
|
||||
<div className="overflow-hidden flex flex-col">
|
||||
{linkTo ? (
|
||||
@@ -45,7 +44,7 @@ export const SidebarHeader: FC<SidebarHeaderProps> = ({
|
||||
{subtitle}
|
||||
</span>
|
||||
</div>
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -100,10 +99,10 @@ export const SidebarNavItem: FC<SidebarNavItemProps> = ({
|
||||
)
|
||||
}
|
||||
>
|
||||
<Stack alignItems="center" spacing={1.5} direction="row">
|
||||
<div className="flex flex-row gap-3 items-center">
|
||||
<Icon className="size-4" />
|
||||
{children}
|
||||
</Stack>
|
||||
</div>
|
||||
</NavLink>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
import type { Meta, StoryObj } from "@storybook/react-vite";
|
||||
import { Stack } from "./Stack";
|
||||
|
||||
const meta: Meta<typeof Stack> = {
|
||||
title: "components/Stack",
|
||||
component: Stack,
|
||||
args: {
|
||||
children: (
|
||||
<>
|
||||
<span>チェンソーマン</span>
|
||||
<span>ジョジョの奇妙な冒険</span>
|
||||
<span>スパイファミリー</span>
|
||||
<span>葬送のフリーレン</span>
|
||||
<span>少女革命ウテナ</span>
|
||||
<span>PSYCHO-PASS サイコパス</span>
|
||||
<span>機動戦士ガンダム 水星の魔女</span>
|
||||
<span>勇気爆発バーンブレイバーン</span>
|
||||
<span>Re:ゼロから始める異世界生活</span>
|
||||
<span>ダンジョン飯</span>
|
||||
</>
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof Stack>;
|
||||
|
||||
export const Vertical: Story = {};
|
||||
|
||||
export const VerticalCenter: Story = {
|
||||
args: {
|
||||
alignItems: "center",
|
||||
},
|
||||
};
|
||||
|
||||
export const Horizontal: Story = {
|
||||
args: {
|
||||
direction: "row",
|
||||
},
|
||||
};
|
||||
|
||||
export const HorizontalWrap: Story = {
|
||||
args: {
|
||||
direction: "row",
|
||||
wrap: "wrap",
|
||||
},
|
||||
};
|
||||
@@ -1,42 +0,0 @@
|
||||
import type { CSSObject } from "@emotion/react";
|
||||
|
||||
type StackProps = React.ComponentPropsWithRef<"div"> & {
|
||||
className?: string;
|
||||
direction?: "column" | "row";
|
||||
spacing?: number;
|
||||
alignItems?: CSSObject["alignItems"];
|
||||
justifyContent?: CSSObject["justifyContent"];
|
||||
wrap?: CSSObject["flexWrap"];
|
||||
};
|
||||
|
||||
/**
|
||||
* @deprecated Stack component is deprecated. Use Tailwind flex utilities instead.
|
||||
*/
|
||||
export const Stack: React.FC<StackProps> = (props) => {
|
||||
const {
|
||||
children,
|
||||
direction = "column",
|
||||
spacing = 2,
|
||||
alignItems,
|
||||
justifyContent,
|
||||
wrap,
|
||||
...divProps
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<div
|
||||
{...divProps}
|
||||
css={{
|
||||
display: "flex",
|
||||
flexDirection: direction,
|
||||
gap: spacing * 8,
|
||||
alignItems: alignItems,
|
||||
justifyContent: justifyContent,
|
||||
flexWrap: wrap,
|
||||
maxWidth: "100%",
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,5 +1,4 @@
|
||||
import type { ComponentProps, FC } from "react";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { cn } from "#/utils/cn";
|
||||
|
||||
/**
|
||||
@@ -7,14 +6,13 @@ import { cn } from "#/utils/cn";
|
||||
* buttons, checkboxes, or switches to ensure proper styling.
|
||||
*/
|
||||
|
||||
export const StackLabel: FC<ComponentProps<typeof Stack>> = ({
|
||||
export const StackLabel: FC<ComponentProps<"div">> = ({
|
||||
className,
|
||||
...props
|
||||
}) => {
|
||||
return (
|
||||
<Stack
|
||||
spacing={0.5}
|
||||
className={cn("pl-3 font-medium", className)}
|
||||
<div
|
||||
className={cn("flex flex-col gap-1 pl-3 font-medium", className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -5,7 +5,6 @@ import {
|
||||
Sidebar as BaseSidebar,
|
||||
SettingsSidebarNavItem as SidebarNavItem,
|
||||
} from "#/components/Sidebar/Sidebar";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import type { Permissions } from "#/modules/permissions";
|
||||
import { getPrereleaseFlag } from "#/utils/buildInfo";
|
||||
|
||||
@@ -86,9 +85,9 @@ export const DeploymentSidebarView: FC<DeploymentSidebarViewProps> = ({
|
||||
)}
|
||||
{permissions.viewAnyGroup && (
|
||||
<SidebarNavItem href="/deployment/groups">
|
||||
<Stack direction="row" alignItems="center" spacing={0.5}>
|
||||
<div className="flex flex-row items-center gap-1">
|
||||
Groups {showOrganizations && <ArrowUpRightIcon size={16} />}
|
||||
</Stack>
|
||||
</div>
|
||||
</SidebarNavItem>
|
||||
)}
|
||||
{permissions.viewOrganizationIDPSyncSettings && (
|
||||
@@ -108,9 +107,9 @@ export const DeploymentSidebarView: FC<DeploymentSidebarViewProps> = ({
|
||||
)}
|
||||
{permissions.editDeploymentConfig && (
|
||||
<SidebarNavItem href="/agents/settings/agents">
|
||||
<Stack direction="row" alignItems="center" spacing={0.5}>
|
||||
<div className="flex flex-row items-center gap-1">
|
||||
Manage Coder Agents <ArrowUpRightIcon size={16} />
|
||||
</Stack>
|
||||
</div>
|
||||
</SidebarNavItem>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -15,7 +15,6 @@ import type {
|
||||
WorkspaceAgentMetadata,
|
||||
} from "#/api/typesGenerated";
|
||||
import { Skeleton } from "#/components/Skeleton/Skeleton";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
@@ -139,7 +138,7 @@ export const AgentMetadata: FC<AgentMetadataProps> = ({
|
||||
|
||||
const AgentMetadataSkeleton: FC = () => {
|
||||
return (
|
||||
<Stack alignItems="baseline" direction="row" spacing={6}>
|
||||
<div className="flex flex-row items-baseline gap-12">
|
||||
<div className="leading-relaxed flex flex-col overflow-visible flex-shrink-0">
|
||||
<Skeleton width={40} height={6} variant="text" />
|
||||
<Skeleton width={65} height={8} variant="text" />
|
||||
@@ -154,7 +153,7 @@ const AgentMetadataSkeleton: FC = () => {
|
||||
<Skeleton width={40} height={6} variant="text" />
|
||||
<Skeleton width={65} height={8} variant="text" />
|
||||
</div>
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
HelpPopoverTitle,
|
||||
HelpPopoverTrigger,
|
||||
} from "#/components/HelpPopover/HelpPopover";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { agentVersionStatus } from "../../utils/workspace";
|
||||
|
||||
type AgentOutdatedTooltipProps = {
|
||||
@@ -46,25 +45,25 @@ export const AgentOutdatedTooltip: FC<AgentOutdatedTooltipProps> = ({
|
||||
</span>
|
||||
</HelpPopoverTrigger>
|
||||
<HelpPopoverContent>
|
||||
<Stack spacing={1}>
|
||||
<div className="flex flex-col gap-2">
|
||||
<div>
|
||||
<HelpPopoverTitle>{title}</HelpPopoverTitle>
|
||||
<HelpPopoverText>{text}</HelpPopoverText>
|
||||
</div>
|
||||
|
||||
<Stack spacing={0.5}>
|
||||
<div className="flex flex-col gap-1">
|
||||
<span className="font-semibold text-content-primary">
|
||||
Agent version
|
||||
</span>
|
||||
<span>{agent.version}</span>
|
||||
</Stack>
|
||||
</div>
|
||||
|
||||
<Stack spacing={0.5}>
|
||||
<div className="flex flex-col gap-1">
|
||||
<span className="font-semibold text-content-primary">
|
||||
Server version
|
||||
</span>
|
||||
<span>{serverVersion}</span>
|
||||
</Stack>
|
||||
</div>
|
||||
|
||||
<HelpPopoverLinksGroup>
|
||||
<HelpPopoverAction
|
||||
@@ -78,7 +77,7 @@ export const AgentOutdatedTooltip: FC<AgentOutdatedTooltipProps> = ({
|
||||
Update workspace
|
||||
</HelpPopoverAction>
|
||||
</HelpPopoverLinksGroup>
|
||||
</Stack>
|
||||
</div>
|
||||
</HelpPopoverContent>
|
||||
</HelpPopover>
|
||||
);
|
||||
|
||||
@@ -3,7 +3,6 @@ import type { FC } from "react";
|
||||
import type { WorkspaceAgent } from "#/api/typesGenerated";
|
||||
import { TerminalIcon } from "#/components/Icons/TerminalIcon";
|
||||
import { VSCodeIcon } from "#/components/Icons/VSCodeIcon";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { DisplayAppNameMap } from "./AppLink/AppLink";
|
||||
import { AppPreview } from "./AppLink/AppPreview";
|
||||
import { BaseIcon } from "./AppLink/BaseIcon";
|
||||
@@ -22,27 +21,21 @@ export const AgentRowPreview: FC<AgentRowPreviewProps> = ({
|
||||
alignValues,
|
||||
}) => {
|
||||
return (
|
||||
<Stack
|
||||
<div
|
||||
key={agent.id}
|
||||
direction="row"
|
||||
alignItems="center"
|
||||
justifyContent="space-between"
|
||||
className="flex flex-row items-center justify-between gap-4"
|
||||
css={styles.agentRow}
|
||||
>
|
||||
<Stack direction="row" alignItems="baseline">
|
||||
<div className="flex flex-row items-baseline gap-4">
|
||||
<div css={styles.agentStatusWrapper}>
|
||||
<div css={styles.agentStatusPreview} />
|
||||
</div>
|
||||
<Stack
|
||||
alignItems="baseline"
|
||||
direction="row"
|
||||
spacing={4}
|
||||
<div
|
||||
className="flex flex-row items-baseline gap-8"
|
||||
css={styles.agentData}
|
||||
>
|
||||
<Stack
|
||||
direction="row"
|
||||
alignItems="baseline"
|
||||
spacing={1}
|
||||
<div
|
||||
className="flex flex-row items-baseline gap-2"
|
||||
css={[
|
||||
styles.noShrink,
|
||||
styles.agentDataItem,
|
||||
@@ -55,12 +48,10 @@ export const AgentRowPreview: FC<AgentRowPreviewProps> = ({
|
||||
>
|
||||
<span>Agent:</span>
|
||||
<span css={styles.agentDataValue}>{agent.name}</span>
|
||||
</Stack>
|
||||
</div>
|
||||
|
||||
<Stack
|
||||
direction="row"
|
||||
alignItems="baseline"
|
||||
spacing={1}
|
||||
<div
|
||||
className="flex flex-row items-baseline gap-2"
|
||||
css={[
|
||||
styles.noShrink,
|
||||
styles.agentDataItem,
|
||||
@@ -75,21 +66,14 @@ export const AgentRowPreview: FC<AgentRowPreviewProps> = ({
|
||||
<span css={[styles.agentDataValue, styles.agentOS]}>
|
||||
{agent.operating_system}
|
||||
</span>
|
||||
</Stack>
|
||||
</div>
|
||||
|
||||
<Stack
|
||||
direction="row"
|
||||
alignItems="center"
|
||||
spacing={1}
|
||||
<div
|
||||
className="flex flex-row items-center gap-2"
|
||||
css={styles.agentDataItem}
|
||||
>
|
||||
<span>Apps:</span>
|
||||
<Stack
|
||||
direction="row"
|
||||
alignItems="center"
|
||||
spacing={0.5}
|
||||
wrap="wrap"
|
||||
>
|
||||
<div className="flex flex-row items-center gap-1 flex-wrap">
|
||||
{/* We display all modules returned in agent.apps */}
|
||||
{agent.apps.map((app) => (
|
||||
<AppPreview key={app.slug}>
|
||||
@@ -130,11 +114,11 @@ export const AgentRowPreview: FC<AgentRowPreviewProps> = ({
|
||||
{agent.apps.length === 0 && agent.display_apps.length === 0 && (
|
||||
<span css={styles.agentDataValue}>None</span>
|
||||
)}
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
import type { FC, PropsWithChildren } from "react";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
export const AppPreview: FC<PropsWithChildren> = ({ children }) => {
|
||||
return (
|
||||
<Stack
|
||||
className="flex items-center h-8 px-3 rounded-full border border-solid border-surface-quaternary text-content-primary bg-surface-secondary flex-shrink-0 w-fit text-xs [&>svg]:w-[13px] [&>img]:w-[13px]"
|
||||
alignItems="center"
|
||||
direction="row"
|
||||
spacing={1}
|
||||
>
|
||||
<div className="flex flex-row items-center gap-2 h-8 px-3 rounded-full border border-solid border-surface-quaternary text-content-primary bg-surface-secondary flex-shrink-0 w-fit text-xs [&>svg]:w-[13px] [&>img]:w-[13px]">
|
||||
{children}
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -5,7 +5,6 @@ import { ChevronDownIcon } from "#/components/AnimatedIcons/ChevronDown";
|
||||
import { Button } from "#/components/Button/Button";
|
||||
import { CopyableValue } from "#/components/CopyableValue/CopyableValue";
|
||||
import { MemoizedInlineMarkdown } from "#/components/Markdown/InlineMarkdown";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
@@ -97,13 +96,11 @@ export const ResourceCard: FC<ResourceCardProps> = ({ resource, agentRow }) => {
|
||||
|
||||
return (
|
||||
<div key={resource.id} css={styles.resourceCard} className="resource-card">
|
||||
<Stack
|
||||
direction="row"
|
||||
alignItems="flex-start"
|
||||
<div
|
||||
className="flex flex-row items-start gap-20"
|
||||
css={styles.resourceCardHeader}
|
||||
spacing={10}
|
||||
>
|
||||
<Stack direction="row" spacing={1} css={styles.resourceCardProfile}>
|
||||
<div className="flex flex-row gap-2" css={styles.resourceCardProfile}>
|
||||
<div>
|
||||
<ResourceAvatar resource={resource} />
|
||||
</div>
|
||||
@@ -111,7 +108,7 @@ export const ResourceCard: FC<ResourceCardProps> = ({ resource, agentRow }) => {
|
||||
<div css={styles.metadataLabel}>{resource.type}</div>
|
||||
<div css={styles.metadataValue}>{resource.name}</div>
|
||||
</div>
|
||||
</Stack>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="grow-[2] grid gap-x-10 gap-y-6"
|
||||
@@ -180,7 +177,7 @@ export const ResourceCard: FC<ResourceCardProps> = ({ resource, agentRow }) => {
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</Stack>
|
||||
</div>
|
||||
|
||||
{resource.agents && resource.agents.length > 0 && (
|
||||
<div>{resource.agents.map(agentRow)}</div>
|
||||
|
||||
@@ -2,7 +2,6 @@ import { type FC, type JSX, useState } from "react";
|
||||
import type { WorkspaceAgent, WorkspaceResource } from "#/api/typesGenerated";
|
||||
import { ChevronDownIcon } from "#/components/AnimatedIcons/ChevronDown";
|
||||
import { Button } from "#/components/Button/Button";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { ResourceCard } from "./ResourceCard";
|
||||
|
||||
const countAgents = (resource: WorkspaceResource) => {
|
||||
@@ -26,7 +25,7 @@ export const Resources: FC<ResourcesProps> = ({ resources, agentRow }) => {
|
||||
const hasHideResources = resources.some((r) => r.hide);
|
||||
|
||||
return (
|
||||
<Stack direction="column" spacing={0} className="bg-surface-primary">
|
||||
<div className="flex flex-col bg-surface-primary">
|
||||
{displayResources.map((resource) => (
|
||||
<ResourceCard
|
||||
key={resource.id}
|
||||
@@ -50,6 +49,6 @@ export const Resources: FC<ResourcesProps> = ({ resources, agentRow }) => {
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -14,7 +14,6 @@ import {
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "#/components/Popover/Popover";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { docs } from "#/utils/docs";
|
||||
|
||||
interface AgentSSHButtonProps {
|
||||
@@ -49,7 +48,7 @@ export const AgentSSHButton: FC<AgentSSHButtonProps> = ({
|
||||
</HelpPopoverText>
|
||||
|
||||
<ol style={{ margin: 0, padding: 0 }}>
|
||||
<Stack spacing={0.5} className="mt-3">
|
||||
<div className="flex flex-col gap-1 mt-3">
|
||||
<SSHStep
|
||||
helpText="Configure SSH hosts on machine:"
|
||||
codeExample="coder config-ssh"
|
||||
@@ -58,7 +57,7 @@ export const AgentSSHButton: FC<AgentSSHButtonProps> = ({
|
||||
helpText="Connect to the agent:"
|
||||
codeExample={`ssh ${agentName}.${workspaceName}.${workspaceOwnerUsername}.${sshSuffix}`}
|
||||
/>
|
||||
</Stack>
|
||||
</div>
|
||||
</ol>
|
||||
|
||||
<HelpPopoverLinksGroup>
|
||||
|
||||
@@ -36,7 +36,6 @@ import {
|
||||
SelectValue,
|
||||
} from "#/components/Select/Select";
|
||||
import { Slider } from "#/components/Slider/Slider";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { Switch } from "#/components/Switch/Switch";
|
||||
import { TagInput } from "#/components/TagInput/TagInput";
|
||||
import { Textarea } from "#/components/Textarea/Textarea";
|
||||
@@ -505,7 +504,7 @@ const MaskableInput: FC<MaskableInputProps> = ({
|
||||
const [showMaskedInput, setShowMaskedInput] = useState(false);
|
||||
|
||||
return (
|
||||
<Stack direction="row" spacing={0} alignItems="center">
|
||||
<div className="flex flex-row items-center">
|
||||
<Input
|
||||
id={id}
|
||||
type={masked && showMaskedInput ? "text" : type}
|
||||
@@ -535,7 +534,7 @@ const MaskableInput: FC<MaskableInputProps> = ({
|
||||
)}
|
||||
</Button>
|
||||
)}
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -552,7 +551,7 @@ const MaskableTextArea: FC<MaskableInputProps> = ({
|
||||
const [showMaskedInput, setShowMaskedInput] = useState(false);
|
||||
|
||||
return (
|
||||
<Stack direction="row" spacing={0} alignItems="center">
|
||||
<div className="flex flex-row items-center">
|
||||
<Textarea
|
||||
ref={textareaRef}
|
||||
id={id}
|
||||
@@ -589,7 +588,7 @@ const MaskableTextArea: FC<MaskableInputProps> = ({
|
||||
)}
|
||||
</Button>
|
||||
)}
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ import type { DialogProps } from "#/components/Dialogs/Dialog";
|
||||
import { FormFields } from "#/components/Form/Form";
|
||||
import { Loader } from "#/components/Loader/Loader";
|
||||
import { Pill } from "#/components/Pill/Pill";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { TemplateUpdateMessage } from "#/modules/templates/TemplateUpdateMessage";
|
||||
import { createDayString } from "#/utils/createDayString";
|
||||
|
||||
@@ -55,7 +54,7 @@ export const ChangeWorkspaceVersionDialog: FC<
|
||||
confirmText="Change"
|
||||
title="Change version"
|
||||
description={
|
||||
<Stack>
|
||||
<div className="flex flex-col gap-4">
|
||||
<p>You are about to change the version of this workspace.</p>
|
||||
{validVersions ? (
|
||||
<>
|
||||
@@ -90,16 +89,8 @@ export const ChangeWorkspaceVersionDialog: FC<
|
||||
/>
|
||||
}
|
||||
title={
|
||||
<Stack
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
style={{ width: "100%" }}
|
||||
>
|
||||
<Stack
|
||||
direction="row"
|
||||
alignItems="center"
|
||||
spacing={1}
|
||||
>
|
||||
<div className="flex flex-row justify-between gap-4 w-full">
|
||||
<div className="flex flex-row items-center gap-2">
|
||||
{option.name}
|
||||
{option.message && (
|
||||
<InfoIcon
|
||||
@@ -107,10 +98,10 @@ export const ChangeWorkspaceVersionDialog: FC<
|
||||
className="size-icon-xs"
|
||||
/>
|
||||
)}
|
||||
</Stack>
|
||||
</div>
|
||||
{workspace.template_active_version_id ===
|
||||
option.id && <Pill type="success">Active</Pill>}
|
||||
</Stack>
|
||||
</div>
|
||||
}
|
||||
subtitle={createDayString(option.created_at)}
|
||||
/>
|
||||
@@ -155,7 +146,7 @@ export const ChangeWorkspaceVersionDialog: FC<
|
||||
) : (
|
||||
<Loader />
|
||||
)}
|
||||
</Stack>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -12,7 +12,6 @@ import {
|
||||
type ConfirmDialogProps,
|
||||
} from "#/components/Dialogs/ConfirmDialog/ConfirmDialog";
|
||||
import { Skeleton } from "#/components/Skeleton/Skeleton";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { cn } from "#/utils/cn";
|
||||
|
||||
type DownloadLogsDialogProps = Pick<
|
||||
@@ -140,7 +139,7 @@ export const DownloadLogsDialog: FC<DownloadLogsDialogProps> = ({
|
||||
}
|
||||
}}
|
||||
description={
|
||||
<Stack className="pb-4">
|
||||
<div className="flex flex-col gap-4 pb-4">
|
||||
<p>
|
||||
Downloading logs will create a zip file containing all logs from all
|
||||
jobs in this workspace. This may take a while.
|
||||
@@ -162,7 +161,7 @@ export const DownloadLogsDialog: FC<DownloadLogsDialogProps> = ({
|
||||
/>
|
||||
))}
|
||||
</ul>
|
||||
</Stack>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -13,7 +13,6 @@ import {
|
||||
type PaginationResult,
|
||||
} from "#/components/PaginationWidget/PaginationContainer";
|
||||
import { PaywallPremium } from "#/components/Paywall/PaywallPremium";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -56,10 +55,10 @@ export const AuditPageView: FC<AuditPageViewProps> = ({
|
||||
<Margins className="pb-12">
|
||||
<PageHeader>
|
||||
<PageHeaderTitle>
|
||||
<Stack direction="row" spacing={1} alignItems="center">
|
||||
<div className="flex flex-row gap-2 items-center">
|
||||
<span>Audit</span>
|
||||
<AuditHelpPopover />
|
||||
</Stack>
|
||||
</div>
|
||||
</PageHeaderTitle>
|
||||
<PageHeaderSubtitle>View events in your audit log.</PageHeaderSubtitle>
|
||||
</PageHeader>
|
||||
|
||||
@@ -13,7 +13,6 @@ import {
|
||||
type PaginationResult,
|
||||
} from "#/components/PaginationWidget/PaginationContainer";
|
||||
import { PaywallPremium } from "#/components/Paywall/PaywallPremium";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -55,10 +54,10 @@ export const ConnectionLogPageView: FC<ConnectionLogPageViewProps> = ({
|
||||
<Margins className="pb-12">
|
||||
<PageHeader>
|
||||
<PageHeaderTitle>
|
||||
<Stack direction="row" spacing={1} alignItems="center">
|
||||
<div className="flex flex-row gap-2 items-center">
|
||||
<span>Connection Log</span>
|
||||
<ConnectionLogHelpPopover />
|
||||
</Stack>
|
||||
</div>
|
||||
</PageHeaderTitle>
|
||||
<PageHeaderSubtitle>
|
||||
View workspace connection events.
|
||||
|
||||
@@ -2,7 +2,6 @@ import type { Interpolation, Theme } from "@emotion/react";
|
||||
import type { FC } from "react";
|
||||
import { Link, useSearchParams } from "react-router";
|
||||
import type { TemplateExample } from "#/api/typesGenerated";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { TemplateExampleCard } from "#/modules/templates/TemplateExampleCard/TemplateExampleCard";
|
||||
import type { StarterTemplatesByTag } from "#/utils/starterTemplates";
|
||||
|
||||
@@ -64,9 +63,9 @@ export const StarterTemplates: FC<StarterTemplatesProps> = ({
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<Stack direction="row" spacing={4} alignItems="flex-start">
|
||||
<div className="flex flex-row gap-8 items-start">
|
||||
{starterTemplatesByTag && tags && (
|
||||
<Stack className="w-[202px] shrink-0 sticky">
|
||||
<div className="flex flex-col gap-4 w-[202px] shrink-0 sticky">
|
||||
<h2 css={styles.sectionTitle}>Choose a starter template</h2>
|
||||
<span css={styles.filterCaption}>Filter</span>
|
||||
{tags.map((tag) => (
|
||||
@@ -78,7 +77,7 @@ export const StarterTemplates: FC<StarterTemplatesProps> = ({
|
||||
{getTagLabel(tag)} ({starterTemplatesByTag[tag].length})
|
||||
</Link>
|
||||
))}
|
||||
</Stack>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex flex-wrap gap-8 h-max">
|
||||
@@ -93,7 +92,7 @@ export const StarterTemplates: FC<StarterTemplatesProps> = ({
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ import RadioGroup from "@mui/material/RadioGroup";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import type { FC } from "react";
|
||||
import type { TemplateVersionVariable } from "#/api/typesGenerated";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
|
||||
const isBoolean = (variable: TemplateVersionVariable) => {
|
||||
return variable.type === "bool";
|
||||
@@ -41,7 +40,7 @@ export const VariableInput: FC<VariableInputProps> = ({
|
||||
defaultValue,
|
||||
}) => {
|
||||
return (
|
||||
<Stack direction="column" spacing={0.75}>
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<VariableLabel variable={variable} />
|
||||
<div css={styles.input}>
|
||||
<VariableField
|
||||
@@ -51,7 +50,7 @@ export const VariableInput: FC<VariableInputProps> = ({
|
||||
defaultValue={defaultValue}
|
||||
/>
|
||||
</div>
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ import {
|
||||
HorizontalForm,
|
||||
} from "#/components/Form/Form";
|
||||
import { Spinner } from "#/components/Spinner/Spinner";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { getFormHelpers, onChangeTrimmed } from "#/utils/formUtils";
|
||||
import {
|
||||
type CreateTokenData,
|
||||
@@ -102,7 +101,7 @@ export const CreateTokenForm: FC<CreateTokenFormProps> = ({
|
||||
classes={{ sectionInfo: classNames.sectionInfo }}
|
||||
>
|
||||
<FormFields>
|
||||
<Stack direction="row">
|
||||
<div className="flex flex-row gap-4">
|
||||
<TextField
|
||||
select
|
||||
label="Lifetime"
|
||||
@@ -153,7 +152,7 @@ export const CreateTokenForm: FC<CreateTokenFormProps> = ({
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Stack>
|
||||
</div>
|
||||
</FormFields>
|
||||
</FormSection>
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import type { FC } from "react";
|
||||
import type { Template, TemplateExample } from "#/api/typesGenerated";
|
||||
import { Avatar } from "#/components/Avatar/Avatar";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
|
||||
interface SelectedTemplateProps {
|
||||
template: Template | TemplateExample;
|
||||
@@ -9,17 +8,14 @@ interface SelectedTemplateProps {
|
||||
|
||||
export const SelectedTemplate: FC<SelectedTemplateProps> = ({ template }) => {
|
||||
return (
|
||||
<Stack
|
||||
direction="row"
|
||||
className="py-5 px-6 rounded-lg bg-surface-primary border border-solid border-border"
|
||||
>
|
||||
<div className="flex flex-row gap-4 py-5 px-6 rounded-lg bg-surface-primary border border-solid border-border">
|
||||
<Avatar
|
||||
variant="icon"
|
||||
size="lg"
|
||||
src={template.icon}
|
||||
fallback={template.name}
|
||||
/>
|
||||
<Stack direction="column" spacing={0}>
|
||||
<div className="flex flex-col">
|
||||
<span className="text-base">
|
||||
{"display_name" in template && template.display_name.length > 0
|
||||
? template.display_name
|
||||
@@ -30,7 +26,7 @@ export const SelectedTemplate: FC<SelectedTemplateProps> = ({ template }) => {
|
||||
{template.description}
|
||||
</span>
|
||||
)}
|
||||
</Stack>
|
||||
</Stack>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
+2
-3
@@ -9,7 +9,6 @@ import {
|
||||
SettingsHeaderDocsLink,
|
||||
SettingsHeaderTitle,
|
||||
} from "#/components/SettingsHeader/SettingsHeader";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { deploymentGroupHasParent } from "#/utils/deployOptions";
|
||||
import { docs } from "#/utils/docs";
|
||||
import OptionsTable from "../OptionsTable";
|
||||
@@ -24,7 +23,7 @@ export const AIGovernanceSettingsPageView: FC<
|
||||
AIGovernanceSettingsPageViewProps
|
||||
> = ({ options, featureAIBridgeEntitled, featureAIBridgeEnabled }) => {
|
||||
return (
|
||||
<Stack direction="column" spacing={6}>
|
||||
<div className="flex flex-col gap-12">
|
||||
<SettingsHeader>
|
||||
<SettingsHeaderTitle>AI Governance</SettingsHeaderTitle>
|
||||
</SettingsHeader>
|
||||
@@ -70,6 +69,6 @@ export const AIGovernanceSettingsPageView: FC<
|
||||
<PaywallAIGovernance />
|
||||
)}
|
||||
</div>
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
+4
-5
@@ -7,7 +7,6 @@ import { SliderPicker, TwitterPicker } from "react-color";
|
||||
import type { BannerConfig } from "#/api/typesGenerated";
|
||||
import { Button } from "#/components/Button/Button";
|
||||
import { Dialog, DialogActionButtons } from "#/components/Dialogs/Dialog";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { AnnouncementBannerView } from "#/modules/dashboard/AnnouncementBanners/AnnouncementBannerView";
|
||||
import { getFormHelpers } from "#/utils/formUtils";
|
||||
|
||||
@@ -50,7 +49,7 @@ export const AnnouncementBannerDialog: FC<AnnouncementBannerDialogProps> = ({
|
||||
|
||||
<div css={styles.dialogContent}>
|
||||
<h3 css={styles.dialogTitle}>Announcement banner</h3>
|
||||
<Stack>
|
||||
<div className="flex flex-col gap-4">
|
||||
<div>
|
||||
<h4 css={styles.settingName}>Message</h4>
|
||||
<TextField
|
||||
@@ -67,7 +66,7 @@ export const AnnouncementBannerDialog: FC<AnnouncementBannerDialogProps> = ({
|
||||
</div>
|
||||
<div>
|
||||
<h4 css={styles.settingName}>Background color</h4>
|
||||
<Stack spacing={2}>
|
||||
<div className="flex flex-col gap-4">
|
||||
{showHuePicker ? (
|
||||
<SliderPicker
|
||||
color={bannerForm.values.background_color}
|
||||
@@ -127,9 +126,9 @@ export const AnnouncementBannerDialog: FC<AnnouncementBannerDialogProps> = ({
|
||||
Show {showHuePicker ? "palette" : "slider"}
|
||||
</Button>
|
||||
</div>
|
||||
</Stack>
|
||||
</div>
|
||||
</div>
|
||||
</Stack>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<DialogActions>
|
||||
|
||||
+4
-9
@@ -12,7 +12,6 @@ import {
|
||||
SettingsHeaderDescription,
|
||||
SettingsHeaderTitle,
|
||||
} from "#/components/SettingsHeader/SettingsHeader";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { Fieldset } from "../Fieldset";
|
||||
import { DividerWithText } from "./DividerWithText";
|
||||
|
||||
@@ -52,11 +51,7 @@ export const AddNewLicensePageView: FC<AddNewLicenseProps> = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<Stack
|
||||
alignItems="baseline"
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<div className="flex flex-row gap-4 items-baseline justify-between">
|
||||
<SettingsHeader>
|
||||
<SettingsHeaderTitle>Add a license</SettingsHeaderTitle>
|
||||
<SettingsHeaderDescription>
|
||||
@@ -70,7 +65,7 @@ export const AddNewLicensePageView: FC<AddNewLicenseProps> = ({
|
||||
All Licenses
|
||||
</RouterLink>
|
||||
</Button>
|
||||
</Stack>
|
||||
</div>
|
||||
|
||||
{savingLicenseError && <ErrorAlert error={savingLicenseError} />}
|
||||
|
||||
@@ -82,7 +77,7 @@ export const AddNewLicensePageView: FC<AddNewLicenseProps> = ({
|
||||
description="Select a text file that contains your license key."
|
||||
/>
|
||||
|
||||
<Stack className="pt-10">
|
||||
<div className="flex flex-col gap-4 pt-10">
|
||||
<DividerWithText>or</DividerWithText>
|
||||
|
||||
<Fieldset
|
||||
@@ -111,7 +106,7 @@ export const AddNewLicensePageView: FC<AddNewLicenseProps> = ({
|
||||
fullWidth
|
||||
/>
|
||||
</Fieldset>
|
||||
</Stack>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
+10
-15
@@ -14,7 +14,6 @@ import {
|
||||
} from "#/components/SettingsHeader/SettingsHeader";
|
||||
import { Skeleton } from "#/components/Skeleton/Skeleton";
|
||||
import { Spinner } from "#/components/Spinner/Spinner";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
@@ -71,11 +70,7 @@ const LicensesSettingsPageView: FC<Props> = ({
|
||||
colors={[theme.palette.primary.main, theme.palette.secondary.main]}
|
||||
/>
|
||||
|
||||
<Stack
|
||||
alignItems="baseline"
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<div className="flex flex-row gap-4 items-baseline justify-between">
|
||||
<SettingsHeader>
|
||||
<SettingsHeaderTitle>Licenses</SettingsHeaderTitle>
|
||||
<SettingsHeaderDescription>
|
||||
@@ -83,7 +78,7 @@ const LicensesSettingsPageView: FC<Props> = ({
|
||||
</SettingsHeaderDescription>
|
||||
</SettingsHeader>
|
||||
|
||||
<Stack direction="row" spacing={2}>
|
||||
<div className="flex flex-row gap-4">
|
||||
<Button variant="outline" asChild>
|
||||
<RouterLink to="/deployment/licenses/add">
|
||||
<PlusIcon />
|
||||
@@ -108,14 +103,14 @@ const LicensesSettingsPageView: FC<Props> = ({
|
||||
minutes.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-4">
|
||||
{isLoading && <Skeleton height={78} />}
|
||||
|
||||
{!isLoading && licenses && licenses?.length > 0 && (
|
||||
<Stack spacing={4} className="licenses">
|
||||
<div className="flex flex-col gap-8 licenses">
|
||||
{[...(licenses ?? [])]
|
||||
?.sort(
|
||||
(a, b) =>
|
||||
@@ -133,13 +128,13 @@ const LicensesSettingsPageView: FC<Props> = ({
|
||||
onRemove={removeLicense}
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!isLoading && licenses?.length === 0 && (
|
||||
<div className="min-h-[240px] flex items-center justify-center rounded-lg border border-solid border-border p-12">
|
||||
<Stack alignItems="center" spacing={1}>
|
||||
<Stack alignItems="center" spacing={0.5}>
|
||||
<div className="flex flex-col gap-2 items-center">
|
||||
<div className="flex flex-col gap-1 items-center">
|
||||
<span className="text-base">
|
||||
You don't have any licenses!
|
||||
</span>
|
||||
@@ -152,8 +147,8 @@ const LicensesSettingsPageView: FC<Props> = ({
|
||||
</MuiLink>{" "}
|
||||
to get started.
|
||||
</span>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
+2
-3
@@ -11,7 +11,6 @@ import {
|
||||
SettingsHeaderDocsLink,
|
||||
SettingsHeaderTitle,
|
||||
} from "#/components/SettingsHeader/SettingsHeader";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import {
|
||||
deploymentGroupHasParent,
|
||||
useDeploymentOptions,
|
||||
@@ -26,7 +25,7 @@ type NetworkSettingsPageViewProps = {
|
||||
export const NetworkSettingsPageView: FC<NetworkSettingsPageViewProps> = ({
|
||||
options,
|
||||
}) => (
|
||||
<Stack direction="column" spacing={6}>
|
||||
<div className="flex flex-col gap-12">
|
||||
<div>
|
||||
<SettingsHeader
|
||||
actions={<SettingsHeaderDocsLink href={docs("/admin/networking")} />}
|
||||
@@ -70,5 +69,5 @@ export const NetworkSettingsPageView: FC<NetworkSettingsPageViewProps> = ({
|
||||
)}
|
||||
</Badges>
|
||||
</div>
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -17,7 +17,6 @@ import {
|
||||
import type { DeploymentValues } from "#/api/typesGenerated";
|
||||
import { Alert } from "#/components/Alert/Alert";
|
||||
import { Button } from "#/components/Button/Button";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
@@ -67,7 +66,7 @@ export const NotificationEvents: FC<NotificationEventsProps> = ({
|
||||
]);
|
||||
|
||||
return (
|
||||
<Stack spacing={4}>
|
||||
<div className="flex flex-col gap-8">
|
||||
{hasWebhookNotifications && !isWebhookConfigured && (
|
||||
<Alert
|
||||
severity="warning"
|
||||
@@ -140,7 +139,7 @@ export const NotificationEvents: FC<NotificationEventsProps> = ({
|
||||
</List>
|
||||
</Card>
|
||||
))}
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
+4
-9
@@ -9,7 +9,6 @@ import {
|
||||
SettingsHeaderDescription,
|
||||
SettingsHeaderTitle,
|
||||
} from "#/components/SettingsHeader/SettingsHeader";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { OAuth2AppForm } from "./OAuth2AppForm";
|
||||
|
||||
type CreateOAuth2AppProps = {
|
||||
@@ -33,11 +32,7 @@ export const CreateOAuth2AppPageView: FC<CreateOAuth2AppProps> = ({
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<Stack
|
||||
alignItems="baseline"
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<div className="flex flex-row gap-4 items-baseline justify-between">
|
||||
<SettingsHeader>
|
||||
<SettingsHeaderTitle>Add an OAuth2 application</SettingsHeaderTitle>
|
||||
<SettingsHeaderDescription>
|
||||
@@ -51,9 +46,9 @@ export const CreateOAuth2AppPageView: FC<CreateOAuth2AppProps> = ({
|
||||
All OAuth2 Applications
|
||||
</RouterLink>
|
||||
</Button>
|
||||
</Stack>
|
||||
</div>
|
||||
|
||||
<Stack>
|
||||
<div className="flex flex-col gap-4">
|
||||
{error ? <ErrorAlert error={error} /> : undefined}
|
||||
<OAuth2AppForm
|
||||
onSubmit={createApp}
|
||||
@@ -62,7 +57,7 @@ export const CreateOAuth2AppPageView: FC<CreateOAuth2AppProps> = ({
|
||||
defaultValues={defaultValues}
|
||||
disabled={!canCreateApp}
|
||||
/>
|
||||
</Stack>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
+6
-15
@@ -18,7 +18,6 @@ import {
|
||||
SettingsHeaderTitle,
|
||||
} from "#/components/SettingsHeader/SettingsHeader";
|
||||
import { Spinner } from "#/components/Spinner/Spinner";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -81,11 +80,7 @@ export const EditOAuth2AppPageView: FC<EditOAuth2AppProps> = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<Stack
|
||||
alignItems="baseline"
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<div className="flex flex-row gap-4 items-baseline justify-between">
|
||||
<SettingsHeader>
|
||||
<SettingsHeaderTitle>Edit OAuth2 application</SettingsHeaderTitle>
|
||||
<SettingsHeaderDescription>
|
||||
@@ -99,7 +94,7 @@ export const EditOAuth2AppPageView: FC<EditOAuth2AppProps> = ({
|
||||
All OAuth2 Applications
|
||||
</RouterLink>
|
||||
</Button>
|
||||
</Stack>
|
||||
</div>
|
||||
|
||||
{fullNewSecret && (
|
||||
<ConfirmDialog
|
||||
@@ -124,7 +119,7 @@ export const EditOAuth2AppPageView: FC<EditOAuth2AppProps> = ({
|
||||
/>
|
||||
)}
|
||||
|
||||
<Stack>
|
||||
<div className="flex flex-col gap-4">
|
||||
{searchParams.has("created") && (
|
||||
<Alert severity="info" dismissible>
|
||||
Your OAuth2 application has been created. Generate a client secret
|
||||
@@ -204,7 +199,7 @@ export const EditOAuth2AppPageView: FC<EditOAuth2AppProps> = ({
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</Stack>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -226,11 +221,7 @@ const OAuth2AppSecretsTable: FC<OAuth2AppSecretsTableProps> = ({
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<Stack
|
||||
alignItems="baseline"
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<div className="flex flex-row gap-4 items-baseline justify-between">
|
||||
<h2>Client secrets</h2>
|
||||
<Button
|
||||
disabled={mutatingResource.createSecret}
|
||||
@@ -240,7 +231,7 @@ const OAuth2AppSecretsTable: FC<OAuth2AppSecretsTableProps> = ({
|
||||
<Spinner loading={mutatingResource.createSecret} />
|
||||
Generate secret
|
||||
</Button>
|
||||
</Stack>
|
||||
</div>
|
||||
|
||||
<Table>
|
||||
<TableHeader>
|
||||
|
||||
+2
-7
@@ -12,7 +12,6 @@ import {
|
||||
SettingsHeaderDescription,
|
||||
SettingsHeaderTitle,
|
||||
} from "#/components/SettingsHeader/SettingsHeader";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -39,11 +38,7 @@ const OAuth2AppsSettingsPageView: FC<OAuth2AppsSettingsProps> = ({
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<Stack
|
||||
alignItems="baseline"
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<div className="flex flex-row gap-4 items-baseline justify-between">
|
||||
<div>
|
||||
<SettingsHeader>
|
||||
<SettingsHeaderTitle>OAuth2 Applications</SettingsHeaderTitle>
|
||||
@@ -61,7 +56,7 @@ const OAuth2AppsSettingsPageView: FC<OAuth2AppsSettingsProps> = ({
|
||||
</Link>
|
||||
</Button>
|
||||
)}
|
||||
</Stack>
|
||||
</div>
|
||||
|
||||
{error && <ErrorAlert error={error} />}
|
||||
|
||||
|
||||
+2
-3
@@ -12,7 +12,6 @@ import {
|
||||
SettingsHeaderDocsLink,
|
||||
SettingsHeaderTitle,
|
||||
} from "#/components/SettingsHeader/SettingsHeader";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
@@ -32,7 +31,7 @@ export const ObservabilitySettingsPageView: FC<
|
||||
ObservabilitySettingsPageViewProps
|
||||
> = ({ options, featureAuditLogEnabled, isPremium }) => {
|
||||
return (
|
||||
<Stack direction="column" spacing={6}>
|
||||
<div className="flex flex-col gap-12">
|
||||
<div>
|
||||
<SettingsHeader>
|
||||
<SettingsHeaderTitle>Observability</SettingsHeaderTitle>
|
||||
@@ -94,6 +93,6 @@ export const ObservabilitySettingsPageView: FC<
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -12,7 +12,6 @@ import {
|
||||
SettingsHeaderDocsLink,
|
||||
SettingsHeaderTitle,
|
||||
} from "#/components/SettingsHeader/SettingsHeader";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { useDeploymentOptions } from "#/utils/deployOptions";
|
||||
import { docs } from "#/utils/docs";
|
||||
import OptionsTable from "../OptionsTable";
|
||||
@@ -42,7 +41,7 @@ export const OverviewPageView: FC<OverviewPageViewProps> = ({
|
||||
</SettingsHeaderDescription>
|
||||
</SettingsHeader>
|
||||
|
||||
<Stack spacing={4}>
|
||||
<div className="flex flex-col gap-8">
|
||||
<UserEngagementChart
|
||||
data={dailyActiveUsers?.entries.map((i) => ({
|
||||
date: i.date,
|
||||
@@ -80,7 +79,7 @@ export const OverviewPageView: FC<OverviewPageViewProps> = ({
|
||||
)}
|
||||
additionalValues={safeExperiments}
|
||||
/>
|
||||
</Stack>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
+2
-3
@@ -12,7 +12,6 @@ import {
|
||||
SettingsHeaderDocsLink,
|
||||
SettingsHeaderTitle,
|
||||
} from "#/components/SettingsHeader/SettingsHeader";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import {
|
||||
deploymentGroupHasParent,
|
||||
useDeploymentOptions,
|
||||
@@ -34,7 +33,7 @@ export const SecuritySettingsPageView: FC<SecuritySettingsPageViewProps> = ({
|
||||
);
|
||||
|
||||
return (
|
||||
<Stack direction="column" spacing={6}>
|
||||
<div className="flex flex-col gap-12">
|
||||
<div>
|
||||
<SettingsHeader>
|
||||
<SettingsHeaderTitle>Security</SettingsHeaderTitle>
|
||||
@@ -90,6 +89,6 @@ export const SecuritySettingsPageView: FC<SecuritySettingsPageViewProps> = ({
|
||||
<OptionsTable options={tlsOptions} />
|
||||
</div>
|
||||
)}
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
+2
-3
@@ -11,7 +11,6 @@ import {
|
||||
SettingsHeaderDocsLink,
|
||||
SettingsHeaderTitle,
|
||||
} from "#/components/SettingsHeader/SettingsHeader";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import {
|
||||
deploymentGroupHasParent,
|
||||
useDeploymentOptions,
|
||||
@@ -34,7 +33,7 @@ export const UserAuthSettingsPageView = ({
|
||||
);
|
||||
|
||||
return (
|
||||
<Stack direction="column" spacing={6}>
|
||||
<div className="flex flex-col gap-12">
|
||||
<div>
|
||||
<SettingsHeader>
|
||||
<SettingsHeaderTitle>User Authentication</SettingsHeaderTitle>
|
||||
@@ -90,6 +89,6 @@ export const UserAuthSettingsPageView = ({
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -26,7 +26,6 @@ import {
|
||||
SettingsHeaderTitle,
|
||||
} from "#/components/SettingsHeader/SettingsHeader";
|
||||
import { Spinner } from "#/components/Spinner/Spinner";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -80,11 +79,7 @@ const CreateEditRolePageView: FC<CreateEditRolePageViewProps> = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<Stack
|
||||
alignItems="baseline"
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<div className="flex flex-row gap-4 items-baseline justify-between">
|
||||
<SettingsHeader>
|
||||
<SettingsHeaderTitle>
|
||||
{role ? "Edit" : "Create"} Custom Role
|
||||
@@ -112,7 +107,7 @@ const CreateEditRolePageView: FC<CreateEditRolePageViewProps> = ({
|
||||
{role !== undefined ? "Save" : "Create Role"}
|
||||
</Button>
|
||||
</div>
|
||||
</Stack>
|
||||
</div>
|
||||
|
||||
<VerticalForm onSubmit={form.handleSubmit}>
|
||||
<FormFields>
|
||||
|
||||
@@ -12,7 +12,6 @@ import {
|
||||
SettingsHeaderDescription,
|
||||
SettingsHeaderTitle,
|
||||
} from "#/components/SettingsHeader/SettingsHeader";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { useFeatureVisibility } from "#/modules/dashboard/useFeatureVisibility";
|
||||
import { useOrganizationSettings } from "#/modules/management/OrganizationSettingsLayout";
|
||||
import { RequirePermission } from "#/modules/permissions/RequirePermission";
|
||||
@@ -71,18 +70,14 @@ const CustomRolesPage: FC = () => {
|
||||
<RequirePermission
|
||||
isFeatureVisible={organizationPermissions?.viewOrgRoles ?? false}
|
||||
>
|
||||
<Stack
|
||||
alignItems="baseline"
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<div className="flex flex-row gap-4 items-baseline justify-between">
|
||||
<SettingsHeader>
|
||||
<SettingsHeaderTitle>Roles</SettingsHeaderTitle>
|
||||
<SettingsHeaderDescription>
|
||||
Manage roles for this organization.
|
||||
</SettingsHeaderDescription>
|
||||
</SettingsHeader>
|
||||
</Stack>
|
||||
</div>
|
||||
|
||||
<CustomRolesPageView
|
||||
builtInRoles={builtInRoles}
|
||||
|
||||
@@ -13,7 +13,6 @@ import {
|
||||
import { EmptyState } from "#/components/EmptyState/EmptyState";
|
||||
import { PaywallPremium } from "#/components/Paywall/PaywallPremium";
|
||||
import { Skeleton } from "#/components/Skeleton/Skeleton";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -49,7 +48,7 @@ export const CustomRolesPageView: FC<CustomRolesPageViewProps> = ({
|
||||
isCustomRolesEnabled,
|
||||
}) => {
|
||||
return (
|
||||
<Stack spacing={4}>
|
||||
<div className="flex flex-col gap-8">
|
||||
{!isCustomRolesEnabled && (
|
||||
<PaywallPremium
|
||||
message="Custom Roles"
|
||||
@@ -57,11 +56,7 @@ export const CustomRolesPageView: FC<CustomRolesPageViewProps> = ({
|
||||
documentationLink={docs("/admin/users/groups-roles")}
|
||||
/>
|
||||
)}
|
||||
<Stack
|
||||
alignItems="baseline"
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<div className="flex flex-row gap-4 items-baseline justify-between">
|
||||
<span>
|
||||
<h2 className="mb-0 text-lg">Custom Roles</h2>
|
||||
<span className="text-sm text-content-secondary leading-relaxed">
|
||||
@@ -77,7 +72,7 @@ export const CustomRolesPageView: FC<CustomRolesPageViewProps> = ({
|
||||
</RouterLink>
|
||||
</Button>
|
||||
)}
|
||||
</Stack>
|
||||
</div>
|
||||
<RoleTable
|
||||
roles={customRoles}
|
||||
isCustomRolesEnabled={isCustomRolesEnabled}
|
||||
@@ -101,7 +96,7 @@ export const CustomRolesPageView: FC<CustomRolesPageViewProps> = ({
|
||||
canDeleteOrgRole={canDeleteOrgRole}
|
||||
onDeleteRole={onDeleteRole}
|
||||
/>
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ import type {
|
||||
import { ConfirmDialog } from "#/components/Dialogs/ConfirmDialog/ConfirmDialog";
|
||||
import { EmptyState } from "#/components/EmptyState/EmptyState";
|
||||
import { useFilter } from "#/components/Filter/Filter";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { useAuthenticated } from "#/hooks/useAuthenticated";
|
||||
import { usePaginatedQuery } from "#/hooks/usePaginatedQuery";
|
||||
import { shouldShowAISeatColumn } from "#/modules/dashboard/entitlements";
|
||||
@@ -163,7 +162,7 @@ const OrganizationMembersPage: FC = () => {
|
||||
}
|
||||
}}
|
||||
description={
|
||||
<Stack>
|
||||
<div className="flex flex-col gap-4">
|
||||
<p>
|
||||
Removing this member will:
|
||||
<ul>
|
||||
@@ -177,7 +176,7 @@ const OrganizationMembersPage: FC = () => {
|
||||
</p>
|
||||
|
||||
<p className="pb-5">Are you sure you want to remove this member?</p>
|
||||
</Stack>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
</>
|
||||
|
||||
@@ -38,7 +38,6 @@ import {
|
||||
SettingsHeaderTitle,
|
||||
} from "#/components/SettingsHeader/SettingsHeader";
|
||||
import { Spinner } from "#/components/Spinner/Spinner";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -122,23 +121,23 @@ export const OrganizationMembersPageView: FC<
|
||||
<TableRow>
|
||||
<TableHead className="w-2/6">User</TableHead>
|
||||
<TableHead className="w-2/6">
|
||||
<Stack direction="row" spacing={1} alignItems="center">
|
||||
<div className="flex flex-row items-center gap-2">
|
||||
<span>Roles</span>
|
||||
<TableColumnHelpPopover variant="roles" />
|
||||
</Stack>
|
||||
</div>
|
||||
</TableHead>
|
||||
<TableHead className={showAISeatColumn ? "w-1/6" : "w-2/6"}>
|
||||
<Stack direction="row" spacing={1} alignItems="center">
|
||||
<div className="flex flex-row items-center gap-2">
|
||||
<span>Groups</span>
|
||||
<TableColumnHelpPopover variant="groups" />
|
||||
</Stack>
|
||||
</div>
|
||||
</TableHead>
|
||||
{showAISeatColumn && (
|
||||
<TableHead className="w-1/6">
|
||||
<Stack direction="row" spacing={1} alignItems="center">
|
||||
<div className="flex flex-row items-center gap-2">
|
||||
<span>AI add-on</span>
|
||||
<TableColumnHelpPopover variant="ai_addon" />
|
||||
</Stack>
|
||||
</div>
|
||||
</TableHead>
|
||||
)}
|
||||
<TableHead className="w-px whitespace-nowrap text-right" />
|
||||
|
||||
@@ -14,7 +14,6 @@ import {
|
||||
PageHeaderSubtitle,
|
||||
PageHeaderTitle,
|
||||
} from "#/components/PageHeader/PageHeader";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
|
||||
interface StarterTemplatePageViewProps {
|
||||
starterTemplate?: TemplateExample;
|
||||
@@ -59,7 +58,7 @@ export const StarterTemplatePageView: FC<StarterTemplatePageViewProps> = ({
|
||||
</>
|
||||
}
|
||||
>
|
||||
<Stack direction="row" spacing={3} alignItems="center">
|
||||
<div className="flex flex-row gap-6 items-center">
|
||||
<div className="h-12 w-12 flex items-center justify-center [&_img]:w-full">
|
||||
<ExternalImage src={starterTemplate.icon} />
|
||||
</div>
|
||||
@@ -69,7 +68,7 @@ export const StarterTemplatePageView: FC<StarterTemplatePageViewProps> = ({
|
||||
{starterTemplate.description}
|
||||
</PageHeaderSubtitle>
|
||||
</div>
|
||||
</Stack>
|
||||
</div>
|
||||
</PageHeader>
|
||||
|
||||
<div
|
||||
|
||||
@@ -47,7 +47,6 @@ import {
|
||||
} from "#/components/HelpPopover/HelpPopover";
|
||||
import { Link } from "#/components/Link/Link";
|
||||
import { Loader } from "#/components/Loader/Loader";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipArrow,
|
||||
@@ -480,10 +479,7 @@ const TemplateUsagePanel: FC<TemplateUsagePanelProps> = ({
|
||||
<TooltipArrow className="fill-border" />
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Stack
|
||||
spacing={0}
|
||||
className="text-[13px] shrink-0 leading-[1.5] text-content-secondary w-[120px]"
|
||||
>
|
||||
<div className="flex flex-col text-[13px] shrink-0 leading-[1.5] text-content-secondary w-[120px]">
|
||||
{formatTime(usage.seconds)}
|
||||
{usage.times_used > 0 && (
|
||||
<span className="text-[12px] text-content-disabled">
|
||||
@@ -491,7 +487,7 @@ const TemplateUsagePanel: FC<TemplateUsagePanelProps> = ({
|
||||
{usage.times_used === 1 ? "time" : "times"}
|
||||
</span>
|
||||
)}
|
||||
</Stack>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -38,7 +38,6 @@ import {
|
||||
PageHeaderTitle,
|
||||
} from "#/components/PageHeader/PageHeader";
|
||||
import { Pill } from "#/components/Pill/Pill";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { linkToTemplate, useLinks } from "#/modules/navigation";
|
||||
import type { WorkspacePermissions } from "#/modules/permissions/workspaces";
|
||||
import { TemplateStats } from "./TemplateStats";
|
||||
@@ -250,23 +249,22 @@ export const TemplatePageHeader: FC<TemplatePageHeaderProps> = ({
|
||||
</>
|
||||
}
|
||||
>
|
||||
<Stack direction="row">
|
||||
<div className="flex flex-row gap-4">
|
||||
<Avatar
|
||||
size="lg"
|
||||
variant="icon"
|
||||
src={template.icon}
|
||||
fallback={template.name}
|
||||
/>
|
||||
|
||||
<div>
|
||||
<Stack direction="row" alignItems="center" spacing={1}>
|
||||
<div className="flex flex-row items-center gap-2">
|
||||
<PageHeaderTitle>
|
||||
{template.display_name.length > 0
|
||||
? template.display_name
|
||||
: template.name}
|
||||
</PageHeaderTitle>
|
||||
{template.deprecated && <Pill type="warning">Deprecated</Pill>}
|
||||
</Stack>
|
||||
</div>
|
||||
|
||||
{template.deprecation_message !== "" ? (
|
||||
<PageHeaderSubtitle condensed>
|
||||
@@ -282,7 +280,7 @@ export const TemplatePageHeader: FC<TemplatePageHeaderProps> = ({
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</Stack>
|
||||
</div>
|
||||
</PageHeader>
|
||||
<div className="pb-8">
|
||||
<TemplateStats template={template} activeVersion={activeVersion} />
|
||||
|
||||
@@ -6,7 +6,6 @@ import { Avatar } from "#/components/Avatar/Avatar";
|
||||
import { Button } from "#/components/Button/Button";
|
||||
import { InfoTooltip } from "#/components/InfoTooltip/InfoTooltip";
|
||||
import { Pill } from "#/components/Pill/Pill";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { TableCell } from "#/components/Table/Table";
|
||||
import { TimelineEntry } from "#/components/Timeline/TimelineEntry";
|
||||
import { useClickableTableRow } from "#/hooks/useClickableTableRow";
|
||||
@@ -41,39 +40,32 @@ export const VersionRow: FC<VersionRowProps> = ({
|
||||
className={clickableProps.className}
|
||||
>
|
||||
<TableCell css={styles.versionCell}>
|
||||
<Stack
|
||||
direction="row"
|
||||
alignItems="center"
|
||||
<div
|
||||
className="flex flex-row items-center justify-between gap-4"
|
||||
css={styles.versionWrapper}
|
||||
justifyContent="space-between"
|
||||
>
|
||||
<Stack direction="row" alignItems="center">
|
||||
<div className="flex flex-row items-center gap-4">
|
||||
<Avatar
|
||||
fallback={version.created_by.username}
|
||||
src={version.created_by.avatar_url}
|
||||
/>
|
||||
<Stack
|
||||
<div
|
||||
className="flex flex-row items-center gap-2"
|
||||
css={styles.versionSummary}
|
||||
direction="row"
|
||||
alignItems="center"
|
||||
spacing={1}
|
||||
>
|
||||
<span>
|
||||
<strong>{version.created_by.username}</strong> created the
|
||||
version <strong>{version.name}</strong>
|
||||
</span>
|
||||
|
||||
{version.message && (
|
||||
<InfoTooltip title="Message" message={version.message} />
|
||||
)}
|
||||
|
||||
<span css={styles.versionTime}>
|
||||
{new Date(version.created_at).toLocaleTimeString()}
|
||||
</span>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
<Stack direction="row" alignItems="center" spacing={2}>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-row items-center gap-4">
|
||||
{isActive && (
|
||||
<Pill role="status" type="success">
|
||||
Active
|
||||
@@ -132,8 +124,8 @@ export const VersionRow: FC<VersionRowProps> = ({
|
||||
Promote…
|
||||
</Button>
|
||||
)}
|
||||
</Stack>
|
||||
</Stack>
|
||||
</div>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TimelineEntry>
|
||||
);
|
||||
|
||||
+7
-13
@@ -23,7 +23,6 @@ import {
|
||||
import { IconField } from "#/components/IconField/IconField";
|
||||
import { Link } from "#/components/Link/Link";
|
||||
import { Spinner } from "#/components/Spinner/Spinner";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import {
|
||||
StackLabel,
|
||||
StackLabelHelperText,
|
||||
@@ -164,7 +163,7 @@ export const TemplateSettingsForm: FC<TemplateSettingsForm> = ({
|
||||
title="Operations"
|
||||
description="Regulate actions allowed on workspaces created from this template."
|
||||
>
|
||||
<FormFields spacing={6}>
|
||||
<FormFields className="gap-12">
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Checkbox
|
||||
@@ -217,15 +216,10 @@ export const TemplateSettingsForm: FC<TemplateSettingsForm> = ({
|
||||
</span>
|
||||
|
||||
{!advancedSchedulingEnabled && (
|
||||
<Stack
|
||||
direction="row"
|
||||
spacing={2}
|
||||
alignItems="center"
|
||||
className="mt-4"
|
||||
>
|
||||
<div className="flex flex-row gap-4 items-center mt-4">
|
||||
<PremiumBadge />
|
||||
<span>Premium license required to be enabled.</span>
|
||||
</Stack>
|
||||
</div>
|
||||
)}
|
||||
</StackLabelHelperText>
|
||||
</StackLabel>
|
||||
@@ -317,14 +311,14 @@ export const TemplateSettingsForm: FC<TemplateSettingsForm> = ({
|
||||
label="Deprecation Message"
|
||||
/>
|
||||
{!accessControlEnabled && (
|
||||
<Stack direction="row" spacing={2} alignItems="center">
|
||||
<div className="flex flex-row gap-4 items-center">
|
||||
<PremiumBadge />
|
||||
<FormHelperText>
|
||||
Premium license required to deprecate templates.
|
||||
{template.deprecated &&
|
||||
" You cannot change the message, but you may remove it to mark this template as no longer deprecated."}
|
||||
</FormHelperText>
|
||||
</Stack>
|
||||
</div>
|
||||
)}
|
||||
</FormFields>
|
||||
</FormSection>
|
||||
@@ -358,12 +352,12 @@ export const TemplateSettingsForm: FC<TemplateSettingsForm> = ({
|
||||
<MenuItem value="public">Public</MenuItem>
|
||||
</TextField>
|
||||
{!portSharingControlsEnabled && (
|
||||
<Stack direction="row" spacing={2} alignItems="center">
|
||||
<div className="flex flex-row gap-4 items-center">
|
||||
<PremiumBadge />
|
||||
<FormHelperText>
|
||||
Premium license required to control max port sharing level.
|
||||
</FormHelperText>
|
||||
</Stack>
|
||||
</div>
|
||||
)}
|
||||
</FormFields>
|
||||
</FormSection>
|
||||
|
||||
+4
-11
@@ -1,7 +1,6 @@
|
||||
import FormHelperText from "@mui/material/FormHelperText";
|
||||
import type { FC } from "react";
|
||||
import { Button } from "#/components/Button/Button";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import {
|
||||
sortedDays,
|
||||
type TemplateAutostartRequirementDaysValue,
|
||||
@@ -21,14 +20,8 @@ export const TemplateScheduleAutostart: FC<TemplateScheduleAutostartProps> = ({
|
||||
onChange,
|
||||
}) => {
|
||||
return (
|
||||
<Stack alignItems="start" spacing={1}>
|
||||
<Stack
|
||||
direction="row"
|
||||
spacing={0}
|
||||
alignItems="baseline"
|
||||
justifyContent="center"
|
||||
className="w-full gap-0.5"
|
||||
>
|
||||
<div className="flex flex-col gap-2 items-start">
|
||||
<div className="flex flex-row items-baseline justify-center w-full gap-0.5">
|
||||
{(
|
||||
[
|
||||
{ value: "monday", key: "Mon" },
|
||||
@@ -60,11 +53,11 @@ export const TemplateScheduleAutostart: FC<TemplateScheduleAutostartProps> = ({
|
||||
{day.key}
|
||||
</Button>
|
||||
))}
|
||||
</Stack>
|
||||
</div>
|
||||
<FormHelperText>
|
||||
<AutostartHelperText allowed={enabled} days={value} />
|
||||
</FormHelperText>
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ const DORMANT_AUTODELETION_DEFAULT = 30 * MS_DAY_CONVERSION;
|
||||
* The default form field space is 4 but since this form is quite heavy I think
|
||||
* increase the space can make it feels lighter.
|
||||
*/
|
||||
const FORM_FIELDS_SPACING = 8;
|
||||
const FORM_FIELDS_GAP = "gap-16";
|
||||
|
||||
export interface TemplateScheduleForm {
|
||||
template: Template;
|
||||
@@ -287,7 +287,7 @@ export const TemplateScheduleForm: FC<TemplateScheduleForm> = ({
|
||||
title="Autostop"
|
||||
description="Define when workspaces created from this template are stopped."
|
||||
>
|
||||
<FormFields spacing={FORM_FIELDS_SPACING}>
|
||||
<FormFields className={FORM_FIELDS_GAP}>
|
||||
<TextField
|
||||
{...getFieldHelpers("default_ttl_ms", {
|
||||
helperText: (
|
||||
@@ -443,7 +443,7 @@ export const TemplateScheduleForm: FC<TemplateScheduleForm> = ({
|
||||
title="Dormancy"
|
||||
description="When enabled, Coder will mark workspaces as dormant after a period of time with no connections. Dormant workspaces can be auto-deleted (see below) or manually reviewed by the workspace owner or admins."
|
||||
>
|
||||
<FormFields spacing={FORM_FIELDS_SPACING}>
|
||||
<FormFields className={FORM_FIELDS_GAP}>
|
||||
<div className="flex flex-col gap-8">
|
||||
<div className="flex items-start">
|
||||
<Switch
|
||||
|
||||
@@ -7,7 +7,6 @@ import type { AuthorizationResponse, Template } from "#/api/typesGenerated";
|
||||
import { ErrorAlert } from "#/components/Alert/ErrorAlert";
|
||||
import { Loader } from "#/components/Loader/Loader";
|
||||
import { Margins } from "#/components/Margins/Margins";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { pageTitle } from "#/utils/page";
|
||||
import { Sidebar } from "./Sidebar";
|
||||
|
||||
@@ -54,7 +53,7 @@ export const TemplateSettingsLayout: FC = () => {
|
||||
<title>{pageTitle(templateName, "Settings")}</title>
|
||||
|
||||
<Margins>
|
||||
<Stack className="py-12" direction="row" spacing={10}>
|
||||
<div className="flex flex-row gap-20 py-12">
|
||||
{templateQuery.isError || permissionsQuery.isError ? (
|
||||
<ErrorAlert error={templateQuery.error} />
|
||||
) : (
|
||||
@@ -72,7 +71,7 @@ export const TemplateSettingsLayout: FC = () => {
|
||||
</Suspense>
|
||||
</TemplateSettings.Provider>
|
||||
)}
|
||||
</Stack>
|
||||
</div>
|
||||
</Margins>
|
||||
</>
|
||||
);
|
||||
|
||||
+2
-3
@@ -10,7 +10,6 @@ import {
|
||||
PageHeader,
|
||||
PageHeaderTitle,
|
||||
} from "#/components/PageHeader/PageHeader";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { TemplateVariablesForm } from "./TemplateVariablesForm";
|
||||
|
||||
interface TemplateVariablesPageViewProps {
|
||||
@@ -51,14 +50,14 @@ export const TemplateVariablesPageView: FC<TemplateVariablesPageViewProps> = ({
|
||||
<PageHeaderTitle>Template variables</PageHeaderTitle>
|
||||
</PageHeader>
|
||||
{hasError && (
|
||||
<Stack className="mb-16">
|
||||
<div className="flex flex-col gap-4 mb-16">
|
||||
{Boolean(errors.buildError) && (
|
||||
<ErrorAlert error={errors.buildError} />
|
||||
)}
|
||||
{Boolean(errors.publishError) && (
|
||||
<ErrorAlert error={errors.publishError} />
|
||||
)}
|
||||
</Stack>
|
||||
</div>
|
||||
)}
|
||||
{templateVersion && templateVariables && templateVariables.length > 0 && (
|
||||
<TemplateVariablesForm
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import TextField from "@mui/material/TextField";
|
||||
import { type ChangeEvent, type FC, useState } from "react";
|
||||
import { ConfirmDialog } from "#/components/Dialogs/ConfirmDialog/ConfirmDialog";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { type FileTree, isFolder, validatePath } from "#/utils/filetree";
|
||||
|
||||
interface CreateFileDialogProps {
|
||||
@@ -59,7 +58,7 @@ export const CreateFileDialog: FC<CreateFileDialogProps> = ({
|
||||
confirmText="Create"
|
||||
title="Create File"
|
||||
description={
|
||||
<Stack spacing={4}>
|
||||
<div className="flex flex-col gap-8">
|
||||
<p>
|
||||
Specify the path to a file to be created. This path can contain
|
||||
slashes too.
|
||||
@@ -81,7 +80,7 @@ export const CreateFileDialog: FC<CreateFileDialogProps> = ({
|
||||
onChange={handleChange}
|
||||
label="File Path"
|
||||
/>
|
||||
</Stack>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
);
|
||||
@@ -180,7 +179,7 @@ export const RenameFileDialog: FC<RenameFileDialogProps> = ({
|
||||
confirmText="Rename"
|
||||
title="Rename File"
|
||||
description={
|
||||
<Stack>
|
||||
<div className="flex flex-col gap-4">
|
||||
<p>
|
||||
Rename <strong>{filename}</strong> to something else. This path can
|
||||
contain slashes too!
|
||||
@@ -202,7 +201,7 @@ export const RenameFileDialog: FC<RenameFileDialogProps> = ({
|
||||
onChange={handleChange}
|
||||
label="File Path"
|
||||
/>
|
||||
</Stack>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -17,7 +17,6 @@ import {
|
||||
HelpPopoverText,
|
||||
HelpPopoverTitle,
|
||||
} from "#/components/HelpPopover/HelpPopover";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import type { PublishVersionData } from "#/pages/TemplateVersionEditorPage/types";
|
||||
import { docs } from "#/utils/docs";
|
||||
import { getFormHelpers } from "#/utils/formUtils";
|
||||
@@ -74,7 +73,7 @@ export const PublishTemplateVersionDialog: FC<
|
||||
title="Publish new version"
|
||||
description={
|
||||
<form id="publish-version" onSubmit={form.handleSubmit}>
|
||||
<Stack>
|
||||
<div className="flex flex-col gap-4">
|
||||
<p>You are about to publish a new version of this template.</p>
|
||||
<FormFields>
|
||||
<TextField
|
||||
@@ -93,7 +92,7 @@ export const PublishTemplateVersionDialog: FC<
|
||||
rows={5}
|
||||
/>
|
||||
|
||||
<Stack direction="row">
|
||||
<div className="flex flex-row gap-4">
|
||||
<FormControlLabel
|
||||
label="Promote to active version"
|
||||
control={
|
||||
@@ -135,9 +134,9 @@ export const PublishTemplateVersionDialog: FC<
|
||||
</HelpPopoverLinksGroup>
|
||||
</HelpPopoverContent>
|
||||
</HelpPopover>
|
||||
</Stack>
|
||||
</div>
|
||||
</FormFields>
|
||||
</Stack>
|
||||
</div>
|
||||
</form>
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
PageHeaderCaption,
|
||||
PageHeaderTitle,
|
||||
} from "#/components/PageHeader/PageHeader";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { Stats, StatsItem } from "#/components/Stats/Stats";
|
||||
import { linkToTemplate, useLinks } from "#/modules/navigation";
|
||||
import { TemplateFiles } from "#/modules/templates/TemplateFiles/TemplateFiles";
|
||||
@@ -71,7 +70,7 @@ export const TemplateVersionPageView: FC<TemplateVersionPageViewProps> = ({
|
||||
|
||||
{!currentFiles && !error && <Loader />}
|
||||
|
||||
<Stack spacing={4}>
|
||||
<div className="flex flex-col gap-8">
|
||||
{Boolean(error) && <ErrorAlert error={error} />}
|
||||
{currentVersion?.message && (
|
||||
<TemplateUpdateMessage>
|
||||
@@ -117,7 +116,7 @@ export const TemplateVersionPageView: FC<TemplateVersionPageViewProps> = ({
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Stack>
|
||||
</div>
|
||||
</Margins>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -4,7 +4,6 @@ import { Link as RouterLink } from "react-router";
|
||||
import type { TemplateExample } from "#/api/typesGenerated";
|
||||
import { Button } from "#/components/Button/Button";
|
||||
import { CodeExample } from "#/components/CodeExample/CodeExample";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { TableEmpty } from "#/components/TableEmpty/TableEmpty";
|
||||
import { TemplateExampleCard } from "#/modules/templates/TemplateExampleCard/TemplateExampleCard";
|
||||
import { docs } from "#/utils/docs";
|
||||
@@ -71,19 +70,18 @@ export const EmptyTemplates: FC<EmptyTemplatesProps> = ({
|
||||
</>
|
||||
}
|
||||
cta={
|
||||
<Stack alignItems="center" spacing={4}>
|
||||
<div className="flex flex-col gap-8 items-center">
|
||||
<div className="flex flex-wrap justify-center gap-4">
|
||||
{featuredExamples.map((example) => (
|
||||
<TemplateExampleCard example={example} key={example.id} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
<Button size="sm" asChild className="rounded-full">
|
||||
<RouterLink to="/starter-templates">
|
||||
View all starter templates
|
||||
</RouterLink>
|
||||
</Button>
|
||||
</Stack>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -26,7 +26,6 @@ import {
|
||||
PageHeaderTitle,
|
||||
} from "#/components/PageHeader/PageHeader";
|
||||
import { Skeleton } from "#/components/Skeleton/Skeleton";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -228,10 +227,10 @@ export const TemplatesPageView: FC<TemplatesPageViewProps> = ({
|
||||
}
|
||||
>
|
||||
<PageHeaderTitle>
|
||||
<Stack spacing={1} direction="row" alignItems="center">
|
||||
<div className="flex flex-row gap-2 items-center">
|
||||
Templates
|
||||
<TemplateHelpPopover />
|
||||
</Stack>
|
||||
</div>
|
||||
</PageHeaderTitle>
|
||||
<PageHeaderSubtitle>
|
||||
Select a template to create a workspace.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import type { FC } from "react";
|
||||
import { useQuery } from "react-query";
|
||||
import { groupsForUser } from "#/api/queries/groups";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { useAuthContext } from "#/contexts/auth/AuthProvider";
|
||||
import { useAuthenticated } from "#/hooks/useAuthenticated";
|
||||
import { useDashboard } from "#/modules/dashboard/useDashboard";
|
||||
@@ -22,7 +21,7 @@ const AccountPage: FC = () => {
|
||||
});
|
||||
|
||||
return (
|
||||
<Stack spacing={6}>
|
||||
<div className="flex flex-col gap-12">
|
||||
<Section title="Account" description="Update your account info">
|
||||
<AccountForm
|
||||
editable={permissions?.updateUsers ?? false}
|
||||
@@ -41,7 +40,7 @@ const AccountPage: FC = () => {
|
||||
error={groupsQuery.error}
|
||||
/>
|
||||
)}
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ import {
|
||||
} from "#/components/DropdownMenu/DropdownMenu";
|
||||
import { Loader } from "#/components/Loader/Loader";
|
||||
import { Spinner } from "#/components/Spinner/Spinner";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -130,7 +129,7 @@ const ExternalAuthRow: FC<ExternalAuthRowProps> = ({
|
||||
return (
|
||||
<TableRow key={app.id}>
|
||||
<TableCell>
|
||||
<Stack direction="row" alignItems="center" spacing={1}>
|
||||
<div className="flex flex-row items-center gap-2">
|
||||
<Avatar variant="icon" src={app.display_icon} fallback={name} />
|
||||
<span className="font-semibold">{name}</span>
|
||||
{/*
|
||||
@@ -147,14 +146,13 @@ const ExternalAuthRow: FC<ExternalAuthRowProps> = ({
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
{link?.validate_error && (
|
||||
<span>
|
||||
<span className="pl-[1em] text-content-destructive">Error: </span>
|
||||
{link?.validate_error}
|
||||
</span>
|
||||
)}
|
||||
</Stack>
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell className="text-right">
|
||||
<Button
|
||||
|
||||
@@ -3,7 +3,6 @@ import type * as TypesGen from "#/api/typesGenerated";
|
||||
import { ErrorAlert } from "#/components/Alert/ErrorAlert";
|
||||
import { Avatar } from "#/components/Avatar/Avatar";
|
||||
import { Button } from "#/components/Button/Button";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -67,10 +66,10 @@ const OAuth2AppRow: FC<OAuth2AppRowProps> = ({ app, revoke }) => {
|
||||
return (
|
||||
<TableRow key={app.id} data-testid={`app-${app.id}`}>
|
||||
<TableCell>
|
||||
<Stack direction="row" spacing={1} alignItems="center">
|
||||
<div className="flex flex-row gap-2 items-center">
|
||||
<Avatar variant="icon" src={app.icon} fallback={app.name} />
|
||||
<span className="font-semibold">{app.name}</span>
|
||||
</Stack>
|
||||
</div>
|
||||
</TableCell>
|
||||
|
||||
<TableCell>
|
||||
|
||||
@@ -4,7 +4,6 @@ import type { GitSSHKey } from "#/api/typesGenerated";
|
||||
import { ErrorAlert } from "#/components/Alert/ErrorAlert";
|
||||
import { Button } from "#/components/Button/Button";
|
||||
import { CodeExample } from "#/components/CodeExample/CodeExample";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
|
||||
interface SSHKeysPageViewProps {
|
||||
isLoading: boolean;
|
||||
@@ -28,7 +27,7 @@ export const SSHKeysPageView: FC<SSHKeysPageViewProps> = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
<div className="flex flex-col gap-4">
|
||||
{/* Regenerating the key is not an option if getSSHKey fails.
|
||||
Only one of the error messages will exist at a single time */}
|
||||
{Boolean(getSSHKeyError) && <ErrorAlert error={getSSHKeyError} />}
|
||||
@@ -56,6 +55,6 @@ export const SSHKeysPageView: FC<SSHKeysPageViewProps> = ({
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -12,7 +12,6 @@ import { ErrorAlert } from "#/components/Alert/ErrorAlert";
|
||||
import { Button } from "#/components/Button/Button";
|
||||
import { Form, FormFields } from "#/components/Form/Form";
|
||||
import { Spinner } from "#/components/Spinner/Spinner";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { getFormHelpers } from "#/utils/formUtils";
|
||||
import { quietHoursDisplay, timeToCron, validTime } from "#/utils/schedule";
|
||||
import { getPreferredTimezone, timeZones } from "#/utils/timeZones";
|
||||
@@ -102,7 +101,7 @@ export const ScheduleForm: FC<ScheduleFormProps> = ({
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
<Stack direction="row">
|
||||
<div className="flex flex-row gap-4">
|
||||
<TextField
|
||||
{...getFieldHelpers("time")}
|
||||
disabled={isLoading || !initialValues.user_can_set}
|
||||
@@ -123,7 +122,7 @@ export const ScheduleForm: FC<ScheduleFormProps> = ({
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
</Stack>
|
||||
</div>
|
||||
|
||||
<TextField
|
||||
disabled
|
||||
|
||||
@@ -3,7 +3,6 @@ import {
|
||||
FeatureStageBadge,
|
||||
type featureStageBadgeTypes,
|
||||
} from "#/components/FeatureStageBadge/FeatureStageBadge";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
|
||||
type SectionLayout = "fixed" | "fluid";
|
||||
|
||||
@@ -41,7 +40,7 @@ export const Section: FC<SectionProps> = ({
|
||||
<div className="mb-6 flex flex-row justify-between">
|
||||
<div>
|
||||
{title && (
|
||||
<Stack direction="row" alignItems="center">
|
||||
<div className="flex flex-row items-center gap-4">
|
||||
<h4 className="text-2xl font-medium m-0 mb-2">{title}</h4>
|
||||
{featureStage && (
|
||||
<FeatureStageBadge
|
||||
@@ -50,7 +49,7 @@ export const Section: FC<SectionProps> = ({
|
||||
className="mb-[5px]"
|
||||
/>
|
||||
)}
|
||||
</Stack>
|
||||
</div>
|
||||
)}
|
||||
{description && typeof description === "string" && (
|
||||
<p className={DESCRIPTION_CLASS}>{description}</p>
|
||||
|
||||
@@ -4,7 +4,6 @@ import { toast } from "sonner";
|
||||
import { API } from "#/api/api";
|
||||
import { authMethods, updatePassword } from "#/api/queries/users";
|
||||
import { Loader } from "#/components/Loader/Loader";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { useAuthenticated } from "#/hooks/useAuthenticated";
|
||||
import { Section } from "../Section";
|
||||
import { SecurityForm } from "./SecurityForm";
|
||||
@@ -71,12 +70,12 @@ export const SecurityPageView: FC<SecurityPageViewProps> = ({
|
||||
oidc,
|
||||
}) => {
|
||||
return (
|
||||
<Stack spacing={6}>
|
||||
<div className="flex flex-col gap-12">
|
||||
<Section title="Security" description="Update your account password">
|
||||
<SecurityForm {...security.form} />
|
||||
</Section>
|
||||
{oidc && <SingleSignOnSection {...oidc.section} />}
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ import { Button } from "#/components/Button/Button";
|
||||
import { ConfirmDialog } from "#/components/Dialogs/ConfirmDialog/ConfirmDialog";
|
||||
import { EmptyState } from "#/components/EmptyState/EmptyState";
|
||||
import { ExternalImage } from "#/components/ExternalImage/ExternalImage";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { docs } from "#/utils/docs";
|
||||
import { Section } from "../Section";
|
||||
|
||||
@@ -258,7 +257,7 @@ const ConfirmLoginTypeChangeModal: FC<ConfirmLoginTypeChangeModalProps> = ({
|
||||
title="Change login type"
|
||||
confirmLoading={loading}
|
||||
description={
|
||||
<Stack spacing={4}>
|
||||
<div className="flex flex-col gap-8">
|
||||
<p>
|
||||
After changing your login type, you will not be able to change it
|
||||
again. Are you sure you want to proceed and change your login type?
|
||||
@@ -283,7 +282,7 @@ const ConfirmLoginTypeChangeModal: FC<ConfirmLoginTypeChangeModalProps> = ({
|
||||
label="Confirm your password"
|
||||
type="password"
|
||||
/>
|
||||
</Stack>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -3,7 +3,6 @@ import { type FC, useState } from "react";
|
||||
import { Link as RouterLink } from "react-router";
|
||||
import type { APIKeyWithOwner } from "#/api/typesGenerated";
|
||||
import { Button } from "#/components/Button/Button";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { cn } from "#/utils/cn";
|
||||
import { Section } from "../Section";
|
||||
import { ConfirmDeleteDialog } from "./ConfirmDeleteDialog";
|
||||
@@ -68,14 +67,14 @@ const TokensPage: FC = () => {
|
||||
};
|
||||
|
||||
const TokenActions: FC = () => (
|
||||
<Stack direction="row" justifyContent="end" className="mb-2">
|
||||
<div className="flex flex-row justify-end gap-4 mb-2">
|
||||
<Button asChild variant="outline">
|
||||
<RouterLink to="new">
|
||||
<PlusIcon />
|
||||
Add token
|
||||
</RouterLink>
|
||||
</Button>
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default TokensPage;
|
||||
|
||||
@@ -7,7 +7,6 @@ import type { APIKeyWithOwner } from "#/api/typesGenerated";
|
||||
import { ErrorAlert } from "#/components/Alert/ErrorAlert";
|
||||
import { Button } from "#/components/Button/Button";
|
||||
import { ChooseOne, Cond } from "#/components/Conditionals/ChooseOne";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -48,7 +47,7 @@ export const TokensPageView: FC<TokensPageViewProps> = ({
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
<div className="flex flex-col gap-4">
|
||||
{Boolean(getTokensError) && <ErrorAlert error={getTokensError} />}
|
||||
{Boolean(deleteTokenError) && <ErrorAlert error={deleteTokenError} />}
|
||||
|
||||
@@ -129,6 +128,6 @@ export const TokensPageView: FC<TokensPageViewProps> = ({
|
||||
</ChooseOne>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -7,7 +7,6 @@ import {
|
||||
SettingsHeaderDescription,
|
||||
SettingsHeaderTitle,
|
||||
} from "#/components/SettingsHeader/SettingsHeader";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -39,7 +38,7 @@ export const WorkspaceProxyView: FC<WorkspaceProxyViewProps> = ({
|
||||
selectProxyError,
|
||||
}) => {
|
||||
return (
|
||||
<Stack>
|
||||
<div className="flex flex-col gap-4">
|
||||
<SettingsHeader>
|
||||
<SettingsHeaderTitle>Workspace Proxies</SettingsHeaderTitle>
|
||||
<SettingsHeaderDescription>
|
||||
@@ -81,6 +80,6 @@ export const WorkspaceProxyView: FC<WorkspaceProxyViewProps> = ({
|
||||
</ChooseOne>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import type { FC } from "react";
|
||||
import type { GroupsByUserId } from "#/api/queries/groups";
|
||||
import type * as TypesGen from "#/api/typesGenerated";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
@@ -64,23 +63,23 @@ export const UsersTable: FC<UsersTableProps> = ({
|
||||
<TableRow>
|
||||
<TableHead className="w-2/6">User</TableHead>
|
||||
<TableHead className="w-2/6">
|
||||
<Stack direction="row" spacing={1} alignItems="center">
|
||||
<div className="flex flex-row gap-2 items-center">
|
||||
<span>Roles</span>
|
||||
<TableColumnHelpPopover variant="roles" />
|
||||
</Stack>
|
||||
</div>
|
||||
</TableHead>
|
||||
<TableHead className="w-1/6">
|
||||
<Stack direction="row" spacing={1} alignItems="center">
|
||||
<div className="flex flex-row gap-2 items-center">
|
||||
<span>Groups</span>
|
||||
<TableColumnHelpPopover variant="groups" />
|
||||
</Stack>
|
||||
</div>
|
||||
</TableHead>
|
||||
{showAISeatColumn && (
|
||||
<TableHead className="w-1/6">
|
||||
<Stack direction="row" spacing={1} alignItems="center">
|
||||
<div className="flex flex-row gap-2 items-center">
|
||||
<span>AI add-on</span>
|
||||
<TableColumnHelpPopover variant="ai_addon" />
|
||||
</Stack>
|
||||
</div>
|
||||
</TableHead>
|
||||
)}
|
||||
<TableHead className="w-1/6">Login Type</TableHead>
|
||||
|
||||
@@ -22,7 +22,6 @@ import {
|
||||
PageHeaderSubtitle,
|
||||
PageHeaderTitle,
|
||||
} from "#/components/PageHeader/FullWidthPageHeader";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { Stats, StatsItem } from "#/components/Stats/Stats";
|
||||
import {
|
||||
TAB_PADDING_X,
|
||||
@@ -101,14 +100,13 @@ export const WorkspaceBuildPageView: FC<WorkspaceBuildPageViewProps> = ({
|
||||
return (
|
||||
<DashboardFullPage>
|
||||
<FullWidthPageHeader sticky={false}>
|
||||
<Stack direction="row">
|
||||
<div className="flex flex-row gap-4">
|
||||
<BuildAvatar build={build} size="lg" />
|
||||
<div>
|
||||
<PageHeaderTitle>Build #{build.build_number}</PageHeaderTitle>
|
||||
<PageHeaderSubtitle>{build.initiator_name}</PageHeaderSubtitle>
|
||||
</div>
|
||||
</Stack>
|
||||
|
||||
</div>
|
||||
<Stats
|
||||
aria-label="Build details"
|
||||
className="flex flex-col items-start gap-2 px-0 border-none grow basis-0 md:flex-row md:gap-x-12 md:gap-y-6"
|
||||
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
import { ErrorAlert } from "#/components/Alert/ErrorAlert";
|
||||
import { Loader } from "#/components/Loader/Loader";
|
||||
import { Margins } from "#/components/Margins/Margins";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { pageTitle } from "#/utils/page";
|
||||
import { Sidebar } from "./Sidebar";
|
||||
import { WorkspaceSettings } from "./useWorkspaceSettings";
|
||||
@@ -37,7 +36,7 @@ export const WorkspaceSettingsLayout: FC = () => {
|
||||
<title>{pageTitle(workspaceName, "Settings")}</title>
|
||||
|
||||
<Margins>
|
||||
<Stack className="py-12" direction="row" spacing={10}>
|
||||
<div className="flex flex-row gap-20 py-12">
|
||||
{error ? (
|
||||
<ErrorAlert error={error} />
|
||||
) : (
|
||||
@@ -58,7 +57,7 @@ export const WorkspaceSettingsLayout: FC = () => {
|
||||
</WorkspaceSettings.Provider>
|
||||
)
|
||||
)}
|
||||
</Stack>
|
||||
</div>
|
||||
</Margins>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -22,7 +22,6 @@ import {
|
||||
import { PaginationAmount } from "#/components/PaginationWidget/PaginationAmount";
|
||||
import { PaginationWidgetBase } from "#/components/PaginationWidget/PaginationWidgetBase";
|
||||
import { Spinner } from "#/components/Spinner/Spinner";
|
||||
import { Stack } from "#/components/Stack/Stack";
|
||||
import { TableToolbar } from "#/components/TableToolbar/TableToolbar";
|
||||
import { WorkspacesTable } from "#/pages/WorkspacesPage/WorkspacesTable";
|
||||
import { mustUpdateWorkspace } from "#/utils/workspace";
|
||||
@@ -99,14 +98,14 @@ export const WorkspacesPageView: FC<WorkspacesPageViewProps> = ({
|
||||
}
|
||||
>
|
||||
<PageHeaderTitle>
|
||||
<Stack direction="row" spacing={1} alignItems="center">
|
||||
<div className="flex flex-row gap-2 items-center">
|
||||
<span>Workspaces</span>
|
||||
<WorkspaceHelpPopover />
|
||||
</Stack>
|
||||
</div>
|
||||
</PageHeaderTitle>
|
||||
</PageHeader>
|
||||
|
||||
<Stack>
|
||||
<div className="flex flex-col gap-4">
|
||||
{hasError(error) && !isApiValidationError(error) && (
|
||||
<ErrorAlert error={error} />
|
||||
)}
|
||||
@@ -118,7 +117,7 @@ export const WorkspacesPageView: FC<WorkspacesPageViewProps> = ({
|
||||
userMenu={filterState.menus.user}
|
||||
organizationsMenu={filterState.menus.organizations}
|
||||
/>
|
||||
</Stack>
|
||||
</div>
|
||||
|
||||
<TableToolbar>
|
||||
{checkedWorkspaces.length > 0 ? (
|
||||
|
||||
Reference in New Issue
Block a user