Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ import {
HelpTooltipLinksGroup,
HelpTooltipText,
HelpTooltipTitle,
HelpTooltipTrigger,
} from "components/HelpTooltip/HelpTooltip";
import { InfoIcon, RotateCcwIcon } from "lucide-react";
import { linkToTemplate, useLinks } from "modules/navigation";
import { type FC, useState } from "react";
import { type FC, type ReactNode, useState } from "react";
import { useQuery } from "react-query";
import {
useWorkspaceUpdate,
Expand All @@ -25,20 +26,31 @@ import {

interface WorkspaceOutdatedTooltipProps {
workspace: Workspace;
children?: ReactNode;
}

export const WorkspaceOutdatedTooltip: FC<WorkspaceOutdatedTooltipProps> = (
props,
) => {
export const WorkspaceOutdatedTooltip: FC<WorkspaceOutdatedTooltipProps> = ({
workspace,
children,
}) => {
const [isOpen, setIsOpen] = useState(false);

return (
<HelpTooltip open={isOpen} onOpenChange={setIsOpen}>
<HelpTooltipIconTrigger size="small" hoverEffect={false}>
<InfoIcon css={styles.icon} />
<span className="sr-only">Outdated info</span>
</HelpTooltipIconTrigger>
<WorkspaceOutdatedTooltipContent isOpen={isOpen} {...props} />
{children ? (
<HelpTooltipTrigger asChild>
<span className="flex items-center gap-1.5 cursor-help">
<InfoIcon css={styles.icon} size={14} />
<span>{children}</span>
</span>
</HelpTooltipTrigger>
) : (
<HelpTooltipIconTrigger size="small" hoverEffect={false}>
<InfoIcon css={styles.icon} />
<span className="sr-only">Outdated info</span>
</HelpTooltipIconTrigger>
)}
<WorkspaceOutdatedTooltipContent isOpen={isOpen} workspace={workspace} />
</HelpTooltip>
);
};
Expand Down
47 changes: 46 additions & 1 deletion site/src/pages/TaskPage/TaskPage.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
} from "testHelpers/entities";
import {
withAuthProvider,
withDashboardProvider,
withGlobalSnackbar,
withProxyProvider,
withWebSocket,
Expand Down Expand Up @@ -65,7 +66,7 @@ const MockVSCodeApp: WorkspaceApp = {
const meta: Meta<typeof TaskPage> = {
title: "pages/TaskPage",
component: TaskPage,
decorators: [withProxyProvider(), withAuthProvider],
decorators: [withProxyProvider(), withAuthProvider, withDashboardProvider],
beforeEach: () => {
spyOn(API, "getTasks").mockResolvedValue(MockTasks);
},
Expand Down Expand Up @@ -402,6 +403,50 @@ export const MainAppHealthy: Story = mainAppHealthStory("healthy");
export const MainAppInitializing: Story = mainAppHealthStory("initializing");
export const MainAppUnhealthy: Story = mainAppHealthStory("unhealthy");

export const OutdatedWorkspace: Story = {
// Given: an 'outdated' workspace (that is, the latest build does not use template's active version)
parameters: {
queries: [
{
key: ["tasks", { owner: MockTask.owner_name }],
data: [MockTask],
},
{
key: ["tasks", MockTask.owner_name, MockTask.id],
data: MockTask,
},
{
key: [
"workspace",
MockTask.owner_name,
MockTask.workspace_name,
"settings",
],
data: {
...MockStoppedWorkspace,
outdated: true,
},
},
{
key: [
"workspaceBuilds",
MockStoppedWorkspace.latest_build.id,
"parameters",
],
data: [],
},
],
},
// Then: a tooltip should be displayed prompting the user to update the workspace.
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const outdatedTooltip = await canvas.findByTestId(
"workspace-outdated-tooltip",
);
expect(outdatedTooltip).toBeVisible();
},
};

export const Active: Story = {
decorators: [withProxyProvider()],
beforeEach: () => {
Expand Down
12 changes: 12 additions & 0 deletions site/src/pages/TaskPage/TaskPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { getAllAppsWithAgent } from "modules/tasks/apps";
import { TasksSidebar } from "modules/tasks/TasksSidebar/TasksSidebar";
import { WorkspaceErrorDialog } from "modules/workspaces/ErrorDialog/WorkspaceErrorDialog";
import { WorkspaceBuildLogs } from "modules/workspaces/WorkspaceBuildLogs/WorkspaceBuildLogs";
import { WorkspaceOutdatedTooltip } from "modules/workspaces/WorkspaceOutdatedTooltip/WorkspaceOutdatedTooltip";
import {
type FC,
type PropsWithChildren,
Expand Down Expand Up @@ -275,9 +276,20 @@ const WorkspaceNotRunning: FC<WorkspaceNotRunningProps> = ({
<span className="text-content-secondary text-sm">
Apps and previous statuses are not available
</span>
{workspace.outdated && (
<div
data-testid="workspace-outdated-tooltip"
className="flex items-center gap-1.5 mt-1 text-content-secondary text-sm"
>
<WorkspaceOutdatedTooltip workspace={workspace}>
You can update your task workspace to a newer version
</WorkspaceOutdatedTooltip>
</div>
)}
<div className="flex flex-row mt-4 gap-4">
<Button
size="sm"
data-testid="task-start-workspace"
disabled={isWaitingForStart}
onClick={() => {
mutateStartWorkspace.mutate({
Expand Down
Loading