jupiter-dynamic-forms 1.12.1 → 1.13.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/index.mjs CHANGED
@@ -523,6 +523,23 @@ class FormValidator {
523
523
  }
524
524
  }
525
525
  class XBRLFormBuilder {
526
+ /**
527
+ * Format period range for display - shows only year when both dates are in same year
528
+ * @param startDate - Period start date in YYYY-MM-DD format
529
+ * @param endDate - Period end date in YYYY-MM-DD format
530
+ * @returns Formatted period string (e.g., "2025" or "2025-01-01 / 2026-12-31")
531
+ */
532
+ static formatPeriodDisplay(startDate, endDate) {
533
+ if (!startDate || !endDate) {
534
+ return `${startDate} / ${endDate}`;
535
+ }
536
+ const startYear = startDate.substring(0, 4);
537
+ const endYear = endDate.substring(0, 4);
538
+ if (startYear === endYear) {
539
+ return startYear;
540
+ }
541
+ return `${startDate} / ${endDate}`;
542
+ }
526
543
  /**
527
544
  * Create unique concept ID by combining original ID with preferred label suffix
528
545
  * This handles cases where the same concept appears multiple times with different labels
@@ -638,41 +655,9 @@ class XBRLFormBuilder {
638
655
  if (!concept.elementAbstract) {
639
656
  let columnIds = [];
640
657
  if ((roleInfo == null ? void 0 : roleInfo.availableColumnIds) && roleInfo.availableColumnIds.length > 0) {
641
- columnIds = roleInfo.availableColumnIds.filter((colId) => {
642
- const isInstantColumn = colId.includes("instant") || colId === "instant";
643
- const isDurationColumn = colId.includes("duration") || colId === "duration";
644
- if (concept.periodType === "instant") {
645
- return isInstantColumn;
646
- } else if (concept.periodType === "duration") {
647
- return isDurationColumn;
648
- } else {
649
- return !isInstantColumn && !isDurationColumn;
650
- }
651
- });
652
- if (columnIds.length === 0 && roleInfo.availableColumnIds.length > 0) {
653
- const hasPeriodColumns = roleInfo.availableColumnIds.some(
654
- (colId) => colId.includes("instant") || colId.includes("duration")
655
- );
656
- if (!hasPeriodColumns) {
657
- columnIds = roleInfo.availableColumnIds;
658
- }
659
- }
658
+ columnIds = roleInfo.availableColumnIds;
660
659
  } else {
661
- if (!(roleInfo == null ? void 0 : roleInfo.periodTypes) || roleInfo.periodTypes.size === 0) {
662
- columnIds = ["default"];
663
- } else if (roleInfo.periodTypes.size === 1 && roleInfo.periodTypes.has("instant")) {
664
- columnIds = ["instant"];
665
- } else if (roleInfo.periodTypes.size === 1 && roleInfo.periodTypes.has("duration")) {
666
- columnIds = ["duration"];
667
- } else {
668
- if (concept.periodType === "instant") {
669
- columnIds = ["instant"];
670
- } else if (concept.periodType === "duration") {
671
- columnIds = ["duration"];
672
- } else {
673
- columnIds = ["duration", "instant"];
674
- }
675
- }
660
+ columnIds = ["duration"];
676
661
  }
677
662
  columnIds.forEach((columnId) => {
678
663
  const field = this.createFieldFromConcept(concept, periodStartDate, periodEndDate, columnId);
@@ -722,13 +707,7 @@ class XBRLFormBuilder {
722
707
  if (forcedColumnId) {
723
708
  columnId = forcedColumnId;
724
709
  } else {
725
- if (concept.periodType === "instant") {
726
- columnId = "instant";
727
- } else if (concept.periodType === "duration") {
728
- columnId = "duration";
729
- } else {
730
- columnId = "default";
731
- }
710
+ columnId = "duration";
732
711
  }
733
712
  const field = {
734
713
  id: `${concept.id}_${columnId}_field`,
@@ -740,11 +719,16 @@ class XBRLFormBuilder {
740
719
  required: false,
741
720
  // Will be determined by validation rules
742
721
  disabled: concept.elementAbstract,
743
- defaultValue: null
722
+ defaultValue: null,
723
+ // Add period information - each field has its own period (defaults from column)
724
+ periodType: concept.periodType === "instant" || concept.periodType === "duration" ? concept.periodType : void 0,
725
+ // Validate and set the period type
726
+ periodStartDate: periodStartDate || "2025-01-01",
727
+ periodEndDate: periodEndDate || "2025-12-31",
728
+ periodInstantDate: concept.periodType === "instant" ? periodEndDate || periodStartDate || "2025-01-01" : void 0
744
729
  };
745
- if (concept.periodType === "duration" || concept.periodType === "instant") {
746
- field.periodStartDate = periodStartDate || "2025-01-01";
747
- field.periodEndDate = periodEndDate || "2025-12-31";
730
+ if (concept.id === "nl-cd_DescriptionLocationNL__a64trl") {
731
+ console.log(`🏗️ [Field Creation] Concept: ${concept.id}, periodType from concept: ${concept.periodType}, Field periodType: ${field.periodType}, ColumnId: ${columnId}`);
748
732
  }
749
733
  return field;
750
734
  }
@@ -888,46 +872,24 @@ class XBRLFormBuilder {
888
872
  if (periodTypes.size === 0) {
889
873
  columns.push({
890
874
  id: "default",
891
- title: "Value",
892
- description: "Default value column",
893
- type: "base",
894
- order: 0,
895
- removable: false
896
- });
897
- } else if (periodTypes.size === 1 && periodTypes.has("instant")) {
898
- columns.push({
899
- id: "instant",
900
- title: periodEndDate,
875
+ title: this.formatPeriodDisplay(periodStartDate, periodEndDate),
901
876
  description: "",
902
877
  type: "base",
903
878
  order: 0,
904
- removable: false
905
- });
906
- } else if (periodTypes.size === 1 && periodTypes.has("duration")) {
907
- columns.push({
908
- id: "duration",
909
- title: `${periodStartDate} / ${periodEndDate}`,
910
- description: "",
911
- type: "base",
912
- order: 0,
913
- removable: false
879
+ removable: false,
880
+ periodStartDate,
881
+ periodEndDate
914
882
  });
915
883
  } else {
916
884
  columns.push({
917
885
  id: "duration",
918
- title: `${periodStartDate} / ${periodEndDate}`,
886
+ title: this.formatPeriodDisplay(periodStartDate, periodEndDate),
919
887
  description: "",
920
888
  type: "base",
921
889
  order: 0,
922
- removable: false
923
- });
924
- columns.push({
925
- id: "instant",
926
- title: periodEndDate,
927
- description: "",
928
- type: "base",
929
- order: 1,
930
- removable: false
890
+ removable: false,
891
+ periodStartDate,
892
+ periodEndDate
931
893
  });
932
894
  }
933
895
  }
@@ -967,30 +929,12 @@ class XBRLFormBuilder {
967
929
  let prevId = "";
968
930
  if (column2.dimensionData) {
969
931
  prevTitle = column2.title;
970
- if (column2.description && column2.description.includes("/")) {
971
- prevDescription = `${prevStartDate} / ${prevEndDate}`;
972
- } else {
973
- prevDescription = prevEndDate;
974
- }
932
+ prevDescription = this.formatPeriodDisplay(prevStartDate, prevEndDate);
975
933
  prevId = `${column2.id}_prev`;
976
934
  } else {
977
- if (column2.id === "instant" || column2.id.includes("instant")) {
978
- prevTitle = prevEndDate;
979
- prevDescription = "";
980
- prevId = `instant_prev_${index}`;
981
- } else if (column2.id === "duration" || column2.id.includes("duration")) {
982
- prevTitle = `${prevStartDate} / ${prevEndDate}`;
983
- prevDescription = "";
984
- prevId = `duration_prev_${index}`;
985
- } else if (column2.title.includes("/")) {
986
- prevTitle = `${prevStartDate} / ${prevEndDate}`;
987
- prevDescription = "";
988
- prevId = `${column2.id}_prev`;
989
- } else {
990
- prevTitle = prevEndDate;
991
- prevDescription = "";
992
- prevId = `${column2.id}_prev`;
993
- }
935
+ prevTitle = this.formatPeriodDisplay(prevStartDate, prevEndDate);
936
+ prevDescription = "";
937
+ prevId = `duration_prev_${index}`;
994
938
  }
995
939
  previousYearColumns.push({
996
940
  ...column2,
@@ -999,7 +943,8 @@ class XBRLFormBuilder {
999
943
  description: prevDescription,
1000
944
  order: column2.order + 100,
1001
945
  // Place after current year columns
1002
- removable: true,
946
+ removable: false,
947
+ // User explicitly chose this via filter dialog
1003
948
  periodStartDate: prevStartDate,
1004
949
  // Set previous year start date
1005
950
  periodEndDate: prevEndDate,
@@ -1073,7 +1018,9 @@ class XBRLFormBuilder {
1073
1018
  }]
1074
1019
  },
1075
1020
  order: 0,
1076
- removable: false
1021
+ removable: false,
1022
+ periodStartDate,
1023
+ periodEndDate
1077
1024
  });
1078
1025
  } else if (periodTypes.size === 1 && periodTypes.has("instant")) {
1079
1026
  columns2.push({
@@ -1101,13 +1048,15 @@ class XBRLFormBuilder {
1101
1048
  }]
1102
1049
  },
1103
1050
  order: 0,
1104
- removable: false
1051
+ removable: false,
1052
+ periodStartDate: periodEndDate,
1053
+ periodEndDate
1105
1054
  });
1106
1055
  } else if (periodTypes.size === 1 && periodTypes.has("duration")) {
1107
1056
  columns2.push({
1108
1057
  id: "typed-duration",
1109
1058
  title: `${axisLabel2} [Typed Input Available]`,
1110
- description: `${periodStartDate} / ${periodEndDate}`,
1059
+ description: this.formatPeriodDisplay(periodStartDate, periodEndDate),
1111
1060
  type: "dimension",
1112
1061
  dimensionData: {
1113
1062
  dimensionId: "typed-duration",
@@ -1129,13 +1078,15 @@ class XBRLFormBuilder {
1129
1078
  }]
1130
1079
  },
1131
1080
  order: 0,
1132
- removable: false
1081
+ removable: false,
1082
+ periodStartDate,
1083
+ periodEndDate
1133
1084
  });
1134
1085
  } else {
1135
1086
  columns2.push({
1136
1087
  id: "typed-duration",
1137
1088
  title: `${axisLabel2} [Typed Input Available]`,
1138
- description: `${periodStartDate} / ${periodEndDate}`,
1089
+ description: this.formatPeriodDisplay(periodStartDate, periodEndDate),
1139
1090
  type: "dimension",
1140
1091
  dimensionData: {
1141
1092
  dimensionId: "typed-duration",
@@ -1157,34 +1108,9 @@ class XBRLFormBuilder {
1157
1108
  }]
1158
1109
  },
1159
1110
  order: 0,
1160
- removable: false
1161
- });
1162
- columns2.push({
1163
- id: "typed-instant",
1164
- title: `${axisLabel2} [Typed Input Available]`,
1165
- description: periodEndDate,
1166
- type: "dimension",
1167
- dimensionData: {
1168
- dimensionId: "typed-instant",
1169
- axisId: dimensionInfo2.axisId,
1170
- memberId: "[typed]",
1171
- memberValue: "Typed Input",
1172
- memberLabel: "Typed Input",
1173
- axis: dimensionInfo2.axisLabel,
1174
- axisLabel: dimensionInfo2.axisLabel,
1175
- memberKey: dimensionInfo2.dimensionKey,
1176
- dimensionIdKey: dimensionInfo2.dimensionIdKey,
1177
- hasTypedMembers: true,
1178
- typedMemberId: dimensionInfo2.typedMemberId,
1179
- typedMembers: [{
1180
- axisId: dimensionInfo2.axisId,
1181
- axisLabel: dimensionInfo2.axisLabel,
1182
- typedMemberId: dimensionInfo2.typedMemberId,
1183
- memberLabel: dimensionInfo2.axisLabel
1184
- }]
1185
- },
1186
- order: 1,
1187
- removable: false
1111
+ removable: false,
1112
+ periodStartDate,
1113
+ periodEndDate
1188
1114
  });
1189
1115
  }
1190
1116
  return columns2;
@@ -1225,7 +1151,9 @@ class XBRLFormBuilder {
1225
1151
  dimensionIdKey: dimensionInfo.dimensionIdKey
1226
1152
  },
1227
1153
  order: 0,
1228
- removable: false
1154
+ removable: false,
1155
+ periodStartDate,
1156
+ periodEndDate
1229
1157
  });
1230
1158
  } else if (periodTypes.size === 1 && periodTypes.has("instant")) {
1231
1159
  columns.push({
@@ -1245,7 +1173,9 @@ class XBRLFormBuilder {
1245
1173
  dimensionIdKey: dimensionInfo.dimensionIdKey
1246
1174
  },
1247
1175
  order: 0,
1248
- removable: false
1176
+ removable: false,
1177
+ periodStartDate: periodEndDate,
1178
+ periodEndDate
1249
1179
  });
1250
1180
  } else if (periodTypes.size === 1 && periodTypes.has("duration")) {
1251
1181
  columns.push({
@@ -1265,13 +1195,15 @@ class XBRLFormBuilder {
1265
1195
  dimensionIdKey: dimensionInfo.dimensionIdKey
1266
1196
  },
1267
1197
  order: 0,
1268
- removable: false
1198
+ removable: false,
1199
+ periodStartDate,
1200
+ periodEndDate
1269
1201
  });
1270
1202
  } else {
1271
1203
  columns.push({
1272
1204
  id: "duration",
1273
1205
  title: `${dimensionInfo.memberLabel}`,
1274
- description: `${periodStartDate} / ${periodEndDate}`,
1206
+ description: this.formatPeriodDisplay(periodStartDate, periodEndDate),
1275
1207
  type: "dimension",
1276
1208
  dimensionData: {
1277
1209
  dimensionId: "duration",
@@ -1285,26 +1217,9 @@ class XBRLFormBuilder {
1285
1217
  dimensionIdKey: dimensionInfo.dimensionIdKey
1286
1218
  },
1287
1219
  order: 0,
1288
- removable: false
1289
- });
1290
- columns.push({
1291
- id: "instant",
1292
- title: `${dimensionInfo.memberLabel}`,
1293
- description: periodEndDate,
1294
- type: "dimension",
1295
- dimensionData: {
1296
- dimensionId: "instant",
1297
- axisId: dimensionInfo.axisId,
1298
- memberId: dimensionInfo.memberId,
1299
- memberValue: dimensionInfo.memberLabel,
1300
- memberLabel: dimensionInfo.memberLabel,
1301
- axis: dimensionInfo.axisLabel,
1302
- axisLabel: dimensionInfo.axisLabel,
1303
- memberKey: dimensionInfo.dimensionKey,
1304
- dimensionIdKey: dimensionInfo.dimensionIdKey
1305
- },
1306
- order: 1,
1307
- removable: false
1220
+ removable: false,
1221
+ periodStartDate,
1222
+ periodEndDate
1308
1223
  });
1309
1224
  }
1310
1225
  return columns;
@@ -1387,58 +1302,20 @@ class XBRLFormBuilder {
1387
1302
  ...typedMembers.map((c2) => `${c2.axisId}|[typed]`)
1388
1303
  ].join("::")
1389
1304
  };
1390
- if (periodTypes.size === 0 || periodTypes.size === 1 && periodTypes.has("duration")) {
1391
- columns.push({
1392
- id: `duration_${index}`,
1393
- title: `${columnTitle}`,
1394
- description: `${periodStartDate} / ${periodEndDate}`,
1395
- type: "dimension",
1396
- dimensionData: {
1397
- ...dimensionData,
1398
- dimensionId: `duration_${index}`
1399
- },
1400
- order: index * 2,
1401
- removable: false
1402
- });
1403
- } else if (periodTypes.size === 1 && periodTypes.has("instant")) {
1404
- columns.push({
1405
- id: `instant_${index}`,
1406
- title: `${columnTitle}`,
1407
- description: periodEndDate,
1408
- type: "dimension",
1409
- dimensionData: {
1410
- ...dimensionData,
1411
- dimensionId: `instant_${index}`
1412
- },
1413
- order: index * 2,
1414
- removable: false
1415
- });
1416
- } else {
1417
- columns.push({
1418
- id: `duration_${index}`,
1419
- title: `${columnTitle}`,
1420
- description: `${periodStartDate} / ${periodEndDate}`,
1421
- type: "dimension",
1422
- dimensionData: {
1423
- ...dimensionData,
1424
- dimensionId: `duration_${index}`
1425
- },
1426
- order: index * 2,
1427
- removable: false
1428
- });
1429
- columns.push({
1430
- id: `instant_${index}`,
1431
- title: `${columnTitle}`,
1432
- description: periodEndDate,
1433
- type: "dimension",
1434
- dimensionData: {
1435
- ...dimensionData,
1436
- dimensionId: `instant_${index}`
1437
- },
1438
- order: index * 2 + 1,
1439
- removable: false
1440
- });
1441
- }
1305
+ columns.push({
1306
+ id: `duration_${index}`,
1307
+ title: `${columnTitle}`,
1308
+ description: this.formatPeriodDisplay(periodStartDate, periodEndDate),
1309
+ type: "dimension",
1310
+ dimensionData: {
1311
+ ...dimensionData,
1312
+ dimensionId: `duration_${index}`
1313
+ },
1314
+ order: index,
1315
+ removable: false,
1316
+ periodStartDate,
1317
+ periodEndDate
1318
+ });
1442
1319
  });
1443
1320
  return columns;
1444
1321
  }
@@ -1568,14 +1445,16 @@ const form$1 = {
1568
1445
  yes: "Yes",
1569
1446
  no: "No",
1570
1447
  noRoleSelected: "No Role Selected",
1571
- pleaseSelectRole: "Please select a role from the list on the left."
1448
+ pleaseSelectRole: "Please select a role from the list on the left.",
1449
+ expandPanel: "Expand side panel",
1450
+ collapsePanel: "Collapse side panel"
1572
1451
  };
1573
1452
  const filter$1 = {
1574
1453
  selectRoles: "Select Roles",
1575
1454
  filterRoles: "Filter Roles",
1576
1455
  title: "Filter Roles",
1577
1456
  description: "Select the roles you want to display in the form. You can search and choose specific roles to focus on or manage all available roles.",
1578
- searchPlaceholder: "Search roles by name, ID, or URI...",
1457
+ searchPlaceholder: "Search..",
1579
1458
  clearSearch: "Clear search",
1580
1459
  showingResults: "Showing",
1581
1460
  of: "of",
@@ -1601,6 +1480,7 @@ const filter$1 = {
1601
1480
  };
1602
1481
  const column$1 = {
1603
1482
  addColumn: "Add Column",
1483
+ columnOptions: "Column Options",
1604
1484
  columnType: "Column Type",
1605
1485
  instantSingleDate: "Instant (single date)",
1606
1486
  durationDates: "Duration (start and end dates)",
@@ -1646,7 +1526,9 @@ const form = {
1646
1526
  yes: "Ja",
1647
1527
  no: "Nee",
1648
1528
  noRoleSelected: "Geen rol geselecteerd",
1649
- pleaseSelectRole: "Selecteer een rol uit de lijst aan de linkerkant."
1529
+ pleaseSelectRole: "Selecteer een rol uit de lijst aan de linkerkant.",
1530
+ expandPanel: "Zijpaneel uitvouwen",
1531
+ collapsePanel: "Zijpaneel inklappen"
1650
1532
  };
1651
1533
  const filter = {
1652
1534
  selectRoles: "Rollen selecteren",
@@ -1679,6 +1561,7 @@ const filter = {
1679
1561
  };
1680
1562
  const column = {
1681
1563
  addColumn: "Kolom toevoegen",
1564
+ columnOptions: "Kolomopties",
1682
1565
  columnType: "Kolomtype",
1683
1566
  instantSingleDate: "Moment (enkele datum)",
1684
1567
  durationDates: "Duur (begin- en einddatum)",
@@ -1948,7 +1831,7 @@ class DraftStorageService {
1948
1831
  /**
1949
1832
  * Create metadata snapshot from current form state
1950
1833
  */
1951
- createMetadataSnapshot(periodStartDate, periodEndDate, language, selectedRoleIds, allSections, typedMemberData, periodPreferences) {
1834
+ createMetadataSnapshot(periodStartDate, periodEndDate, language, selectedRoleIds, allSections, typedMemberData, periodPreferences, periodData) {
1952
1835
  return {
1953
1836
  periodStartDate,
1954
1837
  periodEndDate,
@@ -1957,6 +1840,7 @@ class DraftStorageService {
1957
1840
  customColumns: this.extractCustomColumns(allSections),
1958
1841
  typedMemberData,
1959
1842
  periodPreferences,
1843
+ periodData,
1960
1844
  schemaVersion: this.STORAGE_VERSION
1961
1845
  };
1962
1846
  }
@@ -2242,11 +2126,17 @@ let JupiterFormField = class extends LitElement {
2242
2126
  this.hideLabel = false;
2243
2127
  this._errors = [];
2244
2128
  this._touched = false;
2129
+ this._showPeriodPopup = false;
2245
2130
  }
2246
2131
  willUpdate(changedProperties) {
2247
2132
  if (changedProperties.has("value") || changedProperties.has("field")) {
2248
2133
  this._validateField();
2249
2134
  }
2135
+ if (changedProperties.has("field") && this.field) {
2136
+ if (this.conceptId.includes("DescriptionLocationNL") || this.columnId.startsWith("col-")) {
2137
+ 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}`);
2138
+ }
2139
+ }
2250
2140
  }
2251
2141
  _validateField() {
2252
2142
  var _a;
@@ -2303,6 +2193,49 @@ let JupiterFormField = class extends LitElement {
2303
2193
  bubbles: true
2304
2194
  }));
2305
2195
  }
2196
+ _handlePeriodIconClick() {
2197
+ this._showPeriodPopup = true;
2198
+ }
2199
+ _closePeriodPopup() {
2200
+ this._showPeriodPopup = false;
2201
+ }
2202
+ _handlePopupOverlayClick(e2) {
2203
+ if (e2.target === e2.currentTarget) {
2204
+ this._closePeriodPopup();
2205
+ }
2206
+ }
2207
+ _handlePeriodChange(event, type) {
2208
+ const target = event.target;
2209
+ const value = target.value;
2210
+ console.log(`📅 [FormField] Period change detected: type=${type}, value=${value}, conceptId=${this.conceptId}, columnId=${this.columnId}`);
2211
+ if (type === "instant") {
2212
+ this.periodInstantDate = value;
2213
+ } else if (type === "start") {
2214
+ this.periodStartDate = value;
2215
+ } else if (type === "end") {
2216
+ this.periodEndDate = value;
2217
+ }
2218
+ console.log(`📅 [FormField] Updated local period values: startDate=${this.periodStartDate}, endDate=${this.periodEndDate}, instantDate=${this.periodInstantDate}`);
2219
+ this.dispatchEvent(new CustomEvent("period-change", {
2220
+ detail: {
2221
+ fieldId: this.field.id,
2222
+ conceptId: this.conceptId,
2223
+ columnId: this.columnId,
2224
+ periodType: this.field.periodType,
2225
+ periodStartDate: this.periodStartDate,
2226
+ periodEndDate: this.periodEndDate,
2227
+ periodInstantDate: this.periodInstantDate
2228
+ },
2229
+ bubbles: true,
2230
+ composed: true
2231
+ // CRITICAL: Allows event to cross shadow DOM boundaries
2232
+ }));
2233
+ console.log(`🚀 [FormField] Dispatched period-change event with detail:`, {
2234
+ conceptId: this.conceptId,
2235
+ columnId: this.columnId,
2236
+ periodType: this.field.periodType
2237
+ });
2238
+ }
2306
2239
  _renderInput() {
2307
2240
  var _a;
2308
2241
  const hasErrors = this._errors.some((e2) => e2.severity === "error");
@@ -2415,8 +2348,97 @@ let JupiterFormField = class extends LitElement {
2415
2348
  return "text";
2416
2349
  }
2417
2350
  }
2351
+ _renderPeriodControls() {
2352
+ if (this.conceptId === "nl-cd_DescriptionLocationNL__a64trl") {
2353
+ console.log(`🔍 [FormField Render] Concept: ${this.conceptId}, ColumnId: ${this.columnId}, Field periodType: ${this.field.periodType}, Field periodStartDate: ${this.field.periodStartDate}, Field periodEndDate: ${this.field.periodEndDate}`);
2354
+ }
2355
+ if (!this.field.periodType) {
2356
+ return html``;
2357
+ }
2358
+ if (this.field.periodType === "instant") {
2359
+ return html`
2360
+ <div class="period-controls">
2361
+ <label>Date:</label>
2362
+ <input
2363
+ type="date"
2364
+ .value="${this.periodInstantDate || this.field.periodInstantDate || ""}"
2365
+ @change="${(e2) => this._handlePeriodChange(e2, "instant")}"
2366
+ ?disabled="${this.disabled}"
2367
+ />
2368
+ </div>
2369
+ `;
2370
+ } else if (this.field.periodType === "duration") {
2371
+ return html`
2372
+ <div class="period-controls">
2373
+ <label>From:</label>
2374
+ <input
2375
+ type="date"
2376
+ .value="${this.periodStartDate || this.field.periodStartDate || ""}"
2377
+ @change="${(e2) => this._handlePeriodChange(e2, "start")}"
2378
+ ?disabled="${this.disabled}"
2379
+ />
2380
+ <label>To:</label>
2381
+ <input
2382
+ type="date"
2383
+ .value="${this.periodEndDate || this.field.periodEndDate || ""}"
2384
+ @change="${(e2) => this._handlePeriodChange(e2, "end")}"
2385
+ ?disabled="${this.disabled}"
2386
+ />
2387
+ </div>
2388
+ `;
2389
+ }
2390
+ return html``;
2391
+ }
2392
+ _renderPeriodPopup() {
2393
+ return html`
2394
+ <div class="period-popup-overlay" @click="${this._handlePopupOverlayClick}">
2395
+ <div class="period-popup" @click="${(e2) => e2.stopPropagation()}">
2396
+ <div class="period-popup-header">
2397
+ <div class="period-popup-title">Edit Period</div>
2398
+ <button class="period-popup-close" @click="${this._closePeriodPopup}">
2399
+ ×
2400
+ </button>
2401
+ </div>
2402
+
2403
+ <div class="period-popup-content">
2404
+ ${this.field.periodType === "instant" ? html`
2405
+ <div class="period-controls">
2406
+ <label>Date:</label>
2407
+ <input
2408
+ type="date"
2409
+ .value="${this.periodInstantDate || this.field.periodInstantDate || ""}"
2410
+ @change="${(e2) => this._handlePeriodChange(e2, "instant")}"
2411
+ ?disabled="${this.disabled}"
2412
+ />
2413
+ </div>
2414
+ ` : html`
2415
+ <div class="period-controls">
2416
+ <label>From:</label>
2417
+ <input
2418
+ type="date"
2419
+ .value="${this.periodStartDate || this.field.periodStartDate || ""}"
2420
+ @change="${(e2) => this._handlePeriodChange(e2, "start")}"
2421
+ ?disabled="${this.disabled}"
2422
+ />
2423
+ </div>
2424
+ <div class="period-controls">
2425
+ <label>To:</label>
2426
+ <input
2427
+ type="date"
2428
+ .value="${this.periodEndDate || this.field.periodEndDate || ""}"
2429
+ @change="${(e2) => this._handlePeriodChange(e2, "end")}"
2430
+ ?disabled="${this.disabled}"
2431
+ />
2432
+ </div>
2433
+ `}
2434
+ </div>
2435
+ </div>
2436
+ </div>
2437
+ `;
2438
+ }
2418
2439
  render() {
2419
2440
  const showLabel = !this.hideLabel && this.field.type !== "boolean";
2441
+ const hasPeriodControl = this.field.periodType && (this.field.periodType === "instant" || this.field.periodType === "duration");
2420
2442
  return html`
2421
2443
  <div class="field-container">
2422
2444
  ${showLabel ? html`
@@ -2425,7 +2447,20 @@ let JupiterFormField = class extends LitElement {
2425
2447
  </label>
2426
2448
  ` : ""}
2427
2449
 
2428
- ${this._renderInput()}
2450
+ <div class="field-wrapper">
2451
+ ${this._renderInput()}
2452
+
2453
+ ${hasPeriodControl ? html`
2454
+ <button
2455
+ class="period-icon-btn"
2456
+ type="button"
2457
+ @click="${this._handlePeriodIconClick}"
2458
+ title="Edit period"
2459
+ >
2460
+ 📅
2461
+ </button>
2462
+ ` : ""}
2463
+ </div>
2429
2464
 
2430
2465
  ${this._errors.length > 0 && this._touched ? html`
2431
2466
  <div class="field-errors">
@@ -2437,6 +2472,8 @@ let JupiterFormField = class extends LitElement {
2437
2472
  </div>
2438
2473
  ` : ""}
2439
2474
  </div>
2475
+
2476
+ ${this._showPeriodPopup ? this._renderPeriodPopup() : ""}
2440
2477
  `;
2441
2478
  }
2442
2479
  };
@@ -2467,6 +2504,119 @@ JupiterFormField.styles = css`
2467
2504
  color: var(--jupiter-error-color, #d32f2f);
2468
2505
  }
2469
2506
 
2507
+ .field-wrapper {
2508
+ display: flex;
2509
+ align-items: center;
2510
+ gap: 8px;
2511
+ }
2512
+
2513
+ .period-icon-btn {
2514
+ background: transparent;
2515
+ border: none;
2516
+ cursor: pointer;
2517
+ font-size: 16px;
2518
+ padding: 4px;
2519
+ display: flex;
2520
+ align-items: center;
2521
+ justify-content: center;
2522
+ border-radius: 4px;
2523
+ transition: background-color 0.2s;
2524
+ opacity: 0.7;
2525
+ }
2526
+
2527
+ .period-icon-btn:hover {
2528
+ background-color: rgba(0, 0, 0, 0.05);
2529
+ opacity: 1;
2530
+ }
2531
+
2532
+ .period-popup-overlay {
2533
+ position: fixed;
2534
+ top: 0;
2535
+ left: 0;
2536
+ right: 0;
2537
+ bottom: 0;
2538
+ background: rgba(0, 0, 0, 0.5);
2539
+ display: flex;
2540
+ align-items: center;
2541
+ justify-content: center;
2542
+ z-index: 10000;
2543
+ }
2544
+
2545
+ .period-popup {
2546
+ background: white;
2547
+ border-radius: 8px;
2548
+ padding: 24px;
2549
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
2550
+ max-width: 400px;
2551
+ width: 90%;
2552
+ }
2553
+
2554
+ .period-popup-header {
2555
+ display: flex;
2556
+ justify-content: space-between;
2557
+ align-items: center;
2558
+ margin-bottom: 20px;
2559
+ }
2560
+
2561
+ .period-popup-title {
2562
+ font-size: 18px;
2563
+ font-weight: 600;
2564
+ color: var(--jupiter-text-primary, #333);
2565
+ }
2566
+
2567
+ .period-popup-close {
2568
+ background: transparent;
2569
+ border: none;
2570
+ font-size: 24px;
2571
+ cursor: pointer;
2572
+ padding: 0;
2573
+ width: 32px;
2574
+ height: 32px;
2575
+ display: flex;
2576
+ align-items: center;
2577
+ justify-content: center;
2578
+ border-radius: 4px;
2579
+ transition: background-color 0.2s;
2580
+ }
2581
+
2582
+ .period-popup-close:hover {
2583
+ background-color: rgba(0, 0, 0, 0.05);
2584
+ }
2585
+
2586
+ .period-popup-content {
2587
+ display: flex;
2588
+ flex-direction: column;
2589
+ gap: 16px;
2590
+ }
2591
+
2592
+ .period-popup-content .period-controls {
2593
+ display: grid;
2594
+ grid-template-columns: 60px 1fr;
2595
+ gap: 12px;
2596
+ align-items: center;
2597
+ margin-top: 0;
2598
+ }
2599
+
2600
+ .period-popup-content .period-controls label {
2601
+ font-size: 14px;
2602
+ font-weight: 500;
2603
+ color: var(--jupiter-text-primary, #333);
2604
+ text-align: right;
2605
+ }
2606
+
2607
+ .period-popup-content .period-controls input[type="date"] {
2608
+ padding: 8px 10px;
2609
+ font-size: 14px;
2610
+ border: 1px solid var(--jupiter-border-color, #ddd);
2611
+ border-radius: 4px;
2612
+ }
2613
+
2614
+ .period-popup-content .period-controls input[type="date"]:focus {
2615
+ outline: none;
2616
+ border-color: var(--jupiter-primary-color, #1976d2);
2617
+ box-shadow: 0 0 0 2px var(--jupiter-primary-color-light, rgba(25, 118, 210, 0.2));
2618
+ }
2619
+
2470
2620
  .field-input {
2471
2621
  width: 100%;
2472
2622
  padding: 6px 8px; /* Reduced padding for table cells */
@@ -2545,6 +2695,34 @@ JupiterFormField.styles = css`
2545
2695
  margin: 0;
2546
2696
  width: auto;
2547
2697
  }
2698
+
2699
+ .period-controls {
2700
+ margin-top: 4px;
2701
+ display: flex;
2702
+ gap: 8px;
2703
+ align-items: center;
2704
+ font-size: 12px;
2705
+ }
2706
+
2707
+ .period-controls label {
2708
+ color: var(--jupiter-text-secondary, #666);
2709
+ font-weight: 500;
2710
+ font-size: 11px;
2711
+ margin: 0;
2712
+ }
2713
+
2714
+ .period-controls input[type="date"] {
2715
+ padding: 4px 6px;
2716
+ font-size: 11px;
2717
+ border: 1px solid var(--jupiter-border-color, #ddd);
2718
+ border-radius: 3px;
2719
+ width: 120px;
2720
+ }
2721
+
2722
+ .period-controls input[type="date"]:focus {
2723
+ outline: none;
2724
+ border-color: var(--jupiter-primary-color, #1976d2);
2725
+ }
2548
2726
  `;
2549
2727
  __decorateClass$5([
2550
2728
  n2({ type: Object })
@@ -2570,12 +2748,24 @@ __decorateClass$5([
2570
2748
  __decorateClass$5([
2571
2749
  n2({ type: Boolean })
2572
2750
  ], JupiterFormField.prototype, "hideLabel", 2);
2751
+ __decorateClass$5([
2752
+ n2({ type: String })
2753
+ ], JupiterFormField.prototype, "periodStartDate", 2);
2754
+ __decorateClass$5([
2755
+ n2({ type: String })
2756
+ ], JupiterFormField.prototype, "periodEndDate", 2);
2757
+ __decorateClass$5([
2758
+ n2({ type: String })
2759
+ ], JupiterFormField.prototype, "periodInstantDate", 2);
2573
2760
  __decorateClass$5([
2574
2761
  r()
2575
2762
  ], JupiterFormField.prototype, "_errors", 2);
2576
2763
  __decorateClass$5([
2577
2764
  r()
2578
2765
  ], JupiterFormField.prototype, "_touched", 2);
2766
+ __decorateClass$5([
2767
+ r()
2768
+ ], JupiterFormField.prototype, "_showPeriodPopup", 2);
2579
2769
  JupiterFormField = __decorateClass$5([
2580
2770
  t$1("jupiter-form-field")
2581
2771
  ], JupiterFormField);
@@ -2635,6 +2825,17 @@ let JupiterConceptTree = class extends LitElement {
2635
2825
  bubbles: true
2636
2826
  }));
2637
2827
  }
2828
+ _handlePeriodChange(event) {
2829
+ console.log(`🌲 [ConceptTree] Received period-change event:`, event.detail);
2830
+ event.stopPropagation();
2831
+ this.dispatchEvent(new CustomEvent("period-change", {
2832
+ detail: event.detail,
2833
+ bubbles: true,
2834
+ composed: true
2835
+ // CRITICAL: Allows event to cross shadow DOM boundaries
2836
+ }));
2837
+ console.log(`🌲 [ConceptTree] Forwarded period-change event to form-section`);
2838
+ }
2638
2839
  render() {
2639
2840
  const hasChildren = this.concept.children && this.concept.children.length > 0;
2640
2841
  const level = this.concept.level || 0;
@@ -2669,10 +2870,14 @@ let JupiterConceptTree = class extends LitElement {
2669
2870
  .conceptType="${this.concept.type}"
2670
2871
  .columnId="${column2.id}"
2671
2872
  .value="${this._getFieldValue(field)}"
2873
+ .periodStartDate="${field.periodStartDate || column2.periodStartDate}"
2874
+ .periodEndDate="${field.periodEndDate || column2.periodEndDate}"
2875
+ .periodInstantDate="${field.periodInstantDate || (field.periodType === "instant" ? field.periodEndDate || field.periodStartDate : void 0)}"
2672
2876
  .disabled="${this.disabled}"
2673
2877
  .locale="${this.locale}"
2674
2878
  .hideLabel="${true}"
2675
2879
  @field-change="${this._handleFieldChange}"
2880
+ @period-change="${this._handlePeriodChange}"
2676
2881
  ></jupiter-form-field>
2677
2882
  ` : ""}
2678
2883
  </td>
@@ -3429,6 +3634,8 @@ let JupiterFormSection = class extends LitElement {
3429
3634
  this._expanded = true;
3430
3635
  this._showAddColumnDialog = false;
3431
3636
  this._sectionPeriodType = "duration";
3637
+ this._openMenuColumnId = null;
3638
+ this._insertAfterColumnId = null;
3432
3639
  this._expandedConcepts = /* @__PURE__ */ new Set();
3433
3640
  this._allTreeExpanded = false;
3434
3641
  }
@@ -3437,6 +3644,11 @@ let JupiterFormSection = class extends LitElement {
3437
3644
  this._expanded = this.section.expanded !== false;
3438
3645
  this._determinePeriodType();
3439
3646
  this._checkAndExpandFirstSection();
3647
+ document.addEventListener("click", () => this._closeColumnMenu());
3648
+ }
3649
+ disconnectedCallback() {
3650
+ super.disconnectedCallback();
3651
+ document.removeEventListener("click", () => this._closeColumnMenu());
3440
3652
  }
3441
3653
  updated(changedProperties) {
3442
3654
  super.updated(changedProperties);
@@ -3498,6 +3710,7 @@ let JupiterFormSection = class extends LitElement {
3498
3710
  }));
3499
3711
  }
3500
3712
  _handleRemoveColumn(columnId) {
3713
+ this._openMenuColumnId = null;
3501
3714
  this.dispatchEvent(new CustomEvent("column-remove", {
3502
3715
  detail: {
3503
3716
  columnId,
@@ -3506,6 +3719,19 @@ let JupiterFormSection = class extends LitElement {
3506
3719
  bubbles: true
3507
3720
  }));
3508
3721
  }
3722
+ _toggleColumnMenu(columnId, event) {
3723
+ event.stopPropagation();
3724
+ this._openMenuColumnId = this._openMenuColumnId === columnId ? null : columnId;
3725
+ }
3726
+ _closeColumnMenu() {
3727
+ this._openMenuColumnId = null;
3728
+ }
3729
+ _handleAddColumnFromMenu(columnId, event) {
3730
+ event.stopPropagation();
3731
+ this._openMenuColumnId = null;
3732
+ this._insertAfterColumnId = columnId;
3733
+ this._handleAddColumn();
3734
+ }
3509
3735
  _handleAddColumn() {
3510
3736
  const buttonPeriodType = this._determineButtonPeriodType();
3511
3737
  this._sectionPeriodType = buttonPeriodType;
@@ -3549,18 +3775,33 @@ let JupiterFormSection = class extends LitElement {
3549
3775
  this.dispatchEvent(new CustomEvent("column-add-request", {
3550
3776
  detail: {
3551
3777
  sectionId: this.section.id,
3552
- columnRequest: event.detail
3778
+ columnRequest: event.detail,
3779
+ insertAfterColumnId: this._insertAfterColumnId
3780
+ // Include position info
3553
3781
  },
3554
3782
  bubbles: true
3555
3783
  }));
3784
+ this._insertAfterColumnId = null;
3556
3785
  }
3557
3786
  _handleFieldChange(event) {
3558
3787
  event.stopPropagation();
3559
3788
  this.dispatchEvent(new CustomEvent("field-change", {
3560
3789
  detail: event.detail,
3561
- bubbles: true
3790
+ bubbles: true,
3791
+ composed: true
3562
3792
  }));
3563
3793
  }
3794
+ _handlePeriodChange(event) {
3795
+ console.log(`📋 [FormSection] Received period-change event:`, event.detail);
3796
+ event.stopPropagation();
3797
+ this.dispatchEvent(new CustomEvent("period-change", {
3798
+ detail: event.detail,
3799
+ bubbles: true,
3800
+ composed: true
3801
+ // CRITICAL: Allows event to cross shadow DOM boundaries
3802
+ }));
3803
+ console.log(`📋 [FormSection] Forwarded period-change event to dynamic-form`);
3804
+ }
3564
3805
  _flattenConcepts(concepts, expanded = /* @__PURE__ */ new Set()) {
3565
3806
  const result = [];
3566
3807
  for (const concept of concepts) {
@@ -3701,29 +3942,40 @@ let JupiterFormSection = class extends LitElement {
3701
3942
  `)}
3702
3943
  </div>
3703
3944
  ` : ""}
3704
-
3705
- ${column2.removable ? html`
3945
+ </div>
3946
+
3947
+ <!-- Column menu icon (3 vertical dots) -->
3948
+ <div
3949
+ class="column-menu-icon"
3950
+ @click="${(e2) => this._toggleColumnMenu(column2.id, e2)}"
3951
+ title="${I18n.t("column.columnOptions")}"
3952
+ >⋮</div>
3953
+
3954
+ <!-- Context menu -->
3955
+ ${this._openMenuColumnId === column2.id ? html`
3956
+ <div class="column-context-menu">
3706
3957
  <button
3707
- class="remove-column-btn"
3708
- @click="${(e2) => {
3958
+ class="column-context-menu-item"
3959
+ @click="${(e2) => this._handleAddColumnFromMenu(column2.id, e2)}"
3960
+ >
3961
+ ${I18n.t("column.addColumn")}
3962
+ </button>
3963
+ ${column2.removable ? html`
3964
+ <button
3965
+ class="column-context-menu-item remove"
3966
+ @click="${(e2) => {
3709
3967
  e2.stopPropagation();
3710
3968
  this._handleRemoveColumn(column2.id);
3711
3969
  }}"
3712
- title="${I18n.t("column.removeColumn")}"
3713
- >×</button>
3714
- ` : ""}
3715
- </div>
3970
+ >
3971
+ ${I18n.t("column.removeColumn")}
3972
+ </button>
3973
+ ` : ""}
3974
+ </div>
3975
+ ` : ""}
3716
3976
  </th>
3717
3977
  `;
3718
3978
  })}
3719
- <th class="header-cell add-column-only">
3720
- <button class="add-column-btn" @click="${(e2) => {
3721
- e2.stopPropagation();
3722
- this._handleAddColumn();
3723
- }}" title="${I18n.t("column.addColumn")}">
3724
- + ${I18n.t("column.addColumn")}
3725
- </button>
3726
- </th>
3727
3979
  </tr>
3728
3980
  </thead>
3729
3981
  <tbody class="table-body">
@@ -3737,6 +3989,7 @@ let JupiterFormSection = class extends LitElement {
3737
3989
  .locale="${this.locale}"
3738
3990
  .expandedConcepts="${this._expandedConcepts}"
3739
3991
  @field-change="${this._handleFieldChange}"
3992
+ @period-change="${this._handlePeriodChange}"
3740
3993
  @concept-expand="${this._handleConceptExpand}"
3741
3994
  ></jupiter-concept-tree>
3742
3995
  </tr>
@@ -3870,6 +4123,8 @@ JupiterFormSection.styles = css`
3870
4123
  width: 180px;
3871
4124
  font-size: 14px;
3872
4125
  vertical-align: middle;
4126
+ position: relative;
4127
+ overflow: visible;
3873
4128
  }
3874
4129
 
3875
4130
  .header-cell.concept-column {
@@ -3885,47 +4140,69 @@ JupiterFormSection.styles = css`
3885
4140
  position: relative;
3886
4141
  }
3887
4142
 
3888
- /* Special styling for the Add Column button-only column */
3889
- .header-cell.add-column-only {
3890
- width: 15%;
3891
- min-width: 100px;
3892
- max-width: 150px;
3893
- }
3894
-
3895
- .remove-column-btn {
4143
+ .column-menu-icon {
3896
4144
  position: absolute;
3897
- top: 4px;
3898
- right: 4px;
3899
- width: 20px;
3900
- height: 20px;
4145
+ top: 8px;
4146
+ right: 0px;
4147
+ width: 24px;
4148
+ height: 24px;
4149
+ background: transparent;
4150
+ color: var(--jupiter-text-secondary, #666);
3901
4151
  border: none;
3902
- background: var(--jupiter-error-color, #d32f2f);
3903
- color: white;
3904
- border-radius: 50%;
3905
- font-size: 12px;
4152
+ font-size: 20px;
3906
4153
  cursor: pointer;
3907
4154
  display: flex;
3908
4155
  align-items: center;
3909
4156
  justify-content: center;
4157
+ z-index: 10;
4158
+ transition: all 0.2s ease;
4159
+ line-height: 1;
4160
+ font-weight: bold;
4161
+ padding: 0;
4162
+ border-radius: 4px;
3910
4163
  }
3911
4164
 
3912
- .remove-column-btn:hover {
3913
- background: var(--jupiter-error-color-dark, #b71c1c);
4165
+ .column-menu-icon:hover {
4166
+ background: var(--jupiter-background-light, #f0f0f0);
4167
+ color: var(--jupiter-text-primary, #333);
3914
4168
  }
3915
4169
 
3916
- .add-column-btn {
3917
- background: var(--jupiter-primary-color, #667eea);
3918
- color: white;
3919
- border: none;
3920
- padding: 8px 16px;
4170
+ .column-context-menu {
4171
+ position: absolute;
4172
+ top: 32px;
4173
+ right: 4px;
4174
+ background: white;
4175
+ border: 1px solid var(--jupiter-border-color, #ddd);
3921
4176
  border-radius: 4px;
4177
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
4178
+ z-index: 1000;
4179
+ min-width: 150px;
4180
+ padding: 4px 0;
4181
+ }
4182
+
4183
+ .column-context-menu-item {
4184
+ padding: 8px 16px;
3922
4185
  cursor: pointer;
3923
- font-size: 12px;
3924
- margin: 8px;
4186
+ font-size: 14px;
4187
+ color: var(--jupiter-text-primary, #333);
4188
+ transition: background 0.2s ease;
4189
+ border: none;
4190
+ background: transparent;
4191
+ width: 100%;
4192
+ text-align: left;
4193
+ display: block;
3925
4194
  }
3926
4195
 
3927
- .add-column-btn:hover {
3928
- background: var(--jupiter-primary-color-dark, #5a6fd8);
4196
+ .column-context-menu-item:hover {
4197
+ background: var(--jupiter-background-light, #f5f5f5);
4198
+ }
4199
+
4200
+ .column-context-menu-item.remove {
4201
+ color: var(--jupiter-error-color, #d32f2f);
4202
+ }
4203
+
4204
+ .column-context-menu-item.remove:hover {
4205
+ background: var(--jupiter-error-light, #ffebee);
3929
4206
  }
3930
4207
 
3931
4208
  /* Column header content styling */
@@ -4031,6 +4308,12 @@ __decorateClass$2([
4031
4308
  __decorateClass$2([
4032
4309
  r()
4033
4310
  ], JupiterFormSection.prototype, "_sectionPeriodType", 2);
4311
+ __decorateClass$2([
4312
+ r()
4313
+ ], JupiterFormSection.prototype, "_openMenuColumnId", 2);
4314
+ __decorateClass$2([
4315
+ r()
4316
+ ], JupiterFormSection.prototype, "_insertAfterColumnId", 2);
4034
4317
  __decorateClass$2([
4035
4318
  r()
4036
4319
  ], JupiterFormSection.prototype, "_expandedConcepts", 2);
@@ -4352,7 +4635,7 @@ let JupiterFilterRolesDialog = class extends LitElement {
4352
4635
  ${this._filteredRoles.map((role) => {
4353
4636
  var _a;
4354
4637
  const isSelected = this._tempSelectedRoles.has(role.id);
4355
- const showPeriodControls = role.showPeriodControl === true;
4638
+ role.showPeriodControl === true;
4356
4639
  const preferences = this._tempPeriodPreferences[role.id] || { showDuration: true, showInstant: true };
4357
4640
  return html`
4358
4641
  <div class="role-item">
@@ -4368,32 +4651,6 @@ let JupiterFilterRolesDialog = class extends LitElement {
4368
4651
  <p class="role-description">${I18n.t("filter.uri")}: ${role.metadata.roleURI}</p>
4369
4652
  ` : ""}
4370
4653
 
4371
- ${showPeriodControls ? html`
4372
- <div class="period-controls">
4373
- <p class="period-controls-label">${I18n.t("filter.showPeriodColumn")}</p>
4374
- <div class="period-checkboxes">
4375
- <label class="period-checkbox-item">
4376
- <input
4377
- type="checkbox"
4378
- class="period-checkbox"
4379
- .checked="${preferences.showDuration}"
4380
- @change="${(e2) => this._handlePeriodCheckboxChange(e2, role.id, "duration")}"
4381
- />
4382
- <span class="period-checkbox-label">${I18n.t("filter.duration")}</span>
4383
- </label>
4384
- <label class="period-checkbox-item">
4385
- <input
4386
- type="checkbox"
4387
- class="period-checkbox"
4388
- .checked="${preferences.showInstant}"
4389
- @change="${(e2) => this._handlePeriodCheckboxChange(e2, role.id, "instant")}"
4390
- />
4391
- <span class="period-checkbox-label">${I18n.t("filter.instant")}</span>
4392
- </label>
4393
- </div>
4394
- </div>
4395
- ` : ""}
4396
-
4397
4654
  <div class="period-controls">
4398
4655
  <p class="period-controls-label">${I18n.t("filter.additionalOptions")}</p>
4399
4656
  <div class="period-checkboxes">
@@ -4815,6 +5072,8 @@ let JupiterDynamicForm = class extends LitElement {
4815
5072
  this._formData = {};
4816
5073
  this._draftLoaded = false;
4817
5074
  this._preservedFormData = {};
5075
+ this._periodData = {};
5076
+ this._preservedPeriodData = {};
4818
5077
  this._typedMemberData = {};
4819
5078
  this._preservedTypedMemberData = {};
4820
5079
  this._columns = [];
@@ -4828,11 +5087,19 @@ let JupiterDynamicForm = class extends LitElement {
4828
5087
  this._showFilterDialog = false;
4829
5088
  this._periodPreferences = {};
4830
5089
  this._activeSidePanelRoleId = null;
5090
+ this._sidePanelSearchQuery = "";
5091
+ this._sidePanelCollapsed = false;
4831
5092
  this._adminRoleConfigs = {};
4832
5093
  this._skipDraftLoading = false;
4833
5094
  }
4834
5095
  connectedCallback() {
4835
5096
  super.connectedCallback();
5097
+ this.addEventListener("period-change", (e2) => {
5098
+ console.log(`🌍 [GLOBAL DynamicForm] Caught period-change event on element:`, e2);
5099
+ const customEvent = e2;
5100
+ console.log(`🌍 [GLOBAL DynamicForm] Event detail:`, customEvent.detail);
5101
+ this._handlePeriodChange(customEvent);
5102
+ });
4836
5103
  this._initializeForm();
4837
5104
  }
4838
5105
  updated(changedProperties) {
@@ -5214,6 +5481,29 @@ let JupiterDynamicForm = class extends LitElement {
5214
5481
  bubbles: true
5215
5482
  }));
5216
5483
  }
5484
+ _handlePeriodChange(event) {
5485
+ console.log(`🎯 [DynamicForm] _handlePeriodChange called with event:`, event);
5486
+ 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}`);
5489
+ const updatedPeriodData = { ...this._periodData };
5490
+ if (!updatedPeriodData[conceptId]) {
5491
+ updatedPeriodData[conceptId] = {};
5492
+ }
5493
+ updatedPeriodData[conceptId] = {
5494
+ ...updatedPeriodData[conceptId],
5495
+ [columnId]: {
5496
+ startDate: periodStartDate,
5497
+ endDate: periodEndDate,
5498
+ instantDate: periodInstantDate
5499
+ }
5500
+ };
5501
+ this._periodData = updatedPeriodData;
5502
+ console.log(`💾 Period data stored for [${conceptId}][${columnId}]:`, this._periodData[conceptId][columnId]);
5503
+ console.log(`📦 Full period data state:`, JSON.stringify(this._periodData, null, 2));
5504
+ this._dirty = true;
5505
+ this.requestUpdate();
5506
+ }
5217
5507
  /**
5218
5508
  * Generate a unique concept key that includes section context
5219
5509
  */
@@ -5282,8 +5572,8 @@ let JupiterDynamicForm = class extends LitElement {
5282
5572
  }));
5283
5573
  }
5284
5574
  _handleColumnAddRequest(event) {
5285
- const { sectionId, columnRequest } = event.detail;
5286
- this._addColumnFromRequest(columnRequest, sectionId);
5575
+ const { sectionId, columnRequest, insertAfterColumnId } = event.detail;
5576
+ this._addColumnFromRequest(columnRequest, sectionId, insertAfterColumnId);
5287
5577
  }
5288
5578
  _getAvailableDimensionsForSection(sectionId) {
5289
5579
  var _a, _b, _c;
@@ -5330,7 +5620,24 @@ let JupiterDynamicForm = class extends LitElement {
5330
5620
  });
5331
5621
  return availableDimensions;
5332
5622
  }
5333
- _addColumnFromRequest(request, sectionId) {
5623
+ /**
5624
+ * Format period range for display - shows only year when both dates are in same year
5625
+ * @param startDate - Period start date in YYYY-MM-DD format
5626
+ * @param endDate - Period end date in YYYY-MM-DD format
5627
+ * @returns Formatted period string (e.g., "2025" or "2025-01-01 / 2026-12-31")
5628
+ */
5629
+ _formatPeriodDisplay(startDate, endDate) {
5630
+ if (!startDate || !endDate) {
5631
+ return `${startDate || ""} / ${endDate || ""}`;
5632
+ }
5633
+ const startYear = startDate.substring(0, 4);
5634
+ const endYear = endDate.substring(0, 4);
5635
+ if (startYear === endYear) {
5636
+ return startYear;
5637
+ }
5638
+ return `${startDate} / ${endDate}`;
5639
+ }
5640
+ _addColumnFromRequest(request, sectionId, insertAfterColumnId) {
5334
5641
  var _a, _b, _c, _d, _e;
5335
5642
  const timestamp = Date.now();
5336
5643
  const newColumnId = `col-${timestamp}`;
@@ -5340,7 +5647,7 @@ let JupiterDynamicForm = class extends LitElement {
5340
5647
  title = request.instantDate || "";
5341
5648
  description = "";
5342
5649
  } else if (request.periodType === "duration" || request.periodType === "mixed") {
5343
- title = `${request.startDate} / ${request.endDate}`;
5650
+ title = this._formatPeriodDisplay(request.startDate, request.endDate);
5344
5651
  description = "";
5345
5652
  }
5346
5653
  let dimensionData = {
@@ -5360,7 +5667,7 @@ let JupiterDynamicForm = class extends LitElement {
5360
5667
  dimensionKeys.push(`${dimSelection.axisId}|${dimSelection.memberId}`);
5361
5668
  }
5362
5669
  }
5363
- const periodPart = request.periodType === "instant" ? `(${request.instantDate})` : `(${request.startDate} / ${request.endDate})`;
5670
+ const periodPart = request.periodType === "instant" ? `(${request.instantDate})` : `(${this._formatPeriodDisplay(request.startDate, request.endDate)})`;
5364
5671
  if (dimensionParts.length > 0) {
5365
5672
  title = `${dimensionParts.join(" | ")} ${periodPart}`;
5366
5673
  dimensionData = {
@@ -5384,7 +5691,7 @@ let JupiterDynamicForm = class extends LitElement {
5384
5691
  const axisLabel = ((_d = dimension.labels.find((l2) => l2.role === "http://www.xbrl.org/2003/role/label")) == null ? void 0 : _d.label) || dimension.conceptName;
5385
5692
  const firstMember = dimension.members[0];
5386
5693
  const memberLabel = ((_e = firstMember.labels.find((l2) => l2.role === "http://www.xbrl.org/2003/role/label")) == null ? void 0 : _e.label) || firstMember.conceptName;
5387
- const periodPart = request.periodType === "instant" ? `(${request.instantDate})` : `(${request.startDate} / ${request.endDate})`;
5694
+ const periodPart = request.periodType === "instant" ? `(${request.instantDate})` : `(${this._formatPeriodDisplay(request.startDate, request.endDate)})`;
5388
5695
  title = `${memberLabel} ${periodPart}`;
5389
5696
  dimensionData = {
5390
5697
  dimensionId: newColumnId,
@@ -5410,7 +5717,10 @@ let JupiterDynamicForm = class extends LitElement {
5410
5717
  type: dimensionData.memberKey ? "dimension" : "dimension",
5411
5718
  order: this._columns.length,
5412
5719
  removable: true,
5413
- dimensionData
5720
+ dimensionData,
5721
+ // CRITICAL: Add period dates so they can be saved to draft and restored
5722
+ periodStartDate: request.periodType === "instant" ? request.instantDate : request.startDate,
5723
+ periodEndDate: request.periodType === "instant" ? request.instantDate : request.endDate
5414
5724
  };
5415
5725
  if (request.selectedDimensions && request.selectedDimensions.length > 0) {
5416
5726
  const typedMembers = {};
@@ -5442,7 +5752,20 @@ let JupiterDynamicForm = class extends LitElement {
5442
5752
  if (!targetSection.columns) {
5443
5753
  targetSection.columns = [...this._columns];
5444
5754
  }
5445
- targetSection.columns = [...targetSection.columns, newColumn];
5755
+ if (insertAfterColumnId) {
5756
+ const insertIndex = targetSection.columns.findIndex((col) => col.id === insertAfterColumnId);
5757
+ if (insertIndex !== -1) {
5758
+ targetSection.columns = [
5759
+ ...targetSection.columns.slice(0, insertIndex + 1),
5760
+ newColumn,
5761
+ ...targetSection.columns.slice(insertIndex + 1)
5762
+ ];
5763
+ } else {
5764
+ targetSection.columns = [...targetSection.columns, newColumn];
5765
+ }
5766
+ } else {
5767
+ targetSection.columns = [...targetSection.columns, newColumn];
5768
+ }
5446
5769
  }
5447
5770
  }
5448
5771
  this._replicateFieldsForNewColumn(newColumnId, request, sectionId);
@@ -5523,9 +5846,12 @@ let JupiterDynamicForm = class extends LitElement {
5523
5846
  disabled: existingField.disabled,
5524
5847
  validation: existingField.validation,
5525
5848
  defaultValue: existingField.defaultValue,
5849
+ periodType: concept.periodType,
5850
+ // Add periodType from concept
5526
5851
  // Set period dates from the add column request
5527
5852
  periodStartDate: request.periodType === "instant" ? request.instantDate : request.startDate,
5528
- periodEndDate: request.periodType === "instant" ? request.instantDate : request.endDate
5853
+ periodEndDate: request.periodType === "instant" ? request.instantDate : request.endDate,
5854
+ periodInstantDate: concept.periodType === "instant" ? request.instantDate || request.startDate : void 0
5529
5855
  };
5530
5856
  } else {
5531
5857
  field = {
@@ -5539,9 +5865,12 @@ let JupiterDynamicForm = class extends LitElement {
5539
5865
  disabled: false,
5540
5866
  validation: [],
5541
5867
  defaultValue: "",
5868
+ periodType: concept.periodType,
5869
+ // Add periodType from concept
5542
5870
  // Set period dates from the add column request
5543
5871
  periodStartDate: request.periodType === "instant" ? request.instantDate : request.startDate,
5544
- periodEndDate: request.periodType === "instant" ? request.instantDate : request.endDate
5872
+ periodEndDate: request.periodType === "instant" ? request.instantDate : request.endDate,
5873
+ periodInstantDate: concept.periodType === "instant" ? request.instantDate || request.startDate : void 0
5545
5874
  };
5546
5875
  }
5547
5876
  if (!concept.fields) {
@@ -5612,7 +5941,8 @@ let JupiterDynamicForm = class extends LitElement {
5612
5941
  this._selectedRoleIds,
5613
5942
  this._allSections,
5614
5943
  this._typedMemberData,
5615
- this._periodPreferences
5944
+ this._periodPreferences,
5945
+ this._periodData
5616
5946
  );
5617
5947
  const saved = this._draftStorageService.saveDraft(draftData, metadata);
5618
5948
  this.dynaformsFacts = draftData;
@@ -5712,6 +6042,10 @@ let JupiterDynamicForm = class extends LitElement {
5712
6042
  this._preservedTypedMemberData = {};
5713
6043
  console.log("🔄 Restored typed member data");
5714
6044
  }
6045
+ if (metadata.periodData) {
6046
+ this._periodData = metadata.periodData;
6047
+ console.log("🔄 Restored custom field-level period data:", Object.keys(this._periodData).length, "concepts");
6048
+ }
5715
6049
  if (metadata.periodPreferences) {
5716
6050
  this._periodPreferences = metadata.periodPreferences;
5717
6051
  console.log("🔄 Restored period preferences (including previous year settings):", this._periodPreferences);
@@ -5729,6 +6063,8 @@ let JupiterDynamicForm = class extends LitElement {
5729
6063
  this._allSections = this._filterRolesByFinancialStatementsType(this._allSections);
5730
6064
  }
5731
6065
  console.log("✅ Schema rebuilt with restored period preferences");
6066
+ console.log("🔄 Applying custom period data to schema fields...");
6067
+ this._applyCustomPeriodDataToFields();
5732
6068
  if (metadata.customColumns && metadata.customColumns.length > 0) {
5733
6069
  this._mergeAdditionalCustomColumns(metadata.customColumns);
5734
6070
  console.log(`🔄 Merged ${metadata.customColumns.length} additional custom columns`);
@@ -5741,6 +6077,7 @@ let JupiterDynamicForm = class extends LitElement {
5741
6077
  }
5742
6078
  }
5743
6079
  const restoredFormData = {};
6080
+ const restoredPeriodData = {};
5744
6081
  formData.forEach((entry) => {
5745
6082
  let { conceptId, value, columnId, period } = entry;
5746
6083
  if (!columnId && period) {
@@ -5757,9 +6094,33 @@ let JupiterDynamicForm = class extends LitElement {
5757
6094
  }
5758
6095
  restoredFormData[conceptIdToUse][columnId] = value;
5759
6096
  console.log(`📦 Restored: ${conceptIdToUse}[${columnId}] = ${value}`);
6097
+ if (period) {
6098
+ if (!restoredPeriodData[conceptIdToUse]) {
6099
+ restoredPeriodData[conceptIdToUse] = {};
6100
+ }
6101
+ if (period.type === "instant") {
6102
+ restoredPeriodData[conceptIdToUse][columnId] = {
6103
+ instantDate: period.date
6104
+ };
6105
+ console.log(`📅 [Restore Period] Extracted instant date for ${conceptIdToUse}/${columnId}: ${period.date}`);
6106
+ } else if (period.type === "duration") {
6107
+ restoredPeriodData[conceptIdToUse][columnId] = {
6108
+ startDate: period.startDate,
6109
+ endDate: period.endDate
6110
+ };
6111
+ console.log(`📅 [Restore Period] Extracted duration dates for ${conceptIdToUse}/${columnId}: ${period.startDate} - ${period.endDate}`);
6112
+ }
6113
+ }
5760
6114
  });
5761
6115
  this._formData = { ...this._formData, ...restoredFormData };
5762
6116
  console.log(`🔄 Restored ${Object.keys(restoredFormData).length} concepts with data`);
6117
+ this._periodData = {
6118
+ ...this._periodData,
6119
+ ...metadata.periodData || {},
6120
+ ...restoredPeriodData
6121
+ };
6122
+ console.log(`📅 [Period Restore] Merged period data: ${Object.keys(this._periodData).length} concepts with custom periods`);
6123
+ console.log(`📅 [Period Restore] Full _periodData after merge:`, JSON.stringify(this._periodData, null, 2));
5763
6124
  if (this._selectedRoleIds.length > 0) {
5764
6125
  this._applyRoleFilter();
5765
6126
  }
@@ -5888,16 +6249,20 @@ let JupiterDynamicForm = class extends LitElement {
5888
6249
  this._allSections.forEach((section2) => {
5889
6250
  const savedColumns = columnsBySection.get(section2.id);
5890
6251
  if (savedColumns) {
5891
- section2.columns = savedColumns.map((col) => ({
5892
- id: col.columnId,
5893
- title: col.label,
5894
- type: col.dimensionData ? "dimension" : "base",
5895
- periodStartDate: col.startDate || col.date,
5896
- periodEndDate: col.endDate || col.date,
5897
- dimensionData: col.dimensionData,
5898
- order: 0,
5899
- removable: col.columnId !== "duration" && col.columnId !== "instant"
5900
- }));
6252
+ section2.columns = savedColumns.map((col) => {
6253
+ const column2 = {
6254
+ id: col.columnId,
6255
+ title: col.label,
6256
+ type: col.dimensionData ? "dimension" : "base",
6257
+ periodStartDate: col.startDate || col.date,
6258
+ periodEndDate: col.endDate || col.date,
6259
+ dimensionData: col.dimensionData,
6260
+ order: 0,
6261
+ removable: col.columnId !== "duration" && col.columnId !== "instant"
6262
+ };
6263
+ console.log(`📅 [Draft Restore] Restoring column ${col.columnId}: startDate=${column2.periodStartDate}, endDate=${column2.periodEndDate}`);
6264
+ return column2;
6265
+ });
5901
6266
  this._regenerateFieldsForSection(section2);
5902
6267
  console.log(` └─ Restored ${savedColumns.length} columns for section ${section2.id}`);
5903
6268
  }
@@ -5932,6 +6297,7 @@ let JupiterDynamicForm = class extends LitElement {
5932
6297
  section2.columns = [];
5933
6298
  }
5934
6299
  customColumnsForSection.forEach((col) => {
6300
+ console.log(`📅 [Merge Custom Column] Column ${col.columnId}: col.startDate=${col.startDate}, col.endDate=${col.endDate}, col.date=${col.date}, col.periodType=${col.periodType}`);
5935
6301
  const existingColumn = section2.columns.find((c2) => c2.id === col.columnId);
5936
6302
  if (!existingColumn) {
5937
6303
  const newColumn = {
@@ -5944,6 +6310,7 @@ let JupiterDynamicForm = class extends LitElement {
5944
6310
  order: section2.columns.length,
5945
6311
  removable: true
5946
6312
  };
6313
+ console.log(`📅 [New Column Created] Column ${newColumn.id}: periodStartDate=${newColumn.periodStartDate}, periodEndDate=${newColumn.periodEndDate}`);
5947
6314
  section2.columns.push(newColumn);
5948
6315
  console.log(` └─ Added custom column ${col.columnId} to section ${section2.id}`);
5949
6316
  }
@@ -5958,6 +6325,51 @@ let JupiterDynamicForm = class extends LitElement {
5958
6325
  };
5959
6326
  }
5960
6327
  }
6328
+ /**
6329
+ * Apply custom period data from _periodData to all existing fields
6330
+ * This is called after schema rebuild to preserve user-modified period dates
6331
+ */
6332
+ _applyCustomPeriodDataToFields() {
6333
+ if (!this._periodData || Object.keys(this._periodData).length === 0) {
6334
+ console.log("ℹ️ No custom period data to apply");
6335
+ return;
6336
+ }
6337
+ let appliedCount = 0;
6338
+ const applyToConceptTree = (concepts) => {
6339
+ concepts.forEach((concept) => {
6340
+ if (this._periodData[concept.id]) {
6341
+ const conceptPeriodData = this._periodData[concept.id];
6342
+ if (concept.fields) {
6343
+ concept.fields.forEach((field) => {
6344
+ const customPeriod = conceptPeriodData[field.columnId];
6345
+ if (customPeriod) {
6346
+ if (customPeriod.startDate) {
6347
+ field.periodStartDate = customPeriod.startDate;
6348
+ }
6349
+ if (customPeriod.endDate) {
6350
+ field.periodEndDate = customPeriod.endDate;
6351
+ }
6352
+ if (customPeriod.instantDate) {
6353
+ field.periodInstantDate = customPeriod.instantDate;
6354
+ }
6355
+ appliedCount++;
6356
+ console.log(`✅ [Apply Period] Updated field ${concept.id}/${field.columnId}: start=${field.periodStartDate}, end=${field.periodEndDate}, instant=${field.periodInstantDate}`);
6357
+ }
6358
+ });
6359
+ }
6360
+ }
6361
+ if (concept.children && concept.children.length > 0) {
6362
+ applyToConceptTree(concept.children);
6363
+ }
6364
+ });
6365
+ };
6366
+ this._allSections.forEach((section2) => {
6367
+ if (section2.concepts && section2.concepts.length > 0) {
6368
+ applyToConceptTree(section2.concepts);
6369
+ }
6370
+ });
6371
+ console.log(`📅 [Apply Period] Applied custom period data to ${appliedCount} fields`);
6372
+ }
5961
6373
  _regenerateFieldsForSection(section2) {
5962
6374
  if (!section2.columns)
5963
6375
  return;
@@ -5975,24 +6387,47 @@ let JupiterDynamicForm = class extends LitElement {
5975
6387
  );
5976
6388
  if (shouldShowConcept) {
5977
6389
  section2.columns.forEach((column2) => {
6390
+ var _a;
5978
6391
  const conceptPeriodType = concept.periodType;
5979
6392
  const columnPeriodType = this._inferColumnPeriodType(column2);
5980
6393
  if (concept.abstract)
5981
6394
  return;
5982
- if (conceptPeriodType && columnPeriodType) {
6395
+ const shouldSkipPeriodCheck = !columnPeriodType || column2.id === "duration" || column2.id === "default";
6396
+ if (!shouldSkipPeriodCheck && conceptPeriodType && columnPeriodType) {
5983
6397
  if (conceptPeriodType !== columnPeriodType) {
6398
+ console.log(`⏭️ [Field Regeneration] Skipping field for ${concept.id} in column ${column2.id}: conceptPeriodType=${conceptPeriodType}, columnPeriodType=${columnPeriodType}`);
5984
6399
  return;
5985
6400
  }
5986
6401
  }
5987
- concept.fields.push({
6402
+ const newField = {
5988
6403
  id: `${concept.id}_${column2.id}`,
5989
6404
  conceptId: concept.id,
5990
6405
  columnId: column2.id,
5991
6406
  type: this._mapConceptTypeToFieldType(concept.type),
5992
6407
  label: concept.label,
6408
+ periodType: conceptPeriodType,
6409
+ // Add periodType from concept
5993
6410
  periodStartDate: column2.periodStartDate,
5994
- periodEndDate: column2.periodEndDate
5995
- });
6411
+ periodEndDate: column2.periodEndDate,
6412
+ periodInstantDate: conceptPeriodType === "instant" ? column2.periodEndDate || column2.periodStartDate : void 0
6413
+ };
6414
+ if ((_a = this._periodData[concept.id]) == null ? void 0 : _a[column2.id]) {
6415
+ const customPeriod = this._periodData[concept.id][column2.id];
6416
+ if (customPeriod.startDate)
6417
+ newField.periodStartDate = customPeriod.startDate;
6418
+ if (customPeriod.endDate)
6419
+ newField.periodEndDate = customPeriod.endDate;
6420
+ if (customPeriod.instantDate)
6421
+ newField.periodInstantDate = customPeriod.instantDate;
6422
+ console.log(`✅ [Field Regeneration] Applied custom period data to ${concept.id}/${column2.id}:`, customPeriod);
6423
+ console.log(`✅ [Field Regeneration] Field properties after apply: periodStartDate=${newField.periodStartDate}, periodEndDate=${newField.periodEndDate}, periodInstantDate=${newField.periodInstantDate}`);
6424
+ } else {
6425
+ console.log(`ℹ️ [Field Regeneration] No custom period data for ${concept.id}/${column2.id}. Checking _periodData:`, this._periodData[concept.id]);
6426
+ }
6427
+ if (concept.id.includes("DescriptionLocationNL") || column2.id.startsWith("col-")) {
6428
+ console.log(`📅 [Field Regeneration] Concept ${concept.id}, Column ${column2.id}: field.periodStartDate=${newField.periodStartDate}, field.periodEndDate=${newField.periodEndDate}, column.periodStartDate=${column2.periodStartDate}`);
6429
+ }
6430
+ concept.fields.push(newField);
5996
6431
  });
5997
6432
  }
5998
6433
  if (concept.children) {
@@ -6098,26 +6533,30 @@ let JupiterDynamicForm = class extends LitElement {
6098
6533
  return null;
6099
6534
  }
6100
6535
  _addConceptDataToSubmission(concept, columnId, value, submissionData, section2) {
6101
- var _a;
6536
+ var _a, _b;
6102
6537
  const field = concept.fields.find((f2) => f2.columnId === columnId);
6103
6538
  if (!field)
6104
6539
  return;
6105
6540
  const isInstant = concept.periodType === "instant";
6541
+ const fieldPeriodData = (_a = this._periodData[concept.id]) == null ? void 0 : _a[columnId];
6106
6542
  const column2 = this._findColumnByIdInAllSections(columnId);
6107
- console.log(`🔍 [Submission] Concept: ${concept.id}, Column: ${columnId}, Column Period: ${(column2 == null ? void 0 : column2.periodStartDate) || "none"} - ${(column2 == null ? void 0 : column2.periodEndDate) || "none"}`);
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) || field.periodStartDate || this.periodStartDate;
6545
+ const periodEndDate = (fieldPeriodData == null ? void 0 : fieldPeriodData.endDate) || (column2 == null ? void 0 : column2.periodEndDate) || field.periodEndDate || this.periodEndDate;
6546
+ const periodInstantDate = (fieldPeriodData == null ? void 0 : fieldPeriodData.instantDate) || field.periodInstantDate || periodEndDate || periodStartDate;
6108
6547
  const entry = {
6109
6548
  conceptId: concept.originalConceptId || concept.id,
6110
6549
  columnId,
6111
6550
  value,
6112
6551
  period: {
6113
6552
  type: concept.periodType || "duration",
6114
- ...isInstant ? { date: (column2 == null ? void 0 : column2.periodEndDate) || field.periodStartDate || this.periodStartDate } : {
6115
- startDate: (column2 == null ? void 0 : column2.periodStartDate) || field.periodStartDate || this.periodStartDate,
6116
- endDate: (column2 == null ? void 0 : column2.periodEndDate) || field.periodEndDate || this.periodEndDate
6553
+ ...isInstant ? { date: periodInstantDate } : {
6554
+ startDate: periodStartDate,
6555
+ endDate: periodEndDate
6117
6556
  }
6118
6557
  }
6119
6558
  };
6120
- if ((_a = column2 == null ? void 0 : column2.dimensionData) == null ? void 0 : _a.memberLabel) {
6559
+ if ((_b = column2 == null ? void 0 : column2.dimensionData) == null ? void 0 : _b.memberLabel) {
6121
6560
  entry.dimension = column2.dimensionData.memberLabel;
6122
6561
  }
6123
6562
  submissionData.push(entry);
@@ -6254,11 +6693,12 @@ let JupiterDynamicForm = class extends LitElement {
6254
6693
  }
6255
6694
  if (concept.fields && concept.fields.length > 0) {
6256
6695
  concept.fields.forEach((field) => {
6257
- var _a, _b;
6696
+ var _a, _b, _c;
6258
6697
  const conceptData = this._formData[concept.id];
6259
6698
  const fieldValue = conceptData == null ? void 0 : conceptData[field.columnId];
6260
6699
  if (fieldValue !== void 0 && fieldValue !== null && fieldValue !== "") {
6261
6700
  const column2 = this._findColumnByIdInSection(field.columnId, section2);
6701
+ const fieldPeriodData = (_a = this._periodData[concept.id]) == null ? void 0 : _a[field.columnId];
6262
6702
  const submissionEntry = {
6263
6703
  conceptId: concept.id,
6264
6704
  columnId: field.columnId,
@@ -6269,13 +6709,16 @@ let JupiterDynamicForm = class extends LitElement {
6269
6709
  }
6270
6710
  };
6271
6711
  if (concept.periodType === "instant") {
6272
- submissionEntry.period.date = (column2 == null ? void 0 : column2.periodEndDate) || field.periodStartDate || this.periodStartDate;
6712
+ const instantDate = (fieldPeriodData == null ? void 0 : fieldPeriodData.instantDate) || (fieldPeriodData == null ? void 0 : fieldPeriodData.endDate) || (column2 == null ? void 0 : column2.periodEndDate) || field.periodInstantDate || field.periodEndDate || field.periodStartDate || this.periodStartDate;
6713
+ submissionEntry.period.date = instantDate;
6273
6714
  } else {
6274
- submissionEntry.period.startDate = (column2 == null ? void 0 : column2.periodStartDate) || field.periodStartDate || this.periodStartDate;
6275
- submissionEntry.period.endDate = (column2 == null ? void 0 : column2.periodEndDate) || field.periodEndDate || this.periodEndDate;
6715
+ const startDate = (fieldPeriodData == null ? void 0 : fieldPeriodData.startDate) || (column2 == null ? void 0 : column2.periodStartDate) || field.periodStartDate || this.periodStartDate;
6716
+ const endDate = (fieldPeriodData == null ? void 0 : fieldPeriodData.endDate) || (column2 == null ? void 0 : column2.periodEndDate) || field.periodEndDate || this.periodEndDate;
6717
+ submissionEntry.period.startDate = startDate;
6718
+ submissionEntry.period.endDate = endDate;
6276
6719
  }
6277
- console.log(`🔍 [Submission] Concept: ${concept.id}, Column: ${field.columnId}, 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}`}`);
6278
- if ((column2 == null ? void 0 : column2.type) === "dimension" && ((_a = column2.dimensionData) == null ? void 0 : _a.dimensionIdKey)) {
6720
+ console.log(`🔍 [Submission] Concept: ${concept.id}, Column: ${field.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}`}`);
6721
+ if ((column2 == null ? void 0 : column2.type) === "dimension" && ((_b = column2.dimensionData) == null ? void 0 : _b.dimensionIdKey)) {
6279
6722
  submissionEntry.dimension = column2.dimensionData.dimensionIdKey;
6280
6723
  console.log(`🔍 [DynamicForm] Using dimension key from field's column (${field.columnId}):`, column2.dimensionData.dimensionIdKey);
6281
6724
  } else {
@@ -6311,7 +6754,7 @@ let JupiterDynamicForm = class extends LitElement {
6311
6754
  console.log(`🔍 [DynamicForm] Column details:`, {
6312
6755
  id: column2.id,
6313
6756
  type: column2.type,
6314
- hasTypedMembers: (_b = column2.dimensionData) == null ? void 0 : _b.hasTypedMembers,
6757
+ hasTypedMembers: (_c = column2.dimensionData) == null ? void 0 : _c.hasTypedMembers,
6315
6758
  dimensionData: column2.dimensionData
6316
6759
  });
6317
6760
  }
@@ -6356,6 +6799,36 @@ let JupiterDynamicForm = class extends LitElement {
6356
6799
  _handleSidePanelRoleClick(roleId) {
6357
6800
  this._activeSidePanelRoleId = roleId;
6358
6801
  }
6802
+ _handleSidePanelSearchInput(event) {
6803
+ const input = event.target;
6804
+ this._sidePanelSearchQuery = input.value;
6805
+ }
6806
+ _clearSidePanelSearch() {
6807
+ var _a;
6808
+ this._sidePanelSearchQuery = "";
6809
+ const searchInput = (_a = this.shadowRoot) == null ? void 0 : _a.querySelector(".side-panel-search-input");
6810
+ if (searchInput) {
6811
+ searchInput.value = "";
6812
+ searchInput.focus();
6813
+ }
6814
+ }
6815
+ _toggleSidePanelCollapse() {
6816
+ this._sidePanelCollapsed = !this._sidePanelCollapsed;
6817
+ }
6818
+ _filterSidePanelSections(sections) {
6819
+ if (!this._sidePanelSearchQuery.trim()) {
6820
+ return sections;
6821
+ }
6822
+ const query = this._sidePanelSearchQuery.toLowerCase().trim();
6823
+ return sections.filter((section2) => {
6824
+ var _a, _b, _c;
6825
+ const titleMatch = section2.title.toLowerCase().includes(query);
6826
+ const idMatch = section2.id.toLowerCase().includes(query);
6827
+ const descriptionMatch = ((_a = section2.description) == null ? void 0 : _a.toLowerCase().includes(query)) || false;
6828
+ const uriMatch = ((_c = (_b = section2.metadata) == null ? void 0 : _b.roleURI) == null ? void 0 : _c.toLowerCase().includes(query)) || false;
6829
+ return titleMatch || idMatch || descriptionMatch || uriMatch;
6830
+ });
6831
+ }
6359
6832
  _renderAdminModeContent(section2) {
6360
6833
  var _a, _b, _c;
6361
6834
  if (!section2) {
@@ -6500,6 +6973,7 @@ let JupiterDynamicForm = class extends LitElement {
6500
6973
  .isFirstSection="${index === 0}"
6501
6974
  .availableDimensions="${this._getAvailableDimensionsForSection(section2.id)}"
6502
6975
  @field-change="${this._handleFieldChange}"
6976
+ @period-change="${this._handlePeriodChange}"
6503
6977
  @typed-member-change="${this._handleTypedMemberChange}"
6504
6978
  @section-expand="${this._handleSectionExpand}"
6505
6979
  @concept-expand="${this._handleConceptExpand}"
@@ -6512,22 +6986,71 @@ let JupiterDynamicForm = class extends LitElement {
6512
6986
  }
6513
6987
  _renderSidePanelLayout(schema, config, showValidationSummary, errorCount) {
6514
6988
  const visibleSections = schema.sections;
6515
- if (!this._activeSidePanelRoleId || !visibleSections.find((s2) => s2.id === this._activeSidePanelRoleId)) {
6516
- this._activeSidePanelRoleId = visibleSections.length > 0 ? visibleSections[0].id : null;
6989
+ const filteredSections = this._filterSidePanelSections(visibleSections);
6990
+ if (!this._activeSidePanelRoleId || !filteredSections.find((s2) => s2.id === this._activeSidePanelRoleId)) {
6991
+ this._activeSidePanelRoleId = filteredSections.length > 0 ? filteredSections[0].id : null;
6517
6992
  }
6518
6993
  const activeSection = visibleSections.find((s2) => s2.id === this._activeSidePanelRoleId);
6519
6994
  return html`
6520
6995
  <div class="side-panel-layout">
6521
6996
  <!-- Left: Roles List (filtered) -->
6522
- <div class="side-panel-roles-list">
6523
- ${visibleSections.map((section2) => html`
6524
- <div
6525
- class="side-panel-role-item ${section2.id === this._activeSidePanelRoleId ? "active" : ""}"
6526
- @click="${() => this._handleSidePanelRoleClick(section2.id)}"
6527
- >
6528
- ${section2.title}
6997
+ <div class="side-panel-roles-list ${this._sidePanelCollapsed ? "collapsed" : ""}">
6998
+ <!-- Toggle Button -->
6999
+ <button
7000
+ class="side-panel-toggle-btn ${this._sidePanelCollapsed ? "collapsed" : ""}"
7001
+ @click="${this._toggleSidePanelCollapse}"
7002
+ title="${this._sidePanelCollapsed ? I18n.t("form.expandPanel") : I18n.t("form.collapsePanel")}"
7003
+ >
7004
+ <svg viewBox="0 0 24 24">
7005
+ <path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/>
7006
+ </svg>
7007
+ </button>
7008
+
7009
+ ${!this._sidePanelCollapsed ? html`
7010
+ <!-- Search Input -->
7011
+ <div class="side-panel-search-container">
7012
+ <input
7013
+ type="text"
7014
+ class="side-panel-search-input"
7015
+ placeholder="${I18n.t("filter.searchPlaceholder")}"
7016
+ .value="${this._sidePanelSearchQuery}"
7017
+ @input="${this._handleSidePanelSearchInput}"
7018
+ />
7019
+ ${this._sidePanelSearchQuery ? html`
7020
+ <button class="side-panel-clear-search" @click="${this._clearSidePanelSearch}" title="${I18n.t("filter.clearSearch")}">
7021
+ ×
7022
+ </button>
7023
+ ` : html`
7024
+ <svg class="side-panel-search-icon" viewBox="0 0 24 24">
7025
+ <path d="M15.5 14h-.79l-.28-.27A6.471 6.471 0 0 0 16 9.5 6.5 6.5 0 1 0 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>
7026
+ </svg>
7027
+ `}
7028
+ </div>
7029
+
7030
+ <!-- Search Results Info -->
7031
+ ${this._sidePanelSearchQuery.trim() && filteredSections.length !== visibleSections.length ? html`
7032
+ <div class="side-panel-search-results-info">
7033
+ ${filteredSections.length} ${I18n.t("filter.of")} ${visibleSections.length} ${I18n.t("filter.roles")}
6529
7034
  </div>
6530
- `)}
7035
+ ` : ""}
7036
+
7037
+ <!-- Roles List -->
7038
+ ${filteredSections.length === 0 ? html`
7039
+ <div class="side-panel-no-results">
7040
+ ${I18n.t("filter.noRolesFound")} "${this._sidePanelSearchQuery}"<br>
7041
+ ${I18n.t("filter.tryDifferentSearch")}
7042
+ </div>
7043
+ ` : html`
7044
+ ${filteredSections.map((section2) => html`
7045
+ <div
7046
+ class="side-panel-role-item ${section2.id === this._activeSidePanelRoleId ? "active" : ""}"
7047
+ @click="${() => this._handleSidePanelRoleClick(section2.id)}"
7048
+ >
7049
+ ${section2.title}
7050
+ </div>
7051
+ `)}
7052
+ `}
7053
+ ` : ""}
6531
7054
  </div>
6532
7055
 
6533
7056
  <!-- Right: Active Section Content -->
@@ -6883,6 +7406,132 @@ JupiterDynamicForm.styles = css`
6883
7406
  border-right: 1px solid var(--jupiter-border-color, #ddd);
6884
7407
  overflow-y: auto;
6885
7408
  background: var(--jupiter-background-light, #f8f9fa);
7409
+ display: flex;
7410
+ flex-direction: column;
7411
+ transition: width 0.3s ease, min-width 0.3s ease;
7412
+ position: relative;
7413
+ }
7414
+
7415
+ .side-panel-roles-list.collapsed {
7416
+ width: 48px;
7417
+ min-width: 48px;
7418
+ overflow: visible;
7419
+ border-right: 1px solid var(--jupiter-border-color, #ddd);
7420
+ }
7421
+
7422
+ .side-panel-toggle-btn {
7423
+ position: absolute;
7424
+ top: 0px;
7425
+ right: 0px;
7426
+ width: 32px;
7427
+ height: 32px;
7428
+ border: 1px solid var(--jupiter-border-color, #ddd);
7429
+ background: var(--jupiter-background, #fff);
7430
+ border-radius: 4px;
7431
+ cursor: pointer;
7432
+ display: flex;
7433
+ align-items: center;
7434
+ justify-content: center;
7435
+ z-index: 100;
7436
+ transition: all 0.2s ease;
7437
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
7438
+ }
7439
+
7440
+ .side-panel-toggle-btn:hover {
7441
+ background: var(--jupiter-primary-color, #1976d2);
7442
+ color: white;
7443
+ border-color: var(--jupiter-primary-color, #1976d2);
7444
+ }
7445
+
7446
+ .side-panel-toggle-btn svg {
7447
+ width: 20px;
7448
+ height: 20px;
7449
+ fill: currentColor;
7450
+ transition: transform 0.3s ease;
7451
+ }
7452
+
7453
+ .side-panel-toggle-btn.collapsed svg {
7454
+ transform: rotate(180deg);
7455
+ }
7456
+
7457
+ .side-panel-search-container {
7458
+ position: sticky;
7459
+ top: 0;
7460
+ z-index: 10;
7461
+ background: var(--jupiter-background, #fff);
7462
+ padding: 16px;
7463
+ border-bottom: 1px solid var(--jupiter-border-color, #ddd);
7464
+ }
7465
+
7466
+ .side-panel-search-input {
7467
+ width: 100%;
7468
+ padding: 10px 40px 10px 12px;
7469
+ border: 1px solid var(--jupiter-border-color, #ddd);
7470
+ border-radius: 4px;
7471
+ font-size: 14px;
7472
+ font-family: inherit;
7473
+ background: var(--jupiter-background, #fff);
7474
+ color: var(--jupiter-text-primary, #333);
7475
+ transition: border-color 0.2s ease;
7476
+ box-sizing: border-box;
7477
+ }
7478
+
7479
+ .side-panel-search-input:focus {
7480
+ outline: none;
7481
+ border-color: var(--jupiter-primary-color, #1976d2);
7482
+ box-shadow: 0 0 0 2px rgba(25, 118, 210, 0.1);
7483
+ }
7484
+
7485
+ .side-panel-search-input::placeholder {
7486
+ color: var(--jupiter-text-secondary, #666);
7487
+ }
7488
+
7489
+ .side-panel-search-icon {
7490
+ position: absolute;
7491
+ right: 28px;
7492
+ top: 50%;
7493
+ transform: translateY(-50%);
7494
+ width: 16px;
7495
+ height: 16px;
7496
+ fill: var(--jupiter-text-secondary, #666);
7497
+ pointer-events: none;
7498
+ }
7499
+
7500
+ .side-panel-clear-search {
7501
+ position: absolute;
7502
+ right: 28px;
7503
+ top: 50%;
7504
+ transform: translateY(-50%);
7505
+ background: none;
7506
+ border: none;
7507
+ cursor: pointer;
7508
+ padding: 2px;
7509
+ border-radius: 2px;
7510
+ color: var(--jupiter-text-secondary, #666);
7511
+ font-size: 20px;
7512
+ line-height: 1;
7513
+ transition: color 0.2s ease;
7514
+ }
7515
+
7516
+ .side-panel-clear-search:hover {
7517
+ color: var(--jupiter-text-primary, #333);
7518
+ }
7519
+
7520
+ .side-panel-search-results-info {
7521
+ font-size: 12px;
7522
+ color: var(--jupiter-text-secondary, #666);
7523
+ padding: 8px 16px;
7524
+ text-align: center;
7525
+ border-bottom: 1px solid var(--jupiter-border-color, #e0e0e0);
7526
+ background: var(--jupiter-background-light, #f8f9fa);
7527
+ }
7528
+
7529
+ .side-panel-no-results {
7530
+ padding: 40px 20px;
7531
+ text-align: center;
7532
+ color: var(--jupiter-text-secondary, #666);
7533
+ font-size: 14px;
7534
+ line-height: 1.6;
6886
7535
  }
6887
7536
 
6888
7537
  .side-panel-role-item {
@@ -7037,6 +7686,12 @@ __decorateClass([
7037
7686
  __decorateClass([
7038
7687
  r()
7039
7688
  ], JupiterDynamicForm.prototype, "_preservedFormData", 2);
7689
+ __decorateClass([
7690
+ r()
7691
+ ], JupiterDynamicForm.prototype, "_periodData", 2);
7692
+ __decorateClass([
7693
+ r()
7694
+ ], JupiterDynamicForm.prototype, "_preservedPeriodData", 2);
7040
7695
  __decorateClass([
7041
7696
  r()
7042
7697
  ], JupiterDynamicForm.prototype, "_typedMemberData", 2);
@@ -7079,6 +7734,12 @@ __decorateClass([
7079
7734
  __decorateClass([
7080
7735
  r()
7081
7736
  ], JupiterDynamicForm.prototype, "_activeSidePanelRoleId", 2);
7737
+ __decorateClass([
7738
+ r()
7739
+ ], JupiterDynamicForm.prototype, "_sidePanelSearchQuery", 2);
7740
+ __decorateClass([
7741
+ r()
7742
+ ], JupiterDynamicForm.prototype, "_sidePanelCollapsed", 2);
7082
7743
  __decorateClass([
7083
7744
  r()
7084
7745
  ], JupiterDynamicForm.prototype, "_adminRoleConfigs", 2);