jupiter-dynamic-forms 1.10.1 â 1.12.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/README.md +57 -9
- package/dist/core/DynamicFormRefactored.d.ts +18 -0
- package/dist/core/DynamicFormRefactored.d.ts.map +1 -1
- package/dist/core/dynamic-form.d.ts +27 -1
- package/dist/core/dynamic-form.d.ts.map +1 -1
- package/dist/index.js +101 -101
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +675 -18
- package/dist/index.mjs.map +1 -1
- package/dist/schema/types.d.ts +1 -0
- package/dist/schema/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1791,6 +1791,194 @@ class I18n {
|
|
|
1791
1791
|
}
|
|
1792
1792
|
}
|
|
1793
1793
|
I18n.currentLanguage = "en";
|
|
1794
|
+
class DraftStorageService {
|
|
1795
|
+
constructor(useSessionStorage = false) {
|
|
1796
|
+
this.DRAFT_DATA_KEY = "jupiter-form-draft-data";
|
|
1797
|
+
this.DRAFT_METADATA_KEY = "jupiter-form-draft-metadata";
|
|
1798
|
+
this.STORAGE_VERSION = "1.0";
|
|
1799
|
+
this._storage = useSessionStorage ? sessionStorage : localStorage;
|
|
1800
|
+
console.log(`đž DraftStorageService initialized (using ${useSessionStorage ? "sessionStorage" : "localStorage"})`);
|
|
1801
|
+
}
|
|
1802
|
+
// ===========================================
|
|
1803
|
+
// Public API Methods
|
|
1804
|
+
// ===========================================
|
|
1805
|
+
/**
|
|
1806
|
+
* Save complete draft including data and metadata
|
|
1807
|
+
*/
|
|
1808
|
+
saveDraft(submissionData, metadata) {
|
|
1809
|
+
try {
|
|
1810
|
+
const draft = {
|
|
1811
|
+
formData: submissionData,
|
|
1812
|
+
metadata: {
|
|
1813
|
+
...metadata,
|
|
1814
|
+
savedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1815
|
+
},
|
|
1816
|
+
version: this.STORAGE_VERSION
|
|
1817
|
+
};
|
|
1818
|
+
this._storage.setItem(this.DRAFT_DATA_KEY, JSON.stringify(draft.formData));
|
|
1819
|
+
this._storage.setItem(this.DRAFT_METADATA_KEY, JSON.stringify(draft.metadata));
|
|
1820
|
+
console.log("â
Draft saved successfully", {
|
|
1821
|
+
entries: submissionData.length,
|
|
1822
|
+
timestamp: draft.metadata.savedAt,
|
|
1823
|
+
roles: metadata.selectedRoleIds.length,
|
|
1824
|
+
customColumns: metadata.customColumns.length
|
|
1825
|
+
});
|
|
1826
|
+
return true;
|
|
1827
|
+
} catch (error) {
|
|
1828
|
+
console.error("â Failed to save draft:", error);
|
|
1829
|
+
return false;
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1832
|
+
/**
|
|
1833
|
+
* Load saved draft
|
|
1834
|
+
*/
|
|
1835
|
+
loadDraft() {
|
|
1836
|
+
try {
|
|
1837
|
+
const dataStr = this._storage.getItem(this.DRAFT_DATA_KEY);
|
|
1838
|
+
const metadataStr = this._storage.getItem(this.DRAFT_METADATA_KEY);
|
|
1839
|
+
if (!dataStr || !metadataStr) {
|
|
1840
|
+
console.log("âšī¸ No saved draft found");
|
|
1841
|
+
return null;
|
|
1842
|
+
}
|
|
1843
|
+
const formData = JSON.parse(dataStr);
|
|
1844
|
+
const metadata = JSON.parse(metadataStr);
|
|
1845
|
+
console.log("â
Draft loaded successfully", {
|
|
1846
|
+
entries: formData.length,
|
|
1847
|
+
savedAt: metadata.savedAt,
|
|
1848
|
+
roles: metadata.selectedRoleIds.length,
|
|
1849
|
+
customColumns: metadata.customColumns.length
|
|
1850
|
+
});
|
|
1851
|
+
return {
|
|
1852
|
+
formData,
|
|
1853
|
+
metadata,
|
|
1854
|
+
version: this.STORAGE_VERSION
|
|
1855
|
+
};
|
|
1856
|
+
} catch (error) {
|
|
1857
|
+
console.error("â Failed to load draft:", error);
|
|
1858
|
+
return null;
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
/**
|
|
1862
|
+
* Check if a draft exists
|
|
1863
|
+
*/
|
|
1864
|
+
hasDraft() {
|
|
1865
|
+
return this._storage.getItem(this.DRAFT_DATA_KEY) !== null && this._storage.getItem(this.DRAFT_METADATA_KEY) !== null;
|
|
1866
|
+
}
|
|
1867
|
+
/**
|
|
1868
|
+
* Get draft metadata only (without full data)
|
|
1869
|
+
*/
|
|
1870
|
+
getDraftMetadata() {
|
|
1871
|
+
try {
|
|
1872
|
+
const metadataStr = this._storage.getItem(this.DRAFT_METADATA_KEY);
|
|
1873
|
+
if (!metadataStr)
|
|
1874
|
+
return null;
|
|
1875
|
+
return JSON.parse(metadataStr);
|
|
1876
|
+
} catch (error) {
|
|
1877
|
+
console.error("â Failed to load draft metadata:", error);
|
|
1878
|
+
return null;
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1881
|
+
/**
|
|
1882
|
+
* Clear saved draft
|
|
1883
|
+
*/
|
|
1884
|
+
clearDraft() {
|
|
1885
|
+
try {
|
|
1886
|
+
this._storage.removeItem(this.DRAFT_DATA_KEY);
|
|
1887
|
+
this._storage.removeItem(this.DRAFT_METADATA_KEY);
|
|
1888
|
+
console.log("đī¸ Draft cleared successfully");
|
|
1889
|
+
return true;
|
|
1890
|
+
} catch (error) {
|
|
1891
|
+
console.error("â Failed to clear draft:", error);
|
|
1892
|
+
return false;
|
|
1893
|
+
}
|
|
1894
|
+
}
|
|
1895
|
+
/**
|
|
1896
|
+
* Get draft age in milliseconds
|
|
1897
|
+
*/
|
|
1898
|
+
getDraftAge() {
|
|
1899
|
+
const metadata = this.getDraftMetadata();
|
|
1900
|
+
if (!metadata)
|
|
1901
|
+
return null;
|
|
1902
|
+
const savedAt = new Date(metadata.savedAt);
|
|
1903
|
+
const now = /* @__PURE__ */ new Date();
|
|
1904
|
+
return now.getTime() - savedAt.getTime();
|
|
1905
|
+
}
|
|
1906
|
+
/**
|
|
1907
|
+
* Check if draft is older than specified time (in milliseconds)
|
|
1908
|
+
*/
|
|
1909
|
+
isDraftStale(maxAge) {
|
|
1910
|
+
const age = this.getDraftAge();
|
|
1911
|
+
return age !== null && age > maxAge;
|
|
1912
|
+
}
|
|
1913
|
+
/**
|
|
1914
|
+
* Extract custom columns from all sections
|
|
1915
|
+
*/
|
|
1916
|
+
extractCustomColumns(allSections) {
|
|
1917
|
+
const customColumns = [];
|
|
1918
|
+
allSections.forEach((section2) => {
|
|
1919
|
+
if (!section2.columns || !Array.isArray(section2.columns)) {
|
|
1920
|
+
return;
|
|
1921
|
+
}
|
|
1922
|
+
section2.columns.forEach((column2) => {
|
|
1923
|
+
customColumns.push({
|
|
1924
|
+
sectionId: section2.id,
|
|
1925
|
+
columnId: column2.id,
|
|
1926
|
+
label: column2.title,
|
|
1927
|
+
// FormColumn uses 'title' not 'label'
|
|
1928
|
+
periodType: this._inferPeriodTypeFromColumn(column2),
|
|
1929
|
+
date: column2.periodStartDate,
|
|
1930
|
+
// Use periodStartDate for instant
|
|
1931
|
+
startDate: column2.periodStartDate,
|
|
1932
|
+
endDate: column2.periodEndDate,
|
|
1933
|
+
dimensionData: column2.dimensionData
|
|
1934
|
+
});
|
|
1935
|
+
});
|
|
1936
|
+
});
|
|
1937
|
+
return customColumns;
|
|
1938
|
+
}
|
|
1939
|
+
/**
|
|
1940
|
+
* Infer period type from column data
|
|
1941
|
+
*/
|
|
1942
|
+
_inferPeriodTypeFromColumn(column2) {
|
|
1943
|
+
if (column2.periodStartDate && column2.periodEndDate) {
|
|
1944
|
+
return "duration";
|
|
1945
|
+
}
|
|
1946
|
+
return "instant";
|
|
1947
|
+
}
|
|
1948
|
+
/**
|
|
1949
|
+
* Create metadata snapshot from current form state
|
|
1950
|
+
*/
|
|
1951
|
+
createMetadataSnapshot(periodStartDate, periodEndDate, language, selectedRoleIds, allSections, typedMemberData, periodPreferences) {
|
|
1952
|
+
return {
|
|
1953
|
+
periodStartDate,
|
|
1954
|
+
periodEndDate,
|
|
1955
|
+
language,
|
|
1956
|
+
selectedRoleIds,
|
|
1957
|
+
customColumns: this.extractCustomColumns(allSections),
|
|
1958
|
+
typedMemberData,
|
|
1959
|
+
periodPreferences,
|
|
1960
|
+
schemaVersion: this.STORAGE_VERSION
|
|
1961
|
+
};
|
|
1962
|
+
}
|
|
1963
|
+
/**
|
|
1964
|
+
* Validate draft compatibility with current schema
|
|
1965
|
+
*/
|
|
1966
|
+
validateDraftCompatibility(draft, currentPeriodStart, currentPeriodEnd) {
|
|
1967
|
+
const warnings = [];
|
|
1968
|
+
if (draft.metadata.periodStartDate !== currentPeriodStart) {
|
|
1969
|
+
warnings.push(`Draft period start (${draft.metadata.periodStartDate}) differs from current (${currentPeriodStart})`);
|
|
1970
|
+
}
|
|
1971
|
+
if (draft.metadata.periodEndDate !== currentPeriodEnd) {
|
|
1972
|
+
warnings.push(`Draft period end (${draft.metadata.periodEndDate}) differs from current (${currentPeriodEnd})`);
|
|
1973
|
+
}
|
|
1974
|
+
const age = this.getDraftAge();
|
|
1975
|
+
if (age && age > 7 * 24 * 60 * 60 * 1e3) {
|
|
1976
|
+
warnings.push(`Draft is ${Math.floor(age / (24 * 60 * 60 * 1e3))} days old`);
|
|
1977
|
+
}
|
|
1978
|
+
const compatible = warnings.length === 0;
|
|
1979
|
+
return { compatible, warnings };
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1794
1982
|
const TYPE_INPUT_MAP = {
|
|
1795
1983
|
// ==========================================
|
|
1796
1984
|
// Dutch XBRL Types (nl-types namespace)
|
|
@@ -3778,7 +3966,7 @@ JupiterFormSection.styles = css`
|
|
|
3778
3966
|
}
|
|
3779
3967
|
|
|
3780
3968
|
.typed-member-header-field {
|
|
3781
|
-
width:
|
|
3969
|
+
width: 96%;
|
|
3782
3970
|
padding: 4px 6px;
|
|
3783
3971
|
border: 1px solid var(--jupiter-border-color, #ddd);
|
|
3784
3972
|
border-radius: 3px;
|
|
@@ -4625,6 +4813,7 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
4625
4813
|
this.mode = "inputForm";
|
|
4626
4814
|
this.financialStatementsTypeAxis = [];
|
|
4627
4815
|
this._formData = {};
|
|
4816
|
+
this._draftLoaded = false;
|
|
4628
4817
|
this._preservedFormData = {};
|
|
4629
4818
|
this._typedMemberData = {};
|
|
4630
4819
|
this._preservedTypedMemberData = {};
|
|
@@ -4640,6 +4829,7 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
4640
4829
|
this._periodPreferences = {};
|
|
4641
4830
|
this._activeSidePanelRoleId = null;
|
|
4642
4831
|
this._adminRoleConfigs = {};
|
|
4832
|
+
this._skipDraftLoading = false;
|
|
4643
4833
|
}
|
|
4644
4834
|
connectedCallback() {
|
|
4645
4835
|
super.connectedCallback();
|
|
@@ -4658,6 +4848,9 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
4658
4848
|
}
|
|
4659
4849
|
_initializeForm() {
|
|
4660
4850
|
var _a;
|
|
4851
|
+
if (!this._draftStorageService) {
|
|
4852
|
+
this._draftStorageService = new DraftStorageService(false);
|
|
4853
|
+
}
|
|
4661
4854
|
if (this.xbrlInput) {
|
|
4662
4855
|
try {
|
|
4663
4856
|
console.log("đ Initializing form from XBRL input:", this.xbrlInput);
|
|
@@ -4717,6 +4910,11 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
4717
4910
|
if ((_a = this.xbrlInput) == null ? void 0 : _a.initialData) {
|
|
4718
4911
|
this._formData = { ...this._formData, ...this.xbrlInput.initialData };
|
|
4719
4912
|
}
|
|
4913
|
+
if (!this._skipDraftLoading) {
|
|
4914
|
+
this._loadDraftIfExists();
|
|
4915
|
+
} else {
|
|
4916
|
+
console.log("âī¸ Skipping draft loading during preference update");
|
|
4917
|
+
}
|
|
4720
4918
|
this._validateForm();
|
|
4721
4919
|
}
|
|
4722
4920
|
_getDefaultSchema() {
|
|
@@ -4934,7 +5132,24 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
4934
5132
|
if (preferencesChanged) {
|
|
4935
5133
|
this._periodPreferences = periodPreferences;
|
|
4936
5134
|
console.log("đ Period preferences updated:", this._periodPreferences);
|
|
5135
|
+
this._skipDraftLoading = true;
|
|
4937
5136
|
this._initializeForm();
|
|
5137
|
+
this._skipDraftLoading = false;
|
|
5138
|
+
if (this._draftStorageService.hasDraft()) {
|
|
5139
|
+
console.log("đž Updating draft with new period preferences...");
|
|
5140
|
+
const draftData = this._generateSubmissionData();
|
|
5141
|
+
const metadata = this._draftStorageService.createMetadataSnapshot(
|
|
5142
|
+
this.periodStartDate,
|
|
5143
|
+
this.periodEndDate,
|
|
5144
|
+
this.language,
|
|
5145
|
+
this._selectedRoleIds,
|
|
5146
|
+
this._allSections,
|
|
5147
|
+
this._typedMemberData,
|
|
5148
|
+
this._periodPreferences
|
|
5149
|
+
);
|
|
5150
|
+
this._draftStorageService.saveDraft(draftData, metadata);
|
|
5151
|
+
console.log("â
Draft updated with new period preferences");
|
|
5152
|
+
}
|
|
4938
5153
|
} else {
|
|
4939
5154
|
this._applyRoleFilter();
|
|
4940
5155
|
}
|
|
@@ -4977,6 +5192,7 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
4977
5192
|
}
|
|
4978
5193
|
_handleFieldChange(event) {
|
|
4979
5194
|
const { fieldId, conceptId, columnId, value } = event.detail;
|
|
5195
|
+
console.log(`đ Field change: conceptId=${conceptId}, columnId=${columnId}, value=${value}, fieldId=${fieldId}`);
|
|
4980
5196
|
const updatedFormData = { ...this._formData };
|
|
4981
5197
|
if (!updatedFormData[conceptId]) {
|
|
4982
5198
|
updatedFormData[conceptId] = {};
|
|
@@ -4984,6 +5200,7 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
4984
5200
|
const oldValue = updatedFormData[conceptId][columnId];
|
|
4985
5201
|
updatedFormData[conceptId] = { ...updatedFormData[conceptId], [columnId]: value };
|
|
4986
5202
|
this._formData = updatedFormData;
|
|
5203
|
+
console.log(`đž Updated formData[${conceptId}]:`, this._formData[conceptId]);
|
|
4987
5204
|
this._touched.add(`${conceptId}-${columnId}`);
|
|
4988
5205
|
this._dirty = true;
|
|
4989
5206
|
this._validateForm();
|
|
@@ -5377,16 +5594,456 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
5377
5594
|
console.log("â
Form submit event dispatched");
|
|
5378
5595
|
}
|
|
5379
5596
|
_handleSaveDraft() {
|
|
5597
|
+
console.log("đž Raw form data before submission generation:", this._formData);
|
|
5380
5598
|
const draftData = this._generateSubmissionData();
|
|
5599
|
+
console.log("đ¤ Generated submission data:", draftData);
|
|
5600
|
+
console.log("đ Submission data breakdown:");
|
|
5601
|
+
draftData.forEach((entry, index) => {
|
|
5602
|
+
console.log(` [${index}] conceptId: ${entry.conceptId}, columnId: ${entry.columnId}, value: ${entry.value}`);
|
|
5603
|
+
});
|
|
5604
|
+
const metadata = this._draftStorageService.createMetadataSnapshot(
|
|
5605
|
+
this.periodStartDate,
|
|
5606
|
+
this.periodEndDate,
|
|
5607
|
+
this.language,
|
|
5608
|
+
this._selectedRoleIds,
|
|
5609
|
+
this._allSections,
|
|
5610
|
+
this._typedMemberData,
|
|
5611
|
+
this._periodPreferences
|
|
5612
|
+
);
|
|
5613
|
+
const saved = this._draftStorageService.saveDraft(draftData, metadata);
|
|
5614
|
+
this.dynaformsFacts = draftData;
|
|
5615
|
+
this.dynaformsMetadata = metadata;
|
|
5381
5616
|
this.dispatchEvent(new CustomEvent("form-save-draft", {
|
|
5382
5617
|
detail: {
|
|
5383
5618
|
data: this._formData,
|
|
5384
5619
|
draftData,
|
|
5620
|
+
metadata,
|
|
5621
|
+
saved,
|
|
5385
5622
|
valid: this._valid,
|
|
5386
|
-
errors: this._errors
|
|
5623
|
+
errors: this._errors,
|
|
5624
|
+
// JSON data ready for external database storage
|
|
5625
|
+
dynaformsFacts: draftData,
|
|
5626
|
+
dynaformsMetadata: metadata
|
|
5387
5627
|
},
|
|
5388
|
-
bubbles: true
|
|
5628
|
+
bubbles: true,
|
|
5629
|
+
composed: true
|
|
5630
|
+
}));
|
|
5631
|
+
console.log("đž Draft saved - localStorage + event emitted", {
|
|
5632
|
+
entries: draftData.length,
|
|
5633
|
+
saved,
|
|
5634
|
+
roles: this._selectedRoleIds.length,
|
|
5635
|
+
customColumns: metadata.customColumns.length,
|
|
5636
|
+
eventEmitted: true
|
|
5637
|
+
});
|
|
5638
|
+
}
|
|
5639
|
+
// ===========================================
|
|
5640
|
+
// Draft Loading & Restoration
|
|
5641
|
+
// ===========================================
|
|
5642
|
+
async _loadDraftIfExists() {
|
|
5643
|
+
console.log("đ Checking for saved draft...");
|
|
5644
|
+
if (this.dynaformsFacts && this.dynaformsMetadata) {
|
|
5645
|
+
console.log("đĻ Using external draft data from properties");
|
|
5646
|
+
const draft2 = {
|
|
5647
|
+
formData: this.dynaformsFacts,
|
|
5648
|
+
metadata: this.dynaformsMetadata
|
|
5649
|
+
};
|
|
5650
|
+
await this._restoreFromDraft(draft2);
|
|
5651
|
+
this._draftLoaded = true;
|
|
5652
|
+
this._draftLoadedAt = this.dynaformsMetadata.savedAt || (/* @__PURE__ */ new Date()).toISOString();
|
|
5653
|
+
this.dispatchEvent(new CustomEvent("form-draft-loaded", {
|
|
5654
|
+
detail: {
|
|
5655
|
+
draft: draft2,
|
|
5656
|
+
source: "external",
|
|
5657
|
+
compatible: true,
|
|
5658
|
+
warnings: []
|
|
5659
|
+
},
|
|
5660
|
+
bubbles: true,
|
|
5661
|
+
composed: true
|
|
5662
|
+
}));
|
|
5663
|
+
console.log("đĨ External draft loaded successfully");
|
|
5664
|
+
return;
|
|
5665
|
+
}
|
|
5666
|
+
if (!this._draftStorageService.hasDraft()) {
|
|
5667
|
+
console.log("âšī¸ No saved draft found");
|
|
5668
|
+
return;
|
|
5669
|
+
}
|
|
5670
|
+
const draft = this._draftStorageService.loadDraft();
|
|
5671
|
+
if (!draft) {
|
|
5672
|
+
console.warn("â ī¸ Failed to load draft");
|
|
5673
|
+
return;
|
|
5674
|
+
}
|
|
5675
|
+
const { compatible, warnings } = this._draftStorageService.validateDraftCompatibility(
|
|
5676
|
+
draft,
|
|
5677
|
+
this.periodStartDate,
|
|
5678
|
+
this.periodEndDate
|
|
5679
|
+
);
|
|
5680
|
+
if (warnings.length > 0) {
|
|
5681
|
+
console.warn("â ī¸ Draft compatibility warnings:", warnings);
|
|
5682
|
+
}
|
|
5683
|
+
await this._restoreFromDraft(draft);
|
|
5684
|
+
this.dispatchEvent(new CustomEvent("form-draft-loaded", {
|
|
5685
|
+
detail: {
|
|
5686
|
+
draft,
|
|
5687
|
+
compatible,
|
|
5688
|
+
warnings
|
|
5689
|
+
},
|
|
5690
|
+
bubbles: true,
|
|
5691
|
+
composed: true
|
|
5389
5692
|
}));
|
|
5693
|
+
console.log("đĨ Draft loaded successfully", {
|
|
5694
|
+
entries: draft.formData.length,
|
|
5695
|
+
savedAt: draft.metadata.savedAt,
|
|
5696
|
+
age: this._draftStorageService.getDraftAge()
|
|
5697
|
+
});
|
|
5698
|
+
}
|
|
5699
|
+
async _restoreFromDraft(draft) {
|
|
5700
|
+
var _a;
|
|
5701
|
+
const { formData, metadata } = draft;
|
|
5702
|
+
if (metadata.selectedRoleIds && metadata.selectedRoleIds.length > 0) {
|
|
5703
|
+
this._selectedRoleIds = metadata.selectedRoleIds;
|
|
5704
|
+
console.log(`đ Restored ${this._selectedRoleIds.length} selected roles`);
|
|
5705
|
+
}
|
|
5706
|
+
if (metadata.typedMemberData) {
|
|
5707
|
+
this._typedMemberData = metadata.typedMemberData;
|
|
5708
|
+
this._preservedTypedMemberData = {};
|
|
5709
|
+
console.log("đ Restored typed member data");
|
|
5710
|
+
}
|
|
5711
|
+
if (metadata.periodPreferences) {
|
|
5712
|
+
this._periodPreferences = metadata.periodPreferences;
|
|
5713
|
+
console.log("đ Restored period preferences (including previous year settings):", this._periodPreferences);
|
|
5714
|
+
if (this.xbrlInput) {
|
|
5715
|
+
console.log("đ Rebuilding schema with restored period preferences...");
|
|
5716
|
+
this._currentSchema = XBRLFormBuilder.buildFormSchema(
|
|
5717
|
+
this.xbrlInput,
|
|
5718
|
+
this.periodStartDate,
|
|
5719
|
+
this.periodEndDate,
|
|
5720
|
+
this.language,
|
|
5721
|
+
this._periodPreferences
|
|
5722
|
+
);
|
|
5723
|
+
this._allSections = [...this._currentSchema.sections];
|
|
5724
|
+
if (this.financialStatementsTypeAxis && this.financialStatementsTypeAxis.length > 0) {
|
|
5725
|
+
this._allSections = this._filterRolesByFinancialStatementsType(this._allSections);
|
|
5726
|
+
}
|
|
5727
|
+
console.log("â
Schema rebuilt with restored period preferences");
|
|
5728
|
+
if (metadata.customColumns && metadata.customColumns.length > 0) {
|
|
5729
|
+
this._mergeAdditionalCustomColumns(metadata.customColumns);
|
|
5730
|
+
console.log(`đ Merged ${metadata.customColumns.length} additional custom columns`);
|
|
5731
|
+
}
|
|
5732
|
+
}
|
|
5733
|
+
} else {
|
|
5734
|
+
if (metadata.customColumns && metadata.customColumns.length > 0) {
|
|
5735
|
+
this._restoreCustomColumns(metadata.customColumns);
|
|
5736
|
+
console.log(`đ Restored ${metadata.customColumns.length} custom columns`);
|
|
5737
|
+
}
|
|
5738
|
+
}
|
|
5739
|
+
const restoredFormData = {};
|
|
5740
|
+
formData.forEach((entry) => {
|
|
5741
|
+
let { conceptId, value, columnId, period } = entry;
|
|
5742
|
+
if (!columnId && period) {
|
|
5743
|
+
columnId = this._inferColumnIdFromPeriod(period, conceptId);
|
|
5744
|
+
if (!columnId) {
|
|
5745
|
+
console.warn(`â ī¸ Could not infer columnId for concept ${conceptId}, skipping...`);
|
|
5746
|
+
return;
|
|
5747
|
+
}
|
|
5748
|
+
}
|
|
5749
|
+
const actualConceptId = this._findActualConceptId(conceptId);
|
|
5750
|
+
const conceptIdToUse = actualConceptId || conceptId;
|
|
5751
|
+
if (!restoredFormData[conceptIdToUse]) {
|
|
5752
|
+
restoredFormData[conceptIdToUse] = {};
|
|
5753
|
+
}
|
|
5754
|
+
restoredFormData[conceptIdToUse][columnId] = value;
|
|
5755
|
+
console.log(`đĻ Restored: ${conceptIdToUse}[${columnId}] = ${value}`);
|
|
5756
|
+
});
|
|
5757
|
+
this._formData = { ...this._formData, ...restoredFormData };
|
|
5758
|
+
console.log(`đ Restored ${Object.keys(restoredFormData).length} concepts with data`);
|
|
5759
|
+
if (this._selectedRoleIds.length > 0) {
|
|
5760
|
+
this._applyRoleFilter();
|
|
5761
|
+
}
|
|
5762
|
+
this._dirty = true;
|
|
5763
|
+
this._touched.clear();
|
|
5764
|
+
this._validateForm();
|
|
5765
|
+
this._allSections = [...this._allSections];
|
|
5766
|
+
this.requestUpdate();
|
|
5767
|
+
await this.updateComplete;
|
|
5768
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
5769
|
+
const fieldCount = ((_a = this.shadowRoot) == null ? void 0 : _a.querySelectorAll("input, textarea, select").length) || 0;
|
|
5770
|
+
console.log(`đ Found ${fieldCount} fields in DOM after update`);
|
|
5771
|
+
if (fieldCount > 0) {
|
|
5772
|
+
this._populateFieldValues(restoredFormData);
|
|
5773
|
+
} else {
|
|
5774
|
+
console.error("â No fields found in DOM even after updateComplete");
|
|
5775
|
+
}
|
|
5776
|
+
console.log("â
Draft restoration completed");
|
|
5777
|
+
}
|
|
5778
|
+
_findActualConceptId(conceptId) {
|
|
5779
|
+
for (const section2 of this._allSections) {
|
|
5780
|
+
const found = this._findActualConceptIdInTree(section2.concepts, conceptId);
|
|
5781
|
+
if (found)
|
|
5782
|
+
return found;
|
|
5783
|
+
}
|
|
5784
|
+
return null;
|
|
5785
|
+
}
|
|
5786
|
+
_findActualConceptIdInTree(concepts, conceptId) {
|
|
5787
|
+
for (const concept of concepts) {
|
|
5788
|
+
if (concept.originalConceptId === conceptId || concept.id === conceptId) {
|
|
5789
|
+
return concept.id;
|
|
5790
|
+
}
|
|
5791
|
+
if (concept.children) {
|
|
5792
|
+
const found = this._findActualConceptIdInTree(concept.children, conceptId);
|
|
5793
|
+
if (found)
|
|
5794
|
+
return found;
|
|
5795
|
+
}
|
|
5796
|
+
}
|
|
5797
|
+
return null;
|
|
5798
|
+
}
|
|
5799
|
+
_inferColumnIdFromPeriod(period, conceptId) {
|
|
5800
|
+
for (const section2 of this._allSections) {
|
|
5801
|
+
const concept = this._findConceptInSection(section2.concepts, conceptId);
|
|
5802
|
+
if (concept && section2.columns) {
|
|
5803
|
+
for (const column2 of section2.columns) {
|
|
5804
|
+
const isInstant = period.type === "instant";
|
|
5805
|
+
const isDuration = period.type === "duration";
|
|
5806
|
+
if (isInstant && period.date) {
|
|
5807
|
+
if (column2.periodStartDate === period.date || column2.periodStartDate === column2.periodEndDate && column2.periodStartDate === period.date) {
|
|
5808
|
+
console.log(`â Inferred columnId: ${column2.id} for concept ${conceptId}`);
|
|
5809
|
+
return column2.id;
|
|
5810
|
+
}
|
|
5811
|
+
} else if (isDuration && period.startDate && period.endDate) {
|
|
5812
|
+
if (column2.periodStartDate === period.startDate && column2.periodEndDate === period.endDate) {
|
|
5813
|
+
console.log(`â Inferred columnId: ${column2.id} for concept ${conceptId}`);
|
|
5814
|
+
return column2.id;
|
|
5815
|
+
}
|
|
5816
|
+
}
|
|
5817
|
+
}
|
|
5818
|
+
if (period.type === "instant") {
|
|
5819
|
+
const instantCol = section2.columns.find((c2) => c2.id === "instant");
|
|
5820
|
+
if (instantCol)
|
|
5821
|
+
return instantCol.id;
|
|
5822
|
+
} else {
|
|
5823
|
+
const durationCol = section2.columns.find((c2) => c2.id === "duration");
|
|
5824
|
+
if (durationCol)
|
|
5825
|
+
return durationCol.id;
|
|
5826
|
+
}
|
|
5827
|
+
}
|
|
5828
|
+
}
|
|
5829
|
+
return null;
|
|
5830
|
+
}
|
|
5831
|
+
_findConceptInSection(concepts, conceptId) {
|
|
5832
|
+
for (const concept of concepts) {
|
|
5833
|
+
if (concept.id === conceptId || concept.originalConceptId === conceptId) {
|
|
5834
|
+
return concept;
|
|
5835
|
+
}
|
|
5836
|
+
if (concept.children) {
|
|
5837
|
+
const found = this._findConceptInSection(concept.children, conceptId);
|
|
5838
|
+
if (found)
|
|
5839
|
+
return found;
|
|
5840
|
+
}
|
|
5841
|
+
}
|
|
5842
|
+
return null;
|
|
5843
|
+
}
|
|
5844
|
+
_populateFieldValues(formData) {
|
|
5845
|
+
let populatedCount = 0;
|
|
5846
|
+
let notFoundCount = 0;
|
|
5847
|
+
console.log("đ Starting field population...");
|
|
5848
|
+
console.log("đĻ Form data to populate:", formData);
|
|
5849
|
+
Object.keys(formData).forEach((conceptId) => {
|
|
5850
|
+
const conceptData = formData[conceptId];
|
|
5851
|
+
Object.keys(conceptData).forEach((columnId) => {
|
|
5852
|
+
var _a, _b;
|
|
5853
|
+
const value = conceptData[columnId];
|
|
5854
|
+
const fieldId = `${conceptId}__${columnId}`;
|
|
5855
|
+
console.log(`đ Looking for field: ${fieldId}`);
|
|
5856
|
+
const fieldElement = (_a = this.shadowRoot) == null ? void 0 : _a.querySelector(`#${CSS.escape(fieldId)}`);
|
|
5857
|
+
if (fieldElement) {
|
|
5858
|
+
if (fieldElement instanceof HTMLInputElement || fieldElement instanceof HTMLTextAreaElement || fieldElement instanceof HTMLSelectElement) {
|
|
5859
|
+
if (fieldElement.type === "checkbox") {
|
|
5860
|
+
fieldElement.checked = Boolean(value);
|
|
5861
|
+
} else {
|
|
5862
|
+
fieldElement.value = value !== null && value !== void 0 ? String(value) : "";
|
|
5863
|
+
}
|
|
5864
|
+
console.log(` â
Populated field ${fieldId} with value:`, value);
|
|
5865
|
+
populatedCount++;
|
|
5866
|
+
}
|
|
5867
|
+
} else {
|
|
5868
|
+
console.warn(` â Field element NOT FOUND: ${fieldId}`);
|
|
5869
|
+
console.warn(` Available fields in DOM:`, Array.from(((_b = this.shadowRoot) == null ? void 0 : _b.querySelectorAll("input, textarea, select")) || []).map((el) => el.id).filter((id) => id.includes(conceptId.split("__")[0])));
|
|
5870
|
+
notFoundCount++;
|
|
5871
|
+
}
|
|
5872
|
+
});
|
|
5873
|
+
});
|
|
5874
|
+
console.log(`â
Field population complete: ${populatedCount} populated, ${notFoundCount} not found`);
|
|
5875
|
+
}
|
|
5876
|
+
_restoreCustomColumns(customColumns) {
|
|
5877
|
+
const columnsBySection = /* @__PURE__ */ new Map();
|
|
5878
|
+
customColumns.forEach((col) => {
|
|
5879
|
+
if (!columnsBySection.has(col.sectionId)) {
|
|
5880
|
+
columnsBySection.set(col.sectionId, []);
|
|
5881
|
+
}
|
|
5882
|
+
columnsBySection.get(col.sectionId).push(col);
|
|
5883
|
+
});
|
|
5884
|
+
this._allSections.forEach((section2) => {
|
|
5885
|
+
const savedColumns = columnsBySection.get(section2.id);
|
|
5886
|
+
if (savedColumns) {
|
|
5887
|
+
section2.columns = savedColumns.map((col) => ({
|
|
5888
|
+
id: col.columnId,
|
|
5889
|
+
title: col.label,
|
|
5890
|
+
type: col.dimensionData ? "dimension" : "base",
|
|
5891
|
+
periodStartDate: col.startDate || col.date,
|
|
5892
|
+
periodEndDate: col.endDate || col.date,
|
|
5893
|
+
dimensionData: col.dimensionData,
|
|
5894
|
+
order: 0,
|
|
5895
|
+
removable: col.columnId !== "duration" && col.columnId !== "instant"
|
|
5896
|
+
}));
|
|
5897
|
+
this._regenerateFieldsForSection(section2);
|
|
5898
|
+
console.log(` ââ Restored ${savedColumns.length} columns for section ${section2.id}`);
|
|
5899
|
+
}
|
|
5900
|
+
});
|
|
5901
|
+
if (this._currentSchema) {
|
|
5902
|
+
this._currentSchema = {
|
|
5903
|
+
...this._currentSchema,
|
|
5904
|
+
sections: this._allSections
|
|
5905
|
+
};
|
|
5906
|
+
}
|
|
5907
|
+
}
|
|
5908
|
+
/**
|
|
5909
|
+
* Merge additional custom columns that were manually added by user
|
|
5910
|
+
* This preserves default columns (duration, instant, previous year) generated by schema builder
|
|
5911
|
+
* and only adds custom columns that don't already exist
|
|
5912
|
+
*/
|
|
5913
|
+
_mergeAdditionalCustomColumns(customColumns) {
|
|
5914
|
+
const columnsBySection = /* @__PURE__ */ new Map();
|
|
5915
|
+
customColumns.forEach((col) => {
|
|
5916
|
+
const isManuallyAdded = col.columnId.startsWith("col-");
|
|
5917
|
+
if (isManuallyAdded) {
|
|
5918
|
+
if (!columnsBySection.has(col.sectionId)) {
|
|
5919
|
+
columnsBySection.set(col.sectionId, []);
|
|
5920
|
+
}
|
|
5921
|
+
columnsBySection.get(col.sectionId).push(col);
|
|
5922
|
+
}
|
|
5923
|
+
});
|
|
5924
|
+
this._allSections.forEach((section2) => {
|
|
5925
|
+
const customColumnsForSection = columnsBySection.get(section2.id);
|
|
5926
|
+
if (customColumnsForSection && customColumnsForSection.length > 0) {
|
|
5927
|
+
if (!section2.columns) {
|
|
5928
|
+
section2.columns = [];
|
|
5929
|
+
}
|
|
5930
|
+
customColumnsForSection.forEach((col) => {
|
|
5931
|
+
const existingColumn = section2.columns.find((c2) => c2.id === col.columnId);
|
|
5932
|
+
if (!existingColumn) {
|
|
5933
|
+
const newColumn = {
|
|
5934
|
+
id: col.columnId,
|
|
5935
|
+
title: col.label,
|
|
5936
|
+
type: col.dimensionData ? "dimension" : "base",
|
|
5937
|
+
periodStartDate: col.startDate || col.date,
|
|
5938
|
+
periodEndDate: col.endDate || col.date,
|
|
5939
|
+
dimensionData: col.dimensionData,
|
|
5940
|
+
order: section2.columns.length,
|
|
5941
|
+
removable: true
|
|
5942
|
+
};
|
|
5943
|
+
section2.columns.push(newColumn);
|
|
5944
|
+
console.log(` ââ Added custom column ${col.columnId} to section ${section2.id}`);
|
|
5945
|
+
}
|
|
5946
|
+
});
|
|
5947
|
+
this._regenerateFieldsForSection(section2);
|
|
5948
|
+
}
|
|
5949
|
+
});
|
|
5950
|
+
if (this._currentSchema) {
|
|
5951
|
+
this._currentSchema = {
|
|
5952
|
+
...this._currentSchema,
|
|
5953
|
+
sections: this._allSections
|
|
5954
|
+
};
|
|
5955
|
+
}
|
|
5956
|
+
}
|
|
5957
|
+
_regenerateFieldsForSection(section2) {
|
|
5958
|
+
if (!section2.columns)
|
|
5959
|
+
return;
|
|
5960
|
+
const sectionPreferences = this._periodPreferences[section2.id] || {
|
|
5961
|
+
showDuration: true,
|
|
5962
|
+
showInstant: true,
|
|
5963
|
+
showPreviousYear: false
|
|
5964
|
+
};
|
|
5965
|
+
const regenerateConcepts = (concepts) => {
|
|
5966
|
+
concepts.forEach((concept) => {
|
|
5967
|
+
concept.fields = [];
|
|
5968
|
+
const shouldShowConcept = this._shouldShowConceptBasedOnPeriodPreferences(
|
|
5969
|
+
concept,
|
|
5970
|
+
sectionPreferences
|
|
5971
|
+
);
|
|
5972
|
+
if (shouldShowConcept) {
|
|
5973
|
+
section2.columns.forEach((column2) => {
|
|
5974
|
+
const conceptPeriodType = concept.periodType;
|
|
5975
|
+
const columnPeriodType = this._inferColumnPeriodType(column2);
|
|
5976
|
+
if (concept.abstract)
|
|
5977
|
+
return;
|
|
5978
|
+
if (conceptPeriodType && columnPeriodType) {
|
|
5979
|
+
if (conceptPeriodType !== columnPeriodType) {
|
|
5980
|
+
return;
|
|
5981
|
+
}
|
|
5982
|
+
}
|
|
5983
|
+
concept.fields.push({
|
|
5984
|
+
id: `${concept.id}_${column2.id}`,
|
|
5985
|
+
conceptId: concept.id,
|
|
5986
|
+
columnId: column2.id,
|
|
5987
|
+
type: this._mapConceptTypeToFieldType(concept.type),
|
|
5988
|
+
label: concept.label,
|
|
5989
|
+
periodStartDate: column2.periodStartDate,
|
|
5990
|
+
periodEndDate: column2.periodEndDate
|
|
5991
|
+
});
|
|
5992
|
+
});
|
|
5993
|
+
}
|
|
5994
|
+
if (concept.children) {
|
|
5995
|
+
regenerateConcepts(concept.children);
|
|
5996
|
+
}
|
|
5997
|
+
});
|
|
5998
|
+
};
|
|
5999
|
+
regenerateConcepts(section2.concepts);
|
|
6000
|
+
}
|
|
6001
|
+
/**
|
|
6002
|
+
* Check if a concept should be shown based on period preferences
|
|
6003
|
+
*/
|
|
6004
|
+
_shouldShowConceptBasedOnPeriodPreferences(concept, preferences) {
|
|
6005
|
+
if (concept.abstract) {
|
|
6006
|
+
return true;
|
|
6007
|
+
}
|
|
6008
|
+
if (!concept.periodType) {
|
|
6009
|
+
return true;
|
|
6010
|
+
}
|
|
6011
|
+
if (concept.periodType === "duration" && !preferences.showDuration) {
|
|
6012
|
+
return false;
|
|
6013
|
+
}
|
|
6014
|
+
if (concept.periodType === "instant" && !preferences.showInstant) {
|
|
6015
|
+
return false;
|
|
6016
|
+
}
|
|
6017
|
+
return true;
|
|
6018
|
+
}
|
|
6019
|
+
_inferColumnPeriodType(column2) {
|
|
6020
|
+
if (column2.periodStartDate && column2.periodEndDate) {
|
|
6021
|
+
return column2.periodStartDate === column2.periodEndDate ? "instant" : "duration";
|
|
6022
|
+
}
|
|
6023
|
+
if (column2.periodStartDate && !column2.periodEndDate) {
|
|
6024
|
+
return "instant";
|
|
6025
|
+
}
|
|
6026
|
+
return void 0;
|
|
6027
|
+
}
|
|
6028
|
+
_mapConceptTypeToFieldType(conceptType) {
|
|
6029
|
+
if (!conceptType)
|
|
6030
|
+
return "text";
|
|
6031
|
+
if (conceptType.includes("monetary") || conceptType.includes("Monetary")) {
|
|
6032
|
+
return "number";
|
|
6033
|
+
}
|
|
6034
|
+
if (conceptType.includes("date") || conceptType.includes("Date")) {
|
|
6035
|
+
return "date";
|
|
6036
|
+
}
|
|
6037
|
+
if (conceptType.includes("boolean") || conceptType.includes("Boolean")) {
|
|
6038
|
+
return "boolean";
|
|
6039
|
+
}
|
|
6040
|
+
if (conceptType.includes("integer") || conceptType.includes("Integer")) {
|
|
6041
|
+
return "number";
|
|
6042
|
+
}
|
|
6043
|
+
if (conceptType.includes("decimal") || conceptType.includes("Decimal")) {
|
|
6044
|
+
return "number";
|
|
6045
|
+
}
|
|
6046
|
+
return "text";
|
|
5390
6047
|
}
|
|
5391
6048
|
_generateSubmissionData() {
|
|
5392
6049
|
const submissionData = [];
|
|
@@ -5427,20 +6084,6 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
5427
6084
|
}
|
|
5428
6085
|
return null;
|
|
5429
6086
|
}
|
|
5430
|
-
_findConceptInSection(concepts, conceptId) {
|
|
5431
|
-
for (const concept of concepts) {
|
|
5432
|
-
if (concept.id === conceptId) {
|
|
5433
|
-
return concept;
|
|
5434
|
-
}
|
|
5435
|
-
if (concept.children) {
|
|
5436
|
-
const found = this._findConceptInSection(concept.children, conceptId);
|
|
5437
|
-
if (found) {
|
|
5438
|
-
return found;
|
|
5439
|
-
}
|
|
5440
|
-
}
|
|
5441
|
-
}
|
|
5442
|
-
return null;
|
|
5443
|
-
}
|
|
5444
6087
|
_findSectionForConcept(conceptId) {
|
|
5445
6088
|
for (const section2 of this._allSections) {
|
|
5446
6089
|
const concept = this._findConceptInSection(section2.concepts, conceptId);
|
|
@@ -5457,10 +6100,10 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
5457
6100
|
return;
|
|
5458
6101
|
const isInstant = concept.periodType === "instant";
|
|
5459
6102
|
const column2 = this._findColumnByIdInAllSections(columnId);
|
|
5460
|
-
alert("hi");
|
|
5461
6103
|
console.log(`đ [Submission] Concept: ${concept.id}, Column: ${columnId}, Column Period: ${(column2 == null ? void 0 : column2.periodStartDate) || "none"} - ${(column2 == null ? void 0 : column2.periodEndDate) || "none"}`);
|
|
5462
6104
|
const entry = {
|
|
5463
6105
|
conceptId: concept.originalConceptId || concept.id,
|
|
6106
|
+
columnId,
|
|
5464
6107
|
value,
|
|
5465
6108
|
period: {
|
|
5466
6109
|
type: concept.periodType || "duration",
|
|
@@ -5614,6 +6257,8 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
5614
6257
|
const column2 = this._findColumnByIdInSection(field.columnId, section2);
|
|
5615
6258
|
const submissionEntry = {
|
|
5616
6259
|
conceptId: concept.id,
|
|
6260
|
+
columnId: field.columnId,
|
|
6261
|
+
// CRITICAL: Include columnId for draft restoration
|
|
5617
6262
|
value: fieldValue,
|
|
5618
6263
|
period: {
|
|
5619
6264
|
type: concept.periodType || "duration"
|
|
@@ -6370,9 +7015,21 @@ __decorateClass([
|
|
|
6370
7015
|
__decorateClass([
|
|
6371
7016
|
n2({ type: Array })
|
|
6372
7017
|
], JupiterDynamicForm.prototype, "financialStatementsTypeAxis", 2);
|
|
7018
|
+
__decorateClass([
|
|
7019
|
+
n2({ type: Object, attribute: "dynaforms-metadata" })
|
|
7020
|
+
], JupiterDynamicForm.prototype, "dynaformsMetadata", 2);
|
|
7021
|
+
__decorateClass([
|
|
7022
|
+
n2({ type: Object, attribute: "dynaforms-facts" })
|
|
7023
|
+
], JupiterDynamicForm.prototype, "dynaformsFacts", 2);
|
|
6373
7024
|
__decorateClass([
|
|
6374
7025
|
r()
|
|
6375
7026
|
], JupiterDynamicForm.prototype, "_formData", 2);
|
|
7027
|
+
__decorateClass([
|
|
7028
|
+
r()
|
|
7029
|
+
], JupiterDynamicForm.prototype, "_draftLoaded", 2);
|
|
7030
|
+
__decorateClass([
|
|
7031
|
+
r()
|
|
7032
|
+
], JupiterDynamicForm.prototype, "_draftLoadedAt", 2);
|
|
6376
7033
|
__decorateClass([
|
|
6377
7034
|
r()
|
|
6378
7035
|
], JupiterDynamicForm.prototype, "_preservedFormData", 2);
|