Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix: improvements to UX and flow
  • Loading branch information
jaaydenh committed Jun 17, 2025
commit abea8ecdb685b510011a001e05ca2e0c50ec6fd7
1 change: 1 addition & 0 deletions site/src/components/Badge/Badge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const badgeVariants = cva(
"border border-solid border-border-warning bg-surface-orange text-content-warning shadow",
destructive:
"border border-solid border-border-destructive bg-surface-red text-highlight-red shadow",
green: "border border-solid border-surface-green bg-surface-green text-highlight-green shadow",
},
size: {
xs: "text-2xs font-regular h-5 [&_svg]:hidden rounded px-1.5",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import type { TemplateVersionParameter } from "api/typesGenerated";
import { Button } from "components/Button/Button";
import { ConfirmDialog } from "components/Dialogs/ConfirmDialog/ConfirmDialog";
import { Link } from "components/Link/Link";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "components/Dialog/Dialog";
import type { FC } from "react";
import { useNavigate } from "react-router-dom";

interface EphemeralParametersDialogProps {
open: boolean;
Expand All @@ -11,6 +18,7 @@ interface EphemeralParametersDialogProps {
ephemeralParameters: TemplateVersionParameter[];
workspaceOwner: string;
workspaceName: string;
templateVersionId: string;
}

export const EphemeralParametersDialog: FC<EphemeralParametersDialogProps> = ({
Expand All @@ -20,42 +28,57 @@ export const EphemeralParametersDialog: FC<EphemeralParametersDialogProps> = ({
ephemeralParameters,
workspaceOwner,
workspaceName,
templateVersionId,
}) => {
const parametersPageUrl = `/@${workspaceOwner}/${workspaceName}/settings/parameters`;
const navigate = useNavigate();

const description = (
<>
<p>This workspace template has ephemeral parameters that will be reset to their default values:</p>
<div style={{ margin: "16px 0" }}>
{ephemeralParameters.map((param) => (
<div key={param.name} style={{ marginBottom: "8px" }}>
<strong>{param.display_name || param.name}</strong>
{param.description && (
<div style={{ fontSize: "14px", color: "#666" }}>
{param.description}
</div>
)}
</div>
))}
</div>
<p>You can continue without setting values for these parameters, or go to the workspace parameters page to configure them.</p>
<div style={{ marginTop: "16px" }}>
<Button asChild onClick={onClose}>
<Link to={parametersPageUrl}>Go to Parameters Page</Link>
</Button>
</div>
</>
);
const handleGoToParameters = () => {
onClose();
navigate(
`/@${workspaceOwner}/${workspaceName}/settings/parameters?templateVersionId=${templateVersionId}`,
);
};

return (
<ConfirmDialog
open={open}
onClose={onClose}
onConfirm={onContinue}
title="Ephemeral Parameters Detected"
confirmText="Continue Without Setting"
description={description}
type="info"
/>
<Dialog open={open} onOpenChange={(isOpen) => !isOpen && onClose()}>
<DialogContent>
<DialogHeader>
<DialogTitle>Ephemeral Parameters Detected</DialogTitle>
<DialogDescription>
This workspace template has{" "}
<strong className="text-content-primary">
{ephemeralParameters.length}
</strong>{" "}
ephemeral parameters that will be reset to their default values
</DialogDescription>
<DialogDescription>
{ephemeralParameters.map((param) => (
<div key={param.name}>
<p className="text-content-primary m-0 font-bold">
{param.display_name || param.name}
</p>
{param.description && (
<p className="m-0 text-sm text-content-secondary">
{param.description}
</p>
)}
</div>
))}
</DialogDescription>
<DialogDescription>
Would you like to go to the workspace parameters page to review and
update these parameters before continuing?
</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button onClick={onContinue} variant="outline">
Continue
</Button>
<Button onClick={handleGoToParameters}>
Go to workspace parameters
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
};
};
2 changes: 1 addition & 1 deletion site/src/components/EphemeralParametersDialog/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { EphemeralParametersDialog } from "./EphemeralParametersDialog";
export { EphemeralParametersDialog } from "./EphemeralParametersDialog";
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
LinkIcon,
Settings,
TriangleAlert,
Hourglass,
} from "lucide-react";
import { type FC, useEffect, useId, useRef, useState } from "react";
import type { AutofillBuildParameter } from "utils/richParameters";
Expand Down Expand Up @@ -162,6 +163,23 @@ const ParameterLabel: FC<ParameterLabelProps> = ({
</Tooltip>
</TooltipProvider>
)}
{parameter.ephemeral && (
<TooltipProvider delayDuration={100}>
<Tooltip>
<TooltipTrigger asChild>
<span className="flex items-center">
<Badge size="sm" variant="green" border="none">
<Hourglass />
Ephemeral
</Badge>
</span>
</TooltipTrigger>
<TooltipContent className="max-w-xs">
This parameter only applies for a single workspace start
</TooltipContent>
</Tooltip>
</TooltipProvider>
)}
{isPreset && (
<TooltipProvider delayDuration={100}>
<Tooltip>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { useTheme } from "@emotion/react";
import { Button } from "components/Button/Button";
import visuallyHidden from "@mui/utils/visuallyHidden";
import { API } from "api/api";
import type {
TemplateVersionParameter,
Workspace,
WorkspaceBuildParameter,
} from "api/typesGenerated";
import { Button } from "components/Button/Button";
import { FormFields } from "components/Form/Form";
import { TopbarButton } from "components/FullPageLayout/Topbar";
import {
Expand All @@ -27,8 +27,8 @@ import { useFormik } from "formik";
import { ChevronDownIcon } from "lucide-react";
import type { FC } from "react";
import { useQuery } from "react-query";
import { useNavigate } from "react-router-dom";
import { docs } from "utils/docs";
import { Link } from "components/Link/Link";
import { getFormHelpers } from "utils/formUtils";
import {
type AutofillBuildParameter,
Expand Down Expand Up @@ -98,42 +98,47 @@ const BuildParametersPopoverContent: FC<BuildParametersPopoverContentProps> = ({
}) => {
const theme = useTheme();
const popover = usePopover();
const navigate = useNavigate();

if (
!workspace.template_use_classic_parameter_flow &&
ephemeralParameters &&
ephemeralParameters.length > 0
) {
const handleGoToParameters = () => {
popover.setOpen(false);
navigate(
`/@${workspace.owner_name}/${workspace.name}/settings/parameters`,
);
};

// For templates that don't use classic parameter flow, show different UI
if (!workspace.template_use_classic_parameter_flow && ephemeralParameters && ephemeralParameters.length > 0) {
const parametersPageUrl = `/@${workspace.owner_name}/${workspace.name}/settings/parameters`;

return (
<div
css={{
color: theme.palette.text.secondary,
padding: 20,
}}
>
<HelpTooltipTitle>Ephemeral Parameters</HelpTooltipTitle>
<HelpTooltipText css={{ marginBottom: 16 }}>
This template has ephemeral parameters that must be configured on the workspace parameters page:
</HelpTooltipText>

<div css={{ marginBottom: 16 }}>
<div className="flex flex-col gap-4 p-5">
<h1 className="text-xl m-0 text-content-primary font-semibold leading-none ">
Ephemeral Parameters
</h1>
<p className="m-0 text-sm text-content-secondary">
This template has ephemeral parameters that must be configured on the
workspace parameters page
</p>

<div className="flex flex-col gap-2">
{ephemeralParameters.map((param) => (
<div key={param.name} css={{ marginBottom: 8 }}>
<strong>{param.display_name || param.name}</strong>
<div key={param.name} className="flex flex-col gap-2">
<p className="text-content-primary m-0 font-bold">
{param.display_name || param.name}
</p>
{param.description && (
<div css={{ fontSize: 14, color: theme.palette.text.secondary }}>
<div className="m-0 text-sm text-content-secondary">
{param.description}
</div>
)}
</div>
))}
</div>

<Button
asChild
css={{ width: "100%" }}
onClick={() => popover.setOpen(false)}
>
<Link to={parametersPageUrl}>Go to Parameters Page</Link>

<Button className="w-full" onClick={handleGoToParameters}>
Go to workspace parameters
</Button>
</div>
);
Expand Down
Loading
Loading