@burdenoff/microfe-bigconsole 2026.616.1 → 2026.617.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.
|
@@ -309,114 +309,131 @@ var Ee = p(function({ widget: e, onSave: t }) {
|
|
|
309
309
|
})
|
|
310
310
|
]
|
|
311
311
|
});
|
|
312
|
-
})
|
|
313
|
-
|
|
312
|
+
});
|
|
313
|
+
function I(e) {
|
|
314
|
+
let t = e;
|
|
315
|
+
return {
|
|
316
|
+
title: e.title || "",
|
|
317
|
+
description: e.description || "",
|
|
318
|
+
refreshInterval: e.refreshInterval ?? void 0,
|
|
319
|
+
renderer: e.renderer || "BIGCONSOLE",
|
|
320
|
+
template: e.template,
|
|
321
|
+
dataSinkId: t.dataSinkId ?? void 0,
|
|
322
|
+
datasetId: t.datasetId ?? void 0,
|
|
323
|
+
parserId: t.parserId ?? void 0,
|
|
324
|
+
parserRules: t.parserRules ?? void 0,
|
|
325
|
+
config: e.config || {},
|
|
326
|
+
drilldownConfig: e.drilldown ? {
|
|
327
|
+
enabled: e.drilldown.enabled ?? !1,
|
|
328
|
+
targetDashboardId: e.drilldown.targetDashboardId ?? "",
|
|
329
|
+
navigationMode: e.drilldown.navigationMode ?? "MODAL",
|
|
330
|
+
parameterMapping: e.drilldown.parameterMapping ?? {},
|
|
331
|
+
passGlobalFilters: e.drilldown.passGlobalFilters ?? !0,
|
|
332
|
+
maxDepth: e.drilldown.maxDepth ?? 3,
|
|
333
|
+
openIn: e.drilldown.openIn ?? "same"
|
|
334
|
+
} : void 0
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
var L = p(function({ isOpen: s, onClose: c }) {
|
|
338
|
+
let [l, u] = _("general"), [d, f] = _("idle"), [p, y] = _(null), [L, R] = _(!1), z = e((e) => e.selectedWidgetId), De = e((e) => e.widgets), B = e((e) => e.updateWidget), V = z ? De.get(z) : void 0, H = g(null);
|
|
314
339
|
h(() => {
|
|
315
|
-
z
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
passGlobalFilters: z.drilldown.passGlobalFilters ?? !0,
|
|
332
|
-
maxDepth: z.drilldown.maxDepth ?? 3,
|
|
333
|
-
openIn: z.drilldown.openIn ?? "same"
|
|
334
|
-
} : void 0
|
|
335
|
-
}), I(!1), f("idle")) : g(null);
|
|
336
|
-
}, [z]);
|
|
337
|
-
let { updateWidget: B } = n(z?.pageId, z?.dashboardId, { skipFetch: !0 }), { createDrilldown: V, updateDrilldown: H, deleteDrilldown: U } = r(), { dataSinks: W } = a({ skipFetch: !1 }), [G, K] = _(null), { executeParser: Oe } = o({
|
|
338
|
-
consoleId: z?.dashboardId,
|
|
340
|
+
if (!z) {
|
|
341
|
+
H.current = null, y(null), R(!1), f("idle");
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
let e = H.current !== z;
|
|
345
|
+
if (H.current = z, V) {
|
|
346
|
+
if (L && !e) return;
|
|
347
|
+
y(I(V)), R(!1), f("idle");
|
|
348
|
+
} else y(null), R(!1), f("idle");
|
|
349
|
+
}, [
|
|
350
|
+
z,
|
|
351
|
+
V,
|
|
352
|
+
L
|
|
353
|
+
]);
|
|
354
|
+
let { updateWidget: U } = n(V?.pageId, V?.dashboardId, { skipFetch: !0 }), { createDrilldown: Oe, updateDrilldown: ke, deleteDrilldown: Ae } = r(), { dataSinks: W } = a({ skipFetch: !1 }), [G, K] = _(null), { executeParser: je } = o({
|
|
355
|
+
consoleId: V?.dashboardId,
|
|
339
356
|
skipFetch: !0
|
|
340
|
-
}), [
|
|
357
|
+
}), [Me, Ne] = _(!1), { actions: q, loading: J, createAction: Pe, updateAction: Fe, deleteAction: Ie, reorderActions: Y } = i(z || void 0), [Le, X] = _(!1), [Re, Z] = _(void 0), [ze, Be] = _(!1), Ve = m(() => {
|
|
341
358
|
Z(void 0), X(!0);
|
|
342
|
-
}, []),
|
|
359
|
+
}, []), He = m((e) => {
|
|
343
360
|
Z(e), X(!0);
|
|
344
|
-
}, []),
|
|
345
|
-
if (
|
|
346
|
-
|
|
361
|
+
}, []), Ue = m(async (e) => {
|
|
362
|
+
if (z) {
|
|
363
|
+
Be(!0);
|
|
347
364
|
try {
|
|
348
365
|
let t = null;
|
|
349
|
-
if (t = "id" in e ? await
|
|
366
|
+
if (t = "id" in e ? await Fe(e) : await Pe(e), t) {
|
|
350
367
|
let n = [...q];
|
|
351
368
|
if ("id" in e) {
|
|
352
369
|
let r = n.findIndex((t) => t.id === e.id);
|
|
353
370
|
r >= 0 && (n[r] = t);
|
|
354
371
|
} else n.push(t);
|
|
355
|
-
|
|
372
|
+
B(z, { actions: n.sort((e, t) => e.order - t.order) });
|
|
356
373
|
}
|
|
357
374
|
X(!1), Z(void 0);
|
|
358
375
|
} catch {} finally {
|
|
359
|
-
|
|
376
|
+
Be(!1);
|
|
360
377
|
}
|
|
361
378
|
}
|
|
362
379
|
}, [
|
|
363
|
-
|
|
380
|
+
z,
|
|
364
381
|
q,
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
]),
|
|
369
|
-
|
|
382
|
+
Pe,
|
|
383
|
+
Fe,
|
|
384
|
+
B
|
|
385
|
+
]), We = m(async (e) => {
|
|
386
|
+
z && window.confirm("Are you sure you want to delete this action?") && await Ie(e) && B(z, { actions: q.filter((t) => t.id !== e) });
|
|
370
387
|
}, [
|
|
371
|
-
|
|
388
|
+
z,
|
|
372
389
|
q,
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
]),
|
|
376
|
-
if (!
|
|
390
|
+
Ie,
|
|
391
|
+
B
|
|
392
|
+
]), Ge = m(async (e) => {
|
|
393
|
+
if (!z || e === 0) return;
|
|
377
394
|
let t = [...q].sort((e, t) => e.order - t.order), n = t.map((e) => e.id);
|
|
378
|
-
[n[e - 1], n[e]] = [n[e], n[e - 1]], await Y(n) &&
|
|
395
|
+
[n[e - 1], n[e]] = [n[e], n[e - 1]], await Y(n) && B(z, { actions: t.map((e, t) => ({
|
|
379
396
|
...e,
|
|
380
397
|
order: n.indexOf(e.id)
|
|
381
398
|
})).sort((e, t) => e.order - t.order) });
|
|
382
399
|
}, [
|
|
383
|
-
|
|
400
|
+
z,
|
|
384
401
|
q,
|
|
385
402
|
Y,
|
|
386
|
-
|
|
387
|
-
]),
|
|
388
|
-
if (!
|
|
403
|
+
B
|
|
404
|
+
]), Ke = m(async (e) => {
|
|
405
|
+
if (!z) return;
|
|
389
406
|
let t = [...q].sort((e, t) => e.order - t.order);
|
|
390
407
|
if (e === t.length - 1) return;
|
|
391
408
|
let n = t.map((e) => e.id);
|
|
392
|
-
[n[e], n[e + 1]] = [n[e + 1], n[e]], await Y(n) &&
|
|
409
|
+
[n[e], n[e + 1]] = [n[e + 1], n[e]], await Y(n) && B(z, { actions: t.map((e, t) => ({
|
|
393
410
|
...e,
|
|
394
411
|
order: n.indexOf(e.id)
|
|
395
412
|
})).sort((e, t) => e.order - t.order) });
|
|
396
413
|
}, [
|
|
397
|
-
|
|
414
|
+
z,
|
|
398
415
|
q,
|
|
399
416
|
Y,
|
|
400
|
-
|
|
417
|
+
B
|
|
401
418
|
]);
|
|
402
419
|
h(() => {
|
|
403
|
-
|
|
420
|
+
z && q.length >= 0 && !J && B(z, { actions: q });
|
|
404
421
|
}, [
|
|
405
|
-
|
|
422
|
+
z,
|
|
406
423
|
q,
|
|
407
424
|
J,
|
|
408
|
-
|
|
425
|
+
B
|
|
409
426
|
]);
|
|
410
427
|
let Q = m((e, t) => {
|
|
411
|
-
|
|
428
|
+
y((n) => n && {
|
|
412
429
|
...n,
|
|
413
430
|
[e]: t
|
|
414
|
-
}),
|
|
431
|
+
}), R(!0);
|
|
415
432
|
}, []), $ = m((e) => {
|
|
416
|
-
|
|
433
|
+
y((t) => t && {
|
|
417
434
|
...t,
|
|
418
435
|
config: e
|
|
419
|
-
}),
|
|
436
|
+
}), R(!0);
|
|
420
437
|
}, []);
|
|
421
438
|
h(() => {
|
|
422
439
|
if (p?.dataSinkId && W.length > 0) {
|
|
@@ -424,59 +441,59 @@ var Ee = p(function({ widget: e, onSave: t }) {
|
|
|
424
441
|
e && K(e.key);
|
|
425
442
|
} else K(null);
|
|
426
443
|
}, [p?.dataSinkId, W]);
|
|
427
|
-
let
|
|
444
|
+
let qe = m((e) => {
|
|
428
445
|
if (K(e), e) {
|
|
429
446
|
let t = W.find((t) => t.key === e);
|
|
430
|
-
t && (Q("dataSinkId", t.id),
|
|
447
|
+
t && (Q("dataSinkId", t.id), y((t) => t && {
|
|
431
448
|
...t,
|
|
432
449
|
config: {
|
|
433
450
|
...t.config,
|
|
434
451
|
dataSinkKey: e
|
|
435
452
|
}
|
|
436
|
-
}),
|
|
437
|
-
} else Q("dataSinkId", void 0),
|
|
453
|
+
}), R(!0));
|
|
454
|
+
} else Q("dataSinkId", void 0), y((e) => e && {
|
|
438
455
|
...e,
|
|
439
456
|
config: {
|
|
440
457
|
...e.config,
|
|
441
458
|
dataSinkKey: void 0
|
|
442
459
|
},
|
|
443
460
|
parserId: void 0
|
|
444
|
-
}),
|
|
445
|
-
}, [W, Q]),
|
|
446
|
-
if (Q("parserId", e || void 0), e &&
|
|
447
|
-
|
|
461
|
+
}), R(!0);
|
|
462
|
+
}, [W, Q]), Je = m(async (e) => {
|
|
463
|
+
if (Q("parserId", e || void 0), e && V) {
|
|
464
|
+
Ne(!0);
|
|
448
465
|
try {
|
|
449
|
-
let t = await
|
|
466
|
+
let t = await je(e);
|
|
450
467
|
if (t?.success && t.output) {
|
|
451
468
|
let e = we(t.output);
|
|
452
|
-
(e.labelField || e.valueField) && (
|
|
469
|
+
(e.labelField || e.valueField) && (y((t) => {
|
|
453
470
|
if (!t) return t;
|
|
454
471
|
let n = t.config || {}, r = { ...n };
|
|
455
472
|
return e.labelField && !n.labelField && (r.labelField = e.labelField), e.valueField && !n.valueField && (r.valueField = e.valueField), e.xAxisField && !n.xAxisField && (r.xAxisField = e.xAxisField), {
|
|
456
473
|
...t,
|
|
457
474
|
config: r
|
|
458
475
|
};
|
|
459
|
-
}),
|
|
476
|
+
}), R(!0));
|
|
460
477
|
}
|
|
461
478
|
} catch (e) {
|
|
462
479
|
console.warn("Failed to auto-detect parser fields:", e);
|
|
463
480
|
} finally {
|
|
464
|
-
|
|
481
|
+
Ne(!1);
|
|
465
482
|
}
|
|
466
483
|
}
|
|
467
484
|
}, [
|
|
468
485
|
Q,
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
]),
|
|
472
|
-
if (!(!
|
|
486
|
+
je,
|
|
487
|
+
V
|
|
488
|
+
]), Ye = m(async () => {
|
|
489
|
+
if (!(!V || !p)) {
|
|
473
490
|
f("saving");
|
|
474
491
|
try {
|
|
475
492
|
let e = {
|
|
476
|
-
...
|
|
493
|
+
...V.metadata || {},
|
|
477
494
|
description: p.description || ""
|
|
478
|
-
}, t = await
|
|
479
|
-
id:
|
|
495
|
+
}, t = await U({
|
|
496
|
+
id: V.id,
|
|
480
497
|
title: p.title,
|
|
481
498
|
renderer: p.renderer,
|
|
482
499
|
template: p.template,
|
|
@@ -487,12 +504,12 @@ var Ee = p(function({ widget: e, onSave: t }) {
|
|
|
487
504
|
parserId: p.parserId,
|
|
488
505
|
parserRules: p.parserRules,
|
|
489
506
|
metadata: e
|
|
490
|
-
}), n =
|
|
507
|
+
}), n = V.drilldown;
|
|
491
508
|
if (p.drilldownConfig) {
|
|
492
509
|
let { enabled: e, targetDashboardId: t, navigationMode: r, parameterMapping: i, passGlobalFilters: a, maxDepth: o, openIn: s } = p.drilldownConfig;
|
|
493
|
-
if (
|
|
494
|
-
let c = await
|
|
495
|
-
id:
|
|
510
|
+
if (V.drilldown?.id) {
|
|
511
|
+
let c = await ke({
|
|
512
|
+
id: V.drilldown.id,
|
|
496
513
|
targetDashboardId: t,
|
|
497
514
|
parameterMapping: i,
|
|
498
515
|
navigationMode: r,
|
|
@@ -503,8 +520,8 @@ var Ee = p(function({ widget: e, onSave: t }) {
|
|
|
503
520
|
});
|
|
504
521
|
c && (n = c);
|
|
505
522
|
} else if (t) {
|
|
506
|
-
let c = await
|
|
507
|
-
sourceWidgetId:
|
|
523
|
+
let c = await Oe({
|
|
524
|
+
sourceWidgetId: V.id,
|
|
508
525
|
targetDashboardId: t,
|
|
509
526
|
parameterMapping: i || {},
|
|
510
527
|
navigationMode: r,
|
|
@@ -517,8 +534,8 @@ var Ee = p(function({ widget: e, onSave: t }) {
|
|
|
517
534
|
enabled: e
|
|
518
535
|
});
|
|
519
536
|
}
|
|
520
|
-
} else
|
|
521
|
-
t ? (
|
|
537
|
+
} else V.drilldown?.id && !p.drilldownConfig && (await Ae(V.drilldown.id), n = void 0);
|
|
538
|
+
t ? (B(V.id, {
|
|
522
539
|
title: p.title,
|
|
523
540
|
description: p.description,
|
|
524
541
|
renderer: p.renderer,
|
|
@@ -531,49 +548,29 @@ var Ee = p(function({ widget: e, onSave: t }) {
|
|
|
531
548
|
parserRules: p.parserRules,
|
|
532
549
|
drilldown: n,
|
|
533
550
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
534
|
-
}), f("saved"),
|
|
551
|
+
}), f("saved"), R(!1), setTimeout(() => f("idle"), 2e3)) : f("error");
|
|
535
552
|
} catch {
|
|
536
553
|
f("error");
|
|
537
554
|
}
|
|
538
555
|
}
|
|
539
556
|
}, [
|
|
540
|
-
|
|
557
|
+
V,
|
|
541
558
|
p,
|
|
559
|
+
U,
|
|
542
560
|
B,
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
title: z.title || "",
|
|
550
|
-
description: z.description || "",
|
|
551
|
-
refreshInterval: z.refreshInterval ?? void 0,
|
|
552
|
-
renderer: z.renderer || "BIGCONSOLE",
|
|
553
|
-
template: z.template,
|
|
554
|
-
dataSinkId: z.dataSinkId ?? void 0,
|
|
555
|
-
datasetId: z.datasetId ?? void 0,
|
|
556
|
-
parserId: z.parserId ?? void 0,
|
|
557
|
-
parserRules: z.parserRules ?? void 0,
|
|
558
|
-
config: z.config || {},
|
|
559
|
-
drilldownConfig: z.drilldown ? {
|
|
560
|
-
enabled: z.drilldown.enabled ?? !1,
|
|
561
|
-
targetDashboardId: z.drilldown.targetDashboardId ?? "",
|
|
562
|
-
navigationMode: z.drilldown.navigationMode ?? "MODAL",
|
|
563
|
-
parameterMapping: z.drilldown.parameterMapping ?? {},
|
|
564
|
-
passGlobalFilters: z.drilldown.passGlobalFilters ?? !0,
|
|
565
|
-
maxDepth: z.drilldown.maxDepth ?? 3,
|
|
566
|
-
openIn: z.drilldown.openIn ?? "same"
|
|
567
|
-
} : void 0
|
|
568
|
-
}), I(!1), f("idle"));
|
|
569
|
-
}, [z]), Je = m((e) => {
|
|
561
|
+
Oe,
|
|
562
|
+
ke,
|
|
563
|
+
Ae
|
|
564
|
+
]), Xe = m(() => {
|
|
565
|
+
V && (y(I(V)), R(!1), f("idle"));
|
|
566
|
+
}, [V]), Ze = m((e) => {
|
|
570
567
|
$(e);
|
|
571
|
-
}, [$]),
|
|
572
|
-
|
|
568
|
+
}, [$]), Qe = m((e) => {
|
|
569
|
+
y((t) => t && {
|
|
573
570
|
...t,
|
|
574
571
|
drilldownConfig: e
|
|
575
|
-
}),
|
|
576
|
-
}, []),
|
|
572
|
+
}), R(!0);
|
|
573
|
+
}, []), $e = V ? t(V.type) : null, et = V ? Te(V.type) : null;
|
|
577
574
|
return /* @__PURE__ */ S(me, {
|
|
578
575
|
open: s,
|
|
579
576
|
onOpenChange: (e) => !e && c(),
|
|
@@ -638,7 +635,7 @@ var Ee = p(function({ widget: e, onSave: t }) {
|
|
|
638
635
|
color: "var(--color-text-primary)",
|
|
639
636
|
margin: 0
|
|
640
637
|
},
|
|
641
|
-
children:
|
|
638
|
+
children: V ? "Widget Properties" : "Properties"
|
|
642
639
|
}),
|
|
643
640
|
d === "saving" && /* @__PURE__ */ S(M, { style: {
|
|
644
641
|
height: "var(--size-icon-sm)",
|
|
@@ -655,19 +652,19 @@ var Ee = p(function({ widget: e, onSave: t }) {
|
|
|
655
652
|
color: "var(--color-status-error-bg)"
|
|
656
653
|
} })
|
|
657
654
|
]
|
|
658
|
-
}),
|
|
655
|
+
}), $e && /* @__PURE__ */ S(ge, {
|
|
659
656
|
style: {
|
|
660
657
|
fontSize: "var(--font-size-body-sm)",
|
|
661
658
|
color: "var(--color-text-secondary)",
|
|
662
659
|
margin: "var(--space-controlGap) 0 0 0",
|
|
663
660
|
fontWeight: "var(--font-weight-medium)"
|
|
664
661
|
},
|
|
665
|
-
children:
|
|
662
|
+
children: $e.name
|
|
666
663
|
})]
|
|
667
664
|
})]
|
|
668
665
|
})
|
|
669
666
|
}),
|
|
670
|
-
|
|
667
|
+
V ? /* @__PURE__ */ C(ye, {
|
|
671
668
|
value: l,
|
|
672
669
|
onValueChange: (e) => u(e),
|
|
673
670
|
style: {
|
|
@@ -901,7 +898,7 @@ var Ee = p(function({ widget: e, onSave: t }) {
|
|
|
901
898
|
}),
|
|
902
899
|
p.renderer && p.renderer !== "BIGCONSOLE" && /* @__PURE__ */ S(Ee, {
|
|
903
900
|
widget: {
|
|
904
|
-
...
|
|
901
|
+
...V,
|
|
905
902
|
template: p.template,
|
|
906
903
|
renderer: p.renderer
|
|
907
904
|
},
|
|
@@ -930,7 +927,7 @@ var Ee = p(function({ widget: e, onSave: t }) {
|
|
|
930
927
|
/* @__PURE__ */ S(E, { children: "DataSink" }),
|
|
931
928
|
/* @__PURE__ */ S(ee, {
|
|
932
929
|
value: G,
|
|
933
|
-
onChange:
|
|
930
|
+
onChange: qe,
|
|
934
931
|
placeholder: "Select a DataSink..."
|
|
935
932
|
}),
|
|
936
933
|
G && /* @__PURE__ */ C("p", {
|
|
@@ -955,9 +952,9 @@ var Ee = p(function({ widget: e, onSave: t }) {
|
|
|
955
952
|
children: [
|
|
956
953
|
/* @__PURE__ */ S(E, { children: "Parser" }),
|
|
957
954
|
/* @__PURE__ */ S(te, {
|
|
958
|
-
consoleId:
|
|
955
|
+
consoleId: V?.dashboardId || "",
|
|
959
956
|
value: p.parserId || null,
|
|
960
|
-
onChange:
|
|
957
|
+
onChange: Je,
|
|
961
958
|
filterInputSinkKey: G || void 0,
|
|
962
959
|
filterStatus: void 0,
|
|
963
960
|
placeholder: G ? "Select a parser..." : "Select a DataSink first...",
|
|
@@ -965,7 +962,7 @@ var Ee = p(function({ widget: e, onSave: t }) {
|
|
|
965
962
|
}),
|
|
966
963
|
/* @__PURE__ */ S("p", {
|
|
967
964
|
className: "text-xs text-muted-foreground",
|
|
968
|
-
children:
|
|
965
|
+
children: Me ? /* @__PURE__ */ C("span", {
|
|
969
966
|
className: "flex items-center gap-1",
|
|
970
967
|
children: [/* @__PURE__ */ S(M, { style: {
|
|
971
968
|
width: "12px",
|
|
@@ -1316,7 +1313,7 @@ var Ee = p(function({ widget: e, onSave: t }) {
|
|
|
1316
1313
|
children: "Configure buttons on this widget"
|
|
1317
1314
|
})] }), /* @__PURE__ */ C(w, {
|
|
1318
1315
|
size: "sm",
|
|
1319
|
-
onClick:
|
|
1316
|
+
onClick: Ve,
|
|
1320
1317
|
children: [/* @__PURE__ */ S(le, { className: "size-4" }), "Add"]
|
|
1321
1318
|
})]
|
|
1322
1319
|
}), J ? /* @__PURE__ */ S("div", {
|
|
@@ -1340,14 +1337,14 @@ var Ee = p(function({ widget: e, onSave: t }) {
|
|
|
1340
1337
|
children: [/* @__PURE__ */ S(w, {
|
|
1341
1338
|
variant: "ghost",
|
|
1342
1339
|
size: "icon-sm",
|
|
1343
|
-
onClick: () =>
|
|
1340
|
+
onClick: () => Ge(t),
|
|
1344
1341
|
disabled: t === 0,
|
|
1345
1342
|
className: "h-5 w-5",
|
|
1346
1343
|
children: /* @__PURE__ */ S(se, { className: "size-3" })
|
|
1347
1344
|
}), /* @__PURE__ */ S(w, {
|
|
1348
1345
|
variant: "ghost",
|
|
1349
1346
|
size: "icon-sm",
|
|
1350
|
-
onClick: () =>
|
|
1347
|
+
onClick: () => Ke(t),
|
|
1351
1348
|
disabled: t === q.length - 1,
|
|
1352
1349
|
className: "h-5 w-5",
|
|
1353
1350
|
children: /* @__PURE__ */ S(oe, { className: "size-3" })
|
|
@@ -1375,12 +1372,12 @@ var Ee = p(function({ widget: e, onSave: t }) {
|
|
|
1375
1372
|
children: [/* @__PURE__ */ S(w, {
|
|
1376
1373
|
variant: "ghost",
|
|
1377
1374
|
size: "icon-sm",
|
|
1378
|
-
onClick: () =>
|
|
1375
|
+
onClick: () => He(e),
|
|
1379
1376
|
children: /* @__PURE__ */ S(ce, { className: "size-4" })
|
|
1380
1377
|
}), /* @__PURE__ */ S(w, {
|
|
1381
1378
|
variant: "ghost",
|
|
1382
1379
|
size: "icon-sm",
|
|
1383
|
-
onClick: () =>
|
|
1380
|
+
onClick: () => We(e.id),
|
|
1384
1381
|
children: /* @__PURE__ */ S(ue, { className: "size-4" })
|
|
1385
1382
|
})]
|
|
1386
1383
|
})
|
|
@@ -1393,33 +1390,33 @@ var Ee = p(function({ widget: e, onSave: t }) {
|
|
|
1393
1390
|
value: "drilldown",
|
|
1394
1391
|
className: "mt-0",
|
|
1395
1392
|
children: /* @__PURE__ */ S(ae, {
|
|
1396
|
-
widget:
|
|
1397
|
-
onChange:
|
|
1393
|
+
widget: V,
|
|
1394
|
+
onChange: Qe
|
|
1398
1395
|
})
|
|
1399
1396
|
}),
|
|
1400
1397
|
/* @__PURE__ */ S(N, {
|
|
1401
1398
|
value: "webhooks",
|
|
1402
1399
|
className: "mt-0",
|
|
1403
1400
|
children: /* @__PURE__ */ S(re, {
|
|
1404
|
-
dashboardId:
|
|
1405
|
-
widgetId:
|
|
1401
|
+
dashboardId: V.dashboardId,
|
|
1402
|
+
widgetId: V.id
|
|
1406
1403
|
})
|
|
1407
1404
|
}),
|
|
1408
1405
|
/* @__PURE__ */ S(N, {
|
|
1409
1406
|
value: "events",
|
|
1410
1407
|
className: "mt-0",
|
|
1411
1408
|
children: /* @__PURE__ */ S(ie, {
|
|
1412
|
-
dashboardId:
|
|
1413
|
-
widgetId:
|
|
1409
|
+
dashboardId: V.dashboardId,
|
|
1410
|
+
widgetId: V.id,
|
|
1414
1411
|
maxHeight: "calc(100vh - 350px)"
|
|
1415
1412
|
})
|
|
1416
1413
|
}),
|
|
1417
1414
|
/* @__PURE__ */ S(N, {
|
|
1418
1415
|
value: "appearance",
|
|
1419
1416
|
className: "mt-0",
|
|
1420
|
-
children:
|
|
1421
|
-
config:
|
|
1422
|
-
onChange:
|
|
1417
|
+
children: et ? /* @__PURE__ */ S(et, {
|
|
1418
|
+
config: V.config || {},
|
|
1419
|
+
onChange: Ze
|
|
1423
1420
|
}) : /* @__PURE__ */ S("div", {
|
|
1424
1421
|
className: "p-4 bg-muted rounded-lg text-center",
|
|
1425
1422
|
children: /* @__PURE__ */ S("p", {
|
|
@@ -1440,7 +1437,7 @@ var Ee = p(function({ widget: e, onSave: t }) {
|
|
|
1440
1437
|
})]
|
|
1441
1438
|
})
|
|
1442
1439
|
}),
|
|
1443
|
-
|
|
1440
|
+
V && /* @__PURE__ */ C("div", {
|
|
1444
1441
|
style: {
|
|
1445
1442
|
padding: "var(--space-cardPadding)",
|
|
1446
1443
|
borderTop: "1px solid var(--color-border)",
|
|
@@ -1448,7 +1445,7 @@ var Ee = p(function({ widget: e, onSave: t }) {
|
|
|
1448
1445
|
flexShrink: 0
|
|
1449
1446
|
},
|
|
1450
1447
|
children: [
|
|
1451
|
-
|
|
1448
|
+
L && /* @__PURE__ */ C("div", {
|
|
1452
1449
|
style: {
|
|
1453
1450
|
display: "flex",
|
|
1454
1451
|
alignItems: "center",
|
|
@@ -1474,7 +1471,7 @@ var Ee = p(function({ widget: e, onSave: t }) {
|
|
|
1474
1471
|
children: "You have unsaved changes"
|
|
1475
1472
|
})]
|
|
1476
1473
|
}),
|
|
1477
|
-
d === "saved" && !
|
|
1474
|
+
d === "saved" && !L && /* @__PURE__ */ C("div", {
|
|
1478
1475
|
style: {
|
|
1479
1476
|
display: "flex",
|
|
1480
1477
|
alignItems: "center",
|
|
@@ -1530,13 +1527,13 @@ var Ee = p(function({ widget: e, onSave: t }) {
|
|
|
1530
1527
|
gap: "var(--space-controlGap)"
|
|
1531
1528
|
},
|
|
1532
1529
|
children: [/* @__PURE__ */ S(w, {
|
|
1533
|
-
onClick:
|
|
1534
|
-
disabled: d === "saving" || !
|
|
1530
|
+
onClick: Ye,
|
|
1531
|
+
disabled: d === "saving" || !L,
|
|
1535
1532
|
style: {
|
|
1536
1533
|
flex: 1,
|
|
1537
1534
|
height: "var(--size-controlHeight-md)",
|
|
1538
|
-
backgroundColor:
|
|
1539
|
-
opacity:
|
|
1535
|
+
backgroundColor: L ? "var(--color-action-primary-bg)" : void 0,
|
|
1536
|
+
opacity: L ? 1 : .5
|
|
1540
1537
|
},
|
|
1541
1538
|
children: d === "saving" ? /* @__PURE__ */ C("span", {
|
|
1542
1539
|
style: {
|
|
@@ -1561,11 +1558,11 @@ var Ee = p(function({ widget: e, onSave: t }) {
|
|
|
1561
1558
|
})
|
|
1562
1559
|
}), /* @__PURE__ */ C(w, {
|
|
1563
1560
|
variant: "outline",
|
|
1564
|
-
onClick:
|
|
1565
|
-
disabled: d === "saving" || !
|
|
1561
|
+
onClick: Xe,
|
|
1562
|
+
disabled: d === "saving" || !L,
|
|
1566
1563
|
style: {
|
|
1567
1564
|
height: "var(--size-controlHeight-md)",
|
|
1568
|
-
opacity:
|
|
1565
|
+
opacity: L ? 1 : .5
|
|
1569
1566
|
},
|
|
1570
1567
|
children: [/* @__PURE__ */ S(x, { style: {
|
|
1571
1568
|
width: "var(--size-icon-sm)",
|
|
@@ -1576,19 +1573,19 @@ var Ee = p(function({ widget: e, onSave: t }) {
|
|
|
1576
1573
|
]
|
|
1577
1574
|
}),
|
|
1578
1575
|
/* @__PURE__ */ S(ne, {
|
|
1579
|
-
isOpen:
|
|
1580
|
-
action:
|
|
1581
|
-
isLoading:
|
|
1576
|
+
isOpen: Le,
|
|
1577
|
+
action: Re,
|
|
1578
|
+
isLoading: ze,
|
|
1582
1579
|
onClose: () => {
|
|
1583
1580
|
X(!1), Z(void 0);
|
|
1584
1581
|
},
|
|
1585
|
-
onSave:
|
|
1582
|
+
onSave: Ue
|
|
1586
1583
|
})
|
|
1587
1584
|
]
|
|
1588
1585
|
})
|
|
1589
1586
|
});
|
|
1590
1587
|
});
|
|
1591
1588
|
//#endregion
|
|
1592
|
-
export {
|
|
1589
|
+
export { L as default };
|
|
1593
1590
|
|
|
1594
1591
|
//# sourceMappingURL=PropertiesPanel.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PropertiesPanel.js","names":[],"sources":["../../../../src/bigconsole/components/widgets/PropertiesPanel.tsx"],"sourcesContent":["/**\n * PropertiesPanel Component\n *\n * Right-side panel for widget configuration.\n * v2.0: Added Actions tab for managing widget actions.\n * Uses fe-libs shared components for consistent styling.\n */\n\nimport React, { type FC, memo, useCallback, useState, useEffect, useRef } from 'react';\nimport { Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription } from '@burdenoff/fe-libs/ui';\nimport { Tabs, TabsList, TabsTrigger, TabsContent } from '@burdenoff/fe-libs/ui';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { Input } from '@burdenoff/fe-libs/ui';\nimport { Textarea } from '@burdenoff/fe-libs/ui';\nimport { Label } from '@burdenoff/fe-libs/ui';\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@burdenoff/fe-libs/ui';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { Card, CardContent } from '@burdenoff/fe-libs/ui';\nimport { Plus, ChevronUp, ChevronDown, Pencil, Trash2, ExternalLink, Check, X, Info } from 'lucide-react';\nimport type { Widget, WidgetType, DataSourceType, RendererType } from '../../types';\nimport { useWidgetStore } from '../../store';\nimport { useWidgetOperations, useDrilldownOperations } from '../../hooks';\nimport {\n useWidgetActions,\n type WidgetAction,\n type CreateWidgetActionInput,\n type UpdateWidgetActionInput,\n} from '../../hooks/useWidgetActions';\nimport { getWidgetDefinition } from './WidgetRegistry';\nimport { ActionConfigDialog } from './ActionConfigDialog';\nimport { WebhookConfigPanel } from './webhook-config';\nimport { EventLogViewer } from './event-logs';\nimport { DrilldownConfigPanel, type DrilldownConfig } from './DrilldownConfigPanel';\n// Data Source selectors\nimport { DataSinkSelector } from '../parser/DataSinkSelector';\nimport { ParserSelector } from '../parser/ParserSelector';\nimport { useDataSinkOperations } from '../../hooks/useDataSinkOperations';\nimport { useParserOperations } from '../../hooks/useParserOperations';\n\n// Config components\nimport { MetricCardConfig } from './metric-card/MetricCardConfig';\nimport { ChartConfig } from './chart/ChartConfig';\nimport { TableConfig } from './table/TableConfig';\nimport { GaugeConfig } from './gauge/GaugeConfig';\nimport { ProgressConfig } from './progress/ProgressConfig';\nimport { ListConfig } from './list/ListConfig';\n\n// ============================================================================\n// v2.0: Renderer Options\n// ============================================================================\n\nconst RENDERER_OPTIONS: { value: RendererType; label: string; description: string }[] = [\n { value: 'BIGCONSOLE', label: 'BigConsole Native', description: 'Full-featured native widgets' },\n { value: 'ADAPTIVE_CARD', label: 'Adaptive Cards', description: 'Microsoft Teams/Outlook format' },\n { value: 'BLOCKKIT', label: 'Block Kit', description: 'Slack format' },\n { value: 'CUSTOM', label: 'Custom', description: 'Custom React component' },\n];\n\n// ============================================================================\n// Data Source Constants\n// ============================================================================\n\nconst DATA_SOURCE_TYPES: { value: DataSourceType; label: string; description: string }[] = [\n { value: 'DATASINK', label: 'DataSink', description: 'Use data from BigConsole DataSinks' },\n { value: 'REST_API', label: 'REST API', description: 'Fetch data from REST endpoints' },\n { value: 'GRAPHQL', label: 'GraphQL', description: 'Query data using GraphQL' },\n { value: 'SQL', label: 'SQL Database', description: 'Query SQL databases directly' },\n { value: 'WEBSOCKET', label: 'WebSocket', description: 'Real-time data streaming' },\n { value: 'MOCK', label: 'Sample JSON', description: 'Manually enter sample JSON data' },\n];\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface PropertiesPanelProps {\n isOpen: boolean;\n onClose: () => void;\n}\n\ntype TabId = 'general' | 'data' | 'actions' | 'drilldown' | 'webhooks' | 'events' | 'appearance';\n\n// Action style colors\nconst ACTION_STYLE_COLORS: Record<string, string> = {\n PRIMARY: 'bg-action-primary',\n SECONDARY: 'bg-muted-foreground',\n SUCCESS: 'bg-state-success',\n WARNING: 'bg-state-warning',\n DANGER: 'bg-state-error',\n};\n\n// ============================================================================\n// Config Component Map\n// ============================================================================\n\n/**\n * Detects field names from parser output and returns suggested labelField and valueField\n * @param output - The parser execution output\n * @returns Object with suggested labelField and valueField\n */\nfunction detectFieldsFromParserOutput(output: unknown): {\n labelField?: string;\n valueField?: string;\n xAxisField?: string;\n} {\n if (!output) return {};\n\n // If output is an array, look at the first item\n const sampleItem = Array.isArray(output) ? output[0] : output;\n\n if (!sampleItem || typeof sampleItem !== 'object') return {};\n\n const keys = Object.keys(sampleItem as Record<string, unknown>);\n\n // Common label field names (in order of priority)\n const labelFieldCandidates = [\n 'name',\n 'label',\n 'category',\n 'title',\n 'key',\n 'id',\n 'month',\n 'date',\n 'region',\n 'product',\n ];\n // Common value field names (in order of priority)\n const valueFieldCandidates = ['value', 'amount', 'count', 'total', 'revenue', 'sales', 'quantity', 'orders', 'sum'];\n\n let labelField: string | undefined;\n let valueField: string | undefined;\n\n // Find the best label field\n for (const candidate of labelFieldCandidates) {\n if (keys.includes(candidate)) {\n labelField = candidate;\n break;\n }\n }\n\n // Find the best value field\n for (const candidate of valueFieldCandidates) {\n if (keys.includes(candidate)) {\n valueField = candidate;\n break;\n }\n }\n\n // If no standard names found, use heuristics:\n // - First string field as label\n // - First number field as value\n if (!labelField || !valueField) {\n for (const key of keys) {\n const val = (sampleItem as Record<string, unknown>)[key];\n if (!labelField && typeof val === 'string') {\n labelField = key;\n }\n if (!valueField && typeof val === 'number') {\n valueField = key;\n }\n if (labelField && valueField) break;\n }\n }\n\n return {\n labelField,\n valueField,\n xAxisField: labelField, // For line/bar charts, xAxisField is usually the same as labelField\n };\n}\n\nfunction getConfigComponent(type: WidgetType) {\n switch (type) {\n case 'metric_card':\n case 'kpi_card_comparison':\n return MetricCardConfig;\n case 'chart':\n case 'funnel_chart':\n return ChartConfig;\n case 'table':\n case 'pivot_table':\n return TableConfig;\n case 'gauge':\n return GaugeConfig;\n case 'progress':\n return ProgressConfig;\n case 'list':\n return ListConfig;\n default:\n return null;\n }\n}\n\n// ============================================================================\n// Template Editor Component\n// ============================================================================\n\ninterface TemplateEditorProps {\n widget: Widget;\n onSave: (template: Record<string, unknown>) => void;\n}\n\nconst TemplateEditor: FC<TemplateEditorProps> = memo(function TemplateEditor({ widget, onSave }) {\n const [localValue, setLocalValue] = useState<string>('');\n const [jsonError, setJsonError] = useState<string | null>(null);\n const initializedRef = useRef(false);\n\n // Initialize from widget.template only once per widget\n useEffect(() => {\n try {\n const templateStr =\n widget.template && typeof widget.template === 'object' ? JSON.stringify(widget.template, null, 2) : '';\n setLocalValue(templateStr);\n setJsonError(null);\n initializedRef.current = true;\n } catch {\n setLocalValue('');\n }\n }, [widget.id, widget.template]);\n\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n const value = e.target.value;\n setLocalValue(value);\n\n if (value.trim() === '') {\n setJsonError(null);\n // Empty template is valid - notify parent\n onSave({});\n } else {\n try {\n const parsed = JSON.parse(value);\n setJsonError(null);\n // Valid JSON - immediately notify parent so main Save button becomes active\n onSave(parsed);\n } catch (err) {\n setJsonError((err as Error).message);\n // Don't call onSave for invalid JSON\n }\n }\n },\n [onSave]\n );\n\n const handleFormat = useCallback(() => {\n try {\n const parsed = JSON.parse(localValue);\n const formatted = JSON.stringify(parsed, null, 2);\n setLocalValue(formatted);\n setJsonError(null);\n onSave(parsed);\n } catch (err) {\n setJsonError((err as Error).message);\n }\n }, [localValue, onSave]);\n\n return (\n <div\n style={{\n paddingTop: 'var(--space-formGap)',\n borderTop: '1px solid var(--color-border)',\n }}\n >\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n <label\n style={{\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)',\n color: 'var(--color-text-primary)',\n }}\n >\n Template (JSON)\n </label>\n {jsonError && (\n <span\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-status-error-text)',\n fontWeight: 'var(--font-weight-medium)',\n }}\n >\n Invalid JSON\n </span>\n )}\n </div>\n\n <Textarea\n value={localValue}\n onChange={handleChange}\n spellCheck={false}\n placeholder={`Enter ${widget.renderer} template JSON...`}\n style={{\n fontFamily: 'var(--font-family-mono)',\n fontSize: 'var(--font-size-body-sm)',\n minHeight: '180px',\n borderColor: jsonError ? 'var(--color-status-error-border)' : undefined,\n resize: 'vertical',\n }}\n />\n\n {jsonError && (\n <p\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-status-error-text)',\n backgroundColor: 'var(--color-status-error-bgSubtle)',\n padding: 'var(--space-controlGap)',\n borderRadius: 'var(--radius-button)',\n marginTop: 'var(--space-controlGap)',\n }}\n >\n {jsonError}\n </p>\n )}\n\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-controlGap)',\n marginTop: 'var(--space-controlGap)',\n }}\n >\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={handleFormat}\n disabled={!!jsonError || localValue.trim() === ''}\n style={{ height: 'var(--size-controlHeight-sm)', fontWeight: 'var(--font-weight-semibold)' }}\n >\n Format\n </Button>\n {!jsonError && localValue.trim() !== '' && (\n <span\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-status-success-text)',\n display: 'flex',\n alignItems: 'center',\n gap: '4px',\n }}\n >\n <Check style={{ width: '12px', height: '12px' }} />\n Valid JSON\n </span>\n )}\n </div>\n\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-muted)',\n marginTop: 'var(--space-controlGap)',\n paddingTop: 'var(--space-controlGap)',\n borderTop: '1px solid var(--color-border)',\n }}\n >\n <span style={{ fontWeight: 'var(--font-weight-medium)' }}>Ctrl+S to save</span>\n {widget.renderer === 'ADAPTIVE_CARD' && (\n <a\n href=\"https://adaptivecards.io/designer/\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-controlGap)',\n color: 'var(--color-text-link)',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-medium)',\n textDecoration: 'none',\n }}\n >\n Designer\n <ExternalLink style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />\n </a>\n )}\n {widget.renderer === 'BLOCKKIT' && (\n <a\n href=\"https://app.slack.com/block-kit-builder\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-controlGap)',\n color: 'var(--color-text-link)',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-medium)',\n textDecoration: 'none',\n }}\n >\n Block Kit Builder\n <ExternalLink style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />\n </a>\n )}\n </div>\n </div>\n );\n});\n\n// ============================================================================\n// Local Form State Type\n// ============================================================================\n\ninterface LocalFormState {\n title: string;\n description: string;\n refreshInterval: number | undefined;\n renderer: RendererType;\n template: Record<string, unknown> | undefined;\n // v2.0: Data source fields (DataSink → Parser → Widget)\n dataSinkId: string | undefined;\n datasetId: string | undefined;\n parserId: string | undefined;\n parserRules: string | undefined;\n config: Record<string, unknown>;\n // Drilldown configuration\n drilldownConfig: DrilldownConfig | undefined;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const PropertiesPanel: FC<PropertiesPanelProps> = memo(function PropertiesPanel({ isOpen, onClose }) {\n const [activeTab, setActiveTab] = useState<TabId>('general');\n const [saveStatus, setSaveStatus] = useState<'idle' | 'saving' | 'saved' | 'error'>('idle');\n const [localForm, setLocalForm] = useState<LocalFormState | null>(null);\n const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);\n\n const selectedWidgetId = useWidgetStore((state) => state.selectedWidgetId);\n const widgets = useWidgetStore((state) => state.widgets);\n const updateWidgetInStore = useWidgetStore((state) => state.updateWidget);\n\n const selectedWidget = selectedWidgetId ? widgets.get(selectedWidgetId) : undefined;\n\n useEffect(() => {\n if (selectedWidget) {\n setLocalForm({\n title: selectedWidget.title || '',\n description: selectedWidget.description || '',\n refreshInterval: selectedWidget.refreshInterval ?? undefined,\n renderer: (selectedWidget.renderer as RendererType) || 'BIGCONSOLE',\n template: selectedWidget.template as Record<string, unknown> | undefined,\n // v2.0: Data source fields (DataSink → Parser → Widget)\n dataSinkId: (selectedWidget as unknown as Record<string, string | undefined>).dataSinkId ?? undefined,\n datasetId: (selectedWidget as unknown as Record<string, string | undefined>).datasetId ?? undefined,\n parserId: (selectedWidget as unknown as Record<string, string | undefined>).parserId ?? undefined,\n parserRules: (selectedWidget as unknown as Record<string, string | undefined>).parserRules ?? undefined,\n config: (selectedWidget.config as Record<string, unknown>) || {},\n // Drilldown configuration\n drilldownConfig: selectedWidget.drilldown\n ? {\n enabled: selectedWidget.drilldown.enabled ?? false,\n targetDashboardId: selectedWidget.drilldown.targetDashboardId ?? '',\n navigationMode: selectedWidget.drilldown.navigationMode ?? 'MODAL',\n parameterMapping: (selectedWidget.drilldown.parameterMapping as Record<string, string>) ?? {},\n passGlobalFilters: selectedWidget.drilldown.passGlobalFilters ?? true,\n maxDepth: selectedWidget.drilldown.maxDepth ?? 3,\n openIn: selectedWidget.drilldown.openIn ?? 'same',\n }\n : undefined,\n });\n setHasUnsavedChanges(false);\n setSaveStatus('idle');\n } else {\n setLocalForm(null);\n }\n }, [selectedWidget]);\n\n const { updateWidget: updateWidgetApi } = useWidgetOperations(selectedWidget?.pageId, selectedWidget?.dashboardId, {\n skipFetch: true,\n });\n\n // Drilldown operations\n const { createDrilldown, updateDrilldown, deleteDrilldown } = useDrilldownOperations();\n\n // DataSink operations - for looking up DataSink by key\n const { dataSinks } = useDataSinkOperations({ skipFetch: false });\n\n // Track selected DataSink key for filtering parsers\n const [selectedDataSinkKey, setSelectedDataSinkKey] = useState<string | null>(null);\n\n // Parser operations - for executing parser to detect fields\n const { executeParser } = useParserOperations({\n consoleId: selectedWidget?.dashboardId,\n skipFetch: true,\n });\n\n // Track if we're auto-detecting fields\n const [isDetectingFields, setIsDetectingFields] = useState(false);\n\n const {\n actions,\n loading: actionsLoading,\n createAction,\n updateAction,\n deleteAction,\n reorderActions,\n } = useWidgetActions(selectedWidgetId || undefined);\n\n const [isActionDialogOpen, setIsActionDialogOpen] = useState(false);\n const [editingAction, setEditingAction] = useState<WidgetAction | undefined>(undefined);\n const [actionSaving, setActionSaving] = useState(false);\n\n const handleAddAction = useCallback(() => {\n setEditingAction(undefined);\n setIsActionDialogOpen(true);\n }, []);\n\n const handleEditAction = useCallback((action: WidgetAction) => {\n setEditingAction(action);\n setIsActionDialogOpen(true);\n }, []);\n\n const handleSaveAction = useCallback(\n async (data: Omit<CreateWidgetActionInput, 'widgetId'> | UpdateWidgetActionInput) => {\n if (!selectedWidgetId) return;\n\n setActionSaving(true);\n try {\n let newAction: WidgetAction | null = null;\n if ('id' in data) {\n newAction = await updateAction(data);\n } else {\n newAction = await createAction(data);\n }\n\n // Immediately sync to widget store after successful save\n // This ensures the widget displays the action right away\n if (newAction) {\n const currentActions = [...actions];\n if ('id' in data) {\n // Update existing action\n const idx = currentActions.findIndex((a) => a.id === data.id);\n if (idx >= 0) {\n currentActions[idx] = newAction;\n }\n } else {\n // Add new action\n currentActions.push(newAction);\n }\n // Sort by order and update store\n const sortedActions = currentActions.sort((a, b) => a.order - b.order);\n updateWidgetInStore(selectedWidgetId, { actions: sortedActions });\n }\n\n setIsActionDialogOpen(false);\n setEditingAction(undefined);\n } catch (err) {\n } finally {\n setActionSaving(false);\n }\n },\n [selectedWidgetId, actions, createAction, updateAction, updateWidgetInStore]\n );\n\n const handleDeleteAction = useCallback(\n async (actionId: string) => {\n if (!selectedWidgetId) return;\n\n if (window.confirm('Are you sure you want to delete this action?')) {\n const success = await deleteAction(actionId);\n if (success) {\n // Immediately sync to widget store after deletion\n const updatedActions = actions.filter((a) => a.id !== actionId);\n updateWidgetInStore(selectedWidgetId, { actions: updatedActions });\n }\n }\n },\n [selectedWidgetId, actions, deleteAction, updateWidgetInStore]\n );\n\n const handleMoveActionUp = useCallback(\n async (index: number) => {\n if (!selectedWidgetId || index === 0) return;\n const sortedActions = [...actions].sort((a, b) => a.order - b.order);\n const newOrder = sortedActions.map((a) => a.id);\n [newOrder[index - 1], newOrder[index]] = [newOrder[index], newOrder[index - 1]];\n const success = await reorderActions(newOrder);\n if (success) {\n // Immediately update local order for UI responsiveness\n const reordered = sortedActions\n .map((a, _i) => ({\n ...a,\n order: newOrder.indexOf(a.id),\n }))\n .sort((a, b) => a.order - b.order);\n updateWidgetInStore(selectedWidgetId, { actions: reordered });\n }\n },\n [selectedWidgetId, actions, reorderActions, updateWidgetInStore]\n );\n\n const handleMoveActionDown = useCallback(\n async (index: number) => {\n if (!selectedWidgetId) return;\n const sortedActions = [...actions].sort((a, b) => a.order - b.order);\n if (index === sortedActions.length - 1) return;\n const newOrder = sortedActions.map((a) => a.id);\n [newOrder[index], newOrder[index + 1]] = [newOrder[index + 1], newOrder[index]];\n const success = await reorderActions(newOrder);\n if (success) {\n // Immediately update local order for UI responsiveness\n const reordered = sortedActions\n .map((a, _i) => ({\n ...a,\n order: newOrder.indexOf(a.id),\n }))\n .sort((a, b) => a.order - b.order);\n updateWidgetInStore(selectedWidgetId, { actions: reordered });\n }\n },\n [selectedWidgetId, actions, reorderActions, updateWidgetInStore]\n );\n\n useEffect(() => {\n if (selectedWidgetId && actions.length >= 0 && !actionsLoading) {\n updateWidgetInStore(selectedWidgetId, { actions });\n }\n }, [selectedWidgetId, actions, actionsLoading, updateWidgetInStore]);\n\n const updateLocalForm = useCallback(<K extends keyof LocalFormState>(key: K, value: LocalFormState[K]) => {\n setLocalForm((prev) => (prev ? { ...prev, [key]: value } : prev));\n setHasUnsavedChanges(true);\n }, []);\n\n const updateLocalConfig = useCallback((newConfig: Record<string, unknown>) => {\n setLocalForm((prev) => (prev ? { ...prev, config: newConfig } : prev));\n setHasUnsavedChanges(true);\n }, []);\n\n // Initialize selectedDataSinkKey from widget's dataSinkId\n useEffect(() => {\n if (localForm?.dataSinkId && dataSinks.length > 0) {\n const ds = dataSinks.find((d) => d.id === localForm.dataSinkId);\n if (ds) {\n setSelectedDataSinkKey(ds.key);\n }\n } else {\n setSelectedDataSinkKey(null);\n }\n }, [localForm?.dataSinkId, dataSinks]);\n\n // Handle DataSink selection - looks up ID from key and updates form\n const handleDataSinkChange = useCallback(\n (key: string | null) => {\n setSelectedDataSinkKey(key);\n if (key) {\n const ds = dataSinks.find((d) => d.key === key);\n if (ds) {\n updateLocalForm('dataSinkId', ds.id);\n // Also update config.dataSinkKey for backward compatibility\n setLocalForm((prev) =>\n prev\n ? {\n ...prev,\n config: { ...prev.config, dataSinkKey: key },\n }\n : prev\n );\n setHasUnsavedChanges(true);\n }\n } else {\n updateLocalForm('dataSinkId', undefined);\n setLocalForm((prev) =>\n prev\n ? {\n ...prev,\n config: { ...prev.config, dataSinkKey: undefined },\n parserId: undefined, // Clear parser when DataSink is cleared\n }\n : prev\n );\n setHasUnsavedChanges(true);\n }\n },\n [dataSinks, updateLocalForm]\n );\n\n // Handle Parser selection - with auto-detection of field mappings\n const handleParserChange = useCallback(\n async (parserId: string | null) => {\n updateLocalForm('parserId', parserId || undefined);\n\n // If a parser is selected, execute it to detect field structure\n if (parserId && selectedWidget) {\n setIsDetectingFields(true);\n try {\n const result = await executeParser(parserId);\n\n if (result?.success && result.output) {\n const detectedFields = detectFieldsFromParserOutput(result.output);\n\n // Only auto-populate if fields were detected and not already set\n if (detectedFields.labelField || detectedFields.valueField) {\n setLocalForm((prev) => {\n if (!prev) return prev;\n\n const currentConfig = prev.config || {};\n const newConfig = { ...currentConfig };\n\n // Auto-populate labelField if not already set\n if (detectedFields.labelField && !currentConfig.labelField) {\n newConfig.labelField = detectedFields.labelField;\n }\n\n // Auto-populate valueField if not already set\n if (detectedFields.valueField && !currentConfig.valueField) {\n newConfig.valueField = detectedFields.valueField;\n }\n\n // Auto-populate xAxisField for line/bar/area charts if not already set\n if (detectedFields.xAxisField && !currentConfig.xAxisField) {\n newConfig.xAxisField = detectedFields.xAxisField;\n }\n\n return { ...prev, config: newConfig };\n });\n setHasUnsavedChanges(true);\n }\n }\n } catch (err) {\n // Silent fail - user can still manually configure fields\n console.warn('Failed to auto-detect parser fields:', err);\n } finally {\n setIsDetectingFields(false);\n }\n }\n },\n [updateLocalForm, executeParser, selectedWidget]\n );\n\n const handleSaveAll = useCallback(async () => {\n if (!selectedWidget || !localForm) return;\n\n setSaveStatus('saving');\n\n try {\n const metadata = { ...(selectedWidget.metadata || {}), description: localForm.description || '' };\n\n const result = await updateWidgetApi({\n id: selectedWidget.id,\n title: localForm.title,\n renderer: localForm.renderer,\n template: localForm.template,\n config: localForm.config,\n refreshInterval: localForm.refreshInterval,\n // v2.0: Data source fields (DataSink → Parser → Widget)\n dataSinkId: localForm.dataSinkId,\n datasetId: localForm.datasetId,\n parserId: localForm.parserId,\n parserRules: localForm.parserRules,\n metadata,\n });\n\n // Save drilldown configuration to backend\n let savedDrilldown = selectedWidget.drilldown;\n if (localForm.drilldownConfig) {\n const { enabled, targetDashboardId, navigationMode, parameterMapping, passGlobalFilters, maxDepth, openIn } =\n localForm.drilldownConfig;\n\n if (selectedWidget.drilldown?.id) {\n // Update existing drilldown\n const drilldownResult = await updateDrilldown({\n id: selectedWidget.drilldown.id,\n targetDashboardId,\n parameterMapping,\n navigationMode,\n enabled,\n passGlobalFilters,\n maxDepth,\n openIn,\n });\n if (drilldownResult) {\n savedDrilldown = drilldownResult;\n }\n } else if (targetDashboardId) {\n // Create new drilldown (only if targetDashboardId is set)\n const drilldownResult = await createDrilldown({\n sourceWidgetId: selectedWidget.id,\n targetDashboardId,\n parameterMapping: parameterMapping || {},\n navigationMode,\n passGlobalFilters,\n maxDepth,\n openIn,\n });\n if (drilldownResult) {\n savedDrilldown = { ...drilldownResult, enabled };\n }\n }\n } else if (selectedWidget.drilldown?.id && !localForm.drilldownConfig) {\n // Delete drilldown if it existed but was removed\n await deleteDrilldown(selectedWidget.drilldown.id);\n savedDrilldown = undefined;\n }\n\n if (result) {\n updateWidgetInStore(selectedWidget.id, {\n title: localForm.title,\n description: localForm.description,\n renderer: localForm.renderer,\n template: localForm.template,\n config: localForm.config,\n refreshInterval: localForm.refreshInterval,\n // v2.0: Data source fields\n dataSinkId: localForm.dataSinkId,\n datasetId: localForm.datasetId,\n parserId: localForm.parserId,\n parserRules: localForm.parserRules,\n // Drilldown configuration from backend\n drilldown: savedDrilldown,\n // Update timestamp to trigger WidgetWrapper re-render (fixes drilldown mode change bug)\n updatedAt: new Date().toISOString(),\n } as Partial<Widget>);\n\n setSaveStatus('saved');\n setHasUnsavedChanges(false);\n setTimeout(() => setSaveStatus('idle'), 2000);\n } else {\n setSaveStatus('error');\n }\n } catch (err) {\n setSaveStatus('error');\n }\n }, [\n selectedWidget,\n localForm,\n updateWidgetApi,\n updateWidgetInStore,\n createDrilldown,\n updateDrilldown,\n deleteDrilldown,\n ]);\n\n const handleDiscardAll = useCallback(() => {\n if (!selectedWidget) return;\n\n setLocalForm({\n title: selectedWidget.title || '',\n description: selectedWidget.description || '',\n refreshInterval: selectedWidget.refreshInterval ?? undefined,\n renderer: (selectedWidget.renderer as RendererType) || 'BIGCONSOLE',\n template: selectedWidget.template as Record<string, unknown> | undefined,\n // v2.0: Data source fields (DataSink → Parser → Widget)\n dataSinkId: (selectedWidget as unknown as Record<string, string | undefined>).dataSinkId ?? undefined,\n datasetId: (selectedWidget as unknown as Record<string, string | undefined>).datasetId ?? undefined,\n parserId: (selectedWidget as unknown as Record<string, string | undefined>).parserId ?? undefined,\n parserRules: (selectedWidget as unknown as Record<string, string | undefined>).parserRules ?? undefined,\n config: (selectedWidget.config as Record<string, unknown>) || {},\n // Drilldown configuration\n drilldownConfig: selectedWidget.drilldown\n ? {\n enabled: selectedWidget.drilldown.enabled ?? false,\n targetDashboardId: selectedWidget.drilldown.targetDashboardId ?? '',\n navigationMode: selectedWidget.drilldown.navigationMode ?? 'MODAL',\n parameterMapping: (selectedWidget.drilldown.parameterMapping as Record<string, string>) ?? {},\n passGlobalFilters: selectedWidget.drilldown.passGlobalFilters ?? true,\n maxDepth: selectedWidget.drilldown.maxDepth ?? 3,\n openIn: selectedWidget.drilldown.openIn ?? 'same',\n }\n : undefined,\n });\n setHasUnsavedChanges(false);\n setSaveStatus('idle');\n }, [selectedWidget]);\n\n const handleConfigChange = useCallback(\n (newConfig: Record<string, unknown>) => {\n updateLocalConfig(newConfig);\n },\n [updateLocalConfig]\n );\n\n const handleDrilldownChange = useCallback((config: DrilldownConfig) => {\n setLocalForm((prev) => (prev ? { ...prev, drilldownConfig: config } : prev));\n setHasUnsavedChanges(true);\n }, []);\n\n const definition = selectedWidget ? getWidgetDefinition(selectedWidget.type) : null;\n const ConfigComponent = selectedWidget ? getConfigComponent(selectedWidget.type) : null;\n\n return (\n <Sheet open={isOpen} onOpenChange={(open) => !open && onClose()} modal={false}>\n <SheetContent\n style={{\n width: '420px',\n maxWidth: '90vw',\n padding: 0,\n display: 'flex',\n flexDirection: 'column',\n height: '100%',\n overflow: 'hidden',\n }}\n >\n <SheetHeader\n style={{\n padding: 'var(--space-cardPadding)',\n borderBottom: '1px solid var(--color-border)',\n backgroundColor: 'var(--color-bg-surface)',\n flexShrink: 0,\n }}\n >\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-controlGap)' }}>\n <div\n style={{\n display: 'flex',\n height: 'var(--size-controlHeight-lg)',\n width: 'var(--size-controlHeight-lg)',\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: 'var(--radius-card)',\n backgroundColor: 'var(--color-action-primary-bg)',\n boxShadow: 'var(--shadow-elevation-2)',\n flexShrink: 0,\n }}\n >\n <Info\n style={{\n height: 'var(--size-icon-md)',\n width: 'var(--size-icon-md)',\n color: 'var(--color-action-primary-text)',\n }}\n />\n </div>\n <div style={{ flex: 1, minWidth: 0 }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-iconGap)' }}>\n <SheetTitle\n style={{\n fontSize: 'var(--font-size-body-md)',\n fontWeight: 'var(--font-weight-bold)',\n color: 'var(--color-text-primary)',\n margin: 0,\n }}\n >\n {selectedWidget ? 'Widget Properties' : 'Properties'}\n </SheetTitle>\n {saveStatus === 'saving' && (\n <Spinner style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />\n )}\n {saveStatus === 'saved' && (\n <Check\n style={{\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n color: 'var(--color-status-success-bg)',\n }}\n />\n )}\n {saveStatus === 'error' && (\n <X\n style={{\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n color: 'var(--color-status-error-bg)',\n }}\n />\n )}\n </div>\n {definition && (\n <SheetDescription\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-secondary)',\n margin: 'var(--space-controlGap) 0 0 0',\n fontWeight: 'var(--font-weight-medium)',\n }}\n >\n {definition.name}\n </SheetDescription>\n )}\n </div>\n </div>\n </SheetHeader>\n\n {selectedWidget ? (\n <Tabs\n value={activeTab}\n onValueChange={(v) => setActiveTab(v as TabId)}\n style={{ flex: 1, display: 'flex', flexDirection: 'column', minHeight: 0, overflow: 'hidden' }}\n >\n <TabsList\n style={{\n width: '100%',\n display: 'flex',\n justifyContent: 'flex-start',\n borderRadius: 0,\n borderBottom: '1px solid var(--color-border)',\n padding: '0 8px',\n backgroundColor: 'var(--color-bg-sunken)',\n height: 'var(--size-controlHeight-lg)',\n flexShrink: 0,\n gap: '2px',\n overflowX: 'auto',\n }}\n >\n <TabsTrigger\n value=\"general\"\n style={{\n fontWeight: 'var(--font-weight-semibold)',\n fontSize: '12px',\n padding: '6px 8px',\n flexShrink: 0,\n }}\n >\n General\n </TabsTrigger>\n <TabsTrigger\n value=\"data\"\n style={{\n fontWeight: 'var(--font-weight-semibold)',\n fontSize: '12px',\n padding: '6px 8px',\n flexShrink: 0,\n }}\n >\n Data\n </TabsTrigger>\n <TabsTrigger\n value=\"actions\"\n style={{\n fontWeight: 'var(--font-weight-semibold)',\n fontSize: '12px',\n padding: '6px 8px',\n flexShrink: 0,\n }}\n >\n Actions\n </TabsTrigger>\n <TabsTrigger\n value=\"drilldown\"\n style={{\n fontWeight: 'var(--font-weight-semibold)',\n fontSize: '12px',\n padding: '6px 8px',\n flexShrink: 0,\n }}\n >\n Drilldown\n </TabsTrigger>\n <TabsTrigger\n value=\"webhooks\"\n style={{\n fontWeight: 'var(--font-weight-semibold)',\n fontSize: '12px',\n padding: '6px 8px',\n flexShrink: 0,\n }}\n >\n Hooks\n </TabsTrigger>\n <TabsTrigger\n value=\"events\"\n style={{\n fontWeight: 'var(--font-weight-semibold)',\n fontSize: '12px',\n padding: '6px 8px',\n flexShrink: 0,\n }}\n >\n Events\n </TabsTrigger>\n <TabsTrigger\n value=\"appearance\"\n style={{\n fontWeight: 'var(--font-weight-semibold)',\n fontSize: '12px',\n padding: '6px 8px',\n flexShrink: 0,\n }}\n >\n Style\n </TabsTrigger>\n </TabsList>\n\n <div style={{ flex: 1, overflow: 'auto', padding: 'var(--space-cardPadding)', minHeight: 0 }}>\n <TabsContent value=\"general\" className=\"mt-0\">\n {localForm && (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-formGap)' }}>\n {/* Title Field */}\n <div>\n <label\n htmlFor=\"title\"\n style={{\n display: 'block',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)',\n color: 'var(--color-text-primary)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n Title\n </label>\n <Input\n id=\"title\"\n value={localForm.title}\n onChange={(e) => updateLocalForm('title', e.target.value)}\n style={{ height: 'var(--size-controlHeight-md)', fontSize: 'var(--font-size-body-sm)' }}\n />\n </div>\n\n {/* Description Field */}\n <div>\n <label\n htmlFor=\"description\"\n style={{\n display: 'block',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)',\n color: 'var(--color-text-primary)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n Description\n </label>\n <Textarea\n id=\"description\"\n value={localForm.description}\n onChange={(e) => updateLocalForm('description', e.target.value)}\n rows={3}\n style={{ fontSize: 'var(--font-size-body-sm)', resize: 'none' }}\n />\n </div>\n\n {/* Auto-Refresh Field */}\n <div>\n <label\n htmlFor=\"refresh\"\n style={{\n display: 'block',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)',\n color: 'var(--color-text-primary)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n Auto-Refresh (seconds)\n </label>\n <Input\n id=\"refresh\"\n type=\"number\"\n value={localForm.refreshInterval || ''}\n onChange={(e) =>\n updateLocalForm('refreshInterval', e.target.value ? Number(e.target.value) : undefined)\n }\n min={0}\n placeholder=\"No auto-refresh\"\n style={{ height: 'var(--size-controlHeight-md)', fontSize: 'var(--font-size-body-sm)' }}\n />\n </div>\n\n {/* Renderer Field */}\n <div\n style={{\n paddingTop: 'var(--space-formGap)',\n borderTop: '1px solid var(--color-border)',\n }}\n >\n <label\n style={{\n display: 'block',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)',\n color: 'var(--color-text-primary)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n Renderer\n </label>\n <Select\n value={localForm.renderer}\n onValueChange={(value) => {\n const newRenderer = value as RendererType;\n updateLocalForm('renderer', newRenderer);\n if (newRenderer === 'BIGCONSOLE') {\n updateLocalForm('template', undefined);\n }\n }}\n >\n <SelectTrigger\n style={{ height: 'var(--size-controlHeight-md)', fontSize: 'var(--font-size-body-sm)' }}\n >\n <SelectValue placeholder=\"Select renderer\" />\n </SelectTrigger>\n <SelectContent\n position=\"popper\"\n side=\"bottom\"\n sideOffset={4}\n align=\"start\"\n style={{\n zIndex: 9999,\n maxHeight: '200px',\n backgroundColor: 'var(--color-overlay-popoverBg, var(--color-bg-surface, #ffffff))',\n border: '1px solid var(--color-border)',\n boxShadow: 'var(--shadow-elevation-3)',\n borderRadius: 'var(--radius-button)',\n }}\n >\n {RENDERER_OPTIONS.map((opt) => (\n <SelectItem key={opt.value} value={opt.value}>\n {opt.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <p\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-muted)',\n marginTop: 'var(--space-controlGap)',\n }}\n >\n {RENDERER_OPTIONS.find((r) => r.value === localForm.renderer)?.description as React.ReactNode}\n </p>\n </div>\n\n {localForm.renderer && localForm.renderer !== 'BIGCONSOLE' && (\n <TemplateEditor\n widget={\n { ...selectedWidget, template: localForm.template, renderer: localForm.renderer } as Widget\n }\n onSave={(template) => updateLocalForm('template', template)}\n />\n )}\n </div>\n )}\n </TabsContent>\n\n <TabsContent value=\"data\" className=\"mt-0 space-y-4\">\n {localForm && (\n <>\n {/* Data Source Section */}\n <div className=\"space-y-4\">\n <div className=\"p-3 bg-muted rounded-md border border-border\">\n <p className=\"text-xs text-muted-foreground\">\n Connect this widget to a DataSink and Parser to display transformed data.\n </p>\n </div>\n\n {/* DataSink Selector */}\n <div className=\"space-y-2\">\n <Label>DataSink</Label>\n <DataSinkSelector\n value={selectedDataSinkKey}\n onChange={handleDataSinkChange}\n placeholder=\"Select a DataSink...\"\n />\n {selectedDataSinkKey && (\n <p className=\"text-xs text-muted-foreground\">\n Key: {selectedDataSinkKey}\n {localForm.dataSinkId && (\n <span className=\"ml-2 text-text-tertiary\">ID: {localForm.dataSinkId.slice(0, 8)}...</span>\n )}\n </p>\n )}\n </div>\n\n {/* Parser Selector - filtered by selected DataSink */}\n <div className=\"space-y-2\">\n <Label>Parser</Label>\n <ParserSelector\n consoleId={selectedWidget?.dashboardId || ''}\n value={localForm.parserId || null}\n onChange={handleParserChange}\n filterInputSinkKey={selectedDataSinkKey || undefined}\n filterStatus={undefined}\n placeholder={selectedDataSinkKey ? 'Select a parser...' : 'Select a DataSink first...'}\n disabled={!selectedDataSinkKey}\n />\n <p className=\"text-xs text-muted-foreground\">\n {isDetectingFields ? (\n <span className=\"flex items-center gap-1\">\n <Spinner style={{ width: '12px', height: '12px' }} />\n Auto-detecting field mappings...\n </span>\n ) : selectedDataSinkKey ? (\n 'Showing parsers that use this DataSink as input'\n ) : (\n 'Select a DataSink to see available parsers'\n )}\n </p>\n </div>\n\n {/* Auto-detected Field Mappings */}\n {!!(localForm.parserId && (localForm.config?.labelField || localForm.config?.valueField)) && (\n <div className=\"p-3 bg-green-50 dark:bg-green-950/30 rounded-md border border-green-200 dark:border-green-800\">\n <p className=\"text-xs font-medium text-green-700 dark:text-green-400 mb-2\">\n ✓ Field mappings configured\n </p>\n <div className=\"text-xs text-green-600 dark:text-green-500 space-y-1\">\n {!!localForm.config?.labelField && (\n <p>\n Label Field:{' '}\n <code className=\"bg-green-100 dark:bg-green-900 px-1 rounded\">\n {String(localForm.config.labelField)}\n </code>\n </p>\n )}\n {!!localForm.config?.valueField && (\n <p>\n Value Field:{' '}\n <code className=\"bg-green-100 dark:bg-green-900 px-1 rounded\">\n {String(localForm.config.valueField)}\n </code>\n </p>\n )}\n {!!localForm.config?.xAxisField && (\n <p>\n X-Axis Field:{' '}\n <code className=\"bg-green-100 dark:bg-green-900 px-1 rounded\">\n {String(localForm.config.xAxisField)}\n </code>\n </p>\n )}\n </div>\n </div>\n )}\n\n {/* Data Path (Optional) */}\n <div className=\"space-y-2\">\n <Label>Data Path (Optional)</Label>\n <Input\n value={(localForm.config?.dataPath as string) || ''}\n onChange={(e) =>\n updateLocalConfig({ ...localForm.config, dataPath: e.target.value || undefined })\n }\n placeholder=\"e.g., summary.totalRevenue\"\n />\n <p className=\"text-xs text-muted-foreground\">\n Path to extract specific data from the parser output (dot notation)\n </p>\n </div>\n </div>\n\n {/* Divider */}\n <div className=\"border-t border-border pt-4\">\n <Label className=\"text-xs text-muted-foreground uppercase tracking-wide\">\n Alternative Data Sources\n </Label>\n </div>\n\n {/* Data Source Type Selector */}\n <div className=\"space-y-2\">\n <Label>Data Source Type</Label>\n <Select\n value={(localForm.config?.dataSourceType as string) || ''}\n onValueChange={(value) =>\n updateLocalConfig({ ...localForm.config, dataSourceType: value || undefined })\n }\n >\n <SelectTrigger\n style={{ height: 'var(--size-controlHeight-md)', fontSize: 'var(--font-size-body-sm)' }}\n >\n <SelectValue placeholder=\"Select type...\" />\n </SelectTrigger>\n <SelectContent\n position=\"popper\"\n side=\"bottom\"\n sideOffset={4}\n align=\"start\"\n style={{\n zIndex: 9999,\n maxHeight: '200px',\n backgroundColor: 'var(--color-overlay-popoverBg, var(--color-bg-surface, #ffffff))',\n border: '1px solid var(--color-border)',\n boxShadow: 'var(--shadow-elevation-3)',\n borderRadius: 'var(--radius-button)',\n }}\n >\n {DATA_SOURCE_TYPES.map((type) => (\n <SelectItem key={type.value} value={type.value}>\n {type.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {localForm.config?.dataSourceType === 'REST_API' && (\n <div className=\"space-y-3\">\n {/* Endpoint URL */}\n <div className=\"space-y-2\">\n <Label>Endpoint URL *</Label>\n <Input\n value={(localForm.config?.endpointUrl as string) || ''}\n onChange={(e) =>\n updateLocalConfig({ ...localForm.config, endpointUrl: e.target.value || undefined })\n }\n placeholder=\"https://api.example.com/data\"\n />\n </div>\n\n {/* HTTP Method */}\n <div className=\"space-y-2\">\n <Label>HTTP Method</Label>\n <Select\n value={(localForm.config?.httpMethod as string) || 'GET'}\n onValueChange={(value) => updateLocalConfig({ ...localForm.config, httpMethod: value })}\n >\n <SelectTrigger style={{ height: 'var(--size-controlHeight-md)' }}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent position=\"popper\" side=\"bottom\" sideOffset={4}>\n <SelectItem value=\"GET\">GET</SelectItem>\n <SelectItem value=\"POST\">POST</SelectItem>\n <SelectItem value=\"PUT\">PUT</SelectItem>\n <SelectItem value=\"DELETE\">DELETE</SelectItem>\n </SelectContent>\n </Select>\n </div>\n\n {/* Headers */}\n <div className=\"space-y-2\">\n <Label>Headers (JSON)</Label>\n <Textarea\n value={(localForm.config?.headers as string) || ''}\n onChange={(e) =>\n updateLocalConfig({ ...localForm.config, headers: e.target.value || undefined })\n }\n rows={3}\n placeholder='{\"Authorization\": \"Bearer token\", \"Content-Type\": \"application/json\"}'\n className=\"font-mono text-xs\"\n />\n </div>\n\n {/* Authentication Type */}\n <div className=\"space-y-2\">\n <Label>Authentication</Label>\n <Select\n value={(localForm.config?.authType as string) || 'none'}\n onValueChange={(value) => updateLocalConfig({ ...localForm.config, authType: value })}\n >\n <SelectTrigger style={{ height: 'var(--size-controlHeight-md)' }}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent position=\"popper\" side=\"bottom\" sideOffset={4}>\n <SelectItem value=\"none\">None</SelectItem>\n <SelectItem value=\"api_key\">API Key</SelectItem>\n <SelectItem value=\"bearer\">Bearer Token</SelectItem>\n <SelectItem value=\"basic\">Basic Auth</SelectItem>\n </SelectContent>\n </Select>\n </div>\n\n {/* Auth Value (conditional) */}\n {!!(localForm.config?.authType && localForm.config.authType !== 'none') && (\n <div className=\"space-y-2\">\n <Label>\n {String(localForm.config.authType) === 'basic' ? 'Credentials (user:pass)' : 'Token/Key'}\n </Label>\n <Input\n type=\"password\"\n value={(localForm.config?.authValue as string) || ''}\n onChange={(e) =>\n updateLocalConfig({ ...localForm.config, authValue: e.target.value || undefined })\n }\n placeholder={\n localForm.config.authType === 'basic' ? 'username:password' : 'Enter token or API key'\n }\n />\n </div>\n )}\n\n {/* Request Body (for POST/PUT) */}\n {(localForm.config?.httpMethod === 'POST' || localForm.config?.httpMethod === 'PUT') && (\n <div className=\"space-y-2\">\n <Label>Request Body (JSON)</Label>\n <Textarea\n value={(localForm.config?.requestBody as string) || ''}\n onChange={(e) =>\n updateLocalConfig({ ...localForm.config, requestBody: e.target.value || undefined })\n }\n rows={4}\n placeholder='{\"key\": \"value\"}'\n className=\"font-mono text-xs\"\n />\n </div>\n )}\n\n {/* Data Path */}\n <div className=\"space-y-2\">\n <Label>Data Path (optional)</Label>\n <Input\n value={(localForm.config?.dataPath as string) || ''}\n onChange={(e) =>\n updateLocalConfig({ ...localForm.config, dataPath: e.target.value || undefined })\n }\n placeholder=\"$.data.items or .data.items\"\n />\n <p className=\"text-xs text-muted-foreground\">\n JSONPath or dot notation to extract data from response\n </p>\n </div>\n </div>\n )}\n\n {localForm.config?.dataSourceType === 'GRAPHQL' && (\n <div className=\"space-y-3\">\n {/* GraphQL Endpoint */}\n <div className=\"space-y-2\">\n <Label>GraphQL Endpoint *</Label>\n <Input\n value={(localForm.config?.graphqlEndpoint as string) || ''}\n onChange={(e) =>\n updateLocalConfig({ ...localForm.config, graphqlEndpoint: e.target.value || undefined })\n }\n placeholder=\"https://api.example.com/graphql\"\n />\n </div>\n\n {/* GraphQL Query */}\n <div className=\"space-y-2\">\n <Label>Query *</Label>\n <Textarea\n value={(localForm.config?.graphqlQuery as string) || ''}\n onChange={(e) =>\n updateLocalConfig({ ...localForm.config, graphqlQuery: e.target.value || undefined })\n }\n rows={6}\n placeholder={`query GetData($limit: Int) {\n items(limit: $limit) {\n id\n name\n value\n }\n}`}\n className=\"font-mono text-xs\"\n />\n </div>\n\n {/* GraphQL Variables */}\n <div className=\"space-y-2\">\n <Label>Variables (JSON, optional)</Label>\n <Textarea\n value={(localForm.config?.graphqlVariables as string) || ''}\n onChange={(e) =>\n updateLocalConfig({ ...localForm.config, graphqlVariables: e.target.value || undefined })\n }\n rows={3}\n placeholder='{\"limit\": 10, \"offset\": 0}'\n className=\"font-mono text-xs\"\n />\n </div>\n\n {/* Headers */}\n <div className=\"space-y-2\">\n <Label>Headers (JSON, optional)</Label>\n <Textarea\n value={(localForm.config?.headers as string) || ''}\n onChange={(e) =>\n updateLocalConfig({ ...localForm.config, headers: e.target.value || undefined })\n }\n rows={2}\n placeholder='{\"Authorization\": \"Bearer token\"}'\n className=\"font-mono text-xs\"\n />\n </div>\n\n {/* Data Path */}\n <div className=\"space-y-2\">\n <Label>Data Path (optional)</Label>\n <Input\n value={(localForm.config?.dataPath as string) || ''}\n onChange={(e) =>\n updateLocalConfig({ ...localForm.config, dataPath: e.target.value || undefined })\n }\n placeholder=\".data.items\"\n />\n <p className=\"text-xs text-muted-foreground\">Path to extract data from GraphQL response</p>\n </div>\n </div>\n )}\n\n {localForm.config?.dataSourceType === 'MOCK' && (\n <div className=\"space-y-2\">\n <Label>Sample Data (JSON)</Label>\n <Textarea\n value={(localForm.config?.mockData as string) || ''}\n onChange={(e) =>\n updateLocalConfig({ ...localForm.config, mockData: e.target.value || undefined })\n }\n rows={5}\n placeholder='{\"value\": 100}'\n className=\"font-mono text-sm\"\n />\n </div>\n )}\n </>\n )}\n </TabsContent>\n\n <TabsContent value=\"actions\" className=\"mt-0 space-y-4\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h3 className=\"text-sm font-medium\">Widget Actions</h3>\n <p className=\"text-xs text-muted-foreground\">Configure buttons on this widget</p>\n </div>\n <Button size=\"sm\" onClick={handleAddAction}>\n <Plus className=\"size-4\" />\n Add\n </Button>\n </div>\n\n {actionsLoading ? (\n <div className=\"flex justify-center py-8\">\n <Spinner className=\"size-6\" />\n </div>\n ) : actions.length === 0 ? (\n <div className=\"py-8 text-center\">\n <Info className=\"size-10 mx-auto mb-2 text-muted-foreground/50\" />\n <p className=\"text-sm text-muted-foreground\">No actions configured</p>\n </div>\n ) : (\n <div className=\"space-y-2\">\n {[...actions]\n .sort((a, b) => a.order - b.order)\n .map((action, index) => (\n <Card key={action.id} className={action.disabled ? 'opacity-60' : ''}>\n <CardContent className=\"p-3 flex items-center gap-2\">\n <div className=\"flex flex-col gap-0.5\">\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={() => handleMoveActionUp(index)}\n disabled={index === 0}\n className=\"h-5 w-5\"\n >\n <ChevronUp className=\"size-3\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={() => handleMoveActionDown(index)}\n disabled={index === actions.length - 1}\n className=\"h-5 w-5\"\n >\n <ChevronDown className=\"size-3\" />\n </Button>\n </div>\n\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span\n className={`size-2 rounded-full ${ACTION_STYLE_COLORS[action.style] || 'bg-muted-foreground'}`}\n />\n <span className=\"text-sm font-medium truncate\">{action.label}</span>\n </div>\n <p className=\"text-xs text-muted-foreground\">\n {action.name} • {action.type}\n </p>\n </div>\n\n <div className=\"flex gap-1\">\n <Button variant=\"ghost\" size=\"icon-sm\" onClick={() => handleEditAction(action)}>\n <Pencil className=\"size-4\" />\n </Button>\n <Button variant=\"ghost\" size=\"icon-sm\" onClick={() => handleDeleteAction(action.id)}>\n <Trash2 className=\"size-4\" />\n </Button>\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n )}\n </TabsContent>\n\n <TabsContent value=\"drilldown\" className=\"mt-0\">\n <DrilldownConfigPanel widget={selectedWidget} onChange={handleDrilldownChange} />\n </TabsContent>\n\n <TabsContent value=\"webhooks\" className=\"mt-0\">\n <WebhookConfigPanel dashboardId={selectedWidget.dashboardId} widgetId={selectedWidget.id} />\n </TabsContent>\n\n <TabsContent value=\"events\" className=\"mt-0\">\n <EventLogViewer\n dashboardId={selectedWidget.dashboardId}\n widgetId={selectedWidget.id}\n maxHeight=\"calc(100vh - 350px)\"\n />\n </TabsContent>\n\n <TabsContent value=\"appearance\" className=\"mt-0\">\n {ConfigComponent ? (\n <ConfigComponent\n config={((selectedWidget.config as Record<string, unknown>) || {}) as never}\n onChange={handleConfigChange as never}\n />\n ) : (\n <div className=\"p-4 bg-muted rounded-lg text-center\">\n <p className=\"text-sm text-muted-foreground\">No style options for this widget type</p>\n </div>\n )}\n </TabsContent>\n </div>\n </Tabs>\n ) : (\n <div className=\"flex-1 flex items-center justify-center p-4\">\n <div className=\"text-center\">\n <Info className=\"size-12 mx-auto mb-3 text-muted-foreground\" />\n <p className=\"text-sm text-muted-foreground\">Select a widget to edit</p>\n </div>\n </div>\n )}\n\n {/* Global Save/Discard Footer */}\n {selectedWidget && (\n <div\n style={{\n padding: 'var(--space-cardPadding)',\n borderTop: '1px solid var(--color-border)',\n backgroundColor: 'var(--color-bg-sunken)',\n flexShrink: 0,\n }}\n >\n {/* Status indicator */}\n {hasUnsavedChanges && (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-iconGap)',\n marginBottom: 'var(--space-controlGap)',\n padding: 'var(--space-controlGap)',\n backgroundColor: 'var(--color-status-warning-bgSubtle, rgba(251, 191, 36, 0.1))',\n borderRadius: 'var(--radius-button)',\n border: '1px solid var(--color-status-warning-border, rgba(251, 191, 36, 0.3))',\n }}\n >\n <div\n style={{\n width: '8px',\n height: '8px',\n borderRadius: '50%',\n backgroundColor: 'var(--color-status-warning-bg)',\n flexShrink: 0,\n }}\n />\n <span\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-status-warning-text, #92400e)',\n fontWeight: 'var(--font-weight-medium)',\n }}\n >\n You have unsaved changes\n </span>\n </div>\n )}\n\n {saveStatus === 'saved' && !hasUnsavedChanges && (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-iconGap)',\n marginBottom: 'var(--space-controlGap)',\n padding: 'var(--space-controlGap)',\n backgroundColor: 'var(--color-status-success-bgSubtle, rgba(34, 197, 94, 0.1))',\n borderRadius: 'var(--radius-button)',\n border: '1px solid var(--color-status-success-border, rgba(34, 197, 94, 0.3))',\n }}\n >\n <Check\n style={{\n width: 'var(--size-icon-sm)',\n height: 'var(--size-icon-sm)',\n color: 'var(--color-status-success-text)',\n flexShrink: 0,\n }}\n />\n <span\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-status-success-text)',\n fontWeight: 'var(--font-weight-medium)',\n }}\n >\n All changes saved\n </span>\n </div>\n )}\n\n {saveStatus === 'error' && (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-iconGap)',\n marginBottom: 'var(--space-controlGap)',\n padding: 'var(--space-controlGap)',\n backgroundColor: 'var(--color-status-error-bgSubtle)',\n borderRadius: 'var(--radius-button)',\n border: '1px solid var(--color-status-error-border)',\n }}\n >\n <X\n style={{\n width: 'var(--size-icon-sm)',\n height: 'var(--size-icon-sm)',\n color: 'var(--color-status-error-text)',\n flexShrink: 0,\n }}\n />\n <span\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-status-error-text)',\n fontWeight: 'var(--font-weight-medium)',\n }}\n >\n Failed to save changes\n </span>\n </div>\n )}\n\n {/* Action buttons */}\n <div style={{ display: 'flex', gap: 'var(--space-controlGap)' }}>\n <Button\n onClick={handleSaveAll}\n disabled={saveStatus === 'saving' || !hasUnsavedChanges}\n style={{\n flex: 1,\n height: 'var(--size-controlHeight-md)',\n backgroundColor: hasUnsavedChanges ? 'var(--color-action-primary-bg)' : undefined,\n opacity: hasUnsavedChanges ? 1 : 0.5,\n }}\n >\n {saveStatus === 'saving' ? (\n <span style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-iconGap)' }}>\n <Spinner style={{ width: 'var(--size-icon-sm)', height: 'var(--size-icon-sm)' }} />\n Saving...\n </span>\n ) : (\n <span style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-iconGap)' }}>\n <Check style={{ width: 'var(--size-icon-sm)', height: 'var(--size-icon-sm)' }} />\n Save Changes\n </span>\n )}\n </Button>\n <Button\n variant=\"outline\"\n onClick={handleDiscardAll}\n disabled={saveStatus === 'saving' || !hasUnsavedChanges}\n style={{\n height: 'var(--size-controlHeight-md)',\n opacity: hasUnsavedChanges ? 1 : 0.5,\n }}\n >\n <X style={{ width: 'var(--size-icon-sm)', height: 'var(--size-icon-sm)' }} />\n Discard\n </Button>\n </div>\n </div>\n )}\n\n <ActionConfigDialog\n isOpen={isActionDialogOpen}\n action={editingAction}\n isLoading={actionSaving}\n onClose={() => {\n setIsActionDialogOpen(false);\n setEditingAction(undefined);\n }}\n onSave={handleSaveAction}\n />\n </SheetContent>\n </Sheet>\n );\n});\n\nexport default PropertiesPanel;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PropertiesPanel.js","names":[],"sources":["../../../../src/bigconsole/components/widgets/PropertiesPanel.tsx"],"sourcesContent":["/**\n * PropertiesPanel Component\n *\n * Right-side panel for widget configuration.\n * v2.0: Added Actions tab for managing widget actions.\n * Uses fe-libs shared components for consistent styling.\n */\n\nimport React, { type FC, memo, useCallback, useState, useEffect, useRef } from 'react';\nimport { Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription } from '@burdenoff/fe-libs/ui';\nimport { Tabs, TabsList, TabsTrigger, TabsContent } from '@burdenoff/fe-libs/ui';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { Input } from '@burdenoff/fe-libs/ui';\nimport { Textarea } from '@burdenoff/fe-libs/ui';\nimport { Label } from '@burdenoff/fe-libs/ui';\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@burdenoff/fe-libs/ui';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { Card, CardContent } from '@burdenoff/fe-libs/ui';\nimport { Plus, ChevronUp, ChevronDown, Pencil, Trash2, ExternalLink, Check, X, Info } from 'lucide-react';\nimport type { Widget, WidgetType, DataSourceType, RendererType } from '../../types';\nimport { useWidgetStore } from '../../store';\nimport { useWidgetOperations, useDrilldownOperations } from '../../hooks';\nimport {\n useWidgetActions,\n type WidgetAction,\n type CreateWidgetActionInput,\n type UpdateWidgetActionInput,\n} from '../../hooks/useWidgetActions';\nimport { getWidgetDefinition } from './WidgetRegistry';\nimport { ActionConfigDialog } from './ActionConfigDialog';\nimport { WebhookConfigPanel } from './webhook-config';\nimport { EventLogViewer } from './event-logs';\nimport { DrilldownConfigPanel, type DrilldownConfig } from './DrilldownConfigPanel';\n// Data Source selectors\nimport { DataSinkSelector } from '../parser/DataSinkSelector';\nimport { ParserSelector } from '../parser/ParserSelector';\nimport { useDataSinkOperations } from '../../hooks/useDataSinkOperations';\nimport { useParserOperations } from '../../hooks/useParserOperations';\n\n// Config components\nimport { MetricCardConfig } from './metric-card/MetricCardConfig';\nimport { ChartConfig } from './chart/ChartConfig';\nimport { TableConfig } from './table/TableConfig';\nimport { GaugeConfig } from './gauge/GaugeConfig';\nimport { ProgressConfig } from './progress/ProgressConfig';\nimport { ListConfig } from './list/ListConfig';\n\n// ============================================================================\n// v2.0: Renderer Options\n// ============================================================================\n\nconst RENDERER_OPTIONS: { value: RendererType; label: string; description: string }[] = [\n { value: 'BIGCONSOLE', label: 'BigConsole Native', description: 'Full-featured native widgets' },\n { value: 'ADAPTIVE_CARD', label: 'Adaptive Cards', description: 'Microsoft Teams/Outlook format' },\n { value: 'BLOCKKIT', label: 'Block Kit', description: 'Slack format' },\n { value: 'CUSTOM', label: 'Custom', description: 'Custom React component' },\n];\n\n// ============================================================================\n// Data Source Constants\n// ============================================================================\n\nconst DATA_SOURCE_TYPES: { value: DataSourceType; label: string; description: string }[] = [\n { value: 'DATASINK', label: 'DataSink', description: 'Use data from BigConsole DataSinks' },\n { value: 'REST_API', label: 'REST API', description: 'Fetch data from REST endpoints' },\n { value: 'GRAPHQL', label: 'GraphQL', description: 'Query data using GraphQL' },\n { value: 'SQL', label: 'SQL Database', description: 'Query SQL databases directly' },\n { value: 'WEBSOCKET', label: 'WebSocket', description: 'Real-time data streaming' },\n { value: 'MOCK', label: 'Sample JSON', description: 'Manually enter sample JSON data' },\n];\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface PropertiesPanelProps {\n isOpen: boolean;\n onClose: () => void;\n}\n\ntype TabId = 'general' | 'data' | 'actions' | 'drilldown' | 'webhooks' | 'events' | 'appearance';\n\n// Action style colors\nconst ACTION_STYLE_COLORS: Record<string, string> = {\n PRIMARY: 'bg-action-primary',\n SECONDARY: 'bg-muted-foreground',\n SUCCESS: 'bg-state-success',\n WARNING: 'bg-state-warning',\n DANGER: 'bg-state-error',\n};\n\n// ============================================================================\n// Config Component Map\n// ============================================================================\n\n/**\n * Detects field names from parser output and returns suggested labelField and valueField\n * @param output - The parser execution output\n * @returns Object with suggested labelField and valueField\n */\nfunction detectFieldsFromParserOutput(output: unknown): {\n labelField?: string;\n valueField?: string;\n xAxisField?: string;\n} {\n if (!output) return {};\n\n // If output is an array, look at the first item\n const sampleItem = Array.isArray(output) ? output[0] : output;\n\n if (!sampleItem || typeof sampleItem !== 'object') return {};\n\n const keys = Object.keys(sampleItem as Record<string, unknown>);\n\n // Common label field names (in order of priority)\n const labelFieldCandidates = [\n 'name',\n 'label',\n 'category',\n 'title',\n 'key',\n 'id',\n 'month',\n 'date',\n 'region',\n 'product',\n ];\n // Common value field names (in order of priority)\n const valueFieldCandidates = ['value', 'amount', 'count', 'total', 'revenue', 'sales', 'quantity', 'orders', 'sum'];\n\n let labelField: string | undefined;\n let valueField: string | undefined;\n\n // Find the best label field\n for (const candidate of labelFieldCandidates) {\n if (keys.includes(candidate)) {\n labelField = candidate;\n break;\n }\n }\n\n // Find the best value field\n for (const candidate of valueFieldCandidates) {\n if (keys.includes(candidate)) {\n valueField = candidate;\n break;\n }\n }\n\n // If no standard names found, use heuristics:\n // - First string field as label\n // - First number field as value\n if (!labelField || !valueField) {\n for (const key of keys) {\n const val = (sampleItem as Record<string, unknown>)[key];\n if (!labelField && typeof val === 'string') {\n labelField = key;\n }\n if (!valueField && typeof val === 'number') {\n valueField = key;\n }\n if (labelField && valueField) break;\n }\n }\n\n return {\n labelField,\n valueField,\n xAxisField: labelField, // For line/bar charts, xAxisField is usually the same as labelField\n };\n}\n\nfunction getConfigComponent(type: WidgetType) {\n switch (type) {\n case 'metric_card':\n case 'kpi_card_comparison':\n return MetricCardConfig;\n case 'chart':\n case 'funnel_chart':\n return ChartConfig;\n case 'table':\n case 'pivot_table':\n return TableConfig;\n case 'gauge':\n return GaugeConfig;\n case 'progress':\n return ProgressConfig;\n case 'list':\n return ListConfig;\n default:\n return null;\n }\n}\n\n// ============================================================================\n// Template Editor Component\n// ============================================================================\n\ninterface TemplateEditorProps {\n widget: Widget;\n onSave: (template: Record<string, unknown>) => void;\n}\n\nconst TemplateEditor: FC<TemplateEditorProps> = memo(function TemplateEditor({ widget, onSave }) {\n const [localValue, setLocalValue] = useState<string>('');\n const [jsonError, setJsonError] = useState<string | null>(null);\n const initializedRef = useRef(false);\n\n // Initialize from widget.template only once per widget\n useEffect(() => {\n try {\n const templateStr =\n widget.template && typeof widget.template === 'object' ? JSON.stringify(widget.template, null, 2) : '';\n setLocalValue(templateStr);\n setJsonError(null);\n initializedRef.current = true;\n } catch {\n setLocalValue('');\n }\n }, [widget.id, widget.template]);\n\n const handleChange = useCallback(\n (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n const value = e.target.value;\n setLocalValue(value);\n\n if (value.trim() === '') {\n setJsonError(null);\n // Empty template is valid - notify parent\n onSave({});\n } else {\n try {\n const parsed = JSON.parse(value);\n setJsonError(null);\n // Valid JSON - immediately notify parent so main Save button becomes active\n onSave(parsed);\n } catch (err) {\n setJsonError((err as Error).message);\n // Don't call onSave for invalid JSON\n }\n }\n },\n [onSave]\n );\n\n const handleFormat = useCallback(() => {\n try {\n const parsed = JSON.parse(localValue);\n const formatted = JSON.stringify(parsed, null, 2);\n setLocalValue(formatted);\n setJsonError(null);\n onSave(parsed);\n } catch (err) {\n setJsonError((err as Error).message);\n }\n }, [localValue, onSave]);\n\n return (\n <div\n style={{\n paddingTop: 'var(--space-formGap)',\n borderTop: '1px solid var(--color-border)',\n }}\n >\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n <label\n style={{\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)',\n color: 'var(--color-text-primary)',\n }}\n >\n Template (JSON)\n </label>\n {jsonError && (\n <span\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-status-error-text)',\n fontWeight: 'var(--font-weight-medium)',\n }}\n >\n Invalid JSON\n </span>\n )}\n </div>\n\n <Textarea\n value={localValue}\n onChange={handleChange}\n spellCheck={false}\n placeholder={`Enter ${widget.renderer} template JSON...`}\n style={{\n fontFamily: 'var(--font-family-mono)',\n fontSize: 'var(--font-size-body-sm)',\n minHeight: '180px',\n borderColor: jsonError ? 'var(--color-status-error-border)' : undefined,\n resize: 'vertical',\n }}\n />\n\n {jsonError && (\n <p\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-status-error-text)',\n backgroundColor: 'var(--color-status-error-bgSubtle)',\n padding: 'var(--space-controlGap)',\n borderRadius: 'var(--radius-button)',\n marginTop: 'var(--space-controlGap)',\n }}\n >\n {jsonError}\n </p>\n )}\n\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-controlGap)',\n marginTop: 'var(--space-controlGap)',\n }}\n >\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={handleFormat}\n disabled={!!jsonError || localValue.trim() === ''}\n style={{ height: 'var(--size-controlHeight-sm)', fontWeight: 'var(--font-weight-semibold)' }}\n >\n Format\n </Button>\n {!jsonError && localValue.trim() !== '' && (\n <span\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-status-success-text)',\n display: 'flex',\n alignItems: 'center',\n gap: '4px',\n }}\n >\n <Check style={{ width: '12px', height: '12px' }} />\n Valid JSON\n </span>\n )}\n </div>\n\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-muted)',\n marginTop: 'var(--space-controlGap)',\n paddingTop: 'var(--space-controlGap)',\n borderTop: '1px solid var(--color-border)',\n }}\n >\n <span style={{ fontWeight: 'var(--font-weight-medium)' }}>Ctrl+S to save</span>\n {widget.renderer === 'ADAPTIVE_CARD' && (\n <a\n href=\"https://adaptivecards.io/designer/\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-controlGap)',\n color: 'var(--color-text-link)',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-medium)',\n textDecoration: 'none',\n }}\n >\n Designer\n <ExternalLink style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />\n </a>\n )}\n {widget.renderer === 'BLOCKKIT' && (\n <a\n href=\"https://app.slack.com/block-kit-builder\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-controlGap)',\n color: 'var(--color-text-link)',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-medium)',\n textDecoration: 'none',\n }}\n >\n Block Kit Builder\n <ExternalLink style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />\n </a>\n )}\n </div>\n </div>\n );\n});\n\n// ============================================================================\n// Local Form State Type\n// ============================================================================\n\ninterface LocalFormState {\n title: string;\n description: string;\n refreshInterval: number | undefined;\n renderer: RendererType;\n template: Record<string, unknown> | undefined;\n // v2.0: Data source fields (DataSink → Parser → Widget)\n dataSinkId: string | undefined;\n datasetId: string | undefined;\n parserId: string | undefined;\n parserRules: string | undefined;\n config: Record<string, unknown>;\n // Drilldown configuration\n drilldownConfig: DrilldownConfig | undefined;\n}\n\nfunction createLocalFormStateFromWidget(widget: Widget): LocalFormState {\n const widgetFields = widget as unknown as Record<string, string | undefined>;\n\n return {\n title: widget.title || '',\n description: widget.description || '',\n refreshInterval: widget.refreshInterval ?? undefined,\n renderer: (widget.renderer as RendererType) || 'BIGCONSOLE',\n template: widget.template as Record<string, unknown> | undefined,\n // v2.0: Data source fields (DataSink → Parser → Widget)\n dataSinkId: widgetFields.dataSinkId ?? undefined,\n datasetId: widgetFields.datasetId ?? undefined,\n parserId: widgetFields.parserId ?? undefined,\n parserRules: widgetFields.parserRules ?? undefined,\n config: (widget.config as Record<string, unknown>) || {},\n // Drilldown configuration\n drilldownConfig: widget.drilldown\n ? {\n enabled: widget.drilldown.enabled ?? false,\n targetDashboardId: widget.drilldown.targetDashboardId ?? '',\n navigationMode: widget.drilldown.navigationMode ?? 'MODAL',\n parameterMapping: (widget.drilldown.parameterMapping as Record<string, string>) ?? {},\n passGlobalFilters: widget.drilldown.passGlobalFilters ?? true,\n maxDepth: widget.drilldown.maxDepth ?? 3,\n openIn: widget.drilldown.openIn ?? 'same',\n }\n : undefined,\n };\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport const PropertiesPanel: FC<PropertiesPanelProps> = memo(function PropertiesPanel({ isOpen, onClose }) {\n const [activeTab, setActiveTab] = useState<TabId>('general');\n const [saveStatus, setSaveStatus] = useState<'idle' | 'saving' | 'saved' | 'error'>('idle');\n const [localForm, setLocalForm] = useState<LocalFormState | null>(null);\n const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);\n\n const selectedWidgetId = useWidgetStore((state) => state.selectedWidgetId);\n const widgets = useWidgetStore((state) => state.widgets);\n const updateWidgetInStore = useWidgetStore((state) => state.updateWidget);\n\n const selectedWidget = selectedWidgetId ? widgets.get(selectedWidgetId) : undefined;\n const previousSelectedWidgetIdRef = useRef<string | null>(null);\n\n useEffect(() => {\n if (!selectedWidgetId) {\n previousSelectedWidgetIdRef.current = null;\n setLocalForm(null);\n setHasUnsavedChanges(false);\n setSaveStatus('idle');\n return;\n }\n\n const widgetSwitched = previousSelectedWidgetIdRef.current !== selectedWidgetId;\n previousSelectedWidgetIdRef.current = selectedWidgetId;\n\n if (selectedWidget) {\n if (hasUnsavedChanges && !widgetSwitched) return;\n\n setLocalForm(createLocalFormStateFromWidget(selectedWidget));\n setHasUnsavedChanges(false);\n setSaveStatus('idle');\n } else {\n setLocalForm(null);\n setHasUnsavedChanges(false);\n setSaveStatus('idle');\n }\n }, [selectedWidgetId, selectedWidget, hasUnsavedChanges]);\n\n const { updateWidget: updateWidgetApi } = useWidgetOperations(selectedWidget?.pageId, selectedWidget?.dashboardId, {\n skipFetch: true,\n });\n\n // Drilldown operations\n const { createDrilldown, updateDrilldown, deleteDrilldown } = useDrilldownOperations();\n\n // DataSink operations - for looking up DataSink by key\n const { dataSinks } = useDataSinkOperations({ skipFetch: false });\n\n // Track selected DataSink key for filtering parsers\n const [selectedDataSinkKey, setSelectedDataSinkKey] = useState<string | null>(null);\n\n // Parser operations - for executing parser to detect fields\n const { executeParser } = useParserOperations({\n consoleId: selectedWidget?.dashboardId,\n skipFetch: true,\n });\n\n // Track if we're auto-detecting fields\n const [isDetectingFields, setIsDetectingFields] = useState(false);\n\n const {\n actions,\n loading: actionsLoading,\n createAction,\n updateAction,\n deleteAction,\n reorderActions,\n } = useWidgetActions(selectedWidgetId || undefined);\n\n const [isActionDialogOpen, setIsActionDialogOpen] = useState(false);\n const [editingAction, setEditingAction] = useState<WidgetAction | undefined>(undefined);\n const [actionSaving, setActionSaving] = useState(false);\n\n const handleAddAction = useCallback(() => {\n setEditingAction(undefined);\n setIsActionDialogOpen(true);\n }, []);\n\n const handleEditAction = useCallback((action: WidgetAction) => {\n setEditingAction(action);\n setIsActionDialogOpen(true);\n }, []);\n\n const handleSaveAction = useCallback(\n async (data: Omit<CreateWidgetActionInput, 'widgetId'> | UpdateWidgetActionInput) => {\n if (!selectedWidgetId) return;\n\n setActionSaving(true);\n try {\n let newAction: WidgetAction | null = null;\n if ('id' in data) {\n newAction = await updateAction(data);\n } else {\n newAction = await createAction(data);\n }\n\n // Immediately sync to widget store after successful save\n // This ensures the widget displays the action right away\n if (newAction) {\n const currentActions = [...actions];\n if ('id' in data) {\n // Update existing action\n const idx = currentActions.findIndex((a) => a.id === data.id);\n if (idx >= 0) {\n currentActions[idx] = newAction;\n }\n } else {\n // Add new action\n currentActions.push(newAction);\n }\n // Sort by order and update store\n const sortedActions = currentActions.sort((a, b) => a.order - b.order);\n updateWidgetInStore(selectedWidgetId, { actions: sortedActions });\n }\n\n setIsActionDialogOpen(false);\n setEditingAction(undefined);\n } catch (err) {\n } finally {\n setActionSaving(false);\n }\n },\n [selectedWidgetId, actions, createAction, updateAction, updateWidgetInStore]\n );\n\n const handleDeleteAction = useCallback(\n async (actionId: string) => {\n if (!selectedWidgetId) return;\n\n if (window.confirm('Are you sure you want to delete this action?')) {\n const success = await deleteAction(actionId);\n if (success) {\n // Immediately sync to widget store after deletion\n const updatedActions = actions.filter((a) => a.id !== actionId);\n updateWidgetInStore(selectedWidgetId, { actions: updatedActions });\n }\n }\n },\n [selectedWidgetId, actions, deleteAction, updateWidgetInStore]\n );\n\n const handleMoveActionUp = useCallback(\n async (index: number) => {\n if (!selectedWidgetId || index === 0) return;\n const sortedActions = [...actions].sort((a, b) => a.order - b.order);\n const newOrder = sortedActions.map((a) => a.id);\n [newOrder[index - 1], newOrder[index]] = [newOrder[index], newOrder[index - 1]];\n const success = await reorderActions(newOrder);\n if (success) {\n // Immediately update local order for UI responsiveness\n const reordered = sortedActions\n .map((a, _i) => ({\n ...a,\n order: newOrder.indexOf(a.id),\n }))\n .sort((a, b) => a.order - b.order);\n updateWidgetInStore(selectedWidgetId, { actions: reordered });\n }\n },\n [selectedWidgetId, actions, reorderActions, updateWidgetInStore]\n );\n\n const handleMoveActionDown = useCallback(\n async (index: number) => {\n if (!selectedWidgetId) return;\n const sortedActions = [...actions].sort((a, b) => a.order - b.order);\n if (index === sortedActions.length - 1) return;\n const newOrder = sortedActions.map((a) => a.id);\n [newOrder[index], newOrder[index + 1]] = [newOrder[index + 1], newOrder[index]];\n const success = await reorderActions(newOrder);\n if (success) {\n // Immediately update local order for UI responsiveness\n const reordered = sortedActions\n .map((a, _i) => ({\n ...a,\n order: newOrder.indexOf(a.id),\n }))\n .sort((a, b) => a.order - b.order);\n updateWidgetInStore(selectedWidgetId, { actions: reordered });\n }\n },\n [selectedWidgetId, actions, reorderActions, updateWidgetInStore]\n );\n\n useEffect(() => {\n if (selectedWidgetId && actions.length >= 0 && !actionsLoading) {\n updateWidgetInStore(selectedWidgetId, { actions });\n }\n }, [selectedWidgetId, actions, actionsLoading, updateWidgetInStore]);\n\n const updateLocalForm = useCallback(<K extends keyof LocalFormState>(key: K, value: LocalFormState[K]) => {\n setLocalForm((prev) => (prev ? { ...prev, [key]: value } : prev));\n setHasUnsavedChanges(true);\n }, []);\n\n const updateLocalConfig = useCallback((newConfig: Record<string, unknown>) => {\n setLocalForm((prev) => (prev ? { ...prev, config: newConfig } : prev));\n setHasUnsavedChanges(true);\n }, []);\n\n // Initialize selectedDataSinkKey from widget's dataSinkId\n useEffect(() => {\n if (localForm?.dataSinkId && dataSinks.length > 0) {\n const ds = dataSinks.find((d) => d.id === localForm.dataSinkId);\n if (ds) {\n setSelectedDataSinkKey(ds.key);\n }\n } else {\n setSelectedDataSinkKey(null);\n }\n }, [localForm?.dataSinkId, dataSinks]);\n\n // Handle DataSink selection - looks up ID from key and updates form\n const handleDataSinkChange = useCallback(\n (key: string | null) => {\n setSelectedDataSinkKey(key);\n if (key) {\n const ds = dataSinks.find((d) => d.key === key);\n if (ds) {\n updateLocalForm('dataSinkId', ds.id);\n // Also update config.dataSinkKey for backward compatibility\n setLocalForm((prev) =>\n prev\n ? {\n ...prev,\n config: { ...prev.config, dataSinkKey: key },\n }\n : prev\n );\n setHasUnsavedChanges(true);\n }\n } else {\n updateLocalForm('dataSinkId', undefined);\n setLocalForm((prev) =>\n prev\n ? {\n ...prev,\n config: { ...prev.config, dataSinkKey: undefined },\n parserId: undefined, // Clear parser when DataSink is cleared\n }\n : prev\n );\n setHasUnsavedChanges(true);\n }\n },\n [dataSinks, updateLocalForm]\n );\n\n // Handle Parser selection - with auto-detection of field mappings\n const handleParserChange = useCallback(\n async (parserId: string | null) => {\n updateLocalForm('parserId', parserId || undefined);\n\n // If a parser is selected, execute it to detect field structure\n if (parserId && selectedWidget) {\n setIsDetectingFields(true);\n try {\n const result = await executeParser(parserId);\n\n if (result?.success && result.output) {\n const detectedFields = detectFieldsFromParserOutput(result.output);\n\n // Only auto-populate if fields were detected and not already set\n if (detectedFields.labelField || detectedFields.valueField) {\n setLocalForm((prev) => {\n if (!prev) return prev;\n\n const currentConfig = prev.config || {};\n const newConfig = { ...currentConfig };\n\n // Auto-populate labelField if not already set\n if (detectedFields.labelField && !currentConfig.labelField) {\n newConfig.labelField = detectedFields.labelField;\n }\n\n // Auto-populate valueField if not already set\n if (detectedFields.valueField && !currentConfig.valueField) {\n newConfig.valueField = detectedFields.valueField;\n }\n\n // Auto-populate xAxisField for line/bar/area charts if not already set\n if (detectedFields.xAxisField && !currentConfig.xAxisField) {\n newConfig.xAxisField = detectedFields.xAxisField;\n }\n\n return { ...prev, config: newConfig };\n });\n setHasUnsavedChanges(true);\n }\n }\n } catch (err) {\n // Silent fail - user can still manually configure fields\n console.warn('Failed to auto-detect parser fields:', err);\n } finally {\n setIsDetectingFields(false);\n }\n }\n },\n [updateLocalForm, executeParser, selectedWidget]\n );\n\n const handleSaveAll = useCallback(async () => {\n if (!selectedWidget || !localForm) return;\n\n setSaveStatus('saving');\n\n try {\n const metadata = { ...(selectedWidget.metadata || {}), description: localForm.description || '' };\n\n const result = await updateWidgetApi({\n id: selectedWidget.id,\n title: localForm.title,\n renderer: localForm.renderer,\n template: localForm.template,\n config: localForm.config,\n refreshInterval: localForm.refreshInterval,\n // v2.0: Data source fields (DataSink → Parser → Widget)\n dataSinkId: localForm.dataSinkId,\n datasetId: localForm.datasetId,\n parserId: localForm.parserId,\n parserRules: localForm.parserRules,\n metadata,\n });\n\n // Save drilldown configuration to backend\n let savedDrilldown = selectedWidget.drilldown;\n if (localForm.drilldownConfig) {\n const { enabled, targetDashboardId, navigationMode, parameterMapping, passGlobalFilters, maxDepth, openIn } =\n localForm.drilldownConfig;\n\n if (selectedWidget.drilldown?.id) {\n // Update existing drilldown\n const drilldownResult = await updateDrilldown({\n id: selectedWidget.drilldown.id,\n targetDashboardId,\n parameterMapping,\n navigationMode,\n enabled,\n passGlobalFilters,\n maxDepth,\n openIn,\n });\n if (drilldownResult) {\n savedDrilldown = drilldownResult;\n }\n } else if (targetDashboardId) {\n // Create new drilldown (only if targetDashboardId is set)\n const drilldownResult = await createDrilldown({\n sourceWidgetId: selectedWidget.id,\n targetDashboardId,\n parameterMapping: parameterMapping || {},\n navigationMode,\n passGlobalFilters,\n maxDepth,\n openIn,\n });\n if (drilldownResult) {\n savedDrilldown = { ...drilldownResult, enabled };\n }\n }\n } else if (selectedWidget.drilldown?.id && !localForm.drilldownConfig) {\n // Delete drilldown if it existed but was removed\n await deleteDrilldown(selectedWidget.drilldown.id);\n savedDrilldown = undefined;\n }\n\n if (result) {\n updateWidgetInStore(selectedWidget.id, {\n title: localForm.title,\n description: localForm.description,\n renderer: localForm.renderer,\n template: localForm.template,\n config: localForm.config,\n refreshInterval: localForm.refreshInterval,\n // v2.0: Data source fields\n dataSinkId: localForm.dataSinkId,\n datasetId: localForm.datasetId,\n parserId: localForm.parserId,\n parserRules: localForm.parserRules,\n // Drilldown configuration from backend\n drilldown: savedDrilldown,\n // Update timestamp to trigger WidgetWrapper re-render (fixes drilldown mode change bug)\n updatedAt: new Date().toISOString(),\n } as Partial<Widget>);\n\n setSaveStatus('saved');\n setHasUnsavedChanges(false);\n setTimeout(() => setSaveStatus('idle'), 2000);\n } else {\n setSaveStatus('error');\n }\n } catch (err) {\n setSaveStatus('error');\n }\n }, [\n selectedWidget,\n localForm,\n updateWidgetApi,\n updateWidgetInStore,\n createDrilldown,\n updateDrilldown,\n deleteDrilldown,\n ]);\n\n const handleDiscardAll = useCallback(() => {\n if (!selectedWidget) return;\n\n setLocalForm(createLocalFormStateFromWidget(selectedWidget));\n setHasUnsavedChanges(false);\n setSaveStatus('idle');\n }, [selectedWidget]);\n\n const handleConfigChange = useCallback(\n (newConfig: Record<string, unknown>) => {\n updateLocalConfig(newConfig);\n },\n [updateLocalConfig]\n );\n\n const handleDrilldownChange = useCallback((config: DrilldownConfig) => {\n setLocalForm((prev) => (prev ? { ...prev, drilldownConfig: config } : prev));\n setHasUnsavedChanges(true);\n }, []);\n\n const definition = selectedWidget ? getWidgetDefinition(selectedWidget.type) : null;\n const ConfigComponent = selectedWidget ? getConfigComponent(selectedWidget.type) : null;\n\n return (\n <Sheet open={isOpen} onOpenChange={(open) => !open && onClose()} modal={false}>\n <SheetContent\n style={{\n width: '420px',\n maxWidth: '90vw',\n padding: 0,\n display: 'flex',\n flexDirection: 'column',\n height: '100%',\n overflow: 'hidden',\n }}\n >\n <SheetHeader\n style={{\n padding: 'var(--space-cardPadding)',\n borderBottom: '1px solid var(--color-border)',\n backgroundColor: 'var(--color-bg-surface)',\n flexShrink: 0,\n }}\n >\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-controlGap)' }}>\n <div\n style={{\n display: 'flex',\n height: 'var(--size-controlHeight-lg)',\n width: 'var(--size-controlHeight-lg)',\n alignItems: 'center',\n justifyContent: 'center',\n borderRadius: 'var(--radius-card)',\n backgroundColor: 'var(--color-action-primary-bg)',\n boxShadow: 'var(--shadow-elevation-2)',\n flexShrink: 0,\n }}\n >\n <Info\n style={{\n height: 'var(--size-icon-md)',\n width: 'var(--size-icon-md)',\n color: 'var(--color-action-primary-text)',\n }}\n />\n </div>\n <div style={{ flex: 1, minWidth: 0 }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-iconGap)' }}>\n <SheetTitle\n style={{\n fontSize: 'var(--font-size-body-md)',\n fontWeight: 'var(--font-weight-bold)',\n color: 'var(--color-text-primary)',\n margin: 0,\n }}\n >\n {selectedWidget ? 'Widget Properties' : 'Properties'}\n </SheetTitle>\n {saveStatus === 'saving' && (\n <Spinner style={{ height: 'var(--size-icon-sm)', width: 'var(--size-icon-sm)' }} />\n )}\n {saveStatus === 'saved' && (\n <Check\n style={{\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n color: 'var(--color-status-success-bg)',\n }}\n />\n )}\n {saveStatus === 'error' && (\n <X\n style={{\n height: 'var(--size-icon-sm)',\n width: 'var(--size-icon-sm)',\n color: 'var(--color-status-error-bg)',\n }}\n />\n )}\n </div>\n {definition && (\n <SheetDescription\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-secondary)',\n margin: 'var(--space-controlGap) 0 0 0',\n fontWeight: 'var(--font-weight-medium)',\n }}\n >\n {definition.name}\n </SheetDescription>\n )}\n </div>\n </div>\n </SheetHeader>\n\n {selectedWidget ? (\n <Tabs\n value={activeTab}\n onValueChange={(v) => setActiveTab(v as TabId)}\n style={{ flex: 1, display: 'flex', flexDirection: 'column', minHeight: 0, overflow: 'hidden' }}\n >\n <TabsList\n style={{\n width: '100%',\n display: 'flex',\n justifyContent: 'flex-start',\n borderRadius: 0,\n borderBottom: '1px solid var(--color-border)',\n padding: '0 8px',\n backgroundColor: 'var(--color-bg-sunken)',\n height: 'var(--size-controlHeight-lg)',\n flexShrink: 0,\n gap: '2px',\n overflowX: 'auto',\n }}\n >\n <TabsTrigger\n value=\"general\"\n style={{\n fontWeight: 'var(--font-weight-semibold)',\n fontSize: '12px',\n padding: '6px 8px',\n flexShrink: 0,\n }}\n >\n General\n </TabsTrigger>\n <TabsTrigger\n value=\"data\"\n style={{\n fontWeight: 'var(--font-weight-semibold)',\n fontSize: '12px',\n padding: '6px 8px',\n flexShrink: 0,\n }}\n >\n Data\n </TabsTrigger>\n <TabsTrigger\n value=\"actions\"\n style={{\n fontWeight: 'var(--font-weight-semibold)',\n fontSize: '12px',\n padding: '6px 8px',\n flexShrink: 0,\n }}\n >\n Actions\n </TabsTrigger>\n <TabsTrigger\n value=\"drilldown\"\n style={{\n fontWeight: 'var(--font-weight-semibold)',\n fontSize: '12px',\n padding: '6px 8px',\n flexShrink: 0,\n }}\n >\n Drilldown\n </TabsTrigger>\n <TabsTrigger\n value=\"webhooks\"\n style={{\n fontWeight: 'var(--font-weight-semibold)',\n fontSize: '12px',\n padding: '6px 8px',\n flexShrink: 0,\n }}\n >\n Hooks\n </TabsTrigger>\n <TabsTrigger\n value=\"events\"\n style={{\n fontWeight: 'var(--font-weight-semibold)',\n fontSize: '12px',\n padding: '6px 8px',\n flexShrink: 0,\n }}\n >\n Events\n </TabsTrigger>\n <TabsTrigger\n value=\"appearance\"\n style={{\n fontWeight: 'var(--font-weight-semibold)',\n fontSize: '12px',\n padding: '6px 8px',\n flexShrink: 0,\n }}\n >\n Style\n </TabsTrigger>\n </TabsList>\n\n <div style={{ flex: 1, overflow: 'auto', padding: 'var(--space-cardPadding)', minHeight: 0 }}>\n <TabsContent value=\"general\" className=\"mt-0\">\n {localForm && (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-formGap)' }}>\n {/* Title Field */}\n <div>\n <label\n htmlFor=\"title\"\n style={{\n display: 'block',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)',\n color: 'var(--color-text-primary)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n Title\n </label>\n <Input\n id=\"title\"\n value={localForm.title}\n onChange={(e) => updateLocalForm('title', e.target.value)}\n style={{ height: 'var(--size-controlHeight-md)', fontSize: 'var(--font-size-body-sm)' }}\n />\n </div>\n\n {/* Description Field */}\n <div>\n <label\n htmlFor=\"description\"\n style={{\n display: 'block',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)',\n color: 'var(--color-text-primary)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n Description\n </label>\n <Textarea\n id=\"description\"\n value={localForm.description}\n onChange={(e) => updateLocalForm('description', e.target.value)}\n rows={3}\n style={{ fontSize: 'var(--font-size-body-sm)', resize: 'none' }}\n />\n </div>\n\n {/* Auto-Refresh Field */}\n <div>\n <label\n htmlFor=\"refresh\"\n style={{\n display: 'block',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)',\n color: 'var(--color-text-primary)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n Auto-Refresh (seconds)\n </label>\n <Input\n id=\"refresh\"\n type=\"number\"\n value={localForm.refreshInterval || ''}\n onChange={(e) =>\n updateLocalForm('refreshInterval', e.target.value ? Number(e.target.value) : undefined)\n }\n min={0}\n placeholder=\"No auto-refresh\"\n style={{ height: 'var(--size-controlHeight-md)', fontSize: 'var(--font-size-body-sm)' }}\n />\n </div>\n\n {/* Renderer Field */}\n <div\n style={{\n paddingTop: 'var(--space-formGap)',\n borderTop: '1px solid var(--color-border)',\n }}\n >\n <label\n style={{\n display: 'block',\n fontSize: 'var(--font-size-body-sm)',\n fontWeight: 'var(--font-weight-semibold)',\n color: 'var(--color-text-primary)',\n marginBottom: 'var(--space-controlGap)',\n }}\n >\n Renderer\n </label>\n <Select\n value={localForm.renderer}\n onValueChange={(value) => {\n const newRenderer = value as RendererType;\n updateLocalForm('renderer', newRenderer);\n if (newRenderer === 'BIGCONSOLE') {\n updateLocalForm('template', undefined);\n }\n }}\n >\n <SelectTrigger\n style={{ height: 'var(--size-controlHeight-md)', fontSize: 'var(--font-size-body-sm)' }}\n >\n <SelectValue placeholder=\"Select renderer\" />\n </SelectTrigger>\n <SelectContent\n position=\"popper\"\n side=\"bottom\"\n sideOffset={4}\n align=\"start\"\n style={{\n zIndex: 9999,\n maxHeight: '200px',\n backgroundColor: 'var(--color-overlay-popoverBg, var(--color-bg-surface, #ffffff))',\n border: '1px solid var(--color-border)',\n boxShadow: 'var(--shadow-elevation-3)',\n borderRadius: 'var(--radius-button)',\n }}\n >\n {RENDERER_OPTIONS.map((opt) => (\n <SelectItem key={opt.value} value={opt.value}>\n {opt.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <p\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-text-muted)',\n marginTop: 'var(--space-controlGap)',\n }}\n >\n {RENDERER_OPTIONS.find((r) => r.value === localForm.renderer)?.description as React.ReactNode}\n </p>\n </div>\n\n {localForm.renderer && localForm.renderer !== 'BIGCONSOLE' && (\n <TemplateEditor\n widget={\n { ...selectedWidget, template: localForm.template, renderer: localForm.renderer } as Widget\n }\n onSave={(template) => updateLocalForm('template', template)}\n />\n )}\n </div>\n )}\n </TabsContent>\n\n <TabsContent value=\"data\" className=\"mt-0 space-y-4\">\n {localForm && (\n <>\n {/* Data Source Section */}\n <div className=\"space-y-4\">\n <div className=\"p-3 bg-muted rounded-md border border-border\">\n <p className=\"text-xs text-muted-foreground\">\n Connect this widget to a DataSink and Parser to display transformed data.\n </p>\n </div>\n\n {/* DataSink Selector */}\n <div className=\"space-y-2\">\n <Label>DataSink</Label>\n <DataSinkSelector\n value={selectedDataSinkKey}\n onChange={handleDataSinkChange}\n placeholder=\"Select a DataSink...\"\n />\n {selectedDataSinkKey && (\n <p className=\"text-xs text-muted-foreground\">\n Key: {selectedDataSinkKey}\n {localForm.dataSinkId && (\n <span className=\"ml-2 text-text-tertiary\">ID: {localForm.dataSinkId.slice(0, 8)}...</span>\n )}\n </p>\n )}\n </div>\n\n {/* Parser Selector - filtered by selected DataSink */}\n <div className=\"space-y-2\">\n <Label>Parser</Label>\n <ParserSelector\n consoleId={selectedWidget?.dashboardId || ''}\n value={localForm.parserId || null}\n onChange={handleParserChange}\n filterInputSinkKey={selectedDataSinkKey || undefined}\n filterStatus={undefined}\n placeholder={selectedDataSinkKey ? 'Select a parser...' : 'Select a DataSink first...'}\n disabled={!selectedDataSinkKey}\n />\n <p className=\"text-xs text-muted-foreground\">\n {isDetectingFields ? (\n <span className=\"flex items-center gap-1\">\n <Spinner style={{ width: '12px', height: '12px' }} />\n Auto-detecting field mappings...\n </span>\n ) : selectedDataSinkKey ? (\n 'Showing parsers that use this DataSink as input'\n ) : (\n 'Select a DataSink to see available parsers'\n )}\n </p>\n </div>\n\n {/* Auto-detected Field Mappings */}\n {!!(localForm.parserId && (localForm.config?.labelField || localForm.config?.valueField)) && (\n <div className=\"p-3 bg-green-50 dark:bg-green-950/30 rounded-md border border-green-200 dark:border-green-800\">\n <p className=\"text-xs font-medium text-green-700 dark:text-green-400 mb-2\">\n ✓ Field mappings configured\n </p>\n <div className=\"text-xs text-green-600 dark:text-green-500 space-y-1\">\n {!!localForm.config?.labelField && (\n <p>\n Label Field:{' '}\n <code className=\"bg-green-100 dark:bg-green-900 px-1 rounded\">\n {String(localForm.config.labelField)}\n </code>\n </p>\n )}\n {!!localForm.config?.valueField && (\n <p>\n Value Field:{' '}\n <code className=\"bg-green-100 dark:bg-green-900 px-1 rounded\">\n {String(localForm.config.valueField)}\n </code>\n </p>\n )}\n {!!localForm.config?.xAxisField && (\n <p>\n X-Axis Field:{' '}\n <code className=\"bg-green-100 dark:bg-green-900 px-1 rounded\">\n {String(localForm.config.xAxisField)}\n </code>\n </p>\n )}\n </div>\n </div>\n )}\n\n {/* Data Path (Optional) */}\n <div className=\"space-y-2\">\n <Label>Data Path (Optional)</Label>\n <Input\n value={(localForm.config?.dataPath as string) || ''}\n onChange={(e) =>\n updateLocalConfig({ ...localForm.config, dataPath: e.target.value || undefined })\n }\n placeholder=\"e.g., summary.totalRevenue\"\n />\n <p className=\"text-xs text-muted-foreground\">\n Path to extract specific data from the parser output (dot notation)\n </p>\n </div>\n </div>\n\n {/* Divider */}\n <div className=\"border-t border-border pt-4\">\n <Label className=\"text-xs text-muted-foreground uppercase tracking-wide\">\n Alternative Data Sources\n </Label>\n </div>\n\n {/* Data Source Type Selector */}\n <div className=\"space-y-2\">\n <Label>Data Source Type</Label>\n <Select\n value={(localForm.config?.dataSourceType as string) || ''}\n onValueChange={(value) =>\n updateLocalConfig({ ...localForm.config, dataSourceType: value || undefined })\n }\n >\n <SelectTrigger\n style={{ height: 'var(--size-controlHeight-md)', fontSize: 'var(--font-size-body-sm)' }}\n >\n <SelectValue placeholder=\"Select type...\" />\n </SelectTrigger>\n <SelectContent\n position=\"popper\"\n side=\"bottom\"\n sideOffset={4}\n align=\"start\"\n style={{\n zIndex: 9999,\n maxHeight: '200px',\n backgroundColor: 'var(--color-overlay-popoverBg, var(--color-bg-surface, #ffffff))',\n border: '1px solid var(--color-border)',\n boxShadow: 'var(--shadow-elevation-3)',\n borderRadius: 'var(--radius-button)',\n }}\n >\n {DATA_SOURCE_TYPES.map((type) => (\n <SelectItem key={type.value} value={type.value}>\n {type.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n\n {localForm.config?.dataSourceType === 'REST_API' && (\n <div className=\"space-y-3\">\n {/* Endpoint URL */}\n <div className=\"space-y-2\">\n <Label>Endpoint URL *</Label>\n <Input\n value={(localForm.config?.endpointUrl as string) || ''}\n onChange={(e) =>\n updateLocalConfig({ ...localForm.config, endpointUrl: e.target.value || undefined })\n }\n placeholder=\"https://api.example.com/data\"\n />\n </div>\n\n {/* HTTP Method */}\n <div className=\"space-y-2\">\n <Label>HTTP Method</Label>\n <Select\n value={(localForm.config?.httpMethod as string) || 'GET'}\n onValueChange={(value) => updateLocalConfig({ ...localForm.config, httpMethod: value })}\n >\n <SelectTrigger style={{ height: 'var(--size-controlHeight-md)' }}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent position=\"popper\" side=\"bottom\" sideOffset={4}>\n <SelectItem value=\"GET\">GET</SelectItem>\n <SelectItem value=\"POST\">POST</SelectItem>\n <SelectItem value=\"PUT\">PUT</SelectItem>\n <SelectItem value=\"DELETE\">DELETE</SelectItem>\n </SelectContent>\n </Select>\n </div>\n\n {/* Headers */}\n <div className=\"space-y-2\">\n <Label>Headers (JSON)</Label>\n <Textarea\n value={(localForm.config?.headers as string) || ''}\n onChange={(e) =>\n updateLocalConfig({ ...localForm.config, headers: e.target.value || undefined })\n }\n rows={3}\n placeholder='{\"Authorization\": \"Bearer token\", \"Content-Type\": \"application/json\"}'\n className=\"font-mono text-xs\"\n />\n </div>\n\n {/* Authentication Type */}\n <div className=\"space-y-2\">\n <Label>Authentication</Label>\n <Select\n value={(localForm.config?.authType as string) || 'none'}\n onValueChange={(value) => updateLocalConfig({ ...localForm.config, authType: value })}\n >\n <SelectTrigger style={{ height: 'var(--size-controlHeight-md)' }}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent position=\"popper\" side=\"bottom\" sideOffset={4}>\n <SelectItem value=\"none\">None</SelectItem>\n <SelectItem value=\"api_key\">API Key</SelectItem>\n <SelectItem value=\"bearer\">Bearer Token</SelectItem>\n <SelectItem value=\"basic\">Basic Auth</SelectItem>\n </SelectContent>\n </Select>\n </div>\n\n {/* Auth Value (conditional) */}\n {!!(localForm.config?.authType && localForm.config.authType !== 'none') && (\n <div className=\"space-y-2\">\n <Label>\n {String(localForm.config.authType) === 'basic' ? 'Credentials (user:pass)' : 'Token/Key'}\n </Label>\n <Input\n type=\"password\"\n value={(localForm.config?.authValue as string) || ''}\n onChange={(e) =>\n updateLocalConfig({ ...localForm.config, authValue: e.target.value || undefined })\n }\n placeholder={\n localForm.config.authType === 'basic' ? 'username:password' : 'Enter token or API key'\n }\n />\n </div>\n )}\n\n {/* Request Body (for POST/PUT) */}\n {(localForm.config?.httpMethod === 'POST' || localForm.config?.httpMethod === 'PUT') && (\n <div className=\"space-y-2\">\n <Label>Request Body (JSON)</Label>\n <Textarea\n value={(localForm.config?.requestBody as string) || ''}\n onChange={(e) =>\n updateLocalConfig({ ...localForm.config, requestBody: e.target.value || undefined })\n }\n rows={4}\n placeholder='{\"key\": \"value\"}'\n className=\"font-mono text-xs\"\n />\n </div>\n )}\n\n {/* Data Path */}\n <div className=\"space-y-2\">\n <Label>Data Path (optional)</Label>\n <Input\n value={(localForm.config?.dataPath as string) || ''}\n onChange={(e) =>\n updateLocalConfig({ ...localForm.config, dataPath: e.target.value || undefined })\n }\n placeholder=\"$.data.items or .data.items\"\n />\n <p className=\"text-xs text-muted-foreground\">\n JSONPath or dot notation to extract data from response\n </p>\n </div>\n </div>\n )}\n\n {localForm.config?.dataSourceType === 'GRAPHQL' && (\n <div className=\"space-y-3\">\n {/* GraphQL Endpoint */}\n <div className=\"space-y-2\">\n <Label>GraphQL Endpoint *</Label>\n <Input\n value={(localForm.config?.graphqlEndpoint as string) || ''}\n onChange={(e) =>\n updateLocalConfig({ ...localForm.config, graphqlEndpoint: e.target.value || undefined })\n }\n placeholder=\"https://api.example.com/graphql\"\n />\n </div>\n\n {/* GraphQL Query */}\n <div className=\"space-y-2\">\n <Label>Query *</Label>\n <Textarea\n value={(localForm.config?.graphqlQuery as string) || ''}\n onChange={(e) =>\n updateLocalConfig({ ...localForm.config, graphqlQuery: e.target.value || undefined })\n }\n rows={6}\n placeholder={`query GetData($limit: Int) {\n items(limit: $limit) {\n id\n name\n value\n }\n}`}\n className=\"font-mono text-xs\"\n />\n </div>\n\n {/* GraphQL Variables */}\n <div className=\"space-y-2\">\n <Label>Variables (JSON, optional)</Label>\n <Textarea\n value={(localForm.config?.graphqlVariables as string) || ''}\n onChange={(e) =>\n updateLocalConfig({ ...localForm.config, graphqlVariables: e.target.value || undefined })\n }\n rows={3}\n placeholder='{\"limit\": 10, \"offset\": 0}'\n className=\"font-mono text-xs\"\n />\n </div>\n\n {/* Headers */}\n <div className=\"space-y-2\">\n <Label>Headers (JSON, optional)</Label>\n <Textarea\n value={(localForm.config?.headers as string) || ''}\n onChange={(e) =>\n updateLocalConfig({ ...localForm.config, headers: e.target.value || undefined })\n }\n rows={2}\n placeholder='{\"Authorization\": \"Bearer token\"}'\n className=\"font-mono text-xs\"\n />\n </div>\n\n {/* Data Path */}\n <div className=\"space-y-2\">\n <Label>Data Path (optional)</Label>\n <Input\n value={(localForm.config?.dataPath as string) || ''}\n onChange={(e) =>\n updateLocalConfig({ ...localForm.config, dataPath: e.target.value || undefined })\n }\n placeholder=\".data.items\"\n />\n <p className=\"text-xs text-muted-foreground\">Path to extract data from GraphQL response</p>\n </div>\n </div>\n )}\n\n {localForm.config?.dataSourceType === 'MOCK' && (\n <div className=\"space-y-2\">\n <Label>Sample Data (JSON)</Label>\n <Textarea\n value={(localForm.config?.mockData as string) || ''}\n onChange={(e) =>\n updateLocalConfig({ ...localForm.config, mockData: e.target.value || undefined })\n }\n rows={5}\n placeholder='{\"value\": 100}'\n className=\"font-mono text-sm\"\n />\n </div>\n )}\n </>\n )}\n </TabsContent>\n\n <TabsContent value=\"actions\" className=\"mt-0 space-y-4\">\n <div className=\"flex items-center justify-between\">\n <div>\n <h3 className=\"text-sm font-medium\">Widget Actions</h3>\n <p className=\"text-xs text-muted-foreground\">Configure buttons on this widget</p>\n </div>\n <Button size=\"sm\" onClick={handleAddAction}>\n <Plus className=\"size-4\" />\n Add\n </Button>\n </div>\n\n {actionsLoading ? (\n <div className=\"flex justify-center py-8\">\n <Spinner className=\"size-6\" />\n </div>\n ) : actions.length === 0 ? (\n <div className=\"py-8 text-center\">\n <Info className=\"size-10 mx-auto mb-2 text-muted-foreground/50\" />\n <p className=\"text-sm text-muted-foreground\">No actions configured</p>\n </div>\n ) : (\n <div className=\"space-y-2\">\n {[...actions]\n .sort((a, b) => a.order - b.order)\n .map((action, index) => (\n <Card key={action.id} className={action.disabled ? 'opacity-60' : ''}>\n <CardContent className=\"p-3 flex items-center gap-2\">\n <div className=\"flex flex-col gap-0.5\">\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={() => handleMoveActionUp(index)}\n disabled={index === 0}\n className=\"h-5 w-5\"\n >\n <ChevronUp className=\"size-3\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={() => handleMoveActionDown(index)}\n disabled={index === actions.length - 1}\n className=\"h-5 w-5\"\n >\n <ChevronDown className=\"size-3\" />\n </Button>\n </div>\n\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span\n className={`size-2 rounded-full ${ACTION_STYLE_COLORS[action.style] || 'bg-muted-foreground'}`}\n />\n <span className=\"text-sm font-medium truncate\">{action.label}</span>\n </div>\n <p className=\"text-xs text-muted-foreground\">\n {action.name} • {action.type}\n </p>\n </div>\n\n <div className=\"flex gap-1\">\n <Button variant=\"ghost\" size=\"icon-sm\" onClick={() => handleEditAction(action)}>\n <Pencil className=\"size-4\" />\n </Button>\n <Button variant=\"ghost\" size=\"icon-sm\" onClick={() => handleDeleteAction(action.id)}>\n <Trash2 className=\"size-4\" />\n </Button>\n </div>\n </CardContent>\n </Card>\n ))}\n </div>\n )}\n </TabsContent>\n\n <TabsContent value=\"drilldown\" className=\"mt-0\">\n <DrilldownConfigPanel widget={selectedWidget} onChange={handleDrilldownChange} />\n </TabsContent>\n\n <TabsContent value=\"webhooks\" className=\"mt-0\">\n <WebhookConfigPanel dashboardId={selectedWidget.dashboardId} widgetId={selectedWidget.id} />\n </TabsContent>\n\n <TabsContent value=\"events\" className=\"mt-0\">\n <EventLogViewer\n dashboardId={selectedWidget.dashboardId}\n widgetId={selectedWidget.id}\n maxHeight=\"calc(100vh - 350px)\"\n />\n </TabsContent>\n\n <TabsContent value=\"appearance\" className=\"mt-0\">\n {ConfigComponent ? (\n <ConfigComponent\n config={((selectedWidget.config as Record<string, unknown>) || {}) as never}\n onChange={handleConfigChange as never}\n />\n ) : (\n <div className=\"p-4 bg-muted rounded-lg text-center\">\n <p className=\"text-sm text-muted-foreground\">No style options for this widget type</p>\n </div>\n )}\n </TabsContent>\n </div>\n </Tabs>\n ) : (\n <div className=\"flex-1 flex items-center justify-center p-4\">\n <div className=\"text-center\">\n <Info className=\"size-12 mx-auto mb-3 text-muted-foreground\" />\n <p className=\"text-sm text-muted-foreground\">Select a widget to edit</p>\n </div>\n </div>\n )}\n\n {/* Global Save/Discard Footer */}\n {selectedWidget && (\n <div\n style={{\n padding: 'var(--space-cardPadding)',\n borderTop: '1px solid var(--color-border)',\n backgroundColor: 'var(--color-bg-sunken)',\n flexShrink: 0,\n }}\n >\n {/* Status indicator */}\n {hasUnsavedChanges && (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-iconGap)',\n marginBottom: 'var(--space-controlGap)',\n padding: 'var(--space-controlGap)',\n backgroundColor: 'var(--color-status-warning-bgSubtle, rgba(251, 191, 36, 0.1))',\n borderRadius: 'var(--radius-button)',\n border: '1px solid var(--color-status-warning-border, rgba(251, 191, 36, 0.3))',\n }}\n >\n <div\n style={{\n width: '8px',\n height: '8px',\n borderRadius: '50%',\n backgroundColor: 'var(--color-status-warning-bg)',\n flexShrink: 0,\n }}\n />\n <span\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-status-warning-text, #92400e)',\n fontWeight: 'var(--font-weight-medium)',\n }}\n >\n You have unsaved changes\n </span>\n </div>\n )}\n\n {saveStatus === 'saved' && !hasUnsavedChanges && (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-iconGap)',\n marginBottom: 'var(--space-controlGap)',\n padding: 'var(--space-controlGap)',\n backgroundColor: 'var(--color-status-success-bgSubtle, rgba(34, 197, 94, 0.1))',\n borderRadius: 'var(--radius-button)',\n border: '1px solid var(--color-status-success-border, rgba(34, 197, 94, 0.3))',\n }}\n >\n <Check\n style={{\n width: 'var(--size-icon-sm)',\n height: 'var(--size-icon-sm)',\n color: 'var(--color-status-success-text)',\n flexShrink: 0,\n }}\n />\n <span\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-status-success-text)',\n fontWeight: 'var(--font-weight-medium)',\n }}\n >\n All changes saved\n </span>\n </div>\n )}\n\n {saveStatus === 'error' && (\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 'var(--space-iconGap)',\n marginBottom: 'var(--space-controlGap)',\n padding: 'var(--space-controlGap)',\n backgroundColor: 'var(--color-status-error-bgSubtle)',\n borderRadius: 'var(--radius-button)',\n border: '1px solid var(--color-status-error-border)',\n }}\n >\n <X\n style={{\n width: 'var(--size-icon-sm)',\n height: 'var(--size-icon-sm)',\n color: 'var(--color-status-error-text)',\n flexShrink: 0,\n }}\n />\n <span\n style={{\n fontSize: 'var(--font-size-body-sm)',\n color: 'var(--color-status-error-text)',\n fontWeight: 'var(--font-weight-medium)',\n }}\n >\n Failed to save changes\n </span>\n </div>\n )}\n\n {/* Action buttons */}\n <div style={{ display: 'flex', gap: 'var(--space-controlGap)' }}>\n <Button\n onClick={handleSaveAll}\n disabled={saveStatus === 'saving' || !hasUnsavedChanges}\n style={{\n flex: 1,\n height: 'var(--size-controlHeight-md)',\n backgroundColor: hasUnsavedChanges ? 'var(--color-action-primary-bg)' : undefined,\n opacity: hasUnsavedChanges ? 1 : 0.5,\n }}\n >\n {saveStatus === 'saving' ? (\n <span style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-iconGap)' }}>\n <Spinner style={{ width: 'var(--size-icon-sm)', height: 'var(--size-icon-sm)' }} />\n Saving...\n </span>\n ) : (\n <span style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-iconGap)' }}>\n <Check style={{ width: 'var(--size-icon-sm)', height: 'var(--size-icon-sm)' }} />\n Save Changes\n </span>\n )}\n </Button>\n <Button\n variant=\"outline\"\n onClick={handleDiscardAll}\n disabled={saveStatus === 'saving' || !hasUnsavedChanges}\n style={{\n height: 'var(--size-controlHeight-md)',\n opacity: hasUnsavedChanges ? 1 : 0.5,\n }}\n >\n <X style={{ width: 'var(--size-icon-sm)', height: 'var(--size-icon-sm)' }} />\n Discard\n </Button>\n </div>\n </div>\n )}\n\n <ActionConfigDialog\n isOpen={isActionDialogOpen}\n action={editingAction}\n isLoading={actionSaving}\n onClose={() => {\n setIsActionDialogOpen(false);\n setEditingAction(undefined);\n }}\n onSave={handleSaveAction}\n />\n </SheetContent>\n </Sheet>\n );\n});\n\nexport default PropertiesPanel;\n"],"mappings":"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"}
|