• 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.81
/projects/igniteui-angular/src/lib/data-operations/data-util.ts
1
import { IGroupByResult } from './grouping-result.interface';
2

3
import { IPagingState, PagingError } from './paging-state.interface';
4

5
import { IGroupByKey } from './groupby-expand-state.interface';
6
import { IGroupByRecord } from './groupby-record.interface';
7
import { IGroupingState } from './groupby-state.interface';
8
import { mergeObjects, mkenum } from '../core/utils';
9
import { Transaction, TransactionType, HierarchicalTransaction } from '../services/transaction/transaction';
10
import { getHierarchy, isHierarchyMatch } from './operations';
11
import { GridType } from '../grids/common/grid.interface';
12
import { ITreeGridRecord } from '../grids/tree-grid/tree-grid.interfaces';
13
import { ISortingExpression } from './sorting-strategy';
14
import {
15
    IGridSortingStrategy,
16
    IGridGroupingStrategy,
17
    IgxDataRecordSorting,
18
    IgxSorting,
19
    IgxGrouping
20
} from '../grids/common/strategy';
21
import { DefaultDataCloneStrategy, IDataCloneStrategy } from '../data-operations/data-clone-strategy';
22
import { IGroupingExpression } from './grouping-expression.interface';
23

24
/**
25
 * @hidden
26
 */
27
 export const DataType = /*@__PURE__*/mkenum({
2✔
28
    String: 'string',
29
    Number: 'number',
30
    Boolean: 'boolean',
31
    Date: 'date',
32
    DateTime: 'dateTime',
33
    Time: 'time',
34
    Currency: 'currency',
35
    Percent: 'percent',
36
    Image: 'image'
37
});
38
export type DataType = (typeof DataType)[keyof typeof DataType];
39

40
/**
41
 * @hidden
42
 */
43
export const GridColumnDataType = DataType;
2✔
44
export type GridColumnDataType = (typeof GridColumnDataType)[keyof typeof GridColumnDataType];
45

46
/**
47
 * @hidden
48
 */
