@flamingo-stack/openframe-frontend-core 0.0.516 → 0.0.517-1651.4264.1
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/{chunk-NG7ZMEYW.cjs → chunk-2LMIHPQH.cjs} +4 -4
- package/dist/{chunk-NG7ZMEYW.cjs.map → chunk-2LMIHPQH.cjs.map} +1 -1
- package/dist/{chunk-SIMZ3VS2.js → chunk-45TSVW73.js} +2 -2
- package/dist/{chunk-3XHAX6MO.cjs → chunk-476N4NBC.cjs} +26 -26
- package/dist/{chunk-3XHAX6MO.cjs.map → chunk-476N4NBC.cjs.map} +1 -1
- package/dist/{chunk-ARTBN7XU.js → chunk-A5WEANTA.js} +2 -2
- package/dist/{chunk-BVBY7UMD.cjs → chunk-ARB3MVHH.cjs} +47 -3
- package/dist/chunk-ARB3MVHH.cjs.map +1 -0
- package/dist/{chunk-KXB6PGWV.js → chunk-CJ55TI4A.js} +4 -4
- package/dist/{chunk-UIIMQTTL.cjs → chunk-CV4IMEEH.cjs} +37 -37
- package/dist/{chunk-UIIMQTTL.cjs.map → chunk-CV4IMEEH.cjs.map} +1 -1
- package/dist/{chunk-FMZX2FOK.cjs → chunk-GWS2J3VC.cjs} +31 -31
- package/dist/{chunk-FMZX2FOK.cjs.map → chunk-GWS2J3VC.cjs.map} +1 -1
- package/dist/{chunk-FLI5RMO4.js → chunk-GXSKS5RO.js} +2 -2
- package/dist/{chunk-ZWTIHBXS.cjs → chunk-HNWJSFEV.cjs} +3 -3
- package/dist/{chunk-ZWTIHBXS.cjs.map → chunk-HNWJSFEV.cjs.map} +1 -1
- package/dist/{chunk-CALVHRRU.cjs → chunk-HOPPNUGS.cjs} +5 -5
- package/dist/{chunk-CALVHRRU.cjs.map → chunk-HOPPNUGS.cjs.map} +1 -1
- package/dist/{chunk-W5TUW7US.js → chunk-I75L6RSN.js} +2 -2
- package/dist/{chunk-5JLSIN72.cjs → chunk-J4C4IY2F.cjs} +9 -9
- package/dist/{chunk-5JLSIN72.cjs.map → chunk-J4C4IY2F.cjs.map} +1 -1
- package/dist/{chunk-SIFO7F7J.js → chunk-J6TFTLXF.js} +2 -2
- package/dist/{chunk-2T356SFJ.cjs → chunk-KG52CG6Y.cjs} +14 -14
- package/dist/{chunk-2T356SFJ.cjs.map → chunk-KG52CG6Y.cjs.map} +1 -1
- package/dist/{chunk-4GSNSWXD.cjs → chunk-N2LZPULX.cjs} +11 -11
- package/dist/{chunk-4GSNSWXD.cjs.map → chunk-N2LZPULX.cjs.map} +1 -1
- package/dist/{chunk-4XFAIQMV.js → chunk-O3CJ6IWP.js} +2 -2
- package/dist/{chunk-6IQKCE6Q.js → chunk-OCNHD5XM.js} +6 -6
- package/dist/{chunk-YR3YLAGA.js → chunk-QRAGH5CS.js} +2 -2
- package/dist/{chunk-XNC2JU6D.cjs → chunk-R7JZC5RX.cjs} +7 -7
- package/dist/{chunk-XNC2JU6D.cjs.map → chunk-R7JZC5RX.cjs.map} +1 -1
- package/dist/{chunk-CI2NKT45.cjs → chunk-SXWPJHP7.cjs} +26 -26
- package/dist/{chunk-CI2NKT45.cjs.map → chunk-SXWPJHP7.cjs.map} +1 -1
- package/dist/{chunk-FTA3OFFU.cjs → chunk-U5ZE22FV.cjs} +61 -61
- package/dist/{chunk-FTA3OFFU.cjs.map → chunk-U5ZE22FV.cjs.map} +1 -1
- package/dist/{chunk-5UZZ5UTH.js → chunk-UL7QF323.js} +2 -2
- package/dist/{chunk-XBL4OPPW.js → chunk-V6FISTDB.js} +2 -2
- package/dist/{chunk-5JMFC6DQ.js → chunk-VGK6CXYG.js} +5 -5
- package/dist/{chunk-MAWBYVGA.cjs → chunk-VSUGMXAV.cjs} +87 -87
- package/dist/{chunk-MAWBYVGA.cjs.map → chunk-VSUGMXAV.cjs.map} +1 -1
- package/dist/{chunk-5MJBM4AT.js → chunk-VXMKRJYN.js} +46 -2
- package/dist/{chunk-5MJBM4AT.js.map → chunk-VXMKRJYN.js.map} +1 -1
- package/dist/{chunk-YUYDBVBF.js → chunk-YXF4JKKQ.js} +4 -4
- package/dist/components/case-studies/index.cjs +8 -8
- package/dist/components/case-studies/index.js +2 -2
- package/dist/components/chat/index.cjs +2 -2
- package/dist/components/chat/index.js +1 -1
- package/dist/components/contact/index.cjs +3 -3
- package/dist/components/contact/index.js +2 -2
- package/dist/components/docs/index.cjs +5 -5
- package/dist/components/docs/index.js +4 -4
- package/dist/components/embeds/index.cjs +3 -3
- package/dist/components/embeds/index.js +2 -2
- package/dist/components/faq/index.cjs +3 -3
- package/dist/components/faq/index.js +2 -2
- package/dist/components/features/index.cjs +2 -2
- package/dist/components/features/index.js +1 -1
- package/dist/components/help-center-pages/index.cjs +22 -22
- package/dist/components/help-center-pages/index.js +13 -13
- package/dist/components/index.cjs +136 -132
- package/dist/components/index.cjs.map +1 -1
- package/dist/components/index.js +15 -11
- package/dist/components/index.js.map +1 -1
- package/dist/components/meeting-scheduler/index.cjs +34 -34
- package/dist/components/meeting-scheduler/index.js +3 -3
- package/dist/components/navigation/index.cjs +2 -2
- package/dist/components/navigation/index.js +1 -1
- package/dist/components/onboarding-guides/index.cjs +5 -5
- package/dist/components/onboarding-guides/index.js +4 -4
- package/dist/components/related-content/index.cjs +3 -3
- package/dist/components/related-content/index.js +2 -2
- package/dist/components/tickets/index.cjs +6 -6
- package/dist/components/tickets/index.js +5 -5
- package/dist/components/ui/index.cjs +6 -2
- package/dist/components/ui/index.cjs.map +1 -1
- package/dist/components/ui/index.js +5 -1
- package/dist/components/ui/test-run.d.ts +13 -0
- package/dist/components/ui/test-run.d.ts.map +1 -1
- package/dist/index.cjs +6 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +5 -1
- package/package.json +1 -1
- package/src/components/ui/test-run.tsx +59 -6
- package/src/stories/TestRun.stories.tsx +20 -2
- package/dist/chunk-BVBY7UMD.cjs.map +0 -1
- /package/dist/{chunk-SIMZ3VS2.js.map → chunk-45TSVW73.js.map} +0 -0
- /package/dist/{chunk-ARTBN7XU.js.map → chunk-A5WEANTA.js.map} +0 -0
- /package/dist/{chunk-KXB6PGWV.js.map → chunk-CJ55TI4A.js.map} +0 -0
- /package/dist/{chunk-FLI5RMO4.js.map → chunk-GXSKS5RO.js.map} +0 -0
- /package/dist/{chunk-W5TUW7US.js.map → chunk-I75L6RSN.js.map} +0 -0
- /package/dist/{chunk-SIFO7F7J.js.map → chunk-J6TFTLXF.js.map} +0 -0
- /package/dist/{chunk-4XFAIQMV.js.map → chunk-O3CJ6IWP.js.map} +0 -0
- /package/dist/{chunk-6IQKCE6Q.js.map → chunk-OCNHD5XM.js.map} +0 -0
- /package/dist/{chunk-YR3YLAGA.js.map → chunk-QRAGH5CS.js.map} +0 -0
- /package/dist/{chunk-5UZZ5UTH.js.map → chunk-UL7QF323.js.map} +0 -0
- /package/dist/{chunk-XBL4OPPW.js.map → chunk-V6FISTDB.js.map} +0 -0
- /package/dist/{chunk-5JMFC6DQ.js.map → chunk-VGK6CXYG.js.map} +0 -0
- /package/dist/{chunk-YUYDBVBF.js.map → chunk-YXF4JKKQ.js.map} +0 -0
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import type { ColumnDef, Row } from '@tanstack/react-table'
|
|
4
4
|
import * as React from 'react'
|
|
5
|
-
import { SearchIcon } from '../icons-v2-generated'
|
|
5
|
+
import { Copy02Icon, SearchIcon } from '../icons-v2-generated'
|
|
6
|
+
import { useCopyToClipboard } from '../../hooks/use-copy-to-clipboard'
|
|
6
7
|
import { cn } from '../../utils/cn'
|
|
7
8
|
import { formatTime } from '../../utils/format-date'
|
|
8
9
|
import { DataTable } from './data-table'
|
|
@@ -10,6 +11,7 @@ import { useDataTable } from './data-table/use-data-table'
|
|
|
10
11
|
import { NoData } from './no-data'
|
|
11
12
|
import type { QueryResultRow } from './query-report-table'
|
|
12
13
|
import { ScrollShadow } from './scroll-fade'
|
|
14
|
+
import { Tag } from './tag'
|
|
13
15
|
|
|
14
16
|
/*
|
|
15
17
|
* Live test-run building blocks: the UI (timing stats, one-row skeleton,
|
|
@@ -129,15 +131,37 @@ export interface TestRunResultsProps {
|
|
|
129
131
|
className?: string
|
|
130
132
|
}
|
|
131
133
|
|
|
134
|
+
/** Red error banner with a copy-to-clipboard action, per the test-run design. */
|
|
135
|
+
export function TestRunErrorBanner({ error, className }: { error: string; className?: string }) {
|
|
136
|
+
const { copy } = useCopyToClipboard({ successDescription: 'Error message copied to clipboard' })
|
|
137
|
+
return (
|
|
138
|
+
<div
|
|
139
|
+
role="alert"
|
|
140
|
+
className={cn(
|
|
141
|
+
'flex items-center justify-between gap-[var(--spacing-system-s)]',
|
|
142
|
+
'rounded-[6px] border border-ods-error bg-ods-error-secondary',
|
|
143
|
+
'px-[var(--spacing-system-mf)] py-[var(--spacing-system-s)]',
|
|
144
|
+
className,
|
|
145
|
+
)}
|
|
146
|
+
>
|
|
147
|
+
<p className="text-h4 text-ods-error min-w-0 break-words">{error}</p>
|
|
148
|
+
<button
|
|
149
|
+
type="button"
|
|
150
|
+
aria-label="Copy error message"
|
|
151
|
+
onClick={() => copy(error)}
|
|
152
|
+
className="shrink-0 text-ods-error hover:opacity-80 transition-opacity focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ods-focus rounded-sm"
|
|
153
|
+
>
|
|
154
|
+
<Copy02Icon className="size-5" />
|
|
155
|
+
</button>
|
|
156
|
+
</div>
|
|
157
|
+
)
|
|
158
|
+
}
|
|
159
|
+
|
|
132
160
|
/** Error line + empty state + result table for a finished/running test run. */
|
|
133
161
|
export function TestRunResults({ isActive, displayRows, firstError, className }: TestRunResultsProps) {
|
|
134
162
|
return (
|
|
135
163
|
<div className={cn('flex flex-col gap-[var(--spacing-system-xsf)]', className)}>
|
|
136
|
-
{firstError &&
|
|
137
|
-
<p role="alert" className="text-h6 text-ods-error">
|
|
138
|
-
{firstError}
|
|
139
|
-
</p>
|
|
140
|
-
)}
|
|
164
|
+
{firstError && <TestRunErrorBanner error={firstError} />}
|
|
141
165
|
{!isActive && displayRows.length === 0 ? (
|
|
142
166
|
// With zero rows the error line alone explains the outcome; a
|
|
143
167
|
// "No results returned" empty state next to it would mislead.
|
|
@@ -164,6 +188,30 @@ export function TimingStat({ value, label, className }: { value: string; label:
|
|
|
164
188
|
)
|
|
165
189
|
}
|
|
166
190
|
|
|
191
|
+
/** Overall run outcome shown in a test-run controls row. */
|
|
192
|
+
export type TestRunStatus = 'idle' | 'running' | 'success' | 'error'
|
|
193
|
+
|
|
194
|
+
const TEST_RUN_STATUS_TAGS: Record<Exclude<TestRunStatus, 'idle'>, { label: string; variant: 'warning' | 'success' | 'error' }> = {
|
|
195
|
+
running: { label: 'IN PROCESS', variant: 'warning' },
|
|
196
|
+
success: { label: 'SUCCESS', variant: 'success' },
|
|
197
|
+
error: { label: 'ERROR', variant: 'error' },
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/** Status stat cell: "-" before the first run, then a colored state tag. */
|
|
201
|
+
export function TestRunStatusStat({ status, className }: { status: TestRunStatus; className?: string }) {
|
|
202
|
+
const tag = status === 'idle' ? null : TEST_RUN_STATUS_TAGS[status]
|
|
203
|
+
return (
|
|
204
|
+
<div className={cn('flex flex-col justify-center items-start min-w-0 gap-[var(--spacing-system-xxs)]', className)}>
|
|
205
|
+
{tag ? (
|
|
206
|
+
<Tag label={tag.label} variant={tag.variant} className="pointer-events-none" />
|
|
207
|
+
) : (
|
|
208
|
+
<span className="text-h4 text-ods-text-secondary truncate">-</span>
|
|
209
|
+
)}
|
|
210
|
+
<span className="text-h6 text-ods-text-secondary truncate">Status</span>
|
|
211
|
+
</div>
|
|
212
|
+
)
|
|
213
|
+
}
|
|
214
|
+
|
|
167
215
|
/**
|
|
168
216
|
* The transport-side contract `useTestRunState` observes. Matches the shape
|
|
169
217
|
* of a live-campaign hook (e.g. Fleet live queries in OpenFrame) without
|
|
@@ -248,6 +296,10 @@ export function useTestRunState(campaign: TestRunCampaignState) {
|
|
|
248
296
|
|
|
249
297
|
const firstError = isFinished && campaign.errors.length > 0 ? campaign.errors[0].error : null
|
|
250
298
|
|
|
299
|
+
// Overall run outcome for the Status stat: '-' until a run starts, then
|
|
300
|
+
// IN PROCESS while active, and SUCCESS/ERROR once the campaign finishes.
|
|
301
|
+
const status: TestRunStatus = isActive ? 'running' : hasRun && isFinished ? (firstError ? 'error' : 'success') : 'idle'
|
|
302
|
+
|
|
251
303
|
// Started/Duration show zeros until the current run's timing is real:
|
|
252
304
|
// hasRun=false after a reset, and campaignStatus resets while the next
|
|
253
305
|
// run is being created, so stale values never linger on screen.
|
|
@@ -271,6 +323,7 @@ export function useTestRunState(campaign: TestRunCampaignState) {
|
|
|
271
323
|
isActive,
|
|
272
324
|
isFinished,
|
|
273
325
|
showResults,
|
|
326
|
+
status,
|
|
274
327
|
firstError,
|
|
275
328
|
startedLabel,
|
|
276
329
|
durationLabel,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/nextjs-vite';
|
|
2
|
-
import { TestResultsSkeleton, TestRunResults, TimingStat } from '../components/ui/test-run';
|
|
2
|
+
import { TestResultsSkeleton, TestRunResults, TestRunStatusStat, TimingStat } from '../components/ui/test-run';
|
|
3
3
|
|
|
4
4
|
const meta = {
|
|
5
5
|
title: 'UI/TestRun',
|
|
@@ -85,7 +85,7 @@ export const EmptyResult: Story = {
|
|
|
85
85
|
),
|
|
86
86
|
};
|
|
87
87
|
|
|
88
|
-
/** Finished with an error:
|
|
88
|
+
/** Finished with an error: red banner with a copy action replaces the empty state. */
|
|
89
89
|
export const WithError: Story = {
|
|
90
90
|
args: {
|
|
91
91
|
isActive: false,
|
|
@@ -111,8 +111,26 @@ export const TimingAndSkeleton: Story = {
|
|
|
111
111
|
<div className="flex items-center gap-[var(--spacing-system-m)]">
|
|
112
112
|
<TimingStat value="02:15 PM" label="Started" className="flex-1" />
|
|
113
113
|
<TimingStat value="00:00:05" label="Duration" className="flex-1" />
|
|
114
|
+
<TestRunStatusStat status="running" className="flex-1" />
|
|
114
115
|
</div>
|
|
115
116
|
<TestResultsSkeleton />
|
|
116
117
|
</div>
|
|
117
118
|
),
|
|
118
119
|
};
|
|
120
|
+
|
|
121
|
+
/** The four Status stat states: "-" before a run, then a colored tag. */
|
|
122
|
+
export const StatusStates: Story = {
|
|
123
|
+
args: {
|
|
124
|
+
isActive: false,
|
|
125
|
+
displayRows: [],
|
|
126
|
+
firstError: null,
|
|
127
|
+
},
|
|
128
|
+
render: () => (
|
|
129
|
+
<div className="flex max-w-[720px] items-center gap-[var(--spacing-system-l)] bg-ods-bg p-[var(--spacing-system-mf)]">
|
|
130
|
+
<TestRunStatusStat status="idle" />
|
|
131
|
+
<TestRunStatusStat status="running" />
|
|
132
|
+
<TestRunStatusStat status="success" />
|
|
133
|
+
<TestRunStatusStat status="error" />
|
|
134
|
+
</div>
|
|
135
|
+
),
|
|
136
|
+
};
|