@workflow/web-shared 5.0.0-beta.1 → 5.0.0-beta.10
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/README.md +1 -1
- package/dist/components/error-boundary.js +1 -1
- package/dist/components/event-list-view.d.ts +18 -1
- package/dist/components/event-list-view.d.ts.map +1 -1
- package/dist/components/event-list-view.js +219 -125
- package/dist/components/hook-actions.js +1 -1
- package/dist/components/index.d.ts +4 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +5 -2
- package/dist/components/new-trace-viewer/components/copy-button.d.ts +9 -0
- package/dist/components/new-trace-viewer/components/copy-button.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/copy-button.js +27 -0
- package/dist/components/new-trace-viewer/components/event-list.d.ts +10 -0
- package/dist/components/new-trace-viewer/components/event-list.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/event-list.js +39 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.d.ts +18 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/copy-selection.js +54 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.d.ts +20 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/middle-truncate.js +81 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/truncate.d.ts +25 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/truncate.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/truncate.js +101 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.d.ts +20 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.js +114 -0
- package/dist/components/new-trace-viewer/components/split-pane.d.ts +14 -0
- package/dist/components/new-trace-viewer/components/split-pane.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/split-pane.js +99 -0
- package/dist/components/new-trace-viewer/components/timeline.d.ts +34 -0
- package/dist/components/new-trace-viewer/components/timeline.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/timeline.js +223 -0
- package/dist/components/new-trace-viewer/context.d.ts +15 -0
- package/dist/components/new-trace-viewer/context.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/context.js +47 -0
- package/dist/components/new-trace-viewer/detail-panel.d.ts +10 -0
- package/dist/components/new-trace-viewer/detail-panel.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/detail-panel.js +13 -0
- package/dist/components/new-trace-viewer/icons.d.ts +6 -0
- package/dist/components/new-trace-viewer/icons.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/icons.js +15 -0
- package/dist/components/new-trace-viewer/search.d.ts +19 -0
- package/dist/components/new-trace-viewer/search.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/search.js +134 -0
- package/dist/components/new-trace-viewer/trace-viewer.d.ts +8 -0
- package/dist/components/new-trace-viewer/trace-viewer.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/trace-viewer.js +387 -0
- package/dist/components/new-trace-viewer/types.d.ts +1 -0
- package/dist/components/new-trace-viewer/types.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/types.js +2 -0
- package/dist/components/new-trace-viewer/util/constants.d.ts +1 -0
- package/dist/components/new-trace-viewer/util/constants.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/util/constants.js +2 -0
- package/dist/components/new-trace-viewer/utils.d.ts +46 -0
- package/dist/components/new-trace-viewer/utils.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/utils.js +330 -0
- package/dist/components/run-trace-view.d.ts +2 -1
- package/dist/components/run-trace-view.d.ts.map +1 -1
- package/dist/components/run-trace-view.js +3 -3
- package/dist/components/sidebar/attribute-panel.d.ts +7 -1
- package/dist/components/sidebar/attribute-panel.d.ts.map +1 -1
- package/dist/components/sidebar/attribute-panel.js +131 -70
- package/dist/components/sidebar/conversation-view.js +1 -1
- package/dist/components/sidebar/copyable-data-block.d.ts +1 -0
- package/dist/components/sidebar/copyable-data-block.d.ts.map +1 -1
- package/dist/components/sidebar/copyable-data-block.js +16 -15
- package/dist/components/sidebar/detail-card.d.ts +5 -6
- package/dist/components/sidebar/detail-card.d.ts.map +1 -1
- package/dist/components/sidebar/detail-card.js +32 -16
- package/dist/components/sidebar/entity-detail-panel.d.ts +3 -1
- package/dist/components/sidebar/entity-detail-panel.d.ts.map +1 -1
- package/dist/components/sidebar/entity-detail-panel.js +20 -37
- package/dist/components/sidebar/events-list.d.ts.map +1 -1
- package/dist/components/sidebar/events-list.js +21 -15
- package/dist/components/sidebar/resolve-hook-modal.js +1 -1
- package/dist/components/sidebar/sidebar-data-context.d.ts +29 -0
- package/dist/components/sidebar/sidebar-data-context.d.ts.map +1 -0
- package/dist/components/sidebar/sidebar-data-context.js +19 -0
- package/dist/components/stream-viewer.d.ts +1 -1
- package/dist/components/stream-viewer.d.ts.map +1 -1
- package/dist/components/stream-viewer.js +3 -27
- package/dist/components/trace-viewer/components/map.js +1 -1
- package/dist/components/trace-viewer/components/markers.js +1 -1
- package/dist/components/trace-viewer/components/node.js +1 -1
- package/dist/components/trace-viewer/components/search-input.js +1 -1
- package/dist/components/trace-viewer/components/search.js +1 -1
- package/dist/components/trace-viewer/components/span-content.js +1 -1
- package/dist/components/trace-viewer/components/span-detail-panel.js +1 -1
- package/dist/components/trace-viewer/components/span-segments.js +1 -1
- package/dist/components/trace-viewer/components/span-strategies.js +1 -1
- package/dist/components/trace-viewer/components/ui.js +1 -1
- package/dist/components/trace-viewer/components/zoom-button.js +1 -1
- package/dist/components/trace-viewer/components/zoom-icons.js +1 -1
- package/dist/components/trace-viewer/context.js +1 -1
- package/dist/components/trace-viewer/index.js +1 -1
- package/dist/components/trace-viewer/trace-viewer.js +1 -1
- package/dist/components/trace-viewer/types.js +1 -1
- package/dist/components/trace-viewer/util/constants.js +1 -1
- package/dist/components/trace-viewer/util/scrollbar-width.js +1 -1
- package/dist/components/trace-viewer/util/timing.d.ts +1 -1
- package/dist/components/trace-viewer/util/timing.d.ts.map +1 -1
- package/dist/components/trace-viewer/util/timing.js +6 -9
- package/dist/components/trace-viewer/util/tree.js +1 -1
- package/dist/components/trace-viewer/util/use-immediate-style.js +1 -1
- package/dist/components/trace-viewer/util/use-streaming-spans.js +1 -1
- package/dist/components/trace-viewer/util/use-trackpad-zoom.js +1 -1
- package/dist/components/trace-viewer/worker.js +1 -1
- package/dist/components/trace-viewer-new.d.ts +10 -0
- package/dist/components/trace-viewer-new.d.ts.map +1 -0
- package/dist/components/trace-viewer-new.js +23 -0
- package/dist/components/ui/alert.js +1 -1
- package/dist/components/ui/button.d.ts +10 -0
- package/dist/components/ui/button.d.ts.map +1 -0
- package/dist/components/ui/button.js +46 -0
- package/dist/components/ui/card.js +1 -1
- package/dist/components/ui/data-inspector.d.ts +39 -1
- package/dist/components/ui/data-inspector.d.ts.map +1 -1
- package/dist/components/ui/data-inspector.js +207 -22
- package/dist/components/ui/decrypt-button.js +1 -1
- package/dist/components/ui/error-card.js +1 -1
- package/dist/components/ui/error-stack-block.d.ts.map +1 -1
- package/dist/components/ui/error-stack-block.js +27 -19
- package/dist/components/ui/icon-button.d.ts +13 -0
- package/dist/components/ui/icon-button.d.ts.map +1 -0
- package/dist/components/ui/icon-button.js +29 -0
- package/dist/components/ui/inspector-theme.d.ts +9 -10
- package/dist/components/ui/inspector-theme.d.ts.map +1 -1
- package/dist/components/ui/inspector-theme.js +39 -72
- package/dist/components/ui/load-more-button.js +1 -1
- package/dist/components/ui/menu-dropdown.js +1 -1
- package/dist/components/ui/skeleton.js +1 -1
- package/dist/components/ui/spinner.js +1 -1
- package/dist/components/ui/timestamp-tooltip.js +1 -1
- package/dist/components/workflow-trace-view.d.ts +3 -1
- package/dist/components/workflow-trace-view.d.ts.map +1 -1
- package/dist/components/workflow-trace-view.js +10 -5
- package/dist/components/workflow-traces/event-colors.js +1 -1
- package/dist/components/workflow-traces/trace-colors.js +1 -1
- package/dist/components/workflow-traces/trace-span-construction.d.ts +2 -2
- package/dist/components/workflow-traces/trace-span-construction.d.ts.map +1 -1
- package/dist/components/workflow-traces/trace-span-construction.js +19 -6
- package/dist/components/workflow-traces/trace-time-utils.js +1 -1
- package/dist/hooks/use-dark-mode.js +1 -1
- package/dist/hooks/use-reduced-motion.d.ts +10 -0
- package/dist/hooks/use-reduced-motion.d.ts.map +1 -0
- package/dist/hooks/use-reduced-motion.js +29 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/lib/event-analysis.js +1 -1
- package/dist/lib/event-materialization.js +1 -1
- package/dist/lib/exact-event-search-id.d.ts +25 -0
- package/dist/lib/exact-event-search-id.d.ts.map +1 -0
- package/dist/lib/exact-event-search-id.js +39 -0
- package/dist/lib/hydration.d.ts +14 -1
- package/dist/lib/hydration.d.ts.map +1 -1
- package/dist/lib/hydration.js +157 -4
- package/dist/lib/stream-display.d.ts +18 -0
- package/dist/lib/stream-display.d.ts.map +1 -0
- package/dist/lib/stream-display.js +30 -0
- package/dist/lib/toast.js +1 -1
- package/dist/lib/trace-builder.d.ts.map +1 -1
- package/dist/lib/trace-builder.js +3 -2
- package/dist/lib/utils.d.ts +9 -9
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +27 -32
- package/dist/styles.css +475 -1
- package/package.json +6 -4
- package/src/components/event-list-view.tsx +421 -262
- package/src/components/index.ts +12 -1
- package/src/components/new-trace-viewer/components/copy-button.tsx +68 -0
- package/src/components/new-trace-viewer/components/event-list.tsx +127 -0
- package/src/components/new-trace-viewer/components/middle-truncate/copy-selection.ts +114 -0
- package/src/components/new-trace-viewer/components/middle-truncate/middle-truncate.tsx +157 -0
- package/src/components/new-trace-viewer/components/middle-truncate/truncate.ts +132 -0
- package/src/components/new-trace-viewer/components/middle-truncate/use-middle-truncate.ts +167 -0
- package/src/components/new-trace-viewer/components/split-pane.tsx +185 -0
- package/src/components/new-trace-viewer/components/timeline.tsx +552 -0
- package/src/components/new-trace-viewer/context.tsx +92 -0
- package/src/components/new-trace-viewer/detail-panel.tsx +55 -0
- package/src/components/new-trace-viewer/icons.tsx +79 -0
- package/src/components/new-trace-viewer/search.ts +178 -0
- package/src/components/new-trace-viewer/trace-viewer.tsx +694 -0
- package/src/components/new-trace-viewer/types.ts +0 -0
- package/src/components/new-trace-viewer/util/constants.ts +0 -0
- package/src/components/new-trace-viewer/utils.ts +482 -0
- package/src/components/run-trace-view.tsx +3 -0
- package/src/components/sidebar/attribute-panel.tsx +240 -196
- package/src/components/sidebar/copyable-data-block.tsx +49 -27
- package/src/components/sidebar/detail-card.tsx +119 -59
- package/src/components/sidebar/entity-detail-panel.tsx +92 -148
- package/src/components/sidebar/events-list.tsx +51 -76
- package/src/components/sidebar/sidebar-data-context.tsx +62 -0
- package/src/components/stream-viewer.tsx +18 -40
- package/src/components/trace-viewer/util/timing.ts +5 -9
- package/src/components/trace-viewer-new.tsx +49 -0
- package/src/components/ui/button.tsx +68 -0
- package/src/components/ui/data-inspector.tsx +427 -31
- package/src/components/ui/error-stack-block.tsx +39 -30
- package/src/components/ui/icon-button.tsx +57 -0
- package/src/components/ui/inspector-theme.ts +39 -81
- package/src/components/workflow-trace-view.tsx +12 -2
- package/src/components/workflow-traces/trace-span-construction.ts +24 -6
- package/src/hooks/use-reduced-motion.ts +34 -0
- package/src/index.ts +9 -0
- package/src/lib/exact-event-search-id.ts +67 -0
- package/src/lib/hydration.ts +169 -1
- package/src/lib/stream-display.ts +48 -0
- package/src/lib/trace-builder.ts +2 -1
- package/src/lib/utils.ts +27 -32
- package/src/styles.css +475 -1
- package/dist/components/error-boundary.js.map +0 -1
- package/dist/components/event-list-view.js.map +0 -1
- package/dist/components/hook-actions.js.map +0 -1
- package/dist/components/index.js.map +0 -1
- package/dist/components/run-trace-view.js.map +0 -1
- package/dist/components/sidebar/attribute-panel.js.map +0 -1
- package/dist/components/sidebar/conversation-view.js.map +0 -1
- package/dist/components/sidebar/copyable-data-block.js.map +0 -1
- package/dist/components/sidebar/detail-card.js.map +0 -1
- package/dist/components/sidebar/entity-detail-panel.js.map +0 -1
- package/dist/components/sidebar/events-list.js.map +0 -1
- package/dist/components/sidebar/resolve-hook-modal.js.map +0 -1
- package/dist/components/stream-viewer.js.map +0 -1
- package/dist/components/trace-viewer/components/map.js.map +0 -1
- package/dist/components/trace-viewer/components/markers.js.map +0 -1
- package/dist/components/trace-viewer/components/node.js.map +0 -1
- package/dist/components/trace-viewer/components/search-input.js.map +0 -1
- package/dist/components/trace-viewer/components/search.js.map +0 -1
- package/dist/components/trace-viewer/components/span-content.js.map +0 -1
- package/dist/components/trace-viewer/components/span-detail-panel.js.map +0 -1
- package/dist/components/trace-viewer/components/span-segments.js.map +0 -1
- package/dist/components/trace-viewer/components/span-strategies.js.map +0 -1
- package/dist/components/trace-viewer/components/ui.js.map +0 -1
- package/dist/components/trace-viewer/components/zoom-button.js.map +0 -1
- package/dist/components/trace-viewer/components/zoom-icons.js.map +0 -1
- package/dist/components/trace-viewer/context.js.map +0 -1
- package/dist/components/trace-viewer/index.js.map +0 -1
- package/dist/components/trace-viewer/trace-viewer.js.map +0 -1
- package/dist/components/trace-viewer/types.js.map +0 -1
- package/dist/components/trace-viewer/util/constants.js.map +0 -1
- package/dist/components/trace-viewer/util/scrollbar-width.js.map +0 -1
- package/dist/components/trace-viewer/util/timing.js.map +0 -1
- package/dist/components/trace-viewer/util/tree.js.map +0 -1
- package/dist/components/trace-viewer/util/use-immediate-style.js.map +0 -1
- package/dist/components/trace-viewer/util/use-streaming-spans.js.map +0 -1
- package/dist/components/trace-viewer/util/use-trackpad-zoom.js.map +0 -1
- package/dist/components/trace-viewer/worker.js.map +0 -1
- package/dist/components/ui/alert.js.map +0 -1
- package/dist/components/ui/card.js.map +0 -1
- package/dist/components/ui/data-inspector.js.map +0 -1
- package/dist/components/ui/decrypt-button.js.map +0 -1
- package/dist/components/ui/error-card.js.map +0 -1
- package/dist/components/ui/error-stack-block.js.map +0 -1
- package/dist/components/ui/inspector-theme.js.map +0 -1
- package/dist/components/ui/load-more-button.js.map +0 -1
- package/dist/components/ui/menu-dropdown.js.map +0 -1
- package/dist/components/ui/skeleton.js.map +0 -1
- package/dist/components/ui/spinner.js.map +0 -1
- package/dist/components/ui/timestamp-tooltip.js.map +0 -1
- package/dist/components/workflow-trace-view.js.map +0 -1
- package/dist/components/workflow-traces/event-colors.js.map +0 -1
- package/dist/components/workflow-traces/trace-colors.js.map +0 -1
- package/dist/components/workflow-traces/trace-span-construction.js.map +0 -1
- package/dist/components/workflow-traces/trace-time-utils.js.map +0 -1
- package/dist/hooks/use-dark-mode.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/lib/event-analysis.js.map +0 -1
- package/dist/lib/event-materialization.js.map +0 -1
- package/dist/lib/hydration.js.map +0 -1
- package/dist/lib/toast.js.map +0 -1
- package/dist/lib/trace-builder.js.map +0 -1
- package/dist/lib/utils.js.map +0 -1
|
@@ -3,13 +3,24 @@
|
|
|
3
3
|
import { parseStepName, parseWorkflowName } from '@workflow/utils/parse-name';
|
|
4
4
|
import type { Event, WorkflowRun } from '@workflow/world';
|
|
5
5
|
import { Check, ChevronRight, Copy } from 'lucide-react';
|
|
6
|
-
import type {
|
|
6
|
+
import type {
|
|
7
|
+
KeyboardEvent as ReactKeyboardEvent,
|
|
8
|
+
MouseEvent as ReactMouseEvent,
|
|
9
|
+
ReactNode,
|
|
10
|
+
} from 'react';
|
|
7
11
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
8
12
|
import { Virtuoso, type VirtuosoHandle } from 'react-virtuoso';
|
|
9
13
|
import { isEncryptedMarker } from '../lib/hydration';
|
|
14
|
+
import {
|
|
15
|
+
parseExactWorkflowSearchId,
|
|
16
|
+
looksLikeWorkflowIdSearchInput,
|
|
17
|
+
type ExactIdSearchResult,
|
|
18
|
+
type ExactWorkflowSearchIdKind,
|
|
19
|
+
} from '../lib/exact-event-search-id';
|
|
10
20
|
import { DecryptButton } from './ui/decrypt-button';
|
|
11
21
|
import { formatDuration } from '../lib/utils';
|
|
12
|
-
import {
|
|
22
|
+
import { useToast } from '../lib/toast';
|
|
23
|
+
import { DataInspector, DecryptClickContext } from './ui/data-inspector';
|
|
13
24
|
import {
|
|
14
25
|
ErrorStackBlock,
|
|
15
26
|
isStructuredErrorWithStack,
|
|
@@ -142,7 +153,7 @@ function buildNameMaps(
|
|
|
142
153
|
return { correlationNameMap, workflowName };
|
|
143
154
|
}
|
|
144
155
|
|
|
145
|
-
interface DurationInfo {
|
|
156
|
+
export interface DurationInfo {
|
|
146
157
|
/** Time from created → started (ms) */
|
|
147
158
|
queued?: number;
|
|
148
159
|
/** Time from started → completed/failed/cancelled (ms) */
|
|
@@ -154,19 +165,30 @@ interface DurationInfo {
|
|
|
154
165
|
* created ↔ started (queued) and started ↔ completed/failed/cancelled (ran).
|
|
155
166
|
* Also computes run-level durations under the key '__run__'.
|
|
156
167
|
*/
|
|
157
|
-
function buildDurationMap(events: Event[]): Map<string, DurationInfo> {
|
|
168
|
+
export function buildDurationMap(events: Event[]): Map<string, DurationInfo> {
|
|
169
|
+
// Process events in chronological order so the result doesn't depend on
|
|
170
|
+
// the caller's sort direction. Retried steps emit multiple `step_started`
|
|
171
|
+
// events for the same correlationId; the queued duration must be measured
|
|
172
|
+
// against the first one, not the last.
|
|
173
|
+
const chronological = [...events].sort(
|
|
174
|
+
(a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()
|
|
175
|
+
);
|
|
176
|
+
|
|
158
177
|
const createdTimes = new Map<string, number>();
|
|
178
|
+
const firstStartedTimes = new Map<string, number>();
|
|
159
179
|
const startedTimes = new Map<string, number>();
|
|
160
180
|
const durations = new Map<string, DurationInfo>();
|
|
161
181
|
|
|
162
|
-
for (const event of
|
|
182
|
+
for (const event of chronological) {
|
|
163
183
|
const ts = new Date(event.createdAt).getTime();
|
|
164
184
|
const key = event.correlationId ?? '__run__';
|
|
165
185
|
const type: string = event.eventType;
|
|
166
186
|
|
|
167
187
|
// Track created times (first event for each correlation)
|
|
168
188
|
if (type === 'step_created' || type === 'run_created') {
|
|
169
|
-
createdTimes.
|
|
189
|
+
if (!createdTimes.has(key)) {
|
|
190
|
+
createdTimes.set(key, ts);
|
|
191
|
+
}
|
|
170
192
|
}
|
|
171
193
|
|
|
172
194
|
// Track started times & compute queued duration
|
|
@@ -176,16 +198,21 @@ function buildDurationMap(events: Event[]): Map<string, DurationInfo> {
|
|
|
176
198
|
type === 'workflow_started'
|
|
177
199
|
) {
|
|
178
200
|
startedTimes.set(key, ts);
|
|
179
|
-
//
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
201
|
+
// The queued duration is anchored on the first start event only —
|
|
202
|
+
// subsequent step_started events come from retries.
|
|
203
|
+
if (!firstStartedTimes.has(key)) {
|
|
204
|
+
firstStartedTimes.set(key, ts);
|
|
205
|
+
// If no explicit created event was seen, use the started time as created
|
|
206
|
+
if (!createdTimes.has(key)) {
|
|
207
|
+
createdTimes.set(key, ts);
|
|
208
|
+
}
|
|
209
|
+
const createdAt = createdTimes.get(key);
|
|
210
|
+
const info = durations.get(key) ?? {};
|
|
211
|
+
if (createdAt !== undefined) {
|
|
212
|
+
info.queued = ts - createdAt;
|
|
213
|
+
}
|
|
214
|
+
durations.set(key, info);
|
|
187
215
|
}
|
|
188
|
-
durations.set(key, info);
|
|
189
216
|
}
|
|
190
217
|
|
|
191
218
|
// Compute ran duration on terminal events
|
|
@@ -703,6 +730,14 @@ interface EventsListProps {
|
|
|
703
730
|
onDecrypt?: () => void;
|
|
704
731
|
/** Whether the encryption key is currently being fetched. */
|
|
705
732
|
isDecrypting?: boolean;
|
|
733
|
+
/** Run-level hint: the run contains encrypted data (from probe). */
|
|
734
|
+
hasEncryptedData?: boolean;
|
|
735
|
+
/** Fetch events for an exact correlation or event ID. */
|
|
736
|
+
onExactIdSearch?: (
|
|
737
|
+
id: string,
|
|
738
|
+
kind: ExactWorkflowSearchIdKind,
|
|
739
|
+
signal?: AbortSignal
|
|
740
|
+
) => Promise<ExactIdSearchResult>;
|
|
706
741
|
}
|
|
707
742
|
|
|
708
743
|
function EventRow({
|
|
@@ -725,6 +760,7 @@ function EventRow({
|
|
|
725
760
|
onCacheEventData,
|
|
726
761
|
encryptionKey,
|
|
727
762
|
onEncryptedDataDetected,
|
|
763
|
+
suppressGroupDimming = false,
|
|
728
764
|
}: {
|
|
729
765
|
event: Event;
|
|
730
766
|
index: number;
|
|
@@ -745,6 +781,8 @@ function EventRow({
|
|
|
745
781
|
onCacheEventData: (eventId: string, data: unknown) => void;
|
|
746
782
|
encryptionKey?: Uint8Array;
|
|
747
783
|
onEncryptedDataDetected?: () => void;
|
|
784
|
+
/** Exact-ID search results should not dim unrelated rows. */
|
|
785
|
+
suppressGroupDimming?: boolean;
|
|
748
786
|
}) {
|
|
749
787
|
const [isLoading, setIsLoading] = useState(false);
|
|
750
788
|
const [loadedEventData, setLoadedEventData] = useState<unknown | null>(
|
|
@@ -786,7 +824,7 @@ function EventRow({
|
|
|
786
824
|
|
|
787
825
|
const hasActive = activeGroupKey !== undefined;
|
|
788
826
|
const isRelated = rowGroupKey !== undefined && rowGroupKey === activeGroupKey;
|
|
789
|
-
const isDimmed = hasActive && !isRelated;
|
|
827
|
+
const isDimmed = hasActive && !isRelated && !suppressGroupDimming;
|
|
790
828
|
const isPulsing = hasActive && isRelated;
|
|
791
829
|
|
|
792
830
|
// Gutter state derived from selectedGroupRange
|
|
@@ -1136,7 +1174,10 @@ export function EventListView({
|
|
|
1136
1174
|
onSortOrderChange,
|
|
1137
1175
|
onDecrypt,
|
|
1138
1176
|
isDecrypting = false,
|
|
1177
|
+
hasEncryptedData: hasEncryptedDataProp = false,
|
|
1178
|
+
onExactIdSearch,
|
|
1139
1179
|
}: EventsListProps) {
|
|
1180
|
+
const toast = useToast();
|
|
1140
1181
|
const [internalSortOrder, setInternalSortOrder] = useState<'asc' | 'desc'>(
|
|
1141
1182
|
'asc'
|
|
1142
1183
|
);
|
|
@@ -1152,25 +1193,42 @@ export function EventListView({
|
|
|
1152
1193
|
[onSortOrderChange]
|
|
1153
1194
|
);
|
|
1154
1195
|
|
|
1196
|
+
const [searchQuery, setSearchQuery] = useState('');
|
|
1197
|
+
const [searchResults, setSearchResults] = useState<Event[] | null>(null);
|
|
1198
|
+
const [searchResultsTruncated, setSearchResultsTruncated] = useState(false);
|
|
1199
|
+
const [searchError, setSearchError] = useState<string | null>(null);
|
|
1200
|
+
const [searchLoading, setSearchLoading] = useState(false);
|
|
1201
|
+
const [searchNotFound, setSearchNotFound] = useState(false);
|
|
1202
|
+
const searchRequestRef = useRef(0);
|
|
1203
|
+
const virtuosoRef = useRef<VirtuosoHandle>(null);
|
|
1204
|
+
|
|
1205
|
+
const parsedSearchId = useMemo(
|
|
1206
|
+
() => parseExactWorkflowSearchId(searchQuery),
|
|
1207
|
+
[searchQuery]
|
|
1208
|
+
);
|
|
1209
|
+
const isExactSearchActive = searchResults !== null;
|
|
1210
|
+
|
|
1155
1211
|
const sortedEvents = useMemo(() => {
|
|
1156
|
-
|
|
1212
|
+
const sourceEvents = isExactSearchActive ? searchResults : (events ?? []);
|
|
1213
|
+
if (sourceEvents.length === 0) return [];
|
|
1157
1214
|
const dir = effectiveSortOrder === 'desc' ? -1 : 1;
|
|
1158
|
-
return [...
|
|
1215
|
+
return [...sourceEvents].sort(
|
|
1159
1216
|
(a, b) =>
|
|
1160
1217
|
dir *
|
|
1161
1218
|
(new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime())
|
|
1162
1219
|
);
|
|
1163
|
-
}, [events, effectiveSortOrder]);
|
|
1220
|
+
}, [events, effectiveSortOrder, isExactSearchActive, searchResults]);
|
|
1164
1221
|
|
|
1165
1222
|
// Detect encrypted fields across all loaded events (inline eventData).
|
|
1166
1223
|
const hasEncryptedInlineData = useMemo(() => {
|
|
1167
|
-
|
|
1168
|
-
|
|
1224
|
+
const sourceEvents = isExactSearchActive ? searchResults : events;
|
|
1225
|
+
if (!sourceEvents) return false;
|
|
1226
|
+
for (const event of sourceEvents) {
|
|
1169
1227
|
const ed = (event as Record<string, unknown>).eventData;
|
|
1170
1228
|
if (hasEncryptedValues(ed)) return true;
|
|
1171
1229
|
}
|
|
1172
1230
|
return false;
|
|
1173
|
-
}, [events]);
|
|
1231
|
+
}, [events, isExactSearchActive, searchResults]);
|
|
1174
1232
|
|
|
1175
1233
|
// Tracks whether any expanded row's lazy-loaded data contained encrypted markers.
|
|
1176
1234
|
// Set to true by EventRow via onEncryptedDataDetected; never reset (sticky).
|
|
@@ -1180,11 +1238,16 @@ export function EventListView({
|
|
|
1180
1238
|
setFoundEncryptedInLazyData(true);
|
|
1181
1239
|
}, []);
|
|
1182
1240
|
|
|
1183
|
-
const hasEncryptedData =
|
|
1241
|
+
const hasEncryptedData =
|
|
1242
|
+
hasEncryptedDataProp || hasEncryptedInlineData || foundEncryptedInLazyData;
|
|
1184
1243
|
|
|
1185
1244
|
const { correlationNameMap, workflowName } = useMemo(
|
|
1186
|
-
() =>
|
|
1187
|
-
|
|
1245
|
+
() =>
|
|
1246
|
+
buildNameMaps(
|
|
1247
|
+
isExactSearchActive ? searchResults : (events ?? null),
|
|
1248
|
+
run ?? null
|
|
1249
|
+
),
|
|
1250
|
+
[events, isExactSearchActive, run, searchResults]
|
|
1188
1251
|
);
|
|
1189
1252
|
|
|
1190
1253
|
const durationMap = useMemo(
|
|
@@ -1274,68 +1337,139 @@ export function EventListView({
|
|
|
1274
1337
|
return first >= 0 ? { first, last } : null;
|
|
1275
1338
|
}, [activeGroupKey, sortedEvents]);
|
|
1276
1339
|
|
|
1277
|
-
const [searchQuery, setSearchQuery] = useState('');
|
|
1278
|
-
const virtuosoRef = useRef<VirtuosoHandle>(null);
|
|
1279
|
-
|
|
1280
|
-
const searchIndex = useMemo(() => {
|
|
1281
|
-
const entries: {
|
|
1282
|
-
fields: string[];
|
|
1283
|
-
groupKey?: string;
|
|
1284
|
-
eventId: string;
|
|
1285
|
-
index: number;
|
|
1286
|
-
}[] = [];
|
|
1287
|
-
for (let i = 0; i < sortedEvents.length; i++) {
|
|
1288
|
-
const ev = sortedEvents[i];
|
|
1289
|
-
const isRun = isRunLevel(ev.eventType);
|
|
1290
|
-
const name = isRun
|
|
1291
|
-
? (workflowName ?? '')
|
|
1292
|
-
: ev.correlationId
|
|
1293
|
-
? (correlationNameMap.get(ev.correlationId) ?? '')
|
|
1294
|
-
: '';
|
|
1295
|
-
entries.push({
|
|
1296
|
-
fields: [
|
|
1297
|
-
ev.eventId,
|
|
1298
|
-
ev.correlationId ?? '',
|
|
1299
|
-
ev.eventType,
|
|
1300
|
-
formatEventType(ev.eventType),
|
|
1301
|
-
name,
|
|
1302
|
-
].map((f) => f.toLowerCase()),
|
|
1303
|
-
groupKey: ev.correlationId ?? (isRun ? '__run__' : undefined),
|
|
1304
|
-
eventId: ev.eventId,
|
|
1305
|
-
index: i,
|
|
1306
|
-
});
|
|
1307
|
-
}
|
|
1308
|
-
return entries;
|
|
1309
|
-
}, [sortedEvents, correlationNameMap, workflowName]);
|
|
1310
|
-
|
|
1311
1340
|
useEffect(() => {
|
|
1312
|
-
const
|
|
1313
|
-
if (!
|
|
1341
|
+
const trimmed = searchQuery.trim();
|
|
1342
|
+
if (!trimmed) {
|
|
1343
|
+
searchRequestRef.current += 1;
|
|
1344
|
+
setSearchResults(null);
|
|
1345
|
+
setSearchResultsTruncated(false);
|
|
1346
|
+
setSearchError(null);
|
|
1347
|
+
setSearchLoading(false);
|
|
1348
|
+
setSearchNotFound(false);
|
|
1314
1349
|
setSelectedGroupKey(undefined);
|
|
1315
1350
|
return;
|
|
1316
1351
|
}
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1352
|
+
|
|
1353
|
+
const parsed = parseExactWorkflowSearchId(trimmed);
|
|
1354
|
+
if (!parsed || !onExactIdSearch) {
|
|
1355
|
+
setSearchResults(null);
|
|
1356
|
+
setSearchLoading(false);
|
|
1357
|
+
setSearchNotFound(false);
|
|
1358
|
+
return;
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
const requestId = ++searchRequestRef.current;
|
|
1362
|
+
setSearchLoading(true);
|
|
1363
|
+
setSearchNotFound(false);
|
|
1364
|
+
setSearchError(null);
|
|
1365
|
+
|
|
1366
|
+
const abortController = new AbortController();
|
|
1367
|
+
|
|
1368
|
+
const timer = setTimeout(() => {
|
|
1369
|
+
void (async () => {
|
|
1370
|
+
try {
|
|
1371
|
+
const results = await onExactIdSearch(
|
|
1372
|
+
parsed.id,
|
|
1373
|
+
parsed.kind,
|
|
1374
|
+
abortController.signal
|
|
1375
|
+
);
|
|
1376
|
+
if (
|
|
1377
|
+
abortController.signal.aborted ||
|
|
1378
|
+
searchRequestRef.current !== requestId
|
|
1379
|
+
) {
|
|
1380
|
+
return;
|
|
1381
|
+
}
|
|
1382
|
+
|
|
1383
|
+
if (results.status === 'error') {
|
|
1384
|
+
setSearchResults([]);
|
|
1385
|
+
setSearchResultsTruncated(false);
|
|
1386
|
+
setSearchNotFound(false);
|
|
1387
|
+
setSearchError(results.message);
|
|
1388
|
+
setSelectedGroupKey(undefined);
|
|
1389
|
+
return;
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
if (
|
|
1393
|
+
results.status === 'not_found' ||
|
|
1394
|
+
(results.status === 'ok' && results.events.length === 0)
|
|
1395
|
+
) {
|
|
1396
|
+
setSearchResults([]);
|
|
1397
|
+
setSearchResultsTruncated(false);
|
|
1398
|
+
setSearchNotFound(true);
|
|
1399
|
+
setSearchError(null);
|
|
1400
|
+
setSelectedGroupKey(undefined);
|
|
1401
|
+
return;
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
setSearchResults(results.events);
|
|
1405
|
+
setSearchResultsTruncated(Boolean(results.truncated));
|
|
1406
|
+
setSearchNotFound(false);
|
|
1407
|
+
setSearchError(null);
|
|
1408
|
+
setSelectedGroupKey(
|
|
1409
|
+
parsed.kind === 'event'
|
|
1410
|
+
? (() => {
|
|
1411
|
+
const first = results.events[0];
|
|
1412
|
+
if (!first) return undefined;
|
|
1413
|
+
return isRunLevel(first.eventType)
|
|
1414
|
+
? '__run__'
|
|
1415
|
+
: (first.correlationId ?? undefined);
|
|
1416
|
+
})()
|
|
1417
|
+
: parsed.id
|
|
1418
|
+
);
|
|
1419
|
+
virtuosoRef.current?.scrollToIndex({
|
|
1420
|
+
index: 0,
|
|
1421
|
+
align: 'start',
|
|
1422
|
+
behavior: 'smooth',
|
|
1423
|
+
});
|
|
1424
|
+
} catch {
|
|
1425
|
+
if (
|
|
1426
|
+
abortController.signal.aborted ||
|
|
1427
|
+
searchRequestRef.current !== requestId
|
|
1428
|
+
) {
|
|
1429
|
+
return;
|
|
1430
|
+
}
|
|
1431
|
+
setSearchResults([]);
|
|
1432
|
+
setSearchResultsTruncated(false);
|
|
1433
|
+
setSearchNotFound(false);
|
|
1434
|
+
setSearchError('Failed to search events. Try again.');
|
|
1435
|
+
setSelectedGroupKey(undefined);
|
|
1436
|
+
} finally {
|
|
1437
|
+
if (
|
|
1438
|
+
searchRequestRef.current === requestId &&
|
|
1439
|
+
!abortController.signal.aborted
|
|
1440
|
+
) {
|
|
1441
|
+
setSearchLoading(false);
|
|
1326
1442
|
}
|
|
1327
1443
|
}
|
|
1444
|
+
})();
|
|
1445
|
+
}, 300);
|
|
1446
|
+
|
|
1447
|
+
return () => {
|
|
1448
|
+
clearTimeout(timer);
|
|
1449
|
+
abortController.abort();
|
|
1450
|
+
};
|
|
1451
|
+
}, [searchQuery, onExactIdSearch]);
|
|
1452
|
+
|
|
1453
|
+
const handleSearchKeyDown = useCallback(
|
|
1454
|
+
(event: ReactKeyboardEvent<HTMLInputElement>) => {
|
|
1455
|
+
if (event.key !== 'Enter') {
|
|
1456
|
+
return;
|
|
1328
1457
|
}
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1458
|
+
|
|
1459
|
+
const trimmed = searchQuery.trim();
|
|
1460
|
+
if (
|
|
1461
|
+
!trimmed ||
|
|
1462
|
+
parseExactWorkflowSearchId(trimmed) ||
|
|
1463
|
+
!onExactIdSearch ||
|
|
1464
|
+
!looksLikeWorkflowIdSearchInput(trimmed)
|
|
1465
|
+
) {
|
|
1466
|
+
return;
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1469
|
+
toast.info('Enter a full step ID, wait ID, hook ID, or event ID');
|
|
1470
|
+
},
|
|
1471
|
+
[searchQuery, onExactIdSearch, toast]
|
|
1472
|
+
);
|
|
1339
1473
|
|
|
1340
1474
|
// Track whether we've ever had events to distinguish initial load from refetch
|
|
1341
1475
|
const hasHadEventsRef = useRef(false);
|
|
@@ -1381,207 +1515,232 @@ export function EventListView({
|
|
|
1381
1515
|
);
|
|
1382
1516
|
}
|
|
1383
1517
|
|
|
1384
|
-
if (!isLoading && (!events || events.length === 0)) {
|
|
1385
|
-
return (
|
|
1386
|
-
<div
|
|
1387
|
-
className="flex items-center justify-center h-full text-sm"
|
|
1388
|
-
style={{ color: 'var(--ds-gray-700)' }}
|
|
1389
|
-
>
|
|
1390
|
-
No events found
|
|
1391
|
-
</div>
|
|
1392
|
-
);
|
|
1393
|
-
}
|
|
1394
|
-
|
|
1395
1518
|
return (
|
|
1396
|
-
<
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
<div
|
|
1400
|
-
style
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
display: 'flex',
|
|
1404
|
-
gap: 6,
|
|
1405
|
-
}}
|
|
1406
|
-
>
|
|
1407
|
-
<label
|
|
1519
|
+
<DecryptClickContext.Provider
|
|
1520
|
+
value={onDecrypt ? { onDecrypt, isDecrypting } : undefined}
|
|
1521
|
+
>
|
|
1522
|
+
<div className="h-full flex flex-col overflow-hidden">
|
|
1523
|
+
<style>{`@keyframes workflow-dot-pulse{0%{transform:scale(1);opacity:.7}70%,100%{transform:scale(2.2);opacity:0}}`}</style>
|
|
1524
|
+
{/* Search bar + sort */}
|
|
1525
|
+
<div
|
|
1408
1526
|
style={{
|
|
1527
|
+
padding: 6,
|
|
1528
|
+
backgroundColor: 'var(--ds-background-100)',
|
|
1409
1529
|
display: 'flex',
|
|
1410
|
-
|
|
1411
|
-
justifyContent: 'center',
|
|
1412
|
-
borderRadius: 6,
|
|
1413
|
-
boxShadow: '0 0 0 1px var(--ds-gray-alpha-400)',
|
|
1414
|
-
background: 'var(--ds-background-100)',
|
|
1415
|
-
height: 40,
|
|
1416
|
-
flex: 1,
|
|
1417
|
-
minWidth: 0,
|
|
1530
|
+
gap: 6,
|
|
1418
1531
|
}}
|
|
1419
1532
|
>
|
|
1420
|
-
<
|
|
1533
|
+
<label
|
|
1421
1534
|
style={{
|
|
1422
|
-
width: 40,
|
|
1423
|
-
height: 40,
|
|
1424
1535
|
display: 'flex',
|
|
1425
1536
|
alignItems: 'center',
|
|
1426
1537
|
justifyContent: 'center',
|
|
1427
|
-
|
|
1428
|
-
|
|
1538
|
+
borderRadius: 6,
|
|
1539
|
+
boxShadow: '0 0 0 1px var(--ds-gray-alpha-400)',
|
|
1540
|
+
background: 'var(--ds-background-100)',
|
|
1541
|
+
height: 40,
|
|
1542
|
+
flex: 1,
|
|
1543
|
+
minWidth: 0,
|
|
1429
1544
|
}}
|
|
1430
1545
|
>
|
|
1431
|
-
<
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1546
|
+
<div
|
|
1547
|
+
style={{
|
|
1548
|
+
width: 40,
|
|
1549
|
+
height: 40,
|
|
1550
|
+
display: 'flex',
|
|
1551
|
+
alignItems: 'center',
|
|
1552
|
+
justifyContent: 'center',
|
|
1553
|
+
color: 'var(--ds-gray-800)',
|
|
1554
|
+
flexShrink: 0,
|
|
1555
|
+
}}
|
|
1438
1556
|
>
|
|
1439
|
-
<
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1557
|
+
<svg
|
|
1558
|
+
width={16}
|
|
1559
|
+
height={16}
|
|
1560
|
+
viewBox="0 0 16 16"
|
|
1561
|
+
fill="none"
|
|
1562
|
+
aria-hidden="true"
|
|
1563
|
+
focusable="false"
|
|
1564
|
+
>
|
|
1565
|
+
<circle
|
|
1566
|
+
cx="7"
|
|
1567
|
+
cy="7"
|
|
1568
|
+
r="4.5"
|
|
1569
|
+
stroke="currentColor"
|
|
1570
|
+
strokeWidth="1.5"
|
|
1571
|
+
/>
|
|
1572
|
+
<path
|
|
1573
|
+
d="M11.5 11.5L14 14"
|
|
1574
|
+
stroke="currentColor"
|
|
1575
|
+
strokeWidth="1.5"
|
|
1576
|
+
strokeLinecap="round"
|
|
1577
|
+
/>
|
|
1578
|
+
</svg>
|
|
1579
|
+
</div>
|
|
1580
|
+
<input
|
|
1581
|
+
type="search"
|
|
1582
|
+
placeholder="Search by step ID, wait ID, hook ID, or event ID…"
|
|
1583
|
+
value={searchQuery}
|
|
1584
|
+
onChange={(e) => setSearchQuery(e.target.value)}
|
|
1585
|
+
onKeyDown={handleSearchKeyDown}
|
|
1586
|
+
disabled={!onExactIdSearch}
|
|
1587
|
+
title={
|
|
1588
|
+
onExactIdSearch
|
|
1589
|
+
? undefined
|
|
1590
|
+
: 'Exact ID search is unavailable in this view.'
|
|
1591
|
+
}
|
|
1592
|
+
style={{
|
|
1593
|
+
marginLeft: -16,
|
|
1594
|
+
paddingInline: 12,
|
|
1595
|
+
fontFamily: 'inherit',
|
|
1596
|
+
fontSize: 14,
|
|
1597
|
+
background: 'transparent',
|
|
1598
|
+
border: 'none',
|
|
1599
|
+
outline: 'none',
|
|
1600
|
+
height: 40,
|
|
1601
|
+
width: '100%',
|
|
1602
|
+
opacity: onExactIdSearch ? 1 : 0.5,
|
|
1603
|
+
cursor: onExactIdSearch ? 'text' : 'not-allowed',
|
|
1604
|
+
}}
|
|
1605
|
+
/>
|
|
1606
|
+
</label>
|
|
1607
|
+
<MenuDropdown
|
|
1608
|
+
options={SORT_OPTIONS}
|
|
1609
|
+
value={effectiveSortOrder}
|
|
1610
|
+
onChange={handleSortOrderChange}
|
|
1482
1611
|
/>
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
borderColor: 'var(--ds-gray-alpha-200)',
|
|
1491
|
-
color: 'var(--ds-gray-900)',
|
|
1492
|
-
backgroundColor: 'var(--ds-background-100)',
|
|
1493
|
-
}}
|
|
1494
|
-
>
|
|
1495
|
-
<div className="flex-shrink-0" style={{ width: GUTTER_WIDTH }} />
|
|
1496
|
-
<div className="w-5 flex-shrink-0" />
|
|
1497
|
-
<div className="min-w-0 px-4" style={{ flex: '2 1 0%' }}>
|
|
1498
|
-
Time
|
|
1499
|
-
</div>
|
|
1500
|
-
<div className="min-w-0 px-4" style={{ flex: '2 1 0%' }}>
|
|
1501
|
-
Event Type
|
|
1502
|
-
</div>
|
|
1503
|
-
<div className="min-w-0 px-4" style={{ flex: '2 1 0%' }}>
|
|
1504
|
-
Name
|
|
1505
|
-
</div>
|
|
1506
|
-
<div className="min-w-0 px-4" style={{ flex: '3 1 0%' }}>
|
|
1507
|
-
Correlation ID
|
|
1508
|
-
</div>
|
|
1509
|
-
<div className="min-w-0 px-4" style={{ flex: '3 1 0%' }}>
|
|
1510
|
-
Event ID
|
|
1612
|
+
{(hasEncryptedData || encryptionKey) && onDecrypt && (
|
|
1613
|
+
<DecryptButton
|
|
1614
|
+
decrypted={!!encryptionKey}
|
|
1615
|
+
loading={isDecrypting}
|
|
1616
|
+
onClick={onDecrypt}
|
|
1617
|
+
/>
|
|
1618
|
+
)}
|
|
1511
1619
|
</div>
|
|
1512
|
-
</div>
|
|
1513
1620
|
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
overscan={20}
|
|
1522
|
-
defaultItemHeight={40}
|
|
1523
|
-
endReached={() => {
|
|
1524
|
-
if (!hasMoreEvents || isLoadingMoreEvents) {
|
|
1525
|
-
return;
|
|
1526
|
-
}
|
|
1527
|
-
void onLoadMoreEvents?.();
|
|
1528
|
-
}}
|
|
1529
|
-
itemContent={(index: number) => {
|
|
1530
|
-
const ev = sortedEvents[index];
|
|
1531
|
-
return (
|
|
1532
|
-
<EventRow
|
|
1533
|
-
event={ev}
|
|
1534
|
-
index={index}
|
|
1535
|
-
isFirst={index === 0}
|
|
1536
|
-
isLast={index === sortedEvents.length - 1}
|
|
1537
|
-
isExpanded={expandedEventIds.has(ev.eventId)}
|
|
1538
|
-
onToggleExpand={toggleEventExpanded}
|
|
1539
|
-
activeGroupKey={activeGroupKey}
|
|
1540
|
-
selectedGroupKey={selectedGroupKey}
|
|
1541
|
-
selectedGroupRange={selectedGroupRange}
|
|
1542
|
-
correlationNameMap={correlationNameMap}
|
|
1543
|
-
workflowName={workflowName}
|
|
1544
|
-
durationMap={durationMap}
|
|
1545
|
-
onSelectGroup={onSelectGroup}
|
|
1546
|
-
onHoverGroup={onHoverGroup}
|
|
1547
|
-
onLoadEventData={onLoadEventData}
|
|
1548
|
-
cachedEventData={
|
|
1549
|
-
eventDataCacheRef.current.get(ev.eventId) ?? null
|
|
1550
|
-
}
|
|
1551
|
-
onCacheEventData={cacheEventData}
|
|
1552
|
-
encryptionKey={encryptionKey}
|
|
1553
|
-
onEncryptedDataDetected={handleEncryptedDataDetected}
|
|
1554
|
-
/>
|
|
1555
|
-
);
|
|
1621
|
+
{/* Header */}
|
|
1622
|
+
<div
|
|
1623
|
+
className="flex items-center gap-0 text-[13px] font-medium h-10 border-b flex-shrink-0"
|
|
1624
|
+
style={{
|
|
1625
|
+
borderColor: 'var(--ds-gray-alpha-200)',
|
|
1626
|
+
color: 'var(--ds-gray-900)',
|
|
1627
|
+
backgroundColor: 'var(--ds-background-100)',
|
|
1556
1628
|
}}
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1629
|
+
>
|
|
1630
|
+
<div className="flex-shrink-0" style={{ width: GUTTER_WIDTH }} />
|
|
1631
|
+
<div className="w-5 flex-shrink-0" />
|
|
1632
|
+
<div className="min-w-0 px-4" style={{ flex: '2 1 0%' }}>
|
|
1633
|
+
Time
|
|
1634
|
+
</div>
|
|
1635
|
+
<div className="min-w-0 px-4" style={{ flex: '2 1 0%' }}>
|
|
1636
|
+
Event Type
|
|
1637
|
+
</div>
|
|
1638
|
+
<div className="min-w-0 px-4" style={{ flex: '2 1 0%' }}>
|
|
1639
|
+
Name
|
|
1640
|
+
</div>
|
|
1641
|
+
<div className="min-w-0 px-4" style={{ flex: '3 1 0%' }}>
|
|
1642
|
+
Correlation ID
|
|
1643
|
+
</div>
|
|
1644
|
+
<div className="min-w-0 px-4" style={{ flex: '3 1 0%' }}>
|
|
1645
|
+
Event ID
|
|
1646
|
+
</div>
|
|
1647
|
+
</div>
|
|
1560
1648
|
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
<div className="pointer-events-auto">
|
|
1577
|
-
<LoadMoreButton
|
|
1578
|
-
loading={isLoadingMoreEvents}
|
|
1579
|
-
onClick={() => void onLoadMoreEvents?.()}
|
|
1580
|
-
/>
|
|
1581
|
-
</div>
|
|
1649
|
+
{/* Virtualized event rows or refetching skeleton */}
|
|
1650
|
+
{isRefetching || searchLoading ? (
|
|
1651
|
+
<RowsSkeleton />
|
|
1652
|
+
) : sortedEvents.length === 0 ? (
|
|
1653
|
+
<div
|
|
1654
|
+
className="flex flex-1 items-center justify-center px-6 text-center text-sm"
|
|
1655
|
+
style={{ color: 'var(--ds-gray-700)' }}
|
|
1656
|
+
>
|
|
1657
|
+
{searchNotFound && searchQuery.trim()
|
|
1658
|
+
? `No events found for ${searchQuery.trim()}`
|
|
1659
|
+
: searchError
|
|
1660
|
+
? searchError
|
|
1661
|
+
: parsedSearchId && searchQuery.trim() && !onExactIdSearch
|
|
1662
|
+
? 'Exact ID search is unavailable in this view.'
|
|
1663
|
+
: 'No events found'}
|
|
1582
1664
|
</div>
|
|
1665
|
+
) : (
|
|
1666
|
+
<Virtuoso
|
|
1667
|
+
ref={virtuosoRef}
|
|
1668
|
+
totalCount={sortedEvents.length}
|
|
1669
|
+
overscan={20}
|
|
1670
|
+
defaultItemHeight={40}
|
|
1671
|
+
endReached={() => {
|
|
1672
|
+
if (
|
|
1673
|
+
isExactSearchActive ||
|
|
1674
|
+
!hasMoreEvents ||
|
|
1675
|
+
isLoadingMoreEvents
|
|
1676
|
+
) {
|
|
1677
|
+
return;
|
|
1678
|
+
}
|
|
1679
|
+
void onLoadMoreEvents?.();
|
|
1680
|
+
}}
|
|
1681
|
+
itemContent={(index: number) => {
|
|
1682
|
+
const ev = sortedEvents[index];
|
|
1683
|
+
return (
|
|
1684
|
+
<EventRow
|
|
1685
|
+
event={ev}
|
|
1686
|
+
index={index}
|
|
1687
|
+
isFirst={index === 0}
|
|
1688
|
+
isLast={index === sortedEvents.length - 1}
|
|
1689
|
+
isExpanded={expandedEventIds.has(ev.eventId)}
|
|
1690
|
+
onToggleExpand={toggleEventExpanded}
|
|
1691
|
+
activeGroupKey={activeGroupKey}
|
|
1692
|
+
selectedGroupKey={selectedGroupKey}
|
|
1693
|
+
selectedGroupRange={selectedGroupRange}
|
|
1694
|
+
correlationNameMap={correlationNameMap}
|
|
1695
|
+
workflowName={workflowName}
|
|
1696
|
+
durationMap={durationMap}
|
|
1697
|
+
onSelectGroup={onSelectGroup}
|
|
1698
|
+
onHoverGroup={onHoverGroup}
|
|
1699
|
+
onLoadEventData={onLoadEventData}
|
|
1700
|
+
cachedEventData={
|
|
1701
|
+
eventDataCacheRef.current.get(ev.eventId) ?? null
|
|
1702
|
+
}
|
|
1703
|
+
onCacheEventData={cacheEventData}
|
|
1704
|
+
encryptionKey={encryptionKey}
|
|
1705
|
+
onEncryptedDataDetected={handleEncryptedDataDetected}
|
|
1706
|
+
suppressGroupDimming={isExactSearchActive}
|
|
1707
|
+
/>
|
|
1708
|
+
);
|
|
1709
|
+
}}
|
|
1710
|
+
style={{ flex: 1, minHeight: 0 }}
|
|
1711
|
+
/>
|
|
1583
1712
|
)}
|
|
1713
|
+
|
|
1714
|
+
{/* Fixed footer — count + load more */}
|
|
1715
|
+
<div
|
|
1716
|
+
className="relative flex-shrink-0 flex items-center h-10 border-t px-4 text-xs"
|
|
1717
|
+
style={{
|
|
1718
|
+
borderColor: 'var(--ds-gray-alpha-200)',
|
|
1719
|
+
color: 'var(--ds-gray-900)',
|
|
1720
|
+
backgroundColor: 'var(--ds-background-100)',
|
|
1721
|
+
}}
|
|
1722
|
+
>
|
|
1723
|
+
<span>
|
|
1724
|
+
{isExactSearchActive
|
|
1725
|
+
? searchError
|
|
1726
|
+
? searchError
|
|
1727
|
+
: searchNotFound
|
|
1728
|
+
? `No events found for ${searchQuery.trim()}`
|
|
1729
|
+
: `${sortedEvents.length} event${sortedEvents.length !== 1 ? 's' : ''} for ${searchQuery.trim()}${searchResultsTruncated ? ' (results may be truncated)' : ''}`
|
|
1730
|
+
: `${sortedEvents.length} event${sortedEvents.length !== 1 ? 's' : ''} loaded`}
|
|
1731
|
+
</span>
|
|
1732
|
+
{!isExactSearchActive && hasMoreEvents && (
|
|
1733
|
+
<div className="absolute inset-0 flex items-center justify-center pointer-events-none">
|
|
1734
|
+
<div className="pointer-events-auto">
|
|
1735
|
+
<LoadMoreButton
|
|
1736
|
+
loading={isLoadingMoreEvents}
|
|
1737
|
+
onClick={() => void onLoadMoreEvents?.()}
|
|
1738
|
+
/>
|
|
1739
|
+
</div>
|
|
1740
|
+
</div>
|
|
1741
|
+
)}
|
|
1742
|
+
</div>
|
|
1584
1743
|
</div>
|
|
1585
|
-
</
|
|
1744
|
+
</DecryptClickContext.Provider>
|
|
1586
1745
|
);
|
|
1587
1746
|
}
|