cat-qw-lib 2.6.30 → 2.6.32

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.
@@ -3730,14 +3730,14 @@ class WidgetAdminService extends BaseService {
3730
3730
  listLabelProperty: "name",
3731
3731
  },
3732
3732
  {
3733
- name: "dictionaryID",
3733
+ name: "dataDictionaryId",
3734
3734
  dataSource: DATASOURCES.DICTIONARY,
3735
3735
  listValueProperty: "_id",
3736
3736
  listLabelProperty: "name",
3737
3737
  },
3738
3738
  {
3739
- name: "dictionaryItemID",
3740
- dataSource: "DataDictionaries/dictionaryItems",
3739
+ name: "dictionaryItemId",
3740
+ dataSource: DATASOURCES.DELETEDICTIONARYITEM,
3741
3741
  listValueProperty: "_id",
3742
3742
  listLabelProperty: "key",
3743
3743
  },
@@ -3812,7 +3812,7 @@ class WidgetAdminService extends BaseService {
3812
3812
  return String(value);
3813
3813
  }
3814
3814
  /**
3815
- * Parses style from form (string or already-object) for API submit.
3815
+ * Parses style from form (string or object) and returns an object payload for API submit.
3816
3816
  */
3817
3817
  parseStylePayload(input) {
3818
3818
  if (input === null || input === undefined) {
@@ -3893,8 +3893,8 @@ class WidgetModel extends BaseModel {
3893
3893
  */
3894
3894
  class WidgetItemModel extends BaseModel {
3895
3895
  name;
3896
- dictionaryItemID;
3897
- dictionaryID;
3896
+ dictionaryItemId;
3897
+ dataDictionaryId;
3898
3898
  style;
3899
3899
  isActive = true;
3900
3900
  }
@@ -3902,8 +3902,8 @@ class WidgetItemModel extends BaseModel {
3902
3902
  * BadgeModel class represents the model of a badge.
3903
3903
  */
3904
3904
  class BadgeModel {
3905
- dictionaryItemID;
3906
- dictionaryID;
3905
+ dictionaryItemId;
3906
+ dataDictionaryId;
3907
3907
  style;
3908
3908
  }
3909
3909
 
@@ -3945,6 +3945,7 @@ class WidgetAdminFormComponent extends BaseFormComponent {
3945
3945
  badgeDictionaryItemArray = [];
3946
3946
  widgetOptionsArray = [];
3947
3947
  widgetLayoutTypeList = widgetLayoutTypeList;
3948
+ enableDictionaryDebugLogs = true;
3948
3949
  constructor(service, validatorService, widgetStore, query, router, activatedRoute, baseStore, baseQuery) {
3949
3950
  super(service, validatorService, router, activatedRoute);
3950
3951
  this.service = service;
@@ -3965,24 +3966,46 @@ class WidgetAdminFormComponent extends BaseFormComponent {
3965
3966
  super.init();
3966
3967
  this.baseStore.setIsApiValidated(null);
3967
3968
  this.recordChange.asObservable().subscribe((record) => {
3968
- // Ensure arrays are initialized
3969
- if (!record.dataItems)
3970
- record.dataItems = [];
3971
- if (!record.badges)
3972
- record.badges = [];
3973
- this.normalizeLoadedRecordStyles(record);
3969
+ // recordChange can emit readonly store objects; clone before normalization/mutation.
3970
+ const editableRecord = structuredClone((record || {}));
3971
+ const withAliases = this.normalizeIncomingDictionaryAliases(editableRecord);
3972
+ const withStyles = this.normalizeLoadedRecordStyles(withAliases);
3973
+ this.record = withStyles;
3974
+ // Hydrate dependent dictionary-item dropdown arrays immediately on edit load.
3975
+ this.refreshDictionaryItemListsForRecord();
3974
3976
  // Dictionaries are scoped by apiConfigId (not queueID — that field does not exist on widget).
3975
- this.handleAPIChange(record.apiConfigId);
3977
+ this.handleAPIChange(this.record.apiConfigId);
3976
3978
  });
3977
3979
  }
3980
+ /**
3981
+ * Normalize backend dictionary keys into UI form keys on edit load.
3982
+ * This lets dropdowns preselect values immediately without user re-selection.
3983
+ */
3984
+ normalizeIncomingDictionaryAliases(record) {
3985
+ return {
3986
+ ...record,
3987
+ dataItems: (record.dataItems || []).map((item) => ({
3988
+ ...item,
3989
+ dataDictionaryId: item.dataDictionaryId || item.dictionaryID || '',
3990
+ dictionaryItemId: item.dictionaryItemId || item.dictionaryItemID || '',
3991
+ })),
3992
+ badges: (record.badges || []).map((badge) => ({
3993
+ ...badge,
3994
+ dataDictionaryId: badge.dataDictionaryId || badge.dictionaryID || '',
3995
+ dictionaryItemId: badge.dictionaryItemId || badge.dictionaryItemID || '',
3996
+ })),
3997
+ };
3998
+ }
3978
3999
  handleWidgetItemAddBtnClick() {
3979
4000
  if (!(this.record.name && this.record.apiConfigId))
3980
4001
  return;
3981
4002
  if (Array.isArray(this.record.dataItems)) {
3982
4003
  const hasEmptyItem = this.record.dataItems.some((item) => {
3983
4004
  const isItemNameEmpty = !item.name || item.name.trim() === SHARED.EMPTY;
3984
- const isDictionaryEmpty = !item.dictionaryID || item.dictionaryID.trim() === SHARED.EMPTY;
3985
- const isDictionaryItemEmpty = !item.dictionaryItemID || item.dictionaryItemID.trim() === SHARED.EMPTY;
4005
+ const dictionaryId = item.dataDictionaryId || item.dictionaryID;
4006
+ const dictionaryItemId = item.dictionaryItemId || item.dictionaryItemID;
4007
+ const isDictionaryEmpty = !dictionaryId || dictionaryId.trim() === SHARED.EMPTY;
4008
+ const isDictionaryItemEmpty = !dictionaryItemId || dictionaryItemId.trim() === SHARED.EMPTY;
3986
4009
  return isItemNameEmpty && isDictionaryItemEmpty && isDictionaryEmpty;
3987
4010
  });
3988
4011
  if (hasEmptyItem) {
@@ -3997,9 +4020,25 @@ class WidgetAdminFormComponent extends BaseFormComponent {
3997
4020
  }
3998
4021
  handleAPIChange(apiConfigId) {
3999
4022
  this.query.getLists().subscribe((allLists) => {
4000
- const allDictionaryRecords = allLists.find((list) => list.forProperty === 'dictionaryID')?.records;
4023
+ const dictionaryListMeta = allLists.find((list) => list.forProperty === 'dataDictionaryId' || list.forProperty === 'dictionaryID');
4024
+ const allDictionaryRecords = dictionaryListMeta?.records;
4025
+ if (this.enableDictionaryDebugLogs) {
4026
+ console.log('[WidgetAdmin] dictionary list resolved', {
4027
+ expectedForProperty: ['dataDictionaryId', 'dictionaryID'],
4028
+ actualForProperty: dictionaryListMeta?.forProperty,
4029
+ dataSource: dictionaryListMeta?.dataSource,
4030
+ totalRecords: allDictionaryRecords?.length || 0,
4031
+ selectedApiConfigId: apiConfigId
4032
+ });
4033
+ }
4001
4034
  this.dictionaries =
4002
- allDictionaryRecords?.filter((item) => String(item.apiConfigId ?? '') === String(apiConfigId ?? '')) || [];
4035
+ allDictionaryRecords?.filter((item) => String(item.apiConfigId ?? item.apiConfigID ?? '') === String(apiConfigId ?? '')) || [];
4036
+ if (this.enableDictionaryDebugLogs) {
4037
+ console.log('[WidgetAdmin] dictionary records after apiConfigId filter', {
4038
+ selectedApiConfigId: apiConfigId,
4039
+ filteredCount: this.dictionaries.length,
4040
+ });
4041
+ }
4003
4042
  this.refreshDictionaryItemListsForRecord();
4004
4043
  });
4005
4044
  }
@@ -4009,33 +4048,70 @@ class WidgetAdminFormComponent extends BaseFormComponent {
4009
4048
  */
4010
4049
  refreshDictionaryItemListsForRecord() {
4011
4050
  this.query.getLists().subscribe((allLists) => {
4012
- const allDictionaryItemRecords = allLists.find((list) => list.forProperty === 'dictionaryItemID')?.records || [];
4013
- const itemsForDictionary = (dictionaryId) => dictionaryId
4014
- ? allDictionaryItemRecords.filter((item) => item.dictionaryID === dictionaryId)
4015
- : [];
4051
+ const dictionaryItemListMeta = allLists.find((list) => list.forProperty === 'dictionaryItemId' || list.forProperty === 'dictionaryItemID');
4052
+ const allDictionaryItemRecords = dictionaryItemListMeta?.records || [];
4053
+ if (this.enableDictionaryDebugLogs) {
4054
+ console.log('[WidgetAdmin] dictionary item list resolved', {
4055
+ expectedForProperty: ['dictionaryItemId', 'dictionaryItemID'],
4056
+ actualForProperty: dictionaryItemListMeta?.forProperty,
4057
+ dataSource: dictionaryItemListMeta?.dataSource,
4058
+ totalRecords: allDictionaryItemRecords.length,
4059
+ });
4060
+ }
4061
+ const itemsForDictionary = (dictionaryId) => this.getDictionaryItemsByDictionaryId(allDictionaryItemRecords, dictionaryId);
4016
4062
  const r = this.record;
4017
4063
  this.headerDictionaryItems = itemsForDictionary(r.headerDictionaryID);
4018
4064
  this.subHeaderDictionaryItems = itemsForDictionary(r.subHeaderDictionaryID);
4019
- this.dictionaryItemArray = (r.dataItems || []).map((item) => itemsForDictionary(item.dictionaryID));
4020
- this.badgeDictionaryItemArray = (r.badges || []).map((badge) => itemsForDictionary(badge.dictionaryID));
4065
+ this.dictionaryItemArray = (r.dataItems || []).map((item) => itemsForDictionary(item.dataDictionaryId || item.dictionaryID));
4066
+ this.badgeDictionaryItemArray = (r.badges || []).map((badge) => itemsForDictionary(badge.dataDictionaryId || badge.dictionaryID));
4021
4067
  });
4022
4068
  }
4069
+ getDictionaryItemsByDictionaryId(allDictionaryItemRecords, dictionaryId) {
4070
+ if (!dictionaryId) {
4071
+ return [];
4072
+ }
4073
+ const byLegacyDictionaryId = allDictionaryItemRecords.filter((item) => item.dataDictionaryId === dictionaryId || item.dictionaryID === dictionaryId);
4074
+ if (byLegacyDictionaryId.length > 0) {
4075
+ if (this.enableDictionaryDebugLogs) {
4076
+ console.log('[WidgetAdmin] dictionary items matched by dictionary id relation', {
4077
+ dictionaryId,
4078
+ matchedCount: byLegacyDictionaryId.length
4079
+ });
4080
+ }
4081
+ return byLegacyDictionaryId;
4082
+ }
4083
+ const selectedDictionary = this.dictionaries.find((d) => d._id === dictionaryId);
4084
+ const dictionaryItemsIds = selectedDictionary?.dictionaryItemsIds || [];
4085
+ if (!Array.isArray(dictionaryItemsIds) || dictionaryItemsIds.length === 0) {
4086
+ return [];
4087
+ }
4088
+ const dictionaryItemsIdSet = new Set(dictionaryItemsIds.map((id) => String(id)));
4089
+ const byDictionaryItemsIds = allDictionaryItemRecords.filter((item) => dictionaryItemsIdSet.has(String(item._id)));
4090
+ if (this.enableDictionaryDebugLogs) {
4091
+ console.log('[WidgetAdmin] dictionary items matched by dictionaryItemsIds fallback', {
4092
+ dictionaryId,
4093
+ dictionaryItemsIdsCount: dictionaryItemsIds.length,
4094
+ matchedCount: byDictionaryItemsIds.length
4095
+ });
4096
+ }
4097
+ return byDictionaryItemsIds;
4098
+ }
4023
4099
  handleHeaderDictionarySelect(dictionaryId) {
4024
4100
  this.query.getLists().subscribe((allLists) => {
4025
- const allDictionaryItemRecords = allLists.find((list) => list.forProperty === 'dictionaryItemID')?.records;
4026
- this.headerDictionaryItems = allDictionaryItemRecords?.filter((item) => item.dictionaryID === dictionaryId) || [];
4101
+ const allDictionaryItemRecords = allLists.find((list) => list.forProperty === 'dictionaryItemId' || list.forProperty === 'dictionaryItemID')?.records;
4102
+ this.headerDictionaryItems = this.getDictionaryItemsByDictionaryId(allDictionaryItemRecords || [], dictionaryId);
4027
4103
  });
4028
4104
  }
4029
4105
  handleSubHeaderDictionarySelect(dictionaryId) {
4030
4106
  this.query.getLists().subscribe((allLists) => {
4031
- const allDictionaryItemRecords = allLists.find((list) => list.forProperty === 'dictionaryItemID')?.records;
4032
- this.subHeaderDictionaryItems = allDictionaryItemRecords?.filter((item) => item.dictionaryID === dictionaryId) || [];
4107
+ const allDictionaryItemRecords = allLists.find((list) => list.forProperty === 'dictionaryItemId' || list.forProperty === 'dictionaryItemID')?.records;
4108
+ this.subHeaderDictionaryItems = this.getDictionaryItemsByDictionaryId(allDictionaryItemRecords || [], dictionaryId);
4033
4109
  });
4034
4110
  }
4035
4111
  handleWidgetItemDictionarySelect(dictionaryId, index) {
4036
4112
  this.query.getLists().subscribe((allLists) => {
4037
- const allDictionaryItemRecords = allLists.find((list) => list.forProperty === 'dictionaryItemID')?.records;
4038
- this.dictionaryItemArray[index] = allDictionaryItemRecords?.filter((item) => item.dictionaryID === dictionaryId) || [];
4113
+ const allDictionaryItemRecords = allLists.find((list) => list.forProperty === 'dictionaryItemId' || list.forProperty === 'dictionaryItemID')?.records;
4114
+ this.dictionaryItemArray[index] = this.getDictionaryItemsByDictionaryId(allDictionaryItemRecords || [], dictionaryId);
4039
4115
  });
4040
4116
  }
4041
4117
  handleBadgeAddBtnClick() {
@@ -4043,8 +4119,10 @@ class WidgetAdminFormComponent extends BaseFormComponent {
4043
4119
  return;
4044
4120
  if (Array.isArray(this.record.badges)) {
4045
4121
  const hasEmptyBadge = this.record.badges.some((badge) => {
4046
- const isDictionaryEmpty = !badge.dictionaryID || badge.dictionaryID.trim() === SHARED.EMPTY;
4047
- const isDictionaryItemEmpty = !badge.dictionaryItemID || badge.dictionaryItemID.trim() === SHARED.EMPTY;
4122
+ const dictionaryId = badge.dataDictionaryId || badge.dictionaryID;
4123
+ const dictionaryItemId = badge.dictionaryItemId || badge.dictionaryItemID;
4124
+ const isDictionaryEmpty = !dictionaryId || dictionaryId.trim() === SHARED.EMPTY;
4125
+ const isDictionaryItemEmpty = !dictionaryItemId || dictionaryItemId.trim() === SHARED.EMPTY;
4048
4126
  return isDictionaryItemEmpty && isDictionaryEmpty;
4049
4127
  });
4050
4128
  if (hasEmptyBadge) {
@@ -4059,8 +4137,8 @@ class WidgetAdminFormComponent extends BaseFormComponent {
4059
4137
  }
4060
4138
  handleBadgeDictionarySelect(dictionaryId, index) {
4061
4139
  this.query.getLists().subscribe((allLists) => {
4062
- const allDictionaryItemRecords = allLists.find((list) => list.forProperty === 'dictionaryItemID')?.records;
4063
- this.badgeDictionaryItemArray[index] = allDictionaryItemRecords?.filter((item) => item.dictionaryID === dictionaryId) || [];
4140
+ const allDictionaryItemRecords = allLists.find((list) => list.forProperty === 'dictionaryItemId' || list.forProperty === 'dictionaryItemID')?.records;
4141
+ this.badgeDictionaryItemArray[index] = this.getDictionaryItemsByDictionaryId(allDictionaryItemRecords || [], dictionaryId);
4064
4142
  });
4065
4143
  }
4066
4144
  handleDeleteBadge(index) {
@@ -4085,31 +4163,42 @@ class WidgetAdminFormComponent extends BaseFormComponent {
4085
4163
  * Text-box controls expect stringified JSON; API returns nested objects → "[object Object]" without this.
4086
4164
  */
4087
4165
  normalizeLoadedRecordStyles(record) {
4088
- if (record.style !== undefined && record.style !== null && record.style !== '') {
4089
- record.style = this.service.coerceStyleToJsonText(record.style);
4090
- }
4091
- record.dataItems?.forEach((item) => {
4092
- if (item.style !== undefined && item.style !== null && item.style !== '') {
4093
- item.style = this.service.coerceStyleToJsonText(item.style);
4094
- }
4095
- });
4096
- record.badges?.forEach((badge) => {
4097
- if (badge.style !== undefined && badge.style !== null && badge.style !== '') {
4098
- badge.style = this.service.coerceStyleToJsonText(badge.style);
4099
- }
4100
- });
4166
+ return {
4167
+ ...record,
4168
+ style: this.service.coerceStyleToJsonText(record.style),
4169
+ dataItems: (record.dataItems || []).map((item) => ({
4170
+ ...item,
4171
+ style: this.service.coerceStyleToJsonText(item.style),
4172
+ })),
4173
+ badges: (record.badges || []).map((badge) => ({
4174
+ ...badge,
4175
+ style: this.service.coerceStyleToJsonText(badge.style),
4176
+ })),
4177
+ };
4101
4178
  }
4102
4179
  handleSubmit() {
4103
4180
  this.record.style = this.service.parseStylePayload(this.record.style);
4104
- this.record.dataItems = this.record.dataItems.map((item) => ({
4105
- ...item,
4106
- style: this.service.parseStylePayload(item.style),
4107
- }));
4181
+ this.record.dataItems = this.record.dataItems.map((item) => {
4182
+ const raw = item;
4183
+ const { dataDictionaryId, dictionaryItemId, ...rest } = raw;
4184
+ return {
4185
+ ...rest,
4186
+ dictionaryID: dataDictionaryId || raw.dictionaryID || '',
4187
+ dictionaryItemID: dictionaryItemId || raw.dictionaryItemID || '',
4188
+ style: this.service.parseStylePayload(raw.style),
4189
+ };
4190
+ });
4108
4191
  if (this.record.badges && Array.isArray(this.record.badges)) {
4109
- this.record.badges = this.record.badges.map((badge) => ({
4110
- ...badge,
4111
- style: this.service.parseStylePayload(badge.style),
4112
- }));
4192
+ this.record.badges = this.record.badges.map((badge) => {
4193
+ const raw = badge;
4194
+ const { dataDictionaryId, dictionaryItemId, ...rest } = raw;
4195
+ return {
4196
+ ...rest,
4197
+ dictionaryID: dataDictionaryId || raw.dictionaryID || '',
4198
+ dictionaryItemID: dictionaryItemId || raw.dictionaryItemID || '',
4199
+ style: this.service.parseStylePayload(raw.style),
4200
+ };
4201
+ });
4113
4202
  }
4114
4203
  else {
4115
4204
  this.record.badges = [];