• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

IgniteUI / igniteui-angular / 13331632524

14 Feb 2025 02:51PM CUT coverage: 22.015% (-69.6%) from 91.622%
13331632524

Pull #15372

github

web-flow
Merge d52d57714 into bcb78ae0a
Pull Request #15372: chore(*): test ci passing

1990 of 15592 branches covered (12.76%)

431 of 964 new or added lines in 18 files covered. (44.71%)

19956 existing lines in 307 files now uncovered.

6452 of 29307 relevant lines covered (22.02%)

249.17 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

5.3
/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid.pipes.ts
1
import { Inject, Pipe, PipeTransform } from '@angular/core';
2
import { cloneArray, cloneHierarchicalArray } from '../../core/utils';
3
import { DataUtil } from '../../data-operations/data-util';
4
import { ITreeGridRecord } from './tree-grid.interfaces';
5
import { GridType, IGX_GRID_BASE } from '../common/grid.interface';
6
import { GridPagingMode } from '../common/enums';
7
import { TransactionType } from '../../services/public_api';
8
import { IgxAddRow } from '../common/crud.service';
9
import { ISortingExpression } from '../../data-operations/sorting-strategy';
10
import { IGridSortingStrategy } from '../common/strategy';
11
import { IGroupingExpression } from '../../data-operations/grouping-expression.interface';
12

13
/**
14
 * @hidden
15
 */
16
@Pipe({
17
    name: 'treeGridHierarchizing',
18
    standalone: true
19
})
20
export class IgxTreeGridHierarchizingPipe implements PipeTransform {
2✔
21

UNCOV
22
    constructor(@Inject(IGX_GRID_BASE) private grid: GridType) { }
×
23

24
    public transform(collection: any[], primaryKey: string, foreignKey: string, childDataKey: string, _: number): ITreeGridRecord[] {
UNCOV
25
        let hierarchicalRecords: ITreeGridRecord[] = [];
×
UNCOV
26
        const treeGridRecordsMap = new Map<any, ITreeGridRecord>();
×
UNCOV
27
        const flatData: any[] = [];
×
28

UNCOV
29
        if (!collection || !collection.length) {
×
UNCOV
30
            this.grid.flatData = collection;
×
UNCOV
31
            this.grid.records = treeGridRecordsMap;
×
UNCOV
32
            this.grid.rootRecords = collection;
×
UNCOV
33
            return collection;
×
34
        }
35

UNCOV
36
        if (childDataKey) {
×
UNCOV
37
            hierarchicalRecords = this.hierarchizeRecursive(collection, primaryKey, childDataKey, undefined,
×
38
                flatData, 0, treeGridRecordsMap);
UNCOV
39
        } else if (primaryKey) {
×
UNCOV
40
            hierarchicalRecords = this.hierarchizeFlatData(collection, primaryKey, foreignKey, treeGridRecordsMap, flatData);
×
41
        }
42

UNCOV
43
        this.grid.flatData = this.grid.transactions.enabled ?
×
44
            flatData.filter(rec => {
UNCOV
45
                const state = this.grid.transactions.getState(this.getRowID(primaryKey, rec));
×
UNCOV
46
                return !state || state.type !== TransactionType.ADD;
×
47
            }) : flatData;
UNCOV
48
        this.grid.records = treeGridRecordsMap;
×
UNCOV
49
        this.grid.rootRecords = hierarchicalRecords;
×
UNCOV
50
        return hierarchicalRecords;
×
51
    }
52

53
    private getRowID(primaryKey: any, rowData: any) {
UNCOV
54
        return primaryKey ? rowData[primaryKey] : rowData;
×
55
    }
56

57
    private hierarchizeFlatData(collection: any[], primaryKey: string, foreignKey: string,
58
        map: Map<any, ITreeGridRecord>, flatData: any[]):
59
        ITreeGridRecord[] {
UNCOV
60
        const result: ITreeGridRecord[] = [];
×
UNCOV
61
        const missingParentRecords: ITreeGridRecord[] = [];
×
UNCOV
62
        collection.forEach(row => {
×
UNCOV
63
            const record: ITreeGridRecord = {
×
64
                key: this.getRowID(primaryKey, row),
65
                data: row,
66
                children: []
67
            };
UNCOV
68
            const parent = map.get(row[foreignKey]);
×
UNCOV
69
            if (parent) {
×
UNCOV
70
                record.parent = parent;
×
UNCOV
71
                parent.children.push(record);
×
72
            } else {
UNCOV
73
                missingParentRecords.push(record);
×
74
            }
75

UNCOV
76
            map.set(row[primaryKey], record);
×
77
        });
78

UNCOV
79
        missingParentRecords.forEach(record => {
×
UNCOV
80
            const parent = map.get(record.data[foreignKey]);
×
UNCOV
81
            if (parent) {
×
UNCOV
82
                record.parent = parent;
×
UNCOV
83
                parent.children.push(record);
×
84
            } else {
UNCOV
85
                result.push(record);
×
86
            }
87
        });
88

UNCOV
89
        this.setIndentationLevels(result, 0, flatData);
×
90

UNCOV
91
        return result;
×
92
    }
93

94
    private setIndentationLevels(collection: ITreeGridRecord[], indentationLevel: number, flatData: any[]) {
UNCOV
95
        for (const record of collection) {
×
UNCOV
96
            record.level = indentationLevel;
×
UNCOV
97
            record.expanded = this.grid.gridAPI.get_row_expansion_state(record);
×
UNCOV
98
            flatData.push(record.data);
×
99

UNCOV
100
            if (record.children && record.children.length > 0) {
×
UNCOV
101
                this.setIndentationLevels(record.children, indentationLevel + 1, flatData);
×
102
            }
103
        }
104
    }
105

106
    private hierarchizeRecursive(collection: any[], primaryKey: string, childDataKey: string,
107
        parent: ITreeGridRecord, flatData: any[], indentationLevel: number, map: Map<any, ITreeGridRecord>): ITreeGridRecord[] {
UNCOV
108
        const result: ITreeGridRecord[] = [];
×
109

UNCOV
110
        for (const item of collection) {
×
UNCOV
111
            const record: ITreeGridRecord = {
×
112
                key: this.getRowID(primaryKey, item),
113
                data: item,
114
                parent,
115
                level: indentationLevel
116
            };
UNCOV
117
            record.expanded = this.grid.gridAPI.get_row_expansion_state(record);
×
UNCOV
118
            flatData.push(item);
×
UNCOV
119
            map.set(record.key, record);
×
UNCOV
120
            record.children = item[childDataKey] ?
×
121
                this.hierarchizeRecursive(item[childDataKey], primaryKey, childDataKey, record, flatData, indentationLevel + 1, map) :
122
                undefined;
UNCOV
123
            result.push(record);
×
124
        }
125

UNCOV
126
        return result;
×
127
    }
128
}
129

