jupiter-dynamic-forms 1.19.8 → 1.20.0
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/dynamic-form.d.ts +11 -0
- package/dist/core/dynamic-form.d.ts.map +1 -1
- package/dist/core/form-section.d.ts +18 -0
- package/dist/core/form-section.d.ts.map +1 -1
- package/dist/index.js +10 -10
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +109 -23
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -6432,50 +6432,87 @@ let JupiterFormSection = class extends LitElement {
|
|
|
6432
6432
|
this._totalChildConceptsMap.clear();
|
|
6433
6433
|
this._traverseTotalGroups(concepts);
|
|
6434
6434
|
}
|
|
6435
|
+
/**
|
|
6436
|
+
* JDF-038: XBRL uses more than one preferredLabel role to mark a "total" row — the plain
|
|
6437
|
+
* `.../role/totalLabel` and the sign-flipped `.../role/negatedTotalLabel` (used for subtotals of
|
|
6438
|
+
* negated/expense items, e.g. "Total of sum of expenses"). A case-sensitive `includes('totalLabel')`
|
|
6439
|
+
* misses the latter, because "negatedTotalLabel" contains "TotalLabel" with a capital T. Case-insensitive
|
|
6440
|
+
* matching is the single source of truth for "is this row a total" everywhere in this file.
|
|
6441
|
+
*/
|
|
6442
|
+
static _isTotalLabel(preferredLabel) {
|
|
6443
|
+
return !!(preferredLabel == null ? void 0 : preferredLabel.toLowerCase().includes("totallabel"));
|
|
6444
|
+
}
|
|
6445
|
+
/**
|
|
6446
|
+
* A member of a total's sibling/child group can itself be a presentation-only abstract wrapper
|
|
6447
|
+
* (e.g. "Group equity" wrapping Equity + Third party share + "Total of group equity") rather than
|
|
6448
|
+
* a value-bearing concept. Abstract concepts never have a form field, so resolve them to the nested
|
|
6449
|
+
* totalLabel concept that actually carries their aggregate value — otherwise the outer total's
|
|
6450
|
+
* calculation silently drops that whole subgroup (formData lookup on the abstract's id is always empty).
|
|
6451
|
+
*/
|
|
6452
|
+
static _resolveValueConcept(node, depth = 0) {
|
|
6453
|
+
var _a;
|
|
6454
|
+
if (!node.abstract)
|
|
6455
|
+
return node;
|
|
6456
|
+
if (depth > 5 || !((_a = node.children) == null ? void 0 : _a.length))
|
|
6457
|
+
return null;
|
|
6458
|
+
const nestedTotal = node.children.find((c2) => JupiterFormSection._isTotalLabel(c2.preferredLabel));
|
|
6459
|
+
if (!nestedTotal)
|
|
6460
|
+
return null;
|
|
6461
|
+
return JupiterFormSection._resolveValueConcept(nestedTotal, depth + 1);
|
|
6462
|
+
}
|
|
6463
|
+
_registerTotalGroup(totalConcept, members) {
|
|
6464
|
+
const resolvedMembers = members.map((m) => JupiterFormSection._resolveValueConcept(m)).filter((m) => m !== null);
|
|
6465
|
+
if (resolvedMembers.length === 0)
|
|
6466
|
+
return;
|
|
6467
|
+
const memberIds = resolvedMembers.map((m) => m.id);
|
|
6468
|
+
this._totalChildrenMap.set(totalConcept.id, memberIds);
|
|
6469
|
+
this._totalConceptMap.set(totalConcept.id, totalConcept);
|
|
6470
|
+
this._totalChildConceptsMap.set(totalConcept.id, resolvedMembers);
|
|
6471
|
+
for (const memberId of memberIds) {
|
|
6472
|
+
this._memberParentMap.set(memberId, totalConcept.id);
|
|
6473
|
+
}
|
|
6474
|
+
}
|
|
6435
6475
|
_traverseTotalGroups(concepts) {
|
|
6436
|
-
var _a, _b
|
|
6476
|
+
var _a, _b;
|
|
6437
6477
|
for (let i2 = 0; i2 < concepts.length; i2++) {
|
|
6438
6478
|
const concept = concepts[i2];
|
|
6439
|
-
if ((
|
|
6440
|
-
if ((
|
|
6441
|
-
|
|
6442
|
-
this._totalChildrenMap.set(concept.id, childIds);
|
|
6443
|
-
this._totalConceptMap.set(concept.id, concept);
|
|
6444
|
-
this._totalChildConceptsMap.set(concept.id, concept.children);
|
|
6445
|
-
for (const childId of childIds) {
|
|
6446
|
-
this._memberParentMap.set(childId, concept.id);
|
|
6447
|
-
}
|
|
6479
|
+
if (JupiterFormSection._isTotalLabel(concept.preferredLabel)) {
|
|
6480
|
+
if ((_a = concept.children) == null ? void 0 : _a.length) {
|
|
6481
|
+
this._registerTotalGroup(concept, concept.children);
|
|
6448
6482
|
} else {
|
|
6449
6483
|
let lastTotalIdx = -1;
|
|
6450
6484
|
for (let j = i2 - 1; j >= 0; j--) {
|
|
6451
|
-
if ((
|
|
6485
|
+
if (JupiterFormSection._isTotalLabel(concepts[j].preferredLabel)) {
|
|
6452
6486
|
lastTotalIdx = j;
|
|
6453
6487
|
break;
|
|
6454
6488
|
}
|
|
6455
6489
|
}
|
|
6456
6490
|
const siblings = concepts.slice(lastTotalIdx + 1, i2);
|
|
6457
6491
|
if (siblings.length > 0) {
|
|
6458
|
-
|
|
6459
|
-
|
|
6460
|
-
this.
|
|
6461
|
-
this._totalChildConceptsMap.set(concept.id, siblings);
|
|
6462
|
-
for (const siblingId of siblingIds) {
|
|
6463
|
-
this._memberParentMap.set(siblingId, concept.id);
|
|
6464
|
-
}
|
|
6492
|
+
this._registerTotalGroup(concept, siblings);
|
|
6493
|
+
} else if (lastTotalIdx >= 0) {
|
|
6494
|
+
this._registerTotalGroup(concept, [concepts[lastTotalIdx]]);
|
|
6465
6495
|
}
|
|
6466
6496
|
}
|
|
6467
6497
|
}
|
|
6468
|
-
if ((
|
|
6498
|
+
if ((_b = concept.children) == null ? void 0 : _b.length) {
|
|
6469
6499
|
this._traverseTotalGroups(concept.children);
|
|
6470
6500
|
}
|
|
6471
6501
|
}
|
|
6472
6502
|
}
|
|
6473
6503
|
_runCalculationCheck(conceptId, columnId) {
|
|
6504
|
+
const totalIds = /* @__PURE__ */ new Set();
|
|
6505
|
+
if (this._totalConceptMap.has(conceptId))
|
|
6506
|
+
totalIds.add(conceptId);
|
|
6507
|
+
const parentTotalId = this._memberParentMap.get(conceptId);
|
|
6508
|
+
if (parentTotalId)
|
|
6509
|
+
totalIds.add(parentTotalId);
|
|
6510
|
+
for (const totalConceptId of totalIds) {
|
|
6511
|
+
this._evaluateTotal(totalConceptId, columnId);
|
|
6512
|
+
}
|
|
6513
|
+
}
|
|
6514
|
+
_evaluateTotal(totalConceptId, columnId) {
|
|
6474
6515
|
var _a;
|
|
6475
|
-
const isSelfTotal = this._totalConceptMap.has(conceptId);
|
|
6476
|
-
const totalConceptId = isSelfTotal ? conceptId : this._memberParentMap.get(conceptId);
|
|
6477
|
-
if (!totalConceptId)
|
|
6478
|
-
return;
|
|
6479
6516
|
const totalConcept = this._totalConceptMap.get(totalConceptId);
|
|
6480
6517
|
const totalRaw = (_a = this.formData[totalConceptId]) == null ? void 0 : _a[columnId];
|
|
6481
6518
|
const key = `${totalConceptId}__${columnId}`;
|
|
@@ -10757,6 +10794,52 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
10757
10794
|
}
|
|
10758
10795
|
return instantDate || endDate || startDate || "2025-01-01";
|
|
10759
10796
|
}
|
|
10797
|
+
/**
|
|
10798
|
+
* JDF-037: Self-heals legacy periodStartLabel instant dates.
|
|
10799
|
+
* Drafts saved before JDF-024 have periodStartLabel concepts with the instant date
|
|
10800
|
+
* set to the column's own year instead of one day before periodStartDate. Reuses
|
|
10801
|
+
* _resolveInstantDate (no new date math) to correct both _periodData and the live
|
|
10802
|
+
* field.periodInstantDate so UI and saved output never disagree. Idempotent: only
|
|
10803
|
+
* writes when the stored value actually differs from the corrected one.
|
|
10804
|
+
*/
|
|
10805
|
+
_correctLegacyPeriodStartInstantDates() {
|
|
10806
|
+
this._allSections.forEach((section2) => {
|
|
10807
|
+
this._correctPeriodStartInstantDatesInConcepts(section2.concepts, section2);
|
|
10808
|
+
});
|
|
10809
|
+
}
|
|
10810
|
+
_correctPeriodStartInstantDatesInConcepts(concepts, section2) {
|
|
10811
|
+
concepts.forEach((concept) => {
|
|
10812
|
+
var _a, _b;
|
|
10813
|
+
if (((_a = concept.preferredLabel) == null ? void 0 : _a.includes("periodStartLabel")) && concept.periodType === "instant" && ((_b = concept.fields) == null ? void 0 : _b.length)) {
|
|
10814
|
+
concept.fields.forEach((field2) => {
|
|
10815
|
+
this._correctFieldPeriodStartInstantDate(concept, field2, concept.id, section2);
|
|
10816
|
+
const repeatCount = this._repeatCounts[concept.id] || 0;
|
|
10817
|
+
for (let n3 = 1; n3 <= repeatCount; n3++) {
|
|
10818
|
+
this._correctFieldPeriodStartInstantDate(concept, field2, `${concept.id}__repeat_${n3}`, section2);
|
|
10819
|
+
}
|
|
10820
|
+
});
|
|
10821
|
+
}
|
|
10822
|
+
if (concept.children) {
|
|
10823
|
+
this._correctPeriodStartInstantDatesInConcepts(concept.children, section2);
|
|
10824
|
+
}
|
|
10825
|
+
});
|
|
10826
|
+
}
|
|
10827
|
+
_correctFieldPeriodStartInstantDate(concept, field2, periodDataKey, section2) {
|
|
10828
|
+
var _a;
|
|
10829
|
+
const column2 = this._findColumnByIdInSection(field2.columnId, section2);
|
|
10830
|
+
const fieldPeriodData = (_a = this._periodData[periodDataKey]) == null ? void 0 : _a[field2.columnId];
|
|
10831
|
+
const periodStartDate = (fieldPeriodData == null ? void 0 : fieldPeriodData.startDate) || (column2 == null ? void 0 : column2.periodStartDate) || field2.periodStartDate || this.periodStartDate;
|
|
10832
|
+
const periodEndDate = (fieldPeriodData == null ? void 0 : fieldPeriodData.endDate) || (column2 == null ? void 0 : column2.periodEndDate) || field2.periodEndDate || this.periodEndDate;
|
|
10833
|
+
const correctedInstantDate = this._resolveInstantDate(concept.preferredLabel, void 0, periodStartDate, periodEndDate);
|
|
10834
|
+
if (fieldPeriodData && fieldPeriodData.instantDate !== correctedInstantDate) {
|
|
10835
|
+
console.log(`🩹 [Legacy Period Correction] ${periodDataKey}/${field2.columnId}: instantDate ${fieldPeriodData.instantDate} → ${correctedInstantDate}`);
|
|
10836
|
+
fieldPeriodData.instantDate = correctedInstantDate;
|
|
10837
|
+
}
|
|
10838
|
+
if (field2.periodInstantDate !== correctedInstantDate) {
|
|
10839
|
+
console.log(`🩹 [Legacy Period Correction] field ${concept.id}/${field2.columnId}: periodInstantDate ${field2.periodInstantDate} → ${correctedInstantDate}`);
|
|
10840
|
+
field2.periodInstantDate = correctedInstantDate;
|
|
10841
|
+
}
|
|
10842
|
+
}
|
|
10760
10843
|
_addColumnFromRequest(request, sectionId, insertAfterColumnId) {
|
|
10761
10844
|
var _a, _b, _c, _d, _e;
|
|
10762
10845
|
const timestamp = Date.now();
|
|
@@ -11056,6 +11139,7 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
11056
11139
|
this.requestUpdate();
|
|
11057
11140
|
return;
|
|
11058
11141
|
}
|
|
11142
|
+
this._correctLegacyPeriodStartInstantDates();
|
|
11059
11143
|
const submissionData = this._generateSubmissionData();
|
|
11060
11144
|
console.log("📊 Form Submission Data:", JSON.stringify(submissionData, null, 2));
|
|
11061
11145
|
console.log("📊 Submission Data Summary:");
|
|
@@ -11091,6 +11175,7 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
11091
11175
|
console.log("💾 Raw form data before submission generation:", this._formData);
|
|
11092
11176
|
console.log("🏷️ Unit data before submission generation:", this._unitData);
|
|
11093
11177
|
console.log("📋 Enhanced selectedRoleIds with roleURI and order:", this._selectedRoleIds);
|
|
11178
|
+
this._correctLegacyPeriodStartInstantDates();
|
|
11094
11179
|
const draftData = this._generateSubmissionData();
|
|
11095
11180
|
console.log("📤 Generated submission data:", draftData);
|
|
11096
11181
|
console.log("📊 Submission data breakdown:");
|
|
@@ -11349,6 +11434,7 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
11349
11434
|
};
|
|
11350
11435
|
console.log(`🏷️ [Unit Restore] Merged unit data: ${Object.keys(this._unitData).length} concepts with custom units`);
|
|
11351
11436
|
console.log(`🏷️ [Unit Restore] Full _unitData after merge:`, JSON.stringify(this._unitData, null, 2));
|
|
11437
|
+
this._correctLegacyPeriodStartInstantDates();
|
|
11352
11438
|
if (this._selectedRoleIds.length > 0) {
|
|
11353
11439
|
this._applyRoleFilter();
|
|
11354
11440
|
}
|