feat: don't redirect to task page when it is created (#19919)

**Demo:**

https://github.com/user-attachments/assets/3ffaa13e-553f-43d2-9fad-d4d3ea7a4ede

Closes https://github.com/coder/coder/issues/19675
This commit is contained in:
Bruno Quaresma
2025-09-24 10:05:38 -03:00
committed by GitHub
parent 8f3e03ad40
commit 6d0943a53a
3 changed files with 25 additions and 11 deletions
+4 -9
View File
@@ -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<TaskPromptProps> = ({
error,
onRetry,
}) => {
const navigate = useNavigate();
if (error) {
return <TaskPromptLoadingError error={error} onRetry={onRetry} />;
}
@@ -64,8 +61,8 @@ export const TaskPrompt: FC<TaskPromptProps> = ({
return (
<CreateTaskForm
templates={templates}
onSuccess={(task) => {
navigate(`/tasks/${task.owner_name}/${task.name}`);
onSuccess={() => {
displaySuccess("Task created successfully");
}}
/>
);
@@ -195,9 +192,7 @@ const CreateTaskForm: FC<CreateTaskFormProps> = ({ templates, onSuccess }) => {
template_version_preset_id: selectedPresetId,
}),
onSuccess: async (task) => {
await queryClient.invalidateQueries({
queryKey: ["tasks"],
});
await queryClient.invalidateQueries({ queryKey: ["tasks"] });
onSuccess(task);
},
});
+12 -2
View File
@@ -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);
});
});
},
};
+9
View File
@@ -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",