130
/**
131
 * @hidden
132
 */
133
@Pipe({
134
    name: 'treeGridFlattening',
135
    standalone: true
136
})
137
export class IgxTreeGridFlatteningPipe implements PipeTransform {
2✔
138

UNCOV
139
    constructor(@Inject(IGX_GRID_BASE) private grid: GridType) { }
×
140

141
    public transform(collection: ITreeGridRecord[],
142
        expandedLevels: number, expandedStates: Map<any, boolean>, _: number): any[] {
143

UNCOV
144
        const data: ITreeGridRecord[] = [];
×
145

UNCOV
146
        this.grid.processedRootRecords = collection;
×
UNCOV
147
        this.grid.processedRecords = new Map<any, ITreeGridRecord>();
×
148

UNCOV
149
        this.getFlatDataRecursive(collection, data, expandedLevels, expandedStates, true);
×
150

UNCOV
151
        this.grid.processedExpandedFlatData = data.map(r => r.data);
×
152

UNCOV
153
        return data;
×
154
    }
155

156
    private getFlatDataRecursive(collection: ITreeGridRecord[], data: ITreeGridRecord[],
157
        expandedLevels: number, expandedStates: Map<any, boolean>, parentExpanded: boolean) {
UNCOV
158
        if (!collection || !collection.length) {
×
UNCOV
159
            return;
×
160
        }
161

UNCOV
162
        for (const hierarchicalRecord of collection) {
×
UNCOV
163
            if (parentExpanded) {
×
UNCOV
164
                data.push(hierarchicalRecord);
×
165
            }
166

UNCOV
167
            hierarchicalRecord.expanded = this.grid.gridAPI.get_row_expansion_state(hierarchicalRecord);
×
168

UNCOV
169
            this.updateNonProcessedRecordExpansion(this.grid, hierarchicalRecord);
×
170

UNCOV
171
            this.grid.processedRecords.set(hierarchicalRecord.key, hierarchicalRecord);
×
172

UNCOV
173
            this.getFlatDataRecursive(hierarchicalRecord.children, data, expandedLevels,
×
174
                expandedStates, parentExpanded && hierarchicalRecord.expanded);
×
175
        }
176
    }
177

178
    private updateNonProcessedRecordExpansion(grid: GridType, record: ITreeGridRecord) {
UNCOV
179
        const rec = grid.records.get(record.key);
×
UNCOV
180
        rec.expanded = record.expanded;
×
181
    }
182
}
183

