@sentry/junior-dashboard 0.264.0 → 0.265.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +2 -5
- package/dist/app.js +119 -35
- package/dist/client.js +145 -136
- package/dist/index.d.ts +0 -1
- package/dist/index.js +119 -35
- package/dist/tailwind.css +1 -1
- package/package.json +5 -4
- package/src/api/schema.ts +0 -1
- package/src/app.ts +5 -20
- package/src/client/App.tsx +29 -31
- package/src/client/api.ts +7 -0
- package/src/client/components/BottomSheet.tsx +12 -2
- package/src/client/components/CopyButton.tsx +83 -0
- package/src/client/components/DetailsPanel.tsx +133 -0
- package/src/client/components/Drawer.tsx +15 -24
- package/src/client/components/FilterBar.tsx +16 -31
- package/src/client/components/Metric.tsx +33 -23
- package/src/client/components/PageContentSkeleton.tsx +1 -1
- package/src/client/components/Pagination.tsx +1 -1
- package/src/client/components/ParticipantAvatarStack.tsx +40 -36
- package/src/client/components/ProfileMenu.tsx +27 -93
- package/src/client/components/README.md +86 -77
- package/src/client/components/SegmentedNav.tsx +1 -1
- package/src/client/components/ShimmerText.tsx +2 -6
- package/src/client/components/ThemeSwitcher.tsx +19 -15
- package/src/client/components/charts/ActivityChart.tsx +173 -288
- package/src/client/components/charts/CacheWrites.tsx +63 -50
- package/src/client/components/charts/InputCacheChart.tsx +137 -131
- package/src/client/components/charts/README.md +4 -4
- package/src/client/components/charts/SystemMetricCharts.tsx +68 -95
- package/src/client/components/charts/WorkspaceUsageChart.tsx +42 -62
- package/src/client/components/controls/DirectorySortSelect.tsx +3 -3
- package/src/client/components/controls/TimeRangeSelector.tsx +10 -15
- package/src/client/components/layout/DashboardHeader.tsx +44 -90
- package/src/client/components/layout/SecondaryNavigation.tsx +2 -1
- package/src/client/components/layout/VisualViewportShell.tsx +2 -2
- package/src/client/components/ui/accordion.tsx +77 -0
- package/src/client/components/ui/alert-dialog.tsx +89 -0
- package/src/client/components/ui/button.tsx +85 -0
- package/src/client/components/ui/chart.tsx +74 -0
- package/src/client/components/ui/checkbox.tsx +26 -0
- package/src/client/components/ui/collapsible.tsx +22 -0
- package/src/client/components/ui/field.tsx +49 -0
- package/src/client/components/ui/input.tsx +35 -0
- package/src/client/components/ui/native-select.tsx +57 -0
- package/src/client/components/ui/popover.tsx +67 -0
- package/src/client/components/ui/radio-group.tsx +32 -0
- package/src/client/components/ui/sheet.tsx +13 -3
- package/src/client/components/ui/skeleton.tsx +19 -0
- package/src/client/components/ui/table.tsx +80 -0
- package/src/client/components/ui/tabs.tsx +75 -0
- package/src/client/components/ui/textarea.tsx +17 -0
- package/src/client/components/ui/toast.tsx +215 -0
- package/src/client/components/ui/toggle-group.tsx +36 -0
- package/src/client/components/ui/toggle.tsx +37 -0
- package/src/client/components/ui/tooltip.tsx +168 -0
- package/src/client/components/ui/trace.tsx +96 -0
- package/src/client/conversations/ChatLayout.tsx +7 -3
- package/src/client/conversations/ConversationBrief.tsx +17 -6
- package/src/client/conversations/ConversationComposer.tsx +26 -12
- package/src/client/conversations/ConversationDetails.tsx +147 -62
- package/src/client/conversations/ConversationEventDetails.tsx +141 -0
- package/src/client/conversations/ConversationEventLog.tsx +150 -129
- package/src/client/conversations/ConversationHeader.tsx +8 -3
- package/src/client/conversations/ConversationHeaderActions.tsx +90 -82
- package/src/client/conversations/ConversationHomeList.tsx +1 -1
- package/src/client/conversations/ConversationLinkedWork.tsx +118 -0
- package/src/client/conversations/ConversationMeta.tsx +55 -88
- package/src/client/conversations/ConversationPage.tsx +220 -101
- package/src/client/conversations/ConversationSidebar.tsx +48 -29
- package/src/client/conversations/ConversationWatches.tsx +165 -0
- package/src/client/conversations/ConversationWorkspace.tsx +12 -22
- package/src/client/conversations/ConversationWorkspaceLoading.tsx +1 -1
- package/src/client/conversations/DetailsList.tsx +124 -0
- package/src/client/conversations/EventDetails.tsx +42 -8
- package/src/client/conversations/ForkConversationButton.tsx +27 -16
- package/src/client/conversations/ObjectCard.tsx +20 -8
- package/src/client/conversations/PendingMailboxStack.tsx +52 -33
- package/src/client/conversations/README.md +86 -13
- package/src/client/conversations/ShareConversationButton.tsx +25 -13
- package/src/client/conversations/SubagentTranscriptDrawer.tsx +21 -15
- package/src/client/conversations/ToolFrame.tsx +36 -52
- package/src/client/conversations/TranscriptActivityGroup.tsx +13 -4
- package/src/client/conversations/TranscriptAutomationTriggerView.tsx +5 -4
- package/src/client/conversations/TranscriptContextEventView.tsx +25 -11
- package/src/client/conversations/TranscriptHeadingRow.tsx +7 -7
- package/src/client/conversations/TranscriptLoading.tsx +1 -1
- package/src/client/conversations/TranscriptMarkdown.tsx +25 -20
- package/src/client/conversations/TranscriptMessageContextView.tsx +8 -2
- package/src/client/conversations/TranscriptMessageView.tsx +6 -1
- package/src/client/conversations/TranscriptReasoningView.tsx +54 -68
- package/src/client/conversations/TranscriptTimestamp.tsx +9 -7
- package/src/client/conversations/TranscriptToolView.tsx +1 -1
- package/src/client/conversations/TranscriptTurnContextView.tsx +99 -27
- package/src/client/conversations/TranscriptView.tsx +63 -27
- package/src/client/conversations/eventLog.ts +57 -0
- package/src/client/conversations/eventTime.ts +60 -0
- package/src/client/conversations/queries.ts +29 -0
- package/src/client/conversations/transcriptBottomPinning.ts +34 -0
- package/src/client/format.ts +5 -0
- package/src/client/pages/ConnectionsPage.tsx +2 -2
- package/src/client/pages/PersonalTokensPage.tsx +4 -4
- package/src/client/pages/SettingsPage.tsx +9 -10
- package/src/client/pages/admin/ServiceAccountsSection.tsx +2 -2
- package/src/client/pages/automations/AutomationCostChart.tsx +50 -71
- package/src/client/pages/automations/AutomationDeleteDialog.tsx +87 -0
- package/src/client/pages/automations/AutomationDetails.tsx +193 -0
- package/src/client/pages/automations/AutomationEditPage.tsx +7 -8
- package/src/client/pages/automations/AutomationEditor.tsx +41 -29
- package/src/client/pages/automations/AutomationEditorLoading.tsx +1 -1
- package/src/client/pages/automations/AutomationEventFields.tsx +202 -119
- package/src/client/pages/automations/AutomationExecutionChart.tsx +51 -64
- package/src/client/pages/automations/AutomationExecutionStatusChart.tsx +47 -70
- package/src/client/pages/automations/AutomationExecutionsPage.tsx +150 -126
- package/src/client/pages/automations/AutomationFilters.tsx +189 -74
- package/src/client/pages/automations/AutomationLifecycle.tsx +109 -78
- package/src/client/pages/automations/AutomationOutcomeFields.tsx +26 -24
- package/src/client/pages/automations/AutomationRecentRuns.tsx +143 -0
- package/src/client/pages/automations/AutomationRow.tsx +12 -138
- package/src/client/pages/automations/AutomationRunDetails.tsx +307 -0
- package/src/client/pages/automations/AutomationRunsPage.tsx +119 -94
- package/src/client/pages/automations/AutomationScheduleFields.tsx +51 -51
- package/src/client/pages/automations/AutomationStatus.tsx +201 -0
- package/src/client/pages/automations/AutomationVersionsPage.tsx +65 -28
- package/src/client/pages/automations/AutomationsPage.tsx +80 -68
- package/src/client/pages/automations/AutomationsPageLayout.tsx +46 -14
- package/src/client/pages/automations/README.md +57 -0
- package/src/client/pages/automations/TriggerFilters.tsx +22 -0
- package/src/client/pages/automations/automationFormat.ts +37 -23
- package/src/client/pages/code/CodeActivityChart.tsx +59 -101
- package/src/client/pages/code/CodePage.tsx +52 -55
- package/src/client/pages/code/RepositoryPage.tsx +6 -8
- package/src/client/pages/locations/LocationActivityChart.tsx +53 -70
- package/src/client/pages/locations/LocationDirectoryActivityChart.tsx +60 -80
- package/src/client/pages/memory/MemoryCostChart.tsx +79 -103
- package/src/client/pages/memory/MemoryDetails.tsx +218 -0
- package/src/client/pages/memory/MemoryPage.tsx +168 -112
- package/src/client/pages/memory/MemoryPageLayout.tsx +33 -9
- package/src/client/pages/memory/MemoryTimeline.tsx +46 -69
- package/src/client/pages/memory/memoryRecord.ts +1 -1
- package/src/client/pages/people/ContributionGrid.tsx +23 -16
- package/src/client/pages/people/PeopleActivityChart.tsx +68 -107
- package/src/client/pages/people/ProfileCodeChanges.tsx +5 -5
- package/src/client/pages/system/BaseSandboxCard.tsx +1 -1
- package/src/client/pages/system/ConversationActivityChart.tsx +49 -67
- package/src/client/pages/system/GuardianActivity.tsx +1 -2
- package/src/client/pages/system/PluginBarChart.tsx +106 -87
- package/src/client/pages/system/PluginReportRecordSet.tsx +25 -24
- package/src/client/pages/system/README.md +23 -0
- package/src/client/pages/system/SystemNavigation.tsx +5 -1
- package/src/client/pages/system/WorkspaceDeleteDialog.tsx +111 -0
- package/src/client/pages/system/WorkspaceDetails.tsx +200 -43
- package/src/client/pages/system/WorkspaceEditor.tsx +59 -61
- package/src/client/pages/system/WorkspaceFormPage.tsx +23 -47
- package/src/client/pages/system/WorkspaceList.tsx +20 -30
- package/src/client/pages/system/WorkspacesPage.tsx +117 -119
- package/src/client/pages/system/sandboxSize.ts +8 -0
- package/src/client/pages/system/workspaceQueries.ts +53 -0
- package/src/client/pages/user/PluginUserPage.tsx +51 -2
- package/src/client/pages/user/pluginUserPageData.ts +1 -6
- package/src/client/styles.ts +4 -0
- package/src/client.tsx +7 -1
- package/src/mock-reporting/automation-collection.ts +4 -2
- package/src/mock-reporting/fixtures.ts +23 -7
- package/src/mock-reporting/routes.ts +12 -0
- package/src/mock-reporting/watches.ts +94 -0
- package/src/shell.ts +4 -9
- package/src/tailwind.css +0 -10
- package/src/client/components/Button.tsx +0 -118
- package/src/client/components/Field.tsx +0 -53
- package/src/client/components/SegmentedTabs.tsx +0 -119
- package/src/client/components/Select.tsx +0 -52
- package/src/client/components/Skeleton.tsx +0 -17
- package/src/client/components/TextInput.tsx +0 -58
- package/src/client/components/Tooltip.tsx +0 -216
- package/src/client/components/charts/useChartLayout.ts +0 -27
- package/src/client/components/ui/sheet.LICENSE +0 -21
- package/src/client/conversations/ConversationDetailsFrame.tsx +0 -119
- package/src/client/conversations/CopyMarkdownButton.tsx +0 -65
- package/src/client/pages/automations/AutomationDetailsDrawer.tsx +0 -219
- package/src/client/pages/dev/ChartFixtures.tsx +0 -325
- package/src/client/pages/dev/ComponentsPage.tsx +0 -899
- package/src/client/pages/dev/ConversationFixture.tsx +0 -231
- package/src/client/pages/dev/ObjectFixtures.tsx +0 -138
- package/src/client/pages/dev/SegmentedFixtures.tsx +0 -59
- package/src/client/pages/dev/SelectFixtures.tsx +0 -62
- package/src/client/pages/dev/TranscriptActivityFixtures.tsx +0 -206
- package/src/client/pages/memory/MemoryDetailsDrawer.tsx +0 -167
- package/src/client/pages/system/SandboxSizeSummary.tsx +0 -47
- package/src/client/pages/system/SnapshotSummary.tsx +0 -78
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { useEffect, useMemo, useState } from "react";
|
|
2
2
|
import { CalendarClock, Zap } from "lucide-react";
|
|
3
|
-
import { useNavigate } from "react-router";
|
|
4
3
|
import type { AutomationRun } from "@sentry/junior/api/schema";
|
|
5
4
|
|
|
6
5
|
import { useAutomationRunsData } from "../../api";
|
|
7
|
-
import { ToggleButton } from "../../components/Button";
|
|
8
6
|
import { FilterBar, FilterGroup } from "../../components/FilterBar";
|
|
9
7
|
import { InlineError } from "../../components/InlineError";
|
|
10
8
|
import { PageContentSkeleton } from "../../components/PageContentSkeleton";
|
|
@@ -13,22 +11,32 @@ import {
|
|
|
13
11
|
pageItems,
|
|
14
12
|
PagePagination,
|
|
15
13
|
} from "../../components/Pagination";
|
|
16
|
-
import
|
|
14
|
+
import { SelectableRow } from "../../components/SelectableRow";
|
|
17
15
|
import { StatusDot } from "../../components/StatusDot";
|
|
16
|
+
import { ToggleGroup, ToggleGroupItem } from "../../components/ui/toggle-group";
|
|
18
17
|
import { Card } from "../../components/layout/Card";
|
|
19
18
|
import { PageHeader } from "../../components/layout/PageHeader";
|
|
20
|
-
import { conversationPath } from "../../conversations/conversationRoutes";
|
|
21
19
|
import {
|
|
22
20
|
formatCompactNumber,
|
|
23
21
|
formatCostSummary,
|
|
24
22
|
formatRuntime,
|
|
25
|
-
formatTime,
|
|
26
23
|
} from "../../format";
|
|
27
24
|
import {
|
|
28
25
|
useDebouncedSearchParam,
|
|
29
26
|
useSearchParamEnum,
|
|
30
27
|
} from "../../searchParams";
|
|
31
28
|
import { cn } from "../../styles";
|
|
29
|
+
import {
|
|
30
|
+
AutomationRunDetails,
|
|
31
|
+
AutomationRunsFrame,
|
|
32
|
+
RunConversationLink,
|
|
33
|
+
useAutomationRunSelection,
|
|
34
|
+
} from "./AutomationRunDetails";
|
|
35
|
+
import {
|
|
36
|
+
automationRunStatusTone,
|
|
37
|
+
automationRunTitle,
|
|
38
|
+
formatAutomationRunTime,
|
|
39
|
+
} from "./automationFormat";
|
|
32
40
|
|
|
33
41
|
const RUN_PAGE_SIZE = 25;
|
|
34
42
|
const RUN_KINDS = ["all", "scheduled", "event"] as const;
|
|
@@ -36,7 +44,7 @@ const RUN_STATUSES = ["all", "completed", "failed", "blocked"] as const;
|
|
|
36
44
|
const EMPTY_RUNS: AutomationRun[] = [];
|
|
37
45
|
/** Leading label columns flex; metric columns stay equal fixed widths. */
|
|
38
46
|
const RUN_GRID =
|
|
39
|
-
"grid-cols-[minmax(0,1.4fr)_minmax(0,1.2fr)_5.5rem_5.5rem_5.
|
|
47
|
+
"grid-cols-[minmax(0,1.4fr)_minmax(0,1.2fr)_5.5rem_5.5rem_5.5rem_2rem]";
|
|
40
48
|
|
|
41
49
|
type RunKindFilter = (typeof RUN_KINDS)[number];
|
|
42
50
|
type RunStatusFilter = (typeof RUN_STATUSES)[number];
|
|
@@ -85,9 +93,29 @@ export function AutomationRunsPage(props: { enabled: boolean }) {
|
|
|
85
93
|
}, [page, totalPages]);
|
|
86
94
|
|
|
87
95
|
const loading = !query.data && !query.error;
|
|
96
|
+
const selection = useAutomationRunSelection(
|
|
97
|
+
pagedRuns.map((run) => run.executionId),
|
|
98
|
+
);
|
|
99
|
+
const selectedRun = selection.runId
|
|
100
|
+
? runs.find((run) => run.executionId === selection.runId)
|
|
101
|
+
: undefined;
|
|
88
102
|
|
|
89
103
|
return (
|
|
90
|
-
|
|
104
|
+
<AutomationRunsFrame
|
|
105
|
+
details={
|
|
106
|
+
selection.runId ? (
|
|
107
|
+
<AutomationRunDetails
|
|
108
|
+
key={selection.runId}
|
|
109
|
+
loading={loading}
|
|
110
|
+
onClose={selection.close}
|
|
111
|
+
run={selectedRun}
|
|
112
|
+
showAutomation
|
|
113
|
+
/>
|
|
114
|
+
) : null
|
|
115
|
+
}
|
|
116
|
+
label="Runs list"
|
|
117
|
+
listRef={selection.listRef}
|
|
118
|
+
>
|
|
91
119
|
<PageHeader
|
|
92
120
|
description="Newest runs across your automations and automations in public destinations."
|
|
93
121
|
title="Runs"
|
|
@@ -105,28 +133,34 @@ export function AutomationRunsPage(props: { enabled: boolean }) {
|
|
|
105
133
|
}}
|
|
106
134
|
>
|
|
107
135
|
<FilterGroup label="Type">
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
136
|
+
<ToggleGroup
|
|
137
|
+
className="flex-wrap gap-2"
|
|
138
|
+
onValueChange={([next]) => {
|
|
139
|
+
if (next) setKind(next);
|
|
140
|
+
}}
|
|
141
|
+
value={[kind]}
|
|
142
|
+
>
|
|
143
|
+
{RUN_KINDS.map((value) => (
|
|
144
|
+
<ToggleGroupItem key={value} value={value} variant="pill">
|
|
145
|
+
{value}
|
|
146
|
+
</ToggleGroupItem>
|
|
147
|
+
))}
|
|
148
|
+
</ToggleGroup>
|
|
118
149
|
</FilterGroup>
|
|
119
150
|
<FilterGroup label="Status">
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
151
|
+
<ToggleGroup
|
|
152
|
+
className="flex-wrap gap-2"
|
|
153
|
+
onValueChange={([next]) => {
|
|
154
|
+
if (next) setStatus(next);
|
|
155
|
+
}}
|
|
156
|
+
value={[status]}
|
|
157
|
+
>
|
|
158
|
+
{RUN_STATUSES.map((value) => (
|
|
159
|
+
<ToggleGroupItem key={value} value={value} variant="pill">
|
|
160
|
+
{value}
|
|
161
|
+
</ToggleGroupItem>
|
|
162
|
+
))}
|
|
163
|
+
</ToggleGroup>
|
|
130
164
|
</FilterGroup>
|
|
131
165
|
</FilterBar>
|
|
132
166
|
<div className="flex flex-wrap items-baseline justify-between gap-x-5 gap-y-1 border-b border-dashboard-border-subtle pb-3">
|
|
@@ -155,11 +189,11 @@ export function AutomationRunsPage(props: { enabled: boolean }) {
|
|
|
155
189
|
<div className="min-w-0 overflow-x-auto">
|
|
156
190
|
<div className="min-w-[44rem]">
|
|
157
191
|
<div
|
|
192
|
+
aria-hidden="true"
|
|
158
193
|
className={cn(
|
|
159
194
|
"sticky top-0 z-[1] hidden items-center gap-4 border-b border-dashboard-border-subtle bg-dashboard-overlay-soft px-4 py-2.5 font-sans font-medium text-xs text-dashboard-text-muted md:grid",
|
|
160
195
|
RUN_GRID,
|
|
161
196
|
)}
|
|
162
|
-
role="row"
|
|
163
197
|
>
|
|
164
198
|
<div>Run</div>
|
|
165
199
|
<div>Automation</div>
|
|
@@ -167,11 +201,17 @@ export function AutomationRunsPage(props: { enabled: boolean }) {
|
|
|
167
201
|
<div>Tokens</div>
|
|
168
202
|
<div>Cost</div>
|
|
169
203
|
</div>
|
|
170
|
-
<div
|
|
204
|
+
<div
|
|
205
|
+
className="min-w-0"
|
|
206
|
+
onKeyDown={selection.onRowsKeyDown}
|
|
207
|
+
role="list"
|
|
208
|
+
>
|
|
171
209
|
{pagedRuns.map((run) => (
|
|
172
210
|
<AutomationRunRow
|
|
173
211
|
key={`${run.kind}:${run.executionId}`}
|
|
212
|
+
onSelect={() => selection.toggle(run.executionId)}
|
|
174
213
|
run={run}
|
|
214
|
+
selected={selection.runId === run.executionId}
|
|
175
215
|
/>
|
|
176
216
|
))}
|
|
177
217
|
</div>
|
|
@@ -193,7 +233,7 @@ export function AutomationRunsPage(props: { enabled: boolean }) {
|
|
|
193
233
|
) : null}
|
|
194
234
|
</>
|
|
195
235
|
)}
|
|
196
|
-
|
|
236
|
+
</AutomationRunsFrame>
|
|
197
237
|
);
|
|
198
238
|
}
|
|
199
239
|
|
|
@@ -208,12 +248,12 @@ function emptyRunsText(input: {
|
|
|
208
248
|
return "No visible automations have run yet.";
|
|
209
249
|
}
|
|
210
250
|
|
|
211
|
-
function AutomationRunRow(props: {
|
|
251
|
+
function AutomationRunRow(props: {
|
|
252
|
+
onSelect(): void;
|
|
253
|
+
run: AutomationRun;
|
|
254
|
+
selected: boolean;
|
|
255
|
+
}) {
|
|
212
256
|
const { run } = props;
|
|
213
|
-
const navigate = useNavigate();
|
|
214
|
-
const title =
|
|
215
|
-
run.title?.trim() ||
|
|
216
|
-
(run.conversationId ? run.automationTitle : "No conversation");
|
|
217
257
|
const costLabel =
|
|
218
258
|
formatCostSummary(
|
|
219
259
|
run.costUsd === undefined ? undefined : { total: run.costUsd },
|
|
@@ -221,54 +261,56 @@ function AutomationRunRow(props: { run: AutomationRun }) {
|
|
|
221
261
|
const durationLabel = formatRuntime(run.durationMs) || "—";
|
|
222
262
|
const tokensLabel =
|
|
223
263
|
run.totalTokens === undefined ? "—" : formatCompactNumber(run.totalTokens);
|
|
224
|
-
const openConversation = () => {
|
|
225
|
-
if (run.conversationId) navigate(conversationPath(run.conversationId));
|
|
226
|
-
};
|
|
227
264
|
|
|
228
265
|
return (
|
|
229
266
|
<div
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
RUN_GRID,
|
|
234
|
-
run.conversationId
|
|
235
|
-
? "cursor-pointer hover:bg-dashboard-fill-soft"
|
|
236
|
-
: "cursor-default opacity-80",
|
|
237
|
-
)}
|
|
238
|
-
onClick={openConversation}
|
|
239
|
-
onKeyDown={(event) => {
|
|
240
|
-
if (!run.conversationId) return;
|
|
241
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
242
|
-
event.preventDefault();
|
|
243
|
-
openConversation();
|
|
244
|
-
}
|
|
245
|
-
}}
|
|
246
|
-
role={run.conversationId ? "link" : "row"}
|
|
247
|
-
tabIndex={run.conversationId ? 0 : undefined}
|
|
267
|
+
className="border-b border-dashboard-border-subtle last:border-b-0"
|
|
268
|
+
data-run-id={run.executionId}
|
|
269
|
+
role="listitem"
|
|
248
270
|
>
|
|
249
|
-
<
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
<
|
|
264
|
-
|
|
265
|
-
|
|
271
|
+
<SelectableRow
|
|
272
|
+
className={cn(
|
|
273
|
+
"grid min-w-0 items-center gap-4 overflow-hidden px-4 py-3 max-md:grid-cols-1 max-md:gap-y-2 max-md:py-3.5",
|
|
274
|
+
RUN_GRID,
|
|
275
|
+
)}
|
|
276
|
+
onSelect={props.onSelect}
|
|
277
|
+
selected={props.selected}
|
|
278
|
+
>
|
|
279
|
+
<button
|
|
280
|
+
aria-expanded={props.selected}
|
|
281
|
+
className="block min-w-0 cursor-pointer rounded-md border-0 bg-transparent p-0 text-left focus-visible:outline focus-visible:outline-2 focus-visible:outline-dashboard-focus"
|
|
282
|
+
onClick={props.onSelect}
|
|
283
|
+
type="button"
|
|
284
|
+
>
|
|
285
|
+
<span className="block truncate text-sm font-medium leading-snug text-dashboard-text">
|
|
286
|
+
{automationRunTitle(run, run.automationTitle)}
|
|
287
|
+
</span>
|
|
288
|
+
<span className="mt-1 block truncate text-xs text-dashboard-text-muted">
|
|
289
|
+
{formatAutomationRunTime(run.executedAt)}
|
|
266
290
|
</span>
|
|
291
|
+
</button>
|
|
292
|
+
<div className="min-w-0 overflow-hidden">
|
|
293
|
+
<div className="truncate text-sm text-dashboard-text">
|
|
294
|
+
{run.automationTitle}
|
|
295
|
+
</div>
|
|
296
|
+
<div className="mt-1 flex min-w-0 items-center gap-1.5 overflow-hidden text-dashboard-text-muted">
|
|
297
|
+
<AutomationKindIcon kind={run.kind} />
|
|
298
|
+
<StatusDot
|
|
299
|
+
label={run.status}
|
|
300
|
+
tone={automationRunStatusTone(run.status)}
|
|
301
|
+
/>
|
|
302
|
+
<span className="truncate text-xs text-dashboard-text-muted">
|
|
303
|
+
{run.status}
|
|
304
|
+
</span>
|
|
305
|
+
</div>
|
|
267
306
|
</div>
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
307
|
+
<MetricCell label="Duration" value={durationLabel} />
|
|
308
|
+
<MetricCell label="Tokens" value={tokensLabel} />
|
|
309
|
+
<MetricCell label="Cost" value={costLabel} />
|
|
310
|
+
<div className="max-md:hidden">
|
|
311
|
+
<RunConversationLink conversationId={run.conversationId} />
|
|
312
|
+
</div>
|
|
313
|
+
</SelectableRow>
|
|
272
314
|
</div>
|
|
273
315
|
);
|
|
274
316
|
}
|
|
@@ -305,20 +347,3 @@ function AutomationKindIcon(props: { kind: AutomationRun["kind"] }) {
|
|
|
305
347
|
</span>
|
|
306
348
|
);
|
|
307
349
|
}
|
|
308
|
-
|
|
309
|
-
function runStatusTone(status: AutomationRun["status"]): StatusChipTone {
|
|
310
|
-
if (status === "failed") return "danger";
|
|
311
|
-
if (status === "blocked") return "warning";
|
|
312
|
-
return "success";
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
function formatRunDate(value: string): string {
|
|
316
|
-
return formatTime(value, {
|
|
317
|
-
day: "numeric",
|
|
318
|
-
hour: "numeric",
|
|
319
|
-
minute: "2-digit",
|
|
320
|
-
month: "short",
|
|
321
|
-
timeZoneName: "short",
|
|
322
|
-
year: "numeric",
|
|
323
|
-
});
|
|
324
|
-
}
|
|
@@ -6,12 +6,12 @@ import {
|
|
|
6
6
|
automationSchedulePreviewSchema,
|
|
7
7
|
type AutomationEdit,
|
|
8
8
|
} from "@sentry/junior/api/schema";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
9
|
+
import { Button } from "../../components/ui/button";
|
|
10
|
+
import { Input } from "../../components/ui/input";
|
|
11
|
+
import { Field, FieldDescription, FieldLabel } from "../../components/ui/field";
|
|
12
|
+
import { NativeSelect } from "../../components/ui/native-select";
|
|
13
|
+
import { ToggleGroup, ToggleGroupItem } from "../../components/ui/toggle-group";
|
|
13
14
|
import { post, DashboardApiError } from "../../http";
|
|
14
|
-
import { cn } from "../../styles";
|
|
15
15
|
import {
|
|
16
16
|
scheduleDraft,
|
|
17
17
|
weekdays,
|
|
@@ -64,8 +64,9 @@ export function AutomationScheduleFields(props: {
|
|
|
64
64
|
return (
|
|
65
65
|
<>
|
|
66
66
|
<div className="grid grid-cols-1 items-start gap-4 sm:grid-cols-2">
|
|
67
|
-
<Field
|
|
68
|
-
<
|
|
67
|
+
<Field>
|
|
68
|
+
<FieldLabel htmlFor="schedule-frequency">Repeat</FieldLabel>
|
|
69
|
+
<NativeSelect
|
|
69
70
|
id="schedule-frequency"
|
|
70
71
|
value={frequency}
|
|
71
72
|
onChange={(e) => {
|
|
@@ -106,10 +107,11 @@ export function AutomationScheduleFields(props: {
|
|
|
106
107
|
<option value="weekly">Every week</option>
|
|
107
108
|
<option value="monthly">Every month</option>
|
|
108
109
|
<option value="yearly">Every year</option>
|
|
109
|
-
</
|
|
110
|
+
</NativeSelect>
|
|
110
111
|
</Field>
|
|
111
|
-
<Field
|
|
112
|
-
<
|
|
112
|
+
<Field>
|
|
113
|
+
<FieldLabel htmlFor="schedule-time">Time</FieldLabel>
|
|
114
|
+
<Input
|
|
113
115
|
size="comfortable"
|
|
114
116
|
id="schedule-time"
|
|
115
117
|
type="time"
|
|
@@ -136,41 +138,31 @@ export function AutomationScheduleFields(props: {
|
|
|
136
138
|
{value.frequency === "weekly" ? (
|
|
137
139
|
<fieldset>
|
|
138
140
|
<legend className="mb-2 text-sm font-semibold">On</legend>
|
|
139
|
-
<
|
|
141
|
+
<ToggleGroup
|
|
142
|
+
className="grid grid-cols-7 gap-1.5"
|
|
143
|
+
multiple
|
|
144
|
+
onValueChange={(next) =>
|
|
145
|
+
props.onChange({ ...value, weekdays: next })
|
|
146
|
+
}
|
|
147
|
+
value={value.weekdays ?? []}
|
|
148
|
+
>
|
|
140
149
|
{[...weekdays.slice(1), weekdays[0]].map((day) => (
|
|
141
|
-
<
|
|
142
|
-
type="button"
|
|
150
|
+
<ToggleGroupItem
|
|
143
151
|
key={day}
|
|
144
152
|
aria-label={day}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
props.onChange({
|
|
148
|
-
...value,
|
|
149
|
-
weekdays: value.weekdays?.includes(day)
|
|
150
|
-
? value.weekdays.filter((d) => d !== day)
|
|
151
|
-
: [...(value.weekdays ?? []), day],
|
|
152
|
-
})
|
|
153
|
-
}
|
|
154
|
-
className={cn(
|
|
155
|
-
"min-h-11 cursor-pointer rounded-md border px-1 text-xs font-medium capitalize focus-visible:outline-2 focus-visible:outline-dashboard-focus sm:min-h-10 sm:text-sm",
|
|
156
|
-
value.weekdays?.includes(day)
|
|
157
|
-
? "border-dashboard-focus/50 bg-dashboard-focus/10 text-dashboard-focus"
|
|
158
|
-
: "border-dashboard-border-emphasis text-dashboard-text-muted hover:bg-dashboard-fill-hover",
|
|
159
|
-
)}
|
|
153
|
+
className="h-auto min-h-11 min-w-0 border-dashboard-border-emphasis px-1 capitalize data-pressed:border-dashboard-focus/50 data-pressed:bg-dashboard-focus/10 data-pressed:text-dashboard-focus sm:min-h-10 sm:text-sm"
|
|
154
|
+
value={day}
|
|
160
155
|
>
|
|
161
156
|
{day.slice(0, 3)}
|
|
162
|
-
</
|
|
157
|
+
</ToggleGroupItem>
|
|
163
158
|
))}
|
|
164
|
-
</
|
|
159
|
+
</ToggleGroup>
|
|
165
160
|
</fieldset>
|
|
166
161
|
) : null}
|
|
167
162
|
<div className="grid grid-cols-1 items-start gap-4 sm:grid-cols-2">
|
|
168
|
-
<Field
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
help="Number of calendar periods between runs."
|
|
172
|
-
>
|
|
173
|
-
<TextInput
|
|
163
|
+
<Field>
|
|
164
|
+
<FieldLabel htmlFor="schedule-interval">Interval</FieldLabel>
|
|
165
|
+
<Input
|
|
174
166
|
size="comfortable"
|
|
175
167
|
id="schedule-interval"
|
|
176
168
|
type="number"
|
|
@@ -181,9 +173,13 @@ export function AutomationScheduleFields(props: {
|
|
|
181
173
|
props.onChange({ ...value, interval: e.target.valueAsNumber })
|
|
182
174
|
}
|
|
183
175
|
/>
|
|
176
|
+
<FieldDescription id="schedule-interval-help">
|
|
177
|
+
Number of calendar periods between runs.
|
|
178
|
+
</FieldDescription>
|
|
184
179
|
</Field>
|
|
185
|
-
<Field
|
|
186
|
-
<
|
|
180
|
+
<Field>
|
|
181
|
+
<FieldLabel htmlFor="schedule-start">Start date</FieldLabel>
|
|
182
|
+
<Input
|
|
187
183
|
size="comfortable"
|
|
188
184
|
id="schedule-start"
|
|
189
185
|
type="date"
|
|
@@ -199,8 +195,9 @@ export function AutomationScheduleFields(props: {
|
|
|
199
195
|
</div>
|
|
200
196
|
{value.frequency === "monthly" || value.frequency === "yearly" ? (
|
|
201
197
|
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
|
|
202
|
-
<Field
|
|
203
|
-
<
|
|
198
|
+
<Field>
|
|
199
|
+
<FieldLabel htmlFor="schedule-day">Day of month</FieldLabel>
|
|
200
|
+
<Input
|
|
204
201
|
size="comfortable"
|
|
205
202
|
id="schedule-day"
|
|
206
203
|
type="number"
|
|
@@ -216,8 +213,9 @@ export function AutomationScheduleFields(props: {
|
|
|
216
213
|
/>
|
|
217
214
|
</Field>
|
|
218
215
|
{value.frequency === "yearly" ? (
|
|
219
|
-
<Field
|
|
220
|
-
<
|
|
216
|
+
<Field>
|
|
217
|
+
<FieldLabel htmlFor="schedule-month">Month</FieldLabel>
|
|
218
|
+
<NativeSelect
|
|
221
219
|
id="schedule-month"
|
|
222
220
|
value={value.month ?? 1}
|
|
223
221
|
onChange={(e) =>
|
|
@@ -235,15 +233,16 @@ export function AutomationScheduleFields(props: {
|
|
|
235
233
|
}).format(new Date(Date.UTC(2026, index, 1)))}
|
|
236
234
|
</option>
|
|
237
235
|
))}
|
|
238
|
-
</
|
|
236
|
+
</NativeSelect>
|
|
239
237
|
</Field>
|
|
240
238
|
) : null}
|
|
241
239
|
</div>
|
|
242
240
|
) : null}
|
|
243
241
|
</>
|
|
244
242
|
) : (
|
|
245
|
-
<Field
|
|
246
|
-
<
|
|
243
|
+
<Field>
|
|
244
|
+
<FieldLabel htmlFor="schedule-date">Date</FieldLabel>
|
|
245
|
+
<Input
|
|
247
246
|
size="comfortable"
|
|
248
247
|
id="schedule-date"
|
|
249
248
|
type="date"
|
|
@@ -257,12 +256,9 @@ export function AutomationScheduleFields(props: {
|
|
|
257
256
|
/>
|
|
258
257
|
</Field>
|
|
259
258
|
)}
|
|
260
|
-
<Field
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
help="Use an IANA timezone. The schedule follows local time, including daylight saving time."
|
|
264
|
-
>
|
|
265
|
-
<TextInput
|
|
259
|
+
<Field>
|
|
260
|
+
<FieldLabel htmlFor="schedule-timezone">Timezone</FieldLabel>
|
|
261
|
+
<Input
|
|
266
262
|
size="comfortable"
|
|
267
263
|
id="schedule-timezone"
|
|
268
264
|
list="automation-timezones"
|
|
@@ -276,6 +272,10 @@ export function AutomationScheduleFields(props: {
|
|
|
276
272
|
<option key={zone}>{zone}</option>
|
|
277
273
|
))}
|
|
278
274
|
</datalist>
|
|
275
|
+
<FieldDescription id="schedule-timezone-help">
|
|
276
|
+
Use an IANA timezone. The schedule follows local time, including
|
|
277
|
+
daylight saving time.
|
|
278
|
+
</FieldDescription>
|
|
279
279
|
</Field>
|
|
280
280
|
<div
|
|
281
281
|
role="status"
|