@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.js
CHANGED
|
@@ -1845,6 +1845,9 @@ function toFiniteNumber(v) {
|
|
|
1845
1845
|
const n = Number(v);
|
|
1846
1846
|
return Number.isFinite(n) ? n : NaN;
|
|
1847
1847
|
}
|
|
1848
|
+
function isValidServiceIdRef(value) {
|
|
1849
|
+
return typeof value === "number" && Number.isFinite(value) || typeof value === "string" && value.trim().length > 0;
|
|
1850
|
+
}
|
|
1848
1851
|
function constraintFitOk(svcMap, candidate, constraints) {
|
|
1849
1852
|
const cap = getServiceCapability(svcMap, candidate);
|
|
1850
1853
|
if (!cap) return false;
|
|
@@ -1853,18 +1856,32 @@ function constraintFitOk(svcMap, candidate, constraints) {
|
|
|
1853
1856
|
return !(constraints.cancel === true && !cap.cancel);
|
|
1854
1857
|
}
|
|
1855
1858
|
function getServiceCapability(svcMap, candidate) {
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
if (
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1859
|
+
var _a;
|
|
1860
|
+
return (_a = getServiceCapabilityEntry(svcMap, candidate)) == null ? void 0 : _a.capability;
|
|
1861
|
+
}
|
|
1862
|
+
function getServiceCapabilityCanonicalRef(svcMap, candidate) {
|
|
1863
|
+
const entry = getServiceCapabilityEntry(svcMap, candidate);
|
|
1864
|
+
if (!entry) return void 0;
|
|
1865
|
+
return getCanonicalServiceRef(entry.key, entry.capability);
|
|
1866
|
+
}
|
|
1867
|
+
function getServiceCapabilityAliases(svcMap, candidate) {
|
|
1868
|
+
const entry = getServiceCapabilityEntry(svcMap, candidate);
|
|
1869
|
+
if (!entry) return [];
|
|
1870
|
+
return collectServiceRefAliases(entry.key, entry.capability);
|
|
1871
|
+
}
|
|
1872
|
+
function isSameServiceCapabilityRef(svcMap, left, right) {
|
|
1873
|
+
if (!isValidServiceIdRef(left) || !isValidServiceIdRef(right)) return false;
|
|
1874
|
+
const leftAliases = new Set(
|
|
1875
|
+
getServiceCapabilityAliases(svcMap, left).map((value) => String(value))
|
|
1876
|
+
);
|
|
1877
|
+
if (!leftAliases.size) {
|
|
1878
|
+
leftAliases.add(String(left));
|
|
1866
1879
|
}
|
|
1867
|
-
|
|
1880
|
+
const rightAliases = getServiceCapabilityAliases(svcMap, right);
|
|
1881
|
+
if (!rightAliases.length) {
|
|
1882
|
+
return leftAliases.has(String(right));
|
|
1883
|
+
}
|
|
1884
|
+
return rightAliases.some((value) => leftAliases.has(String(value)));
|
|
1868
1885
|
}
|
|
1869
1886
|
function normalizeRatePolicy(policy) {
|
|
1870
1887
|
var _a;
|
|
@@ -1900,6 +1917,74 @@ function rateOk(svcMap, candidate, primary, policy) {
|
|
|
1900
1917
|
if (!Number.isFinite(cRate) || !Number.isFinite(pRate)) return false;
|
|
1901
1918
|
return passesRatePolicy(policy.ratePolicy, pRate, cRate);
|
|
1902
1919
|
}
|
|
1920
|
+
function getServiceCapabilityEntry(svcMap, candidate) {
|
|
1921
|
+
if (candidate === void 0 || candidate === null) return void 0;
|
|
1922
|
+
const direct = svcMap[candidate];
|
|
1923
|
+
if (direct) {
|
|
1924
|
+
return { key: String(candidate), capability: direct };
|
|
1925
|
+
}
|
|
1926
|
+
const byString = svcMap[String(candidate)];
|
|
1927
|
+
if (byString) {
|
|
1928
|
+
return { key: String(candidate), capability: byString };
|
|
1929
|
+
}
|
|
1930
|
+
if (typeof candidate === "string") {
|
|
1931
|
+
const maybeNumber = Number(candidate);
|
|
1932
|
+
if (Number.isFinite(maybeNumber)) {
|
|
1933
|
+
const byNumber = svcMap[maybeNumber];
|
|
1934
|
+
if (byNumber) {
|
|
1935
|
+
return { key: String(maybeNumber), capability: byNumber };
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
}
|
|
1939
|
+
const target = String(candidate);
|
|
1940
|
+
for (const [key, capability] of Object.entries(svcMap != null ? svcMap : {})) {
|
|
1941
|
+
if (collectServiceRefAliases(key, capability).some(
|
|
1942
|
+
(alias) => String(alias) === target
|
|
1943
|
+
)) {
|
|
1944
|
+
return { key, capability };
|
|
1945
|
+
}
|
|
1946
|
+
}
|
|
1947
|
+
return void 0;
|
|
1948
|
+
}
|
|
1949
|
+
function collectServiceRefAliases(key, capability) {
|
|
1950
|
+
const out = [];
|
|
1951
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1952
|
+
const push = (value) => {
|
|
1953
|
+
if (!isValidServiceIdRef(value)) return;
|
|
1954
|
+
const normalized = normalizeServiceRef(value);
|
|
1955
|
+
if (!normalized) return;
|
|
1956
|
+
const aliasKey = String(normalized);
|
|
1957
|
+
if (seen.has(aliasKey)) return;
|
|
1958
|
+
seen.add(aliasKey);
|
|
1959
|
+
out.push(normalized);
|
|
1960
|
+
};
|
|
1961
|
+
push(getCanonicalServiceRef(key, capability));
|
|
1962
|
+
push(capability.service);
|
|
1963
|
+
push(capability.key);
|
|
1964
|
+
push(capability.id);
|
|
1965
|
+
return out;
|
|
1966
|
+
}
|
|
1967
|
+
function getCanonicalServiceRef(key, capability) {
|
|
1968
|
+
const explicitRefs = [capability.service, capability.key, capability.id];
|
|
1969
|
+
for (const ref of explicitRefs) {
|
|
1970
|
+
if (!isValidServiceIdRef(ref)) continue;
|
|
1971
|
+
if (String(ref) === key) {
|
|
1972
|
+
return ref;
|
|
1973
|
+
}
|
|
1974
|
+
}
|
|
1975
|
+
return normalizeServiceRef(key);
|
|
1976
|
+
}
|
|
1977
|
+
function normalizeServiceRef(value) {
|
|
1978
|
+
if (!isValidServiceIdRef(value)) return void 0;
|
|
1979
|
+
if (typeof value === "number") return value;
|
|
1980
|
+
const trimmed = value.trim();
|
|
1981
|
+
if (!trimmed) return void 0;
|
|
1982
|
+
const asNumber = Number(trimmed);
|
|
1983
|
+
if (Number.isFinite(asNumber) && String(asNumber) === trimmed) {
|
|
1984
|
+
return asNumber;
|
|
1985
|
+
}
|
|
1986
|
+
return trimmed;
|
|
1987
|
+
}
|
|
1903
1988
|
|
|
1904
1989
|
// src/core/validate/steps/rates.ts
|
|
1905
1990
|
function validateRates(v) {
|
|
@@ -3345,7 +3430,7 @@ function collectFailedFallbacks(props, services, settings) {
|
|
|
3345
3430
|
const s = { ...DEFAULT_SETTINGS, ...settings != null ? settings : {} };
|
|
3346
3431
|
const out = [];
|
|
3347
3432
|
const fb = (_a = props.fallbacks) != null ? _a : {};
|
|
3348
|
-
const primaryRate = (
|
|
3433
|
+
const primaryRate = (primary) => rateOf(services, primary);
|
|
3349
3434
|
for (const [nodeId, list] of Object.entries((_b = fb.nodes) != null ? _b : {})) {
|
|
3350
3435
|
const { primary, tagContexts } = primaryForNode(props, nodeId);
|
|
3351
3436
|
if (!primary) {
|
|
@@ -3358,34 +3443,34 @@ function collectFailedFallbacks(props, services, settings) {
|
|
|
3358
3443
|
});
|
|
3359
3444
|
continue;
|
|
3360
3445
|
}
|
|
3361
|
-
for (const
|
|
3362
|
-
const
|
|
3363
|
-
if (!
|
|
3446
|
+
for (const candidate of list) {
|
|
3447
|
+
const capability = getCap(services, candidate);
|
|
3448
|
+
if (!capability) {
|
|
3364
3449
|
out.push({
|
|
3365
3450
|
scope: "node",
|
|
3366
3451
|
nodeId,
|
|
3367
3452
|
primary,
|
|
3368
|
-
candidate
|
|
3453
|
+
candidate,
|
|
3369
3454
|
reason: "unknown_service"
|
|
3370
3455
|
});
|
|
3371
3456
|
continue;
|
|
3372
3457
|
}
|
|
3373
|
-
if (
|
|
3458
|
+
if (isSameServiceCapabilityRef(services, candidate, primary)) {
|
|
3374
3459
|
out.push({
|
|
3375
3460
|
scope: "node",
|
|
3376
3461
|
nodeId,
|
|
3377
3462
|
primary,
|
|
3378
|
-
candidate
|
|
3463
|
+
candidate,
|
|
3379
3464
|
reason: "cycle"
|
|
3380
3465
|
});
|
|
3381
3466
|
continue;
|
|
3382
3467
|
}
|
|
3383
|
-
if (!passesRate(s.ratePolicy, primaryRate(primary),
|
|
3468
|
+
if (!passesRate(s.ratePolicy, primaryRate(primary), capability.rate)) {
|
|
3384
3469
|
out.push({
|
|
3385
3470
|
scope: "node",
|
|
3386
3471
|
nodeId,
|
|
3387
3472
|
primary,
|
|
3388
|
-
candidate
|
|
3473
|
+
candidate,
|
|
3389
3474
|
reason: "rate_violation"
|
|
3390
3475
|
});
|
|
3391
3476
|
continue;
|
|
@@ -3395,58 +3480,55 @@ function collectFailedFallbacks(props, services, settings) {
|
|
|
3395
3480
|
scope: "node",
|
|
3396
3481
|
nodeId,
|
|
3397
3482
|
primary,
|
|
3398
|
-
candidate
|
|
3483
|
+
candidate,
|
|
3399
3484
|
reason: "no_tag_context"
|
|
3400
3485
|
});
|
|
3401
3486
|
continue;
|
|
3402
3487
|
}
|
|
3403
|
-
let anyPass = false;
|
|
3404
|
-
let anyFail = false;
|
|
3405
3488
|
for (const tagId of tagContexts) {
|
|
3406
|
-
const
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3489
|
+
const fitsConstraints = s.requireConstraintFit ? satisfiesTagConstraints(
|
|
3490
|
+
tagId,
|
|
3491
|
+
{ services, props },
|
|
3492
|
+
capability
|
|
3493
|
+
) : true;
|
|
3494
|
+
if (fitsConstraints) continue;
|
|
3495
|
+
out.push({
|
|
3496
|
+
scope: "node",
|
|
3497
|
+
nodeId,
|
|
3498
|
+
primary,
|
|
3499
|
+
candidate,
|
|
3500
|
+
tagContext: tagId,
|
|
3501
|
+
reason: "constraint_mismatch"
|
|
3502
|
+
});
|
|
3419
3503
|
}
|
|
3420
|
-
void anyPass;
|
|
3421
|
-
void anyFail;
|
|
3422
3504
|
}
|
|
3423
3505
|
}
|
|
3424
3506
|
for (const [primary, list] of Object.entries((_c = fb.global) != null ? _c : {})) {
|
|
3425
|
-
for (const
|
|
3426
|
-
const
|
|
3427
|
-
if (!
|
|
3507
|
+
for (const candidate of list) {
|
|
3508
|
+
const capability = getCap(services, candidate);
|
|
3509
|
+
if (!capability) {
|
|
3428
3510
|
out.push({
|
|
3429
3511
|
scope: "global",
|
|
3430
3512
|
primary,
|
|
3431
|
-
candidate
|
|
3513
|
+
candidate,
|
|
3432
3514
|
reason: "unknown_service"
|
|
3433
3515
|
});
|
|
3434
3516
|
continue;
|
|
3435
3517
|
}
|
|
3436
|
-
if (
|
|
3518
|
+
if (isSameServiceCapabilityRef(services, candidate, primary)) {
|
|
3437
3519
|
out.push({
|
|
3438
3520
|
scope: "global",
|
|
3439
3521
|
primary,
|
|
3440
|
-
candidate
|
|
3522
|
+
candidate,
|
|
3441
3523
|
reason: "cycle"
|
|
3442
3524
|
});
|
|
3443
3525
|
continue;
|
|
3444
3526
|
}
|
|
3445
|
-
if (!passesRate(s.ratePolicy, primaryRate(primary),
|
|
3527
|
+
if (!passesRate(s.ratePolicy, primaryRate(primary), capability.rate)) {
|
|
3446
3528
|
out.push({
|
|
3447
3529
|
scope: "global",
|
|
3448
3530
|
primary,
|
|
3449
|
-
candidate
|
|
3531
|
+
candidate,
|
|
3450
3532
|
reason: "rate_violation"
|
|
3451
3533
|
});
|
|
3452
3534
|
}
|
|
@@ -3455,52 +3537,61 @@ function collectFailedFallbacks(props, services, settings) {
|
|
|
3455
3537
|
return out;
|
|
3456
3538
|
}
|
|
3457
3539
|
function rateOf(map, id) {
|
|
3458
|
-
var _a;
|
|
3540
|
+
var _a, _b;
|
|
3459
3541
|
if (id === void 0 || id === null) return void 0;
|
|
3460
|
-
|
|
3461
|
-
return (_a = c == null ? void 0 : c.rate) != null ? _a : void 0;
|
|
3542
|
+
return (_b = (_a = getCap(map, id)) == null ? void 0 : _a.rate) != null ? _b : void 0;
|
|
3462
3543
|
}
|
|
3463
|
-
function passesRate(policy, primaryRate,
|
|
3464
|
-
if (typeof
|
|
3544
|
+
function passesRate(policy, primaryRate, candidateRate) {
|
|
3545
|
+
if (typeof candidateRate !== "number" || !Number.isFinite(candidateRate)) {
|
|
3465
3546
|
return false;
|
|
3466
|
-
|
|
3547
|
+
}
|
|
3548
|
+
if (typeof primaryRate !== "number" || !Number.isFinite(primaryRate)) {
|
|
3467
3549
|
return false;
|
|
3468
|
-
|
|
3550
|
+
}
|
|
3551
|
+
return passesRatePolicy(
|
|
3552
|
+
normalizeRatePolicy(policy),
|
|
3553
|
+
primaryRate,
|
|
3554
|
+
candidateRate
|
|
3555
|
+
);
|
|
3469
3556
|
}
|
|
3470
3557
|
function getCap(map, id) {
|
|
3471
3558
|
return getServiceCapability(map, id);
|
|
3472
3559
|
}
|
|
3473
|
-
function isCapFlagEnabled(
|
|
3560
|
+
function isCapFlagEnabled(capability, flagId) {
|
|
3474
3561
|
var _a, _b;
|
|
3475
|
-
const fromFlags = (_b = (_a =
|
|
3562
|
+
const fromFlags = (_b = (_a = capability.flags) == null ? void 0 : _a[flagId]) == null ? void 0 : _b.enabled;
|
|
3476
3563
|
if (fromFlags === true) return true;
|
|
3477
3564
|
if (fromFlags === false) return false;
|
|
3478
|
-
const legacy =
|
|
3565
|
+
const legacy = capability[flagId];
|
|
3479
3566
|
return legacy === true;
|
|
3480
3567
|
}
|
|
3481
|
-
function satisfiesTagConstraints(tagId, ctx,
|
|
3482
|
-
const tag = ctx.props.filters.find((
|
|
3483
|
-
const
|
|
3484
|
-
if (!
|
|
3485
|
-
for (const [key, value] of Object.entries(
|
|
3486
|
-
if (value === true && !isCapFlagEnabled(
|
|
3568
|
+
function satisfiesTagConstraints(tagId, ctx, capability) {
|
|
3569
|
+
const tag = ctx.props.filters.find((item) => item.id === tagId);
|
|
3570
|
+
const effectiveConstraints2 = tag == null ? void 0 : tag.constraints;
|
|
3571
|
+
if (!effectiveConstraints2) return true;
|
|
3572
|
+
for (const [key, value] of Object.entries(effectiveConstraints2)) {
|
|
3573
|
+
if (value === true && !isCapFlagEnabled(capability, key)) {
|
|
3487
3574
|
return false;
|
|
3488
3575
|
}
|
|
3489
3576
|
}
|
|
3490
3577
|
return true;
|
|
3491
3578
|
}
|
|
3492
3579
|
function primaryForNode(props, nodeId) {
|
|
3493
|
-
const tag = props.filters.find((
|
|
3580
|
+
const tag = props.filters.find((item) => item.id === nodeId);
|
|
3494
3581
|
if (tag) {
|
|
3495
3582
|
return { primary: tag.service_id, tagContexts: [tag.id] };
|
|
3496
3583
|
}
|
|
3497
3584
|
const field = props.fields.find(
|
|
3498
|
-
(
|
|
3585
|
+
(item) => Array.isArray(item.options) && item.options.some((option2) => option2.id === nodeId)
|
|
3499
3586
|
);
|
|
3500
|
-
if (!field)
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3587
|
+
if (!field) {
|
|
3588
|
+
return { tagContexts: [], reasonNoPrimary: "no_parent_field" };
|
|
3589
|
+
}
|
|
3590
|
+
const option = field.options.find((item) => item.id === nodeId);
|
|
3591
|
+
return {
|
|
3592
|
+
primary: option.service_id,
|
|
3593
|
+
tagContexts: bindIdsToArray(field.bind_id)
|
|
3594
|
+
};
|
|
3504
3595
|
}
|
|
3505
3596
|
function bindIdsToArray(bind) {
|
|
3506
3597
|
if (!bind) return [];
|
|
@@ -3510,43 +3601,54 @@ function getEligibleFallbacks(params) {
|
|
|
3510
3601
|
var _a, _b, _c, _d, _e, _f;
|
|
3511
3602
|
const s = { ...DEFAULT_SETTINGS, ...(_a = params.settings) != null ? _a : {} };
|
|
3512
3603
|
const { primary, nodeId, tagId, services } = params;
|
|
3513
|
-
const
|
|
3514
|
-
const
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3604
|
+
const excludes = /* @__PURE__ */ new Set();
|
|
3605
|
+
for (const ref of (_b = params.exclude) != null ? _b : []) {
|
|
3606
|
+
addComparableServiceRef(excludes, services, ref);
|
|
3607
|
+
}
|
|
3608
|
+
addComparableServiceRef(excludes, services, primary);
|
|
3609
|
+
const source = (_c = params.source) != null ? _c : "registered";
|
|
3610
|
+
const candidateLists = source === "all_services" ? [listServicePoolCandidates(services)] : listRegisteredFallbackCandidates(
|
|
3611
|
+
(_d = params.fallbacks) != null ? _d : {},
|
|
3612
|
+
primary,
|
|
3613
|
+
nodeId,
|
|
3614
|
+
services
|
|
3615
|
+
);
|
|
3616
|
+
if (!candidateLists.length) return [];
|
|
3521
3617
|
const primaryRate = rateOf(services, primary);
|
|
3522
3618
|
const seen = /* @__PURE__ */ new Set();
|
|
3523
3619
|
const eligible = [];
|
|
3524
|
-
for (const list of
|
|
3525
|
-
for (const
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
if (
|
|
3529
|
-
|
|
3530
|
-
const
|
|
3531
|
-
|
|
3532
|
-
|
|
3620
|
+
for (const list of candidateLists) {
|
|
3621
|
+
for (const candidate of list) {
|
|
3622
|
+
if (hasComparableServiceRef(excludes, services, candidate)) continue;
|
|
3623
|
+
const capability = getCap(services, candidate);
|
|
3624
|
+
if (!capability) continue;
|
|
3625
|
+
const candidateId = (_e = getServiceCapabilityCanonicalRef(services, candidate)) != null ? _e : candidate;
|
|
3626
|
+
const candidateIdentity = getComparableServiceRefKey(
|
|
3627
|
+
services,
|
|
3628
|
+
candidateId
|
|
3629
|
+
);
|
|
3630
|
+
if (((_f = params.unique) != null ? _f : true) && seen.has(candidateIdentity)) continue;
|
|
3631
|
+
seen.add(candidateIdentity);
|
|
3632
|
+
if (!passesRate(s.ratePolicy, primaryRate, capability.rate)) {
|
|
3633
|
+
continue;
|
|
3634
|
+
}
|
|
3533
3635
|
if (s.requireConstraintFit && tagId) {
|
|
3534
|
-
const
|
|
3636
|
+
const fitsConstraints = satisfiesTagConstraints(
|
|
3535
3637
|
tagId,
|
|
3536
3638
|
{ props: params.props, services },
|
|
3537
|
-
|
|
3639
|
+
capability
|
|
3538
3640
|
);
|
|
3539
|
-
if (!
|
|
3641
|
+
if (!fitsConstraints) continue;
|
|
3540
3642
|
}
|
|
3541
|
-
eligible.push(
|
|
3643
|
+
eligible.push(candidateId);
|
|
3542
3644
|
}
|
|
3543
3645
|
}
|
|
3544
3646
|
if (s.selectionStrategy === "cheapest") {
|
|
3545
|
-
eligible.sort((
|
|
3647
|
+
eligible.sort((left, right) => {
|
|
3546
3648
|
var _a2, _b2;
|
|
3547
|
-
const
|
|
3548
|
-
const
|
|
3549
|
-
return
|
|
3649
|
+
const leftRate = (_a2 = rateOf(services, left)) != null ? _a2 : Infinity;
|
|
3650
|
+
const rightRate = (_b2 = rateOf(services, right)) != null ? _b2 : Infinity;
|
|
3651
|
+
return leftRate - rightRate;
|
|
3550
3652
|
});
|
|
3551
3653
|
}
|
|
3552
3654
|
if (typeof params.limit === "number" && params.limit >= 0) {
|
|
@@ -3554,10 +3656,104 @@ function getEligibleFallbacks(params) {
|
|
|
3554
3656
|
}
|
|
3555
3657
|
return eligible;
|
|
3556
3658
|
}
|
|
3659
|
+
function getAssignedServiceIds(params) {
|
|
3660
|
+
var _a, _b, _c, _d, _e;
|
|
3661
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3662
|
+
const out = [];
|
|
3663
|
+
const push = (value) => {
|
|
3664
|
+
if (!isValidServiceIdRef(value)) return;
|
|
3665
|
+
const key = String(value);
|
|
3666
|
+
if (seen.has(key)) return;
|
|
3667
|
+
seen.add(key);
|
|
3668
|
+
out.push(value);
|
|
3669
|
+
};
|
|
3670
|
+
const props = params.props;
|
|
3671
|
+
if (props) {
|
|
3672
|
+
for (const tag of (_a = props.filters) != null ? _a : []) {
|
|
3673
|
+
push(tag.service_id);
|
|
3674
|
+
}
|
|
3675
|
+
for (const field of (_b = props.fields) != null ? _b : []) {
|
|
3676
|
+
const fieldService = field.service_id;
|
|
3677
|
+
if (field.button === true) {
|
|
3678
|
+
push(fieldService);
|
|
3679
|
+
}
|
|
3680
|
+
for (const option of (_c = field.options) != null ? _c : []) {
|
|
3681
|
+
if (option.pricing_role === "utility") continue;
|
|
3682
|
+
push(option.service_id);
|
|
3683
|
+
}
|
|
3684
|
+
}
|
|
3685
|
+
}
|
|
3686
|
+
const snapshot = params.snapshot;
|
|
3687
|
+
if (snapshot) {
|
|
3688
|
+
for (const serviceId of (_d = snapshot.services) != null ? _d : []) {
|
|
3689
|
+
push(serviceId);
|
|
3690
|
+
}
|
|
3691
|
+
for (const list of Object.values((_e = snapshot.serviceMap) != null ? _e : {})) {
|
|
3692
|
+
for (const serviceId of list != null ? list : []) {
|
|
3693
|
+
push(serviceId);
|
|
3694
|
+
}
|
|
3695
|
+
}
|
|
3696
|
+
}
|
|
3697
|
+
return out;
|
|
3698
|
+
}
|
|
3557
3699
|
function getFallbackRegistrationInfo(props, nodeId) {
|
|
3558
3700
|
const { primary, tagContexts } = primaryForNode(props, nodeId);
|
|
3559
3701
|
return { primary, tagContexts };
|
|
3560
3702
|
}
|
|
3703
|
+
function listRegisteredFallbackCandidates(fallbacks, primary, nodeId, services) {
|
|
3704
|
+
var _a, _b;
|
|
3705
|
+
const lists = [];
|
|
3706
|
+
if (nodeId && ((_a = fallbacks.nodes) == null ? void 0 : _a[nodeId])) {
|
|
3707
|
+
lists.push(fallbacks.nodes[nodeId]);
|
|
3708
|
+
}
|
|
3709
|
+
for (const [registeredPrimary, list] of Object.entries((_b = fallbacks.global) != null ? _b : {})) {
|
|
3710
|
+
if (!isMatchingServiceRef(services, registeredPrimary, primary)) continue;
|
|
3711
|
+
lists.push(list);
|
|
3712
|
+
}
|
|
3713
|
+
return lists;
|
|
3714
|
+
}
|
|
3715
|
+
function listServicePoolCandidates(services) {
|
|
3716
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3717
|
+
const out = [];
|
|
3718
|
+
for (const [key, capability] of Object.entries(services != null ? services : {})) {
|
|
3719
|
+
const candidate = getServicePoolCandidateId(key, capability);
|
|
3720
|
+
if (!isValidServiceIdRef(candidate)) continue;
|
|
3721
|
+
const identity = getComparableServiceRefKey(services, candidate);
|
|
3722
|
+
if (seen.has(identity)) continue;
|
|
3723
|
+
seen.add(identity);
|
|
3724
|
+
out.push(candidate);
|
|
3725
|
+
}
|
|
3726
|
+
return out;
|
|
3727
|
+
}
|
|
3728
|
+
function getServicePoolCandidateId(key, capability) {
|
|
3729
|
+
var _a;
|
|
3730
|
+
return (_a = getServiceCapabilityCanonicalRef({ [key]: capability }, key)) != null ? _a : key;
|
|
3731
|
+
}
|
|
3732
|
+
function addComparableServiceRef(target, services, value) {
|
|
3733
|
+
for (const ref of getComparableServiceRefs(services, value)) {
|
|
3734
|
+
target.add(ref);
|
|
3735
|
+
}
|
|
3736
|
+
}
|
|
3737
|
+
function hasComparableServiceRef(target, services, value) {
|
|
3738
|
+
return getComparableServiceRefs(services, value).some((ref) => target.has(ref));
|
|
3739
|
+
}
|
|
3740
|
+
function getComparableServiceRefKey(services, value) {
|
|
3741
|
+
if (!isValidServiceIdRef(value)) return "";
|
|
3742
|
+
const canonical = getServiceCapabilityCanonicalRef(services, value);
|
|
3743
|
+
return String(canonical != null ? canonical : value);
|
|
3744
|
+
}
|
|
3745
|
+
function getComparableServiceRefs(services, value) {
|
|
3746
|
+
if (!isValidServiceIdRef(value)) return [];
|
|
3747
|
+
const aliases = getServiceCapabilityAliases(services, value);
|
|
3748
|
+
if (!aliases.length) {
|
|
3749
|
+
return [String(value)];
|
|
3750
|
+
}
|
|
3751
|
+
return aliases.map((ref) => String(ref));
|
|
3752
|
+
}
|
|
3753
|
+
function isMatchingServiceRef(services, left, right) {
|
|
3754
|
+
if (!services) return String(left) === String(right);
|
|
3755
|
+
return isSameServiceCapabilityRef(services, left, right);
|
|
3756
|
+
}
|
|
3561
3757
|
|
|
3562
3758
|
// src/core/tag-relations.ts
|
|
3563
3759
|
var toId = (x) => typeof x === "string" ? x : x.id;
|
|
@@ -5096,6 +5292,7 @@ function createFallbackEditor(options = {}) {
|
|
|
5096
5292
|
const original = cloneFallbacks(options.fallbacks);
|
|
5097
5293
|
let current = cloneFallbacks(options.fallbacks);
|
|
5098
5294
|
const props = options.props;
|
|
5295
|
+
const snapshot = options.snapshot;
|
|
5099
5296
|
const services = (_a = options.services) != null ? _a : {};
|
|
5100
5297
|
const settings = (_b = options.settings) != null ? _b : {};
|
|
5101
5298
|
function state() {
|
|
@@ -5190,7 +5387,11 @@ function createFallbackEditor(options = {}) {
|
|
|
5190
5387
|
const allowed2 = [];
|
|
5191
5388
|
for (const candidate of normalized) {
|
|
5192
5389
|
const reasons = [];
|
|
5193
|
-
if (
|
|
5390
|
+
if (isSameServiceCapabilityRef(
|
|
5391
|
+
services,
|
|
5392
|
+
candidate,
|
|
5393
|
+
context.primary
|
|
5394
|
+
)) {
|
|
5194
5395
|
reasons.push("self_reference");
|
|
5195
5396
|
}
|
|
5196
5397
|
if (reasons.length) {
|
|
@@ -5278,7 +5479,19 @@ function createFallbackEditor(options = {}) {
|
|
|
5278
5479
|
return writeScope(context, []);
|
|
5279
5480
|
}
|
|
5280
5481
|
function eligible(context, opt) {
|
|
5482
|
+
var _a2, _b2;
|
|
5281
5483
|
if (!props) return [];
|
|
5484
|
+
const source = (_a2 = opt == null ? void 0 : opt.source) != null ? _a2 : "all_services";
|
|
5485
|
+
const exclude2 = normalizeCandidateList(
|
|
5486
|
+
[
|
|
5487
|
+
...(_b2 = opt == null ? void 0 : opt.exclude) != null ? _b2 : [],
|
|
5488
|
+
...source === "all_services" ? [
|
|
5489
|
+
...getAssignedServiceIds({ props, snapshot }),
|
|
5490
|
+
...getScope(context)
|
|
5491
|
+
] : []
|
|
5492
|
+
],
|
|
5493
|
+
true
|
|
5494
|
+
);
|
|
5282
5495
|
if (context.scope === "global") {
|
|
5283
5496
|
return getEligibleFallbacks({
|
|
5284
5497
|
primary: context.primary,
|
|
@@ -5286,9 +5499,10 @@ function createFallbackEditor(options = {}) {
|
|
|
5286
5499
|
fallbacks: current,
|
|
5287
5500
|
settings,
|
|
5288
5501
|
props,
|
|
5289
|
-
exclude:
|
|
5502
|
+
exclude: exclude2,
|
|
5290
5503
|
unique: opt == null ? void 0 : opt.unique,
|
|
5291
|
-
limit: opt == null ? void 0 : opt.limit
|
|
5504
|
+
limit: opt == null ? void 0 : opt.limit,
|
|
5505
|
+
source
|
|
5292
5506
|
});
|
|
5293
5507
|
}
|
|
5294
5508
|
const info = getFallbackRegistrationInfo(props, context.nodeId);
|
|
@@ -5296,14 +5510,19 @@ function createFallbackEditor(options = {}) {
|
|
|
5296
5510
|
return getEligibleFallbacks({
|
|
5297
5511
|
primary: info.primary,
|
|
5298
5512
|
nodeId: context.nodeId,
|
|
5299
|
-
tagId:
|
|
5513
|
+
tagId: resolveNodeTagContext({
|
|
5514
|
+
nodeId: context.nodeId,
|
|
5515
|
+
snapshot,
|
|
5516
|
+
fallbackTagContexts: info.tagContexts
|
|
5517
|
+
}),
|
|
5300
5518
|
services,
|
|
5301
5519
|
fallbacks: current,
|
|
5302
5520
|
settings,
|
|
5303
5521
|
props,
|
|
5304
|
-
exclude:
|
|
5522
|
+
exclude: exclude2,
|
|
5305
5523
|
unique: opt == null ? void 0 : opt.unique,
|
|
5306
|
-
limit: opt == null ? void 0 : opt.limit
|
|
5524
|
+
limit: opt == null ? void 0 : opt.limit,
|
|
5525
|
+
source
|
|
5307
5526
|
});
|
|
5308
5527
|
}
|
|
5309
5528
|
function writeScope(context, nextList) {
|
|
@@ -5361,14 +5580,14 @@ function sameFallbacks(a, b) {
|
|
|
5361
5580
|
function normalizeCandidateList(input, preserveOrder) {
|
|
5362
5581
|
const out = [];
|
|
5363
5582
|
for (const item of input != null ? input : []) {
|
|
5364
|
-
if (!
|
|
5583
|
+
if (!isValidServiceIdRef2(item)) continue;
|
|
5365
5584
|
const exists = out.some((x) => String(x) === String(item));
|
|
5366
5585
|
if (exists) continue;
|
|
5367
5586
|
out.push(item);
|
|
5368
5587
|
}
|
|
5369
5588
|
return preserveOrder ? out : out;
|
|
5370
5589
|
}
|
|
5371
|
-
function
|
|
5590
|
+
function isValidServiceIdRef2(value) {
|
|
5372
5591
|
return typeof value === "number" && Number.isFinite(value) || typeof value === "string" && value.trim().length > 0;
|
|
5373
5592
|
}
|
|
5374
5593
|
function clamp(n, min, max) {
|
|
@@ -5377,7 +5596,7 @@ function clamp(n, min, max) {
|
|
|
5377
5596
|
function getNodeRegistrationInfo(props, nodeId) {
|
|
5378
5597
|
const tag = props.filters.find((t) => t.id === nodeId);
|
|
5379
5598
|
if (tag) {
|
|
5380
|
-
if (!
|
|
5599
|
+
if (!isValidServiceIdRef2(tag.service_id)) {
|
|
5381
5600
|
return { ok: false, reasons: ["no_primary"] };
|
|
5382
5601
|
}
|
|
5383
5602
|
return {
|
|
@@ -5390,7 +5609,7 @@ function getNodeRegistrationInfo(props, nodeId) {
|
|
|
5390
5609
|
if (!hit) {
|
|
5391
5610
|
return { ok: false, reasons: ["node_not_found"] };
|
|
5392
5611
|
}
|
|
5393
|
-
if (!
|
|
5612
|
+
if (!isValidServiceIdRef2(hit.option.service_id)) {
|
|
5394
5613
|
return { ok: false, reasons: ["no_primary"] };
|
|
5395
5614
|
}
|
|
5396
5615
|
return {
|
|
@@ -5412,6 +5631,15 @@ function bindIdsToArray2(v) {
|
|
|
5412
5631
|
if (Array.isArray(v)) return v.filter(Boolean);
|
|
5413
5632
|
return v ? [v] : [];
|
|
5414
5633
|
}
|
|
5634
|
+
function resolveNodeTagContext(params) {
|
|
5635
|
+
var _a, _b, _c;
|
|
5636
|
+
const nodeContexts = (_c = (_b = (_a = params.snapshot) == null ? void 0 : _a.meta) == null ? void 0 : _b.context) == null ? void 0 : _c.nodeContexts;
|
|
5637
|
+
if (nodeContexts && Object.prototype.hasOwnProperty.call(nodeContexts, params.nodeId)) {
|
|
5638
|
+
const tagId = nodeContexts[params.nodeId];
|
|
5639
|
+
return typeof tagId === "string" && tagId.trim().length > 0 ? tagId : void 0;
|
|
5640
|
+
}
|
|
5641
|
+
return params.fallbackTagContexts[0];
|
|
5642
|
+
}
|
|
5415
5643
|
function mapDiagReason(reason) {
|
|
5416
5644
|
switch (String(reason)) {
|
|
5417
5645
|
case "unknown_service":
|
|
@@ -12113,10 +12341,10 @@ function FallbackEditorInner({ className }) {
|
|
|
12113
12341
|
"div",
|
|
12114
12342
|
{
|
|
12115
12343
|
className: [
|
|
12116
|
-
"min-h-
|
|
12344
|
+
"h-full min-h-0 overflow-hidden bg-zinc-100 p-4 text-zinc-900 dark:bg-zinc-950 dark:text-zinc-100",
|
|
12117
12345
|
className
|
|
12118
12346
|
].filter(Boolean).join(" "),
|
|
12119
|
-
children: /* @__PURE__ */ jsxs2("div", { className: "
|
|
12347
|
+
children: /* @__PURE__ */ jsxs2("div", { className: "flex h-full min-h-0 flex-col gap-4", children: [
|
|
12120
12348
|
/* @__PURE__ */ jsx6(
|
|
12121
12349
|
FallbackEditorHeader,
|
|
12122
12350
|
{
|
|
@@ -12128,9 +12356,9 @@ function FallbackEditorInner({ className }) {
|
|
|
12128
12356
|
saving: headerSaving
|
|
12129
12357
|
}
|
|
12130
12358
|
),
|
|
12131
|
-
/* @__PURE__ */ jsxs2("div", { className: "grid gap-4 xl:grid-cols-[300px_minmax(0,1fr)_360px]", children: [
|
|
12359
|
+
/* @__PURE__ */ jsxs2("div", { className: "grid min-h-0 flex-1 gap-4 overflow-hidden xl:grid-cols-[300px_minmax(0,1fr)_360px]", children: [
|
|
12132
12360
|
/* @__PURE__ */ jsx6(FallbackServiceSidebar, {}),
|
|
12133
|
-
/* @__PURE__ */ jsxs2("div", { className: "flex min-h-0 flex-col gap-4", children: [
|
|
12361
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex min-h-0 flex-col gap-4 overflow-y-auto", children: [
|
|
12134
12362
|
/* @__PURE__ */ jsx6("section", { className: "rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900", children: /* @__PURE__ */ jsxs2("div", { className: "flex flex-wrap items-start justify-between gap-4", children: [
|
|
12135
12363
|
/* @__PURE__ */ jsxs2("div", { children: [
|
|
12136
12364
|
/* @__PURE__ */ jsx6("h2", { className: "text-lg font-semibold text-zinc-900 dark:text-zinc-100", children: activeServiceId !== void 0 ? `Service #${String(activeServiceId)}` : "No service selected" }),
|
|
@@ -12184,6 +12412,7 @@ function TabButton({
|
|
|
12184
12412
|
|
|
12185
12413
|
// src/react/fallback-editor/VirtualServiceList.tsx
|
|
12186
12414
|
import React7 from "react";
|
|
12415
|
+
import { Check } from "lucide-react";
|
|
12187
12416
|
import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
12188
12417
|
function VirtualServiceList({
|
|
12189
12418
|
items,
|
|
@@ -12226,7 +12455,7 @@ function VirtualServiceList({
|
|
|
12226
12455
|
{
|
|
12227
12456
|
type: "button",
|
|
12228
12457
|
onClick: () => onToggle(item.id),
|
|
12229
|
-
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",
|
|
12458
|
+
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",
|
|
12230
12459
|
style: {
|
|
12231
12460
|
top: index * rowHeight,
|
|
12232
12461
|
height: rowHeight
|
|
@@ -12246,12 +12475,13 @@ function VirtualServiceList({
|
|
|
12246
12475
|
] })
|
|
12247
12476
|
] }),
|
|
12248
12477
|
/* @__PURE__ */ jsx7(
|
|
12249
|
-
"
|
|
12478
|
+
"span",
|
|
12250
12479
|
{
|
|
12251
|
-
|
|
12252
|
-
|
|
12253
|
-
|
|
12254
|
-
|
|
12480
|
+
className: [
|
|
12481
|
+
"inline-flex h-4 w-4 items-center justify-center rounded border transition",
|
|
12482
|
+
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"
|
|
12483
|
+
].join(" "),
|
|
12484
|
+
children: /* @__PURE__ */ jsx7(Check, { className: "h-3 w-3" })
|
|
12255
12485
|
}
|
|
12256
12486
|
)
|
|
12257
12487
|
]
|
|
@@ -12274,7 +12504,7 @@ function FallbackDetailsPanel() {
|
|
|
12274
12504
|
() => services.find((s) => String(s.id) === String(activeServiceId)),
|
|
12275
12505
|
[services, activeServiceId]
|
|
12276
12506
|
);
|
|
12277
|
-
return /* @__PURE__ */ jsxs4("aside", { className: "flex min-h-0 flex-col gap-4", children: [
|
|
12507
|
+
return /* @__PURE__ */ jsxs4("aside", { className: "flex min-h-0 flex-col gap-4 overflow-y-auto", children: [
|
|
12278
12508
|
/* @__PURE__ */ jsxs4("section", { className: "rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
12279
12509
|
/* @__PURE__ */ jsx8("h3", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: "Primary service info" }),
|
|
12280
12510
|
!service ? /* @__PURE__ */ jsx8("p", { className: "mt-3 text-sm text-zinc-500 dark:text-zinc-400", children: "No service selected." }) : /* @__PURE__ */ jsxs4("div", { className: "mt-3 space-y-2 text-sm", children: [
|
|
@@ -12401,6 +12631,7 @@ function FallbackEditorHeader({
|
|
|
12401
12631
|
|
|
12402
12632
|
// src/react/fallback-editor/FallbackSettingsPanel.tsx
|
|
12403
12633
|
import React9 from "react";
|
|
12634
|
+
import { InputField as InputField21 } from "@timeax/form-palette";
|
|
12404
12635
|
import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
12405
12636
|
function FallbackSettingsPanel() {
|
|
12406
12637
|
var _a, _b, _c;
|
|
@@ -12436,7 +12667,7 @@ function FallbackSettingsPanel() {
|
|
|
12436
12667
|
kind: "lte_primary",
|
|
12437
12668
|
pct: 5
|
|
12438
12669
|
};
|
|
12439
|
-
return /* @__PURE__ */ jsxs6("section", { className: "rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
12670
|
+
return /* @__PURE__ */ jsxs6("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: [
|
|
12440
12671
|
/* @__PURE__ */ jsxs6("div", { className: "mb-4 flex items-start justify-between gap-3", children: [
|
|
12441
12672
|
/* @__PURE__ */ jsxs6("div", { children: [
|
|
12442
12673
|
/* @__PURE__ */ jsx10("h3", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: "Fallback settings" }),
|
|
@@ -12462,30 +12693,17 @@ function FallbackSettingsPanel() {
|
|
|
12462
12693
|
{
|
|
12463
12694
|
title: "Require constraint fit",
|
|
12464
12695
|
hint: "Reject or warn when a candidate does not match effective tag constraints.",
|
|
12465
|
-
children: /* @__PURE__ */
|
|
12466
|
-
|
|
12696
|
+
children: /* @__PURE__ */ jsx10(
|
|
12697
|
+
InputField21,
|
|
12467
12698
|
{
|
|
12468
|
-
|
|
12469
|
-
|
|
12699
|
+
variant: "toggle",
|
|
12700
|
+
value: Boolean(draft.requireConstraintFit),
|
|
12701
|
+
onChange: ({ value }) => setDraft((prev) => ({
|
|
12470
12702
|
...prev,
|
|
12471
|
-
requireConstraintFit:
|
|
12703
|
+
requireConstraintFit: Boolean(value)
|
|
12472
12704
|
})),
|
|
12473
|
-
|
|
12474
|
-
|
|
12475
|
-
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"
|
|
12476
|
-
].join(" "),
|
|
12477
|
-
children: [
|
|
12478
|
-
/* @__PURE__ */ jsx10("span", { children: draft.requireConstraintFit ? "Enabled" : "Disabled" }),
|
|
12479
|
-
/* @__PURE__ */ jsx10(
|
|
12480
|
-
"span",
|
|
12481
|
-
{
|
|
12482
|
-
className: [
|
|
12483
|
-
"h-2.5 w-2.5 rounded-full",
|
|
12484
|
-
draft.requireConstraintFit ? "bg-green-500" : "bg-zinc-400"
|
|
12485
|
-
].join(" ")
|
|
12486
|
-
}
|
|
12487
|
-
)
|
|
12488
|
-
]
|
|
12705
|
+
onText: "Enabled",
|
|
12706
|
+
offText: "Disabled"
|
|
12489
12707
|
}
|
|
12490
12708
|
)
|
|
12491
12709
|
}
|
|
@@ -12496,12 +12714,13 @@ function FallbackSettingsPanel() {
|
|
|
12496
12714
|
title: "Rate policy",
|
|
12497
12715
|
hint: "Controls how fallback service rates are compared against the primary service.",
|
|
12498
12716
|
children: /* @__PURE__ */ jsxs6("div", { className: "flex flex-col gap-2 md:items-end", children: [
|
|
12499
|
-
/* @__PURE__ */
|
|
12500
|
-
|
|
12717
|
+
/* @__PURE__ */ jsx10(
|
|
12718
|
+
InputField21,
|
|
12501
12719
|
{
|
|
12720
|
+
variant: "select",
|
|
12502
12721
|
value: ratePolicy.kind,
|
|
12503
|
-
onChange: (
|
|
12504
|
-
const kind =
|
|
12722
|
+
onChange: ({ value }) => {
|
|
12723
|
+
const kind = value;
|
|
12505
12724
|
if (kind === "eq_primary") {
|
|
12506
12725
|
setRatePolicy({ kind: "eq_primary" });
|
|
12507
12726
|
return;
|
|
@@ -12526,30 +12745,39 @@ function FallbackSettingsPanel() {
|
|
|
12526
12745
|
pct: currentPct
|
|
12527
12746
|
});
|
|
12528
12747
|
},
|
|
12529
|
-
|
|
12530
|
-
|
|
12531
|
-
|
|
12532
|
-
|
|
12533
|
-
|
|
12534
|
-
|
|
12535
|
-
|
|
12748
|
+
options: [
|
|
12749
|
+
{ value: "eq_primary", label: "eq_primary" },
|
|
12750
|
+
{
|
|
12751
|
+
value: "lte_primary",
|
|
12752
|
+
label: "lte_primary"
|
|
12753
|
+
},
|
|
12754
|
+
{ value: "within_pct", label: "within_pct" },
|
|
12755
|
+
{
|
|
12756
|
+
value: "at_least_pct_lower",
|
|
12757
|
+
label: "at_least_pct_lower"
|
|
12758
|
+
}
|
|
12759
|
+
],
|
|
12760
|
+
clearable: false
|
|
12536
12761
|
}
|
|
12537
12762
|
),
|
|
12538
12763
|
ratePolicy.kind !== "eq_primary" && /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
|
|
12539
|
-
/* @__PURE__ */ jsx10(
|
|
12540
|
-
|
|
12764
|
+
/* @__PURE__ */ jsx10("div", { className: "w-32", children: /* @__PURE__ */ jsx10(
|
|
12765
|
+
InputField21,
|
|
12541
12766
|
{
|
|
12542
|
-
|
|
12543
|
-
min: 0,
|
|
12544
|
-
step: "0.01",
|
|
12767
|
+
variant: "number",
|
|
12545
12768
|
value: ratePolicy.pct,
|
|
12546
|
-
onChange: (
|
|
12547
|
-
const pct = Number(
|
|
12548
|
-
setRatePolicy({
|
|
12769
|
+
onChange: ({ value }) => {
|
|
12770
|
+
const pct = typeof value === "number" ? value : Number(value != null ? value : 0);
|
|
12771
|
+
setRatePolicy({
|
|
12772
|
+
...ratePolicy,
|
|
12773
|
+
pct
|
|
12774
|
+
});
|
|
12549
12775
|
},
|
|
12550
|
-
|
|
12776
|
+
min: 0,
|
|
12777
|
+
step: 0.01,
|
|
12778
|
+
fullWidth: true
|
|
12551
12779
|
}
|
|
12552
|
-
),
|
|
12780
|
+
) }),
|
|
12553
12781
|
/* @__PURE__ */ jsx10("span", { className: "text-sm text-zinc-500 dark:text-zinc-400", children: "%" })
|
|
12554
12782
|
] })
|
|
12555
12783
|
] })
|
|
@@ -12560,19 +12788,20 @@ function FallbackSettingsPanel() {
|
|
|
12560
12788
|
{
|
|
12561
12789
|
title: "Selection strategy",
|
|
12562
12790
|
hint: "How valid fallback candidates are ordered in previews.",
|
|
12563
|
-
children: /* @__PURE__ */
|
|
12564
|
-
|
|
12791
|
+
children: /* @__PURE__ */ jsx10(
|
|
12792
|
+
InputField21,
|
|
12565
12793
|
{
|
|
12794
|
+
variant: "select",
|
|
12566
12795
|
value: (_b = draft.selectionStrategy) != null ? _b : "priority",
|
|
12567
|
-
onChange: (
|
|
12796
|
+
onChange: ({ value }) => setDraft((prev) => ({
|
|
12568
12797
|
...prev,
|
|
12569
|
-
selectionStrategy:
|
|
12798
|
+
selectionStrategy: value
|
|
12570
12799
|
})),
|
|
12571
|
-
|
|
12572
|
-
|
|
12573
|
-
|
|
12574
|
-
|
|
12575
|
-
|
|
12800
|
+
options: [
|
|
12801
|
+
{ value: "priority", label: "priority" },
|
|
12802
|
+
{ value: "cheapest", label: "cheapest" }
|
|
12803
|
+
],
|
|
12804
|
+
clearable: false
|
|
12576
12805
|
}
|
|
12577
12806
|
)
|
|
12578
12807
|
}
|
|
@@ -12582,19 +12811,20 @@ function FallbackSettingsPanel() {
|
|
|
12582
12811
|
{
|
|
12583
12812
|
title: "Mode",
|
|
12584
12813
|
hint: "Use strict for enforced filtering, dev for advisory feedback.",
|
|
12585
|
-
children: /* @__PURE__ */
|
|
12586
|
-
|
|
12814
|
+
children: /* @__PURE__ */ jsx10(
|
|
12815
|
+
InputField21,
|
|
12587
12816
|
{
|
|
12817
|
+
variant: "select",
|
|
12588
12818
|
value: (_c = draft.mode) != null ? _c : "strict",
|
|
12589
|
-
onChange: (
|
|
12819
|
+
onChange: ({ value }) => setDraft((prev) => ({
|
|
12590
12820
|
...prev,
|
|
12591
|
-
mode:
|
|
12821
|
+
mode: value
|
|
12592
12822
|
})),
|
|
12593
|
-
|
|
12594
|
-
|
|
12595
|
-
|
|
12596
|
-
|
|
12597
|
-
|
|
12823
|
+
options: [
|
|
12824
|
+
{ value: "strict", label: "strict" },
|
|
12825
|
+
{ value: "dev", label: "dev" }
|
|
12826
|
+
],
|
|
12827
|
+
clearable: false
|
|
12598
12828
|
}
|
|
12599
12829
|
)
|
|
12600
12830
|
}
|
|
@@ -12620,6 +12850,8 @@ function SettingRow({
|
|
|
12620
12850
|
|
|
12621
12851
|
// src/react/fallback-editor/FallbackServiceSidebar.tsx
|
|
12622
12852
|
import { useMemo as useMemo7, useState as useState4 } from "react";
|
|
12853
|
+
import { InputField as InputField22 } from "@timeax/form-palette";
|
|
12854
|
+
import { Search } from "lucide-react";
|
|
12623
12855
|
import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
12624
12856
|
function FallbackServiceSidebar() {
|
|
12625
12857
|
const { activeServiceId, setActiveServiceId, get } = useFallbackEditor();
|
|
@@ -12635,22 +12867,26 @@ function FallbackServiceSidebar() {
|
|
|
12635
12867
|
}
|
|
12636
12868
|
);
|
|
12637
12869
|
}, [query, services]);
|
|
12638
|
-
return /* @__PURE__ */ jsxs7("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: [
|
|
12870
|
+
return /* @__PURE__ */ jsxs7("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: [
|
|
12639
12871
|
/* @__PURE__ */ jsxs7("div", { className: "border-b border-zinc-200 p-4 dark:border-zinc-800", children: [
|
|
12640
12872
|
/* @__PURE__ */ jsx11("h2", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: "Primary services" }),
|
|
12641
12873
|
/* @__PURE__ */ jsx11("p", { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400", children: "Services currently active in the builder/runtime context." })
|
|
12642
12874
|
] }),
|
|
12643
12875
|
/* @__PURE__ */ jsxs7("div", { className: "flex min-h-0 flex-1 flex-col p-4", children: [
|
|
12644
|
-
/* @__PURE__ */ jsx11(
|
|
12645
|
-
|
|
12876
|
+
/* @__PURE__ */ jsx11("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__ */ jsx11(
|
|
12877
|
+
InputField22,
|
|
12646
12878
|
{
|
|
12879
|
+
variant: "text",
|
|
12647
12880
|
value: query,
|
|
12648
|
-
onChange: (
|
|
12881
|
+
onChange: ({ value }) => setQuery(String(value != null ? value : "")),
|
|
12649
12882
|
placeholder: "Search primary service...",
|
|
12650
|
-
|
|
12883
|
+
leadingControl: /* @__PURE__ */ jsx11(Search, { className: "h-4 w-4 text-zinc-400" }),
|
|
12884
|
+
joinControls: true,
|
|
12885
|
+
extendBoxToControls: true,
|
|
12886
|
+
fullWidth: true
|
|
12651
12887
|
}
|
|
12652
|
-
),
|
|
12653
|
-
/* @__PURE__ */ jsx11("div", { className: "mt-3 flex-1 space-y-2 overflow-auto", children: filtered.map((service) => {
|
|
12888
|
+
) }),
|
|
12889
|
+
/* @__PURE__ */ jsx11("div", { className: "mt-3 flex-1 space-y-2 overflow-y-auto", children: filtered.map((service) => {
|
|
12654
12890
|
var _a, _b;
|
|
12655
12891
|
const active = String(service.id) === String(activeServiceId);
|
|
12656
12892
|
const count = get(service.id).length;
|
|
@@ -12661,7 +12897,7 @@ function FallbackServiceSidebar() {
|
|
|
12661
12897
|
onClick: () => setActiveServiceId(service.id),
|
|
12662
12898
|
className: [
|
|
12663
12899
|
"w-full rounded-2xl border p-3 text-left transition",
|
|
12664
|
-
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"
|
|
12900
|
+
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"
|
|
12665
12901
|
].join(" "),
|
|
12666
12902
|
children: /* @__PURE__ */ jsxs7("div", { className: "flex items-start justify-between gap-3", children: [
|
|
12667
12903
|
/* @__PURE__ */ jsxs7("div", { className: "min-w-0", children: [
|
|
@@ -12691,11 +12927,174 @@ function FallbackServiceSidebar() {
|
|
|
12691
12927
|
}
|
|
12692
12928
|
|
|
12693
12929
|
// src/react/fallback-editor/FallbackRegistrationsPanel.tsx
|
|
12694
|
-
import
|
|
12930
|
+
import React11 from "react";
|
|
12931
|
+
import { Fragment, jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
12932
|
+
function FallbackRegistrationsPanel() {
|
|
12933
|
+
const { activeServiceId, remove: remove2, clear, check } = useFallbackEditor();
|
|
12934
|
+
const registrations = useActiveFallbackRegistrations();
|
|
12935
|
+
const eligibleServices = useEligibleServiceList();
|
|
12936
|
+
const [candidatePickerOpen, setCandidatePickerOpen] = React11.useState(false);
|
|
12937
|
+
const [candidateContext, setCandidateContext] = React11.useState(null);
|
|
12938
|
+
const [candidatePrimaryId, setCandidatePrimaryId] = React11.useState(void 0);
|
|
12939
|
+
const [registrationDialogOpen, setRegistrationDialogOpen] = React11.useState(false);
|
|
12940
|
+
const makeContext = React11.useCallback(
|
|
12941
|
+
(registration) => {
|
|
12942
|
+
if (registration.scope === "global") {
|
|
12943
|
+
return {
|
|
12944
|
+
scope: "global",
|
|
12945
|
+
primary: registration.primary
|
|
12946
|
+
};
|
|
12947
|
+
}
|
|
12948
|
+
return {
|
|
12949
|
+
scope: "node",
|
|
12950
|
+
nodeId: registration.scopeId
|
|
12951
|
+
};
|
|
12952
|
+
},
|
|
12953
|
+
[]
|
|
12954
|
+
);
|
|
12955
|
+
const openCandidatePicker = React11.useCallback(
|
|
12956
|
+
(context, primaryId) => {
|
|
12957
|
+
setCandidateContext(context);
|
|
12958
|
+
setCandidatePrimaryId(primaryId);
|
|
12959
|
+
setCandidatePickerOpen(true);
|
|
12960
|
+
},
|
|
12961
|
+
[]
|
|
12962
|
+
);
|
|
12963
|
+
if (activeServiceId === void 0 || activeServiceId === null) {
|
|
12964
|
+
return /* @__PURE__ */ jsx12("section", { className: "rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900 ", children: /* @__PURE__ */ jsx12("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." }) });
|
|
12965
|
+
}
|
|
12966
|
+
return /* @__PURE__ */ jsxs8(Fragment, { children: [
|
|
12967
|
+
/* @__PURE__ */ jsxs8("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: [
|
|
12968
|
+
/* @__PURE__ */ jsxs8("div", { className: "mb-4 flex items-start justify-between gap-3", children: [
|
|
12969
|
+
/* @__PURE__ */ jsxs8("div", { children: [
|
|
12970
|
+
/* @__PURE__ */ jsx12("h3", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: "Registered fallbacks" }),
|
|
12971
|
+
/* @__PURE__ */ jsx12("p", { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400", children: "Use eligible services as fallback candidates for the selected primary." })
|
|
12972
|
+
] }),
|
|
12973
|
+
/* @__PURE__ */ jsx12(
|
|
12974
|
+
"button",
|
|
12975
|
+
{
|
|
12976
|
+
type: "button",
|
|
12977
|
+
onClick: () => setRegistrationDialogOpen(true),
|
|
12978
|
+
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",
|
|
12979
|
+
children: "Add registration"
|
|
12980
|
+
}
|
|
12981
|
+
)
|
|
12982
|
+
] }),
|
|
12983
|
+
/* @__PURE__ */ jsx12("div", { className: "space-y-4", children: registrations.length === 0 ? /* @__PURE__ */ jsx12("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) => {
|
|
12984
|
+
var _a;
|
|
12985
|
+
const context = makeContext(reg);
|
|
12986
|
+
const candidates = reg.services;
|
|
12987
|
+
return /* @__PURE__ */ jsxs8(
|
|
12988
|
+
"div",
|
|
12989
|
+
{
|
|
12990
|
+
className: "rounded-2xl border border-zinc-200 bg-zinc-50 p-4 dark:border-zinc-800 dark:bg-zinc-950",
|
|
12991
|
+
children: [
|
|
12992
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [
|
|
12993
|
+
/* @__PURE__ */ jsxs8("div", { children: [
|
|
12994
|
+
/* @__PURE__ */ jsx12("div", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: reg.scope === "global" ? "Global registration" : `Node \xB7 ${reg.scopeId}` }),
|
|
12995
|
+
/* @__PURE__ */ jsxs8("div", { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400", children: [
|
|
12996
|
+
"Primary #",
|
|
12997
|
+
String(reg.primary)
|
|
12998
|
+
] })
|
|
12999
|
+
] }),
|
|
13000
|
+
/* @__PURE__ */ jsxs8("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: [
|
|
13001
|
+
reg.scope,
|
|
13002
|
+
reg.scopeId ? ` \xB7 ${reg.scopeId}` : ""
|
|
13003
|
+
] })
|
|
13004
|
+
] }),
|
|
13005
|
+
/* @__PURE__ */ jsx12("div", { className: "mt-4 flex flex-wrap gap-2", children: candidates.length === 0 ? /* @__PURE__ */ jsx12("span", { className: "text-xs text-zinc-500 dark:text-zinc-400", children: "No fallback services yet." }) : candidates.map((candidate) => {
|
|
13006
|
+
var _a2;
|
|
13007
|
+
const preview = check(context, [
|
|
13008
|
+
candidate
|
|
13009
|
+
]);
|
|
13010
|
+
const rejected = preview.rejected[0];
|
|
13011
|
+
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";
|
|
13012
|
+
const service = eligibleServices.find(
|
|
13013
|
+
(s) => String(s.id) === String(candidate)
|
|
13014
|
+
);
|
|
13015
|
+
return /* @__PURE__ */ jsxs8(
|
|
13016
|
+
"div",
|
|
13017
|
+
{
|
|
13018
|
+
className: `inline-flex items-center gap-2 rounded-xl border px-3 py-2 text-xs ${tone}`,
|
|
13019
|
+
children: [
|
|
13020
|
+
/* @__PURE__ */ jsx12("span", { children: service ? `#${String(service.id)} \xB7 ${(_a2 = service.name) != null ? _a2 : "Unnamed"}` : `#${String(candidate)}` }),
|
|
13021
|
+
rejected ? /* @__PURE__ */ jsx12("span", { className: "rounded-full border border-current/20 px-2 py-0.5 text-[10px]", children: rejected.reasons.join(
|
|
13022
|
+
", "
|
|
13023
|
+
) }) : /* @__PURE__ */ jsx12("span", { className: "rounded-full border border-current/20 px-2 py-0.5 text-[10px]", children: "valid" }),
|
|
13024
|
+
/* @__PURE__ */ jsx12(
|
|
13025
|
+
"button",
|
|
13026
|
+
{
|
|
13027
|
+
type: "button",
|
|
13028
|
+
onClick: () => remove2(
|
|
13029
|
+
context,
|
|
13030
|
+
candidate
|
|
13031
|
+
),
|
|
13032
|
+
className: "text-current/70 hover:text-current",
|
|
13033
|
+
children: "\xD7"
|
|
13034
|
+
}
|
|
13035
|
+
)
|
|
13036
|
+
]
|
|
13037
|
+
},
|
|
13038
|
+
String(candidate)
|
|
13039
|
+
);
|
|
13040
|
+
}) }),
|
|
13041
|
+
/* @__PURE__ */ jsxs8("div", { className: "mt-4 flex gap-2", children: [
|
|
13042
|
+
/* @__PURE__ */ jsx12(
|
|
13043
|
+
"button",
|
|
13044
|
+
{
|
|
13045
|
+
type: "button",
|
|
13046
|
+
onClick: () => openCandidatePicker(
|
|
13047
|
+
context,
|
|
13048
|
+
reg.primary
|
|
13049
|
+
),
|
|
13050
|
+
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",
|
|
13051
|
+
children: "Add fallback"
|
|
13052
|
+
}
|
|
13053
|
+
),
|
|
13054
|
+
/* @__PURE__ */ jsx12(
|
|
13055
|
+
"button",
|
|
13056
|
+
{
|
|
13057
|
+
type: "button",
|
|
13058
|
+
onClick: () => clear(context),
|
|
13059
|
+
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",
|
|
13060
|
+
children: "Clear"
|
|
13061
|
+
}
|
|
13062
|
+
)
|
|
13063
|
+
] })
|
|
13064
|
+
]
|
|
13065
|
+
},
|
|
13066
|
+
`${reg.scope}:${String((_a = reg.scopeId) != null ? _a : "global")}:${index}`
|
|
13067
|
+
);
|
|
13068
|
+
}) })
|
|
13069
|
+
] }),
|
|
13070
|
+
/* @__PURE__ */ jsx12(
|
|
13071
|
+
FallbackAddRegistrationDialog,
|
|
13072
|
+
{
|
|
13073
|
+
open: registrationDialogOpen,
|
|
13074
|
+
onClose: () => setRegistrationDialogOpen(false),
|
|
13075
|
+
onSelect: (context, primaryId) => {
|
|
13076
|
+
setRegistrationDialogOpen(false);
|
|
13077
|
+
openCandidatePicker(context, primaryId);
|
|
13078
|
+
}
|
|
13079
|
+
}
|
|
13080
|
+
),
|
|
13081
|
+
/* @__PURE__ */ jsx12(
|
|
13082
|
+
FallbackAddCandidatesDialog,
|
|
13083
|
+
{
|
|
13084
|
+
open: candidatePickerOpen,
|
|
13085
|
+
onClose: () => setCandidatePickerOpen(false),
|
|
13086
|
+
context: candidateContext,
|
|
13087
|
+
primaryId: candidatePrimaryId
|
|
13088
|
+
}
|
|
13089
|
+
)
|
|
13090
|
+
] });
|
|
13091
|
+
}
|
|
12695
13092
|
|
|
12696
13093
|
// src/react/fallback-editor/FallbackAddCandidatesDialog.tsx
|
|
12697
|
-
import
|
|
12698
|
-
import {
|
|
13094
|
+
import React12 from "react";
|
|
13095
|
+
import { InputField as InputField23 } from "@timeax/form-palette";
|
|
13096
|
+
import { Search as Search2 } from "lucide-react";
|
|
13097
|
+
import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
12699
13098
|
function FallbackAddCandidatesDialog({
|
|
12700
13099
|
open,
|
|
12701
13100
|
onClose,
|
|
@@ -12704,23 +13103,23 @@ function FallbackAddCandidatesDialog({
|
|
|
12704
13103
|
}) {
|
|
12705
13104
|
const { eligible, addMany } = useFallbackEditor();
|
|
12706
13105
|
const eligibleServices = useEligibleServiceList();
|
|
12707
|
-
const [query, setQuery] =
|
|
12708
|
-
const [filterEligibleOnly, setFilterEligibleOnly] =
|
|
12709
|
-
const [selected, setSelected] =
|
|
12710
|
-
const [submitting, setSubmitting] =
|
|
12711
|
-
|
|
13106
|
+
const [query, setQuery] = React12.useState("");
|
|
13107
|
+
const [filterEligibleOnly, setFilterEligibleOnly] = React12.useState(true);
|
|
13108
|
+
const [selected, setSelected] = React12.useState(/* @__PURE__ */ new Set());
|
|
13109
|
+
const [submitting, setSubmitting] = React12.useState(false);
|
|
13110
|
+
React12.useEffect(() => {
|
|
12712
13111
|
if (!open) {
|
|
12713
13112
|
setQuery("");
|
|
12714
13113
|
setFilterEligibleOnly(true);
|
|
12715
13114
|
setSelected(/* @__PURE__ */ new Set());
|
|
12716
13115
|
}
|
|
12717
13116
|
}, [open]);
|
|
12718
|
-
const allowedIds =
|
|
13117
|
+
const allowedIds = React12.useMemo(() => {
|
|
12719
13118
|
if (!context) return null;
|
|
12720
13119
|
if (!filterEligibleOnly) return null;
|
|
12721
13120
|
return new Set(eligible(context).map((id) => String(id)));
|
|
12722
13121
|
}, [context, filterEligibleOnly, eligible]);
|
|
12723
|
-
const items =
|
|
13122
|
+
const items = React12.useMemo(() => {
|
|
12724
13123
|
const q = query.trim().toLowerCase();
|
|
12725
13124
|
return eligibleServices.filter((service) => {
|
|
12726
13125
|
var _a, _b;
|
|
@@ -12755,34 +13154,37 @@ function FallbackAddCandidatesDialog({
|
|
|
12755
13154
|
}
|
|
12756
13155
|
}
|
|
12757
13156
|
if (!open || !context) return null;
|
|
12758
|
-
return /* @__PURE__ */
|
|
12759
|
-
/* @__PURE__ */
|
|
12760
|
-
/* @__PURE__ */
|
|
12761
|
-
/* @__PURE__ */
|
|
13157
|
+
return /* @__PURE__ */ jsx13("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4", children: /* @__PURE__ */ jsxs9("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: [
|
|
13158
|
+
/* @__PURE__ */ jsxs9("div", { className: "border-b border-zinc-200 p-4 dark:border-zinc-800", children: [
|
|
13159
|
+
/* @__PURE__ */ jsx13("h3", { className: "text-base font-semibold text-zinc-900 dark:text-zinc-100", children: "Add fallback services" }),
|
|
13160
|
+
/* @__PURE__ */ jsx13("p", { className: "mt-1 text-sm text-zinc-500 dark:text-zinc-400", children: "Search and select one or more eligible fallback candidates." })
|
|
12762
13161
|
] }),
|
|
12763
|
-
/* @__PURE__ */
|
|
12764
|
-
/* @__PURE__ */
|
|
12765
|
-
|
|
13162
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex flex-col gap-3 p-4", children: [
|
|
13163
|
+
/* @__PURE__ */ jsx13(
|
|
13164
|
+
InputField23,
|
|
12766
13165
|
{
|
|
13166
|
+
variant: "text",
|
|
12767
13167
|
value: query,
|
|
12768
|
-
onChange: (
|
|
13168
|
+
onChange: ({ value }) => setQuery(String(value != null ? value : "")),
|
|
12769
13169
|
placeholder: "Search eligible services...",
|
|
12770
|
-
|
|
13170
|
+
leadingControl: /* @__PURE__ */ jsx13(Search2, { className: "h-4 w-4 text-zinc-400" }),
|
|
13171
|
+
joinControls: true,
|
|
13172
|
+
extendBoxToControls: true,
|
|
13173
|
+
fullWidth: true
|
|
12771
13174
|
}
|
|
12772
13175
|
),
|
|
12773
|
-
/* @__PURE__ */
|
|
12774
|
-
|
|
12775
|
-
|
|
12776
|
-
|
|
12777
|
-
|
|
12778
|
-
|
|
12779
|
-
|
|
12780
|
-
|
|
12781
|
-
|
|
12782
|
-
|
|
12783
|
-
|
|
12784
|
-
|
|
12785
|
-
/* @__PURE__ */ jsx12(
|
|
13176
|
+
/* @__PURE__ */ jsx13(
|
|
13177
|
+
InputField23,
|
|
13178
|
+
{
|
|
13179
|
+
variant: "toggle",
|
|
13180
|
+
value: filterEligibleOnly,
|
|
13181
|
+
onChange: ({ value }) => setFilterEligibleOnly(Boolean(value)),
|
|
13182
|
+
label: "Filter eligible only",
|
|
13183
|
+
onText: "On",
|
|
13184
|
+
offText: "Off"
|
|
13185
|
+
}
|
|
13186
|
+
),
|
|
13187
|
+
/* @__PURE__ */ jsx13(
|
|
12786
13188
|
VirtualServiceList,
|
|
12787
13189
|
{
|
|
12788
13190
|
items,
|
|
@@ -12792,28 +13194,28 @@ function FallbackAddCandidatesDialog({
|
|
|
12792
13194
|
}
|
|
12793
13195
|
)
|
|
12794
13196
|
] }),
|
|
12795
|
-
/* @__PURE__ */
|
|
12796
|
-
/* @__PURE__ */
|
|
13197
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between border-t border-zinc-200 p-4 dark:border-zinc-800", children: [
|
|
13198
|
+
/* @__PURE__ */ jsxs9("div", { className: "text-sm text-zinc-500 dark:text-zinc-400", children: [
|
|
12797
13199
|
selected.size,
|
|
12798
13200
|
" selected"
|
|
12799
13201
|
] }),
|
|
12800
|
-
/* @__PURE__ */
|
|
12801
|
-
/* @__PURE__ */
|
|
13202
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex gap-2", children: [
|
|
13203
|
+
/* @__PURE__ */ jsx13(
|
|
12802
13204
|
"button",
|
|
12803
13205
|
{
|
|
12804
13206
|
type: "button",
|
|
12805
13207
|
onClick: onClose,
|
|
12806
|
-
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",
|
|
13208
|
+
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",
|
|
12807
13209
|
children: "Cancel"
|
|
12808
13210
|
}
|
|
12809
13211
|
),
|
|
12810
|
-
/* @__PURE__ */
|
|
13212
|
+
/* @__PURE__ */ jsx13(
|
|
12811
13213
|
"button",
|
|
12812
13214
|
{
|
|
12813
13215
|
type: "button",
|
|
12814
13216
|
onClick: handleAdd,
|
|
12815
13217
|
disabled: selected.size === 0 || submitting,
|
|
12816
|
-
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",
|
|
13218
|
+
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",
|
|
12817
13219
|
children: submitting ? "Adding..." : "Add selected"
|
|
12818
13220
|
}
|
|
12819
13221
|
)
|
|
@@ -12823,8 +13225,9 @@ function FallbackAddCandidatesDialog({
|
|
|
12823
13225
|
}
|
|
12824
13226
|
|
|
12825
13227
|
// src/react/fallback-editor/FallbackAddRegistrationDialog.tsx
|
|
12826
|
-
import
|
|
12827
|
-
import {
|
|
13228
|
+
import React13 from "react";
|
|
13229
|
+
import { InputField as InputField24 } from "@timeax/form-palette";
|
|
13230
|
+
import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
12828
13231
|
function FallbackAddRegistrationDialog({
|
|
12829
13232
|
open,
|
|
12830
13233
|
onClose,
|
|
@@ -12832,23 +13235,23 @@ function FallbackAddRegistrationDialog({
|
|
|
12832
13235
|
}) {
|
|
12833
13236
|
const { activeServiceId, serviceProps, snapshot } = useFallbackEditor();
|
|
12834
13237
|
const registrations = useActiveFallbackRegistrations();
|
|
12835
|
-
const [scope, setScope] =
|
|
12836
|
-
const [nodeId, setNodeId] =
|
|
12837
|
-
const mode =
|
|
13238
|
+
const [scope, setScope] = React13.useState("global");
|
|
13239
|
+
const [nodeId, setNodeId] = React13.useState("");
|
|
13240
|
+
const mode = React13.useMemo(() => {
|
|
12838
13241
|
if (snapshot) return "snapshot";
|
|
12839
13242
|
if (serviceProps) return "props";
|
|
12840
13243
|
return "none";
|
|
12841
13244
|
}, [snapshot, serviceProps]);
|
|
12842
|
-
|
|
13245
|
+
React13.useEffect(() => {
|
|
12843
13246
|
if (open) {
|
|
12844
13247
|
setScope("global");
|
|
12845
13248
|
setNodeId("");
|
|
12846
13249
|
}
|
|
12847
13250
|
}, [open]);
|
|
12848
|
-
const hasGlobal =
|
|
13251
|
+
const hasGlobal = React13.useMemo(() => {
|
|
12849
13252
|
return registrations.some((r) => r.scope === "global");
|
|
12850
13253
|
}, [registrations]);
|
|
12851
|
-
const nodeTargets =
|
|
13254
|
+
const nodeTargets = React13.useMemo(() => {
|
|
12852
13255
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
|
|
12853
13256
|
if (activeServiceId === void 0 || activeServiceId === null) {
|
|
12854
13257
|
return [];
|
|
@@ -12938,12 +13341,12 @@ function FallbackAddRegistrationDialog({
|
|
|
12938
13341
|
}
|
|
12939
13342
|
return [];
|
|
12940
13343
|
}, [mode, snapshot, serviceProps, activeServiceId]);
|
|
12941
|
-
|
|
13344
|
+
React13.useEffect(() => {
|
|
12942
13345
|
if (hasGlobal && scope === "global") {
|
|
12943
13346
|
setScope("node");
|
|
12944
13347
|
}
|
|
12945
13348
|
}, [hasGlobal, scope]);
|
|
12946
|
-
|
|
13349
|
+
React13.useEffect(() => {
|
|
12947
13350
|
if (scope === "node" && nodeId) {
|
|
12948
13351
|
const exists = nodeTargets.some((node) => node.id === nodeId);
|
|
12949
13352
|
if (!exists) setNodeId("");
|
|
@@ -12974,100 +13377,74 @@ function FallbackAddRegistrationDialog({
|
|
|
12974
13377
|
}
|
|
12975
13378
|
if (!open) return null;
|
|
12976
13379
|
const nodeScopeDisabled = nodeTargets.length === 0;
|
|
12977
|
-
return /* @__PURE__ */
|
|
12978
|
-
/* @__PURE__ */
|
|
12979
|
-
/* @__PURE__ */
|
|
12980
|
-
/* @__PURE__ */
|
|
13380
|
+
return /* @__PURE__ */ jsx14("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/60 p-4", children: /* @__PURE__ */ jsxs10("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: [
|
|
13381
|
+
/* @__PURE__ */ jsxs10("div", { className: "border-b border-zinc-200 p-4 dark:border-zinc-800", children: [
|
|
13382
|
+
/* @__PURE__ */ jsx14("h3", { className: "text-base font-semibold text-zinc-900 dark:text-zinc-100", children: "Add registration" }),
|
|
13383
|
+
/* @__PURE__ */ jsx14("p", { className: "mt-1 text-sm text-zinc-500 dark:text-zinc-400", children: "Choose the registration scope before selecting fallback candidates." })
|
|
12981
13384
|
] }),
|
|
12982
|
-
/* @__PURE__ */
|
|
12983
|
-
/* @__PURE__ */
|
|
12984
|
-
/* @__PURE__ */
|
|
12985
|
-
/* @__PURE__ */
|
|
12986
|
-
|
|
12987
|
-
|
|
12988
|
-
|
|
13385
|
+
/* @__PURE__ */ jsxs10("div", { className: "space-y-4 p-4", children: [
|
|
13386
|
+
/* @__PURE__ */ jsxs10("div", { className: "space-y-2", children: [
|
|
13387
|
+
/* @__PURE__ */ jsx14("div", { className: "text-sm font-medium text-zinc-900 dark:text-zinc-100", children: "Scope" }),
|
|
13388
|
+
/* @__PURE__ */ jsx14(
|
|
13389
|
+
InputField24,
|
|
13390
|
+
{
|
|
13391
|
+
variant: "radio",
|
|
13392
|
+
value: scope,
|
|
13393
|
+
onChange: ({ value }) => setScope(value),
|
|
13394
|
+
options: [
|
|
13395
|
+
...!hasGlobal ? [
|
|
13396
|
+
{
|
|
13397
|
+
value: "global",
|
|
13398
|
+
label: "Global"
|
|
13399
|
+
}
|
|
13400
|
+
] : [],
|
|
12989
13401
|
{
|
|
12990
|
-
|
|
12991
|
-
|
|
12992
|
-
checked: scope === "global",
|
|
12993
|
-
onChange: () => setScope("global"),
|
|
12994
|
-
className: "mt-1 h-4 w-4"
|
|
13402
|
+
value: "node",
|
|
13403
|
+
label: nodeScopeDisabled ? "Node (Unavailable)" : "Node"
|
|
12995
13404
|
}
|
|
12996
|
-
|
|
12997
|
-
|
|
12998
|
-
|
|
12999
|
-
|
|
13000
|
-
] })
|
|
13001
|
-
] }),
|
|
13002
|
-
/* @__PURE__ */ jsxs9(
|
|
13003
|
-
"label",
|
|
13004
|
-
{
|
|
13005
|
-
className: [
|
|
13006
|
-
"flex items-start gap-3 rounded-xl border p-3",
|
|
13007
|
-
nodeScopeDisabled ? "cursor-not-allowed border-zinc-200 opacity-60 dark:border-zinc-800" : "cursor-pointer border-zinc-200 dark:border-zinc-800"
|
|
13008
|
-
].join(" "),
|
|
13009
|
-
children: [
|
|
13010
|
-
/* @__PURE__ */ jsx13(
|
|
13011
|
-
"input",
|
|
13012
|
-
{
|
|
13013
|
-
type: "radio",
|
|
13014
|
-
name: "scope",
|
|
13015
|
-
checked: scope === "node",
|
|
13016
|
-
onChange: () => setScope("node"),
|
|
13017
|
-
disabled: nodeScopeDisabled,
|
|
13018
|
-
className: "mt-1 h-4 w-4"
|
|
13019
|
-
}
|
|
13020
|
-
),
|
|
13021
|
-
/* @__PURE__ */ jsxs9("div", { children: [
|
|
13022
|
-
/* @__PURE__ */ jsx13("div", { className: "text-sm font-medium text-zinc-900 dark:text-zinc-100", children: "Node" }),
|
|
13023
|
-
/* @__PURE__ */ jsx13("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." })
|
|
13024
|
-
] })
|
|
13025
|
-
]
|
|
13026
|
-
}
|
|
13027
|
-
)
|
|
13028
|
-
] })
|
|
13405
|
+
]
|
|
13406
|
+
}
|
|
13407
|
+
),
|
|
13408
|
+
/* @__PURE__ */ jsx14("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." })
|
|
13029
13409
|
] }),
|
|
13030
|
-
scope === "node" && /* @__PURE__ */
|
|
13031
|
-
/* @__PURE__ */
|
|
13032
|
-
/* @__PURE__ */
|
|
13033
|
-
|
|
13410
|
+
scope === "node" && /* @__PURE__ */ jsxs10("div", { className: "space-y-2", children: [
|
|
13411
|
+
/* @__PURE__ */ jsx14("div", { className: "text-sm font-medium text-zinc-900 dark:text-zinc-100", children: "Node id" }),
|
|
13412
|
+
/* @__PURE__ */ jsx14(
|
|
13413
|
+
InputField24,
|
|
13034
13414
|
{
|
|
13035
|
-
|
|
13036
|
-
|
|
13037
|
-
|
|
13038
|
-
|
|
13039
|
-
|
|
13040
|
-
|
|
13041
|
-
|
|
13042
|
-
|
|
13043
|
-
|
|
13044
|
-
|
|
13045
|
-
|
|
13046
|
-
String(node.serviceId)
|
|
13047
|
-
] }, node.id))
|
|
13048
|
-
]
|
|
13415
|
+
variant: "select",
|
|
13416
|
+
value: nodeId || void 0,
|
|
13417
|
+
onChange: ({ value }) => setNodeId(String(value != null ? value : "")),
|
|
13418
|
+
options: nodeTargets.map((node) => ({
|
|
13419
|
+
value: node.id,
|
|
13420
|
+
label: `[${node.kind}] ${node.label} \xB7 #${String(node.serviceId)}`
|
|
13421
|
+
})),
|
|
13422
|
+
placeholder: "Select node...",
|
|
13423
|
+
searchable: true,
|
|
13424
|
+
clearable: false,
|
|
13425
|
+
fullWidth: true
|
|
13049
13426
|
}
|
|
13050
13427
|
),
|
|
13051
|
-
nodeScopeDisabled ? /* @__PURE__ */
|
|
13428
|
+
nodeScopeDisabled ? /* @__PURE__ */ jsx14("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
|
|
13052
13429
|
] })
|
|
13053
13430
|
] }),
|
|
13054
|
-
/* @__PURE__ */
|
|
13055
|
-
/* @__PURE__ */
|
|
13431
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-end gap-2 border-t border-zinc-200 p-4 dark:border-zinc-800", children: [
|
|
13432
|
+
/* @__PURE__ */ jsx14(
|
|
13056
13433
|
"button",
|
|
13057
13434
|
{
|
|
13058
13435
|
type: "button",
|
|
13059
13436
|
onClick: onClose,
|
|
13060
|
-
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",
|
|
13437
|
+
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",
|
|
13061
13438
|
children: "Cancel"
|
|
13062
13439
|
}
|
|
13063
13440
|
),
|
|
13064
|
-
/* @__PURE__ */
|
|
13441
|
+
/* @__PURE__ */ jsx14(
|
|
13065
13442
|
"button",
|
|
13066
13443
|
{
|
|
13067
13444
|
type: "button",
|
|
13068
13445
|
onClick: handleContinue,
|
|
13069
13446
|
disabled: activeServiceId === void 0 || scope === "node" && !nodeId,
|
|
13070
|
-
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",
|
|
13447
|
+
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",
|
|
13071
13448
|
children: "Continue"
|
|
13072
13449
|
}
|
|
13073
13450
|
)
|
|
@@ -13104,169 +13481,6 @@ function resolveNodeMeta(props, nodeId) {
|
|
|
13104
13481
|
}
|
|
13105
13482
|
return { kind: "node", label: nodeId };
|
|
13106
13483
|
}
|
|
13107
|
-
|
|
13108
|
-
// src/react/fallback-editor/FallbackRegistrationsPanel.tsx
|
|
13109
|
-
import { Fragment, jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
13110
|
-
function FallbackRegistrationsPanel() {
|
|
13111
|
-
const { activeServiceId, remove: remove2, clear, check } = useFallbackEditor();
|
|
13112
|
-
const registrations = useActiveFallbackRegistrations();
|
|
13113
|
-
const eligibleServices = useEligibleServiceList();
|
|
13114
|
-
const [candidatePickerOpen, setCandidatePickerOpen] = React13.useState(false);
|
|
13115
|
-
const [candidateContext, setCandidateContext] = React13.useState(null);
|
|
13116
|
-
const [candidatePrimaryId, setCandidatePrimaryId] = React13.useState(void 0);
|
|
13117
|
-
const [registrationDialogOpen, setRegistrationDialogOpen] = React13.useState(false);
|
|
13118
|
-
const makeContext = React13.useCallback(
|
|
13119
|
-
(registration) => {
|
|
13120
|
-
if (registration.scope === "global") {
|
|
13121
|
-
return {
|
|
13122
|
-
scope: "global",
|
|
13123
|
-
primary: registration.primary
|
|
13124
|
-
};
|
|
13125
|
-
}
|
|
13126
|
-
return {
|
|
13127
|
-
scope: "node",
|
|
13128
|
-
nodeId: registration.scopeId
|
|
13129
|
-
};
|
|
13130
|
-
},
|
|
13131
|
-
[]
|
|
13132
|
-
);
|
|
13133
|
-
const openCandidatePicker = React13.useCallback(
|
|
13134
|
-
(context, primaryId) => {
|
|
13135
|
-
setCandidateContext(context);
|
|
13136
|
-
setCandidatePrimaryId(primaryId);
|
|
13137
|
-
setCandidatePickerOpen(true);
|
|
13138
|
-
},
|
|
13139
|
-
[]
|
|
13140
|
-
);
|
|
13141
|
-
if (activeServiceId === void 0 || activeServiceId === null) {
|
|
13142
|
-
return /* @__PURE__ */ jsx14("section", { className: "rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900", children: /* @__PURE__ */ jsx14("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." }) });
|
|
13143
|
-
}
|
|
13144
|
-
return /* @__PURE__ */ jsxs10(Fragment, { children: [
|
|
13145
|
-
/* @__PURE__ */ jsxs10("section", { className: "rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-800 dark:bg-zinc-900", children: [
|
|
13146
|
-
/* @__PURE__ */ jsxs10("div", { className: "mb-4 flex items-start justify-between gap-3", children: [
|
|
13147
|
-
/* @__PURE__ */ jsxs10("div", { children: [
|
|
13148
|
-
/* @__PURE__ */ jsx14("h3", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: "Registered fallbacks" }),
|
|
13149
|
-
/* @__PURE__ */ jsx14("p", { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400", children: "Use eligible services as fallback candidates for the selected primary." })
|
|
13150
|
-
] }),
|
|
13151
|
-
/* @__PURE__ */ jsx14(
|
|
13152
|
-
"button",
|
|
13153
|
-
{
|
|
13154
|
-
type: "button",
|
|
13155
|
-
onClick: () => setRegistrationDialogOpen(true),
|
|
13156
|
-
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",
|
|
13157
|
-
children: "Add registration"
|
|
13158
|
-
}
|
|
13159
|
-
)
|
|
13160
|
-
] }),
|
|
13161
|
-
/* @__PURE__ */ jsx14("div", { className: "space-y-4", children: registrations.length === 0 ? /* @__PURE__ */ jsx14("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) => {
|
|
13162
|
-
var _a;
|
|
13163
|
-
const context = makeContext(reg);
|
|
13164
|
-
const candidates = reg.services;
|
|
13165
|
-
return /* @__PURE__ */ jsxs10(
|
|
13166
|
-
"div",
|
|
13167
|
-
{
|
|
13168
|
-
className: "rounded-2xl border border-zinc-200 bg-zinc-50 p-4 dark:border-zinc-800 dark:bg-zinc-950",
|
|
13169
|
-
children: [
|
|
13170
|
-
/* @__PURE__ */ jsxs10("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [
|
|
13171
|
-
/* @__PURE__ */ jsxs10("div", { children: [
|
|
13172
|
-
/* @__PURE__ */ jsx14("div", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: reg.scope === "global" ? "Global registration" : `Node \xB7 ${reg.scopeId}` }),
|
|
13173
|
-
/* @__PURE__ */ jsxs10("div", { className: "mt-1 text-xs text-zinc-500 dark:text-zinc-400", children: [
|
|
13174
|
-
"Primary #",
|
|
13175
|
-
String(reg.primary)
|
|
13176
|
-
] })
|
|
13177
|
-
] }),
|
|
13178
|
-
/* @__PURE__ */ jsxs10("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: [
|
|
13179
|
-
reg.scope,
|
|
13180
|
-
reg.scopeId ? ` \xB7 ${reg.scopeId}` : ""
|
|
13181
|
-
] })
|
|
13182
|
-
] }),
|
|
13183
|
-
/* @__PURE__ */ jsx14("div", { className: "mt-4 flex flex-wrap gap-2", children: candidates.length === 0 ? /* @__PURE__ */ jsx14("span", { className: "text-xs text-zinc-500 dark:text-zinc-400", children: "No fallback services yet." }) : candidates.map((candidate) => {
|
|
13184
|
-
var _a2;
|
|
13185
|
-
const preview = check(context, [
|
|
13186
|
-
candidate
|
|
13187
|
-
]);
|
|
13188
|
-
const rejected = preview.rejected[0];
|
|
13189
|
-
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";
|
|
13190
|
-
const service = eligibleServices.find(
|
|
13191
|
-
(s) => String(s.id) === String(candidate)
|
|
13192
|
-
);
|
|
13193
|
-
return /* @__PURE__ */ jsxs10(
|
|
13194
|
-
"div",
|
|
13195
|
-
{
|
|
13196
|
-
className: `inline-flex items-center gap-2 rounded-xl border px-3 py-2 text-xs ${tone}`,
|
|
13197
|
-
children: [
|
|
13198
|
-
/* @__PURE__ */ jsx14("span", { children: service ? `#${String(service.id)} \xB7 ${(_a2 = service.name) != null ? _a2 : "Unnamed"}` : `#${String(candidate)}` }),
|
|
13199
|
-
rejected ? /* @__PURE__ */ jsx14("span", { className: "rounded-full border border-current/20 px-2 py-0.5 text-[10px]", children: rejected.reasons.join(
|
|
13200
|
-
", "
|
|
13201
|
-
) }) : /* @__PURE__ */ jsx14("span", { className: "rounded-full border border-current/20 px-2 py-0.5 text-[10px]", children: "valid" }),
|
|
13202
|
-
/* @__PURE__ */ jsx14(
|
|
13203
|
-
"button",
|
|
13204
|
-
{
|
|
13205
|
-
type: "button",
|
|
13206
|
-
onClick: () => remove2(
|
|
13207
|
-
context,
|
|
13208
|
-
candidate
|
|
13209
|
-
),
|
|
13210
|
-
className: "text-current/70 hover:text-current",
|
|
13211
|
-
children: "\xD7"
|
|
13212
|
-
}
|
|
13213
|
-
)
|
|
13214
|
-
]
|
|
13215
|
-
},
|
|
13216
|
-
String(candidate)
|
|
13217
|
-
);
|
|
13218
|
-
}) }),
|
|
13219
|
-
/* @__PURE__ */ jsxs10("div", { className: "mt-4 flex gap-2", children: [
|
|
13220
|
-
/* @__PURE__ */ jsx14(
|
|
13221
|
-
"button",
|
|
13222
|
-
{
|
|
13223
|
-
type: "button",
|
|
13224
|
-
onClick: () => openCandidatePicker(
|
|
13225
|
-
context,
|
|
13226
|
-
reg.primary
|
|
13227
|
-
),
|
|
13228
|
-
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",
|
|
13229
|
-
children: "Add fallback"
|
|
13230
|
-
}
|
|
13231
|
-
),
|
|
13232
|
-
/* @__PURE__ */ jsx14(
|
|
13233
|
-
"button",
|
|
13234
|
-
{
|
|
13235
|
-
type: "button",
|
|
13236
|
-
onClick: () => clear(context),
|
|
13237
|
-
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",
|
|
13238
|
-
children: "Clear"
|
|
13239
|
-
}
|
|
13240
|
-
)
|
|
13241
|
-
] })
|
|
13242
|
-
]
|
|
13243
|
-
},
|
|
13244
|
-
`${reg.scope}:${String((_a = reg.scopeId) != null ? _a : "global")}:${index}`
|
|
13245
|
-
);
|
|
13246
|
-
}) })
|
|
13247
|
-
] }),
|
|
13248
|
-
/* @__PURE__ */ jsx14(
|
|
13249
|
-
FallbackAddRegistrationDialog,
|
|
13250
|
-
{
|
|
13251
|
-
open: registrationDialogOpen,
|
|
13252
|
-
onClose: () => setRegistrationDialogOpen(false),
|
|
13253
|
-
onSelect: (context, primaryId) => {
|
|
13254
|
-
setRegistrationDialogOpen(false);
|
|
13255
|
-
openCandidatePicker(context, primaryId);
|
|
13256
|
-
}
|
|
13257
|
-
}
|
|
13258
|
-
),
|
|
13259
|
-
/* @__PURE__ */ jsx14(
|
|
13260
|
-
FallbackAddCandidatesDialog,
|
|
13261
|
-
{
|
|
13262
|
-
open: candidatePickerOpen,
|
|
13263
|
-
onClose: () => setCandidatePickerOpen(false),
|
|
13264
|
-
context: candidateContext,
|
|
13265
|
-
primaryId: candidatePrimaryId
|
|
13266
|
-
}
|
|
13267
|
-
)
|
|
13268
|
-
] });
|
|
13269
|
-
}
|
|
13270
13484
|
export {
|
|
13271
13485
|
CanvasAPI,
|
|
13272
13486
|
EventBus,
|