@workflow/web-shared 5.0.0-beta.1 → 5.0.0-beta.3
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.map +1 -1
- package/dist/components/event-list-view.d.ts +3 -1
- package/dist/components/event-list-view.d.ts.map +1 -1
- package/dist/components/event-list-view.js +53 -53
- package/dist/components/event-list-view.js.map +1 -1
- package/dist/components/hook-actions.js.map +1 -1
- package/dist/components/index.d.ts +3 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +3 -1
- package/dist/components/index.js.map +1 -1
- 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/copy-button.js.map +1 -0
- package/dist/components/new-trace-viewer/components/event-list.d.ts +8 -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 +35 -0
- package/dist/components/new-trace-viewer/components/event-list.js.map +1 -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 +100 -0
- package/dist/components/new-trace-viewer/components/split-pane.js.map +1 -0
- package/dist/components/new-trace-viewer/components/timeline.d.ts +32 -0
- package/dist/components/new-trace-viewer/components/timeline.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/components/timeline.js +134 -0
- package/dist/components/new-trace-viewer/components/timeline.js.map +1 -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 +49 -0
- package/dist/components/new-trace-viewer/context.js.map +1 -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 +11 -0
- package/dist/components/new-trace-viewer/detail-panel.js.map +1 -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/icons.js.map +1 -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 +329 -0
- package/dist/components/new-trace-viewer/trace-viewer.js.map +1 -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/types.js.map +1 -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/util/constants.js.map +1 -0
- package/dist/components/new-trace-viewer/utils.d.ts +47 -0
- package/dist/components/new-trace-viewer/utils.d.ts.map +1 -0
- package/dist/components/new-trace-viewer/utils.js +358 -0
- package/dist/components/new-trace-viewer/utils.js.map +1 -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 +2 -2
- package/dist/components/run-trace-view.js.map +1 -1
- 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 +76 -47
- package/dist/components/sidebar/attribute-panel.js.map +1 -1
- package/dist/components/sidebar/conversation-view.js.map +1 -1
- package/dist/components/sidebar/copyable-data-block.js +1 -1
- package/dist/components/sidebar/copyable-data-block.js.map +1 -1
- package/dist/components/sidebar/detail-card.d.ts.map +1 -1
- package/dist/components/sidebar/detail-card.js +1 -1
- package/dist/components/sidebar/detail-card.js.map +1 -1
- 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 +16 -36
- package/dist/components/sidebar/entity-detail-panel.js.map +1 -1
- package/dist/components/sidebar/events-list.d.ts.map +1 -1
- package/dist/components/sidebar/events-list.js +2 -2
- package/dist/components/sidebar/events-list.js.map +1 -1
- package/dist/components/sidebar/resolve-hook-modal.js.map +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/sidebar/sidebar-data-context.js.map +1 -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 +2 -26
- package/dist/components/stream-viewer.js.map +1 -1
- package/dist/components/trace-viewer/components/map.js.map +1 -1
- package/dist/components/trace-viewer/components/markers.js.map +1 -1
- package/dist/components/trace-viewer/components/node.js.map +1 -1
- package/dist/components/trace-viewer/components/search-input.js.map +1 -1
- package/dist/components/trace-viewer/components/search.js.map +1 -1
- package/dist/components/trace-viewer/components/span-content.js.map +1 -1
- package/dist/components/trace-viewer/components/span-detail-panel.js.map +1 -1
- package/dist/components/trace-viewer/components/span-segments.js.map +1 -1
- package/dist/components/trace-viewer/components/span-strategies.js.map +1 -1
- package/dist/components/trace-viewer/components/ui.js.map +1 -1
- package/dist/components/trace-viewer/components/zoom-button.js.map +1 -1
- package/dist/components/trace-viewer/components/zoom-icons.js.map +1 -1
- package/dist/components/trace-viewer/context.js.map +1 -1
- package/dist/components/trace-viewer/index.js.map +1 -1
- package/dist/components/trace-viewer/trace-viewer.js.map +1 -1
- package/dist/components/trace-viewer/types.js.map +1 -1
- package/dist/components/trace-viewer/util/constants.js.map +1 -1
- package/dist/components/trace-viewer/util/scrollbar-width.js.map +1 -1
- package/dist/components/trace-viewer/util/timing.js.map +1 -1
- package/dist/components/trace-viewer/util/tree.js.map +1 -1
- package/dist/components/trace-viewer/util/use-immediate-style.js.map +1 -1
- package/dist/components/trace-viewer/util/use-streaming-spans.js.map +1 -1
- package/dist/components/trace-viewer/util/use-trackpad-zoom.js.map +1 -1
- package/dist/components/trace-viewer/worker.js.map +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/trace-viewer-new.js.map +1 -0
- package/dist/components/ui/alert.js.map +1 -1
- package/dist/components/ui/card.js.map +1 -1
- package/dist/components/ui/data-inspector.d.ts +38 -1
- package/dist/components/ui/data-inspector.d.ts.map +1 -1
- package/dist/components/ui/data-inspector.js +211 -21
- package/dist/components/ui/data-inspector.js.map +1 -1
- package/dist/components/ui/decrypt-button.js.map +1 -1
- package/dist/components/ui/error-card.js.map +1 -1
- package/dist/components/ui/error-stack-block.js.map +1 -1
- 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 +38 -71
- package/dist/components/ui/inspector-theme.js.map +1 -1
- package/dist/components/ui/load-more-button.js.map +1 -1
- package/dist/components/ui/menu-dropdown.js.map +1 -1
- package/dist/components/ui/skeleton.js.map +1 -1
- package/dist/components/ui/spinner.js.map +1 -1
- package/dist/components/ui/timestamp-tooltip.js.map +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 +9 -4
- package/dist/components/workflow-trace-view.js.map +1 -1
- package/dist/components/workflow-traces/event-colors.js.map +1 -1
- package/dist/components/workflow-traces/trace-colors.js.map +1 -1
- package/dist/components/workflow-traces/trace-span-construction.js +1 -1
- package/dist/components/workflow-traces/trace-span-construction.js.map +1 -1
- package/dist/components/workflow-traces/trace-time-utils.js.map +1 -1
- package/dist/hooks/use-dark-mode.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/event-analysis.js.map +1 -1
- package/dist/lib/event-materialization.js.map +1 -1
- package/dist/lib/hydration.d.ts +8 -1
- package/dist/lib/hydration.d.ts.map +1 -1
- package/dist/lib/hydration.js +32 -2
- package/dist/lib/hydration.js.map +1 -1
- 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/stream-display.js.map +1 -0
- package/dist/lib/toast.js.map +1 -1
- package/dist/lib/trace-builder.js.map +1 -1
- package/dist/lib/utils.d.ts +7 -9
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +17 -22
- package/dist/lib/utils.js.map +1 -1
- package/dist/styles.css +470 -1
- package/package.json +4 -3
- package/src/components/event-list-view.tsx +181 -173
- package/src/components/index.ts +11 -1
- package/src/components/new-trace-viewer/components/copy-button.tsx +68 -0
- package/src/components/new-trace-viewer/components/event-list.tsx +109 -0
- package/src/components/new-trace-viewer/components/split-pane.tsx +186 -0
- package/src/components/new-trace-viewer/components/timeline.tsx +378 -0
- package/src/components/new-trace-viewer/context.tsx +94 -0
- package/src/components/new-trace-viewer/detail-panel.tsx +57 -0
- package/src/components/new-trace-viewer/icons.tsx +79 -0
- package/src/components/new-trace-viewer/trace-viewer.tsx +585 -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 +524 -0
- package/src/components/run-trace-view.tsx +3 -0
- package/src/components/sidebar/attribute-panel.tsx +200 -138
- package/src/components/sidebar/copyable-data-block.tsx +1 -1
- package/src/components/sidebar/detail-card.tsx +1 -19
- package/src/components/sidebar/entity-detail-panel.tsx +91 -147
- package/src/components/sidebar/events-list.tsx +9 -6
- package/src/components/sidebar/sidebar-data-context.tsx +62 -0
- package/src/components/stream-viewer.tsx +18 -40
- package/src/components/trace-viewer-new.tsx +49 -0
- package/src/components/ui/data-inspector.tsx +436 -31
- 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 +1 -1
- package/src/index.ts +2 -0
- package/src/lib/hydration.ts +37 -0
- package/src/lib/stream-display.ts +48 -0
- package/src/lib/utils.ts +18 -23
- package/src/styles.css +470 -1
|
@@ -9,7 +9,7 @@ import { Virtuoso, type VirtuosoHandle } from 'react-virtuoso';
|
|
|
9
9
|
import { isEncryptedMarker } from '../lib/hydration';
|
|
10
10
|
import { DecryptButton } from './ui/decrypt-button';
|
|
11
11
|
import { formatDuration } from '../lib/utils';
|
|
12
|
-
import { DataInspector } from './ui/data-inspector';
|
|
12
|
+
import { DataInspector, DecryptClickContext } from './ui/data-inspector';
|
|
13
13
|
import {
|
|
14
14
|
ErrorStackBlock,
|
|
15
15
|
isStructuredErrorWithStack,
|
|
@@ -703,6 +703,8 @@ interface EventsListProps {
|
|
|
703
703
|
onDecrypt?: () => void;
|
|
704
704
|
/** Whether the encryption key is currently being fetched. */
|
|
705
705
|
isDecrypting?: boolean;
|
|
706
|
+
/** Run-level hint: the run contains encrypted data (from probe). */
|
|
707
|
+
hasEncryptedData?: boolean;
|
|
706
708
|
}
|
|
707
709
|
|
|
708
710
|
function EventRow({
|
|
@@ -1136,6 +1138,7 @@ export function EventListView({
|
|
|
1136
1138
|
onSortOrderChange,
|
|
1137
1139
|
onDecrypt,
|
|
1138
1140
|
isDecrypting = false,
|
|
1141
|
+
hasEncryptedData: hasEncryptedDataProp = false,
|
|
1139
1142
|
}: EventsListProps) {
|
|
1140
1143
|
const [internalSortOrder, setInternalSortOrder] = useState<'asc' | 'desc'>(
|
|
1141
1144
|
'asc'
|
|
@@ -1180,7 +1183,8 @@ export function EventListView({
|
|
|
1180
1183
|
setFoundEncryptedInLazyData(true);
|
|
1181
1184
|
}, []);
|
|
1182
1185
|
|
|
1183
|
-
const hasEncryptedData =
|
|
1186
|
+
const hasEncryptedData =
|
|
1187
|
+
hasEncryptedDataProp || hasEncryptedInlineData || foundEncryptedInLazyData;
|
|
1184
1188
|
|
|
1185
1189
|
const { correlationNameMap, workflowName } = useMemo(
|
|
1186
1190
|
() => buildNameMaps(events ?? null, run ?? null),
|
|
@@ -1393,195 +1397,199 @@ export function EventListView({
|
|
|
1393
1397
|
}
|
|
1394
1398
|
|
|
1395
1399
|
return (
|
|
1396
|
-
<
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
<div
|
|
1400
|
-
style
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
display: 'flex',
|
|
1404
|
-
gap: 6,
|
|
1405
|
-
}}
|
|
1406
|
-
>
|
|
1407
|
-
<label
|
|
1400
|
+
<DecryptClickContext.Provider
|
|
1401
|
+
value={onDecrypt ? { onDecrypt, isDecrypting } : undefined}
|
|
1402
|
+
>
|
|
1403
|
+
<div className="h-full flex flex-col overflow-hidden">
|
|
1404
|
+
<style>{`@keyframes workflow-dot-pulse{0%{transform:scale(1);opacity:.7}70%,100%{transform:scale(2.2);opacity:0}}`}</style>
|
|
1405
|
+
{/* Search bar + sort */}
|
|
1406
|
+
<div
|
|
1408
1407
|
style={{
|
|
1408
|
+
padding: 6,
|
|
1409
|
+
backgroundColor: 'var(--ds-background-100)',
|
|
1409
1410
|
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,
|
|
1411
|
+
gap: 6,
|
|
1418
1412
|
}}
|
|
1419
1413
|
>
|
|
1420
|
-
<
|
|
1414
|
+
<label
|
|
1421
1415
|
style={{
|
|
1422
|
-
width: 40,
|
|
1423
|
-
height: 40,
|
|
1424
1416
|
display: 'flex',
|
|
1425
1417
|
alignItems: 'center',
|
|
1426
1418
|
justifyContent: 'center',
|
|
1427
|
-
|
|
1428
|
-
|
|
1419
|
+
borderRadius: 6,
|
|
1420
|
+
boxShadow: '0 0 0 1px var(--ds-gray-alpha-400)',
|
|
1421
|
+
background: 'var(--ds-background-100)',
|
|
1422
|
+
height: 40,
|
|
1423
|
+
flex: 1,
|
|
1424
|
+
minWidth: 0,
|
|
1429
1425
|
}}
|
|
1430
1426
|
>
|
|
1431
|
-
<
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1427
|
+
<div
|
|
1428
|
+
style={{
|
|
1429
|
+
width: 40,
|
|
1430
|
+
height: 40,
|
|
1431
|
+
display: 'flex',
|
|
1432
|
+
alignItems: 'center',
|
|
1433
|
+
justifyContent: 'center',
|
|
1434
|
+
color: 'var(--ds-gray-800)',
|
|
1435
|
+
flexShrink: 0,
|
|
1436
|
+
}}
|
|
1438
1437
|
>
|
|
1439
|
-
<
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1438
|
+
<svg
|
|
1439
|
+
width={16}
|
|
1440
|
+
height={16}
|
|
1441
|
+
viewBox="0 0 16 16"
|
|
1442
|
+
fill="none"
|
|
1443
|
+
aria-hidden="true"
|
|
1444
|
+
focusable="false"
|
|
1445
|
+
>
|
|
1446
|
+
<circle
|
|
1447
|
+
cx="7"
|
|
1448
|
+
cy="7"
|
|
1449
|
+
r="4.5"
|
|
1450
|
+
stroke="currentColor"
|
|
1451
|
+
strokeWidth="1.5"
|
|
1452
|
+
/>
|
|
1453
|
+
<path
|
|
1454
|
+
d="M11.5 11.5L14 14"
|
|
1455
|
+
stroke="currentColor"
|
|
1456
|
+
strokeWidth="1.5"
|
|
1457
|
+
strokeLinecap="round"
|
|
1458
|
+
/>
|
|
1459
|
+
</svg>
|
|
1460
|
+
</div>
|
|
1461
|
+
<input
|
|
1462
|
+
type="search"
|
|
1463
|
+
placeholder="Search by name, event type, or ID…"
|
|
1464
|
+
value={searchQuery}
|
|
1465
|
+
onChange={(e) => setSearchQuery(e.target.value)}
|
|
1466
|
+
style={{
|
|
1467
|
+
marginLeft: -16,
|
|
1468
|
+
paddingInline: 12,
|
|
1469
|
+
fontFamily: 'inherit',
|
|
1470
|
+
fontSize: 14,
|
|
1471
|
+
background: 'transparent',
|
|
1472
|
+
border: 'none',
|
|
1473
|
+
outline: 'none',
|
|
1474
|
+
height: 40,
|
|
1475
|
+
width: '100%',
|
|
1476
|
+
}}
|
|
1477
|
+
/>
|
|
1478
|
+
</label>
|
|
1479
|
+
<MenuDropdown
|
|
1480
|
+
options={SORT_OPTIONS}
|
|
1481
|
+
value={effectiveSortOrder}
|
|
1482
|
+
onChange={handleSortOrderChange}
|
|
1483
|
+
/>
|
|
1484
|
+
{(hasEncryptedData || encryptionKey) && onDecrypt && (
|
|
1485
|
+
<DecryptButton
|
|
1486
|
+
decrypted={!!encryptionKey}
|
|
1487
|
+
loading={isDecrypting}
|
|
1488
|
+
onClick={onDecrypt}
|
|
1489
|
+
/>
|
|
1490
|
+
)}
|
|
1491
|
+
</div>
|
|
1492
|
+
|
|
1493
|
+
{/* Header */}
|
|
1494
|
+
<div
|
|
1495
|
+
className="flex items-center gap-0 text-[13px] font-medium h-10 border-b flex-shrink-0"
|
|
1496
|
+
style={{
|
|
1497
|
+
borderColor: 'var(--ds-gray-alpha-200)',
|
|
1498
|
+
color: 'var(--ds-gray-900)',
|
|
1499
|
+
backgroundColor: 'var(--ds-background-100)',
|
|
1500
|
+
}}
|
|
1501
|
+
>
|
|
1502
|
+
<div className="flex-shrink-0" style={{ width: GUTTER_WIDTH }} />
|
|
1503
|
+
<div className="w-5 flex-shrink-0" />
|
|
1504
|
+
<div className="min-w-0 px-4" style={{ flex: '2 1 0%' }}>
|
|
1505
|
+
Time
|
|
1453
1506
|
</div>
|
|
1454
|
-
<
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1507
|
+
<div className="min-w-0 px-4" style={{ flex: '2 1 0%' }}>
|
|
1508
|
+
Event Type
|
|
1509
|
+
</div>
|
|
1510
|
+
<div className="min-w-0 px-4" style={{ flex: '2 1 0%' }}>
|
|
1511
|
+
Name
|
|
1512
|
+
</div>
|
|
1513
|
+
<div className="min-w-0 px-4" style={{ flex: '3 1 0%' }}>
|
|
1514
|
+
Correlation ID
|
|
1515
|
+
</div>
|
|
1516
|
+
<div className="min-w-0 px-4" style={{ flex: '3 1 0%' }}>
|
|
1517
|
+
Event ID
|
|
1518
|
+
</div>
|
|
1519
|
+
</div>
|
|
1520
|
+
|
|
1521
|
+
{/* Virtualized event rows or refetching skeleton */}
|
|
1522
|
+
{isRefetching ? (
|
|
1523
|
+
<RowsSkeleton />
|
|
1524
|
+
) : (
|
|
1525
|
+
<Virtuoso
|
|
1526
|
+
ref={virtuosoRef}
|
|
1527
|
+
totalCount={sortedEvents.length}
|
|
1528
|
+
overscan={20}
|
|
1529
|
+
defaultItemHeight={40}
|
|
1530
|
+
endReached={() => {
|
|
1531
|
+
if (!hasMoreEvents || isLoadingMoreEvents) {
|
|
1532
|
+
return;
|
|
1533
|
+
}
|
|
1534
|
+
void onLoadMoreEvents?.();
|
|
1469
1535
|
}}
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1536
|
+
itemContent={(index: number) => {
|
|
1537
|
+
const ev = sortedEvents[index];
|
|
1538
|
+
return (
|
|
1539
|
+
<EventRow
|
|
1540
|
+
event={ev}
|
|
1541
|
+
index={index}
|
|
1542
|
+
isFirst={index === 0}
|
|
1543
|
+
isLast={index === sortedEvents.length - 1}
|
|
1544
|
+
isExpanded={expandedEventIds.has(ev.eventId)}
|
|
1545
|
+
onToggleExpand={toggleEventExpanded}
|
|
1546
|
+
activeGroupKey={activeGroupKey}
|
|
1547
|
+
selectedGroupKey={selectedGroupKey}
|
|
1548
|
+
selectedGroupRange={selectedGroupRange}
|
|
1549
|
+
correlationNameMap={correlationNameMap}
|
|
1550
|
+
workflowName={workflowName}
|
|
1551
|
+
durationMap={durationMap}
|
|
1552
|
+
onSelectGroup={onSelectGroup}
|
|
1553
|
+
onHoverGroup={onHoverGroup}
|
|
1554
|
+
onLoadEventData={onLoadEventData}
|
|
1555
|
+
cachedEventData={
|
|
1556
|
+
eventDataCacheRef.current.get(ev.eventId) ?? null
|
|
1557
|
+
}
|
|
1558
|
+
onCacheEventData={cacheEventData}
|
|
1559
|
+
encryptionKey={encryptionKey}
|
|
1560
|
+
onEncryptedDataDetected={handleEncryptedDataDetected}
|
|
1561
|
+
/>
|
|
1562
|
+
);
|
|
1563
|
+
}}
|
|
1564
|
+
style={{ flex: 1, minHeight: 0 }}
|
|
1482
1565
|
/>
|
|
1483
1566
|
)}
|
|
1484
|
-
</div>
|
|
1485
|
-
|
|
1486
|
-
{/* Header */}
|
|
1487
|
-
<div
|
|
1488
|
-
className="flex items-center gap-0 text-[13px] font-medium h-10 border-b flex-shrink-0"
|
|
1489
|
-
style={{
|
|
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
|
|
1511
|
-
</div>
|
|
1512
|
-
</div>
|
|
1513
1567
|
|
|
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
|
-
);
|
|
1568
|
+
{/* Fixed footer — count + load more */}
|
|
1569
|
+
<div
|
|
1570
|
+
className="relative flex-shrink-0 flex items-center h-10 border-t px-4 text-xs"
|
|
1571
|
+
style={{
|
|
1572
|
+
borderColor: 'var(--ds-gray-alpha-200)',
|
|
1573
|
+
color: 'var(--ds-gray-900)',
|
|
1574
|
+
backgroundColor: 'var(--ds-background-100)',
|
|
1556
1575
|
}}
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
<span>
|
|
1571
|
-
{sortedEvents.length} event
|
|
1572
|
-
{sortedEvents.length !== 1 ? 's' : ''} loaded
|
|
1573
|
-
</span>
|
|
1574
|
-
{hasMoreEvents && (
|
|
1575
|
-
<div className="absolute inset-0 flex items-center justify-center pointer-events-none">
|
|
1576
|
-
<div className="pointer-events-auto">
|
|
1577
|
-
<LoadMoreButton
|
|
1578
|
-
loading={isLoadingMoreEvents}
|
|
1579
|
-
onClick={() => void onLoadMoreEvents?.()}
|
|
1580
|
-
/>
|
|
1576
|
+
>
|
|
1577
|
+
<span>
|
|
1578
|
+
{sortedEvents.length} event
|
|
1579
|
+
{sortedEvents.length !== 1 ? 's' : ''} loaded
|
|
1580
|
+
</span>
|
|
1581
|
+
{hasMoreEvents && (
|
|
1582
|
+
<div className="absolute inset-0 flex items-center justify-center pointer-events-none">
|
|
1583
|
+
<div className="pointer-events-auto">
|
|
1584
|
+
<LoadMoreButton
|
|
1585
|
+
loading={isLoadingMoreEvents}
|
|
1586
|
+
onClick={() => void onLoadMoreEvents?.()}
|
|
1587
|
+
/>
|
|
1588
|
+
</div>
|
|
1581
1589
|
</div>
|
|
1582
|
-
|
|
1583
|
-
|
|
1590
|
+
)}
|
|
1591
|
+
</div>
|
|
1584
1592
|
</div>
|
|
1585
|
-
</
|
|
1593
|
+
</DecryptClickContext.Provider>
|
|
1586
1594
|
);
|
|
1587
1595
|
}
|
package/src/components/index.ts
CHANGED
|
@@ -15,15 +15,25 @@ export {
|
|
|
15
15
|
} from './hook-actions';
|
|
16
16
|
export { RunTraceView } from './run-trace-view';
|
|
17
17
|
export { ConversationView } from './sidebar/conversation-view';
|
|
18
|
+
export {
|
|
19
|
+
SidebarDataProvider,
|
|
20
|
+
type SidebarDataContextValue,
|
|
21
|
+
} from './sidebar/sidebar-data-context';
|
|
18
22
|
export type {
|
|
19
23
|
SelectedSpanInfo,
|
|
20
24
|
SpanSelectionInfo,
|
|
21
25
|
} from './sidebar/entity-detail-panel';
|
|
22
26
|
export { type StreamChunk, StreamViewer } from './stream-viewer';
|
|
23
27
|
export type { Span, SpanEvent } from './trace-viewer/types';
|
|
24
|
-
export {
|
|
28
|
+
export {
|
|
29
|
+
DataInspector,
|
|
30
|
+
type DataInspectorProps,
|
|
31
|
+
DecryptClickContext,
|
|
32
|
+
type DecryptClickContextValue,
|
|
33
|
+
} from './ui/data-inspector';
|
|
25
34
|
export { DecryptButton } from './ui/decrypt-button';
|
|
26
35
|
export { LoadMoreButton } from './ui/load-more-button';
|
|
27
36
|
export { MenuDropdown, type MenuDropdownOption } from './ui/menu-dropdown';
|
|
28
37
|
export { Spinner } from './ui/spinner';
|
|
29
38
|
export { WorkflowTraceViewer } from './workflow-trace-view';
|
|
39
|
+
export { NewTraceViewer } from './trace-viewer-new';
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Check, Copy } from 'lucide-react';
|
|
4
|
+
import { type JSX, useEffect, useRef, useState } from 'react';
|
|
5
|
+
import { cn } from '../../../lib/utils';
|
|
6
|
+
|
|
7
|
+
interface CopyButtonProps {
|
|
8
|
+
copyText: string;
|
|
9
|
+
ariaLabel: string;
|
|
10
|
+
className?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function CopyButton({
|
|
14
|
+
copyText,
|
|
15
|
+
ariaLabel,
|
|
16
|
+
className,
|
|
17
|
+
}: CopyButtonProps): JSX.Element {
|
|
18
|
+
const [copied, setCopied] = useState(false);
|
|
19
|
+
const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
20
|
+
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
return () => {
|
|
23
|
+
if (timeoutRef.current) {
|
|
24
|
+
clearTimeout(timeoutRef.current);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}, []);
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<button
|
|
31
|
+
type="button"
|
|
32
|
+
aria-label={ariaLabel}
|
|
33
|
+
className={cn(
|
|
34
|
+
'cursor-pointer text-gray-800 hover:text-gray-1000 bg-transparent border-none p-1 m-0',
|
|
35
|
+
className
|
|
36
|
+
)}
|
|
37
|
+
onClick={(e) => {
|
|
38
|
+
e.stopPropagation();
|
|
39
|
+
if (timeoutRef.current) {
|
|
40
|
+
clearTimeout(timeoutRef.current);
|
|
41
|
+
}
|
|
42
|
+
void navigator.clipboard.writeText(copyText).then(() => {
|
|
43
|
+
setCopied(true);
|
|
44
|
+
timeoutRef.current = setTimeout(() => setCopied(false), 1000);
|
|
45
|
+
});
|
|
46
|
+
}}
|
|
47
|
+
>
|
|
48
|
+
<div className="relative w-3 h-3">
|
|
49
|
+
<div
|
|
50
|
+
className={cn(
|
|
51
|
+
'absolute inset-0 flex items-center justify-center transition-all duration-150 ease-out',
|
|
52
|
+
copied ? 'scale-100 opacity-100' : 'scale-0 opacity-0'
|
|
53
|
+
)}
|
|
54
|
+
>
|
|
55
|
+
<Check className="w-3 h-3" />
|
|
56
|
+
</div>
|
|
57
|
+
<div
|
|
58
|
+
className={cn(
|
|
59
|
+
'absolute inset-0 flex items-center justify-center transition-all duration-150 ease-out',
|
|
60
|
+
copied ? 'scale-0 opacity-0' : 'scale-100 opacity-100'
|
|
61
|
+
)}
|
|
62
|
+
>
|
|
63
|
+
<Copy className="w-3 h-3" />
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
</button>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { Circle } from 'lucide-react';
|
|
2
|
+
import { cn } from '../../../lib/utils';
|
|
3
|
+
import type { Span } from '../../trace-viewer/types';
|
|
4
|
+
import { formatDuration, getHighResInMs } from '../../trace-viewer/util/timing';
|
|
5
|
+
import {
|
|
6
|
+
WorkflowIcon,
|
|
7
|
+
WebhookIcon,
|
|
8
|
+
SleepIcon,
|
|
9
|
+
StepForwardIcon,
|
|
10
|
+
} from '../icons';
|
|
11
|
+
|
|
12
|
+
interface EventStyle {
|
|
13
|
+
icon: React.ComponentType<{ className?: string }>;
|
|
14
|
+
className: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const eventStyles: Record<string, EventStyle> = {
|
|
18
|
+
run: { icon: WorkflowIcon, className: 'text-blue-900' },
|
|
19
|
+
step: { icon: StepForwardIcon, className: 'text-green-900' },
|
|
20
|
+
hook: { icon: WebhookIcon, className: 'text-yellow-900' },
|
|
21
|
+
sleep: { icon: SleepIcon, className: 'text-gray-900' },
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const defaultStyle: EventStyle = {
|
|
25
|
+
icon: Circle,
|
|
26
|
+
className: 'text-gray-900',
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
function getEventStyle(resource: string, isErrored: boolean): EventStyle {
|
|
30
|
+
const style = eventStyles[resource] ?? defaultStyle;
|
|
31
|
+
return {
|
|
32
|
+
icon: style.icon,
|
|
33
|
+
className: cn(isErrored ? 'text-red-900' : style.className),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const EventRow = ({
|
|
38
|
+
span,
|
|
39
|
+
isSelected,
|
|
40
|
+
onSelectSpan,
|
|
41
|
+
}: {
|
|
42
|
+
span: Span;
|
|
43
|
+
isSelected: boolean;
|
|
44
|
+
onSelectSpan: (spanId: string) => void;
|
|
45
|
+
}) => {
|
|
46
|
+
const durationMs = getHighResInMs(span.duration);
|
|
47
|
+
const isErrored =
|
|
48
|
+
(span.attributes.data as Record<string, unknown>).status === 'failed';
|
|
49
|
+
const { icon: Icon, className: tagClassName } = getEventStyle(
|
|
50
|
+
span.resource,
|
|
51
|
+
isErrored
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<li
|
|
56
|
+
className="overflow-clip group"
|
|
57
|
+
role="treeitem"
|
|
58
|
+
aria-selected={isSelected}
|
|
59
|
+
aria-expanded={isSelected}
|
|
60
|
+
aria-level={1}
|
|
61
|
+
onClick={() => onSelectSpan(span.spanId)}
|
|
62
|
+
>
|
|
63
|
+
<div className="hover:bg-gray-100 group-aria-selected:bg-gray-100 group-aria-selected:hover:bg-gray-200 hover:aria-selected:bg-gray-100 rounded-sm px-2 h-[34px] py-1.5 flex">
|
|
64
|
+
<div className="flex items-center gap-2">
|
|
65
|
+
<span className={tagClassName}>
|
|
66
|
+
<Icon className="w-4 h-4" />
|
|
67
|
+
</span>
|
|
68
|
+
<span className="text-label-14">{span.name}</span>
|
|
69
|
+
</div>
|
|
70
|
+
<div className="ml-auto">
|
|
71
|
+
<span className="text-label-14 text-gray-900 tabular-nums">
|
|
72
|
+
{formatDuration(durationMs)}
|
|
73
|
+
</span>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
</li>
|
|
77
|
+
);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const EventList = ({
|
|
81
|
+
spans,
|
|
82
|
+
activeSpanId,
|
|
83
|
+
onSelectSpan,
|
|
84
|
+
}: {
|
|
85
|
+
spans: Span[];
|
|
86
|
+
activeSpanId: string | null;
|
|
87
|
+
onSelectSpan: (spanId: string) => void;
|
|
88
|
+
}) => {
|
|
89
|
+
return (
|
|
90
|
+
<ul
|
|
91
|
+
id="event-list"
|
|
92
|
+
role="tree"
|
|
93
|
+
className="block min-h-0 overflow-visible px-2 py-2"
|
|
94
|
+
>
|
|
95
|
+
{spans.map((span) => {
|
|
96
|
+
return (
|
|
97
|
+
<EventRow
|
|
98
|
+
key={span.spanId}
|
|
99
|
+
span={span}
|
|
100
|
+
isSelected={span.spanId === activeSpanId}
|
|
101
|
+
onSelectSpan={onSelectSpan}
|
|
102
|
+
/>
|
|
103
|
+
);
|
|
104
|
+
})}
|
|
105
|
+
</ul>
|
|
106
|
+
);
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
export default EventList;
|