jupiter-dynamic-forms 1.12.2 → 1.14.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/DynamicFormRefactored.d.ts.map +1 -1
- package/dist/core/add-column-dialog.d.ts.map +1 -1
- package/dist/core/concept-tree.d.ts +5 -0
- package/dist/core/concept-tree.d.ts.map +1 -1
- package/dist/core/dynamic-form.d.ts +15 -0
- package/dist/core/dynamic-form.d.ts.map +1 -1
- package/dist/core/form-field.d.ts +17 -0
- 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/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +288 -75
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1347 -178
- package/dist/index.mjs.map +1 -1
- package/dist/schema/types.d.ts +4 -0
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/schema/xbrl-types.d.ts +25 -1
- package/dist/schema/xbrl-types.d.ts.map +1 -1
- package/dist/utils/type-input-mapping.d.ts +79 -13
- package/dist/utils/type-input-mapping.d.ts.map +1 -1
- package/dist/utils/xbrl-form-builder.d.ts.map +1 -1
- package/dist/utils/xbrl-validation.d.ts +62 -0
- package/dist/utils/xbrl-validation.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -346,9 +346,9 @@ class FormValidator {
|
|
|
346
346
|
static validateField(fieldId, conceptId, columnId, value, fieldType, rules = []) {
|
|
347
347
|
const errors = [];
|
|
348
348
|
for (const rule of rules) {
|
|
349
|
-
const
|
|
350
|
-
if (
|
|
351
|
-
errors.push(
|
|
349
|
+
const error2 = this.validateRule(fieldId, conceptId, columnId, value, fieldType, rule);
|
|
350
|
+
if (error2) {
|
|
351
|
+
errors.push(error2);
|
|
352
352
|
}
|
|
353
353
|
}
|
|
354
354
|
return errors;
|
|
@@ -579,18 +579,25 @@ class XBRLFormBuilder {
|
|
|
579
579
|
* @param periodPreferences - User preferences for which period columns to show per role
|
|
580
580
|
*/
|
|
581
581
|
static buildFormSchema(xbrlInput, periodStartDate, periodEndDate, language = "en", periodPreferences) {
|
|
582
|
-
var _a;
|
|
582
|
+
var _a, _b;
|
|
583
583
|
if (!xbrlInput.presentation || xbrlInput.presentation.length === 0) {
|
|
584
584
|
throw new Error("XBRL presentation data is required");
|
|
585
585
|
}
|
|
586
586
|
const presentationData = xbrlInput.presentation[0];
|
|
587
587
|
const hypercubeData = (_a = xbrlInput.hypercubes) == null ? void 0 : _a[0];
|
|
588
|
+
const datatypes = Array.isArray(xbrlInput.datatypes) ? xbrlInput.datatypes : ((_b = xbrlInput.datatypes) == null ? void 0 : _b.concepts) || [];
|
|
588
589
|
const sections = [];
|
|
589
590
|
const sortedRoles = [...presentationData.roles].sort((a2, b2) => {
|
|
590
591
|
return a2.role.localeCompare(b2.role);
|
|
591
592
|
});
|
|
592
593
|
sortedRoles.forEach((role) => {
|
|
593
594
|
const section2 = this.buildSectionFromRole(role, periodStartDate, periodEndDate, hypercubeData, language, periodPreferences);
|
|
595
|
+
if (datatypes && datatypes.length > 0) {
|
|
596
|
+
section2.datatypes = datatypes;
|
|
597
|
+
console.log(`✅ [buildFormSchema] Attached ${datatypes.length} datatypes to section ${section2.id}`);
|
|
598
|
+
} else {
|
|
599
|
+
console.warn(`⚠️ [buildFormSchema] No datatypes available for section ${section2.id}`);
|
|
600
|
+
}
|
|
594
601
|
this.assignFieldColumnIds(section2);
|
|
595
602
|
sections.push(section2);
|
|
596
603
|
});
|
|
@@ -660,9 +667,9 @@ class XBRLFormBuilder {
|
|
|
660
667
|
columnIds = ["duration"];
|
|
661
668
|
}
|
|
662
669
|
columnIds.forEach((columnId) => {
|
|
663
|
-
const
|
|
664
|
-
if (
|
|
665
|
-
fields.push(
|
|
670
|
+
const field2 = this.createFieldFromConcept(concept, periodStartDate, periodEndDate, columnId);
|
|
671
|
+
if (field2)
|
|
672
|
+
fields.push(field2);
|
|
666
673
|
});
|
|
667
674
|
}
|
|
668
675
|
const children = [];
|
|
@@ -709,7 +716,7 @@ class XBRLFormBuilder {
|
|
|
709
716
|
} else {
|
|
710
717
|
columnId = "duration";
|
|
711
718
|
}
|
|
712
|
-
const
|
|
719
|
+
const field2 = {
|
|
713
720
|
id: `${concept.id}_${columnId}_field`,
|
|
714
721
|
conceptId: concept.id,
|
|
715
722
|
columnId,
|
|
@@ -728,9 +735,9 @@ class XBRLFormBuilder {
|
|
|
728
735
|
periodInstantDate: concept.periodType === "instant" ? periodEndDate || periodStartDate || "2025-01-01" : void 0
|
|
729
736
|
};
|
|
730
737
|
if (concept.id === "nl-cd_DescriptionLocationNL__a64trl") {
|
|
731
|
-
console.log(`🏗️ [Field Creation] Concept: ${concept.id}, periodType from concept: ${concept.periodType}, Field periodType: ${
|
|
738
|
+
console.log(`🏗️ [Field Creation] Concept: ${concept.id}, periodType from concept: ${concept.periodType}, Field periodType: ${field2.periodType}, ColumnId: ${columnId}`);
|
|
732
739
|
}
|
|
733
|
-
return
|
|
740
|
+
return field2;
|
|
734
741
|
}
|
|
735
742
|
/**
|
|
736
743
|
* Map XBRL data type to form field type
|
|
@@ -786,8 +793,8 @@ class XBRLFormBuilder {
|
|
|
786
793
|
* Recursively assign column IDs to fields in a concept tree
|
|
787
794
|
*/
|
|
788
795
|
static assignColumnIdsToConceptFields(conceptTree, columnIds) {
|
|
789
|
-
conceptTree.fields = conceptTree.fields.filter((
|
|
790
|
-
return columnIds.includes(
|
|
796
|
+
conceptTree.fields = conceptTree.fields.filter((field2) => {
|
|
797
|
+
return columnIds.includes(field2.columnId);
|
|
791
798
|
});
|
|
792
799
|
if (conceptTree.children) {
|
|
793
800
|
conceptTree.children.forEach((child) => {
|
|
@@ -911,8 +918,8 @@ class XBRLFormBuilder {
|
|
|
911
918
|
const date = new Date(dateString);
|
|
912
919
|
date.setFullYear(date.getFullYear() - 1);
|
|
913
920
|
return date.toISOString().split("T")[0];
|
|
914
|
-
} catch (
|
|
915
|
-
console.error(`Error calculating previous year for date ${dateString}:`,
|
|
921
|
+
} catch (error2) {
|
|
922
|
+
console.error(`Error calculating previous year for date ${dateString}:`, error2);
|
|
916
923
|
return dateString;
|
|
917
924
|
}
|
|
918
925
|
}
|
|
@@ -1500,6 +1507,25 @@ const column$1 = {
|
|
|
1500
1507
|
const section$1 = {
|
|
1501
1508
|
enterPlaceholder: "Enter"
|
|
1502
1509
|
};
|
|
1510
|
+
const field$1 = {
|
|
1511
|
+
selectOption: "Select an option...",
|
|
1512
|
+
select: "Select...",
|
|
1513
|
+
enterDetailedExplanation: "Enter detailed explanation...",
|
|
1514
|
+
enterAmountNoDecimals: "Enter amount (no decimals)",
|
|
1515
|
+
enterCurrency: "0.00",
|
|
1516
|
+
enterText: "Enter text",
|
|
1517
|
+
enterWholeNumber: "Enter whole number",
|
|
1518
|
+
enterPositiveNumber: "Enter positive number",
|
|
1519
|
+
enterDecimalValue: "Enter decimal value",
|
|
1520
|
+
enterNumberOfShares: "Enter number of shares",
|
|
1521
|
+
yearFormat: "YYYY",
|
|
1522
|
+
enterPercentage: "Enter percentage",
|
|
1523
|
+
emailPlaceholder: "email@example.com",
|
|
1524
|
+
urlPlaceholder: "https://example.com",
|
|
1525
|
+
phonePlaceholder: "+1 (555) 000-0000",
|
|
1526
|
+
enterValue: "Enter value",
|
|
1527
|
+
enterDetailedInformation: "Enter detailed information..."
|
|
1528
|
+
};
|
|
1503
1529
|
const admin$1 = {
|
|
1504
1530
|
title: "Configure Roles",
|
|
1505
1531
|
description: "Select which roles should display the 'Show Previous Year' checkbox and configure period type columns."
|
|
@@ -1508,13 +1534,26 @@ const validation$1 = {
|
|
|
1508
1534
|
summary: "Please fix the following errors before submitting:",
|
|
1509
1535
|
errorsFound: "errors found"
|
|
1510
1536
|
};
|
|
1537
|
+
const error$1 = {
|
|
1538
|
+
popup: {
|
|
1539
|
+
title: "Validation Errors",
|
|
1540
|
+
message: "Please fix the following validation errors before saving:",
|
|
1541
|
+
field: "Field:",
|
|
1542
|
+
value: "Value:",
|
|
1543
|
+
errors: "Errors:",
|
|
1544
|
+
clickToFocus: "Click to focus this field",
|
|
1545
|
+
ok: "OK"
|
|
1546
|
+
}
|
|
1547
|
+
};
|
|
1511
1548
|
const enTranslations = {
|
|
1512
1549
|
form: form$1,
|
|
1513
1550
|
filter: filter$1,
|
|
1514
1551
|
column: column$1,
|
|
1515
1552
|
section: section$1,
|
|
1553
|
+
field: field$1,
|
|
1516
1554
|
admin: admin$1,
|
|
1517
|
-
validation: validation$1
|
|
1555
|
+
validation: validation$1,
|
|
1556
|
+
error: error$1
|
|
1518
1557
|
};
|
|
1519
1558
|
const form = {
|
|
1520
1559
|
loading: "Formulier laden...",
|
|
@@ -1581,6 +1620,25 @@ const column = {
|
|
|
1581
1620
|
const section = {
|
|
1582
1621
|
enterPlaceholder: "Invoeren"
|
|
1583
1622
|
};
|
|
1623
|
+
const field = {
|
|
1624
|
+
selectOption: "Selecteer een optie...",
|
|
1625
|
+
select: "Selecteer...",
|
|
1626
|
+
enterDetailedExplanation: "Voer gedetailleerde uitleg in...",
|
|
1627
|
+
enterAmountNoDecimals: "Voer bedrag in (geen decimalen)",
|
|
1628
|
+
enterCurrency: "0,00",
|
|
1629
|
+
enterText: "Voer tekst in",
|
|
1630
|
+
enterWholeNumber: "Voer geheel getal in",
|
|
1631
|
+
enterPositiveNumber: "Voer positief getal in",
|
|
1632
|
+
enterDecimalValue: "Voer decimale waarde in",
|
|
1633
|
+
enterNumberOfShares: "Voer aantal aandelen in",
|
|
1634
|
+
yearFormat: "JJJJ",
|
|
1635
|
+
enterPercentage: "Voer percentage in",
|
|
1636
|
+
emailPlaceholder: "email@voorbeeld.nl",
|
|
1637
|
+
urlPlaceholder: "https://voorbeeld.nl",
|
|
1638
|
+
phonePlaceholder: "+31 (0)20 123 4567",
|
|
1639
|
+
enterValue: "Voer waarde in",
|
|
1640
|
+
enterDetailedInformation: "Voer gedetailleerde informatie in..."
|
|
1641
|
+
};
|
|
1584
1642
|
const admin = {
|
|
1585
1643
|
title: "Rollen configureren",
|
|
1586
1644
|
description: "Selecteer welke rollen het selectievakje 'Vorig jaar weergeven' moeten weergeven en configureer periodetype kolommen."
|
|
@@ -1589,13 +1647,26 @@ const validation = {
|
|
|
1589
1647
|
summary: "Corrigeer de volgende fouten voordat u indient:",
|
|
1590
1648
|
errorsFound: "fouten gevonden"
|
|
1591
1649
|
};
|
|
1650
|
+
const error = {
|
|
1651
|
+
popup: {
|
|
1652
|
+
title: "Validatiefouten",
|
|
1653
|
+
message: "Corrigeer de volgende validatiefouten voordat u opslaat:",
|
|
1654
|
+
field: "Veld:",
|
|
1655
|
+
value: "Waarde:",
|
|
1656
|
+
errors: "Fouten:",
|
|
1657
|
+
clickToFocus: "Klik om dit veld te focussen",
|
|
1658
|
+
ok: "OK"
|
|
1659
|
+
}
|
|
1660
|
+
};
|
|
1592
1661
|
const nlTranslations = {
|
|
1593
1662
|
form,
|
|
1594
1663
|
filter,
|
|
1595
1664
|
column,
|
|
1596
1665
|
section,
|
|
1666
|
+
field,
|
|
1597
1667
|
admin,
|
|
1598
|
-
validation
|
|
1668
|
+
validation,
|
|
1669
|
+
error
|
|
1599
1670
|
};
|
|
1600
1671
|
const translations = {
|
|
1601
1672
|
en: enTranslations,
|
|
@@ -1707,8 +1778,8 @@ class DraftStorageService {
|
|
|
1707
1778
|
customColumns: metadata.customColumns.length
|
|
1708
1779
|
});
|
|
1709
1780
|
return true;
|
|
1710
|
-
} catch (
|
|
1711
|
-
console.error("❌ Failed to save draft:",
|
|
1781
|
+
} catch (error2) {
|
|
1782
|
+
console.error("❌ Failed to save draft:", error2);
|
|
1712
1783
|
return false;
|
|
1713
1784
|
}
|
|
1714
1785
|
}
|
|
@@ -1736,8 +1807,8 @@ class DraftStorageService {
|
|
|
1736
1807
|
metadata,
|
|
1737
1808
|
version: this.STORAGE_VERSION
|
|
1738
1809
|
};
|
|
1739
|
-
} catch (
|
|
1740
|
-
console.error("❌ Failed to load draft:",
|
|
1810
|
+
} catch (error2) {
|
|
1811
|
+
console.error("❌ Failed to load draft:", error2);
|
|
1741
1812
|
return null;
|
|
1742
1813
|
}
|
|
1743
1814
|
}
|
|
@@ -1756,8 +1827,8 @@ class DraftStorageService {
|
|
|
1756
1827
|
if (!metadataStr)
|
|
1757
1828
|
return null;
|
|
1758
1829
|
return JSON.parse(metadataStr);
|
|
1759
|
-
} catch (
|
|
1760
|
-
console.error("❌ Failed to load draft metadata:",
|
|
1830
|
+
} catch (error2) {
|
|
1831
|
+
console.error("❌ Failed to load draft metadata:", error2);
|
|
1761
1832
|
return null;
|
|
1762
1833
|
}
|
|
1763
1834
|
}
|
|
@@ -1770,8 +1841,8 @@ class DraftStorageService {
|
|
|
1770
1841
|
this._storage.removeItem(this.DRAFT_METADATA_KEY);
|
|
1771
1842
|
console.log("🗑️ Draft cleared successfully");
|
|
1772
1843
|
return true;
|
|
1773
|
-
} catch (
|
|
1774
|
-
console.error("❌ Failed to clear draft:",
|
|
1844
|
+
} catch (error2) {
|
|
1845
|
+
console.error("❌ Failed to clear draft:", error2);
|
|
1775
1846
|
return false;
|
|
1776
1847
|
}
|
|
1777
1848
|
}
|
|
@@ -1831,7 +1902,7 @@ class DraftStorageService {
|
|
|
1831
1902
|
/**
|
|
1832
1903
|
* Create metadata snapshot from current form state
|
|
1833
1904
|
*/
|
|
1834
|
-
createMetadataSnapshot(periodStartDate, periodEndDate, language, selectedRoleIds, allSections, typedMemberData, periodPreferences, periodData) {
|
|
1905
|
+
createMetadataSnapshot(periodStartDate, periodEndDate, language, selectedRoleIds, allSections, typedMemberData, periodPreferences, periodData, unitData) {
|
|
1835
1906
|
return {
|
|
1836
1907
|
periodStartDate,
|
|
1837
1908
|
periodEndDate,
|
|
@@ -1841,6 +1912,7 @@ class DraftStorageService {
|
|
|
1841
1912
|
typedMemberData,
|
|
1842
1913
|
periodPreferences,
|
|
1843
1914
|
periodData,
|
|
1915
|
+
unitData,
|
|
1844
1916
|
schemaVersion: this.STORAGE_VERSION
|
|
1845
1917
|
};
|
|
1846
1918
|
}
|
|
@@ -1863,6 +1935,204 @@ class DraftStorageService {
|
|
|
1863
1935
|
return { compatible, warnings };
|
|
1864
1936
|
}
|
|
1865
1937
|
}
|
|
1938
|
+
class XBRLValidator {
|
|
1939
|
+
/**
|
|
1940
|
+
* Validates a value against XBRL datatype validation rules
|
|
1941
|
+
* Only validates when value is not blank
|
|
1942
|
+
*
|
|
1943
|
+
* @param conceptType - The XBRL concept type (e.g., "nl-types:houseNumberNLItemType")
|
|
1944
|
+
* @param value - The input value to validate
|
|
1945
|
+
* @param datatypes - Array of XBRL datatypes from taxonomy
|
|
1946
|
+
* @returns Validation result with errors if any
|
|
1947
|
+
*/
|
|
1948
|
+
static validateConceptValue(conceptType, value, datatypes) {
|
|
1949
|
+
const errors = [];
|
|
1950
|
+
if (value === null || value === void 0 || value === "") {
|
|
1951
|
+
return { valid: true, errors: [] };
|
|
1952
|
+
}
|
|
1953
|
+
if (!conceptType || !datatypes || datatypes.length === 0) {
|
|
1954
|
+
return { valid: true, errors: [] };
|
|
1955
|
+
}
|
|
1956
|
+
const datatype = this.findDatatype(conceptType, datatypes);
|
|
1957
|
+
if (!datatype || !datatype.validation) {
|
|
1958
|
+
return { valid: true, errors: [] };
|
|
1959
|
+
}
|
|
1960
|
+
const validation2 = datatype.validation;
|
|
1961
|
+
const stringValue = String(value);
|
|
1962
|
+
if (validation2.pattern) {
|
|
1963
|
+
const patternError = this.validatePattern(stringValue, validation2.pattern);
|
|
1964
|
+
if (patternError) {
|
|
1965
|
+
errors.push(patternError);
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1968
|
+
if (validation2.length !== void 0) {
|
|
1969
|
+
const lengthError = this.validateExactLength(stringValue, validation2.length);
|
|
1970
|
+
if (lengthError) {
|
|
1971
|
+
errors.push(lengthError);
|
|
1972
|
+
}
|
|
1973
|
+
}
|
|
1974
|
+
if (validation2.minLength !== void 0) {
|
|
1975
|
+
const minLengthError = this.validateMinLength(stringValue, validation2.minLength);
|
|
1976
|
+
if (minLengthError) {
|
|
1977
|
+
errors.push(minLengthError);
|
|
1978
|
+
}
|
|
1979
|
+
}
|
|
1980
|
+
if (validation2.maxLength !== void 0) {
|
|
1981
|
+
const maxLengthError = this.validateMaxLength(stringValue, validation2.maxLength);
|
|
1982
|
+
if (maxLengthError) {
|
|
1983
|
+
errors.push(maxLengthError);
|
|
1984
|
+
}
|
|
1985
|
+
}
|
|
1986
|
+
if (validation2.totalDigits !== void 0) {
|
|
1987
|
+
const totalDigitsError = this.validateTotalDigits(stringValue, validation2.totalDigits);
|
|
1988
|
+
if (totalDigitsError) {
|
|
1989
|
+
errors.push(totalDigitsError);
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1992
|
+
return {
|
|
1993
|
+
valid: errors.length === 0,
|
|
1994
|
+
errors
|
|
1995
|
+
};
|
|
1996
|
+
}
|
|
1997
|
+
/**
|
|
1998
|
+
* Finds the datatype definition for a given concept type
|
|
1999
|
+
* Handles both exact matches and base type chain resolution
|
|
2000
|
+
*/
|
|
2001
|
+
static findDatatype(conceptType, datatypes) {
|
|
2002
|
+
let datatype = datatypes.find((dt) => dt.type === conceptType);
|
|
2003
|
+
if (datatype) {
|
|
2004
|
+
return datatype;
|
|
2005
|
+
}
|
|
2006
|
+
const visited = /* @__PURE__ */ new Set();
|
|
2007
|
+
let currentType = conceptType;
|
|
2008
|
+
while (currentType && !visited.has(currentType)) {
|
|
2009
|
+
visited.add(currentType);
|
|
2010
|
+
datatype = datatypes.find((dt) => dt.type === currentType);
|
|
2011
|
+
if (datatype) {
|
|
2012
|
+
if (datatype.validation) {
|
|
2013
|
+
return datatype;
|
|
2014
|
+
}
|
|
2015
|
+
currentType = datatype.basetype;
|
|
2016
|
+
} else {
|
|
2017
|
+
break;
|
|
2018
|
+
}
|
|
2019
|
+
}
|
|
2020
|
+
return void 0;
|
|
2021
|
+
}
|
|
2022
|
+
/**
|
|
2023
|
+
* Validates that value matches the regex pattern
|
|
2024
|
+
*/
|
|
2025
|
+
static validatePattern(value, pattern) {
|
|
2026
|
+
try {
|
|
2027
|
+
const regex = new RegExp(`^${pattern}$`);
|
|
2028
|
+
if (!regex.test(value)) {
|
|
2029
|
+
return {
|
|
2030
|
+
type: "pattern",
|
|
2031
|
+
message: `Value does not match required pattern: ${pattern}`,
|
|
2032
|
+
expectedValue: pattern,
|
|
2033
|
+
actualValue: value
|
|
2034
|
+
};
|
|
2035
|
+
}
|
|
2036
|
+
} catch (error2) {
|
|
2037
|
+
console.error(`Invalid regex pattern: ${pattern}`, error2);
|
|
2038
|
+
return {
|
|
2039
|
+
type: "pattern",
|
|
2040
|
+
message: `Invalid pattern configuration: ${pattern}`,
|
|
2041
|
+
expectedValue: pattern,
|
|
2042
|
+
actualValue: value
|
|
2043
|
+
};
|
|
2044
|
+
}
|
|
2045
|
+
return null;
|
|
2046
|
+
}
|
|
2047
|
+
/**
|
|
2048
|
+
* Validates that value has exact length
|
|
2049
|
+
*/
|
|
2050
|
+
static validateExactLength(value, requiredLength) {
|
|
2051
|
+
if (value.length !== requiredLength) {
|
|
2052
|
+
return {
|
|
2053
|
+
type: "length",
|
|
2054
|
+
message: `Value must be exactly ${requiredLength} characters (current: ${value.length})`,
|
|
2055
|
+
expectedValue: requiredLength,
|
|
2056
|
+
actualValue: value.length
|
|
2057
|
+
};
|
|
2058
|
+
}
|
|
2059
|
+
return null;
|
|
2060
|
+
}
|
|
2061
|
+
/**
|
|
2062
|
+
* Validates minimum length
|
|
2063
|
+
*/
|
|
2064
|
+
static validateMinLength(value, minLength) {
|
|
2065
|
+
if (value.length < minLength) {
|
|
2066
|
+
return {
|
|
2067
|
+
type: "minLength",
|
|
2068
|
+
message: `Value must be at least ${minLength} characters (current: ${value.length})`,
|
|
2069
|
+
expectedValue: minLength,
|
|
2070
|
+
actualValue: value.length
|
|
2071
|
+
};
|
|
2072
|
+
}
|
|
2073
|
+
return null;
|
|
2074
|
+
}
|
|
2075
|
+
/**
|
|
2076
|
+
* Validates maximum length
|
|
2077
|
+
*/
|
|
2078
|
+
static validateMaxLength(value, maxLength) {
|
|
2079
|
+
if (value.length > maxLength) {
|
|
2080
|
+
return {
|
|
2081
|
+
type: "maxLength",
|
|
2082
|
+
message: `Value must not exceed ${maxLength} characters (current: ${value.length})`,
|
|
2083
|
+
expectedValue: maxLength,
|
|
2084
|
+
actualValue: value.length
|
|
2085
|
+
};
|
|
2086
|
+
}
|
|
2087
|
+
return null;
|
|
2088
|
+
}
|
|
2089
|
+
/**
|
|
2090
|
+
* Validates total digits (for numeric values)
|
|
2091
|
+
*/
|
|
2092
|
+
static validateTotalDigits(value, totalDigits) {
|
|
2093
|
+
const digitsOnly = value.replace(/[^\d]/g, "");
|
|
2094
|
+
if (digitsOnly.length > totalDigits) {
|
|
2095
|
+
return {
|
|
2096
|
+
type: "totalDigits",
|
|
2097
|
+
message: `Value must not exceed ${totalDigits} total digits (current: ${digitsOnly.length})`,
|
|
2098
|
+
expectedValue: totalDigits,
|
|
2099
|
+
actualValue: digitsOnly.length
|
|
2100
|
+
};
|
|
2101
|
+
}
|
|
2102
|
+
return null;
|
|
2103
|
+
}
|
|
2104
|
+
/**
|
|
2105
|
+
* Gets a human-readable summary of validation rules for a concept type
|
|
2106
|
+
* Useful for displaying validation hints to users
|
|
2107
|
+
*/
|
|
2108
|
+
static getValidationRulesSummary(conceptType, datatypes) {
|
|
2109
|
+
if (!conceptType || !datatypes) {
|
|
2110
|
+
return [];
|
|
2111
|
+
}
|
|
2112
|
+
const datatype = this.findDatatype(conceptType, datatypes);
|
|
2113
|
+
if (!datatype || !datatype.validation) {
|
|
2114
|
+
return [];
|
|
2115
|
+
}
|
|
2116
|
+
const validation2 = datatype.validation;
|
|
2117
|
+
const rules = [];
|
|
2118
|
+
if (validation2.pattern) {
|
|
2119
|
+
rules.push(`Must match pattern: ${validation2.pattern}`);
|
|
2120
|
+
}
|
|
2121
|
+
if (validation2.length !== void 0) {
|
|
2122
|
+
rules.push(`Must be exactly ${validation2.length} characters`);
|
|
2123
|
+
}
|
|
2124
|
+
if (validation2.minLength !== void 0) {
|
|
2125
|
+
rules.push(`Minimum ${validation2.minLength} characters`);
|
|
2126
|
+
}
|
|
2127
|
+
if (validation2.maxLength !== void 0) {
|
|
2128
|
+
rules.push(`Maximum ${validation2.maxLength} characters`);
|
|
2129
|
+
}
|
|
2130
|
+
if (validation2.totalDigits !== void 0) {
|
|
2131
|
+
rules.push(`Maximum ${validation2.totalDigits} total digits`);
|
|
2132
|
+
}
|
|
2133
|
+
return rules;
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
1866
2136
|
const TYPE_INPUT_MAP = {
|
|
1867
2137
|
// ==========================================
|
|
1868
2138
|
// Dutch XBRL Types (nl-types namespace)
|
|
@@ -1870,7 +2140,7 @@ const TYPE_INPUT_MAP = {
|
|
|
1870
2140
|
// Text area for long-form explanations
|
|
1871
2141
|
"nl-types:formattedExplanationItemType": {
|
|
1872
2142
|
fieldType: "textarea",
|
|
1873
|
-
placeholder: "
|
|
2143
|
+
placeholder: I18n.t("field.enterDetailedExplanation")
|
|
1874
2144
|
},
|
|
1875
2145
|
// Monetary values without decimals (whole numbers only)
|
|
1876
2146
|
"nl-types:monetaryNoDecimals20ItemType": {
|
|
@@ -1878,7 +2148,7 @@ const TYPE_INPUT_MAP = {
|
|
|
1878
2148
|
htmlInputType: "number",
|
|
1879
2149
|
allowDecimals: false,
|
|
1880
2150
|
step: 1,
|
|
1881
|
-
placeholder: "
|
|
2151
|
+
placeholder: I18n.t("field.enterAmountNoDecimals")
|
|
1882
2152
|
},
|
|
1883
2153
|
// ==========================================
|
|
1884
2154
|
// Standard XBRL Types (xbrli namespace)
|
|
@@ -1889,13 +2159,13 @@ const TYPE_INPUT_MAP = {
|
|
|
1889
2159
|
htmlInputType: "number",
|
|
1890
2160
|
allowDecimals: true,
|
|
1891
2161
|
step: 0.01,
|
|
1892
|
-
placeholder: "
|
|
2162
|
+
placeholder: I18n.t("field.enterCurrency")
|
|
1893
2163
|
},
|
|
1894
2164
|
// String/text types
|
|
1895
2165
|
"xbrli:stringItemType": {
|
|
1896
2166
|
fieldType: "text",
|
|
1897
2167
|
htmlInputType: "text",
|
|
1898
|
-
placeholder: "
|
|
2168
|
+
placeholder: I18n.t("field.enterText")
|
|
1899
2169
|
},
|
|
1900
2170
|
// Date types
|
|
1901
2171
|
"xbrli:dateItemType": {
|
|
@@ -1912,7 +2182,7 @@ const TYPE_INPUT_MAP = {
|
|
|
1912
2182
|
htmlInputType: "number",
|
|
1913
2183
|
allowDecimals: false,
|
|
1914
2184
|
step: 1,
|
|
1915
|
-
placeholder: "
|
|
2185
|
+
placeholder: I18n.t("field.enterWholeNumber")
|
|
1916
2186
|
},
|
|
1917
2187
|
"xbrli:nonNegativeIntegerItemType": {
|
|
1918
2188
|
fieldType: "integer",
|
|
@@ -1920,7 +2190,7 @@ const TYPE_INPUT_MAP = {
|
|
|
1920
2190
|
allowDecimals: false,
|
|
1921
2191
|
min: 0,
|
|
1922
2192
|
step: 1,
|
|
1923
|
-
placeholder: "
|
|
2193
|
+
placeholder: I18n.t("field.enterPositiveNumber")
|
|
1924
2194
|
},
|
|
1925
2195
|
"xbrli:positiveIntegerItemType": {
|
|
1926
2196
|
fieldType: "integer",
|
|
@@ -1928,7 +2198,7 @@ const TYPE_INPUT_MAP = {
|
|
|
1928
2198
|
allowDecimals: false,
|
|
1929
2199
|
min: 1,
|
|
1930
2200
|
step: 1,
|
|
1931
|
-
placeholder: "
|
|
2201
|
+
placeholder: I18n.t("field.enterPositiveNumber")
|
|
1932
2202
|
},
|
|
1933
2203
|
// Numeric types - decimals
|
|
1934
2204
|
"xbrli:decimalItemType": {
|
|
@@ -1936,7 +2206,7 @@ const TYPE_INPUT_MAP = {
|
|
|
1936
2206
|
htmlInputType: "number",
|
|
1937
2207
|
allowDecimals: true,
|
|
1938
2208
|
step: "any",
|
|
1939
|
-
placeholder: "
|
|
2209
|
+
placeholder: I18n.t("field.enterDecimalValue")
|
|
1940
2210
|
},
|
|
1941
2211
|
// Shares (typically whole numbers or with limited decimals)
|
|
1942
2212
|
"xbrli:sharesItemType": {
|
|
@@ -1945,7 +2215,7 @@ const TYPE_INPUT_MAP = {
|
|
|
1945
2215
|
allowDecimals: true,
|
|
1946
2216
|
min: 0,
|
|
1947
2217
|
step: 0.01,
|
|
1948
|
-
placeholder: "
|
|
2218
|
+
placeholder: I18n.t("field.enterNumberOfShares")
|
|
1949
2219
|
},
|
|
1950
2220
|
"xbrli:shares": {
|
|
1951
2221
|
fieldType: "number",
|
|
@@ -1953,7 +2223,7 @@ const TYPE_INPUT_MAP = {
|
|
|
1953
2223
|
allowDecimals: true,
|
|
1954
2224
|
min: 0,
|
|
1955
2225
|
step: 0.01,
|
|
1956
|
-
placeholder: "
|
|
2226
|
+
placeholder: I18n.t("field.enterNumberOfShares")
|
|
1957
2227
|
},
|
|
1958
2228
|
// Year (gYear)
|
|
1959
2229
|
"xbrli:gYearItemType": {
|
|
@@ -1963,7 +2233,7 @@ const TYPE_INPUT_MAP = {
|
|
|
1963
2233
|
min: 1900,
|
|
1964
2234
|
max: 2100,
|
|
1965
2235
|
step: 1,
|
|
1966
|
-
placeholder: "
|
|
2236
|
+
placeholder: I18n.t("field.yearFormat")
|
|
1967
2237
|
},
|
|
1968
2238
|
// Boolean types
|
|
1969
2239
|
"xbrli:booleanItemType": {
|
|
@@ -1977,14 +2247,14 @@ const TYPE_INPUT_MAP = {
|
|
|
1977
2247
|
htmlInputType: "number",
|
|
1978
2248
|
allowDecimals: true,
|
|
1979
2249
|
step: 0.01,
|
|
1980
|
-
placeholder: "
|
|
2250
|
+
placeholder: I18n.t("field.enterPercentage")
|
|
1981
2251
|
},
|
|
1982
2252
|
"xbrli:percentItemType": {
|
|
1983
2253
|
fieldType: "percentage",
|
|
1984
2254
|
htmlInputType: "number",
|
|
1985
2255
|
allowDecimals: true,
|
|
1986
2256
|
step: 0.01,
|
|
1987
|
-
placeholder: "
|
|
2257
|
+
placeholder: I18n.t("field.enterPercentage")
|
|
1988
2258
|
},
|
|
1989
2259
|
// ==========================================
|
|
1990
2260
|
// Contact/Communication types
|
|
@@ -1992,27 +2262,36 @@ const TYPE_INPUT_MAP = {
|
|
|
1992
2262
|
"xbrli:emailItemType": {
|
|
1993
2263
|
fieldType: "email",
|
|
1994
2264
|
htmlInputType: "email",
|
|
1995
|
-
placeholder: "
|
|
2265
|
+
placeholder: I18n.t("field.emailPlaceholder")
|
|
1996
2266
|
},
|
|
1997
2267
|
"xbrli:urlItemType": {
|
|
1998
2268
|
fieldType: "url",
|
|
1999
2269
|
htmlInputType: "url",
|
|
2000
|
-
placeholder: "
|
|
2270
|
+
placeholder: I18n.t("field.urlPlaceholder")
|
|
2001
2271
|
},
|
|
2002
2272
|
"xbrli:telephoneItemType": {
|
|
2003
2273
|
fieldType: "tel",
|
|
2004
2274
|
htmlInputType: "tel",
|
|
2005
|
-
placeholder: "
|
|
2275
|
+
placeholder: I18n.t("field.phonePlaceholder")
|
|
2006
2276
|
}
|
|
2007
2277
|
};
|
|
2008
|
-
function getInputTypeForConceptType(conceptType) {
|
|
2278
|
+
function getInputTypeForConceptType(conceptType, datatypes) {
|
|
2009
2279
|
if (!conceptType) {
|
|
2010
2280
|
return {
|
|
2011
2281
|
fieldType: "text",
|
|
2012
2282
|
htmlInputType: "text",
|
|
2013
|
-
placeholder: "
|
|
2283
|
+
placeholder: I18n.t("field.enterValue")
|
|
2014
2284
|
};
|
|
2015
2285
|
}
|
|
2286
|
+
if (datatypes && datatypes.length > 0) {
|
|
2287
|
+
const baseTypeChain = resolveBaseTypeChain(conceptType, datatypes);
|
|
2288
|
+
if (baseTypeChain.length > 0) {
|
|
2289
|
+
const config = determineInputTypeFromBaseChain(baseTypeChain, datatypes);
|
|
2290
|
+
console.log(`🔍 [Type Resolution] ${conceptType} → Chain:`, baseTypeChain, "→ Type:", config.fieldType, config.enumerations ? `(${config.enumerations.length} options)` : "");
|
|
2291
|
+
return config;
|
|
2292
|
+
}
|
|
2293
|
+
}
|
|
2294
|
+
console.log(`⚠️ [Type Resolution Fallback] Using pattern matching for: ${conceptType}`);
|
|
2016
2295
|
if (TYPE_INPUT_MAP[conceptType]) {
|
|
2017
2296
|
return TYPE_INPUT_MAP[conceptType];
|
|
2018
2297
|
}
|
|
@@ -2024,7 +2303,7 @@ function getInputTypeForConceptType(conceptType) {
|
|
|
2024
2303
|
htmlInputType: "number",
|
|
2025
2304
|
allowDecimals: false,
|
|
2026
2305
|
step: 1,
|
|
2027
|
-
placeholder: "
|
|
2306
|
+
placeholder: I18n.t("field.enterAmountNoDecimals")
|
|
2028
2307
|
};
|
|
2029
2308
|
}
|
|
2030
2309
|
return {
|
|
@@ -2032,13 +2311,13 @@ function getInputTypeForConceptType(conceptType) {
|
|
|
2032
2311
|
htmlInputType: "number",
|
|
2033
2312
|
allowDecimals: true,
|
|
2034
2313
|
step: 0.01,
|
|
2035
|
-
placeholder: "
|
|
2314
|
+
placeholder: I18n.t("field.enterCurrency")
|
|
2036
2315
|
};
|
|
2037
2316
|
}
|
|
2038
2317
|
if (lowerType.includes("explanation") || lowerType.includes("description") || lowerType.includes("notes") || lowerType.includes("formatted")) {
|
|
2039
2318
|
return {
|
|
2040
2319
|
fieldType: "textarea",
|
|
2041
|
-
placeholder: "
|
|
2320
|
+
placeholder: I18n.t("field.enterDetailedInformation")
|
|
2042
2321
|
};
|
|
2043
2322
|
}
|
|
2044
2323
|
if (lowerType.includes("date")) {
|
|
@@ -2067,7 +2346,7 @@ function getInputTypeForConceptType(conceptType) {
|
|
|
2067
2346
|
allowDecimals: false,
|
|
2068
2347
|
min: isPositive ? 1 : isNonNegative ? 0 : void 0,
|
|
2069
2348
|
step: 1,
|
|
2070
|
-
placeholder: "
|
|
2349
|
+
placeholder: I18n.t("field.enterWholeNumber")
|
|
2071
2350
|
};
|
|
2072
2351
|
}
|
|
2073
2352
|
if (lowerType.includes("decimal") || lowerType.includes("numeric") || lowerType.includes("number")) {
|
|
@@ -2076,7 +2355,7 @@ function getInputTypeForConceptType(conceptType) {
|
|
|
2076
2355
|
htmlInputType: "number",
|
|
2077
2356
|
allowDecimals: true,
|
|
2078
2357
|
step: "any",
|
|
2079
|
-
placeholder: "
|
|
2358
|
+
placeholder: I18n.t("field.enterDecimalValue")
|
|
2080
2359
|
};
|
|
2081
2360
|
}
|
|
2082
2361
|
if (lowerType.includes("percent") || lowerType.includes("pure")) {
|
|
@@ -2085,13 +2364,13 @@ function getInputTypeForConceptType(conceptType) {
|
|
|
2085
2364
|
htmlInputType: "number",
|
|
2086
2365
|
allowDecimals: true,
|
|
2087
2366
|
step: 0.01,
|
|
2088
|
-
placeholder: "
|
|
2367
|
+
placeholder: I18n.t("field.enterPercentage")
|
|
2089
2368
|
};
|
|
2090
2369
|
}
|
|
2091
2370
|
return {
|
|
2092
2371
|
fieldType: "text",
|
|
2093
2372
|
htmlInputType: "text",
|
|
2094
|
-
placeholder: "
|
|
2373
|
+
placeholder: I18n.t("field.enterValue")
|
|
2095
2374
|
};
|
|
2096
2375
|
}
|
|
2097
2376
|
function isTextareaType(fieldType) {
|
|
@@ -2106,6 +2385,145 @@ function isNumericType(fieldType) {
|
|
|
2106
2385
|
function isSelectType(fieldType) {
|
|
2107
2386
|
return fieldType === "select";
|
|
2108
2387
|
}
|
|
2388
|
+
function resolveBaseTypeChain(typeName, datatypes) {
|
|
2389
|
+
const baseTypeChain = [];
|
|
2390
|
+
if (!typeName) {
|
|
2391
|
+
return baseTypeChain;
|
|
2392
|
+
}
|
|
2393
|
+
if (!datatypes || datatypes.length === 0) {
|
|
2394
|
+
baseTypeChain.push(typeName);
|
|
2395
|
+
return baseTypeChain;
|
|
2396
|
+
}
|
|
2397
|
+
let currentType = typeName;
|
|
2398
|
+
const visitedTypes = /* @__PURE__ */ new Set();
|
|
2399
|
+
while (currentType) {
|
|
2400
|
+
baseTypeChain.push(currentType);
|
|
2401
|
+
if (visitedTypes.has(currentType)) {
|
|
2402
|
+
console.warn(`Circular reference detected in datatype hierarchy for type: ${currentType}`);
|
|
2403
|
+
break;
|
|
2404
|
+
}
|
|
2405
|
+
visitedTypes.add(currentType);
|
|
2406
|
+
const foundDatatype = datatypes.find((dt) => dt.type === currentType);
|
|
2407
|
+
if (!foundDatatype || !foundDatatype.basetype || foundDatatype.basetype.trim() === "") {
|
|
2408
|
+
break;
|
|
2409
|
+
}
|
|
2410
|
+
currentType = foundDatatype.basetype;
|
|
2411
|
+
}
|
|
2412
|
+
return baseTypeChain;
|
|
2413
|
+
}
|
|
2414
|
+
function collectEnumerationsFromChain(baseTypeChain, datatypes) {
|
|
2415
|
+
if (!baseTypeChain || baseTypeChain.length === 0 || !datatypes || datatypes.length === 0) {
|
|
2416
|
+
return void 0;
|
|
2417
|
+
}
|
|
2418
|
+
for (const typeName of baseTypeChain) {
|
|
2419
|
+
const datatype = datatypes.find((dt) => dt.type === typeName);
|
|
2420
|
+
if (datatype && datatype.enumerations && datatype.enumerations.length > 0) {
|
|
2421
|
+
return datatype.enumerations.map((enumItem) => ({
|
|
2422
|
+
id: enumItem.id || enumItem.value,
|
|
2423
|
+
// Use value as fallback if id not present
|
|
2424
|
+
value: enumItem.value,
|
|
2425
|
+
label: enumItem.value
|
|
2426
|
+
// Use value as display label
|
|
2427
|
+
}));
|
|
2428
|
+
}
|
|
2429
|
+
}
|
|
2430
|
+
return void 0;
|
|
2431
|
+
}
|
|
2432
|
+
function determineInputTypeFromBaseChain(baseTypeChain, datatypes) {
|
|
2433
|
+
if (!baseTypeChain || baseTypeChain.length === 0) {
|
|
2434
|
+
return {
|
|
2435
|
+
fieldType: "text",
|
|
2436
|
+
htmlInputType: "text",
|
|
2437
|
+
placeholder: I18n.t("field.enterValue")
|
|
2438
|
+
};
|
|
2439
|
+
}
|
|
2440
|
+
if (datatypes && datatypes.length > 0) {
|
|
2441
|
+
const enumerations = collectEnumerationsFromChain(baseTypeChain, datatypes);
|
|
2442
|
+
if (enumerations && enumerations.length > 0) {
|
|
2443
|
+
return {
|
|
2444
|
+
fieldType: "select",
|
|
2445
|
+
enumerations,
|
|
2446
|
+
placeholder: I18n.t("field.selectOption")
|
|
2447
|
+
};
|
|
2448
|
+
}
|
|
2449
|
+
}
|
|
2450
|
+
const chainLower = baseTypeChain.map((type) => type.toLowerCase());
|
|
2451
|
+
const chainString = chainLower.join("|");
|
|
2452
|
+
if (baseTypeChain.some((type) => type === "nl-types:formattedExplanationItemType") || chainString.includes("formattedexplanation") || chainString.includes("formatted") && chainString.includes("explanation")) {
|
|
2453
|
+
return {
|
|
2454
|
+
fieldType: "textarea",
|
|
2455
|
+
placeholder: I18n.t("field.enterDetailedExplanation")
|
|
2456
|
+
};
|
|
2457
|
+
}
|
|
2458
|
+
if (chainLower.some((type) => type.includes("date"))) {
|
|
2459
|
+
if (chainString.includes("datetime") || chainString.includes("time")) {
|
|
2460
|
+
return {
|
|
2461
|
+
fieldType: "datetime",
|
|
2462
|
+
htmlInputType: "datetime-local"
|
|
2463
|
+
};
|
|
2464
|
+
}
|
|
2465
|
+
return {
|
|
2466
|
+
fieldType: "date",
|
|
2467
|
+
htmlInputType: "date"
|
|
2468
|
+
};
|
|
2469
|
+
}
|
|
2470
|
+
if (chainLower.some((type) => type.includes("boolean") || type.includes("bool"))) {
|
|
2471
|
+
return {
|
|
2472
|
+
fieldType: "boolean"
|
|
2473
|
+
};
|
|
2474
|
+
}
|
|
2475
|
+
if (chainLower.some((type) => type.includes("integer") || type === "integer")) {
|
|
2476
|
+
const isNonNegative = chainString.includes("nonnegative") || chainString.includes("non-negative");
|
|
2477
|
+
const isPositive = chainString.includes("positive");
|
|
2478
|
+
return {
|
|
2479
|
+
fieldType: "integer",
|
|
2480
|
+
htmlInputType: "number",
|
|
2481
|
+
allowDecimals: false,
|
|
2482
|
+
min: isPositive ? 1 : isNonNegative ? 0 : void 0,
|
|
2483
|
+
step: 1,
|
|
2484
|
+
placeholder: I18n.t("field.enterWholeNumber")
|
|
2485
|
+
};
|
|
2486
|
+
}
|
|
2487
|
+
if (chainLower.some((type) => type.includes("decimal") || type === "decimal")) {
|
|
2488
|
+
if (chainString.includes("monetary") || chainString.includes("currency")) {
|
|
2489
|
+
if (chainString.includes("nodecimals") || chainString.includes("no-decimals") || chainString.includes("nodecimals20")) {
|
|
2490
|
+
return {
|
|
2491
|
+
fieldType: "number",
|
|
2492
|
+
htmlInputType: "number",
|
|
2493
|
+
allowDecimals: false,
|
|
2494
|
+
step: 1,
|
|
2495
|
+
placeholder: I18n.t("field.enterAmountNoDecimals")
|
|
2496
|
+
};
|
|
2497
|
+
}
|
|
2498
|
+
return {
|
|
2499
|
+
fieldType: "currency",
|
|
2500
|
+
htmlInputType: "number",
|
|
2501
|
+
allowDecimals: true,
|
|
2502
|
+
step: 0.01,
|
|
2503
|
+
placeholder: I18n.t("field.enterCurrency")
|
|
2504
|
+
};
|
|
2505
|
+
}
|
|
2506
|
+
return {
|
|
2507
|
+
fieldType: "decimal",
|
|
2508
|
+
htmlInputType: "number",
|
|
2509
|
+
allowDecimals: true,
|
|
2510
|
+
step: "any",
|
|
2511
|
+
placeholder: I18n.t("field.enterDecimalValue")
|
|
2512
|
+
};
|
|
2513
|
+
}
|
|
2514
|
+
if (baseTypeChain.some((type) => type === "xbrli:stringItemType") || chainLower.some((type) => type === "string" || type.includes("stringitem"))) {
|
|
2515
|
+
return {
|
|
2516
|
+
fieldType: "text",
|
|
2517
|
+
htmlInputType: "text",
|
|
2518
|
+
placeholder: I18n.t("field.enterText")
|
|
2519
|
+
};
|
|
2520
|
+
}
|
|
2521
|
+
return {
|
|
2522
|
+
fieldType: "text",
|
|
2523
|
+
htmlInputType: "text",
|
|
2524
|
+
placeholder: I18n.t("field.enterValue")
|
|
2525
|
+
};
|
|
2526
|
+
}
|
|
2109
2527
|
var __defProp$5 = Object.defineProperty;
|
|
2110
2528
|
var __getOwnPropDesc$5 = Object.getOwnPropertyDescriptor;
|
|
2111
2529
|
var __decorateClass$5 = (decorators, target, key, kind) => {
|
|
@@ -2120,18 +2538,35 @@ var __decorateClass$5 = (decorators, target, key, kind) => {
|
|
|
2120
2538
|
let JupiterFormField = class extends LitElement {
|
|
2121
2539
|
constructor() {
|
|
2122
2540
|
super(...arguments);
|
|
2541
|
+
this.defaultUnits = [];
|
|
2123
2542
|
this.value = null;
|
|
2124
2543
|
this.disabled = false;
|
|
2125
2544
|
this.locale = "en-US";
|
|
2126
2545
|
this.hideLabel = false;
|
|
2127
2546
|
this._errors = [];
|
|
2547
|
+
this._xbrlErrors = [];
|
|
2128
2548
|
this._touched = false;
|
|
2129
2549
|
this._showPeriodPopup = false;
|
|
2550
|
+
this._availableUnits = [];
|
|
2130
2551
|
}
|
|
2131
2552
|
willUpdate(changedProperties) {
|
|
2553
|
+
var _a;
|
|
2132
2554
|
if (changedProperties.has("value") || changedProperties.has("field")) {
|
|
2133
2555
|
this._validateField();
|
|
2134
2556
|
}
|
|
2557
|
+
if (changedProperties.has("unit") && this.unit) {
|
|
2558
|
+
console.log(`🏷️ [FormField willUpdate] Unit property changed to: ${this.unit}, conceptId: ${this.conceptId}, columnId: ${this.columnId}`);
|
|
2559
|
+
this.dispatchEvent(new CustomEvent("unit-change", {
|
|
2560
|
+
detail: {
|
|
2561
|
+
fieldId: (_a = this.field) == null ? void 0 : _a.id,
|
|
2562
|
+
conceptId: this.conceptId,
|
|
2563
|
+
columnId: this.columnId,
|
|
2564
|
+
unit: this.unit
|
|
2565
|
+
},
|
|
2566
|
+
bubbles: true,
|
|
2567
|
+
composed: true
|
|
2568
|
+
}));
|
|
2569
|
+
}
|
|
2135
2570
|
if (changedProperties.has("field") && this.field) {
|
|
2136
2571
|
if (this.conceptId.includes("DescriptionLocationNL") || this.columnId.startsWith("col-")) {
|
|
2137
2572
|
console.log(`📅 [FormField willUpdate] Concept ${this.conceptId}, Column ${this.columnId}: field.periodType=${this.field.periodType}, field.periodStartDate=${this.field.periodStartDate}, field.periodEndDate=${this.field.periodEndDate}, field.periodInstantDate=${this.field.periodInstantDate}`);
|
|
@@ -2184,21 +2619,138 @@ let JupiterFormField = class extends LitElement {
|
|
|
2184
2619
|
}
|
|
2185
2620
|
_handleBlur() {
|
|
2186
2621
|
this._touched = true;
|
|
2622
|
+
this._validateXBRLDatatype();
|
|
2623
|
+
console.log(`🟦 [FormField] Blur event - fieldId: ${this.field.id}, conceptId: ${this.conceptId}, columnId: ${this.columnId}`);
|
|
2624
|
+
console.log(`🟦 [FormField] Current _xbrlErrors:`, this._xbrlErrors);
|
|
2625
|
+
console.log(`🟦 [FormField] Current value:`, this.value);
|
|
2187
2626
|
this.dispatchEvent(new CustomEvent("field-blur", {
|
|
2188
2627
|
detail: {
|
|
2189
2628
|
fieldId: this.field.id,
|
|
2190
2629
|
conceptId: this.conceptId,
|
|
2191
|
-
columnId: this.columnId
|
|
2630
|
+
columnId: this.columnId,
|
|
2631
|
+
xbrlValidationErrors: this._xbrlErrors
|
|
2192
2632
|
},
|
|
2193
|
-
bubbles: true
|
|
2633
|
+
bubbles: true,
|
|
2634
|
+
composed: true
|
|
2635
|
+
// CRITICAL: Allow event to cross Shadow DOM boundaries
|
|
2194
2636
|
}));
|
|
2637
|
+
console.log(`🟦 [FormField] Dispatched field-blur event with ${this._xbrlErrors.length} errors`);
|
|
2638
|
+
}
|
|
2639
|
+
/**
|
|
2640
|
+
* Validates the current value against XBRL datatype validation rules
|
|
2641
|
+
* Called on blur event when user loses focus on the input field
|
|
2642
|
+
*/
|
|
2643
|
+
_validateXBRLDatatype() {
|
|
2644
|
+
this._xbrlErrors = [];
|
|
2645
|
+
if (this.value === null || this.value === void 0 || this.value === "") {
|
|
2646
|
+
return;
|
|
2647
|
+
}
|
|
2648
|
+
if (!this.conceptType || !this.datatypes || this.datatypes.length === 0) {
|
|
2649
|
+
return;
|
|
2650
|
+
}
|
|
2651
|
+
const validationResult = XBRLValidator.validateConceptValue(
|
|
2652
|
+
this.conceptType,
|
|
2653
|
+
this.value,
|
|
2654
|
+
this.datatypes
|
|
2655
|
+
);
|
|
2656
|
+
if (!validationResult.valid) {
|
|
2657
|
+
this._xbrlErrors = validationResult.errors;
|
|
2658
|
+
console.log(`❌ [FormField] XBRL Validation failed for ${this.conceptId}:`, {
|
|
2659
|
+
conceptType: this.conceptType,
|
|
2660
|
+
value: this.value,
|
|
2661
|
+
errors: this._xbrlErrors
|
|
2662
|
+
});
|
|
2663
|
+
} else {
|
|
2664
|
+
console.log(`✅ [FormField] XBRL Validation passed for ${this.conceptId}`);
|
|
2665
|
+
}
|
|
2195
2666
|
}
|
|
2196
2667
|
_handlePeriodIconClick() {
|
|
2668
|
+
this._availableUnits = this._collectUnitsForConceptType();
|
|
2669
|
+
console.log(`📊 [FormField] Collected ${this._availableUnits.length} units for concept ${this.conceptId}:`, this._availableUnits);
|
|
2670
|
+
console.log(`📊 [FormField] Current unit value: ${this.unit}`);
|
|
2671
|
+
console.log(`📊 [FormField] ConceptId: ${this.conceptId}, ColumnId: ${this.columnId}`);
|
|
2672
|
+
if (!this.unit && this._availableUnits.length > 0) {
|
|
2673
|
+
let unitToSelect = null;
|
|
2674
|
+
const defaultUnit = this._availableUnits.find((u2) => u2.isDefault === true);
|
|
2675
|
+
if (defaultUnit) {
|
|
2676
|
+
unitToSelect = defaultUnit.id;
|
|
2677
|
+
console.log(`🎯 [FormField] Auto-selecting default unit: ${defaultUnit.id} (${defaultUnit.label})`);
|
|
2678
|
+
} else if (this._availableUnits.length === 1) {
|
|
2679
|
+
unitToSelect = this._availableUnits[0].id;
|
|
2680
|
+
console.log(`🎯 [FormField] Auto-selecting single available unit: ${unitToSelect}`);
|
|
2681
|
+
}
|
|
2682
|
+
if (unitToSelect) {
|
|
2683
|
+
this.unit = unitToSelect;
|
|
2684
|
+
this.dispatchEvent(new CustomEvent("unit-change", {
|
|
2685
|
+
detail: {
|
|
2686
|
+
fieldId: this.field.id,
|
|
2687
|
+
conceptId: this.conceptId,
|
|
2688
|
+
columnId: this.columnId,
|
|
2689
|
+
unit: this.unit
|
|
2690
|
+
},
|
|
2691
|
+
bubbles: true,
|
|
2692
|
+
composed: true
|
|
2693
|
+
}));
|
|
2694
|
+
}
|
|
2695
|
+
} else if (this.unit) {
|
|
2696
|
+
console.log(`📊 [FormField] Unit already set, dispatching unit-change to ensure parent stores it: ${this.unit}`);
|
|
2697
|
+
this.dispatchEvent(new CustomEvent("unit-change", {
|
|
2698
|
+
detail: {
|
|
2699
|
+
fieldId: this.field.id,
|
|
2700
|
+
conceptId: this.conceptId,
|
|
2701
|
+
columnId: this.columnId,
|
|
2702
|
+
unit: this.unit
|
|
2703
|
+
},
|
|
2704
|
+
bubbles: true,
|
|
2705
|
+
composed: true
|
|
2706
|
+
}));
|
|
2707
|
+
}
|
|
2197
2708
|
this._showPeriodPopup = true;
|
|
2198
2709
|
}
|
|
2710
|
+
/**
|
|
2711
|
+
* Collects units from the concept's type or its basetype chain
|
|
2712
|
+
* @returns Array of unit objects with id, label, and isDefault
|
|
2713
|
+
*/
|
|
2714
|
+
_collectUnitsForConceptType() {
|
|
2715
|
+
if (!this.conceptType || !this.datatypes) {
|
|
2716
|
+
return [];
|
|
2717
|
+
}
|
|
2718
|
+
const baseTypeChain = resolveBaseTypeChain(this.conceptType, this.datatypes);
|
|
2719
|
+
console.log(`🔍 [Unit Resolution] Concept: ${this.conceptId}, Type: ${this.conceptType}, BaseType Chain:`, baseTypeChain);
|
|
2720
|
+
for (const typeName of baseTypeChain) {
|
|
2721
|
+
const datatype = this.datatypes.find((dt) => dt.type === typeName);
|
|
2722
|
+
if (datatype && datatype.units && Array.isArray(datatype.units) && datatype.units.length > 0) {
|
|
2723
|
+
console.log(`✅ [Unit Resolution] Found ${datatype.units.length} units in type: ${typeName}`);
|
|
2724
|
+
return datatype.units;
|
|
2725
|
+
}
|
|
2726
|
+
}
|
|
2727
|
+
console.log(`ℹ️ [Unit Resolution] No units found for concept ${this.conceptId}`);
|
|
2728
|
+
return [];
|
|
2729
|
+
}
|
|
2199
2730
|
_closePeriodPopup() {
|
|
2200
2731
|
this._showPeriodPopup = false;
|
|
2201
2732
|
}
|
|
2733
|
+
_handleUnitChange(event) {
|
|
2734
|
+
const target = event.target;
|
|
2735
|
+
const value = target.value;
|
|
2736
|
+
console.log(`🏷️ [FormField] Unit change detected: value=${value}, conceptId=${this.conceptId}, columnId=${this.columnId}`);
|
|
2737
|
+
console.log(`🏷️ [FormField] Previous unit value: ${this.unit}`);
|
|
2738
|
+
this.unit = value;
|
|
2739
|
+
console.log(`🏷️ [FormField] Updated unit value to: ${this.unit}`);
|
|
2740
|
+
const eventDetail = {
|
|
2741
|
+
fieldId: this.field.id,
|
|
2742
|
+
conceptId: this.conceptId,
|
|
2743
|
+
columnId: this.columnId,
|
|
2744
|
+
unit: this.unit
|
|
2745
|
+
};
|
|
2746
|
+
console.log(`🏷️ [FormField] Dispatching unit-change event with detail:`, eventDetail);
|
|
2747
|
+
this.dispatchEvent(new CustomEvent("unit-change", {
|
|
2748
|
+
detail: eventDetail,
|
|
2749
|
+
bubbles: true,
|
|
2750
|
+
composed: true
|
|
2751
|
+
}));
|
|
2752
|
+
console.log(`🏷️ [FormField] unit-change event dispatched`);
|
|
2753
|
+
}
|
|
2202
2754
|
_handlePopupOverlayClick(e2) {
|
|
2203
2755
|
if (e2.target === e2.currentTarget) {
|
|
2204
2756
|
this._closePeriodPopup();
|
|
@@ -2224,7 +2776,8 @@ let JupiterFormField = class extends LitElement {
|
|
|
2224
2776
|
periodType: this.field.periodType,
|
|
2225
2777
|
periodStartDate: this.periodStartDate,
|
|
2226
2778
|
periodEndDate: this.periodEndDate,
|
|
2227
|
-
periodInstantDate: this.periodInstantDate
|
|
2779
|
+
periodInstantDate: this.periodInstantDate,
|
|
2780
|
+
unit: this.unit
|
|
2228
2781
|
},
|
|
2229
2782
|
bubbles: true,
|
|
2230
2783
|
composed: true
|
|
@@ -2237,13 +2790,12 @@ let JupiterFormField = class extends LitElement {
|
|
|
2237
2790
|
});
|
|
2238
2791
|
}
|
|
2239
2792
|
_renderInput() {
|
|
2240
|
-
var _a;
|
|
2241
2793
|
const hasErrors = this._errors.some((e2) => e2.severity === "error");
|
|
2242
2794
|
const hasWarnings = this._errors.some((e2) => e2.severity === "warning");
|
|
2243
2795
|
const cssClass = `field-input ${hasErrors ? "error" : hasWarnings ? "warning" : ""}`;
|
|
2244
2796
|
const fieldId = `${this.conceptId}__${this.columnId}`;
|
|
2245
2797
|
const fieldName = `data[${this.conceptId}][${this.columnId}]`;
|
|
2246
|
-
const typeConfig = getInputTypeForConceptType(this.conceptType);
|
|
2798
|
+
const typeConfig = getInputTypeForConceptType(this.conceptType, this.datatypes);
|
|
2247
2799
|
if (this.conceptType)
|
|
2248
2800
|
;
|
|
2249
2801
|
const effectiveFieldType = typeConfig.fieldType || this.field.type || "text";
|
|
@@ -2263,6 +2815,7 @@ let JupiterFormField = class extends LitElement {
|
|
|
2263
2815
|
`;
|
|
2264
2816
|
}
|
|
2265
2817
|
if (effectiveFieldType === "select" || this.field.type === "select") {
|
|
2818
|
+
const selectOptions = typeConfig.enumerations || this.field.options || [];
|
|
2266
2819
|
return html`
|
|
2267
2820
|
<select
|
|
2268
2821
|
id="${fieldId}"
|
|
@@ -2274,16 +2827,21 @@ let JupiterFormField = class extends LitElement {
|
|
|
2274
2827
|
@focus="${this._handleFocus}"
|
|
2275
2828
|
@blur="${this._handleBlur}"
|
|
2276
2829
|
>
|
|
2277
|
-
<option value=""
|
|
2278
|
-
${
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2830
|
+
<option value="">${typeConfig.placeholder || I18n.t("field.select")}</option>
|
|
2831
|
+
${selectOptions.map((option) => {
|
|
2832
|
+
const optionValue = option.value;
|
|
2833
|
+
const optionLabel = option.label || option.value;
|
|
2834
|
+
const isDisabled = option.disabled || false;
|
|
2835
|
+
return html`
|
|
2836
|
+
<option
|
|
2837
|
+
value="${optionValue}"
|
|
2838
|
+
?disabled="${isDisabled}"
|
|
2839
|
+
?selected="${this.value === optionValue}"
|
|
2840
|
+
>
|
|
2841
|
+
${optionLabel}
|
|
2842
|
+
</option>
|
|
2843
|
+
`;
|
|
2844
|
+
})}
|
|
2287
2845
|
</select>
|
|
2288
2846
|
`;
|
|
2289
2847
|
}
|
|
@@ -2431,6 +2989,25 @@ let JupiterFormField = class extends LitElement {
|
|
|
2431
2989
|
/>
|
|
2432
2990
|
</div>
|
|
2433
2991
|
`}
|
|
2992
|
+
|
|
2993
|
+
${this._availableUnits.length > 0 ? html`
|
|
2994
|
+
<div class="period-controls">
|
|
2995
|
+
<label>Unit:</label>
|
|
2996
|
+
<select
|
|
2997
|
+
.value="${this.unit || ""}"
|
|
2998
|
+
@change="${this._handleUnitChange}"
|
|
2999
|
+
?disabled="${this.disabled}"
|
|
3000
|
+
class="unit-select"
|
|
3001
|
+
>
|
|
3002
|
+
<option value="">Select Unit</option>
|
|
3003
|
+
${this._availableUnits.map((unit) => html`
|
|
3004
|
+
<option value="${unit.id}" ?selected="${this.unit === unit.id}">
|
|
3005
|
+
${unit.label || unit.id}
|
|
3006
|
+
</option>
|
|
3007
|
+
`)}
|
|
3008
|
+
</select>
|
|
3009
|
+
</div>
|
|
3010
|
+
` : ""}
|
|
2434
3011
|
</div>
|
|
2435
3012
|
</div>
|
|
2436
3013
|
</div>
|
|
@@ -2464,9 +3041,19 @@ let JupiterFormField = class extends LitElement {
|
|
|
2464
3041
|
|
|
2465
3042
|
${this._errors.length > 0 && this._touched ? html`
|
|
2466
3043
|
<div class="field-errors">
|
|
2467
|
-
${this._errors.map((
|
|
2468
|
-
<span class="field-error ${
|
|
2469
|
-
${
|
|
3044
|
+
${this._errors.map((error2) => html`
|
|
3045
|
+
<span class="field-error ${error2.severity}">
|
|
3046
|
+
${error2.message}
|
|
3047
|
+
</span>
|
|
3048
|
+
`)}
|
|
3049
|
+
</div>
|
|
3050
|
+
` : ""}
|
|
3051
|
+
|
|
3052
|
+
${this._xbrlErrors.length > 0 && this._touched ? html`
|
|
3053
|
+
<div class="field-errors">
|
|
3054
|
+
${this._xbrlErrors.map((error2) => html`
|
|
3055
|
+
<span class="field-error error">
|
|
3056
|
+
${error2.message}
|
|
2470
3057
|
</span>
|
|
2471
3058
|
`)}
|
|
2472
3059
|
</div>
|
|
@@ -2617,6 +3204,28 @@ JupiterFormField.styles = css`
|
|
|
2617
3204
|
box-shadow: 0 0 0 2px var(--jupiter-primary-color-light, rgba(25, 118, 210, 0.2));
|
|
2618
3205
|
}
|
|
2619
3206
|
|
|
3207
|
+
.period-popup-content .period-controls .unit-select {
|
|
3208
|
+
padding: 8px 10px;
|
|
3209
|
+
font-size: 14px;
|
|
3210
|
+
border: 1px solid var(--jupiter-border-color, #ddd);
|
|
3211
|
+
border-radius: 4px;
|
|
3212
|
+
background: var(--jupiter-input-background, #fff);
|
|
3213
|
+
color: var(--jupiter-text-primary, #333);
|
|
3214
|
+
cursor: pointer;
|
|
3215
|
+
}
|
|
3216
|
+
|
|
3217
|
+
.period-popup-content .period-controls .unit-select:focus {
|
|
3218
|
+
outline: none;
|
|
3219
|
+
border-color: var(--jupiter-primary-color, #1976d2);
|
|
3220
|
+
box-shadow: 0 0 0 2px var(--jupiter-primary-color-light, rgba(25, 118, 210, 0.2));
|
|
3221
|
+
}
|
|
3222
|
+
|
|
3223
|
+
.period-popup-content .period-controls .unit-select:disabled {
|
|
3224
|
+
background: var(--jupiter-disabled-background, #f5f5f5);
|
|
3225
|
+
color: var(--jupiter-disabled-text, #999);
|
|
3226
|
+
cursor: not-allowed;
|
|
3227
|
+
}
|
|
3228
|
+
|
|
2620
3229
|
.field-input {
|
|
2621
3230
|
width: 100%;
|
|
2622
3231
|
padding: 6px 8px; /* Reduced padding for table cells */
|
|
@@ -2733,6 +3342,12 @@ __decorateClass$5([
|
|
|
2733
3342
|
__decorateClass$5([
|
|
2734
3343
|
n2({ type: String })
|
|
2735
3344
|
], JupiterFormField.prototype, "conceptType", 2);
|
|
3345
|
+
__decorateClass$5([
|
|
3346
|
+
n2({ type: Array })
|
|
3347
|
+
], JupiterFormField.prototype, "datatypes", 2);
|
|
3348
|
+
__decorateClass$5([
|
|
3349
|
+
n2({ type: Array })
|
|
3350
|
+
], JupiterFormField.prototype, "defaultUnits", 2);
|
|
2736
3351
|
__decorateClass$5([
|
|
2737
3352
|
n2({ type: String })
|
|
2738
3353
|
], JupiterFormField.prototype, "columnId", 2);
|
|
@@ -2757,15 +3372,24 @@ __decorateClass$5([
|
|
|
2757
3372
|
__decorateClass$5([
|
|
2758
3373
|
n2({ type: String })
|
|
2759
3374
|
], JupiterFormField.prototype, "periodInstantDate", 2);
|
|
3375
|
+
__decorateClass$5([
|
|
3376
|
+
n2({ type: String })
|
|
3377
|
+
], JupiterFormField.prototype, "unit", 2);
|
|
2760
3378
|
__decorateClass$5([
|
|
2761
3379
|
r()
|
|
2762
3380
|
], JupiterFormField.prototype, "_errors", 2);
|
|
3381
|
+
__decorateClass$5([
|
|
3382
|
+
r()
|
|
3383
|
+
], JupiterFormField.prototype, "_xbrlErrors", 2);
|
|
2763
3384
|
__decorateClass$5([
|
|
2764
3385
|
r()
|
|
2765
3386
|
], JupiterFormField.prototype, "_touched", 2);
|
|
2766
3387
|
__decorateClass$5([
|
|
2767
3388
|
r()
|
|
2768
3389
|
], JupiterFormField.prototype, "_showPeriodPopup", 2);
|
|
3390
|
+
__decorateClass$5([
|
|
3391
|
+
r()
|
|
3392
|
+
], JupiterFormField.prototype, "_availableUnits", 2);
|
|
2769
3393
|
JupiterFormField = __decorateClass$5([
|
|
2770
3394
|
t$1("jupiter-form-field")
|
|
2771
3395
|
], JupiterFormField);
|
|
@@ -2785,6 +3409,9 @@ let JupiterConceptTree = class extends LitElement {
|
|
|
2785
3409
|
super(...arguments);
|
|
2786
3410
|
this.columns = [];
|
|
2787
3411
|
this.formData = {};
|
|
3412
|
+
this.periodData = {};
|
|
3413
|
+
this.unitData = {};
|
|
3414
|
+
this.defaultUnits = [];
|
|
2788
3415
|
this.disabled = false;
|
|
2789
3416
|
this.locale = "en-US";
|
|
2790
3417
|
this.expandedConcepts = /* @__PURE__ */ new Set();
|
|
@@ -2812,11 +3439,11 @@ let JupiterConceptTree = class extends LitElement {
|
|
|
2812
3439
|
}
|
|
2813
3440
|
_getFieldForColumn(columnId) {
|
|
2814
3441
|
var _a;
|
|
2815
|
-
return (_a = this.concept.fields) == null ? void 0 : _a.find((
|
|
3442
|
+
return (_a = this.concept.fields) == null ? void 0 : _a.find((field2) => field2.columnId === columnId);
|
|
2816
3443
|
}
|
|
2817
|
-
_getFieldValue(
|
|
3444
|
+
_getFieldValue(field2) {
|
|
2818
3445
|
var _a;
|
|
2819
|
-
return (_a = this.formData[this.concept.id]) == null ? void 0 : _a[
|
|
3446
|
+
return (_a = this.formData[this.concept.id]) == null ? void 0 : _a[field2.columnId];
|
|
2820
3447
|
}
|
|
2821
3448
|
_handleFieldChange(event) {
|
|
2822
3449
|
event.stopPropagation();
|
|
@@ -2859,20 +3486,25 @@ let JupiterConceptTree = class extends LitElement {
|
|
|
2859
3486
|
|
|
2860
3487
|
<!-- Input Field Cells (Period Columns) - Only for non-abstract concepts -->
|
|
2861
3488
|
${this.columns.map((column2) => {
|
|
2862
|
-
|
|
2863
|
-
const
|
|
3489
|
+
var _a, _b;
|
|
3490
|
+
const field2 = this._getFieldForColumn(column2.id);
|
|
3491
|
+
const shouldShowField = !isAbstract && field2;
|
|
3492
|
+
const storedUnit = (_b = (_a = this.unitData) == null ? void 0 : _a[this.concept.id]) == null ? void 0 : _b[column2.id];
|
|
2864
3493
|
return html`
|
|
2865
3494
|
<td class="field-cell ${!shouldShowField ? "empty" : ""} ${isAbstract ? "abstract-row" : ""}">
|
|
2866
3495
|
${shouldShowField ? html`
|
|
2867
3496
|
<jupiter-form-field
|
|
2868
|
-
.field="${
|
|
3497
|
+
.field="${field2}"
|
|
2869
3498
|
.conceptId="${this.concept.id}"
|
|
2870
3499
|
.conceptType="${this.concept.type}"
|
|
3500
|
+
.datatypes="${this.datatypes}"
|
|
3501
|
+
.defaultUnits="${this.defaultUnits}"
|
|
2871
3502
|
.columnId="${column2.id}"
|
|
2872
|
-
.value="${this._getFieldValue(
|
|
2873
|
-
.
|
|
2874
|
-
.
|
|
2875
|
-
.
|
|
3503
|
+
.value="${this._getFieldValue(field2)}"
|
|
3504
|
+
.unit="${storedUnit || ""}"
|
|
3505
|
+
.periodStartDate="${field2.periodStartDate || column2.periodStartDate}"
|
|
3506
|
+
.periodEndDate="${field2.periodEndDate || column2.periodEndDate}"
|
|
3507
|
+
.periodInstantDate="${field2.periodInstantDate || (field2.periodType === "instant" ? field2.periodEndDate || field2.periodStartDate : void 0)}"
|
|
2876
3508
|
.disabled="${this.disabled}"
|
|
2877
3509
|
.locale="${this.locale}"
|
|
2878
3510
|
.hideLabel="${true}"
|
|
@@ -2998,6 +3630,15 @@ __decorateClass$4([
|
|
|
2998
3630
|
__decorateClass$4([
|
|
2999
3631
|
n2({ type: Object })
|
|
3000
3632
|
], JupiterConceptTree.prototype, "formData", 2);
|
|
3633
|
+
__decorateClass$4([
|
|
3634
|
+
n2({ type: Object })
|
|
3635
|
+
], JupiterConceptTree.prototype, "periodData", 2);
|
|
3636
|
+
__decorateClass$4([
|
|
3637
|
+
n2({ type: Object })
|
|
3638
|
+
], JupiterConceptTree.prototype, "unitData", 2);
|
|
3639
|
+
__decorateClass$4([
|
|
3640
|
+
n2({ type: Array })
|
|
3641
|
+
], JupiterConceptTree.prototype, "defaultUnits", 2);
|
|
3001
3642
|
__decorateClass$4([
|
|
3002
3643
|
n2({ type: Boolean })
|
|
3003
3644
|
], JupiterConceptTree.prototype, "disabled", 2);
|
|
@@ -3007,6 +3648,9 @@ __decorateClass$4([
|
|
|
3007
3648
|
__decorateClass$4([
|
|
3008
3649
|
n2({ type: Set })
|
|
3009
3650
|
], JupiterConceptTree.prototype, "expandedConcepts", 2);
|
|
3651
|
+
__decorateClass$4([
|
|
3652
|
+
n2({ type: Array })
|
|
3653
|
+
], JupiterConceptTree.prototype, "datatypes", 2);
|
|
3010
3654
|
__decorateClass$4([
|
|
3011
3655
|
r()
|
|
3012
3656
|
], JupiterConceptTree.prototype, "_expanded", 2);
|
|
@@ -3061,9 +3705,9 @@ let JupiterAddColumnDialog = class extends LitElement {
|
|
|
3061
3705
|
if (!this._isFormValid())
|
|
3062
3706
|
return;
|
|
3063
3707
|
const request = {
|
|
3064
|
-
periodType: this.periodType === "mixed" ?
|
|
3708
|
+
periodType: this.periodType === "mixed" ? "duration" : this.periodType
|
|
3065
3709
|
};
|
|
3066
|
-
if (this.periodType === "instant"
|
|
3710
|
+
if (this.periodType === "instant") {
|
|
3067
3711
|
request.instantDate = this._instantDate;
|
|
3068
3712
|
} else {
|
|
3069
3713
|
request.startDate = this._startDate;
|
|
@@ -3078,13 +3722,7 @@ let JupiterAddColumnDialog = class extends LitElement {
|
|
|
3078
3722
|
}));
|
|
3079
3723
|
}
|
|
3080
3724
|
_isFormValid() {
|
|
3081
|
-
if (this.periodType === "mixed") {
|
|
3082
|
-
if (this._selectedType === "instant") {
|
|
3083
|
-
return !!this._instantDate;
|
|
3084
|
-
} else {
|
|
3085
|
-
return !!this._startDate && !!this._endDate && this._startDate <= this._endDate;
|
|
3086
|
-
}
|
|
3087
|
-
} else if (this.periodType === "duration") {
|
|
3725
|
+
if (this.periodType === "mixed" || this.periodType === "duration") {
|
|
3088
3726
|
return !!this._startDate && !!this._endDate && this._startDate <= this._endDate;
|
|
3089
3727
|
} else if (this.periodType === "instant") {
|
|
3090
3728
|
return !!this._instantDate;
|
|
@@ -3182,22 +3820,7 @@ let JupiterAddColumnDialog = class extends LitElement {
|
|
|
3182
3820
|
</div>
|
|
3183
3821
|
|
|
3184
3822
|
<div class="dialog-content">
|
|
3185
|
-
${this.periodType === "
|
|
3186
|
-
<div class="form-group">
|
|
3187
|
-
<label class="form-label required">${I18n.t("column.columnType")}</label>
|
|
3188
|
-
<select
|
|
3189
|
-
class="form-input"
|
|
3190
|
-
.value="${this._selectedType}"
|
|
3191
|
-
@change="${this._handleSelectedTypeChange}"
|
|
3192
|
-
required
|
|
3193
|
-
>
|
|
3194
|
-
<option value="instant">${I18n.t("column.instantSingleDate")}</option>
|
|
3195
|
-
<option value="duration">${I18n.t("column.durationDates")}</option>
|
|
3196
|
-
</select>
|
|
3197
|
-
</div>
|
|
3198
|
-
` : ""}
|
|
3199
|
-
|
|
3200
|
-
${this.periodType === "instant" || this.periodType === "mixed" && this._selectedType === "instant" ? html`
|
|
3823
|
+
${this.periodType === "instant" ? html`
|
|
3201
3824
|
<div class="form-group">
|
|
3202
3825
|
<label class="form-label required">${I18n.t("column.instantDate")}</label>
|
|
3203
3826
|
<input
|
|
@@ -3624,7 +4247,10 @@ let JupiterFormSection = class extends LitElement {
|
|
|
3624
4247
|
super(...arguments);
|
|
3625
4248
|
this.columns = [];
|
|
3626
4249
|
this.formData = {};
|
|
4250
|
+
this.periodData = {};
|
|
4251
|
+
this.unitData = {};
|
|
3627
4252
|
this.typedMemberData = {};
|
|
4253
|
+
this.defaultUnits = [];
|
|
3628
4254
|
this.disabled = false;
|
|
3629
4255
|
this.collapsible = true;
|
|
3630
4256
|
this.locale = "en-US";
|
|
@@ -3984,7 +4610,11 @@ let JupiterFormSection = class extends LitElement {
|
|
|
3984
4610
|
<jupiter-concept-tree
|
|
3985
4611
|
.concept="${concept}"
|
|
3986
4612
|
.columns="${this.columns}"
|
|
4613
|
+
.datatypes="${this.datatypes}"
|
|
3987
4614
|
.formData="${this.formData}"
|
|
4615
|
+
.periodData="${this.periodData}"
|
|
4616
|
+
.unitData="${this.unitData}"
|
|
4617
|
+
.defaultUnits="${this.defaultUnits}"
|
|
3988
4618
|
.disabled="${this.disabled}"
|
|
3989
4619
|
.locale="${this.locale}"
|
|
3990
4620
|
.expandedConcepts="${this._expandedConcepts}"
|
|
@@ -4275,12 +4905,24 @@ __decorateClass$2([
|
|
|
4275
4905
|
__decorateClass$2([
|
|
4276
4906
|
n2({ type: Array })
|
|
4277
4907
|
], JupiterFormSection.prototype, "columns", 2);
|
|
4908
|
+
__decorateClass$2([
|
|
4909
|
+
n2({ type: Array })
|
|
4910
|
+
], JupiterFormSection.prototype, "datatypes", 2);
|
|
4278
4911
|
__decorateClass$2([
|
|
4279
4912
|
n2({ type: Object })
|
|
4280
4913
|
], JupiterFormSection.prototype, "formData", 2);
|
|
4914
|
+
__decorateClass$2([
|
|
4915
|
+
n2({ type: Object })
|
|
4916
|
+
], JupiterFormSection.prototype, "periodData", 2);
|
|
4917
|
+
__decorateClass$2([
|
|
4918
|
+
n2({ type: Object })
|
|
4919
|
+
], JupiterFormSection.prototype, "unitData", 2);
|
|
4281
4920
|
__decorateClass$2([
|
|
4282
4921
|
n2({ type: Object })
|
|
4283
4922
|
], JupiterFormSection.prototype, "typedMemberData", 2);
|
|
4923
|
+
__decorateClass$2([
|
|
4924
|
+
n2({ type: Array })
|
|
4925
|
+
], JupiterFormSection.prototype, "defaultUnits", 2);
|
|
4284
4926
|
__decorateClass$2([
|
|
4285
4927
|
n2({ type: Boolean })
|
|
4286
4928
|
], JupiterFormSection.prototype, "disabled", 2);
|
|
@@ -5069,11 +5711,14 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
5069
5711
|
this.display = "accordion";
|
|
5070
5712
|
this.mode = "inputForm";
|
|
5071
5713
|
this.financialStatementsTypeAxis = [];
|
|
5714
|
+
this.defaultUnits = [];
|
|
5072
5715
|
this._formData = {};
|
|
5073
5716
|
this._draftLoaded = false;
|
|
5074
5717
|
this._preservedFormData = {};
|
|
5075
5718
|
this._periodData = {};
|
|
5076
5719
|
this._preservedPeriodData = {};
|
|
5720
|
+
this._unitData = {};
|
|
5721
|
+
this._preservedUnitData = {};
|
|
5077
5722
|
this._typedMemberData = {};
|
|
5078
5723
|
this._preservedTypedMemberData = {};
|
|
5079
5724
|
this._columns = [];
|
|
@@ -5082,6 +5727,8 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
5082
5727
|
this._dirty = false;
|
|
5083
5728
|
this._valid = true;
|
|
5084
5729
|
this._submitted = false;
|
|
5730
|
+
this._xbrlFormErrors = [];
|
|
5731
|
+
this._showErrorPopup = false;
|
|
5085
5732
|
this._allSections = [];
|
|
5086
5733
|
this._selectedRoleIds = [];
|
|
5087
5734
|
this._showFilterDialog = false;
|
|
@@ -5100,6 +5747,17 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
5100
5747
|
console.log(`🌍 [GLOBAL DynamicForm] Event detail:`, customEvent.detail);
|
|
5101
5748
|
this._handlePeriodChange(customEvent);
|
|
5102
5749
|
});
|
|
5750
|
+
this.addEventListener("unit-change", (e2) => {
|
|
5751
|
+
console.log(`🏷️ [GLOBAL DynamicForm] Caught unit-change event on element:`, e2);
|
|
5752
|
+
const customEvent = e2;
|
|
5753
|
+
console.log(`🏷️ [GLOBAL DynamicForm] Event detail:`, customEvent.detail);
|
|
5754
|
+
this._handleUnitChange(customEvent);
|
|
5755
|
+
});
|
|
5756
|
+
this.addEventListener("field-blur", (e2) => {
|
|
5757
|
+
console.log("🚨 [DynamicForm] field-blur event listener triggered!", e2);
|
|
5758
|
+
const customEvent = e2;
|
|
5759
|
+
this._handleFieldBlur(customEvent);
|
|
5760
|
+
});
|
|
5103
5761
|
this._initializeForm();
|
|
5104
5762
|
}
|
|
5105
5763
|
updated(changedProperties) {
|
|
@@ -5109,10 +5767,46 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
5109
5767
|
if (changedProperties.has("financialStatementsTypeAxis")) {
|
|
5110
5768
|
console.log("🔄 financialStatementsTypeAxis changed:", this.financialStatementsTypeAxis);
|
|
5111
5769
|
}
|
|
5770
|
+
if ((changedProperties.has("xbrlInput") || changedProperties.has("defaultUnits")) && this.xbrlInput && this.defaultUnits && this.defaultUnits.length > 0) {
|
|
5771
|
+
this._applyDefaultUnitsToDatatypes();
|
|
5772
|
+
}
|
|
5112
5773
|
if (changedProperties.has("xbrlInput") || changedProperties.has("schema") || changedProperties.has("language") || changedProperties.has("periodStartDate") || changedProperties.has("periodEndDate") || changedProperties.has("financialStatementsTypeAxis")) {
|
|
5113
5774
|
this._initializeForm();
|
|
5114
5775
|
}
|
|
5115
5776
|
}
|
|
5777
|
+
/**
|
|
5778
|
+
* Apply developer-provided default units to datatypes by setting isDefault=true
|
|
5779
|
+
* This allows units to be auto-selected for derived types (e.g., nl-types:monetaryNoDecimals20ItemType)
|
|
5780
|
+
*/
|
|
5781
|
+
_applyDefaultUnitsToDatatypes() {
|
|
5782
|
+
var _a;
|
|
5783
|
+
if (!((_a = this.xbrlInput) == null ? void 0 : _a.datatypes) || !this.defaultUnits || this.defaultUnits.length === 0) {
|
|
5784
|
+
return;
|
|
5785
|
+
}
|
|
5786
|
+
console.log("🔧 [DynamicForm] Applying defaultUnits to datatypes:", this.defaultUnits);
|
|
5787
|
+
const datatypesArray = Array.isArray(this.xbrlInput.datatypes) ? this.xbrlInput.datatypes : this.xbrlInput.datatypes.concepts;
|
|
5788
|
+
if (!datatypesArray || datatypesArray.length === 0) {
|
|
5789
|
+
console.warn("⚠️ [DynamicForm] No datatypes found to apply defaults to");
|
|
5790
|
+
return;
|
|
5791
|
+
}
|
|
5792
|
+
this.defaultUnits.forEach((defaultUnitMap) => {
|
|
5793
|
+
Object.entries(defaultUnitMap).forEach(([datatypeId, unitId]) => {
|
|
5794
|
+
const datatype = datatypesArray.find((dt) => dt.type === datatypeId || dt.id === datatypeId);
|
|
5795
|
+
if (datatype && datatype.units && datatype.units.length > 0) {
|
|
5796
|
+
const targetUnit = datatype.units.find((u2) => u2.id === unitId);
|
|
5797
|
+
if (targetUnit) {
|
|
5798
|
+
datatype.units.forEach((u2) => u2.isDefault = false);
|
|
5799
|
+
targetUnit.isDefault = true;
|
|
5800
|
+
console.log(`✅ [DynamicForm] Set isDefault=true for unit "${unitId}" in datatype "${datatypeId}"`);
|
|
5801
|
+
} else {
|
|
5802
|
+
console.warn(`⚠️ [DynamicForm] Unit "${unitId}" not found in datatype "${datatypeId}"`);
|
|
5803
|
+
}
|
|
5804
|
+
} else {
|
|
5805
|
+
console.warn(`⚠️ [DynamicForm] Datatype "${datatypeId}" not found or has no units`);
|
|
5806
|
+
}
|
|
5807
|
+
});
|
|
5808
|
+
});
|
|
5809
|
+
}
|
|
5116
5810
|
_initializeForm() {
|
|
5117
5811
|
var _a;
|
|
5118
5812
|
if (!this._draftStorageService) {
|
|
@@ -5155,8 +5849,8 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
5155
5849
|
removable: false
|
|
5156
5850
|
}
|
|
5157
5851
|
];
|
|
5158
|
-
} catch (
|
|
5159
|
-
console.error("❌ Error building form from XBRL input:",
|
|
5852
|
+
} catch (error2) {
|
|
5853
|
+
console.error("❌ Error building form from XBRL input:", error2);
|
|
5160
5854
|
this._currentSchema = this._getDefaultSchema();
|
|
5161
5855
|
this._allSections = [];
|
|
5162
5856
|
this._selectedRoleIds = [];
|
|
@@ -5351,9 +6045,9 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
5351
6045
|
if (this._formData[concept.id]) {
|
|
5352
6046
|
this._preservedFormData[concept.id] = { ...this._formData[concept.id] };
|
|
5353
6047
|
}
|
|
5354
|
-
concept.fields.forEach((
|
|
5355
|
-
if (this._typedMemberData[
|
|
5356
|
-
this._preservedTypedMemberData[
|
|
6048
|
+
concept.fields.forEach((field2) => {
|
|
6049
|
+
if (this._typedMemberData[field2.columnId]) {
|
|
6050
|
+
this._preservedTypedMemberData[field2.columnId] = { ...this._typedMemberData[field2.columnId] };
|
|
5357
6051
|
}
|
|
5358
6052
|
});
|
|
5359
6053
|
if (concept.children) {
|
|
@@ -5371,9 +6065,9 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
5371
6065
|
if (this._preservedFormData[concept.id]) {
|
|
5372
6066
|
this._formData[concept.id] = { ...this._preservedFormData[concept.id] };
|
|
5373
6067
|
}
|
|
5374
|
-
concept.fields.forEach((
|
|
5375
|
-
if (this._preservedTypedMemberData[
|
|
5376
|
-
this._typedMemberData[
|
|
6068
|
+
concept.fields.forEach((field2) => {
|
|
6069
|
+
if (this._preservedTypedMemberData[field2.columnId]) {
|
|
6070
|
+
this._typedMemberData[field2.columnId] = { ...this._preservedTypedMemberData[field2.columnId] };
|
|
5377
6071
|
}
|
|
5378
6072
|
});
|
|
5379
6073
|
if (concept.children) {
|
|
@@ -5408,7 +6102,9 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
5408
6102
|
this._selectedRoleIds,
|
|
5409
6103
|
this._allSections,
|
|
5410
6104
|
this._typedMemberData,
|
|
5411
|
-
this._periodPreferences
|
|
6105
|
+
this._periodPreferences,
|
|
6106
|
+
this._periodData,
|
|
6107
|
+
this._unitData
|
|
5412
6108
|
);
|
|
5413
6109
|
this._draftStorageService.saveDraft(currentFormData, currentMetadata);
|
|
5414
6110
|
console.log("✅ Current form data saved to draft storage");
|
|
@@ -5418,8 +6114,8 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
5418
6114
|
console.log("📥 Restoring form data from draft after reinitialization...");
|
|
5419
6115
|
this._loadDraftIfExists().then(() => {
|
|
5420
6116
|
console.log("✅ Form data restored successfully after reinitialization");
|
|
5421
|
-
}).catch((
|
|
5422
|
-
console.error("❌ Error restoring form data after reinitialization:",
|
|
6117
|
+
}).catch((error2) => {
|
|
6118
|
+
console.error("❌ Error restoring form data after reinitialization:", error2);
|
|
5423
6119
|
});
|
|
5424
6120
|
} else {
|
|
5425
6121
|
this._applyRoleFilter();
|
|
@@ -5444,15 +6140,15 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
5444
6140
|
return;
|
|
5445
6141
|
for (const section2 of schema.sections) {
|
|
5446
6142
|
for (const concept of section2.concepts) {
|
|
5447
|
-
for (const
|
|
5448
|
-
const value = (_a = this._formData[concept.id]) == null ? void 0 : _a[
|
|
6143
|
+
for (const field2 of concept.fields) {
|
|
6144
|
+
const value = (_a = this._formData[concept.id]) == null ? void 0 : _a[field2.columnId];
|
|
5449
6145
|
const fieldErrors = FormValidator.validateField(
|
|
5450
|
-
|
|
6146
|
+
field2.id,
|
|
5451
6147
|
concept.id,
|
|
5452
|
-
|
|
6148
|
+
field2.columnId,
|
|
5453
6149
|
value,
|
|
5454
|
-
|
|
5455
|
-
|
|
6150
|
+
field2.type,
|
|
6151
|
+
field2.validation || []
|
|
5456
6152
|
);
|
|
5457
6153
|
errors.push(...fieldErrors);
|
|
5458
6154
|
}
|
|
@@ -5484,8 +6180,8 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
5484
6180
|
_handlePeriodChange(event) {
|
|
5485
6181
|
console.log(`🎯 [DynamicForm] _handlePeriodChange called with event:`, event);
|
|
5486
6182
|
console.log(`🎯 [DynamicForm] Event detail:`, event.detail);
|
|
5487
|
-
const { conceptId, columnId, periodType, periodStartDate, periodEndDate, periodInstantDate } = event.detail;
|
|
5488
|
-
console.log(`📅 Period change received: conceptId=${conceptId}, columnId=${columnId}, periodType=${periodType}, startDate=${periodStartDate}, endDate=${periodEndDate}, instantDate=${periodInstantDate}`);
|
|
6183
|
+
const { conceptId, columnId, periodType, periodStartDate, periodEndDate, periodInstantDate, unit } = event.detail;
|
|
6184
|
+
console.log(`📅 Period change received: conceptId=${conceptId}, columnId=${columnId}, periodType=${periodType}, startDate=${periodStartDate}, endDate=${periodEndDate}, instantDate=${periodInstantDate}, unit=${unit}`);
|
|
5489
6185
|
const updatedPeriodData = { ...this._periodData };
|
|
5490
6186
|
if (!updatedPeriodData[conceptId]) {
|
|
5491
6187
|
updatedPeriodData[conceptId] = {};
|
|
@@ -5501,9 +6197,37 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
5501
6197
|
this._periodData = updatedPeriodData;
|
|
5502
6198
|
console.log(`💾 Period data stored for [${conceptId}][${columnId}]:`, this._periodData[conceptId][columnId]);
|
|
5503
6199
|
console.log(`📦 Full period data state:`, JSON.stringify(this._periodData, null, 2));
|
|
6200
|
+
if (unit) {
|
|
6201
|
+
this._storeUnit(conceptId, columnId, unit);
|
|
6202
|
+
}
|
|
5504
6203
|
this._dirty = true;
|
|
5505
6204
|
this.requestUpdate();
|
|
5506
6205
|
}
|
|
6206
|
+
_handleUnitChange(event) {
|
|
6207
|
+
console.log(`🏷️ [DynamicForm] _handleUnitChange called with event:`, event);
|
|
6208
|
+
console.log(`🏷️ [DynamicForm] Event detail:`, event.detail);
|
|
6209
|
+
const { conceptId, columnId, unit } = event.detail;
|
|
6210
|
+
console.log(`🏷️ Unit change received: conceptId=${conceptId}, columnId=${columnId}, unit=${unit}`);
|
|
6211
|
+
this._storeUnit(conceptId, columnId, unit);
|
|
6212
|
+
this._dirty = true;
|
|
6213
|
+
this.requestUpdate();
|
|
6214
|
+
}
|
|
6215
|
+
_storeUnit(conceptId, columnId, unit) {
|
|
6216
|
+
console.log(`🔧 [_storeUnit] Called with conceptId=${conceptId}, columnId=${columnId}, unit=${unit}`);
|
|
6217
|
+
console.log(`🔧 [_storeUnit] Current _unitData before update:`, JSON.stringify(this._unitData, null, 2));
|
|
6218
|
+
const updatedUnitData = { ...this._unitData };
|
|
6219
|
+
if (!updatedUnitData[conceptId]) {
|
|
6220
|
+
console.log(`🔧 [_storeUnit] Creating new entry for conceptId: ${conceptId}`);
|
|
6221
|
+
updatedUnitData[conceptId] = {};
|
|
6222
|
+
}
|
|
6223
|
+
updatedUnitData[conceptId] = {
|
|
6224
|
+
...updatedUnitData[conceptId],
|
|
6225
|
+
[columnId]: unit
|
|
6226
|
+
};
|
|
6227
|
+
this._unitData = updatedUnitData;
|
|
6228
|
+
console.log(`💾 [_storeUnit] Unit data stored for [${conceptId}][${columnId}]:`, this._unitData[conceptId][columnId]);
|
|
6229
|
+
console.log(`📦 [_storeUnit] Full unit data state after update:`, JSON.stringify(this._unitData, null, 2));
|
|
6230
|
+
}
|
|
5507
6231
|
/**
|
|
5508
6232
|
* Generate a unique concept key that includes section context
|
|
5509
6233
|
*/
|
|
@@ -5533,6 +6257,164 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
5533
6257
|
bubbles: true
|
|
5534
6258
|
}));
|
|
5535
6259
|
}
|
|
6260
|
+
_handleFieldBlur(event) {
|
|
6261
|
+
var _a;
|
|
6262
|
+
console.log(`🟧 [DynamicForm] _handleFieldBlur received event:`, event);
|
|
6263
|
+
console.log(`🟧 [DynamicForm] Event detail:`, event.detail);
|
|
6264
|
+
const { fieldId, conceptId, columnId, xbrlValidationErrors } = event.detail;
|
|
6265
|
+
console.log(`🟧 [DynamicForm] Extracted - fieldId: ${fieldId}, conceptId: ${conceptId}, columnId: ${columnId}`);
|
|
6266
|
+
console.log(`🟧 [DynamicForm] xbrlValidationErrors:`, xbrlValidationErrors);
|
|
6267
|
+
let sectionId = "";
|
|
6268
|
+
const path = event.composedPath();
|
|
6269
|
+
console.log(`🟧 [DynamicForm] Event path length: ${path.length}`);
|
|
6270
|
+
for (const element of path) {
|
|
6271
|
+
const el = element;
|
|
6272
|
+
if (el.tagName === "JUPITER-FORM-SECTION") {
|
|
6273
|
+
sectionId = el.getAttribute("section-id") || "";
|
|
6274
|
+
console.log(`🟧 [DynamicForm] Found section element with id: ${sectionId}`);
|
|
6275
|
+
break;
|
|
6276
|
+
}
|
|
6277
|
+
}
|
|
6278
|
+
console.log(`🟧 [DynamicForm] Found sectionId: ${sectionId}`);
|
|
6279
|
+
console.log(`🟧 [DynamicForm] Processing errors - has errors: ${xbrlValidationErrors && xbrlValidationErrors.length > 0}`);
|
|
6280
|
+
if (xbrlValidationErrors && xbrlValidationErrors.length > 0) {
|
|
6281
|
+
console.log(`🟧 [DynamicForm] Adding/updating error for fieldId: ${fieldId}, sectionId: ${sectionId}`);
|
|
6282
|
+
const value = ((_a = this._formData[conceptId]) == null ? void 0 : _a[columnId]) || "";
|
|
6283
|
+
const existingIndex = this._xbrlFormErrors.findIndex(
|
|
6284
|
+
(e2) => e2.fieldId === fieldId && e2.sectionId === sectionId
|
|
6285
|
+
);
|
|
6286
|
+
const newError = {
|
|
6287
|
+
sectionId,
|
|
6288
|
+
fieldId,
|
|
6289
|
+
conceptId,
|
|
6290
|
+
columnId,
|
|
6291
|
+
value,
|
|
6292
|
+
errors: xbrlValidationErrors
|
|
6293
|
+
};
|
|
6294
|
+
console.log(`🟧 [DynamicForm] New error object:`, newError);
|
|
6295
|
+
console.log(`🟧 [DynamicForm] Existing index: ${existingIndex}`);
|
|
6296
|
+
if (existingIndex >= 0) {
|
|
6297
|
+
this._xbrlFormErrors = [
|
|
6298
|
+
...this._xbrlFormErrors.slice(0, existingIndex),
|
|
6299
|
+
newError,
|
|
6300
|
+
...this._xbrlFormErrors.slice(existingIndex + 1)
|
|
6301
|
+
];
|
|
6302
|
+
console.log(`🟧 [DynamicForm] Updated existing error at index ${existingIndex}`);
|
|
6303
|
+
} else {
|
|
6304
|
+
this._xbrlFormErrors = [...this._xbrlFormErrors, newError];
|
|
6305
|
+
console.log(`🟧 [DynamicForm] Added new error`);
|
|
6306
|
+
}
|
|
6307
|
+
} else {
|
|
6308
|
+
console.log(`🟧 [DynamicForm] Removing error (if exists) for fieldId: ${fieldId}, sectionId: ${sectionId}`);
|
|
6309
|
+
const beforeLength = this._xbrlFormErrors.length;
|
|
6310
|
+
this._xbrlFormErrors = this._xbrlFormErrors.filter(
|
|
6311
|
+
(e2) => !(e2.fieldId === fieldId && e2.sectionId === sectionId)
|
|
6312
|
+
);
|
|
6313
|
+
console.log(`🟧 [DynamicForm] Removed ${beforeLength - this._xbrlFormErrors.length} errors`);
|
|
6314
|
+
}
|
|
6315
|
+
console.log(`🔍 [Validation] Total errors: ${this._xbrlFormErrors.length}`, this._xbrlFormErrors);
|
|
6316
|
+
}
|
|
6317
|
+
_getSectionTitle(sectionId) {
|
|
6318
|
+
console.log(`🔍 [_getSectionTitle] Looking for sectionId: "${sectionId}"`);
|
|
6319
|
+
console.log(`🔍 [_getSectionTitle] Available sections:`, this._allSections.map((s2) => ({ id: s2.id, title: s2.title })));
|
|
6320
|
+
const section2 = this._allSections.find((s2) => s2.id === sectionId);
|
|
6321
|
+
const result = (section2 == null ? void 0 : section2.title) || sectionId || "(Unknown Section)";
|
|
6322
|
+
console.log(`🔍 [_getSectionTitle] Result: "${result}"`);
|
|
6323
|
+
return result;
|
|
6324
|
+
}
|
|
6325
|
+
async _handleErrorFieldClick(conceptId, columnId, sectionId) {
|
|
6326
|
+
var _a, _b, _c, _d;
|
|
6327
|
+
console.log(`🎯 [Error Click] Attempting to focus field: ${conceptId}__${columnId} in section: ${sectionId}`);
|
|
6328
|
+
this._showErrorPopup = false;
|
|
6329
|
+
this.requestUpdate();
|
|
6330
|
+
await this.updateComplete;
|
|
6331
|
+
if (this.display === "sidePanel" && this._activeSidePanelRoleId !== sectionId) {
|
|
6332
|
+
console.log(`🔀 Switching to section: ${sectionId} (currently on: ${this._activeSidePanelRoleId})`);
|
|
6333
|
+
this._activeSidePanelRoleId = sectionId;
|
|
6334
|
+
this.requestUpdate();
|
|
6335
|
+
await this.updateComplete;
|
|
6336
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
6337
|
+
}
|
|
6338
|
+
const sectionElements = (_a = this.shadowRoot) == null ? void 0 : _a.querySelectorAll("jupiter-form-section");
|
|
6339
|
+
let targetSection = null;
|
|
6340
|
+
sectionElements == null ? void 0 : sectionElements.forEach((sectionEl) => {
|
|
6341
|
+
var _a2;
|
|
6342
|
+
if (((_a2 = sectionEl.section) == null ? void 0 : _a2.id) === sectionId) {
|
|
6343
|
+
targetSection = sectionEl;
|
|
6344
|
+
}
|
|
6345
|
+
});
|
|
6346
|
+
if (!targetSection) {
|
|
6347
|
+
console.warn(`⚠️ Section not found: ${sectionId}`);
|
|
6348
|
+
return;
|
|
6349
|
+
}
|
|
6350
|
+
console.log(`✅ Found section element:`, targetSection);
|
|
6351
|
+
if ((_b = targetSection.section) == null ? void 0 : _b.collapsed) {
|
|
6352
|
+
console.log(`📂 Expanding collapsed section`);
|
|
6353
|
+
targetSection.section.collapsed = false;
|
|
6354
|
+
targetSection.requestUpdate();
|
|
6355
|
+
await targetSection.updateComplete;
|
|
6356
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
6357
|
+
} else {
|
|
6358
|
+
await targetSection.updateComplete;
|
|
6359
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
6360
|
+
}
|
|
6361
|
+
console.log(`🔍 Section shadow DOM exists: ${!!targetSection.shadowRoot}`);
|
|
6362
|
+
if (targetSection.shadowRoot) {
|
|
6363
|
+
console.log(`🔍 Shadow DOM innerHTML length: ${((_c = targetSection.shadowRoot.innerHTML) == null ? void 0 : _c.length) || 0}`);
|
|
6364
|
+
const allElements = targetSection.shadowRoot.querySelectorAll("*");
|
|
6365
|
+
console.log(`🔍 Total elements in shadow DOM: ${allElements.length}`);
|
|
6366
|
+
const customElements2 = Array.from(allElements).filter((el) => {
|
|
6367
|
+
const element = el;
|
|
6368
|
+
return !!(element.tagName && element.tagName.includes("-"));
|
|
6369
|
+
});
|
|
6370
|
+
console.log(`🔍 Custom elements found:`, customElements2.map((el) => el.tagName).join(", "));
|
|
6371
|
+
}
|
|
6372
|
+
const fieldId = `${conceptId}_${columnId}_field`;
|
|
6373
|
+
console.log(`🔍 Looking for input with fieldId: ${fieldId}`);
|
|
6374
|
+
console.log(`🔍 Looking for field with conceptId: ${conceptId} AND columnId: ${columnId}`);
|
|
6375
|
+
const conceptTrees = (_d = targetSection.shadowRoot) == null ? void 0 : _d.querySelectorAll("jupiter-concept-tree");
|
|
6376
|
+
let targetInput = null;
|
|
6377
|
+
console.log(`🔍 Found ${(conceptTrees == null ? void 0 : conceptTrees.length) || 0} concept-tree elements`);
|
|
6378
|
+
if (conceptTrees) {
|
|
6379
|
+
conceptTrees.forEach((conceptTree, treeIndex) => {
|
|
6380
|
+
var _a2;
|
|
6381
|
+
if (targetInput)
|
|
6382
|
+
return;
|
|
6383
|
+
const formFieldsInTree = (_a2 = conceptTree.shadowRoot) == null ? void 0 : _a2.querySelectorAll("jupiter-form-field");
|
|
6384
|
+
console.log(`🔍 Concept tree ${treeIndex}: Found ${(formFieldsInTree == null ? void 0 : formFieldsInTree.length) || 0} form-field elements`);
|
|
6385
|
+
formFieldsInTree == null ? void 0 : formFieldsInTree.forEach((fieldEl, fieldIndex) => {
|
|
6386
|
+
var _a3;
|
|
6387
|
+
if (targetInput)
|
|
6388
|
+
return;
|
|
6389
|
+
console.log(` Field ${fieldIndex}: conceptId=${fieldEl.conceptId}, columnId=${fieldEl.columnId}`);
|
|
6390
|
+
if (fieldEl.conceptId === conceptId && fieldEl.columnId === columnId) {
|
|
6391
|
+
const inputEl = (_a3 = fieldEl.shadowRoot) == null ? void 0 : _a3.querySelector("input, textarea");
|
|
6392
|
+
console.log(` -> Matched! Input element found: ${!!inputEl}`);
|
|
6393
|
+
if (inputEl) {
|
|
6394
|
+
targetInput = inputEl;
|
|
6395
|
+
console.log(`✅ Found input element in form-field`);
|
|
6396
|
+
}
|
|
6397
|
+
}
|
|
6398
|
+
});
|
|
6399
|
+
});
|
|
6400
|
+
}
|
|
6401
|
+
if (!targetInput) {
|
|
6402
|
+
console.warn(`⚠️ Input field not found for: ${fieldId}`);
|
|
6403
|
+
return;
|
|
6404
|
+
}
|
|
6405
|
+
const input = targetInput;
|
|
6406
|
+
targetSection.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
6407
|
+
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
6408
|
+
input.focus();
|
|
6409
|
+
if (input.tagName === "INPUT" || input.tagName === "TEXTAREA") {
|
|
6410
|
+
input.select();
|
|
6411
|
+
}
|
|
6412
|
+
input.style.boxShadow = "0 0 0 3px rgba(220, 38, 38, 0.5)";
|
|
6413
|
+
setTimeout(() => {
|
|
6414
|
+
input.style.boxShadow = "";
|
|
6415
|
+
}, 2e3);
|
|
6416
|
+
console.log(`✅ Successfully focused field: ${conceptId}__${columnId}`);
|
|
6417
|
+
}
|
|
5536
6418
|
_handleSectionExpand(event) {
|
|
5537
6419
|
this.dispatchEvent(new CustomEvent("section-expand", {
|
|
5538
6420
|
detail: event.detail,
|
|
@@ -5798,7 +6680,7 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
5798
6680
|
delete this._formData[concept.id][columnId];
|
|
5799
6681
|
}
|
|
5800
6682
|
if (concept.fields) {
|
|
5801
|
-
concept.fields = concept.fields.filter((
|
|
6683
|
+
concept.fields = concept.fields.filter((field2) => field2.columnId !== columnId);
|
|
5802
6684
|
}
|
|
5803
6685
|
if (concept.children) {
|
|
5804
6686
|
this._removeColumnDataFromConcepts(concept.children, columnId);
|
|
@@ -5809,7 +6691,8 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
5809
6691
|
if (concept.abstract) {
|
|
5810
6692
|
return false;
|
|
5811
6693
|
}
|
|
5812
|
-
|
|
6694
|
+
const isDimensionColumn = request.selectedDimensions && request.selectedDimensions.length > 0;
|
|
6695
|
+
if (!isDimensionColumn && concept.periodType) {
|
|
5813
6696
|
if (request.periodType === "instant" && concept.periodType !== "instant") {
|
|
5814
6697
|
return false;
|
|
5815
6698
|
}
|
|
@@ -5833,9 +6716,9 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
5833
6716
|
var _a;
|
|
5834
6717
|
if (this._shouldCreateFieldForConcept(concept, request)) {
|
|
5835
6718
|
const existingField = (_a = concept.fields) == null ? void 0 : _a[0];
|
|
5836
|
-
let
|
|
6719
|
+
let field2;
|
|
5837
6720
|
if (existingField) {
|
|
5838
|
-
|
|
6721
|
+
field2 = {
|
|
5839
6722
|
id: `${concept.id}_${columnId}`,
|
|
5840
6723
|
conceptId: concept.id,
|
|
5841
6724
|
columnId,
|
|
@@ -5848,13 +6731,15 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
5848
6731
|
defaultValue: existingField.defaultValue,
|
|
5849
6732
|
periodType: concept.periodType,
|
|
5850
6733
|
// Add periodType from concept
|
|
6734
|
+
conceptType: concept.type,
|
|
6735
|
+
// CRITICAL: Include conceptType for XBRL validation
|
|
5851
6736
|
// Set period dates from the add column request
|
|
5852
6737
|
periodStartDate: request.periodType === "instant" ? request.instantDate : request.startDate,
|
|
5853
6738
|
periodEndDate: request.periodType === "instant" ? request.instantDate : request.endDate,
|
|
5854
6739
|
periodInstantDate: concept.periodType === "instant" ? request.instantDate || request.startDate : void 0
|
|
5855
6740
|
};
|
|
5856
6741
|
} else {
|
|
5857
|
-
|
|
6742
|
+
field2 = {
|
|
5858
6743
|
id: `${concept.id}_${columnId}`,
|
|
5859
6744
|
conceptId: concept.id,
|
|
5860
6745
|
columnId,
|
|
@@ -5867,6 +6752,8 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
5867
6752
|
defaultValue: "",
|
|
5868
6753
|
periodType: concept.periodType,
|
|
5869
6754
|
// Add periodType from concept
|
|
6755
|
+
conceptType: concept.type,
|
|
6756
|
+
// CRITICAL: Include conceptType for XBRL validation
|
|
5870
6757
|
// Set period dates from the add column request
|
|
5871
6758
|
periodStartDate: request.periodType === "instant" ? request.instantDate : request.startDate,
|
|
5872
6759
|
periodEndDate: request.periodType === "instant" ? request.instantDate : request.endDate,
|
|
@@ -5876,7 +6763,7 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
5876
6763
|
if (!concept.fields) {
|
|
5877
6764
|
concept.fields = [];
|
|
5878
6765
|
}
|
|
5879
|
-
concept.fields.push(
|
|
6766
|
+
concept.fields.push(field2);
|
|
5880
6767
|
}
|
|
5881
6768
|
if (concept.children) {
|
|
5882
6769
|
this._replicateFieldsForSection(concept.children, columnId, request, formBuilder);
|
|
@@ -5915,6 +6802,10 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
5915
6802
|
this._validateForm();
|
|
5916
6803
|
const submissionData = this._generateSubmissionData();
|
|
5917
6804
|
console.log("📊 Form Submission Data:", JSON.stringify(submissionData, null, 2));
|
|
6805
|
+
console.log("📊 Submission Data Summary:");
|
|
6806
|
+
submissionData.forEach((entry, index) => {
|
|
6807
|
+
console.log(` [${index}] conceptId: ${entry.conceptId}, columnId: ${entry.columnId}, value: ${entry.value}, unit: ${entry.unit || "none"}`);
|
|
6808
|
+
});
|
|
5918
6809
|
this.dispatchEvent(new CustomEvent("form-submit", {
|
|
5919
6810
|
detail: {
|
|
5920
6811
|
data: this._formData,
|
|
@@ -5927,12 +6818,23 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
5927
6818
|
console.log("✅ Form submit event dispatched");
|
|
5928
6819
|
}
|
|
5929
6820
|
_handleSaveDraft() {
|
|
6821
|
+
console.log(`🔵 [Save Draft] Checking for errors...`);
|
|
6822
|
+
console.log(`🔵 [Save Draft] _xbrlFormErrors.length: ${this._xbrlFormErrors.length}`);
|
|
6823
|
+
console.log(`🔵 [Save Draft] _xbrlFormErrors:`, this._xbrlFormErrors);
|
|
6824
|
+
if (this._xbrlFormErrors.length > 0) {
|
|
6825
|
+
console.log("❌ [Save Draft] Cannot save - validation errors present:", this._xbrlFormErrors);
|
|
6826
|
+
this._showErrorPopup = true;
|
|
6827
|
+
this.requestUpdate();
|
|
6828
|
+
return;
|
|
6829
|
+
}
|
|
6830
|
+
console.log(`✅ [Save Draft] No validation errors, proceeding with save...`);
|
|
5930
6831
|
console.log("💾 Raw form data before submission generation:", this._formData);
|
|
6832
|
+
console.log("🏷️ Unit data before submission generation:", this._unitData);
|
|
5931
6833
|
const draftData = this._generateSubmissionData();
|
|
5932
6834
|
console.log("📤 Generated submission data:", draftData);
|
|
5933
6835
|
console.log("📊 Submission data breakdown:");
|
|
5934
6836
|
draftData.forEach((entry, index) => {
|
|
5935
|
-
console.log(` [${index}] conceptId: ${entry.conceptId}, columnId: ${entry.columnId}, value: ${entry.value}`);
|
|
6837
|
+
console.log(` [${index}] conceptId: ${entry.conceptId}, columnId: ${entry.columnId}, value: ${entry.value}, unit: ${entry.unit || "none"}`);
|
|
5936
6838
|
});
|
|
5937
6839
|
const metadata = this._draftStorageService.createMetadataSnapshot(
|
|
5938
6840
|
this.periodStartDate,
|
|
@@ -5942,7 +6844,8 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
5942
6844
|
this._allSections,
|
|
5943
6845
|
this._typedMemberData,
|
|
5944
6846
|
this._periodPreferences,
|
|
5945
|
-
this._periodData
|
|
6847
|
+
this._periodData,
|
|
6848
|
+
this._unitData
|
|
5946
6849
|
);
|
|
5947
6850
|
const saved = this._draftStorageService.saveDraft(draftData, metadata);
|
|
5948
6851
|
this.dynaformsFacts = draftData;
|
|
@@ -6046,6 +6949,10 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
6046
6949
|
this._periodData = metadata.periodData;
|
|
6047
6950
|
console.log("🔄 Restored custom field-level period data:", Object.keys(this._periodData).length, "concepts");
|
|
6048
6951
|
}
|
|
6952
|
+
if (metadata.unitData) {
|
|
6953
|
+
this._unitData = metadata.unitData;
|
|
6954
|
+
console.log("🔄 Restored custom field-level unit data:", Object.keys(this._unitData).length, "concepts");
|
|
6955
|
+
}
|
|
6049
6956
|
if (metadata.periodPreferences) {
|
|
6050
6957
|
this._periodPreferences = metadata.periodPreferences;
|
|
6051
6958
|
console.log("🔄 Restored period preferences (including previous year settings):", this._periodPreferences);
|
|
@@ -6078,8 +6985,9 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
6078
6985
|
}
|
|
6079
6986
|
const restoredFormData = {};
|
|
6080
6987
|
const restoredPeriodData = {};
|
|
6988
|
+
const restoredUnitData = {};
|
|
6081
6989
|
formData.forEach((entry) => {
|
|
6082
|
-
let { conceptId, value, columnId, period } = entry;
|
|
6990
|
+
let { conceptId, value, columnId, period, unit } = entry;
|
|
6083
6991
|
if (!columnId && period) {
|
|
6084
6992
|
columnId = this._inferColumnIdFromPeriod(period, conceptId);
|
|
6085
6993
|
if (!columnId) {
|
|
@@ -6111,6 +7019,13 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
6111
7019
|
console.log(`📅 [Restore Period] Extracted duration dates for ${conceptIdToUse}/${columnId}: ${period.startDate} - ${period.endDate}`);
|
|
6112
7020
|
}
|
|
6113
7021
|
}
|
|
7022
|
+
if (unit) {
|
|
7023
|
+
if (!restoredUnitData[conceptIdToUse]) {
|
|
7024
|
+
restoredUnitData[conceptIdToUse] = {};
|
|
7025
|
+
}
|
|
7026
|
+
restoredUnitData[conceptIdToUse][columnId] = unit;
|
|
7027
|
+
console.log(`🏷️ [Restore Unit] Extracted unit for ${conceptIdToUse}/${columnId}: ${unit}`);
|
|
7028
|
+
}
|
|
6114
7029
|
});
|
|
6115
7030
|
this._formData = { ...this._formData, ...restoredFormData };
|
|
6116
7031
|
console.log(`🔄 Restored ${Object.keys(restoredFormData).length} concepts with data`);
|
|
@@ -6121,6 +7036,13 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
6121
7036
|
};
|
|
6122
7037
|
console.log(`📅 [Period Restore] Merged period data: ${Object.keys(this._periodData).length} concepts with custom periods`);
|
|
6123
7038
|
console.log(`📅 [Period Restore] Full _periodData after merge:`, JSON.stringify(this._periodData, null, 2));
|
|
7039
|
+
this._unitData = {
|
|
7040
|
+
...this._unitData,
|
|
7041
|
+
...metadata.unitData || {},
|
|
7042
|
+
...restoredUnitData
|
|
7043
|
+
};
|
|
7044
|
+
console.log(`🏷️ [Unit Restore] Merged unit data: ${Object.keys(this._unitData).length} concepts with custom units`);
|
|
7045
|
+
console.log(`🏷️ [Unit Restore] Full _unitData after merge:`, JSON.stringify(this._unitData, null, 2));
|
|
6124
7046
|
if (this._selectedRoleIds.length > 0) {
|
|
6125
7047
|
this._applyRoleFilter();
|
|
6126
7048
|
}
|
|
@@ -6247,6 +7169,7 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
6247
7169
|
columnsBySection.get(col.sectionId).push(col);
|
|
6248
7170
|
});
|
|
6249
7171
|
this._allSections.forEach((section2) => {
|
|
7172
|
+
var _a;
|
|
6250
7173
|
const savedColumns = columnsBySection.get(section2.id);
|
|
6251
7174
|
if (savedColumns) {
|
|
6252
7175
|
section2.columns = savedColumns.map((col) => {
|
|
@@ -6258,11 +7181,22 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
6258
7181
|
periodEndDate: col.endDate || col.date,
|
|
6259
7182
|
dimensionData: col.dimensionData,
|
|
6260
7183
|
order: 0,
|
|
6261
|
-
removable: col.columnId !== "duration" && col.columnId !== "instant"
|
|
7184
|
+
removable: col.columnId !== "duration" && col.columnId !== "instant",
|
|
7185
|
+
periodType: col.periodType
|
|
7186
|
+
// CRITICAL: Preserve explicit period type
|
|
6262
7187
|
};
|
|
6263
|
-
console.log(`📅 [Draft Restore] Restoring column ${col.columnId}: startDate=${column2.periodStartDate}, endDate=${column2.periodEndDate}`);
|
|
7188
|
+
console.log(`📅 [Draft Restore] Restoring column ${col.columnId}: startDate=${column2.periodStartDate}, endDate=${column2.periodEndDate}, periodType=${column2.periodType}`);
|
|
6264
7189
|
return column2;
|
|
6265
7190
|
});
|
|
7191
|
+
if (((_a = this.xbrlInput) == null ? void 0 : _a.datatypes) && !section2.datatypes) {
|
|
7192
|
+
const datatypesArray = Array.isArray(this.xbrlInput.datatypes) ? this.xbrlInput.datatypes : this.xbrlInput.datatypes.concepts || [];
|
|
7193
|
+
section2.datatypes = datatypesArray;
|
|
7194
|
+
console.log(`✅ [Draft Restore] Attached ${datatypesArray.length} datatypes to section ${section2.id}`);
|
|
7195
|
+
} else if (section2.datatypes) {
|
|
7196
|
+
console.log(`ℹ️ [Draft Restore] Section ${section2.id} already has ${section2.datatypes.length} datatypes`);
|
|
7197
|
+
} else {
|
|
7198
|
+
console.warn(`⚠️ [Draft Restore] No datatypes available for section ${section2.id}`);
|
|
7199
|
+
}
|
|
6266
7200
|
this._regenerateFieldsForSection(section2);
|
|
6267
7201
|
console.log(` └─ Restored ${savedColumns.length} columns for section ${section2.id}`);
|
|
6268
7202
|
}
|
|
@@ -6291,11 +7225,21 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
6291
7225
|
}
|
|
6292
7226
|
});
|
|
6293
7227
|
this._allSections.forEach((section2) => {
|
|
7228
|
+
var _a;
|
|
6294
7229
|
const customColumnsForSection = columnsBySection.get(section2.id);
|
|
6295
7230
|
if (customColumnsForSection && customColumnsForSection.length > 0) {
|
|
6296
7231
|
if (!section2.columns) {
|
|
6297
7232
|
section2.columns = [];
|
|
6298
7233
|
}
|
|
7234
|
+
if (((_a = this.xbrlInput) == null ? void 0 : _a.datatypes) && !section2.datatypes) {
|
|
7235
|
+
const datatypesArray = Array.isArray(this.xbrlInput.datatypes) ? this.xbrlInput.datatypes : this.xbrlInput.datatypes.concepts || [];
|
|
7236
|
+
section2.datatypes = datatypesArray;
|
|
7237
|
+
console.log(`✅ [Merge Custom] Attached ${datatypesArray.length} datatypes to section ${section2.id}`);
|
|
7238
|
+
} else if (section2.datatypes) {
|
|
7239
|
+
console.log(`ℹ️ [Merge Custom] Section ${section2.id} already has ${section2.datatypes.length} datatypes`);
|
|
7240
|
+
} else {
|
|
7241
|
+
console.warn(`⚠️ [Merge Custom] No datatypes available for section ${section2.id}`);
|
|
7242
|
+
}
|
|
6299
7243
|
customColumnsForSection.forEach((col) => {
|
|
6300
7244
|
console.log(`📅 [Merge Custom Column] Column ${col.columnId}: col.startDate=${col.startDate}, col.endDate=${col.endDate}, col.date=${col.date}, col.periodType=${col.periodType}`);
|
|
6301
7245
|
const existingColumn = section2.columns.find((c2) => c2.id === col.columnId);
|
|
@@ -6308,9 +7252,11 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
6308
7252
|
periodEndDate: col.endDate || col.date,
|
|
6309
7253
|
dimensionData: col.dimensionData,
|
|
6310
7254
|
order: section2.columns.length,
|
|
6311
|
-
removable: true
|
|
7255
|
+
removable: true,
|
|
7256
|
+
periodType: col.periodType
|
|
7257
|
+
// CRITICAL: Preserve explicit period type
|
|
6312
7258
|
};
|
|
6313
|
-
console.log(`📅 [New Column Created] Column ${newColumn.id}: periodStartDate=${newColumn.periodStartDate}, periodEndDate=${newColumn.periodEndDate}`);
|
|
7259
|
+
console.log(`📅 [New Column Created] Column ${newColumn.id}: periodStartDate=${newColumn.periodStartDate}, periodEndDate=${newColumn.periodEndDate}, periodType=${newColumn.periodType}`);
|
|
6314
7260
|
section2.columns.push(newColumn);
|
|
6315
7261
|
console.log(` └─ Added custom column ${col.columnId} to section ${section2.id}`);
|
|
6316
7262
|
}
|
|
@@ -6340,20 +7286,20 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
6340
7286
|
if (this._periodData[concept.id]) {
|
|
6341
7287
|
const conceptPeriodData = this._periodData[concept.id];
|
|
6342
7288
|
if (concept.fields) {
|
|
6343
|
-
concept.fields.forEach((
|
|
6344
|
-
const customPeriod = conceptPeriodData[
|
|
7289
|
+
concept.fields.forEach((field2) => {
|
|
7290
|
+
const customPeriod = conceptPeriodData[field2.columnId];
|
|
6345
7291
|
if (customPeriod) {
|
|
6346
7292
|
if (customPeriod.startDate) {
|
|
6347
|
-
|
|
7293
|
+
field2.periodStartDate = customPeriod.startDate;
|
|
6348
7294
|
}
|
|
6349
7295
|
if (customPeriod.endDate) {
|
|
6350
|
-
|
|
7296
|
+
field2.periodEndDate = customPeriod.endDate;
|
|
6351
7297
|
}
|
|
6352
7298
|
if (customPeriod.instantDate) {
|
|
6353
|
-
|
|
7299
|
+
field2.periodInstantDate = customPeriod.instantDate;
|
|
6354
7300
|
}
|
|
6355
7301
|
appliedCount++;
|
|
6356
|
-
console.log(`✅ [Apply Period] Updated field ${concept.id}/${
|
|
7302
|
+
console.log(`✅ [Apply Period] Updated field ${concept.id}/${field2.columnId}: start=${field2.periodStartDate}, end=${field2.periodEndDate}, instant=${field2.periodInstantDate}`);
|
|
6357
7303
|
}
|
|
6358
7304
|
});
|
|
6359
7305
|
}
|
|
@@ -6392,7 +7338,10 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
6392
7338
|
const columnPeriodType = this._inferColumnPeriodType(column2);
|
|
6393
7339
|
if (concept.abstract)
|
|
6394
7340
|
return;
|
|
6395
|
-
const
|
|
7341
|
+
const isCustomColumn = column2.id.startsWith("col-");
|
|
7342
|
+
const isDimensionColumn = column2.id.startsWith("duration_") || column2.id.startsWith("instant_");
|
|
7343
|
+
const isMixedSection = section2.showPeriodControl === true;
|
|
7344
|
+
const shouldSkipPeriodCheck = !columnPeriodType || column2.id === "duration" || column2.id === "default" || isCustomColumn && isMixedSection || isDimensionColumn;
|
|
6396
7345
|
if (!shouldSkipPeriodCheck && conceptPeriodType && columnPeriodType) {
|
|
6397
7346
|
if (conceptPeriodType !== columnPeriodType) {
|
|
6398
7347
|
console.log(`⏭️ [Field Regeneration] Skipping field for ${concept.id} in column ${column2.id}: conceptPeriodType=${conceptPeriodType}, columnPeriodType=${columnPeriodType}`);
|
|
@@ -6407,6 +7356,8 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
6407
7356
|
label: concept.label,
|
|
6408
7357
|
periodType: conceptPeriodType,
|
|
6409
7358
|
// Add periodType from concept
|
|
7359
|
+
conceptType: concept.type,
|
|
7360
|
+
// CRITICAL: Include conceptType for XBRL validation
|
|
6410
7361
|
periodStartDate: column2.periodStartDate,
|
|
6411
7362
|
periodEndDate: column2.periodEndDate,
|
|
6412
7363
|
periodInstantDate: conceptPeriodType === "instant" ? column2.periodEndDate || column2.periodStartDate : void 0
|
|
@@ -6456,6 +7407,9 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
6456
7407
|
return true;
|
|
6457
7408
|
}
|
|
6458
7409
|
_inferColumnPeriodType(column2) {
|
|
7410
|
+
if (column2.periodType) {
|
|
7411
|
+
return column2.periodType;
|
|
7412
|
+
}
|
|
6459
7413
|
if (column2.periodStartDate && column2.periodEndDate) {
|
|
6460
7414
|
return column2.periodStartDate === column2.periodEndDate ? "instant" : "duration";
|
|
6461
7415
|
}
|
|
@@ -6533,17 +7487,18 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
6533
7487
|
return null;
|
|
6534
7488
|
}
|
|
6535
7489
|
_addConceptDataToSubmission(concept, columnId, value, submissionData, section2) {
|
|
6536
|
-
var _a, _b;
|
|
6537
|
-
const
|
|
6538
|
-
if (!
|
|
7490
|
+
var _a, _b, _c;
|
|
7491
|
+
const field2 = concept.fields.find((f2) => f2.columnId === columnId);
|
|
7492
|
+
if (!field2)
|
|
6539
7493
|
return;
|
|
6540
7494
|
const isInstant = concept.periodType === "instant";
|
|
6541
7495
|
const fieldPeriodData = (_a = this._periodData[concept.id]) == null ? void 0 : _a[columnId];
|
|
7496
|
+
const fieldUnit = (_b = this._unitData[concept.id]) == null ? void 0 : _b[columnId];
|
|
6542
7497
|
const column2 = this._findColumnByIdInAllSections(columnId);
|
|
6543
|
-
console.log(`🔍 [Submission] Concept: ${concept.id}, Column: ${columnId}, Field Period: ${fieldPeriodData ? JSON.stringify(fieldPeriodData) : "none"}, Column Period: ${(column2 == null ? void 0 : column2.periodStartDate) || "none"} - ${(column2 == null ? void 0 : column2.periodEndDate) || "none"}`);
|
|
6544
|
-
const periodStartDate = (fieldPeriodData == null ? void 0 : fieldPeriodData.startDate) || (column2 == null ? void 0 : column2.periodStartDate) ||
|
|
6545
|
-
const periodEndDate = (fieldPeriodData == null ? void 0 : fieldPeriodData.endDate) || (column2 == null ? void 0 : column2.periodEndDate) ||
|
|
6546
|
-
const periodInstantDate = (fieldPeriodData == null ? void 0 : fieldPeriodData.instantDate) ||
|
|
7498
|
+
console.log(`🔍 [Submission] Concept: ${concept.id}, Column: ${columnId}, Field Period: ${fieldPeriodData ? JSON.stringify(fieldPeriodData) : "none"}, Unit: ${fieldUnit || "none"}, Column Period: ${(column2 == null ? void 0 : column2.periodStartDate) || "none"} - ${(column2 == null ? void 0 : column2.periodEndDate) || "none"}`);
|
|
7499
|
+
const periodStartDate = (fieldPeriodData == null ? void 0 : fieldPeriodData.startDate) || (column2 == null ? void 0 : column2.periodStartDate) || field2.periodStartDate || this.periodStartDate;
|
|
7500
|
+
const periodEndDate = (fieldPeriodData == null ? void 0 : fieldPeriodData.endDate) || (column2 == null ? void 0 : column2.periodEndDate) || field2.periodEndDate || this.periodEndDate;
|
|
7501
|
+
const periodInstantDate = (fieldPeriodData == null ? void 0 : fieldPeriodData.instantDate) || field2.periodInstantDate || periodEndDate || periodStartDate;
|
|
6547
7502
|
const entry = {
|
|
6548
7503
|
conceptId: concept.originalConceptId || concept.id,
|
|
6549
7504
|
columnId,
|
|
@@ -6556,9 +7511,14 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
6556
7511
|
}
|
|
6557
7512
|
}
|
|
6558
7513
|
};
|
|
6559
|
-
if (
|
|
7514
|
+
if (fieldUnit) {
|
|
7515
|
+
entry.unit = fieldUnit;
|
|
7516
|
+
console.log(`✅ [Submission] Adding unit to entry: ${fieldUnit} for ${concept.id}/${columnId}`);
|
|
7517
|
+
}
|
|
7518
|
+
if ((_c = column2 == null ? void 0 : column2.dimensionData) == null ? void 0 : _c.memberLabel) {
|
|
6560
7519
|
entry.dimension = column2.dimensionData.memberLabel;
|
|
6561
7520
|
}
|
|
7521
|
+
console.log(`📤 [Submission Entry] Created entry:`, JSON.stringify(entry, null, 2));
|
|
6562
7522
|
submissionData.push(entry);
|
|
6563
7523
|
}
|
|
6564
7524
|
_findColumnByIdInAllSections(columnId) {
|
|
@@ -6681,27 +7641,27 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
6681
7641
|
console.warn(`[DUPLICATE DEBUG] Processing concept ${concept.originalConceptId || concept.id} in target role`);
|
|
6682
7642
|
if (concept.fields) {
|
|
6683
7643
|
console.warn(`[DUPLICATE DEBUG] Concept has ${concept.fields.length} fields`);
|
|
6684
|
-
concept.fields.forEach((
|
|
7644
|
+
concept.fields.forEach((field2, index) => {
|
|
6685
7645
|
var _a;
|
|
6686
|
-
console.warn(`[DUPLICATE DEBUG] Field ${index}: columnId=${
|
|
7646
|
+
console.warn(`[DUPLICATE DEBUG] Field ${index}: columnId=${field2.columnId}, current value=${(_a = this._formData[concept.id]) == null ? void 0 : _a[field2.columnId]}`);
|
|
6687
7647
|
});
|
|
6688
7648
|
}
|
|
6689
7649
|
}
|
|
6690
7650
|
if (concept.fields && concept.fields.length > 1) {
|
|
6691
|
-
concept.fields.forEach((
|
|
7651
|
+
concept.fields.forEach((field2, index) => {
|
|
6692
7652
|
});
|
|
6693
7653
|
}
|
|
6694
7654
|
if (concept.fields && concept.fields.length > 0) {
|
|
6695
|
-
concept.fields.forEach((
|
|
6696
|
-
var _a, _b, _c;
|
|
7655
|
+
concept.fields.forEach((field2) => {
|
|
7656
|
+
var _a, _b, _c, _d;
|
|
6697
7657
|
const conceptData = this._formData[concept.id];
|
|
6698
|
-
const fieldValue = conceptData == null ? void 0 : conceptData[
|
|
7658
|
+
const fieldValue = conceptData == null ? void 0 : conceptData[field2.columnId];
|
|
6699
7659
|
if (fieldValue !== void 0 && fieldValue !== null && fieldValue !== "") {
|
|
6700
|
-
const column2 = this._findColumnByIdInSection(
|
|
6701
|
-
const fieldPeriodData = (_a = this._periodData[concept.id]) == null ? void 0 : _a[
|
|
7660
|
+
const column2 = this._findColumnByIdInSection(field2.columnId, section2);
|
|
7661
|
+
const fieldPeriodData = (_a = this._periodData[concept.id]) == null ? void 0 : _a[field2.columnId];
|
|
6702
7662
|
const submissionEntry = {
|
|
6703
7663
|
conceptId: concept.id,
|
|
6704
|
-
columnId:
|
|
7664
|
+
columnId: field2.columnId,
|
|
6705
7665
|
// CRITICAL: Include columnId for draft restoration
|
|
6706
7666
|
value: fieldValue,
|
|
6707
7667
|
period: {
|
|
@@ -6709,27 +7669,34 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
6709
7669
|
}
|
|
6710
7670
|
};
|
|
6711
7671
|
if (concept.periodType === "instant") {
|
|
6712
|
-
const instantDate = (fieldPeriodData == null ? void 0 : fieldPeriodData.instantDate) || (fieldPeriodData == null ? void 0 : fieldPeriodData.endDate) || (column2 == null ? void 0 : column2.periodEndDate) ||
|
|
7672
|
+
const instantDate = (fieldPeriodData == null ? void 0 : fieldPeriodData.instantDate) || (fieldPeriodData == null ? void 0 : fieldPeriodData.endDate) || (column2 == null ? void 0 : column2.periodEndDate) || field2.periodInstantDate || field2.periodEndDate || field2.periodStartDate || this.periodStartDate;
|
|
6713
7673
|
submissionEntry.period.date = instantDate;
|
|
6714
7674
|
} else {
|
|
6715
|
-
const startDate = (fieldPeriodData == null ? void 0 : fieldPeriodData.startDate) || (column2 == null ? void 0 : column2.periodStartDate) ||
|
|
6716
|
-
const endDate = (fieldPeriodData == null ? void 0 : fieldPeriodData.endDate) || (column2 == null ? void 0 : column2.periodEndDate) ||
|
|
7675
|
+
const startDate = (fieldPeriodData == null ? void 0 : fieldPeriodData.startDate) || (column2 == null ? void 0 : column2.periodStartDate) || field2.periodStartDate || this.periodStartDate;
|
|
7676
|
+
const endDate = (fieldPeriodData == null ? void 0 : fieldPeriodData.endDate) || (column2 == null ? void 0 : column2.periodEndDate) || field2.periodEndDate || this.periodEndDate;
|
|
6717
7677
|
submissionEntry.period.startDate = startDate;
|
|
6718
7678
|
submissionEntry.period.endDate = endDate;
|
|
6719
7679
|
}
|
|
6720
|
-
console.log(`🔍 [Submission] Concept: ${concept.id}, Column: ${
|
|
6721
|
-
|
|
7680
|
+
console.log(`🔍 [Submission] Concept: ${concept.id}, Column: ${field2.columnId}, Field Period: ${fieldPeriodData ? JSON.stringify(fieldPeriodData) : "none"}, Column Period: ${(column2 == null ? void 0 : column2.periodStartDate) || "none"} - ${(column2 == null ? void 0 : column2.periodEndDate) || "none"}, Used Period: ${submissionEntry.period.type === "instant" ? submissionEntry.period.date : `${submissionEntry.period.startDate} - ${submissionEntry.period.endDate}`}`);
|
|
7681
|
+
const fieldUnit = (_b = this._unitData[concept.id]) == null ? void 0 : _b[field2.columnId];
|
|
7682
|
+
if (fieldUnit) {
|
|
7683
|
+
submissionEntry.unit = fieldUnit;
|
|
7684
|
+
console.log(`✅ [Submission] Adding unit to entry: ${fieldUnit} for ${concept.id}/${field2.columnId}`);
|
|
7685
|
+
} else {
|
|
7686
|
+
console.log(`⚠️ [Submission] No unit found in _unitData for ${concept.id}/${field2.columnId}. _unitData state:`, JSON.stringify(this._unitData, null, 2));
|
|
7687
|
+
}
|
|
7688
|
+
if ((column2 == null ? void 0 : column2.type) === "dimension" && ((_c = column2.dimensionData) == null ? void 0 : _c.dimensionIdKey)) {
|
|
6722
7689
|
submissionEntry.dimension = column2.dimensionData.dimensionIdKey;
|
|
6723
|
-
console.log(`🔍 [DynamicForm] Using dimension key from field's column (${
|
|
7690
|
+
console.log(`🔍 [DynamicForm] Using dimension key from field's column (${field2.columnId}):`, column2.dimensionData.dimensionIdKey);
|
|
6724
7691
|
} else {
|
|
6725
|
-
console.log(`🔍 [DynamicForm] No dimension data found for field column ${
|
|
7692
|
+
console.log(`🔍 [DynamicForm] No dimension data found for field column ${field2.columnId}. Column type: ${column2 == null ? void 0 : column2.type}, has dimensionData: ${!!(column2 == null ? void 0 : column2.dimensionData)}`);
|
|
6726
7693
|
}
|
|
6727
|
-
if (this._typedMemberData[
|
|
7694
|
+
if (this._typedMemberData[field2.columnId]) {
|
|
6728
7695
|
const applicableTypedDimensions = this._getApplicableTypedDimensions(concept, section2);
|
|
6729
7696
|
console.log(`🔍 [DynamicForm] Concept ${concept.id} applicable typed dimensions:`, applicableTypedDimensions);
|
|
6730
7697
|
if (applicableTypedDimensions.length > 0) {
|
|
6731
7698
|
const filteredTypedMembers = {};
|
|
6732
|
-
const allTypedMemberData = this._typedMemberData[
|
|
7699
|
+
const allTypedMemberData = this._typedMemberData[field2.columnId];
|
|
6733
7700
|
applicableTypedDimensions.forEach((dimensionId) => {
|
|
6734
7701
|
if (allTypedMemberData[dimensionId]) {
|
|
6735
7702
|
const memberName = this._getTypedMemberNameForAxis(dimensionId, section2);
|
|
@@ -6749,12 +7716,12 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
6749
7716
|
console.log(`🔍 [DynamicForm] Skipping typed members for concept ${concept.id} - not applicable to this hypercube`);
|
|
6750
7717
|
}
|
|
6751
7718
|
} else {
|
|
6752
|
-
console.log(`🔍 [DynamicForm] No typed member data found for column ${
|
|
7719
|
+
console.log(`🔍 [DynamicForm] No typed member data found for column ${field2.columnId}. Available columns:`, Object.keys(this._typedMemberData));
|
|
6753
7720
|
if (column2) {
|
|
6754
7721
|
console.log(`🔍 [DynamicForm] Column details:`, {
|
|
6755
7722
|
id: column2.id,
|
|
6756
7723
|
type: column2.type,
|
|
6757
|
-
hasTypedMembers: (
|
|
7724
|
+
hasTypedMembers: (_d = column2.dimensionData) == null ? void 0 : _d.hasTypedMembers,
|
|
6758
7725
|
dimensionData: column2.dimensionData
|
|
6759
7726
|
});
|
|
6760
7727
|
}
|
|
@@ -6887,13 +7854,13 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
6887
7854
|
</div>
|
|
6888
7855
|
`;
|
|
6889
7856
|
}
|
|
6890
|
-
_handleAdminCheckboxChange(roleId,
|
|
7857
|
+
_handleAdminCheckboxChange(roleId, field2, checked) {
|
|
6891
7858
|
const currentConfig = this._adminRoleConfigs[roleId] || { showPreviousYear: false };
|
|
6892
7859
|
this._adminRoleConfigs = {
|
|
6893
7860
|
...this._adminRoleConfigs,
|
|
6894
7861
|
[roleId]: {
|
|
6895
7862
|
...currentConfig,
|
|
6896
|
-
[
|
|
7863
|
+
[field2]: checked
|
|
6897
7864
|
}
|
|
6898
7865
|
};
|
|
6899
7866
|
}
|
|
@@ -6943,8 +7910,8 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
6943
7910
|
<div class="validation-summary">
|
|
6944
7911
|
<h4 class="validation-summary-title">${I18n.t("validation.summary")}</h4>
|
|
6945
7912
|
<ul class="validation-summary-list">
|
|
6946
|
-
${this._errors.filter((e2) => e2.severity === "error").map((
|
|
6947
|
-
<li class="validation-summary-item">${
|
|
7913
|
+
${this._errors.filter((e2) => e2.severity === "error").map((error2) => html`
|
|
7914
|
+
<li class="validation-summary-item">${error2.message}</li>
|
|
6948
7915
|
`)}
|
|
6949
7916
|
</ul>
|
|
6950
7917
|
</div>
|
|
@@ -6961,12 +7928,19 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
6961
7928
|
<p>${I18n.t("filter.selectRoles")}</p>
|
|
6962
7929
|
<p>${I18n.t("filter.roles")}: ${this._allSections.length}</p>
|
|
6963
7930
|
</div>
|
|
6964
|
-
` : schema.sections.map((section2, index) =>
|
|
7931
|
+
` : schema.sections.map((section2, index) => {
|
|
7932
|
+
var _a;
|
|
7933
|
+
return html`
|
|
6965
7934
|
<jupiter-form-section
|
|
7935
|
+
section-id="${section2.id}"
|
|
6966
7936
|
.section="${section2}"
|
|
6967
7937
|
.columns="${section2.columns || this._columns}"
|
|
7938
|
+
.datatypes="${section2.datatypes || ((_a = this.xbrlInput) == null ? void 0 : _a.datatypes)}"
|
|
6968
7939
|
.formData="${this._formData}"
|
|
7940
|
+
.periodData="${this._periodData}"
|
|
7941
|
+
.unitData="${this._unitData}"
|
|
6969
7942
|
.typedMemberData="${this._typedMemberData}"
|
|
7943
|
+
.defaultUnits="${this.defaultUnits}"
|
|
6970
7944
|
.disabled="${this.disabled || this.readonly}"
|
|
6971
7945
|
.collapsible="${config.collapsibleSections !== false}"
|
|
6972
7946
|
.locale="${config.locale || "en-US"}"
|
|
@@ -6980,11 +7954,13 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
6980
7954
|
@column-remove="${this._handleColumnRemove}"
|
|
6981
7955
|
@column-add-request="${this._handleColumnAddRequest}"
|
|
6982
7956
|
></jupiter-form-section>
|
|
6983
|
-
|
|
7957
|
+
`;
|
|
7958
|
+
})}
|
|
6984
7959
|
</div>
|
|
6985
7960
|
`;
|
|
6986
7961
|
}
|
|
6987
7962
|
_renderSidePanelLayout(schema, config, showValidationSummary, errorCount) {
|
|
7963
|
+
var _a;
|
|
6988
7964
|
const visibleSections = schema.sections;
|
|
6989
7965
|
const filteredSections = this._filterSidePanelSections(visibleSections);
|
|
6990
7966
|
if (!this._activeSidePanelRoleId || !filteredSections.find((s2) => s2.id === this._activeSidePanelRoleId)) {
|
|
@@ -7061,8 +8037,8 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
7061
8037
|
<div class="validation-summary">
|
|
7062
8038
|
<h4 class="validation-summary-title">Please fix the following errors:</h4>
|
|
7063
8039
|
<ul class="validation-summary-list">
|
|
7064
|
-
${this._errors.filter((e2) => e2.severity === "error").map((
|
|
7065
|
-
<li class="validation-summary-item">${
|
|
8040
|
+
${this._errors.filter((e2) => e2.severity === "error").map((error2) => html`
|
|
8041
|
+
<li class="validation-summary-item">${error2.message}</li>
|
|
7066
8042
|
`)}
|
|
7067
8043
|
</ul>
|
|
7068
8044
|
</div>
|
|
@@ -7075,10 +8051,15 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
7075
8051
|
</div>
|
|
7076
8052
|
` : activeSection ? html`
|
|
7077
8053
|
<jupiter-form-section
|
|
8054
|
+
section-id="${activeSection.id}"
|
|
7078
8055
|
.section="${activeSection}"
|
|
7079
8056
|
.columns="${activeSection.columns || this._columns}"
|
|
8057
|
+
.datatypes="${activeSection.datatypes || ((_a = this.xbrlInput) == null ? void 0 : _a.datatypes)}"
|
|
7080
8058
|
.formData="${this._formData}"
|
|
8059
|
+
.periodData="${this._periodData}"
|
|
8060
|
+
.unitData="${this._unitData}"
|
|
7081
8061
|
.typedMemberData="${this._typedMemberData}"
|
|
8062
|
+
.defaultUnits="${this.defaultUnits}"
|
|
7082
8063
|
.disabled="${this.disabled || this.readonly}"
|
|
7083
8064
|
.collapsible="${false}"
|
|
7084
8065
|
.hideHeader="${true}"
|
|
@@ -7198,6 +8179,53 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
7198
8179
|
@click="${this._handleFilterDialogCancel}"
|
|
7199
8180
|
></jupiter-filter-roles-dialog>
|
|
7200
8181
|
` : ""}
|
|
8182
|
+
|
|
8183
|
+
<!-- Validation Error Popup -->
|
|
8184
|
+
${this._showErrorPopup ? html`
|
|
8185
|
+
<div class="error-popup-overlay" @click="${() => {
|
|
8186
|
+
this._showErrorPopup = false;
|
|
8187
|
+
this.requestUpdate();
|
|
8188
|
+
}}">
|
|
8189
|
+
<div class="error-popup" @click="${(e2) => e2.stopPropagation()}">
|
|
8190
|
+
<div class="error-popup-header">
|
|
8191
|
+
<h3>⚠️ ${I18n.t("error.popup.title")}</h3>
|
|
8192
|
+
<button class="error-popup-close" @click="${() => {
|
|
8193
|
+
this._showErrorPopup = false;
|
|
8194
|
+
this.requestUpdate();
|
|
8195
|
+
}}">×</button>
|
|
8196
|
+
</div>
|
|
8197
|
+
<div class="error-popup-content">
|
|
8198
|
+
<p>${I18n.t("error.popup.message")}</p>
|
|
8199
|
+
<ul class="error-list">
|
|
8200
|
+
${this._xbrlFormErrors.map((error2) => html`
|
|
8201
|
+
<li>
|
|
8202
|
+
<strong>${I18n.t("error.popup.field")}</strong>
|
|
8203
|
+
<a
|
|
8204
|
+
href="javascript:void(0)"
|
|
8205
|
+
class="error-field-link"
|
|
8206
|
+
@click="${() => this._handleErrorFieldClick(error2.conceptId, error2.columnId, error2.sectionId)}"
|
|
8207
|
+
title="${I18n.t("error.popup.clickToFocus")}"
|
|
8208
|
+
>
|
|
8209
|
+
${error2.conceptId}__${error2.columnId}
|
|
8210
|
+
</a><br>
|
|
8211
|
+
<strong>${I18n.t("error.popup.value")}</strong> ${error2.value}<br>
|
|
8212
|
+
<strong>${I18n.t("error.popup.errors")}</strong>
|
|
8213
|
+
<ul>
|
|
8214
|
+
${error2.errors.map((err) => html`<li>${err.message}</li>`)}
|
|
8215
|
+
</ul>
|
|
8216
|
+
</li>
|
|
8217
|
+
`)}
|
|
8218
|
+
</ul>
|
|
8219
|
+
</div>
|
|
8220
|
+
<div class="error-popup-footer">
|
|
8221
|
+
<button class="btn-primary" @click="${() => {
|
|
8222
|
+
this._showErrorPopup = false;
|
|
8223
|
+
this.requestUpdate();
|
|
8224
|
+
}}">${I18n.t("error.popup.ok")}</button>
|
|
8225
|
+
</div>
|
|
8226
|
+
</div>
|
|
8227
|
+
</div>
|
|
8228
|
+
` : ""}
|
|
7201
8229
|
</div>
|
|
7202
8230
|
`;
|
|
7203
8231
|
}
|
|
@@ -7631,6 +8659,128 @@ JupiterDynamicForm.styles = css`
|
|
|
7631
8659
|
cursor: pointer;
|
|
7632
8660
|
user-select: none;
|
|
7633
8661
|
}
|
|
8662
|
+
|
|
8663
|
+
/* Error Popup Styles */
|
|
8664
|
+
.error-popup-overlay {
|
|
8665
|
+
position: fixed;
|
|
8666
|
+
top: 0;
|
|
8667
|
+
left: 0;
|
|
8668
|
+
right: 0;
|
|
8669
|
+
bottom: 0;
|
|
8670
|
+
background: rgba(0, 0, 0, 0.5);
|
|
8671
|
+
display: flex;
|
|
8672
|
+
align-items: center;
|
|
8673
|
+
justify-content: center;
|
|
8674
|
+
z-index: 10000;
|
|
8675
|
+
}
|
|
8676
|
+
|
|
8677
|
+
.error-popup {
|
|
8678
|
+
background: white;
|
|
8679
|
+
border-radius: 8px;
|
|
8680
|
+
max-width: 600px;
|
|
8681
|
+
width: 90%;
|
|
8682
|
+
max-height: 80vh;
|
|
8683
|
+
overflow: hidden;
|
|
8684
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
|
|
8685
|
+
display: flex;
|
|
8686
|
+
flex-direction: column;
|
|
8687
|
+
}
|
|
8688
|
+
|
|
8689
|
+
.error-popup-header {
|
|
8690
|
+
display: flex;
|
|
8691
|
+
justify-content: space-between;
|
|
8692
|
+
align-items: center;
|
|
8693
|
+
padding: 20px 24px;
|
|
8694
|
+
border-bottom: 1px solid var(--jupiter-border-color, #ddd);
|
|
8695
|
+
background: var(--jupiter-section-header-background, #f0f2f5);
|
|
8696
|
+
}
|
|
8697
|
+
|
|
8698
|
+
.error-popup-header h3 {
|
|
8699
|
+
margin: 0;
|
|
8700
|
+
font-size: 18px;
|
|
8701
|
+
font-weight: 600;
|
|
8702
|
+
color: var(--jupiter-error-color, #d32f2f);
|
|
8703
|
+
}
|
|
8704
|
+
|
|
8705
|
+
.error-popup-close {
|
|
8706
|
+
background: transparent;
|
|
8707
|
+
border: none;
|
|
8708
|
+
font-size: 28px;
|
|
8709
|
+
cursor: pointer;
|
|
8710
|
+
padding: 0;
|
|
8711
|
+
width: 32px;
|
|
8712
|
+
height: 32px;
|
|
8713
|
+
display: flex;
|
|
8714
|
+
align-items: center;
|
|
8715
|
+
justify-content: center;
|
|
8716
|
+
border-radius: 4px;
|
|
8717
|
+
color: var(--jupiter-text-color, #333);
|
|
8718
|
+
transition: background-color 0.2s;
|
|
8719
|
+
}
|
|
8720
|
+
|
|
8721
|
+
.error-popup-close:hover {
|
|
8722
|
+
background-color: rgba(0, 0, 0, 0.05);
|
|
8723
|
+
}
|
|
8724
|
+
|
|
8725
|
+
.error-popup-content {
|
|
8726
|
+
padding: 24px;
|
|
8727
|
+
overflow-y: auto;
|
|
8728
|
+
flex: 1;
|
|
8729
|
+
}
|
|
8730
|
+
|
|
8731
|
+
.error-popup-content p {
|
|
8732
|
+
margin: 0 0 16px 0;
|
|
8733
|
+
color: var(--jupiter-text-primary, #333);
|
|
8734
|
+
}
|
|
8735
|
+
|
|
8736
|
+
.error-list {
|
|
8737
|
+
list-style: none;
|
|
8738
|
+
padding: 0;
|
|
8739
|
+
margin: 0;
|
|
8740
|
+
}
|
|
8741
|
+
|
|
8742
|
+
.error-list > li {
|
|
8743
|
+
padding: 12px;
|
|
8744
|
+
background: #f8f9fa;
|
|
8745
|
+
border: 1px solid #dee2e6;
|
|
8746
|
+
border-radius: 4px;
|
|
8747
|
+
margin-bottom: 12px;
|
|
8748
|
+
}
|
|
8749
|
+
|
|
8750
|
+
.error-list > li strong {
|
|
8751
|
+
color: var(--jupiter-text-primary, #333);
|
|
8752
|
+
font-weight: 600;
|
|
8753
|
+
}
|
|
8754
|
+
|
|
8755
|
+
.error-list ul {
|
|
8756
|
+
margin: 8px 0 0 0;
|
|
8757
|
+
padding-left: 20px;
|
|
8758
|
+
}
|
|
8759
|
+
|
|
8760
|
+
.error-list ul li {
|
|
8761
|
+
color: var(--jupiter-error-color, #d32f2f);
|
|
8762
|
+
margin: 4px 0;
|
|
8763
|
+
}
|
|
8764
|
+
|
|
8765
|
+
.error-popup-footer {
|
|
8766
|
+
padding: 16px 24px;
|
|
8767
|
+
border-top: 1px solid var(--jupiter-border-color, #ddd);
|
|
8768
|
+
display: flex;
|
|
8769
|
+
justify-content: flex-end;
|
|
8770
|
+
gap: 12px;
|
|
8771
|
+
}
|
|
8772
|
+
|
|
8773
|
+
.error-field-link {
|
|
8774
|
+
color: #0066cc;
|
|
8775
|
+
text-decoration: underline;
|
|
8776
|
+
cursor: pointer;
|
|
8777
|
+
font-family: monospace;
|
|
8778
|
+
}
|
|
8779
|
+
|
|
8780
|
+
.error-field-link:hover {
|
|
8781
|
+
color: #0052a3;
|
|
8782
|
+
text-decoration: none;
|
|
8783
|
+
}
|
|
7634
8784
|
`;
|
|
7635
8785
|
__decorateClass([
|
|
7636
8786
|
n2({ type: Object })
|
|
@@ -7668,6 +8818,9 @@ __decorateClass([
|
|
|
7668
8818
|
__decorateClass([
|
|
7669
8819
|
n2({ type: Array })
|
|
7670
8820
|
], JupiterDynamicForm.prototype, "financialStatementsTypeAxis", 2);
|
|
8821
|
+
__decorateClass([
|
|
8822
|
+
n2({ type: Array })
|
|
8823
|
+
], JupiterDynamicForm.prototype, "defaultUnits", 2);
|
|
7671
8824
|
__decorateClass([
|
|
7672
8825
|
n2({ type: Object, attribute: "dynaforms-metadata" })
|
|
7673
8826
|
], JupiterDynamicForm.prototype, "dynaformsMetadata", 2);
|
|
@@ -7692,6 +8845,12 @@ __decorateClass([
|
|
|
7692
8845
|
__decorateClass([
|
|
7693
8846
|
r()
|
|
7694
8847
|
], JupiterDynamicForm.prototype, "_preservedPeriodData", 2);
|
|
8848
|
+
__decorateClass([
|
|
8849
|
+
r()
|
|
8850
|
+
], JupiterDynamicForm.prototype, "_unitData", 2);
|
|
8851
|
+
__decorateClass([
|
|
8852
|
+
r()
|
|
8853
|
+
], JupiterDynamicForm.prototype, "_preservedUnitData", 2);
|
|
7695
8854
|
__decorateClass([
|
|
7696
8855
|
r()
|
|
7697
8856
|
], JupiterDynamicForm.prototype, "_typedMemberData", 2);
|
|
@@ -7716,6 +8875,12 @@ __decorateClass([
|
|
|
7716
8875
|
__decorateClass([
|
|
7717
8876
|
r()
|
|
7718
8877
|
], JupiterDynamicForm.prototype, "_submitted", 2);
|
|
8878
|
+
__decorateClass([
|
|
8879
|
+
r()
|
|
8880
|
+
], JupiterDynamicForm.prototype, "_xbrlFormErrors", 2);
|
|
8881
|
+
__decorateClass([
|
|
8882
|
+
r()
|
|
8883
|
+
], JupiterDynamicForm.prototype, "_showErrorPopup", 2);
|
|
7719
8884
|
__decorateClass([
|
|
7720
8885
|
r()
|
|
7721
8886
|
], JupiterDynamicForm.prototype, "_currentSchema", 2);
|
|
@@ -7756,11 +8921,15 @@ export {
|
|
|
7756
8921
|
JupiterFormField,
|
|
7757
8922
|
JupiterFormSection,
|
|
7758
8923
|
TYPE_INPUT_MAP,
|
|
8924
|
+
XBRLValidator,
|
|
8925
|
+
collectEnumerationsFromChain,
|
|
8926
|
+
determineInputTypeFromBaseChain,
|
|
7759
8927
|
getInputTypeForConceptType,
|
|
7760
8928
|
isCheckboxType,
|
|
7761
8929
|
isNumericType,
|
|
7762
8930
|
isSelectType,
|
|
7763
8931
|
isTextareaType,
|
|
8932
|
+
resolveBaseTypeChain,
|
|
7764
8933
|
version
|
|
7765
8934
|
};
|
|
7766
8935
|
//# sourceMappingURL=index.mjs.map
|