From 978e218237594de2f43858d55ed848e5ef00800a Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Thu, 26 Jun 2025 20:53:31 +0000 Subject: [PATCH 1/4] feat: redirect to the task page after creation --- site/src/pages/TasksPage/TasksPage.tsx | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/site/src/pages/TasksPage/TasksPage.tsx b/site/src/pages/TasksPage/TasksPage.tsx index f86979f8eae00..cd8b08d121102 100644 --- a/site/src/pages/TasksPage/TasksPage.tsx +++ b/site/src/pages/TasksPage/TasksPage.tsx @@ -2,7 +2,7 @@ import Skeleton from "@mui/material/Skeleton"; import { API } from "api/api"; import { getErrorDetail, getErrorMessage } from "api/errors"; import { disabledRefetchOptions } from "api/queries/util"; -import type { Template } from "api/typesGenerated"; +import type { Template, Workspace } from "api/typesGenerated"; import { ErrorAlert } from "components/Alert/ErrorAlert"; import { Avatar } from "components/Avatar/Avatar"; import { AvatarData } from "components/Avatar/AvatarData"; @@ -46,7 +46,7 @@ import { generateWorkspaceName } from "modules/workspaces/generateWorkspaceName" import { type FC, type ReactNode, useState } from "react"; import { Helmet } from "react-helmet-async"; import { useMutation, useQuery, useQueryClient } from "react-query"; -import { Link as RouterLink } from "react-router-dom"; +import { Link as RouterLink, useNavigate } from "react-router-dom"; import TextareaAutosize from "react-textarea-autosize"; import { pageTitle } from "utils/page"; import { relativeTime } from "utils/time"; @@ -157,6 +157,7 @@ const TaskFormSection: FC<{ filter: TasksFilter; onFilterChange: (filter: TasksFilter) => void; }> = ({ showFilter, filter, onFilterChange }) => { + const navigate = useNavigate(); const { data: templates, error, @@ -184,7 +185,14 @@ const TaskFormSection: FC<{ } return ( <> - + { + navigate( + `/tasks/${task.workspace.owner_name}/${task.workspace.name}`, + ); + }} + /> {showFilter && ( )} @@ -196,9 +204,10 @@ type CreateTaskMutationFnProps = { prompt: string; templateId: string }; type TaskFormProps = { templates: Template[]; + onSuccess: (task: Task) => void; }; -const TaskForm: FC = ({ templates }) => { +const TaskForm: FC = ({ templates, onSuccess }) => { const { user } = useAuthenticated(); const queryClient = useQueryClient(); @@ -220,10 +229,11 @@ const TaskForm: FC = ({ templates }) => { const createTaskMutation = useMutation({ mutationFn: async ({ prompt, templateId }: CreateTaskMutationFnProps) => data.createTask(prompt, user.id, templateId), - onSuccess: async () => { + onSuccess: async (task) => { await queryClient.invalidateQueries({ queryKey: ["tasks"], }); + onSuccess(task); }, }); @@ -244,7 +254,6 @@ const TaskForm: FC = ({ templates }) => { prompt, templateId: templateID, }); - form.reset(); } catch (error) { const message = getErrorMessage(error, "Error creating task"); const detail = getErrorDetail(error) ?? "Please try again"; From fa138effe7a3a7412d429f5eda7ca0c07046ce79 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Fri, 27 Jun 2025 14:00:47 +0000 Subject: [PATCH 2/4] fmt --- site/src/pages/TasksPage/TasksPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/pages/TasksPage/TasksPage.tsx b/site/src/pages/TasksPage/TasksPage.tsx index cd8b08d121102..49a8717592b59 100644 --- a/site/src/pages/TasksPage/TasksPage.tsx +++ b/site/src/pages/TasksPage/TasksPage.tsx @@ -2,7 +2,7 @@ import Skeleton from "@mui/material/Skeleton"; import { API } from "api/api"; import { getErrorDetail, getErrorMessage } from "api/errors"; import { disabledRefetchOptions } from "api/queries/util"; -import type { Template, Workspace } from "api/typesGenerated"; +import type { Template } from "api/typesGenerated"; import { ErrorAlert } from "components/Alert/ErrorAlert"; import { Avatar } from "components/Avatar/Avatar"; import { AvatarData } from "components/Avatar/AvatarData"; From 1127a3da628e5fd9a86fd15a81163bf533bed458 Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Fri, 27 Jun 2025 14:37:29 +0000 Subject: [PATCH 3/4] Fix tests --- .../src/pages/TasksPage/TasksPage.stories.tsx | 45 +++++++++++-------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/site/src/pages/TasksPage/TasksPage.stories.tsx b/site/src/pages/TasksPage/TasksPage.stories.tsx index 9707532d82ded..490e6f99e78c3 100644 --- a/site/src/pages/TasksPage/TasksPage.stories.tsx +++ b/site/src/pages/TasksPage/TasksPage.stories.tsx @@ -17,6 +17,7 @@ import { withProxyProvider, } from "testHelpers/storybook"; import TasksPage, { data } from "./TasksPage"; +import { reactRouterParameters } from "storybook-addon-remix-react-router"; const meta: Meta = { title: "pages/TasksPage", @@ -132,6 +133,23 @@ const newTaskData = { export const CreateTaskSuccessfully: Story = { decorators: [withProxyProvider()], + parameters: { + reactRouter: reactRouterParameters({ + location: { + path: "/tasks", + }, + routing: [ + { + path: "/tasks", + useStoryElement: true, + }, + { + path: "/tasks/:ownerName/:workspaceName", + element:

Task page

, + }, + ], + }), + }, beforeEach: () => { spyOn(data, "fetchAITemplates").mockResolvedValue([MockTemplate]); spyOn(data, "fetchTasks") @@ -150,10 +168,8 @@ export const CreateTaskSuccessfully: Story = { await userEvent.click(submitButton); }); - await step("Verify task in the table", async () => { - await canvas.findByRole("row", { - name: new RegExp(newTaskData.prompt, "i"), - }); + await step("Redirects to the task page", async () => { + await canvas.findByText(/task page/i); }); }, }; @@ -187,7 +203,7 @@ export const CreateTaskError: Story = { }, }; -export const WithExternalAuth: Story = { +export const WithAuthenticatedExternalAuth: Story = { decorators: [withProxyProvider()], beforeEach: () => { spyOn(data, "fetchTasks") @@ -201,26 +217,17 @@ export const WithExternalAuth: Story = { play: async ({ canvasElement, step }) => { const canvas = within(canvasElement); - await step("Run task", async () => { - const prompt = await canvas.findByLabelText(/prompt/i); - await userEvent.type(prompt, newTaskData.prompt); - const submitButton = canvas.getByRole("button", { name: /run task/i }); - await waitFor(() => expect(submitButton).toBeEnabled()); - await userEvent.click(submitButton); - }); - - await step("Verify task in the table", async () => { - await canvas.findByRole("row", { - name: new RegExp(newTaskData.prompt, "i"), - }); - }); - await step("Does not render external auth", async () => { expect( canvas.queryByText(/external authentication/), ).not.toBeInTheDocument(); }); }, + parameters: { + chromatic: { + disableSnapshot: true, + }, + }, }; export const MissingExternalAuth: Story = { From a455556ea634bcb4b6f61c90e43ffd9771b7f62e Mon Sep 17 00:00:00 2001 From: BrunoQuaresma Date: Fri, 27 Jun 2025 14:38:09 +0000 Subject: [PATCH 4/4] fmt --- site/src/pages/TasksPage/TasksPage.stories.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/pages/TasksPage/TasksPage.stories.tsx b/site/src/pages/TasksPage/TasksPage.stories.tsx index 490e6f99e78c3..1b1770f586768 100644 --- a/site/src/pages/TasksPage/TasksPage.stories.tsx +++ b/site/src/pages/TasksPage/TasksPage.stories.tsx @@ -2,6 +2,7 @@ import type { Meta, StoryObj } from "@storybook/react"; import { expect, spyOn, userEvent, waitFor, within } from "@storybook/test"; import { API } from "api/api"; import { MockUsers } from "pages/UsersPage/storybookData/users"; +import { reactRouterParameters } from "storybook-addon-remix-react-router"; import { MockTemplate, MockTemplateVersionExternalAuthGithub, @@ -17,7 +18,6 @@ import { withProxyProvider, } from "testHelpers/storybook"; import TasksPage, { data } from "./TasksPage"; -import { reactRouterParameters } from "storybook-addon-remix-react-router"; const meta: Meta = { title: "pages/TasksPage",