@myrtex-org/form 1.1.80 → 1.1.82

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.
@@ -17,7 +17,7 @@ import { AutoSaveStore, ToasterType, LabelModule, ModalServiceComponent, MODAL_D
17
17
  import { HttpHeaders, HttpClient, HTTP_INTERCEPTORS } from '@angular/common/http';
18
18
  import * as i2$1 from '@myrtex-org/templates';
19
19
  import { FormHeaderModule, MenuAdminModule } from '@myrtex-org/templates';
20
- import { cloneDeep } from 'lodash-es';
20
+ import { cloneDeep, isArray } from 'lodash-es';
21
21
  import * as i2$2 from '@angular/forms';
22
22
  import { FormsModule } from '@angular/forms';
23
23
  import { provideNgxMask } from 'ngx-mask';
@@ -1731,40 +1731,32 @@ class InputDateComponent extends BaseFieldComponent {
1731
1731
  return this.settings.options.viewType === DateTypeEnum.DateTime;
1732
1732
  }
1733
1733
  updateValue(event) {
1734
+ console.log(`[DateComponent -> updateValue] [sysName: ${this.settings.sysName}] Событие от UI элемента:`, event);
1734
1735
  if (this._isInit) {
1735
- console.group(`=== ДАТА [${this.settings.sysName}]: Пользовательский ввод (updateValue) ===`);
1736
- console.log('Событие от mrx-input-date-time (event):', structuredClone(event));
1737
- this._isUpdatingInternal = true;
1736
+ this._isUpdatingInternal = true; // Блокируем внешние обновления на время ввода
1738
1737
  if (this.settings.options.range) {
1739
1738
  if (!event.value || event.value.length === 0) {
1740
- console.log('Диапазон пустой, сброс значений');
1741
1739
  this.dateModel = [];
1742
1740
  this.modelStart.value = null;
1743
1741
  this.modelEnd.value = null;
1744
1742
  this.modelCounter = 0;
1745
1743
  }
1746
1744
  else if (event.value.length === 2) {
1747
- console.log(`Установка диапазона: Start = ${event.value[0]}, End = ${event.value[1]}`);
1748
1745
  this.dateModel = [event.value[0], event.value[1]];
1749
1746
  this.modelStart.value = event.value[0];
1750
1747
  this.modelEnd.value = event.value[1];
1751
1748
  this.modelCounter = this._getDaysDifference(this.modelStart.value, this.modelEnd.value);
1752
- console.log('Высчитанный modelCounter (дней):', this.modelCounter);
1753
1749
  }
1754
1750
  this.model.value = this.dateModel;
1755
1751
  }
1756
1752
  else {
1757
- console.log('Одиночная дата:', event.value);
1758
1753
  this.dateModel = event.value;
1759
1754
  this.model.value = event.value;
1760
1755
  }
1761
- console.log('Вызываем dispatchModify со значением:', structuredClone(event));
1756
+ console.log(`[DateComponent -> updateValue] Сформирован вызов dispatchModify. Отправляемое значение:`, this._transformOutputValue());
1762
1757
  this.dispatchModify(event);
1763
- setTimeout(() => {
1764
- this._isUpdatingInternal = false;
1765
- console.log(`=== ДАТА [${this.settings.sysName}]: Снята блокировка _isUpdatingInternal ===`);
1766
- }, 600);
1767
- console.groupEnd();
1758
+ // Снимаем блокировку чуть позже, когда Store переварит изменения
1759
+ setTimeout(() => this._isUpdatingInternal = false, 600);
1768
1760
  }
1769
1761
  }
1770
1762
  updateCounter(value) {
@@ -1799,8 +1791,26 @@ class InputDateComponent extends BaseFieldComponent {
1799
1791
  _initSubscriptionForValue() {
1800
1792
  this._subscriptions$.push(this._store.select(selectValueModel(this.settings))
1801
1793
  .subscribe((result) => {
1802
- if (!result || this._isUpdatingInternal)
1794
+ console.log(`[DateComponent -> Store Subscription] [sysName: ${this.settings.sysName}] Получено из Store:`, structuredClone(result));
1795
+ if (!result || this._isUpdatingInternal) {
1796
+ if (this._isUpdatingInternal)
1797
+ console.log(`[DateComponent] Пропущено обновление из Store, так как _isUpdatingInternal = true`);
1803
1798
  return;
1799
+ }
1800
+ // Если компонент уже инициализирован, проверяем, нужно ли обновляться.
1801
+ // Мы НЕ обновляемся, если данные в Store идентичны тем, что мы уже держим в памяти.
1802
+ if (this._isInit) {
1803
+ const newValue = Array.isArray(result)
1804
+ ? JSON.stringify([result[0]?.value, result[1]?.value])
1805
+ : JSON.stringify(result.value);
1806
+ const currentValue = this.settings.options.range
1807
+ ? JSON.stringify([this.modelStart?.value, this.modelEnd?.value])
1808
+ : JSON.stringify(this.model?.value);
1809
+ if (newValue === currentValue) {
1810
+ return; // Данные те же самые, выходим, чтобы не запускать таймер заново
1811
+ }
1812
+ }
1813
+ // Если данные реально новые (пришли извне), обновляем локальные модели
1804
1814
  if (Array.isArray(result)) {
1805
1815
  this.modelStart = structuredClone(result[0]) || defaultValueModel(this.settings);
1806
1816
  this.modelEnd = structuredClone(result[1]) || defaultValueModel(this.settings);
@@ -1812,6 +1822,7 @@ class InputDateComponent extends BaseFieldComponent {
1812
1822
  }));
1813
1823
  }
1814
1824
  _customInit() {
1825
+ console.log(`[DateComponent -> _customInit] [sysName: ${this.settings.sysName}] Настройка локальных моделей. Текущее состояние range:`, this.settings.options.range);
1815
1826
  if (this.settings.options.range) {
1816
1827
  if (!this.modelStart) {
1817
1828
  this.modelStart = defaultValueModel(this.settings);
@@ -1824,20 +1835,20 @@ class InputDateComponent extends BaseFieldComponent {
1824
1835
  this.model = defaultValueModel(this.settings);
1825
1836
  }
1826
1837
  if (this.settings.options.range) {
1827
- // Проверяем наличие значений в распакованных моделях начала и конца
1828
1838
  if (this.modelStart?.value && this.modelEnd?.value) {
1829
1839
  this.dateModel = [this.modelStart.value, this.modelEnd.value];
1830
1840
  this.modelCounter = this._getDaysDifference(this.modelStart.value, this.modelEnd.value);
1831
1841
  }
1832
- else {
1842
+ else if (!this.modelStart?.value && !this.modelEnd?.value) {
1843
+ // Очищаем только если в Store реально пусто
1833
1844
  this.dateModel = [];
1834
1845
  this.modelCounter = 0;
1835
1846
  }
1836
1847
  }
1837
1848
  else {
1838
- // Обычная одиночная дата (itb6-id1) берет строку из `.value`
1839
1849
  this.dateModel = this.model.value;
1840
1850
  }
1851
+ console.log(`[DateComponent -> _customInit] Результат инициализации: dateModel =`, this.dateModel, 'modelCounter =', this.modelCounter);
1841
1852
  this._isInit = true;
1842
1853
  this._detector.markForCheck();
1843
1854
  }
@@ -2189,104 +2200,39 @@ class InputTableModalComponent extends ModalServiceComponent {
2189
2200
  this.title = data.title;
2190
2201
  this.okText = data.okText;
2191
2202
  this.settings = data.settings;
2203
+ this.rowModel = data.rowModel;
2192
2204
  this.isCheckRequired = data.isCheckRequired;
2193
- // Клонируем входящую модель строки
2194
- const preparedRowModel = structuredClone(data.rowModel);
2195
- // Проверяем все компоненты таблицы. Если это Range-календарь, подготавливаем массив моделей
2196
- this.settings.components.forEach(component => {
2197
- if (component.type === ComponentType.InputDate && component.options?.range) {
2198
- const cell = preparedRowModel.data.find(x => x.sysName === component.sysName);
2199
- // Если в таблице лежал массив строк дат ['ISO...', 'ISO...'] или пустой массив
2200
- if (cell && Array.isArray(cell.value) && (cell.value.length === 2 || cell.value.length === 0)) {
2201
- const dateStart = cell.value[0] || null;
2202
- const dateEnd = cell.value[1] || null;
2203
- // Превращаем в массив моделей, который так ждет InputDateComponent
2204
- cell.value = [
2205
- { sysName: component.sysName, type: component.type, valueType: component.valueType, value: dateStart },
2206
- { sysName: component.sysName, type: component.type, valueType: component.valueType, value: dateEnd }
2207
- ];
2208
- }
2209
- }
2205
+ console.log('[Modal -> Constructor] Данные, пришедшие в модалку:', {
2206
+ title: data.title,
2207
+ rowModel: structuredClone(data.rowModel)
2210
2208
  });
2211
- this.rowModel = preparedRowModel;
2212
2209
  this.result = { result: false, rowModel: this.rowModel };
2213
2210
  }
2214
2211
  componentValueChanged(valueModel) {
2215
- console.group('=== МОДАЛКА: Изменение значения в форме ===');
2216
- const incomingModels = Array.isArray(valueModel) ? valueModel : [valueModel];
2217
- const cloneRowModel = structuredClone(this.rowModel);
2218
- // Шаг 1: Сначала просто обновляем в cloneRowModel те точечные значения, которые сейчас прилетели
2219
- incomingModels.forEach(incoming => {
2220
- // Ищем ячейку в строке по sysName
2221
- const cell = cloneRowModel.data.find(c => c.sysName === incoming.sysName);
2222
- if (cell) {
2223
- // Находим настройки этого компонента, чтобы понять, range это или нет
2224
- const compSettings = this.settings.components.find(x => x.sysName === incoming.sysName);
2225
- const isRange = compSettings?.type === ComponentType.InputDate && compSettings.options?.range;
2226
- if (isRange) {
2227
- // Если это range, то FormDispenser мог прислать либо массив моделей, либо одну из них
2228
- // Нам нужно аккуратно обновить массив строк в cell.value
2229
- if (!Array.isArray(cell.value)) {
2230
- cell.value = [null, null];
2231
- }
2232
- // Если прилетел массив (например, при первой инициализации или полном изменении)
2233
- if (incomingModels.length > 1 && incomingModels.every(m => m.sysName === incoming.sysName)) {
2234
- cell.value = [incomingModels[0].value, incomingModels[1].value];
2235
- }
2236
- else {
2237
- // Если прилетела одиночная модель из диапазона (например, обновилась только одна дата),
2238
- // или FormDispenser плюнул объект, у которого внутри value уже лежит массив/дата.
2239
- // Проверяем, что именно внутри incoming.value
2240
- if (Array.isArray(incoming.value)) {
2241
- cell.value = [incoming.value[0], incoming.value[1]];
2242
- }
2243
- else {
2244
- // Самый частый случай при частичном изменении формы:
2245
- // Пытаемся понять, это стартовая дата или конечная. Если это невозможно определить напрямую,
2246
- // и нам важен порядок, то FormDispenser обычно шлет массив.
2247
- // Но если он прислал одиночную строку, а у нас в cell.value уже что-то было:
2248
- cell.value = Array.isArray(incoming.value) ? incoming.value : [incoming.value, cell.value[1]];
2249
- }
2250
- }
2251
- }
2252
- else {
2253
- // Для всех остальных обычных полей (строки, переключатели, одиночные даты)
2254
- cell.value = incoming.value;
2255
- }
2256
- }
2257
- });
2258
- // Шаг 2: Валидация структуры. Проверяем ВСЕ range-компоненты в строке.
2259
- // Если где-то по ошибке оказалась строка вместо массива (как в вашем логе), принудительно чиним структуру!
2260
- this.settings.components.forEach(component => {
2261
- if (component.type === ComponentType.InputDate && component.options?.range) {
2262
- const cell = cloneRowModel.data.find(c => c.sysName === component.sysName);
2263
- if (cell && !Array.isArray(cell.value)) {
2264
- console.warn(`[Фикс структуры] Поле ${component.sysName} имело неверный тип значения:`, cell.value);
2265
- // Заворачиваем одиночную строку в массив, чтобы не ломать логику таблицы
2266
- cell.value = cell.value ? [cell.value, null] : [null, null];
2267
- }
2268
- }
2269
- });
2270
- this.rowModel = cloneRowModel;
2212
+ console.log('[Modal -> componentValueChanged] Изменение компонента. Пришло значение:', structuredClone(valueModel));
2213
+ if (isArray(valueModel)) {
2214
+ valueModel.forEach(model => {
2215
+ this._transformValues(model);
2216
+ });
2217
+ }
2218
+ else {
2219
+ this._transformValues(valueModel);
2220
+ }
2271
2221
  this._recalculateFormulaFields();
2272
2222
  this.emptyRow = this.rowModel.data.every(x => this.isEmpty(x.value, x.valueType));
2273
- console.log('Итоговый rowModel в памяти модалки:', structuredClone(this.rowModel));
2274
- console.groupEnd();
2275
2223
  }
2276
2224
  ok() {
2277
- console.group('=== МОДАЛКА: Нажата кнопка ОК ===');
2278
- console.log('Финальный rowModel перед отправкой в таблицу:', structuredClone(this.rowModel));
2225
+ console.log('[Modal -> OK] Попытка сохранения. Текущая модель перед закрытием:', structuredClone(this.rowModel));
2279
2226
  if (!this._isValid()) {
2280
- console.warn('Валидация модалки НЕ ПРОЙДЕНА');
2227
+ console.warn('[Modal -> OK] Форма не валидна!');
2228
+ // включаем подсветку полей
2281
2229
  this.store.dispatch(updateCheckRequired({ isCheckRequired: true }));
2282
- console.groupEnd();
2283
2230
  return;
2284
2231
  }
2285
- console.log('Валидация успешна. Закрываем модалку с результатом true.');
2232
+ // возвращаем признак как был до открытия модалки
2286
2233
  this.store.dispatch(updateCheckRequired({ isCheckRequired: this.isCheckRequired }));
2287
2234
  this.result = { result: true, rowModel: this.rowModel };
2288
2235
  this.dialogRef.close(structuredClone(this.result));
2289
- console.groupEnd();
2290
2236
  }
2291
2237
  close() {
2292
2238
  // возвращаем признак как был до открытия модалки
@@ -2297,8 +2243,15 @@ class InputTableModalComponent extends ModalServiceComponent {
2297
2243
  _transformValues(value) {
2298
2244
  const cloneRowModel = structuredClone(this.rowModel);
2299
2245
  const findValue = cloneRowModel.data.find((c) => c.sysName === value.sysName);
2246
+ console.log(`[Modal -> _transformValues] Пытаемся обновить поле "${value.sysName}". Найдено в rowModel.data:`, structuredClone(findValue));
2247
+ // const cloneRowModel = structuredClone(this.rowModel);
2248
+ // const findValue: ComponentValueModel | undefined = cloneRowModel.data.find((c: ComponentValueModel) => c.sysName === value.sysName);
2300
2249
  if (findValue) {
2301
2250
  findValue.value = value.value;
2251
+ console.log(`[Modal -> _transformValues] Успешно обновили "${value.sysName}". Новое значение поля:`, findValue.value);
2252
+ }
2253
+ else {
2254
+ console.warn(`[Modal -> _transformValues] Внимание! Поле с sysName "${value.sysName}" не найдено в rowModel.data`);
2302
2255
  }
2303
2256
  this.rowModel = cloneRowModel;
2304
2257
  }
@@ -2478,6 +2431,8 @@ class InputTableComponent {
2478
2431
  this._subscriptions$.forEach((subscription) => subscription.unsubscribe());
2479
2432
  }
2480
2433
  createRow() {
2434
+ const initialRowModel = getRowModel(this.settings);
2435
+ console.log('[Table -> Create Row] Исходная модель для новой строки:', structuredClone(initialRowModel));
2481
2436
  this._modalService.open(InputTableModalComponent, {
2482
2437
  title: 'Создание строки',
2483
2438
  okText: 'Создать',
@@ -2485,15 +2440,11 @@ class InputTableComponent {
2485
2440
  rowModel: getRowModel(this.settings),
2486
2441
  isCheckRequired: this._isCheckRequired
2487
2442
  }).afterClosed().subscribe(resolve => {
2443
+ console.log('[Table <- Modal Closed (Create)] Результат из модалки:', structuredClone(resolve));
2488
2444
  if (resolve.result) {
2489
- console.group('=== ТАБЛИЦА: Получены данные после СОЗДАНИЯ ===');
2490
- console.log('Данные строки из модалки (resolve.rowModel):', structuredClone(resolve.rowModel));
2491
2445
  this._rows = [...structuredClone(this._rows), resolve.rowModel];
2492
2446
  this._initDataSource(this._rows);
2493
- const nextValueModel = this._buildTableValueModel();
2494
- console.log('Сформированная модель таблицы для отправки в Store:', structuredClone(nextValueModel));
2495
2447
  this._changeSubject$.next(this._buildTableValueModel());
2496
- console.groupEnd();
2497
2448
  }
2498
2449
  });
2499
2450
  }
@@ -2510,13 +2461,17 @@ class InputTableComponent {
2510
2461
  }
2511
2462
  editRow(event) {
2512
2463
  const findRow = this._rows.find(item => item.id === event.row.data.id);
2464
+ console.log('[Table -> Edit Row] Данные строки из клика (event.row.data):', event.row.data);
2465
+ console.log('[Table -> Edit Row] Найдено в локальном rows:', structuredClone(findRow));
2466
+ // const findRow: TableRowModel | undefined = this._rows.find(item => item.id === event.row.data.id);
2513
2467
  if (findRow) {
2514
2468
  this._modalService.open(InputTableModalComponent, {
2515
2469
  title: 'Редактирование строки',
2516
2470
  okText: 'Сохранить',
2517
2471
  settings: this.settings,
2518
- rowModel: structuredClone(findRow) // Просто передаем клон строки, где внутри лежит массив строк дат
2472
+ rowModel: findRow
2519
2473
  }).afterClosed().subscribe(resolve => {
2474
+ console.log('[Table <- Modal Closed (Edit)] Результат из модалки:', structuredClone(resolve));
2520
2475
  if (resolve.result) {
2521
2476
  const cloneRows = structuredClone(this._rows);
2522
2477
  const editableRow = cloneRows.find(row => row.id === resolve.rowModel.id);
@@ -2573,6 +2528,7 @@ class InputTableComponent {
2573
2528
  this._rows = [];
2574
2529
  }
2575
2530
  _initDataSource(data) {
2531
+ console.log('[Table -> _initDataSource] Преобразование rows в dataSource таблицы. Исходный rows:', structuredClone(data));
2576
2532
  this.dataSource = data.map((item) => {
2577
2533
  const newDataItem = {};
2578
2534
  for (let i in item.data) {
@@ -2581,6 +2537,7 @@ class InputTableComponent {
2581
2537
  newDataItem.id = item.id;
2582
2538
  return newDataItem;
2583
2539
  });
2540
+ console.log('[Table -> _initDataSource] Итоговый dataSource для DevExtreme:', structuredClone(this.dataSource));
2584
2541
  this._detector.detectChanges();
2585
2542
  if (this.dataGrid?.instance) {
2586
2543
  this.dataGrid.instance.refresh();
@@ -2621,19 +2578,6 @@ class InputTableComponent {
2621
2578
  format: this.getFormat(component),
2622
2579
  minWidth: 160
2623
2580
  };
2624
- if (component.type === ComponentType.InputDate && component.options?.range) {
2625
- column.calculateCellValue = (rowData) => {
2626
- const cellData = rowData[component.sysName]; // Массив строк ['2026...', '2026...']
2627
- if (Array.isArray(cellData) && cellData.length === 2) {
2628
- const startRaw = cellData[0];
2629
- const endRaw = cellData[1];
2630
- if (startRaw || endRaw) {
2631
- return `${this._formatToRuDate(startRaw)} - ${this._formatToRuDate(endRaw)}`;
2632
- }
2633
- }
2634
- return cellData ? this._formatToRuDate(cellData) : '';
2635
- };
2636
- }
2637
2581
  if (dataType === 'boolean') {
2638
2582
  column.calculateCellValue = (rowData) => {
2639
2583
  const value = rowData[component.sysName];
@@ -2680,17 +2624,6 @@ class InputTableComponent {
2680
2624
  }
2681
2625
  return column;
2682
2626
  }
2683
- _formatToRuDate(dateString) {
2684
- if (!dateString)
2685
- return '...';
2686
- const date = new Date(dateString);
2687
- if (isNaN(date.getTime()))
2688
- return '...';
2689
- const day = String(date.getDate()).padStart(2, '0');
2690
- const month = String(date.getMonth() + 1).padStart(2, '0');
2691
- const year = date.getFullYear();
2692
- return `${day}.${month}.${year}`;
2693
- }
2694
2627
  getLookupData(directoryName) {
2695
2628
  // Проверяем кэш
2696
2629
  if (this._lookupsCache.has(directoryName)) {