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
8 changes: 7 additions & 1 deletion frontend/components/task-dialog/header.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
"use client";

import type { Task } from "@/app/api/queries/useGetTasksQuery";
import { DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { useIsCloudBrand } from "@/contexts/brand-context";
import {
ALL_TASK_FILE_TYPES,
formatTaskFileTypeLabel,
isTaskInProgressStatus,
type TaskFileStatusCategory,
} from "@/lib/task-utils";
import { cn } from "@/lib/utils";
Expand All @@ -13,6 +15,7 @@ import { TaskDialogFilters } from "./filters";

interface TaskDialogHeaderProps {
taskId: string;
taskStatus?: Task["status"];
search: string;
onSearchChange: (value: string) => void;
fileType: string;
Expand All @@ -27,6 +30,7 @@ interface TaskDialogHeaderProps {

export function TaskDialogHeader({
taskId,
taskStatus,
search,
onSearchChange,
fileType,
Expand All @@ -44,6 +48,8 @@ export function TaskDialogHeader({
fileType === ALL_TASK_FILE_TYPES
? allTypesLabel
: formatTaskFileTypeLabel(fileType);
const titlePrefix =
taskStatus && isTaskInProgressStatus(taskStatus) ? "Active task" : "Task";

return (
<header
Expand All @@ -68,7 +74,7 @@ export function TaskDialogHeader({
!isCloudBrand && "px-4",
)}
>
Task {taskId}
{titlePrefix} {taskId}
</DialogTitle>
</DialogHeader>

Expand Down
50 changes: 30 additions & 20 deletions frontend/components/task-dialog/task-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ function TaskDialogContent({
// Always offer "All file types"; only disable while task data is loading.
const fileTypeDisabled = !task;
const showRetryActions = retryableCount > 0;
const isCancelOnly = !showRetryActions;

return (
<div
Expand All @@ -72,6 +73,7 @@ function TaskDialogContent({
>
<TaskDialogHeader
taskId={task_id}
taskStatus={task?.status}
search={search}
onSearchChange={setSearch}
fileType={fileType}
Expand Down Expand Up @@ -126,32 +128,23 @@ function TaskDialogContent({

<DialogFooter
className={cn(
"w-full shrink-0 flex-row items-stretch sm:justify-normal sm:space-x-0",
"w-full shrink-0 flex-row items-stretch sm:space-x-0",
isCloudBrand
? "gap-0 border-t bg-layer-contextual p-0"
: "gap-2 border-t bg-task-dialog-oss px-6 py-4",
: cn(
"gap-2 border-t bg-task-dialog-oss px-6 py-4",
isCancelOnly ? "justify-start" : "justify-end",
),
)}
>
<Button
type="button"
variant="ghost"
className={cn(
showRetryActions && "min-w-0 flex-1",
isCloudBrand &&
showRetryActions &&
"justify-start rounded-none px-4 text-left",
)}
onClick={onClose}
disabled={isRetrying}
>
{isCloudBrand ? "Cancel" : "Close"}
</Button>
{showRetryActions && selectedCount > 0 ? (
<Button
type="button"
className={cn(
"min-w-0 flex-1",
isCloudBrand && "justify-start rounded-none px-4 text-left",
"min-w-0",
isCloudBrand
? "w-1/2 justify-start rounded-none px-4 text-left"
: "flex-1",
)}
disabled={isRetrying || !task}
onClick={() => void handleRetrySelected()}
Expand All @@ -163,15 +156,32 @@ function TaskDialogContent({
<Button
type="button"
className={cn(
"min-w-0 flex-1",
isCloudBrand && "justify-start rounded-none px-4 text-left",
"min-w-0",
isCloudBrand
? "w-1/2 justify-start rounded-none px-4 text-left"
: "flex-1",
)}
disabled={isRetrying || !task}
onClick={() => void handleRetryAll()}
>
{isRetrying ? "Retrying…" : "Retry all"}
</Button>
) : null}
<Button
type="button"
variant={isCloudBrand && isCancelOnly ? "default" : "ghost"}
ignoreTitleCase
className={cn(
isCloudBrand
? "w-1/2 shrink-0 justify-start rounded-none px-4 text-left"
: "shrink-0",
isCloudBrand && showRetryActions && "ml-auto",
)}
onClick={onClose}
disabled={isRetrying}
>
{isCancelOnly ? "Close" : "Cancel"}
</Button>
Comment thread
coderabbitai[bot] marked this conversation as resolved.
</DialogFooter>
</div>
);
Expand Down
14 changes: 3 additions & 11 deletions frontend/components/task-error-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ import * as AccordionPrimitive from "@radix-ui/react-accordion";
import { AlertCircle, ChevronDown, Flag, XCircle } from "lucide-react";
import { useMemo, useState } from "react";
import { IncidentReporterIcon } from "@/components/icons/incident-reporter-icon";
import TaskDialog from "@/components/task-dialog";
import {
Accordion,
AccordionContent,
AccordionItem,
} from "@/components/ui/accordion";
import { useIsCloudBrand } from "@/contexts/brand-context";
import { type Task } from "@/contexts/task-context";
import { type Task, useTask } from "@/contexts/task-context";
import {
formatApiComponent,
resolveTaskFileError,
Expand Down Expand Up @@ -43,10 +42,10 @@ export function TaskErrorContent({
defaultExpanded = false,
}: TaskErrorContentProps) {
const isCloudBrand = useIsCloudBrand();
const { openTaskDialog } = useTask();
const [accordionValue, setAccordionValue] = useState(
defaultExpanded ? "failed-files" : "",
);
const [isTaskDialogOpen, setIsTaskDialogOpen] = useState(false);
const isExpanded = accordionValue === "failed-files";

const failedEntries = useMemo(() => getFailedFileEntries(task), [task]);
Expand Down Expand Up @@ -90,7 +89,7 @@ export function TaskErrorContent({
type="button"
aria-label="Open task details"
className="inline-flex shrink-0 items-center justify-center text-muted-foreground hover:text-foreground"
onClick={() => setIsTaskDialogOpen(true)}
onClick={() => openTaskDialog(task.task_id)}
>
<IncidentReporterIcon className="size-4" />
</button>
Expand Down Expand Up @@ -237,13 +236,6 @@ export function TaskErrorContent({
</AccordionItem>
</Accordion>
</div>

<TaskDialog
open={isTaskDialogOpen}
onOpenChange={setIsTaskDialogOpen}
task_id={task.task_id}
onClose={() => setIsTaskDialogOpen(false)}
/>
</div>
);
}
14 changes: 12 additions & 2 deletions frontend/components/task-notification-menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
XCircle,
} from "lucide-react";
import { useEffect, useMemo, useRef, useState } from "react";
import { IncidentReporterIcon } from "@/components/icons/incident-reporter-icon";
import { TaskCollapsibleSection } from "@/components/task-collapsible-section";
import { TaskErrorContent } from "@/components/task-error-content";
import { TaskPanelHeader } from "@/components/task-panel-header";
Expand Down Expand Up @@ -43,6 +44,7 @@ export function TaskNotificationMenu() {
selectedTaskTrigger,
cancelTask,
closeMenu,
openTaskDialog,
} = useTask();
const [isPastOpen, setIsPastOpen] = useState(true);
const lastHandledSelectionTriggerRef = useRef(0);
Expand Down Expand Up @@ -361,8 +363,8 @@ export function TaskNotificationMenu() {
className="bg-card/50 border-0 shadow-none py-mmd px-4"
>
<CardHeader className="p-0 pb-2">
<div className="flex items-center justify-between">
<CardTitle className="text-sm flex items-center gap-2">
<div className="flex items-center justify-between gap-2">
<CardTitle className="text-sm flex min-w-0 flex-1 items-center gap-2">
{showTaskIcon &&
getTaskIcon(
task.status,
Expand All @@ -371,6 +373,14 @@ export function TaskNotificationMenu() {
)}
Task {task.task_id.substring(0, 8)}...
</CardTitle>
<button
type="button"
aria-label="Open task details"
className="inline-flex shrink-0 items-center justify-center text-muted-foreground hover:text-foreground"
onClick={() => openTaskDialog(task.task_id)}
>
<IncidentReporterIcon className="size-4" />
</button>
</div>
<CardDescription className="text-xs">
Started {formatRelativeTime(task.created_at)}
Expand Down
38 changes: 37 additions & 1 deletion frontend/contexts/task-context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
useGetTasksQuery,
} from "@/app/api/queries/useGetTasksQuery";
import type { ListFilesResponse } from "@/app/api/queries/useListFiles";
import TaskDialog from "@/components/task-dialog";
import { useAuth } from "@/contexts/auth-context";
import { useOnboardingState } from "@/hooks/use-onboarding-state";
import { trackProcessFailure, trackProcessSuccess } from "@/lib/analytics";
Expand Down Expand Up @@ -74,6 +75,10 @@ interface TaskContextType {
setSelectedTaskId: (taskId: string | null) => void;
selectedTaskTrigger: number;
selectTask: (taskId: string | null) => void;
isTaskDialogOpen: boolean;
taskDialogTaskId: string | null;
openTaskDialog: (taskId: string) => void;
closeTaskDialog: () => void;
// React Query states
isLoading: boolean;
error: Error | null;
Expand All @@ -87,7 +92,17 @@ export function TaskProvider({ children }: { children: React.ReactNode }) {
const [isRecentTasksExpanded, setIsRecentTasksExpanded] = useState(false);
const [selectedTaskId, setSelectedTaskId] = useState<string | null>(null);
const [selectedTaskTrigger, setSelectedTaskTrigger] = useState(0);
const [taskDialogTaskId, setTaskDialogTaskId] = useState<string | null>(null);
const [isTaskDialogOpen, setIsTaskDialogOpen] = useState(false);
const previousTasksRef = useRef<Task[]>([]);
const openTaskDialog = useCallback((taskId: string) => {
setTaskDialogTaskId(taskId);
setIsTaskDialogOpen(true);
}, []);
const closeTaskDialog = useCallback(() => {
setIsTaskDialogOpen(false);
setTaskDialogTaskId(null);
}, []);
const selectTask = useCallback((taskId: string | null) => {
setSelectedTaskId(taskId);
if (taskId) {
Expand Down Expand Up @@ -636,11 +651,32 @@ export function TaskProvider({ children }: { children: React.ReactNode }) {
setSelectedTaskId,
selectedTaskTrigger,
selectTask,
isTaskDialogOpen,
taskDialogTaskId,
openTaskDialog,
closeTaskDialog,
isLoading,
error,
};

return <TaskContext.Provider value={value}>{children}</TaskContext.Provider>;
return (
<TaskContext.Provider value={value}>
{children}
{taskDialogTaskId ? (
<TaskDialog
open={isTaskDialogOpen}
onOpenChange={(open) => {
setIsTaskDialogOpen(open);
if (!open) {
setTaskDialogTaskId(null);
}
}}
task_id={taskDialogTaskId}
onClose={closeTaskDialog}
/>
) : null}
</TaskContext.Provider>
);
}

export function useTask() {
Expand Down
Loading