49
export class DataUtil {
50
    public static sort<T>(data: T[], expressions: ISortingExpression[], sorting: IGridSortingStrategy = new IgxSorting(),
×
51
        grid?: GridType): T[] {
UNCOV
52
        return sorting.sort(data, expressions, grid);
×
53
    }
54

55
    public static treeGridSort(hierarchicalData: ITreeGridRecord[],
56
        expressions: ISortingExpression[],
57
        sorting: IGridSortingStrategy = new IgxDataRecordSorting(),
×
58
        parent?: ITreeGridRecord,
59
        grid?: GridType): ITreeGridRecord[] {
UNCOV
60
        let res: ITreeGridRecord[] = [];
×
UNCOV
61
        hierarchicalData.forEach((hr: ITreeGridRecord) => {
×
UNCOV
62
            const rec: ITreeGridRecord = DataUtil.cloneTreeGridRecord(hr);
×
UNCOV
63
            rec.parent = parent;
×
UNCOV
64
            if (rec.children) {
×
UNCOV
65
                rec.children = DataUtil.treeGridSort(rec.children, expressions, sorting, rec, grid);
×
66
            }
UNCOV
67
            res.push(rec);
×
68
        });
69

UNCOV
70
        res = DataUtil.sort(res, expressions, sorting, grid);
×
71

UNCOV
72
        return res;
×
73
    }
74

75
    public static cloneTreeGridRecord(hierarchicalRecord: ITreeGridRecord) {
UNCOV
76
        const rec: ITreeGridRecord = {
×
77
            key: hierarchicalRecord.key,
78
            data: hierarchicalRecord.data,
79
            children: hierarchicalRecord.children,
80
            isFilteredOutParent: hierarchicalRecord.isFilteredOutParent,
81
            level: hierarchicalRecord.level,
82
            expanded: hierarchicalRecord.expanded
83
        };
UNCOV
84
        return rec;
×
85
    }
86

87
    public static group<T>(data: T[], state: IGroupingState, grouping: IGridGroupingStrategy = new IgxGrouping(), grid: GridType = null,
×
88
        groupsRecords: any[] = [], fullResult: IGroupByResult = { data: [], metadata: [] }): IGroupByResult {
×
UNCOV
89
        groupsRecords.splice(0, groupsRecords.length);
×
UNCOV
90
        return grouping.groupBy(data, state, grid, groupsRecords, fullResult);
×
91
    }
92

93
    public static page<T>(data: T[], state: IPagingState, dataLength?: number): T[] {
UNCOV
94
        if (!state) {
×
UNCOV
95
            return data;
×
96
        }
UNCOV
97
        const len = dataLength !== undefined ? dataLength : data.length;
×
UNCOV
98
        const index = state.index;
×
UNCOV
99
        const res = [];
×
UNCOV
100
        const recordsPerPage = dataLength !== undefined && state.recordsPerPage > dataLength ? dataLength : state.recordsPerPage;
×
UNCOV
101
        state.metadata = {
×
102
            countPages: 0,
103
            countRecords: len,
104
            error: PagingError.None
105
        };
UNCOV
106
        if (index < 0 || isNaN(index)) {
×
UNCOV
107
            state.metadata.error = PagingError.IncorrectPageIndex;
×
UNCOV
108
            return res;
×
109
        }
UNCOV
110
        if (recordsPerPage <= 0 || isNaN(recordsPerPage)) {
×
UNCOV
111
            state.metadata.error = PagingError.IncorrectRecordsPerPage;
×
UNCOV
112
            return res;
×
113
        }
UNCOV
114
        state.metadata.countPages = Math.ceil(len / recordsPerPage);
×
UNCOV
115
        if (!len) {
×
116
            return data;
×
117
        }
UNCOV
118
        if (index >= state.metadata.countPages) {
×
UNCOV
119
            state.metadata.error = PagingError.IncorrectPageIndex;
×
UNCOV
120
            return res;
×
121
        }
UNCOV
122
        return data.slice(index * recordsPerPage, (index + 1) * recordsPerPage);
×
123
    }
124

125
    public static correctPagingState(state: IPagingState, length: number) {
UNCOV
126
        const maxPage = Math.ceil(length / state.recordsPerPage) - 1;
×
UNCOV
127
        if (!isNaN(maxPage) && state.index > maxPage) {
×
UNCOV
128
            state.index = maxPage;
×
129
        }
130
    }
131

132
    public static getHierarchy(gRow: IGroupByRecord): Array<IGroupByKey> {
UNCOV
133
        return getHierarchy(gRow);
×
134
    }
135

136
    public static isHierarchyMatch(h1: Array<IGroupByKey>, h2: Array<IGroupByKey>, expressions: IGroupingExpression[]): boolean {
UNCOV
137
        return isHierarchyMatch(h1, h2, expressions);
×
138
    }
139

140
    /**
141
     * Merges all changes from provided transactions into provided data collection
142
     *
143
     * @param data Collection to merge
144
     * @param transactions Transactions to merge into data
145
     * @param primaryKey Primary key of the collection, if any
146
     * @param deleteRows Should delete rows with DELETE transaction type from data
147
     * @returns Provided data collections updated with all provided transactions
148
     */
149
    public static mergeTransactions<T>(data: T[], transactions: Transaction[], primaryKey?: any, cloneStrategy: IDataCloneStrategy = new DefaultDataCloneStrategy(), deleteRows = false): T[] {
×
UNCOV
150
        data.forEach((item: any, index: number) => {
×
UNCOV
151
            const rowId = primaryKey ? item[primaryKey] : item;
×
UNCOV
152
            const transaction = transactions.find(t => t.id === rowId);
×
UNCOV
153
            if (transaction && transaction.type === TransactionType.UPDATE) {
×
UNCOV
154
                data[index] = mergeObjects(cloneStrategy.clone(data[index]), transaction.newValue);
×
155
            }
156
        });
157

UNCOV
158
        if (deleteRows) {
×
UNCOV
159
            transactions
×
UNCOV
160
                .filter(t => t.type === TransactionType.DELETE)
×
161
                .forEach(t => {
UNCOV
162
                    const index = primaryKey ? data.findIndex(d => d[primaryKey] === t.id) : data.findIndex(d => d === t.id);
×
UNCOV
163
                    if (0 <= index && index < data.length) {
×
UNCOV
164
                        data.splice(index, 1);
×
165
                    }
166
                });
167
        }
168

UNCOV
169
        data.push(...transactions
×
UNCOV
170
            .filter(t => t.type === TransactionType.ADD)
×
UNCOV
171
            .map(t => t.newValue));
×
172

UNCOV
173
        return data;
×
174
    }
175

176
    /**
177
     * Merges all changes from provided transactions into provided hierarchical data collection
178
     *
179
     * @param data Collection to merge
180
     * @param transactions Transactions to merge into data
181
     * @param childDataKey Data key of child collections
182
     * @param primaryKey Primary key of the collection, if any
183
     * @param deleteRows Should delete rows with DELETE transaction type from data
184
     * @returns Provided data collections updated with all provided transactions
185
     */
186
    public static mergeHierarchicalTransactions(
187
        data: any[],
188
        transactions: HierarchicalTransaction[],
189
        childDataKey: any,
190
        primaryKey?: any,
191
        cloneStrategy: IDataCloneStrategy = new DefaultDataCloneStrategy(),
×
192
        deleteRows = false): any[] {
×
UNCOV
193
        for (const transaction of transactions) {
×
UNCOV
194
            if (transaction.path) {
×
UNCOV
195
                const parent = this.findParentFromPath(data, primaryKey, childDataKey, transaction.path);
×
UNCOV
196
                let collection: any[] = parent ? parent[childDataKey] : data;
×
UNCOV
197
                switch (transaction.type) {
×
198
                    case TransactionType.ADD:
199
                        //  if there is no parent this is ADD row at root level
UNCOV
200
                        if (parent && !parent[childDataKey]) {
×
UNCOV
201
                            parent[childDataKey] = collection = [];
×
202
                        }
UNCOV
203
                        collection.push(transaction.newValue);
×
UNCOV
204
                        break;
×
205
                    case TransactionType.UPDATE:
UNCOV
206
                        const updateIndex = collection.findIndex(x => x[primaryKey] === transaction.id);
×
UNCOV
207
                        if (updateIndex !== -1) {
×
UNCOV
208
                            collection[updateIndex] = mergeObjects(cloneStrategy.clone(collection[updateIndex]), transaction.newValue);
×
209
                        }
UNCOV
210
                        break;
×
211
                    case TransactionType.DELETE:
UNCOV
212
                        if (deleteRows) {
×
UNCOV
213
                            const deleteIndex = collection.findIndex(r => r[primaryKey] === transaction.id);
×
UNCOV
214
                            if (deleteIndex !== -1) {
×
UNCOV
215
                                collection.splice(deleteIndex, 1);
×
216
                            }
217
                        }
UNCOV
218
                        break;
×
219
                }
220
            } else {
221
                //  if there is no path this is ADD row in root. Push the newValue to data
UNCOV
222
                data.push(transaction.newValue);
×
223
            }
224
        }
UNCOV
225
        return data;
×
226
    }
227

228
    public static parseValue(dataType: GridColumnDataType, value: any): any {
229
        if (dataType === GridColumnDataType.Number || dataType === GridColumnDataType.Currency || dataType === GridColumnDataType.Percent) {
16✔
230
            value = parseFloat(value);
2✔
231
        }
232

233
        return value;
16✔
234
    }
235

236
    private static findParentFromPath(data: any[], primaryKey: any, childDataKey: any, path: any[]): any {
UNCOV
237
        let collection: any[] = data;
×
238
        let result: any;
239

UNCOV
240
        for (const id of path) {
×
UNCOV
241
            result = collection && collection.find(x => x[primaryKey] === id);
×
UNCOV
242
            if (!result) {
×
243
                break;
×
244
            }
245

UNCOV
246
            collection = result[childDataKey];
×
247
        }
248

UNCOV
249
        return result;
×
250
    }
251
}
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