jupiter-dynamic-forms 1.15.0 → 1.15.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/concept-tree.d.ts +1 -1
- package/dist/core/concept-tree.d.ts.map +1 -1
- package/dist/core/dynamic-form.d.ts +15 -1
- package/dist/core/dynamic-form.d.ts.map +1 -1
- package/dist/core/filter-roles-dialog.d.ts.map +1 -1
- package/dist/core/form-field.d.ts +1 -1
- package/dist/core/form-field.d.ts.map +1 -1
- package/dist/core/form-section.d.ts +6 -1
- package/dist/core/form-section.d.ts.map +1 -1
- package/dist/index.js +28 -25
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +118 -32
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -3073,18 +3073,29 @@ let JupiterFormField = class extends LitElement {
|
|
|
3073
3073
|
if (availableUnits.length === 0) {
|
|
3074
3074
|
return;
|
|
3075
3075
|
}
|
|
3076
|
-
if (
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
console.log(
|
|
3076
|
+
if (this.unit)
|
|
3077
|
+
return;
|
|
3078
|
+
const defaultUnit = availableUnits.find((u2) => u2.isDefault === true) ?? (availableUnits.length === 1 ? availableUnits[0] : null);
|
|
3079
|
+
if (defaultUnit) {
|
|
3080
|
+
this.unit = defaultUnit.id;
|
|
3081
|
+
this.dispatchEvent(new CustomEvent("unit-change", {
|
|
3082
|
+
detail: { fieldId: this.field.id, conceptId: this.conceptId, columnId: this.columnId, unit: this.unit },
|
|
3083
|
+
bubbles: true,
|
|
3084
|
+
composed: true
|
|
3085
|
+
}));
|
|
3086
|
+
console.log(`🎯 [FormField] Auto-selected default unit on blur: ${this.unit} for ${this.conceptId}`);
|
|
3087
|
+
return;
|
|
3087
3088
|
}
|
|
3089
|
+
this._xbrlErrors = [
|
|
3090
|
+
...this._xbrlErrors,
|
|
3091
|
+
{
|
|
3092
|
+
type: "unit",
|
|
3093
|
+
message: I18n.t("validation.unitRequired"),
|
|
3094
|
+
expectedValue: availableUnits.map((u2) => u2.label).join(", "),
|
|
3095
|
+
actualValue: ""
|
|
3096
|
+
}
|
|
3097
|
+
];
|
|
3098
|
+
console.log(`❌ [FormField] Unit validation failed for ${this.conceptId}: unit is required but not selected`);
|
|
3088
3099
|
}
|
|
3089
3100
|
_handlePeriodIconClick() {
|
|
3090
3101
|
this._availableUnits = this._collectUnitsForConceptType();
|
|
@@ -3512,7 +3523,7 @@ let JupiterFormField = class extends LitElement {
|
|
|
3512
3523
|
}
|
|
3513
3524
|
const hasUserValue = this.value !== null && this.value !== void 0;
|
|
3514
3525
|
const effectiveValue = isPredefinedValue ? this.masterData[baseConceptId] : hasUserValue ? this.value : factValue;
|
|
3515
|
-
const effectiveDisabled = isPredefinedValue || this.disabled;
|
|
3526
|
+
const effectiveDisabled = isPredefinedValue || this.disabled || this.mode === "readonly";
|
|
3516
3527
|
return html`
|
|
3517
3528
|
<div class="field-container">
|
|
3518
3529
|
${showLabel ? html`
|
|
@@ -3524,9 +3535,9 @@ let JupiterFormField = class extends LitElement {
|
|
|
3524
3535
|
<div class="field-wrapper">
|
|
3525
3536
|
${this._renderInput(effectiveValue, effectiveDisabled)}
|
|
3526
3537
|
|
|
3527
|
-
${hasPeriodControl ? html`
|
|
3528
|
-
<button
|
|
3529
|
-
class="period-icon-btn"
|
|
3538
|
+
${hasPeriodControl && this.mode !== "readonly" ? html`
|
|
3539
|
+
<button
|
|
3540
|
+
class="period-icon-btn"
|
|
3530
3541
|
type="button"
|
|
3531
3542
|
@click="${this._handlePeriodIconClick}"
|
|
3532
3543
|
title="Edit period"
|
|
@@ -4978,6 +4989,20 @@ let JupiterFormSection = class extends LitElement {
|
|
|
4978
4989
|
}
|
|
4979
4990
|
return result;
|
|
4980
4991
|
}
|
|
4992
|
+
/**
|
|
4993
|
+
* Returns true when every column cell for a concept has no value.
|
|
4994
|
+
* Used in readonly mode to hide fully-blank rows.
|
|
4995
|
+
*/
|
|
4996
|
+
_isConceptRowBlank(concept) {
|
|
4997
|
+
var _a;
|
|
4998
|
+
for (const column2 of this.columns) {
|
|
4999
|
+
const value = (_a = this.formData[concept.id]) == null ? void 0 : _a[column2.id];
|
|
5000
|
+
if (value !== null && value !== void 0 && value !== "") {
|
|
5001
|
+
return false;
|
|
5002
|
+
}
|
|
5003
|
+
}
|
|
5004
|
+
return true;
|
|
5005
|
+
}
|
|
4981
5006
|
_getAllConceptIds(concepts) {
|
|
4982
5007
|
const result = [];
|
|
4983
5008
|
for (const concept of concepts) {
|
|
@@ -5109,24 +5134,25 @@ let JupiterFormSection = class extends LitElement {
|
|
|
5109
5134
|
` : ""}
|
|
5110
5135
|
</div>
|
|
5111
5136
|
|
|
5112
|
-
<!-- Column menu icon (
|
|
5113
|
-
|
|
5137
|
+
<!-- Column menu icon (hidden in readonly mode) -->
|
|
5138
|
+
${this.mode !== "readonly" ? html`
|
|
5139
|
+
<div
|
|
5114
5140
|
class="column-menu-icon"
|
|
5115
5141
|
@click="${(e2) => this._toggleColumnMenu(column2.id, e2)}"
|
|
5116
5142
|
title="${I18n.t("column.columnOptions")}"
|
|
5117
5143
|
>⋮</div>
|
|
5118
|
-
|
|
5144
|
+
|
|
5119
5145
|
<!-- Context menu -->
|
|
5120
5146
|
${this._openMenuColumnId === column2.id ? html`
|
|
5121
5147
|
<div class="column-context-menu">
|
|
5122
|
-
<button
|
|
5148
|
+
<button
|
|
5123
5149
|
class="column-context-menu-item"
|
|
5124
5150
|
@click="${(e2) => this._handleAddColumnFromMenu(column2.id, e2)}"
|
|
5125
5151
|
>
|
|
5126
5152
|
${I18n.t("column.addColumn")}
|
|
5127
5153
|
</button>
|
|
5128
5154
|
${column2.removable ? html`
|
|
5129
|
-
<button
|
|
5155
|
+
<button
|
|
5130
5156
|
class="column-context-menu-item remove"
|
|
5131
5157
|
@click="${(e2) => {
|
|
5132
5158
|
e2.stopPropagation();
|
|
@@ -5138,13 +5164,14 @@ let JupiterFormSection = class extends LitElement {
|
|
|
5138
5164
|
` : ""}
|
|
5139
5165
|
</div>
|
|
5140
5166
|
` : ""}
|
|
5167
|
+
` : ""}
|
|
5141
5168
|
</th>
|
|
5142
5169
|
`;
|
|
5143
5170
|
})}
|
|
5144
5171
|
</tr>
|
|
5145
5172
|
</thead>
|
|
5146
5173
|
<tbody class="table-body">
|
|
5147
|
-
${this._flattenConcepts(this.section.concepts, this._expandedConcepts).map((concept) => html`
|
|
5174
|
+
${this._flattenConcepts(this.section.concepts, this._expandedConcepts).filter((concept) => this.mode !== "readonly" || !this._isConceptRowBlank(concept)).map((concept) => html`
|
|
5148
5175
|
<tr>
|
|
5149
5176
|
<jupiter-concept-tree
|
|
5150
5177
|
.concept="${concept}"
|
|
@@ -5765,13 +5792,9 @@ let JupiterFilterRolesDialog = class extends LitElement {
|
|
|
5765
5792
|
}));
|
|
5766
5793
|
}
|
|
5767
5794
|
_handleApply() {
|
|
5768
|
-
const
|
|
5769
|
-
const
|
|
5770
|
-
|
|
5771
|
-
const indexB = this.availableRoles.findIndex((r2) => r2.id === b2);
|
|
5772
|
-
return indexA - indexB;
|
|
5773
|
-
});
|
|
5774
|
-
this._chosenRoleOrder = orderedByOriginal;
|
|
5795
|
+
const orderedSelected = this._chosenRoleOrder.filter((id) => this._tempSelectedRoles.has(id));
|
|
5796
|
+
const notInOrder = Array.from(this._tempSelectedRoles).filter((id) => !this._chosenRoleOrder.includes(id));
|
|
5797
|
+
this._chosenRoleOrder = [...orderedSelected, ...notInOrder];
|
|
5775
5798
|
const orderedRolesWithMetadata = this._chosenRoleOrder.map((roleId, index) => {
|
|
5776
5799
|
var _a;
|
|
5777
5800
|
const role = this.availableRoles.find((r2) => r2.id === roleId);
|
|
@@ -7197,6 +7220,7 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
7197
7220
|
console.log("🌐 Using language:", this.language);
|
|
7198
7221
|
this._initializePeriodPreferencesFromData();
|
|
7199
7222
|
this._applyAxisFilterToPeriodPreferences();
|
|
7223
|
+
this._applyDimensionShowPreviousYear();
|
|
7200
7224
|
console.log("⚙️ Using period preferences:", this._periodPreferences);
|
|
7201
7225
|
this._currentSchema = XBRLFormBuilder.buildFormSchema(
|
|
7202
7226
|
this.xbrlInput,
|
|
@@ -7537,6 +7561,41 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
7537
7561
|
}
|
|
7538
7562
|
this._periodPreferences = preferences;
|
|
7539
7563
|
}
|
|
7564
|
+
/**
|
|
7565
|
+
* In admin mode, auto-enables showPreviousYear for roles that have at least one dimension
|
|
7566
|
+
* member selected (from roleFilterAxes defaults). This ensures such roles render with a
|
|
7567
|
+
* minimum of two columns (current + previous year) on fresh initialization.
|
|
7568
|
+
*
|
|
7569
|
+
* Skipped when form state is being restored from external props or localStorage so that
|
|
7570
|
+
* the user's previously saved preferences are not overridden.
|
|
7571
|
+
*/
|
|
7572
|
+
_applyDimensionShowPreviousYear() {
|
|
7573
|
+
var _a, _b;
|
|
7574
|
+
if (this.mode !== "admin")
|
|
7575
|
+
return;
|
|
7576
|
+
const hasExternalState = !!(this.dynaformsFacts && this.dynaformsMetadata);
|
|
7577
|
+
const hasLocalDraft = ((_a = this._draftStorageService) == null ? void 0 : _a.hasDraft()) ?? false;
|
|
7578
|
+
if (hasExternalState || hasLocalDraft)
|
|
7579
|
+
return;
|
|
7580
|
+
const updated = { ...this._periodPreferences };
|
|
7581
|
+
let changed = false;
|
|
7582
|
+
for (const roleId of Object.keys(updated)) {
|
|
7583
|
+
const prefs = updated[roleId];
|
|
7584
|
+
if (prefs.showPreviousYear)
|
|
7585
|
+
continue;
|
|
7586
|
+
const hasDimensionMembers = ((_b = prefs.dimensionSelections) == null ? void 0 : _b.some(
|
|
7587
|
+
(ds) => ds.selectedMemberIds && ds.selectedMemberIds.length > 0
|
|
7588
|
+
)) ?? false;
|
|
7589
|
+
if (hasDimensionMembers) {
|
|
7590
|
+
updated[roleId] = { ...prefs, showPreviousYear: true };
|
|
7591
|
+
changed = true;
|
|
7592
|
+
console.log(`📅 [JDF-010] Auto-enabled showPreviousYear for role "${roleId}" (has dimension members)`);
|
|
7593
|
+
}
|
|
7594
|
+
}
|
|
7595
|
+
if (changed) {
|
|
7596
|
+
this._periodPreferences = updated;
|
|
7597
|
+
}
|
|
7598
|
+
}
|
|
7540
7599
|
/**
|
|
7541
7600
|
* Helper method to extract roleIds from _selectedRoleIds
|
|
7542
7601
|
* Handles both legacy string[] and enhanced object[] structure
|
|
@@ -9684,6 +9743,32 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
9684
9743
|
_toggleSidePanelCollapse() {
|
|
9685
9744
|
this._sidePanelCollapsed = !this._sidePanelCollapsed;
|
|
9686
9745
|
}
|
|
9746
|
+
/**
|
|
9747
|
+
* Returns true when every non-abstract concept row in the section has no value
|
|
9748
|
+
* in any column. Used in readonly mode to hide fully-blank sections.
|
|
9749
|
+
*/
|
|
9750
|
+
_isSectionBlank(section2) {
|
|
9751
|
+
const columns = section2.columns || this._columns;
|
|
9752
|
+
const hasValue = (concepts) => {
|
|
9753
|
+
var _a;
|
|
9754
|
+
for (const concept of concepts) {
|
|
9755
|
+
if (!concept.abstract) {
|
|
9756
|
+
for (const column2 of columns) {
|
|
9757
|
+
const value = (_a = this._formData[concept.id]) == null ? void 0 : _a[column2.id];
|
|
9758
|
+
if (value !== null && value !== void 0 && value !== "") {
|
|
9759
|
+
return true;
|
|
9760
|
+
}
|
|
9761
|
+
}
|
|
9762
|
+
}
|
|
9763
|
+
if (concept.children && concept.children.length > 0) {
|
|
9764
|
+
if (hasValue(concept.children))
|
|
9765
|
+
return true;
|
|
9766
|
+
}
|
|
9767
|
+
}
|
|
9768
|
+
return false;
|
|
9769
|
+
};
|
|
9770
|
+
return !hasValue(section2.concepts);
|
|
9771
|
+
}
|
|
9687
9772
|
_filterSidePanelSections(sections) {
|
|
9688
9773
|
if (!this._sidePanelSearchQuery.trim()) {
|
|
9689
9774
|
return sections;
|
|
@@ -10076,7 +10161,7 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
10076
10161
|
<p>${I18n.t("filter.selectRoles")}</p>
|
|
10077
10162
|
<p>${I18n.t("filter.roles")}: ${this._allSections.length}</p>
|
|
10078
10163
|
</div>
|
|
10079
|
-
` : schema.sections.map((section2, index) => {
|
|
10164
|
+
` : (this.mode === "readonly" ? schema.sections.filter((s2) => !this._isSectionBlank(s2)) : schema.sections).map((section2, index) => {
|
|
10080
10165
|
var _a;
|
|
10081
10166
|
return html`
|
|
10082
10167
|
<jupiter-form-section
|
|
@@ -10113,7 +10198,7 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
10113
10198
|
}
|
|
10114
10199
|
_renderSidePanelLayout(schema, config, showValidationSummary, errorCount) {
|
|
10115
10200
|
var _a;
|
|
10116
|
-
const visibleSections = schema.sections;
|
|
10201
|
+
const visibleSections = this.mode === "readonly" ? schema.sections.filter((s2) => !this._isSectionBlank(s2)) : schema.sections;
|
|
10117
10202
|
const filteredSections = this._filterSidePanelSections(visibleSections);
|
|
10118
10203
|
if (!this._activeSidePanelRoleId || !filteredSections.find((s2) => s2.id === this._activeSidePanelRoleId)) {
|
|
10119
10204
|
this._activeSidePanelRoleId = filteredSections.length > 0 ? filteredSections[0].id : null;
|
|
@@ -10290,7 +10375,8 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
10290
10375
|
<!-- Form Content -->
|
|
10291
10376
|
${this.display === "sidePanel" ? this._renderSidePanelLayout(schema, config, showValidationSummary, errorCount) : this._renderAccordionLayout(schema, config, showValidationSummary, errorCount)}
|
|
10292
10377
|
|
|
10293
|
-
<!-- Form Actions - Fixed Footer -->
|
|
10378
|
+
<!-- Form Actions - Fixed Footer (hidden in readonly mode) -->
|
|
10379
|
+
${this.mode !== "readonly" ? html`
|
|
10294
10380
|
<div class="form-actions">
|
|
10295
10381
|
<!-- Filter Roles Button (shown when more than 10 roles) -->
|
|
10296
10382
|
${this._shouldShowFilterButton() ? html`
|
|
@@ -10325,8 +10411,8 @@ let JupiterDynamicForm = class extends LitElement {
|
|
|
10325
10411
|
${this.submitButtonLabel || I18n.t("form.submit")}
|
|
10326
10412
|
</button>
|
|
10327
10413
|
|
|
10328
|
-
|
|
10329
10414
|
</div>
|
|
10415
|
+
` : ""}
|
|
10330
10416
|
|
|
10331
10417
|
<!-- Filter Roles Dialog -->
|
|
10332
10418
|
${this._showFilterDialog ? html`
|