jupiter-dynamic-forms 1.19.7 → 1.19.9
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 +4 -2
- package/dist/core/concept-tree.d.ts.map +1 -1
- package/dist/core/dynamic-form.d.ts +13 -0
- package/dist/core/dynamic-form.d.ts.map +1 -1
- package/dist/core/form-section.d.ts +8 -1
- package/dist/core/form-section.d.ts.map +1 -1
- package/dist/index.js +79 -28
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +322 -44
- package/dist/index.mjs.map +1 -1
- package/dist/schema/types.d.ts +18 -0
- package/dist/schema/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1805,6 +1805,15 @@ const error$1 = {
|
|
|
1805
1805
|
ok: "OK"
|
|
1806
1806
|
}
|
|
1807
1807
|
};
|
|
1808
|
+
const calculationWarning$1 = {
|
|
1809
|
+
title: "Calculation warning",
|
|
1810
|
+
summaryLine: 'Total "{{label}}" should equal {{calculated}}, but you entered {{entered}}.',
|
|
1811
|
+
childrenPrefix: "Children:",
|
|
1812
|
+
childAdded: "{{label}} = {{value}} (added)",
|
|
1813
|
+
childSubtracted: "{{label}} = {{value}} (subtracted, opposite balance)",
|
|
1814
|
+
added: "Added",
|
|
1815
|
+
subtracted: "Subtracted (opposite balance)"
|
|
1816
|
+
};
|
|
1808
1817
|
const enTranslations = {
|
|
1809
1818
|
conceptInfo: conceptInfo$1,
|
|
1810
1819
|
form: form$1,
|
|
@@ -1815,7 +1824,8 @@ const enTranslations = {
|
|
|
1815
1824
|
admin: admin$1,
|
|
1816
1825
|
validation: validation$1,
|
|
1817
1826
|
xbrlValidation: xbrlValidation$1,
|
|
1818
|
-
error: error$1
|
|
1827
|
+
error: error$1,
|
|
1828
|
+
calculationWarning: calculationWarning$1
|
|
1819
1829
|
};
|
|
1820
1830
|
const conceptInfo = {
|
|
1821
1831
|
title: "Conceptinformatie",
|
|
@@ -1990,6 +2000,15 @@ const error = {
|
|
|
1990
2000
|
ok: "OK"
|
|
1991
2001
|
}
|
|
1992
2002
|
};
|
|
2003
|
+
const calculationWarning = {
|
|
2004
|
+
title: "Berekeningswaarschuwing",
|
|
2005
|
+
summaryLine: 'Totaal "{{label}}" zou {{calculated}} moeten zijn, maar u heeft {{entered}} ingevoerd.',
|
|
2006
|
+
childrenPrefix: "Onderdelen:",
|
|
2007
|
+
childAdded: "{{label}} = {{value}} (opgeteld)",
|
|
2008
|
+
childSubtracted: "{{label}} = {{value}} (afgetrokken, tegengestelde balans)",
|
|
2009
|
+
added: "Opgeteld",
|
|
2010
|
+
subtracted: "Afgetrokken (tegengestelde balans)"
|
|
2011
|
+
};
|
|
1993
2012
|
const nlTranslations = {
|
|
1994
2013
|
conceptInfo,
|
|
1995
2014
|
form,
|
|
@@ -2000,7 +2019,8 @@ const nlTranslations = {
|
|
|
2000
2019
|
admin,
|
|
2001
2020
|
validation,
|
|
2002
2021
|
xbrlValidation,
|
|
2003
|
-
error
|
|
2022
|
+
error,
|
|
2023
|
+
calculationWarning
|
|
2004
2024
|
};
|
|
2005
2025
|
const translations = {
|
|
2006
2026
|
en: enTranslations,
|
|
@@ -4936,6 +4956,79 @@ let JupiterConceptTree = class extends LitElement {
|
|
|
4936
4956
|
dialog.addEventListener("close", () => document.body.removeChild(dialog));
|
|
4937
4957
|
dialog.showModal();
|
|
4938
4958
|
}
|
|
4959
|
+
_ensureCalcWarningDialogStyles() {
|
|
4960
|
+
if (document.getElementById("jdf-calc-warning-dialog-styles"))
|
|
4961
|
+
return;
|
|
4962
|
+
const style = document.createElement("style");
|
|
4963
|
+
style.id = "jdf-calc-warning-dialog-styles";
|
|
4964
|
+
style.textContent = `
|
|
4965
|
+
dialog.jdf-calc-warning-dialog {
|
|
4966
|
+
border: none; border-radius: 8px; padding: 0;
|
|
4967
|
+
max-width: 480px; width: 90vw;
|
|
4968
|
+
box-shadow: 0 8px 32px rgba(0,0,0,0.2); overflow: hidden;
|
|
4969
|
+
}
|
|
4970
|
+
dialog.jdf-calc-warning-dialog::backdrop { background: rgba(0,0,0,0.35); }
|
|
4971
|
+
.jdf-calc-warning-header {
|
|
4972
|
+
background: #fff3e0; padding: 14px 20px;
|
|
4973
|
+
display: flex; align-items: center; justify-content: space-between;
|
|
4974
|
+
border-bottom: 1px solid #ffcc80;
|
|
4975
|
+
}
|
|
4976
|
+
.jdf-calc-warning-title { font-size: 15px; font-weight: 600; color: #e65100; margin: 0; font-family: inherit; }
|
|
4977
|
+
.jdf-calc-warning-close-btn {
|
|
4978
|
+
width: 28px; height: 28px; border: none; background: transparent;
|
|
4979
|
+
font-size: 20px; line-height: 1; cursor: pointer; color: #666;
|
|
4980
|
+
border-radius: 4px; display: flex; align-items: center; justify-content: center;
|
|
4981
|
+
padding: 0; font-family: inherit;
|
|
4982
|
+
}
|
|
4983
|
+
.jdf-calc-warning-close-btn:hover { background: #ffe0b2; color: #e65100; }
|
|
4984
|
+
.jdf-calc-warning-body { padding: 20px; font-family: inherit; font-size: 13px; color: #333; }
|
|
4985
|
+
.jdf-calc-warning-summary { margin: 0 0 12px 0; font-weight: 600; }
|
|
4986
|
+
.jdf-calc-warning-table { width: 100%; border-collapse: collapse; font-size: 13px; font-family: inherit; }
|
|
4987
|
+
.jdf-calc-warning-table tr:not(:last-child) td { border-bottom: 1px solid #f0f0f0; }
|
|
4988
|
+
.jdf-calc-warning-table td { padding: 6px 4px; vertical-align: top; }
|
|
4989
|
+
.jdf-calc-warning-sign { font-weight: 600; white-space: nowrap; }
|
|
4990
|
+
.jdf-calc-warning-sign.added { color: #2e7d32; }
|
|
4991
|
+
.jdf-calc-warning-sign.subtracted { color: #c62828; }
|
|
4992
|
+
`;
|
|
4993
|
+
document.head.appendChild(style);
|
|
4994
|
+
}
|
|
4995
|
+
_openCalculationWarningDialog(e2, mismatch) {
|
|
4996
|
+
var _a;
|
|
4997
|
+
e2.stopPropagation();
|
|
4998
|
+
this._ensureCalcWarningDialogStyles();
|
|
4999
|
+
const rowsHtml = mismatch.children.map((child) => `
|
|
5000
|
+
<tr>
|
|
5001
|
+
<td>${this._escapeHtml(child.label)}</td>
|
|
5002
|
+
<td>${this._escapeHtml(String(child.value))}</td>
|
|
5003
|
+
<td>${this._escapeHtml(child.balance || "—")}</td>
|
|
5004
|
+
<td class="jdf-calc-warning-sign ${child.weight === 1 ? "added" : "subtracted"}">
|
|
5005
|
+
${this._escapeHtml(child.weight === 1 ? I18n.t("calculationWarning.added") : I18n.t("calculationWarning.subtracted"))}
|
|
5006
|
+
</td>
|
|
5007
|
+
</tr>
|
|
5008
|
+
`).join("");
|
|
5009
|
+
const dialog = document.createElement("dialog");
|
|
5010
|
+
dialog.className = "jdf-calc-warning-dialog";
|
|
5011
|
+
dialog.innerHTML = `
|
|
5012
|
+
<div class="jdf-calc-warning-header">
|
|
5013
|
+
<h3 class="jdf-calc-warning-title">⚠️ ${this._escapeHtml(I18n.t("calculationWarning.title"))}</h3>
|
|
5014
|
+
<button class="jdf-calc-warning-close-btn" type="button" aria-label="${this._escapeHtml(I18n.t("conceptInfo.close"))}">×</button>
|
|
5015
|
+
</div>
|
|
5016
|
+
<div class="jdf-calc-warning-body">
|
|
5017
|
+
<p class="jdf-calc-warning-summary">${this._escapeHtml(mismatch.message)}</p>
|
|
5018
|
+
<table class="jdf-calc-warning-table">${rowsHtml}</table>
|
|
5019
|
+
</div>
|
|
5020
|
+
`;
|
|
5021
|
+
document.body.appendChild(dialog);
|
|
5022
|
+
(_a = dialog.querySelector(".jdf-calc-warning-close-btn")) == null ? void 0 : _a.addEventListener("click", () => dialog.close());
|
|
5023
|
+
dialog.addEventListener("click", (ev) => {
|
|
5024
|
+
const rect = dialog.getBoundingClientRect();
|
|
5025
|
+
if (ev.clientX < rect.left || ev.clientX > rect.right || ev.clientY < rect.top || ev.clientY > rect.bottom) {
|
|
5026
|
+
dialog.close();
|
|
5027
|
+
}
|
|
5028
|
+
});
|
|
5029
|
+
dialog.addEventListener("close", () => document.body.removeChild(dialog));
|
|
5030
|
+
dialog.showModal();
|
|
5031
|
+
}
|
|
4939
5032
|
render() {
|
|
4940
5033
|
const hasChildren = this.concept.children && this.concept.children.length > 0;
|
|
4941
5034
|
const level = this.concept.level || 0;
|
|
@@ -4980,8 +5073,17 @@ let JupiterConceptTree = class extends LitElement {
|
|
|
4980
5073
|
const shouldShowField = !isAbstract && field2;
|
|
4981
5074
|
const storedUnit = (_b = (_a = this.unitData) == null ? void 0 : _a[this.concept.id]) == null ? void 0 : _b[column2.id];
|
|
4982
5075
|
const storedDecimals = (_d = (_c = this.decimalsData) == null ? void 0 : _c[this.concept.id]) == null ? void 0 : _d[column2.id];
|
|
5076
|
+
const calcMismatch = this.mode !== "readonly" ? (_e = this.calculationMismatches) == null ? void 0 : _e.get(`${this.concept.id}__${column2.id}`) : void 0;
|
|
4983
5077
|
return html`
|
|
4984
|
-
<td class="field-cell ${!shouldShowField ? "empty" : ""} ${isAbstract ? "abstract-row" : ""} ${this.highlightType && column2.id === this.highlightColumnId ? "highlight-" + this.highlightType : ""} ${
|
|
5078
|
+
<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" : ""}">
|
|
5079
|
+
${calcMismatch ? html`
|
|
5080
|
+
<button
|
|
5081
|
+
class="calc-warning-badge"
|
|
5082
|
+
type="button"
|
|
5083
|
+
title="${calcMismatch.message}"
|
|
5084
|
+
@click="${(e2) => this._openCalculationWarningDialog(e2, calcMismatch)}"
|
|
5085
|
+
>!</button>
|
|
5086
|
+
` : ""}
|
|
4985
5087
|
${shouldShowField ? html`
|
|
4986
5088
|
<jupiter-form-field
|
|
4987
5089
|
.field="${field2}"
|
|
@@ -5118,6 +5220,7 @@ JupiterConceptTree.styles = css`
|
|
|
5118
5220
|
}
|
|
5119
5221
|
|
|
5120
5222
|
.field-cell {
|
|
5223
|
+
position: relative;
|
|
5121
5224
|
vertical-align: middle;
|
|
5122
5225
|
padding: 2px 6px;
|
|
5123
5226
|
border: 1px solid var(--primaryTextColor, var(--jupiter-border-color, #ddd));
|
|
@@ -5192,8 +5295,35 @@ JupiterConceptTree.styles = css`
|
|
|
5192
5295
|
background: rgba(25, 118, 210, 0.07);
|
|
5193
5296
|
}
|
|
5194
5297
|
|
|
5195
|
-
|
|
5196
|
-
|
|
5298
|
+
/* Non-blocking JDF-036 live total/debit-credit mismatch warning — deliberately amber, distinct
|
|
5299
|
+
from any future genuinely-blocking calculation error, which should use a red style instead. */
|
|
5300
|
+
.field-cell.calc-warning {
|
|
5301
|
+
box-shadow: inset 0 0 0 2px var(--jupiter-warning-color, #ff9800);
|
|
5302
|
+
}
|
|
5303
|
+
|
|
5304
|
+
.calc-warning-badge {
|
|
5305
|
+
position: absolute;
|
|
5306
|
+
top: 2px;
|
|
5307
|
+
right: 2px;
|
|
5308
|
+
width: 16px;
|
|
5309
|
+
height: 16px;
|
|
5310
|
+
border-radius: 50%;
|
|
5311
|
+
border: none;
|
|
5312
|
+
background: var(--jupiter-warning-color, #ff9800);
|
|
5313
|
+
color: #fff;
|
|
5314
|
+
font-size: 10px;
|
|
5315
|
+
font-weight: 700;
|
|
5316
|
+
line-height: 1;
|
|
5317
|
+
padding: 0;
|
|
5318
|
+
display: flex;
|
|
5319
|
+
align-items: center;
|
|
5320
|
+
justify-content: center;
|
|
5321
|
+
cursor: pointer;
|
|
5322
|
+
z-index: 3;
|
|
5323
|
+
}
|
|
5324
|
+
|
|
5325
|
+
.calc-warning-badge:hover {
|
|
5326
|
+
background: #e65100;
|
|
5197
5327
|
}
|
|
5198
5328
|
|
|
5199
5329
|
/* Row-level highlight while a field in this row has focus. Applied to every
|
|
@@ -5324,7 +5454,7 @@ __decorateClass$5([
|
|
|
5324
5454
|
], JupiterConceptTree.prototype, "highlightColumnId", 2);
|
|
5325
5455
|
__decorateClass$5([
|
|
5326
5456
|
n2({ type: Object })
|
|
5327
|
-
], JupiterConceptTree.prototype, "
|
|
5457
|
+
], JupiterConceptTree.prototype, "calculationMismatches", 2);
|
|
5328
5458
|
__decorateClass$5([
|
|
5329
5459
|
n2({ type: String })
|
|
5330
5460
|
], JupiterConceptTree.prototype, "language", 2);
|
|
@@ -6029,12 +6159,18 @@ let JupiterFormSection = class extends LitElement {
|
|
|
6029
6159
|
this._boundFieldBlur = (e2) => {
|
|
6030
6160
|
this._clearHighlights();
|
|
6031
6161
|
this._focusedConceptId = null;
|
|
6162
|
+
if (this.mode === "readonly")
|
|
6163
|
+
return;
|
|
6164
|
+
const detail = e2.detail;
|
|
6165
|
+
if ((detail == null ? void 0 : detail.conceptId) && (detail == null ? void 0 : detail.columnId)) {
|
|
6166
|
+
this._runCalculationCheck(detail.conceptId, detail.columnId);
|
|
6167
|
+
}
|
|
6032
6168
|
};
|
|
6033
6169
|
this._expandedConcepts = /* @__PURE__ */ new Set();
|
|
6034
6170
|
this._allTreeExpanded = false;
|
|
6035
6171
|
this._highlightMap = /* @__PURE__ */ new Map();
|
|
6036
6172
|
this._focusedConceptId = null;
|
|
6037
|
-
this.
|
|
6173
|
+
this._calculationMismatches = /* @__PURE__ */ new Map();
|
|
6038
6174
|
this._totalChildrenMap = /* @__PURE__ */ new Map();
|
|
6039
6175
|
this._memberParentMap = /* @__PURE__ */ new Map();
|
|
6040
6176
|
this._totalConceptMap = /* @__PURE__ */ new Map();
|
|
@@ -6342,50 +6478,100 @@ let JupiterFormSection = class extends LitElement {
|
|
|
6342
6478
|
return;
|
|
6343
6479
|
const totalConcept = this._totalConceptMap.get(totalConceptId);
|
|
6344
6480
|
const totalRaw = (_a = this.formData[totalConceptId]) == null ? void 0 : _a[columnId];
|
|
6345
|
-
const
|
|
6481
|
+
const key = `${totalConceptId}__${columnId}`;
|
|
6346
6482
|
if (totalRaw === null || totalRaw === void 0 || totalRaw === "") {
|
|
6347
|
-
|
|
6348
|
-
const next2 = new Set(this._calculationErrorKeys);
|
|
6349
|
-
next2.delete(errorKey);
|
|
6350
|
-
this._calculationErrorKeys = next2;
|
|
6351
|
-
}
|
|
6483
|
+
this._clearCalculationMismatch(key);
|
|
6352
6484
|
return;
|
|
6353
6485
|
}
|
|
6354
6486
|
const totalValue = parseFloat(totalRaw);
|
|
6355
|
-
if (isNaN(totalValue))
|
|
6487
|
+
if (isNaN(totalValue)) {
|
|
6488
|
+
this._clearCalculationMismatch(key);
|
|
6356
6489
|
return;
|
|
6490
|
+
}
|
|
6357
6491
|
const children = this._totalChildConceptsMap.get(totalConceptId) || [];
|
|
6358
|
-
const
|
|
6359
|
-
|
|
6360
|
-
|
|
6361
|
-
|
|
6362
|
-
|
|
6363
|
-
|
|
6364
|
-
|
|
6365
|
-
|
|
6366
|
-
|
|
6367
|
-
if (!isValid) {
|
|
6368
|
-
next.add(errorKey);
|
|
6369
|
-
} else {
|
|
6370
|
-
next.delete(errorKey);
|
|
6492
|
+
const { calculatedSum, hasAnyValue, breakdown } = JupiterFormSection._buildCalculationBreakdown(
|
|
6493
|
+
children,
|
|
6494
|
+
this.formData,
|
|
6495
|
+
columnId,
|
|
6496
|
+
totalConcept.balance
|
|
6497
|
+
);
|
|
6498
|
+
if (!hasAnyValue || JupiterFormSection._checkTotal(totalValue, calculatedSum)) {
|
|
6499
|
+
this._clearCalculationMismatch(key);
|
|
6500
|
+
return;
|
|
6371
6501
|
}
|
|
6372
|
-
|
|
6502
|
+
const detailWithoutMessage = {
|
|
6503
|
+
totalConceptId,
|
|
6504
|
+
totalLabel: totalConcept.label,
|
|
6505
|
+
columnId,
|
|
6506
|
+
sectionId: this.section.id,
|
|
6507
|
+
enteredTotal: totalValue,
|
|
6508
|
+
calculatedSum,
|
|
6509
|
+
children: breakdown
|
|
6510
|
+
};
|
|
6511
|
+
const detail = {
|
|
6512
|
+
...detailWithoutMessage,
|
|
6513
|
+
message: JupiterFormSection._buildMismatchMessage(detailWithoutMessage)
|
|
6514
|
+
};
|
|
6515
|
+
const next = new Map(this._calculationMismatches);
|
|
6516
|
+
next.set(key, detail);
|
|
6517
|
+
this._calculationMismatches = next;
|
|
6518
|
+
this._dispatchCalculationMismatchChanged(key, detail);
|
|
6519
|
+
}
|
|
6520
|
+
_clearCalculationMismatch(key) {
|
|
6521
|
+
if (!this._calculationMismatches.has(key))
|
|
6522
|
+
return;
|
|
6523
|
+
const next = new Map(this._calculationMismatches);
|
|
6524
|
+
next.delete(key);
|
|
6525
|
+
this._calculationMismatches = next;
|
|
6526
|
+
this._dispatchCalculationMismatchChanged(key, null);
|
|
6527
|
+
}
|
|
6528
|
+
_dispatchCalculationMismatchChanged(key, mismatch) {
|
|
6529
|
+
this.dispatchEvent(new CustomEvent("calculation-mismatch-changed", {
|
|
6530
|
+
detail: { key, mismatch },
|
|
6531
|
+
bubbles: true,
|
|
6532
|
+
composed: true
|
|
6533
|
+
}));
|
|
6534
|
+
}
|
|
6535
|
+
/** Single source of truth for the debit/credit weighting used both to validate the total and to build the breakdown shown to the user. */
|
|
6536
|
+
static _resolveWeight(totalBalance, childBalance) {
|
|
6537
|
+
return !totalBalance || !childBalance || totalBalance === childBalance ? 1 : -1;
|
|
6373
6538
|
}
|
|
6374
|
-
static
|
|
6539
|
+
static _buildCalculationBreakdown(children, formData, columnId, totalBalance) {
|
|
6540
|
+
var _a;
|
|
6375
6541
|
let calculatedSum = 0;
|
|
6376
6542
|
let hasAnyValue = false;
|
|
6543
|
+
const breakdown = [];
|
|
6377
6544
|
for (const child of children) {
|
|
6378
|
-
const val = parseFloat(child.
|
|
6545
|
+
const val = parseFloat((_a = formData[child.id]) == null ? void 0 : _a[columnId]);
|
|
6379
6546
|
if (isNaN(val))
|
|
6380
6547
|
continue;
|
|
6381
6548
|
hasAnyValue = true;
|
|
6382
|
-
const weight =
|
|
6549
|
+
const weight = JupiterFormSection._resolveWeight(totalBalance, child.balance);
|
|
6383
6550
|
calculatedSum += weight * val;
|
|
6551
|
+
breakdown.push({ conceptId: child.id, label: child.label, value: val, balance: child.balance, weight });
|
|
6384
6552
|
}
|
|
6385
|
-
|
|
6386
|
-
|
|
6553
|
+
return { calculatedSum, hasAnyValue, breakdown };
|
|
6554
|
+
}
|
|
6555
|
+
static _checkTotal(totalValue, calculatedSum) {
|
|
6387
6556
|
return Math.abs(calculatedSum - totalValue) < 0.01;
|
|
6388
6557
|
}
|
|
6558
|
+
static _formatNumber(n3) {
|
|
6559
|
+
return Number.isInteger(n3) ? String(n3) : n3.toFixed(2);
|
|
6560
|
+
}
|
|
6561
|
+
static _buildMismatchMessage(detail) {
|
|
6562
|
+
const summary = I18n.t("calculationWarning.summaryLine", {
|
|
6563
|
+
label: detail.totalLabel,
|
|
6564
|
+
calculated: JupiterFormSection._formatNumber(detail.calculatedSum),
|
|
6565
|
+
entered: JupiterFormSection._formatNumber(detail.enteredTotal)
|
|
6566
|
+
});
|
|
6567
|
+
if (detail.children.length === 0)
|
|
6568
|
+
return summary;
|
|
6569
|
+
const childLines = detail.children.map((child) => I18n.t(
|
|
6570
|
+
child.weight === 1 ? "calculationWarning.childAdded" : "calculationWarning.childSubtracted",
|
|
6571
|
+
{ label: child.label, value: JupiterFormSection._formatNumber(child.value) }
|
|
6572
|
+
));
|
|
6573
|
+
return `${summary} ${I18n.t("calculationWarning.childrenPrefix")} ${childLines.join("; ")}`;
|
|
6574
|
+
}
|
|
6389
6575
|
_handleFieldFocusForHighlight(event) {
|
|
6390
6576
|
var _a, _b;
|
|
6391
6577
|
const conceptId = (_a = event.detail) == null ? void 0 : _a.conceptId;
|
|
@@ -6481,7 +6667,7 @@ let JupiterFormSection = class extends LitElement {
|
|
|
6481
6667
|
.highlightType="${(_a2 = this._highlightMap.get(instanceConcept.id)) == null ? void 0 : _a2.type}"
|
|
6482
6668
|
.highlightColumnId="${(_b = this._highlightMap.get(instanceConcept.id)) == null ? void 0 : _b.columnId}"
|
|
6483
6669
|
.rowFocused="${this._focusedConceptId === instanceConcept.id}"
|
|
6484
|
-
.
|
|
6670
|
+
.calculationMismatches="${this._calculationMismatches}"
|
|
6485
6671
|
@field-change="${this._handleFieldChange}"
|
|
6486
6672
|
@field-focus="${this._handleFieldFocusForHighlight}"
|
|
6487
6673
|
@period-change="${this._handlePeriodChange}"
|
|
@@ -7054,7 +7240,7 @@ __decorateClass$3([
|
|
|
7054
7240
|
], JupiterFormSection.prototype, "_focusedConceptId", 2);
|
|
7055
7241
|
__decorateClass$3([
|
|
7056
7242
|
r()
|
|
7057
|
-
], JupiterFormSection.prototype, "
|
|
7243
|
+
], JupiterFormSection.prototype, "_calculationMismatches", 2);
|
|
7058
7244
|
JupiterFormSection = __decorateClass$3([
|
|
7059
7245
|
t$1("jupiter-form-section")
|
|
7060
7246
|
], JupiterFormSection);
|
|
@@ -9097,6 +9283,7 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
9097
9283
|
this._valid = true;
|
|
9098
9284
|
this._submitted = false;
|
|
9099
9285
|
this._xbrlFormErrors = [];
|
|
9286
|
+
this._calculationWarnings = /* @__PURE__ */ new Map();
|
|
9100
9287
|
this._showErrorPopup = false;
|
|
9101
9288
|
this._submitDisabled = false;
|
|
9102
9289
|
this._allSections = [];
|
|
@@ -9144,6 +9331,9 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
9144
9331
|
const customEvent = e2;
|
|
9145
9332
|
this._handleFieldBlur(customEvent);
|
|
9146
9333
|
});
|
|
9334
|
+
this.addEventListener("calculation-mismatch-changed", (e2) => {
|
|
9335
|
+
this._handleCalculationMismatchChanged(e2);
|
|
9336
|
+
});
|
|
9147
9337
|
document.addEventListener("click", () => {
|
|
9148
9338
|
if (this._showRoleContextMenu) {
|
|
9149
9339
|
this._showRoleContextMenu = false;
|
|
@@ -9931,9 +10121,29 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
9931
10121
|
}
|
|
9932
10122
|
}
|
|
9933
10123
|
}
|
|
10124
|
+
errors.push(...Array.from(this._calculationWarnings.values()));
|
|
9934
10125
|
this._errors = errors;
|
|
9935
10126
|
this._valid = errors.filter((e2) => e2.severity === "error").length === 0;
|
|
9936
10127
|
}
|
|
10128
|
+
_handleCalculationMismatchChanged(event) {
|
|
10129
|
+
const { key, mismatch } = event.detail;
|
|
10130
|
+
const next = new Map(this._calculationWarnings);
|
|
10131
|
+
if (mismatch) {
|
|
10132
|
+
next.set(key, {
|
|
10133
|
+
fieldId: `${mismatch.totalConceptId}__${mismatch.columnId}`,
|
|
10134
|
+
conceptId: mismatch.totalConceptId,
|
|
10135
|
+
columnId: mismatch.columnId,
|
|
10136
|
+
message: mismatch.message,
|
|
10137
|
+
severity: "warning",
|
|
10138
|
+
rule: { type: "custom", message: mismatch.message, severity: "warning" },
|
|
10139
|
+
details: mismatch
|
|
10140
|
+
});
|
|
10141
|
+
} else {
|
|
10142
|
+
next.delete(key);
|
|
10143
|
+
}
|
|
10144
|
+
this._calculationWarnings = next;
|
|
10145
|
+
this._validateForm();
|
|
10146
|
+
}
|
|
9937
10147
|
_handleFieldChange(event) {
|
|
9938
10148
|
const { fieldId, conceptId, columnId, value } = event.detail;
|
|
9939
10149
|
console.log(`📝 Field change: conceptId=${conceptId}, columnId=${columnId}, value=${value}, fieldId=${fieldId}`);
|
|
@@ -10547,6 +10757,52 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
10547
10757
|
}
|
|
10548
10758
|
return instantDate || endDate || startDate || "2025-01-01";
|
|
10549
10759
|
}
|
|
10760
|
+
/**
|
|
10761
|
+
* JDF-037: Self-heals legacy periodStartLabel instant dates.
|
|
10762
|
+
* Drafts saved before JDF-024 have periodStartLabel concepts with the instant date
|
|
10763
|
+
* set to the column's own year instead of one day before periodStartDate. Reuses
|
|
10764
|
+
* _resolveInstantDate (no new date math) to correct both _periodData and the live
|
|
10765
|
+
* field.periodInstantDate so UI and saved output never disagree. Idempotent: only
|
|
10766
|
+
* writes when the stored value actually differs from the corrected one.
|
|
10767
|
+
*/
|
|
10768
|
+
_correctLegacyPeriodStartInstantDates() {
|
|
10769
|
+
this._allSections.forEach((section2) => {
|
|
10770
|
+
this._correctPeriodStartInstantDatesInConcepts(section2.concepts, section2);
|
|
10771
|
+
});
|
|
10772
|
+
}
|
|
10773
|
+
_correctPeriodStartInstantDatesInConcepts(concepts, section2) {
|
|
10774
|
+
concepts.forEach((concept) => {
|
|
10775
|
+
var _a, _b;
|
|
10776
|
+
if (((_a = concept.preferredLabel) == null ? void 0 : _a.includes("periodStartLabel")) && concept.periodType === "instant" && ((_b = concept.fields) == null ? void 0 : _b.length)) {
|
|
10777
|
+
concept.fields.forEach((field2) => {
|
|
10778
|
+
this._correctFieldPeriodStartInstantDate(concept, field2, concept.id, section2);
|
|
10779
|
+
const repeatCount = this._repeatCounts[concept.id] || 0;
|
|
10780
|
+
for (let n3 = 1; n3 <= repeatCount; n3++) {
|
|
10781
|
+
this._correctFieldPeriodStartInstantDate(concept, field2, `${concept.id}__repeat_${n3}`, section2);
|
|
10782
|
+
}
|
|
10783
|
+
});
|
|
10784
|
+
}
|
|
10785
|
+
if (concept.children) {
|
|
10786
|
+
this._correctPeriodStartInstantDatesInConcepts(concept.children, section2);
|
|
10787
|
+
}
|
|
10788
|
+
});
|
|
10789
|
+
}
|
|
10790
|
+
_correctFieldPeriodStartInstantDate(concept, field2, periodDataKey, section2) {
|
|
10791
|
+
var _a;
|
|
10792
|
+
const column2 = this._findColumnByIdInSection(field2.columnId, section2);
|
|
10793
|
+
const fieldPeriodData = (_a = this._periodData[periodDataKey]) == null ? void 0 : _a[field2.columnId];
|
|
10794
|
+
const periodStartDate = (fieldPeriodData == null ? void 0 : fieldPeriodData.startDate) || (column2 == null ? void 0 : column2.periodStartDate) || field2.periodStartDate || this.periodStartDate;
|
|
10795
|
+
const periodEndDate = (fieldPeriodData == null ? void 0 : fieldPeriodData.endDate) || (column2 == null ? void 0 : column2.periodEndDate) || field2.periodEndDate || this.periodEndDate;
|
|
10796
|
+
const correctedInstantDate = this._resolveInstantDate(concept.preferredLabel, void 0, periodStartDate, periodEndDate);
|
|
10797
|
+
if (fieldPeriodData && fieldPeriodData.instantDate !== correctedInstantDate) {
|
|
10798
|
+
console.log(`🩹 [Legacy Period Correction] ${periodDataKey}/${field2.columnId}: instantDate ${fieldPeriodData.instantDate} → ${correctedInstantDate}`);
|
|
10799
|
+
fieldPeriodData.instantDate = correctedInstantDate;
|
|
10800
|
+
}
|
|
10801
|
+
if (field2.periodInstantDate !== correctedInstantDate) {
|
|
10802
|
+
console.log(`🩹 [Legacy Period Correction] field ${concept.id}/${field2.columnId}: periodInstantDate ${field2.periodInstantDate} → ${correctedInstantDate}`);
|
|
10803
|
+
field2.periodInstantDate = correctedInstantDate;
|
|
10804
|
+
}
|
|
10805
|
+
}
|
|
10550
10806
|
_addColumnFromRequest(request, sectionId, insertAfterColumnId) {
|
|
10551
10807
|
var _a, _b, _c, _d, _e;
|
|
10552
10808
|
const timestamp = Date.now();
|
|
@@ -10846,6 +11102,7 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
10846
11102
|
this.requestUpdate();
|
|
10847
11103
|
return;
|
|
10848
11104
|
}
|
|
11105
|
+
this._correctLegacyPeriodStartInstantDates();
|
|
10849
11106
|
const submissionData = this._generateSubmissionData();
|
|
10850
11107
|
console.log("📊 Form Submission Data:", JSON.stringify(submissionData, null, 2));
|
|
10851
11108
|
console.log("📊 Submission Data Summary:");
|
|
@@ -10881,6 +11138,7 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
10881
11138
|
console.log("💾 Raw form data before submission generation:", this._formData);
|
|
10882
11139
|
console.log("🏷️ Unit data before submission generation:", this._unitData);
|
|
10883
11140
|
console.log("📋 Enhanced selectedRoleIds with roleURI and order:", this._selectedRoleIds);
|
|
11141
|
+
this._correctLegacyPeriodStartInstantDates();
|
|
10884
11142
|
const draftData = this._generateSubmissionData();
|
|
10885
11143
|
console.log("📤 Generated submission data:", draftData);
|
|
10886
11144
|
console.log("📊 Submission data breakdown:");
|
|
@@ -11139,6 +11397,7 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
11139
11397
|
};
|
|
11140
11398
|
console.log(`🏷️ [Unit Restore] Merged unit data: ${Object.keys(this._unitData).length} concepts with custom units`);
|
|
11141
11399
|
console.log(`🏷️ [Unit Restore] Full _unitData after merge:`, JSON.stringify(this._unitData, null, 2));
|
|
11400
|
+
this._correctLegacyPeriodStartInstantDates();
|
|
11142
11401
|
if (this._selectedRoleIds.length > 0) {
|
|
11143
11402
|
this._applyRoleFilter();
|
|
11144
11403
|
}
|
|
@@ -12645,11 +12904,11 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
12645
12904
|
<div class="form-sections">
|
|
12646
12905
|
<!-- Validation Summary -->
|
|
12647
12906
|
${showValidationSummary ? html`
|
|
12648
|
-
<div class="validation-summary">
|
|
12649
|
-
<h4 class="validation-summary-title">${I18n.t("validation.summary")}</h4>
|
|
12907
|
+
<div class="validation-summary ${errorCount === 0 ? "warnings-only" : ""}">
|
|
12908
|
+
<h4 class="validation-summary-title">${errorCount > 0 ? I18n.t("validation.summary") : I18n.t("calculationWarning.title")}</h4>
|
|
12650
12909
|
<ul class="validation-summary-list">
|
|
12651
|
-
${this._errors.filter((e2) => e2.severity === "error").map((error2) => html`
|
|
12652
|
-
<li class="validation-summary-item">${error2.message}</li>
|
|
12910
|
+
${this._errors.filter((e2) => e2.severity === "error" || e2.severity === "warning" && this.mode !== "readonly").map((error2) => html`
|
|
12911
|
+
<li class="validation-summary-item ${error2.severity}">${error2.severity === "warning" ? "⚠️ " : ""}${error2.message}</li>
|
|
12653
12912
|
`)}
|
|
12654
12913
|
</ul>
|
|
12655
12914
|
</div>
|
|
@@ -12809,11 +13068,11 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
12809
13068
|
<div class="form-sections">
|
|
12810
13069
|
<!-- Validation Summary -->
|
|
12811
13070
|
${showValidationSummary ? html`
|
|
12812
|
-
<div class="validation-summary">
|
|
12813
|
-
<h4 class="validation-summary-title">
|
|
13071
|
+
<div class="validation-summary ${errorCount === 0 ? "warnings-only" : ""}">
|
|
13072
|
+
<h4 class="validation-summary-title">${errorCount > 0 ? I18n.t("validation.summary") : I18n.t("calculationWarning.title")}</h4>
|
|
12814
13073
|
<ul class="validation-summary-list">
|
|
12815
|
-
${this._errors.filter((e2) => e2.severity === "error").map((error2) => html`
|
|
12816
|
-
<li class="validation-summary-item">${error2.message}</li>
|
|
13074
|
+
${this._errors.filter((e2) => e2.severity === "error" || e2.severity === "warning" && this.mode !== "readonly").map((error2) => html`
|
|
13075
|
+
<li class="validation-summary-item ${error2.severity}">${error2.severity === "warning" ? "⚠️ " : ""}${error2.message}</li>
|
|
12817
13076
|
`)}
|
|
12818
13077
|
</ul>
|
|
12819
13078
|
</div>
|
|
@@ -13163,8 +13422,9 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
13163
13422
|
render() {
|
|
13164
13423
|
var _a;
|
|
13165
13424
|
const errorCount = this._errors.filter((e2) => e2.severity === "error").length;
|
|
13425
|
+
const warningCount = this.mode === "readonly" ? 0 : this._errors.filter((e2) => e2.severity === "warning").length;
|
|
13166
13426
|
const config = this.config || {};
|
|
13167
|
-
const showValidationSummary = config.showValidationSummary !== false && errorCount > 0 && this._submitted;
|
|
13427
|
+
const showValidationSummary = config.showValidationSummary !== false && (errorCount > 0 && this._submitted || warningCount > 0);
|
|
13168
13428
|
const schema = this._currentSchema;
|
|
13169
13429
|
if (!schema) {
|
|
13170
13430
|
return html`<div>${I18n.t("form.loading")}</div>`;
|
|
@@ -13429,6 +13689,21 @@ JupiterDynamicForm.styles = css`
|
|
|
13429
13689
|
margin-bottom: 4px;
|
|
13430
13690
|
}
|
|
13431
13691
|
|
|
13692
|
+
/* JDF-036: when the summary contains only non-blocking calculation warnings (no blocking
|
|
13693
|
+
errors), style the whole box amber rather than error-red so it doesn't read as blocking. */
|
|
13694
|
+
.validation-summary.warnings-only {
|
|
13695
|
+
background: var(--jupiter-warning-background, #fff3e0);
|
|
13696
|
+
border-color: var(--jupiter-warning-color, #ff9800);
|
|
13697
|
+
}
|
|
13698
|
+
|
|
13699
|
+
.validation-summary.warnings-only .validation-summary-title {
|
|
13700
|
+
color: var(--jupiter-warning-color, #ff9800);
|
|
13701
|
+
}
|
|
13702
|
+
|
|
13703
|
+
.validation-summary-item.warning {
|
|
13704
|
+
color: var(--jupiter-warning-color, #ff9800);
|
|
13705
|
+
}
|
|
13706
|
+
|
|
13432
13707
|
.form-actions button {
|
|
13433
13708
|
padding: 10px 20px;
|
|
13434
13709
|
border: none;
|
|
@@ -14279,6 +14554,9 @@ __decorateClass([
|
|
|
14279
14554
|
__decorateClass([
|
|
14280
14555
|
r()
|
|
14281
14556
|
], JupiterDynamicForm.prototype, "_xbrlFormErrors", 2);
|
|
14557
|
+
__decorateClass([
|
|
14558
|
+
r()
|
|
14559
|
+
], JupiterDynamicForm.prototype, "_calculationWarnings", 2);
|
|
14282
14560
|
__decorateClass([
|
|
14283
14561
|
r()
|
|
14284
14562
|
], JupiterDynamicForm.prototype, "_showErrorPopup", 2);
|