jupiter-dynamic-forms 1.20.2 → 1.20.4
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/concept-tree.d.ts.map +1 -1
- package/dist/core/dynamic-form.d.ts +49 -1
- package/dist/core/dynamic-form.d.ts.map +1 -1
- package/dist/core/form-field.d.ts.map +1 -1
- package/dist/core/form-section.d.ts +4 -0
- package/dist/core/form-section.d.ts.map +1 -1
- package/dist/core/formula-validation-dialog.d.ts +32 -0
- package/dist/core/formula-validation-dialog.d.ts.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +484 -183
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1846 -282
- package/dist/index.mjs.map +1 -1
- package/dist/schema/types.d.ts +33 -0
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/schema/xbrl-types.d.ts +67 -0
- package/dist/schema/xbrl-types.d.ts.map +1 -1
- package/dist/utils/formula-constants.d.ts +7 -0
- package/dist/utils/formula-constants.d.ts.map +1 -0
- package/dist/utils/formula-expression-evaluator.d.ts +64 -0
- package/dist/utils/formula-expression-evaluator.d.ts.map +1 -0
- package/dist/utils/formula-precondition-evaluator.d.ts +33 -0
- package/dist/utils/formula-precondition-evaluator.d.ts.map +1 -0
- package/dist/utils/formula-resolution-context.d.ts +53 -0
- package/dist/utils/formula-resolution-context.d.ts.map +1 -0
- package/dist/utils/formula-variable-resolver.d.ts +48 -0
- package/dist/utils/formula-variable-resolver.d.ts.map +1 -0
- package/dist/utils/total-group-resolver.d.ts +68 -0
- package/dist/utils/total-group-resolver.d.ts.map +1 -0
- package/dist/utils/total-label.d.ts +9 -0
- package/dist/utils/total-label.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1668,7 +1668,8 @@ const form$1 = {
|
|
|
1668
1668
|
download: "Download",
|
|
1669
1669
|
cancelValidation: "Cancel Validation",
|
|
1670
1670
|
lastValidationResults: "Last Validation Results",
|
|
1671
|
-
validationInProgress: "Validation In Progress"
|
|
1671
|
+
validationInProgress: "Validation In Progress",
|
|
1672
|
+
quickValidate: "Quick Validate"
|
|
1672
1673
|
};
|
|
1673
1674
|
const filter$1 = {
|
|
1674
1675
|
selectRoles: "Select Roles",
|
|
@@ -1817,6 +1818,15 @@ const calculationWarning$1 = {
|
|
|
1817
1818
|
added: "Added",
|
|
1818
1819
|
subtracted: "Subtracted (opposite balance)"
|
|
1819
1820
|
};
|
|
1821
|
+
const formulaValidation$1 = {
|
|
1822
|
+
dialogTitle: "Formula check results",
|
|
1823
|
+
allPassed: "All formula checks passed",
|
|
1824
|
+
summaryCount: "{{failed}} of {{total}} checks failed",
|
|
1825
|
+
summaryCountBreakdown: "{{warnings}} warnings, {{errors}} errors",
|
|
1826
|
+
severityWarning: "Warning",
|
|
1827
|
+
severityError: "Error",
|
|
1828
|
+
close: "Close"
|
|
1829
|
+
};
|
|
1820
1830
|
const enTranslations = {
|
|
1821
1831
|
conceptInfo: conceptInfo$1,
|
|
1822
1832
|
form: form$1,
|
|
@@ -1828,7 +1838,8 @@ const enTranslations = {
|
|
|
1828
1838
|
validation: validation$1,
|
|
1829
1839
|
xbrlValidation: xbrlValidation$1,
|
|
1830
1840
|
error: error$1,
|
|
1831
|
-
calculationWarning: calculationWarning$1
|
|
1841
|
+
calculationWarning: calculationWarning$1,
|
|
1842
|
+
formulaValidation: formulaValidation$1
|
|
1832
1843
|
};
|
|
1833
1844
|
const conceptInfo = {
|
|
1834
1845
|
title: "Conceptinformatie",
|
|
@@ -1863,7 +1874,8 @@ const form = {
|
|
|
1863
1874
|
download: "Downloaden",
|
|
1864
1875
|
cancelValidation: "Validatie annuleren",
|
|
1865
1876
|
lastValidationResults: "Laatste validatieresultaten",
|
|
1866
|
-
validationInProgress: "Validatie bezig"
|
|
1877
|
+
validationInProgress: "Validatie bezig",
|
|
1878
|
+
quickValidate: "Snel valideren"
|
|
1867
1879
|
};
|
|
1868
1880
|
const filter = {
|
|
1869
1881
|
selectRoles: "Rollen selecteren",
|
|
@@ -2012,6 +2024,15 @@ const calculationWarning = {
|
|
|
2012
2024
|
added: "Opgeteld",
|
|
2013
2025
|
subtracted: "Afgetrokken (tegengestelde balans)"
|
|
2014
2026
|
};
|
|
2027
|
+
const formulaValidation = {
|
|
2028
|
+
dialogTitle: "Resultaten formulecontrole",
|
|
2029
|
+
allPassed: "Alle formulecontroles geslaagd",
|
|
2030
|
+
summaryCount: "{{failed}} van {{total}} controles mislukt",
|
|
2031
|
+
summaryCountBreakdown: "{{warnings}} waarschuwingen, {{errors}} fouten",
|
|
2032
|
+
severityWarning: "Waarschuwing",
|
|
2033
|
+
severityError: "Fout",
|
|
2034
|
+
close: "Sluiten"
|
|
2035
|
+
};
|
|
2015
2036
|
const nlTranslations = {
|
|
2016
2037
|
conceptInfo,
|
|
2017
2038
|
form,
|
|
@@ -2023,7 +2044,8 @@ const nlTranslations = {
|
|
|
2023
2044
|
validation,
|
|
2024
2045
|
xbrlValidation,
|
|
2025
2046
|
error,
|
|
2026
|
-
calculationWarning
|
|
2047
|
+
calculationWarning,
|
|
2048
|
+
formulaValidation
|
|
2027
2049
|
};
|
|
2028
2050
|
const translations = {
|
|
2029
2051
|
en: enTranslations,
|
|
@@ -2102,6 +2124,9 @@ class I18n {
|
|
|
2102
2124
|
}
|
|
2103
2125
|
}
|
|
2104
2126
|
I18n.currentLanguage = "en";
|
|
2127
|
+
function isTotalLabel$1(preferredLabel) {
|
|
2128
|
+
return !!(preferredLabel == null ? void 0 : preferredLabel.toLowerCase().includes("totallabel"));
|
|
2129
|
+
}
|
|
2105
2130
|
class DraftStorageService {
|
|
2106
2131
|
constructor(useSessionStorage = false) {
|
|
2107
2132
|
this.DRAFT_DATA_KEY = "jupiter-form-draft-data";
|
|
@@ -2261,7 +2286,7 @@ class DraftStorageService {
|
|
|
2261
2286
|
/**
|
|
2262
2287
|
* Create metadata snapshot from current form state
|
|
2263
2288
|
*/
|
|
2264
|
-
createMetadataSnapshot(periodStartDate, periodEndDate, language, selectedRoleIds, allSections, typedMemberData, periodPreferences, periodData, unitData, reportingLanguage = "en", repeatCounts, decimalsData, roleCompletedStates, hiddenColumns) {
|
|
2289
|
+
createMetadataSnapshot(periodStartDate, periodEndDate, language, selectedRoleIds, allSections, typedMemberData, periodPreferences, periodData, unitData, reportingLanguage = "en", repeatCounts, decimalsData, roleCompletedStates, hiddenColumns, totalManuallyEditedData) {
|
|
2265
2290
|
return {
|
|
2266
2291
|
periodStartDate,
|
|
2267
2292
|
periodEndDate,
|
|
@@ -2278,6 +2303,7 @@ class DraftStorageService {
|
|
|
2278
2303
|
repeatCounts,
|
|
2279
2304
|
roleCompletedStates,
|
|
2280
2305
|
hiddenColumns,
|
|
2306
|
+
totalManuallyEditedData,
|
|
2281
2307
|
schemaVersion: this.STORAGE_VERSION
|
|
2282
2308
|
};
|
|
2283
2309
|
}
|
|
@@ -2300,6 +2326,882 @@ class DraftStorageService {
|
|
|
2300
2326
|
return { compatible, warnings };
|
|
2301
2327
|
}
|
|
2302
2328
|
}
|
|
2329
|
+
const CALCULATION_TOLERANCE = 0.01;
|
|
2330
|
+
class FormulaExpressionError extends Error {
|
|
2331
|
+
constructor(message, test, reason = "unsupported-syntax") {
|
|
2332
|
+
super(message);
|
|
2333
|
+
this.test = test;
|
|
2334
|
+
this.reason = reason;
|
|
2335
|
+
this.name = "FormulaExpressionError";
|
|
2336
|
+
}
|
|
2337
|
+
}
|
|
2338
|
+
const TOKEN_PATTERN = /\s*(?:(\$[A-Za-z_][\w-]*)|(-?\d+(?:\.\d+)?)|([A-Za-z][\w:-]*)|('[^']*')|(\()|(\))|(\+)|(-)|(=))/y;
|
|
2339
|
+
function tokenize(test) {
|
|
2340
|
+
const tokens = [];
|
|
2341
|
+
TOKEN_PATTERN.lastIndex = 0;
|
|
2342
|
+
let index = 0;
|
|
2343
|
+
while (index < test.length) {
|
|
2344
|
+
TOKEN_PATTERN.lastIndex = index;
|
|
2345
|
+
const match = TOKEN_PATTERN.exec(test);
|
|
2346
|
+
if (!match || match.index !== index) {
|
|
2347
|
+
if (/^\s*$/.test(test.slice(index)))
|
|
2348
|
+
break;
|
|
2349
|
+
throw new FormulaExpressionError(`Unrecognized token at position ${index}: "${test.slice(index, index + 10)}..."`, test, "unsupported-syntax");
|
|
2350
|
+
}
|
|
2351
|
+
const [full, variable, number, ident, string, lparen, rparen, plus, minus, equals] = match;
|
|
2352
|
+
if (variable)
|
|
2353
|
+
tokens.push({ type: "VARIABLE", value: variable.slice(1) });
|
|
2354
|
+
else if (number)
|
|
2355
|
+
tokens.push({ type: "NUMBER", value: number });
|
|
2356
|
+
else if (ident)
|
|
2357
|
+
tokens.push({ type: "IDENT", value: ident });
|
|
2358
|
+
else if (string)
|
|
2359
|
+
tokens.push({ type: "STRING", value: string.slice(1, -1) });
|
|
2360
|
+
else if (lparen)
|
|
2361
|
+
tokens.push({ type: "LPAREN", value: lparen });
|
|
2362
|
+
else if (rparen)
|
|
2363
|
+
tokens.push({ type: "RPAREN", value: rparen });
|
|
2364
|
+
else if (plus)
|
|
2365
|
+
tokens.push({ type: "PLUS", value: plus });
|
|
2366
|
+
else if (minus)
|
|
2367
|
+
tokens.push({ type: "MINUS", value: minus });
|
|
2368
|
+
else if (equals)
|
|
2369
|
+
tokens.push({ type: "EQUALS", value: equals });
|
|
2370
|
+
index += full.length;
|
|
2371
|
+
}
|
|
2372
|
+
tokens.push({ type: "EOF", value: "" });
|
|
2373
|
+
return tokens;
|
|
2374
|
+
}
|
|
2375
|
+
class Parser {
|
|
2376
|
+
constructor(tokens, test) {
|
|
2377
|
+
this.tokens = tokens;
|
|
2378
|
+
this.test = test;
|
|
2379
|
+
this.pos = 0;
|
|
2380
|
+
}
|
|
2381
|
+
peek() {
|
|
2382
|
+
return this.tokens[this.pos];
|
|
2383
|
+
}
|
|
2384
|
+
next() {
|
|
2385
|
+
return this.tokens[this.pos++];
|
|
2386
|
+
}
|
|
2387
|
+
expect(type) {
|
|
2388
|
+
const token = this.next();
|
|
2389
|
+
if (token.type !== type) {
|
|
2390
|
+
throw new FormulaExpressionError(
|
|
2391
|
+
`Expected ${type} but got ${token.type} ("${token.value}")`,
|
|
2392
|
+
this.test,
|
|
2393
|
+
"parse-error"
|
|
2394
|
+
);
|
|
2395
|
+
}
|
|
2396
|
+
return token;
|
|
2397
|
+
}
|
|
2398
|
+
parseBoolExpr() {
|
|
2399
|
+
const node = this.parseOrExpr();
|
|
2400
|
+
if (this.peek().type !== "EOF") {
|
|
2401
|
+
throw new FormulaExpressionError(
|
|
2402
|
+
`Unexpected trailing token "${this.peek().value}"`,
|
|
2403
|
+
this.test,
|
|
2404
|
+
"unsupported-syntax"
|
|
2405
|
+
);
|
|
2406
|
+
}
|
|
2407
|
+
return node;
|
|
2408
|
+
}
|
|
2409
|
+
parseOrExpr() {
|
|
2410
|
+
const terms = [this.parseAndExpr()];
|
|
2411
|
+
while (this.peek().type === "IDENT" && this.peek().value === "or") {
|
|
2412
|
+
this.next();
|
|
2413
|
+
terms.push(this.parseAndExpr());
|
|
2414
|
+
}
|
|
2415
|
+
return terms.length === 1 ? terms[0] : { kind: "or", terms };
|
|
2416
|
+
}
|
|
2417
|
+
parseAndExpr() {
|
|
2418
|
+
const terms = [this.parseBoolTerm()];
|
|
2419
|
+
while (this.peek().type === "IDENT" && this.peek().value === "and") {
|
|
2420
|
+
this.next();
|
|
2421
|
+
terms.push(this.parseBoolTerm());
|
|
2422
|
+
}
|
|
2423
|
+
return terms.length === 1 ? terms[0] : { kind: "and", terms };
|
|
2424
|
+
}
|
|
2425
|
+
parseBoolTerm() {
|
|
2426
|
+
const token = this.peek();
|
|
2427
|
+
if (token.type === "IDENT" && token.value === "not") {
|
|
2428
|
+
this.next();
|
|
2429
|
+
this.expect("LPAREN");
|
|
2430
|
+
const arg = this.parseOrExpr();
|
|
2431
|
+
this.expect("RPAREN");
|
|
2432
|
+
return { kind: "not", arg };
|
|
2433
|
+
}
|
|
2434
|
+
if (token.type === "IDENT" && token.value === "empty") {
|
|
2435
|
+
this.next();
|
|
2436
|
+
this.expect("LPAREN");
|
|
2437
|
+
const variable = this.expect("VARIABLE").value;
|
|
2438
|
+
this.expect("RPAREN");
|
|
2439
|
+
return { kind: "empty", variable };
|
|
2440
|
+
}
|
|
2441
|
+
if (token.type === "IDENT" && token.value === "xff:has-fallback-value") {
|
|
2442
|
+
this.next();
|
|
2443
|
+
this.expect("LPAREN");
|
|
2444
|
+
const inner = this.next();
|
|
2445
|
+
if (inner.type !== "IDENT" || inner.value !== "xs:QName") {
|
|
2446
|
+
throw new FormulaExpressionError(
|
|
2447
|
+
`Expected xs:QName(...) inside xff:has-fallback-value(...), got "${inner.value}"`,
|
|
2448
|
+
this.test,
|
|
2449
|
+
"unsupported-syntax"
|
|
2450
|
+
);
|
|
2451
|
+
}
|
|
2452
|
+
this.expect("LPAREN");
|
|
2453
|
+
const variableName = this.expect("STRING").value;
|
|
2454
|
+
this.expect("RPAREN");
|
|
2455
|
+
this.expect("RPAREN");
|
|
2456
|
+
return { kind: "hasFallbackValue", variableName };
|
|
2457
|
+
}
|
|
2458
|
+
const left = this.parseValueExpr();
|
|
2459
|
+
const opToken = this.peek();
|
|
2460
|
+
if (opToken.type === "EQUALS") {
|
|
2461
|
+
this.next();
|
|
2462
|
+
return { kind: "comparison", op: "=", left, right: this.parseValueExpr() };
|
|
2463
|
+
}
|
|
2464
|
+
if (opToken.type === "IDENT" && opToken.value === "eq") {
|
|
2465
|
+
this.next();
|
|
2466
|
+
return { kind: "comparison", op: "eq", left, right: this.parseValueExpr() };
|
|
2467
|
+
}
|
|
2468
|
+
throw new FormulaExpressionError(
|
|
2469
|
+
`Expected a comparison operator ("=" or "eq") after value expression, got "${opToken.value}"`,
|
|
2470
|
+
this.test,
|
|
2471
|
+
"unsupported-syntax"
|
|
2472
|
+
);
|
|
2473
|
+
}
|
|
2474
|
+
parseValueExpr() {
|
|
2475
|
+
const terms = [];
|
|
2476
|
+
let sign = 1;
|
|
2477
|
+
if (this.peek().type === "PLUS") {
|
|
2478
|
+
this.next();
|
|
2479
|
+
} else if (this.peek().type === "MINUS") {
|
|
2480
|
+
this.next();
|
|
2481
|
+
sign = -1;
|
|
2482
|
+
}
|
|
2483
|
+
terms.push({ sign, term: this.parseValueTerm() });
|
|
2484
|
+
while (this.peek().type === "PLUS" || this.peek().type === "MINUS") {
|
|
2485
|
+
const opSign = this.next().type === "PLUS" ? 1 : -1;
|
|
2486
|
+
terms.push({ sign: opSign, term: this.parseValueTerm() });
|
|
2487
|
+
}
|
|
2488
|
+
return terms.length === 1 && terms[0].sign === 1 ? terms[0].term : { kind: "additive", terms };
|
|
2489
|
+
}
|
|
2490
|
+
parseValueTerm() {
|
|
2491
|
+
const token = this.peek();
|
|
2492
|
+
if (token.type === "NUMBER") {
|
|
2493
|
+
this.next();
|
|
2494
|
+
return { kind: "number", value: Number(token.value) };
|
|
2495
|
+
}
|
|
2496
|
+
if (token.type === "VARIABLE") {
|
|
2497
|
+
this.next();
|
|
2498
|
+
return { kind: "variable", name: token.value };
|
|
2499
|
+
}
|
|
2500
|
+
if (token.type === "IDENT" && token.value === "sum") {
|
|
2501
|
+
this.next();
|
|
2502
|
+
this.expect("LPAREN");
|
|
2503
|
+
const variable = this.expect("VARIABLE").value;
|
|
2504
|
+
this.expect("RPAREN");
|
|
2505
|
+
return { kind: "sum", variable };
|
|
2506
|
+
}
|
|
2507
|
+
if (token.type === "LPAREN") {
|
|
2508
|
+
this.next();
|
|
2509
|
+
const inner = this.parseValueExpr();
|
|
2510
|
+
this.expect("RPAREN");
|
|
2511
|
+
return inner;
|
|
2512
|
+
}
|
|
2513
|
+
throw new FormulaExpressionError(
|
|
2514
|
+
`Expected a number, variable, sum(...), or parenthesized expression, got "${token.value}"`,
|
|
2515
|
+
this.test,
|
|
2516
|
+
"unsupported-syntax"
|
|
2517
|
+
);
|
|
2518
|
+
}
|
|
2519
|
+
}
|
|
2520
|
+
function lookup(bindings, name) {
|
|
2521
|
+
return bindings.get(name);
|
|
2522
|
+
}
|
|
2523
|
+
function evalSum(variable, bindings) {
|
|
2524
|
+
const binding = lookup(bindings, variable);
|
|
2525
|
+
if (binding === void 0)
|
|
2526
|
+
return 0;
|
|
2527
|
+
if (Array.isArray(binding))
|
|
2528
|
+
return binding.reduce((total, value) => total + value, 0);
|
|
2529
|
+
return binding;
|
|
2530
|
+
}
|
|
2531
|
+
function evalValue(node, bindings, test) {
|
|
2532
|
+
switch (node.kind) {
|
|
2533
|
+
case "number":
|
|
2534
|
+
return node.value;
|
|
2535
|
+
case "sum":
|
|
2536
|
+
return evalSum(node.variable, bindings);
|
|
2537
|
+
case "variable": {
|
|
2538
|
+
const binding = lookup(bindings, node.name);
|
|
2539
|
+
if (binding === void 0) {
|
|
2540
|
+
throw new FormulaExpressionError(
|
|
2541
|
+
`Variable "$${node.name}" has no bound fact and cannot be evaluated directly (only sum()/empty() tolerate an unbound variable)`,
|
|
2542
|
+
test,
|
|
2543
|
+
"unbound-variable"
|
|
2544
|
+
);
|
|
2545
|
+
}
|
|
2546
|
+
if (Array.isArray(binding)) {
|
|
2547
|
+
throw new FormulaExpressionError(
|
|
2548
|
+
`Variable "$${node.name}" is a sequence and must be wrapped in sum(...) to be used in arithmetic`,
|
|
2549
|
+
test,
|
|
2550
|
+
"unsupported-syntax"
|
|
2551
|
+
);
|
|
2552
|
+
}
|
|
2553
|
+
return binding;
|
|
2554
|
+
}
|
|
2555
|
+
case "additive":
|
|
2556
|
+
return node.terms.reduce((total, { sign, term }) => total + sign * evalValue(term, bindings, test), 0);
|
|
2557
|
+
}
|
|
2558
|
+
}
|
|
2559
|
+
function evalBool(node, bindings, test, fallbackUsage) {
|
|
2560
|
+
switch (node.kind) {
|
|
2561
|
+
case "or":
|
|
2562
|
+
return node.terms.some((term) => evalBool(term, bindings, test, fallbackUsage));
|
|
2563
|
+
case "and":
|
|
2564
|
+
return node.terms.every((term) => evalBool(term, bindings, test, fallbackUsage));
|
|
2565
|
+
case "not":
|
|
2566
|
+
return !evalBool(node.arg, bindings, test, fallbackUsage);
|
|
2567
|
+
case "empty": {
|
|
2568
|
+
const binding = lookup(bindings, node.variable);
|
|
2569
|
+
return binding === void 0 || Array.isArray(binding) && binding.length === 0;
|
|
2570
|
+
}
|
|
2571
|
+
case "hasFallbackValue": {
|
|
2572
|
+
const usedFallback = fallbackUsage.get(node.variableName);
|
|
2573
|
+
if (usedFallback === void 0) {
|
|
2574
|
+
throw new FormulaExpressionError(
|
|
2575
|
+
`xff:has-fallback-value(xs:QName('${node.variableName}')) could not be evaluated — no fallback-usage tracked for this variable (either not one of this assertion's FACT_VARIABLEs, or it matched zero facts with no fallbackValue declared)`,
|
|
2576
|
+
test,
|
|
2577
|
+
"unbound-variable"
|
|
2578
|
+
);
|
|
2579
|
+
}
|
|
2580
|
+
return usedFallback;
|
|
2581
|
+
}
|
|
2582
|
+
case "comparison": {
|
|
2583
|
+
const left = evalValue(node.left, bindings, test);
|
|
2584
|
+
const right = evalValue(node.right, bindings, test);
|
|
2585
|
+
return Math.abs(left - right) < CALCULATION_TOLERANCE;
|
|
2586
|
+
}
|
|
2587
|
+
}
|
|
2588
|
+
}
|
|
2589
|
+
function evaluateFormulaTest(test, bindings, fallbackUsage = /* @__PURE__ */ new Map()) {
|
|
2590
|
+
const tokens = tokenize(test);
|
|
2591
|
+
const ast = new Parser(tokens, test).parseBoolExpr();
|
|
2592
|
+
return evalBool(ast, bindings, test, fallbackUsage);
|
|
2593
|
+
}
|
|
2594
|
+
const EXISTENCE_TEST_PATTERN = /^\.\s*(eq|ne|gt|lt|ge|le)\s+(-?\d+(?:\.\d+)?)$/;
|
|
2595
|
+
function compareExistence(op, count, threshold) {
|
|
2596
|
+
switch (op) {
|
|
2597
|
+
case "eq":
|
|
2598
|
+
return count === threshold;
|
|
2599
|
+
case "ne":
|
|
2600
|
+
return count !== threshold;
|
|
2601
|
+
case "gt":
|
|
2602
|
+
return count > threshold;
|
|
2603
|
+
case "lt":
|
|
2604
|
+
return count < threshold;
|
|
2605
|
+
case "ge":
|
|
2606
|
+
return count >= threshold;
|
|
2607
|
+
case "le":
|
|
2608
|
+
return count <= threshold;
|
|
2609
|
+
}
|
|
2610
|
+
}
|
|
2611
|
+
function evaluateExistenceTest(test, matchedFactCount) {
|
|
2612
|
+
const trimmed = (test ?? "").trim();
|
|
2613
|
+
if (trimmed === "") {
|
|
2614
|
+
return matchedFactCount > 0;
|
|
2615
|
+
}
|
|
2616
|
+
const clauses = trimmed.split(/\bor\b/);
|
|
2617
|
+
return clauses.some((clause) => {
|
|
2618
|
+
const match = EXISTENCE_TEST_PATTERN.exec(clause.trim());
|
|
2619
|
+
if (!match) {
|
|
2620
|
+
throw new FormulaExpressionError(`Unsupported existence-assertion test shape: "${clause.trim()}"`, trimmed, "unsupported-syntax");
|
|
2621
|
+
}
|
|
2622
|
+
const [, op, thresholdText] = match;
|
|
2623
|
+
return compareExistence(op, matchedFactCount, Number(thresholdText));
|
|
2624
|
+
});
|
|
2625
|
+
}
|
|
2626
|
+
function isTotalLabel(preferredLabel) {
|
|
2627
|
+
return !!(preferredLabel == null ? void 0 : preferredLabel.toLowerCase().includes("totallabel"));
|
|
2628
|
+
}
|
|
2629
|
+
function isNegatedTotalLabel(preferredLabel) {
|
|
2630
|
+
return !!(preferredLabel == null ? void 0 : preferredLabel.toLowerCase().includes("negatedtotallabel"));
|
|
2631
|
+
}
|
|
2632
|
+
function resolveValueNode(node, accessors, depth = 0) {
|
|
2633
|
+
if (!accessors.isAbstract(node))
|
|
2634
|
+
return node;
|
|
2635
|
+
if (depth > 5)
|
|
2636
|
+
return null;
|
|
2637
|
+
const children = accessors.getChildren(node);
|
|
2638
|
+
const nestedTotal = children.find((child) => isTotalLabel(accessors.getPreferredLabel(child)));
|
|
2639
|
+
if (!nestedTotal)
|
|
2640
|
+
return null;
|
|
2641
|
+
return resolveValueNode(nestedTotal, accessors, depth + 1);
|
|
2642
|
+
}
|
|
2643
|
+
function resolveTotalGroupMembers(nodes, i2, lastTotalIdx, rawSiblings, accessors) {
|
|
2644
|
+
if (lastTotalIdx < 0)
|
|
2645
|
+
return rawSiblings;
|
|
2646
|
+
const node = nodes[i2];
|
|
2647
|
+
if (isNegatedTotalLabel(accessors.getPreferredLabel(node))) {
|
|
2648
|
+
return rawSiblings.length > 0 ? rawSiblings : [nodes[lastTotalIdx]];
|
|
2649
|
+
}
|
|
2650
|
+
if (rawSiblings.length > 0) {
|
|
2651
|
+
return [nodes[lastTotalIdx], ...rawSiblings];
|
|
2652
|
+
}
|
|
2653
|
+
if (isNegatedTotalLabel(accessors.getPreferredLabel(nodes[lastTotalIdx]))) {
|
|
2654
|
+
let grandTotalIdx = -1;
|
|
2655
|
+
for (let k = lastTotalIdx - 1; k >= 0; k--) {
|
|
2656
|
+
if (isTotalLabel(accessors.getPreferredLabel(nodes[k]))) {
|
|
2657
|
+
grandTotalIdx = k;
|
|
2658
|
+
break;
|
|
2659
|
+
}
|
|
2660
|
+
}
|
|
2661
|
+
return grandTotalIdx >= 0 ? [nodes[grandTotalIdx], nodes[lastTotalIdx]] : [nodes[lastTotalIdx]];
|
|
2662
|
+
}
|
|
2663
|
+
return [nodes[lastTotalIdx]];
|
|
2664
|
+
}
|
|
2665
|
+
function buildTotalGroupChildrenIndex(roots, accessors) {
|
|
2666
|
+
const index = /* @__PURE__ */ new Map();
|
|
2667
|
+
function registerGroup(totalNode, members) {
|
|
2668
|
+
const resolvedIds = [];
|
|
2669
|
+
for (const member of members) {
|
|
2670
|
+
const resolved = resolveValueNode(member, accessors);
|
|
2671
|
+
if (resolved)
|
|
2672
|
+
resolvedIds.push(accessors.getId(resolved));
|
|
2673
|
+
}
|
|
2674
|
+
if (resolvedIds.length === 0)
|
|
2675
|
+
return;
|
|
2676
|
+
index.set(accessors.getId(totalNode), resolvedIds);
|
|
2677
|
+
}
|
|
2678
|
+
function traverse(nodes) {
|
|
2679
|
+
for (let i2 = 0; i2 < nodes.length; i2++) {
|
|
2680
|
+
const node = nodes[i2];
|
|
2681
|
+
if (isTotalLabel(accessors.getPreferredLabel(node))) {
|
|
2682
|
+
const children2 = accessors.getChildren(node);
|
|
2683
|
+
if (children2.length === 0) {
|
|
2684
|
+
let lastTotalIdx = -1;
|
|
2685
|
+
for (let j = i2 - 1; j >= 0; j--) {
|
|
2686
|
+
if (isTotalLabel(accessors.getPreferredLabel(nodes[j]))) {
|
|
2687
|
+
lastTotalIdx = j;
|
|
2688
|
+
break;
|
|
2689
|
+
}
|
|
2690
|
+
}
|
|
2691
|
+
const rawSiblings = nodes.slice(lastTotalIdx + 1, i2);
|
|
2692
|
+
const members = resolveTotalGroupMembers(nodes, i2, lastTotalIdx, rawSiblings, accessors);
|
|
2693
|
+
if (members.length > 0)
|
|
2694
|
+
registerGroup(node, members);
|
|
2695
|
+
}
|
|
2696
|
+
}
|
|
2697
|
+
const children = accessors.getChildren(node);
|
|
2698
|
+
if (children.length > 0)
|
|
2699
|
+
traverse(children);
|
|
2700
|
+
}
|
|
2701
|
+
}
|
|
2702
|
+
traverse(roots);
|
|
2703
|
+
return index;
|
|
2704
|
+
}
|
|
2705
|
+
function isNonEmptyRawValue(rawValue) {
|
|
2706
|
+
return rawValue !== void 0 && rawValue !== null && rawValue !== "";
|
|
2707
|
+
}
|
|
2708
|
+
function collectAllCandidates(formData) {
|
|
2709
|
+
const candidates = [];
|
|
2710
|
+
for (const conceptId of Object.keys(formData)) {
|
|
2711
|
+
const columnValues = formData[conceptId] || {};
|
|
2712
|
+
for (const columnId of Object.keys(columnValues)) {
|
|
2713
|
+
if (isNonEmptyRawValue(columnValues[columnId])) {
|
|
2714
|
+
candidates.push({ conceptId, columnId });
|
|
2715
|
+
}
|
|
2716
|
+
}
|
|
2717
|
+
}
|
|
2718
|
+
return candidates;
|
|
2719
|
+
}
|
|
2720
|
+
function indexConceptTree(concept, conceptByQName, conceptById, conceptIdByQName, conceptIdByQNameHasChildren, childrenIndex) {
|
|
2721
|
+
const info = {
|
|
2722
|
+
conceptId: concept.id,
|
|
2723
|
+
qname: concept.name,
|
|
2724
|
+
balance: concept.balance
|
|
2725
|
+
};
|
|
2726
|
+
conceptById.set(concept.id, info);
|
|
2727
|
+
(conceptByQName.get(concept.name) ?? conceptByQName.set(concept.name, []).get(concept.name)).push(info);
|
|
2728
|
+
const children = concept.children || [];
|
|
2729
|
+
const hasOwnChildren = children.length > 0;
|
|
2730
|
+
const alreadyHasChildren = conceptIdByQNameHasChildren.get(concept.name) === true;
|
|
2731
|
+
if (!conceptIdByQName.has(concept.name) || hasOwnChildren && !alreadyHasChildren) {
|
|
2732
|
+
conceptIdByQName.set(concept.name, concept.id);
|
|
2733
|
+
conceptIdByQNameHasChildren.set(concept.name, hasOwnChildren);
|
|
2734
|
+
}
|
|
2735
|
+
childrenIndex.set(
|
|
2736
|
+
concept.id,
|
|
2737
|
+
children.map((child) => child.id)
|
|
2738
|
+
);
|
|
2739
|
+
children.forEach((child) => indexConceptTree(child, conceptByQName, conceptById, conceptIdByQName, conceptIdByQNameHasChildren, childrenIndex));
|
|
2740
|
+
}
|
|
2741
|
+
function indexMemberTree(member, memberQNameToId) {
|
|
2742
|
+
if (!memberQNameToId.has(member.conceptName))
|
|
2743
|
+
memberQNameToId.set(member.conceptName, member.id);
|
|
2744
|
+
(member.children || []).forEach((child) => indexMemberTree(child, memberQNameToId));
|
|
2745
|
+
}
|
|
2746
|
+
const PRESENTATION_TOTAL_GROUP_ACCESSORS = {
|
|
2747
|
+
getId: (concept) => concept.id,
|
|
2748
|
+
getPreferredLabel: (concept) => concept.preferredLabel,
|
|
2749
|
+
isAbstract: (concept) => concept.abstract === true,
|
|
2750
|
+
getChildren: (concept) => concept.children || []
|
|
2751
|
+
};
|
|
2752
|
+
function buildFormulaResolutionContext(formData, columns, sections, hypercubeRoles, periodStartDate, periodEndDate) {
|
|
2753
|
+
const conceptByQName = /* @__PURE__ */ new Map();
|
|
2754
|
+
const conceptById = /* @__PURE__ */ new Map();
|
|
2755
|
+
const conceptIdByQNamePerRole = /* @__PURE__ */ new Map();
|
|
2756
|
+
const childrenByRole = /* @__PURE__ */ new Map();
|
|
2757
|
+
const totalGroupChildrenByRole = /* @__PURE__ */ new Map();
|
|
2758
|
+
sections.forEach((section2) => {
|
|
2759
|
+
const childrenIndex = /* @__PURE__ */ new Map();
|
|
2760
|
+
const conceptIdByQName = /* @__PURE__ */ new Map();
|
|
2761
|
+
const conceptIdByQNameHasChildren = /* @__PURE__ */ new Map();
|
|
2762
|
+
section2.concepts.forEach((concept) => indexConceptTree(concept, conceptByQName, conceptById, conceptIdByQName, conceptIdByQNameHasChildren, childrenIndex));
|
|
2763
|
+
childrenByRole.set(section2.roleURI, childrenIndex);
|
|
2764
|
+
conceptIdByQNamePerRole.set(section2.roleURI, conceptIdByQName);
|
|
2765
|
+
totalGroupChildrenByRole.set(section2.roleURI, buildTotalGroupChildrenIndex(section2.concepts, PRESENTATION_TOTAL_GROUP_ACCESSORS));
|
|
2766
|
+
});
|
|
2767
|
+
const dimensionQNameToId = /* @__PURE__ */ new Map();
|
|
2768
|
+
const memberQNameToId = /* @__PURE__ */ new Map();
|
|
2769
|
+
(hypercubeRoles || []).forEach((role) => {
|
|
2770
|
+
role.items.forEach((item) => {
|
|
2771
|
+
item.dimensions.forEach((dimension) => {
|
|
2772
|
+
if (!dimensionQNameToId.has(dimension.conceptName)) {
|
|
2773
|
+
dimensionQNameToId.set(dimension.conceptName, dimension.id);
|
|
2774
|
+
}
|
|
2775
|
+
(dimension.members || []).forEach((member) => indexMemberTree(member, memberQNameToId));
|
|
2776
|
+
});
|
|
2777
|
+
});
|
|
2778
|
+
});
|
|
2779
|
+
return {
|
|
2780
|
+
formData,
|
|
2781
|
+
columns,
|
|
2782
|
+
periodStartDate,
|
|
2783
|
+
periodEndDate,
|
|
2784
|
+
conceptByQName,
|
|
2785
|
+
conceptById,
|
|
2786
|
+
conceptIdByQNamePerRole,
|
|
2787
|
+
childrenByRole,
|
|
2788
|
+
totalGroupChildrenByRole,
|
|
2789
|
+
dimensionQNameToId,
|
|
2790
|
+
memberQNameToId,
|
|
2791
|
+
allCandidates: collectAllCandidates(formData)
|
|
2792
|
+
};
|
|
2793
|
+
}
|
|
2794
|
+
function collectDescendantConceptIds(childrenIndex, rootConceptId) {
|
|
2795
|
+
const result = [];
|
|
2796
|
+
const stack = [...childrenIndex.get(rootConceptId) || []];
|
|
2797
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2798
|
+
while (stack.length > 0) {
|
|
2799
|
+
const conceptId = stack.pop();
|
|
2800
|
+
if (seen.has(conceptId))
|
|
2801
|
+
continue;
|
|
2802
|
+
seen.add(conceptId);
|
|
2803
|
+
result.push(conceptId);
|
|
2804
|
+
stack.push(...childrenIndex.get(conceptId) || []);
|
|
2805
|
+
}
|
|
2806
|
+
return result;
|
|
2807
|
+
}
|
|
2808
|
+
function candidateKey(candidate) {
|
|
2809
|
+
return `${candidate.conceptId}::${candidate.columnId}`;
|
|
2810
|
+
}
|
|
2811
|
+
function resolveMatchedCandidates(variable, ctx) {
|
|
2812
|
+
return intersectCandidates(variable.filters.map((filter2) => resolveFilter(filter2, ctx.allCandidates, ctx)));
|
|
2813
|
+
}
|
|
2814
|
+
function getColumn(ctx, columnId) {
|
|
2815
|
+
return ctx.columns.find((column2) => column2.id === columnId);
|
|
2816
|
+
}
|
|
2817
|
+
function columnMatchesExplicitDimension(column2, axisId, memberId) {
|
|
2818
|
+
if (!(column2 == null ? void 0 : column2.dimensionData))
|
|
2819
|
+
return false;
|
|
2820
|
+
const primaryMatch = column2.dimensionData.axisId === axisId && (memberId === void 0 || column2.dimensionData.memberId === memberId);
|
|
2821
|
+
if (primaryMatch)
|
|
2822
|
+
return true;
|
|
2823
|
+
return (column2.dimensionData.combinations || []).some(
|
|
2824
|
+
(combo) => combo.axisId === axisId && (memberId === void 0 || combo.memberId === memberId)
|
|
2825
|
+
);
|
|
2826
|
+
}
|
|
2827
|
+
function columnMatchesTypedDimension(column2, axisId) {
|
|
2828
|
+
if (!(column2 == null ? void 0 : column2.dimensionData))
|
|
2829
|
+
return false;
|
|
2830
|
+
if (column2.dimensionData.typedMemberId !== void 0 && column2.dimensionData.axisId === axisId)
|
|
2831
|
+
return true;
|
|
2832
|
+
return (column2.dimensionData.typedMembers || []).some((typedMember) => typedMember.axisId === axisId);
|
|
2833
|
+
}
|
|
2834
|
+
function paramTokenName(rawDate) {
|
|
2835
|
+
if (!rawDate)
|
|
2836
|
+
return void 0;
|
|
2837
|
+
return rawDate.startsWith("$") ? rawDate.slice(1) : rawDate;
|
|
2838
|
+
}
|
|
2839
|
+
function resolveParamDate(paramToken, ctx) {
|
|
2840
|
+
const isStart = paramToken.includes("StartDate");
|
|
2841
|
+
const isEnd = paramToken.includes("EndDate") || paramToken === "FinancialReportingPeriodCurrentEndDateParam";
|
|
2842
|
+
if (paramToken.startsWith("FinancialReportingPeriodCurrent")) {
|
|
2843
|
+
return isStart ? { start: ctx.periodStartDate } : isEnd ? { end: ctx.periodEndDate } : void 0;
|
|
2844
|
+
}
|
|
2845
|
+
if (paramToken.startsWith("FinancialReportingPeriodPrePrevious") || paramToken.startsWith("FinancialReportingPeriodPrevious")) {
|
|
2846
|
+
const previousYearColumn = findPreviousYearColumn(ctx);
|
|
2847
|
+
if (!previousYearColumn)
|
|
2848
|
+
return void 0;
|
|
2849
|
+
return isStart ? { start: previousYearColumn.periodStartDate } : isEnd ? { end: previousYearColumn.periodEndDate } : void 0;
|
|
2850
|
+
}
|
|
2851
|
+
return void 0;
|
|
2852
|
+
}
|
|
2853
|
+
function findPreviousYearColumn(ctx) {
|
|
2854
|
+
return ctx.columns.find((column2) => column2.periodEndDate !== void 0 && column2.periodEndDate < ctx.periodEndDate);
|
|
2855
|
+
}
|
|
2856
|
+
function columnEffectivePeriod(column2, ctx) {
|
|
2857
|
+
return {
|
|
2858
|
+
start: (column2 == null ? void 0 : column2.periodStartDate) ?? ctx.periodStartDate,
|
|
2859
|
+
end: (column2 == null ? void 0 : column2.periodEndDate) ?? ctx.periodEndDate
|
|
2860
|
+
};
|
|
2861
|
+
}
|
|
2862
|
+
function columnMatchesPeriod(column2, dateAttribute, ctx) {
|
|
2863
|
+
const paramToken = paramTokenName(dateAttribute);
|
|
2864
|
+
if (!paramToken)
|
|
2865
|
+
return false;
|
|
2866
|
+
const resolved = resolveParamDate(paramToken, ctx);
|
|
2867
|
+
if (!resolved)
|
|
2868
|
+
return false;
|
|
2869
|
+
const period = columnEffectivePeriod(column2, ctx);
|
|
2870
|
+
const targetDate = resolved.end ?? resolved.start;
|
|
2871
|
+
return period.end === targetDate;
|
|
2872
|
+
}
|
|
2873
|
+
function unionCandidates(lists) {
|
|
2874
|
+
const merged = /* @__PURE__ */ new Map();
|
|
2875
|
+
lists.forEach((list) => list.forEach((candidate) => merged.set(candidateKey(candidate), candidate)));
|
|
2876
|
+
return Array.from(merged.values());
|
|
2877
|
+
}
|
|
2878
|
+
function matchFilter(filter2, universe, ctx) {
|
|
2879
|
+
var _a, _b;
|
|
2880
|
+
switch (filter2.type) {
|
|
2881
|
+
case "CONCEPT_NAME": {
|
|
2882
|
+
const qname = filter2.attributes["concept.qname"];
|
|
2883
|
+
const infos = qname ? ctx.conceptByQName.get(qname) : void 0;
|
|
2884
|
+
if (!infos || infos.length === 0)
|
|
2885
|
+
return [];
|
|
2886
|
+
const conceptIds = new Set(infos.map((info) => info.conceptId));
|
|
2887
|
+
return universe.filter((candidate) => conceptIds.has(candidate.conceptId));
|
|
2888
|
+
}
|
|
2889
|
+
case "CONCEPT_BALANCE": {
|
|
2890
|
+
const balance = filter2.attributes["balance"];
|
|
2891
|
+
return universe.filter((candidate) => {
|
|
2892
|
+
var _a2;
|
|
2893
|
+
return ((_a2 = ctx.conceptById.get(candidate.conceptId)) == null ? void 0 : _a2.balance) === balance;
|
|
2894
|
+
});
|
|
2895
|
+
}
|
|
2896
|
+
case "CONCEPT_RELATION": {
|
|
2897
|
+
const anchorQName = filter2.attributes["qname"];
|
|
2898
|
+
const linkrole = filter2.attributes["linkrole"];
|
|
2899
|
+
const axis = filter2.attributes["axis"];
|
|
2900
|
+
const anchorConceptId = anchorQName && linkrole ? (_a = ctx.conceptIdByQNamePerRole.get(linkrole)) == null ? void 0 : _a.get(anchorQName) : void 0;
|
|
2901
|
+
const childrenIndex = linkrole ? ctx.childrenByRole.get(linkrole) : void 0;
|
|
2902
|
+
if (!anchorConceptId || !childrenIndex)
|
|
2903
|
+
return [];
|
|
2904
|
+
let relatedConceptIds;
|
|
2905
|
+
if (axis === "descendant") {
|
|
2906
|
+
relatedConceptIds = collectDescendantConceptIds(childrenIndex, anchorConceptId);
|
|
2907
|
+
} else {
|
|
2908
|
+
const nestedChildren = childrenIndex.get(anchorConceptId) || [];
|
|
2909
|
+
relatedConceptIds = nestedChildren.length > 0 ? nestedChildren : ((_b = ctx.totalGroupChildrenByRole.get(linkrole ?? "")) == null ? void 0 : _b.get(anchorConceptId)) || [];
|
|
2910
|
+
}
|
|
2911
|
+
const relatedSet = new Set(relatedConceptIds);
|
|
2912
|
+
return universe.filter((candidate) => relatedSet.has(candidate.conceptId));
|
|
2913
|
+
}
|
|
2914
|
+
case "EXPLICIT_DIMENSION": {
|
|
2915
|
+
const dimensionQName = filter2.attributes["dimension.qname"];
|
|
2916
|
+
const memberQName = filter2.attributes["member.qname"];
|
|
2917
|
+
const axisId = dimensionQName ? ctx.dimensionQNameToId.get(dimensionQName) : void 0;
|
|
2918
|
+
const memberId = memberQName ? ctx.memberQNameToId.get(memberQName) : void 0;
|
|
2919
|
+
if (!axisId)
|
|
2920
|
+
return [];
|
|
2921
|
+
return universe.filter((candidate) => columnMatchesExplicitDimension(getColumn(ctx, candidate.columnId), axisId, memberId));
|
|
2922
|
+
}
|
|
2923
|
+
case "TYPED_DIMENSION": {
|
|
2924
|
+
const dimensionQName = filter2.attributes["dimension.qname"];
|
|
2925
|
+
const axisId = dimensionQName ? ctx.dimensionQNameToId.get(dimensionQName) : void 0;
|
|
2926
|
+
if (!axisId)
|
|
2927
|
+
return [];
|
|
2928
|
+
return universe.filter((candidate) => columnMatchesTypedDimension(getColumn(ctx, candidate.columnId), axisId));
|
|
2929
|
+
}
|
|
2930
|
+
case "PERIOD_INSTANT":
|
|
2931
|
+
case "PERIOD_END": {
|
|
2932
|
+
const dateAttribute = filter2.attributes["date"];
|
|
2933
|
+
return universe.filter((candidate) => columnMatchesPeriod(getColumn(ctx, candidate.columnId), dateAttribute, ctx));
|
|
2934
|
+
}
|
|
2935
|
+
case "OR_FILTER":
|
|
2936
|
+
return unionCandidates(filter2.children.map((child) => resolveFilter(child, universe, ctx)));
|
|
2937
|
+
case "ASPECT_COVER":
|
|
2938
|
+
return universe;
|
|
2939
|
+
default:
|
|
2940
|
+
return [];
|
|
2941
|
+
}
|
|
2942
|
+
}
|
|
2943
|
+
function resolveFilter(filter2, universe, ctx) {
|
|
2944
|
+
const matched = matchFilter(filter2, universe, ctx);
|
|
2945
|
+
if (!filter2.complement)
|
|
2946
|
+
return matched;
|
|
2947
|
+
const matchedKeys = new Set(matched.map(candidateKey));
|
|
2948
|
+
return universe.filter((candidate) => !matchedKeys.has(candidateKey(candidate)));
|
|
2949
|
+
}
|
|
2950
|
+
function intersectCandidates(sets) {
|
|
2951
|
+
if (sets.length === 0)
|
|
2952
|
+
return [];
|
|
2953
|
+
return sets.reduce((acc, set) => {
|
|
2954
|
+
const setKeys = new Set(set.map(candidateKey));
|
|
2955
|
+
return acc.filter((candidate) => setKeys.has(candidateKey(candidate)));
|
|
2956
|
+
});
|
|
2957
|
+
}
|
|
2958
|
+
function resolveFormulaVariable(variable, ctx) {
|
|
2959
|
+
const matched = resolveMatchedCandidates(variable, ctx);
|
|
2960
|
+
const values = matched.map((candidate) => {
|
|
2961
|
+
var _a;
|
|
2962
|
+
return parseFloat((_a = ctx.formData[candidate.conceptId]) == null ? void 0 : _a[candidate.columnId]);
|
|
2963
|
+
}).filter((value) => !Number.isNaN(value));
|
|
2964
|
+
if (variable.bindAsSequence) {
|
|
2965
|
+
if (values.length === 0 && variable.fallbackValue === "()")
|
|
2966
|
+
return [];
|
|
2967
|
+
if (values.length === 0)
|
|
2968
|
+
return void 0;
|
|
2969
|
+
return values;
|
|
2970
|
+
}
|
|
2971
|
+
if (values.length === 0)
|
|
2972
|
+
return void 0;
|
|
2973
|
+
if (values.length > 1) {
|
|
2974
|
+
console.warn(
|
|
2975
|
+
`[formula-variable-resolver] Variable "${variable.name}" is scalar (bindAsSequence: false) but matched ${values.length} facts; using the first match by column order. This can legitimately happen when filters under-constrain the candidate set.`
|
|
2976
|
+
);
|
|
2977
|
+
}
|
|
2978
|
+
return values[0];
|
|
2979
|
+
}
|
|
2980
|
+
function resolveFormulaVariableMatchCount(variable, ctx) {
|
|
2981
|
+
return resolveMatchedCandidates(variable, ctx).length;
|
|
2982
|
+
}
|
|
2983
|
+
function resolveFormulaVariableUsedFallback(variable, ctx) {
|
|
2984
|
+
const matchCount = resolveFormulaVariableMatchCount(variable, ctx);
|
|
2985
|
+
if (matchCount > 0)
|
|
2986
|
+
return false;
|
|
2987
|
+
if (variable.fallbackValue !== void 0)
|
|
2988
|
+
return true;
|
|
2989
|
+
return void 0;
|
|
2990
|
+
}
|
|
2991
|
+
function collectConceptNameQNames(filters) {
|
|
2992
|
+
const qnames = [];
|
|
2993
|
+
for (const filter2 of filters) {
|
|
2994
|
+
if (filter2.type === "CONCEPT_NAME") {
|
|
2995
|
+
const qname = filter2.attributes["concept.qname"];
|
|
2996
|
+
if (qname)
|
|
2997
|
+
qnames.push(qname);
|
|
2998
|
+
} else if (filter2.type === "OR_FILTER") {
|
|
2999
|
+
qnames.push(...collectConceptNameQNames(filter2.children));
|
|
3000
|
+
}
|
|
3001
|
+
}
|
|
3002
|
+
return qnames;
|
|
3003
|
+
}
|
|
3004
|
+
function resolveVariableConceptQNames(variable) {
|
|
3005
|
+
return collectConceptNameQNames(variable.filters);
|
|
3006
|
+
}
|
|
3007
|
+
function resolveVariableColumnsForConcept(variable, targetConceptId, ctx) {
|
|
3008
|
+
const universe = ctx.columns.map((column2) => ({ conceptId: targetConceptId, columnId: column2.id }));
|
|
3009
|
+
const resolved = intersectCandidates(variable.filters.map((filter2) => resolveFilter(filter2, universe, ctx)));
|
|
3010
|
+
return resolved.map((candidate) => candidate.columnId);
|
|
3011
|
+
}
|
|
3012
|
+
function buildAssertionBindings(assertion, ctx) {
|
|
3013
|
+
const bindings = /* @__PURE__ */ new Map();
|
|
3014
|
+
for (const variable of assertion.variables) {
|
|
3015
|
+
bindings.set(variable.name, resolveFormulaVariable(variable, ctx));
|
|
3016
|
+
}
|
|
3017
|
+
return bindings;
|
|
3018
|
+
}
|
|
3019
|
+
function buildAssertionFallbackUsage(assertion, ctx) {
|
|
3020
|
+
var _a;
|
|
3021
|
+
const usesHasFallbackValue = ((_a = assertion.test) == null ? void 0 : _a.includes("has-fallback-value")) || assertion.preconditions.some((precondition) => precondition.test.includes("has-fallback-value"));
|
|
3022
|
+
if (!usesHasFallbackValue)
|
|
3023
|
+
return /* @__PURE__ */ new Map();
|
|
3024
|
+
const fallbackUsage = /* @__PURE__ */ new Map();
|
|
3025
|
+
for (const variable of assertion.variables) {
|
|
3026
|
+
const usedFallback = resolveFormulaVariableUsedFallback(variable, ctx);
|
|
3027
|
+
if (usedFallback !== void 0)
|
|
3028
|
+
fallbackUsage.set(variable.name, usedFallback);
|
|
3029
|
+
}
|
|
3030
|
+
return fallbackUsage;
|
|
3031
|
+
}
|
|
3032
|
+
function evaluateAssertionPreconditions(preconditions, bindings, fallbackUsage = /* @__PURE__ */ new Map()) {
|
|
3033
|
+
if (preconditions.length === 0)
|
|
3034
|
+
return { satisfied: true };
|
|
3035
|
+
for (const precondition of preconditions) {
|
|
3036
|
+
let result;
|
|
3037
|
+
try {
|
|
3038
|
+
result = evaluateFormulaTest(precondition.test, bindings, fallbackUsage);
|
|
3039
|
+
} catch (error2) {
|
|
3040
|
+
if (error2 instanceof FormulaExpressionError) {
|
|
3041
|
+
return { satisfied: false, skipReason: "unresolvable" };
|
|
3042
|
+
}
|
|
3043
|
+
throw error2;
|
|
3044
|
+
}
|
|
3045
|
+
if (!result) {
|
|
3046
|
+
return { satisfied: false, skipReason: "precondition" };
|
|
3047
|
+
}
|
|
3048
|
+
}
|
|
3049
|
+
return { satisfied: true };
|
|
3050
|
+
}
|
|
3051
|
+
class FormulaValidationService {
|
|
3052
|
+
/**
|
|
3053
|
+
* Evaluates every assertion in `xbrlInput.formula[0].roles` (only the first entrypoint,
|
|
3054
|
+
* consistent with how xbrl-form-builder.ts uses presentation/hypercube data) against the
|
|
3055
|
+
* given resolution context. One bad assertion never aborts the other 783 — resolution/
|
|
3056
|
+
* evaluation errors are caught per-assertion and recorded as skipped, not thrown.
|
|
3057
|
+
*/
|
|
3058
|
+
evaluate(xbrlInput, ctx, language) {
|
|
3059
|
+
var _a;
|
|
3060
|
+
const formulaData = (_a = xbrlInput.formula) == null ? void 0 : _a[0];
|
|
3061
|
+
if (!formulaData)
|
|
3062
|
+
return [];
|
|
3063
|
+
const results = [];
|
|
3064
|
+
for (const role of formulaData.roles) {
|
|
3065
|
+
for (const assertion of role.assertions) {
|
|
3066
|
+
results.push(this._evaluateAssertion(assertion, role, ctx, language));
|
|
3067
|
+
}
|
|
3068
|
+
}
|
|
3069
|
+
return results;
|
|
3070
|
+
}
|
|
3071
|
+
summarize(results) {
|
|
3072
|
+
const summary = {
|
|
3073
|
+
totalAssertions: results.length,
|
|
3074
|
+
evaluated: 0,
|
|
3075
|
+
skipped: 0,
|
|
3076
|
+
passed: 0,
|
|
3077
|
+
failed: 0,
|
|
3078
|
+
failedWarnings: 0,
|
|
3079
|
+
failedErrors: 0
|
|
3080
|
+
};
|
|
3081
|
+
for (const result of results) {
|
|
3082
|
+
if (result.skipped) {
|
|
3083
|
+
summary.skipped += 1;
|
|
3084
|
+
continue;
|
|
3085
|
+
}
|
|
3086
|
+
summary.evaluated += 1;
|
|
3087
|
+
if (result.satisfied) {
|
|
3088
|
+
summary.passed += 1;
|
|
3089
|
+
} else {
|
|
3090
|
+
summary.failed += 1;
|
|
3091
|
+
if (result.severity === "ERROR")
|
|
3092
|
+
summary.failedErrors += 1;
|
|
3093
|
+
else
|
|
3094
|
+
summary.failedWarnings += 1;
|
|
3095
|
+
}
|
|
3096
|
+
}
|
|
3097
|
+
return summary;
|
|
3098
|
+
}
|
|
3099
|
+
_evaluateAssertion(assertion, role, ctx, language) {
|
|
3100
|
+
try {
|
|
3101
|
+
const bindings = buildAssertionBindings(assertion, ctx);
|
|
3102
|
+
const fallbackUsage = buildAssertionFallbackUsage(assertion, ctx);
|
|
3103
|
+
const precondition = evaluateAssertionPreconditions(assertion.preconditions, bindings, fallbackUsage);
|
|
3104
|
+
if (!precondition.satisfied) {
|
|
3105
|
+
return this._skippedResult(assertion, role, precondition.skipReason ?? "unresolvable");
|
|
3106
|
+
}
|
|
3107
|
+
if (assertion.type === "EXISTENCE_ASSERTION") {
|
|
3108
|
+
const matchedFactCount = resolveFormulaVariableMatchCount(assertion.variables[0], ctx);
|
|
3109
|
+
const satisfied2 = evaluateExistenceTest(assertion.test, matchedFactCount);
|
|
3110
|
+
return this._evaluatedResult(assertion, role, ctx, satisfied2, language, matchedFactCount);
|
|
3111
|
+
}
|
|
3112
|
+
const satisfied = evaluateFormulaTest(assertion.test, bindings, fallbackUsage);
|
|
3113
|
+
return this._evaluatedResult(assertion, role, ctx, satisfied, language);
|
|
3114
|
+
} catch (error2) {
|
|
3115
|
+
if (error2 instanceof FormulaExpressionError) {
|
|
3116
|
+
console.warn(`[FormulaValidationService] Assertion "${assertion.id}" could not be evaluated (${error2.reason}): ${error2.message}`);
|
|
3117
|
+
return this._skippedResult(assertion, role, "unresolvable");
|
|
3118
|
+
}
|
|
3119
|
+
throw error2;
|
|
3120
|
+
}
|
|
3121
|
+
}
|
|
3122
|
+
_skippedResult(assertion, role, skipReason) {
|
|
3123
|
+
return {
|
|
3124
|
+
assertionId: assertion.id,
|
|
3125
|
+
roleURI: role.roleURI,
|
|
3126
|
+
roleLabel: role.role,
|
|
3127
|
+
type: assertion.type,
|
|
3128
|
+
severity: assertion.severity,
|
|
3129
|
+
satisfied: false,
|
|
3130
|
+
skipped: true,
|
|
3131
|
+
skipReason
|
|
3132
|
+
};
|
|
3133
|
+
}
|
|
3134
|
+
_evaluatedResult(assertion, role, ctx, satisfied, language, matchedFactCount) {
|
|
3135
|
+
const message = satisfied ? void 0 : this._pickMessage(assertion, language);
|
|
3136
|
+
return {
|
|
3137
|
+
assertionId: assertion.id,
|
|
3138
|
+
roleURI: role.roleURI,
|
|
3139
|
+
roleLabel: role.role,
|
|
3140
|
+
type: assertion.type,
|
|
3141
|
+
severity: assertion.severity,
|
|
3142
|
+
satisfied,
|
|
3143
|
+
skipped: false,
|
|
3144
|
+
message,
|
|
3145
|
+
matchedFactCount,
|
|
3146
|
+
conceptLinks: message ? this._buildConceptLinks(assertion, role.roleURI, ctx, message) : void 0
|
|
3147
|
+
};
|
|
3148
|
+
}
|
|
3149
|
+
_pickMessage(assertion, language) {
|
|
3150
|
+
const messages = assertion.messages;
|
|
3151
|
+
if (messages.length === 0)
|
|
3152
|
+
return void 0;
|
|
3153
|
+
const message = messages.find((m) => m.xmlLang === language) ?? messages.find((m) => m.xmlLang === "en") ?? messages[0];
|
|
3154
|
+
return this._stripTechnicalDetail(message.text);
|
|
3155
|
+
}
|
|
3156
|
+
/**
|
|
3157
|
+
* Taxonomy-authored messages append raw XBRL Formula/XPath debug expressions after the
|
|
3158
|
+
* human-readable sentence, delimited by " | {...}" (e.g. `xff:has-fallback-value(...)`,
|
|
3159
|
+
* `varArc_...` variable names) — see the fixture's `*_formula.json` message text. That debug
|
|
3160
|
+
* payload is meaningless to a non-technical filer, so only the sentence preceding it is shown.
|
|
3161
|
+
*/
|
|
3162
|
+
_stripTechnicalDetail(text) {
|
|
3163
|
+
const braceIndex = text.indexOf("{");
|
|
3164
|
+
if (braceIndex === -1)
|
|
3165
|
+
return text.trim();
|
|
3166
|
+
return text.slice(0, braceIndex).replace(/\|\s*$/, "").trim();
|
|
3167
|
+
}
|
|
3168
|
+
/**
|
|
3169
|
+
* JDF-059: resolves every concept the assertion's variables name directly (JDF-045's
|
|
3170
|
+
* `resolveVariableConceptQNames`) to a clickable fact location — but only the ones the
|
|
3171
|
+
* (already-stripped) message text actually mentions by backtick-quoted local name, e.g.
|
|
3172
|
+
* `` `Equity` `` — a concept a variable references internally (say, as a dimensional
|
|
3173
|
+
* exclusion) but the message never calls out by name has nothing for the user to click on, so
|
|
3174
|
+
* it's left out rather than guessed at. Column resolution reuses the assertion's own filters
|
|
3175
|
+
* (`resolveVariableColumnsForConcept`), so the link always points at the exact fact this
|
|
3176
|
+
* specific assertion run cared about — never just "some field for this concept" — including an
|
|
3177
|
+
* empty one for a failed "MUST exist" assertion, so the user can navigate straight to where the
|
|
3178
|
+
* missing value belongs.
|
|
3179
|
+
*/
|
|
3180
|
+
_buildConceptLinks(assertion, roleURI, ctx, message) {
|
|
3181
|
+
var _a, _b, _c;
|
|
3182
|
+
const links = [];
|
|
3183
|
+
const seenLabels = /* @__PURE__ */ new Set();
|
|
3184
|
+
for (const variable of assertion.variables) {
|
|
3185
|
+
for (const qname of resolveVariableConceptQNames(variable)) {
|
|
3186
|
+
const conceptId = ((_a = ctx.conceptIdByQNamePerRole.get(roleURI)) == null ? void 0 : _a.get(qname)) ?? ((_c = (_b = ctx.conceptByQName.get(qname)) == null ? void 0 : _b[0]) == null ? void 0 : _c.conceptId);
|
|
3187
|
+
if (!conceptId)
|
|
3188
|
+
continue;
|
|
3189
|
+
const label = qname.includes(":") ? qname.split(":").pop() : qname;
|
|
3190
|
+
if (seenLabels.has(label))
|
|
3191
|
+
continue;
|
|
3192
|
+
if (!new RegExp("`" + this._escapeRegExp(label) + "`").test(message))
|
|
3193
|
+
continue;
|
|
3194
|
+
const columns = resolveVariableColumnsForConcept(variable, conceptId, ctx);
|
|
3195
|
+
links.push({ label, conceptQName: qname, conceptId, columnId: columns[0] });
|
|
3196
|
+
seenLabels.add(label);
|
|
3197
|
+
}
|
|
3198
|
+
}
|
|
3199
|
+
return links;
|
|
3200
|
+
}
|
|
3201
|
+
_escapeRegExp(text) {
|
|
3202
|
+
return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3203
|
+
}
|
|
3204
|
+
}
|
|
2303
3205
|
class FactMatcher {
|
|
2304
3206
|
/**
|
|
2305
3207
|
* Find a matching fact for a given cell context
|
|
@@ -3153,15 +4055,15 @@ function determineInputTypeFromBaseChain(baseTypeChain, datatypes) {
|
|
|
3153
4055
|
placeholder: I18n.t("field.enterValue")
|
|
3154
4056
|
};
|
|
3155
4057
|
}
|
|
3156
|
-
var __defProp$
|
|
3157
|
-
var __getOwnPropDesc$
|
|
3158
|
-
var __decorateClass$
|
|
3159
|
-
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$
|
|
4058
|
+
var __defProp$7 = Object.defineProperty;
|
|
4059
|
+
var __getOwnPropDesc$7 = Object.getOwnPropertyDescriptor;
|
|
4060
|
+
var __decorateClass$7 = (decorators, target, key, kind) => {
|
|
4061
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$7(target, key) : target;
|
|
3160
4062
|
for (var i2 = decorators.length - 1, decorator; i2 >= 0; i2--)
|
|
3161
4063
|
if (decorator = decorators[i2])
|
|
3162
4064
|
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
3163
4065
|
if (kind && result)
|
|
3164
|
-
__defProp$
|
|
4066
|
+
__defProp$7(target, key, result);
|
|
3165
4067
|
return result;
|
|
3166
4068
|
};
|
|
3167
4069
|
let JupiterFormField = class extends LitElement {
|
|
@@ -4178,6 +5080,7 @@ let JupiterFormField = class extends LitElement {
|
|
|
4178
5080
|
<button
|
|
4179
5081
|
class="period-icon-btn"
|
|
4180
5082
|
type="button"
|
|
5083
|
+
tabindex="-1"
|
|
4181
5084
|
@click="${this._handlePeriodIconClick}"
|
|
4182
5085
|
title="Edit period"
|
|
4183
5086
|
>
|
|
@@ -4674,99 +5577,99 @@ JupiterFormField.styles = css`
|
|
|
4674
5577
|
animation: concept-highlight-pulse 10s ease-out forwards;
|
|
4675
5578
|
}
|
|
4676
5579
|
`;
|
|
4677
|
-
__decorateClass$
|
|
5580
|
+
__decorateClass$7([
|
|
4678
5581
|
n2({ type: Object })
|
|
4679
5582
|
], JupiterFormField.prototype, "field", 2);
|
|
4680
|
-
__decorateClass$
|
|
5583
|
+
__decorateClass$7([
|
|
4681
5584
|
n2({ type: String })
|
|
4682
5585
|
], JupiterFormField.prototype, "conceptId", 2);
|
|
4683
|
-
__decorateClass$
|
|
5586
|
+
__decorateClass$7([
|
|
4684
5587
|
n2({ type: String })
|
|
4685
5588
|
], JupiterFormField.prototype, "conceptType", 2);
|
|
4686
|
-
__decorateClass$
|
|
5589
|
+
__decorateClass$7([
|
|
4687
5590
|
n2({ type: Array })
|
|
4688
5591
|
], JupiterFormField.prototype, "datatypes", 2);
|
|
4689
|
-
__decorateClass$
|
|
5592
|
+
__decorateClass$7([
|
|
4690
5593
|
n2({ type: Array })
|
|
4691
5594
|
], JupiterFormField.prototype, "defaultUnits", 2);
|
|
4692
|
-
__decorateClass$
|
|
5595
|
+
__decorateClass$7([
|
|
4693
5596
|
n2({ type: String })
|
|
4694
5597
|
], JupiterFormField.prototype, "columnId", 2);
|
|
4695
|
-
__decorateClass$
|
|
5598
|
+
__decorateClass$7([
|
|
4696
5599
|
n2()
|
|
4697
5600
|
], JupiterFormField.prototype, "value", 2);
|
|
4698
|
-
__decorateClass$
|
|
5601
|
+
__decorateClass$7([
|
|
4699
5602
|
n2({ type: Boolean })
|
|
4700
5603
|
], JupiterFormField.prototype, "disabled", 2);
|
|
4701
|
-
__decorateClass$
|
|
5604
|
+
__decorateClass$7([
|
|
4702
5605
|
n2({ type: String })
|
|
4703
5606
|
], JupiterFormField.prototype, "locale", 2);
|
|
4704
|
-
__decorateClass$
|
|
5607
|
+
__decorateClass$7([
|
|
4705
5608
|
n2({ type: Boolean })
|
|
4706
5609
|
], JupiterFormField.prototype, "hideLabel", 2);
|
|
4707
|
-
__decorateClass$
|
|
5610
|
+
__decorateClass$7([
|
|
4708
5611
|
n2({ type: String })
|
|
4709
5612
|
], JupiterFormField.prototype, "mode", 2);
|
|
4710
|
-
__decorateClass$
|
|
5613
|
+
__decorateClass$7([
|
|
4711
5614
|
n2({ type: Object })
|
|
4712
5615
|
], JupiterFormField.prototype, "masterData", 2);
|
|
4713
|
-
__decorateClass$
|
|
5616
|
+
__decorateClass$7([
|
|
4714
5617
|
n2({ type: Array })
|
|
4715
5618
|
], JupiterFormField.prototype, "facts", 2);
|
|
4716
|
-
__decorateClass$
|
|
5619
|
+
__decorateClass$7([
|
|
4717
5620
|
n2({ type: Object })
|
|
4718
5621
|
], JupiterFormField.prototype, "column", 2);
|
|
4719
|
-
__decorateClass$
|
|
5622
|
+
__decorateClass$7([
|
|
4720
5623
|
n2({ type: String })
|
|
4721
5624
|
], JupiterFormField.prototype, "periodStartDate", 2);
|
|
4722
|
-
__decorateClass$
|
|
5625
|
+
__decorateClass$7([
|
|
4723
5626
|
n2({ type: String })
|
|
4724
5627
|
], JupiterFormField.prototype, "periodEndDate", 2);
|
|
4725
|
-
__decorateClass$
|
|
5628
|
+
__decorateClass$7([
|
|
4726
5629
|
n2({ type: String })
|
|
4727
5630
|
], JupiterFormField.prototype, "periodInstantDate", 2);
|
|
4728
|
-
__decorateClass$
|
|
5631
|
+
__decorateClass$7([
|
|
4729
5632
|
n2({ type: String })
|
|
4730
5633
|
], JupiterFormField.prototype, "unit", 2);
|
|
4731
|
-
__decorateClass$
|
|
5634
|
+
__decorateClass$7([
|
|
4732
5635
|
n2({ type: String })
|
|
4733
5636
|
], JupiterFormField.prototype, "decimals", 2);
|
|
4734
|
-
__decorateClass$
|
|
5637
|
+
__decorateClass$7([
|
|
4735
5638
|
n2({ type: String })
|
|
4736
5639
|
], JupiterFormField.prototype, "globalDecimals", 2);
|
|
4737
|
-
__decorateClass$
|
|
5640
|
+
__decorateClass$7([
|
|
4738
5641
|
n2({ type: Object })
|
|
4739
5642
|
], JupiterFormField.prototype, "typedMemberValues", 2);
|
|
4740
|
-
__decorateClass$
|
|
5643
|
+
__decorateClass$7([
|
|
4741
5644
|
r()
|
|
4742
5645
|
], JupiterFormField.prototype, "_errors", 2);
|
|
4743
|
-
__decorateClass$
|
|
5646
|
+
__decorateClass$7([
|
|
4744
5647
|
r()
|
|
4745
5648
|
], JupiterFormField.prototype, "_xbrlErrors", 2);
|
|
4746
|
-
__decorateClass$
|
|
5649
|
+
__decorateClass$7([
|
|
4747
5650
|
r()
|
|
4748
5651
|
], JupiterFormField.prototype, "_touched", 2);
|
|
4749
|
-
__decorateClass$
|
|
5652
|
+
__decorateClass$7([
|
|
4750
5653
|
r()
|
|
4751
5654
|
], JupiterFormField.prototype, "_showPeriodPopup", 2);
|
|
4752
|
-
__decorateClass$
|
|
5655
|
+
__decorateClass$7([
|
|
4753
5656
|
r()
|
|
4754
5657
|
], JupiterFormField.prototype, "_availableUnits", 2);
|
|
4755
|
-
__decorateClass$
|
|
5658
|
+
__decorateClass$7([
|
|
4756
5659
|
r()
|
|
4757
5660
|
], JupiterFormField.prototype, "_numericDraftValue", 2);
|
|
4758
|
-
JupiterFormField = __decorateClass$
|
|
5661
|
+
JupiterFormField = __decorateClass$7([
|
|
4759
5662
|
t$1("jupiter-form-field")
|
|
4760
5663
|
], JupiterFormField);
|
|
4761
|
-
var __defProp$
|
|
4762
|
-
var __getOwnPropDesc$
|
|
4763
|
-
var __decorateClass$
|
|
4764
|
-
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$
|
|
5664
|
+
var __defProp$6 = Object.defineProperty;
|
|
5665
|
+
var __getOwnPropDesc$6 = Object.getOwnPropertyDescriptor;
|
|
5666
|
+
var __decorateClass$6 = (decorators, target, key, kind) => {
|
|
5667
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$6(target, key) : target;
|
|
4765
5668
|
for (var i2 = decorators.length - 1, decorator; i2 >= 0; i2--)
|
|
4766
5669
|
if (decorator = decorators[i2])
|
|
4767
5670
|
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
4768
5671
|
if (kind && result)
|
|
4769
|
-
__defProp$
|
|
5672
|
+
__defProp$6(target, key, result);
|
|
4770
5673
|
return result;
|
|
4771
5674
|
};
|
|
4772
5675
|
let JupiterConceptTree = class extends LitElement {
|
|
@@ -5036,6 +5939,7 @@ let JupiterConceptTree = class extends LitElement {
|
|
|
5036
5939
|
const hasChildren = this.concept.children && this.concept.children.length > 0;
|
|
5037
5940
|
const level = this.concept.level || 0;
|
|
5038
5941
|
const isAbstract = this.concept.abstract || false;
|
|
5942
|
+
const isTotal = isTotalLabel$1(this.concept.preferredLabel);
|
|
5039
5943
|
return html`
|
|
5040
5944
|
<!-- Concept Name Cell (Left Column) -->
|
|
5041
5945
|
<td class="concept-name-cell ${isAbstract ? "abstract" : hasChildren ? "" : "leaf"} ${this.rowFocused ? "row-focused" : ""}">
|
|
@@ -5045,7 +5949,7 @@ let JupiterConceptTree = class extends LitElement {
|
|
|
5045
5949
|
@click="${this._toggleExpanded}">
|
|
5046
5950
|
${hasChildren ? "▶" : ""}
|
|
5047
5951
|
</div>
|
|
5048
|
-
<div class="concept-label"
|
|
5952
|
+
<div class="concept-label ${isTotal ? "total-concept-label" : ""}"
|
|
5049
5953
|
@click="${this._toggleExpanded}"
|
|
5050
5954
|
title="${this.concept.id}${this.concept.description ? " - " + this.concept.description : ""}">
|
|
5051
5955
|
${this.concept.label}
|
|
@@ -5053,14 +5957,14 @@ let JupiterConceptTree = class extends LitElement {
|
|
|
5053
5957
|
${this.concept.balance ? html`
|
|
5054
5958
|
<div class="concept-balance ${this.concept.balance}">${this.concept.balance}</div>
|
|
5055
5959
|
` : ""}
|
|
5056
|
-
<button class="concept-info-btn" type="button" title="${I18n.t("conceptInfo.title")}"
|
|
5960
|
+
<button class="concept-info-btn" type="button" tabindex="-1" title="${I18n.t("conceptInfo.title")}"
|
|
5057
5961
|
@click="${this._openInfoDialog}">ℹ</button>
|
|
5058
5962
|
${this.showAddButton ? html`
|
|
5059
|
-
<button class="repeat-btn" type="button" title="Add row"
|
|
5963
|
+
<button class="repeat-btn" type="button" tabindex="-1" title="Add row"
|
|
5060
5964
|
@click="${this._handleAddRepeat}">+</button>
|
|
5061
5965
|
` : ""}
|
|
5062
5966
|
${this.showRemoveButton ? html`
|
|
5063
|
-
<button class="repeat-btn remove" type="button" title="Remove row"
|
|
5967
|
+
<button class="repeat-btn remove" type="button" tabindex="-1" title="Remove row"
|
|
5064
5968
|
@click="${this._handleRemoveRepeat}">−</button>
|
|
5065
5969
|
` : ""}
|
|
5066
5970
|
</div>
|
|
@@ -5078,11 +5982,12 @@ let JupiterConceptTree = class extends LitElement {
|
|
|
5078
5982
|
const storedDecimals = (_d = (_c = this.decimalsData) == null ? void 0 : _c[this.concept.id]) == null ? void 0 : _d[column2.id];
|
|
5079
5983
|
const calcMismatch = this.mode !== "readonly" ? (_e = this.calculationMismatches) == null ? void 0 : _e.get(`${this.concept.id}__${column2.id}`) : void 0;
|
|
5080
5984
|
return html`
|
|
5081
|
-
<td class="field-cell ${!shouldShowField ? "empty" : ""} ${isAbstract ? "abstract-row" : ""} ${this.highlightType && column2.id === this.highlightColumnId ? "highlight-" + this.highlightType : ""} ${calcMismatch ? "calc-warning" : ""} ${this.rowFocused ? "row-focused" : ""}">
|
|
5985
|
+
<td class="field-cell ${!shouldShowField ? "empty" : ""} ${isAbstract ? "abstract-row" : ""} ${isTotal ? "total-row" : ""} ${this.highlightType && column2.id === this.highlightColumnId ? "highlight-" + this.highlightType : ""} ${calcMismatch ? "calc-warning" : ""} ${this.rowFocused ? "row-focused" : ""}">
|
|
5082
5986
|
${calcMismatch ? html`
|
|
5083
5987
|
<button
|
|
5084
5988
|
class="calc-warning-badge"
|
|
5085
5989
|
type="button"
|
|
5990
|
+
tabindex="-1"
|
|
5086
5991
|
title="${calcMismatch.message}"
|
|
5087
5992
|
@click="${(e2) => this._openCalculationWarningDialog(e2, calcMismatch)}"
|
|
5088
5993
|
>!</button>
|
|
@@ -5199,6 +6104,10 @@ JupiterConceptTree.styles = css`
|
|
|
5199
6104
|
min-width: 0; /* Allows flex item to shrink below content size */
|
|
5200
6105
|
}
|
|
5201
6106
|
|
|
6107
|
+
.concept-label.total-concept-label {
|
|
6108
|
+
font-weight: 700;
|
|
6109
|
+
}
|
|
6110
|
+
|
|
5202
6111
|
.concept-balance {
|
|
5203
6112
|
margin-left: 8px;
|
|
5204
6113
|
font-size: 11px;
|
|
@@ -5290,6 +6199,10 @@ JupiterConceptTree.styles = css`
|
|
|
5290
6199
|
color: #fff;
|
|
5291
6200
|
}
|
|
5292
6201
|
|
|
6202
|
+
.field-cell.total-row {
|
|
6203
|
+
background: var(--jupiter-total-cell-background, rgba(0, 0, 0, 0.045));
|
|
6204
|
+
}
|
|
6205
|
+
|
|
5293
6206
|
.field-cell.highlight-total {
|
|
5294
6207
|
background: rgba(25, 118, 210, 0.15);
|
|
5295
6208
|
}
|
|
@@ -5395,90 +6308,90 @@ JupiterConceptTree.styles = css`
|
|
|
5395
6308
|
}
|
|
5396
6309
|
|
|
5397
6310
|
`;
|
|
5398
|
-
__decorateClass$
|
|
6311
|
+
__decorateClass$6([
|
|
5399
6312
|
n2({ type: Object })
|
|
5400
6313
|
], JupiterConceptTree.prototype, "concept", 2);
|
|
5401
|
-
__decorateClass$
|
|
6314
|
+
__decorateClass$6([
|
|
5402
6315
|
n2({ type: Array })
|
|
5403
6316
|
], JupiterConceptTree.prototype, "columns", 2);
|
|
5404
|
-
__decorateClass$
|
|
6317
|
+
__decorateClass$6([
|
|
5405
6318
|
n2({ type: Object })
|
|
5406
6319
|
], JupiterConceptTree.prototype, "formData", 2);
|
|
5407
|
-
__decorateClass$
|
|
6320
|
+
__decorateClass$6([
|
|
5408
6321
|
n2({ type: Object })
|
|
5409
6322
|
], JupiterConceptTree.prototype, "periodData", 2);
|
|
5410
|
-
__decorateClass$
|
|
6323
|
+
__decorateClass$6([
|
|
5411
6324
|
n2({ type: Object })
|
|
5412
6325
|
], JupiterConceptTree.prototype, "unitData", 2);
|
|
5413
|
-
__decorateClass$
|
|
6326
|
+
__decorateClass$6([
|
|
5414
6327
|
n2({ type: Object })
|
|
5415
6328
|
], JupiterConceptTree.prototype, "decimalsData", 2);
|
|
5416
|
-
__decorateClass$
|
|
6329
|
+
__decorateClass$6([
|
|
5417
6330
|
n2({ type: String })
|
|
5418
6331
|
], JupiterConceptTree.prototype, "globalDecimals", 2);
|
|
5419
|
-
__decorateClass$
|
|
6332
|
+
__decorateClass$6([
|
|
5420
6333
|
n2({ type: Array })
|
|
5421
6334
|
], JupiterConceptTree.prototype, "defaultUnits", 2);
|
|
5422
|
-
__decorateClass$
|
|
6335
|
+
__decorateClass$6([
|
|
5423
6336
|
n2({ type: Boolean })
|
|
5424
6337
|
], JupiterConceptTree.prototype, "disabled", 2);
|
|
5425
|
-
__decorateClass$
|
|
6338
|
+
__decorateClass$6([
|
|
5426
6339
|
n2({ type: String })
|
|
5427
6340
|
], JupiterConceptTree.prototype, "locale", 2);
|
|
5428
|
-
__decorateClass$
|
|
6341
|
+
__decorateClass$6([
|
|
5429
6342
|
n2({ type: Set })
|
|
5430
6343
|
], JupiterConceptTree.prototype, "expandedConcepts", 2);
|
|
5431
|
-
__decorateClass$
|
|
6344
|
+
__decorateClass$6([
|
|
5432
6345
|
n2({ type: Array })
|
|
5433
6346
|
], JupiterConceptTree.prototype, "datatypes", 2);
|
|
5434
|
-
__decorateClass$
|
|
6347
|
+
__decorateClass$6([
|
|
5435
6348
|
n2({ type: String })
|
|
5436
6349
|
], JupiterConceptTree.prototype, "mode", 2);
|
|
5437
|
-
__decorateClass$
|
|
6350
|
+
__decorateClass$6([
|
|
5438
6351
|
n2({ type: Object })
|
|
5439
6352
|
], JupiterConceptTree.prototype, "masterData", 2);
|
|
5440
|
-
__decorateClass$
|
|
6353
|
+
__decorateClass$6([
|
|
5441
6354
|
n2({ type: Array })
|
|
5442
6355
|
], JupiterConceptTree.prototype, "facts", 2);
|
|
5443
|
-
__decorateClass$
|
|
6356
|
+
__decorateClass$6([
|
|
5444
6357
|
n2({ type: Object })
|
|
5445
6358
|
], JupiterConceptTree.prototype, "typedMemberData", 2);
|
|
5446
|
-
__decorateClass$
|
|
6359
|
+
__decorateClass$6([
|
|
5447
6360
|
n2({ type: Boolean })
|
|
5448
6361
|
], JupiterConceptTree.prototype, "showAddButton", 2);
|
|
5449
|
-
__decorateClass$
|
|
6362
|
+
__decorateClass$6([
|
|
5450
6363
|
n2({ type: Boolean })
|
|
5451
6364
|
], JupiterConceptTree.prototype, "showRemoveButton", 2);
|
|
5452
|
-
__decorateClass$
|
|
6365
|
+
__decorateClass$6([
|
|
5453
6366
|
n2({ type: String })
|
|
5454
6367
|
], JupiterConceptTree.prototype, "highlightType", 2);
|
|
5455
|
-
__decorateClass$
|
|
6368
|
+
__decorateClass$6([
|
|
5456
6369
|
n2({ type: String })
|
|
5457
6370
|
], JupiterConceptTree.prototype, "highlightColumnId", 2);
|
|
5458
|
-
__decorateClass$
|
|
6371
|
+
__decorateClass$6([
|
|
5459
6372
|
n2({ type: Object })
|
|
5460
6373
|
], JupiterConceptTree.prototype, "calculationMismatches", 2);
|
|
5461
|
-
__decorateClass$
|
|
6374
|
+
__decorateClass$6([
|
|
5462
6375
|
n2({ type: String })
|
|
5463
6376
|
], JupiterConceptTree.prototype, "language", 2);
|
|
5464
|
-
__decorateClass$
|
|
6377
|
+
__decorateClass$6([
|
|
5465
6378
|
n2({ type: Boolean })
|
|
5466
6379
|
], JupiterConceptTree.prototype, "rowFocused", 2);
|
|
5467
|
-
__decorateClass$
|
|
6380
|
+
__decorateClass$6([
|
|
5468
6381
|
r()
|
|
5469
6382
|
], JupiterConceptTree.prototype, "_expanded", 2);
|
|
5470
|
-
JupiterConceptTree = __decorateClass$
|
|
6383
|
+
JupiterConceptTree = __decorateClass$6([
|
|
5471
6384
|
t$1("jupiter-concept-tree")
|
|
5472
6385
|
], JupiterConceptTree);
|
|
5473
|
-
var __defProp$
|
|
5474
|
-
var __getOwnPropDesc$
|
|
5475
|
-
var __decorateClass$
|
|
5476
|
-
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$
|
|
6386
|
+
var __defProp$5 = Object.defineProperty;
|
|
6387
|
+
var __getOwnPropDesc$5 = Object.getOwnPropertyDescriptor;
|
|
6388
|
+
var __decorateClass$5 = (decorators, target, key, kind) => {
|
|
6389
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$5(target, key) : target;
|
|
5477
6390
|
for (var i2 = decorators.length - 1, decorator; i2 >= 0; i2--)
|
|
5478
6391
|
if (decorator = decorators[i2])
|
|
5479
6392
|
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
5480
6393
|
if (kind && result)
|
|
5481
|
-
__defProp$
|
|
6394
|
+
__defProp$5(target, key, result);
|
|
5482
6395
|
return result;
|
|
5483
6396
|
};
|
|
5484
6397
|
let JupiterAddColumnDialog = class extends LitElement {
|
|
@@ -6087,48 +7000,48 @@ JupiterAddColumnDialog.styles = css`
|
|
|
6087
7000
|
line-height: 1.4;
|
|
6088
7001
|
}
|
|
6089
7002
|
`;
|
|
6090
|
-
__decorateClass$
|
|
7003
|
+
__decorateClass$5([
|
|
6091
7004
|
n2({ type: String })
|
|
6092
7005
|
], JupiterAddColumnDialog.prototype, "periodType", 2);
|
|
6093
|
-
__decorateClass$
|
|
7006
|
+
__decorateClass$5([
|
|
6094
7007
|
n2({ type: Boolean })
|
|
6095
7008
|
], JupiterAddColumnDialog.prototype, "open", 2);
|
|
6096
|
-
__decorateClass$
|
|
7009
|
+
__decorateClass$5([
|
|
6097
7010
|
n2({ type: Array })
|
|
6098
7011
|
], JupiterAddColumnDialog.prototype, "availableDimensions", 2);
|
|
6099
|
-
__decorateClass$
|
|
7012
|
+
__decorateClass$5([
|
|
6100
7013
|
n2({ type: String })
|
|
6101
7014
|
], JupiterAddColumnDialog.prototype, "periodStartDate", 2);
|
|
6102
|
-
__decorateClass$
|
|
7015
|
+
__decorateClass$5([
|
|
6103
7016
|
n2({ type: String })
|
|
6104
7017
|
], JupiterAddColumnDialog.prototype, "periodEndDate", 2);
|
|
6105
|
-
__decorateClass$
|
|
7018
|
+
__decorateClass$5([
|
|
6106
7019
|
r()
|
|
6107
7020
|
], JupiterAddColumnDialog.prototype, "_startDate", 2);
|
|
6108
|
-
__decorateClass$
|
|
7021
|
+
__decorateClass$5([
|
|
6109
7022
|
r()
|
|
6110
7023
|
], JupiterAddColumnDialog.prototype, "_endDate", 2);
|
|
6111
|
-
__decorateClass$
|
|
7024
|
+
__decorateClass$5([
|
|
6112
7025
|
r()
|
|
6113
7026
|
], JupiterAddColumnDialog.prototype, "_instantDate", 2);
|
|
6114
|
-
__decorateClass$
|
|
7027
|
+
__decorateClass$5([
|
|
6115
7028
|
r()
|
|
6116
7029
|
], JupiterAddColumnDialog.prototype, "_selectedType", 2);
|
|
6117
|
-
__decorateClass$
|
|
7030
|
+
__decorateClass$5([
|
|
6118
7031
|
r()
|
|
6119
7032
|
], JupiterAddColumnDialog.prototype, "_selectedDimensions", 2);
|
|
6120
|
-
JupiterAddColumnDialog = __decorateClass$
|
|
7033
|
+
JupiterAddColumnDialog = __decorateClass$5([
|
|
6121
7034
|
t$1("jupiter-add-column-dialog")
|
|
6122
7035
|
], JupiterAddColumnDialog);
|
|
6123
|
-
var __defProp$
|
|
6124
|
-
var __getOwnPropDesc$
|
|
6125
|
-
var __decorateClass$
|
|
6126
|
-
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$
|
|
7036
|
+
var __defProp$4 = Object.defineProperty;
|
|
7037
|
+
var __getOwnPropDesc$4 = Object.getOwnPropertyDescriptor;
|
|
7038
|
+
var __decorateClass$4 = (decorators, target, key, kind) => {
|
|
7039
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$4(target, key) : target;
|
|
6127
7040
|
for (var i2 = decorators.length - 1, decorator; i2 >= 0; i2--)
|
|
6128
7041
|
if (decorator = decorators[i2])
|
|
6129
7042
|
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
6130
7043
|
if (kind && result)
|
|
6131
|
-
__defProp$
|
|
7044
|
+
__defProp$4(target, key, result);
|
|
6132
7045
|
return result;
|
|
6133
7046
|
};
|
|
6134
7047
|
let JupiterFormSection = class extends LitElement {
|
|
@@ -6155,6 +7068,7 @@ let JupiterFormSection = class extends LitElement {
|
|
|
6155
7068
|
this.periodEndDate = "";
|
|
6156
7069
|
this.language = "en";
|
|
6157
7070
|
this.calculationEnabled = false;
|
|
7071
|
+
this.totalManuallyEditedData = {};
|
|
6158
7072
|
this._expanded = true;
|
|
6159
7073
|
this._showAddColumnDialog = false;
|
|
6160
7074
|
this._sectionPeriodType = "duration";
|
|
@@ -6179,6 +7093,7 @@ let JupiterFormSection = class extends LitElement {
|
|
|
6179
7093
|
this._memberParentMap = /* @__PURE__ */ new Map();
|
|
6180
7094
|
this._totalConceptMap = /* @__PURE__ */ new Map();
|
|
6181
7095
|
this._totalChildConceptsMap = /* @__PURE__ */ new Map();
|
|
7096
|
+
this._sessionManuallyEditedTotals = /* @__PURE__ */ new Set();
|
|
6182
7097
|
}
|
|
6183
7098
|
connectedCallback() {
|
|
6184
7099
|
super.connectedCallback();
|
|
@@ -6206,6 +7121,9 @@ let JupiterFormSection = class extends LitElement {
|
|
|
6206
7121
|
this._clearCalculationState();
|
|
6207
7122
|
}
|
|
6208
7123
|
}
|
|
7124
|
+
if (changedProperties.has("totalManuallyEditedData")) {
|
|
7125
|
+
this._sessionManuallyEditedTotals.clear();
|
|
7126
|
+
}
|
|
6209
7127
|
}
|
|
6210
7128
|
_checkAndExpandFirstSection() {
|
|
6211
7129
|
if (this.isFirstSection && this.section && this.section.concepts) {
|
|
@@ -6355,6 +7273,15 @@ let JupiterFormSection = class extends LitElement {
|
|
|
6355
7273
|
}
|
|
6356
7274
|
_handleFieldChange(event) {
|
|
6357
7275
|
event.stopPropagation();
|
|
7276
|
+
const { conceptId, columnId } = event.detail || {};
|
|
7277
|
+
if (conceptId && columnId && this._totalConceptMap.has(conceptId)) {
|
|
7278
|
+
this._sessionManuallyEditedTotals.add(`${conceptId}__${columnId}`);
|
|
7279
|
+
this.dispatchEvent(new CustomEvent("total-manually-edited", {
|
|
7280
|
+
detail: { conceptId, columnId },
|
|
7281
|
+
bubbles: true,
|
|
7282
|
+
composed: true
|
|
7283
|
+
}));
|
|
7284
|
+
}
|
|
6358
7285
|
this.dispatchEvent(new CustomEvent("field-change", {
|
|
6359
7286
|
detail: event.detail,
|
|
6360
7287
|
bubbles: true,
|
|
@@ -6383,6 +7310,13 @@ let JupiterFormSection = class extends LitElement {
|
|
|
6383
7310
|
}
|
|
6384
7311
|
return result;
|
|
6385
7312
|
}
|
|
7313
|
+
_isTotalManuallyEdited(totalConceptId, columnId) {
|
|
7314
|
+
var _a, _b;
|
|
7315
|
+
const key = `${totalConceptId}__${columnId}`;
|
|
7316
|
+
if (this._sessionManuallyEditedTotals.has(key))
|
|
7317
|
+
return true;
|
|
7318
|
+
return ((_b = (_a = this.totalManuallyEditedData) == null ? void 0 : _a[totalConceptId]) == null ? void 0 : _b[columnId]) === true;
|
|
7319
|
+
}
|
|
6386
7320
|
/**
|
|
6387
7321
|
* Returns true when every column cell for a concept has no value.
|
|
6388
7322
|
* Used in readonly mode to hide fully-blank rows.
|
|
@@ -6463,7 +7397,7 @@ let JupiterFormSection = class extends LitElement {
|
|
|
6463
7397
|
* matching is the single source of truth for "is this row a total" everywhere in this file.
|
|
6464
7398
|
*/
|
|
6465
7399
|
static _isTotalLabel(preferredLabel) {
|
|
6466
|
-
return
|
|
7400
|
+
return isTotalLabel$1(preferredLabel);
|
|
6467
7401
|
}
|
|
6468
7402
|
/**
|
|
6469
7403
|
* JDF-041: distinguishes a self-contained "deduction block" subtotal (negatedTotalLabel, e.g.
|
|
@@ -6584,10 +7518,29 @@ let JupiterFormSection = class extends LitElement {
|
|
|
6584
7518
|
}
|
|
6585
7519
|
}
|
|
6586
7520
|
_evaluateTotal(totalConceptId, columnId) {
|
|
6587
|
-
var _a;
|
|
7521
|
+
var _a, _b;
|
|
6588
7522
|
const totalConcept = this._totalConceptMap.get(totalConceptId);
|
|
6589
|
-
const totalRaw = (_a = this.formData[totalConceptId]) == null ? void 0 : _a[columnId];
|
|
6590
7523
|
const key = `${totalConceptId}__${columnId}`;
|
|
7524
|
+
const children = this._totalChildConceptsMap.get(totalConceptId) || [];
|
|
7525
|
+
const { calculatedSum, hasAnyValue, breakdown } = this._buildCalculationBreakdown(
|
|
7526
|
+
children,
|
|
7527
|
+
this.formData,
|
|
7528
|
+
columnId,
|
|
7529
|
+
totalConcept.balance
|
|
7530
|
+
);
|
|
7531
|
+
if (!this._isTotalManuallyEdited(totalConceptId, columnId)) {
|
|
7532
|
+
if (hasAnyValue) {
|
|
7533
|
+
const currentRaw = (_a = this.formData[totalConceptId]) == null ? void 0 : _a[columnId];
|
|
7534
|
+
const currentValue = parseFloat(currentRaw);
|
|
7535
|
+
const isBlank = currentRaw === null || currentRaw === void 0 || currentRaw === "";
|
|
7536
|
+
if (isBlank || isNaN(currentValue) || !JupiterFormSection._checkTotal(currentValue, calculatedSum)) {
|
|
7537
|
+
this._dispatchCalculationTotalAutoPopulated(totalConceptId, columnId, calculatedSum);
|
|
7538
|
+
}
|
|
7539
|
+
}
|
|
7540
|
+
this._clearCalculationMismatch(key);
|
|
7541
|
+
return;
|
|
7542
|
+
}
|
|
7543
|
+
const totalRaw = (_b = this.formData[totalConceptId]) == null ? void 0 : _b[columnId];
|
|
6591
7544
|
if (totalRaw === null || totalRaw === void 0 || totalRaw === "") {
|
|
6592
7545
|
this._clearCalculationMismatch(key);
|
|
6593
7546
|
return;
|
|
@@ -6597,13 +7550,6 @@ let JupiterFormSection = class extends LitElement {
|
|
|
6597
7550
|
this._clearCalculationMismatch(key);
|
|
6598
7551
|
return;
|
|
6599
7552
|
}
|
|
6600
|
-
const children = this._totalChildConceptsMap.get(totalConceptId) || [];
|
|
6601
|
-
const { calculatedSum, hasAnyValue, breakdown } = this._buildCalculationBreakdown(
|
|
6602
|
-
children,
|
|
6603
|
-
this.formData,
|
|
6604
|
-
columnId,
|
|
6605
|
-
totalConcept.balance
|
|
6606
|
-
);
|
|
6607
7553
|
if (!hasAnyValue || JupiterFormSection._checkTotal(totalValue, calculatedSum)) {
|
|
6608
7554
|
this._clearCalculationMismatch(key);
|
|
6609
7555
|
return;
|
|
@@ -6626,6 +7572,13 @@ let JupiterFormSection = class extends LitElement {
|
|
|
6626
7572
|
this._calculationMismatches = next;
|
|
6627
7573
|
this._dispatchCalculationMismatchChanged(key, detail);
|
|
6628
7574
|
}
|
|
7575
|
+
_dispatchCalculationTotalAutoPopulated(conceptId, columnId, value) {
|
|
7576
|
+
this.dispatchEvent(new CustomEvent("calculation-total-auto-populated", {
|
|
7577
|
+
detail: { conceptId, columnId, value, sectionId: this.section.id },
|
|
7578
|
+
bubbles: true,
|
|
7579
|
+
composed: true
|
|
7580
|
+
}));
|
|
7581
|
+
}
|
|
6629
7582
|
_clearCalculationMismatch(key) {
|
|
6630
7583
|
if (!this._calculationMismatches.has(key))
|
|
6631
7584
|
return;
|
|
@@ -6689,7 +7642,7 @@ let JupiterFormSection = class extends LitElement {
|
|
|
6689
7642
|
return { calculatedSum, hasAnyValue, breakdown };
|
|
6690
7643
|
}
|
|
6691
7644
|
static _checkTotal(totalValue, calculatedSum) {
|
|
6692
|
-
return Math.abs(calculatedSum - totalValue) <
|
|
7645
|
+
return Math.abs(calculatedSum - totalValue) < CALCULATION_TOLERANCE;
|
|
6693
7646
|
}
|
|
6694
7647
|
static _formatNumber(n3) {
|
|
6695
7648
|
return Number.isInteger(n3) ? String(n3) : n3.toFixed(2);
|
|
@@ -7275,123 +8228,126 @@ JupiterFormSection.styles = css`
|
|
|
7275
8228
|
font-style: italic;
|
|
7276
8229
|
}
|
|
7277
8230
|
`;
|
|
7278
|
-
__decorateClass$
|
|
8231
|
+
__decorateClass$4([
|
|
7279
8232
|
n2({ type: Object })
|
|
7280
8233
|
], JupiterFormSection.prototype, "section", 2);
|
|
7281
|
-
__decorateClass$
|
|
8234
|
+
__decorateClass$4([
|
|
7282
8235
|
n2({ type: Array })
|
|
7283
8236
|
], JupiterFormSection.prototype, "columns", 2);
|
|
7284
|
-
__decorateClass$
|
|
8237
|
+
__decorateClass$4([
|
|
7285
8238
|
n2({ type: Array })
|
|
7286
8239
|
], JupiterFormSection.prototype, "datatypes", 2);
|
|
7287
|
-
__decorateClass$
|
|
8240
|
+
__decorateClass$4([
|
|
7288
8241
|
n2({ type: Object })
|
|
7289
8242
|
], JupiterFormSection.prototype, "formData", 2);
|
|
7290
|
-
__decorateClass$
|
|
8243
|
+
__decorateClass$4([
|
|
7291
8244
|
n2({ type: Object })
|
|
7292
8245
|
], JupiterFormSection.prototype, "periodData", 2);
|
|
7293
|
-
__decorateClass$
|
|
8246
|
+
__decorateClass$4([
|
|
7294
8247
|
n2({ type: Object })
|
|
7295
8248
|
], JupiterFormSection.prototype, "unitData", 2);
|
|
7296
|
-
__decorateClass$
|
|
8249
|
+
__decorateClass$4([
|
|
7297
8250
|
n2({ type: Object })
|
|
7298
8251
|
], JupiterFormSection.prototype, "decimalsData", 2);
|
|
7299
|
-
__decorateClass$
|
|
8252
|
+
__decorateClass$4([
|
|
7300
8253
|
n2({ type: String })
|
|
7301
8254
|
], JupiterFormSection.prototype, "globalDecimals", 2);
|
|
7302
|
-
__decorateClass$
|
|
8255
|
+
__decorateClass$4([
|
|
7303
8256
|
n2({ type: Object })
|
|
7304
8257
|
], JupiterFormSection.prototype, "typedMemberData", 2);
|
|
7305
|
-
__decorateClass$
|
|
8258
|
+
__decorateClass$4([
|
|
7306
8259
|
n2({ type: Object })
|
|
7307
8260
|
], JupiterFormSection.prototype, "repeatCounts", 2);
|
|
7308
|
-
__decorateClass$
|
|
8261
|
+
__decorateClass$4([
|
|
7309
8262
|
n2({ type: Array })
|
|
7310
8263
|
], JupiterFormSection.prototype, "defaultUnits", 2);
|
|
7311
|
-
__decorateClass$
|
|
8264
|
+
__decorateClass$4([
|
|
7312
8265
|
n2({ type: Boolean })
|
|
7313
8266
|
], JupiterFormSection.prototype, "disabled", 2);
|
|
7314
|
-
__decorateClass$
|
|
8267
|
+
__decorateClass$4([
|
|
7315
8268
|
n2({ type: Boolean })
|
|
7316
8269
|
], JupiterFormSection.prototype, "collapsible", 2);
|
|
7317
|
-
__decorateClass$
|
|
8270
|
+
__decorateClass$4([
|
|
7318
8271
|
n2({ type: String })
|
|
7319
8272
|
], JupiterFormSection.prototype, "locale", 2);
|
|
7320
|
-
__decorateClass$
|
|
8273
|
+
__decorateClass$4([
|
|
7321
8274
|
n2({ type: Boolean })
|
|
7322
8275
|
], JupiterFormSection.prototype, "isFirstSection", 2);
|
|
7323
|
-
__decorateClass$
|
|
8276
|
+
__decorateClass$4([
|
|
7324
8277
|
n2({ type: Array })
|
|
7325
8278
|
], JupiterFormSection.prototype, "availableDimensions", 2);
|
|
7326
|
-
__decorateClass$
|
|
8279
|
+
__decorateClass$4([
|
|
7327
8280
|
n2({ type: Boolean })
|
|
7328
8281
|
], JupiterFormSection.prototype, "hideHeader", 2);
|
|
7329
|
-
__decorateClass$
|
|
8282
|
+
__decorateClass$4([
|
|
7330
8283
|
n2({ type: String })
|
|
7331
8284
|
], JupiterFormSection.prototype, "mode", 2);
|
|
7332
|
-
__decorateClass$
|
|
8285
|
+
__decorateClass$4([
|
|
7333
8286
|
n2({ type: Boolean })
|
|
7334
8287
|
], JupiterFormSection.prototype, "showFactsOnly", 2);
|
|
7335
|
-
__decorateClass$
|
|
8288
|
+
__decorateClass$4([
|
|
7336
8289
|
n2({ type: Object })
|
|
7337
8290
|
], JupiterFormSection.prototype, "conceptMatchIds", 2);
|
|
7338
|
-
__decorateClass$
|
|
8291
|
+
__decorateClass$4([
|
|
7339
8292
|
n2({ type: Object })
|
|
7340
8293
|
], JupiterFormSection.prototype, "masterData", 2);
|
|
7341
|
-
__decorateClass$
|
|
8294
|
+
__decorateClass$4([
|
|
7342
8295
|
n2({ type: String })
|
|
7343
8296
|
], JupiterFormSection.prototype, "periodStartDate", 2);
|
|
7344
|
-
__decorateClass$
|
|
8297
|
+
__decorateClass$4([
|
|
7345
8298
|
n2({ type: String })
|
|
7346
8299
|
], JupiterFormSection.prototype, "periodEndDate", 2);
|
|
7347
|
-
__decorateClass$
|
|
8300
|
+
__decorateClass$4([
|
|
7348
8301
|
n2({ type: String })
|
|
7349
8302
|
], JupiterFormSection.prototype, "language", 2);
|
|
7350
|
-
__decorateClass$
|
|
8303
|
+
__decorateClass$4([
|
|
7351
8304
|
n2({ type: Boolean })
|
|
7352
8305
|
], JupiterFormSection.prototype, "calculationEnabled", 2);
|
|
7353
|
-
__decorateClass$
|
|
8306
|
+
__decorateClass$4([
|
|
8307
|
+
n2({ type: Object })
|
|
8308
|
+
], JupiterFormSection.prototype, "totalManuallyEditedData", 2);
|
|
8309
|
+
__decorateClass$4([
|
|
7354
8310
|
r()
|
|
7355
8311
|
], JupiterFormSection.prototype, "_expanded", 2);
|
|
7356
|
-
__decorateClass$
|
|
8312
|
+
__decorateClass$4([
|
|
7357
8313
|
r()
|
|
7358
8314
|
], JupiterFormSection.prototype, "_showAddColumnDialog", 2);
|
|
7359
|
-
__decorateClass$
|
|
8315
|
+
__decorateClass$4([
|
|
7360
8316
|
r()
|
|
7361
8317
|
], JupiterFormSection.prototype, "_sectionPeriodType", 2);
|
|
7362
|
-
__decorateClass$
|
|
8318
|
+
__decorateClass$4([
|
|
7363
8319
|
r()
|
|
7364
8320
|
], JupiterFormSection.prototype, "_openMenuColumnId", 2);
|
|
7365
|
-
__decorateClass$
|
|
8321
|
+
__decorateClass$4([
|
|
7366
8322
|
r()
|
|
7367
8323
|
], JupiterFormSection.prototype, "_insertAfterColumnId", 2);
|
|
7368
|
-
__decorateClass$
|
|
8324
|
+
__decorateClass$4([
|
|
7369
8325
|
r()
|
|
7370
8326
|
], JupiterFormSection.prototype, "_expandedConcepts", 2);
|
|
7371
|
-
__decorateClass$
|
|
8327
|
+
__decorateClass$4([
|
|
7372
8328
|
r()
|
|
7373
8329
|
], JupiterFormSection.prototype, "_allTreeExpanded", 2);
|
|
7374
|
-
__decorateClass$
|
|
8330
|
+
__decorateClass$4([
|
|
7375
8331
|
r()
|
|
7376
8332
|
], JupiterFormSection.prototype, "_highlightMap", 2);
|
|
7377
|
-
__decorateClass$
|
|
8333
|
+
__decorateClass$4([
|
|
7378
8334
|
r()
|
|
7379
8335
|
], JupiterFormSection.prototype, "_focusedConceptId", 2);
|
|
7380
|
-
__decorateClass$
|
|
8336
|
+
__decorateClass$4([
|
|
7381
8337
|
r()
|
|
7382
8338
|
], JupiterFormSection.prototype, "_calculationMismatches", 2);
|
|
7383
|
-
JupiterFormSection = __decorateClass$
|
|
8339
|
+
JupiterFormSection = __decorateClass$4([
|
|
7384
8340
|
t$1("jupiter-form-section")
|
|
7385
8341
|
], JupiterFormSection);
|
|
7386
|
-
var __defProp$
|
|
7387
|
-
var __getOwnPropDesc$
|
|
7388
|
-
var __decorateClass$
|
|
7389
|
-
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$
|
|
8342
|
+
var __defProp$3 = Object.defineProperty;
|
|
8343
|
+
var __getOwnPropDesc$3 = Object.getOwnPropertyDescriptor;
|
|
8344
|
+
var __decorateClass$3 = (decorators, target, key, kind) => {
|
|
8345
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$3(target, key) : target;
|
|
7390
8346
|
for (var i2 = decorators.length - 1, decorator; i2 >= 0; i2--)
|
|
7391
8347
|
if (decorator = decorators[i2])
|
|
7392
8348
|
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
7393
8349
|
if (kind && result)
|
|
7394
|
-
__defProp$
|
|
8350
|
+
__defProp$3(target, key, result);
|
|
7395
8351
|
return result;
|
|
7396
8352
|
};
|
|
7397
8353
|
let JupiterAdvancedFilter = class extends LitElement {
|
|
@@ -7580,27 +8536,27 @@ JupiterAdvancedFilter.styles = css`
|
|
|
7580
8536
|
color: var(--primaryTextColor, var(--jupiter-text-primary, #333));
|
|
7581
8537
|
}
|
|
7582
8538
|
`;
|
|
7583
|
-
__decorateClass$
|
|
8539
|
+
__decorateClass$3([
|
|
7584
8540
|
n2({ type: Boolean })
|
|
7585
8541
|
], JupiterAdvancedFilter.prototype, "showFactsOnly", 2);
|
|
7586
|
-
__decorateClass$
|
|
8542
|
+
__decorateClass$3([
|
|
7587
8543
|
n2({ type: String })
|
|
7588
8544
|
], JupiterAdvancedFilter.prototype, "conceptSearchText", 2);
|
|
7589
|
-
__decorateClass$
|
|
8545
|
+
__decorateClass$3([
|
|
7590
8546
|
r()
|
|
7591
8547
|
], JupiterAdvancedFilter.prototype, "_localConceptSearchText", 2);
|
|
7592
|
-
JupiterAdvancedFilter = __decorateClass$
|
|
8548
|
+
JupiterAdvancedFilter = __decorateClass$3([
|
|
7593
8549
|
t$1("jupiter-advanced-filter")
|
|
7594
8550
|
], JupiterAdvancedFilter);
|
|
7595
|
-
var __defProp$
|
|
7596
|
-
var __getOwnPropDesc$
|
|
7597
|
-
var __decorateClass$
|
|
7598
|
-
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$
|
|
8551
|
+
var __defProp$2 = Object.defineProperty;
|
|
8552
|
+
var __getOwnPropDesc$2 = Object.getOwnPropertyDescriptor;
|
|
8553
|
+
var __decorateClass$2 = (decorators, target, key, kind) => {
|
|
8554
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$2(target, key) : target;
|
|
7599
8555
|
for (var i2 = decorators.length - 1, decorator; i2 >= 0; i2--)
|
|
7600
8556
|
if (decorator = decorators[i2])
|
|
7601
8557
|
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
7602
8558
|
if (kind && result)
|
|
7603
|
-
__defProp$
|
|
8559
|
+
__defProp$2(target, key, result);
|
|
7604
8560
|
return result;
|
|
7605
8561
|
};
|
|
7606
8562
|
let _lastViewWasAdvancedFilter = false;
|
|
@@ -9217,162 +10173,539 @@ JupiterFilterRolesDialog.styles = css`
|
|
|
9217
10173
|
border-color: var(--jupiter-primary-color, #1976d2);
|
|
9218
10174
|
}
|
|
9219
10175
|
|
|
9220
|
-
.picklist-item.selected {
|
|
9221
|
-
background: var(--jupiter-primary-color, #1976d2);
|
|
9222
|
-
color: white;
|
|
9223
|
-
border-color: var(--jupiter-primary-color, #1976d2);
|
|
10176
|
+
.picklist-item.selected {
|
|
10177
|
+
background: var(--jupiter-primary-color, #1976d2);
|
|
10178
|
+
color: white;
|
|
10179
|
+
border-color: var(--jupiter-primary-color, #1976d2);
|
|
10180
|
+
}
|
|
10181
|
+
|
|
10182
|
+
.picklist-item.dragging {
|
|
10183
|
+
opacity: 0.5;
|
|
10184
|
+
cursor: move;
|
|
10185
|
+
}
|
|
10186
|
+
|
|
10187
|
+
.picklist-item.drag-over {
|
|
10188
|
+
border-top: 3px solid var(--jupiter-primary-color, #1976d2);
|
|
10189
|
+
margin-top: 3px;
|
|
10190
|
+
}
|
|
10191
|
+
|
|
10192
|
+
.picklist-item[draggable="true"] {
|
|
10193
|
+
cursor: move;
|
|
10194
|
+
}
|
|
10195
|
+
|
|
10196
|
+
.picklist-item-label {
|
|
10197
|
+
font-weight: 500;
|
|
10198
|
+
font-size: 14px;
|
|
10199
|
+
margin-bottom: 4px;
|
|
10200
|
+
}
|
|
10201
|
+
|
|
10202
|
+
.picklist-item-value {
|
|
10203
|
+
font-size: 11px;
|
|
10204
|
+
opacity: 0.8;
|
|
10205
|
+
word-break: break-all;
|
|
10206
|
+
}
|
|
10207
|
+
|
|
10208
|
+
.picklist-controls {
|
|
10209
|
+
display: flex;
|
|
10210
|
+
flex-direction: column;
|
|
10211
|
+
justify-content: center;
|
|
10212
|
+
gap: 8px;
|
|
10213
|
+
padding: 0 8px;
|
|
10214
|
+
}
|
|
10215
|
+
|
|
10216
|
+
.picklist-button {
|
|
10217
|
+
background: var(--jupiter-primary-color, #1976d2);
|
|
10218
|
+
color: white;
|
|
10219
|
+
border: none;
|
|
10220
|
+
padding: 8px 16px;
|
|
10221
|
+
border-radius: 4px;
|
|
10222
|
+
cursor: pointer;
|
|
10223
|
+
font-size: 14px;
|
|
10224
|
+
transition: background-color 0.2s ease;
|
|
10225
|
+
}
|
|
10226
|
+
|
|
10227
|
+
.picklist-button:hover:not(:disabled) {
|
|
10228
|
+
background: var(--jupiter-primary-color-dark, #1565c0);
|
|
10229
|
+
}
|
|
10230
|
+
|
|
10231
|
+
.picklist-button:disabled {
|
|
10232
|
+
opacity: 0.4;
|
|
10233
|
+
cursor: not-allowed;
|
|
10234
|
+
}
|
|
10235
|
+
|
|
10236
|
+
.picklist-count {
|
|
10237
|
+
padding: 8px 12px;
|
|
10238
|
+
font-size: 12px;
|
|
10239
|
+
color: var(--jupiter-text-secondary, #666);
|
|
10240
|
+
background: var(--jupiter-background-light, #f8f9fa);
|
|
10241
|
+
border-top: 1px solid var(--jupiter-border-color, #ddd);
|
|
10242
|
+
text-align: center;
|
|
10243
|
+
}
|
|
10244
|
+
|
|
10245
|
+
.btn-text {
|
|
10246
|
+
background: none;
|
|
10247
|
+
border: none;
|
|
10248
|
+
color: var(--buttonBgColor, var(--jupiter-primary-color, #1976d2));
|
|
10249
|
+
padding: 10px 8px;
|
|
10250
|
+
font-size: 14px;
|
|
10251
|
+
font-weight: 500;
|
|
10252
|
+
font-family: inherit;
|
|
10253
|
+
cursor: pointer;
|
|
10254
|
+
margin-right: auto;
|
|
10255
|
+
border-radius: 4px;
|
|
10256
|
+
transition: background-color 0.2s ease;
|
|
10257
|
+
}
|
|
10258
|
+
|
|
10259
|
+
.btn-text:hover {
|
|
10260
|
+
background: var(--menuBgColorLighter, var(--jupiter-hover-background, #f5f5f5));
|
|
10261
|
+
}
|
|
10262
|
+
`;
|
|
10263
|
+
__decorateClass$2([
|
|
10264
|
+
n2({ type: Boolean, reflect: true })
|
|
10265
|
+
], JupiterFilterRolesDialog.prototype, "open", 2);
|
|
10266
|
+
__decorateClass$2([
|
|
10267
|
+
n2({ type: Array })
|
|
10268
|
+
], JupiterFilterRolesDialog.prototype, "availableRoles", 2);
|
|
10269
|
+
__decorateClass$2([
|
|
10270
|
+
n2({ type: Array })
|
|
10271
|
+
], JupiterFilterRolesDialog.prototype, "selectedRoleIds", 2);
|
|
10272
|
+
__decorateClass$2([
|
|
10273
|
+
n2({ type: Object })
|
|
10274
|
+
], JupiterFilterRolesDialog.prototype, "periodPreferences", 2);
|
|
10275
|
+
__decorateClass$2([
|
|
10276
|
+
n2({ type: String })
|
|
10277
|
+
], JupiterFilterRolesDialog.prototype, "mode", 2);
|
|
10278
|
+
__decorateClass$2([
|
|
10279
|
+
n2({ type: Object })
|
|
10280
|
+
], JupiterFilterRolesDialog.prototype, "hypercubeData", 2);
|
|
10281
|
+
__decorateClass$2([
|
|
10282
|
+
n2({ type: Boolean })
|
|
10283
|
+
], JupiterFilterRolesDialog.prototype, "showFactsOnly", 2);
|
|
10284
|
+
__decorateClass$2([
|
|
10285
|
+
n2({ type: String })
|
|
10286
|
+
], JupiterFilterRolesDialog.prototype, "conceptSearchText", 2);
|
|
10287
|
+
__decorateClass$2([
|
|
10288
|
+
r()
|
|
10289
|
+
], JupiterFilterRolesDialog.prototype, "_tempSelectedRoles", 2);
|
|
10290
|
+
__decorateClass$2([
|
|
10291
|
+
r()
|
|
10292
|
+
], JupiterFilterRolesDialog.prototype, "_searchQuery", 2);
|
|
10293
|
+
__decorateClass$2([
|
|
10294
|
+
r()
|
|
10295
|
+
], JupiterFilterRolesDialog.prototype, "_filteredRoles", 2);
|
|
10296
|
+
__decorateClass$2([
|
|
10297
|
+
r()
|
|
10298
|
+
], JupiterFilterRolesDialog.prototype, "_tempPeriodPreferences", 2);
|
|
10299
|
+
__decorateClass$2([
|
|
10300
|
+
r()
|
|
10301
|
+
], JupiterFilterRolesDialog.prototype, "_selectedAvailableRole", 2);
|
|
10302
|
+
__decorateClass$2([
|
|
10303
|
+
r()
|
|
10304
|
+
], JupiterFilterRolesDialog.prototype, "_selectedChosenRole", 2);
|
|
10305
|
+
__decorateClass$2([
|
|
10306
|
+
r()
|
|
10307
|
+
], JupiterFilterRolesDialog.prototype, "_chosenSearchQuery", 2);
|
|
10308
|
+
__decorateClass$2([
|
|
10309
|
+
r()
|
|
10310
|
+
], JupiterFilterRolesDialog.prototype, "_draggedRoleId", 2);
|
|
10311
|
+
__decorateClass$2([
|
|
10312
|
+
r()
|
|
10313
|
+
], JupiterFilterRolesDialog.prototype, "_dragOverRoleId", 2);
|
|
10314
|
+
__decorateClass$2([
|
|
10315
|
+
r()
|
|
10316
|
+
], JupiterFilterRolesDialog.prototype, "_chosenRoleOrder", 2);
|
|
10317
|
+
__decorateClass$2([
|
|
10318
|
+
r()
|
|
10319
|
+
], JupiterFilterRolesDialog.prototype, "_showAdvancedFilter", 2);
|
|
10320
|
+
__decorateClass$2([
|
|
10321
|
+
r()
|
|
10322
|
+
], JupiterFilterRolesDialog.prototype, "_showFactsOnly", 2);
|
|
10323
|
+
__decorateClass$2([
|
|
10324
|
+
r()
|
|
10325
|
+
], JupiterFilterRolesDialog.prototype, "_conceptSearchText", 2);
|
|
10326
|
+
__decorateClass$2([
|
|
10327
|
+
r()
|
|
10328
|
+
], JupiterFilterRolesDialog.prototype, "_collapsedRoles", 2);
|
|
10329
|
+
JupiterFilterRolesDialog = __decorateClass$2([
|
|
10330
|
+
t$1("jupiter-filter-roles-dialog")
|
|
10331
|
+
], JupiterFilterRolesDialog);
|
|
10332
|
+
var __defProp$1 = Object.defineProperty;
|
|
10333
|
+
var __getOwnPropDesc$1 = Object.getOwnPropertyDescriptor;
|
|
10334
|
+
var __decorateClass$1 = (decorators, target, key, kind) => {
|
|
10335
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$1(target, key) : target;
|
|
10336
|
+
for (var i2 = decorators.length - 1, decorator; i2 >= 0; i2--)
|
|
10337
|
+
if (decorator = decorators[i2])
|
|
10338
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
10339
|
+
if (kind && result)
|
|
10340
|
+
__defProp$1(target, key, result);
|
|
10341
|
+
return result;
|
|
10342
|
+
};
|
|
10343
|
+
let JupiterFormulaValidationDialog = class extends LitElement {
|
|
10344
|
+
constructor() {
|
|
10345
|
+
super(...arguments);
|
|
10346
|
+
this.results = [];
|
|
10347
|
+
this.open = false;
|
|
10348
|
+
this._collapsedGroups = /* @__PURE__ */ new Set();
|
|
10349
|
+
this._boundHandleKeydown = this._handleKeydown.bind(this);
|
|
10350
|
+
}
|
|
10351
|
+
connectedCallback() {
|
|
10352
|
+
super.connectedCallback();
|
|
10353
|
+
window.addEventListener("keydown", this._boundHandleKeydown);
|
|
10354
|
+
}
|
|
10355
|
+
disconnectedCallback() {
|
|
10356
|
+
window.removeEventListener("keydown", this._boundHandleKeydown);
|
|
10357
|
+
super.disconnectedCallback();
|
|
10358
|
+
}
|
|
10359
|
+
_handleKeydown(event) {
|
|
10360
|
+
if (this.open && event.key === "Escape") {
|
|
10361
|
+
this._handleClose();
|
|
10362
|
+
}
|
|
10363
|
+
}
|
|
10364
|
+
_handleClose() {
|
|
10365
|
+
this.open = false;
|
|
10366
|
+
this.dispatchEvent(new CustomEvent("dialog-cancel", { bubbles: true }));
|
|
10367
|
+
}
|
|
10368
|
+
_toggleGroup(roleLabel) {
|
|
10369
|
+
if (this._collapsedGroups.has(roleLabel)) {
|
|
10370
|
+
this._collapsedGroups.delete(roleLabel);
|
|
10371
|
+
} else {
|
|
10372
|
+
this._collapsedGroups.add(roleLabel);
|
|
10373
|
+
}
|
|
10374
|
+
this.requestUpdate();
|
|
10375
|
+
}
|
|
10376
|
+
// JDF-059: navigates the host form to the exact fact this assertion's variable resolved to
|
|
10377
|
+
// (or its empty target cell, for a "must exist" failure) and closes this dialog, mirroring the
|
|
10378
|
+
// existing "click a validation error, land on its field" flow this feature deliberately reuses
|
|
10379
|
+
// rather than building a second focus mechanism.
|
|
10380
|
+
_handleConceptLinkClick(link) {
|
|
10381
|
+
this.dispatchEvent(new CustomEvent("formula-concept-click", {
|
|
10382
|
+
detail: { conceptId: link.conceptId, conceptQName: link.conceptQName, columnId: link.columnId },
|
|
10383
|
+
bubbles: true,
|
|
10384
|
+
composed: true
|
|
10385
|
+
}));
|
|
10386
|
+
}
|
|
10387
|
+
// Splits a message on its backtick-quoted concept mentions and renders the ones this
|
|
10388
|
+
// assertion resolved a fact location for (`result.conceptLinks`) as click-to-focus buttons;
|
|
10389
|
+
// any other backtick mention (e.g. an enumerated value like `Na`, not a concept) renders as
|
|
10390
|
+
// plain text with the backticks dropped, since there is nothing to link it to.
|
|
10391
|
+
_renderMessage(result) {
|
|
10392
|
+
const message = result.message ?? "";
|
|
10393
|
+
const linkByLabel = new Map((result.conceptLinks ?? []).map((link) => [link.label, link]));
|
|
10394
|
+
const parts = message.split(/(`[^`]+`)/g);
|
|
10395
|
+
return html`${parts.map((part) => {
|
|
10396
|
+
const match = /^`([^`]+)`$/.exec(part);
|
|
10397
|
+
if (!match)
|
|
10398
|
+
return part;
|
|
10399
|
+
const link = linkByLabel.get(match[1]);
|
|
10400
|
+
if (!link)
|
|
10401
|
+
return match[1];
|
|
10402
|
+
return html`<button type="button" class="concept-link" @click="${() => this._handleConceptLinkClick(link)}">${match[1]}</button>`;
|
|
10403
|
+
})}`;
|
|
10404
|
+
}
|
|
10405
|
+
_groupByRole(failures) {
|
|
10406
|
+
const grouped = failures.reduce((groups, result) => {
|
|
10407
|
+
var _a;
|
|
10408
|
+
(groups[_a = result.roleLabel] ?? (groups[_a] = [])).push(result);
|
|
10409
|
+
return groups;
|
|
10410
|
+
}, {});
|
|
10411
|
+
return Object.entries(grouped);
|
|
10412
|
+
}
|
|
10413
|
+
render() {
|
|
10414
|
+
if (!this.open)
|
|
10415
|
+
return html``;
|
|
10416
|
+
const failures = this.results.filter((result) => !result.skipped && !result.satisfied);
|
|
10417
|
+
const groups = this._groupByRole(failures);
|
|
10418
|
+
const summary = this.summary;
|
|
10419
|
+
return html`
|
|
10420
|
+
<div class="dialog" @click="${(e2) => e2.stopPropagation()}">
|
|
10421
|
+
<div class="dialog-header">
|
|
10422
|
+
<h2 class="dialog-title">${I18n.t("formulaValidation.dialogTitle")}</h2>
|
|
10423
|
+
${summary ? html`
|
|
10424
|
+
<p class="dialog-summary">
|
|
10425
|
+
${I18n.t("formulaValidation.summaryCount", { failed: summary.failed, total: summary.totalAssertions })}
|
|
10426
|
+
${summary.failed > 0 ? html`— ${I18n.t("formulaValidation.summaryCountBreakdown", { warnings: summary.failedWarnings, errors: summary.failedErrors })}` : ""}
|
|
10427
|
+
</p>
|
|
10428
|
+
` : ""}
|
|
10429
|
+
</div>
|
|
10430
|
+
|
|
10431
|
+
<div class="dialog-content">
|
|
10432
|
+
${failures.length === 0 ? html`
|
|
10433
|
+
<div class="all-passed">
|
|
10434
|
+
<div class="all-passed-icon">✓</div>
|
|
10435
|
+
<div class="all-passed-text">${I18n.t("formulaValidation.allPassed")}</div>
|
|
10436
|
+
</div>
|
|
10437
|
+
` : groups.map(([roleLabel, rows]) => {
|
|
10438
|
+
const collapsed = this._collapsedGroups.has(roleLabel);
|
|
10439
|
+
return html`
|
|
10440
|
+
<div class="role-group">
|
|
10441
|
+
<div class="role-group-header" @click="${() => this._toggleGroup(roleLabel)}">
|
|
10442
|
+
<span class="role-group-title">${roleLabel}</span>
|
|
10443
|
+
<span class="role-group-count">${rows.length}</span>
|
|
10444
|
+
<button class="role-group-toggle" type="button">${collapsed ? "▸" : "▾"}</button>
|
|
10445
|
+
</div>
|
|
10446
|
+
${collapsed ? "" : html`
|
|
10447
|
+
<div class="role-group-rows">
|
|
10448
|
+
${rows.map((result) => html`
|
|
10449
|
+
<div class="assertion-row">
|
|
10450
|
+
<span class="severity-badge ${result.severity === "ERROR" ? "error" : "warning"}">
|
|
10451
|
+
${result.severity === "ERROR" ? I18n.t("formulaValidation.severityError") : I18n.t("formulaValidation.severityWarning")}
|
|
10452
|
+
</span>
|
|
10453
|
+
<span class="assertion-message">${this._renderMessage(result)}</span>
|
|
10454
|
+
</div>
|
|
10455
|
+
`)}
|
|
10456
|
+
</div>
|
|
10457
|
+
`}
|
|
10458
|
+
</div>
|
|
10459
|
+
`;
|
|
10460
|
+
})}
|
|
10461
|
+
</div>
|
|
10462
|
+
|
|
10463
|
+
<div class="dialog-actions">
|
|
10464
|
+
<button class="btn btn-primary" @click="${this._handleClose}">
|
|
10465
|
+
${I18n.t("formulaValidation.close")}
|
|
10466
|
+
</button>
|
|
10467
|
+
</div>
|
|
10468
|
+
</div>
|
|
10469
|
+
`;
|
|
10470
|
+
}
|
|
10471
|
+
};
|
|
10472
|
+
JupiterFormulaValidationDialog.styles = css`
|
|
10473
|
+
:host {
|
|
10474
|
+
position: fixed;
|
|
10475
|
+
top: 0;
|
|
10476
|
+
left: 0;
|
|
10477
|
+
width: 100%;
|
|
10478
|
+
height: 100%;
|
|
10479
|
+
background: rgba(0, 0, 0, 0.5);
|
|
10480
|
+
z-index: 1100;
|
|
10481
|
+
display: flex;
|
|
10482
|
+
align-items: center;
|
|
10483
|
+
justify-content: center;
|
|
10484
|
+
opacity: 0;
|
|
10485
|
+
visibility: hidden;
|
|
10486
|
+
transition: opacity 0.3s ease, visibility 0.3s ease;
|
|
10487
|
+
}
|
|
10488
|
+
|
|
10489
|
+
:host([open]) {
|
|
10490
|
+
opacity: 1;
|
|
10491
|
+
visibility: visible;
|
|
10492
|
+
}
|
|
10493
|
+
|
|
10494
|
+
.dialog {
|
|
10495
|
+
background: var(--bg-color-2, var(--jupiter-card-background, #fff));
|
|
10496
|
+
border-radius: 8px;
|
|
10497
|
+
padding: 24px;
|
|
10498
|
+
min-width: 420px;
|
|
10499
|
+
max-width: 640px;
|
|
10500
|
+
width: 90vw;
|
|
10501
|
+
max-height: 90vh;
|
|
10502
|
+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
|
|
10503
|
+
transform: scale(0.9);
|
|
10504
|
+
transition: transform 0.3s ease;
|
|
10505
|
+
display: flex;
|
|
10506
|
+
flex-direction: column;
|
|
10507
|
+
}
|
|
10508
|
+
|
|
10509
|
+
:host([open]) .dialog {
|
|
10510
|
+
transform: scale(1);
|
|
10511
|
+
}
|
|
10512
|
+
|
|
10513
|
+
.dialog-header {
|
|
10514
|
+
margin-bottom: 16px;
|
|
10515
|
+
flex-shrink: 0;
|
|
10516
|
+
}
|
|
10517
|
+
|
|
10518
|
+
.dialog-title {
|
|
10519
|
+
font-size: 20px;
|
|
10520
|
+
font-weight: 600;
|
|
10521
|
+
color: var(--primaryTextColor, var(--jupiter-text-primary, #333));
|
|
10522
|
+
margin: 0 0 8px 0;
|
|
10523
|
+
}
|
|
10524
|
+
|
|
10525
|
+
.dialog-summary {
|
|
10526
|
+
font-size: 14px;
|
|
10527
|
+
color: var(--jupiter-text-secondary, #666);
|
|
10528
|
+
margin: 0;
|
|
10529
|
+
}
|
|
10530
|
+
|
|
10531
|
+
/* JDF-035 dialog-overflow fix: min-height: 0 is required on a flex-column scrollable child,
|
|
10532
|
+
otherwise the browser lets it grow past the dialog's max-height instead of scrolling. */
|
|
10533
|
+
.dialog-content {
|
|
10534
|
+
margin-bottom: 20px;
|
|
10535
|
+
flex: 1;
|
|
10536
|
+
overflow-y: auto;
|
|
10537
|
+
min-height: 0;
|
|
10538
|
+
}
|
|
10539
|
+
|
|
10540
|
+
.all-passed {
|
|
10541
|
+
display: flex;
|
|
10542
|
+
flex-direction: column;
|
|
10543
|
+
align-items: center;
|
|
10544
|
+
gap: 12px;
|
|
10545
|
+
padding: 32px 16px;
|
|
10546
|
+
color: var(--jupiter-text-primary, #333);
|
|
10547
|
+
}
|
|
10548
|
+
|
|
10549
|
+
.all-passed-icon {
|
|
10550
|
+
width: 40px;
|
|
10551
|
+
height: 40px;
|
|
10552
|
+
border-radius: 50%;
|
|
10553
|
+
background: var(--jupiter-success-color, #4caf50);
|
|
10554
|
+
color: #fff;
|
|
10555
|
+
display: flex;
|
|
10556
|
+
align-items: center;
|
|
10557
|
+
justify-content: center;
|
|
10558
|
+
font-size: 22px;
|
|
10559
|
+
font-weight: 700;
|
|
10560
|
+
}
|
|
10561
|
+
|
|
10562
|
+
.all-passed-text {
|
|
10563
|
+
font-size: 15px;
|
|
10564
|
+
font-weight: 500;
|
|
10565
|
+
}
|
|
10566
|
+
|
|
10567
|
+
.role-group {
|
|
10568
|
+
border: 1px solid var(--jupiter-border-color, #ddd);
|
|
10569
|
+
border-radius: 4px;
|
|
10570
|
+
margin-bottom: 12px;
|
|
10571
|
+
overflow: hidden;
|
|
10572
|
+
}
|
|
10573
|
+
|
|
10574
|
+
.role-group-header {
|
|
10575
|
+
display: flex;
|
|
10576
|
+
align-items: center;
|
|
10577
|
+
justify-content: space-between;
|
|
10578
|
+
gap: 8px;
|
|
10579
|
+
padding: 10px 12px;
|
|
10580
|
+
background: var(--jupiter-card-background, #fafafa);
|
|
10581
|
+
cursor: pointer;
|
|
10582
|
+
user-select: none;
|
|
10583
|
+
}
|
|
10584
|
+
|
|
10585
|
+
.role-group-title {
|
|
10586
|
+
font-weight: 600;
|
|
10587
|
+
font-size: 14px;
|
|
10588
|
+
color: var(--primaryTextColor, var(--jupiter-text-primary, #333));
|
|
10589
|
+
}
|
|
10590
|
+
|
|
10591
|
+
.role-group-count {
|
|
10592
|
+
font-size: 12px;
|
|
10593
|
+
color: var(--jupiter-text-secondary, #666);
|
|
10594
|
+
}
|
|
10595
|
+
|
|
10596
|
+
.role-group-toggle {
|
|
10597
|
+
background: none;
|
|
10598
|
+
border: none;
|
|
10599
|
+
cursor: pointer;
|
|
10600
|
+
font-size: 12px;
|
|
10601
|
+
color: var(--jupiter-text-secondary, #666);
|
|
10602
|
+
padding: 0 4px;
|
|
9224
10603
|
}
|
|
9225
10604
|
|
|
9226
|
-
.
|
|
9227
|
-
|
|
9228
|
-
cursor: move;
|
|
10605
|
+
.role-group-rows {
|
|
10606
|
+
padding: 4px 12px 8px 12px;
|
|
9229
10607
|
}
|
|
9230
10608
|
|
|
9231
|
-
.
|
|
9232
|
-
|
|
9233
|
-
|
|
10609
|
+
.assertion-row {
|
|
10610
|
+
display: flex;
|
|
10611
|
+
align-items: flex-start;
|
|
10612
|
+
gap: 8px;
|
|
10613
|
+
padding: 8px 0;
|
|
10614
|
+
border-top: 1px solid var(--jupiter-border-color, #eee);
|
|
9234
10615
|
}
|
|
9235
10616
|
|
|
9236
|
-
.
|
|
9237
|
-
|
|
10617
|
+
.assertion-row:first-child {
|
|
10618
|
+
border-top: none;
|
|
9238
10619
|
}
|
|
9239
10620
|
|
|
9240
|
-
.
|
|
9241
|
-
|
|
9242
|
-
|
|
9243
|
-
|
|
10621
|
+
.severity-badge {
|
|
10622
|
+
flex-shrink: 0;
|
|
10623
|
+
display: inline-flex;
|
|
10624
|
+
align-items: center;
|
|
10625
|
+
gap: 4px;
|
|
10626
|
+
padding: 2px 8px;
|
|
10627
|
+
border-radius: 10px;
|
|
10628
|
+
font-size: 11px;
|
|
10629
|
+
font-weight: 700;
|
|
10630
|
+
color: #fff;
|
|
10631
|
+
white-space: nowrap;
|
|
9244
10632
|
}
|
|
9245
10633
|
|
|
9246
|
-
.
|
|
9247
|
-
|
|
9248
|
-
opacity: 0.8;
|
|
9249
|
-
word-break: break-all;
|
|
10634
|
+
.severity-badge.warning {
|
|
10635
|
+
background: var(--jupiter-warning-color, #ff9800);
|
|
9250
10636
|
}
|
|
9251
10637
|
|
|
9252
|
-
.
|
|
9253
|
-
|
|
9254
|
-
flex-direction: column;
|
|
9255
|
-
justify-content: center;
|
|
9256
|
-
gap: 8px;
|
|
9257
|
-
padding: 0 8px;
|
|
10638
|
+
.severity-badge.error {
|
|
10639
|
+
background: var(--jupiter-error-color, #d32f2f);
|
|
9258
10640
|
}
|
|
9259
10641
|
|
|
9260
|
-
.
|
|
9261
|
-
|
|
9262
|
-
color:
|
|
9263
|
-
|
|
9264
|
-
padding: 8px 16px;
|
|
9265
|
-
border-radius: 4px;
|
|
9266
|
-
cursor: pointer;
|
|
9267
|
-
font-size: 14px;
|
|
9268
|
-
transition: background-color 0.2s ease;
|
|
10642
|
+
.assertion-message {
|
|
10643
|
+
font-size: 13px;
|
|
10644
|
+
color: var(--primaryTextColor, var(--jupiter-text-primary, #333));
|
|
10645
|
+
line-height: 1.4;
|
|
9269
10646
|
}
|
|
9270
10647
|
|
|
9271
|
-
.
|
|
9272
|
-
|
|
10648
|
+
.concept-link {
|
|
10649
|
+
font: inherit;
|
|
10650
|
+
font-weight: 600;
|
|
10651
|
+
color: var(--buttonBgColor, var(--jupiter-primary-color, #1976d2));
|
|
10652
|
+
background: none;
|
|
10653
|
+
border: none;
|
|
10654
|
+
padding: 0;
|
|
10655
|
+
margin: 0;
|
|
10656
|
+
cursor: pointer;
|
|
10657
|
+
text-decoration: underline;
|
|
10658
|
+
text-underline-offset: 2px;
|
|
9273
10659
|
}
|
|
9274
10660
|
|
|
9275
|
-
.
|
|
9276
|
-
opacity: 0.
|
|
9277
|
-
cursor: not-allowed;
|
|
10661
|
+
.concept-link:hover {
|
|
10662
|
+
opacity: 0.8;
|
|
9278
10663
|
}
|
|
9279
10664
|
|
|
9280
|
-
.
|
|
9281
|
-
|
|
9282
|
-
|
|
9283
|
-
|
|
9284
|
-
|
|
10665
|
+
.dialog-actions {
|
|
10666
|
+
display: flex;
|
|
10667
|
+
gap: 12px;
|
|
10668
|
+
justify-content: flex-end;
|
|
10669
|
+
flex-shrink: 0;
|
|
9285
10670
|
border-top: 1px solid var(--jupiter-border-color, #ddd);
|
|
9286
|
-
|
|
10671
|
+
padding-top: 16px;
|
|
10672
|
+
margin-top: 16px;
|
|
9287
10673
|
}
|
|
9288
10674
|
|
|
9289
|
-
.btn
|
|
9290
|
-
|
|
10675
|
+
.btn {
|
|
10676
|
+
padding: 10px 20px;
|
|
9291
10677
|
border: none;
|
|
9292
|
-
|
|
9293
|
-
padding: 10px 8px;
|
|
10678
|
+
border-radius: 4px;
|
|
9294
10679
|
font-size: 14px;
|
|
9295
10680
|
font-weight: 500;
|
|
9296
|
-
font-family: inherit;
|
|
9297
10681
|
cursor: pointer;
|
|
9298
|
-
margin-right: auto;
|
|
9299
|
-
border-radius: 4px;
|
|
9300
10682
|
transition: background-color 0.2s ease;
|
|
9301
10683
|
}
|
|
9302
10684
|
|
|
9303
|
-
.btn-
|
|
9304
|
-
background: var(--
|
|
10685
|
+
.btn-primary {
|
|
10686
|
+
background: var(--buttonBgColor, var(--jupiter-primary-color, #1976d2));
|
|
10687
|
+
color: var(--buttonTextColor, white);
|
|
10688
|
+
}
|
|
10689
|
+
|
|
10690
|
+
.btn-primary:hover {
|
|
10691
|
+
opacity: 0.9;
|
|
9305
10692
|
}
|
|
9306
10693
|
`;
|
|
9307
|
-
__decorateClass$1([
|
|
9308
|
-
n2({ type: Boolean, reflect: true })
|
|
9309
|
-
], JupiterFilterRolesDialog.prototype, "open", 2);
|
|
9310
|
-
__decorateClass$1([
|
|
9311
|
-
n2({ type: Array })
|
|
9312
|
-
], JupiterFilterRolesDialog.prototype, "availableRoles", 2);
|
|
9313
10694
|
__decorateClass$1([
|
|
9314
10695
|
n2({ type: Array })
|
|
9315
|
-
],
|
|
9316
|
-
__decorateClass$1([
|
|
9317
|
-
n2({ type: Object })
|
|
9318
|
-
], JupiterFilterRolesDialog.prototype, "periodPreferences", 2);
|
|
9319
|
-
__decorateClass$1([
|
|
9320
|
-
n2({ type: String })
|
|
9321
|
-
], JupiterFilterRolesDialog.prototype, "mode", 2);
|
|
10696
|
+
], JupiterFormulaValidationDialog.prototype, "results", 2);
|
|
9322
10697
|
__decorateClass$1([
|
|
9323
10698
|
n2({ type: Object })
|
|
9324
|
-
],
|
|
9325
|
-
__decorateClass$1([
|
|
9326
|
-
n2({ type: Boolean })
|
|
9327
|
-
], JupiterFilterRolesDialog.prototype, "showFactsOnly", 2);
|
|
9328
|
-
__decorateClass$1([
|
|
9329
|
-
n2({ type: String })
|
|
9330
|
-
], JupiterFilterRolesDialog.prototype, "conceptSearchText", 2);
|
|
9331
|
-
__decorateClass$1([
|
|
9332
|
-
r()
|
|
9333
|
-
], JupiterFilterRolesDialog.prototype, "_tempSelectedRoles", 2);
|
|
9334
|
-
__decorateClass$1([
|
|
9335
|
-
r()
|
|
9336
|
-
], JupiterFilterRolesDialog.prototype, "_searchQuery", 2);
|
|
9337
|
-
__decorateClass$1([
|
|
9338
|
-
r()
|
|
9339
|
-
], JupiterFilterRolesDialog.prototype, "_filteredRoles", 2);
|
|
9340
|
-
__decorateClass$1([
|
|
9341
|
-
r()
|
|
9342
|
-
], JupiterFilterRolesDialog.prototype, "_tempPeriodPreferences", 2);
|
|
9343
|
-
__decorateClass$1([
|
|
9344
|
-
r()
|
|
9345
|
-
], JupiterFilterRolesDialog.prototype, "_selectedAvailableRole", 2);
|
|
9346
|
-
__decorateClass$1([
|
|
9347
|
-
r()
|
|
9348
|
-
], JupiterFilterRolesDialog.prototype, "_selectedChosenRole", 2);
|
|
9349
|
-
__decorateClass$1([
|
|
9350
|
-
r()
|
|
9351
|
-
], JupiterFilterRolesDialog.prototype, "_chosenSearchQuery", 2);
|
|
9352
|
-
__decorateClass$1([
|
|
9353
|
-
r()
|
|
9354
|
-
], JupiterFilterRolesDialog.prototype, "_draggedRoleId", 2);
|
|
9355
|
-
__decorateClass$1([
|
|
9356
|
-
r()
|
|
9357
|
-
], JupiterFilterRolesDialog.prototype, "_dragOverRoleId", 2);
|
|
9358
|
-
__decorateClass$1([
|
|
9359
|
-
r()
|
|
9360
|
-
], JupiterFilterRolesDialog.prototype, "_chosenRoleOrder", 2);
|
|
9361
|
-
__decorateClass$1([
|
|
9362
|
-
r()
|
|
9363
|
-
], JupiterFilterRolesDialog.prototype, "_showAdvancedFilter", 2);
|
|
9364
|
-
__decorateClass$1([
|
|
9365
|
-
r()
|
|
9366
|
-
], JupiterFilterRolesDialog.prototype, "_showFactsOnly", 2);
|
|
10699
|
+
], JupiterFormulaValidationDialog.prototype, "summary", 2);
|
|
9367
10700
|
__decorateClass$1([
|
|
9368
|
-
|
|
9369
|
-
],
|
|
10701
|
+
n2({ type: Boolean, reflect: true })
|
|
10702
|
+
], JupiterFormulaValidationDialog.prototype, "open", 2);
|
|
9370
10703
|
__decorateClass$1([
|
|
9371
10704
|
r()
|
|
9372
|
-
],
|
|
9373
|
-
|
|
9374
|
-
t$1("jupiter-
|
|
9375
|
-
],
|
|
10705
|
+
], JupiterFormulaValidationDialog.prototype, "_collapsedGroups", 2);
|
|
10706
|
+
JupiterFormulaValidationDialog = __decorateClass$1([
|
|
10707
|
+
t$1("jupiter-formula-validation-dialog")
|
|
10708
|
+
], JupiterFormulaValidationDialog);
|
|
9376
10709
|
var __defProp = Object.defineProperty;
|
|
9377
10710
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
9378
10711
|
var __decorateClass = (decorators, target, key, kind) => {
|
|
@@ -9392,6 +10725,7 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
9392
10725
|
this.disabled = false;
|
|
9393
10726
|
this.readonly = false;
|
|
9394
10727
|
this.calculationEnabled = false;
|
|
10728
|
+
this.formulaEnabled = false;
|
|
9395
10729
|
this.periodStartDate = "2025-01-01";
|
|
9396
10730
|
this.periodEndDate = "2025-12-31";
|
|
9397
10731
|
this.language = "en";
|
|
@@ -9411,6 +10745,7 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
9411
10745
|
this._unitData = {};
|
|
9412
10746
|
this._preservedUnitData = {};
|
|
9413
10747
|
this._decimalsData = {};
|
|
10748
|
+
this._totalManuallyEditedData = {};
|
|
9414
10749
|
this._effectiveMasterData = void 0;
|
|
9415
10750
|
this._typedMemberData = {};
|
|
9416
10751
|
this._preservedTypedMemberData = {};
|
|
@@ -9443,6 +10778,9 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
9443
10778
|
this._contextMenuY = 0;
|
|
9444
10779
|
this._contextMenuRoleId = null;
|
|
9445
10780
|
this._validationStatus = "idle";
|
|
10781
|
+
this._formulaValidationResults = [];
|
|
10782
|
+
this._showFormulaValidationDialog = false;
|
|
10783
|
+
this._formulaValidationService = new FormulaValidationService();
|
|
9446
10784
|
this._skipDraftLoading = false;
|
|
9447
10785
|
this._skipPeriodPreferencesRestore = false;
|
|
9448
10786
|
this._autoSaveTimer = null;
|
|
@@ -9474,6 +10812,24 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
9474
10812
|
this.addEventListener("calculation-mismatch-changed", (e2) => {
|
|
9475
10813
|
this._handleCalculationMismatchChanged(e2);
|
|
9476
10814
|
});
|
|
10815
|
+
this.addEventListener("total-manually-edited", (e2) => {
|
|
10816
|
+
const { conceptId, columnId } = e2.detail;
|
|
10817
|
+
const updated = { ...this._totalManuallyEditedData };
|
|
10818
|
+
updated[conceptId] = { ...updated[conceptId], [columnId]: true };
|
|
10819
|
+
this._totalManuallyEditedData = updated;
|
|
10820
|
+
});
|
|
10821
|
+
this.addEventListener("calculation-total-auto-populated", (e2) => {
|
|
10822
|
+
const { conceptId, columnId, value } = e2.detail;
|
|
10823
|
+
const oldValue = this._writeFormDataValue(conceptId, columnId, value);
|
|
10824
|
+
this._touched.add(`${conceptId}-${columnId}`);
|
|
10825
|
+
this._dirty = true;
|
|
10826
|
+
this._validateForm();
|
|
10827
|
+
this.requestUpdate();
|
|
10828
|
+
this.dispatchEvent(new CustomEvent("field-change", {
|
|
10829
|
+
detail: { fieldId: conceptId, conceptId, columnId, value, oldValue, source: "auto-calculated" },
|
|
10830
|
+
bubbles: true
|
|
10831
|
+
}));
|
|
10832
|
+
});
|
|
9477
10833
|
document.addEventListener("click", () => {
|
|
9478
10834
|
if (this._showRoleContextMenu) {
|
|
9479
10835
|
this._showRoleContextMenu = false;
|
|
@@ -10148,6 +11504,20 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
10148
11504
|
const roleCount = this._getRoleIdsArray().length;
|
|
10149
11505
|
console.log(`🚫 Filter dialog cancelled. Current selection: ${roleCount}/${this._allSections.length}`);
|
|
10150
11506
|
}
|
|
11507
|
+
// JDF-050: closes the formula-validation results dialog opened by JDF-049's pre-flight.
|
|
11508
|
+
// Purely a visibility toggle — submit already proceeded on the click that opened it
|
|
11509
|
+
// (non-blocking, per the corrected JDF-043 Q4 decision), so there is nothing to resume here.
|
|
11510
|
+
_handleFormulaValidationDialogCancel() {
|
|
11511
|
+
this._showFormulaValidationDialog = false;
|
|
11512
|
+
}
|
|
11513
|
+
// JDF-059: a concept name inside a formula-validation message was clicked — close the popup
|
|
11514
|
+
// (mirrors the existing "click a validation error, land on its field" UX from the host-rendered
|
|
11515
|
+
// show-validation-results flow) and jump straight to the exact fact the assertion's own variable
|
|
11516
|
+
// resolution identified, via `columnId` rather than re-deriving it from dimensions.
|
|
11517
|
+
_handleFormulaConceptClick(event) {
|
|
11518
|
+
this._showFormulaValidationDialog = false;
|
|
11519
|
+
this.scrollToConcept(event.detail.conceptQName, void 0, void 0, event.detail.columnId);
|
|
11520
|
+
}
|
|
10151
11521
|
_handleRoleFilterApply(event) {
|
|
10152
11522
|
var _a, _b;
|
|
10153
11523
|
const { selectedRoleIds, periodPreferences } = event.detail;
|
|
@@ -10175,7 +11545,8 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
10175
11545
|
this._repeatCounts,
|
|
10176
11546
|
this._decimalsData,
|
|
10177
11547
|
void 0,
|
|
10178
|
-
this._getHiddenColumnsForMetadata()
|
|
11548
|
+
this._getHiddenColumnsForMetadata(),
|
|
11549
|
+
this._totalManuallyEditedData
|
|
10179
11550
|
);
|
|
10180
11551
|
this._draftStorageService.saveDraft(currentFormData, currentMetadata);
|
|
10181
11552
|
console.log("✅ Current form data saved to draft storage with NEW preferences");
|
|
@@ -10284,9 +11655,13 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
10284
11655
|
this._calculationWarnings = next;
|
|
10285
11656
|
this._validateForm();
|
|
10286
11657
|
}
|
|
10287
|
-
|
|
10288
|
-
|
|
10289
|
-
|
|
11658
|
+
/**
|
|
11659
|
+
* JDF-058: single source of truth for writing a value into `_formData` with the immutable-update
|
|
11660
|
+
* pattern Lit reactivity needs — shared by a real user keystroke (`_handleFieldChange`) and the
|
|
11661
|
+
* auto-populate-totals `calculation-total-auto-populated` handler, so the update logic isn't
|
|
11662
|
+
* duplicated. Returns the value that was previously stored, for event `oldValue` fields.
|
|
11663
|
+
*/
|
|
11664
|
+
_writeFormDataValue(conceptId, columnId, value) {
|
|
10290
11665
|
const updatedFormData = { ...this._formData };
|
|
10291
11666
|
if (!updatedFormData[conceptId]) {
|
|
10292
11667
|
updatedFormData[conceptId] = {};
|
|
@@ -10294,6 +11669,12 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
10294
11669
|
const oldValue = updatedFormData[conceptId][columnId];
|
|
10295
11670
|
updatedFormData[conceptId] = { ...updatedFormData[conceptId], [columnId]: value };
|
|
10296
11671
|
this._formData = updatedFormData;
|
|
11672
|
+
return oldValue;
|
|
11673
|
+
}
|
|
11674
|
+
_handleFieldChange(event) {
|
|
11675
|
+
const { fieldId, conceptId, columnId, value } = event.detail;
|
|
11676
|
+
console.log(`📝 Field change: conceptId=${conceptId}, columnId=${columnId}, value=${value}, fieldId=${fieldId}`);
|
|
11677
|
+
const oldValue = this._writeFormDataValue(conceptId, columnId, value);
|
|
10297
11678
|
console.log(`💾 Updated formData[${conceptId}]:`, this._formData[conceptId]);
|
|
10298
11679
|
this._touched.add(`${conceptId}-${columnId}`);
|
|
10299
11680
|
this._dirty = true;
|
|
@@ -11296,6 +12677,89 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
11296
12677
|
this._submitDisabled = false;
|
|
11297
12678
|
}, 1e3);
|
|
11298
12679
|
}
|
|
12680
|
+
/**
|
|
12681
|
+
* Handler for the standalone "Quick Validate" button (visible only when `formulaEnabled` is
|
|
12682
|
+
* true). Runs the formula-assertion pre-flight in isolation from the original Validate/submit
|
|
12683
|
+
* button, which no longer triggers formula validation as a side effect.
|
|
12684
|
+
*/
|
|
12685
|
+
_handleQuickValidate() {
|
|
12686
|
+
if (this.mode === "admin")
|
|
12687
|
+
return;
|
|
12688
|
+
this._runFormulaValidationPreflight();
|
|
12689
|
+
}
|
|
12690
|
+
/**
|
|
12691
|
+
* JDF-049: runs FormulaValidationService against the live form state and stores the results
|
|
12692
|
+
* for the results dialog (JDF-050). Graceful no-op — per JDF-048's gating and this ticket's
|
|
12693
|
+
* "no Validate-formulas affordance/effect when formula data is absent" requirement — when
|
|
12694
|
+
* `formulaEnabled` is off or `xbrlInput.formula` has no roles. Never blocks the caller; always
|
|
12695
|
+
* returns before any resolution work is attempted when gated off (JDF-048's "zero evaluation
|
|
12696
|
+
* cost when off" requirement).
|
|
12697
|
+
*/
|
|
12698
|
+
_runFormulaValidationPreflight() {
|
|
12699
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
12700
|
+
if (!this.formulaEnabled)
|
|
12701
|
+
return;
|
|
12702
|
+
const formulaRoles = (_c = (_b = (_a = this.xbrlInput) == null ? void 0 : _a.formula) == null ? void 0 : _b[0]) == null ? void 0 : _c.roles;
|
|
12703
|
+
if (!formulaRoles || formulaRoles.length === 0)
|
|
12704
|
+
return;
|
|
12705
|
+
const scopeSections = ((_e = (_d = this._currentSchema) == null ? void 0 : _d.sections) == null ? void 0 : _e.length) ? this._currentSchema.sections : this._allSections;
|
|
12706
|
+
if (!scopeSections || scopeSections.length === 0)
|
|
12707
|
+
return;
|
|
12708
|
+
const visibleRoleURIs = new Set(scopeSections.map((section2) => {
|
|
12709
|
+
var _a2;
|
|
12710
|
+
return ((_a2 = section2.metadata) == null ? void 0 : _a2.roleURI) || section2.id;
|
|
12711
|
+
}));
|
|
12712
|
+
const scopedFormulaRoles = formulaRoles.filter((role) => visibleRoleURIs.has(role.roleURI));
|
|
12713
|
+
if (scopedFormulaRoles.length === 0)
|
|
12714
|
+
return;
|
|
12715
|
+
const conceptSections = scopeSections.map((section2) => {
|
|
12716
|
+
var _a2;
|
|
12717
|
+
return {
|
|
12718
|
+
roleURI: ((_a2 = section2.metadata) == null ? void 0 : _a2.roleURI) || section2.id,
|
|
12719
|
+
concepts: section2.concepts
|
|
12720
|
+
};
|
|
12721
|
+
});
|
|
12722
|
+
const ctx = buildFormulaResolutionContext(
|
|
12723
|
+
this._formData,
|
|
12724
|
+
this._mergeAllSectionColumns(),
|
|
12725
|
+
conceptSections,
|
|
12726
|
+
(_h = (_g = (_f = this.xbrlInput) == null ? void 0 : _f.hypercubes) == null ? void 0 : _g[0]) == null ? void 0 : _h.roles,
|
|
12727
|
+
this.periodStartDate,
|
|
12728
|
+
this.periodEndDate
|
|
12729
|
+
);
|
|
12730
|
+
const scopedXbrlInput = {
|
|
12731
|
+
...this.xbrlInput,
|
|
12732
|
+
formula: [{ ...this.xbrlInput.formula[0], roles: scopedFormulaRoles }]
|
|
12733
|
+
};
|
|
12734
|
+
const results = this._formulaValidationService.evaluate(scopedXbrlInput, ctx, this.language);
|
|
12735
|
+
const summary = this._formulaValidationService.summarize(results);
|
|
12736
|
+
this._formulaValidationResults = results;
|
|
12737
|
+
this._formulaValidationSummary = summary;
|
|
12738
|
+
const hasFailures = results.some((result) => !result.skipped && !result.satisfied);
|
|
12739
|
+
if (hasFailures) {
|
|
12740
|
+
this._showFormulaValidationDialog = true;
|
|
12741
|
+
}
|
|
12742
|
+
this.dispatchEvent(new CustomEvent("formula-validation-complete", {
|
|
12743
|
+
detail: { results, summary },
|
|
12744
|
+
bubbles: true,
|
|
12745
|
+
composed: true
|
|
12746
|
+
}));
|
|
12747
|
+
}
|
|
12748
|
+
/**
|
|
12749
|
+
* Formula assertions can reference concepts/dimensions from any disclosure role, but
|
|
12750
|
+
* `FormColumn`s (especially dimension columns) are tracked per-section (`section.columns`),
|
|
12751
|
+
* with `this._columns` as the shared/default fallback (see the pattern at L1398/L2814/L5284).
|
|
12752
|
+
* `_formData` itself is already global (keyed by conceptId/columnId, no section nesting), so a
|
|
12753
|
+
* single merged, deduplicated-by-id column list is the correct match for it.
|
|
12754
|
+
*/
|
|
12755
|
+
_mergeAllSectionColumns() {
|
|
12756
|
+
const merged = /* @__PURE__ */ new Map();
|
|
12757
|
+
this._columns.forEach((column2) => merged.set(column2.id, column2));
|
|
12758
|
+
this._allSections.forEach((section2) => {
|
|
12759
|
+
(section2.columns || []).forEach((column2) => merged.set(column2.id, column2));
|
|
12760
|
+
});
|
|
12761
|
+
return Array.from(merged.values());
|
|
12762
|
+
}
|
|
11299
12763
|
_handleSaveDraft(source = "manual") {
|
|
11300
12764
|
console.log(`🔵 [Save Draft] Checking for errors...`);
|
|
11301
12765
|
console.log(`🔵 [Save Draft] _xbrlFormErrors.length: ${this._xbrlFormErrors.length}`);
|
|
@@ -11333,7 +12797,8 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
11333
12797
|
this._repeatCounts,
|
|
11334
12798
|
this._decimalsData,
|
|
11335
12799
|
roleCompletedStates,
|
|
11336
|
-
this._getHiddenColumnsForMetadata()
|
|
12800
|
+
this._getHiddenColumnsForMetadata(),
|
|
12801
|
+
this._totalManuallyEditedData
|
|
11337
12802
|
);
|
|
11338
12803
|
const draftPayloadSnapshot = JSON.stringify({
|
|
11339
12804
|
draftData,
|
|
@@ -11475,6 +12940,10 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
11475
12940
|
);
|
|
11476
12941
|
console.log("🔄 Restored hidden columns for", this._hiddenColumnIds.size, "sections");
|
|
11477
12942
|
}
|
|
12943
|
+
if (metadata.totalManuallyEditedData) {
|
|
12944
|
+
this._totalManuallyEditedData = metadata.totalManuallyEditedData;
|
|
12945
|
+
console.log("🔄 Restored total manually-edited data:", Object.keys(this._totalManuallyEditedData).length, "concepts");
|
|
12946
|
+
}
|
|
11478
12947
|
if (metadata.periodPreferences) {
|
|
11479
12948
|
if (this._skipPeriodPreferencesRestore) {
|
|
11480
12949
|
console.log("⏭️ Skipping period preferences restoration - using new filter selections");
|
|
@@ -11554,6 +13023,7 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
11554
13023
|
});
|
|
11555
13024
|
this._formData = { ...this._formData, ...restoredFormData };
|
|
11556
13025
|
console.log(`🔄 Restored ${Object.keys(restoredFormData).length} concepts with data`);
|
|
13026
|
+
this._seedLegacyManuallyEditedTotals(restoredFormData);
|
|
11557
13027
|
this._initializeGlobalDecimalsFromRoundingData();
|
|
11558
13028
|
this._periodData = {
|
|
11559
13029
|
...this._periodData,
|
|
@@ -11687,6 +13157,47 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
11687
13157
|
});
|
|
11688
13158
|
console.log(`✅ Field population complete: ${populatedCount} populated, ${notFoundCount} not found`);
|
|
11689
13159
|
}
|
|
13160
|
+
/**
|
|
13161
|
+
* JDF-058: seed the manual-edit dirty flag for any total whose value predates this feature, so
|
|
13162
|
+
* upgrading never silently recomputes a customer's pre-existing, already-filed totals. Walks
|
|
13163
|
+
* `_allSections` (the full pool, including currently-hidden/filtered-out sections — a hidden
|
|
13164
|
+
* total's pre-existing value must stay protected the moment its section becomes visible again),
|
|
13165
|
+
* not just the currently-selected roles. Idempotent: only seeds a cell that has no explicit
|
|
13166
|
+
* `totalManuallyEditedData` entry already (i.e. `metadata.totalManuallyEditedData` didn't cover
|
|
13167
|
+
* it), so re-running on an already-seeded draft is a no-op. Does not touch `restoredFormData`.
|
|
13168
|
+
*/
|
|
13169
|
+
_seedLegacyManuallyEditedTotals(restoredFormData) {
|
|
13170
|
+
const seeded = { ...this._totalManuallyEditedData };
|
|
13171
|
+
let changed = false;
|
|
13172
|
+
const walk = (concepts) => {
|
|
13173
|
+
var _a;
|
|
13174
|
+
for (const concept of concepts) {
|
|
13175
|
+
if (isTotalLabel$1(concept.preferredLabel)) {
|
|
13176
|
+
const values = restoredFormData[concept.id];
|
|
13177
|
+
if (values) {
|
|
13178
|
+
for (const columnId of Object.keys(values)) {
|
|
13179
|
+
const value = values[columnId];
|
|
13180
|
+
const isBlank = value === null || value === void 0 || value === "";
|
|
13181
|
+
if (!isBlank && ((_a = seeded[concept.id]) == null ? void 0 : _a[columnId]) === void 0) {
|
|
13182
|
+
seeded[concept.id] = { ...seeded[concept.id] || {}, [columnId]: true };
|
|
13183
|
+
changed = true;
|
|
13184
|
+
}
|
|
13185
|
+
}
|
|
13186
|
+
}
|
|
13187
|
+
}
|
|
13188
|
+
if (concept.children && concept.children.length > 0) {
|
|
13189
|
+
walk(concept.children);
|
|
13190
|
+
}
|
|
13191
|
+
}
|
|
13192
|
+
};
|
|
13193
|
+
for (const section2 of this._allSections) {
|
|
13194
|
+
walk(section2.concepts || []);
|
|
13195
|
+
}
|
|
13196
|
+
if (changed) {
|
|
13197
|
+
this._totalManuallyEditedData = seeded;
|
|
13198
|
+
console.log("🔒 [JDF-058] Seeded manual-edit protection for pre-existing total values in legacy draft");
|
|
13199
|
+
}
|
|
13200
|
+
}
|
|
11690
13201
|
_restoreCustomColumns(customColumns) {
|
|
11691
13202
|
const columnsBySection = /* @__PURE__ */ new Map();
|
|
11692
13203
|
customColumns.forEach((col) => {
|
|
@@ -13136,6 +14647,7 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
13136
14647
|
.periodStartDate="${this.periodStartDate}"
|
|
13137
14648
|
.periodEndDate="${this.periodEndDate}"
|
|
13138
14649
|
.calculationEnabled="${this.calculationEnabled}"
|
|
14650
|
+
.totalManuallyEditedData="${this._totalManuallyEditedData}"
|
|
13139
14651
|
@field-change="${this._handleFieldChange}"
|
|
13140
14652
|
@period-change="${this._handlePeriodChange}"
|
|
13141
14653
|
@typed-member-change="${this._handleTypedMemberChange}"
|
|
@@ -13284,6 +14796,7 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
13284
14796
|
.periodStartDate="${this.periodStartDate}"
|
|
13285
14797
|
.periodEndDate="${this.periodEndDate}"
|
|
13286
14798
|
.calculationEnabled="${this.calculationEnabled}"
|
|
14799
|
+
.totalManuallyEditedData="${this._totalManuallyEditedData}"
|
|
13287
14800
|
@field-change="${this._handleFieldChange}"
|
|
13288
14801
|
@typed-member-change="${this._handleTypedMemberChange}"
|
|
13289
14802
|
@add-concept-repeat="${this._handleAddConceptRepeat}"
|
|
@@ -13382,9 +14895,9 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
13382
14895
|
return dims.length === 1 && this._normalizeAxisId(col.dimensionData.axisId ?? "") === this._normalizeAxisId(dims[0].axis) && this._normalizeMemberId(col.dimensionData.memberId ?? "") === this._normalizeMemberId(dims[0].member);
|
|
13383
14896
|
})) == null ? void 0 : _a.id;
|
|
13384
14897
|
}
|
|
13385
|
-
async scrollToConcept(conceptName, dimensions, match) {
|
|
14898
|
+
async scrollToConcept(conceptName, dimensions, match, columnId) {
|
|
13386
14899
|
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
|
13387
|
-
console.log(`[scrollToConcept] ▶ START conceptName=${conceptName} value=${match == null ? void 0 : match.value} dims=${JSON.stringify(dimensions)}`);
|
|
14900
|
+
console.log(`[scrollToConcept] ▶ START conceptName=${conceptName} value=${match == null ? void 0 : match.value} dims=${JSON.stringify(dimensions)} columnId=${columnId}`);
|
|
13388
14901
|
let targetSection = null;
|
|
13389
14902
|
let targetConcept = null;
|
|
13390
14903
|
const sectionsToSearch = [
|
|
@@ -13398,7 +14911,19 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
13398
14911
|
for (const section2 of sectionsToSearch) {
|
|
13399
14912
|
const found = this._findConceptByName(section2.concepts, conceptName);
|
|
13400
14913
|
if (found) {
|
|
13401
|
-
if (
|
|
14914
|
+
if (columnId) {
|
|
14915
|
+
const cols = section2.columns ?? this._columns;
|
|
14916
|
+
const hasColumn = cols.some((c2) => c2.id === columnId);
|
|
14917
|
+
console.log(`[scrollToConcept] Section "${section2.id}" has concept "${found.id}" | columnId="${columnId}" present=${hasColumn}`);
|
|
14918
|
+
if (hasColumn) {
|
|
14919
|
+
targetSection = section2;
|
|
14920
|
+
targetConcept = found;
|
|
14921
|
+
break;
|
|
14922
|
+
} else if (!targetSection) {
|
|
14923
|
+
targetSection = section2;
|
|
14924
|
+
targetConcept = found;
|
|
14925
|
+
}
|
|
14926
|
+
} else if (dimensions == null ? void 0 : dimensions.length) {
|
|
13402
14927
|
const cols = section2.columns ?? this._columns;
|
|
13403
14928
|
const colId = this._findColumnByDimensions(cols, dimensions);
|
|
13404
14929
|
console.log(`[scrollToConcept] Section "${section2.id}" has concept "${found.id}" | colMatch=${colId ?? "null"} | cols=${cols.map((c2) => c2.id).join(",")}`);
|
|
@@ -13431,7 +14956,9 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
13431
14956
|
let targetColumnId = null;
|
|
13432
14957
|
const hasValueMatch = (match == null ? void 0 : match.value) !== void 0 && (match == null ? void 0 : match.value) !== null;
|
|
13433
14958
|
const targetValue = hasValueMatch ? String(match.value) : null;
|
|
13434
|
-
if (
|
|
14959
|
+
if (columnId) {
|
|
14960
|
+
targetColumnId = columnId;
|
|
14961
|
+
} else if (dimensions == null ? void 0 : dimensions.length) {
|
|
13435
14962
|
targetColumnId = this._findColumnByDimensions(columns, dimensions) ?? null;
|
|
13436
14963
|
} else if (!hasValueMatch) {
|
|
13437
14964
|
targetColumnId = ((_b = columns[0]) == null ? void 0 : _b.id) ?? null;
|
|
@@ -13677,6 +15204,15 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
13677
15204
|
</button>
|
|
13678
15205
|
` : ""}
|
|
13679
15206
|
|
|
15207
|
+
${this.formulaEnabled && this.mode !== "admin" ? html`
|
|
15208
|
+
<button
|
|
15209
|
+
class="btn-secondary btn-quick-validate"
|
|
15210
|
+
@click="${this._handleQuickValidate}"
|
|
15211
|
+
?disabled="${this.disabled || this.readonly || this._validationStatus === "inProgress"}"
|
|
15212
|
+
>
|
|
15213
|
+
${I18n.t("form.quickValidate")}
|
|
15214
|
+
</button>
|
|
15215
|
+
` : ""}
|
|
13680
15216
|
|
|
13681
15217
|
<button
|
|
13682
15218
|
class="btn-primary"
|
|
@@ -13706,7 +15242,19 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
13706
15242
|
@click="${this._handleFilterDialogCancel}"
|
|
13707
15243
|
></jupiter-filter-roles-dialog>
|
|
13708
15244
|
` : ""}
|
|
13709
|
-
|
|
15245
|
+
|
|
15246
|
+
<!-- Formula Validation Results Dialog (JDF-050) -->
|
|
15247
|
+
${this._showFormulaValidationDialog ? html`
|
|
15248
|
+
<jupiter-formula-validation-dialog
|
|
15249
|
+
?open="${this._showFormulaValidationDialog}"
|
|
15250
|
+
.results="${this._formulaValidationResults}"
|
|
15251
|
+
.summary="${this._formulaValidationSummary}"
|
|
15252
|
+
@dialog-cancel="${this._handleFormulaValidationDialogCancel}"
|
|
15253
|
+
@formula-concept-click="${this._handleFormulaConceptClick}"
|
|
15254
|
+
@click="${this._handleFormulaValidationDialogCancel}"
|
|
15255
|
+
></jupiter-formula-validation-dialog>
|
|
15256
|
+
` : ""}
|
|
15257
|
+
|
|
13710
15258
|
<!-- Validation Error Popup -->
|
|
13711
15259
|
${this._showErrorPopup ? html`
|
|
13712
15260
|
<div class="error-popup-overlay" @click="${() => {
|
|
@@ -14623,6 +16171,9 @@ __decorateClass([
|
|
|
14623
16171
|
__decorateClass([
|
|
14624
16172
|
n2({ type: Boolean, attribute: "calculation-enabled" })
|
|
14625
16173
|
], JupiterDynamicForm.prototype, "calculationEnabled", 2);
|
|
16174
|
+
__decorateClass([
|
|
16175
|
+
n2({ type: Boolean, attribute: "formula-enabled" })
|
|
16176
|
+
], JupiterDynamicForm.prototype, "formulaEnabled", 2);
|
|
14626
16177
|
__decorateClass([
|
|
14627
16178
|
n2({ type: String })
|
|
14628
16179
|
], JupiterDynamicForm.prototype, "periodStartDate", 2);
|
|
@@ -14695,6 +16246,9 @@ __decorateClass([
|
|
|
14695
16246
|
__decorateClass([
|
|
14696
16247
|
r()
|
|
14697
16248
|
], JupiterDynamicForm.prototype, "_decimalsData", 2);
|
|
16249
|
+
__decorateClass([
|
|
16250
|
+
r()
|
|
16251
|
+
], JupiterDynamicForm.prototype, "_totalManuallyEditedData", 2);
|
|
14698
16252
|
__decorateClass([
|
|
14699
16253
|
r()
|
|
14700
16254
|
], JupiterDynamicForm.prototype, "_effectiveMasterData", 2);
|
|
@@ -14794,6 +16348,15 @@ __decorateClass([
|
|
|
14794
16348
|
__decorateClass([
|
|
14795
16349
|
r()
|
|
14796
16350
|
], JupiterDynamicForm.prototype, "_validationStatus", 2);
|
|
16351
|
+
__decorateClass([
|
|
16352
|
+
r()
|
|
16353
|
+
], JupiterDynamicForm.prototype, "_formulaValidationResults", 2);
|
|
16354
|
+
__decorateClass([
|
|
16355
|
+
r()
|
|
16356
|
+
], JupiterDynamicForm.prototype, "_formulaValidationSummary", 2);
|
|
16357
|
+
__decorateClass([
|
|
16358
|
+
r()
|
|
16359
|
+
], JupiterDynamicForm.prototype, "_showFormulaValidationDialog", 2);
|
|
14797
16360
|
JupiterDynamicForm = __decorateClass([
|
|
14798
16361
|
t$1("jupiter-dynamic-form")
|
|
14799
16362
|
], JupiterDynamicForm);
|
|
@@ -14808,6 +16371,7 @@ export {
|
|
|
14808
16371
|
JupiterFilterRolesDialog,
|
|
14809
16372
|
JupiterFormField,
|
|
14810
16373
|
JupiterFormSection,
|
|
16374
|
+
JupiterFormulaValidationDialog,
|
|
14811
16375
|
TYPE_INPUT_MAP,
|
|
14812
16376
|
XBRLValidator,
|
|
14813
16377
|
collectEnumerationsFromChain,
|