@timeax/service-builder 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +19 -2
- package/dist/index.js +1778 -519
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -4750,7 +4750,8 @@ import { LuTags as LuTags2 } from "react-icons/lu";
|
|
|
4750
4750
|
import { MdOutlineRadioButtonChecked as MdOutlineRadioButtonChecked2 } from "react-icons/md";
|
|
4751
4751
|
import { RxInput as RxInput2 } from "react-icons/rx";
|
|
4752
4752
|
import { Fragment as Fragment5, jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
4753
|
-
var
|
|
4753
|
+
var SELECTED_NODE_RING_CLASS = "ring-2 ring-sky-300 shadow-lg shadow-sky-300/20 dark:ring-sky-400";
|
|
4754
|
+
var ACTIVE_NODE_OUTLINE_CLASS = "outline-2 outline-solid outline-emerald-500 dark:outline-emerald-400";
|
|
4754
4755
|
var HIGHLIGHT_NODE_OUTLINE_CLASS = "outline-2 outline-solid outline-amber-300 dark:outline-amber-200";
|
|
4755
4756
|
function NodeShell({
|
|
4756
4757
|
label,
|
|
@@ -4782,7 +4783,7 @@ function NodeShell({
|
|
|
4782
4783
|
isManualHighlighted ? "manual-highlighted" : "",
|
|
4783
4784
|
focusDimLevel && focusDimLevel !== "none" ? `dim-${focusDimLevel}` : ""
|
|
4784
4785
|
].filter(Boolean).join(" "),
|
|
4785
|
-
className: "group relative min-w-44 rounded-lg bg-white p-3 ring-1 ring-slate-200 shadow-[0_4px_12px_rgba(0,0,0,0.05)] transition-all duration-200 dark:bg-slate-900 dark:ring-slate-700 " + (selected ? `${
|
|
4786
|
+
className: "group relative min-w-44 rounded-lg bg-white p-3 ring-1 ring-slate-200 shadow-[0_4px_12px_rgba(0,0,0,0.05)] transition-all duration-200 dark:bg-slate-900 dark:ring-slate-700 " + (selected ? `${SELECTED_NODE_RING_CLASS} ` : "hover:shadow-lg ") + (isActiveNode ? `${ACTIVE_NODE_OUTLINE_CLASS} ` : "") + (isCurrentTag ? "ring-2 ring-emerald-500 bg-emerald-50/70 shadow-lg shadow-emerald-500/25 dark:bg-emerald-500/10 " : "") + (isVisibleGroupField ? "ring-2 ring-emerald-300 bg-emerald-50/35 dark:bg-emerald-500/5 " : "") + (isRelatedTag ? "ring-1 ring-teal-300 bg-teal-50/25 dark:bg-teal-500/8 " : "") + (isManualHighlighted ? `${HIGHLIGHT_NODE_OUTLINE_CLASS} ` : "") + (draggingService && canAssignService2 ? "border border-dashed border-emerald-400 " : "") + (!canAssignService2 && draggingService ? "opacity-70 " : "") + dimClass,
|
|
4786
4787
|
onDragOver: (event) => {
|
|
4787
4788
|
if (!canAcceptDropPayload?.(event.dataTransfer)) return;
|
|
4788
4789
|
event.preventDefault();
|
|
@@ -4879,7 +4880,7 @@ function OptionNode(props) {
|
|
|
4879
4880
|
props.data.isManualHighlighted ? "manual-highlighted" : "",
|
|
4880
4881
|
props.data.focusDimLevel && props.data.focusDimLevel !== "none" ? `dim-${props.data.focusDimLevel}` : ""
|
|
4881
4882
|
].filter(Boolean).join(" "),
|
|
4882
|
-
className: "relative rounded-full border px-4 py-1.5 text-sm bg-white text-slate-800 transition dark:bg-slate-900 dark:text-slate-200 " + (props.selected ?
|
|
4883
|
+
className: "relative rounded-full border px-4 py-1.5 text-sm bg-white text-slate-800 transition dark:bg-slate-900 dark:text-slate-200 " + (props.selected ? `border-sky-300 bg-sky-50 text-sky-700 dark:bg-sky-500/15 dark:border-sky-400 ${SELECTED_NODE_RING_CLASS} ` : "border-slate-300 dark:border-slate-700 ") + (props.data.isActiveNode ? `${ACTIVE_NODE_OUTLINE_CLASS} ` : "") + (props.data.isCurrentTag ? "ring-2 ring-emerald-500 bg-emerald-50/70 dark:bg-emerald-500/10 " : "") + (props.data.isVisibleGroupField ? "ring-2 ring-emerald-300 bg-emerald-50/35 dark:bg-emerald-500/5 " : "") + (props.data.isRelatedTag ? "ring-1 ring-teal-300 bg-teal-50/25 dark:bg-teal-500/8 " : "") + (props.data.isManualHighlighted ? `${HIGHLIGHT_NODE_OUTLINE_CLASS} ` : "") + (props.data.focusDimLevel === "soft" ? "opacity-80 " : props.data.focusDimLevel === "medium" ? "opacity-[0.55] " : props.data.focusDimLevel === "strong" ? "opacity-35 " : ""),
|
|
4883
4884
|
onDragOver: (event) => {
|
|
4884
4885
|
if (!props.data.canAcceptDropPayload?.(event.dataTransfer)) return;
|
|
4885
4886
|
event.preventDefault();
|
|
@@ -4909,7 +4910,7 @@ function CommentNode(props) {
|
|
|
4909
4910
|
return /* @__PURE__ */ jsxs12(
|
|
4910
4911
|
"div",
|
|
4911
4912
|
{
|
|
4912
|
-
className: "h-48 w-64 rounded-lg border border-[#E0E0E0] bg-[#FEFBEA] shadow-md transition-all hover:shadow-lg dark:border-[#555] dark:bg-[#4a4a38] " + (props.selected ? `${
|
|
4913
|
+
className: "h-48 w-64 rounded-lg border border-[#E0E0E0] bg-[#FEFBEA] shadow-md transition-all hover:shadow-lg dark:border-[#555] dark:bg-[#4a4a38] " + (props.selected ? `${SELECTED_NODE_RING_CLASS} ` : ""),
|
|
4913
4914
|
children: [
|
|
4914
4915
|
/* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2 border-b border-[#E0E0E0]/70 px-3 py-2 text-xs font-medium text-slate-600 dark:border-[#555] dark:text-slate-300", children: [
|
|
4915
4916
|
/* @__PURE__ */ jsx16(BsChatSquareQuote2, {}),
|
|
@@ -14395,9 +14396,14 @@ var wireframe_tags_widget_default = WireframeTagsWidget;
|
|
|
14395
14396
|
// src/panels/right/tabs/wireframe.tsx
|
|
14396
14397
|
import { useOrderFlow, Wrapper } from "@timeax/digital-service-engine/react";
|
|
14397
14398
|
import { useCanvas as useCanvas16, useWorkspace as useWorkspace14 } from "@timeax/digital-service-engine/workspace";
|
|
14398
|
-
import { useCallback as useCallback19, useMemo as useMemo33 } from "react";
|
|
14399
|
+
import { useCallback as useCallback19, useMemo as useMemo33, useState as useState33 } from "react";
|
|
14400
|
+
import { BsChevronDown as BsChevronDown2 } from "react-icons/bs";
|
|
14399
14401
|
import { jsx as jsx71, jsxs as jsxs51 } from "react/jsx-runtime";
|
|
14400
14402
|
var CHECKBOX_SINGLE_EXTRA_PROPS = Object.freeze({ single: true });
|
|
14403
|
+
function formatMetricNumber(value) {
|
|
14404
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return "--";
|
|
14405
|
+
return new Intl.NumberFormat("en-US", { maximumFractionDigits: 4 }).format(value);
|
|
14406
|
+
}
|
|
14401
14407
|
function Wireframe() {
|
|
14402
14408
|
const canvas = useCanvas16();
|
|
14403
14409
|
const ws = useWorkspace14();
|
|
@@ -14406,7 +14412,109 @@ function Wireframe() {
|
|
|
14406
14412
|
const previewFields = useMemo33(() => getVisiblePreviewFields(canvas, currentTag?.id), [canvas.props, canvas.selectionInfo, canvas.activeId]);
|
|
14407
14413
|
const selectedOptionsCount = canvas.selectionInfo.optionIds.length;
|
|
14408
14414
|
const flow = useOrderFlow();
|
|
14409
|
-
const
|
|
14415
|
+
const [isFooterOpen, setIsFooterOpen] = useState33(true);
|
|
14416
|
+
const footerSummary = useMemo33(() => {
|
|
14417
|
+
const minText = formatMetricNumber(flow.min);
|
|
14418
|
+
const maxText = formatMetricNumber(flow.max);
|
|
14419
|
+
const rangeText = minText === "--" && maxText === "--" ? "--" : `${minText} - ${maxText}`;
|
|
14420
|
+
return [
|
|
14421
|
+
{ label: "Tag", value: currentTag?.raw.label ?? "No active tag" },
|
|
14422
|
+
{ label: "Visible fields", value: String(previewFields.length) },
|
|
14423
|
+
{ label: "Selected options", value: String(selectedOptionsCount) },
|
|
14424
|
+
{ label: "Quantity", value: formatMetricNumber(flow.quantityPreview) },
|
|
14425
|
+
{ label: "Min/Max", value: rangeText },
|
|
14426
|
+
{ label: "Services", value: String(flow.services.length), detailsKind: "services" },
|
|
14427
|
+
{ label: "Base", value: formatMetricNumber(flow.pricingPreview?.base), detailsKind: "pricing" },
|
|
14428
|
+
{ label: "Utilities", value: formatMetricNumber(flow.pricingPreview?.utilities), detailsKind: "pricing" },
|
|
14429
|
+
{ label: "Total", value: formatMetricNumber(flow.pricingPreview?.total), detailsKind: "pricing" },
|
|
14430
|
+
{ label: "Utility lines", value: String(flow.pricingPreview?.utilityBreakdown?.length ?? 0), detailsKind: "utility_lines" }
|
|
14431
|
+
];
|
|
14432
|
+
}, [
|
|
14433
|
+
currentTag?.raw.label,
|
|
14434
|
+
flow.max,
|
|
14435
|
+
flow.min,
|
|
14436
|
+
flow.pricingPreview?.base,
|
|
14437
|
+
flow.pricingPreview?.total,
|
|
14438
|
+
flow.pricingPreview?.utilities,
|
|
14439
|
+
flow.pricingPreview?.utilityBreakdown?.length,
|
|
14440
|
+
flow.quantityPreview,
|
|
14441
|
+
flow.services.length,
|
|
14442
|
+
previewFields.length,
|
|
14443
|
+
selectedOptionsCount
|
|
14444
|
+
]);
|
|
14445
|
+
const serviceDetails = useMemo33(() => {
|
|
14446
|
+
const servicesMap = ws.services.data ?? {};
|
|
14447
|
+
return flow.services.map((serviceId) => {
|
|
14448
|
+
const service = servicesMap[String(serviceId)];
|
|
14449
|
+
return {
|
|
14450
|
+
id: serviceId,
|
|
14451
|
+
name: service?.name ?? `Service ${String(serviceId)}`,
|
|
14452
|
+
rate: service?.rate,
|
|
14453
|
+
min: service?.min,
|
|
14454
|
+
max: service?.max
|
|
14455
|
+
};
|
|
14456
|
+
});
|
|
14457
|
+
}, [flow.services, ws.services.data]);
|
|
14458
|
+
const renderPillDetails = useCallback19(
|
|
14459
|
+
(kind) => {
|
|
14460
|
+
if (kind === "services") {
|
|
14461
|
+
return /* @__PURE__ */ jsxs51("div", { className: "space-y-2", children: [
|
|
14462
|
+
/* @__PURE__ */ jsx71("p", { className: "text-xs font-semibold text-slate-700 dark:text-slate-200", children: "Visible Services" }),
|
|
14463
|
+
serviceDetails.length ? /* @__PURE__ */ jsx71("div", { className: "max-h-56 space-y-2 overflow-auto pr-1", children: serviceDetails.map((service) => /* @__PURE__ */ jsxs51("div", { className: "rounded-md border border-slate-200 bg-slate-50 px-2 py-1.5 text-xs dark:border-slate-700 dark:bg-slate-900", children: [
|
|
14464
|
+
/* @__PURE__ */ jsx71("p", { className: "font-medium text-slate-700 dark:text-slate-200", children: service.name }),
|
|
14465
|
+
/* @__PURE__ */ jsxs51("p", { className: "text-slate-500 dark:text-slate-400", children: [
|
|
14466
|
+
"ID: ",
|
|
14467
|
+
String(service.id)
|
|
14468
|
+
] }),
|
|
14469
|
+
/* @__PURE__ */ jsxs51("p", { className: "text-slate-500 dark:text-slate-400", children: [
|
|
14470
|
+
"Rate: ",
|
|
14471
|
+
formatMetricNumber(service.rate),
|
|
14472
|
+
" \xB7 Min/Max: ",
|
|
14473
|
+
formatMetricNumber(service.min),
|
|
14474
|
+
" - ",
|
|
14475
|
+
formatMetricNumber(service.max)
|
|
14476
|
+
] })
|
|
14477
|
+
] }, String(service.id))) }) : /* @__PURE__ */ jsx71("p", { className: "text-xs text-slate-500 dark:text-slate-400", children: "No services are currently active for this selection." })
|
|
14478
|
+
] });
|
|
14479
|
+
}
|
|
14480
|
+
if (kind === "utility_lines") {
|
|
14481
|
+
const lines = flow.pricingPreview?.utilityBreakdown ?? [];
|
|
14482
|
+
return /* @__PURE__ */ jsxs51("div", { className: "space-y-2", children: [
|
|
14483
|
+
/* @__PURE__ */ jsx71("p", { className: "text-xs font-semibold text-slate-700 dark:text-slate-200", children: "Utility Breakdown" }),
|
|
14484
|
+
lines.length ? /* @__PURE__ */ jsx71("div", { className: "max-h-56 space-y-2 overflow-auto pr-1", children: lines.map((line, index) => /* @__PURE__ */ jsxs51("div", { className: "rounded-md border border-slate-200 bg-slate-50 px-2 py-1.5 text-xs dark:border-slate-700 dark:bg-slate-900", children: [
|
|
14485
|
+
/* @__PURE__ */ jsxs51("p", { className: "font-medium text-slate-700 dark:text-slate-200", children: [
|
|
14486
|
+
"Node: ",
|
|
14487
|
+
line.nodeId
|
|
14488
|
+
] }),
|
|
14489
|
+
/* @__PURE__ */ jsxs51("p", { className: "text-slate-500 dark:text-slate-400", children: [
|
|
14490
|
+
"Mode: ",
|
|
14491
|
+
line.mode
|
|
14492
|
+
] }),
|
|
14493
|
+
/* @__PURE__ */ jsxs51("p", { className: "text-slate-500 dark:text-slate-400", children: [
|
|
14494
|
+
"Amount: ",
|
|
14495
|
+
formatMetricNumber(line.amount)
|
|
14496
|
+
] })
|
|
14497
|
+
] }, `${line.nodeId}:${index}`)) }) : /* @__PURE__ */ jsx71("p", { className: "text-xs text-slate-500 dark:text-slate-400", children: "No utility line items in the current preview." })
|
|
14498
|
+
] });
|
|
14499
|
+
}
|
|
14500
|
+
return /* @__PURE__ */ jsxs51("div", { className: "space-y-1 text-xs", children: [
|
|
14501
|
+
/* @__PURE__ */ jsx71("p", { className: "font-semibold text-slate-700 dark:text-slate-200", children: "Pricing Summary" }),
|
|
14502
|
+
/* @__PURE__ */ jsxs51("p", { className: "text-slate-500 dark:text-slate-400", children: [
|
|
14503
|
+
"Base: ",
|
|
14504
|
+
formatMetricNumber(flow.pricingPreview?.base)
|
|
14505
|
+
] }),
|
|
14506
|
+
/* @__PURE__ */ jsxs51("p", { className: "text-slate-500 dark:text-slate-400", children: [
|
|
14507
|
+
"Utilities: ",
|
|
14508
|
+
formatMetricNumber(flow.pricingPreview?.utilities)
|
|
14509
|
+
] }),
|
|
14510
|
+
/* @__PURE__ */ jsxs51("p", { className: "text-slate-500 dark:text-slate-400", children: [
|
|
14511
|
+
"Total: ",
|
|
14512
|
+
formatMetricNumber(flow.pricingPreview?.total)
|
|
14513
|
+
] })
|
|
14514
|
+
] });
|
|
14515
|
+
},
|
|
14516
|
+
[flow.pricingPreview?.base, flow.pricingPreview?.total, flow.pricingPreview?.utilities, flow.pricingPreview?.utilityBreakdown, serviceDetails]
|
|
14517
|
+
);
|
|
14410
14518
|
const { visibleTag, parents, children, visibleFields } = useMemo33(() => {
|
|
14411
14519
|
const result = canvas.api.selection.visibleGroup();
|
|
14412
14520
|
const notices = canvas.api.builder.getProps().notices;
|
|
@@ -14552,7 +14660,44 @@ function Wireframe() {
|
|
|
14552
14660
|
}
|
|
14553
14661
|
) })
|
|
14554
14662
|
] }) }) }),
|
|
14555
|
-
/* @__PURE__ */
|
|
14663
|
+
/* @__PURE__ */ jsxs51("div", { className: "mt-auto border-t border-slate-200 px-4 py-2 text-xs text-slate-600 dark:border-slate-800 dark:text-slate-300", children: [
|
|
14664
|
+
/* @__PURE__ */ jsxs51(
|
|
14665
|
+
"button",
|
|
14666
|
+
{
|
|
14667
|
+
type: "button",
|
|
14668
|
+
className: "flex w-full items-center justify-between rounded-md px-1 py-1 text-left hover:bg-slate-100/70 dark:hover:bg-slate-900/80",
|
|
14669
|
+
onClick: () => setIsFooterOpen((prev) => !prev),
|
|
14670
|
+
"aria-expanded": isFooterOpen,
|
|
14671
|
+
"aria-controls": "wireframe-footer-summary",
|
|
14672
|
+
children: [
|
|
14673
|
+
/* @__PURE__ */ jsx71("span", { className: "font-medium", children: "Order preview summary" }),
|
|
14674
|
+
/* @__PURE__ */ jsx71(BsChevronDown2, { className: `transition-transform ${isFooterOpen ? "rotate-180" : "rotate-0"}` })
|
|
14675
|
+
]
|
|
14676
|
+
}
|
|
14677
|
+
),
|
|
14678
|
+
isFooterOpen ? /* @__PURE__ */ jsx71("div", { id: "wireframe-footer-summary", className: "mt-2 flex flex-wrap gap-2", children: footerSummary.map((item) => {
|
|
14679
|
+
const chip = /* @__PURE__ */ jsxs51("span", { className: "inline-flex items-center gap-1 rounded-md border border-slate-200 bg-slate-50 px-2 py-1 dark:border-slate-700 dark:bg-slate-900", children: [
|
|
14680
|
+
/* @__PURE__ */ jsxs51("span", { className: "text-slate-500 dark:text-slate-400", children: [
|
|
14681
|
+
item.label,
|
|
14682
|
+
":"
|
|
14683
|
+
] }),
|
|
14684
|
+
/* @__PURE__ */ jsx71("span", { className: "font-medium text-slate-700 dark:text-slate-200", children: item.value })
|
|
14685
|
+
] });
|
|
14686
|
+
if (!item.detailsKind) return /* @__PURE__ */ jsx71("div", { children: chip }, item.label);
|
|
14687
|
+
return /* @__PURE__ */ jsxs51(Popover, { children: [
|
|
14688
|
+
/* @__PURE__ */ jsx71(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx71(
|
|
14689
|
+
"button",
|
|
14690
|
+
{
|
|
14691
|
+
type: "button",
|
|
14692
|
+
className: "rounded-md transition-transform hover:scale-[1.01] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sky-500/50",
|
|
14693
|
+
"aria-label": `${item.label} details`,
|
|
14694
|
+
children: chip
|
|
14695
|
+
}
|
|
14696
|
+
) }),
|
|
14697
|
+
/* @__PURE__ */ jsx71(PopoverContent, { align: "start", side: "top", sideOffset: 8, collisionPadding: 12, className: "w-80 rounded-xl p-3", children: renderPillDetails(item.detailsKind) })
|
|
14698
|
+
] }, item.label);
|
|
14699
|
+
}) }) : null
|
|
14700
|
+
] })
|
|
14556
14701
|
] });
|
|
14557
14702
|
}
|
|
14558
14703
|
var wireframe_default = Wireframe;
|
|
@@ -14595,17 +14740,1172 @@ var RightPanel = ({ onShare, onPlay }) => {
|
|
|
14595
14740
|
};
|
|
14596
14741
|
var right_default = RightPanel;
|
|
14597
14742
|
|
|
14743
|
+
// src/components/ui/resizable.tsx
|
|
14744
|
+
import { GripVertical } from "lucide-react";
|
|
14745
|
+
import "react";
|
|
14746
|
+
import { Group as Group2, Panel as Panel3, Separator as Separator3 } from "react-resizable-panels";
|
|
14747
|
+
import { jsx as jsx73 } from "react/jsx-runtime";
|
|
14748
|
+
function ResizablePanelGroup({
|
|
14749
|
+
className,
|
|
14750
|
+
direction = "horizontal",
|
|
14751
|
+
...props
|
|
14752
|
+
}) {
|
|
14753
|
+
return /* @__PURE__ */ jsx73(Group2, { className: cn("flex h-full w-full data-[group-orientation=vertical]:flex-col", className), orientation: direction, ...props });
|
|
14754
|
+
}
|
|
14755
|
+
function ResizablePanel({
|
|
14756
|
+
className,
|
|
14757
|
+
...props
|
|
14758
|
+
}) {
|
|
14759
|
+
return /* @__PURE__ */ jsx73(Panel3, { className: cn("min-h-0 min-w-0", className), ...props });
|
|
14760
|
+
}
|
|
14761
|
+
function ResizableHandle({
|
|
14762
|
+
withHandle,
|
|
14763
|
+
className,
|
|
14764
|
+
...props
|
|
14765
|
+
}) {
|
|
14766
|
+
return /* @__PURE__ */ jsx73(
|
|
14767
|
+
Separator3,
|
|
14768
|
+
{
|
|
14769
|
+
className: cn(
|
|
14770
|
+
"relative flex w-3 shrink-0 items-center justify-center bg-transparent outline-none transition-colors after:absolute after:inset-y-3 after:left-1/2 after:w-px after:-translate-x-1/2 after:rounded-full after:bg-slate-200 dark:after:bg-slate-800",
|
|
14771
|
+
"hover:after:bg-slate-300 dark:hover:after:bg-slate-700",
|
|
14772
|
+
className
|
|
14773
|
+
),
|
|
14774
|
+
...props,
|
|
14775
|
+
children: withHandle ? /* @__PURE__ */ jsx73("div", { className: "z-10 flex h-10 w-3 items-center justify-center rounded-md border border-slate-200 bg-white text-slate-400 shadow-sm dark:border-slate-800 dark:bg-slate-950 dark:text-slate-500", children: /* @__PURE__ */ jsx73(GripVertical, { className: "h-3.5 w-3.5" }) }) : null
|
|
14776
|
+
}
|
|
14777
|
+
);
|
|
14778
|
+
}
|
|
14779
|
+
|
|
14780
|
+
// src/workspace/fallback-editor/native-fallback-editor.tsx
|
|
14781
|
+
import { FallbackEditorProvider, useActiveFallbackRegistrations as useActiveFallbackRegistrations4, useFallbackEditor as useFallbackEditor6, usePrimaryServiceList as usePrimaryServiceList3 } from "@timeax/digital-service-engine/react";
|
|
14782
|
+
import { useMemo as useMemo37 } from "react";
|
|
14783
|
+
|
|
14784
|
+
// src/workspace/fallback-editor/fallback-details-panel.tsx
|
|
14785
|
+
import { useActiveFallbackRegistrations, useFallbackEditor, usePrimaryServiceList } from "@timeax/digital-service-engine/react";
|
|
14786
|
+
import { useMemo as useMemo34 } from "react";
|
|
14787
|
+
|
|
14788
|
+
// src/workspace/fallback-editor/shared.tsx
|
|
14789
|
+
import { X } from "lucide-react";
|
|
14790
|
+
import { jsx as jsx74, jsxs as jsxs53 } from "react/jsx-runtime";
|
|
14791
|
+
var surfaceClassName = "rounded-md border border-slate-200/80 bg-white/95 shadow-sm backdrop-blur dark:border-slate-800 dark:bg-slate-950/85";
|
|
14792
|
+
function SectionCard({
|
|
14793
|
+
className,
|
|
14794
|
+
children
|
|
14795
|
+
}) {
|
|
14796
|
+
return /* @__PURE__ */ jsx74("section", { className: cn(surfaceClassName, className), children });
|
|
14797
|
+
}
|
|
14798
|
+
function SectionHeader2({
|
|
14799
|
+
title,
|
|
14800
|
+
description,
|
|
14801
|
+
action,
|
|
14802
|
+
className
|
|
14803
|
+
}) {
|
|
14804
|
+
return /* @__PURE__ */ jsxs53("div", { className: cn("flex items-start justify-between gap-3", className), children: [
|
|
14805
|
+
/* @__PURE__ */ jsxs53("div", { className: "min-w-0", children: [
|
|
14806
|
+
/* @__PURE__ */ jsx74("h3", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: title }),
|
|
14807
|
+
description ? /* @__PURE__ */ jsx74("p", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: description }) : null
|
|
14808
|
+
] }),
|
|
14809
|
+
action ? /* @__PURE__ */ jsx74("div", { className: "shrink-0", children: action }) : null
|
|
14810
|
+
] });
|
|
14811
|
+
}
|
|
14812
|
+
function EmptyState2({
|
|
14813
|
+
title,
|
|
14814
|
+
description,
|
|
14815
|
+
className
|
|
14816
|
+
}) {
|
|
14817
|
+
return /* @__PURE__ */ jsxs53(
|
|
14818
|
+
"div",
|
|
14819
|
+
{
|
|
14820
|
+
className: cn(
|
|
14821
|
+
"flex min-h-40 flex-col items-center justify-center rounded-md border border-dashed border-slate-300 bg-slate-50/80 px-5 py-8 text-center dark:border-slate-700 dark:bg-slate-900/40",
|
|
14822
|
+
className
|
|
14823
|
+
),
|
|
14824
|
+
children: [
|
|
14825
|
+
/* @__PURE__ */ jsx74("h4", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: title }),
|
|
14826
|
+
/* @__PURE__ */ jsx74("p", { className: "mt-2 max-w-sm text-sm text-slate-500 dark:text-slate-400", children: description })
|
|
14827
|
+
]
|
|
14828
|
+
}
|
|
14829
|
+
);
|
|
14830
|
+
}
|
|
14831
|
+
function DetailRow({
|
|
14832
|
+
label,
|
|
14833
|
+
value,
|
|
14834
|
+
className
|
|
14835
|
+
}) {
|
|
14836
|
+
return /* @__PURE__ */ jsxs53("div", { className: cn("flex items-start justify-between gap-3 rounded-md bg-slate-50 px-3 py-2 dark:bg-slate-900/70", className), children: [
|
|
14837
|
+
/* @__PURE__ */ jsx74("span", { className: "text-sm text-slate-500 dark:text-slate-400", children: label }),
|
|
14838
|
+
/* @__PURE__ */ jsx74("span", { className: "text-right text-sm font-medium text-slate-900 dark:text-slate-100", children: value })
|
|
14839
|
+
] });
|
|
14840
|
+
}
|
|
14841
|
+
function ToneBadge({
|
|
14842
|
+
label,
|
|
14843
|
+
tone = "neutral",
|
|
14844
|
+
className
|
|
14845
|
+
}) {
|
|
14846
|
+
const palette = tone === "info" ? "border-sky-200 bg-sky-50 text-sky-700 dark:border-sky-500/30 dark:bg-sky-500/10 dark:text-sky-200" : tone === "success" ? "border-emerald-200 bg-emerald-50 text-emerald-700 dark:border-emerald-500/30 dark:bg-emerald-500/10 dark:text-emerald-200" : tone === "warning" ? "border-amber-200 bg-amber-50 text-amber-700 dark:border-amber-500/30 dark:bg-amber-500/10 dark:text-amber-200" : tone === "danger" ? "border-rose-200 bg-rose-50 text-rose-700 dark:border-rose-500/30 dark:bg-rose-500/10 dark:text-rose-200" : "border-slate-200 bg-white text-slate-600 dark:border-slate-700 dark:bg-slate-950 dark:text-slate-300";
|
|
14847
|
+
return /* @__PURE__ */ jsx74("span", { className: cn("inline-flex rounded-md border px-2.5 py-1 text-[11px] font-medium", palette, className), children: label });
|
|
14848
|
+
}
|
|
14849
|
+
function ModalShell({
|
|
14850
|
+
open,
|
|
14851
|
+
title,
|
|
14852
|
+
description,
|
|
14853
|
+
onClose,
|
|
14854
|
+
children,
|
|
14855
|
+
footer,
|
|
14856
|
+
size = "default"
|
|
14857
|
+
}) {
|
|
14858
|
+
if (!open) return null;
|
|
14859
|
+
return /* @__PURE__ */ jsx74(
|
|
14860
|
+
"div",
|
|
14861
|
+
{
|
|
14862
|
+
className: "fixed inset-0 z-[60] flex items-center justify-center bg-slate-950/65 p-4 backdrop-blur-sm",
|
|
14863
|
+
onMouseDown: (event) => {
|
|
14864
|
+
if (event.target === event.currentTarget) onClose();
|
|
14865
|
+
},
|
|
14866
|
+
children: /* @__PURE__ */ jsxs53(
|
|
14867
|
+
"div",
|
|
14868
|
+
{
|
|
14869
|
+
className: cn(
|
|
14870
|
+
"flex max-h-[85vh] w-full flex-col overflow-hidden rounded-md border border-slate-200 bg-white shadow-2xl dark:border-slate-800 dark:bg-slate-950",
|
|
14871
|
+
size === "wide" ? "max-w-4xl" : "max-w-xl"
|
|
14872
|
+
),
|
|
14873
|
+
onMouseDown: (event) => event.stopPropagation(),
|
|
14874
|
+
children: [
|
|
14875
|
+
/* @__PURE__ */ jsxs53("div", { className: "flex items-start justify-between gap-4 border-b border-slate-200 px-6 py-4 dark:border-slate-800", children: [
|
|
14876
|
+
/* @__PURE__ */ jsxs53("div", { className: "min-w-0", children: [
|
|
14877
|
+
/* @__PURE__ */ jsx74("h3", { className: "text-base font-semibold text-slate-900 dark:text-slate-100", children: title }),
|
|
14878
|
+
description ? /* @__PURE__ */ jsx74("p", { className: "mt-1 text-sm text-slate-500 dark:text-slate-400", children: description }) : null
|
|
14879
|
+
] }),
|
|
14880
|
+
/* @__PURE__ */ jsx74(Button, { type: "button", variant: "ghost", size: "icon-sm", onClick: onClose, className: "rounded-md", children: /* @__PURE__ */ jsx74(X, { className: "size-4" }) })
|
|
14881
|
+
] }),
|
|
14882
|
+
/* @__PURE__ */ jsx74(ScrollArea, { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsx74("div", { className: "p-6", children }) }),
|
|
14883
|
+
footer ? /* @__PURE__ */ jsx74("div", { className: "border-t border-slate-200 px-6 py-4 dark:border-slate-800", children: footer }) : null
|
|
14884
|
+
]
|
|
14885
|
+
}
|
|
14886
|
+
)
|
|
14887
|
+
}
|
|
14888
|
+
);
|
|
14889
|
+
}
|
|
14890
|
+
|
|
14891
|
+
// src/workspace/fallback-editor/fallback-details-panel.tsx
|
|
14892
|
+
import { jsx as jsx75, jsxs as jsxs54 } from "react/jsx-runtime";
|
|
14893
|
+
function FallbackDetailsPanel() {
|
|
14894
|
+
const { activeServiceId, state, settings, check } = useFallbackEditor();
|
|
14895
|
+
const services2 = usePrimaryServiceList();
|
|
14896
|
+
const registrations = useActiveFallbackRegistrations();
|
|
14897
|
+
const service = useMemo34(() => services2.find((entry) => String(entry.id) === String(activeServiceId)), [services2, activeServiceId]);
|
|
14898
|
+
const diagnostics = useMemo34(() => {
|
|
14899
|
+
return registrations.flatMap((registration) => {
|
|
14900
|
+
const context = toScopeRef(registration);
|
|
14901
|
+
const result = check(context, registration.services);
|
|
14902
|
+
const rejected = result.rejected.map((item) => ({
|
|
14903
|
+
scope: registration.scope,
|
|
14904
|
+
scopeId: registration.scopeId,
|
|
14905
|
+
candidate: item.candidate,
|
|
14906
|
+
reasons: item.reasons
|
|
14907
|
+
}));
|
|
14908
|
+
if (result.warnings.length === 0 && rejected.length === 0) {
|
|
14909
|
+
return [
|
|
14910
|
+
{
|
|
14911
|
+
scope: registration.scope,
|
|
14912
|
+
scopeId: registration.scopeId,
|
|
14913
|
+
candidate: null,
|
|
14914
|
+
reasons: ["valid"]
|
|
14915
|
+
}
|
|
14916
|
+
];
|
|
14917
|
+
}
|
|
14918
|
+
return [...rejected, ...result.warnings.map((reason) => ({ scope: registration.scope, scopeId: registration.scopeId, candidate: null, reasons: [reason] }))];
|
|
14919
|
+
});
|
|
14920
|
+
}, [check, registrations]);
|
|
14921
|
+
return /* @__PURE__ */ jsx75(ScrollArea, { className: "min-h-0 flex-1 overflow-y-auto pr-1", "data-testid": "fallback-editor-details-scroll", children: /* @__PURE__ */ jsxs54("aside", { className: "flex flex-col gap-4", children: [
|
|
14922
|
+
/* @__PURE__ */ jsxs54(SectionCard, { className: "p-4", children: [
|
|
14923
|
+
/* @__PURE__ */ jsx75(SectionHeader2, { title: "Primary service", description: "Current editor target and change state." }),
|
|
14924
|
+
/* @__PURE__ */ jsxs54("div", { className: "mt-4 space-y-2", children: [
|
|
14925
|
+
/* @__PURE__ */ jsx75(
|
|
14926
|
+
DetailRow,
|
|
14927
|
+
{
|
|
14928
|
+
label: "Service",
|
|
14929
|
+
value: service ? `${service.name ?? "Unnamed"} (#${String(service.id)})` : "No service selected"
|
|
14930
|
+
}
|
|
14931
|
+
),
|
|
14932
|
+
/* @__PURE__ */ jsx75(DetailRow, { label: "Platform", value: service?.platform ?? "-" }),
|
|
14933
|
+
/* @__PURE__ */ jsx75(DetailRow, { label: "Rate", value: typeof service?.rate === "number" ? String(service.rate) : "-" }),
|
|
14934
|
+
/* @__PURE__ */ jsx75(DetailRow, { label: "Changed", value: state.changed ? "Yes" : "No" })
|
|
14935
|
+
] })
|
|
14936
|
+
] }),
|
|
14937
|
+
/* @__PURE__ */ jsxs54(SectionCard, { className: "p-4", children: [
|
|
14938
|
+
/* @__PURE__ */ jsx75(SectionHeader2, { title: "Policy", description: "Effective fallback rules applied by the provider." }),
|
|
14939
|
+
/* @__PURE__ */ jsxs54("div", { className: "mt-4 space-y-2", children: [
|
|
14940
|
+
/* @__PURE__ */ jsx75(DetailRow, { label: "Constraint fit", value: settings.requireConstraintFit ? "Enabled" : "Disabled" }),
|
|
14941
|
+
/* @__PURE__ */ jsx75(DetailRow, { label: "Rate policy", value: formatRatePolicy(settings) }),
|
|
14942
|
+
/* @__PURE__ */ jsx75(DetailRow, { label: "Strategy", value: settings.selectionStrategy ?? "priority" }),
|
|
14943
|
+
/* @__PURE__ */ jsx75(DetailRow, { label: "Mode", value: settings.mode ?? "strict" })
|
|
14944
|
+
] })
|
|
14945
|
+
] }),
|
|
14946
|
+
/* @__PURE__ */ jsxs54(SectionCard, { className: "flex min-h-0 flex-col overflow-hidden", children: [
|
|
14947
|
+
/* @__PURE__ */ jsx75("div", { className: "border-b border-slate-200 px-4 py-4 dark:border-slate-800", children: /* @__PURE__ */ jsx75(SectionHeader2, { title: "Diagnostics", description: "Live validation hints for the selected service registrations." }) }),
|
|
14948
|
+
/* @__PURE__ */ jsx75(ScrollArea, { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsx75("div", { className: "space-y-2 p-3", children: diagnostics.length ? diagnostics.map((entry, index) => {
|
|
14949
|
+
const tone = entry.reasons[0] === "valid" ? "success" : entry.reasons.includes("rate_violation") || entry.reasons.includes("constraint_mismatch") ? "danger" : "warning";
|
|
14950
|
+
return /* @__PURE__ */ jsx75(
|
|
14951
|
+
"div",
|
|
14952
|
+
{
|
|
14953
|
+
className: "rounded-md border border-slate-200 bg-slate-50/80 p-3 dark:border-slate-800 dark:bg-slate-900/60",
|
|
14954
|
+
children: /* @__PURE__ */ jsxs54("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
14955
|
+
/* @__PURE__ */ jsx75(ToneBadge, { label: entry.scope === "global" ? "Global" : `Node ${entry.scopeId ?? ""}`.trim() }),
|
|
14956
|
+
entry.candidate != null ? /* @__PURE__ */ jsx75(ToneBadge, { label: `Candidate #${String(entry.candidate)}`, tone: "info" }) : null,
|
|
14957
|
+
/* @__PURE__ */ jsx75(ToneBadge, { label: entry.reasons.join(", "), tone })
|
|
14958
|
+
] })
|
|
14959
|
+
},
|
|
14960
|
+
`${entry.scope}:${String(entry.scopeId ?? "global")}:${String(entry.candidate ?? "none")}:${index}`
|
|
14961
|
+
);
|
|
14962
|
+
}) : /* @__PURE__ */ jsx75("div", { className: "rounded-md border border-dashed border-slate-300 bg-slate-50/80 px-4 py-8 text-center text-sm text-slate-500 dark:border-slate-700 dark:bg-slate-900/40 dark:text-slate-400", children: "No registrations selected yet." }) }) })
|
|
14963
|
+
] }),
|
|
14964
|
+
/* @__PURE__ */ jsxs54(SectionCard, { className: "flex min-h-0 flex-col overflow-hidden", children: [
|
|
14965
|
+
/* @__PURE__ */ jsx75("div", { className: "border-b border-slate-200 px-4 py-4 dark:border-slate-800", children: /* @__PURE__ */ jsx75(SectionHeader2, { title: "Current payload", description: "Serialized fallback state from the provider." }) }),
|
|
14966
|
+
/* @__PURE__ */ jsx75(ScrollArea, { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsx75("pre", { className: "p-4 text-xs text-slate-700 dark:text-slate-200", children: JSON.stringify(state.current, null, 2) }) })
|
|
14967
|
+
] })
|
|
14968
|
+
] }) });
|
|
14969
|
+
}
|
|
14970
|
+
function toScopeRef(registration) {
|
|
14971
|
+
if (registration.scope === "global") {
|
|
14972
|
+
return {
|
|
14973
|
+
scope: "global",
|
|
14974
|
+
primary: registration.primary
|
|
14975
|
+
};
|
|
14976
|
+
}
|
|
14977
|
+
return {
|
|
14978
|
+
scope: "node",
|
|
14979
|
+
nodeId: registration.scopeId
|
|
14980
|
+
};
|
|
14981
|
+
}
|
|
14982
|
+
function formatRatePolicy(settings) {
|
|
14983
|
+
if (settings.ratePolicy?.kind === "eq_primary") return "eq_primary";
|
|
14984
|
+
if (settings.ratePolicy?.kind === "within_pct") return `within_pct (${settings.ratePolicy.pct}%)`;
|
|
14985
|
+
if (settings.ratePolicy?.kind === "at_least_pct_lower") return `at_least_pct_lower (${settings.ratePolicy.pct}%)`;
|
|
14986
|
+
if (settings.ratePolicy?.kind === "lte_primary") return `lte_primary (${settings.ratePolicy.pct}%)`;
|
|
14987
|
+
return "lte_primary (5%)";
|
|
14988
|
+
}
|
|
14989
|
+
|
|
14990
|
+
// src/workspace/fallback-editor/fallback-editor-header.tsx
|
|
14991
|
+
import { RotateCcw, Save, ShieldCheck } from "lucide-react";
|
|
14992
|
+
import { jsx as jsx76, jsxs as jsxs55 } from "react/jsx-runtime";
|
|
14993
|
+
function FallbackEditorHeader({
|
|
14994
|
+
activeServiceLabel,
|
|
14995
|
+
registrationCount,
|
|
14996
|
+
changed,
|
|
14997
|
+
onReset,
|
|
14998
|
+
onValidate,
|
|
14999
|
+
onSave,
|
|
15000
|
+
resetting = false,
|
|
15001
|
+
validating = false,
|
|
15002
|
+
saving = false
|
|
15003
|
+
}) {
|
|
15004
|
+
return /* @__PURE__ */ jsx76(SectionCard, { className: "px-5 py-4", children: /* @__PURE__ */ jsxs55("div", { className: "flex flex-col gap-4 xl:flex-row xl:items-center xl:justify-between", children: [
|
|
15005
|
+
/* @__PURE__ */ jsxs55("div", { className: "space-y-3", children: [
|
|
15006
|
+
/* @__PURE__ */ jsx76(
|
|
15007
|
+
SectionHeader2,
|
|
15008
|
+
{
|
|
15009
|
+
title: "Fallback editor",
|
|
15010
|
+
description: "Manage global and node-scoped fallback registrations with the workspace design system."
|
|
15011
|
+
}
|
|
15012
|
+
),
|
|
15013
|
+
/* @__PURE__ */ jsxs55("div", { className: "flex flex-wrap items-center gap-2 text-xs", children: [
|
|
15014
|
+
/* @__PURE__ */ jsx76(ToneBadge, { label: activeServiceLabel ?? "No service selected", tone: "info" }),
|
|
15015
|
+
/* @__PURE__ */ jsx76(ToneBadge, { label: `${registrationCount} registration${registrationCount === 1 ? "" : "s"}` }),
|
|
15016
|
+
/* @__PURE__ */ jsx76(ToneBadge, { label: changed ? "Unsaved changes" : "Synced", tone: changed ? "warning" : "success" })
|
|
15017
|
+
] })
|
|
15018
|
+
] }),
|
|
15019
|
+
/* @__PURE__ */ jsxs55("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
15020
|
+
/* @__PURE__ */ jsxs55(Button, { type: "button", variant: "outline", onClick: onReset, disabled: resetting, children: [
|
|
15021
|
+
/* @__PURE__ */ jsx76(RotateCcw, { className: "size-4" }),
|
|
15022
|
+
resetting ? "Resetting..." : "Reset"
|
|
15023
|
+
] }),
|
|
15024
|
+
/* @__PURE__ */ jsxs55(Button, { type: "button", variant: "outline", onClick: onValidate, disabled: validating, children: [
|
|
15025
|
+
/* @__PURE__ */ jsx76(ShieldCheck, { className: "size-4" }),
|
|
15026
|
+
validating ? "Validating..." : "Validate"
|
|
15027
|
+
] }),
|
|
15028
|
+
/* @__PURE__ */ jsx76(Separator2, { orientation: "vertical", className: "hidden h-8 xl:block" }),
|
|
15029
|
+
/* @__PURE__ */ jsxs55(Button, { type: "button", onClick: onSave, disabled: saving, children: [
|
|
15030
|
+
/* @__PURE__ */ jsx76(Save, { className: "size-4" }),
|
|
15031
|
+
saving ? "Saving..." : "Save changes"
|
|
15032
|
+
] })
|
|
15033
|
+
] })
|
|
15034
|
+
] }) });
|
|
15035
|
+
}
|
|
15036
|
+
|
|
15037
|
+
// src/workspace/fallback-editor/fallback-registrations-panel.tsx
|
|
15038
|
+
import { useActiveFallbackRegistrations as useActiveFallbackRegistrations3, useEligibleServiceList as useEligibleServiceList2, useFallbackEditor as useFallbackEditor3 } from "@timeax/digital-service-engine/react";
|
|
15039
|
+
import { Plus, Trash2, X as X2 } from "lucide-react";
|
|
15040
|
+
import { useCallback as useCallback20, useState as useState35 } from "react";
|
|
15041
|
+
|
|
15042
|
+
// src/workspace/fallback-editor/fallback-dialogs.tsx
|
|
15043
|
+
import { InputField as InputField16 } from "@timeax/form-palette";
|
|
15044
|
+
import { useActiveFallbackRegistrations as useActiveFallbackRegistrations2, useEligibleServiceList, useFallbackEditor as useFallbackEditor2 } from "@timeax/digital-service-engine/react";
|
|
15045
|
+
import { Check, Search } from "lucide-react";
|
|
15046
|
+
import { useEffect as useEffect21, useMemo as useMemo35, useState as useState34 } from "react";
|
|
15047
|
+
import { jsx as jsx77, jsxs as jsxs56 } from "react/jsx-runtime";
|
|
15048
|
+
function FallbackAddRegistrationDialog({
|
|
15049
|
+
open,
|
|
15050
|
+
onClose,
|
|
15051
|
+
onSelect
|
|
15052
|
+
}) {
|
|
15053
|
+
const { activeServiceId, serviceProps, snapshot } = useFallbackEditor2();
|
|
15054
|
+
const registrations = useActiveFallbackRegistrations2();
|
|
15055
|
+
const [scope, setScope] = useState34("global");
|
|
15056
|
+
const [nodeId, setNodeId] = useState34("");
|
|
15057
|
+
const mode = useMemo35(() => {
|
|
15058
|
+
if (snapshot) return "snapshot";
|
|
15059
|
+
if (serviceProps) return "props";
|
|
15060
|
+
return "none";
|
|
15061
|
+
}, [snapshot, serviceProps]);
|
|
15062
|
+
useEffect21(() => {
|
|
15063
|
+
if (open) {
|
|
15064
|
+
setScope("global");
|
|
15065
|
+
setNodeId("");
|
|
15066
|
+
}
|
|
15067
|
+
}, [open]);
|
|
15068
|
+
const hasGlobal = useMemo35(() => registrations.some((registration) => registration.scope === "global"), [registrations]);
|
|
15069
|
+
const nodeTargets = useMemo35(() => {
|
|
15070
|
+
if (activeServiceId === void 0 || activeServiceId === null) return [];
|
|
15071
|
+
if (mode === "snapshot" && snapshot?.serviceMap) {
|
|
15072
|
+
const entries = [];
|
|
15073
|
+
for (const [id, primaryIds] of Object.entries(snapshot.serviceMap)) {
|
|
15074
|
+
const matchesPrimary = (primaryIds ?? []).some((serviceId) => String(serviceId) === String(activeServiceId));
|
|
15075
|
+
if (!matchesPrimary) continue;
|
|
15076
|
+
const meta = resolveNodeMeta(serviceProps, id);
|
|
15077
|
+
entries.push({
|
|
15078
|
+
id,
|
|
15079
|
+
kind: meta.kind,
|
|
15080
|
+
label: meta.label,
|
|
15081
|
+
serviceId: activeServiceId
|
|
15082
|
+
});
|
|
15083
|
+
}
|
|
15084
|
+
return dedupeNodeTargets(entries);
|
|
15085
|
+
}
|
|
15086
|
+
if (mode === "props" && serviceProps) {
|
|
15087
|
+
const entries = [];
|
|
15088
|
+
for (const tag of serviceProps.filters ?? []) {
|
|
15089
|
+
if (tag.service_id == null || String(tag.service_id) !== String(activeServiceId)) continue;
|
|
15090
|
+
entries.push({
|
|
15091
|
+
id: tag.id,
|
|
15092
|
+
kind: "tag",
|
|
15093
|
+
label: tag.label ?? tag.title ?? tag.id,
|
|
15094
|
+
serviceId: tag.service_id
|
|
15095
|
+
});
|
|
15096
|
+
}
|
|
15097
|
+
for (const field of serviceProps.fields ?? []) {
|
|
15098
|
+
if (field.service_id != null && String(field.service_id) === String(activeServiceId)) {
|
|
15099
|
+
entries.push({
|
|
15100
|
+
id: field.id,
|
|
15101
|
+
kind: "field",
|
|
15102
|
+
label: field.label ?? field.title ?? field.id,
|
|
15103
|
+
serviceId: field.service_id
|
|
15104
|
+
});
|
|
15105
|
+
}
|
|
15106
|
+
for (const option of field.options ?? []) {
|
|
15107
|
+
if (option.service_id == null || String(option.service_id) !== String(activeServiceId)) continue;
|
|
15108
|
+
entries.push({
|
|
15109
|
+
id: option.id,
|
|
15110
|
+
kind: "option",
|
|
15111
|
+
label: option.label ?? option.title ?? String(option.value ?? option.id),
|
|
15112
|
+
serviceId: option.service_id
|
|
15113
|
+
});
|
|
15114
|
+
}
|
|
15115
|
+
}
|
|
15116
|
+
return dedupeNodeTargets(entries);
|
|
15117
|
+
}
|
|
15118
|
+
return [];
|
|
15119
|
+
}, [activeServiceId, mode, serviceProps, snapshot]);
|
|
15120
|
+
useEffect21(() => {
|
|
15121
|
+
if (hasGlobal && scope === "global") {
|
|
15122
|
+
setScope("node");
|
|
15123
|
+
}
|
|
15124
|
+
}, [hasGlobal, scope]);
|
|
15125
|
+
useEffect21(() => {
|
|
15126
|
+
if (!nodeId) return;
|
|
15127
|
+
if (nodeTargets.some((entry) => entry.id === nodeId)) return;
|
|
15128
|
+
setNodeId("");
|
|
15129
|
+
}, [nodeId, nodeTargets]);
|
|
15130
|
+
function handleContinue() {
|
|
15131
|
+
if (activeServiceId === void 0 || activeServiceId === null) return;
|
|
15132
|
+
if (scope === "global") {
|
|
15133
|
+
onSelect(
|
|
15134
|
+
{
|
|
15135
|
+
scope: "global",
|
|
15136
|
+
primary: activeServiceId
|
|
15137
|
+
},
|
|
15138
|
+
activeServiceId
|
|
15139
|
+
);
|
|
15140
|
+
return;
|
|
15141
|
+
}
|
|
15142
|
+
if (!nodeId) return;
|
|
15143
|
+
const node = nodeTargets.find((entry) => entry.id === nodeId);
|
|
15144
|
+
onSelect(
|
|
15145
|
+
{
|
|
15146
|
+
scope: "node",
|
|
15147
|
+
nodeId
|
|
15148
|
+
},
|
|
15149
|
+
node?.serviceId ?? activeServiceId
|
|
15150
|
+
);
|
|
15151
|
+
}
|
|
15152
|
+
const nodeScopeDisabled = nodeTargets.length === 0;
|
|
15153
|
+
return /* @__PURE__ */ jsx77(
|
|
15154
|
+
ModalShell,
|
|
15155
|
+
{
|
|
15156
|
+
open,
|
|
15157
|
+
onClose,
|
|
15158
|
+
title: "Add registration",
|
|
15159
|
+
description: "Choose the registration scope before selecting fallback candidates.",
|
|
15160
|
+
footer: /* @__PURE__ */ jsxs56("div", { className: "flex items-center justify-end gap-2", children: [
|
|
15161
|
+
/* @__PURE__ */ jsx77(Button, { type: "button", variant: "ghost", onClick: onClose, className: "rounded-md", children: "Cancel" }),
|
|
15162
|
+
/* @__PURE__ */ jsx77(Button, { type: "button", onClick: handleContinue, disabled: activeServiceId === void 0 || scope === "node" && !nodeId, className: "rounded-md", children: "Continue" })
|
|
15163
|
+
] }),
|
|
15164
|
+
children: /* @__PURE__ */ jsxs56("div", { className: "space-y-5", children: [
|
|
15165
|
+
/* @__PURE__ */ jsxs56("div", { className: "space-y-2", children: [
|
|
15166
|
+
/* @__PURE__ */ jsx77("label", { className: "text-sm font-medium text-slate-900 dark:text-slate-100", children: "Scope" }),
|
|
15167
|
+
/* @__PURE__ */ jsx77(
|
|
15168
|
+
InputField16,
|
|
15169
|
+
{
|
|
15170
|
+
variant: "radio",
|
|
15171
|
+
label: "Scope",
|
|
15172
|
+
value: scope,
|
|
15173
|
+
onChange: ({ value }) => setScope(value),
|
|
15174
|
+
options: [
|
|
15175
|
+
...!hasGlobal ? [{ value: "global", label: "Global" }] : [],
|
|
15176
|
+
{ value: "node", label: nodeScopeDisabled ? "Node (Unavailable)" : "Node" }
|
|
15177
|
+
]
|
|
15178
|
+
}
|
|
15179
|
+
),
|
|
15180
|
+
/* @__PURE__ */ jsx77("p", { className: "text-xs text-slate-500 dark:text-slate-400", children: scope === "global" ? "Use one global registration for this primary service." : mode === "snapshot" ? "Pick a node currently active in the order snapshot for this primary service." : mode === "props" ? "Pick a tag, field, or option from ServiceProps that maps to this primary service." : "Node-scoped registration is unavailable without OrderSnapshot or ServiceProps." })
|
|
15181
|
+
] }),
|
|
15182
|
+
scope === "node" ? /* @__PURE__ */ jsxs56("div", { className: "space-y-2", children: [
|
|
15183
|
+
/* @__PURE__ */ jsx77("label", { className: "text-sm font-medium text-slate-900 dark:text-slate-100", children: "Node id" }),
|
|
15184
|
+
/* @__PURE__ */ jsx77(
|
|
15185
|
+
InputField16,
|
|
15186
|
+
{
|
|
15187
|
+
variant: "select",
|
|
15188
|
+
label: "Node id",
|
|
15189
|
+
value: nodeId || void 0,
|
|
15190
|
+
onChange: ({ value }) => setNodeId(String(value ?? "")),
|
|
15191
|
+
options: nodeTargets.map((node) => ({
|
|
15192
|
+
value: node.id,
|
|
15193
|
+
label: `[${node.kind}] ${node.label} - #${String(node.serviceId)}`
|
|
15194
|
+
})),
|
|
15195
|
+
placeholder: "Select node",
|
|
15196
|
+
searchable: true,
|
|
15197
|
+
clearable: false,
|
|
15198
|
+
fullWidth: true
|
|
15199
|
+
}
|
|
15200
|
+
),
|
|
15201
|
+
nodeScopeDisabled ? /* @__PURE__ */ jsx77("p", { className: "text-xs text-slate-500 dark:text-slate-400", children: mode === "snapshot" ? "No active snapshot nodes were found for this primary service." : mode === "props" ? "No ServiceProps nodes were found for this primary service." : "Node-scoped registration requires either OrderSnapshot or ServiceProps." }) : null
|
|
15202
|
+
] }) : null
|
|
15203
|
+
] })
|
|
15204
|
+
}
|
|
15205
|
+
);
|
|
15206
|
+
}
|
|
15207
|
+
function FallbackAddCandidatesDialog({
|
|
15208
|
+
open,
|
|
15209
|
+
onClose,
|
|
15210
|
+
context,
|
|
15211
|
+
primaryId
|
|
15212
|
+
}) {
|
|
15213
|
+
const { eligible, addMany } = useFallbackEditor2();
|
|
15214
|
+
const eligibleServices = useEligibleServiceList();
|
|
15215
|
+
const [query, setQuery] = useState34("");
|
|
15216
|
+
const [filterEligibleOnly, setFilterEligibleOnly] = useState34(true);
|
|
15217
|
+
const [selected, setSelected] = useState34(/* @__PURE__ */ new Set());
|
|
15218
|
+
const [submitting, setSubmitting] = useState34(false);
|
|
15219
|
+
useEffect21(() => {
|
|
15220
|
+
if (!open) {
|
|
15221
|
+
setQuery("");
|
|
15222
|
+
setFilterEligibleOnly(true);
|
|
15223
|
+
setSelected(/* @__PURE__ */ new Set());
|
|
15224
|
+
}
|
|
15225
|
+
}, [open]);
|
|
15226
|
+
const allowedIds = useMemo35(() => {
|
|
15227
|
+
if (!context || !filterEligibleOnly) return null;
|
|
15228
|
+
return new Set(eligible(context).map((id) => String(id)));
|
|
15229
|
+
}, [context, eligible, filterEligibleOnly]);
|
|
15230
|
+
const items = useMemo35(() => {
|
|
15231
|
+
const normalizedQuery = query.trim().toLowerCase();
|
|
15232
|
+
return eligibleServices.filter((service) => {
|
|
15233
|
+
if (primaryId !== void 0 && String(service.id) === String(primaryId)) return false;
|
|
15234
|
+
if (allowedIds && !allowedIds.has(String(service.id))) return false;
|
|
15235
|
+
if (!normalizedQuery) return true;
|
|
15236
|
+
return String(service.id).includes(normalizedQuery) || String(service.name ?? "").toLowerCase().includes(normalizedQuery) || String(service.platform ?? "").toLowerCase().includes(normalizedQuery);
|
|
15237
|
+
});
|
|
15238
|
+
}, [allowedIds, eligibleServices, primaryId, query]);
|
|
15239
|
+
function toggle(id) {
|
|
15240
|
+
setSelected((previous) => {
|
|
15241
|
+
const next = new Set(previous);
|
|
15242
|
+
const key = String(id);
|
|
15243
|
+
if (next.has(key)) next.delete(key);
|
|
15244
|
+
else next.add(key);
|
|
15245
|
+
return next;
|
|
15246
|
+
});
|
|
15247
|
+
}
|
|
15248
|
+
async function handleAdd() {
|
|
15249
|
+
if (!context || selected.size === 0) return;
|
|
15250
|
+
setSubmitting(true);
|
|
15251
|
+
try {
|
|
15252
|
+
const ids = items.filter((item) => selected.has(String(item.id))).map((item) => item.id);
|
|
15253
|
+
addMany(context, ids);
|
|
15254
|
+
onClose();
|
|
15255
|
+
} finally {
|
|
15256
|
+
setSubmitting(false);
|
|
15257
|
+
}
|
|
15258
|
+
}
|
|
15259
|
+
return /* @__PURE__ */ jsx77(
|
|
15260
|
+
ModalShell,
|
|
15261
|
+
{
|
|
15262
|
+
open: open && Boolean(context),
|
|
15263
|
+
onClose,
|
|
15264
|
+
title: "Add fallback services",
|
|
15265
|
+
description: "Search and select one or more eligible fallback candidates.",
|
|
15266
|
+
size: "wide",
|
|
15267
|
+
footer: /* @__PURE__ */ jsxs56("div", { className: "flex items-center justify-between gap-4", children: [
|
|
15268
|
+
/* @__PURE__ */ jsxs56("p", { className: "text-sm text-slate-500 dark:text-slate-400", children: [
|
|
15269
|
+
selected.size,
|
|
15270
|
+
" selected"
|
|
15271
|
+
] }),
|
|
15272
|
+
/* @__PURE__ */ jsxs56("div", { className: "flex items-center gap-2", children: [
|
|
15273
|
+
/* @__PURE__ */ jsx77(Button, { type: "button", variant: "ghost", onClick: onClose, className: "rounded-md", children: "Cancel" }),
|
|
15274
|
+
/* @__PURE__ */ jsx77(Button, { type: "button", onClick: () => void handleAdd(), disabled: selected.size === 0 || submitting, className: "rounded-md", children: submitting ? "Adding..." : "Add selected" })
|
|
15275
|
+
] })
|
|
15276
|
+
] }),
|
|
15277
|
+
children: /* @__PURE__ */ jsxs56("div", { className: "space-y-4", children: [
|
|
15278
|
+
/* @__PURE__ */ jsxs56("div", { className: "grid gap-3 md:grid-cols-[minmax(0,1fr)_220px]", children: [
|
|
15279
|
+
/* @__PURE__ */ jsx77(
|
|
15280
|
+
InputField16,
|
|
15281
|
+
{
|
|
15282
|
+
variant: "text",
|
|
15283
|
+
label: "Search eligible services",
|
|
15284
|
+
value: query,
|
|
15285
|
+
onChange: ({ value }) => setQuery(String(value ?? "")),
|
|
15286
|
+
placeholder: "Search eligible services",
|
|
15287
|
+
leadingControl: /* @__PURE__ */ jsx77(Search, { className: "size-4 text-slate-400" }),
|
|
15288
|
+
joinControls: true,
|
|
15289
|
+
extendBoxToControls: true,
|
|
15290
|
+
fullWidth: true
|
|
15291
|
+
}
|
|
15292
|
+
),
|
|
15293
|
+
/* @__PURE__ */ jsx77("div", { className: "rounded-md border border-slate-200 bg-slate-50/70 px-4 py-3 dark:border-slate-800 dark:bg-slate-900/70", children: /* @__PURE__ */ jsx77(
|
|
15294
|
+
InputField16,
|
|
15295
|
+
{
|
|
15296
|
+
variant: "toggle",
|
|
15297
|
+
label: "Filter eligible only",
|
|
15298
|
+
value: filterEligibleOnly,
|
|
15299
|
+
onChange: ({ value }) => setFilterEligibleOnly(Boolean(value)),
|
|
15300
|
+
onText: "On",
|
|
15301
|
+
offText: "Off"
|
|
15302
|
+
}
|
|
15303
|
+
) })
|
|
15304
|
+
] }),
|
|
15305
|
+
/* @__PURE__ */ jsx77(
|
|
15306
|
+
VirtualServiceList,
|
|
15307
|
+
{
|
|
15308
|
+
items,
|
|
15309
|
+
selected,
|
|
15310
|
+
onToggle: toggle,
|
|
15311
|
+
emptyText: "No eligible services found."
|
|
15312
|
+
}
|
|
15313
|
+
)
|
|
15314
|
+
] })
|
|
15315
|
+
}
|
|
15316
|
+
);
|
|
15317
|
+
}
|
|
15318
|
+
function VirtualServiceList({
|
|
15319
|
+
items,
|
|
15320
|
+
selected,
|
|
15321
|
+
onToggle,
|
|
15322
|
+
height = 420,
|
|
15323
|
+
rowHeight = 72,
|
|
15324
|
+
emptyText = "No services found."
|
|
15325
|
+
}) {
|
|
15326
|
+
const [scrollTop, setScrollTop] = useState34(0);
|
|
15327
|
+
const total = items.length;
|
|
15328
|
+
const visibleCount = Math.ceil(height / rowHeight);
|
|
15329
|
+
const overscan = 6;
|
|
15330
|
+
const start = Math.max(0, Math.floor(scrollTop / rowHeight) - overscan);
|
|
15331
|
+
const end = Math.min(total, start + visibleCount + overscan * 2);
|
|
15332
|
+
const visibleItems = items.slice(start, end);
|
|
15333
|
+
if (total === 0) {
|
|
15334
|
+
return /* @__PURE__ */ jsx77(
|
|
15335
|
+
"div",
|
|
15336
|
+
{
|
|
15337
|
+
className: "flex items-center justify-center rounded-md border border-dashed border-slate-300 bg-slate-50/80 text-sm text-slate-500 dark:border-slate-700 dark:bg-slate-900/40 dark:text-slate-400",
|
|
15338
|
+
style: { height },
|
|
15339
|
+
children: emptyText
|
|
15340
|
+
}
|
|
15341
|
+
);
|
|
15342
|
+
}
|
|
15343
|
+
return /* @__PURE__ */ jsx77(
|
|
15344
|
+
"div",
|
|
15345
|
+
{
|
|
15346
|
+
className: "overflow-auto rounded-md border border-slate-200 bg-white/90 dark:border-slate-800 dark:bg-slate-950/70",
|
|
15347
|
+
style: { height },
|
|
15348
|
+
onScroll: (event) => setScrollTop(event.currentTarget.scrollTop),
|
|
15349
|
+
children: /* @__PURE__ */ jsx77("div", { className: "relative", style: { height: total * rowHeight }, children: visibleItems.map((item, index) => {
|
|
15350
|
+
const absoluteIndex = start + index;
|
|
15351
|
+
const key = String(item.id);
|
|
15352
|
+
const checked = selected.has(key);
|
|
15353
|
+
return /* @__PURE__ */ jsxs56(
|
|
15354
|
+
"button",
|
|
15355
|
+
{
|
|
15356
|
+
type: "button",
|
|
15357
|
+
onClick: () => onToggle(item.id),
|
|
15358
|
+
className: cn(
|
|
15359
|
+
"absolute left-0 right-0 flex items-center justify-between gap-3 border-b border-slate-100 px-4 text-left transition dark:border-slate-800",
|
|
15360
|
+
checked ? "bg-sky-50 dark:bg-sky-500/10" : "bg-white/90 hover:bg-slate-50 dark:bg-slate-950/70 dark:hover:bg-slate-900"
|
|
15361
|
+
),
|
|
15362
|
+
style: { top: absoluteIndex * rowHeight, height: rowHeight },
|
|
15363
|
+
children: [
|
|
15364
|
+
/* @__PURE__ */ jsxs56("div", { className: "min-w-0", children: [
|
|
15365
|
+
/* @__PURE__ */ jsxs56("div", { className: "truncate text-sm font-semibold text-slate-900 dark:text-slate-100", children: [
|
|
15366
|
+
"Service #",
|
|
15367
|
+
String(item.id),
|
|
15368
|
+
" - ",
|
|
15369
|
+
item.name ?? "Unnamed"
|
|
15370
|
+
] }),
|
|
15371
|
+
/* @__PURE__ */ jsxs56("div", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: [
|
|
15372
|
+
item.platform ?? "Unknown platform",
|
|
15373
|
+
typeof item.rate === "number" ? ` | Rate ${item.rate}` : ""
|
|
15374
|
+
] })
|
|
15375
|
+
] }),
|
|
15376
|
+
/* @__PURE__ */ jsxs56("div", { className: "flex items-center gap-2", children: [
|
|
15377
|
+
checked ? /* @__PURE__ */ jsx77(ToneBadge, { label: "Selected", tone: "info" }) : null,
|
|
15378
|
+
/* @__PURE__ */ jsx77(
|
|
15379
|
+
"span",
|
|
15380
|
+
{
|
|
15381
|
+
className: cn(
|
|
15382
|
+
"inline-flex size-5 items-center justify-center rounded-md border transition",
|
|
15383
|
+
checked ? "border-sky-500 bg-sky-500 text-white" : "border-slate-300 bg-white text-transparent dark:border-slate-700 dark:bg-slate-900"
|
|
15384
|
+
),
|
|
15385
|
+
children: /* @__PURE__ */ jsx77(Check, { className: "size-3.5" })
|
|
15386
|
+
}
|
|
15387
|
+
)
|
|
15388
|
+
] })
|
|
15389
|
+
]
|
|
15390
|
+
},
|
|
15391
|
+
key
|
|
15392
|
+
);
|
|
15393
|
+
}) })
|
|
15394
|
+
}
|
|
15395
|
+
);
|
|
15396
|
+
}
|
|
15397
|
+
function resolveNodeMeta(props, nodeId) {
|
|
15398
|
+
if (!props) return { kind: "node", label: nodeId };
|
|
15399
|
+
const tag = props.filters?.find((entry) => entry.id === nodeId);
|
|
15400
|
+
if (tag) {
|
|
15401
|
+
return {
|
|
15402
|
+
kind: "tag",
|
|
15403
|
+
label: tag.label ?? tag.title ?? tag.id
|
|
15404
|
+
};
|
|
15405
|
+
}
|
|
15406
|
+
const field = props.fields?.find((entry) => entry.id === nodeId);
|
|
15407
|
+
if (field) {
|
|
15408
|
+
return {
|
|
15409
|
+
kind: "field",
|
|
15410
|
+
label: field.label ?? field.title ?? field.id
|
|
15411
|
+
};
|
|
15412
|
+
}
|
|
15413
|
+
for (const fieldItem of props.fields ?? []) {
|
|
15414
|
+
const option = fieldItem.options?.find((entry) => entry.id === nodeId);
|
|
15415
|
+
if (!option) continue;
|
|
15416
|
+
return {
|
|
15417
|
+
kind: "option",
|
|
15418
|
+
label: option.label ?? option.title ?? String(option.value ?? option.id)
|
|
15419
|
+
};
|
|
15420
|
+
}
|
|
15421
|
+
return { kind: "node", label: nodeId };
|
|
15422
|
+
}
|
|
15423
|
+
function dedupeNodeTargets(entries) {
|
|
15424
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15425
|
+
return entries.filter((entry) => {
|
|
15426
|
+
if (seen.has(entry.id)) return false;
|
|
15427
|
+
seen.add(entry.id);
|
|
15428
|
+
return true;
|
|
15429
|
+
});
|
|
15430
|
+
}
|
|
15431
|
+
function registrationToScope(registration) {
|
|
15432
|
+
if (registration.scope === "global") {
|
|
15433
|
+
return {
|
|
15434
|
+
scope: "global",
|
|
15435
|
+
primary: registration.primary
|
|
15436
|
+
};
|
|
15437
|
+
}
|
|
15438
|
+
return {
|
|
15439
|
+
scope: "node",
|
|
15440
|
+
nodeId: registration.scopeId
|
|
15441
|
+
};
|
|
15442
|
+
}
|
|
15443
|
+
|
|
15444
|
+
// src/workspace/fallback-editor/fallback-registrations-panel.tsx
|
|
15445
|
+
import { Fragment as Fragment15, jsx as jsx78, jsxs as jsxs57 } from "react/jsx-runtime";
|
|
15446
|
+
function FallbackRegistrationsPanel() {
|
|
15447
|
+
const { activeServiceId, remove, clear, check } = useFallbackEditor3();
|
|
15448
|
+
const registrations = useActiveFallbackRegistrations3();
|
|
15449
|
+
const eligibleServices = useEligibleServiceList2();
|
|
15450
|
+
const [candidatePickerOpen, setCandidatePickerOpen] = useState35(false);
|
|
15451
|
+
const [candidateContext, setCandidateContext] = useState35(null);
|
|
15452
|
+
const [candidatePrimaryId, setCandidatePrimaryId] = useState35(void 0);
|
|
15453
|
+
const [registrationDialogOpen, setRegistrationDialogOpen] = useState35(false);
|
|
15454
|
+
const openCandidatePicker = useCallback20((context, primaryId) => {
|
|
15455
|
+
setCandidateContext(context);
|
|
15456
|
+
setCandidatePrimaryId(primaryId);
|
|
15457
|
+
setCandidatePickerOpen(true);
|
|
15458
|
+
}, []);
|
|
15459
|
+
if (activeServiceId === void 0 || activeServiceId === null) {
|
|
15460
|
+
return /* @__PURE__ */ jsx78(SectionCard, { className: "p-5", children: /* @__PURE__ */ jsx78(
|
|
15461
|
+
EmptyState2,
|
|
15462
|
+
{
|
|
15463
|
+
title: "Select a primary service",
|
|
15464
|
+
description: "Pick a service from the left sidebar to review or create fallback registrations."
|
|
15465
|
+
}
|
|
15466
|
+
) });
|
|
15467
|
+
}
|
|
15468
|
+
return /* @__PURE__ */ jsxs57(Fragment15, { children: [
|
|
15469
|
+
/* @__PURE__ */ jsxs57(SectionCard, { className: "flex min-h-0 flex-col flex-1 overflow-hidden", children: [
|
|
15470
|
+
/* @__PURE__ */ jsx78("div", { className: "border-b border-slate-200 px-5 py-4 dark:border-slate-800", children: /* @__PURE__ */ jsx78(
|
|
15471
|
+
SectionHeader2,
|
|
15472
|
+
{
|
|
15473
|
+
title: "Registered fallbacks",
|
|
15474
|
+
description: "Add global or node-scoped registrations, then curate the fallback candidates for each scope.",
|
|
15475
|
+
action: /* @__PURE__ */ jsxs57(Button, { type: "button", variant: "outline", onClick: () => setRegistrationDialogOpen(true), className: "rounded-md", children: [
|
|
15476
|
+
/* @__PURE__ */ jsx78(Plus, { className: "size-4" }),
|
|
15477
|
+
"Add registration"
|
|
15478
|
+
] })
|
|
15479
|
+
}
|
|
15480
|
+
) }),
|
|
15481
|
+
/* @__PURE__ */ jsx78(ScrollArea, { className: "min-h-0 flex-1", "data-testid": "fallback-editor-registrations-scroll", children: /* @__PURE__ */ jsx78("div", { className: "space-y-4 p-4", children: registrations.length === 0 ? /* @__PURE__ */ jsx78(
|
|
15482
|
+
EmptyState2,
|
|
15483
|
+
{
|
|
15484
|
+
title: "No registrations yet",
|
|
15485
|
+
description: "Create a global or node-scoped registration for the selected primary service."
|
|
15486
|
+
}
|
|
15487
|
+
) : registrations.map((registration, index) => {
|
|
15488
|
+
const context = registrationToScope(registration);
|
|
15489
|
+
const candidates = registration.services;
|
|
15490
|
+
return /* @__PURE__ */ jsxs57(
|
|
15491
|
+
"div",
|
|
15492
|
+
{
|
|
15493
|
+
className: "rounded-md border border-slate-200 bg-slate-50/80 p-4 shadow-sm dark:border-slate-800 dark:bg-slate-900/60",
|
|
15494
|
+
children: [
|
|
15495
|
+
/* @__PURE__ */ jsxs57("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [
|
|
15496
|
+
/* @__PURE__ */ jsxs57("div", { className: "space-y-2", children: [
|
|
15497
|
+
/* @__PURE__ */ jsxs57("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
15498
|
+
/* @__PURE__ */ jsx78(ToneBadge, { label: registration.scope === "global" ? "Global registration" : `Node ${registration.scopeId ?? ""}`.trim(), tone: "info" }),
|
|
15499
|
+
/* @__PURE__ */ jsx78(ToneBadge, { label: `Primary #${String(registration.primary)}` })
|
|
15500
|
+
] }),
|
|
15501
|
+
/* @__PURE__ */ jsx78("p", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: registration.scope === "global" ? "Primary service fallback list" : `Node-scoped fallback list for ${registration.scopeId}` })
|
|
15502
|
+
] }),
|
|
15503
|
+
/* @__PURE__ */ jsxs57("div", { className: "flex items-center gap-2", children: [
|
|
15504
|
+
/* @__PURE__ */ jsxs57(Button, { type: "button", variant: "outline", onClick: () => openCandidatePicker(context, registration.primary), className: "rounded-md", children: [
|
|
15505
|
+
/* @__PURE__ */ jsx78(Plus, { className: "size-4" }),
|
|
15506
|
+
"Add fallback"
|
|
15507
|
+
] }),
|
|
15508
|
+
/* @__PURE__ */ jsxs57(Button, { type: "button", variant: "outline", onClick: () => clear(context), className: "rounded-md", children: [
|
|
15509
|
+
/* @__PURE__ */ jsx78(Trash2, { className: "size-4" }),
|
|
15510
|
+
"Clear"
|
|
15511
|
+
] })
|
|
15512
|
+
] })
|
|
15513
|
+
] }),
|
|
15514
|
+
/* @__PURE__ */ jsx78("div", { className: "mt-4 flex flex-wrap gap-2", children: candidates.length === 0 ? /* @__PURE__ */ jsx78("span", { className: "text-xs text-slate-500 dark:text-slate-400", children: "No fallback services yet." }) : candidates.map((candidate) => {
|
|
15515
|
+
const preview = check(context, [candidate]);
|
|
15516
|
+
const rejected = preview.rejected[0];
|
|
15517
|
+
const service = eligibleServices.find((entry) => String(entry.id) === String(candidate));
|
|
15518
|
+
return /* @__PURE__ */ jsxs57(
|
|
15519
|
+
"div",
|
|
15520
|
+
{
|
|
15521
|
+
className: [
|
|
15522
|
+
"inline-flex items-center gap-2 rounded-md border px-3 py-1.5 text-xs",
|
|
15523
|
+
rejected ? "border-rose-200 bg-rose-50 text-rose-700 dark:border-rose-500/30 dark:bg-rose-500/10 dark:text-rose-200" : "border-slate-200 bg-white text-slate-700 dark:border-slate-700 dark:bg-slate-950 dark:text-slate-200"
|
|
15524
|
+
].join(" "),
|
|
15525
|
+
children: [
|
|
15526
|
+
/* @__PURE__ */ jsx78("span", { children: service ? `#${String(service.id)} - ${service.name ?? "Unnamed"}` : `#${String(candidate)}` }),
|
|
15527
|
+
/* @__PURE__ */ jsx78(
|
|
15528
|
+
ToneBadge,
|
|
15529
|
+
{
|
|
15530
|
+
label: rejected ? rejected.reasons.join(", ") : "valid",
|
|
15531
|
+
tone: rejected ? "danger" : "success"
|
|
15532
|
+
}
|
|
15533
|
+
),
|
|
15534
|
+
/* @__PURE__ */ jsx78(
|
|
15535
|
+
"button",
|
|
15536
|
+
{
|
|
15537
|
+
type: "button",
|
|
15538
|
+
"aria-label": `Remove candidate ${String(candidate)}`,
|
|
15539
|
+
onClick: () => remove(context, candidate),
|
|
15540
|
+
className: "text-current/70 transition hover:text-current",
|
|
15541
|
+
children: /* @__PURE__ */ jsx78(X2, { className: "size-3.5" })
|
|
15542
|
+
}
|
|
15543
|
+
)
|
|
15544
|
+
]
|
|
15545
|
+
},
|
|
15546
|
+
String(candidate)
|
|
15547
|
+
);
|
|
15548
|
+
}) })
|
|
15549
|
+
]
|
|
15550
|
+
},
|
|
15551
|
+
`${registration.scope}:${String(registration.scopeId ?? "global")}:${index}`
|
|
15552
|
+
);
|
|
15553
|
+
}) }) })
|
|
15554
|
+
] }),
|
|
15555
|
+
/* @__PURE__ */ jsx78(
|
|
15556
|
+
FallbackAddRegistrationDialog,
|
|
15557
|
+
{
|
|
15558
|
+
open: registrationDialogOpen,
|
|
15559
|
+
onClose: () => setRegistrationDialogOpen(false),
|
|
15560
|
+
onSelect: (context, primaryId) => {
|
|
15561
|
+
setRegistrationDialogOpen(false);
|
|
15562
|
+
openCandidatePicker(context, primaryId);
|
|
15563
|
+
}
|
|
15564
|
+
}
|
|
15565
|
+
),
|
|
15566
|
+
/* @__PURE__ */ jsx78(
|
|
15567
|
+
FallbackAddCandidatesDialog,
|
|
15568
|
+
{
|
|
15569
|
+
open: candidatePickerOpen,
|
|
15570
|
+
onClose: () => setCandidatePickerOpen(false),
|
|
15571
|
+
context: candidateContext,
|
|
15572
|
+
primaryId: candidatePrimaryId
|
|
15573
|
+
}
|
|
15574
|
+
)
|
|
15575
|
+
] });
|
|
15576
|
+
}
|
|
15577
|
+
|
|
15578
|
+
// src/workspace/fallback-editor/fallback-service-sidebar.tsx
|
|
15579
|
+
import { useFallbackEditor as useFallbackEditor4, usePrimaryServiceList as usePrimaryServiceList2 } from "@timeax/digital-service-engine/react";
|
|
15580
|
+
import { InputField as InputField17 } from "@timeax/form-palette";
|
|
15581
|
+
import { Search as Search2 } from "lucide-react";
|
|
15582
|
+
import { useMemo as useMemo36, useState as useState36 } from "react";
|
|
15583
|
+
import { jsx as jsx79, jsxs as jsxs58 } from "react/jsx-runtime";
|
|
15584
|
+
function FallbackServiceSidebar() {
|
|
15585
|
+
const { activeServiceId, setActiveServiceId, get } = useFallbackEditor4();
|
|
15586
|
+
const services2 = usePrimaryServiceList2();
|
|
15587
|
+
const [query, setQuery] = useState36("");
|
|
15588
|
+
const filtered = useMemo36(() => {
|
|
15589
|
+
const normalizedQuery = query.trim().toLowerCase();
|
|
15590
|
+
if (!normalizedQuery) return services2;
|
|
15591
|
+
return services2.filter((service) => {
|
|
15592
|
+
return String(service.id).includes(normalizedQuery) || String(service.name ?? "").toLowerCase().includes(normalizedQuery) || String(service.platform ?? "").toLowerCase().includes(normalizedQuery);
|
|
15593
|
+
});
|
|
15594
|
+
}, [query, services2]);
|
|
15595
|
+
return /* @__PURE__ */ jsxs58(SectionCard, { className: "flex h-full min-h-0 min-w-70 flex-col overflow-hidden border-r-0", children: [
|
|
15596
|
+
/* @__PURE__ */ jsxs58("div", { className: "border-b border-slate-200 px-4 py-4 dark:border-slate-800 space-y-2", children: [
|
|
15597
|
+
/* @__PURE__ */ jsx79(SectionHeader2, { title: "Primary services", description: "Choose the primary service whose fallback registrations you want to edit." }),
|
|
15598
|
+
/* @__PURE__ */ jsx79(
|
|
15599
|
+
InputField17,
|
|
15600
|
+
{
|
|
15601
|
+
variant: "text",
|
|
15602
|
+
value: query,
|
|
15603
|
+
onChange: ({ value }) => setQuery(String(value ?? "")),
|
|
15604
|
+
placeholder: "Search primary service",
|
|
15605
|
+
icon: /* @__PURE__ */ jsx79(Search2, { className: "size-4 text-slate-400" })
|
|
15606
|
+
}
|
|
15607
|
+
)
|
|
15608
|
+
] }),
|
|
15609
|
+
/* @__PURE__ */ jsx79(ScrollArea, { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsx79("div", { className: "space-y-2 p-3", children: filtered.map((service) => {
|
|
15610
|
+
const selected = String(service.id) === String(activeServiceId);
|
|
15611
|
+
const count = get(service.id).length;
|
|
15612
|
+
return /* @__PURE__ */ jsx79(
|
|
15613
|
+
"button",
|
|
15614
|
+
{
|
|
15615
|
+
type: "button",
|
|
15616
|
+
onClick: () => setActiveServiceId(service.id),
|
|
15617
|
+
className: cn(
|
|
15618
|
+
"w-full rounded-md border px-4 py-3 text-left transition",
|
|
15619
|
+
"hover:-translate-y-0.5 hover:border-slate-300 hover:shadow-md dark:hover:border-slate-700",
|
|
15620
|
+
selected ? "border-sky-300 bg-sky-50 shadow-sm dark:border-sky-500/40 dark:bg-sky-500/10" : "border-slate-200 bg-white/90 dark:border-slate-800 dark:bg-slate-950/70"
|
|
15621
|
+
),
|
|
15622
|
+
children: /* @__PURE__ */ jsxs58("div", { className: "flex items-start justify-between gap-3", children: [
|
|
15623
|
+
/* @__PURE__ */ jsxs58("div", { className: "min-w-0", children: [
|
|
15624
|
+
/* @__PURE__ */ jsxs58("p", { title: service.name, className: "truncate text-sm font-semibold text-slate-900 dark:text-slate-100", children: [
|
|
15625
|
+
"Service #",
|
|
15626
|
+
String(service.id),
|
|
15627
|
+
" - ",
|
|
15628
|
+
service.name ?? "Unnamed"
|
|
15629
|
+
] }),
|
|
15630
|
+
/* @__PURE__ */ jsxs58("p", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: [
|
|
15631
|
+
service.platform ?? "Unknown platform",
|
|
15632
|
+
typeof service.rate === "number" ? ` | Rate ${service.rate}` : ""
|
|
15633
|
+
] })
|
|
15634
|
+
] }),
|
|
15635
|
+
/* @__PURE__ */ jsx79(ToneBadge, { label: `${count} reg`, tone: selected ? "info" : "neutral", className: "shrink-0" })
|
|
15636
|
+
] })
|
|
15637
|
+
},
|
|
15638
|
+
String(service.id)
|
|
15639
|
+
);
|
|
15640
|
+
}) }) })
|
|
15641
|
+
] });
|
|
15642
|
+
}
|
|
15643
|
+
|
|
15644
|
+
// src/workspace/fallback-editor/fallback-settings-panel.tsx
|
|
15645
|
+
import { useFallbackEditor as useFallbackEditor5 } from "@timeax/digital-service-engine/react";
|
|
15646
|
+
import { InputField as InputField18 } from "@timeax/form-palette";
|
|
15647
|
+
import { useEffect as useEffect22, useState as useState37 } from "react";
|
|
15648
|
+
import { jsx as jsx80, jsxs as jsxs59 } from "react/jsx-runtime";
|
|
15649
|
+
function FallbackSettingsPanel() {
|
|
15650
|
+
const { settings, saveSettings, settingsSaving } = useFallbackEditor5();
|
|
15651
|
+
const [draft, setDraft] = useState37(settings);
|
|
15652
|
+
const [error, setError] = useState37(null);
|
|
15653
|
+
const [saved, setSaved] = useState37(false);
|
|
15654
|
+
useEffect22(() => {
|
|
15655
|
+
setDraft(settings);
|
|
15656
|
+
setSaved(false);
|
|
15657
|
+
setError(null);
|
|
15658
|
+
}, [settings]);
|
|
15659
|
+
const changed = JSON.stringify(draft ?? {}) !== JSON.stringify(settings ?? {});
|
|
15660
|
+
const ratePolicy = draft.ratePolicy ?? { kind: "lte_primary", pct: 5 };
|
|
15661
|
+
async function handleSave() {
|
|
15662
|
+
setError(null);
|
|
15663
|
+
setSaved(false);
|
|
15664
|
+
try {
|
|
15665
|
+
await saveSettings(draft);
|
|
15666
|
+
setSaved(true);
|
|
15667
|
+
} catch (nextError) {
|
|
15668
|
+
setError(nextError instanceof Error ? nextError.message : "Failed to save fallback settings.");
|
|
15669
|
+
}
|
|
15670
|
+
}
|
|
15671
|
+
function setRatePolicy(next) {
|
|
15672
|
+
setDraft((previous) => ({
|
|
15673
|
+
...previous,
|
|
15674
|
+
ratePolicy: next
|
|
15675
|
+
}));
|
|
15676
|
+
}
|
|
15677
|
+
return /* @__PURE__ */ jsxs59(SectionCard, { className: "flex flex-1 min-h-0 flex-col overflow-hidden", children: [
|
|
15678
|
+
/* @__PURE__ */ jsx80("div", { className: "border-b border-slate-200 px-5 py-4 dark:border-slate-800", children: /* @__PURE__ */ jsx80(
|
|
15679
|
+
SectionHeader2,
|
|
15680
|
+
{
|
|
15681
|
+
title: "Fallback settings",
|
|
15682
|
+
description: "Persist policy changes through the host editor without changing the fallback payload shape.",
|
|
15683
|
+
action: /* @__PURE__ */ jsx80(Button, { type: "button", onClick: () => void handleSave(), disabled: !changed || settingsSaving, className: "rounded-md", children: settingsSaving ? "Saving..." : "Save settings" })
|
|
15684
|
+
}
|
|
15685
|
+
) }),
|
|
15686
|
+
/* @__PURE__ */ jsx80(ScrollArea, { className: "min-h-0 flex-1 p-5", "data-testid": "fallback-editor-settings-scroll", children: /* @__PURE__ */ jsxs59("div", { className: "space-y-5", children: [
|
|
15687
|
+
/* @__PURE__ */ jsx80(SettingRow, { title: "Require constraint fit", hint: "Reject or warn when a candidate does not match effective tag constraints.", children: /* @__PURE__ */ jsx80(
|
|
15688
|
+
InputField18,
|
|
15689
|
+
{
|
|
15690
|
+
variant: "toggle",
|
|
15691
|
+
value: Boolean(draft.requireConstraintFit),
|
|
15692
|
+
onChange: ({ value }) => setDraft((previous) => ({
|
|
15693
|
+
...previous,
|
|
15694
|
+
requireConstraintFit: Boolean(value)
|
|
15695
|
+
})),
|
|
15696
|
+
onText: "Enabled",
|
|
15697
|
+
offText: "Disabled"
|
|
15698
|
+
}
|
|
15699
|
+
) }),
|
|
15700
|
+
/* @__PURE__ */ jsx80(SettingRow, { title: "Rate policy", hint: "Controls how fallback service rates are compared against the primary service.", children: /* @__PURE__ */ jsx80("div", { className: "flex flex-col gap-2 md:items-end", children: /* @__PURE__ */ jsx80(
|
|
15701
|
+
InputField18,
|
|
15702
|
+
{
|
|
15703
|
+
variant: "select",
|
|
15704
|
+
value: ratePolicy.kind,
|
|
15705
|
+
onChange: ({ value }) => {
|
|
15706
|
+
const kind = value;
|
|
15707
|
+
const pct = ratePolicy.kind === "eq_primary" ? 5 : ratePolicy.pct;
|
|
15708
|
+
if (kind === "eq_primary") {
|
|
15709
|
+
setRatePolicy({ kind: "eq_primary" });
|
|
15710
|
+
return;
|
|
15711
|
+
}
|
|
15712
|
+
if (kind === "lte_primary") {
|
|
15713
|
+
setRatePolicy({ kind: "lte_primary", pct });
|
|
15714
|
+
return;
|
|
15715
|
+
}
|
|
15716
|
+
if (kind === "within_pct") {
|
|
15717
|
+
setRatePolicy({ kind: "within_pct", pct });
|
|
15718
|
+
return;
|
|
15719
|
+
}
|
|
15720
|
+
setRatePolicy({ kind: "at_least_pct_lower", pct });
|
|
15721
|
+
},
|
|
15722
|
+
options: [
|
|
15723
|
+
{ value: "eq_primary", label: "Equals Primary" },
|
|
15724
|
+
{ value: "lte_primary", label: "Less than or Equals" },
|
|
15725
|
+
{ value: "within_pct", label: "Within Range" },
|
|
15726
|
+
{ value: "at_least_pct_lower", label: "Lower by" }
|
|
15727
|
+
],
|
|
15728
|
+
clearable: false
|
|
15729
|
+
}
|
|
15730
|
+
) }) }),
|
|
15731
|
+
ratePolicy.kind !== "eq_primary" ? /* @__PURE__ */ jsx80(SettingRow, { title: "Rate Percentage", hint: "Rate percentage the policy is guarded by", children: /* @__PURE__ */ jsx80("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx80("div", { className: "w-32", children: /* @__PURE__ */ jsx80(
|
|
15732
|
+
InputField18,
|
|
15733
|
+
{
|
|
15734
|
+
variant: "number",
|
|
15735
|
+
value: ratePolicy.pct,
|
|
15736
|
+
onChange: ({ value }) => {
|
|
15737
|
+
const pct = typeof value === "number" ? value : Number(value ?? 0);
|
|
15738
|
+
setRatePolicy({
|
|
15739
|
+
...ratePolicy,
|
|
15740
|
+
pct
|
|
15741
|
+
});
|
|
15742
|
+
},
|
|
15743
|
+
min: 0,
|
|
15744
|
+
step: 0.01,
|
|
15745
|
+
fullWidth: true,
|
|
15746
|
+
showButtons: true,
|
|
15747
|
+
trailingIcons: [/* @__PURE__ */ jsx80("span", { className: "pr-2", children: "%" })]
|
|
15748
|
+
}
|
|
15749
|
+
) }) }) }) : null,
|
|
15750
|
+
/* @__PURE__ */ jsx80(SettingRow, { title: "Selection strategy", hint: "How valid fallback candidates are ordered in previews.", children: /* @__PURE__ */ jsx80(
|
|
15751
|
+
InputField18,
|
|
15752
|
+
{
|
|
15753
|
+
variant: "select",
|
|
15754
|
+
label: "Selection strategy",
|
|
15755
|
+
value: draft.selectionStrategy ?? "priority",
|
|
15756
|
+
onChange: ({ value }) => setDraft((previous) => ({
|
|
15757
|
+
...previous,
|
|
15758
|
+
selectionStrategy: value
|
|
15759
|
+
})),
|
|
15760
|
+
options: [
|
|
15761
|
+
{ value: "priority", label: "priority" },
|
|
15762
|
+
{ value: "cheapest", label: "cheapest" }
|
|
15763
|
+
],
|
|
15764
|
+
clearable: false
|
|
15765
|
+
}
|
|
15766
|
+
) }),
|
|
15767
|
+
/* @__PURE__ */ jsx80(SettingRow, { title: "Mode", hint: "Use strict for enforced filtering, dev for advisory feedback.", children: /* @__PURE__ */ jsx80(
|
|
15768
|
+
InputField18,
|
|
15769
|
+
{
|
|
15770
|
+
variant: "select",
|
|
15771
|
+
label: "Mode",
|
|
15772
|
+
value: draft.mode ?? "strict",
|
|
15773
|
+
onChange: ({ value }) => setDraft((previous) => ({
|
|
15774
|
+
...previous,
|
|
15775
|
+
mode: value
|
|
15776
|
+
})),
|
|
15777
|
+
options: [
|
|
15778
|
+
{ value: "strict", label: "strict" },
|
|
15779
|
+
{ value: "dev", label: "dev" }
|
|
15780
|
+
],
|
|
15781
|
+
clearable: false
|
|
15782
|
+
}
|
|
15783
|
+
) }),
|
|
15784
|
+
saved && !error ? /* @__PURE__ */ jsx80(Alert, { className: "border border-emerald-200 bg-emerald-50 text-emerald-700 dark:border-emerald-500/30 dark:bg-emerald-500/10 dark:text-emerald-200", children: /* @__PURE__ */ jsx80(AlertDescription, { children: "Settings saved." }) }) : null,
|
|
15785
|
+
error ? /* @__PURE__ */ jsx80(Alert, { variant: "destructive", className: "border border-rose-200 bg-rose-50 dark:border-rose-500/30 dark:bg-rose-500/10", children: /* @__PURE__ */ jsx80(AlertDescription, { children: error }) }) : null
|
|
15786
|
+
] }) })
|
|
15787
|
+
] });
|
|
15788
|
+
}
|
|
15789
|
+
function SettingRow({ title, hint, children }) {
|
|
15790
|
+
return /* @__PURE__ */ jsxs59("div", { className: "flex flex-col gap-3 border-b border-dashed border-slate-200 pb-5 last:border-b-0 last:pb-0 md:flex-row md:items-center md:justify-between dark:border-slate-800", children: [
|
|
15791
|
+
/* @__PURE__ */ jsxs59("div", { className: "max-w-xl", children: [
|
|
15792
|
+
/* @__PURE__ */ jsx80("div", { className: "text-sm font-medium text-slate-900 dark:text-slate-100", children: title }),
|
|
15793
|
+
/* @__PURE__ */ jsx80("div", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: hint })
|
|
15794
|
+
] }),
|
|
15795
|
+
/* @__PURE__ */ jsx80("div", { children })
|
|
15796
|
+
] });
|
|
15797
|
+
}
|
|
15798
|
+
|
|
15799
|
+
// src/workspace/fallback-editor/native-fallback-editor.tsx
|
|
15800
|
+
import { jsx as jsx81, jsxs as jsxs60 } from "react/jsx-runtime";
|
|
15801
|
+
function NativeFallbackEditor({
|
|
15802
|
+
className,
|
|
15803
|
+
fallbacks,
|
|
15804
|
+
props,
|
|
15805
|
+
snapshot,
|
|
15806
|
+
primaryServices,
|
|
15807
|
+
eligibleServices,
|
|
15808
|
+
settings,
|
|
15809
|
+
initialServiceId,
|
|
15810
|
+
initialTab,
|
|
15811
|
+
onSettingsChange,
|
|
15812
|
+
onSave,
|
|
15813
|
+
onValidate,
|
|
15814
|
+
onReset
|
|
15815
|
+
}) {
|
|
15816
|
+
return /* @__PURE__ */ jsx81(
|
|
15817
|
+
FallbackEditorProvider,
|
|
15818
|
+
{
|
|
15819
|
+
fallbacks,
|
|
15820
|
+
props,
|
|
15821
|
+
snapshot,
|
|
15822
|
+
primaryServices,
|
|
15823
|
+
eligibleServices,
|
|
15824
|
+
settings,
|
|
15825
|
+
initialServiceId,
|
|
15826
|
+
initialTab,
|
|
15827
|
+
onSettingsChange,
|
|
15828
|
+
onSave,
|
|
15829
|
+
onValidate,
|
|
15830
|
+
onReset,
|
|
15831
|
+
children: /* @__PURE__ */ jsx81(NativeFallbackEditorInner, { className })
|
|
15832
|
+
}
|
|
15833
|
+
);
|
|
15834
|
+
}
|
|
15835
|
+
function NativeFallbackEditorInner({ className }) {
|
|
15836
|
+
const {
|
|
15837
|
+
activeTab,
|
|
15838
|
+
setActiveTab,
|
|
15839
|
+
activeServiceId,
|
|
15840
|
+
saveFallbacks,
|
|
15841
|
+
validateFallbacks,
|
|
15842
|
+
resetEditor,
|
|
15843
|
+
state,
|
|
15844
|
+
headerSaving,
|
|
15845
|
+
headerValidating,
|
|
15846
|
+
headerResetting
|
|
15847
|
+
} = useFallbackEditor6();
|
|
15848
|
+
const registrations = useActiveFallbackRegistrations4();
|
|
15849
|
+
const services2 = usePrimaryServiceList3();
|
|
15850
|
+
const activeServiceLabel = useMemo37(() => {
|
|
15851
|
+
const service = services2.find((entry) => String(entry.id) === String(activeServiceId));
|
|
15852
|
+
if (!service) return void 0;
|
|
15853
|
+
return `${service.name ?? "Unnamed"} (#${String(service.id)})`;
|
|
15854
|
+
}, [activeServiceId, services2]);
|
|
15855
|
+
return /* @__PURE__ */ jsxs60("div", { className: cn("flex h-full min-h-0 flex-col gap-4 text-slate-900 dark:text-slate-100", className), children: [
|
|
15856
|
+
/* @__PURE__ */ jsx81(
|
|
15857
|
+
FallbackEditorHeader,
|
|
15858
|
+
{
|
|
15859
|
+
activeServiceLabel,
|
|
15860
|
+
registrationCount: registrations.length,
|
|
15861
|
+
changed: state.changed,
|
|
15862
|
+
onReset: resetEditor,
|
|
15863
|
+
onValidate: validateFallbacks,
|
|
15864
|
+
onSave: saveFallbacks,
|
|
15865
|
+
resetting: headerResetting,
|
|
15866
|
+
validating: headerValidating,
|
|
15867
|
+
saving: headerSaving
|
|
15868
|
+
}
|
|
15869
|
+
),
|
|
15870
|
+
/* @__PURE__ */ jsxs60(ResizablePanelGroup, { direction: "horizontal", className: "min-h-0 flex-1 gap-0 overflow-hidden", "data-testid": "fallback-editor-layout", children: [
|
|
15871
|
+
/* @__PURE__ */ jsx81(ResizablePanel, { defaultSize: 300, minSize: 300, maxSize: 350, className: "", children: /* @__PURE__ */ jsx81("div", { className: "flex h-full min-h-0 min-w-70", "data-testid": "fallback-editor-sidebar-panel", children: /* @__PURE__ */ jsx81(FallbackServiceSidebar, {}) }) }),
|
|
15872
|
+
/* @__PURE__ */ jsx81(ResizableHandle, {}),
|
|
15873
|
+
/* @__PURE__ */ jsx81(ResizablePanel, { defaultSize: 78, minSize: 66, className: "pl-4", children: /* @__PURE__ */ jsxs60("div", { className: "grid h-full min-h-0 gap-4 xl:grid-cols-[minmax(0,1fr)_360px]", "data-testid": "fallback-editor-main-panel", children: [
|
|
15874
|
+
/* @__PURE__ */ jsxs60(
|
|
15875
|
+
Tabs,
|
|
15876
|
+
{
|
|
15877
|
+
value: activeTab,
|
|
15878
|
+
onValueChange: (value) => setActiveTab(value),
|
|
15879
|
+
className: "min-h-0 gap-4 overflow-hidden",
|
|
15880
|
+
children: [
|
|
15881
|
+
/* @__PURE__ */ jsx81(SectionCard, { className: "shrink-0 px-5 py-4", children: /* @__PURE__ */ jsxs60("div", { className: "flex flex-col gap-4 lg:flex-row lg:items-start lg:justify-between", children: [
|
|
15882
|
+
/* @__PURE__ */ jsxs60("div", { className: "min-w-0", children: [
|
|
15883
|
+
/* @__PURE__ */ jsx81("h2", { className: "text-lg font-semibold text-slate-900 dark:text-slate-100", children: activeServiceId != null ? `Service #${String(activeServiceId)}` : "No service selected" }),
|
|
15884
|
+
/* @__PURE__ */ jsx81("p", { className: "mt-1 text-sm text-slate-500 dark:text-slate-400", children: "Edit fallback registrations, review validation hints, and persist policy updates." })
|
|
15885
|
+
] }),
|
|
15886
|
+
/* @__PURE__ */ jsxs60(TabsList, { children: [
|
|
15887
|
+
/* @__PURE__ */ jsx81(TabsTrigger, { value: "registrations", children: "Registrations" }),
|
|
15888
|
+
/* @__PURE__ */ jsx81(TabsTrigger, { value: "settings", children: "Settings" })
|
|
15889
|
+
] })
|
|
15890
|
+
] }) }),
|
|
15891
|
+
/* @__PURE__ */ jsx81(TabsContent, { value: "registrations", className: "min-h-0 overflow-hidden", "data-testid": "fallback-editor-registrations-tab", children: /* @__PURE__ */ jsx81(FallbackRegistrationsPanel, {}) }),
|
|
15892
|
+
/* @__PURE__ */ jsx81(TabsContent, { value: "settings", className: "min-h-0 flex flex-col overflow-hidden", "data-testid": "fallback-editor-settings-tab", children: /* @__PURE__ */ jsx81(FallbackSettingsPanel, {}) })
|
|
15893
|
+
]
|
|
15894
|
+
}
|
|
15895
|
+
),
|
|
15896
|
+
/* @__PURE__ */ jsx81("div", { className: "min-h-0 overflow-hidden flex flex-col", "data-testid": "fallback-editor-details-panel", children: /* @__PURE__ */ jsx81(FallbackDetailsPanel, {}) })
|
|
15897
|
+
] }) })
|
|
15898
|
+
] })
|
|
15899
|
+
] });
|
|
15900
|
+
}
|
|
15901
|
+
|
|
14598
15902
|
// src/workspace/fallback-editor-modal.tsx
|
|
14599
15903
|
import { useCanvas as useCanvas18, useWorkspace as useWorkspace15 } from "@timeax/digital-service-engine/workspace";
|
|
14600
15904
|
import cloneDeep4 from "lodash/cloneDeep";
|
|
14601
|
-
import {
|
|
15905
|
+
import { createContext as createContext4, useCallback as useCallback21, useContext as useContext4, useEffect as useEffect23, useMemo as useMemo38, useState as useState38 } from "react";
|
|
14602
15906
|
import { createPortal as createPortal4 } from "react-dom";
|
|
14603
15907
|
import { FiX as FiX4 } from "react-icons/fi";
|
|
14604
|
-
import { jsx as
|
|
14605
|
-
var LazyFallbackEditor = lazy(async () => {
|
|
14606
|
-
const mod = await import("@timeax/digital-service-engine/react");
|
|
14607
|
-
return { default: mod.FallbackEditor };
|
|
14608
|
-
});
|
|
15908
|
+
import { jsx as jsx82, jsxs as jsxs61 } from "react/jsx-runtime";
|
|
14609
15909
|
var noop2 = () => {
|
|
14610
15910
|
};
|
|
14611
15911
|
var defaultContextValue2 = {
|
|
@@ -14618,14 +15918,14 @@ var FallbackEditorModalContext = createContext4(defaultContextValue2);
|
|
|
14618
15918
|
function FallbackEditorModalProvider({ children }) {
|
|
14619
15919
|
const canvas = useCanvas18();
|
|
14620
15920
|
const ws = useWorkspace15();
|
|
14621
|
-
const [launch, setLaunch] =
|
|
14622
|
-
const [sessionId, setSessionId] =
|
|
14623
|
-
const [surfaceError, setSurfaceError] =
|
|
14624
|
-
const close =
|
|
15921
|
+
const [launch, setLaunch] = useState38(null);
|
|
15922
|
+
const [sessionId, setSessionId] = useState38(0);
|
|
15923
|
+
const [surfaceError, setSurfaceError] = useState38(null);
|
|
15924
|
+
const close = useCallback21(() => {
|
|
14625
15925
|
setLaunch(null);
|
|
14626
15926
|
setSurfaceError(null);
|
|
14627
15927
|
}, []);
|
|
14628
|
-
const openForNode =
|
|
15928
|
+
const openForNode = useCallback21((input) => {
|
|
14629
15929
|
setSurfaceError(null);
|
|
14630
15930
|
setSessionId((current) => current + 1);
|
|
14631
15931
|
setLaunch({
|
|
@@ -14636,7 +15936,7 @@ function FallbackEditorModalProvider({ children }) {
|
|
|
14636
15936
|
nodeLabel: input.nodeLabel ?? input.nodeId
|
|
14637
15937
|
});
|
|
14638
15938
|
}, []);
|
|
14639
|
-
const openForService =
|
|
15939
|
+
const openForService = useCallback21((input) => {
|
|
14640
15940
|
setSurfaceError(null);
|
|
14641
15941
|
setSessionId((current) => current + 1);
|
|
14642
15942
|
setLaunch({
|
|
@@ -14645,7 +15945,7 @@ function FallbackEditorModalProvider({ children }) {
|
|
|
14645
15945
|
serviceName: input.serviceName
|
|
14646
15946
|
});
|
|
14647
15947
|
}, []);
|
|
14648
|
-
const persistProps =
|
|
15948
|
+
const persistProps = useCallback21(
|
|
14649
15949
|
(label, mutate) => {
|
|
14650
15950
|
const editorAny = canvas.api.editor;
|
|
14651
15951
|
if (typeof editorAny.transact !== "function" || typeof editorAny.replaceProps !== "function") {
|
|
@@ -14659,7 +15959,7 @@ function FallbackEditorModalProvider({ children }) {
|
|
|
14659
15959
|
},
|
|
14660
15960
|
[canvas.api.builder, canvas.api.editor, canvas.props]
|
|
14661
15961
|
);
|
|
14662
|
-
const handleSave =
|
|
15962
|
+
const handleSave = useCallback21(
|
|
14663
15963
|
async (nextFallbacks) => {
|
|
14664
15964
|
setSurfaceError(null);
|
|
14665
15965
|
try {
|
|
@@ -14676,7 +15976,7 @@ function FallbackEditorModalProvider({ children }) {
|
|
|
14676
15976
|
},
|
|
14677
15977
|
[close, persistProps]
|
|
14678
15978
|
);
|
|
14679
|
-
const handleSettingsChange =
|
|
15979
|
+
const handleSettingsChange = useCallback21(
|
|
14680
15980
|
async (nextSettings) => {
|
|
14681
15981
|
setSurfaceError(null);
|
|
14682
15982
|
try {
|
|
@@ -14692,26 +15992,26 @@ function FallbackEditorModalProvider({ children }) {
|
|
|
14692
15992
|
},
|
|
14693
15993
|
[persistProps]
|
|
14694
15994
|
);
|
|
14695
|
-
const launchTitle =
|
|
15995
|
+
const launchTitle = useMemo38(() => {
|
|
14696
15996
|
if (!launch) return "Fallback editor";
|
|
14697
15997
|
if (launch.source === "node") {
|
|
14698
15998
|
return launch.nodeLabel ? `Fallback editor for ${launch.nodeLabel}` : "Fallback editor";
|
|
14699
15999
|
}
|
|
14700
16000
|
return launch.serviceName ? `Fallback editor for ${launch.serviceName}` : `Fallback editor for service #${String(launch.initialServiceId)}`;
|
|
14701
16001
|
}, [launch]);
|
|
14702
|
-
const launchDescription =
|
|
16002
|
+
const launchDescription = useMemo38(() => {
|
|
14703
16003
|
if (!launch) return "";
|
|
14704
16004
|
if (launch.source === "node") {
|
|
14705
16005
|
return `Browse and edit fallback registrations for service #${String(launch.initialServiceId)}. Node-scoped and global registrations remain available inside the editor.`;
|
|
14706
16006
|
}
|
|
14707
16007
|
return `Browse and edit all fallback registrations for service #${String(launch.initialServiceId)} from Active Services.`;
|
|
14708
16008
|
}, [launch]);
|
|
14709
|
-
const servicesMap =
|
|
14710
|
-
const fallbackSettings =
|
|
16009
|
+
const servicesMap = useMemo38(() => ws.services.data ?? {}, [ws.services.data]);
|
|
16010
|
+
const fallbackSettings = useMemo38(
|
|
14711
16011
|
() => canvas.props?.fallbackSettings ?? {},
|
|
14712
16012
|
[canvas.props]
|
|
14713
16013
|
);
|
|
14714
|
-
|
|
16014
|
+
useEffect23(() => {
|
|
14715
16015
|
if (!launch) return;
|
|
14716
16016
|
const onKeyDown = (event) => {
|
|
14717
16017
|
if (event.key === "Escape") close();
|
|
@@ -14719,7 +16019,7 @@ function FallbackEditorModalProvider({ children }) {
|
|
|
14719
16019
|
window.addEventListener("keydown", onKeyDown);
|
|
14720
16020
|
return () => window.removeEventListener("keydown", onKeyDown);
|
|
14721
16021
|
}, [close, launch]);
|
|
14722
|
-
const value =
|
|
16022
|
+
const value = useMemo38(
|
|
14723
16023
|
() => ({
|
|
14724
16024
|
openForNode,
|
|
14725
16025
|
openForService,
|
|
@@ -14728,51 +16028,45 @@ function FallbackEditorModalProvider({ children }) {
|
|
|
14728
16028
|
}),
|
|
14729
16029
|
[close, launch, openForNode, openForService]
|
|
14730
16030
|
);
|
|
14731
|
-
return /* @__PURE__ */
|
|
16031
|
+
return /* @__PURE__ */ jsxs61(FallbackEditorModalContext.Provider, { value, children: [
|
|
14732
16032
|
children,
|
|
14733
16033
|
typeof document !== "undefined" && launch ? createPortal4(
|
|
14734
|
-
/* @__PURE__ */
|
|
16034
|
+
/* @__PURE__ */ jsx82(
|
|
14735
16035
|
"div",
|
|
14736
16036
|
{
|
|
14737
16037
|
className: "fixed inset-0 z-50 flex items-center justify-center bg-slate-950/60 p-4 backdrop-blur-sm",
|
|
14738
16038
|
onMouseDown: (event) => {
|
|
14739
16039
|
if (event.target === event.currentTarget) close();
|
|
14740
16040
|
},
|
|
14741
|
-
children: /* @__PURE__ */
|
|
16041
|
+
children: /* @__PURE__ */ jsxs61(
|
|
14742
16042
|
"div",
|
|
14743
16043
|
{
|
|
14744
16044
|
className: cn(
|
|
14745
|
-
"flex h-[min(90vh,56rem)] w-[min(96vw,88rem)] flex-col overflow-hidden rounded-
|
|
16045
|
+
"flex h-[min(90vh,56rem)] w-[min(96vw,88rem)] flex-col overflow-hidden rounded-md border border-slate-200 bg-white shadow-2xl dark:border-slate-800 dark:bg-slate-950"
|
|
14746
16046
|
),
|
|
14747
16047
|
children: [
|
|
14748
|
-
/* @__PURE__ */
|
|
14749
|
-
/* @__PURE__ */
|
|
14750
|
-
/* @__PURE__ */
|
|
14751
|
-
/* @__PURE__ */
|
|
16048
|
+
/* @__PURE__ */ jsxs61("div", { className: "flex items-start justify-between gap-4 border-b border-slate-200 px-6 py-4 dark:border-slate-800", children: [
|
|
16049
|
+
/* @__PURE__ */ jsxs61("div", { className: "min-w-0", children: [
|
|
16050
|
+
/* @__PURE__ */ jsx82("h2", { className: "text-lg font-semibold text-slate-900 dark:text-slate-100", children: launchTitle }),
|
|
16051
|
+
/* @__PURE__ */ jsx82("p", { className: "mt-1 text-sm text-slate-500 dark:text-slate-400", children: launchDescription })
|
|
14752
16052
|
] }),
|
|
14753
|
-
/* @__PURE__ */
|
|
16053
|
+
/* @__PURE__ */ jsx82(Button, { type: "button", variant: "ghost", size: "sm", onClick: close, className: "h-9 rounded-md px-2", children: /* @__PURE__ */ jsx82(FiX4, {}) })
|
|
14754
16054
|
] }),
|
|
14755
|
-
surfaceError ? /* @__PURE__ */
|
|
14756
|
-
/* @__PURE__ */
|
|
14757
|
-
|
|
16055
|
+
surfaceError ? /* @__PURE__ */ jsx82("div", { className: "border-b border-rose-200 bg-rose-50 px-6 py-3 text-sm text-rose-700 dark:border-rose-900/40 dark:bg-rose-950/20 dark:text-rose-200", children: surfaceError }) : null,
|
|
16056
|
+
/* @__PURE__ */ jsx82("div", { className: "min-h-0 flex-1 overflow-hidden", children: /* @__PURE__ */ jsx82(
|
|
16057
|
+
NativeFallbackEditor,
|
|
14758
16058
|
{
|
|
14759
|
-
|
|
14760
|
-
|
|
14761
|
-
|
|
14762
|
-
|
|
14763
|
-
|
|
14764
|
-
|
|
14765
|
-
|
|
14766
|
-
|
|
14767
|
-
|
|
14768
|
-
|
|
14769
|
-
|
|
14770
|
-
onSettingsChange: handleSettingsChange,
|
|
14771
|
-
onSave: handleSave
|
|
14772
|
-
},
|
|
14773
|
-
`${launch.source}:${String(launch.initialServiceId)}:${sessionId}`
|
|
14774
|
-
)
|
|
14775
|
-
}
|
|
16059
|
+
className: "h-full p-5",
|
|
16060
|
+
fallbacks: canvas.props.fallbacks,
|
|
16061
|
+
props: canvas.props,
|
|
16062
|
+
primaryServices: servicesMap,
|
|
16063
|
+
eligibleServices: servicesMap,
|
|
16064
|
+
settings: fallbackSettings,
|
|
16065
|
+
initialServiceId: launch.initialServiceId,
|
|
16066
|
+
onSettingsChange: handleSettingsChange,
|
|
16067
|
+
onSave: handleSave
|
|
16068
|
+
},
|
|
16069
|
+
`${launch.source}:${String(launch.initialServiceId)}:${sessionId}`
|
|
14776
16070
|
) })
|
|
14777
16071
|
]
|
|
14778
16072
|
}
|
|
@@ -14789,7 +16083,7 @@ function useFallbackEditorModal() {
|
|
|
14789
16083
|
|
|
14790
16084
|
// src/workspace/bottom-panel/index.tsx
|
|
14791
16085
|
import { useCanvas as useCanvas21, useWorkspace as useWorkspace16 } from "@timeax/digital-service-engine/workspace";
|
|
14792
|
-
import { useCallback as
|
|
16086
|
+
import { useCallback as useCallback22, useEffect as useEffect26, useMemo as useMemo40, useRef as useRef12, useState as useState41 } from "react";
|
|
14793
16087
|
import { FiEye as FiEye3, FiEyeOff as FiEyeOff2, FiSearch, FiTerminal as FiTerminal2, FiX as FiX6 } from "react-icons/fi";
|
|
14794
16088
|
import { LuGripHorizontal, LuLayers3 } from "react-icons/lu";
|
|
14795
16089
|
import { MdOutlineSync } from "react-icons/md";
|
|
@@ -14802,7 +16096,7 @@ import { FiInfo as FiInfo3, FiTrash2, FiX as FiX5 } from "react-icons/fi";
|
|
|
14802
16096
|
import "@timeax/digital-service-engine/workspace";
|
|
14803
16097
|
import { startTransition } from "react";
|
|
14804
16098
|
import { FiAlertCircle as FiAlertCircle4, FiInfo as FiInfo2 } from "react-icons/fi";
|
|
14805
|
-
import { jsx as
|
|
16099
|
+
import { jsx as jsx83 } from "react/jsx-runtime";
|
|
14806
16100
|
var PANEL_MARGIN = 8;
|
|
14807
16101
|
var PANEL_LEFT_KEY = "service-builder.bottom-panel.pos-x";
|
|
14808
16102
|
var PANEL_BOTTOM_KEY = "service-builder.bottom-panel.pos-y";
|
|
@@ -14817,9 +16111,9 @@ function sameIds(a, b) {
|
|
|
14817
16111
|
return a.length === b.length && a.every((value, index) => value === b[index]);
|
|
14818
16112
|
}
|
|
14819
16113
|
function iconForSeverity(severity) {
|
|
14820
|
-
if (severity === "error") return /* @__PURE__ */
|
|
14821
|
-
if (severity === "warning") return /* @__PURE__ */
|
|
14822
|
-
return /* @__PURE__ */
|
|
16114
|
+
if (severity === "error") return /* @__PURE__ */ jsx83(FiAlertCircle4, { className: "text-lg text-rose-500" });
|
|
16115
|
+
if (severity === "warning") return /* @__PURE__ */ jsx83(FiAlertCircle4, { className: "text-lg text-amber-500" });
|
|
16116
|
+
return /* @__PURE__ */ jsx83(FiInfo2, { className: "text-lg text-sky-500" });
|
|
14823
16117
|
}
|
|
14824
16118
|
function severityBadgeClassName(severity) {
|
|
14825
16119
|
return cn(
|
|
@@ -15000,7 +16294,7 @@ function toNodeChip(canvas, id) {
|
|
|
15000
16294
|
}
|
|
15001
16295
|
|
|
15002
16296
|
// src/workspace/bottom-panel/console-tab.tsx
|
|
15003
|
-
import { Fragment as
|
|
16297
|
+
import { Fragment as Fragment16, jsx as jsx84, jsxs as jsxs62 } from "react/jsx-runtime";
|
|
15004
16298
|
function ConsoleTab({
|
|
15005
16299
|
errors,
|
|
15006
16300
|
notices,
|
|
@@ -15029,21 +16323,21 @@ function ConsoleTab({
|
|
|
15029
16323
|
];
|
|
15030
16324
|
const activeIntro = introState[subTab];
|
|
15031
16325
|
const introCopy = getConsoleIntroCopy(subTab);
|
|
15032
|
-
return /* @__PURE__ */
|
|
15033
|
-
!activeIntro.closed ? /* @__PURE__ */
|
|
15034
|
-
/* @__PURE__ */
|
|
15035
|
-
/* @__PURE__ */
|
|
15036
|
-
!activeIntro.minimized ? /* @__PURE__ */
|
|
15037
|
-
/* @__PURE__ */
|
|
15038
|
-
/* @__PURE__ */
|
|
15039
|
-
/* @__PURE__ */
|
|
15040
|
-
/* @__PURE__ */
|
|
15041
|
-
/* @__PURE__ */
|
|
16326
|
+
return /* @__PURE__ */ jsxs62("div", { className: "space-y-4", children: [
|
|
16327
|
+
!activeIntro.closed ? /* @__PURE__ */ jsx84("div", { className: "rounded-2xl border border-sky-200/80 bg-sky-50/70 p-3 dark:border-sky-500/20 dark:bg-sky-500/10", children: /* @__PURE__ */ jsxs62("div", { className: "flex items-start justify-between gap-3", children: [
|
|
16328
|
+
/* @__PURE__ */ jsxs62("div", { className: "min-w-0", children: [
|
|
16329
|
+
/* @__PURE__ */ jsx84("p", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: introCopy.title }),
|
|
16330
|
+
!activeIntro.minimized ? /* @__PURE__ */ jsxs62(Fragment16, { children: [
|
|
16331
|
+
/* @__PURE__ */ jsx84("p", { className: "mt-1 text-xs text-slate-600 dark:text-slate-300", children: introCopy.description }),
|
|
16332
|
+
/* @__PURE__ */ jsxs62("div", { className: "mt-2 flex flex-wrap items-center gap-2 text-[11px] text-slate-500 dark:text-slate-400", children: [
|
|
16333
|
+
/* @__PURE__ */ jsx84("span", { className: "rounded-full bg-white/80 px-2 py-0.5 dark:bg-slate-900/70", children: validating ? "Validating..." : "Console idle" }),
|
|
16334
|
+
/* @__PURE__ */ jsx84("span", { className: "rounded-full bg-white/80 px-2 py-0.5 dark:bg-slate-900/70", children: shortcutLabel }),
|
|
16335
|
+
/* @__PURE__ */ jsx84("span", { className: "rounded-full bg-white/80 px-2 py-0.5 dark:bg-slate-900/70", children: "Press Escape to close" })
|
|
15042
16336
|
] })
|
|
15043
16337
|
] }) : null
|
|
15044
16338
|
] }),
|
|
15045
|
-
/* @__PURE__ */
|
|
15046
|
-
/* @__PURE__ */
|
|
16339
|
+
/* @__PURE__ */ jsxs62("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
16340
|
+
/* @__PURE__ */ jsx84(
|
|
15047
16341
|
"button",
|
|
15048
16342
|
{
|
|
15049
16343
|
type: "button",
|
|
@@ -15052,7 +16346,7 @@ function ConsoleTab({
|
|
|
15052
16346
|
children: activeIntro.minimized ? "Expand" : "Minimize"
|
|
15053
16347
|
}
|
|
15054
16348
|
),
|
|
15055
|
-
/* @__PURE__ */
|
|
16349
|
+
/* @__PURE__ */ jsx84(
|
|
15056
16350
|
"button",
|
|
15057
16351
|
{
|
|
15058
16352
|
type: "button",
|
|
@@ -15063,9 +16357,9 @@ function ConsoleTab({
|
|
|
15063
16357
|
)
|
|
15064
16358
|
] })
|
|
15065
16359
|
] }) }) : null,
|
|
15066
|
-
/* @__PURE__ */
|
|
15067
|
-
/* @__PURE__ */
|
|
15068
|
-
/* @__PURE__ */
|
|
16360
|
+
/* @__PURE__ */ jsxs62("div", { className: "rounded-2xl border border-slate-200 bg-white/70 p-3 dark:border-slate-800 dark:bg-slate-950/40", children: [
|
|
16361
|
+
/* @__PURE__ */ jsxs62("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [
|
|
16362
|
+
/* @__PURE__ */ jsx84("div", { className: "flex flex-wrap items-center gap-2", children: subTabs.map((tab) => /* @__PURE__ */ jsxs62(
|
|
15069
16363
|
"button",
|
|
15070
16364
|
{
|
|
15071
16365
|
type: "button",
|
|
@@ -15075,20 +16369,20 @@ function ConsoleTab({
|
|
|
15075
16369
|
subTab === tab.id ? "bg-slate-900 text-white dark:bg-slate-100 dark:text-slate-900" : "bg-slate-100 text-slate-600 hover:bg-slate-200 dark:bg-slate-900 dark:text-slate-300 dark:hover:bg-slate-800"
|
|
15076
16370
|
),
|
|
15077
16371
|
children: [
|
|
15078
|
-
/* @__PURE__ */
|
|
15079
|
-
/* @__PURE__ */
|
|
16372
|
+
/* @__PURE__ */ jsx84("span", { children: tab.label }),
|
|
16373
|
+
/* @__PURE__ */ jsx84("span", { className: "rounded-full bg-black/10 px-1.5 py-0.5 text-[10px] dark:bg-white/10", children: tab.count })
|
|
15080
16374
|
]
|
|
15081
16375
|
},
|
|
15082
16376
|
tab.id
|
|
15083
16377
|
)) }),
|
|
15084
|
-
subTab === "logs" && logRows.length ? /* @__PURE__ */
|
|
15085
|
-
/* @__PURE__ */
|
|
16378
|
+
subTab === "logs" && logRows.length ? /* @__PURE__ */ jsxs62(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => errors.clear("logs"), className: "h-8 rounded-xl px-3 text-xs", children: [
|
|
16379
|
+
/* @__PURE__ */ jsx84(FiTrash2, {}),
|
|
15086
16380
|
"Clear logs"
|
|
15087
16381
|
] }) : null
|
|
15088
16382
|
] }),
|
|
15089
|
-
/* @__PURE__ */
|
|
15090
|
-
/* @__PURE__ */
|
|
15091
|
-
/* @__PURE__ */
|
|
16383
|
+
/* @__PURE__ */ jsxs62("div", { className: "mt-3 flex flex-wrap items-center gap-2", children: [
|
|
16384
|
+
/* @__PURE__ */ jsx84("span", { className: "text-[11px] font-semibold tracking-[0.16em] text-slate-500 uppercase dark:text-slate-400", children: "Scope" }),
|
|
16385
|
+
/* @__PURE__ */ jsx84(
|
|
15092
16386
|
"button",
|
|
15093
16387
|
{
|
|
15094
16388
|
type: "button",
|
|
@@ -15100,7 +16394,7 @@ function ConsoleTab({
|
|
|
15100
16394
|
children: "All items"
|
|
15101
16395
|
}
|
|
15102
16396
|
),
|
|
15103
|
-
/* @__PURE__ */
|
|
16397
|
+
/* @__PURE__ */ jsx84(
|
|
15104
16398
|
"button",
|
|
15105
16399
|
{
|
|
15106
16400
|
type: "button",
|
|
@@ -15112,9 +16406,9 @@ function ConsoleTab({
|
|
|
15112
16406
|
children: "Active node"
|
|
15113
16407
|
}
|
|
15114
16408
|
),
|
|
15115
|
-
subTab !== "logs" ? /* @__PURE__ */
|
|
15116
|
-
/* @__PURE__ */
|
|
15117
|
-
["all", "error", "warning", "info"].map((option) => /* @__PURE__ */
|
|
16409
|
+
subTab !== "logs" ? /* @__PURE__ */ jsxs62(Fragment16, { children: [
|
|
16410
|
+
/* @__PURE__ */ jsx84("span", { className: "ml-2 text-[11px] font-semibold tracking-[0.16em] text-slate-500 uppercase dark:text-slate-400", children: "Severity" }),
|
|
16411
|
+
["all", "error", "warning", "info"].map((option) => /* @__PURE__ */ jsx84(
|
|
15118
16412
|
"button",
|
|
15119
16413
|
{
|
|
15120
16414
|
type: "button",
|
|
@@ -15129,23 +16423,23 @@ function ConsoleTab({
|
|
|
15129
16423
|
))
|
|
15130
16424
|
] }) : null
|
|
15131
16425
|
] }),
|
|
15132
|
-
scopeFilter === "activeNode" && !hasActiveSelection ? /* @__PURE__ */
|
|
16426
|
+
scopeFilter === "activeNode" && !hasActiveSelection ? /* @__PURE__ */ jsx84("p", { className: "mt-2 text-xs text-amber-700 dark:text-amber-300", children: "No active node selected. Select a node to filter by active scope." }) : null
|
|
15133
16427
|
] }),
|
|
15134
|
-
subTab === "validation" ? validationRows.length ? /* @__PURE__ */
|
|
16428
|
+
subTab === "validation" ? validationRows.length ? /* @__PURE__ */ jsx84("div", { className: "space-y-3", children: validationRows.map((row) => /* @__PURE__ */ jsx84(ValidationCard, { onNodeClick, row }, row.id)) }) : /* @__PURE__ */ jsx84(
|
|
15135
16429
|
EmptyState,
|
|
15136
16430
|
{
|
|
15137
16431
|
title: "No validation rows for this filter",
|
|
15138
16432
|
description: scopeFilter === "activeNode" ? "No validation rows match the current active node scope." : "No validation rows match the current severity filter."
|
|
15139
16433
|
}
|
|
15140
16434
|
) : null,
|
|
15141
|
-
subTab === "logs" ? logRows.length ? /* @__PURE__ */
|
|
16435
|
+
subTab === "logs" ? logRows.length ? /* @__PURE__ */ jsx84("div", { className: "space-y-3", children: logRows.map((row) => /* @__PURE__ */ jsx84(LogCard, { row, onRemove: () => errors.removeLog(row.id) }, row.id)) }) : /* @__PURE__ */ jsx84(
|
|
15142
16436
|
EmptyState,
|
|
15143
16437
|
{
|
|
15144
16438
|
title: "No logs for this filter",
|
|
15145
16439
|
description: scopeFilter === "activeNode" ? "No logs are linked to the current active node scope." : "No logs have been captured yet."
|
|
15146
16440
|
}
|
|
15147
16441
|
) : null,
|
|
15148
|
-
subTab === "notices" ? noticeRows.length ? /* @__PURE__ */
|
|
16442
|
+
subTab === "notices" ? noticeRows.length ? /* @__PURE__ */ jsx84("div", { className: "space-y-3", children: noticeRows.map((row) => /* @__PURE__ */ jsx84(NoticeCard, { notice: row, onNodeClick }, row.id)) }) : /* @__PURE__ */ jsx84(
|
|
15149
16443
|
EmptyState,
|
|
15150
16444
|
{
|
|
15151
16445
|
title: "No notices for this filter",
|
|
@@ -15158,21 +16452,21 @@ function NoticeCard({ notice, onNodeClick }) {
|
|
|
15158
16452
|
const canvas = useCanvas20();
|
|
15159
16453
|
const targetNodeId = notice.target.scope === "node" ? notice.target.node_id : null;
|
|
15160
16454
|
const targetChip = notice.target.scope === "node" ? toNodeChip(canvas, notice.target.node_id) : "Global notice";
|
|
15161
|
-
return /* @__PURE__ */
|
|
15162
|
-
/* @__PURE__ */
|
|
15163
|
-
/* @__PURE__ */
|
|
15164
|
-
/* @__PURE__ */
|
|
15165
|
-
/* @__PURE__ */
|
|
15166
|
-
/* @__PURE__ */
|
|
15167
|
-
/* @__PURE__ */
|
|
16455
|
+
return /* @__PURE__ */ jsx84("div", { className: "rounded-2xl border border-slate-200 bg-white p-4 shadow-sm dark:border-slate-800 dark:bg-slate-950/90", children: /* @__PURE__ */ jsxs62("div", { className: "flex items-start gap-3", children: [
|
|
16456
|
+
/* @__PURE__ */ jsx84("div", { className: "mt-0.5", children: iconForSeverity(notice.severity) }),
|
|
16457
|
+
/* @__PURE__ */ jsxs62("div", { className: "min-w-0 flex-1 space-y-2", children: [
|
|
16458
|
+
/* @__PURE__ */ jsxs62("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
16459
|
+
/* @__PURE__ */ jsx84("span", { className: severityBadgeClassName(notice.severity), children: notice.kind }),
|
|
16460
|
+
/* @__PURE__ */ jsx84("span", { className: "rounded-full bg-slate-100 px-2.5 py-1 text-[10px] font-semibold tracking-[0.16em] text-slate-600 uppercase dark:bg-slate-900 dark:text-slate-300", children: notice.type }),
|
|
16461
|
+
/* @__PURE__ */ jsx84("span", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: notice.title })
|
|
15168
16462
|
] }),
|
|
15169
|
-
notice.description ? /* @__PURE__ */
|
|
15170
|
-
notice.reason ? /* @__PURE__ */
|
|
16463
|
+
notice.description ? /* @__PURE__ */ jsx84("p", { className: "text-sm text-slate-600 dark:text-slate-300", children: notice.description }) : null,
|
|
16464
|
+
notice.reason ? /* @__PURE__ */ jsxs62("p", { className: "text-xs text-slate-500 dark:text-slate-400", children: [
|
|
15171
16465
|
"Reason: ",
|
|
15172
16466
|
notice.reason
|
|
15173
16467
|
] }) : null,
|
|
15174
|
-
/* @__PURE__ */
|
|
15175
|
-
notice.target.scope === "node" ? /* @__PURE__ */
|
|
16468
|
+
/* @__PURE__ */ jsxs62("div", { className: "flex flex-wrap items-center gap-2 text-xs text-slate-500 dark:text-slate-400", children: [
|
|
16469
|
+
notice.target.scope === "node" ? /* @__PURE__ */ jsx84(
|
|
15176
16470
|
"button",
|
|
15177
16471
|
{
|
|
15178
16472
|
type: "button",
|
|
@@ -15180,13 +16474,13 @@ function NoticeCard({ notice, onNodeClick }) {
|
|
|
15180
16474
|
className: "rounded-full bg-slate-100 px-2.5 py-1 text-xs text-slate-700 transition hover:bg-slate-200 dark:bg-slate-900 dark:text-slate-300 dark:hover:bg-slate-800",
|
|
15181
16475
|
children: targetChip
|
|
15182
16476
|
}
|
|
15183
|
-
) : /* @__PURE__ */
|
|
15184
|
-
notice.marked_at ? /* @__PURE__ */
|
|
15185
|
-
notice.icon ? /* @__PURE__ */
|
|
16477
|
+
) : /* @__PURE__ */ jsx84("span", { className: "rounded-full bg-slate-100 px-2.5 py-1 text-xs text-slate-700 dark:bg-slate-900 dark:text-slate-300", children: targetChip }),
|
|
16478
|
+
notice.marked_at ? /* @__PURE__ */ jsx84("span", { children: new Date(notice.marked_at).toLocaleString() }) : null,
|
|
16479
|
+
notice.icon ? /* @__PURE__ */ jsxs62("span", { children: [
|
|
15186
16480
|
"Icon: ",
|
|
15187
16481
|
notice.icon
|
|
15188
16482
|
] }) : null,
|
|
15189
|
-
notice.color ? /* @__PURE__ */
|
|
16483
|
+
notice.color ? /* @__PURE__ */ jsxs62("span", { children: [
|
|
15190
16484
|
"Color: ",
|
|
15191
16485
|
notice.color
|
|
15192
16486
|
] }) : null
|
|
@@ -15197,19 +16491,19 @@ function NoticeCard({ notice, onNodeClick }) {
|
|
|
15197
16491
|
function ValidationCard({ row, onNodeClick }) {
|
|
15198
16492
|
const canvas = useCanvas20();
|
|
15199
16493
|
const scope = describeValidationScope(canvas, row);
|
|
15200
|
-
return /* @__PURE__ */
|
|
16494
|
+
return /* @__PURE__ */ jsx84(
|
|
15201
16495
|
"div",
|
|
15202
16496
|
{
|
|
15203
16497
|
className: "rounded-2xl border border-slate-200 bg-white p-4 shadow-sm dark:border-slate-800 dark:bg-slate-950/90",
|
|
15204
16498
|
onClick: () => scope.length && canvas.api.setHighlighted(scope),
|
|
15205
|
-
children: /* @__PURE__ */
|
|
15206
|
-
/* @__PURE__ */
|
|
15207
|
-
/* @__PURE__ */
|
|
15208
|
-
/* @__PURE__ */
|
|
15209
|
-
/* @__PURE__ */
|
|
15210
|
-
/* @__PURE__ */
|
|
16499
|
+
children: /* @__PURE__ */ jsxs62("div", { className: "flex items-start gap-3", children: [
|
|
16500
|
+
/* @__PURE__ */ jsx84("div", { className: "mt-0.5", children: iconForSeverity(row.severity) }),
|
|
16501
|
+
/* @__PURE__ */ jsxs62("div", { className: "min-w-0 flex-1", children: [
|
|
16502
|
+
/* @__PURE__ */ jsxs62("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
16503
|
+
/* @__PURE__ */ jsx84("span", { className: severityBadgeClassName(row.severity), children: row.code.replaceAll("_", " ") }),
|
|
16504
|
+
/* @__PURE__ */ jsx84("span", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: row.message })
|
|
15211
16505
|
] }),
|
|
15212
|
-
scope.length ? /* @__PURE__ */
|
|
16506
|
+
scope.length ? /* @__PURE__ */ jsx84("div", { className: "mt-3 flex flex-wrap gap-2", children: scope.map((item) => /* @__PURE__ */ jsx84(
|
|
15213
16507
|
"span",
|
|
15214
16508
|
{
|
|
15215
16509
|
onClick: () => onNodeClick(row.nodeId),
|
|
@@ -15224,17 +16518,17 @@ function ValidationCard({ row, onNodeClick }) {
|
|
|
15224
16518
|
);
|
|
15225
16519
|
}
|
|
15226
16520
|
function LogCard({ row, onRemove }) {
|
|
15227
|
-
return /* @__PURE__ */
|
|
15228
|
-
/* @__PURE__ */
|
|
15229
|
-
/* @__PURE__ */
|
|
15230
|
-
/* @__PURE__ */
|
|
15231
|
-
/* @__PURE__ */
|
|
15232
|
-
/* @__PURE__ */
|
|
16521
|
+
return /* @__PURE__ */ jsx84("div", { className: "rounded-2xl border border-slate-200 bg-white p-4 shadow-sm dark:border-slate-800 dark:bg-slate-950/90", children: /* @__PURE__ */ jsxs62("div", { className: "flex items-start gap-3", children: [
|
|
16522
|
+
/* @__PURE__ */ jsx84("div", { className: "mt-0.5", children: /* @__PURE__ */ jsx84(FiInfo3, { className: "text-lg text-sky-500" }) }),
|
|
16523
|
+
/* @__PURE__ */ jsxs62("div", { className: "min-w-0 flex-1", children: [
|
|
16524
|
+
/* @__PURE__ */ jsxs62("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
16525
|
+
/* @__PURE__ */ jsx84("span", { className: "rounded-full bg-sky-100 px-2.5 py-1 text-[10px] font-semibold tracking-[0.16em] text-sky-700 uppercase dark:bg-sky-500/15 dark:text-sky-200", children: row.code ?? "log" }),
|
|
16526
|
+
/* @__PURE__ */ jsx84("span", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: row.message })
|
|
15233
16527
|
] }),
|
|
15234
|
-
/* @__PURE__ */
|
|
15235
|
-
/* @__PURE__ */
|
|
15236
|
-
/* @__PURE__ */
|
|
15237
|
-
/* @__PURE__ */
|
|
16528
|
+
/* @__PURE__ */ jsxs62("div", { className: "mt-3 flex items-center justify-between gap-3 text-xs text-slate-500 dark:text-slate-400", children: [
|
|
16529
|
+
/* @__PURE__ */ jsx84("span", { children: new Date(row.createdAt).toLocaleTimeString() }),
|
|
16530
|
+
/* @__PURE__ */ jsxs62(Button, { type: "button", variant: "ghost", size: "sm", onClick: onRemove, className: "h-7 rounded-xl px-2 text-xs", children: [
|
|
16531
|
+
/* @__PURE__ */ jsx84(FiX5, {}),
|
|
15238
16532
|
"Dismiss"
|
|
15239
16533
|
] })
|
|
15240
16534
|
] })
|
|
@@ -15243,8 +16537,8 @@ function LogCard({ row, onRemove }) {
|
|
|
15243
16537
|
}
|
|
15244
16538
|
|
|
15245
16539
|
// src/workspace/bottom-panel/service-picker-dialog.tsx
|
|
15246
|
-
import { InputField as
|
|
15247
|
-
import { useEffect as
|
|
16540
|
+
import { InputField as InputField19 } from "@timeax/form-palette";
|
|
16541
|
+
import { useEffect as useEffect24, useMemo as useMemo39, useState as useState39 } from "react";
|
|
15248
16542
|
import { createPortal as createPortal5 } from "react-dom";
|
|
15249
16543
|
|
|
15250
16544
|
// src/workspace/bottom-panel/service-picker.ts
|
|
@@ -15362,7 +16656,7 @@ function isScalar(value) {
|
|
|
15362
16656
|
}
|
|
15363
16657
|
|
|
15364
16658
|
// src/workspace/bottom-panel/service-picker-dialog.tsx
|
|
15365
|
-
import { jsx as
|
|
16659
|
+
import { jsx as jsx85, jsxs as jsxs63 } from "react/jsx-runtime";
|
|
15366
16660
|
function ServicePickerDialog({
|
|
15367
16661
|
open,
|
|
15368
16662
|
groupLabel,
|
|
@@ -15373,14 +16667,14 @@ function ServicePickerDialog({
|
|
|
15373
16667
|
onOpenChange,
|
|
15374
16668
|
onConfirm
|
|
15375
16669
|
}) {
|
|
15376
|
-
const [filters, setFilters] =
|
|
15377
|
-
const [selectedIds, setSelectedIds] =
|
|
15378
|
-
|
|
16670
|
+
const [filters, setFilters] = useState39(() => createDefaultServicePickerFilters());
|
|
16671
|
+
const [selectedIds, setSelectedIds] = useState39(/* @__PURE__ */ new Set());
|
|
16672
|
+
useEffect24(() => {
|
|
15379
16673
|
if (!open) return;
|
|
15380
16674
|
setFilters(createDefaultServicePickerFilters());
|
|
15381
16675
|
setSelectedIds(/* @__PURE__ */ new Set());
|
|
15382
16676
|
}, [open]);
|
|
15383
|
-
|
|
16677
|
+
useEffect24(() => {
|
|
15384
16678
|
if (!open) return;
|
|
15385
16679
|
const onKeyDown = (event) => {
|
|
15386
16680
|
if (event.key === "Escape") onOpenChange(false);
|
|
@@ -15388,14 +16682,14 @@ function ServicePickerDialog({
|
|
|
15388
16682
|
window.addEventListener("keydown", onKeyDown);
|
|
15389
16683
|
return () => window.removeEventListener("keydown", onKeyDown);
|
|
15390
16684
|
}, [onOpenChange, open]);
|
|
15391
|
-
const categories =
|
|
16685
|
+
const categories = useMemo39(
|
|
15392
16686
|
() => Array.from(new Set(services2.map((service) => service.category).filter(Boolean))).sort((a, b) => a.localeCompare(b)),
|
|
15393
16687
|
[services2]
|
|
15394
16688
|
);
|
|
15395
|
-
const flags =
|
|
15396
|
-
const metaPaths =
|
|
16689
|
+
const flags = useMemo39(() => Array.from(new Set(services2.flatMap((service) => service.flags))).sort((a, b) => a.localeCompare(b)), [services2]);
|
|
16690
|
+
const metaPaths = useMemo39(() => discoverServiceMetaPaths(Object.values(serviceMap)), [serviceMap]);
|
|
15397
16691
|
const metaValues = metaPaths.find((entry) => entry.path === filters.metaPath)?.values ?? [];
|
|
15398
|
-
const filteredServices =
|
|
16692
|
+
const filteredServices = useMemo39(
|
|
15399
16693
|
() => filterServicePickerServices({
|
|
15400
16694
|
services: services2,
|
|
15401
16695
|
serviceMap,
|
|
@@ -15408,7 +16702,7 @@ function ServicePickerDialog({
|
|
|
15408
16702
|
const selectedCount = selectedIds.size;
|
|
15409
16703
|
const canConfirm = selectedCount > 0;
|
|
15410
16704
|
return createPortal5(
|
|
15411
|
-
/* @__PURE__ */
|
|
16705
|
+
/* @__PURE__ */ jsx85("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-slate-950/45 p-4", children: /* @__PURE__ */ jsxs63(
|
|
15412
16706
|
"div",
|
|
15413
16707
|
{
|
|
15414
16708
|
role: "dialog",
|
|
@@ -15416,17 +16710,17 @@ function ServicePickerDialog({
|
|
|
15416
16710
|
"aria-label": "Service picker",
|
|
15417
16711
|
className: "flex h-[min(80vh,42rem)] w-[min(72rem,calc(100vw-2rem))] flex-col overflow-hidden rounded-3xl border border-slate-200 bg-white shadow-2xl dark:border-slate-800 dark:bg-slate-950",
|
|
15418
16712
|
children: [
|
|
15419
|
-
/* @__PURE__ */
|
|
15420
|
-
/* @__PURE__ */
|
|
15421
|
-
/* @__PURE__ */
|
|
15422
|
-
/* @__PURE__ */
|
|
16713
|
+
/* @__PURE__ */ jsx85("div", { className: "border-b border-slate-200 px-5 py-4 dark:border-slate-800", children: /* @__PURE__ */ jsxs63("div", { className: "flex items-start justify-between gap-4", children: [
|
|
16714
|
+
/* @__PURE__ */ jsxs63("div", { children: [
|
|
16715
|
+
/* @__PURE__ */ jsx85("h3", { className: "text-lg font-semibold text-slate-900 dark:text-slate-100", children: "Assign services to group" }),
|
|
16716
|
+
/* @__PURE__ */ jsx85("p", { className: "mt-1 text-sm text-slate-500 dark:text-slate-400", children: groupLabel ? `Pick one or more services to append into ${groupLabel}.` : "Pick one or more services to append into the selected catalog group." })
|
|
15423
16717
|
] }),
|
|
15424
|
-
/* @__PURE__ */
|
|
16718
|
+
/* @__PURE__ */ jsx85(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => onOpenChange(false), className: "rounded-xl", children: "Close" })
|
|
15425
16719
|
] }) }),
|
|
15426
|
-
/* @__PURE__ */
|
|
15427
|
-
/* @__PURE__ */
|
|
15428
|
-
/* @__PURE__ */
|
|
15429
|
-
|
|
16720
|
+
/* @__PURE__ */ jsxs63("div", { className: "grid h-full min-h-0 flex-1 overflow-hidden md:grid-cols-[18rem_minmax(0,1fr)]", children: [
|
|
16721
|
+
/* @__PURE__ */ jsx85("div", { className: "min-h-0 border-r border-slate-200 dark:border-slate-800", children: /* @__PURE__ */ jsx85(ScrollArea, { className: "h-full min-h-0", children: /* @__PURE__ */ jsxs63("div", { className: "space-y-4 p-4", children: [
|
|
16722
|
+
/* @__PURE__ */ jsx85(FilterField, { label: "Search", children: /* @__PURE__ */ jsx85(
|
|
16723
|
+
InputField19,
|
|
15430
16724
|
{
|
|
15431
16725
|
variant: "text",
|
|
15432
16726
|
label: "Picker search",
|
|
@@ -15436,8 +16730,8 @@ function ServicePickerDialog({
|
|
|
15436
16730
|
autoComplete: "off"
|
|
15437
16731
|
}
|
|
15438
16732
|
) }),
|
|
15439
|
-
/* @__PURE__ */
|
|
15440
|
-
|
|
16733
|
+
/* @__PURE__ */ jsx85(FilterField, { label: "Category", children: /* @__PURE__ */ jsx85(
|
|
16734
|
+
InputField19,
|
|
15441
16735
|
{
|
|
15442
16736
|
variant: "select",
|
|
15443
16737
|
label: "Category filter",
|
|
@@ -15447,8 +16741,8 @@ function ServicePickerDialog({
|
|
|
15447
16741
|
onChange: (event) => setFilters((current) => ({ ...current, category: String(event.value ?? "") }))
|
|
15448
16742
|
}
|
|
15449
16743
|
) }),
|
|
15450
|
-
/* @__PURE__ */
|
|
15451
|
-
|
|
16744
|
+
/* @__PURE__ */ jsx85(FilterField, { label: "Flag", children: /* @__PURE__ */ jsx85(
|
|
16745
|
+
InputField19,
|
|
15452
16746
|
{
|
|
15453
16747
|
variant: "select",
|
|
15454
16748
|
label: "Flag filter",
|
|
@@ -15458,8 +16752,8 @@ function ServicePickerDialog({
|
|
|
15458
16752
|
onChange: (event) => setFilters((current) => ({ ...current, flag: String(event.value ?? "") }))
|
|
15459
16753
|
}
|
|
15460
16754
|
) }),
|
|
15461
|
-
/* @__PURE__ */
|
|
15462
|
-
|
|
16755
|
+
/* @__PURE__ */ jsx85(FilterField, { label: "Activity", children: /* @__PURE__ */ jsx85(
|
|
16756
|
+
InputField19,
|
|
15463
16757
|
{
|
|
15464
16758
|
variant: "select",
|
|
15465
16759
|
label: "Activity filter",
|
|
@@ -15475,9 +16769,9 @@ function ServicePickerDialog({
|
|
|
15475
16769
|
}))
|
|
15476
16770
|
}
|
|
15477
16771
|
) }),
|
|
15478
|
-
/* @__PURE__ */
|
|
15479
|
-
/* @__PURE__ */
|
|
15480
|
-
|
|
16772
|
+
/* @__PURE__ */ jsxs63("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
16773
|
+
/* @__PURE__ */ jsx85(FilterField, { label: "Min rate", children: /* @__PURE__ */ jsx85(
|
|
16774
|
+
InputField19,
|
|
15481
16775
|
{
|
|
15482
16776
|
variant: "number",
|
|
15483
16777
|
label: "Minimum rate filter",
|
|
@@ -15487,8 +16781,8 @@ function ServicePickerDialog({
|
|
|
15487
16781
|
autoComplete: "off"
|
|
15488
16782
|
}
|
|
15489
16783
|
) }),
|
|
15490
|
-
/* @__PURE__ */
|
|
15491
|
-
|
|
16784
|
+
/* @__PURE__ */ jsx85(FilterField, { label: "Max rate", children: /* @__PURE__ */ jsx85(
|
|
16785
|
+
InputField19,
|
|
15492
16786
|
{
|
|
15493
16787
|
variant: "number",
|
|
15494
16788
|
label: "Maximum rate filter",
|
|
@@ -15499,9 +16793,9 @@ function ServicePickerDialog({
|
|
|
15499
16793
|
}
|
|
15500
16794
|
) })
|
|
15501
16795
|
] }),
|
|
15502
|
-
/* @__PURE__ */
|
|
15503
|
-
/* @__PURE__ */
|
|
15504
|
-
|
|
16796
|
+
/* @__PURE__ */ jsx85(FilterField, { label: "Name keyword", children: /* @__PURE__ */ jsxs63("div", { className: "space-y-2", children: [
|
|
16797
|
+
/* @__PURE__ */ jsx85(
|
|
16798
|
+
InputField19,
|
|
15505
16799
|
{
|
|
15506
16800
|
variant: "select",
|
|
15507
16801
|
label: "Keyword mode",
|
|
@@ -15516,8 +16810,8 @@ function ServicePickerDialog({
|
|
|
15516
16810
|
}))
|
|
15517
16811
|
}
|
|
15518
16812
|
),
|
|
15519
|
-
/* @__PURE__ */
|
|
15520
|
-
|
|
16813
|
+
/* @__PURE__ */ jsx85(
|
|
16814
|
+
InputField19,
|
|
15521
16815
|
{
|
|
15522
16816
|
variant: "text",
|
|
15523
16817
|
label: "Keyword filter",
|
|
@@ -15528,8 +16822,8 @@ function ServicePickerDialog({
|
|
|
15528
16822
|
}
|
|
15529
16823
|
)
|
|
15530
16824
|
] }) }),
|
|
15531
|
-
/* @__PURE__ */
|
|
15532
|
-
|
|
16825
|
+
/* @__PURE__ */ jsx85(FilterField, { label: "Meta key", children: /* @__PURE__ */ jsx85(
|
|
16826
|
+
InputField19,
|
|
15533
16827
|
{
|
|
15534
16828
|
variant: "select",
|
|
15535
16829
|
label: "Meta key filter",
|
|
@@ -15543,8 +16837,8 @@ function ServicePickerDialog({
|
|
|
15543
16837
|
}))
|
|
15544
16838
|
}
|
|
15545
16839
|
) }),
|
|
15546
|
-
/* @__PURE__ */
|
|
15547
|
-
|
|
16840
|
+
/* @__PURE__ */ jsx85(FilterField, { label: "Meta value", children: /* @__PURE__ */ jsx85(
|
|
16841
|
+
InputField19,
|
|
15548
16842
|
{
|
|
15549
16843
|
variant: "select",
|
|
15550
16844
|
label: "Meta value filter",
|
|
@@ -15555,7 +16849,7 @@ function ServicePickerDialog({
|
|
|
15555
16849
|
onChange: (event) => setFilters((current) => ({ ...current, metaValue: String(event.value ?? "") }))
|
|
15556
16850
|
}
|
|
15557
16851
|
) }),
|
|
15558
|
-
/* @__PURE__ */
|
|
16852
|
+
/* @__PURE__ */ jsx85("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx85(
|
|
15559
16853
|
Button,
|
|
15560
16854
|
{
|
|
15561
16855
|
type: "button",
|
|
@@ -15570,18 +16864,18 @@ function ServicePickerDialog({
|
|
|
15570
16864
|
}
|
|
15571
16865
|
) })
|
|
15572
16866
|
] }) }) }),
|
|
15573
|
-
/* @__PURE__ */
|
|
15574
|
-
/* @__PURE__ */
|
|
16867
|
+
/* @__PURE__ */ jsxs63("div", { className: "flex min-h-0 flex-col overflow-hidden", children: [
|
|
16868
|
+
/* @__PURE__ */ jsxs63("div", { className: "border-b border-slate-200 px-4 py-3 text-sm text-slate-500 dark:border-slate-800 dark:text-slate-400", children: [
|
|
15575
16869
|
filteredServices.length,
|
|
15576
16870
|
" service",
|
|
15577
16871
|
filteredServices.length === 1 ? "" : "s",
|
|
15578
16872
|
" found"
|
|
15579
16873
|
] }),
|
|
15580
|
-
/* @__PURE__ */
|
|
16874
|
+
/* @__PURE__ */ jsx85(ScrollArea, { className: "h-full min-h-0 flex-1", children: /* @__PURE__ */ jsx85("div", { className: "space-y-2 p-4", children: filteredServices.length ? filteredServices.map((service) => {
|
|
15581
16875
|
const id = String(service.id);
|
|
15582
16876
|
const selected = selectedIds.has(id);
|
|
15583
16877
|
const alreadyAssigned = existingGroupServiceIds.has(id);
|
|
15584
|
-
return /* @__PURE__ */
|
|
16878
|
+
return /* @__PURE__ */ jsxs63(
|
|
15585
16879
|
"label",
|
|
15586
16880
|
{
|
|
15587
16881
|
className: cn(
|
|
@@ -15589,7 +16883,7 @@ function ServicePickerDialog({
|
|
|
15589
16883
|
selected ? "border-blue-300 bg-blue-50 dark:border-blue-500/40 dark:bg-blue-500/10" : "border-slate-200 bg-white hover:border-slate-300 hover:bg-slate-50 dark:border-slate-800 dark:bg-slate-950/60 dark:hover:border-slate-700"
|
|
15590
16884
|
),
|
|
15591
16885
|
children: [
|
|
15592
|
-
/* @__PURE__ */
|
|
16886
|
+
/* @__PURE__ */ jsx85(
|
|
15593
16887
|
"input",
|
|
15594
16888
|
{
|
|
15595
16889
|
type: "checkbox",
|
|
@@ -15603,21 +16897,21 @@ function ServicePickerDialog({
|
|
|
15603
16897
|
})
|
|
15604
16898
|
}
|
|
15605
16899
|
),
|
|
15606
|
-
/* @__PURE__ */
|
|
15607
|
-
/* @__PURE__ */
|
|
15608
|
-
/* @__PURE__ */
|
|
15609
|
-
/* @__PURE__ */
|
|
15610
|
-
/* @__PURE__ */
|
|
15611
|
-
/* @__PURE__ */
|
|
16900
|
+
/* @__PURE__ */ jsxs63("div", { className: "min-w-0 flex-1", children: [
|
|
16901
|
+
/* @__PURE__ */ jsxs63("div", { className: "flex items-center justify-between gap-3", children: [
|
|
16902
|
+
/* @__PURE__ */ jsxs63("div", { className: "min-w-0", children: [
|
|
16903
|
+
/* @__PURE__ */ jsx85("div", { className: "truncate text-sm font-semibold text-slate-900 dark:text-slate-100", children: service.name }),
|
|
16904
|
+
/* @__PURE__ */ jsxs63("div", { className: "mt-1 flex flex-wrap gap-2 text-xs text-slate-500 dark:text-slate-400", children: [
|
|
16905
|
+
/* @__PURE__ */ jsxs63("span", { children: [
|
|
15612
16906
|
"#",
|
|
15613
16907
|
service.id
|
|
15614
16908
|
] }),
|
|
15615
|
-
service.category ? /* @__PURE__ */
|
|
15616
|
-
service.platformId ? /* @__PURE__ */
|
|
16909
|
+
service.category ? /* @__PURE__ */ jsx85("span", { children: service.category }) : null,
|
|
16910
|
+
service.platformId ? /* @__PURE__ */ jsx85("span", { children: service.platformId }) : null
|
|
15617
16911
|
] })
|
|
15618
16912
|
] }),
|
|
15619
|
-
/* @__PURE__ */
|
|
15620
|
-
/* @__PURE__ */
|
|
16913
|
+
/* @__PURE__ */ jsxs63("div", { className: "flex items-center gap-2", children: [
|
|
16914
|
+
/* @__PURE__ */ jsx85(
|
|
15621
16915
|
ServiceMetaPopover,
|
|
15622
16916
|
{
|
|
15623
16917
|
meta: serviceMap[id]?.meta,
|
|
@@ -15625,34 +16919,34 @@ function ServicePickerDialog({
|
|
|
15625
16919
|
stopEventPropagation: true
|
|
15626
16920
|
}
|
|
15627
16921
|
),
|
|
15628
|
-
alreadyAssigned ? /* @__PURE__ */
|
|
16922
|
+
alreadyAssigned ? /* @__PURE__ */ jsx85("span", { className: "rounded-full bg-emerald-50 px-2.5 py-1 text-[11px] text-emerald-700 dark:bg-emerald-500/10 dark:text-emerald-200", children: "Already in group" }) : null
|
|
15629
16923
|
] })
|
|
15630
16924
|
] }),
|
|
15631
|
-
/* @__PURE__ */
|
|
15632
|
-
service.rate != null ? /* @__PURE__ */
|
|
16925
|
+
/* @__PURE__ */ jsxs63("div", { className: "mt-3 flex flex-wrap gap-2", children: [
|
|
16926
|
+
service.rate != null ? /* @__PURE__ */ jsxs63("span", { className: "rounded-full bg-slate-100 px-2.5 py-1 text-[11px] text-slate-600 dark:bg-slate-900 dark:text-slate-300", children: [
|
|
15633
16927
|
"Rate ",
|
|
15634
16928
|
service.rate
|
|
15635
16929
|
] }) : null,
|
|
15636
|
-
service.flags.slice(0, 3).map((flag) => /* @__PURE__ */
|
|
16930
|
+
service.flags.slice(0, 3).map((flag) => /* @__PURE__ */ jsx85("span", { className: "rounded-full bg-amber-50 px-2.5 py-1 text-[11px] text-amber-700 dark:bg-amber-500/10 dark:text-amber-200", children: flag }, flag))
|
|
15637
16931
|
] })
|
|
15638
16932
|
] })
|
|
15639
16933
|
]
|
|
15640
16934
|
},
|
|
15641
16935
|
id
|
|
15642
16936
|
);
|
|
15643
|
-
}) : /* @__PURE__ */
|
|
16937
|
+
}) : /* @__PURE__ */ jsx85("div", { className: "rounded-2xl border border-dashed border-slate-300 px-4 py-10 text-center text-sm text-slate-500 dark:border-slate-700 dark:text-slate-400", children: "No services match the current filters." }) }) })
|
|
15644
16938
|
] })
|
|
15645
16939
|
] }),
|
|
15646
|
-
/* @__PURE__ */
|
|
15647
|
-
/* @__PURE__ */
|
|
16940
|
+
/* @__PURE__ */ jsxs63("div", { className: "flex items-center justify-between gap-3 border-t border-slate-200 px-5 py-4 dark:border-slate-800", children: [
|
|
16941
|
+
/* @__PURE__ */ jsxs63("div", { className: "text-sm text-slate-500 dark:text-slate-400", children: [
|
|
15648
16942
|
selectedCount,
|
|
15649
16943
|
" service",
|
|
15650
16944
|
selectedCount === 1 ? "" : "s",
|
|
15651
16945
|
" selected"
|
|
15652
16946
|
] }),
|
|
15653
|
-
/* @__PURE__ */
|
|
15654
|
-
/* @__PURE__ */
|
|
15655
|
-
/* @__PURE__ */
|
|
16947
|
+
/* @__PURE__ */ jsxs63("div", { className: "flex items-center gap-2", children: [
|
|
16948
|
+
/* @__PURE__ */ jsx85(Button, { type: "button", variant: "outline", onClick: () => onOpenChange(false), className: "rounded-xl", children: "Cancel" }),
|
|
16949
|
+
/* @__PURE__ */ jsx85(
|
|
15656
16950
|
Button,
|
|
15657
16951
|
{
|
|
15658
16952
|
type: "button",
|
|
@@ -15674,8 +16968,8 @@ function ServicePickerDialog({
|
|
|
15674
16968
|
);
|
|
15675
16969
|
}
|
|
15676
16970
|
function FilterField({ label, children }) {
|
|
15677
|
-
return /* @__PURE__ */
|
|
15678
|
-
/* @__PURE__ */
|
|
16971
|
+
return /* @__PURE__ */ jsxs63("label", { className: "block space-y-1.5", children: [
|
|
16972
|
+
/* @__PURE__ */ jsx85("span", { className: "text-[11px] font-semibold uppercase tracking-[0.16em] text-slate-500 dark:text-slate-400", children: label }),
|
|
15679
16973
|
children
|
|
15680
16974
|
] });
|
|
15681
16975
|
}
|
|
@@ -15686,73 +16980,36 @@ function toPickerSelectOptions(values) {
|
|
|
15686
16980
|
}));
|
|
15687
16981
|
}
|
|
15688
16982
|
|
|
15689
|
-
// src/components/ui/resizable.tsx
|
|
15690
|
-
import { GripVertical } from "lucide-react";
|
|
15691
|
-
import "react";
|
|
15692
|
-
import { Group as Group2, Panel as Panel3, Separator as Separator3 } from "react-resizable-panels";
|
|
15693
|
-
import { jsx as jsx77 } from "react/jsx-runtime";
|
|
15694
|
-
function ResizablePanelGroup({
|
|
15695
|
-
className,
|
|
15696
|
-
direction = "horizontal",
|
|
15697
|
-
...props
|
|
15698
|
-
}) {
|
|
15699
|
-
return /* @__PURE__ */ jsx77(Group2, { className: cn("flex h-full w-full data-[group-orientation=vertical]:flex-col", className), orientation: direction, ...props });
|
|
15700
|
-
}
|
|
15701
|
-
function ResizablePanel({
|
|
15702
|
-
className,
|
|
15703
|
-
...props
|
|
15704
|
-
}) {
|
|
15705
|
-
return /* @__PURE__ */ jsx77(Panel3, { className: cn("min-h-0 min-w-0", className), ...props });
|
|
15706
|
-
}
|
|
15707
|
-
function ResizableHandle({
|
|
15708
|
-
withHandle,
|
|
15709
|
-
className,
|
|
15710
|
-
...props
|
|
15711
|
-
}) {
|
|
15712
|
-
return /* @__PURE__ */ jsx77(
|
|
15713
|
-
Separator3,
|
|
15714
|
-
{
|
|
15715
|
-
className: cn(
|
|
15716
|
-
"relative flex w-3 shrink-0 items-center justify-center bg-transparent outline-none transition-colors after:absolute after:inset-y-3 after:left-1/2 after:w-px after:-translate-x-1/2 after:rounded-full after:bg-slate-200 dark:after:bg-slate-800",
|
|
15717
|
-
"hover:after:bg-slate-300 dark:hover:after:bg-slate-700",
|
|
15718
|
-
className
|
|
15719
|
-
),
|
|
15720
|
-
...props,
|
|
15721
|
-
children: withHandle ? /* @__PURE__ */ jsx77("div", { className: "z-10 flex h-10 w-3 items-center justify-center rounded-full border border-slate-200 bg-white text-slate-400 shadow-sm dark:border-slate-800 dark:bg-slate-950 dark:text-slate-500", children: /* @__PURE__ */ jsx77(GripVertical, { className: "h-3.5 w-3.5" }) }) : null
|
|
15722
|
-
}
|
|
15723
|
-
);
|
|
15724
|
-
}
|
|
15725
|
-
|
|
15726
16983
|
// src/workspace/bottom-panel/services-split-pane.tsx
|
|
15727
|
-
import { InputField as
|
|
15728
|
-
import { useEffect as
|
|
16984
|
+
import { InputField as InputField20 } from "@timeax/form-palette";
|
|
16985
|
+
import { useEffect as useEffect25, useState as useState40 } from "react";
|
|
15729
16986
|
import { FaFolderOpen as FaFolderOpen2 } from "react-icons/fa";
|
|
15730
16987
|
import { FiEdit2, FiFilter as FiFilter2, FiFolderPlus, FiPlus as FiPlus2, FiTrash2 as FiTrash22 } from "react-icons/fi";
|
|
15731
16988
|
|
|
15732
16989
|
// src/workspace/bottom-panel/service-detail-card.tsx
|
|
15733
|
-
import { jsx as
|
|
16990
|
+
import { jsx as jsx86, jsxs as jsxs64 } from "react/jsx-runtime";
|
|
15734
16991
|
function ServiceDetailCard({ mode, row, snapshot, onNodeClick, onOpenFallbackQuickAdd, onOpenFallbackEditor }) {
|
|
15735
16992
|
const summary = row.summary;
|
|
15736
16993
|
const service = row.service;
|
|
15737
|
-
return /* @__PURE__ */
|
|
15738
|
-
/* @__PURE__ */
|
|
15739
|
-
/* @__PURE__ */
|
|
15740
|
-
/* @__PURE__ */
|
|
15741
|
-
/* @__PURE__ */
|
|
15742
|
-
/* @__PURE__ */
|
|
15743
|
-
/* @__PURE__ */
|
|
16994
|
+
return /* @__PURE__ */ jsxs64("div", { className: "space-y-5", children: [
|
|
16995
|
+
/* @__PURE__ */ jsxs64("div", { className: "rounded-3xl border border-slate-200 bg-slate-50/80 p-5 dark:border-slate-800 dark:bg-slate-900/40", children: [
|
|
16996
|
+
/* @__PURE__ */ jsxs64("div", { className: "flex flex-wrap items-start justify-between gap-4", children: [
|
|
16997
|
+
/* @__PURE__ */ jsxs64("div", { className: "min-w-0", children: [
|
|
16998
|
+
/* @__PURE__ */ jsxs64("div", { className: "flex items-center gap-2", children: [
|
|
16999
|
+
/* @__PURE__ */ jsx86(StatusDot, { tone: row.statusTone, className: "mt-0.5" }),
|
|
17000
|
+
/* @__PURE__ */ jsxs64("span", { children: [
|
|
15744
17001
|
"#",
|
|
15745
17002
|
summary.id
|
|
15746
17003
|
] })
|
|
15747
17004
|
] }),
|
|
15748
|
-
/* @__PURE__ */
|
|
15749
|
-
summary.category ? /* @__PURE__ */
|
|
15750
|
-
summary.platformId ? /* @__PURE__ */
|
|
17005
|
+
/* @__PURE__ */ jsxs64("div", { className: "mt-2 flex flex-wrap gap-2 text-xs text-slate-500 dark:text-slate-400", children: [
|
|
17006
|
+
summary.category ? /* @__PURE__ */ jsx86("span", { children: summary.category }) : null,
|
|
17007
|
+
summary.platformId ? /* @__PURE__ */ jsx86("span", { children: summary.platformId }) : null
|
|
15751
17008
|
] })
|
|
15752
17009
|
] }),
|
|
15753
|
-
/* @__PURE__ */
|
|
15754
|
-
/* @__PURE__ */
|
|
15755
|
-
mode === "active" && onOpenFallbackQuickAdd ? /* @__PURE__ */
|
|
17010
|
+
/* @__PURE__ */ jsxs64("div", { className: "flex items-center gap-2", children: [
|
|
17011
|
+
/* @__PURE__ */ jsx86(ServiceMetaPopover, { meta: service?.meta }),
|
|
17012
|
+
mode === "active" && onOpenFallbackQuickAdd ? /* @__PURE__ */ jsx86(
|
|
15756
17013
|
"button",
|
|
15757
17014
|
{
|
|
15758
17015
|
type: "button",
|
|
@@ -15761,7 +17018,7 @@ function ServiceDetailCard({ mode, row, snapshot, onNodeClick, onOpenFallbackQui
|
|
|
15761
17018
|
children: "Add fallbacks"
|
|
15762
17019
|
}
|
|
15763
17020
|
) : null,
|
|
15764
|
-
mode === "active" && onOpenFallbackEditor ? /* @__PURE__ */
|
|
17021
|
+
mode === "active" && onOpenFallbackEditor ? /* @__PURE__ */ jsx86(
|
|
15765
17022
|
"button",
|
|
15766
17023
|
{
|
|
15767
17024
|
type: "button",
|
|
@@ -15770,41 +17027,41 @@ function ServiceDetailCard({ mode, row, snapshot, onNodeClick, onOpenFallbackQui
|
|
|
15770
17027
|
children: "Open fallback editor"
|
|
15771
17028
|
}
|
|
15772
17029
|
) : null,
|
|
15773
|
-
/* @__PURE__ */
|
|
17030
|
+
/* @__PURE__ */ jsx86("span", { className: statusBadgeClassName(row.statusTone), children: row.statusLabel })
|
|
15774
17031
|
] })
|
|
15775
17032
|
] }),
|
|
15776
|
-
/* @__PURE__ */
|
|
15777
|
-
/* @__PURE__ */
|
|
15778
|
-
/* @__PURE__ */
|
|
15779
|
-
/* @__PURE__ */
|
|
15780
|
-
/* @__PURE__ */
|
|
17033
|
+
/* @__PURE__ */ jsxs64("div", { className: "mt-4 grid gap-3 sm:grid-cols-2", children: [
|
|
17034
|
+
/* @__PURE__ */ jsx86(DetailMetric, { label: "Rate", value: summary.rate != null ? String(summary.rate) : "Not set" }),
|
|
17035
|
+
/* @__PURE__ */ jsx86(DetailMetric, { label: "Estimate", value: summary.estimate ?? "No estimate" }),
|
|
17036
|
+
/* @__PURE__ */ jsx86(DetailMetric, { label: "Min", value: summary.min != null ? String(summary.min) : "0" }),
|
|
17037
|
+
/* @__PURE__ */ jsx86(DetailMetric, { label: "Max", value: summary.max != null ? String(summary.max) : "Unlimited" })
|
|
15781
17038
|
] })
|
|
15782
17039
|
] }),
|
|
15783
|
-
mode !== "active" ? /* @__PURE__ */
|
|
15784
|
-
/* @__PURE__ */
|
|
17040
|
+
mode !== "active" ? /* @__PURE__ */ jsxs64("section", { className: "space-y-3", children: [
|
|
17041
|
+
/* @__PURE__ */ jsx86(
|
|
15785
17042
|
SectionTitle2,
|
|
15786
17043
|
{
|
|
15787
17044
|
title: "Context fit",
|
|
15788
17045
|
description: mode === "catalog" ? "This summary shows how the service fits the current visible-group context while browsing catalog groups." : "This summary shows how the service fits the current visible-group context."
|
|
15789
17046
|
}
|
|
15790
17047
|
),
|
|
15791
|
-
/* @__PURE__ */
|
|
15792
|
-
/* @__PURE__ */
|
|
15793
|
-
/* @__PURE__ */
|
|
17048
|
+
/* @__PURE__ */ jsxs64("div", { className: "rounded-2xl border border-slate-200 bg-white p-4 dark:border-slate-800 dark:bg-slate-950/80", children: [
|
|
17049
|
+
/* @__PURE__ */ jsxs64("div", { className: "flex flex-wrap gap-2", children: [
|
|
17050
|
+
/* @__PURE__ */ jsx86(
|
|
15794
17051
|
FilterChip,
|
|
15795
17052
|
{
|
|
15796
17053
|
label: row.check?.fitsConstraints ? "Constraints fit" : "Constraint mismatch",
|
|
15797
17054
|
tone: row.check?.fitsConstraints ? "success" : "danger"
|
|
15798
17055
|
}
|
|
15799
17056
|
),
|
|
15800
|
-
/* @__PURE__ */
|
|
17057
|
+
/* @__PURE__ */ jsx86(
|
|
15801
17058
|
FilterChip,
|
|
15802
17059
|
{
|
|
15803
17060
|
label: row.check?.passesRate ? "Rate ok" : "Rate blocked",
|
|
15804
17061
|
tone: row.check?.passesRate ? "success" : "warning"
|
|
15805
17062
|
}
|
|
15806
17063
|
),
|
|
15807
|
-
/* @__PURE__ */
|
|
17064
|
+
/* @__PURE__ */ jsx86(
|
|
15808
17065
|
FilterChip,
|
|
15809
17066
|
{
|
|
15810
17067
|
label: snapshot?.state.enforcePolicies === false ? "Policies relaxed" : row.check?.passesPolicies ? "Policies pass" : "Policy blocked",
|
|
@@ -15812,20 +17069,20 @@ function ServiceDetailCard({ mode, row, snapshot, onNodeClick, onOpenFallbackQui
|
|
|
15812
17069
|
}
|
|
15813
17070
|
)
|
|
15814
17071
|
] }),
|
|
15815
|
-
row.reasonLabels.length ? /* @__PURE__ */
|
|
17072
|
+
row.reasonLabels.length ? /* @__PURE__ */ jsx86("div", { className: "mt-3 flex flex-wrap gap-2", children: row.reasonLabels.map((reason) => /* @__PURE__ */ jsx86(
|
|
15816
17073
|
"span",
|
|
15817
17074
|
{
|
|
15818
17075
|
className: "rounded-full bg-amber-50 px-2.5 py-1 text-xs text-amber-700 dark:bg-amber-500/10 dark:text-amber-200",
|
|
15819
17076
|
children: reason
|
|
15820
17077
|
},
|
|
15821
17078
|
`${row.id}:${reason}`
|
|
15822
|
-
)) }) : /* @__PURE__ */
|
|
17079
|
+
)) }) : /* @__PURE__ */ jsx86("p", { className: "mt-3 text-sm text-slate-500 dark:text-slate-400", children: "This service is a clean fit for the current visible-group and selected-trigger context." })
|
|
15823
17080
|
] })
|
|
15824
17081
|
] }) : null,
|
|
15825
|
-
/* @__PURE__ */
|
|
15826
|
-
/* @__PURE__ */
|
|
15827
|
-
/* @__PURE__ */
|
|
15828
|
-
summary.flags.map((flag) => /* @__PURE__ */
|
|
17082
|
+
/* @__PURE__ */ jsxs64("section", { className: "space-y-3", children: [
|
|
17083
|
+
/* @__PURE__ */ jsx86(SectionTitle2, { title: "Capabilities", description: "Flags and pricing hints attached to this service." }),
|
|
17084
|
+
/* @__PURE__ */ jsx86("div", { className: "rounded-2xl border border-slate-200 bg-white p-4 dark:border-slate-800 dark:bg-slate-950/80", children: summary.flags.length || service?.meta ? /* @__PURE__ */ jsxs64("div", { className: "flex flex-wrap gap-2", children: [
|
|
17085
|
+
summary.flags.map((flag) => /* @__PURE__ */ jsx86(
|
|
15829
17086
|
"span",
|
|
15830
17087
|
{
|
|
15831
17088
|
className: "rounded-full bg-emerald-50 px-2.5 py-1 text-xs text-emerald-700 dark:bg-emerald-500/10 dark:text-emerald-200",
|
|
@@ -15833,7 +17090,7 @@ function ServiceDetailCard({ mode, row, snapshot, onNodeClick, onOpenFallbackQui
|
|
|
15833
17090
|
},
|
|
15834
17091
|
flag
|
|
15835
17092
|
)),
|
|
15836
|
-
Object.keys(service?.meta ?? {}).slice(0, 3).map((key) => /* @__PURE__ */
|
|
17093
|
+
Object.keys(service?.meta ?? {}).slice(0, 3).map((key) => /* @__PURE__ */ jsx86(
|
|
15837
17094
|
"span",
|
|
15838
17095
|
{
|
|
15839
17096
|
className: "rounded-full bg-slate-100 px-2.5 py-1 text-xs text-slate-600 dark:bg-slate-900 dark:text-slate-300",
|
|
@@ -15841,17 +17098,17 @@ function ServiceDetailCard({ mode, row, snapshot, onNodeClick, onOpenFallbackQui
|
|
|
15841
17098
|
},
|
|
15842
17099
|
key
|
|
15843
17100
|
))
|
|
15844
|
-
] }) : /* @__PURE__ */
|
|
17101
|
+
] }) : /* @__PURE__ */ jsx86("p", { className: "text-sm text-slate-500 dark:text-slate-400", children: "No capability flags were published for this service." }) })
|
|
15845
17102
|
] }),
|
|
15846
|
-
/* @__PURE__ */
|
|
15847
|
-
/* @__PURE__ */
|
|
17103
|
+
/* @__PURE__ */ jsxs64("section", { className: "space-y-3", children: [
|
|
17104
|
+
/* @__PURE__ */ jsx86(
|
|
15848
17105
|
SectionTitle2,
|
|
15849
17106
|
{
|
|
15850
17107
|
title: "Bindings",
|
|
15851
17108
|
description: "Nodes currently connected to this service. Click any node to jump back into the canvas."
|
|
15852
17109
|
}
|
|
15853
17110
|
),
|
|
15854
|
-
/* @__PURE__ */
|
|
17111
|
+
/* @__PURE__ */ jsx86("div", { className: "rounded-2xl border border-slate-200 bg-white p-4 dark:border-slate-800 dark:bg-slate-950/80", children: summary.attachedNodeIds.length ? /* @__PURE__ */ jsx86("div", { className: "flex flex-wrap gap-2", children: summary.attachedNodeIds.map((nodeId, index) => /* @__PURE__ */ jsx86(
|
|
15855
17112
|
"button",
|
|
15856
17113
|
{
|
|
15857
17114
|
type: "button",
|
|
@@ -15860,58 +17117,59 @@ function ServiceDetailCard({ mode, row, snapshot, onNodeClick, onOpenFallbackQui
|
|
|
15860
17117
|
children: summary.attachedNodeLabels[index] ?? nodeId
|
|
15861
17118
|
},
|
|
15862
17119
|
`${row.id}:${nodeId}`
|
|
15863
|
-
)) }) : /* @__PURE__ */
|
|
17120
|
+
)) }) : /* @__PURE__ */ jsx86("p", { className: "text-sm text-slate-500 dark:text-slate-400", children: "This service is not attached to any node yet. Drag it from the catalog onto a node to assign it." }) })
|
|
15864
17121
|
] })
|
|
15865
17122
|
] });
|
|
15866
17123
|
}
|
|
15867
17124
|
function SectionTitle2({ title, description }) {
|
|
15868
|
-
return /* @__PURE__ */
|
|
15869
|
-
/* @__PURE__ */
|
|
15870
|
-
/* @__PURE__ */
|
|
17125
|
+
return /* @__PURE__ */ jsxs64("div", { children: [
|
|
17126
|
+
/* @__PURE__ */ jsx86("p", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: title }),
|
|
17127
|
+
/* @__PURE__ */ jsx86("p", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: description })
|
|
15871
17128
|
] });
|
|
15872
17129
|
}
|
|
15873
17130
|
function DetailMetric({ label, value }) {
|
|
15874
|
-
return /* @__PURE__ */
|
|
15875
|
-
/* @__PURE__ */
|
|
15876
|
-
/* @__PURE__ */
|
|
17131
|
+
return /* @__PURE__ */ jsxs64("div", { className: "rounded-2xl bg-white px-4 py-3 dark:bg-slate-950", children: [
|
|
17132
|
+
/* @__PURE__ */ jsx86("p", { className: "text-[11px] font-semibold tracking-[0.16em] text-slate-400 uppercase dark:text-slate-500", children: label }),
|
|
17133
|
+
/* @__PURE__ */ jsx86("p", { className: "mt-2 text-sm font-semibold text-slate-900 dark:text-slate-100", children: value })
|
|
15877
17134
|
] });
|
|
15878
17135
|
}
|
|
15879
17136
|
function FilterChip({ label, tone = "default" }) {
|
|
15880
|
-
return /* @__PURE__ */
|
|
17137
|
+
return /* @__PURE__ */ jsx86("span", { className: cn("rounded-full px-2.5 py-1 text-[11px] font-medium", filterChipClassName(tone)), children: label });
|
|
15881
17138
|
}
|
|
15882
17139
|
|
|
15883
17140
|
// src/workspace/bottom-panel/services-split-pane.tsx
|
|
15884
|
-
import { jsx as
|
|
17141
|
+
import { jsx as jsx87, jsxs as jsxs65 } from "react/jsx-runtime";
|
|
15885
17142
|
var UNGROUPED_TREE_VALUE2 = "__catalog_ungrouped__";
|
|
15886
17143
|
function ServicesSplitPane(props) {
|
|
15887
17144
|
const emptyTitle = props.mode === "active" ? "No active services yet" : "No services match this view";
|
|
15888
17145
|
const emptyDescription = props.mode === "active" ? "Connect a service to a tag, field, or option and it will appear here with its bindings." : props.mode === "catalog" ? "Select a catalog group or create one to organize source services for faster assignment." : "Try changing the search or toggles to bring more services into view.";
|
|
15889
|
-
|
|
15890
|
-
|
|
15891
|
-
|
|
15892
|
-
|
|
15893
|
-
|
|
15894
|
-
/* @__PURE__ */
|
|
15895
|
-
|
|
15896
|
-
/* @__PURE__ */
|
|
17146
|
+
const [size, setSize] = useState40(44);
|
|
17147
|
+
return /* @__PURE__ */ jsx87("div", { className: "min-h-90 p-4", children: /* @__PURE__ */ jsxs65(ResizablePanelGroup, { direction: "horizontal", className: "min-h-90", children: [
|
|
17148
|
+
/* @__PURE__ */ jsx87(ResizablePanel, { onResize: (s) => setSize(s.inPixels), defaultSize: 44, minSize: 30, children: /* @__PURE__ */ jsxs65("section", { className: "flex h-full min-h-0 flex-col overflow-hidden", style: { "--resizable-width": size + "px" }, children: [
|
|
17149
|
+
/* @__PURE__ */ jsxs65("div", { className: "space-y-3 border-b border-slate-100 pr-4 dark:border-slate-800", children: [
|
|
17150
|
+
/* @__PURE__ */ jsxs65("div", { className: "flex items-center justify-between gap-3", children: [
|
|
17151
|
+
/* @__PURE__ */ jsx87("div", { children: /* @__PURE__ */ jsx87("h4", { className: "mt-1 text-base font-semibold text-slate-900 dark:text-slate-100", children: props.mode === "active" ? "Attached services" : props.mode === "catalog" ? "Catalog workspace" : "All services" }) }),
|
|
17152
|
+
/* @__PURE__ */ jsxs65("div", { className: "flex items-center gap-2", children: [
|
|
17153
|
+
props.mode === "catalog" ? /* @__PURE__ */ jsx87("span", { className: "rounded-full bg-blue-50 px-2.5 py-1 text-[10px] font-semibold tracking-[0.16em] text-blue-700 uppercase dark:bg-blue-500/10 dark:text-blue-200", children: props.selectedCatalogGroupLabel ?? "Ungrouped" }) : null,
|
|
17154
|
+
/* @__PURE__ */ jsx87("span", { className: "rounded-full bg-slate-100 px-2.5 py-1 text-[10px] font-semibold tracking-[0.16em] text-slate-600 uppercase dark:bg-slate-900 dark:text-slate-300", children: props.rows.length })
|
|
15897
17155
|
] })
|
|
15898
17156
|
] }),
|
|
15899
|
-
props.mode === "all" && props.appliedSnapshot?.selectedTag ? /* @__PURE__ */
|
|
15900
|
-
/* @__PURE__ */
|
|
15901
|
-
/* @__PURE__ */
|
|
17157
|
+
props.mode === "all" && props.appliedSnapshot?.selectedTag ? /* @__PURE__ */ jsxs65("div", { className: "flex flex-wrap gap-2 pb-3", children: [
|
|
17158
|
+
/* @__PURE__ */ jsx87(FilterChip2, { label: `Context tag: ${props.appliedSnapshot.selectedTag.label}` }),
|
|
17159
|
+
/* @__PURE__ */ jsx87(
|
|
15902
17160
|
FilterChip2,
|
|
15903
17161
|
{
|
|
15904
17162
|
label: `${props.appliedSnapshot.state.selectedButtons.length} selected trigger${props.appliedSnapshot.state.selectedButtons.length === 1 ? "" : "s"}`
|
|
15905
17163
|
}
|
|
15906
17164
|
),
|
|
15907
|
-
/* @__PURE__ */
|
|
17165
|
+
/* @__PURE__ */ jsx87(
|
|
15908
17166
|
FilterChip2,
|
|
15909
17167
|
{
|
|
15910
17168
|
label: `${props.appliedSnapshot.usedServiceIds.length} active service${props.appliedSnapshot.usedServiceIds.length === 1 ? "" : "s"} in context`
|
|
15911
17169
|
}
|
|
15912
17170
|
)
|
|
15913
17171
|
] }) : null,
|
|
15914
|
-
props.mode === "catalog" ? /* @__PURE__ */
|
|
17172
|
+
props.mode === "catalog" ? /* @__PURE__ */ jsx87("div", { className: "space-y-3 pb-3", children: /* @__PURE__ */ jsx87(
|
|
15915
17173
|
CatalogToolbar,
|
|
15916
17174
|
{
|
|
15917
17175
|
groups: props.catalogGroups ?? [],
|
|
@@ -15933,7 +17191,7 @@ function ServicesSplitPane(props) {
|
|
|
15933
17191
|
}
|
|
15934
17192
|
) }) : null
|
|
15935
17193
|
] }),
|
|
15936
|
-
/* @__PURE__ */
|
|
17194
|
+
/* @__PURE__ */ jsx87(ScrollArea, { className: "h-[calc(var(--bottom-panel-height)-14.5rem)] max-h-[calc(var(--bottom-panel-height)-14.5rem)] min-h-0 flex-1", children: /* @__PURE__ */ jsx87("div", { className: "space-y-2 p-3 pl-0", children: props.rows.length === 0 ? /* @__PURE__ */ jsx87(EmptyState, { title: emptyTitle, description: emptyDescription }) : props.rows.map((row) => /* @__PURE__ */ jsxs65(
|
|
15937
17195
|
"button",
|
|
15938
17196
|
{
|
|
15939
17197
|
type: "button",
|
|
@@ -15946,34 +17204,34 @@ function ServicesSplitPane(props) {
|
|
|
15946
17204
|
props.selectedRowId === row.id ? "border-blue-300 bg-blue-50 shadow-sm dark:border-blue-500/40 dark:bg-blue-500/10" : "border-slate-200 bg-white hover:border-slate-300 hover:bg-slate-50 dark:border-slate-800 dark:bg-slate-950/60 dark:hover:border-slate-700"
|
|
15947
17205
|
),
|
|
15948
17206
|
children: [
|
|
15949
|
-
/* @__PURE__ */
|
|
15950
|
-
/* @__PURE__ */
|
|
15951
|
-
/* @__PURE__ */
|
|
15952
|
-
/* @__PURE__ */
|
|
15953
|
-
/* @__PURE__ */
|
|
17207
|
+
/* @__PURE__ */ jsxs65("div", { className: "flex items-start justify-between gap-3", children: [
|
|
17208
|
+
/* @__PURE__ */ jsxs65("div", { className: "min-w-0", children: [
|
|
17209
|
+
/* @__PURE__ */ jsxs65("div", { className: "flex items-center gap-2", children: [
|
|
17210
|
+
/* @__PURE__ */ jsx87(StatusDot, { tone: row.statusTone }),
|
|
17211
|
+
/* @__PURE__ */ jsx87("span", { title: row.summary.name, className: "truncate max-w-[calc(var(--resizable-width)-12rem)] text-sm font-semibold text-slate-900 dark:text-slate-100", children: row.summary.name })
|
|
15954
17212
|
] }),
|
|
15955
|
-
/* @__PURE__ */
|
|
15956
|
-
/* @__PURE__ */
|
|
17213
|
+
/* @__PURE__ */ jsxs65("div", { className: "mt-1 flex flex-wrap items-center gap-2 text-xs text-slate-500 dark:text-slate-400", children: [
|
|
17214
|
+
/* @__PURE__ */ jsxs65("span", { children: [
|
|
15957
17215
|
"#",
|
|
15958
17216
|
row.summary.id
|
|
15959
17217
|
] }),
|
|
15960
|
-
row.summary.category ? /* @__PURE__ */
|
|
15961
|
-
row.summary.platformId ? /* @__PURE__ */
|
|
17218
|
+
row.summary.category ? /* @__PURE__ */ jsx87("span", { children: row.summary.category }) : null,
|
|
17219
|
+
row.summary.platformId ? /* @__PURE__ */ jsx87("span", { children: row.summary.platformId }) : null
|
|
15962
17220
|
] })
|
|
15963
17221
|
] }),
|
|
15964
|
-
/* @__PURE__ */
|
|
17222
|
+
/* @__PURE__ */ jsx87("span", { className: statusBadgeClassName(row.statusTone), children: row.statusLabel })
|
|
15965
17223
|
] }),
|
|
15966
|
-
/* @__PURE__ */
|
|
15967
|
-
/* @__PURE__ */
|
|
17224
|
+
/* @__PURE__ */ jsxs65("div", { className: "mt-3 flex flex-wrap items-center gap-2", children: [
|
|
17225
|
+
/* @__PURE__ */ jsxs65("span", { className: "rounded-full bg-slate-100 px-2.5 py-1 text-[11px] text-slate-600 dark:bg-slate-900 dark:text-slate-300", children: [
|
|
15968
17226
|
row.summary.attachmentCount,
|
|
15969
17227
|
" node",
|
|
15970
17228
|
row.summary.attachmentCount === 1 ? "" : "s"
|
|
15971
17229
|
] }),
|
|
15972
|
-
row.summary.rate != null ? /* @__PURE__ */
|
|
17230
|
+
row.summary.rate != null ? /* @__PURE__ */ jsxs65("span", { className: "rounded-full bg-slate-100 px-2.5 py-1 text-[11px] text-slate-600 dark:bg-slate-900 dark:text-slate-300", children: [
|
|
15973
17231
|
"Rate ",
|
|
15974
17232
|
row.summary.rate
|
|
15975
17233
|
] }) : null,
|
|
15976
|
-
row.reasonLabels.slice(0, 2).map((reason) => /* @__PURE__ */
|
|
17234
|
+
row.reasonLabels.slice(0, 2).map((reason) => /* @__PURE__ */ jsx87(
|
|
15977
17235
|
"span",
|
|
15978
17236
|
{
|
|
15979
17237
|
className: "rounded-full bg-amber-50 px-2.5 py-1 text-[11px] text-amber-700 dark:bg-amber-500/10 dark:text-amber-200",
|
|
@@ -15987,14 +17245,14 @@ function ServicesSplitPane(props) {
|
|
|
15987
17245
|
row.id
|
|
15988
17246
|
)) }) })
|
|
15989
17247
|
] }) }),
|
|
15990
|
-
/* @__PURE__ */
|
|
15991
|
-
/* @__PURE__ */
|
|
15992
|
-
/* @__PURE__ */
|
|
15993
|
-
/* @__PURE__ */
|
|
15994
|
-
/* @__PURE__ */
|
|
15995
|
-
/* @__PURE__ */
|
|
17248
|
+
/* @__PURE__ */ jsx87(ResizableHandle, { withHandle: true }),
|
|
17249
|
+
/* @__PURE__ */ jsx87(ResizablePanel, { defaultSize: 56, minSize: 36, children: /* @__PURE__ */ jsxs65("section", { className: "flex h-full min-h-0 flex-col overflow-hidden", children: [
|
|
17250
|
+
/* @__PURE__ */ jsxs65("div", { className: "border-b border-slate-100 px-4 dark:border-slate-800", children: [
|
|
17251
|
+
/* @__PURE__ */ jsx87("p", { className: "text-xs font-semibold tracking-[0.18em] text-slate-400 uppercase dark:text-slate-500", children: "Service detail" }),
|
|
17252
|
+
/* @__PURE__ */ jsx87("h4", { className: "mt-1 text-base font-semibold text-slate-900 dark:text-slate-100", children: props.detailRow ? props.detailRow.summary.name : "Select a service" }),
|
|
17253
|
+
/* @__PURE__ */ jsx87("p", { className: "mt-1 text-sm text-slate-500 dark:text-slate-400", children: props.mode === "active" ? "Highlight connected nodes, inspect usage, and jump back into the canvas." : props.mode === "catalog" ? "Inspect compatibility, pricing, and bindings while browsing manual catalog groups." : "Inspect compatibility, pricing, and bindings before assigning the service to a node." })
|
|
15996
17254
|
] }),
|
|
15997
|
-
/* @__PURE__ */
|
|
17255
|
+
/* @__PURE__ */ jsx87(ScrollArea, { className: "h-[calc(var(--bottom-panel-height)-14.5rem)] max-h-[calc(var(--bottom-panel-height)-14.5rem)] min-h-0 flex-1", children: /* @__PURE__ */ jsx87("div", { className: "p-5", children: props.detailRow ? /* @__PURE__ */ jsx87(
|
|
15998
17256
|
ServiceDetailCard,
|
|
15999
17257
|
{
|
|
16000
17258
|
mode: props.mode,
|
|
@@ -16004,7 +17262,7 @@ function ServicesSplitPane(props) {
|
|
|
16004
17262
|
onOpenFallbackQuickAdd: props.onOpenFallbackQuickAdd,
|
|
16005
17263
|
onOpenFallbackEditor: props.onOpenFallbackEditor
|
|
16006
17264
|
}
|
|
16007
|
-
) : /* @__PURE__ */
|
|
17265
|
+
) : /* @__PURE__ */ jsx87(
|
|
16008
17266
|
EmptyState,
|
|
16009
17267
|
{
|
|
16010
17268
|
title: "No service selected",
|
|
@@ -16026,8 +17284,8 @@ function CatalogContextPopover({
|
|
|
16026
17284
|
onDraftContextChange
|
|
16027
17285
|
}) {
|
|
16028
17286
|
const context = draftContext;
|
|
16029
|
-
return /* @__PURE__ */
|
|
16030
|
-
/* @__PURE__ */
|
|
17287
|
+
return /* @__PURE__ */ jsxs65(Popover, { open, onOpenChange, children: [
|
|
17288
|
+
/* @__PURE__ */ jsx87(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx87(
|
|
16031
17289
|
"button",
|
|
16032
17290
|
{
|
|
16033
17291
|
type: "button",
|
|
@@ -16036,10 +17294,10 @@ function CatalogContextPopover({
|
|
|
16036
17294
|
"inline-flex h-9 w-9 items-center justify-center rounded-xl border text-sm transition",
|
|
16037
17295
|
compatibleOnly ? "border-blue-200 bg-blue-50 text-blue-700 dark:border-blue-500/30 dark:bg-blue-500/10 dark:text-blue-200" : "border-slate-200 bg-white text-slate-600 hover:bg-slate-100 dark:border-slate-800 dark:bg-slate-950 dark:text-slate-300 dark:hover:bg-slate-900"
|
|
16038
17296
|
),
|
|
16039
|
-
children: /* @__PURE__ */
|
|
17297
|
+
children: /* @__PURE__ */ jsx87(FiFilter2, {})
|
|
16040
17298
|
}
|
|
16041
17299
|
) }),
|
|
16042
|
-
/* @__PURE__ */
|
|
17300
|
+
/* @__PURE__ */ jsxs65(
|
|
16043
17301
|
PopoverContent,
|
|
16044
17302
|
{
|
|
16045
17303
|
align: "end",
|
|
@@ -16047,31 +17305,31 @@ function CatalogContextPopover({
|
|
|
16047
17305
|
collisionPadding: 16,
|
|
16048
17306
|
className: "max-h-[min(32rem,var(--radix-popover-content-available-height))] w-[min(24rem,calc(100vw-2rem))] overflow-hidden rounded-2xl p-0",
|
|
16049
17307
|
children: [
|
|
16050
|
-
/* @__PURE__ */
|
|
16051
|
-
/* @__PURE__ */
|
|
16052
|
-
/* @__PURE__ */
|
|
17308
|
+
/* @__PURE__ */ jsxs65("div", { className: "border-b border-slate-200 px-4 py-3 dark:border-slate-800", children: [
|
|
17309
|
+
/* @__PURE__ */ jsx87("div", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: "Catalog context" }),
|
|
17310
|
+
/* @__PURE__ */ jsx87("p", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: "Control compatibility checks here, or link them to the current workspace context." })
|
|
16053
17311
|
] }),
|
|
16054
|
-
/* @__PURE__ */
|
|
16055
|
-
/* @__PURE__ */
|
|
16056
|
-
/* @__PURE__ */
|
|
16057
|
-
/* @__PURE__ */
|
|
16058
|
-
/* @__PURE__ */
|
|
17312
|
+
/* @__PURE__ */ jsx87(ScrollArea, { className: "h-[calc(var(--radix-popover-content-available-height)-4.5rem)] max-h-[calc(var(--radix-popover-content-available-height)-4.5rem)]", children: /* @__PURE__ */ jsxs65("div", { className: "space-y-4 p-4", children: [
|
|
17313
|
+
/* @__PURE__ */ jsxs65("label", { className: "flex items-start justify-between gap-3 text-sm text-slate-900 dark:text-slate-100", children: [
|
|
17314
|
+
/* @__PURE__ */ jsxs65("span", { className: "min-w-0", children: [
|
|
17315
|
+
/* @__PURE__ */ jsx87("span", { className: "block font-medium", children: "Compatible only" }),
|
|
17316
|
+
/* @__PURE__ */ jsx87("span", { className: "mt-1 block text-xs text-slate-500 dark:text-slate-400", children: "Show only services that fit this catalog context safely." })
|
|
16059
17317
|
] }),
|
|
16060
|
-
/* @__PURE__ */
|
|
17318
|
+
/* @__PURE__ */ jsx87("input", { type: "checkbox", checked: compatibleOnly, onChange: (event) => onCompatibleOnlyChange(event.target.checked) })
|
|
16061
17319
|
] }),
|
|
16062
|
-
/* @__PURE__ */
|
|
16063
|
-
/* @__PURE__ */
|
|
16064
|
-
/* @__PURE__ */
|
|
16065
|
-
/* @__PURE__ */
|
|
17320
|
+
/* @__PURE__ */ jsxs65("label", { className: "flex items-start justify-between gap-3 text-sm text-slate-900 dark:text-slate-100", children: [
|
|
17321
|
+
/* @__PURE__ */ jsxs65("span", { className: "min-w-0", children: [
|
|
17322
|
+
/* @__PURE__ */ jsx87("span", { className: "block font-medium", children: "Link to current context" }),
|
|
17323
|
+
/* @__PURE__ */ jsx87("span", { className: "mt-1 block text-xs text-slate-500 dark:text-slate-400", children: "Mirror the current canvas tag and selected buttons while linked." })
|
|
16066
17324
|
] }),
|
|
16067
|
-
/* @__PURE__ */
|
|
17325
|
+
/* @__PURE__ */ jsx87("input", { type: "checkbox", checked: contextLinked, onChange: (event) => onContextLinkedChange(event.target.checked) })
|
|
16068
17326
|
] }),
|
|
16069
|
-
/* @__PURE__ */
|
|
16070
|
-
/* @__PURE__ */
|
|
16071
|
-
/* @__PURE__ */
|
|
17327
|
+
/* @__PURE__ */ jsxs65("div", { className: "space-y-2 rounded-2xl border border-slate-200 bg-slate-50/70 p-3 dark:border-slate-800 dark:bg-slate-900/40", children: [
|
|
17328
|
+
/* @__PURE__ */ jsx87("div", { className: "text-xs font-semibold tracking-[0.16em] text-slate-500 uppercase dark:text-slate-400", children: "Tags" }),
|
|
17329
|
+
/* @__PURE__ */ jsx87("div", { className: "space-y-2", children: (draftSnapshot?.tags ?? []).map((tag) => {
|
|
16072
17330
|
const selected = context?.selectedTagId === tag.id;
|
|
16073
|
-
return /* @__PURE__ */
|
|
16074
|
-
/* @__PURE__ */
|
|
17331
|
+
return /* @__PURE__ */ jsxs65("label", { className: "flex items-start gap-3 text-sm text-slate-900 dark:text-slate-100", children: [
|
|
17332
|
+
/* @__PURE__ */ jsx87(
|
|
16075
17333
|
"input",
|
|
16076
17334
|
{
|
|
16077
17335
|
type: "radio",
|
|
@@ -16089,25 +17347,25 @@ function CatalogContextPopover({
|
|
|
16089
17347
|
})
|
|
16090
17348
|
}
|
|
16091
17349
|
),
|
|
16092
|
-
/* @__PURE__ */
|
|
16093
|
-
/* @__PURE__ */
|
|
16094
|
-
tag.description ? /* @__PURE__ */
|
|
17350
|
+
/* @__PURE__ */ jsxs65("span", { className: "min-w-0", children: [
|
|
17351
|
+
/* @__PURE__ */ jsx87("span", { className: "block font-medium", children: tag.label }),
|
|
17352
|
+
tag.description ? /* @__PURE__ */ jsx87("span", { className: "block text-xs text-slate-500 dark:text-slate-400", children: tag.description }) : null
|
|
16095
17353
|
] })
|
|
16096
17354
|
] }, tag.id);
|
|
16097
17355
|
}) })
|
|
16098
17356
|
] }),
|
|
16099
|
-
/* @__PURE__ */
|
|
16100
|
-
/* @__PURE__ */
|
|
16101
|
-
draftSnapshot?.buttonGroups?.length ? /* @__PURE__ */
|
|
16102
|
-
/* @__PURE__ */
|
|
16103
|
-
/* @__PURE__ */
|
|
17357
|
+
/* @__PURE__ */ jsxs65("div", { className: "space-y-2 rounded-2xl border border-slate-200 bg-slate-50/70 p-3 dark:border-slate-800 dark:bg-slate-900/40", children: [
|
|
17358
|
+
/* @__PURE__ */ jsx87("div", { className: "text-xs font-semibold tracking-[0.16em] text-slate-500 uppercase dark:text-slate-400", children: "Selected buttons" }),
|
|
17359
|
+
draftSnapshot?.buttonGroups?.length ? /* @__PURE__ */ jsx87("div", { className: "space-y-3", children: draftSnapshot.buttonGroups.map((group) => /* @__PURE__ */ jsxs65("div", { className: "space-y-2", children: [
|
|
17360
|
+
/* @__PURE__ */ jsx87("div", { className: "text-sm font-medium text-slate-900 dark:text-slate-100", children: group.label }),
|
|
17361
|
+
/* @__PURE__ */ jsx87("div", { className: "space-y-1", children: group.options.map((option) => {
|
|
16104
17362
|
const checked = context?.selectedButtons.includes(option.id) ?? false;
|
|
16105
|
-
return /* @__PURE__ */
|
|
17363
|
+
return /* @__PURE__ */ jsxs65(
|
|
16106
17364
|
"label",
|
|
16107
17365
|
{
|
|
16108
17366
|
className: "flex items-start gap-3 text-sm text-slate-900 dark:text-slate-100",
|
|
16109
17367
|
children: [
|
|
16110
|
-
/* @__PURE__ */
|
|
17368
|
+
/* @__PURE__ */ jsx87(
|
|
16111
17369
|
"input",
|
|
16112
17370
|
{
|
|
16113
17371
|
type: "checkbox",
|
|
@@ -16124,22 +17382,22 @@ function CatalogContextPopover({
|
|
|
16124
17382
|
})
|
|
16125
17383
|
}
|
|
16126
17384
|
),
|
|
16127
|
-
/* @__PURE__ */
|
|
16128
|
-
/* @__PURE__ */
|
|
16129
|
-
option.description ? /* @__PURE__ */
|
|
17385
|
+
/* @__PURE__ */ jsxs65("span", { className: "min-w-0", children: [
|
|
17386
|
+
/* @__PURE__ */ jsx87("span", { className: "block", children: option.label }),
|
|
17387
|
+
option.description ? /* @__PURE__ */ jsx87("span", { className: "block text-xs text-slate-500 dark:text-slate-400", children: option.description }) : null
|
|
16130
17388
|
] })
|
|
16131
17389
|
]
|
|
16132
17390
|
},
|
|
16133
17391
|
option.id
|
|
16134
17392
|
);
|
|
16135
17393
|
}) })
|
|
16136
|
-
] }, group.id)) }) : /* @__PURE__ */
|
|
17394
|
+
] }, group.id)) }) : /* @__PURE__ */ jsx87("div", { className: "text-sm text-slate-500 dark:text-slate-400", children: "No visible trigger options for the selected tag." })
|
|
16137
17395
|
] }),
|
|
16138
|
-
/* @__PURE__ */
|
|
16139
|
-
/* @__PURE__ */
|
|
16140
|
-
/* @__PURE__ */
|
|
16141
|
-
/* @__PURE__ */
|
|
16142
|
-
/* @__PURE__ */
|
|
17396
|
+
/* @__PURE__ */ jsxs65("div", { className: "space-y-2 rounded-2xl border border-slate-200 bg-slate-50/70 p-3 dark:border-slate-800 dark:bg-slate-900/40", children: [
|
|
17397
|
+
/* @__PURE__ */ jsx87("div", { className: "text-xs font-semibold tracking-[0.16em] text-slate-500 uppercase dark:text-slate-400", children: "Safety" }),
|
|
17398
|
+
/* @__PURE__ */ jsxs65("label", { className: "flex items-center justify-between gap-3 text-sm text-slate-900 dark:text-slate-100", children: [
|
|
17399
|
+
/* @__PURE__ */ jsx87("span", { children: "Strict safety" }),
|
|
17400
|
+
/* @__PURE__ */ jsx87(
|
|
16143
17401
|
"input",
|
|
16144
17402
|
{
|
|
16145
17403
|
type: "checkbox",
|
|
@@ -16152,9 +17410,9 @@ function CatalogContextPopover({
|
|
|
16152
17410
|
}
|
|
16153
17411
|
)
|
|
16154
17412
|
] }),
|
|
16155
|
-
/* @__PURE__ */
|
|
16156
|
-
/* @__PURE__ */
|
|
16157
|
-
/* @__PURE__ */
|
|
17413
|
+
/* @__PURE__ */ jsxs65("label", { className: "flex items-center justify-between gap-3 text-sm text-slate-900 dark:text-slate-100", children: [
|
|
17414
|
+
/* @__PURE__ */ jsx87("span", { children: "Enforce policies" }),
|
|
17415
|
+
/* @__PURE__ */ jsx87(
|
|
16158
17416
|
"input",
|
|
16159
17417
|
{
|
|
16160
17418
|
type: "checkbox",
|
|
@@ -16188,34 +17446,34 @@ function CatalogToolbar({
|
|
|
16188
17446
|
}) {
|
|
16189
17447
|
const treeValue = selectedGroupId ?? (ungroupedSelected ? UNGROUPED_TREE_VALUE2 : void 0);
|
|
16190
17448
|
const treeOptions = buildCatalogGroupTreeOptions2(groups);
|
|
16191
|
-
return /* @__PURE__ */
|
|
16192
|
-
/* @__PURE__ */
|
|
16193
|
-
/* @__PURE__ */
|
|
17449
|
+
return /* @__PURE__ */ jsxs65("div", { className: "flex items-center justify-between gap-3", children: [
|
|
17450
|
+
/* @__PURE__ */ jsxs65("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
17451
|
+
/* @__PURE__ */ jsx87(
|
|
16194
17452
|
GroupInputPopoverButton,
|
|
16195
17453
|
{
|
|
16196
17454
|
label: "Create top-level group",
|
|
16197
|
-
icon: /* @__PURE__ */
|
|
17455
|
+
icon: /* @__PURE__ */ jsx87(FiPlus2, {}),
|
|
16198
17456
|
submitLabel: "Create",
|
|
16199
17457
|
title: "Create root group",
|
|
16200
17458
|
onSubmit: onCreateRootGroup
|
|
16201
17459
|
}
|
|
16202
17460
|
),
|
|
16203
|
-
/* @__PURE__ */
|
|
17461
|
+
/* @__PURE__ */ jsx87(
|
|
16204
17462
|
GroupInputPopoverButton,
|
|
16205
17463
|
{
|
|
16206
17464
|
label: "Create child group",
|
|
16207
|
-
icon: /* @__PURE__ */
|
|
17465
|
+
icon: /* @__PURE__ */ jsx87(FiFolderPlus, {}),
|
|
16208
17466
|
title: "Create child group",
|
|
16209
17467
|
submitLabel: "Create",
|
|
16210
17468
|
disabled: !selectedGroupId,
|
|
16211
17469
|
onSubmit: onCreateChildGroup
|
|
16212
17470
|
}
|
|
16213
17471
|
),
|
|
16214
|
-
/* @__PURE__ */
|
|
17472
|
+
/* @__PURE__ */ jsx87(
|
|
16215
17473
|
GroupInputPopoverButton,
|
|
16216
17474
|
{
|
|
16217
17475
|
label: "Rename selected group",
|
|
16218
|
-
icon: /* @__PURE__ */
|
|
17476
|
+
icon: /* @__PURE__ */ jsx87(FiEdit2, {}),
|
|
16219
17477
|
title: "Rename group",
|
|
16220
17478
|
submitLabel: "Save",
|
|
16221
17479
|
disabled: !selectedGroupId,
|
|
@@ -16223,11 +17481,11 @@ function CatalogToolbar({
|
|
|
16223
17481
|
onSubmit: onRenameGroup
|
|
16224
17482
|
}
|
|
16225
17483
|
),
|
|
16226
|
-
/* @__PURE__ */
|
|
17484
|
+
/* @__PURE__ */ jsx87(
|
|
16227
17485
|
ConfirmPopoverButton,
|
|
16228
17486
|
{
|
|
16229
17487
|
label: "Delete selected group",
|
|
16230
|
-
icon: /* @__PURE__ */
|
|
17488
|
+
icon: /* @__PURE__ */ jsx87(FiTrash22, {}),
|
|
16231
17489
|
title: "Delete group?",
|
|
16232
17490
|
description: selectedGroupLabel ? `Remove ${selectedGroupLabel} and its child groups.` : "Remove this group and its child groups.",
|
|
16233
17491
|
confirmLabel: "Delete",
|
|
@@ -16235,10 +17493,10 @@ function CatalogToolbar({
|
|
|
16235
17493
|
onConfirm: onDeleteGroup
|
|
16236
17494
|
}
|
|
16237
17495
|
),
|
|
16238
|
-
/* @__PURE__ */
|
|
17496
|
+
/* @__PURE__ */ jsx87(ToolbarIconButton, { label: "Assign services to selected group", disabled: !selectedGroupId, onClick: onAssignServices, children: /* @__PURE__ */ jsx87(FiPlus2, {}) })
|
|
16239
17497
|
] }),
|
|
16240
|
-
/* @__PURE__ */
|
|
16241
|
-
|
|
17498
|
+
/* @__PURE__ */ jsx87(
|
|
17499
|
+
InputField20,
|
|
16242
17500
|
{
|
|
16243
17501
|
variant: "treeselect",
|
|
16244
17502
|
mode: "button",
|
|
@@ -16252,7 +17510,7 @@ function CatalogToolbar({
|
|
|
16252
17510
|
const next = event.value == null ? null : String(event.value);
|
|
16253
17511
|
onSelectGroup(next === UNGROUPED_TREE_VALUE2 ? null : next);
|
|
16254
17512
|
},
|
|
16255
|
-
button: /* @__PURE__ */
|
|
17513
|
+
button: /* @__PURE__ */ jsx87(FaFolderOpen2, {})
|
|
16256
17514
|
}
|
|
16257
17515
|
)
|
|
16258
17516
|
] });
|
|
@@ -16266,13 +17524,13 @@ function GroupInputPopoverButton({
|
|
|
16266
17524
|
disabled = false,
|
|
16267
17525
|
onSubmit
|
|
16268
17526
|
}) {
|
|
16269
|
-
const [open, setOpen] =
|
|
16270
|
-
const [value, setValue] =
|
|
16271
|
-
|
|
17527
|
+
const [open, setOpen] = useState40(false);
|
|
17528
|
+
const [value, setValue] = useState40(initialValue);
|
|
17529
|
+
useEffect25(() => {
|
|
16272
17530
|
if (open) setValue(initialValue);
|
|
16273
17531
|
}, [initialValue, open]);
|
|
16274
|
-
return /* @__PURE__ */
|
|
16275
|
-
/* @__PURE__ */
|
|
17532
|
+
return /* @__PURE__ */ jsxs65(Popover, { open, onOpenChange: setOpen, children: [
|
|
17533
|
+
/* @__PURE__ */ jsx87(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx87(
|
|
16276
17534
|
"button",
|
|
16277
17535
|
{
|
|
16278
17536
|
type: "button",
|
|
@@ -16286,13 +17544,13 @@ function GroupInputPopoverButton({
|
|
|
16286
17544
|
children: icon
|
|
16287
17545
|
}
|
|
16288
17546
|
) }),
|
|
16289
|
-
/* @__PURE__ */
|
|
16290
|
-
/* @__PURE__ */
|
|
16291
|
-
/* @__PURE__ */
|
|
16292
|
-
/* @__PURE__ */
|
|
17547
|
+
/* @__PURE__ */ jsx87(PopoverContent, { align: "start", side: "bottom", sideOffset: 8, collisionPadding: 16, className: "w-80 rounded-2xl", children: /* @__PURE__ */ jsxs65("div", { className: "space-y-3", children: [
|
|
17548
|
+
/* @__PURE__ */ jsxs65("div", { children: [
|
|
17549
|
+
/* @__PURE__ */ jsx87("div", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: title }),
|
|
17550
|
+
/* @__PURE__ */ jsx87("p", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: "Names are editor-side catalog labels only." })
|
|
16293
17551
|
] }),
|
|
16294
|
-
/* @__PURE__ */
|
|
16295
|
-
|
|
17552
|
+
/* @__PURE__ */ jsx87(
|
|
17553
|
+
InputField20,
|
|
16296
17554
|
{
|
|
16297
17555
|
variant: "text",
|
|
16298
17556
|
label: title,
|
|
@@ -16302,9 +17560,9 @@ function GroupInputPopoverButton({
|
|
|
16302
17560
|
autoComplete: "off"
|
|
16303
17561
|
}
|
|
16304
17562
|
),
|
|
16305
|
-
/* @__PURE__ */
|
|
16306
|
-
/* @__PURE__ */
|
|
16307
|
-
/* @__PURE__ */
|
|
17563
|
+
/* @__PURE__ */ jsxs65("div", { className: "flex justify-end gap-2", children: [
|
|
17564
|
+
/* @__PURE__ */ jsx87(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setOpen(false), className: "rounded-xl", children: "Cancel" }),
|
|
17565
|
+
/* @__PURE__ */ jsx87(
|
|
16308
17566
|
Button,
|
|
16309
17567
|
{
|
|
16310
17568
|
type: "button",
|
|
@@ -16333,9 +17591,9 @@ function ConfirmPopoverButton({
|
|
|
16333
17591
|
disabled = false,
|
|
16334
17592
|
onConfirm
|
|
16335
17593
|
}) {
|
|
16336
|
-
const [open, setOpen] =
|
|
16337
|
-
return /* @__PURE__ */
|
|
16338
|
-
/* @__PURE__ */
|
|
17594
|
+
const [open, setOpen] = useState40(false);
|
|
17595
|
+
return /* @__PURE__ */ jsxs65(Popover, { open, onOpenChange: setOpen, children: [
|
|
17596
|
+
/* @__PURE__ */ jsx87(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx87(
|
|
16339
17597
|
"button",
|
|
16340
17598
|
{
|
|
16341
17599
|
type: "button",
|
|
@@ -16349,14 +17607,14 @@ function ConfirmPopoverButton({
|
|
|
16349
17607
|
children: icon
|
|
16350
17608
|
}
|
|
16351
17609
|
) }),
|
|
16352
|
-
/* @__PURE__ */
|
|
16353
|
-
/* @__PURE__ */
|
|
16354
|
-
/* @__PURE__ */
|
|
16355
|
-
/* @__PURE__ */
|
|
17610
|
+
/* @__PURE__ */ jsx87(PopoverContent, { align: "start", side: "bottom", sideOffset: 8, collisionPadding: 16, className: "w-80 rounded-2xl", children: /* @__PURE__ */ jsxs65("div", { className: "space-y-3", children: [
|
|
17611
|
+
/* @__PURE__ */ jsxs65("div", { children: [
|
|
17612
|
+
/* @__PURE__ */ jsx87("div", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: title }),
|
|
17613
|
+
/* @__PURE__ */ jsx87("p", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: description })
|
|
16356
17614
|
] }),
|
|
16357
|
-
/* @__PURE__ */
|
|
16358
|
-
/* @__PURE__ */
|
|
16359
|
-
/* @__PURE__ */
|
|
17615
|
+
/* @__PURE__ */ jsxs65("div", { className: "flex justify-end gap-2", children: [
|
|
17616
|
+
/* @__PURE__ */ jsx87(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setOpen(false), className: "rounded-xl", children: "Cancel" }),
|
|
17617
|
+
/* @__PURE__ */ jsx87(
|
|
16360
17618
|
Button,
|
|
16361
17619
|
{
|
|
16362
17620
|
type: "button",
|
|
@@ -16379,8 +17637,8 @@ function ToolbarIconButton({
|
|
|
16379
17637
|
disabled = false,
|
|
16380
17638
|
onClick
|
|
16381
17639
|
}) {
|
|
16382
|
-
return /* @__PURE__ */
|
|
16383
|
-
/* @__PURE__ */
|
|
17640
|
+
return /* @__PURE__ */ jsxs65(Tooltip, { children: [
|
|
17641
|
+
/* @__PURE__ */ jsx87(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx87(
|
|
16384
17642
|
"button",
|
|
16385
17643
|
{
|
|
16386
17644
|
type: "button",
|
|
@@ -16394,11 +17652,11 @@ function ToolbarIconButton({
|
|
|
16394
17652
|
children
|
|
16395
17653
|
}
|
|
16396
17654
|
) }),
|
|
16397
|
-
/* @__PURE__ */
|
|
17655
|
+
/* @__PURE__ */ jsx87(TooltipContent, { side: "top", sideOffset: 8, children: label })
|
|
16398
17656
|
] });
|
|
16399
17657
|
}
|
|
16400
17658
|
function FilterChip2({ label, tone = "default" }) {
|
|
16401
|
-
return /* @__PURE__ */
|
|
17659
|
+
return /* @__PURE__ */ jsx87("span", { className: cn("rounded-full px-2.5 py-1 text-[11px] font-medium", filterChipClassName(tone)), children: label });
|
|
16402
17660
|
}
|
|
16403
17661
|
function buildCatalogGroupTreeOptions2(groups, parentId = null) {
|
|
16404
17662
|
return groups.filter((group) => (group.parentId ?? null) === parentId).sort((a, b) => (a.order ?? 0) - (b.order ?? 0) || a.label.localeCompare(b.label)).map((group) => {
|
|
@@ -16413,7 +17671,7 @@ function buildCatalogGroupTreeOptions2(groups, parentId = null) {
|
|
|
16413
17671
|
}
|
|
16414
17672
|
|
|
16415
17673
|
// src/workspace/bottom-panel/index.tsx
|
|
16416
|
-
import { Fragment as
|
|
17674
|
+
import { Fragment as Fragment17, jsx as jsx88, jsxs as jsxs66 } from "react/jsx-runtime";
|
|
16417
17675
|
var DRAG_MIME = "application/x-service-builder-service";
|
|
16418
17676
|
function BottomConsolePanel({ controller, errors, activeServices, allServices, onServiceDragStateChange }) {
|
|
16419
17677
|
const canvas = useCanvas21();
|
|
@@ -16424,26 +17682,26 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
|
|
|
16424
17682
|
const policies2 = ws.policies.policies.data ?? [];
|
|
16425
17683
|
const currentTagId = canvas.api.selection.currentTag?.();
|
|
16426
17684
|
const preferredTagId = currentTagId != null ? String(currentTagId) : canvas.layers.tags[0]?.id != null ? String(canvas.layers.tags[0]?.id) : null;
|
|
16427
|
-
const [activeSearch, setActiveSearch] =
|
|
16428
|
-
const [allSearch, setAllSearch] =
|
|
16429
|
-
const [compatibleOnly, setCompatibleOnly] =
|
|
16430
|
-
const [hideActiveServices, setHideActiveServices] =
|
|
16431
|
-
const [filterOpen, setFilterOpen] =
|
|
16432
|
-
const [searchOpen, setSearchOpen] =
|
|
16433
|
-
const [contextLinked, setContextLinked] =
|
|
16434
|
-
const [servicePickerOpen, setServicePickerOpen] =
|
|
16435
|
-
const [selectedActiveServiceId, setSelectedActiveServiceId] =
|
|
16436
|
-
const [selectedAllServiceId, setSelectedAllServiceId] =
|
|
16437
|
-
const [catalogContextDraft, setCatalogContextDraft] =
|
|
17685
|
+
const [activeSearch, setActiveSearch] = useState41("");
|
|
17686
|
+
const [allSearch, setAllSearch] = useState41("");
|
|
17687
|
+
const [compatibleOnly, setCompatibleOnly] = useState41(false);
|
|
17688
|
+
const [hideActiveServices, setHideActiveServices] = useState41(false);
|
|
17689
|
+
const [filterOpen, setFilterOpen] = useState41(false);
|
|
17690
|
+
const [searchOpen, setSearchOpen] = useState41(false);
|
|
17691
|
+
const [contextLinked, setContextLinked] = useState41(false);
|
|
17692
|
+
const [servicePickerOpen, setServicePickerOpen] = useState41(false);
|
|
17693
|
+
const [selectedActiveServiceId, setSelectedActiveServiceId] = useState41(null);
|
|
17694
|
+
const [selectedAllServiceId, setSelectedAllServiceId] = useState41(null);
|
|
17695
|
+
const [catalogContextDraft, setCatalogContextDraft] = useState41(
|
|
16438
17696
|
() => createDefaultServiceContext(canvas.props, preferredTagId)
|
|
16439
17697
|
);
|
|
16440
|
-
const [catalogState, setCatalogState] =
|
|
16441
|
-
const [panelPosition, setPanelPosition] =
|
|
16442
|
-
const [draggingPanel, setDraggingPanel] =
|
|
16443
|
-
const [consoleSubTab, setConsoleSubTab] =
|
|
16444
|
-
const [consoleScopeFilter, setConsoleScopeFilter] =
|
|
16445
|
-
const [consoleSeverityFilter, setConsoleSeverityFilter] =
|
|
16446
|
-
const [consoleIntroState, setConsoleIntroState] =
|
|
17698
|
+
const [catalogState, setCatalogState] = useState41(null);
|
|
17699
|
+
const [panelPosition, setPanelPosition] = useState41(() => readStoredPanelPosition());
|
|
17700
|
+
const [draggingPanel, setDraggingPanel] = useState41(false);
|
|
17701
|
+
const [consoleSubTab, setConsoleSubTab] = useState41("validation");
|
|
17702
|
+
const [consoleScopeFilter, setConsoleScopeFilter] = useState41("all");
|
|
17703
|
+
const [consoleSeverityFilter, setConsoleSeverityFilter] = useState41("all");
|
|
17704
|
+
const [consoleIntroState, setConsoleIntroState] = useState41({
|
|
16447
17705
|
validation: { minimized: false, closed: false },
|
|
16448
17706
|
logs: { minimized: false, closed: false },
|
|
16449
17707
|
notices: { minimized: false, closed: false }
|
|
@@ -16453,11 +17711,11 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
|
|
|
16453
17711
|
const panelRef = useRef12(null);
|
|
16454
17712
|
const searchInputRef = useRef12(null);
|
|
16455
17713
|
const dragStartRef = useRef12(null);
|
|
16456
|
-
const selectedButtons =
|
|
17714
|
+
const selectedButtons = useMemo40(
|
|
16457
17715
|
() => (canvas.api.selection.selectedButtons?.() ?? []).map((value) => String(value)),
|
|
16458
17716
|
[canvas.api.selection, canvas.selectionInfo.ids, canvas.selectionInfo.optionIds]
|
|
16459
17717
|
);
|
|
16460
|
-
const liveSelectionContext =
|
|
17718
|
+
const liveSelectionContext = useMemo40(
|
|
16461
17719
|
() => ({
|
|
16462
17720
|
selectedTagId: preferredTagId,
|
|
16463
17721
|
selectedButtons,
|
|
@@ -16467,15 +17725,15 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
|
|
|
16467
17725
|
[preferredTagId, selectedButtons]
|
|
16468
17726
|
);
|
|
16469
17727
|
const effectiveCatalogContext = contextLinked ? liveSelectionContext : catalogContextDraft;
|
|
16470
|
-
const appliedSnapshot =
|
|
17728
|
+
const appliedSnapshot = useMemo40(
|
|
16471
17729
|
() => buildServiceContextSnapshot({ props: canvas.props, services: servicesMap, state: effectiveCatalogContext }),
|
|
16472
17730
|
[canvas.props, effectiveCatalogContext, servicesMap]
|
|
16473
17731
|
);
|
|
16474
|
-
const draftSnapshot =
|
|
17732
|
+
const draftSnapshot = useMemo40(
|
|
16475
17733
|
() => buildServiceContextSnapshot({ props: canvas.props, services: servicesMap, state: catalogContextDraft }),
|
|
16476
17734
|
[canvas.props, catalogContextDraft, servicesMap]
|
|
16477
17735
|
);
|
|
16478
|
-
const allChecksById =
|
|
17736
|
+
const allChecksById = useMemo40(() => {
|
|
16479
17737
|
if (!appliedSnapshot.selectedTag) return /* @__PURE__ */ new Map();
|
|
16480
17738
|
const candidateIds = Object.values(servicesMap).map((service) => service.id);
|
|
16481
17739
|
const checks = canvas.api.editor.filterServicesForVisibleGroup(candidateIds, {
|
|
@@ -16487,16 +17745,16 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
|
|
|
16487
17745
|
});
|
|
16488
17746
|
return new Map(checks.map((check) => [String(check.id), check]));
|
|
16489
17747
|
}, [appliedSnapshot, canvas.api.editor, policies2, servicesMap]);
|
|
16490
|
-
const hiddenServiceIds =
|
|
17748
|
+
const hiddenServiceIds = useMemo40(() => {
|
|
16491
17749
|
const ids = new Set(activeServices.map((service) => String(service.id)));
|
|
16492
17750
|
for (const id of appliedSnapshot.usedServiceIds) ids.add(String(id));
|
|
16493
17751
|
return ids;
|
|
16494
17752
|
}, [activeServices, appliedSnapshot.usedServiceIds]);
|
|
16495
|
-
const activeRows =
|
|
17753
|
+
const activeRows = useMemo40(
|
|
16496
17754
|
() => activeServices.map((summary) => buildServiceRowVM({ summary, services: servicesMap, search: activeSearch })).filter((row) => row.matchesSearch),
|
|
16497
17755
|
[activeSearch, activeServices, servicesMap]
|
|
16498
17756
|
);
|
|
16499
|
-
const filteredCatalogRows =
|
|
17757
|
+
const filteredCatalogRows = useMemo40(
|
|
16500
17758
|
() => allServices.map(
|
|
16501
17759
|
(summary) => buildServiceRowVM({
|
|
16502
17760
|
summary,
|
|
@@ -16508,25 +17766,25 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
|
|
|
16508
17766
|
).filter((row) => row.matchesSearch).filter((row) => !compatibleOnly || row.isCompatible).filter((row) => !hideActiveServices || !hiddenServiceIds.has(row.id)),
|
|
16509
17767
|
[allChecksById, allSearch, allServices, compatibleOnly, effectiveCatalogContext, hiddenServiceIds, hideActiveServices, servicesMap]
|
|
16510
17768
|
);
|
|
16511
|
-
|
|
17769
|
+
useEffect26(() => {
|
|
16512
17770
|
const next = createDefaultServiceContext(canvas.props, preferredTagId);
|
|
16513
17771
|
setCatalogContextDraft((current) => {
|
|
16514
17772
|
if (contextLinked) return current;
|
|
16515
17773
|
return current.selectedTagId ? current : next;
|
|
16516
17774
|
});
|
|
16517
17775
|
}, [canvas.props, contextLinked, preferredTagId]);
|
|
16518
|
-
|
|
17776
|
+
useEffect26(() => {
|
|
16519
17777
|
if (!contextLinked) return;
|
|
16520
17778
|
setCatalogContextDraft(liveSelectionContext);
|
|
16521
17779
|
}, [contextLinked, liveSelectionContext]);
|
|
16522
|
-
|
|
17780
|
+
useEffect26(() => {
|
|
16523
17781
|
if (contextLinked) return;
|
|
16524
17782
|
const next = sanitizeServiceContext(draftSnapshot, catalogContextDraft);
|
|
16525
17783
|
if (JSON.stringify(next) !== JSON.stringify(catalogContextDraft)) {
|
|
16526
17784
|
setCatalogContextDraft(next);
|
|
16527
17785
|
}
|
|
16528
17786
|
}, [catalogContextDraft, contextLinked, draftSnapshot]);
|
|
16529
|
-
|
|
17787
|
+
useEffect26(() => {
|
|
16530
17788
|
const editor = canvas.api.editor;
|
|
16531
17789
|
const ensured = editor.getCatalog?.() ?? editor.ensureCatalog?.();
|
|
16532
17790
|
if (ensured) setCatalogState(ensured);
|
|
@@ -16544,19 +17802,19 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
|
|
|
16544
17802
|
};
|
|
16545
17803
|
}, [canvas.api]);
|
|
16546
17804
|
const catalogPanelMode = catalogState?.viewMode === "grouped" ? "catalog" : "all";
|
|
16547
|
-
const catalogGroups =
|
|
17805
|
+
const catalogGroups = useMemo40(
|
|
16548
17806
|
() => (catalogState?.nodes ?? []).filter((node) => node.kind === "group").sort((a, b) => (a.order ?? 0) - (b.order ?? 0) || a.label.localeCompare(b.label)),
|
|
16549
17807
|
[catalogState]
|
|
16550
17808
|
);
|
|
16551
17809
|
const selectedCatalogGroupId = catalogGroups.some((node) => node.id === catalogState?.activeNodeId) ? String(catalogState?.activeNodeId) : null;
|
|
16552
|
-
const groupedServiceIds =
|
|
17810
|
+
const groupedServiceIds = useMemo40(() => {
|
|
16553
17811
|
const ids = /* @__PURE__ */ new Set();
|
|
16554
17812
|
for (const group of catalogGroups) {
|
|
16555
17813
|
for (const serviceId of group.serviceIds) ids.add(String(serviceId));
|
|
16556
17814
|
}
|
|
16557
17815
|
return ids;
|
|
16558
17816
|
}, [catalogGroups]);
|
|
16559
|
-
const catalogRows =
|
|
17817
|
+
const catalogRows = useMemo40(() => {
|
|
16560
17818
|
if (!selectedCatalogGroupId) return filteredCatalogRows.filter((row) => !groupedServiceIds.has(row.id));
|
|
16561
17819
|
const selectedGroup = catalogGroups.find((group) => group.id === selectedCatalogGroupId);
|
|
16562
17820
|
if (!selectedGroup) return filteredCatalogRows.filter((row) => !groupedServiceIds.has(row.id));
|
|
@@ -16564,32 +17822,32 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
|
|
|
16564
17822
|
return filteredCatalogRows.filter((row) => allowedIds.has(row.id));
|
|
16565
17823
|
}, [catalogGroups, filteredCatalogRows, groupedServiceIds, selectedCatalogGroupId]);
|
|
16566
17824
|
const visibleAllRows = catalogPanelMode === "catalog" ? catalogRows : filteredCatalogRows;
|
|
16567
|
-
const notices =
|
|
16568
|
-
const activeNodeIds =
|
|
17825
|
+
const notices = useMemo40(() => normalizeNotices(canvas.props?.notices), [canvas.props]);
|
|
17826
|
+
const activeNodeIds = useMemo40(() => {
|
|
16569
17827
|
const ids = /* @__PURE__ */ new Set();
|
|
16570
17828
|
if (canvas.activeId) ids.add(String(canvas.activeId));
|
|
16571
17829
|
for (const id of canvas.selectionInfo.ids) ids.add(String(id));
|
|
16572
17830
|
return ids;
|
|
16573
17831
|
}, [canvas.activeId, canvas.selectionInfo.ids]);
|
|
16574
17832
|
const consoleIssueCount = errors.validation.length + errors.logs.length + notices.length;
|
|
16575
|
-
|
|
17833
|
+
useEffect26(() => {
|
|
16576
17834
|
setSelectedActiveServiceId((current) => ensureSelectedRow(current, activeRows));
|
|
16577
17835
|
}, [activeRows]);
|
|
16578
|
-
|
|
17836
|
+
useEffect26(() => {
|
|
16579
17837
|
if (catalogState?.selectedServiceId == null) return;
|
|
16580
17838
|
setSelectedAllServiceId(String(catalogState.selectedServiceId));
|
|
16581
17839
|
}, [catalogState?.selectedServiceId]);
|
|
16582
|
-
|
|
17840
|
+
useEffect26(() => {
|
|
16583
17841
|
setSelectedAllServiceId((current) => ensureSelectedRow(current, visibleAllRows));
|
|
16584
17842
|
}, [visibleAllRows]);
|
|
16585
|
-
|
|
17843
|
+
useEffect26(() => {
|
|
16586
17844
|
const desiredIds = controller.isOpen && controller.activeTab === "activeServices" && selectedActiveServiceId ? activeRows.find((row) => row.id === selectedActiveServiceId)?.summary.attachedNodeIds ?? [] : [];
|
|
16587
17845
|
if (!sameIds(lastHighlightedIdsRef.current, desiredIds)) {
|
|
16588
17846
|
canvas.api.setHighlighted(desiredIds);
|
|
16589
17847
|
lastHighlightedIdsRef.current = [...desiredIds];
|
|
16590
17848
|
}
|
|
16591
17849
|
}, [activeRows, canvas.api, controller.activeTab, controller.isOpen, selectedActiveServiceId]);
|
|
16592
|
-
|
|
17850
|
+
useEffect26(() => {
|
|
16593
17851
|
return () => {
|
|
16594
17852
|
if (lastHighlightedIdsRef.current.length) {
|
|
16595
17853
|
canvas.api.setHighlighted([]);
|
|
@@ -16597,10 +17855,10 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
|
|
|
16597
17855
|
}
|
|
16598
17856
|
};
|
|
16599
17857
|
}, [canvas.api]);
|
|
16600
|
-
|
|
17858
|
+
useEffect26(() => {
|
|
16601
17859
|
if (searchOpen) searchInputRef.current?.focus();
|
|
16602
17860
|
}, [searchOpen]);
|
|
16603
|
-
|
|
17861
|
+
useEffect26(() => {
|
|
16604
17862
|
setPanelPosition((current) => {
|
|
16605
17863
|
const resolved = resolvePanelPosition(current, panelRef.current, panelContainerRef.current);
|
|
16606
17864
|
persistPanelPosition(resolved);
|
|
@@ -16622,7 +17880,7 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
|
|
|
16622
17880
|
}
|
|
16623
17881
|
event.preventDefault();
|
|
16624
17882
|
};
|
|
16625
|
-
|
|
17883
|
+
useEffect26(() => {
|
|
16626
17884
|
if (!draggingPanel) return;
|
|
16627
17885
|
const onPointerMove = (event) => {
|
|
16628
17886
|
const start = dragStartRef.current;
|
|
@@ -16650,7 +17908,7 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
|
|
|
16650
17908
|
window.removeEventListener("pointercancel", onPointerUp);
|
|
16651
17909
|
};
|
|
16652
17910
|
}, [draggingPanel, panelPosition]);
|
|
16653
|
-
const setCatalogMode =
|
|
17911
|
+
const setCatalogMode = useCallback22(
|
|
16654
17912
|
(mode) => {
|
|
16655
17913
|
const editor = canvas.api.editor;
|
|
16656
17914
|
editor.ensureCatalog?.();
|
|
@@ -16658,27 +17916,27 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
|
|
|
16658
17916
|
},
|
|
16659
17917
|
[canvas.api.editor]
|
|
16660
17918
|
);
|
|
16661
|
-
const handleSelectCatalogService =
|
|
17919
|
+
const handleSelectCatalogService = useCallback22(
|
|
16662
17920
|
(id) => {
|
|
16663
17921
|
setSelectedAllServiceId(id);
|
|
16664
17922
|
canvas.api.editor.setSelectedCatalogService?.(id ?? void 0);
|
|
16665
17923
|
},
|
|
16666
17924
|
[canvas.api.editor]
|
|
16667
17925
|
);
|
|
16668
|
-
const handleSelectCatalogGroup =
|
|
17926
|
+
const handleSelectCatalogGroup = useCallback22(
|
|
16669
17927
|
(groupId) => {
|
|
16670
17928
|
canvas.api.editor.setActiveCatalogNode?.(groupId ?? void 0);
|
|
16671
17929
|
},
|
|
16672
17930
|
[canvas.api.editor]
|
|
16673
17931
|
);
|
|
16674
|
-
const handleCreateRootGroup =
|
|
17932
|
+
const handleCreateRootGroup = useCallback22(
|
|
16675
17933
|
(label) => {
|
|
16676
17934
|
if (!label.trim()) return;
|
|
16677
17935
|
canvas.api.editor.createCatalogGroup?.({ label: label.trim() });
|
|
16678
17936
|
},
|
|
16679
17937
|
[canvas.api.editor]
|
|
16680
17938
|
);
|
|
16681
|
-
const handleCreateChildGroup =
|
|
17939
|
+
const handleCreateChildGroup = useCallback22(
|
|
16682
17940
|
(label) => {
|
|
16683
17941
|
if (!selectedCatalogGroupId) return;
|
|
16684
17942
|
const editor = canvas.api.editor;
|
|
@@ -16687,7 +17945,7 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
|
|
|
16687
17945
|
},
|
|
16688
17946
|
[canvas.api.editor, selectedCatalogGroupId]
|
|
16689
17947
|
);
|
|
16690
|
-
const handleRenameGroup =
|
|
17948
|
+
const handleRenameGroup = useCallback22(
|
|
16691
17949
|
(label) => {
|
|
16692
17950
|
if (!selectedCatalogGroupId) return;
|
|
16693
17951
|
const group = catalogGroups.find((item) => item.id === selectedCatalogGroupId);
|
|
@@ -16697,15 +17955,15 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
|
|
|
16697
17955
|
},
|
|
16698
17956
|
[canvas.api.editor, catalogGroups, selectedCatalogGroupId]
|
|
16699
17957
|
);
|
|
16700
|
-
const handleDeleteGroup =
|
|
17958
|
+
const handleDeleteGroup = useCallback22(() => {
|
|
16701
17959
|
if (!selectedCatalogGroupId) return;
|
|
16702
17960
|
canvas.api.editor.removeCatalogNode?.(selectedCatalogGroupId, { cascade: true });
|
|
16703
17961
|
}, [canvas.api.editor, selectedCatalogGroupId]);
|
|
16704
|
-
const handleAssignServices =
|
|
17962
|
+
const handleAssignServices = useCallback22(() => {
|
|
16705
17963
|
if (!selectedCatalogGroupId) return;
|
|
16706
17964
|
setServicePickerOpen(true);
|
|
16707
17965
|
}, [selectedCatalogGroupId]);
|
|
16708
|
-
const handleConfirmAssignServices =
|
|
17966
|
+
const handleConfirmAssignServices = useCallback22(
|
|
16709
17967
|
(serviceIds) => {
|
|
16710
17968
|
if (!selectedCatalogGroupId || !serviceIds.length) return;
|
|
16711
17969
|
canvas.api.editor.assignServicesToCatalogGroup?.(selectedCatalogGroupId, serviceIds, "append");
|
|
@@ -16713,18 +17971,18 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
|
|
|
16713
17971
|
[canvas.api.editor, selectedCatalogGroupId]
|
|
16714
17972
|
);
|
|
16715
17973
|
const tabs = [
|
|
16716
|
-
{ id: "console", label: "Console", icon: /* @__PURE__ */
|
|
16717
|
-
{ id: "activeServices", label: "Active Services", icon: /* @__PURE__ */
|
|
16718
|
-
{ id: "allServices", label: "All Services", icon: /* @__PURE__ */
|
|
17974
|
+
{ id: "console", label: "Console", icon: /* @__PURE__ */ jsx88(FiTerminal2, {}), count: consoleIssueCount },
|
|
17975
|
+
{ id: "activeServices", label: "Active Services", icon: /* @__PURE__ */ jsx88(MdOutlineSync, {}), count: activeServices.length },
|
|
17976
|
+
{ id: "allServices", label: "All Services", icon: /* @__PURE__ */ jsx88(LuLayers3, {}), count: allServices.length }
|
|
16719
17977
|
];
|
|
16720
17978
|
const selectedActiveRow = activeRows.find((row) => row.id === selectedActiveServiceId) ?? null;
|
|
16721
17979
|
const selectedAllRow = visibleAllRows.find((row) => row.id === selectedAllServiceId) ?? null;
|
|
16722
17980
|
const selectedCatalogGroup = catalogGroups.find((group) => group.id === selectedCatalogGroupId) ?? null;
|
|
16723
|
-
const
|
|
17981
|
+
const Search3 = useMemo40(() => {
|
|
16724
17982
|
if (!["allServices", "activeServices"].includes(controller.activeTab)) return;
|
|
16725
17983
|
const method = controller.activeTab == "allServices" ? setAllSearch : setActiveSearch;
|
|
16726
17984
|
const value = controller.activeTab == "allServices" ? allSearch : activeSearch;
|
|
16727
|
-
return /* @__PURE__ */
|
|
17985
|
+
return /* @__PURE__ */ jsx88("div", { className: "absolute top-0 right-0 z-10", children: /* @__PURE__ */ jsx88(
|
|
16728
17986
|
"input",
|
|
16729
17987
|
{
|
|
16730
17988
|
ref: searchInputRef,
|
|
@@ -16746,8 +18004,8 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
|
|
|
16746
18004
|
}
|
|
16747
18005
|
) });
|
|
16748
18006
|
}, [controller.activeTab, activeSearch, allSearch, setActiveSearch, setAllSearch]);
|
|
16749
|
-
return /* @__PURE__ */
|
|
16750
|
-
/* @__PURE__ */
|
|
18007
|
+
return /* @__PURE__ */ jsxs66("div", { ref: panelContainerRef, className: "pointer-events-none absolute inset-0", children: [
|
|
18008
|
+
/* @__PURE__ */ jsx88(
|
|
16751
18009
|
ServicePickerDialog,
|
|
16752
18010
|
{
|
|
16753
18011
|
open: servicePickerOpen,
|
|
@@ -16760,7 +18018,7 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
|
|
|
16760
18018
|
onConfirm: handleConfirmAssignServices
|
|
16761
18019
|
}
|
|
16762
18020
|
),
|
|
16763
|
-
/* @__PURE__ */
|
|
18021
|
+
/* @__PURE__ */ jsxs66(
|
|
16764
18022
|
Panel,
|
|
16765
18023
|
{
|
|
16766
18024
|
ref: panelRef,
|
|
@@ -16791,8 +18049,8 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
|
|
|
16791
18049
|
["--bottom-panel-height"]: controller.height + "px"
|
|
16792
18050
|
},
|
|
16793
18051
|
children: [
|
|
16794
|
-
/* @__PURE__ */
|
|
16795
|
-
/* @__PURE__ */
|
|
18052
|
+
/* @__PURE__ */ jsxs66("div", { className: "flex items-center justify-between gap-3 border-b border-slate-200/80 px-3 py-2 dark:border-slate-800/80", children: [
|
|
18053
|
+
/* @__PURE__ */ jsx88("div", { className: "flex min-w-0 items-center gap-1", children: tabs.map((tab) => /* @__PURE__ */ jsxs66(
|
|
16796
18054
|
"button",
|
|
16797
18055
|
{
|
|
16798
18056
|
type: "button",
|
|
@@ -16802,9 +18060,9 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
|
|
|
16802
18060
|
controller.activeTab === tab.id ? "bg-slate-100 text-slate-900 dark:bg-slate-900 dark:text-slate-100" : "text-slate-500 hover:bg-slate-100 hover:text-slate-900 dark:text-slate-400 dark:hover:bg-slate-900 dark:hover:text-slate-100"
|
|
16803
18061
|
),
|
|
16804
18062
|
children: [
|
|
16805
|
-
/* @__PURE__ */
|
|
16806
|
-
/* @__PURE__ */
|
|
16807
|
-
typeof tab.count === "number" ? /* @__PURE__ */
|
|
18063
|
+
/* @__PURE__ */ jsx88("span", { className: "text-base", children: tab.icon }),
|
|
18064
|
+
/* @__PURE__ */ jsx88("span", { className: "truncate", children: tab.label }),
|
|
18065
|
+
typeof tab.count === "number" ? /* @__PURE__ */ jsx88(
|
|
16808
18066
|
"span",
|
|
16809
18067
|
{
|
|
16810
18068
|
className: cn(
|
|
@@ -16818,8 +18076,8 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
|
|
|
16818
18076
|
},
|
|
16819
18077
|
tab.id
|
|
16820
18078
|
)) }),
|
|
16821
|
-
/* @__PURE__ */
|
|
16822
|
-
/* @__PURE__ */
|
|
18079
|
+
/* @__PURE__ */ jsxs66("div", { className: "flex items-center gap-1", children: [
|
|
18080
|
+
/* @__PURE__ */ jsxs66(
|
|
16823
18081
|
"button",
|
|
16824
18082
|
{
|
|
16825
18083
|
type: "button",
|
|
@@ -16829,16 +18087,16 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
|
|
|
16829
18087
|
draggingPanel && "cursor-grabbing"
|
|
16830
18088
|
),
|
|
16831
18089
|
children: [
|
|
16832
|
-
/* @__PURE__ */
|
|
16833
|
-
/* @__PURE__ */
|
|
18090
|
+
/* @__PURE__ */ jsx88(LuGripHorizontal, {}),
|
|
18091
|
+
/* @__PURE__ */ jsx88("span", { children: draggingPanel ? "Dragging panel..." : "Drag panel" })
|
|
16834
18092
|
]
|
|
16835
18093
|
}
|
|
16836
18094
|
),
|
|
16837
|
-
/* @__PURE__ */
|
|
16838
|
-
/* @__PURE__ */
|
|
16839
|
-
/* @__PURE__ */
|
|
18095
|
+
/* @__PURE__ */ jsxs66("div", { className: "hidden items-center gap-2 rounded-xl border border-slate-200/80 px-2 py-1 text-xs text-slate-500 md:flex dark:border-slate-800 dark:text-slate-400", children: [
|
|
18096
|
+
/* @__PURE__ */ jsx88(LuGripHorizontal, {}),
|
|
18097
|
+
/* @__PURE__ */ jsx88("span", { children: "Resize from top or side edges" })
|
|
16840
18098
|
] }),
|
|
16841
|
-
/* @__PURE__ */
|
|
18099
|
+
/* @__PURE__ */ jsx88(
|
|
16842
18100
|
Button,
|
|
16843
18101
|
{
|
|
16844
18102
|
type: "button",
|
|
@@ -16846,30 +18104,30 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
|
|
|
16846
18104
|
size: "sm",
|
|
16847
18105
|
onClick: () => controller.close(),
|
|
16848
18106
|
className: "h-8 rounded-xl px-2 text-slate-500 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-100",
|
|
16849
|
-
children: /* @__PURE__ */
|
|
18107
|
+
children: /* @__PURE__ */ jsx88(FiX6, {})
|
|
16850
18108
|
}
|
|
16851
18109
|
)
|
|
16852
18110
|
] })
|
|
16853
18111
|
] }),
|
|
16854
|
-
/* @__PURE__ */
|
|
16855
|
-
controller.activeTab !== "console" ? /* @__PURE__ */
|
|
16856
|
-
/* @__PURE__ */
|
|
16857
|
-
/* @__PURE__ */
|
|
16858
|
-
/* @__PURE__ */
|
|
18112
|
+
/* @__PURE__ */ jsxs66("div", { className: "flex min-h-0 flex-1 flex-col bg-slate-50/70 dark:bg-slate-950/40", children: [
|
|
18113
|
+
controller.activeTab !== "console" ? /* @__PURE__ */ jsxs66("div", { className: "flex items-center justify-between gap-3 border-b border-slate-200/70 px-4 py-3 dark:border-slate-800/70", children: [
|
|
18114
|
+
/* @__PURE__ */ jsxs66("div", { className: "min-w-0", children: [
|
|
18115
|
+
/* @__PURE__ */ jsx88("p", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: controller.activeTab === "activeServices" ? "Connected services" : "Service catalog" }),
|
|
18116
|
+
/* @__PURE__ */ jsx88("p", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: controller.activeTab === "activeServices" ? "Bound services can be highlighted back onto the canvas from here." : catalogPanelMode === "catalog" ? "Browse source services through manual editor-side catalog groups while keeping detail and compatibility visible." : "Browse every source service, filter by current visible-group compatibility, and drag it onto nodes." })
|
|
16859
18117
|
] }),
|
|
16860
|
-
/* @__PURE__ */
|
|
16861
|
-
searchOpen ?
|
|
16862
|
-
/* @__PURE__ */
|
|
18118
|
+
/* @__PURE__ */ jsx88("div", { className: "flex items-center gap-3", children: /* @__PURE__ */ jsxs66("div", { className: "relative flex items-center gap-2", children: [
|
|
18119
|
+
searchOpen ? Search3 : null,
|
|
18120
|
+
/* @__PURE__ */ jsx88(
|
|
16863
18121
|
HeaderIconButton,
|
|
16864
18122
|
{
|
|
16865
18123
|
label: "Search services",
|
|
16866
18124
|
active: searchOpen || Boolean(allSearch),
|
|
16867
18125
|
onClick: () => setSearchOpen(true),
|
|
16868
|
-
children: /* @__PURE__ */
|
|
18126
|
+
children: /* @__PURE__ */ jsx88(FiSearch, {})
|
|
16869
18127
|
}
|
|
16870
18128
|
),
|
|
16871
|
-
controller.activeTab === "allServices" ? /* @__PURE__ */
|
|
16872
|
-
/* @__PURE__ */
|
|
18129
|
+
controller.activeTab === "allServices" ? /* @__PURE__ */ jsxs66(Fragment17, { children: [
|
|
18130
|
+
/* @__PURE__ */ jsx88(
|
|
16873
18131
|
CatalogContextPopover,
|
|
16874
18132
|
{
|
|
16875
18133
|
open: filterOpen,
|
|
@@ -16883,20 +18141,20 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
|
|
|
16883
18141
|
onDraftContextChange: setCatalogContextDraft
|
|
16884
18142
|
}
|
|
16885
18143
|
),
|
|
16886
|
-
/* @__PURE__ */
|
|
16887
|
-
/* @__PURE__ */
|
|
18144
|
+
/* @__PURE__ */ jsx88(CatalogModeSwitch, { mode: catalogPanelMode, onChange: setCatalogMode }),
|
|
18145
|
+
/* @__PURE__ */ jsx88(
|
|
16888
18146
|
HeaderIconButton,
|
|
16889
18147
|
{
|
|
16890
18148
|
label: "Hide active services",
|
|
16891
18149
|
active: hideActiveServices,
|
|
16892
18150
|
onClick: () => setHideActiveServices((current) => !current),
|
|
16893
|
-
children: hideActiveServices ? /* @__PURE__ */
|
|
18151
|
+
children: hideActiveServices ? /* @__PURE__ */ jsx88(FiEyeOff2, {}) : /* @__PURE__ */ jsx88(FiEye3, {})
|
|
16894
18152
|
}
|
|
16895
18153
|
)
|
|
16896
18154
|
] }) : null
|
|
16897
18155
|
] }) })
|
|
16898
18156
|
] }) : null,
|
|
16899
|
-
controller.activeTab === "console" ? /* @__PURE__ */
|
|
18157
|
+
controller.activeTab === "console" ? /* @__PURE__ */ jsx88(ScrollArea, { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsx88("div", { className: "p-4", children: /* @__PURE__ */ jsx88(
|
|
16900
18158
|
ConsoleTab,
|
|
16901
18159
|
{
|
|
16902
18160
|
errors,
|
|
@@ -16922,7 +18180,7 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
|
|
|
16922
18180
|
onNodeClick: (nodeId) => focusNode(canvas, nodeId)
|
|
16923
18181
|
}
|
|
16924
18182
|
) }) }) : null,
|
|
16925
|
-
controller.activeTab === "activeServices" ? /* @__PURE__ */
|
|
18183
|
+
controller.activeTab === "activeServices" ? /* @__PURE__ */ jsx88(
|
|
16926
18184
|
ServicesSplitPane,
|
|
16927
18185
|
{
|
|
16928
18186
|
mode: "active",
|
|
@@ -16943,7 +18201,7 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
|
|
|
16943
18201
|
})
|
|
16944
18202
|
}
|
|
16945
18203
|
) : null,
|
|
16946
|
-
controller.activeTab === "allServices" ? /* @__PURE__ */
|
|
18204
|
+
controller.activeTab === "allServices" ? /* @__PURE__ */ jsx88(
|
|
16947
18205
|
ServicesSplitPane,
|
|
16948
18206
|
{
|
|
16949
18207
|
mode: catalogPanelMode,
|
|
@@ -16996,8 +18254,8 @@ function HeaderIconButton({
|
|
|
16996
18254
|
active = false,
|
|
16997
18255
|
onClick
|
|
16998
18256
|
}) {
|
|
16999
|
-
return /* @__PURE__ */
|
|
17000
|
-
/* @__PURE__ */
|
|
18257
|
+
return /* @__PURE__ */ jsxs66(Tooltip, { children: [
|
|
18258
|
+
/* @__PURE__ */ jsx88(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx88(
|
|
17001
18259
|
"button",
|
|
17002
18260
|
{
|
|
17003
18261
|
type: "button",
|
|
@@ -17010,12 +18268,12 @@ function HeaderIconButton({
|
|
|
17010
18268
|
children
|
|
17011
18269
|
}
|
|
17012
18270
|
) }),
|
|
17013
|
-
/* @__PURE__ */
|
|
18271
|
+
/* @__PURE__ */ jsx88(TooltipContent, { side: "top", sideOffset: 8, children: label })
|
|
17014
18272
|
] });
|
|
17015
18273
|
}
|
|
17016
18274
|
function CatalogModeSwitch({ mode, onChange }) {
|
|
17017
|
-
return /* @__PURE__ */
|
|
17018
|
-
/* @__PURE__ */
|
|
18275
|
+
return /* @__PURE__ */ jsxs66("div", { className: "inline-flex items-center rounded-xl border border-slate-200 bg-white p-1 dark:border-slate-800 dark:bg-slate-950", children: [
|
|
18276
|
+
/* @__PURE__ */ jsx88(
|
|
17019
18277
|
"button",
|
|
17020
18278
|
{
|
|
17021
18279
|
type: "button",
|
|
@@ -17027,7 +18285,7 @@ function CatalogModeSwitch({ mode, onChange }) {
|
|
|
17027
18285
|
children: "All"
|
|
17028
18286
|
}
|
|
17029
18287
|
),
|
|
17030
|
-
/* @__PURE__ */
|
|
18288
|
+
/* @__PURE__ */ jsx88(
|
|
17031
18289
|
"button",
|
|
17032
18290
|
{
|
|
17033
18291
|
type: "button",
|
|
@@ -17050,7 +18308,7 @@ import {
|
|
|
17050
18308
|
useWorkspace as useWorkspace17,
|
|
17051
18309
|
Workspace
|
|
17052
18310
|
} from "@timeax/digital-service-engine/workspace";
|
|
17053
|
-
import { useMemo as
|
|
18311
|
+
import { useMemo as useMemo41, useState as useState42 } from "react";
|
|
17054
18312
|
|
|
17055
18313
|
// backend/memory/create-backend.ts
|
|
17056
18314
|
import { createMemoryWorkspaceBackend } from "@timeax/digital-service-engine/workspace";
|
|
@@ -56453,7 +57711,7 @@ var workspaceBackend = {
|
|
|
56453
57711
|
};
|
|
56454
57712
|
|
|
56455
57713
|
// src/index.tsx
|
|
56456
|
-
import { Fragment as
|
|
57714
|
+
import { Fragment as Fragment18, jsx as jsx89, jsxs as jsxs67 } from "react/jsx-runtime";
|
|
56457
57715
|
var inputRegistry = createInputRegistry();
|
|
56458
57716
|
registerEntries(inputRegistry);
|
|
56459
57717
|
function WorkspaceLayout({ onShare, onPlay, menu }) {
|
|
@@ -56461,13 +57719,13 @@ function WorkspaceLayout({ onShare, onPlay, menu }) {
|
|
|
56461
57719
|
const ws = useWorkspace17();
|
|
56462
57720
|
const errors = useErrors();
|
|
56463
57721
|
const bottomPanel = useBottomConsolePanel();
|
|
56464
|
-
const [draggingServiceId, setDraggingServiceId] =
|
|
56465
|
-
const serviceSummary =
|
|
56466
|
-
return /* @__PURE__ */
|
|
56467
|
-
/* @__PURE__ */
|
|
56468
|
-
/* @__PURE__ */
|
|
56469
|
-
/* @__PURE__ */
|
|
56470
|
-
/* @__PURE__ */
|
|
57722
|
+
const [draggingServiceId, setDraggingServiceId] = useState42(null);
|
|
57723
|
+
const serviceSummary = useMemo41(() => buildServiceSummaries(canvas, ws), [canvas.props, canvas.selectionInfo, canvas.activeId, ws.services.data]);
|
|
57724
|
+
return /* @__PURE__ */ jsx89(FallbackQuickAddProvider, { children: /* @__PURE__ */ jsx89(NodeContextMenuProvider, { children: /* @__PURE__ */ jsx89(FallbackEditorModalProvider, { children: /* @__PURE__ */ jsxs67("div", { className: "relative flex h-screen flex-col overflow-hidden *:font-display", children: [
|
|
57725
|
+
/* @__PURE__ */ jsx89("div", { className: "pointer-events-none absolute top-4 left-1/2 z-30 w-full max-w-2xl -translate-x-1/2 px-4", children: /* @__PURE__ */ jsx89("div", { className: "pointer-events-auto", children: /* @__PURE__ */ jsx89(WorkspaceBootStatusSurface, { boot: ws.boot }) }) }),
|
|
57726
|
+
/* @__PURE__ */ jsxs67("div", { className: "flex grow overflow-hidden", children: [
|
|
57727
|
+
/* @__PURE__ */ jsx89(left_default, { menu }),
|
|
57728
|
+
/* @__PURE__ */ jsx89(
|
|
56471
57729
|
CanvasPanel,
|
|
56472
57730
|
{
|
|
56473
57731
|
errors,
|
|
@@ -56476,9 +57734,9 @@ function WorkspaceLayout({ onShare, onPlay, menu }) {
|
|
|
56476
57734
|
onServiceDragStateChange: (serviceId) => setDraggingServiceId(serviceId)
|
|
56477
57735
|
}
|
|
56478
57736
|
),
|
|
56479
|
-
/* @__PURE__ */
|
|
57737
|
+
/* @__PURE__ */ jsx89(right_default, { onShare, onPlay })
|
|
56480
57738
|
] }),
|
|
56481
|
-
/* @__PURE__ */
|
|
57739
|
+
/* @__PURE__ */ jsx89("div", { className: "pointer-events-none absolute inset-0 z-5", children: /* @__PURE__ */ jsx89(
|
|
56482
57740
|
BottomConsolePanel,
|
|
56483
57741
|
{
|
|
56484
57742
|
controller: bottomPanel,
|
|
@@ -56566,13 +57824,13 @@ var Styles = `
|
|
|
56566
57824
|
|
|
56567
57825
|
`;
|
|
56568
57826
|
function ServiceBuilder({ backend, actor, ratePolicy, fallbackSettings, onShare, onPlay, menu }) {
|
|
56569
|
-
return /* @__PURE__ */
|
|
56570
|
-
/* @__PURE__ */
|
|
56571
|
-
/* @__PURE__ */
|
|
57827
|
+
return /* @__PURE__ */ jsxs67(Fragment18, { children: [
|
|
57828
|
+
/* @__PURE__ */ jsx89("style", { children: Styles }),
|
|
57829
|
+
/* @__PURE__ */ jsx89(InputsProvider, { initialRegistry: inputRegistry, children: /* @__PURE__ */ jsx89(Workspace, { backend, actor, ratePolicy, fallbackSettings, children: () => /* @__PURE__ */ jsx89(WorkspaceLayout, { onShare, onPlay, menu }) }) })
|
|
56572
57830
|
] });
|
|
56573
57831
|
}
|
|
56574
57832
|
function ServiceBuilderWorkspace({ ratePolicy, fallbackSettings, onShare, onPlay, menu }) {
|
|
56575
|
-
return /* @__PURE__ */
|
|
57833
|
+
return /* @__PURE__ */ jsx89(
|
|
56576
57834
|
ServiceBuilder,
|
|
56577
57835
|
{
|
|
56578
57836
|
backend: workspaceBackend,
|
|
@@ -56586,6 +57844,7 @@ function ServiceBuilderWorkspace({ ratePolicy, fallbackSettings, onShare, onPlay
|
|
|
56586
57844
|
);
|
|
56587
57845
|
}
|
|
56588
57846
|
export {
|
|
57847
|
+
NativeFallbackEditor,
|
|
56589
57848
|
ServiceBuilder,
|
|
56590
57849
|
ServiceBuilderWorkspace
|
|
56591
57850
|
};
|