ms-data-grid 0.0.59 → 0.0.60
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.
- package/esm2022/lib/data-grid/data-grid.component.mjs +5069 -0
- package/esm2022/lib/data-grid/statuses.mjs +45 -0
- package/esm2022/lib/data-grid.module.mjs +27 -0
- package/esm2022/lib/directives/cell-render-init.directive.mjs +67 -0
- package/esm2022/lib/directives/cellHost.directive.mjs +16 -0
- package/esm2022/lib/pipes/filter.pipe.mjs +28 -0
- package/esm2022/lib/services/common.service.mjs +259 -0
- package/esm2022/lib/services/copy-service.service.mjs +222 -0
- package/esm2022/lib/services/export.service.mjs +149 -0
- package/esm2022/lib/services/split-columns.service.mjs +143 -0
- package/esm2022/ms-data-grid.mjs +5 -0
- package/esm2022/public-api.mjs +6 -0
- package/fesm2022/ms-data-grid.mjs +6006 -0
- package/fesm2022/ms-data-grid.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/lib/data-grid/data-grid.component.d.ts +564 -0
- package/lib/data-grid/statuses.d.ts +3 -0
- package/lib/data-grid.module.d.ts +15 -0
- package/lib/directives/cell-render-init.directive.d.ts +18 -0
- package/lib/directives/cellHost.directive.d.ts +8 -0
- package/lib/pipes/filter.pipe.d.ts +7 -0
- package/lib/services/common.service.d.ts +18 -0
- package/lib/services/copy-service.service.d.ts +14 -0
- package/lib/services/export.service.d.ts +24 -0
- package/lib/services/split-columns.service.d.ts +9 -0
- package/package.json +51 -38
- package/{src/public-api.ts → public-api.d.ts} +2 -6
- package/ng-package.json +0 -18
- package/src/lib/css/bootstrap.css +0 -12043
- package/src/lib/data-grid/animations.ts +0 -267
- package/src/lib/data-grid/data-grid.component.html +0 -5724
- package/src/lib/data-grid/data-grid.component.scss +0 -2126
- package/src/lib/data-grid/data-grid.component.spec.ts +0 -28
- package/src/lib/data-grid/data-grid.component.ts +0 -5780
- package/src/lib/data-grid/statuses.ts +0 -49
- package/src/lib/data-grid.module.ts +0 -21
- package/src/lib/data-grid.service.spec.ts +0 -16
- package/src/lib/data-grid.service.ts +0 -9
- package/src/lib/directives/cell-render-init.directive.spec.ts +0 -11
- package/src/lib/directives/cell-render-init.directive.ts +0 -65
- package/src/lib/directives/cellHost.directive.spec.ts +0 -11
- package/src/lib/directives/cellHost.directive.ts +0 -10
- package/src/lib/directives/draggable-header.directive.spec.ts +0 -11
- package/src/lib/directives/draggable-header.directive.ts +0 -172
- package/src/lib/pipes/filter.pipe.spec.ts +0 -11
- package/src/lib/pipes/filter.pipe.ts +0 -22
- package/src/lib/services/cell-selection.service.spec.ts +0 -16
- package/src/lib/services/cell-selection.service.ts +0 -205
- package/src/lib/services/common.service.spec.ts +0 -16
- package/src/lib/services/common.service.ts +0 -306
- package/src/lib/services/copy-service.service.spec.ts +0 -16
- package/src/lib/services/copy-service.service.ts +0 -252
- package/src/lib/services/drag-drp.service.spec.ts +0 -16
- package/src/lib/services/drag-drp.service.ts +0 -58
- package/src/lib/services/export.service.spec.ts +0 -16
- package/src/lib/services/export.service.ts +0 -189
- package/src/lib/services/split-columns.service.spec.ts +0 -16
- package/src/lib/services/split-columns.service.ts +0 -148
- package/src/lib/services/swap-columns.service.spec.ts +0 -16
- package/src/lib/services/swap-columns.service.ts +0 -162
- package/src/typings.d.ts +0 -4
- package/tsconfig.lib.json +0 -19
- package/tsconfig.lib.prod.json +0 -10
- package/tsconfig.spec.json +0 -14
|
@@ -1,306 +0,0 @@
|
|
|
1
|
-
import { Injectable } from '@angular/core';
|
|
2
|
-
|
|
3
|
-
@Injectable({
|
|
4
|
-
providedIn: 'root'
|
|
5
|
-
})
|
|
6
|
-
export class CommonService {
|
|
7
|
-
|
|
8
|
-
constructor() { }
|
|
9
|
-
gethasVisibleColumns(columns: any[]): boolean {
|
|
10
|
-
const checkVisible = (columns: any[]): boolean => {
|
|
11
|
-
return columns.some((col) => {
|
|
12
|
-
if (col?.is_visible) return true;
|
|
13
|
-
if (col?.children?.length) {
|
|
14
|
-
return checkVisible(col.children);
|
|
15
|
-
}
|
|
16
|
-
return false;
|
|
17
|
-
});
|
|
18
|
-
};
|
|
19
|
-
return checkVisible(columns);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
gethasInVisibleColumns(columns: any[]): boolean {
|
|
23
|
-
const checkVisible = (columns: any[]): boolean => {
|
|
24
|
-
return columns.some((col) => {
|
|
25
|
-
if (!col?.is_visible) return true;
|
|
26
|
-
if (col?.children?.length) {
|
|
27
|
-
return checkVisible(col.children);
|
|
28
|
-
}
|
|
29
|
-
return false;
|
|
30
|
-
});
|
|
31
|
-
};
|
|
32
|
-
return checkVisible(columns);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
getTotalColumnsLength(columns: any[]): number {
|
|
37
|
-
let count = 0;
|
|
38
|
-
|
|
39
|
-
columns.forEach(col => {
|
|
40
|
-
if (col.children && Array.isArray(col.children) && col.children.length) {
|
|
41
|
-
count += col.children.length; // count children instead of parent
|
|
42
|
-
} else {
|
|
43
|
-
count += 1; // count parent directly
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
return count;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
gethasRightPinnedColumns(columns: any[]): boolean {
|
|
51
|
-
const checkPinnedRight = (columns: any[]): boolean => {
|
|
52
|
-
return columns.some((col) => {
|
|
53
|
-
if (col?.pinned === 'right' && col?.is_visible) return true;
|
|
54
|
-
if (col?.children?.length) {
|
|
55
|
-
return checkPinnedRight(col.children);
|
|
56
|
-
}
|
|
57
|
-
return false;
|
|
58
|
-
});
|
|
59
|
-
};
|
|
60
|
-
return checkPinnedRight(columns);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
gethasLeftPinnedColumns(columns: any[]): boolean {
|
|
64
|
-
const checkPinnedRight = (columns: any[]): boolean => {
|
|
65
|
-
return columns.some((col) => {
|
|
66
|
-
if (col?.pinned === 'left' && col?.is_visible) return true;
|
|
67
|
-
if (col?.children?.length) {
|
|
68
|
-
return checkPinnedRight(col.children);
|
|
69
|
-
}
|
|
70
|
-
return false;
|
|
71
|
-
});
|
|
72
|
-
};
|
|
73
|
-
return checkPinnedRight(columns);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
getExpandedRowCount(data: any[]): number {
|
|
78
|
-
let groupCount = 0;
|
|
79
|
-
let rowCount = 0;
|
|
80
|
-
|
|
81
|
-
data.forEach(group => {
|
|
82
|
-
if (group?.isGroup) {
|
|
83
|
-
groupCount++;
|
|
84
|
-
|
|
85
|
-
if (group?.isExpand && Array.isArray(group?.children)) {
|
|
86
|
-
group.children.forEach((child: any) => {
|
|
87
|
-
if (child.isGroup) {
|
|
88
|
-
if (child.isExpand && Array.isArray(child.children)) {
|
|
89
|
-
rowCount += child.children.length;
|
|
90
|
-
}
|
|
91
|
-
} else {
|
|
92
|
-
rowCount++;
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
if (groupCount === 0) {
|
|
100
|
-
return data.length;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return groupCount + rowCount;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
getFiltersFromColumns(columns: any[], filtersConfig:any []): any[] {
|
|
108
|
-
const result: any[] = [];
|
|
109
|
-
|
|
110
|
-
const checkColumn = (col: any) => {
|
|
111
|
-
if (col.query?.condition === 'none') {
|
|
112
|
-
col.query.second_value = null;
|
|
113
|
-
col.query.second_condition = null;
|
|
114
|
-
}
|
|
115
|
-
const hasFirstValue = col.query?.first_value != null && col.query?.first_value !== "" && filtersConfig.some((ele)=> ele.field == col.field);
|
|
116
|
-
const hasIds = Array.isArray(col.query?._ids) && col.query._ids.length > 0 && filtersConfig.some((ele)=> ele.field == col.field);
|
|
117
|
-
if (hasFirstValue || hasIds) {
|
|
118
|
-
result.push({
|
|
119
|
-
search: col.search ?? "",
|
|
120
|
-
field: col.field,
|
|
121
|
-
type: col.type,
|
|
122
|
-
_ids: col.type == 'dropdown'? col.query?._ids: [],
|
|
123
|
-
query: col.type == 'dropdown'? null : (col?.query?.first_value ? col?.query : null)
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (Array.isArray(col.children) && col.children.length > 0) {
|
|
128
|
-
col.children.forEach(checkColumn);
|
|
129
|
-
}
|
|
130
|
-
};
|
|
131
|
-
columns.forEach(checkColumn);
|
|
132
|
-
|
|
133
|
-
return result;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
async applyFiltersToColumns(columns: any[], filters: any[]): Promise<any[]> {
|
|
137
|
-
for (const col of columns) {
|
|
138
|
-
if (!col.query) {
|
|
139
|
-
col.query = {
|
|
140
|
-
first_value: null,
|
|
141
|
-
second_value: null,
|
|
142
|
-
first_condition: col.type !== 'date' ? 'contain' : 'equal',
|
|
143
|
-
second_condition: null,
|
|
144
|
-
condition: 'none',
|
|
145
|
-
_ids: []
|
|
146
|
-
};
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
const filter = filters.find(f => f.field === col.field);
|
|
150
|
-
|
|
151
|
-
if (filter) {
|
|
152
|
-
if (col.type === 'dropdown') {
|
|
153
|
-
const selectedIds = filter._ids ?? [];
|
|
154
|
-
const dropdownValues = col.column_dropdown_value ?? [];
|
|
155
|
-
|
|
156
|
-
// ✅ Map depending on dropdown value structure
|
|
157
|
-
let selectedLabels: string[] = [];
|
|
158
|
-
|
|
159
|
-
if (Array.isArray(dropdownValues) && dropdownValues.length > 0) {
|
|
160
|
-
if (typeof dropdownValues[0] === 'object') {
|
|
161
|
-
// object-based dropdowns: { id, name/label/value/text }
|
|
162
|
-
selectedLabels = dropdownValues
|
|
163
|
-
.filter(opt => selectedIds.includes(opt.id))
|
|
164
|
-
.map(opt => opt.name ?? opt.label ?? opt.value ?? opt.text ?? '');
|
|
165
|
-
} else {
|
|
166
|
-
// string-based dropdowns
|
|
167
|
-
selectedLabels = dropdownValues.filter(opt => selectedIds.includes(opt));
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// ✅ Store readable text in filterValue (comma-separated)
|
|
172
|
-
col.filterValue = selectedLabels.join(', ');
|
|
173
|
-
|
|
174
|
-
// maintain query state
|
|
175
|
-
col.query._ids = selectedIds;
|
|
176
|
-
col.search = filter.search ?? '';
|
|
177
|
-
|
|
178
|
-
} else {
|
|
179
|
-
// ✅ Non-dropdown filters (text/date/number)
|
|
180
|
-
col.filterValue = filter.search || filter.query?.first_value || '';
|
|
181
|
-
col.search = filter.search ?? '';
|
|
182
|
-
col.query.first_value = filter.query?.first_value ?? null;
|
|
183
|
-
col.query.second_value = filter.query?.second_value ?? null;
|
|
184
|
-
col.query.first_condition =
|
|
185
|
-
filter.query?.first_condition ??
|
|
186
|
-
(col.type !== 'date' ? 'contain' : 'equal');
|
|
187
|
-
col.query.second_condition = filter.query?.second_condition ?? null;
|
|
188
|
-
col.query.condition = filter.query?.condition ?? 'none';
|
|
189
|
-
}
|
|
190
|
-
} else {
|
|
191
|
-
// Clear filter if not present
|
|
192
|
-
col.filterValue = null;
|
|
193
|
-
col.search = '';
|
|
194
|
-
col.query._ids = [];
|
|
195
|
-
col.query.first_value = null;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
// ✅ Recursively apply for children
|
|
199
|
-
if (Array.isArray(col.children) && col.children.length > 0) {
|
|
200
|
-
col.children = await this.applyFiltersToColumns(col.children, filters);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
return columns;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
activeFilteredColumns: any[] = [];
|
|
213
|
-
updateActiveFilteredColumns(columns: any[]): any[] {
|
|
214
|
-
const collectFiltered = (cols: any[]): any[] => {
|
|
215
|
-
let result: any[] = [];
|
|
216
|
-
|
|
217
|
-
for (let i = 0; i < cols.length; i++) {
|
|
218
|
-
const col = cols[i];
|
|
219
|
-
if (col.children && col.children.length > 0) {
|
|
220
|
-
result = result.concat(collectFiltered(col.children));
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
if (col.query) {
|
|
224
|
-
const hasDropdownFilter =
|
|
225
|
-
Array.isArray(col.query._ids) && col.query._ids.length > 0;
|
|
226
|
-
|
|
227
|
-
const hasValueFilter =
|
|
228
|
-
(col.query.first_value && col.query.first_value !== '') ||
|
|
229
|
-
(col.query.second_value && col.query.second_value !== '');
|
|
230
|
-
|
|
231
|
-
if (hasDropdownFilter || hasValueFilter) {
|
|
232
|
-
result.push(col);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
return result;
|
|
237
|
-
};
|
|
238
|
-
this.activeFilteredColumns = [...collectFiltered(columns)];
|
|
239
|
-
return this.activeFilteredColumns;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
hasFieldChanged(current: any, original: any, type: string): boolean {
|
|
245
|
-
switch (type) {
|
|
246
|
-
case 'number':
|
|
247
|
-
return Number(current) !== Number(original);
|
|
248
|
-
|
|
249
|
-
case 'string':
|
|
250
|
-
return String(current || '') !== String(original || '');
|
|
251
|
-
|
|
252
|
-
case 'dropdown':
|
|
253
|
-
if (typeof current === 'object' && typeof original === 'object') {
|
|
254
|
-
return current?.id !== original?.id || current?.value !== original?.value;
|
|
255
|
-
}
|
|
256
|
-
return current !== original;
|
|
257
|
-
|
|
258
|
-
case 'boolean':
|
|
259
|
-
return Boolean(current) !== Boolean(original);
|
|
260
|
-
|
|
261
|
-
case 'date':
|
|
262
|
-
const currentDate = new Date(current).getTime();
|
|
263
|
-
const originalDate = new Date(original).getTime();
|
|
264
|
-
return isNaN(currentDate) || isNaN(originalDate)
|
|
265
|
-
? current !== original
|
|
266
|
-
: currentDate !== originalDate;
|
|
267
|
-
|
|
268
|
-
default:
|
|
269
|
-
return JSON.stringify(current) !== JSON.stringify(original);
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
// Copy column data to column dropdown values in case of absence
|
|
275
|
-
async copyDropdownDataRecursively(columns: any[]): Promise<any[]> {
|
|
276
|
-
for (const col of columns) {
|
|
277
|
-
if (col.type === 'dropdown') {
|
|
278
|
-
const dropdownValues = col.column_dropdown_value;
|
|
279
|
-
const dataValues = col.column_data;
|
|
280
|
-
|
|
281
|
-
if (
|
|
282
|
-
(!Array.isArray(dropdownValues) || dropdownValues.length === 0) &&
|
|
283
|
-
Array.isArray(dataValues) &&
|
|
284
|
-
dataValues.length > 0
|
|
285
|
-
) {
|
|
286
|
-
col.column_dropdown_value = dataValues.map(item =>
|
|
287
|
-
typeof item === 'object'
|
|
288
|
-
? item
|
|
289
|
-
: { id: item, name: item, value: item }
|
|
290
|
-
);
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
if (Array.isArray(col.children) && col.children.length > 0) {
|
|
295
|
-
col.children = await this.copyDropdownDataRecursively(col.children);
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
return columns;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/* tslint:disable:no-unused-variable */
|
|
2
|
-
|
|
3
|
-
import { TestBed, async, inject } from '@angular/core/testing';
|
|
4
|
-
import { CopyServiceService } from './copy-service.service';
|
|
5
|
-
|
|
6
|
-
describe('Service: CopyService', () => {
|
|
7
|
-
beforeEach(() => {
|
|
8
|
-
TestBed.configureTestingModule({
|
|
9
|
-
providers: [CopyServiceService]
|
|
10
|
-
});
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it('should ...', inject([CopyServiceService], (service: CopyServiceService) => {
|
|
14
|
-
expect(service).toBeTruthy();
|
|
15
|
-
}));
|
|
16
|
-
});
|
|
@@ -1,252 +0,0 @@
|
|
|
1
|
-
import { Injectable } from '@angular/core';
|
|
2
|
-
|
|
3
|
-
@Injectable({
|
|
4
|
-
providedIn: 'root'
|
|
5
|
-
})
|
|
6
|
-
export class CopyServiceService {
|
|
7
|
-
|
|
8
|
-
constructor() { }
|
|
9
|
-
getSelectedDataForCopy(
|
|
10
|
-
dataSet: any[],
|
|
11
|
-
columns: any[],
|
|
12
|
-
rowSelectedIndexes: Set<number>,
|
|
13
|
-
selectedCells: any[],
|
|
14
|
-
getNestedValue: (obj: any, path: string) => any
|
|
15
|
-
): any[][] {
|
|
16
|
-
columns = columns.filter(col => col.is_visible);
|
|
17
|
-
const copiedRows: any[][] = [];
|
|
18
|
-
const findRowByVirtualIndex = (vIndex: number) =>
|
|
19
|
-
dataSet.find((r: any) => r.__virtualIndex === vIndex);
|
|
20
|
-
if (rowSelectedIndexes && rowSelectedIndexes.size > 0) {
|
|
21
|
-
const sortedIndexes = [...rowSelectedIndexes].sort((a, b) => a - b);
|
|
22
|
-
for (const vIndex of sortedIndexes) {
|
|
23
|
-
const row = findRowByVirtualIndex(vIndex);
|
|
24
|
-
if (!row) continue;
|
|
25
|
-
const extractValue = (field: string): string => {
|
|
26
|
-
const nested = getNestedValue(row, field);
|
|
27
|
-
const value =
|
|
28
|
-
nested?.value ??
|
|
29
|
-
nested?.name ??
|
|
30
|
-
nested ??
|
|
31
|
-
'-';
|
|
32
|
-
|
|
33
|
-
if (Array.isArray(value)) {
|
|
34
|
-
return value
|
|
35
|
-
.map(v =>
|
|
36
|
-
typeof v === 'object'
|
|
37
|
-
? (v.departmentName ?? v.roleName ?? '')
|
|
38
|
-
: (v?.toString() ?? '')
|
|
39
|
-
)
|
|
40
|
-
.join(', ');
|
|
41
|
-
}
|
|
42
|
-
return value ?? '';
|
|
43
|
-
};
|
|
44
|
-
const mapped = columns.map(col => {
|
|
45
|
-
if (col.children && Array.isArray(col.children)) {
|
|
46
|
-
return col.children.map((c: { field: string }) => extractValue(c.field));
|
|
47
|
-
}
|
|
48
|
-
return [extractValue(col.field)];
|
|
49
|
-
});
|
|
50
|
-
const rowValues = mapped.reduce<string[]>((acc, curr) => acc.concat(curr), []);
|
|
51
|
-
copiedRows.push(rowValues);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
if (selectedCells && selectedCells.length > 0) {
|
|
55
|
-
const rowsMap = new Map<number, any[]>();
|
|
56
|
-
for (const cell of selectedCells) {
|
|
57
|
-
const row = findRowByVirtualIndex(cell.rowIndex);
|
|
58
|
-
if (!row) continue;
|
|
59
|
-
const col = columns[cell.colIndex];
|
|
60
|
-
let fieldName = col?.field;
|
|
61
|
-
if (col?.children && col.children[cell.subColIndex]) {
|
|
62
|
-
fieldName = col.children[cell.subColIndex].field;
|
|
63
|
-
}
|
|
64
|
-
let value = getNestedValue(row, fieldName) || getNestedValue(row, fieldName)?.name || getNestedValue(row, fieldName) || '-';
|
|
65
|
-
if (Array.isArray(value)) {
|
|
66
|
-
value = value
|
|
67
|
-
.map(v =>
|
|
68
|
-
typeof v === 'object'
|
|
69
|
-
? v.departmentName ?? v.roleName ?? v.full_name ?? ''
|
|
70
|
-
: v?.toString() ?? ''
|
|
71
|
-
)
|
|
72
|
-
.join(', ');
|
|
73
|
-
} else {
|
|
74
|
-
value = value ?? '';
|
|
75
|
-
}
|
|
76
|
-
if (!rowsMap.has(cell.rowIndex)) rowsMap.set(cell.rowIndex, []);
|
|
77
|
-
rowsMap.get(cell.rowIndex)!.push(value);
|
|
78
|
-
}
|
|
79
|
-
const sortedCells = [...rowsMap.entries()]
|
|
80
|
-
.sort(([a], [b]) => a - b)
|
|
81
|
-
.map(([_, v]) => v);
|
|
82
|
-
copiedRows.push(...sortedCells);
|
|
83
|
-
}
|
|
84
|
-
if (copiedRows.length === 0) {
|
|
85
|
-
const activeCell = document.querySelector('.active-cell');
|
|
86
|
-
if (activeCell) return [[activeCell.textContent?.trim() || '']];
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const maxCols = copiedRows.reduce((max, row) => Math.max(max, row.length), 0);
|
|
90
|
-
return copiedRows.map(row => {
|
|
91
|
-
const newRow = [...row];
|
|
92
|
-
while (newRow.length < maxCols) newRow.push('');
|
|
93
|
-
return newRow;
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
copyToClipboard(
|
|
99
|
-
selectedData: any[][],
|
|
100
|
-
selector = '.selected-cell, .active-cell, .row-selected'
|
|
101
|
-
): void {
|
|
102
|
-
if (!selectedData || selectedData.length === 0) return;
|
|
103
|
-
const textToCopy = selectedData
|
|
104
|
-
.map(row => row.map(cell => (cell ?? '').toString()).join('\t'))
|
|
105
|
-
.join('\n');
|
|
106
|
-
navigator.clipboard.writeText(textToCopy).catch(err => console.error(err));
|
|
107
|
-
const selectedEls = document.querySelectorAll(selector);
|
|
108
|
-
selectedEls.forEach(el => el.classList.add('flash-bg'));
|
|
109
|
-
setTimeout(() => {
|
|
110
|
-
selectedEls.forEach(el => el.classList.remove('flash-bg'));
|
|
111
|
-
}, 1000);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
updateRows: any[] = [];
|
|
116
|
-
currentColums : any = []
|
|
117
|
-
async pasteFromClipboardText(
|
|
118
|
-
text: string,
|
|
119
|
-
dataSet: any[],
|
|
120
|
-
columns: any[],
|
|
121
|
-
startRowIndex: number,
|
|
122
|
-
startColIndex: number,
|
|
123
|
-
startSubColIndex: number = 0
|
|
124
|
-
): Promise<any> {
|
|
125
|
-
if (!text) return [];
|
|
126
|
-
this.updateRows = [];
|
|
127
|
-
const rows = text.split(/\r?\n/).map(r => r.split('\t'));
|
|
128
|
-
const flattenedColumns: any[] = [];
|
|
129
|
-
columns.forEach(col => {
|
|
130
|
-
if (col.children?.length) {
|
|
131
|
-
col.children.forEach((child: any) => flattenedColumns.push({ parent: col, ...child }));
|
|
132
|
-
} else {
|
|
133
|
-
flattenedColumns.push(col);
|
|
134
|
-
}
|
|
135
|
-
});
|
|
136
|
-
let startFlattenedIndex = 0;
|
|
137
|
-
for (let i = 0; i < startColIndex; i++) {
|
|
138
|
-
const col = columns[i];
|
|
139
|
-
startFlattenedIndex += col.children?.length || 1;
|
|
140
|
-
}
|
|
141
|
-
const startCol = columns[startColIndex];
|
|
142
|
-
if (startCol?.children?.length) {
|
|
143
|
-
startFlattenedIndex += Math.min(startSubColIndex, startCol.children.length - 1);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
rows.forEach((rowValues, rOffset) => {
|
|
147
|
-
const targetRowIndex = startRowIndex + rOffset;
|
|
148
|
-
const row = dataSet.find(r => r?.__virtualIndex === targetRowIndex);
|
|
149
|
-
if (!row) return;
|
|
150
|
-
|
|
151
|
-
rowValues.forEach((value, cOffset) => {
|
|
152
|
-
const targetIndex = startFlattenedIndex + cOffset;
|
|
153
|
-
if (targetIndex < 0 || targetIndex >= flattenedColumns.length) return;
|
|
154
|
-
|
|
155
|
-
const targetColumn = flattenedColumns[targetIndex];
|
|
156
|
-
if(!targetColumn || !targetColumn.is_editable) return;
|
|
157
|
-
if (targetColumn?.type === 'string') {
|
|
158
|
-
this.currentColums.push(targetColumn);
|
|
159
|
-
this.setNestedValue(row, targetColumn, value);
|
|
160
|
-
} else if (targetColumn.type === 'number') {
|
|
161
|
-
const num = Number(value);
|
|
162
|
-
if (!isNaN(num) && value !== '') {
|
|
163
|
-
this.currentColums.push(targetColumn);
|
|
164
|
-
this.setNestedValue(row, targetColumn, num);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
return {updateRows : this.updateRows, currentColums : this.currentColums};
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
setNestedValue(obj: any, column: any, option: any, calledFromInput = false): void {
|
|
175
|
-
if (column.type === 'date' || column.type === 'image') return;
|
|
176
|
-
const path = column.field;
|
|
177
|
-
if (!path) return;
|
|
178
|
-
const keys = path.split('.');
|
|
179
|
-
const lastKey = keys.pop();
|
|
180
|
-
const parent = keys.reduce((acc: any, key: string) => (acc[key] ??= {}), obj);
|
|
181
|
-
if (parent && lastKey) {
|
|
182
|
-
if (typeof option === 'object' && option !== null) {
|
|
183
|
-
parent[lastKey] = {
|
|
184
|
-
id: option.id ?? 1,
|
|
185
|
-
value: option.value ?? option,
|
|
186
|
-
};
|
|
187
|
-
} else {
|
|
188
|
-
parent[lastKey] = option;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
const sendObj = {
|
|
192
|
-
data: { ...obj },
|
|
193
|
-
eventType: 'onCellEdit',
|
|
194
|
-
};
|
|
195
|
-
this.updateRows.push(obj);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
cutSelectedSelectedData(
|
|
200
|
-
dataSet: any[],
|
|
201
|
-
rowSelectedIndexes: Set<number>,
|
|
202
|
-
selectedCells: any[],
|
|
203
|
-
columns: any[],
|
|
204
|
-
setNestedValue: (obj: any, column: any, value: any) => void
|
|
205
|
-
): any {
|
|
206
|
-
let updatedData = [...dataSet];
|
|
207
|
-
if (rowSelectedIndexes?.size) {
|
|
208
|
-
const indexes = [...rowSelectedIndexes];
|
|
209
|
-
updatedData = updatedData.filter(
|
|
210
|
-
(row: any) => !indexes.includes(row.__virtualIndex)
|
|
211
|
-
);
|
|
212
|
-
// rowSelectedIndexes.clear();
|
|
213
|
-
}
|
|
214
|
-
else if (selectedCells?.length) {
|
|
215
|
-
this.updateRows = [];
|
|
216
|
-
for (const cell of selectedCells) {
|
|
217
|
-
const row = updatedData.find(r => r.__virtualIndex === cell.rowIndex);
|
|
218
|
-
if (!row) continue;
|
|
219
|
-
let col = columns[cell.colIndex];
|
|
220
|
-
if (col?.children && col.children[cell.subColIndex]) {
|
|
221
|
-
col = col.children[cell.subColIndex];
|
|
222
|
-
}
|
|
223
|
-
this.setNestedValue(row, col, '');
|
|
224
|
-
}
|
|
225
|
-
// selectedCells.length = 0;
|
|
226
|
-
}
|
|
227
|
-
return {updatedData: updatedData, updatedRows: this.updateRows};
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
cutWithAnimation(
|
|
232
|
-
selectedData: any[][],
|
|
233
|
-
selector = '.selected-cell, .active-cell, .row-selected'
|
|
234
|
-
): void {
|
|
235
|
-
if (!selectedData || selectedData.length === 0) return;
|
|
236
|
-
|
|
237
|
-
const textToCopy = selectedData
|
|
238
|
-
.map(row => row.map(cell => (cell ?? '').toString()).join('\t'))
|
|
239
|
-
.join('\n');
|
|
240
|
-
|
|
241
|
-
navigator.clipboard.writeText(textToCopy).catch(err => console.error(err));
|
|
242
|
-
|
|
243
|
-
// Apply red cut animation
|
|
244
|
-
const selectedEls = document.querySelectorAll(selector);
|
|
245
|
-
selectedEls.forEach(el => el.classList.add('cut-flash-bg'));
|
|
246
|
-
setTimeout(() => {
|
|
247
|
-
selectedEls.forEach(el => el.classList.remove('cut-flash-bg'));
|
|
248
|
-
}, 1000);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/* tslint:disable:no-unused-variable */
|
|
2
|
-
|
|
3
|
-
import { TestBed, async, inject } from '@angular/core/testing';
|
|
4
|
-
import { DragDrpService } from './drag-drp.service';
|
|
5
|
-
|
|
6
|
-
describe('Service: DragDrp', () => {
|
|
7
|
-
beforeEach(() => {
|
|
8
|
-
TestBed.configureTestingModule({
|
|
9
|
-
providers: [DragDrpService]
|
|
10
|
-
});
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it('should ...', inject([DragDrpService], (service: DragDrpService) => {
|
|
14
|
-
expect(service).toBeTruthy();
|
|
15
|
-
}));
|
|
16
|
-
});
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { Injectable } from '@angular/core';
|
|
2
|
-
import { moveItemInArray } from '@angular/cdk/drag-drop';
|
|
3
|
-
|
|
4
|
-
@Injectable({
|
|
5
|
-
providedIn: 'root',
|
|
6
|
-
})
|
|
7
|
-
export class DragDrpService {
|
|
8
|
-
constructor() {}
|
|
9
|
-
|
|
10
|
-
// sortChildColumnInGroup(
|
|
11
|
-
// columns: any[],
|
|
12
|
-
// draggedChild: any,
|
|
13
|
-
// section: 'leftPinnedColumns' | 'centerColumns' | 'rightPinnedColumns',
|
|
14
|
-
// previousIndex: number,
|
|
15
|
-
// currentIndex: number
|
|
16
|
-
// ): any {
|
|
17
|
-
// const pinned =
|
|
18
|
-
// section === 'leftPinnedColumns'
|
|
19
|
-
// ? 'left'
|
|
20
|
-
// : section === 'rightPinnedColumns'
|
|
21
|
-
// ? 'right'
|
|
22
|
-
// : null;
|
|
23
|
-
|
|
24
|
-
// const group = columns.find(
|
|
25
|
-
// (col: any) =>
|
|
26
|
-
// Array.isArray(col.children) &&
|
|
27
|
-
// col.children.some((child: any) => child?.field === draggedChild?.field)
|
|
28
|
-
// );
|
|
29
|
-
|
|
30
|
-
// if (!group) return;
|
|
31
|
-
|
|
32
|
-
// const groupIndex = columns.findIndex((col) => col.header === group.header);
|
|
33
|
-
// const filteredGroup = group.children.filter(
|
|
34
|
-
// (col: any) => col.pinned === pinned
|
|
35
|
-
// );
|
|
36
|
-
|
|
37
|
-
// const prevField = filteredGroup[previousIndex]?.field;
|
|
38
|
-
// const currField = filteredGroup[currentIndex]?.field;
|
|
39
|
-
|
|
40
|
-
// const visiblePrevIndex = group.children.findIndex(
|
|
41
|
-
// (col: any) => col.field === prevField
|
|
42
|
-
// );
|
|
43
|
-
// const visibleCurrIndex = group.children.findIndex(
|
|
44
|
-
// (col: any) => col.field === currField
|
|
45
|
-
// );
|
|
46
|
-
|
|
47
|
-
// moveItemInArray(
|
|
48
|
-
// columns[groupIndex]?.children,
|
|
49
|
-
// visiblePrevIndex,
|
|
50
|
-
// visibleCurrIndex
|
|
51
|
-
// );
|
|
52
|
-
|
|
53
|
-
// return {
|
|
54
|
-
// group,
|
|
55
|
-
// movedField: currField,
|
|
56
|
-
// };
|
|
57
|
-
// }
|
|
58
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/* tslint:disable:no-unused-variable */
|
|
2
|
-
|
|
3
|
-
import { TestBed, async, inject } from '@angular/core/testing';
|
|
4
|
-
import { ExportService } from './export.service';
|
|
5
|
-
|
|
6
|
-
describe('Service: Export', () => {
|
|
7
|
-
beforeEach(() => {
|
|
8
|
-
TestBed.configureTestingModule({
|
|
9
|
-
providers: [ExportService]
|
|
10
|
-
});
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it('should ...', inject([ExportService], (service: ExportService) => {
|
|
14
|
-
expect(service).toBeTruthy();
|
|
15
|
-
}));
|
|
16
|
-
});
|