@workflow/web-shared 4.1.1 → 4.1.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/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/index.d.ts +1 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +1 -1
- package/dist/components/index.js.map +1 -1
- package/dist/components/sidebar/attribute-panel.d.ts +5 -1
- package/dist/components/sidebar/attribute-panel.d.ts.map +1 -1
- package/dist/components/sidebar/attribute-panel.js +35 -25
- package/dist/components/sidebar/attribute-panel.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 +17 -15
- package/dist/components/sidebar/entity-detail-panel.js.map +1 -1
- package/dist/components/ui/data-inspector.d.ts +14 -1
- package/dist/components/ui/data-inspector.d.ts.map +1 -1
- package/dist/components/ui/data-inspector.js +32 -11
- package/dist/components/ui/data-inspector.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 +2 -2
- package/dist/components/workflow-trace-view.js.map +1 -1
- package/dist/index.d.ts +1 -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/hydration.d.ts +7 -0
- package/dist/lib/hydration.d.ts.map +1 -1
- package/dist/lib/hydration.js +25 -0
- package/dist/lib/hydration.js.map +1 -1
- package/package.json +2 -2
- package/src/components/event-list-view.tsx +181 -173
- package/src/components/index.ts +6 -1
- package/src/components/sidebar/attribute-panel.tsx +145 -106
- package/src/components/sidebar/entity-detail-panel.tsx +106 -95
- package/src/components/ui/data-inspector.tsx +84 -19
- package/src/components/workflow-trace-view.tsx +4 -0
- package/src/index.ts +1 -0
- package/src/lib/hydration.ts +26 -0
|
@@ -4,12 +4,13 @@ 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
6
|
import { Lock } from 'lucide-react';
|
|
7
|
+
import { Spinner } from '../ui/spinner';
|
|
7
8
|
import type { KeyboardEvent, ReactNode } from 'react';
|
|
8
|
-
import { useCallback, useMemo, useState } from 'react';
|
|
9
|
+
import { useCallback, useContext, useMemo, useState } from 'react';
|
|
9
10
|
import { isEncryptedMarker, isExpiredMarker } from '../../lib/hydration';
|
|
10
11
|
import { useToast } from '../../lib/toast';
|
|
11
12
|
import { extractConversation, isDoStreamStep } from '../../lib/utils';
|
|
12
|
-
import { StreamClickContext } from '../ui/data-inspector';
|
|
13
|
+
import { DecryptClickContext, StreamClickContext } from '../ui/data-inspector';
|
|
13
14
|
import { ErrorCard } from '../ui/error-card';
|
|
14
15
|
import {
|
|
15
16
|
ErrorStackBlock,
|
|
@@ -180,9 +181,36 @@ function ConversationWithTabs({
|
|
|
180
181
|
* with the lucide Lock icon matching the title bar Decrypt button.
|
|
181
182
|
*/
|
|
182
183
|
function EncryptedFieldBlock() {
|
|
184
|
+
const ctx = useContext(DecryptClickContext);
|
|
185
|
+
if (ctx) {
|
|
186
|
+
return (
|
|
187
|
+
<button
|
|
188
|
+
type="button"
|
|
189
|
+
onClick={ctx.onDecrypt}
|
|
190
|
+
disabled={ctx.isDecrypting}
|
|
191
|
+
className="flex w-full items-center justify-center gap-1.5 rounded-md border px-3 py-2 text-xs cursor-pointer transition-colors"
|
|
192
|
+
style={{
|
|
193
|
+
borderColor: 'var(--ds-gray-400)',
|
|
194
|
+
backgroundColor: 'var(--ds-gray-100)',
|
|
195
|
+
color: 'var(--ds-gray-700)',
|
|
196
|
+
opacity: ctx.isDecrypting ? 0.6 : 1,
|
|
197
|
+
}}
|
|
198
|
+
title="Click to decrypt"
|
|
199
|
+
>
|
|
200
|
+
{ctx.isDecrypting ? (
|
|
201
|
+
<Spinner size={12} />
|
|
202
|
+
) : (
|
|
203
|
+
<Lock className="h-3 w-3" />
|
|
204
|
+
)}
|
|
205
|
+
<span className="font-medium">
|
|
206
|
+
{ctx.isDecrypting ? 'Decrypting…' : 'Decrypt'}
|
|
207
|
+
</span>
|
|
208
|
+
</button>
|
|
209
|
+
);
|
|
210
|
+
}
|
|
183
211
|
return (
|
|
184
212
|
<div
|
|
185
|
-
className="flex items-center gap-1.5 rounded-md border px-3 py-2 text-xs"
|
|
213
|
+
className="flex w-full items-center justify-center gap-1.5 rounded-md border px-3 py-2 text-xs"
|
|
186
214
|
style={{
|
|
187
215
|
borderColor: 'var(--ds-gray-300)',
|
|
188
216
|
backgroundColor: 'var(--ds-gray-100)',
|
|
@@ -689,6 +717,8 @@ export const AttributePanel = ({
|
|
|
689
717
|
error,
|
|
690
718
|
expiredAt,
|
|
691
719
|
onStreamClick,
|
|
720
|
+
onDecrypt,
|
|
721
|
+
isDecrypting = false,
|
|
692
722
|
resource,
|
|
693
723
|
}: {
|
|
694
724
|
data: Record<string, unknown>;
|
|
@@ -698,6 +728,10 @@ export const AttributePanel = ({
|
|
|
698
728
|
expiredAt?: string | Date;
|
|
699
729
|
/** Callback when a stream reference is clicked */
|
|
700
730
|
onStreamClick?: (streamId: string) => void;
|
|
731
|
+
/** Callback when an encrypted marker is clicked (triggers decryption) */
|
|
732
|
+
onDecrypt?: () => void;
|
|
733
|
+
/** Whether decryption is currently in progress */
|
|
734
|
+
isDecrypting?: boolean;
|
|
701
735
|
/** Resource type of the selected span — used to show targeted loading skeletons. */
|
|
702
736
|
resource?: string;
|
|
703
737
|
}) => {
|
|
@@ -798,116 +832,121 @@ export const AttributePanel = ({
|
|
|
798
832
|
|
|
799
833
|
return (
|
|
800
834
|
<StreamClickContext.Provider value={onStreamClick}>
|
|
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
|
-
|
|
827
|
-
|
|
835
|
+
<DecryptClickContext.Provider
|
|
836
|
+
value={onDecrypt ? { onDecrypt, isDecrypting } : undefined}
|
|
837
|
+
>
|
|
838
|
+
<div>
|
|
839
|
+
{/* Basic attributes in a vertical layout with border */}
|
|
840
|
+
{visibleBasicAttributes.length > 0 && (
|
|
841
|
+
<div
|
|
842
|
+
className="mb-3 flex flex-col overflow-hidden rounded-lg border"
|
|
843
|
+
style={{
|
|
844
|
+
borderColor: 'var(--ds-gray-300)',
|
|
845
|
+
}}
|
|
846
|
+
>
|
|
847
|
+
{orderedBasicAttributes.map((attribute, index) => {
|
|
848
|
+
const displayValue = attributeToDisplayFn[
|
|
849
|
+
attribute as keyof typeof attributeToDisplayFn
|
|
850
|
+
]?.(displayData[attribute as keyof typeof displayData]);
|
|
851
|
+
const isModuleSpecifier = attribute === 'moduleSpecifier';
|
|
852
|
+
const moduleSpecifierValue =
|
|
853
|
+
typeof displayValue === 'string'
|
|
854
|
+
? displayValue
|
|
855
|
+
: String(displayValue ?? displayData.moduleSpecifier ?? '');
|
|
856
|
+
const shouldCapitalizeLabel =
|
|
857
|
+
attribute !== 'workflowCoreVersion';
|
|
858
|
+
const showResumeAtSkeleton =
|
|
859
|
+
isLoading && resource === 'sleep' && !displayData.resumeAt;
|
|
860
|
+
const showDivider =
|
|
861
|
+
index < orderedBasicAttributes.length - 1 ||
|
|
862
|
+
showResumeAtSkeleton;
|
|
863
|
+
|
|
864
|
+
return (
|
|
865
|
+
<div key={attribute} className="py-1">
|
|
866
|
+
<div className="flex min-h-[32px] items-center justify-between gap-4 rounded-sm px-2.5 py-1">
|
|
867
|
+
<span
|
|
868
|
+
className={
|
|
869
|
+
shouldCapitalizeLabel
|
|
870
|
+
? 'text-[14px] first-letter:uppercase'
|
|
871
|
+
: 'text-[14px]'
|
|
872
|
+
}
|
|
873
|
+
style={{ color: 'var(--ds-gray-700)' }}
|
|
874
|
+
>
|
|
875
|
+
{getAttributeDisplayName(attribute)}
|
|
876
|
+
</span>
|
|
877
|
+
{isModuleSpecifier ? (
|
|
878
|
+
<button
|
|
879
|
+
type="button"
|
|
880
|
+
className="min-w-0 max-w-[70%] truncate text-right text-[13px] font-mono"
|
|
881
|
+
style={{
|
|
882
|
+
color: 'var(--ds-gray-1000)',
|
|
883
|
+
background: 'transparent',
|
|
884
|
+
border: 'none',
|
|
885
|
+
padding: 0,
|
|
886
|
+
}}
|
|
887
|
+
title={moduleSpecifierValue}
|
|
888
|
+
onClick={() =>
|
|
889
|
+
handleCopyModuleSpecifier(moduleSpecifierValue)
|
|
890
|
+
}
|
|
891
|
+
>
|
|
892
|
+
{moduleSpecifierValue}
|
|
893
|
+
</button>
|
|
894
|
+
) : (
|
|
895
|
+
<span
|
|
896
|
+
className="min-w-0 max-w-[70%] truncate text-right text-[13px] font-mono"
|
|
897
|
+
style={{ color: 'var(--ds-gray-1000)' }}
|
|
898
|
+
>
|
|
899
|
+
{displayValue}
|
|
900
|
+
</span>
|
|
901
|
+
)}
|
|
902
|
+
</div>
|
|
903
|
+
{showDivider ? (
|
|
904
|
+
<div
|
|
905
|
+
className="mx-2.5 border-b"
|
|
906
|
+
style={{ borderColor: 'var(--ds-gray-300)' }}
|
|
907
|
+
/>
|
|
908
|
+
) : null}
|
|
909
|
+
</div>
|
|
910
|
+
);
|
|
911
|
+
})}
|
|
912
|
+
{isLoading && resource === 'sleep' && !displayData.resumeAt && (
|
|
913
|
+
<div className="py-1">
|
|
828
914
|
<div className="flex min-h-[32px] items-center justify-between gap-4 rounded-sm px-2.5 py-1">
|
|
829
915
|
<span
|
|
830
|
-
className=
|
|
831
|
-
shouldCapitalizeLabel
|
|
832
|
-
? 'text-[14px] first-letter:uppercase'
|
|
833
|
-
: 'text-[14px]'
|
|
834
|
-
}
|
|
916
|
+
className="text-[14px] first-letter:uppercase"
|
|
835
917
|
style={{ color: 'var(--ds-gray-700)' }}
|
|
836
918
|
>
|
|
837
|
-
|
|
919
|
+
resumeAt
|
|
838
920
|
</span>
|
|
839
|
-
|
|
840
|
-
<button
|
|
841
|
-
type="button"
|
|
842
|
-
className="min-w-0 max-w-[70%] truncate text-right text-[13px] font-mono"
|
|
843
|
-
style={{
|
|
844
|
-
color: 'var(--ds-gray-1000)',
|
|
845
|
-
background: 'transparent',
|
|
846
|
-
border: 'none',
|
|
847
|
-
padding: 0,
|
|
848
|
-
}}
|
|
849
|
-
title={moduleSpecifierValue}
|
|
850
|
-
onClick={() =>
|
|
851
|
-
handleCopyModuleSpecifier(moduleSpecifierValue)
|
|
852
|
-
}
|
|
853
|
-
>
|
|
854
|
-
{moduleSpecifierValue}
|
|
855
|
-
</button>
|
|
856
|
-
) : (
|
|
857
|
-
<span
|
|
858
|
-
className="min-w-0 max-w-[70%] truncate text-right text-[13px] font-mono"
|
|
859
|
-
style={{ color: 'var(--ds-gray-1000)' }}
|
|
860
|
-
>
|
|
861
|
-
{displayValue}
|
|
862
|
-
</span>
|
|
863
|
-
)}
|
|
921
|
+
<Skeleton className="h-4 w-[55%]" />
|
|
864
922
|
</div>
|
|
865
|
-
{showDivider ? (
|
|
866
|
-
<div
|
|
867
|
-
className="mx-2.5 border-b"
|
|
868
|
-
style={{ borderColor: 'var(--ds-gray-300)' }}
|
|
869
|
-
/>
|
|
870
|
-
) : null}
|
|
871
|
-
</div>
|
|
872
|
-
);
|
|
873
|
-
})}
|
|
874
|
-
{isLoading && resource === 'sleep' && !displayData.resumeAt && (
|
|
875
|
-
<div className="py-1">
|
|
876
|
-
<div className="flex min-h-[32px] items-center justify-between gap-4 rounded-sm px-2.5 py-1">
|
|
877
|
-
<span
|
|
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%]" />
|
|
884
923
|
</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
|
-
</
|
|
924
|
+
)}
|
|
925
|
+
</div>
|
|
926
|
+
)}
|
|
927
|
+
{error ? (
|
|
928
|
+
<ErrorCard
|
|
929
|
+
title="Failed to load resource details"
|
|
930
|
+
details={error.message}
|
|
931
|
+
className="my-4"
|
|
932
|
+
/>
|
|
933
|
+
) : hasExpired ? (
|
|
934
|
+
<ExpiredDataMessage />
|
|
935
|
+
) : (
|
|
936
|
+
<>
|
|
937
|
+
{resolvedAttributes.map((attribute) => (
|
|
938
|
+
<AttributeBlock
|
|
939
|
+
isLoading={isLoading}
|
|
940
|
+
key={attribute}
|
|
941
|
+
attribute={attribute}
|
|
942
|
+
value={displayData[attribute as keyof typeof displayData]}
|
|
943
|
+
context={displayContext}
|
|
944
|
+
/>
|
|
945
|
+
))}
|
|
946
|
+
</>
|
|
947
|
+
)}
|
|
948
|
+
</div>
|
|
949
|
+
</DecryptClickContext.Provider>
|
|
911
950
|
</StreamClickContext.Provider>
|
|
912
951
|
);
|
|
913
952
|
};
|
|
@@ -6,6 +6,7 @@ import { Send, Zap } from 'lucide-react';
|
|
|
6
6
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
7
7
|
import { useToast } from '../../lib/toast';
|
|
8
8
|
import { isEncryptedMarker } from '../../lib/hydration';
|
|
9
|
+
import { DecryptClickContext } from '../ui/data-inspector';
|
|
9
10
|
import { DecryptButton } from '../ui/decrypt-button';
|
|
10
11
|
import { AttributePanel } from './attribute-panel';
|
|
11
12
|
import { EventsList } from './events-list';
|
|
@@ -67,6 +68,7 @@ export function EntityDetailPanel({
|
|
|
67
68
|
onDecrypt,
|
|
68
69
|
isDecrypting = false,
|
|
69
70
|
selectedSpan,
|
|
71
|
+
hasEncryptedData = false,
|
|
70
72
|
}: {
|
|
71
73
|
run: WorkflowRun;
|
|
72
74
|
/** Callback when a stream reference is clicked */
|
|
@@ -103,6 +105,8 @@ export function EntityDetailPanel({
|
|
|
103
105
|
isDecrypting?: boolean;
|
|
104
106
|
/** Info about the currently selected span from the trace viewer */
|
|
105
107
|
selectedSpan: SelectedSpanInfo | null;
|
|
108
|
+
/** Run-level hint: the run contains encrypted data (from probe). */
|
|
109
|
+
hasEncryptedData?: boolean;
|
|
106
110
|
}): React.JSX.Element | null {
|
|
107
111
|
const toast = useToast();
|
|
108
112
|
const [stoppingSleep, setStoppingSleep] = useState(false);
|
|
@@ -391,111 +395,118 @@ export function EntityDetailPanel({
|
|
|
391
395
|
{resourceId}
|
|
392
396
|
</p>
|
|
393
397
|
</div>
|
|
394
|
-
{(hasEncryptedFields || encryptionKey) &&
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
398
|
+
{(hasEncryptedFields || hasEncryptedData || encryptionKey) &&
|
|
399
|
+
onDecrypt && (
|
|
400
|
+
<DecryptButton
|
|
401
|
+
decrypted={!!encryptionKey}
|
|
402
|
+
loading={isDecrypting}
|
|
403
|
+
onClick={onDecrypt}
|
|
404
|
+
/>
|
|
405
|
+
)}
|
|
401
406
|
</div>
|
|
402
407
|
</div>
|
|
403
408
|
|
|
404
|
-
<
|
|
405
|
-
{
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
style={{ color: 'var(--ds-gray-700)' }}
|
|
409
|
+
<DecryptClickContext.Provider
|
|
410
|
+
value={onDecrypt ? { onDecrypt, isDecrypting } : undefined}
|
|
411
|
+
>
|
|
412
|
+
<div className="flex-1 overflow-y-auto px-3 pt-3 pb-8">
|
|
413
|
+
{hasPendingActions && (
|
|
414
|
+
<div
|
|
415
|
+
className="mb-4 rounded-lg border p-2"
|
|
416
|
+
style={{
|
|
417
|
+
borderColor: 'var(--ds-gray-300)',
|
|
418
|
+
backgroundColor: 'var(--ds-gray-100)',
|
|
419
|
+
}}
|
|
416
420
|
>
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
stoppingSleep
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
resolvingHook
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
421
|
+
<p
|
|
422
|
+
className="mb-2 px-1 text-[13px] font-medium uppercase tracking-wide"
|
|
423
|
+
style={{ color: 'var(--ds-gray-700)' }}
|
|
424
|
+
>
|
|
425
|
+
Actions
|
|
426
|
+
</p>
|
|
427
|
+
<div className="flex flex-col gap-2">
|
|
428
|
+
{/* Wake up button for pending sleep calls */}
|
|
429
|
+
{resource === 'sleep' && canWakeUp && (
|
|
430
|
+
<button
|
|
431
|
+
type="button"
|
|
432
|
+
onClick={handleWakeUp}
|
|
433
|
+
disabled={stoppingSleep}
|
|
434
|
+
className={clsx(
|
|
435
|
+
'flex items-center justify-center gap-2 rounded-md px-3 py-2 text-sm font-medium',
|
|
436
|
+
'disabled:opacity-50 disabled:cursor-not-allowed transition-colors',
|
|
437
|
+
stoppingSleep
|
|
438
|
+
? 'opacity-50 cursor-not-allowed'
|
|
439
|
+
: 'cursor-pointer'
|
|
440
|
+
)}
|
|
441
|
+
style={{
|
|
442
|
+
background: 'var(--ds-amber-200)',
|
|
443
|
+
color: 'var(--ds-amber-900)',
|
|
444
|
+
}}
|
|
445
|
+
>
|
|
446
|
+
<Zap className="h-4 w-4" />
|
|
447
|
+
{stoppingSleep ? 'Waking up...' : 'Wake Up Sleep'}
|
|
448
|
+
</button>
|
|
449
|
+
)}
|
|
450
|
+
|
|
451
|
+
{/* Resolve hook button for pending hooks */}
|
|
452
|
+
{resource === 'hook' && canResolveHook && (
|
|
453
|
+
<button
|
|
454
|
+
type="button"
|
|
455
|
+
onClick={() => setShowResolveHookModal(true)}
|
|
456
|
+
disabled={resolvingHook}
|
|
457
|
+
className={clsx(
|
|
458
|
+
'flex items-center justify-center gap-2 rounded-md px-3 py-2 text-sm font-medium',
|
|
459
|
+
'disabled:opacity-50 disabled:cursor-not-allowed transition-colors',
|
|
460
|
+
resolvingHook
|
|
461
|
+
? 'opacity-50 cursor-not-allowed'
|
|
462
|
+
: 'cursor-pointer'
|
|
463
|
+
)}
|
|
464
|
+
style={{
|
|
465
|
+
background: 'var(--ds-gray-1000)',
|
|
466
|
+
color: 'var(--ds-background-100)',
|
|
467
|
+
}}
|
|
468
|
+
>
|
|
469
|
+
<Send className="h-4 w-4" />
|
|
470
|
+
Resolve Hook
|
|
471
|
+
</button>
|
|
472
|
+
)}
|
|
473
|
+
</div>
|
|
465
474
|
</div>
|
|
466
|
-
|
|
467
|
-
)}
|
|
475
|
+
)}
|
|
468
476
|
|
|
469
|
-
|
|
470
|
-
<section>
|
|
471
|
-
<h3
|
|
472
|
-
className="mb-2 text-[13px] font-medium uppercase tracking-wide"
|
|
473
|
-
style={{ color: 'var(--ds-gray-700)' }}
|
|
474
|
-
>
|
|
475
|
-
Details
|
|
476
|
-
</h3>
|
|
477
|
-
<AttributePanel
|
|
478
|
-
data={displayData}
|
|
479
|
-
moduleSpecifier={moduleSpecifier}
|
|
480
|
-
expiredAt={run.expiredAt}
|
|
481
|
-
isLoading={loading}
|
|
482
|
-
error={error ?? undefined}
|
|
483
|
-
onStreamClick={onStreamClick}
|
|
484
|
-
resource={resource}
|
|
485
|
-
/>
|
|
486
|
-
</section>
|
|
487
|
-
|
|
488
|
-
{resource !== 'run' && rawEvents && (
|
|
477
|
+
<div className="space-y-4">
|
|
489
478
|
<section>
|
|
490
|
-
<
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
479
|
+
<h3
|
|
480
|
+
className="mb-2 text-[13px] font-medium uppercase tracking-wide"
|
|
481
|
+
style={{ color: 'var(--ds-gray-700)' }}
|
|
482
|
+
>
|
|
483
|
+
Details
|
|
484
|
+
</h3>
|
|
485
|
+
<AttributePanel
|
|
486
|
+
data={displayData}
|
|
487
|
+
moduleSpecifier={moduleSpecifier}
|
|
488
|
+
expiredAt={run.expiredAt}
|
|
489
|
+
isLoading={loading}
|
|
490
|
+
error={error ?? undefined}
|
|
491
|
+
onStreamClick={onStreamClick}
|
|
492
|
+
onDecrypt={onDecrypt}
|
|
493
|
+
isDecrypting={isDecrypting}
|
|
494
|
+
resource={resource}
|
|
494
495
|
/>
|
|
495
496
|
</section>
|
|
496
|
-
|
|
497
|
+
|
|
498
|
+
{resource !== 'run' && rawEvents && (
|
|
499
|
+
<section>
|
|
500
|
+
<EventsList
|
|
501
|
+
events={rawEvents}
|
|
502
|
+
onLoadEventData={onLoadEventData}
|
|
503
|
+
encryptionKey={encryptionKey}
|
|
504
|
+
/>
|
|
505
|
+
</section>
|
|
506
|
+
)}
|
|
507
|
+
</div>
|
|
497
508
|
</div>
|
|
498
|
-
</
|
|
509
|
+
</DecryptClickContext.Provider>
|
|
499
510
|
|
|
500
511
|
{/* Resolve Hook Modal */}
|
|
501
512
|
<ResolveHookModal
|