184
/** @hidden */
185
@Pipe({
186
    name: 'treeGridSorting',
187
    standalone: true
188
})
189
export class IgxTreeGridSortingPipe implements PipeTransform {
2✔
190

UNCOV
191
    constructor(@Inject(IGX_GRID_BASE) private grid: GridType) { }
×
192

193
    public transform(
194
        hierarchicalData: ITreeGridRecord[],
195
        sortExpressions: ISortingExpression[],
196
        groupExpressions: IGroupingExpression[],
197
        sorting: IGridSortingStrategy,
198
        _: number,
199
        pinned?: boolean): ITreeGridRecord[] {
200

UNCOV
201
        const expressions = groupExpressions ? groupExpressions.concat(sortExpressions) : sortExpressions;
×
202
        let result: ITreeGridRecord[];
UNCOV
203
        if (!expressions.length) {
×
UNCOV
204
            result = hierarchicalData;
×
205
        } else {
UNCOV
206
            result = DataUtil.treeGridSort(hierarchicalData, expressions, sorting, null, this.grid);
×
207
        }
208

UNCOV
209
        const filteredSortedData = [];
×
UNCOV
210
        this.flattenTreeGridRecords(result, filteredSortedData);
×
UNCOV
211
        this.grid.setFilteredSortedData(filteredSortedData, pinned);
×
212

UNCOV
213
        return result;
×
214
    }
215

216
    private flattenTreeGridRecords(records: ITreeGridRecord[], flatData: any[]) {
UNCOV
217
        if (records && records.length) {
×
UNCOV
218
            for (const record of records) {
×
UNCOV
219
                flatData.push(record.data);
×
UNCOV
220
                this.flattenTreeGridRecords(record.children, flatData);
×
221
            }
222
        }
223
    }
224
}
225

