@progress/kendo-angular-grid 21.2.0 → 21.3.0-develop.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,624 @@
1
+ /**-----------------------------------------------------------------------------------------
2
+ * Copyright © 2025 Progress Software Corporation. All rights reserved.
3
+ * Licensed under commercial license. See LICENSE.md in the project root for more information
4
+ *-------------------------------------------------------------------------------------------*/
5
+ import { Injectable, NgZone } from '@angular/core';
6
+ import { isPresent } from '@progress/kendo-angular-common';
7
+ import { ColumnInfoService } from './../../../../common/column-info.service';
8
+ import { ContextService } from './../../../../common/provider.service';
9
+ import { convertDateStringsInFilter, highlightBy } from './utils';
10
+ import { isCheckboxColumn } from '../../../../columns/column-base';
11
+ import { CommandColumnComponent } from '../../../../columns/command-column.component';
12
+ import * as i0 from "@angular/core";
13
+ import * as i1 from "./../../../../common/provider.service";
14
+ import * as i2 from "./../../../../common/column-info.service";
15
+ /**
16
+ * @hidden
17
+ *
18
+ * Service that builds AI requests and processes AI responses for the Grid.
19
+ * Used internally by both the Grid component and the AI Assistant tool.
20
+ */
21
+ export class GridAIRequestResponseService {
22
+ ctx;
23
+ columnInfoService;
24
+ zone;
25
+ constructor(ctx, columnInfoService, zone) {
26
+ this.ctx = ctx;
27
+ this.columnInfoService = columnInfoService;
28
+ this.zone = zone;
29
+ }
30
+ /**
31
+ * Builds the request body for the AI service based on the Grid's column structure.
32
+ * Returns a column descriptor tree that includes column metadata for the AI service.
33
+ */
34
+ buildRequestBody(promptMessage, role) {
35
+ const columnsTree = this.buildColumnDescriptors();
36
+ return {
37
+ role: role || 'user',
38
+ contents: [
39
+ {
40
+ text: promptMessage
41
+ }
42
+ ],
43
+ columns: columnsTree
44
+ };
45
+ }
46
+ /**
47
+ * Builds a nested column descriptor tree based on the Grid's column structure.
48
+ * Includes root columns and their nested children (for ColumnGroup and SpanColumn).
49
+ */
50
+ buildColumnDescriptors() {
51
+ const rootColumns = this.ctx?.grid?.columnList?.rootColumns() || [];
52
+ const buildDescriptor = (col) => {
53
+ const hasChildren = Boolean(col.hasChildren && col.childrenArray?.length);
54
+ const descriptor = {
55
+ id: col.id,
56
+ field: col.field,
57
+ header: col.title
58
+ };
59
+ if (hasChildren) {
60
+ descriptor.columns = col.childrenArray.map((c) => buildDescriptor(c));
61
+ }
62
+ // For special columns that don't have a field, emit an optional type token
63
+ // so the AI service knows how to treat them (checkbox/command/reorder)
64
+ if (!col.field) {
65
+ if (isCheckboxColumn(col)) {
66
+ descriptor.type = 'checkbox';
67
+ }
68
+ else if (col instanceof CommandColumnComponent) {
69
+ descriptor.type = 'command';
70
+ }
71
+ }
72
+ return descriptor;
73
+ };
74
+ return rootColumns.map((col) => buildDescriptor(col));
75
+ }
76
+ /**
77
+ * Processes AI response commands and applies them to the Grid.
78
+ * Returns an array of display messages for each command.
79
+ */
80
+ processCommands(commands, columns, leafColumns) {
81
+ const messages = [];
82
+ this.executeCommands(commands || [], columns, leafColumns, messages);
83
+ return messages;
84
+ }
85
+ executeCommands(commands, columns, leafColumns, messages) {
86
+ if (!commands?.length) {
87
+ return;
88
+ }
89
+ const grid = this.ctx.grid;
90
+ const isFilterable = Boolean(grid.filterable);
91
+ const isSortable = Boolean(grid.sortable);
92
+ const isGroupable = Boolean(grid.groupable);
93
+ const findColumnById = (id) => grid.columnList.toArray().find((c) => c.id === id);
94
+ const updateColumnHierarchy = (column, updater) => {
95
+ const changed = [];
96
+ const queue = [column];
97
+ while (queue.length) {
98
+ const current = queue.shift();
99
+ if (!current) {
100
+ continue;
101
+ }
102
+ const didChange = updater(current);
103
+ if (didChange) {
104
+ changed.push(current);
105
+ }
106
+ if (current.hasChildren && current.childrenArray?.length) {
107
+ queue.push(...current.childrenArray);
108
+ }
109
+ }
110
+ return changed;
111
+ };
112
+ commands.forEach((cmd) => {
113
+ let displayMessage = cmd.message || '';
114
+ if (this.isColumnCommand(cmd.type)) {
115
+ if (cmd.id) {
116
+ const column = findColumnById(cmd.id);
117
+ const replacement = this.getColumnReplacement(column);
118
+ displayMessage = this.replaceQuotedColumnId(displayMessage, replacement);
119
+ }
120
+ }
121
+ messages.push(displayMessage);
122
+ switch (cmd.type) {
123
+ case 'GridSort':
124
+ if (!isSortable) {
125
+ break;
126
+ }
127
+ this.processArrayResponse([cmd.sort], grid.currentState.sort || [], (item) => item.field, (mergedArray) => grid.sortChange.next(mergedArray));
128
+ break;
129
+ case 'GridClearSort':
130
+ if (!isSortable) {
131
+ break;
132
+ }
133
+ grid.sortChange.next([]);
134
+ break;
135
+ case 'GridFilter':
136
+ if (!isFilterable) {
137
+ break;
138
+ }
139
+ this.processFilterResponse(cmd.filter);
140
+ break;
141
+ case 'GridClearFilter':
142
+ if (!isFilterable) {
143
+ break;
144
+ }
145
+ grid.filterChange.next(undefined);
146
+ break;
147
+ case 'GridGroup':
148
+ if (!isGroupable) {
149
+ break;
150
+ }
151
+ this.processArrayResponse([cmd.group], grid.currentState.group || [], (item) => item.field, (mergedArray) => grid.groupChange.next(mergedArray));
152
+ break;
153
+ case 'GridClearGroup':
154
+ if (!isGroupable) {
155
+ break;
156
+ }
157
+ grid.groupChange.next([]);
158
+ break;
159
+ case 'GridHighlight':
160
+ if (!this.ctx.highlightDirective) {
161
+ break;
162
+ }
163
+ this.processHighlightResponse([cmd.highlight], columns);
164
+ break;
165
+ case 'GridClearHighlight':
166
+ if (!this.ctx.highlightDirective) {
167
+ break;
168
+ }
169
+ this.ctx.highlightDirective['setState']([]);
170
+ break;
171
+ case 'GridSelect': {
172
+ this.processSelectionResponse([cmd.select], columns, leafColumns, messages);
173
+ break;
174
+ }
175
+ case 'GridClearSelect': {
176
+ const selectionInstance = this.getSelectionInstance();
177
+ if (!selectionInstance) {
178
+ this.updateLastMessage(messages, this.ctx.localization?.get('aiAssistantSelectionNotEnabled'));
179
+ break;
180
+ }
181
+ this.applySelectionState(selectionInstance, []);
182
+ break;
183
+ }
184
+ case 'GridColumnResize': {
185
+ const col = findColumnById(cmd.id);
186
+ if (!col) {
187
+ break;
188
+ }
189
+ let newWidth;
190
+ if (typeof cmd.size === 'number') {
191
+ newWidth = cmd.size;
192
+ }
193
+ else if (typeof cmd.size === 'string') {
194
+ const numericPart = parseFloat(cmd.size);
195
+ if (!isNaN(numericPart)) {
196
+ newWidth = numericPart;
197
+ }
198
+ }
199
+ if (typeof newWidth === 'number') {
200
+ const oldWidth = col.width;
201
+ col.width = newWidth;
202
+ const args = [{ column: col, oldWidth: oldWidth, newWidth: newWidth }];
203
+ grid.columnResize.emit(args);
204
+ }
205
+ break;
206
+ }
207
+ case 'GridColumnReorder': {
208
+ const col = findColumnById(cmd.id);
209
+ if (!col) {
210
+ break;
211
+ }
212
+ const newPosition = Number(cmd.position);
213
+ if (!isNaN(newPosition) && newPosition >= 0) {
214
+ this.changeColumnPosition(col, newPosition);
215
+ }
216
+ break;
217
+ }
218
+ case 'GridColumnShow':
219
+ case 'GridColumnHide': {
220
+ const col = findColumnById(cmd.id);
221
+ if (!col) {
222
+ break;
223
+ }
224
+ const targetHidden = cmd.type === 'GridColumnHide';
225
+ const changed = updateColumnHierarchy(col, (current) => {
226
+ if (current.hidden === targetHidden) {
227
+ return false;
228
+ }
229
+ current.hidden = targetHidden;
230
+ return true;
231
+ });
232
+ if (changed.length) {
233
+ this.columnInfoService.changeVisibility(changed);
234
+ }
235
+ break;
236
+ }
237
+ case 'GridColumnLock':
238
+ case 'GridColumnUnlock': {
239
+ const col = findColumnById(cmd.id);
240
+ if (!col) {
241
+ break;
242
+ }
243
+ const targetLocked = cmd.type === 'GridColumnLock';
244
+ const changed = updateColumnHierarchy(col, (current) => {
245
+ if (current.locked === targetLocked) {
246
+ return false;
247
+ }
248
+ current.locked = targetLocked;
249
+ return true;
250
+ });
251
+ if (changed.length) {
252
+ this.columnInfoService.changeLocked(changed);
253
+ }
254
+ break;
255
+ }
256
+ case 'GridPage': {
257
+ this.processPageCommand(cmd);
258
+ break;
259
+ }
260
+ case 'GridPageSize': {
261
+ this.processPageSizeCommand(cmd);
262
+ break;
263
+ }
264
+ case 'GridExportExcel': {
265
+ this.runExportWithFileName(this.ctx.excelComponent, cmd.fileName, () => grid.saveAsExcel());
266
+ break;
267
+ }
268
+ case 'GridExportPDF': {
269
+ this.runExportWithFileName(this.ctx.pdfComponent, cmd.fileName, () => grid.emitPDFExportEvent());
270
+ break;
271
+ }
272
+ default:
273
+ break;
274
+ }
275
+ });
276
+ }
277
+ processArrayResponse(newItems, currentItems, getField, updateGrid) {
278
+ if (newItems?.length === 0) {
279
+ updateGrid([]);
280
+ }
281
+ else if (newItems?.length) {
282
+ let mergedArray = [...newItems];
283
+ const newFields = newItems.map(getField);
284
+ const existingItemsToKeep = currentItems.filter(item => !newFields.includes(getField(item)));
285
+ mergedArray = [...mergedArray, ...existingItemsToKeep];
286
+ updateGrid(mergedArray);
287
+ }
288
+ }
289
+ runExportWithFileName(component, fileName, action) {
290
+ if (!component || !fileName) {
291
+ action();
292
+ return;
293
+ }
294
+ const previousFileName = component.fileName;
295
+ component.fileName = fileName;
296
+ action();
297
+ const isExcel = component === this.ctx.excelComponent;
298
+ if (isExcel) {
299
+ this.zone.runOutsideAngular(() => {
300
+ this.ctx.excelComponent.fileCreated.subscribe(() => {
301
+ component.fileName = previousFileName;
302
+ });
303
+ });
304
+ }
305
+ else {
306
+ component.fileName = previousFileName;
307
+ }
308
+ }
309
+ processPageCommand(command) {
310
+ const pageSize = this.getCurrentPageSizeValue();
311
+ if (!isPresent(pageSize) || pageSize <= 0) {
312
+ return;
313
+ }
314
+ const total = this.getTotalItemsCount();
315
+ const requestedPage = Number(command.page);
316
+ let targetPage = Number.isFinite(requestedPage) ? Math.floor(requestedPage) : 1;
317
+ if (targetPage < 1) {
318
+ targetPage = 1;
319
+ }
320
+ if (isPresent(total) && pageSize > 0) {
321
+ const maxPage = Math.max(1, Math.ceil(total / pageSize));
322
+ targetPage = Math.min(targetPage, maxPage);
323
+ }
324
+ const skip = (targetPage - 1) * pageSize;
325
+ this.emitGridPageChange(skip, pageSize);
326
+ }
327
+ processPageSizeCommand(command) {
328
+ const rawPageSize = Number(command.pageSize);
329
+ if (!Number.isFinite(rawPageSize)) {
330
+ return;
331
+ }
332
+ const newPageSize = Math.max(1, Math.floor(rawPageSize));
333
+ const skip = Math.max(0, this.ctx.grid?.skip ?? 0);
334
+ this.ensurePageSizeOption(newPageSize);
335
+ this.emitGridPageChange(skip, newPageSize);
336
+ }
337
+ emitGridPageChange(skip, take) {
338
+ const grid = this.ctx.grid;
339
+ const normalizedSkip = Math.max(0, Math.floor(skip));
340
+ const normalizedTake = Math.max(1, Math.floor(take));
341
+ grid.skip = normalizedSkip;
342
+ grid.pageSize = normalizedTake;
343
+ grid.pageChange.emit({ skip: normalizedSkip, take: normalizedTake });
344
+ }
345
+ ensurePageSizeOption(pageSize) {
346
+ const grid = this.ctx.grid;
347
+ if (!grid) {
348
+ return;
349
+ }
350
+ const pageable = grid.pageable;
351
+ if (!pageable || typeof pageable === 'boolean') {
352
+ return;
353
+ }
354
+ const pageSizes = pageable.pageSizes;
355
+ if (!Array.isArray(pageSizes) || pageSizes.length === 0) {
356
+ return;
357
+ }
358
+ if (pageSizes.includes(pageSize)) {
359
+ return;
360
+ }
361
+ const uniqueSizes = [pageSize, ...pageSizes.filter(size => size !== pageSize)];
362
+ grid.pageable = {
363
+ ...pageable,
364
+ pageSizes: uniqueSizes
365
+ };
366
+ const changeDetector = grid?.changeDetectorRef;
367
+ if (changeDetector && typeof changeDetector.markForCheck === 'function') {
368
+ changeDetector.markForCheck();
369
+ }
370
+ }
371
+ getCurrentPageSizeValue() {
372
+ const grid = this.ctx.grid;
373
+ if (!grid) {
374
+ return null;
375
+ }
376
+ const candidates = [grid.pageSize, grid.currentState?.take, this.ctx.dataBindingDirective?.['state']?.take];
377
+ for (const candidate of candidates) {
378
+ if (typeof candidate === 'number' && candidate > 0) {
379
+ return candidate;
380
+ }
381
+ }
382
+ const pageable = grid.pageable;
383
+ if (pageable && typeof pageable === 'object' && Array.isArray(pageable.pageSizes)) {
384
+ const numericSize = pageable.pageSizes.find(size => typeof size === 'number' && size > 0);
385
+ if (numericSize) {
386
+ return numericSize;
387
+ }
388
+ }
389
+ const originalData = this.ctx.dataBindingDirective?.['originalData'];
390
+ if (Array.isArray(originalData) && originalData.length > 0) {
391
+ return originalData.length;
392
+ }
393
+ return null;
394
+ }
395
+ getTotalItemsCount() {
396
+ const grid = this.ctx.grid;
397
+ if (!grid) {
398
+ return null;
399
+ }
400
+ const gridData = grid.data;
401
+ if (gridData && typeof gridData.total === 'number') {
402
+ return gridData.total;
403
+ }
404
+ const view = grid.view;
405
+ if (view && typeof view.total === 'number') {
406
+ return view.total;
407
+ }
408
+ const originalData = this.ctx.dataBindingDirective?.['originalData'];
409
+ if (Array.isArray(originalData)) {
410
+ return originalData.length;
411
+ }
412
+ return null;
413
+ }
414
+ getSelectionInstance() {
415
+ const selectionDirective = this.ctx.grid?.selectionDirective;
416
+ if (selectionDirective && typeof selectionDirective === 'object') {
417
+ return selectionDirective;
418
+ }
419
+ const defaultSelection = this.ctx.grid?.defaultSelection;
420
+ if (defaultSelection && typeof defaultSelection === 'object') {
421
+ return defaultSelection;
422
+ }
423
+ return null;
424
+ }
425
+ updateLastMessage(messages, newMessage) {
426
+ if (!messages.length) {
427
+ return;
428
+ }
429
+ messages[messages.length - 1] = newMessage;
430
+ }
431
+ isColumnCommand(type) {
432
+ return type === 'GridColumnResize' ||
433
+ type === 'GridColumnReorder' ||
434
+ type === 'GridColumnShow' ||
435
+ type === 'GridColumnHide' ||
436
+ type === 'GridColumnLock' ||
437
+ type === 'GridColumnUnlock';
438
+ }
439
+ getColumnReplacement(column) {
440
+ if (!column) {
441
+ return '';
442
+ }
443
+ if (column.title && String(column.title).trim()) {
444
+ return String(column.title).trim();
445
+ }
446
+ if (column.field && String(column.field).trim()) {
447
+ return String(column.field).trim();
448
+ }
449
+ return '';
450
+ }
451
+ replaceQuotedColumnId(message, replacement) {
452
+ if (!replacement) {
453
+ const columnIdPattern = /(?:&quot;|")(k-grid\d+-col\d+)(?:&quot;|")\s*/g;
454
+ return message.replace(columnIdPattern, '').replace(/\s{2,}/g, ' ').trim();
455
+ }
456
+ const columnIdPattern = /(?:&quot;|")(k-grid\d+-col\d+)(?:&quot;|")/g;
457
+ return message.replace(columnIdPattern, (match) => {
458
+ const isEncoded = match.startsWith('&quot;');
459
+ return isEncoded ? `&quot;${replacement}&quot;` : `"${replacement}"`;
460
+ });
461
+ }
462
+ getHighlightItems(descriptors, columns) {
463
+ if (!descriptors?.length) {
464
+ return [];
465
+ }
466
+ const data = this.ctx.dataBindingDirective?.['originalData'] || [];
467
+ return highlightBy(data, descriptors, columns);
468
+ }
469
+ processSelectionResponse(selection, columns, leafColumns, messages) {
470
+ const selectionInstance = this.getSelectionInstance();
471
+ if (!selectionInstance) {
472
+ this.updateLastMessage(messages, this.ctx.localization?.get('aiAssistantSelectionNotEnabled'));
473
+ return;
474
+ }
475
+ const descriptors = (selection || []).filter((descriptor) => Boolean(descriptor));
476
+ if (descriptors.length === 0) {
477
+ this.applySelectionState(selectionInstance, []);
478
+ return;
479
+ }
480
+ const highlightItems = this.getHighlightItems(descriptors, columns);
481
+ if (!highlightItems.length) {
482
+ this.applySelectionState(selectionInstance, []);
483
+ return;
484
+ }
485
+ const hasCellSelections = highlightItems.some(item => isPresent(item.columnKey));
486
+ const hasRowSelections = highlightItems.some(item => !isPresent(item.columnKey));
487
+ const isCellMode = selectionInstance.isCellSelectionMode;
488
+ if ((!isCellMode && hasCellSelections) || (isCellMode && hasRowSelections)) {
489
+ const key = isCellMode ? 'aiAssistantSelectionRowModeRequired' : 'aiAssistantSelectionCellModeRequired';
490
+ this.updateLastMessage(messages, this.ctx.localization?.get(key));
491
+ return;
492
+ }
493
+ const selectionState = this.mapHighlightItemsToSelection(selectionInstance, highlightItems, isCellMode, leafColumns);
494
+ this.applySelectionState(selectionInstance, selectionState);
495
+ }
496
+ mapHighlightItemsToSelection(selectionInstance, highlightItems, isCellMode, leafColumns) {
497
+ const data = this.ctx.dataBindingDirective?.['originalData'] || [];
498
+ if (isCellMode) {
499
+ const mapped = highlightItems
500
+ .filter(item => isPresent(item.itemKey) && isPresent(item.columnKey))
501
+ .map(item => {
502
+ const rowIndex = item.itemKey;
503
+ const columnIndex = item.columnKey;
504
+ const dataItem = data[rowIndex];
505
+ if (!isPresent(dataItem)) {
506
+ return null;
507
+ }
508
+ if (typeof selectionInstance['getSelectionItem'] === 'function') {
509
+ const columnComponent = leafColumns[columnIndex];
510
+ const selectionItem = selectionInstance['getSelectionItem']({ dataItem, index: rowIndex }, columnComponent, columnIndex);
511
+ if (selectionItem && isPresent(selectionItem.itemKey) && isPresent(selectionItem.columnKey)) {
512
+ return selectionItem;
513
+ }
514
+ return null;
515
+ }
516
+ const itemKey = typeof selectionInstance.getItemKey === 'function'
517
+ ? selectionInstance.getItemKey({ dataItem, index: rowIndex })
518
+ : rowIndex;
519
+ return isPresent(itemKey) ? { itemKey, columnKey: columnIndex } : null;
520
+ })
521
+ .filter((item) => isPresent(item));
522
+ return mapped.filter((item, index, self) => self.findIndex(other => other.itemKey === item.itemKey && other.columnKey === item.columnKey) === index);
523
+ }
524
+ const rowKeys = highlightItems
525
+ .filter(item => isPresent(item.itemKey))
526
+ .map(item => {
527
+ const rowIndex = item.itemKey;
528
+ const dataItem = data[rowIndex];
529
+ if (!isPresent(dataItem)) {
530
+ return null;
531
+ }
532
+ if (typeof selectionInstance.getItemKey === 'function') {
533
+ return selectionInstance.getItemKey({ dataItem, index: rowIndex });
534
+ }
535
+ return rowIndex;
536
+ })
537
+ .filter(isPresent);
538
+ return Array.from(new Set(rowKeys));
539
+ }
540
+ applySelectionState(selectionInstance, selectionState) {
541
+ selectionInstance.selectedKeys = selectionState;
542
+ if (typeof selectionInstance['setState'] === 'function') {
543
+ selectionInstance['setState'](selectionState);
544
+ }
545
+ const changeDetector = selectionInstance['cd'];
546
+ if (changeDetector && typeof changeDetector.markForCheck === 'function') {
547
+ changeDetector.markForCheck();
548
+ }
549
+ if (typeof selectionInstance['notifyChange'] === 'function') {
550
+ selectionInstance['notifyChange']();
551
+ }
552
+ }
553
+ processHighlightResponse(highlight, columns) {
554
+ const highlightedItems = this.getHighlightItems(highlight, columns);
555
+ this.ctx.highlightDirective['setState'](highlightedItems);
556
+ }
557
+ processFilterResponse(filter) {
558
+ const processedFilter = convertDateStringsInFilter(filter);
559
+ const clearFilter = Object.keys(processedFilter).length === 0;
560
+ if (clearFilter) {
561
+ this.ctx.grid.filterChange.next(undefined);
562
+ }
563
+ else if (processedFilter?.filters.length) {
564
+ const currentFilter = this.ctx.grid.currentState.filter;
565
+ let mergedFilter = processedFilter;
566
+ if (currentFilter && currentFilter.filters?.length > 0) {
567
+ mergedFilter = {
568
+ logic: 'and',
569
+ filters: [
570
+ currentFilter,
571
+ processedFilter
572
+ ]
573
+ };
574
+ }
575
+ this.ctx.grid.filterChange.next(mergedFilter);
576
+ }
577
+ }
578
+ changeColumnPosition(column, newPosition) {
579
+ const grid = this.ctx.grid;
580
+ if (!grid?.columns) {
581
+ return;
582
+ }
583
+ const currentColumns = grid.columns.toArray();
584
+ const currentIndex = currentColumns.findIndex(col => col === column);
585
+ if (currentIndex === -1) {
586
+ return;
587
+ }
588
+ if (newPosition < 0 || newPosition >= currentColumns.length) {
589
+ return;
590
+ }
591
+ const sortedColumns = currentColumns
592
+ .map((col, idx) => ({ col, physicalIndex: idx, visualOrder: col.orderIndex ?? idx }))
593
+ .sort((a, b) => a.visualOrder - b.visualOrder);
594
+ const currentVisualPos = sortedColumns.findIndex(item => item.physicalIndex === currentIndex);
595
+ if (currentVisualPos === newPosition) {
596
+ return;
597
+ }
598
+ currentColumns.forEach((col, idx) => {
599
+ const sortedIndex = sortedColumns.findIndex(item => item.physicalIndex === idx);
600
+ if (idx === currentIndex) {
601
+ col.orderIndex = newPosition;
602
+ }
603
+ else if (currentVisualPos < newPosition) {
604
+ col.orderIndex = (sortedIndex > currentVisualPos && sortedIndex <= newPosition)
605
+ ? sortedIndex - 1 : sortedIndex;
606
+ }
607
+ else {
608
+ col.orderIndex = (sortedIndex >= newPosition && sortedIndex < currentVisualPos)
609
+ ? sortedIndex + 1 : sortedIndex;
610
+ }
611
+ col.isReordered = true;
612
+ });
613
+ grid.columnReorder.emit({
614
+ column: column,
615
+ oldIndex: currentVisualPos,
616
+ newIndex: newPosition
617
+ });
618
+ }
619
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GridAIRequestResponseService, deps: [{ token: i1.ContextService }, { token: i2.ColumnInfoService }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
620
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GridAIRequestResponseService });
621
+ }
622
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GridAIRequestResponseService, decorators: [{
623
+ type: Injectable
624
+ }], ctorParameters: () => [{ type: i1.ContextService }, { type: i2.ColumnInfoService }, { type: i0.NgZone }] });