@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,16 @@
|
|
|
3
3
|
import { parseStepName, parseWorkflowName } from '@workflow/utils/parse-name';
|
|
4
4
|
import type { Event, Hook, Step, WorkflowRun } from '@workflow/world';
|
|
5
5
|
import type { ModelMessage } from 'ai';
|
|
6
|
-
import { Lock } from 'lucide-react';
|
|
7
6
|
import type { KeyboardEvent, ReactNode } from 'react';
|
|
8
|
-
import { useCallback, useMemo, useState } from 'react';
|
|
7
|
+
import { useCallback, useContext, useMemo, useState } from 'react';
|
|
9
8
|
import { isEncryptedMarker, isExpiredMarker } from '../../lib/hydration';
|
|
10
9
|
import { useToast } from '../../lib/toast';
|
|
11
10
|
import { extractConversation, isDoStreamStep } from '../../lib/utils';
|
|
12
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
DecryptClickContext,
|
|
13
|
+
RunClickContext,
|
|
14
|
+
StreamClickContext,
|
|
15
|
+
} from '../ui/data-inspector';
|
|
13
16
|
import { ErrorCard } from '../ui/error-card';
|
|
14
17
|
import {
|
|
15
18
|
ErrorStackBlock,
|
|
@@ -17,8 +20,10 @@ import {
|
|
|
17
20
|
} from '../ui/error-stack-block';
|
|
18
21
|
import { Skeleton } from '../ui/skeleton';
|
|
19
22
|
import { TimestampTooltip } from '../ui/timestamp-tooltip';
|
|
23
|
+
import { CopyButton } from '../new-trace-viewer/components/copy-button';
|
|
24
|
+
import { MiddleTruncate } from '../new-trace-viewer/components/middle-truncate/middle-truncate';
|
|
20
25
|
import { ConversationView } from './conversation-view';
|
|
21
|
-
import { CopyableDataBlock } from './copyable-data-block';
|
|
26
|
+
import { CopyableDataBlock, EncryptedDataBlock } from './copyable-data-block';
|
|
22
27
|
import { DetailCard } from './detail-card';
|
|
23
28
|
|
|
24
29
|
/**
|
|
@@ -146,7 +151,7 @@ function ConversationWithTabs({
|
|
|
146
151
|
);
|
|
147
152
|
|
|
148
153
|
return (
|
|
149
|
-
<DetailCard summary=
|
|
154
|
+
<DetailCard summary="Input">
|
|
150
155
|
<TabbedContainer
|
|
151
156
|
tabs={conversationTabs}
|
|
152
157
|
activeTab={activeTab}
|
|
@@ -175,24 +180,8 @@ function ConversationWithTabs({
|
|
|
175
180
|
* Render a value with the shared DataInspector (ObjectInspector with
|
|
176
181
|
* custom theming, nodeRenderer for StreamRef/ClassInstanceRef, etc.)
|
|
177
182
|
*/
|
|
178
|
-
/**
|
|
179
|
-
* Inline display for an encrypted field — no expand, just a flat label
|
|
180
|
-
* with the lucide Lock icon matching the title bar Decrypt button.
|
|
181
|
-
*/
|
|
182
183
|
function EncryptedFieldBlock() {
|
|
183
|
-
return
|
|
184
|
-
<div
|
|
185
|
-
className="flex items-center gap-1.5 rounded-md border px-3 py-2 text-xs"
|
|
186
|
-
style={{
|
|
187
|
-
borderColor: 'var(--ds-gray-300)',
|
|
188
|
-
backgroundColor: 'var(--ds-gray-100)',
|
|
189
|
-
color: 'var(--ds-gray-700)',
|
|
190
|
-
}}
|
|
191
|
-
>
|
|
192
|
-
<Lock className="h-3 w-3" />
|
|
193
|
-
<span className="font-medium">Encrypted</span>
|
|
194
|
-
</div>
|
|
195
|
-
);
|
|
184
|
+
return <EncryptedDataBlock />;
|
|
196
185
|
}
|
|
197
186
|
|
|
198
187
|
/**
|
|
@@ -237,7 +226,9 @@ type AttributeKey =
|
|
|
237
226
|
| 'workflowCoreVersion'
|
|
238
227
|
| 'receivedCount'
|
|
239
228
|
| 'lastReceivedAt'
|
|
240
|
-
| 'disposedAt'
|
|
229
|
+
| 'disposedAt'
|
|
230
|
+
| 'isSystem'
|
|
231
|
+
| 'errorCode';
|
|
241
232
|
|
|
242
233
|
const attributeOrder: AttributeKey[] = [
|
|
243
234
|
'workflowName',
|
|
@@ -286,8 +277,30 @@ const sortByAttributeOrder = (a: string, b: string): number => {
|
|
|
286
277
|
* Display names for attributes that should render differently from their key.
|
|
287
278
|
*/
|
|
288
279
|
const attributeDisplayNames: Partial<Record<AttributeKey, string>> = {
|
|
280
|
+
moduleSpecifier: 'Module',
|
|
281
|
+
workflowName: 'Workflow Name',
|
|
282
|
+
stepName: 'Step Name',
|
|
283
|
+
stepId: 'Step ID',
|
|
284
|
+
hookId: 'Hook ID',
|
|
285
|
+
attempt: 'Attempts',
|
|
286
|
+
eventId: 'Event ID',
|
|
287
|
+
runId: 'Run ID',
|
|
288
|
+
token: 'Token',
|
|
289
|
+
eventType: 'Event Type',
|
|
290
|
+
correlationId: 'Correlation ID',
|
|
291
|
+
deploymentId: 'Deployment ID',
|
|
292
|
+
specVersion: 'Spec Version',
|
|
289
293
|
workflowCoreVersion: '@workflow/core version',
|
|
290
|
-
|
|
294
|
+
createdAt: 'Created',
|
|
295
|
+
startedAt: 'Started',
|
|
296
|
+
updatedAt: 'Updated',
|
|
297
|
+
completedAt: 'Completed',
|
|
298
|
+
expiredAt: 'Expired',
|
|
299
|
+
retryAfter: 'Retry After',
|
|
300
|
+
resumeAt: 'Resume',
|
|
301
|
+
lastReceivedAt: 'Last Received',
|
|
302
|
+
disposedAt: 'Disposed',
|
|
303
|
+
receivedCount: 'Times Resolved',
|
|
291
304
|
};
|
|
292
305
|
|
|
293
306
|
/**
|
|
@@ -374,21 +387,21 @@ const attributeToDisplayFn: Record<
|
|
|
374
387
|
(value: unknown, context?: DisplayContext) => null | string | ReactNode
|
|
375
388
|
> = {
|
|
376
389
|
// Names that need pretty-printing
|
|
377
|
-
workflowName: (
|
|
378
|
-
parseWorkflowName(String(value))?.shortName ?? '?',
|
|
390
|
+
workflowName: (_value: unknown) => null,
|
|
379
391
|
moduleSpecifier: (value: unknown) => getModuleSpecifierFromName(value),
|
|
380
|
-
stepName: (
|
|
392
|
+
stepName: (_value: unknown) => null,
|
|
381
393
|
// IDs
|
|
382
|
-
runId: (
|
|
394
|
+
runId: (_value: unknown) => null,
|
|
383
395
|
stepId: (value: unknown) => String(value),
|
|
384
396
|
hookId: (value: unknown) => String(value),
|
|
385
397
|
eventId: (value: unknown) => String(value),
|
|
386
398
|
// Run/step details
|
|
387
|
-
status: (
|
|
399
|
+
status: (_value: unknown) => null,
|
|
388
400
|
attempt: (value: unknown) => String(value),
|
|
389
401
|
// Hook details
|
|
390
402
|
token: (value: unknown) => String(value),
|
|
391
403
|
isWebhook: (value: unknown) => String(value),
|
|
404
|
+
isSystem: (value: unknown) => String(value),
|
|
392
405
|
receivedCount: (value: unknown) => String(value),
|
|
393
406
|
lastReceivedAt: localMillisecondTimeOrNull,
|
|
394
407
|
disposedAt: localMillisecondTimeOrNull,
|
|
@@ -404,23 +417,36 @@ const attributeToDisplayFn: Record<
|
|
|
404
417
|
projectId: (_value: unknown) => null,
|
|
405
418
|
environment: (_value: unknown) => null,
|
|
406
419
|
executionContext: (_value: unknown) => null,
|
|
420
|
+
// Attributes MVP — string-string metadata attached to the run.
|
|
421
|
+
// Rendered as a JSON block; if empty/missing, hidden by the
|
|
422
|
+
// hasDisplayContent gate above.
|
|
423
|
+
attributes: (value: unknown) => {
|
|
424
|
+
if (!hasDisplayContent(value)) return null;
|
|
425
|
+
return JsonBlock(value);
|
|
426
|
+
},
|
|
407
427
|
// Dates — wrapped with TimestampTooltip showing UTC/local + relative time
|
|
408
428
|
createdAt: timestampWithTooltipOrNull,
|
|
409
429
|
startedAt: timestampWithTooltipOrNull,
|
|
410
|
-
updatedAt:
|
|
430
|
+
updatedAt: (_value: unknown) => null,
|
|
411
431
|
completedAt: timestampWithTooltipOrNull,
|
|
412
|
-
expiredAt:
|
|
432
|
+
expiredAt: (_value: unknown) => null,
|
|
413
433
|
retryAfter: timestampWithTooltipOrNull,
|
|
414
434
|
resumeAt: timestampWithTooltipOrNull,
|
|
415
435
|
// Resolved attributes, won't actually use this function
|
|
416
436
|
metadata: (value: unknown) => {
|
|
417
437
|
if (!hasDisplayContent(value)) return null;
|
|
418
|
-
if (isEncryptedMarker(value)) return <
|
|
438
|
+
if (isEncryptedMarker(value)) return <EncryptedDataBlock />;
|
|
419
439
|
if (isExpiredMarker(value)) return <ExpiredFieldBlock />;
|
|
420
440
|
return JsonBlock(value);
|
|
421
441
|
},
|
|
422
442
|
input: (value: unknown, context?: DisplayContext) => {
|
|
423
|
-
if (isEncryptedMarker(value))
|
|
443
|
+
if (isEncryptedMarker(value)) {
|
|
444
|
+
return (
|
|
445
|
+
<DetailCard summary="Input">
|
|
446
|
+
<EncryptedFieldBlock />
|
|
447
|
+
</DetailCard>
|
|
448
|
+
);
|
|
449
|
+
}
|
|
424
450
|
if (isExpiredMarker(value)) return <ExpiredFieldBlock />;
|
|
425
451
|
// Check if input has args + closure vars structure
|
|
426
452
|
if (value && typeof value === 'object' && 'args' in value) {
|
|
@@ -429,8 +455,6 @@ const attributeToDisplayFn: Record<
|
|
|
429
455
|
closureVars?: Record<string, unknown>;
|
|
430
456
|
thisVal?: unknown;
|
|
431
457
|
};
|
|
432
|
-
const argCount = Array.isArray(args) ? args.length : 0;
|
|
433
|
-
const argLabel = argCount === 1 ? 'argument' : 'arguments';
|
|
434
458
|
const hasClosureVars = hasDisplayContent(closureVars);
|
|
435
459
|
const hasThisVal = hasDisplayContent(thisVal);
|
|
436
460
|
const hasArgs = hasDisplayContent(args);
|
|
@@ -459,22 +483,12 @@ const attributeToDisplayFn: Record<
|
|
|
459
483
|
|
|
460
484
|
// Don't render an empty "Input (0 arguments)" card when no input exists.
|
|
461
485
|
if (!hasArgs && !hasClosureVars && !hasThisVal) {
|
|
462
|
-
return (
|
|
463
|
-
<DetailCard
|
|
464
|
-
summary="Input (no data)"
|
|
465
|
-
disabled
|
|
466
|
-
summaryClassName="text-base py-2"
|
|
467
|
-
/>
|
|
468
|
-
);
|
|
486
|
+
return <DetailCard summary="Input (no data)" disabled />;
|
|
469
487
|
}
|
|
470
488
|
|
|
471
489
|
return (
|
|
472
490
|
<>
|
|
473
|
-
<DetailCard
|
|
474
|
-
summary={`Input (${argCount} ${argLabel})`}
|
|
475
|
-
summaryClassName="text-base py-2"
|
|
476
|
-
contentClassName="mt-0"
|
|
477
|
-
>
|
|
491
|
+
<DetailCard summary="Input">
|
|
478
492
|
{Array.isArray(args)
|
|
479
493
|
? args.map((v, i) => (
|
|
480
494
|
<div className="mt-2 first:mt-0" key={i}>
|
|
@@ -489,30 +503,18 @@ const attributeToDisplayFn: Record<
|
|
|
489
503
|
</DetailCard>
|
|
490
504
|
)}
|
|
491
505
|
{hasThisVal && (
|
|
492
|
-
<DetailCard summary="
|
|
506
|
+
<DetailCard summary="Context">{JsonBlock(thisVal)}</DetailCard>
|
|
493
507
|
)}
|
|
494
508
|
</>
|
|
495
509
|
);
|
|
496
510
|
}
|
|
497
511
|
|
|
498
512
|
// Fallback: treat as plain array or object
|
|
499
|
-
const argCount = Array.isArray(value) ? value.length : 0;
|
|
500
|
-
const argLabel = argCount === 1 ? 'argument' : 'arguments';
|
|
501
513
|
if (!hasDisplayContent(value)) {
|
|
502
|
-
return (
|
|
503
|
-
<DetailCard
|
|
504
|
-
summary="Input (no data)"
|
|
505
|
-
disabled
|
|
506
|
-
summaryClassName="text-base py-2"
|
|
507
|
-
/>
|
|
508
|
-
);
|
|
514
|
+
return <DetailCard summary="Input (no data)" disabled />;
|
|
509
515
|
}
|
|
510
516
|
return (
|
|
511
|
-
<DetailCard
|
|
512
|
-
summary={`Input (${argCount} ${argLabel})`}
|
|
513
|
-
summaryClassName="text-base py-2"
|
|
514
|
-
contentClassName="mt-0"
|
|
515
|
-
>
|
|
517
|
+
<DetailCard summary="Input">
|
|
516
518
|
{Array.isArray(value)
|
|
517
519
|
? value.map((v, i) => (
|
|
518
520
|
<div className="mt-2 first:mt-0" key={i}>
|
|
@@ -524,21 +526,25 @@ const attributeToDisplayFn: Record<
|
|
|
524
526
|
);
|
|
525
527
|
},
|
|
526
528
|
output: (value: unknown) => {
|
|
529
|
+
if (isEncryptedMarker(value)) {
|
|
530
|
+
return (
|
|
531
|
+
<DetailCard summary="Output">
|
|
532
|
+
<EncryptedFieldBlock />
|
|
533
|
+
</DetailCard>
|
|
534
|
+
);
|
|
535
|
+
}
|
|
527
536
|
if (!hasDisplayContent(value)) return null;
|
|
528
|
-
if (isEncryptedMarker(value)) return <EncryptedFieldBlock />;
|
|
529
537
|
if (isExpiredMarker(value)) return <ExpiredFieldBlock />;
|
|
530
|
-
return (
|
|
531
|
-
<DetailCard
|
|
532
|
-
summary="Output"
|
|
533
|
-
summaryClassName="text-base py-2"
|
|
534
|
-
contentClassName="mt-0"
|
|
535
|
-
>
|
|
536
|
-
{JsonBlock(value)}
|
|
537
|
-
</DetailCard>
|
|
538
|
-
);
|
|
538
|
+
return <DetailCard summary="Output">{JsonBlock(value)}</DetailCard>;
|
|
539
539
|
},
|
|
540
540
|
error: (value: unknown) => {
|
|
541
|
-
if (isEncryptedMarker(value))
|
|
541
|
+
if (isEncryptedMarker(value)) {
|
|
542
|
+
return (
|
|
543
|
+
<DetailCard summary="Error" defaultOpen>
|
|
544
|
+
<EncryptedFieldBlock />
|
|
545
|
+
</DetailCard>
|
|
546
|
+
);
|
|
547
|
+
}
|
|
542
548
|
if (isExpiredMarker(value)) return <ExpiredFieldBlock />;
|
|
543
549
|
if (!hasDisplayContent(value)) return null;
|
|
544
550
|
|
|
@@ -546,31 +552,37 @@ const attributeToDisplayFn: Record<
|
|
|
546
552
|
// pre-formatted text. Otherwise fall back to the raw JSON viewer.
|
|
547
553
|
if (isStructuredErrorWithStack(value)) {
|
|
548
554
|
return (
|
|
549
|
-
<DetailCard
|
|
550
|
-
summary="Error"
|
|
551
|
-
summaryClassName="text-base py-2"
|
|
552
|
-
contentClassName="mt-0"
|
|
553
|
-
>
|
|
555
|
+
<DetailCard summary="Error" defaultOpen>
|
|
554
556
|
<ErrorStackBlock value={value} />
|
|
555
557
|
</DetailCard>
|
|
556
558
|
);
|
|
557
559
|
}
|
|
558
560
|
|
|
559
561
|
return (
|
|
560
|
-
<DetailCard
|
|
561
|
-
summary="Error"
|
|
562
|
-
summaryClassName="text-base py-2"
|
|
563
|
-
contentClassName="mt-0"
|
|
564
|
-
>
|
|
562
|
+
<DetailCard summary="Error" defaultOpen>
|
|
565
563
|
{JsonBlock(value)}
|
|
566
564
|
</DetailCard>
|
|
567
565
|
);
|
|
568
566
|
},
|
|
569
567
|
eventData: (value: unknown) => {
|
|
570
|
-
if (isEncryptedMarker(value))
|
|
568
|
+
if (isEncryptedMarker(value)) {
|
|
569
|
+
return (
|
|
570
|
+
<DetailCard summary="Event Data" defaultOpen>
|
|
571
|
+
<EncryptedFieldBlock />
|
|
572
|
+
</DetailCard>
|
|
573
|
+
);
|
|
574
|
+
}
|
|
571
575
|
if (isExpiredMarker(value)) return <ExpiredFieldBlock />;
|
|
572
576
|
if (!hasDisplayContent(value)) return null;
|
|
573
|
-
return
|
|
577
|
+
return (
|
|
578
|
+
<DetailCard summary="Event Data" defaultOpen>
|
|
579
|
+
{JsonBlock(value)}
|
|
580
|
+
</DetailCard>
|
|
581
|
+
);
|
|
582
|
+
},
|
|
583
|
+
errorCode: (value: unknown) => {
|
|
584
|
+
if (typeof value !== 'string' || value.length === 0) return null;
|
|
585
|
+
return String(value);
|
|
574
586
|
},
|
|
575
587
|
};
|
|
576
588
|
|
|
@@ -582,6 +594,15 @@ const resolvableAttributes = [
|
|
|
582
594
|
'eventData',
|
|
583
595
|
];
|
|
584
596
|
|
|
597
|
+
// Attributes whose displayFn renders its own section header via DetailCard,
|
|
598
|
+
// so the outer AttributeBlock should not duplicate the label.
|
|
599
|
+
const selfHeaderedAttributes = new Set([
|
|
600
|
+
'input',
|
|
601
|
+
'output',
|
|
602
|
+
'error',
|
|
603
|
+
'eventData',
|
|
604
|
+
]);
|
|
605
|
+
|
|
585
606
|
const ExpiredDataMessage = () => (
|
|
586
607
|
<div
|
|
587
608
|
className="text-copy-12 rounded-md border p-4 my-2"
|
|
@@ -595,6 +616,13 @@ const ExpiredDataMessage = () => (
|
|
|
595
616
|
</div>
|
|
596
617
|
);
|
|
597
618
|
|
|
619
|
+
const copyableBasicAttributes = new Set<AttributeKey>([
|
|
620
|
+
'stepId',
|
|
621
|
+
'hookId',
|
|
622
|
+
'eventId',
|
|
623
|
+
'deploymentId',
|
|
624
|
+
]);
|
|
625
|
+
|
|
598
626
|
export const AttributeBlock = ({
|
|
599
627
|
attribute,
|
|
600
628
|
value,
|
|
@@ -608,24 +636,26 @@ export const AttributeBlock = ({
|
|
|
608
636
|
inline?: boolean;
|
|
609
637
|
context?: DisplayContext;
|
|
610
638
|
}) => {
|
|
639
|
+
const decryptCtx = useContext(DecryptClickContext);
|
|
611
640
|
const isExpandableLoadingTarget =
|
|
612
641
|
attribute === 'input' ||
|
|
613
642
|
attribute === 'output' ||
|
|
614
643
|
attribute === 'eventData';
|
|
615
644
|
if (isLoading && isExpandableLoadingTarget && !hasDisplayContent(value)) {
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
645
|
+
const label =
|
|
646
|
+
attribute === 'eventData'
|
|
647
|
+
? 'Event Data'
|
|
648
|
+
: attribute === 'output'
|
|
649
|
+
? 'Output'
|
|
650
|
+
: 'Input';
|
|
651
|
+
if (decryptCtx?.hasEncryptedData) {
|
|
652
|
+
return (
|
|
653
|
+
<DetailCard summary={label} defaultOpen={attribute === 'eventData'}>
|
|
654
|
+
<EncryptedFieldBlock />
|
|
655
|
+
</DetailCard>
|
|
656
|
+
);
|
|
657
|
+
}
|
|
658
|
+
return <DetailCard summary={label} />;
|
|
629
659
|
}
|
|
630
660
|
|
|
631
661
|
const displayFn =
|
|
@@ -654,6 +684,10 @@ export const AttributeBlock = ({
|
|
|
654
684
|
);
|
|
655
685
|
}
|
|
656
686
|
|
|
687
|
+
if (selfHeaderedAttributes.has(attribute)) {
|
|
688
|
+
return <>{displayValue}</>;
|
|
689
|
+
}
|
|
690
|
+
|
|
657
691
|
return (
|
|
658
692
|
<div className="relative">
|
|
659
693
|
{typeof isLoading === 'boolean' && isLoading && (
|
|
@@ -664,14 +698,8 @@ export const AttributeBlock = ({
|
|
|
664
698
|
/>
|
|
665
699
|
</div>
|
|
666
700
|
)}
|
|
667
|
-
<div
|
|
668
|
-
|
|
669
|
-
className={`my-2 flex flex-col ${attribute === 'input' || attribute === 'output' || attribute === 'error' ? 'gap-2 my-3.5' : 'gap-0'}`}
|
|
670
|
-
>
|
|
671
|
-
<span
|
|
672
|
-
className={`${attribute === 'input' || attribute === 'output' || attribute === 'error' ? 'text-base' : 'text-xs'} font-medium first-letter:uppercase`}
|
|
673
|
-
style={{ color: 'var(--ds-gray-700)' }}
|
|
674
|
-
>
|
|
701
|
+
<div key={attribute} className="my-2 flex flex-col gap-0">
|
|
702
|
+
<span className="text-label-14 text-gray-1000 font-medium first-letter:uppercase">
|
|
675
703
|
{attribute}
|
|
676
704
|
</span>
|
|
677
705
|
<span className="text-xs" style={{ color: 'var(--ds-gray-1000)' }}>
|
|
@@ -689,6 +717,9 @@ export const AttributePanel = ({
|
|
|
689
717
|
error,
|
|
690
718
|
expiredAt,
|
|
691
719
|
onStreamClick,
|
|
720
|
+
onRunClick,
|
|
721
|
+
onDecrypt,
|
|
722
|
+
isDecrypting = false,
|
|
692
723
|
resource,
|
|
693
724
|
}: {
|
|
694
725
|
data: Record<string, unknown>;
|
|
@@ -698,6 +729,12 @@ export const AttributePanel = ({
|
|
|
698
729
|
expiredAt?: string | Date;
|
|
699
730
|
/** Callback when a stream reference is clicked */
|
|
700
731
|
onStreamClick?: (streamId: string) => void;
|
|
732
|
+
/** Callback when a run reference is clicked */
|
|
733
|
+
onRunClick?: (runId: string) => void;
|
|
734
|
+
/** Callback when an encrypted marker is clicked (triggers decryption) */
|
|
735
|
+
onDecrypt?: () => void;
|
|
736
|
+
/** Whether decryption is currently in progress */
|
|
737
|
+
isDecrypting?: boolean;
|
|
701
738
|
/** Resource type of the selected span — used to show targeted loading skeletons. */
|
|
702
739
|
resource?: string;
|
|
703
740
|
}) => {
|
|
@@ -731,7 +768,9 @@ export const AttributePanel = ({
|
|
|
731
768
|
|
|
732
769
|
if (!isLoading) return present;
|
|
733
770
|
|
|
734
|
-
|
|
771
|
+
if (resource === 'sleep') return present;
|
|
772
|
+
|
|
773
|
+
// During loading, ensure sections appear so their skeletons render
|
|
735
774
|
// in the correct position (above the events section).
|
|
736
775
|
const loadingDefaults = ['input', 'output'];
|
|
737
776
|
for (const key of loadingDefaults) {
|
|
@@ -740,7 +779,7 @@ export const AttributePanel = ({
|
|
|
740
779
|
}
|
|
741
780
|
}
|
|
742
781
|
return present.sort(sortByAttributeOrder);
|
|
743
|
-
}, [displayData, isLoading]);
|
|
782
|
+
}, [displayData, isLoading, resource]);
|
|
744
783
|
|
|
745
784
|
// Filter out attributes that return null
|
|
746
785
|
const visibleBasicAttributes = basicAttributes.filter((attribute) => {
|
|
@@ -796,50 +835,46 @@ export const AttributePanel = ({
|
|
|
796
835
|
});
|
|
797
836
|
}, []);
|
|
798
837
|
|
|
838
|
+
const outerDecryptCtx = useContext(DecryptClickContext);
|
|
839
|
+
const decryptValue = onDecrypt
|
|
840
|
+
? {
|
|
841
|
+
onDecrypt,
|
|
842
|
+
isDecrypting,
|
|
843
|
+
hasEncryptedData: outerDecryptCtx?.hasEncryptedData,
|
|
844
|
+
}
|
|
845
|
+
: outerDecryptCtx;
|
|
846
|
+
|
|
799
847
|
return (
|
|
800
|
-
<
|
|
801
|
-
<
|
|
802
|
-
{
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
showResumeAtSkeleton;
|
|
825
|
-
|
|
826
|
-
return (
|
|
827
|
-
<div key={attribute} className="py-1">
|
|
828
|
-
<div className="flex min-h-[32px] items-center justify-between gap-4 rounded-sm px-2.5 py-1">
|
|
829
|
-
<span
|
|
830
|
-
className={
|
|
831
|
-
shouldCapitalizeLabel
|
|
832
|
-
? 'text-[14px] first-letter:uppercase'
|
|
833
|
-
: 'text-[14px]'
|
|
834
|
-
}
|
|
835
|
-
style={{ color: 'var(--ds-gray-700)' }}
|
|
836
|
-
>
|
|
848
|
+
<RunClickContext.Provider value={onRunClick}>
|
|
849
|
+
<StreamClickContext.Provider value={onStreamClick}>
|
|
850
|
+
<DecryptClickContext.Provider value={decryptValue}>
|
|
851
|
+
{visibleBasicAttributes.length > 0 && (
|
|
852
|
+
<div className="flex flex-col overflow-hidden divide-y divide-gray-alpha-400 mb-3">
|
|
853
|
+
{orderedBasicAttributes.map((attribute) => {
|
|
854
|
+
const displayValue = attributeToDisplayFn[
|
|
855
|
+
attribute as keyof typeof attributeToDisplayFn
|
|
856
|
+
]?.(displayData[attribute as keyof typeof displayData]);
|
|
857
|
+
const isModuleSpecifier = attribute === 'moduleSpecifier';
|
|
858
|
+
const isCopyableBasicAttribute =
|
|
859
|
+
copyableBasicAttributes.has(attribute as AttributeKey) &&
|
|
860
|
+
typeof displayValue === 'string';
|
|
861
|
+
const moduleSpecifierValue =
|
|
862
|
+
typeof displayValue === 'string'
|
|
863
|
+
? displayValue
|
|
864
|
+
: String(displayValue ?? displayData.moduleSpecifier ?? '');
|
|
865
|
+
|
|
866
|
+
return (
|
|
867
|
+
<div
|
|
868
|
+
className="flex items-center justify-between py-2"
|
|
869
|
+
key={attribute}
|
|
870
|
+
>
|
|
871
|
+
<span className="text-label-14 text-gray-900">
|
|
837
872
|
{getAttributeDisplayName(attribute)}
|
|
838
873
|
</span>
|
|
839
874
|
{isModuleSpecifier ? (
|
|
840
875
|
<button
|
|
841
876
|
type="button"
|
|
842
|
-
className="min-w-0 max-w-[70%] truncate text-right text-
|
|
877
|
+
className="min-w-0 max-w-[70%] truncate text-right text-label-13 font-mono"
|
|
843
878
|
style={{
|
|
844
879
|
color: 'var(--ds-gray-1000)',
|
|
845
880
|
background: 'transparent',
|
|
@@ -853,61 +888,70 @@ export const AttributePanel = ({
|
|
|
853
888
|
>
|
|
854
889
|
{moduleSpecifierValue}
|
|
855
890
|
</button>
|
|
856
|
-
) : (
|
|
857
|
-
<
|
|
858
|
-
className="min-w-0 max-w-[70%]
|
|
859
|
-
style={{
|
|
891
|
+
) : isCopyableBasicAttribute ? (
|
|
892
|
+
<div
|
|
893
|
+
className="flex min-w-0 max-w-[70%] items-center justify-end gap-1 text-right text-[13px] font-mono"
|
|
894
|
+
style={{
|
|
895
|
+
color: 'var(--ds-gray-1000)',
|
|
896
|
+
}}
|
|
897
|
+
title={displayValue}
|
|
860
898
|
>
|
|
899
|
+
<MiddleTruncate
|
|
900
|
+
value={displayValue}
|
|
901
|
+
className="flex-1"
|
|
902
|
+
/>
|
|
903
|
+
<CopyButton
|
|
904
|
+
copyText={displayValue}
|
|
905
|
+
ariaLabel={`Copy ${getAttributeDisplayName(attribute)}`}
|
|
906
|
+
className="shrink-0 -mr-1"
|
|
907
|
+
/>
|
|
908
|
+
</div>
|
|
909
|
+
) : (
|
|
910
|
+
<span className="text-right text-label-13 font-mono">
|
|
861
911
|
{displayValue}
|
|
862
912
|
</span>
|
|
863
913
|
)}
|
|
864
914
|
</div>
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
className="text-[14px] first-letter:uppercase"
|
|
879
|
-
style={{ color: 'var(--ds-gray-700)' }}
|
|
880
|
-
>
|
|
881
|
-
resumeAt
|
|
882
|
-
</span>
|
|
883
|
-
<Skeleton className="h-4 w-[55%]" />
|
|
915
|
+
);
|
|
916
|
+
})}
|
|
917
|
+
{isLoading && resource === 'sleep' && !displayData.resumeAt && (
|
|
918
|
+
<div className="py-1">
|
|
919
|
+
<div className="flex min-h-[32px] items-center justify-between gap-4 rounded-sm px-2.5 py-1">
|
|
920
|
+
<span
|
|
921
|
+
className="text-[14px] first-letter:uppercase"
|
|
922
|
+
style={{ color: 'var(--ds-gray-700)' }}
|
|
923
|
+
>
|
|
924
|
+
resumeAt
|
|
925
|
+
</span>
|
|
926
|
+
<Skeleton className="h-4 w-[55%]" />
|
|
927
|
+
</div>
|
|
884
928
|
</div>
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
</
|
|
911
|
-
</
|
|
929
|
+
)}
|
|
930
|
+
</div>
|
|
931
|
+
)}
|
|
932
|
+
{error ? (
|
|
933
|
+
<ErrorCard
|
|
934
|
+
title="Failed to load resource details"
|
|
935
|
+
details={error.message}
|
|
936
|
+
className="my-4"
|
|
937
|
+
/>
|
|
938
|
+
) : hasExpired ? (
|
|
939
|
+
<ExpiredDataMessage />
|
|
940
|
+
) : resolvedAttributes.length > 0 ? (
|
|
941
|
+
<>
|
|
942
|
+
{resolvedAttributes.map((attribute) => (
|
|
943
|
+
<AttributeBlock
|
|
944
|
+
isLoading={isLoading}
|
|
945
|
+
key={attribute}
|
|
946
|
+
attribute={attribute}
|
|
947
|
+
value={displayData[attribute as keyof typeof displayData]}
|
|
948
|
+
context={displayContext}
|
|
949
|
+
/>
|
|
950
|
+
))}
|
|
951
|
+
</>
|
|
952
|
+
) : null}
|
|
953
|
+
</DecryptClickContext.Provider>
|
|
954
|
+
</StreamClickContext.Provider>
|
|
955
|
+
</RunClickContext.Provider>
|
|
912
956
|
);
|
|
913
957
|
};
|