@pie-players/pie-section-player-tools-shared 0.3.43 → 0.3.44
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/floating-panel.d.ts +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.types.d.ts +7 -0
- package/dist/section-controller.d.ts +0 -1
- package/dist/vite.config.d.ts +0 -1
- package/package.json +5 -28
- package/DebugPanelToggles.svelte +0 -84
- package/PanelResizeHandle.svelte +0 -52
- package/PanelWindowControls.svelte +0 -97
- package/SessionDbPanel.svelte +0 -546
- package/SharedFloatingPanel.svelte +0 -304
- package/dist/floating-panel.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/section-controller.d.ts.map +0 -1
- package/dist/vite.config.d.ts.map +0 -1
- package/floating-panel.ts +0 -187
- package/index.ts +0 -21
- package/section-controller.ts +0 -51
- package/vite.config.ts +0 -36
package/SessionDbPanel.svelte
DELETED
|
@@ -1,546 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { onMount } from "svelte";
|
|
3
|
-
import SharedFloatingPanel from "./SharedFloatingPanel.svelte";
|
|
4
|
-
|
|
5
|
-
type PanelMode = "section" | "assessment";
|
|
6
|
-
type DbTableName = "attempt_sessions" | "section_sessions" | "item_sessions" | "assessment_sessions";
|
|
7
|
-
|
|
8
|
-
interface Props {
|
|
9
|
-
mode?: PanelMode;
|
|
10
|
-
assessmentId: string;
|
|
11
|
-
attemptId: string;
|
|
12
|
-
sectionId?: string;
|
|
13
|
-
apiBasePath?: string;
|
|
14
|
-
onResetDb: () => void | Promise<void>;
|
|
15
|
-
onClose: () => void;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
let {
|
|
19
|
-
mode = "section",
|
|
20
|
-
assessmentId,
|
|
21
|
-
attemptId,
|
|
22
|
-
sectionId = "",
|
|
23
|
-
apiBasePath = "/api/session-demo",
|
|
24
|
-
onResetDb,
|
|
25
|
-
onClose,
|
|
26
|
-
}: Props = $props();
|
|
27
|
-
|
|
28
|
-
let pollError = $state<string | null>(null);
|
|
29
|
-
let activeView = $state<"raw-tables" | "reconstructed" | "request-view">("raw-tables");
|
|
30
|
-
let isResettingDb = $state(false);
|
|
31
|
-
let requestViewJson = $state<string>("{}");
|
|
32
|
-
let requestViewError = $state<string | null>(null);
|
|
33
|
-
let isLoadingRequestView = $state(false);
|
|
34
|
-
const POLL_TIMEOUT_MS = 4500;
|
|
35
|
-
|
|
36
|
-
let scopedRows = $state<Record<DbTableName, Array<Record<string, unknown>>>>({
|
|
37
|
-
attempt_sessions: [],
|
|
38
|
-
section_sessions: [],
|
|
39
|
-
item_sessions: [],
|
|
40
|
-
assessment_sessions: [],
|
|
41
|
-
});
|
|
42
|
-
let scopedColumns = $state<Record<DbTableName, string[]>>({
|
|
43
|
-
attempt_sessions: [],
|
|
44
|
-
section_sessions: [],
|
|
45
|
-
item_sessions: [],
|
|
46
|
-
assessment_sessions: [],
|
|
47
|
-
});
|
|
48
|
-
let reconstructedSnapshotJson = $state<string>("{}");
|
|
49
|
-
|
|
50
|
-
const tableOrder = $derived.by(() =>
|
|
51
|
-
mode === "section"
|
|
52
|
-
? (["attempt_sessions", "section_sessions", "item_sessions"] as DbTableName[])
|
|
53
|
-
: (["attempt_sessions", "assessment_sessions"] as DbTableName[]),
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
const viewTitle = $derived.by(() =>
|
|
57
|
-
mode === "section" ? "Show section request" : "Show assessment request",
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
function collectColumns(rows: Array<Record<string, unknown>>): string[] {
|
|
61
|
-
const seen = new Set<string>();
|
|
62
|
-
const columns: string[] = [];
|
|
63
|
-
for (const row of rows) {
|
|
64
|
-
for (const key of Object.keys(row)) {
|
|
65
|
-
if (seen.has(key)) continue;
|
|
66
|
-
seen.add(key);
|
|
67
|
-
columns.push(key);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
return columns;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function formatCellValue(value: unknown): string {
|
|
74
|
-
if (value === null || value === undefined) return "";
|
|
75
|
-
if (typeof value === "object") {
|
|
76
|
-
try {
|
|
77
|
-
return JSON.stringify(value);
|
|
78
|
-
} catch {
|
|
79
|
-
return "[unserializable]";
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
return String(value);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const COLUMN_HEADER_LABELS: Record<string, string> = {
|
|
86
|
-
id: "id",
|
|
87
|
-
assessment_id: "asm_id",
|
|
88
|
-
attempt_id: "att_id",
|
|
89
|
-
demo_user_id: "demo_uid",
|
|
90
|
-
created_at: "created",
|
|
91
|
-
updated_at: "updated",
|
|
92
|
-
attempt_session_id: "att_sess_id",
|
|
93
|
-
section_id: "sec_id",
|
|
94
|
-
current_item_identifier: "curr_item_id",
|
|
95
|
-
visited_item_identifiers: "visited_item_ids",
|
|
96
|
-
section_session_id: "sec_sess_id",
|
|
97
|
-
item_identifier: "item_id",
|
|
98
|
-
canonical_item_id: "canon_item_id",
|
|
99
|
-
session_payload: "payload",
|
|
100
|
-
snapshot_payload: "payload",
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
function abbreviateColumnName(column: string): string {
|
|
104
|
-
const explicit = COLUMN_HEADER_LABELS[column];
|
|
105
|
-
if (explicit) return explicit;
|
|
106
|
-
if (column.length <= 14) return column;
|
|
107
|
-
const parts = column.split("_").filter(Boolean);
|
|
108
|
-
if (parts.length <= 1) return column.slice(0, 14);
|
|
109
|
-
const abbreviated = parts
|
|
110
|
-
.map((part, index) => (index === parts.length - 1 ? part.slice(0, 4) : part.slice(0, 3)))
|
|
111
|
-
.join("_");
|
|
112
|
-
return abbreviated.slice(0, 18);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
function scopedSnapshotKey(): string {
|
|
116
|
-
return mode === "section"
|
|
117
|
-
? `${assessmentId}:${sectionId}:${attemptId}`
|
|
118
|
-
: `${assessmentId}:${attemptId}`;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
function applyStatePayload(payload: unknown): void {
|
|
122
|
-
const state = (payload as { state?: Record<string, unknown> } | null)?.state || {};
|
|
123
|
-
const stateTables = (state?.tables as Record<string, unknown> | undefined) || {};
|
|
124
|
-
|
|
125
|
-
const attemptRows = Array.isArray(stateTables.attempt_sessions)
|
|
126
|
-
? (stateTables.attempt_sessions as Array<Record<string, unknown>>)
|
|
127
|
-
: [];
|
|
128
|
-
const targetAttemptRows = attemptRows.filter(
|
|
129
|
-
(row) => row.assessment_id === assessmentId && row.attempt_id === attemptId,
|
|
130
|
-
);
|
|
131
|
-
const targetAttemptIds = new Set(
|
|
132
|
-
targetAttemptRows
|
|
133
|
-
.map((row) => row.id)
|
|
134
|
-
.filter((id): id is number => typeof id === "number"),
|
|
135
|
-
);
|
|
136
|
-
|
|
137
|
-
const nextRows: Record<DbTableName, Array<Record<string, unknown>>> = {
|
|
138
|
-
attempt_sessions: targetAttemptRows,
|
|
139
|
-
section_sessions: [],
|
|
140
|
-
item_sessions: [],
|
|
141
|
-
assessment_sessions: [],
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
if (mode === "section") {
|
|
145
|
-
const sectionRows = Array.isArray(stateTables.section_sessions)
|
|
146
|
-
? (stateTables.section_sessions as Array<Record<string, unknown>>)
|
|
147
|
-
: [];
|
|
148
|
-
const targetSectionRows = sectionRows.filter(
|
|
149
|
-
(row) =>
|
|
150
|
-
targetAttemptIds.has(row.attempt_session_id as number) &&
|
|
151
|
-
row.section_id === sectionId,
|
|
152
|
-
);
|
|
153
|
-
nextRows.section_sessions = targetSectionRows;
|
|
154
|
-
const targetSectionIds = new Set(
|
|
155
|
-
targetSectionRows
|
|
156
|
-
.map((row) => row.id)
|
|
157
|
-
.filter((id): id is number => typeof id === "number"),
|
|
158
|
-
);
|
|
159
|
-
const itemRows = Array.isArray(stateTables.item_sessions)
|
|
160
|
-
? (stateTables.item_sessions as Array<Record<string, unknown>>)
|
|
161
|
-
: [];
|
|
162
|
-
nextRows.item_sessions = itemRows.filter((row) =>
|
|
163
|
-
targetSectionIds.has(row.section_session_id as number),
|
|
164
|
-
);
|
|
165
|
-
} else {
|
|
166
|
-
const assessmentRows = Array.isArray(stateTables.assessment_sessions)
|
|
167
|
-
? (stateTables.assessment_sessions as Array<Record<string, unknown>>)
|
|
168
|
-
: [];
|
|
169
|
-
nextRows.assessment_sessions = assessmentRows.filter((row) =>
|
|
170
|
-
targetAttemptIds.has(row.attempt_session_id as number),
|
|
171
|
-
);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
scopedRows = nextRows;
|
|
175
|
-
scopedColumns = {
|
|
176
|
-
attempt_sessions: collectColumns(nextRows.attempt_sessions),
|
|
177
|
-
section_sessions: collectColumns(nextRows.section_sessions),
|
|
178
|
-
item_sessions: collectColumns(nextRows.item_sessions),
|
|
179
|
-
assessment_sessions: collectColumns(nextRows.assessment_sessions),
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
const snapshots =
|
|
183
|
-
(state.reconstructedSnapshots as Record<string, unknown> | undefined) || {};
|
|
184
|
-
const key = scopedSnapshotKey();
|
|
185
|
-
reconstructedSnapshotJson = JSON.stringify(snapshots[key] || {}, null, 2);
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
async function handleResetDb(): Promise<void> {
|
|
189
|
-
if (isResettingDb) return;
|
|
190
|
-
isResettingDb = true;
|
|
191
|
-
try {
|
|
192
|
-
await onResetDb();
|
|
193
|
-
} finally {
|
|
194
|
-
isResettingDb = false;
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
async function fetchDbStateOnce(): Promise<void> {
|
|
199
|
-
const controller = new AbortController();
|
|
200
|
-
const timeoutId = setTimeout(() => controller.abort(), POLL_TIMEOUT_MS);
|
|
201
|
-
try {
|
|
202
|
-
const response = await fetch(`${apiBasePath}/state`, {
|
|
203
|
-
signal: controller.signal,
|
|
204
|
-
cache: "no-store",
|
|
205
|
-
});
|
|
206
|
-
if (!response.ok) {
|
|
207
|
-
throw new Error(`DB state request failed (${response.status})`);
|
|
208
|
-
}
|
|
209
|
-
applyStatePayload(await response.json());
|
|
210
|
-
pollError = null;
|
|
211
|
-
} catch (error) {
|
|
212
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
213
|
-
pollError = `DB state request timed out after ${POLL_TIMEOUT_MS}ms`;
|
|
214
|
-
} else {
|
|
215
|
-
pollError = error instanceof Error ? error.message : String(error);
|
|
216
|
-
}
|
|
217
|
-
} finally {
|
|
218
|
-
clearTimeout(timeoutId);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
async function fetchRequestView(): Promise<void> {
|
|
223
|
-
if (activeView !== "request-view") return;
|
|
224
|
-
isLoadingRequestView = true;
|
|
225
|
-
requestViewError = null;
|
|
226
|
-
const query = new URLSearchParams({
|
|
227
|
-
assessmentId,
|
|
228
|
-
attemptId,
|
|
229
|
-
});
|
|
230
|
-
if (mode === "section" && sectionId) {
|
|
231
|
-
query.set("sectionId", sectionId);
|
|
232
|
-
}
|
|
233
|
-
try {
|
|
234
|
-
const response = await fetch(`${apiBasePath}/activity/load?${query.toString()}`, {
|
|
235
|
-
cache: "no-store",
|
|
236
|
-
});
|
|
237
|
-
if (!response.ok) {
|
|
238
|
-
throw new Error(`Request view failed (${response.status})`);
|
|
239
|
-
}
|
|
240
|
-
requestViewJson = JSON.stringify(await response.json(), null, 2);
|
|
241
|
-
} catch (error) {
|
|
242
|
-
requestViewError = error instanceof Error ? error.message : String(error);
|
|
243
|
-
} finally {
|
|
244
|
-
isLoadingRequestView = false;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
$effect(() => {
|
|
249
|
-
if (typeof EventSource === "undefined") {
|
|
250
|
-
pollError = "Live updates are not supported in this browser";
|
|
251
|
-
void fetchDbStateOnce();
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
const eventSource = new EventSource(`${apiBasePath}/state/stream`);
|
|
255
|
-
const onState = (event: MessageEvent<string>) => {
|
|
256
|
-
try {
|
|
257
|
-
applyStatePayload(JSON.parse(event.data));
|
|
258
|
-
if (activeView === "request-view") {
|
|
259
|
-
void fetchRequestView();
|
|
260
|
-
}
|
|
261
|
-
pollError = null;
|
|
262
|
-
} catch (error) {
|
|
263
|
-
pollError = error instanceof Error ? error.message : String(error);
|
|
264
|
-
}
|
|
265
|
-
};
|
|
266
|
-
eventSource.addEventListener("state", onState as EventListener);
|
|
267
|
-
eventSource.onerror = () => {
|
|
268
|
-
pollError = "Live updates disconnected; retrying...";
|
|
269
|
-
};
|
|
270
|
-
return () => {
|
|
271
|
-
eventSource.removeEventListener("state", onState as EventListener);
|
|
272
|
-
eventSource.close();
|
|
273
|
-
};
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
$effect(() => {
|
|
277
|
-
void activeView;
|
|
278
|
-
void assessmentId;
|
|
279
|
-
void sectionId;
|
|
280
|
-
void attemptId;
|
|
281
|
-
void mode;
|
|
282
|
-
if (activeView !== "request-view") return;
|
|
283
|
-
void fetchRequestView();
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
onMount(() => {
|
|
287
|
-
void fetchDbStateOnce();
|
|
288
|
-
});
|
|
289
|
-
</script>
|
|
290
|
-
|
|
291
|
-
<SharedFloatingPanel
|
|
292
|
-
title="Session DB (Server)"
|
|
293
|
-
ariaLabel="Drag session DB panel"
|
|
294
|
-
minWidth={420}
|
|
295
|
-
minHeight={320}
|
|
296
|
-
initialSizing={{
|
|
297
|
-
widthRatio: 0.38,
|
|
298
|
-
heightRatio: 0.78,
|
|
299
|
-
minWidth: 440,
|
|
300
|
-
maxWidth: 900,
|
|
301
|
-
minHeight: 380,
|
|
302
|
-
maxHeight: 900,
|
|
303
|
-
alignX: "right",
|
|
304
|
-
alignY: "bottom",
|
|
305
|
-
paddingX: 18,
|
|
306
|
-
paddingY: 18,
|
|
307
|
-
}}
|
|
308
|
-
className="pie-demo-session-db-panel"
|
|
309
|
-
bodyClass="pie-demo-session-db-panel__content-shell"
|
|
310
|
-
onClose={onClose}
|
|
311
|
-
>
|
|
312
|
-
<div class="pie-demo-session-db-panel__content">
|
|
313
|
-
<div class="pie-demo-session-db-panel__meta">
|
|
314
|
-
<div><strong>assessmentId:</strong> <code>{assessmentId}</code></div>
|
|
315
|
-
{#if mode === "section"}
|
|
316
|
-
<div><strong>sectionId:</strong> <code>{sectionId}</code></div>
|
|
317
|
-
{/if}
|
|
318
|
-
<div><strong>attemptId:</strong> <code>{attemptId}</code></div>
|
|
319
|
-
<div><strong>mode:</strong> <code>{mode}</code></div>
|
|
320
|
-
</div>
|
|
321
|
-
|
|
322
|
-
<div class="pie-demo-session-db-panel__actions">
|
|
323
|
-
<button
|
|
324
|
-
type="button"
|
|
325
|
-
class="pie-demo-session-db-panel__button"
|
|
326
|
-
onclick={() => void handleResetDb()}
|
|
327
|
-
disabled={isResettingDb}
|
|
328
|
-
aria-busy={isResettingDb}
|
|
329
|
-
>
|
|
330
|
-
{isResettingDb ? "Resetting to baseline..." : "Reset DB to baseline"}
|
|
331
|
-
</button>
|
|
332
|
-
<button
|
|
333
|
-
type="button"
|
|
334
|
-
class="pie-demo-session-db-panel__button"
|
|
335
|
-
onclick={() => (activeView = "raw-tables")}
|
|
336
|
-
aria-pressed={activeView === "raw-tables"}
|
|
337
|
-
>
|
|
338
|
-
Show raw tables
|
|
339
|
-
</button>
|
|
340
|
-
<button
|
|
341
|
-
type="button"
|
|
342
|
-
class="pie-demo-session-db-panel__button"
|
|
343
|
-
onclick={() => (activeView = "reconstructed")}
|
|
344
|
-
aria-pressed={activeView === "reconstructed"}
|
|
345
|
-
>
|
|
346
|
-
Show reconstructed snapshots
|
|
347
|
-
</button>
|
|
348
|
-
<button
|
|
349
|
-
type="button"
|
|
350
|
-
class="pie-demo-session-db-panel__button"
|
|
351
|
-
onclick={() => (activeView = "request-view")}
|
|
352
|
-
aria-pressed={activeView === "request-view"}
|
|
353
|
-
>
|
|
354
|
-
{viewTitle}
|
|
355
|
-
</button>
|
|
356
|
-
</div>
|
|
357
|
-
|
|
358
|
-
{#if pollError}
|
|
359
|
-
<div class="pie-demo-session-db-panel__error">{pollError}</div>
|
|
360
|
-
{/if}
|
|
361
|
-
|
|
362
|
-
{#if activeView === "raw-tables"}
|
|
363
|
-
<div class="pie-demo-session-db-panel__tables">
|
|
364
|
-
{#each tableOrder as tableName}
|
|
365
|
-
<h4 class="pie-demo-session-db-panel__table-title">{tableName}</h4>
|
|
366
|
-
<div class="pie-demo-session-db-panel__table-wrap">
|
|
367
|
-
<table class="pie-demo-session-db-panel__table">
|
|
368
|
-
<thead>
|
|
369
|
-
<tr>
|
|
370
|
-
{#each scopedColumns[tableName] as column}
|
|
371
|
-
<th title={column}>{abbreviateColumnName(column)}</th>
|
|
372
|
-
{/each}
|
|
373
|
-
</tr>
|
|
374
|
-
</thead>
|
|
375
|
-
<tbody>
|
|
376
|
-
{#if scopedRows[tableName].length === 0}
|
|
377
|
-
<tr>
|
|
378
|
-
<td colspan={Math.max(scopedColumns[tableName].length, 1)}>No rows</td>
|
|
379
|
-
</tr>
|
|
380
|
-
{:else}
|
|
381
|
-
{#each scopedRows[tableName] as row}
|
|
382
|
-
<tr>
|
|
383
|
-
{#each scopedColumns[tableName] as column}
|
|
384
|
-
<td>{formatCellValue(row[column])}</td>
|
|
385
|
-
{/each}
|
|
386
|
-
</tr>
|
|
387
|
-
{/each}
|
|
388
|
-
{/if}
|
|
389
|
-
</tbody>
|
|
390
|
-
</table>
|
|
391
|
-
</div>
|
|
392
|
-
{/each}
|
|
393
|
-
</div>
|
|
394
|
-
{:else if activeView === "reconstructed"}
|
|
395
|
-
<textarea
|
|
396
|
-
class="pie-demo-session-db-panel__json"
|
|
397
|
-
readonly
|
|
398
|
-
value={reconstructedSnapshotJson}
|
|
399
|
-
spellcheck="false"
|
|
400
|
-
></textarea>
|
|
401
|
-
{:else}
|
|
402
|
-
{#if requestViewError}
|
|
403
|
-
<div class="pie-demo-session-db-panel__error">{requestViewError}</div>
|
|
404
|
-
{/if}
|
|
405
|
-
<textarea
|
|
406
|
-
class="pie-demo-session-db-panel__json"
|
|
407
|
-
readonly
|
|
408
|
-
value={isLoadingRequestView ? "Loading request view..." : requestViewJson}
|
|
409
|
-
spellcheck="false"
|
|
410
|
-
></textarea>
|
|
411
|
-
{/if}
|
|
412
|
-
</div>
|
|
413
|
-
</SharedFloatingPanel>
|
|
414
|
-
|
|
415
|
-
<style>
|
|
416
|
-
.pie-demo-session-db-panel__content {
|
|
417
|
-
display: flex;
|
|
418
|
-
flex-direction: column;
|
|
419
|
-
flex: 1;
|
|
420
|
-
height: 100%;
|
|
421
|
-
min-height: 0;
|
|
422
|
-
overflow-y: hidden;
|
|
423
|
-
overflow-x: hidden;
|
|
424
|
-
padding: 12px;
|
|
425
|
-
font-size: 0.8rem;
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
.pie-demo-session-db-panel__meta {
|
|
429
|
-
display: grid;
|
|
430
|
-
gap: 0.2rem;
|
|
431
|
-
margin-bottom: 0.55rem;
|
|
432
|
-
font-size: 0.78rem;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
.pie-demo-session-db-panel__actions {
|
|
436
|
-
display: flex;
|
|
437
|
-
gap: 0.45rem;
|
|
438
|
-
margin-bottom: 0.5rem;
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
.pie-demo-session-db-panel__button {
|
|
442
|
-
border: 1px solid var(--color-base-300, #d1d5db);
|
|
443
|
-
background: var(--color-base-100, #fff);
|
|
444
|
-
color: var(--color-base-content);
|
|
445
|
-
border-radius: 6px;
|
|
446
|
-
padding: 6px 8px;
|
|
447
|
-
font-size: 0.78rem;
|
|
448
|
-
cursor: pointer;
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
.pie-demo-session-db-panel__button:hover {
|
|
452
|
-
background: color-mix(in srgb, var(--color-base-200) 65%, white);
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
.pie-demo-session-db-panel__button[aria-pressed="true"] {
|
|
456
|
-
background: color-mix(in srgb, var(--color-primary, #2563eb) 18%, transparent);
|
|
457
|
-
font-weight: 600;
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
.pie-demo-session-db-panel__button:disabled {
|
|
461
|
-
opacity: 0.6;
|
|
462
|
-
cursor: not-allowed;
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
.pie-demo-session-db-panel__error {
|
|
466
|
-
margin-bottom: 0.5rem;
|
|
467
|
-
padding: 0.4rem 0.45rem;
|
|
468
|
-
border-radius: 0.3rem;
|
|
469
|
-
background: color-mix(in srgb, var(--color-error) 12%, var(--color-base-100));
|
|
470
|
-
border: 1px solid color-mix(in srgb, var(--color-error) 35%, var(--color-base-300));
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
.pie-demo-session-db-panel__tables {
|
|
474
|
-
display: flex;
|
|
475
|
-
flex-direction: column;
|
|
476
|
-
gap: 0.5rem;
|
|
477
|
-
flex: 1;
|
|
478
|
-
min-height: 0;
|
|
479
|
-
overflow: auto;
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
.pie-demo-session-db-panel__table-title {
|
|
483
|
-
margin: 0;
|
|
484
|
-
font-size: 0.75rem;
|
|
485
|
-
font-weight: 700;
|
|
486
|
-
text-transform: lowercase;
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
.pie-demo-session-db-panel__table-wrap {
|
|
490
|
-
border: 1px solid color-mix(in srgb, var(--color-base-content) 25%, transparent);
|
|
491
|
-
border-radius: 0.3rem;
|
|
492
|
-
background: color-mix(in srgb, var(--color-base-200) 65%, white);
|
|
493
|
-
overflow: auto;
|
|
494
|
-
max-height: 9.5rem;
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
.pie-demo-session-db-panel__table {
|
|
498
|
-
width: 100%;
|
|
499
|
-
border-collapse: collapse;
|
|
500
|
-
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
501
|
-
font-size: 0.72rem;
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
.pie-demo-session-db-panel__table th,
|
|
505
|
-
.pie-demo-session-db-panel__table td {
|
|
506
|
-
padding: 0.25rem 0.35rem;
|
|
507
|
-
border-bottom: 1px solid color-mix(in srgb, var(--color-base-content) 14%, transparent);
|
|
508
|
-
vertical-align: top;
|
|
509
|
-
text-align: left;
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
.pie-demo-session-db-panel__table th {
|
|
513
|
-
position: sticky;
|
|
514
|
-
top: 0;
|
|
515
|
-
background: color-mix(in srgb, var(--color-base-200) 85%, white);
|
|
516
|
-
font-weight: 700;
|
|
517
|
-
font-size: 0.66rem;
|
|
518
|
-
line-height: 1.15;
|
|
519
|
-
padding: 0.18rem 0.3rem;
|
|
520
|
-
white-space: nowrap;
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
.pie-demo-session-db-panel__table td {
|
|
524
|
-
white-space: nowrap;
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
.pie-demo-session-db-panel__meta code,
|
|
528
|
-
.pie-demo-session-db-panel__json {
|
|
529
|
-
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
.pie-demo-session-db-panel__json {
|
|
533
|
-
width: 100%;
|
|
534
|
-
flex: 1;
|
|
535
|
-
min-height: 14rem;
|
|
536
|
-
resize: none;
|
|
537
|
-
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
538
|
-
font-size: 0.75rem;
|
|
539
|
-
border: 1px solid color-mix(in srgb, var(--color-base-content) 25%, transparent);
|
|
540
|
-
border-radius: 0.3rem;
|
|
541
|
-
padding: 0.45rem;
|
|
542
|
-
background: color-mix(in srgb, var(--color-base-200) 65%, white);
|
|
543
|
-
color: var(--color-base-content);
|
|
544
|
-
box-sizing: border-box;
|
|
545
|
-
}
|
|
546
|
-
</style>
|