diff --git a/site/src/pages/TasksPage/TaskPrompt.tsx b/site/src/pages/TasksPage/TaskPrompt.tsx index eeffd60ffb..cebbe2d2ea 100644 --- a/site/src/pages/TasksPage/TaskPrompt.tsx +++ b/site/src/pages/TasksPage/TaskPrompt.tsx @@ -10,7 +10,7 @@ import type { import { ErrorAlert } from "components/Alert/ErrorAlert"; import { Button } from "components/Button/Button"; import { ExternalImage } from "components/ExternalImage/ExternalImage"; -import { displayError } from "components/GlobalSnackbar/utils"; +import { displayError, displaySuccess } from "components/GlobalSnackbar/utils"; import { Link } from "components/Link/Link"; import { Select, @@ -33,7 +33,6 @@ import { RedoIcon, RotateCcwIcon, SendIcon } from "lucide-react"; import { AI_PROMPT_PARAMETER_NAME } from "modules/tasks/tasks"; import { type FC, useEffect, useState } from "react"; import { useMutation, useQuery, useQueryClient } from "react-query"; -import { useNavigate } from "react-router"; import TextareaAutosize from "react-textarea-autosize"; import { docs } from "utils/docs"; @@ -50,8 +49,6 @@ export const TaskPrompt: FC = ({ error, onRetry, }) => { - const navigate = useNavigate(); - if (error) { return ; } @@ -64,8 +61,8 @@ export const TaskPrompt: FC = ({ return ( { - navigate(`/tasks/${task.owner_name}/${task.name}`); + onSuccess={() => { + displaySuccess("Task created successfully"); }} /> ); @@ -195,9 +192,7 @@ const CreateTaskForm: FC = ({ templates, onSuccess }) => { template_version_preset_id: selectedPresetId, }), onSuccess: async (task) => { - await queryClient.invalidateQueries({ - queryKey: ["tasks"], - }); + await queryClient.invalidateQueries({ queryKey: ["tasks"] }); onSuccess(task); }, }); diff --git a/site/src/pages/TasksPage/TasksPage.stories.tsx b/site/src/pages/TasksPage/TasksPage.stories.tsx index 059d76eb20..dfcb081017 100644 --- a/site/src/pages/TasksPage/TasksPage.stories.tsx +++ b/site/src/pages/TasksPage/TasksPage.stories.tsx @@ -226,6 +226,7 @@ export const LoadedTasksWaitingForInputTab: Story = { }; export const CreateTaskSuccessfully: Story = { + decorators: [withGlobalSnackbar], parameters: { reactRouter: reactRouterParameters({ location: { @@ -261,8 +262,17 @@ export const CreateTaskSuccessfully: Story = { await userEvent.click(submitButton); }); - await step("Redirects to the task page", async () => { - await canvas.findByText(/task page/i); + await step("Displays success message", async () => { + const body = within(canvasElement.ownerDocument.body); + const successMessage = await body.findByText(/task created/i); + expect(successMessage).toBeInTheDocument(); + }); + + await step("Find task in the table", async () => { + const table = canvasElement.querySelector("table"); + await waitFor(() => { + expect(table).toHaveTextContent(MockNewTaskData.prompt); + }); }); }, }; diff --git a/site/src/pages/TasksPage/TasksPage.tsx b/site/src/pages/TasksPage/TasksPage.tsx index 1d3340a456..8f9dcadf3e 100644 --- a/site/src/pages/TasksPage/TasksPage.tsx +++ b/site/src/pages/TasksPage/TasksPage.tsx @@ -43,6 +43,15 @@ const TasksPage: FC = () => { queryKey: ["tasks", filter], queryFn: () => API.experimental.getTasks(filter), refetchInterval: 10_000, + // TODO: Switch to sorting by latest_status_app.created_at once it’s reliable. + // Currently, it doesn’t always update fast enough for a good UX, so we’re + // temporarily sorting by workspace.created_at instead. + select: (tasks) => + tasks.toSorted( + (a, b) => + new Date(b.workspace.created_at).getTime() - + new Date(a.workspace.created_at).getTime(), + ), }); const idleTasks = tasksQuery.data?.filter( (task) => task.workspace.latest_app_status?.state === "idle",