@timeax/digital-service-engine 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/index.cjs +364 -119
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +8 -11
- package/dist/core/index.d.ts +8 -11
- package/dist/core/index.js +363 -119
- package/dist/core/index.js.map +1 -1
- package/dist/react/index.cjs +682 -468
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +2 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +682 -468
- package/dist/react/index.js.map +1 -1
- package/dist/schema/index.d.cts +12 -1
- package/dist/schema/index.d.ts +12 -1
- package/dist/workspace/index.cjs +154 -68
- package/dist/workspace/index.cjs.map +1 -1
- package/dist/workspace/index.js +154 -68
- package/dist/workspace/index.js.map +1 -1
- package/package.json +1 -1
package/dist/react/index.cjs
CHANGED
|
@@ -1909,6 +1909,9 @@ function toFiniteNumber(v) {
|
|
|
1909
1909
|
const n = Number(v);
|
|
1910
1910
|
return Number.isFinite(n) ? n : NaN;
|
|
1911
1911
|
}
|
|
1912
|
+
function isValidServiceIdRef(value) {
|
|
1913
|
+
return typeof value === "number" && Number.isFinite(value) || typeof value === "string" && value.trim().length > 0;
|
|
1914
|
+
}
|
|
1912
1915
|
function constraintFitOk(svcMap, candidate, constraints) {
|
|
1913
1916
|
const cap = getServiceCapability(svcMap, candidate);
|
|
1914
1917
|
if (!cap) return false;
|
|
@@ -1917,18 +1920,32 @@ function constraintFitOk(svcMap, candidate, constraints) {
|
|
|
1917
1920
|
return !(constraints.cancel === true && !cap.cancel);
|
|
1918
1921
|
}
|
|
1919
1922
|
function getServiceCapability(svcMap, candidate) {
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
if (
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1923
|
+
var _a;
|
|
1924
|
+
return (_a = getServiceCapabilityEntry(svcMap, candidate)) == null ? void 0 : _a.capability;
|
|
1925
|
+
}
|
|
1926
|
+
function getServiceCapabilityCanonicalRef(svcMap, candidate) {
|
|
1927
|
+
const entry = getServiceCapabilityEntry(svcMap, candidate);
|
|
1928
|
+
if (!entry) return void 0;
|
|
1929
|
+
return getCanonicalServiceRef(entry.key, entry.capability);
|
|
1930
|
+
}
|
|
1931
|
+
function getServiceCapabilityAliases(svcMap, candidate) {
|
|
1932
|
+
const entry = getServiceCapabilityEntry(svcMap, candidate);
|
|
1933
|
+
if (!entry) return [];
|
|
1934
|
+
return collectServiceRefAliases(entry.key, entry.capability);
|
|
1935
|
+
}
|
|
1936
|
+
function isSameServiceCapabilityRef(svcMap, left, right) {
|
|
1937
|
+
if (!isValidServiceIdRef(left) || !isValidServiceIdRef(right)) return false;
|
|
1938
|
+
const leftAliases = new Set(
|
|
1939
|
+
getServiceCapabilityAliases(svcMap, left).map((value) => String(value))
|
|
1940
|
+
);
|
|
1941
|
+
if (!leftAliases.size) {
|
|
1942
|
+
leftAliases.add(String(left));
|
|
1930
1943
|
}
|
|
1931
|
-
|
|
1944
|
+
const rightAliases = getServiceCapabilityAliases(svcMap, right);
|
|
1945
|
+
if (!rightAliases.length) {
|
|
1946
|
+
return leftAliases.has(String(right));
|
|
1947
|
+
}
|
|
1948
|
+
return rightAliases.some((value) => leftAliases.has(String(value)));
|
|
1932
1949
|
}
|
|
1933
1950
|
function normalizeRatePolicy(policy) {
|
|
1934
1951
|
var _a;
|
|
@@ -1964,6 +1981,74 @@ function rateOk(svcMap, candidate, primary, policy) {
|
|
|
1964
1981
|
if (!Number.isFinite(cRate) || !Number.isFinite(pRate)) return false;
|
|
1965
1982
|
return passesRatePolicy(policy.ratePolicy, pRate, cRate);
|
|
1966
1983
|
}
|
|
1984
|
+
function getServiceCapabilityEntry(svcMap, candidate) {
|
|
1985
|
+
if (candidate === void 0 || candidate === null) return void 0;
|
|
1986
|
+
const direct = svcMap[candidate];
|
|
1987
|
+
if (direct) {
|
|
1988
|
+
return { key: String(candidate), capability: direct };
|
|
1989
|
+
}
|
|
1990
|
+
const byString = svcMap[String(candidate)];
|
|
1991
|
+
if (byString) {
|
|
1992
|
+
return { key: String(candidate), capability: byString };
|
|
1993
|
+
}
|
|
1994
|
+
if (typeof candidate === "string") {
|
|
1995
|
+
const maybeNumber = Number(candidate);
|
|
1996
|
+
if (Number.isFinite(maybeNumber)) {
|
|
1997
|
+
const byNumber = svcMap[maybeNumber];
|
|
1998
|
+
if (byNumber) {
|
|
1999
|
+
return { key: String(maybeNumber), capability: byNumber };
|
|
2000
|
+
}
|
|
2001
|
+
}
|
|
2002
|
+
}
|
|
2003
|
+
const target = String(candidate);
|
|
2004
|
+
for (const [key, capability] of Object.entries(svcMap != null ? svcMap : {})) {
|
|
2005
|
+
if (collectServiceRefAliases(key, capability).some(
|
|
2006
|
+
(alias) => String(alias) === target
|
|
2007
|
+
)) {
|
|
2008
|
+
return { key, capability };
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
2011
|
+
return void 0;
|
|
2012
|
+
}
|
|
2013
|
+
function collectServiceRefAliases(key, capability) {
|
|
2014
|
+
const out = [];
|
|
2015
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2016
|
+
const push = (value) => {
|
|
2017
|
+
if (!isValidServiceIdRef(value)) return;
|
|
2018
|
+
const normalized = normalizeServiceRef(value);
|
|
2019
|
+
if (!normalized) return;
|
|
2020
|
+
const aliasKey = String(normalized);
|
|
2021
|
+
if (seen.has(aliasKey)) return;
|
|
2022
|
+
seen.add(aliasKey);
|
|
2023
|
+
out.push(normalized);
|
|
2024
|
+
};
|
|
2025
|
+
push(getCanonicalServiceRef(key, capability));
|
|
2026
|
+
push(capability.service);
|
|
2027
|
+
push(capability.key);
|
|
2028
|
+
push(capability.id);
|
|
2029
|
+
return out;
|
|
2030
|
+
}
|
|
2031
|
+
function getCanonicalServiceRef(key, capability) {
|
|
2032
|
+
const explicitRefs = [capability.service, capability.key, capability.id];
|
|
2033
|
+
for (const ref of explicitRefs) {
|
|
2034
|
+
if (!isValidServiceIdRef(ref)) continue;
|
|
2035
|
+
if (String(ref) === key) {
|
|
2036
|
+
return ref;
|
|
2037
|
+
}
|
|
2038
|
+
}
|
|
2039
|
+
return normalizeServiceRef(key);
|
|
2040
|
+
}
|
|
2041
|
+
function normalizeServiceRef(value) {
|
|
2042
|
+
if (!isValidServiceIdRef(value)) return void 0;
|
|
2043
|
+
if (typeof value === "number") return value;
|
|
2044
|
+
const trimmed = value.trim();
|
|
2045
|
+
if (!trimmed) return void 0;
|
|
2046
|
+
const asNumber = Number(trimmed);
|
|
2047
|
+
if (Number.isFinite(asNumber) && String(asNumber) === trimmed) {
|
|
2048
|
+
return asNumber;
|
|
2049
|
+
}
|
|
2050
|
+
return trimmed;
|
|
2051
|
+
}
|
|
1967
2052
|
|
|
1968
2053
|
// src/core/validate/steps/rates.ts
|
|
1969
2054
|
function validateRates(v) {
|
|
@@ -3409,7 +3494,7 @@ function collectFailedFallbacks(props, services, settings) {
|
|
|
3409
3494
|
const s = { ...DEFAULT_SETTINGS, ...settings != null ? settings : {} };
|
|
3410
3495
|
const out = [];
|
|
3411
3496
|
const fb = (_a = props.fallbacks) != null ? _a : {};
|
|
3412
|
-
const primaryRate = (
|
|
3497
|
+
const primaryRate = (primary) => rateOf(services, primary);
|
|
3413
3498
|
for (const [nodeId, list] of Object.entries((_b = fb.nodes) != null ? _b : {})) {
|
|
3414
3499
|
const { primary, tagContexts } = primaryForNode(props, nodeId);
|
|
3415
3500
|
if (!primary) {
|
|
@@ -3422,34 +3507,34 @@ function collectFailedFallbacks(props, services, settings) {
|
|
|
3422
3507
|
});
|
|
3423
3508
|
continue;
|
|
3424
3509
|
}
|
|
3425
|
-
for (const
|
|
3426
|
-
const
|
|
3427
|
-
if (!
|
|
3510
|
+
for (const candidate of list) {
|
|
3511
|
+
const capability = getCap(services, candidate);
|
|
3512
|
+
if (!capability) {
|
|
3428
3513
|
out.push({
|
|
3429
3514
|
scope: "node",
|
|
3430
3515
|
nodeId,
|
|
3431
3516
|
primary,
|
|
3432
|
-
candidate
|
|
3517
|
+
candidate,
|
|
3433
3518
|
reason: "unknown_service"
|
|
3434
3519
|
});
|
|
3435
3520
|
continue;
|
|
3436
3521
|
}
|
|
3437
|
-
if (
|
|
3522
|
+
if (isSameServiceCapabilityRef(services, candidate, primary)) {
|
|
3438
3523
|
out.push({
|
|
3439
3524
|
scope: "node",
|
|
3440
3525
|
nodeId,
|
|
3441
3526
|
primary,
|
|
3442
|
-
candidate
|
|
3527
|
+
candidate,
|
|
3443
3528
|
reason: "cycle"
|
|
3444
3529
|
});
|
|
3445
3530
|
continue;
|
|
3446
3531
|
}
|
|
3447
|
-
if (!passesRate(s.ratePolicy, primaryRate(primary),
|
|
3532
|
+
if (!passesRate(s.ratePolicy, primaryRate(primary), capability.rate)) {
|
|
3448
3533
|
out.push({
|
|
3449
3534
|
scope: "node",
|
|
3450
3535
|
nodeId,
|
|
3451
3536
|
primary,
|
|
3452
|
-
candidate
|
|
3537
|
+
candidate,
|
|
3453
3538
|
reason: "rate_violation"
|
|
3454
3539
|
});
|
|
3455
3540
|
continue;
|
|
@@ -3459,58 +3544,55 @@ function collectFailedFallbacks(props, services, settings) {
|
|
|
3459
3544
|
scope: "node",
|
|
3460
3545
|
nodeId,
|
|
3461
3546
|
primary,
|
|
3462
|
-
candidate
|
|
3547
|
+
candidate,
|
|
3463
3548
|
reason: "no_tag_context"
|
|
3464
3549
|
});
|
|
3465
3550
|
continue;
|
|
3466
3551
|
}
|
|
3467
|
-
let anyPass = false;
|
|
3468
|
-
let anyFail = false;
|
|
3469
3552
|
for (const tagId of tagContexts) {
|
|
3470
|
-
const
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3553
|
+
const fitsConstraints = s.requireConstraintFit ? satisfiesTagConstraints(
|
|
3554
|
+
tagId,
|
|
3555
|
+
{ services, props },
|
|
3556
|
+
capability
|
|
3557
|
+
) : true;
|
|
3558
|
+
if (fitsConstraints) continue;
|
|
3559
|
+
out.push({
|
|
3560
|
+
scope: "node",
|
|
3561
|
+
nodeId,
|
|
3562
|
+
primary,
|
|
3563
|
+
candidate,
|
|
3564
|
+
tagContext: tagId,
|
|
3565
|
+
reason: "constraint_mismatch"
|
|
3566
|
+
});
|
|
3483
3567
|
}
|
|
3484
|
-
void anyPass;
|
|
3485
|
-
void anyFail;
|
|
3486
3568
|
}
|
|
3487
3569
|
}
|
|
3488
3570
|
for (const [primary, list] of Object.entries((_c = fb.global) != null ? _c : {})) {
|
|
3489
|
-
for (const
|
|
3490
|
-
const
|
|
3491
|
-
if (!
|
|
3571
|
+
for (const candidate of list) {
|
|
3572
|
+
const capability = getCap(services, candidate);
|
|
3573
|
+
if (!capability) {
|
|
3492
3574
|
out.push({
|
|
3493
3575
|
scope: "global",
|
|
3494
3576
|
primary,
|
|
3495
|
-
candidate
|
|
3577
|
+
candidate,
|
|
3496
3578
|
reason: "unknown_service"
|
|
3497
3579
|
});
|
|
3498
3580
|
continue;
|
|
3499
3581
|
}
|
|
3500
|
-
if (
|
|
3582
|
+
if (isSameServiceCapabilityRef(services, candidate, primary)) {
|
|
3501
3583
|
out.push({
|
|
3502
3584
|
scope: "global",
|
|
3503
3585
|
primary,
|
|
3504
|
-
candidate
|
|
3586
|
+
candidate,
|
|
3505
3587
|
reason: "cycle"
|
|
3506
3588
|
});
|
|
3507
3589
|
continue;
|
|
3508
3590
|
}
|
|
3509
|
-
if (!passesRate(s.ratePolicy, primaryRate(primary),
|
|
3591
|
+
if (!passesRate(s.ratePolicy, primaryRate(primary), capability.rate)) {
|
|
3510
3592
|
out.push({
|
|
3511
3593
|
scope: "global",
|
|
3512
3594
|
primary,
|
|
3513
|
-
candidate
|
|
3595
|
+
candidate,
|
|
3514
3596
|
reason: "rate_violation"
|
|
3515
3597
|
});
|
|
3516
3598
|
}
|
|
@@ -3519,52 +3601,61 @@ function collectFailedFallbacks(props, services, settings) {
|
|
|
3519
3601
|
return out;
|
|
3520
3602
|
}
|
|
3521
3603
|
function rateOf(map, id) {
|
|
3522
|
-
var _a;
|
|
3604
|
+
var _a, _b;
|
|
3523
3605
|
if (id === void 0 || id === null) return void 0;
|
|
3524
|
-
|
|
3525
|
-
return (_a = c == null ? void 0 : c.rate) != null ? _a : void 0;
|
|
3606
|
+
return (_b = (_a = getCap(map, id)) == null ? void 0 : _a.rate) != null ? _b : void 0;
|
|
3526
3607
|
}
|
|
3527
|
-
function passesRate(policy, primaryRate,
|
|
3528
|
-
if (typeof
|
|
3608
|
+
function passesRate(policy, primaryRate, candidateRate) {
|
|
3609
|
+
if (typeof candidateRate !== "number" || !Number.isFinite(candidateRate)) {
|
|
3529
3610
|
return false;
|
|
3530
|
-
|
|
3611
|
+
}
|
|
3612
|
+
if (typeof primaryRate !== "number" || !Number.isFinite(primaryRate)) {
|
|
3531
3613
|
return false;
|
|
3532
|
-
|
|
3614
|
+
}
|
|
3615
|
+
return passesRatePolicy(
|
|
3616
|
+
normalizeRatePolicy(policy),
|
|
3617
|
+
primaryRate,
|
|
3618
|
+
candidateRate
|
|
3619
|
+
);
|
|
3533
3620
|
}
|
|
3534
3621
|
function getCap(map, id) {
|
|
3535
3622
|
return getServiceCapability(map, id);
|
|
3536
3623
|
}
|
|
3537
|
-
function isCapFlagEnabled(
|
|
3624
|
+
function isCapFlagEnabled(capability, flagId) {
|
|
3538
3625
|
var _a, _b;
|
|
3539
|
-
const fromFlags = (_b = (_a =
|
|
3626
|
+
const fromFlags = (_b = (_a = capability.flags) == null ? void 0 : _a[flagId]) == null ? void 0 : _b.enabled;
|
|
3540
3627
|
if (fromFlags === true) return true;
|
|
3541
3628
|
if (fromFlags === false) return false;
|
|
3542
|
-
const legacy =
|
|
3629
|
+
const legacy = capability[flagId];
|
|
3543
3630
|
return legacy === true;
|
|
3544
3631
|
}
|
|
3545
|
-
function satisfiesTagConstraints(tagId, ctx,
|
|
3546
|
-
const tag = ctx.props.filters.find((
|
|
3547
|
-
const
|
|
3548
|
-
if (!
|
|
3549
|
-
for (const [key, value] of Object.entries(
|
|
3550
|
-
if (value === true && !isCapFlagEnabled(
|
|
3632
|
+
function satisfiesTagConstraints(tagId, ctx, capability) {
|
|
3633
|
+
const tag = ctx.props.filters.find((item) => item.id === tagId);
|
|
3634
|
+
const effectiveConstraints2 = tag == null ? void 0 : tag.constraints;
|
|
3635
|
+
if (!effectiveConstraints2) return true;
|
|
3636
|
+
for (const [key, value] of Object.entries(effectiveConstraints2)) {
|
|
3637
|
+
if (value === true && !isCapFlagEnabled(capability, key)) {
|
|
3551
3638
|
return false;
|
|
3552
3639
|
}
|
|
3553
3640
|
}
|
|
3554
3641
|
return true;
|
|
3555
3642
|
}
|
|
3556
3643
|
function primaryForNode(props, nodeId) {
|
|
3557
|
-
const tag = props.filters.find((
|
|
3644
|
+
const tag = props.filters.find((item) => item.id === nodeId);
|
|
3558
3645
|
if (tag) {
|
|
3559
3646
|
return { primary: tag.service_id, tagContexts: [tag.id] };
|
|
3560
3647
|
}
|
|
3561
3648
|
const field = props.fields.find(
|
|
3562
|
-
(
|
|
3649
|
+
(item) => Array.isArray(item.options) && item.options.some((option2) => option2.id === nodeId)
|
|
3563
3650
|
);
|
|
3564
|
-
if (!field)
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3651
|
+
if (!field) {
|
|
3652
|
+
return { tagContexts: [], reasonNoPrimary: "no_parent_field" };
|
|
3653
|
+
}
|
|
3654
|
+
const option = field.options.find((item) => item.id === nodeId);
|
|
3655
|
+
return {
|
|
3656
|
+
primary: option.service_id,
|
|
3657
|
+
tagContexts: bindIdsToArray(field.bind_id)
|
|
3658
|
+
};
|
|
3568
3659
|
}
|
|
3569
3660
|
function bindIdsToArray(bind) {
|
|
3570
3661
|
if (!bind) return [];
|
|
@@ -3574,43 +3665,54 @@ function getEligibleFallbacks(params) {
|
|
|
3574
3665
|
var _a, _b, _c, _d, _e, _f;
|
|
3575
3666
|
const s = { ...DEFAULT_SETTINGS, ...(_a = params.settings) != null ? _a : {} };
|
|
3576
3667
|
const { primary, nodeId, tagId, services } = params;
|
|
3577
|
-
const
|
|
3578
|
-
const
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3668
|
+
const excludes = /* @__PURE__ */ new Set();
|
|
3669
|
+
for (const ref of (_b = params.exclude) != null ? _b : []) {
|
|
3670
|
+
addComparableServiceRef(excludes, services, ref);
|
|
3671
|
+
}
|
|
3672
|
+
addComparableServiceRef(excludes, services, primary);
|
|
3673
|
+
const source = (_c = params.source) != null ? _c : "registered";
|
|
3674
|
+
const candidateLists = source === "all_services" ? [listServicePoolCandidates(services)] : listRegisteredFallbackCandidates(
|
|
3675
|
+
(_d = params.fallbacks) != null ? _d : {},
|
|
3676
|
+
primary,
|
|
3677
|
+
nodeId,
|
|
3678
|
+
services
|
|
3679
|
+
);
|
|
3680
|
+
if (!candidateLists.length) return [];
|
|
3585
3681
|
const primaryRate = rateOf(services, primary);
|
|
3586
3682
|
const seen = /* @__PURE__ */ new Set();
|
|
3587
3683
|
const eligible = [];
|
|
3588
|
-
for (const list of
|
|
3589
|
-
for (const
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
if (
|
|
3593
|
-
|
|
3594
|
-
const
|
|
3595
|
-
|
|
3596
|
-
|
|
3684
|
+
for (const list of candidateLists) {
|
|
3685
|
+
for (const candidate of list) {
|
|
3686
|
+
if (hasComparableServiceRef(excludes, services, candidate)) continue;
|
|
3687
|
+
const capability = getCap(services, candidate);
|
|
3688
|
+
if (!capability) continue;
|
|
3689
|
+
const candidateId = (_e = getServiceCapabilityCanonicalRef(services, candidate)) != null ? _e : candidate;
|
|
3690
|
+
const candidateIdentity = getComparableServiceRefKey(
|
|
3691
|
+
services,
|
|
3692
|
+
candidateId
|
|
3693
|
+
);
|
|
3694
|
+
if (((_f = params.unique) != null ? _f : true) && seen.has(candidateIdentity)) continue;
|
|
3695
|
+
seen.add(candidateIdentity);
|
|
3696
|
+
if (!passesRate(s.ratePolicy, primaryRate, capability.rate)) {
|
|
3697
|
+
continue;
|
|
3698
|
+
}
|
|
3597
3699
|
if (s.requireConstraintFit && tagId) {
|
|
3598
|
-
const
|
|
3700
|
+
const fitsConstraints = satisfiesTagConstraints(
|
|
3599
3701
|
tagId,
|
|
3600
3702
|
{ props: params.props, services },
|
|
3601
|
-
|
|
3703
|
+
capability
|
|
3602
3704
|
);
|
|
3603
|
-
if (!
|
|
3705
|
+
if (!fitsConstraints) continue;
|
|
3604
3706
|
}
|
|
3605
|
-
eligible.push(
|
|
3707
|
+
eligible.push(candidateId);
|
|
3606
3708
|
}
|
|
3607
3709
|
}
|
|
3608
3710
|
if (s.selectionStrategy === "cheapest") {
|
|
3609
|
-
eligible.sort((
|
|
3711
|
+
eligible.sort((left, right) => {
|
|
3610
3712
|
var _a2, _b2;
|
|
3611
|
-
const
|
|
3612
|
-
const
|
|
3613
|
-
return
|
|
3713
|
+
const leftRate = (_a2 = rateOf(services, left)) != null ? _a2 : Infinity;
|
|
3714
|
+
const rightRate = (_b2 = rateOf(services, right)) != null ? _b2 : Infinity;
|
|
3715
|
+
return leftRate - rightRate;
|
|
3614
3716
|
});
|
|
3615
3717
|
}
|
|
3616
3718
|
if (typeof params.limit === "number" && params.limit >= 0) {
|
|
@@ -3618,10 +3720,104 @@ function getEligibleFallbacks(params) {
|
|
|
3618
3720
|
}
|
|
3619
3721
|
return eligible;
|
|
3620
3722
|
}
|
|
3723
|
+
function getAssignedServiceIds(params) {
|
|
3724
|
+
var _a, _b, _c, _d, _e;
|
|
3725
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3726
|
+
const out = [];
|
|
3727
|
+
const push = (value) => {
|
|
3728
|
+
if (!isValidServiceIdRef(value)) return;
|
|
3729
|
+
const key = String(value);
|
|
3730
|
+
if (seen.has(key)) return;
|
|
3731
|
+
seen.add(key);
|
|
3732
|
+
out.push(value);
|
|
3733
|
+
};
|
|
3734
|
+
const props = params.props;
|
|
3735
|
+
if (props) {
|
|
3736
|
+
for (const tag of (_a = props.filters) != null ? _a : []) {
|
|
3737
|
+
push(tag.service_id);
|
|
3738
|
+
}
|
|
3739
|
+
for (const field of (_b = props.fields) != null ? _b : []) {
|
|
3740
|
+
const fieldService = field.service_id;
|
|
3741
|
+
if (field.button === true) {
|
|
3742
|
+
push(fieldService);
|
|
3743
|
+
}
|
|
3744
|
+
for (const option of (_c = field.options) != null ? _c : []) {
|
|
3745
|
+
if (option.pricing_role === "utility") continue;
|
|
3746
|
+
push(option.service_id);
|
|
3747
|
+
}
|
|
3748
|
+
}
|
|
3749
|
+
}
|
|
3750
|
+
const snapshot = params.snapshot;
|
|
3751
|
+
if (snapshot) {
|
|
3752
|
+
for (const serviceId of (_d = snapshot.services) != null ? _d : []) {
|
|
3753
|
+
push(serviceId);
|
|
3754
|
+
}
|
|
3755
|
+
for (const list of Object.values((_e = snapshot.serviceMap) != null ? _e : {})) {
|
|
3756
|
+
for (const serviceId of list != null ? list : []) {
|
|
3757
|
+
push(serviceId);
|
|
3758
|
+
}
|
|
3759
|
+
}
|
|
3760
|
+
}
|
|
3761
|
+
return out;
|
|
3762
|
+
}
|
|
3621
3763
|
function getFallbackRegistrationInfo(props, nodeId) {
|
|
3622
3764
|
const { primary, tagContexts } = primaryForNode(props, nodeId);
|
|
3623
3765
|
return { primary, tagContexts };
|
|
3624
3766
|
}
|
|
3767
|
+
function listRegisteredFallbackCandidates(fallbacks, primary, nodeId, services) {
|
|
3768
|
+
var _a, _b;
|
|
3769
|
+
const lists = [];
|
|
3770
|
+
if (nodeId && ((_a = fallbacks.nodes) == null ? void 0 : _a[nodeId])) {
|
|
3771
|
+
lists.push(fallbacks.nodes[nodeId]);
|
|
3772
|
+
}
|
|
3773
|
+
for (const [registeredPrimary, list] of Object.entries((_b = fallbacks.global) != null ? _b : {})) {
|
|
3774
|
+
if (!isMatchingServiceRef(services, registeredPrimary, primary)) continue;
|
|
3775
|
+
lists.push(list);
|
|
3776
|
+
}
|
|
3777
|
+
return lists;
|
|
3778
|
+
}
|
|
3779
|
+
function listServicePoolCandidates(services) {
|
|
3780
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3781
|
+
const out = [];
|
|
3782
|
+
for (const [key, capability] of Object.entries(services != null ? services : {})) {
|
|
3783
|
+
const candidate = getServicePoolCandidateId(key, capability);
|
|
3784
|
+
if (!isValidServiceIdRef(candidate)) continue;
|
|
3785
|
+
const identity = getComparableServiceRefKey(services, candidate);
|
|
3786
|
+
if (seen.has(identity)) continue;
|
|
3787
|
+
seen.add(identity);
|
|
3788
|
+
out.push(candidate);
|
|
3789
|
+
}
|
|
3790
|
+
return out;
|
|
3791
|
+
}
|
|
3792
|
+
function getServicePoolCandidateId(key, capability) {
|
|
3793
|
+
var _a;
|
|
3794
|
+
return (_a = getServiceCapabilityCanonicalRef({ [key]: capability }, key)) != null ? _a : key;
|
|
3795
|
+
}
|
|
3796
|
+
function addComparableServiceRef(target, services, value) {
|
|
3797
|
+
for (const ref of getComparableServiceRefs(services, value)) {
|
|
3798
|
+
target.add(ref);
|
|
3799
|
+
}
|
|
3800
|
+
}
|
|
3801
|
+
function hasComparableServiceRef(target, services, value) {
|
|
3802
|
+
return getComparableServiceRefs(services, value).some((ref) => target.has(ref));
|
|
3803
|
+
}
|
|
3804
|
+
function getComparableServiceRefKey(services, value) {
|
|
3805
|
+
if (!isValidServiceIdRef(value)) return "";
|
|
3806
|
+
const canonical = getServiceCapabilityCanonicalRef(services, value);
|
|
3807
|
+
return String(canonical != null ? canonical : value);
|
|
3808
|
+
}
|
|
3809
|
+
function getComparableServiceRefs(services, value) {
|
|
3810
|
+
if (!isValidServiceIdRef(value)) return [];
|
|
3811
|
+
const aliases = getServiceCapabilityAliases(services, value);
|
|
3812
|
+
if (!aliases.length) {
|
|
3813
|
+
return [String(value)];
|
|
3814
|
+
}
|
|
3815
|
+
return aliases.map((ref) => String(ref));
|
|
3816
|
+
}
|
|
3817
|
+
function isMatchingServiceRef(services, left, right) {
|
|
3818
|
+
if (!services) return String(left) === String(right);
|
|
3819
|
+
return isSameServiceCapabilityRef(services, left, right);
|
|
3820
|
+
}
|
|
3625
3821
|
|
|
3626
3822
|
// src/core/tag-relations.ts
|
|
3627
3823
|
var toId = (x) => typeof x === "string" ? x : x.id;
|
|
@@ -5160,6 +5356,7 @@ function createFallbackEditor(options = {}) {
|
|
|
5160
5356
|
const original = cloneFallbacks(options.fallbacks);
|
|
5161
5357
|
let current = cloneFallbacks(options.fallbacks);
|
|
5162
5358
|
const props = options.props;
|
|
5359
|
+
const snapshot = options.snapshot;
|
|
5163
5360
|
const services = (_a = options.services) != null ? _a : {};
|
|
5164
5361
|
const settings = (_b = options.settings) != null ? _b : {};
|
|
5165
5362
|
function state() {
|
|
@@ -5254,7 +5451,11 @@ function createFallbackEditor(options = {}) {
|
|
|
5254
5451
|
const allowed2 = [];
|
|
5255
5452
|
for (const candidate of normalized) {
|
|
5256
5453
|
const reasons = [];
|
|
5257
|
-
if (
|
|
5454
|
+
if (isSameServiceCapabilityRef(
|
|
5455
|
+
services,
|
|
5456
|
+
candidate,
|
|
5457
|
+
context.primary
|
|
5458
|
+
)) {
|
|
5258
5459
|
reasons.push("self_reference");
|
|
5259
5460
|
}
|
|
5260
5461
|
if (reasons.length) {
|
|
@@ -5342,7 +5543,19 @@ function createFallbackEditor(options = {}) {
|
|
|
5342
5543
|
return writeScope(context, []);
|
|
5343
5544
|
}
|
|
5344
5545
|
function eligible(context, opt) {
|
|
5546
|
+
var _a2, _b2;
|
|
5345
5547
|
if (!props) return [];
|
|
5548
|
+
const source = (_a2 = opt == null ? void 0 : opt.source) != null ? _a2 : "all_services";
|
|
5549
|
+
const exclude2 = normalizeCandidateList(
|
|
5550
|
+
[
|
|
5551
|
+
...(_b2 = opt == null ? void 0 : opt.exclude) != null ? _b2 : [],
|
|
5552
|
+
...source === "all_services" ? [
|
|
5553
|
+
...getAssignedServiceIds({ props, snapshot }),
|
|
5554
|
+
...getScope(context)
|
|
5555
|
+
] : []
|
|
5556
|
+
],
|
|
5557
|
+
true
|
|
5558
|
+
);
|
|
5346
5559
|
if (context.scope === "global") {
|
|
5347
5560
|
return getEligibleFallbacks({
|
|
5348
5561
|
primary: context.primary,
|
|
@@ -5350,9 +5563,10 @@ function createFallbackEditor(options = {}) {
|
|
|
5350
5563
|
fallbacks: current,
|
|
5351
5564
|
settings,
|
|
5352
5565
|
props,
|
|
5353
|
-
exclude:
|
|
5566
|
+
exclude: exclude2,
|
|
5354
5567
|
unique: opt == null ? void 0 : opt.unique,
|
|
5355
|
-
limit: opt == null ? void 0 : opt.limit
|
|
5568
|
+
limit: opt == null ? void 0 : opt.limit,
|
|
5569
|
+
source
|
|
5356
5570
|
});
|
|
5357
5571
|
}
|
|
5358
5572
|
const info = getFallbackRegistrationInfo(props, context.nodeId);
|
|
@@ -5360,14 +5574,19 @@ function createFallbackEditor(options = {}) {
|
|
|
5360
5574
|
return getEligibleFallbacks({
|
|
5361
5575
|
primary: info.primary,
|
|
5362
5576
|
nodeId: context.nodeId,
|
|
5363
|
-
tagId:
|
|
5577
|
+
tagId: resolveNodeTagContext({
|
|
5578
|
+
nodeId: context.nodeId,
|
|
5579
|
+
snapshot,
|
|
5580
|
+
fallbackTagContexts: info.tagContexts
|
|
5581
|
+
}),
|
|
5364
5582
|
services,
|
|
5365
5583
|
fallbacks: current,
|
|
5366
5584
|
settings,
|
|
5367
5585
|
props,
|
|
5368
|
-
exclude:
|
|
5586
|
+
exclude: exclude2,
|
|
5369
5587
|
unique: opt == null ? void 0 : opt.unique,
|
|
5370
|
-
limit: opt == null ? void 0 : opt.limit
|
|
5588
|
+
limit: opt == null ? void 0 : opt.limit,
|
|
5589
|
+
source
|
|
5371
5590
|
});
|
|
5372
5591
|
}
|
|
5373
5592
|
function writeScope(context, nextList) {
|
|
@@ -5425,14 +5644,14 @@ function sameFallbacks(a, b) {
|
|
|
5425
5644
|
function normalizeCandidateList(input, preserveOrder) {
|
|
5426
5645
|
const out = [];
|
|
5427
5646
|
for (const item of input != null ? input : []) {
|
|
5428
|
-
if (!
|
|
5647
|
+
if (!isValidServiceIdRef2(item)) continue;
|
|
5429
5648
|
const exists = out.some((x) => String(x) === String(item));
|
|
5430
5649
|
if (exists) continue;
|
|
5431
5650
|
out.push(item);
|
|
5432
5651
|
}
|
|
5433
5652
|
return preserveOrder ? out : out;
|
|
5434
5653
|
}
|
|
5435
|
-
function
|
|
5654
|
+
function isValidServiceIdRef2(value) {
|
|
5436
5655
|
return typeof value === "number" && Number.isFinite(value) || typeof value === "string" && value.trim().length > 0;
|
|
5437
5656
|
}
|
|
5438
5657
|
function clamp(n, min, max) {
|
|
@@ -5441,7 +5660,7 @@ function clamp(n, min, max) {
|
|
|
5441
5660
|
function getNodeRegistrationInfo(props, nodeId) {
|
|
5442
5661
|
const tag = props.filters.find((t) => t.id === nodeId);
|
|
5443
5662
|
if (tag) {
|
|
5444
|
-
if (!
|
|
5663
|
+
if (!isValidServiceIdRef2(tag.service_id)) {
|
|
5445
5664
|
return { ok: false, reasons: ["no_primary"] };
|
|
5446
5665
|
}
|
|
5447
5666
|
return {
|
|
@@ -5454,7 +5673,7 @@ function getNodeRegistrationInfo(props, nodeId) {
|
|
|
5454
5673
|
if (!hit) {
|
|
5455
5674
|
return { ok: false, reasons: ["node_not_found"] };
|
|
5456
5675
|
}
|
|
5457
|
-
if (!
|
|
5676
|
+
if (!isValidServiceIdRef2(hit.option.service_id)) {
|
|
5458
5677
|
return { ok: false, reasons: ["no_primary"] };
|
|
5459
5678
|
}
|
|
5460
5679
|
return {
|
|
@@ -5476,6 +5695,15 @@ function bindIdsToArray2(v) {
|
|
|
5476
5695
|
if (Array.isArray(v)) return v.filter(Boolean);
|
|
5477
5696
|
return v ? [v] : [];
|
|
5478
5697
|
}
|
|
5698
|
+
function resolveNodeTagContext(params) {
|
|
5699
|
+
var _a, _b, _c;
|
|
5700
|
+
const nodeContexts = (_c = (_b = (_a = params.snapshot) == null ? void 0 : _a.meta) == null ? void 0 : _b.context) == null ? void 0 : _c.nodeContexts;
|
|
5701
|
+
if (nodeContexts && Object.prototype.hasOwnProperty.call(nodeContexts, params.nodeId)) {
|
|
5702
|
+
const tagId = nodeContexts[params.nodeId];
|
|
5703
|
+
return typeof tagId === "string" && tagId.trim().length > 0 ? tagId : void 0;
|
|
5704
|
+
}
|
|
5705
|
+
return params.fallbackTagContexts[0];
|
|
5706
|
+
}
|
|
5479
5707
|
function mapDiagReason(reason) {
|
|
5480
5708
|
switch (String(reason)) {
|
|
5481
5709
|
case "unknown_service":
|
|
@@ -12167,10 +12395,10 @@ function FallbackEditorInner({ className }) {
|
|
|
12167
12395
|
"div",
|
|
12168
12396
|
{
|
|
12169
12397
|
className: [
|
|
12170
|
-
"min-h-
|
|
12398
|
+
"h-full min-h-0 overflow-hidden bg-zinc-100 p-4 text-zinc-900 dark:bg-zinc-950 dark:text-zinc-100",
|
|
12171
12399
|
className
|
|
12172
12400
|
].filter(Boolean).join(" "),
|
|
12173
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "
|
|
12401
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex h-full min-h-0 flex-col gap-4", children: [
|
|
12174
12402
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
12175
12403
|
FallbackEditorHeader,
|
|
12176
12404
|
{
|
|
@@ -12182,9 +12410,9 @@ function FallbackEditorInner({ className }) {
|
|
|
12182
12410
|
saving: headerSaving
|
|
12183
12411
|
}
|
|
12184
12412
|
),
|
|
12185
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "grid gap-4 xl:grid-cols-[300px_minmax(0,1fr)_360px]", children: [
|
|
12413
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "grid min-h-0 flex-1 gap-4 overflow-hidden xl:grid-cols-[300px_minmax(0,1fr)_360px]", children: [
|
|
12186
12414
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FallbackServiceSidebar, {}),
|
|
12187
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex min-h-0 flex-col gap-4", children: [
|
|
12415
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex min-h-0 flex-col gap-4 overflow-y-auto", children: [
|
|
12188
12416
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("section", { className: "rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-wrap items-start justify-between gap-4", children: [
|
|
12189
12417
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { children: [
|
|
12190
12418
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h2", { className: "text-lg font-semibold text-zinc-900 dark:text-zinc-100", children: activeServiceId !== void 0 ? `Service #${String(activeServiceId)}` : "No service selected" }),
|
|
@@ -12238,6 +12466,7 @@ function TabButton({
|
|
|
12238
12466
|
|
|
12239
12467
|
// src/react/fallback-editor/VirtualServiceList.tsx
|
|
12240
12468
|
var import_react17 = __toESM(require("react"), 1);
|
|
12469
|
+
var import_lucide_react = require("lucide-react");
|
|
12241
12470
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
12242
12471
|
function VirtualServiceList({
|
|
12243
12472
|
items,
|
|
@@ -12280,7 +12509,7 @@ function VirtualServiceList({
|
|
|
12280
12509
|
{
|
|
12281
12510
|
type: "button",
|
|
12282
12511
|
onClick: () => onToggle(item.id),
|
|
12283
|
-
className: "absolute left-0 right-0 flex items-center justify-between border-b border-zinc-100 bg-white px-3 text-left hover:bg-zinc-50 dark:border-zinc-800 dark:bg-zinc-900 dark:hover:bg-zinc-800",
|
|
12512
|
+
className: "absolute left-0 right-0 flex items-center justify-between border-b border-zinc-100 bg-white px-3 text-left transition hover:bg-zinc-50 dark:border-zinc-800 dark:bg-zinc-900 dark:hover:bg-zinc-800",
|
|
12284
12513
|
style: {
|
|
12285
12514
|
top: index * rowHeight,
|
|
12286
12515
|
height: rowHeight
|
|
@@ -12300,12 +12529,13 @@ function VirtualServiceList({
|
|
|
12300
12529
|
] })
|
|
12301
12530
|
] }),
|
|
12302
12531
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
12303
|
-
"
|
|
12532
|
+
"span",
|
|
12304
12533
|
{
|
|
12305
|
-
|
|
12306
|
-
|
|
12307
|
-
|
|
12308
|
-
|
|
12534
|
+
className: [
|
|
12535
|
+
"inline-flex h-4 w-4 items-center justify-center rounded border transition",
|
|
12536
|
+
checked ? "border-blue-600 bg-blue-600 text-white dark:border-blue-500 dark:bg-blue-500" : "border-zinc-300 bg-white text-transparent dark:border-zinc-700 dark:bg-zinc-800"
|
|
12537
|
+
].join(" "),
|
|
12538
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react.Check, { className: "h-3 w-3" })
|
|
12309
12539
|
}
|
|
12310
12540
|
)
|
|
12311
12541
|
]
|
|
@@ -12328,7 +12558,7 @@ function FallbackDetailsPanel() {
|
|
|
12328
12558
|
() => services.find((s) => String(s.id) === String(activeServiceId)),
|
|
12329
12559
|
[services, activeServiceId]
|
|
12330
12560
|
);
|
|
12331
|
-
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("aside", { className: "flex min-h-0 flex-col gap-4", children: [
|
|
12561
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("aside", { className: "flex min-h-0 flex-col gap-4 overflow-y-auto", children: [
|
|
12332
12562
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("section", { className: "rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
12333
12563
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h3", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: "Primary service info" }),
|
|
12334
12564
|
!service ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "mt-3 text-sm text-zinc-500 dark:text-zinc-400", children: "No service selected." }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "mt-3 space-y-2 text-sm", children: [
|
|
@@ -12455,6 +12685,7 @@ function FallbackEditorHeader({
|
|
|
12455
12685
|
|
|
12456
12686
|
// src/react/fallback-editor/FallbackSettingsPanel.tsx
|
|
12457
12687
|
var import_react19 = __toESM(require("react"), 1);
|
|
12688
|
+
var import_form_palette23 = require("@timeax/form-palette");
|
|
12458
12689
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
12459
12690
|
function FallbackSettingsPanel() {
|
|
12460
12691
|
var _a, _b, _c;
|
|
@@ -12490,7 +12721,7 @@ function FallbackSettingsPanel() {
|
|
|
12490
12721
|
kind: "lte_primary",
|
|
12491
12722
|
pct: 5
|
|
12492
12723
|
};
|
|
12493
|
-
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("section", { className: "rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
12724
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("section", { className: "overflow-y-auto rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
12494
12725
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "mb-4 flex items-start justify-between gap-3", children: [
|
|
12495
12726
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { children: [
|
|
12496
12727
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h3", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: "Fallback settings" }),
|
|
@@ -12516,30 +12747,17 @@ function FallbackSettingsPanel() {
|
|
|
12516
12747
|
{
|
|
12517
12748
|
title: "Require constraint fit",
|
|
12518
12749
|
hint: "Reject or warn when a candidate does not match effective tag constraints.",
|
|
12519
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime10.
|
|
12520
|
-
|
|
12750
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
12751
|
+
import_form_palette23.InputField,
|
|
12521
12752
|
{
|
|
12522
|
-
|
|
12523
|
-
|
|
12753
|
+
variant: "toggle",
|
|
12754
|
+
value: Boolean(draft.requireConstraintFit),
|
|
12755
|
+
onChange: ({ value }) => setDraft((prev) => ({
|
|
12524
12756
|
...prev,
|
|
12525
|
-
requireConstraintFit:
|
|
12757
|
+
requireConstraintFit: Boolean(value)
|
|
12526
12758
|
})),
|
|
12527
|
-
|
|
12528
|
-
|
|
12529
|
-
draft.requireConstraintFit ? "border-green-300 bg-green-50 text-green-700 dark:border-green-900/50 dark:bg-green-950/30 dark:text-green-300" : "border-zinc-300 bg-white text-zinc-600 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-300"
|
|
12530
|
-
].join(" "),
|
|
12531
|
-
children: [
|
|
12532
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { children: draft.requireConstraintFit ? "Enabled" : "Disabled" }),
|
|
12533
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
12534
|
-
"span",
|
|
12535
|
-
{
|
|
12536
|
-
className: [
|
|
12537
|
-
"h-2.5 w-2.5 rounded-full",
|
|
12538
|
-
draft.requireConstraintFit ? "bg-green-500" : "bg-zinc-400"
|
|
12539
|
-
].join(" ")
|
|
12540
|
-
}
|
|
12541
|
-
)
|
|
12542
|
-
]
|
|
12759
|
+
onText: "Enabled",
|
|
12760
|
+
offText: "Disabled"
|
|
12543
12761
|
}
|
|
12544
12762
|
)
|
|
12545
12763
|
}
|
|
@@ -12550,12 +12768,13 @@ function FallbackSettingsPanel() {
|
|
|
12550
12768
|
title: "Rate policy",
|
|
12551
12769
|
hint: "Controls how fallback service rates are compared against the primary service.",
|
|
12552
12770
|
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex flex-col gap-2 md:items-end", children: [
|
|
12553
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.
|
|
12554
|
-
|
|
12771
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
12772
|
+
import_form_palette23.InputField,
|
|
12555
12773
|
{
|
|
12774
|
+
variant: "select",
|
|
12556
12775
|
value: ratePolicy.kind,
|
|
12557
|
-
onChange: (
|
|
12558
|
-
const kind =
|
|
12776
|
+
onChange: ({ value }) => {
|
|
12777
|
+
const kind = value;
|
|
12559
12778
|
if (kind === "eq_primary") {
|
|
12560
12779
|
setRatePolicy({ kind: "eq_primary" });
|
|
12561
12780
|
return;
|
|
@@ -12580,30 +12799,39 @@ function FallbackSettingsPanel() {
|
|
|
12580
12799
|
pct: currentPct
|
|
12581
12800
|
});
|
|
12582
12801
|
},
|
|
12583
|
-
|
|
12584
|
-
|
|
12585
|
-
|
|
12586
|
-
|
|
12587
|
-
|
|
12588
|
-
|
|
12589
|
-
|
|
12802
|
+
options: [
|
|
12803
|
+
{ value: "eq_primary", label: "eq_primary" },
|
|
12804
|
+
{
|
|
12805
|
+
value: "lte_primary",
|
|
12806
|
+
label: "lte_primary"
|
|
12807
|
+
},
|
|
12808
|
+
{ value: "within_pct", label: "within_pct" },
|
|
12809
|
+
{
|
|
12810
|
+
value: "at_least_pct_lower",
|
|
12811
|
+
label: "at_least_pct_lower"
|
|
12812
|
+
}
|
|
12813
|
+
],
|
|
12814
|
+
clearable: false
|
|
12590
12815
|
}
|
|
12591
12816
|
),
|
|
12592
12817
|
ratePolicy.kind !== "eq_primary" && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
12593
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
12594
|
-
|
|
12818
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "w-32", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
12819
|
+
import_form_palette23.InputField,
|
|
12595
12820
|
{
|
|
12596
|
-
|
|
12597
|
-
min: 0,
|
|
12598
|
-
step: "0.01",
|
|
12821
|
+
variant: "number",
|
|
12599
12822
|
value: ratePolicy.pct,
|
|
12600
|
-
onChange: (
|
|
12601
|
-
const pct = Number(
|
|
12602
|
-
setRatePolicy({
|
|
12823
|
+
onChange: ({ value }) => {
|
|
12824
|
+
const pct = typeof value === "number" ? value : Number(value != null ? value : 0);
|
|
12825
|
+
setRatePolicy({
|
|
12826
|
+
...ratePolicy,
|
|
12827
|
+
pct
|
|
12828
|
+
});
|
|
12603
12829
|
},
|
|
12604
|
-
|
|
12830
|
+
min: 0,
|
|
12831
|
+
step: 0.01,
|
|
12832
|
+
fullWidth: true
|
|
12605
12833
|
}
|
|
12606
|
-
),
|
|
12834
|
+
) }),
|
|
12607
12835
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "text-sm text-zinc-500 dark:text-zinc-400", children: "%" })
|
|
12608
12836
|
] })
|
|
12609
12837
|
] })
|
|
@@ -12614,19 +12842,20 @@ function FallbackSettingsPanel() {
|
|
|
12614
12842
|
{
|
|
12615
12843
|
title: "Selection strategy",
|
|
12616
12844
|
hint: "How valid fallback candidates are ordered in previews.",
|
|
12617
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime10.
|
|
12618
|
-
|
|
12845
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
12846
|
+
import_form_palette23.InputField,
|
|
12619
12847
|
{
|
|
12848
|
+
variant: "select",
|
|
12620
12849
|
value: (_b = draft.selectionStrategy) != null ? _b : "priority",
|
|
12621
|
-
onChange: (
|
|
12850
|
+
onChange: ({ value }) => setDraft((prev) => ({
|
|
12622
12851
|
...prev,
|
|
12623
|
-
selectionStrategy:
|
|
12852
|
+
selectionStrategy: value
|
|
12624
12853
|
})),
|
|
12625
|
-
|
|
12626
|
-
|
|
12627
|
-
|
|
12628
|
-
|
|
12629
|
-
|
|
12854
|
+
options: [
|
|
12855
|
+
{ value: "priority", label: "priority" },
|
|
12856
|
+
{ value: "cheapest", label: "cheapest" }
|
|
12857
|
+
],
|
|
12858
|
+
clearable: false
|
|
12630
12859
|
}
|
|
12631
12860
|
)
|
|
12632
12861
|
}
|
|
@@ -12636,19 +12865,20 @@ function FallbackSettingsPanel() {
|
|
|
12636
12865
|
{
|
|
12637
12866
|
title: "Mode",
|
|
12638
12867
|
hint: "Use strict for enforced filtering, dev for advisory feedback.",
|
|
12639
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime10.
|
|
12640
|
-
|
|
12868
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
12869
|
+
import_form_palette23.InputField,
|
|
12641
12870
|
{
|
|
12871
|
+
variant: "select",
|
|
12642
12872
|
value: (_c = draft.mode) != null ? _c : "strict",
|
|
12643
|
-
onChange: (
|
|
12873
|
+
onChange: ({ value }) => setDraft((prev) => ({
|
|
12644
12874
|
...prev,
|
|
12645
|
-
mode:
|
|
12875
|
+
mode: value
|
|
12646
12876
|
})),
|
|
12647
|
-
|
|
12648
|
-
|
|
12649
|
-
|
|
12650
|
-
|
|
12651
|
-
|
|
12877
|
+
options: [
|
|
12878
|
+
{ value: "strict", label: "strict" },
|
|
12879
|
+
{ value: "dev", label: "dev" }
|
|
12880
|
+
],
|
|
12881
|
+
clearable: false
|
|
12652
12882
|
}
|
|
12653
12883
|
)
|
|
12654
12884
|
}
|
|
@@ -12674,6 +12904,8 @@ function SettingRow({
|
|
|
12674
12904
|
|
|
12675
12905
|
// src/react/fallback-editor/FallbackServiceSidebar.tsx
|
|
12676
12906
|
var import_react20 = require("react");
|
|
12907
|
+
var import_form_palette24 = require("@timeax/form-palette");
|
|
12908
|
+
var import_lucide_react2 = require("lucide-react");
|
|
12677
12909
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
12678
12910
|
function FallbackServiceSidebar() {
|
|
12679
12911
|
const { activeServiceId, setActiveServiceId, get } = useFallbackEditor();
|
|
@@ -12689,22 +12921,26 @@ function FallbackServiceSidebar() {
|
|
|
12689
12921
|
}
|
|
12690
12922
|
);
|
|
12691
12923
|
}, [query, services]);
|
|
12692
|
-
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("aside", { className: "flex min-h-0 flex-col rounded-2xl border border-zinc-200 bg-white shadow-sm dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
12924
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("aside", { className: "flex h-full min-h-0 flex-col overflow-hidden rounded-2xl border border-zinc-200 bg-white shadow-sm dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
12693
12925
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "border-b border-zinc-200 p-4 dark:border-zinc-800", children: [
|
|
12694
12926
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h2", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: "Primary services" }),
|
|
12695
12927
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400", children: "Services currently active in the builder/runtime context." })
|
|
12696
12928
|
] }),
|
|
12697
12929
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex min-h-0 flex-1 flex-col p-4", children: [
|
|
12698
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
12699
|
-
|
|
12930
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "rounded-xl border border-zinc-200 bg-zinc-50/80 p-2 dark:border-zinc-800 dark:bg-zinc-950/80", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
12931
|
+
import_form_palette24.InputField,
|
|
12700
12932
|
{
|
|
12933
|
+
variant: "text",
|
|
12701
12934
|
value: query,
|
|
12702
|
-
onChange: (
|
|
12935
|
+
onChange: ({ value }) => setQuery(String(value != null ? value : "")),
|
|
12703
12936
|
placeholder: "Search primary service...",
|
|
12704
|
-
|
|
12937
|
+
leadingControl: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react2.Search, { className: "h-4 w-4 text-zinc-400" }),
|
|
12938
|
+
joinControls: true,
|
|
12939
|
+
extendBoxToControls: true,
|
|
12940
|
+
fullWidth: true
|
|
12705
12941
|
}
|
|
12706
|
-
),
|
|
12707
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "mt-3 flex-1 space-y-2 overflow-auto", children: filtered.map((service) => {
|
|
12942
|
+
) }),
|
|
12943
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "mt-3 flex-1 space-y-2 overflow-y-auto", children: filtered.map((service) => {
|
|
12708
12944
|
var _a, _b;
|
|
12709
12945
|
const active = String(service.id) === String(activeServiceId);
|
|
12710
12946
|
const count = get(service.id).length;
|
|
@@ -12715,7 +12951,7 @@ function FallbackServiceSidebar() {
|
|
|
12715
12951
|
onClick: () => setActiveServiceId(service.id),
|
|
12716
12952
|
className: [
|
|
12717
12953
|
"w-full rounded-2xl border p-3 text-left transition",
|
|
12718
|
-
active ? "border-blue-500 bg-blue-50 dark:bg-blue-950/30" : "border-zinc-200 bg-zinc-50 hover:border-zinc-300 dark:border-zinc-800 dark:bg-zinc-950 dark:hover:border-zinc-700"
|
|
12954
|
+
active ? "border-blue-500 bg-blue-50 dark:border-blue-500/70 dark:bg-blue-950/30" : "border-zinc-200 bg-zinc-50 hover:border-zinc-300 dark:border-zinc-800 dark:bg-zinc-950 dark:hover:border-zinc-700 dark:hover:bg-zinc-900"
|
|
12719
12955
|
].join(" "),
|
|
12720
12956
|
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex items-start justify-between gap-3", children: [
|
|
12721
12957
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "min-w-0", children: [
|
|
@@ -12745,11 +12981,174 @@ function FallbackServiceSidebar() {
|
|
|
12745
12981
|
}
|
|
12746
12982
|
|
|
12747
12983
|
// src/react/fallback-editor/FallbackRegistrationsPanel.tsx
|
|
12748
|
-
var import_react23 = __toESM(require("react"), 1);
|
|
12749
|
-
|
|
12750
|
-
// src/react/fallback-editor/FallbackAddCandidatesDialog.tsx
|
|
12751
12984
|
var import_react21 = __toESM(require("react"), 1);
|
|
12752
12985
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
12986
|
+
function FallbackRegistrationsPanel() {
|
|
12987
|
+
const { activeServiceId, remove: remove2, clear, check } = useFallbackEditor();
|
|
12988
|
+
const registrations = useActiveFallbackRegistrations();
|
|
12989
|
+
const eligibleServices = useEligibleServiceList();
|
|
12990
|
+
const [candidatePickerOpen, setCandidatePickerOpen] = import_react21.default.useState(false);
|
|
12991
|
+
const [candidateContext, setCandidateContext] = import_react21.default.useState(null);
|
|
12992
|
+
const [candidatePrimaryId, setCandidatePrimaryId] = import_react21.default.useState(void 0);
|
|
12993
|
+
const [registrationDialogOpen, setRegistrationDialogOpen] = import_react21.default.useState(false);
|
|
12994
|
+
const makeContext = import_react21.default.useCallback(
|
|
12995
|
+
(registration) => {
|
|
12996
|
+
if (registration.scope === "global") {
|
|
12997
|
+
return {
|
|
12998
|
+
scope: "global",
|
|
12999
|
+
primary: registration.primary
|
|
13000
|
+
};
|
|
13001
|
+
}
|
|
13002
|
+
return {
|
|
13003
|
+
scope: "node",
|
|
13004
|
+
nodeId: registration.scopeId
|
|
13005
|
+
};
|
|
13006
|
+
},
|
|
13007
|
+
[]
|
|
13008
|
+
);
|
|
13009
|
+
const openCandidatePicker = import_react21.default.useCallback(
|
|
13010
|
+
(context, primaryId) => {
|
|
13011
|
+
setCandidateContext(context);
|
|
13012
|
+
setCandidatePrimaryId(primaryId);
|
|
13013
|
+
setCandidatePickerOpen(true);
|
|
13014
|
+
},
|
|
13015
|
+
[]
|
|
13016
|
+
);
|
|
13017
|
+
if (activeServiceId === void 0 || activeServiceId === null) {
|
|
13018
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("section", { className: "rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900 ", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "rounded-2xl border border-dashed border-zinc-300 p-6 text-sm text-zinc-500 dark:border-zinc-700 dark:text-zinc-400", children: "Select a primary service to start editing." }) });
|
|
13019
|
+
}
|
|
13020
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
13021
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("section", { className: "rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900 overflow-y-auto", children: [
|
|
13022
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "mb-4 flex items-start justify-between gap-3", children: [
|
|
13023
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { children: [
|
|
13024
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h3", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: "Registered fallbacks" }),
|
|
13025
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400", children: "Use eligible services as fallback candidates for the selected primary." })
|
|
13026
|
+
] }),
|
|
13027
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
13028
|
+
"button",
|
|
13029
|
+
{
|
|
13030
|
+
type: "button",
|
|
13031
|
+
onClick: () => setRegistrationDialogOpen(true),
|
|
13032
|
+
className: "rounded-xl border border-zinc-300 bg-white px-3 py-2 text-sm font-medium text-zinc-700 hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-200 dark:hover:bg-zinc-800",
|
|
13033
|
+
children: "Add registration"
|
|
13034
|
+
}
|
|
13035
|
+
)
|
|
13036
|
+
] }),
|
|
13037
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "space-y-4", children: registrations.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "rounded-2xl border border-dashed border-zinc-300 p-6 text-sm text-zinc-500 dark:border-zinc-700 dark:text-zinc-400", children: "No registrations yet for this primary service." }) : registrations.map((reg, index) => {
|
|
13038
|
+
var _a;
|
|
13039
|
+
const context = makeContext(reg);
|
|
13040
|
+
const candidates = reg.services;
|
|
13041
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
13042
|
+
"div",
|
|
13043
|
+
{
|
|
13044
|
+
className: "rounded-2xl border border-zinc-200 bg-zinc-50 p-4 dark:border-zinc-800 dark:bg-zinc-950",
|
|
13045
|
+
children: [
|
|
13046
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [
|
|
13047
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { children: [
|
|
13048
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: reg.scope === "global" ? "Global registration" : `Node \xB7 ${reg.scopeId}` }),
|
|
13049
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400", children: [
|
|
13050
|
+
"Primary #",
|
|
13051
|
+
String(reg.primary)
|
|
13052
|
+
] })
|
|
13053
|
+
] }),
|
|
13054
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "rounded-full border border-zinc-200 bg-white px-2 py-1 text-[11px] text-zinc-600 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-300", children: [
|
|
13055
|
+
reg.scope,
|
|
13056
|
+
reg.scopeId ? ` \xB7 ${reg.scopeId}` : ""
|
|
13057
|
+
] })
|
|
13058
|
+
] }),
|
|
13059
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "mt-4 flex flex-wrap gap-2", children: candidates.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "text-xs text-zinc-500 dark:text-zinc-400", children: "No fallback services yet." }) : candidates.map((candidate) => {
|
|
13060
|
+
var _a2;
|
|
13061
|
+
const preview = check(context, [
|
|
13062
|
+
candidate
|
|
13063
|
+
]);
|
|
13064
|
+
const rejected = preview.rejected[0];
|
|
13065
|
+
const tone = rejected ? "border-red-200 bg-red-50 text-red-700 dark:border-red-900/50 dark:bg-red-950/30 dark:text-red-300" : "border-zinc-200 bg-white text-zinc-700 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-200";
|
|
13066
|
+
const service = eligibleServices.find(
|
|
13067
|
+
(s) => String(s.id) === String(candidate)
|
|
13068
|
+
);
|
|
13069
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
13070
|
+
"div",
|
|
13071
|
+
{
|
|
13072
|
+
className: `inline-flex items-center gap-2 rounded-xl border px-3 py-2 text-xs ${tone}`,
|
|
13073
|
+
children: [
|
|
13074
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: service ? `#${String(service.id)} \xB7 ${(_a2 = service.name) != null ? _a2 : "Unnamed"}` : `#${String(candidate)}` }),
|
|
13075
|
+
rejected ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "rounded-full border border-current/20 px-2 py-0.5 text-[10px]", children: rejected.reasons.join(
|
|
13076
|
+
", "
|
|
13077
|
+
) }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "rounded-full border border-current/20 px-2 py-0.5 text-[10px]", children: "valid" }),
|
|
13078
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
13079
|
+
"button",
|
|
13080
|
+
{
|
|
13081
|
+
type: "button",
|
|
13082
|
+
onClick: () => remove2(
|
|
13083
|
+
context,
|
|
13084
|
+
candidate
|
|
13085
|
+
),
|
|
13086
|
+
className: "text-current/70 hover:text-current",
|
|
13087
|
+
children: "\xD7"
|
|
13088
|
+
}
|
|
13089
|
+
)
|
|
13090
|
+
]
|
|
13091
|
+
},
|
|
13092
|
+
String(candidate)
|
|
13093
|
+
);
|
|
13094
|
+
}) }),
|
|
13095
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "mt-4 flex gap-2", children: [
|
|
13096
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
13097
|
+
"button",
|
|
13098
|
+
{
|
|
13099
|
+
type: "button",
|
|
13100
|
+
onClick: () => openCandidatePicker(
|
|
13101
|
+
context,
|
|
13102
|
+
reg.primary
|
|
13103
|
+
),
|
|
13104
|
+
className: "rounded-xl border border-zinc-300 bg-white px-3 py-2 text-sm font-medium text-zinc-700 hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-200 dark:hover:bg-zinc-800",
|
|
13105
|
+
children: "Add fallback"
|
|
13106
|
+
}
|
|
13107
|
+
),
|
|
13108
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
13109
|
+
"button",
|
|
13110
|
+
{
|
|
13111
|
+
type: "button",
|
|
13112
|
+
onClick: () => clear(context),
|
|
13113
|
+
className: "rounded-xl border border-red-300 bg-white px-3 py-2 text-sm font-medium text-red-600 hover:bg-red-50 dark:border-red-900/50 dark:bg-zinc-900 dark:text-red-300 dark:hover:bg-red-950/20",
|
|
13114
|
+
children: "Clear"
|
|
13115
|
+
}
|
|
13116
|
+
)
|
|
13117
|
+
] })
|
|
13118
|
+
]
|
|
13119
|
+
},
|
|
13120
|
+
`${reg.scope}:${String((_a = reg.scopeId) != null ? _a : "global")}:${index}`
|
|
13121
|
+
);
|
|
13122
|
+
}) })
|
|
13123
|
+
] }),
|
|
13124
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
13125
|
+
FallbackAddRegistrationDialog,
|
|
13126
|
+
{
|
|
13127
|
+
open: registrationDialogOpen,
|
|
13128
|
+
onClose: () => setRegistrationDialogOpen(false),
|
|
13129
|
+
onSelect: (context, primaryId) => {
|
|
13130
|
+
setRegistrationDialogOpen(false);
|
|
13131
|
+
openCandidatePicker(context, primaryId);
|
|
13132
|
+
}
|
|
13133
|
+
}
|
|
13134
|
+
),
|
|
13135
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
13136
|
+
FallbackAddCandidatesDialog,
|
|
13137
|
+
{
|
|
13138
|
+
open: candidatePickerOpen,
|
|
13139
|
+
onClose: () => setCandidatePickerOpen(false),
|
|
13140
|
+
context: candidateContext,
|
|
13141
|
+
primaryId: candidatePrimaryId
|
|
13142
|
+
}
|
|
13143
|
+
)
|
|
13144
|
+
] });
|
|
13145
|
+
}
|
|
13146
|
+
|
|
13147
|
+
// src/react/fallback-editor/FallbackAddCandidatesDialog.tsx
|
|
13148
|
+
var import_react25 = __toESM(require("react"), 1);
|
|
13149
|
+
var import_form_palette25 = require("@timeax/form-palette");
|
|
13150
|
+
var import_lucide_react3 = require("lucide-react");
|
|
13151
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
12753
13152
|
function FallbackAddCandidatesDialog({
|
|
12754
13153
|
open,
|
|
12755
13154
|
onClose,
|
|
@@ -12758,23 +13157,23 @@ function FallbackAddCandidatesDialog({
|
|
|
12758
13157
|
}) {
|
|
12759
13158
|
const { eligible, addMany } = useFallbackEditor();
|
|
12760
13159
|
const eligibleServices = useEligibleServiceList();
|
|
12761
|
-
const [query, setQuery] =
|
|
12762
|
-
const [filterEligibleOnly, setFilterEligibleOnly] =
|
|
12763
|
-
const [selected, setSelected] =
|
|
12764
|
-
const [submitting, setSubmitting] =
|
|
12765
|
-
|
|
13160
|
+
const [query, setQuery] = import_react25.default.useState("");
|
|
13161
|
+
const [filterEligibleOnly, setFilterEligibleOnly] = import_react25.default.useState(true);
|
|
13162
|
+
const [selected, setSelected] = import_react25.default.useState(/* @__PURE__ */ new Set());
|
|
13163
|
+
const [submitting, setSubmitting] = import_react25.default.useState(false);
|
|
13164
|
+
import_react25.default.useEffect(() => {
|
|
12766
13165
|
if (!open) {
|
|
12767
13166
|
setQuery("");
|
|
12768
13167
|
setFilterEligibleOnly(true);
|
|
12769
13168
|
setSelected(/* @__PURE__ */ new Set());
|
|
12770
13169
|
}
|
|
12771
13170
|
}, [open]);
|
|
12772
|
-
const allowedIds =
|
|
13171
|
+
const allowedIds = import_react25.default.useMemo(() => {
|
|
12773
13172
|
if (!context) return null;
|
|
12774
13173
|
if (!filterEligibleOnly) return null;
|
|
12775
13174
|
return new Set(eligible(context).map((id) => String(id)));
|
|
12776
13175
|
}, [context, filterEligibleOnly, eligible]);
|
|
12777
|
-
const items =
|
|
13176
|
+
const items = import_react25.default.useMemo(() => {
|
|
12778
13177
|
const q = query.trim().toLowerCase();
|
|
12779
13178
|
return eligibleServices.filter((service) => {
|
|
12780
13179
|
var _a, _b;
|
|
@@ -12809,34 +13208,37 @@ function FallbackAddCandidatesDialog({
|
|
|
12809
13208
|
}
|
|
12810
13209
|
}
|
|
12811
13210
|
if (!open || !context) return null;
|
|
12812
|
-
return /* @__PURE__ */ (0,
|
|
12813
|
-
/* @__PURE__ */ (0,
|
|
12814
|
-
/* @__PURE__ */ (0,
|
|
12815
|
-
/* @__PURE__ */ (0,
|
|
13211
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex max-h-[85vh] w-full max-w-3xl flex-col rounded-2xl border border-zinc-200 bg-white shadow-2xl dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
13212
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "border-b border-zinc-200 p-4 dark:border-zinc-800", children: [
|
|
13213
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h3", { className: "text-base font-semibold text-zinc-900 dark:text-zinc-100", children: "Add fallback services" }),
|
|
13214
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "mt-1 text-sm text-zinc-500 dark:text-zinc-400", children: "Search and select one or more eligible fallback candidates." })
|
|
12816
13215
|
] }),
|
|
12817
|
-
/* @__PURE__ */ (0,
|
|
12818
|
-
/* @__PURE__ */ (0,
|
|
12819
|
-
|
|
13216
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-col gap-3 p-4", children: [
|
|
13217
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
13218
|
+
import_form_palette25.InputField,
|
|
12820
13219
|
{
|
|
13220
|
+
variant: "text",
|
|
12821
13221
|
value: query,
|
|
12822
|
-
onChange: (
|
|
13222
|
+
onChange: ({ value }) => setQuery(String(value != null ? value : "")),
|
|
12823
13223
|
placeholder: "Search eligible services...",
|
|
12824
|
-
|
|
13224
|
+
leadingControl: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react3.Search, { className: "h-4 w-4 text-zinc-400" }),
|
|
13225
|
+
joinControls: true,
|
|
13226
|
+
extendBoxToControls: true,
|
|
13227
|
+
fullWidth: true
|
|
12825
13228
|
}
|
|
12826
13229
|
),
|
|
12827
|
-
/* @__PURE__ */ (0,
|
|
12828
|
-
|
|
12829
|
-
|
|
12830
|
-
|
|
12831
|
-
|
|
12832
|
-
|
|
12833
|
-
|
|
12834
|
-
|
|
12835
|
-
|
|
12836
|
-
|
|
12837
|
-
|
|
12838
|
-
|
|
12839
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
13230
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
13231
|
+
import_form_palette25.InputField,
|
|
13232
|
+
{
|
|
13233
|
+
variant: "toggle",
|
|
13234
|
+
value: filterEligibleOnly,
|
|
13235
|
+
onChange: ({ value }) => setFilterEligibleOnly(Boolean(value)),
|
|
13236
|
+
label: "Filter eligible only",
|
|
13237
|
+
onText: "On",
|
|
13238
|
+
offText: "Off"
|
|
13239
|
+
}
|
|
13240
|
+
),
|
|
13241
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
12840
13242
|
VirtualServiceList,
|
|
12841
13243
|
{
|
|
12842
13244
|
items,
|
|
@@ -12846,28 +13248,28 @@ function FallbackAddCandidatesDialog({
|
|
|
12846
13248
|
}
|
|
12847
13249
|
)
|
|
12848
13250
|
] }),
|
|
12849
|
-
/* @__PURE__ */ (0,
|
|
12850
|
-
/* @__PURE__ */ (0,
|
|
13251
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center justify-between border-t border-zinc-200 p-4 dark:border-zinc-800", children: [
|
|
13252
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "text-sm text-zinc-500 dark:text-zinc-400", children: [
|
|
12851
13253
|
selected.size,
|
|
12852
13254
|
" selected"
|
|
12853
13255
|
] }),
|
|
12854
|
-
/* @__PURE__ */ (0,
|
|
12855
|
-
/* @__PURE__ */ (0,
|
|
13256
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex gap-2", children: [
|
|
13257
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
12856
13258
|
"button",
|
|
12857
13259
|
{
|
|
12858
13260
|
type: "button",
|
|
12859
13261
|
onClick: onClose,
|
|
12860
|
-
className: "rounded-xl border border-zinc-300 bg-white px-3 py-2 text-sm font-medium text-zinc-700 hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-200 dark:hover:bg-zinc-800",
|
|
13262
|
+
className: "rounded-xl border border-zinc-300 bg-white px-3 py-2 text-sm font-medium text-zinc-700 transition hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-200 dark:hover:bg-zinc-800",
|
|
12861
13263
|
children: "Cancel"
|
|
12862
13264
|
}
|
|
12863
13265
|
),
|
|
12864
|
-
/* @__PURE__ */ (0,
|
|
13266
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
12865
13267
|
"button",
|
|
12866
13268
|
{
|
|
12867
13269
|
type: "button",
|
|
12868
13270
|
onClick: handleAdd,
|
|
12869
13271
|
disabled: selected.size === 0 || submitting,
|
|
12870
|
-
className: "rounded-xl bg-blue-600 px-3 py-2 text-sm font-medium text-white hover:bg-blue-700 disabled:cursor-not-allowed disabled:opacity-60",
|
|
13272
|
+
className: "rounded-xl bg-blue-600 px-3 py-2 text-sm font-medium text-white transition hover:bg-blue-700 disabled:cursor-not-allowed disabled:opacity-60",
|
|
12871
13273
|
children: submitting ? "Adding..." : "Add selected"
|
|
12872
13274
|
}
|
|
12873
13275
|
)
|
|
@@ -12877,8 +13279,9 @@ function FallbackAddCandidatesDialog({
|
|
|
12877
13279
|
}
|
|
12878
13280
|
|
|
12879
13281
|
// src/react/fallback-editor/FallbackAddRegistrationDialog.tsx
|
|
12880
|
-
var
|
|
12881
|
-
var
|
|
13282
|
+
var import_react26 = __toESM(require("react"), 1);
|
|
13283
|
+
var import_form_palette26 = require("@timeax/form-palette");
|
|
13284
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
12882
13285
|
function FallbackAddRegistrationDialog({
|
|
12883
13286
|
open,
|
|
12884
13287
|
onClose,
|
|
@@ -12886,23 +13289,23 @@ function FallbackAddRegistrationDialog({
|
|
|
12886
13289
|
}) {
|
|
12887
13290
|
const { activeServiceId, serviceProps, snapshot } = useFallbackEditor();
|
|
12888
13291
|
const registrations = useActiveFallbackRegistrations();
|
|
12889
|
-
const [scope, setScope] =
|
|
12890
|
-
const [nodeId, setNodeId] =
|
|
12891
|
-
const mode =
|
|
13292
|
+
const [scope, setScope] = import_react26.default.useState("global");
|
|
13293
|
+
const [nodeId, setNodeId] = import_react26.default.useState("");
|
|
13294
|
+
const mode = import_react26.default.useMemo(() => {
|
|
12892
13295
|
if (snapshot) return "snapshot";
|
|
12893
13296
|
if (serviceProps) return "props";
|
|
12894
13297
|
return "none";
|
|
12895
13298
|
}, [snapshot, serviceProps]);
|
|
12896
|
-
|
|
13299
|
+
import_react26.default.useEffect(() => {
|
|
12897
13300
|
if (open) {
|
|
12898
13301
|
setScope("global");
|
|
12899
13302
|
setNodeId("");
|
|
12900
13303
|
}
|
|
12901
13304
|
}, [open]);
|
|
12902
|
-
const hasGlobal =
|
|
13305
|
+
const hasGlobal = import_react26.default.useMemo(() => {
|
|
12903
13306
|
return registrations.some((r) => r.scope === "global");
|
|
12904
13307
|
}, [registrations]);
|
|
12905
|
-
const nodeTargets =
|
|
13308
|
+
const nodeTargets = import_react26.default.useMemo(() => {
|
|
12906
13309
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
12907
13310
|
if (activeServiceId === void 0 || activeServiceId === null) {
|
|
12908
13311
|
return [];
|
|
@@ -12992,12 +13395,12 @@ function FallbackAddRegistrationDialog({
|
|
|
12992
13395
|
}
|
|
12993
13396
|
return [];
|
|
12994
13397
|
}, [mode, snapshot, serviceProps, activeServiceId]);
|
|
12995
|
-
|
|
13398
|
+
import_react26.default.useEffect(() => {
|
|
12996
13399
|
if (hasGlobal && scope === "global") {
|
|
12997
13400
|
setScope("node");
|
|
12998
13401
|
}
|
|
12999
13402
|
}, [hasGlobal, scope]);
|
|
13000
|
-
|
|
13403
|
+
import_react26.default.useEffect(() => {
|
|
13001
13404
|
if (scope === "node" && nodeId) {
|
|
13002
13405
|
const exists = nodeTargets.some((node) => node.id === nodeId);
|
|
13003
13406
|
if (!exists) setNodeId("");
|
|
@@ -13028,100 +13431,74 @@ function FallbackAddRegistrationDialog({
|
|
|
13028
13431
|
}
|
|
13029
13432
|
if (!open) return null;
|
|
13030
13433
|
const nodeScopeDisabled = nodeTargets.length === 0;
|
|
13031
|
-
return /* @__PURE__ */ (0,
|
|
13032
|
-
/* @__PURE__ */ (0,
|
|
13033
|
-
/* @__PURE__ */ (0,
|
|
13034
|
-
/* @__PURE__ */ (0,
|
|
13434
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "w-full max-w-lg rounded-2xl border border-zinc-200 bg-white shadow-2xl dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
13435
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "border-b border-zinc-200 p-4 dark:border-zinc-800", children: [
|
|
13436
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h3", { className: "text-base font-semibold text-zinc-900 dark:text-zinc-100", children: "Add registration" }),
|
|
13437
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "mt-1 text-sm text-zinc-500 dark:text-zinc-400", children: "Choose the registration scope before selecting fallback candidates." })
|
|
13035
13438
|
] }),
|
|
13036
|
-
/* @__PURE__ */ (0,
|
|
13037
|
-
/* @__PURE__ */ (0,
|
|
13038
|
-
/* @__PURE__ */ (0,
|
|
13039
|
-
/* @__PURE__ */ (0,
|
|
13040
|
-
|
|
13041
|
-
|
|
13042
|
-
|
|
13439
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "space-y-4 p-4", children: [
|
|
13440
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "space-y-2", children: [
|
|
13441
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "text-sm font-medium text-zinc-900 dark:text-zinc-100", children: "Scope" }),
|
|
13442
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
13443
|
+
import_form_palette26.InputField,
|
|
13444
|
+
{
|
|
13445
|
+
variant: "radio",
|
|
13446
|
+
value: scope,
|
|
13447
|
+
onChange: ({ value }) => setScope(value),
|
|
13448
|
+
options: [
|
|
13449
|
+
...!hasGlobal ? [
|
|
13450
|
+
{
|
|
13451
|
+
value: "global",
|
|
13452
|
+
label: "Global"
|
|
13453
|
+
}
|
|
13454
|
+
] : [],
|
|
13043
13455
|
{
|
|
13044
|
-
|
|
13045
|
-
|
|
13046
|
-
checked: scope === "global",
|
|
13047
|
-
onChange: () => setScope("global"),
|
|
13048
|
-
className: "mt-1 h-4 w-4"
|
|
13456
|
+
value: "node",
|
|
13457
|
+
label: nodeScopeDisabled ? "Node (Unavailable)" : "Node"
|
|
13049
13458
|
}
|
|
13050
|
-
|
|
13051
|
-
|
|
13052
|
-
|
|
13053
|
-
|
|
13054
|
-
] })
|
|
13055
|
-
] }),
|
|
13056
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
13057
|
-
"label",
|
|
13058
|
-
{
|
|
13059
|
-
className: [
|
|
13060
|
-
"flex items-start gap-3 rounded-xl border p-3",
|
|
13061
|
-
nodeScopeDisabled ? "cursor-not-allowed border-zinc-200 opacity-60 dark:border-zinc-800" : "cursor-pointer border-zinc-200 dark:border-zinc-800"
|
|
13062
|
-
].join(" "),
|
|
13063
|
-
children: [
|
|
13064
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
13065
|
-
"input",
|
|
13066
|
-
{
|
|
13067
|
-
type: "radio",
|
|
13068
|
-
name: "scope",
|
|
13069
|
-
checked: scope === "node",
|
|
13070
|
-
onChange: () => setScope("node"),
|
|
13071
|
-
disabled: nodeScopeDisabled,
|
|
13072
|
-
className: "mt-1 h-4 w-4"
|
|
13073
|
-
}
|
|
13074
|
-
),
|
|
13075
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
|
|
13076
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "text-sm font-medium text-zinc-900 dark:text-zinc-100", children: "Node" }),
|
|
13077
|
-
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400", children: 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." })
|
|
13078
|
-
] })
|
|
13079
|
-
]
|
|
13080
|
-
}
|
|
13081
|
-
)
|
|
13082
|
-
] })
|
|
13459
|
+
]
|
|
13460
|
+
}
|
|
13461
|
+
),
|
|
13462
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "text-xs text-zinc-500 dark:text-zinc-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." })
|
|
13083
13463
|
] }),
|
|
13084
|
-
scope === "node" && /* @__PURE__ */ (0,
|
|
13085
|
-
/* @__PURE__ */ (0,
|
|
13086
|
-
/* @__PURE__ */ (0,
|
|
13087
|
-
|
|
13464
|
+
scope === "node" && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "space-y-2", children: [
|
|
13465
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "text-sm font-medium text-zinc-900 dark:text-zinc-100", children: "Node id" }),
|
|
13466
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
13467
|
+
import_form_palette26.InputField,
|
|
13088
13468
|
{
|
|
13089
|
-
|
|
13090
|
-
|
|
13091
|
-
|
|
13092
|
-
|
|
13093
|
-
|
|
13094
|
-
|
|
13095
|
-
|
|
13096
|
-
|
|
13097
|
-
|
|
13098
|
-
|
|
13099
|
-
|
|
13100
|
-
String(node.serviceId)
|
|
13101
|
-
] }, node.id))
|
|
13102
|
-
]
|
|
13469
|
+
variant: "select",
|
|
13470
|
+
value: nodeId || void 0,
|
|
13471
|
+
onChange: ({ value }) => setNodeId(String(value != null ? value : "")),
|
|
13472
|
+
options: nodeTargets.map((node) => ({
|
|
13473
|
+
value: node.id,
|
|
13474
|
+
label: `[${node.kind}] ${node.label} \xB7 #${String(node.serviceId)}`
|
|
13475
|
+
})),
|
|
13476
|
+
placeholder: "Select node...",
|
|
13477
|
+
searchable: true,
|
|
13478
|
+
clearable: false,
|
|
13479
|
+
fullWidth: true
|
|
13103
13480
|
}
|
|
13104
13481
|
),
|
|
13105
|
-
nodeScopeDisabled ? /* @__PURE__ */ (0,
|
|
13482
|
+
nodeScopeDisabled ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "text-xs text-zinc-500 dark:text-zinc-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
|
|
13106
13483
|
] })
|
|
13107
13484
|
] }),
|
|
13108
|
-
/* @__PURE__ */ (0,
|
|
13109
|
-
/* @__PURE__ */ (0,
|
|
13485
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center justify-end gap-2 border-t border-zinc-200 p-4 dark:border-zinc-800", children: [
|
|
13486
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
13110
13487
|
"button",
|
|
13111
13488
|
{
|
|
13112
13489
|
type: "button",
|
|
13113
13490
|
onClick: onClose,
|
|
13114
|
-
className: "rounded-xl border border-zinc-300 bg-white px-3 py-2 text-sm font-medium text-zinc-700 hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-200 dark:hover:bg-zinc-800",
|
|
13491
|
+
className: "rounded-xl border border-zinc-300 bg-white px-3 py-2 text-sm font-medium text-zinc-700 transition hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-200 dark:hover:bg-zinc-800",
|
|
13115
13492
|
children: "Cancel"
|
|
13116
13493
|
}
|
|
13117
13494
|
),
|
|
13118
|
-
/* @__PURE__ */ (0,
|
|
13495
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
13119
13496
|
"button",
|
|
13120
13497
|
{
|
|
13121
13498
|
type: "button",
|
|
13122
13499
|
onClick: handleContinue,
|
|
13123
13500
|
disabled: activeServiceId === void 0 || scope === "node" && !nodeId,
|
|
13124
|
-
className: "rounded-xl bg-blue-600 px-3 py-2 text-sm font-medium text-white hover:bg-blue-700 disabled:cursor-not-allowed disabled:opacity-60",
|
|
13501
|
+
className: "rounded-xl bg-blue-600 px-3 py-2 text-sm font-medium text-white transition hover:bg-blue-700 disabled:cursor-not-allowed disabled:opacity-60",
|
|
13125
13502
|
children: "Continue"
|
|
13126
13503
|
}
|
|
13127
13504
|
)
|
|
@@ -13158,169 +13535,6 @@ function resolveNodeMeta(props, nodeId) {
|
|
|
13158
13535
|
}
|
|
13159
13536
|
return { kind: "node", label: nodeId };
|
|
13160
13537
|
}
|
|
13161
|
-
|
|
13162
|
-
// src/react/fallback-editor/FallbackRegistrationsPanel.tsx
|
|
13163
|
-
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
13164
|
-
function FallbackRegistrationsPanel() {
|
|
13165
|
-
const { activeServiceId, remove: remove2, clear, check } = useFallbackEditor();
|
|
13166
|
-
const registrations = useActiveFallbackRegistrations();
|
|
13167
|
-
const eligibleServices = useEligibleServiceList();
|
|
13168
|
-
const [candidatePickerOpen, setCandidatePickerOpen] = import_react23.default.useState(false);
|
|
13169
|
-
const [candidateContext, setCandidateContext] = import_react23.default.useState(null);
|
|
13170
|
-
const [candidatePrimaryId, setCandidatePrimaryId] = import_react23.default.useState(void 0);
|
|
13171
|
-
const [registrationDialogOpen, setRegistrationDialogOpen] = import_react23.default.useState(false);
|
|
13172
|
-
const makeContext = import_react23.default.useCallback(
|
|
13173
|
-
(registration) => {
|
|
13174
|
-
if (registration.scope === "global") {
|
|
13175
|
-
return {
|
|
13176
|
-
scope: "global",
|
|
13177
|
-
primary: registration.primary
|
|
13178
|
-
};
|
|
13179
|
-
}
|
|
13180
|
-
return {
|
|
13181
|
-
scope: "node",
|
|
13182
|
-
nodeId: registration.scopeId
|
|
13183
|
-
};
|
|
13184
|
-
},
|
|
13185
|
-
[]
|
|
13186
|
-
);
|
|
13187
|
-
const openCandidatePicker = import_react23.default.useCallback(
|
|
13188
|
-
(context, primaryId) => {
|
|
13189
|
-
setCandidateContext(context);
|
|
13190
|
-
setCandidatePrimaryId(primaryId);
|
|
13191
|
-
setCandidatePickerOpen(true);
|
|
13192
|
-
},
|
|
13193
|
-
[]
|
|
13194
|
-
);
|
|
13195
|
-
if (activeServiceId === void 0 || activeServiceId === null) {
|
|
13196
|
-
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("section", { className: "rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "rounded-2xl border border-dashed border-zinc-300 p-6 text-sm text-zinc-500 dark:border-zinc-700 dark:text-zinc-400", children: "Select a primary service to start editing." }) });
|
|
13197
|
-
}
|
|
13198
|
-
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
|
|
13199
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("section", { className: "rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
13200
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "mb-4 flex items-start justify-between gap-3", children: [
|
|
13201
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { children: [
|
|
13202
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h3", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: "Registered fallbacks" }),
|
|
13203
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400", children: "Use eligible services as fallback candidates for the selected primary." })
|
|
13204
|
-
] }),
|
|
13205
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
13206
|
-
"button",
|
|
13207
|
-
{
|
|
13208
|
-
type: "button",
|
|
13209
|
-
onClick: () => setRegistrationDialogOpen(true),
|
|
13210
|
-
className: "rounded-xl border border-zinc-300 bg-white px-3 py-2 text-sm font-medium text-zinc-700 hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-200 dark:hover:bg-zinc-800",
|
|
13211
|
-
children: "Add registration"
|
|
13212
|
-
}
|
|
13213
|
-
)
|
|
13214
|
-
] }),
|
|
13215
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "space-y-4", children: registrations.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "rounded-2xl border border-dashed border-zinc-300 p-6 text-sm text-zinc-500 dark:border-zinc-700 dark:text-zinc-400", children: "No registrations yet for this primary service." }) : registrations.map((reg, index) => {
|
|
13216
|
-
var _a;
|
|
13217
|
-
const context = makeContext(reg);
|
|
13218
|
-
const candidates = reg.services;
|
|
13219
|
-
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
13220
|
-
"div",
|
|
13221
|
-
{
|
|
13222
|
-
className: "rounded-2xl border border-zinc-200 bg-zinc-50 p-4 dark:border-zinc-800 dark:bg-zinc-950",
|
|
13223
|
-
children: [
|
|
13224
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [
|
|
13225
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { children: [
|
|
13226
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: reg.scope === "global" ? "Global registration" : `Node \xB7 ${reg.scopeId}` }),
|
|
13227
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400", children: [
|
|
13228
|
-
"Primary #",
|
|
13229
|
-
String(reg.primary)
|
|
13230
|
-
] })
|
|
13231
|
-
] }),
|
|
13232
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "rounded-full border border-zinc-200 bg-white px-2 py-1 text-[11px] text-zinc-600 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-300", children: [
|
|
13233
|
-
reg.scope,
|
|
13234
|
-
reg.scopeId ? ` \xB7 ${reg.scopeId}` : ""
|
|
13235
|
-
] })
|
|
13236
|
-
] }),
|
|
13237
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "mt-4 flex flex-wrap gap-2", children: candidates.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "text-xs text-zinc-500 dark:text-zinc-400", children: "No fallback services yet." }) : candidates.map((candidate) => {
|
|
13238
|
-
var _a2;
|
|
13239
|
-
const preview = check(context, [
|
|
13240
|
-
candidate
|
|
13241
|
-
]);
|
|
13242
|
-
const rejected = preview.rejected[0];
|
|
13243
|
-
const tone = rejected ? "border-red-200 bg-red-50 text-red-700 dark:border-red-900/50 dark:bg-red-950/30 dark:text-red-300" : "border-zinc-200 bg-white text-zinc-700 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-200";
|
|
13244
|
-
const service = eligibleServices.find(
|
|
13245
|
-
(s) => String(s.id) === String(candidate)
|
|
13246
|
-
);
|
|
13247
|
-
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
13248
|
-
"div",
|
|
13249
|
-
{
|
|
13250
|
-
className: `inline-flex items-center gap-2 rounded-xl border px-3 py-2 text-xs ${tone}`,
|
|
13251
|
-
children: [
|
|
13252
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: service ? `#${String(service.id)} \xB7 ${(_a2 = service.name) != null ? _a2 : "Unnamed"}` : `#${String(candidate)}` }),
|
|
13253
|
-
rejected ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "rounded-full border border-current/20 px-2 py-0.5 text-[10px]", children: rejected.reasons.join(
|
|
13254
|
-
", "
|
|
13255
|
-
) }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "rounded-full border border-current/20 px-2 py-0.5 text-[10px]", children: "valid" }),
|
|
13256
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
13257
|
-
"button",
|
|
13258
|
-
{
|
|
13259
|
-
type: "button",
|
|
13260
|
-
onClick: () => remove2(
|
|
13261
|
-
context,
|
|
13262
|
-
candidate
|
|
13263
|
-
),
|
|
13264
|
-
className: "text-current/70 hover:text-current",
|
|
13265
|
-
children: "\xD7"
|
|
13266
|
-
}
|
|
13267
|
-
)
|
|
13268
|
-
]
|
|
13269
|
-
},
|
|
13270
|
-
String(candidate)
|
|
13271
|
-
);
|
|
13272
|
-
}) }),
|
|
13273
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "mt-4 flex gap-2", children: [
|
|
13274
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
13275
|
-
"button",
|
|
13276
|
-
{
|
|
13277
|
-
type: "button",
|
|
13278
|
-
onClick: () => openCandidatePicker(
|
|
13279
|
-
context,
|
|
13280
|
-
reg.primary
|
|
13281
|
-
),
|
|
13282
|
-
className: "rounded-xl border border-zinc-300 bg-white px-3 py-2 text-sm font-medium text-zinc-700 hover:bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-900 dark:text-zinc-200 dark:hover:bg-zinc-800",
|
|
13283
|
-
children: "Add fallback"
|
|
13284
|
-
}
|
|
13285
|
-
),
|
|
13286
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
13287
|
-
"button",
|
|
13288
|
-
{
|
|
13289
|
-
type: "button",
|
|
13290
|
-
onClick: () => clear(context),
|
|
13291
|
-
className: "rounded-xl border border-red-300 bg-white px-3 py-2 text-sm font-medium text-red-600 hover:bg-red-50 dark:border-red-900/50 dark:bg-zinc-900 dark:text-red-300 dark:hover:bg-red-950/20",
|
|
13292
|
-
children: "Clear"
|
|
13293
|
-
}
|
|
13294
|
-
)
|
|
13295
|
-
] })
|
|
13296
|
-
]
|
|
13297
|
-
},
|
|
13298
|
-
`${reg.scope}:${String((_a = reg.scopeId) != null ? _a : "global")}:${index}`
|
|
13299
|
-
);
|
|
13300
|
-
}) })
|
|
13301
|
-
] }),
|
|
13302
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
13303
|
-
FallbackAddRegistrationDialog,
|
|
13304
|
-
{
|
|
13305
|
-
open: registrationDialogOpen,
|
|
13306
|
-
onClose: () => setRegistrationDialogOpen(false),
|
|
13307
|
-
onSelect: (context, primaryId) => {
|
|
13308
|
-
setRegistrationDialogOpen(false);
|
|
13309
|
-
openCandidatePicker(context, primaryId);
|
|
13310
|
-
}
|
|
13311
|
-
}
|
|
13312
|
-
),
|
|
13313
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
13314
|
-
FallbackAddCandidatesDialog,
|
|
13315
|
-
{
|
|
13316
|
-
open: candidatePickerOpen,
|
|
13317
|
-
onClose: () => setCandidatePickerOpen(false),
|
|
13318
|
-
context: candidateContext,
|
|
13319
|
-
primaryId: candidatePrimaryId
|
|
13320
|
-
}
|
|
13321
|
-
)
|
|
13322
|
-
] });
|
|
13323
|
-
}
|
|
13324
13538
|
// Annotate the CommonJS export names for ESM import in node:
|
|
13325
13539
|
0 && (module.exports = {
|
|
13326
13540
|
CanvasAPI,
|