226
/** @hidden */
227
@Pipe({
228
    name: 'treeGridPaging',
229
    standalone: true
230
})
231
export class IgxTreeGridPagingPipe implements PipeTransform {
2✔
232

UNCOV
233
    constructor(@Inject(IGX_GRID_BASE) private grid: GridType) { }
×
234

235
    public transform(collection: ITreeGridRecord[], enabled: boolean, page = 0, perPage = 15, _: number): ITreeGridRecord[] {
×
UNCOV
236
        if (!enabled || this.grid.pagingMode !== GridPagingMode.Local) {
×
UNCOV
237
            return collection;
×
238
        }
239

UNCOV
240
        const len = this.grid._totalRecords >= 0 ? this.grid._totalRecords : collection.length;
×
UNCOV
241
        const totalPages = Math.ceil(len / perPage);
×
242

UNCOV
243
        const state = {
×
244
            index: (totalPages > 0 && page >= totalPages) ? totalPages - 1 : page,
×
245
            recordsPerPage: perPage
246
        };
247

UNCOV
248
        const result: ITreeGridRecord[] = DataUtil.page(cloneArray(collection), state, len);
×
UNCOV
249
        this.grid.pagingState = state;
×
UNCOV
250
        this.grid.page = state.index;
×
251

UNCOV
252
        return result;
×
253
    }
254
}
255
/** @hidden */
256
@Pipe({
257
    name: 'treeGridTransaction',
258
    standalone: true
259
})
260
export class IgxTreeGridTransactionPipe implements PipeTransform {
2✔
261

262

UNCOV
263
    constructor(@Inject(IGX_GRID_BASE) private grid: GridType) { }
×
264

265
    public transform(collection: any[], _: number): any[] {
266

UNCOV
267
        if (this.grid.transactions.enabled) {
×
UNCOV
268
            const aggregatedChanges = this.grid.transactions.getAggregatedChanges(true);
×
UNCOV
269
            if (aggregatedChanges.length > 0) {
×
UNCOV
270
                const primaryKey = this.grid.primaryKey;
×
UNCOV
271
                if (!primaryKey) {
×
272
                    return collection;
×
273
                }
274

UNCOV
275
                const childDataKey = this.grid.childDataKey;
×
276

UNCOV
277
                if (childDataKey) {
×
UNCOV
278
                    const hierarchicalDataClone = cloneHierarchicalArray(collection, childDataKey);
×
UNCOV
279
                    return DataUtil.mergeHierarchicalTransactions(
×
280
                        hierarchicalDataClone,
281
                        aggregatedChanges,
282
                        childDataKey,
283
                        this.grid.primaryKey,
284
                        this.grid.dataCloneStrategy
285
                    );
286
                } else {
UNCOV
287
                    const flatDataClone = cloneArray(collection);
×
UNCOV
288
                    return DataUtil.mergeTransactions(
×
289
                        flatDataClone,
290
                        aggregatedChanges,
291
                        this.grid.primaryKey,
292
                        this.grid.dataCloneStrategy);
293
                }
294
            }
295
        }
UNCOV
296
        return collection;
×
297
    }
298
}
299

300
/**
301
 * This pipe maps the original record to ITreeGridRecord format used in TreeGrid.
302
 */
303
@Pipe({
304
    name: 'treeGridNormalizeRecord',
305
    standalone: true
306
})
307
export class IgxTreeGridNormalizeRecordsPipe implements PipeTransform {
2✔
308

UNCOV
309
    constructor(@Inject(IGX_GRID_BASE) private grid: GridType) { }
×
310

311
    public transform(_: any[], __: number): any[] {
UNCOV
312
        const primaryKey = this.grid.primaryKey;
×
313
        // using flattened data because origin data may be hierarchical.
UNCOV
314
        const flatData = this.grid.flatData;
×
UNCOV
315
        const res = flatData ? flatData.map(rec =>
×
UNCOV
316
        ({
×
317
            rowID: this.grid.primaryKey ? rec[primaryKey] : rec,
×
318
            data: rec,
319
            level: 0,
320
            children: []
321
        })) : [];
UNCOV
322
        return res;
×
323
    }
324
}
325

326
@Pipe({
327
    name: 'treeGridAddRow',
328
    standalone: true
329
})
330
export class IgxTreeGridAddRowPipe implements PipeTransform {
2✔
331

UNCOV
332
    constructor(@Inject(IGX_GRID_BASE) private grid: GridType) { }
×
333

334
    public transform(collection: any, isPinned = false, _pipeTrigger: number) {
×
UNCOV
335
        if (!this.grid.rowEditable || !this.grid.crudService.row || this.grid.crudService.row.getClassName() !== IgxAddRow.name ||
×
336
            !this.grid.gridAPI.crudService.addRowParent || isPinned !== this.grid.gridAPI.crudService.addRowParent.isPinned) {
UNCOV
337
            return collection;
×
338
        }
UNCOV
339
        const copy = collection.slice(0);
×
UNCOV
340
        const rec = (this.grid.crudService.row as IgxAddRow).recordRef;
×
UNCOV
341
        if (this.grid.crudService.addRowParent.isPinned) {
×
UNCOV
342
            const parentRowIndex = copy.findIndex(record => record.rowID === this.grid.crudService.addRowParent.rowID);
×
UNCOV
343
            copy.splice(parentRowIndex + 1, 0, rec);
×
344
        } else {
UNCOV
345
            copy.splice(this.grid.crudService.row.index, 0, rec);
×
346
        }
UNCOV
347
        this.grid.records.set(rec.key, rec);
×
UNCOV
348
        return copy;
×
349
    }
350
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc