fix(webapp): update task filter icons and the scheduled run icon (#4065)
## Summary Fixes the Tasks icon on the Runs, Logs, Errors, and metrics pages (and the task-derived queue indicators) to use the correct "T" tasks icon, and shows a clock icon for scheduled runs in the run inspector header. ## Before <img width="1440" height="704" alt="CleanShot 2026-06-28 at 21 39 57@2x" src="https://github.com/user-attachments/assets/d00d5cbf-4726-4695-825b-59f5bdd84529" /> ## After <img width="1370" height="604" alt="CleanShot 2026-06-28 at 21 38 59@2x" src="https://github.com/user-attachments/assets/fb709073-0b9f-409d-a852-72979bf14da6" />
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
---
|
||||
area: webapp
|
||||
type: fix
|
||||
---
|
||||
|
||||
Use the "all tasks" icon (`TasksIcon`) for the Tasks/Task type filter buttons on the Runs, Logs, Errors, and metrics dashboard pages (and the task-derived queue indicators), and show the clock icon for Scheduled runs in the run inspector header instead of the standard task icon.
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
} from "~/components/primitives/Select";
|
||||
import { useSearchParams } from "~/hooks/useSearchParam";
|
||||
import { TaskTriggerSourceIcon } from "~/components/runs/v3/TaskTriggerSource";
|
||||
import { TaskIcon } from "~/assets/icons/TaskIcon";
|
||||
import { TasksIcon } from "~/assets/icons/TasksIcon";
|
||||
import { appliedSummary, FilterMenuProvider } from "~/components/runs/v3/SharedFilters";
|
||||
import { AppliedFilter } from "~/components/primitives/AppliedFilter";
|
||||
|
||||
@@ -41,7 +41,7 @@ export function LogsTaskFilter({ possibleTasks }: LogsTaskFilterProps) {
|
||||
<TasksDropdown
|
||||
trigger={
|
||||
<SelectTrigger
|
||||
icon={<TaskIcon className="size-4" />}
|
||||
icon={<TasksIcon className="size-4" />}
|
||||
variant="secondary/small"
|
||||
shortcut={shortcut}
|
||||
tooltipTitle="Filter by task"
|
||||
@@ -67,7 +67,7 @@ export function LogsTaskFilter({ possibleTasks }: LogsTaskFilterProps) {
|
||||
<Ariakit.Select render={<div className="group cursor-pointer focus-custom" />}>
|
||||
<AppliedFilter
|
||||
label="Task"
|
||||
icon={<TaskIcon className="size-4" />}
|
||||
icon={<TasksIcon className="size-4" />}
|
||||
value={appliedSummary(
|
||||
selectedTasks.map((v) => {
|
||||
const task = possibleTasks.find((task) => task.slug === v);
|
||||
|
||||
@@ -3,7 +3,7 @@ import { RectangleStackIcon } from "@heroicons/react/20/solid";
|
||||
import { useFetcher } from "@remix-run/react";
|
||||
import { matchSorter } from "match-sorter";
|
||||
import { type ReactNode, useMemo } from "react";
|
||||
import { TaskIcon } from "~/assets/icons/TaskIcon";
|
||||
import { TasksIcon } from "~/assets/icons/TasksIcon";
|
||||
import { AppliedFilter } from "~/components/primitives/AppliedFilter";
|
||||
import {
|
||||
ComboBox,
|
||||
@@ -194,7 +194,7 @@ function QueuesDropdown({
|
||||
className="text-text-bright"
|
||||
icon={
|
||||
queue.type === "task" ? (
|
||||
<TaskIcon className="size-4 shrink-0 text-blue-500" />
|
||||
<TasksIcon className="size-4 shrink-0 text-blue-500" />
|
||||
) : (
|
||||
<RectangleStackIcon className="size-4 shrink-0 text-purple-500" />
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { TaskIconSmall } from "~/assets/icons/TaskIcon";
|
||||
import { TasksIcon } from "~/assets/icons/TasksIcon";
|
||||
import { SimpleTooltip } from "~/components/primitives/Tooltip";
|
||||
import { cn } from "~/utils/cn";
|
||||
import { RectangleStackIcon } from "@heroicons/react/20/solid";
|
||||
@@ -19,9 +19,7 @@ export function QueueName({
|
||||
{type === "task" ? (
|
||||
<SimpleTooltip
|
||||
button={
|
||||
<TaskIconSmall
|
||||
className={cn("size-[1.125rem] text-blue-500", paused && "opacity-50")}
|
||||
/>
|
||||
<TasksIcon className={cn("size-[1.125rem] text-blue-500", paused && "opacity-50")} />
|
||||
}
|
||||
content={`This queue was automatically created from your "${name}" task`}
|
||||
/>
|
||||
|
||||
@@ -22,7 +22,7 @@ import { ClockIcon } from "~/assets/icons/ClockIcon";
|
||||
import { ListCheckedIcon } from "~/assets/icons/ListCheckedIcon";
|
||||
import { MachineDefaultIcon } from "~/assets/icons/MachineIcon";
|
||||
import { StatusIcon } from "~/assets/icons/StatusIcon";
|
||||
import { TaskIcon } from "~/assets/icons/TaskIcon";
|
||||
import { TasksIcon } from "~/assets/icons/TasksIcon";
|
||||
import {
|
||||
formatMachinePresetName,
|
||||
MachineLabelCombo,
|
||||
@@ -259,7 +259,7 @@ export function filterIcon(filterKey: string): ReactNode | undefined {
|
||||
case "statuses":
|
||||
return <StatusIcon className="size-4 border-text-bright" />;
|
||||
case "tasks":
|
||||
return <TaskIcon className="size-4" />;
|
||||
return <TasksIcon className="size-4" />;
|
||||
case "tags":
|
||||
return <TagIcon className="size-4" />;
|
||||
case "bulkId":
|
||||
@@ -429,7 +429,7 @@ const filterTypes = [
|
||||
{ name: "schedule", title: "Schedule ID", icon: <ClockIcon className="size-4" /> },
|
||||
{ name: "bulk", title: "Bulk action", icon: <ListCheckedIcon className="size-4" /> },
|
||||
{ name: "error", title: "Error ID", icon: <BugIcon className="size-4" /> },
|
||||
{ name: "source", title: "Task type", icon: <TaskIcon className="size-4" /> },
|
||||
{ name: "source", title: "Task type", icon: <TasksIcon className="size-4" /> },
|
||||
] as const;
|
||||
|
||||
type FilterType = (typeof filterTypes)[number]["name"];
|
||||
@@ -1239,7 +1239,7 @@ function QueuesDropdown({
|
||||
value={queue.value}
|
||||
icon={
|
||||
queue.type === "task" ? (
|
||||
<TaskIcon className="size-4 shrink-0 text-blue-500" />
|
||||
<TasksIcon className="size-4 shrink-0 text-blue-500" />
|
||||
) : (
|
||||
<RectangleStackIcon className="size-4 shrink-0 text-purple-500" />
|
||||
)
|
||||
|
||||
@@ -10,7 +10,7 @@ import { BookOpenIcon, CheckIcon } from "@heroicons/react/24/solid";
|
||||
import { useLocation } from "@remix-run/react";
|
||||
import { formatDuration, formatDurationMilliseconds } from "@trigger.dev/core/v3";
|
||||
import { useCallback, useRef } from "react";
|
||||
import { TaskIconSmall } from "~/assets/icons/TaskIcon";
|
||||
import { TasksIcon } from "~/assets/icons/TasksIcon";
|
||||
import { MachineLabelCombo } from "~/components/MachineLabelCombo";
|
||||
import { MachineTooltipInfo } from "~/components/MachineTooltipInfo";
|
||||
import { Badge } from "~/components/primitives/Badge";
|
||||
@@ -470,7 +470,7 @@ export function TaskRunsTable({
|
||||
buttonClassName="w-fit"
|
||||
button={
|
||||
<span className="flex items-center gap-1">
|
||||
<TaskIconSmall className="size-[1.125rem] text-blue-500" />
|
||||
<TasksIcon className="size-[1.125rem] text-blue-500" />
|
||||
<span>{run.queue.name}</span>
|
||||
</span>
|
||||
}
|
||||
|
||||
@@ -297,6 +297,7 @@ export class SpanPresenter extends BasePresenter {
|
||||
|
||||
const taskKind = RunAnnotations.safeParse(run.annotations).data?.taskKind;
|
||||
const isAgentRun = taskKind === "AGENT";
|
||||
const isScheduled = taskKind === "SCHEDULED";
|
||||
|
||||
let region: { name: string; location: string | null } | null = null;
|
||||
|
||||
@@ -404,6 +405,7 @@ export class SpanPresenter extends BasePresenter {
|
||||
isRunning: RUNNING_STATUSES.includes(run.status),
|
||||
isError: isFailedRunStatus(run.status),
|
||||
isAgentRun,
|
||||
isScheduled,
|
||||
payload,
|
||||
payloadType: run.payloadType,
|
||||
output,
|
||||
|
||||
+13
-2
@@ -392,12 +392,23 @@ function RunBody({
|
||||
<div className="flex items-center justify-between gap-2 overflow-x-hidden px-3 pr-2">
|
||||
<div className="flex items-center gap-1 overflow-x-hidden">
|
||||
<RunIcon
|
||||
name={run.isAgentRun ? "agent" : run.isCached ? "task-cached" : "task"}
|
||||
name={
|
||||
run.isAgentRun
|
||||
? "agent"
|
||||
: run.isScheduled
|
||||
? "scheduled"
|
||||
: run.isCached
|
||||
? "task-cached"
|
||||
: "task"
|
||||
}
|
||||
spanName={run.taskIdentifier}
|
||||
className="size-5 min-h-5 min-w-5"
|
||||
/>
|
||||
<Header2
|
||||
className={cn("overflow-x-hidden", run.isAgentRun ? "text-agents" : "text-blue-500")}
|
||||
className={cn(
|
||||
"overflow-x-hidden",
|
||||
run.isAgentRun ? "text-agents" : run.isScheduled ? "text-schedules" : "text-blue-500"
|
||||
)}
|
||||
>
|
||||
<span className="truncate">
|
||||
{run.taskIdentifier}
|
||||
|
||||
@@ -72,6 +72,7 @@ export async function buildSyntheticSpanRun(args: {
|
||||
|
||||
const taskKind = RunAnnotations.safeParse(run.annotations).data?.taskKind;
|
||||
const isAgentRun = taskKind === "AGENT";
|
||||
const isScheduled = taskKind === "SCHEDULED";
|
||||
|
||||
const queueName = run.queue ?? "task/";
|
||||
const isCancelled = run.status === "CANCELED";
|
||||
@@ -149,6 +150,7 @@ export async function buildSyntheticSpanRun(args: {
|
||||
isRunning: false,
|
||||
isError: isFailed,
|
||||
isAgentRun,
|
||||
isScheduled,
|
||||
payload,
|
||||
payloadType: run.payloadType ?? "application/json",
|
||||
output: undefined,
|
||||
|
||||
Reference in New Issue
Block a user