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.
Files changed (64) hide show
  1. package/esm2022/lib/data-grid/data-grid.component.mjs +5069 -0
  2. package/esm2022/lib/data-grid/statuses.mjs +45 -0
  3. package/esm2022/lib/data-grid.module.mjs +27 -0
  4. package/esm2022/lib/directives/cell-render-init.directive.mjs +67 -0
  5. package/esm2022/lib/directives/cellHost.directive.mjs +16 -0
  6. package/esm2022/lib/pipes/filter.pipe.mjs +28 -0
  7. package/esm2022/lib/services/common.service.mjs +259 -0
  8. package/esm2022/lib/services/copy-service.service.mjs +222 -0
  9. package/esm2022/lib/services/export.service.mjs +149 -0
  10. package/esm2022/lib/services/split-columns.service.mjs +143 -0
  11. package/esm2022/ms-data-grid.mjs +5 -0
  12. package/esm2022/public-api.mjs +6 -0
  13. package/fesm2022/ms-data-grid.mjs +6006 -0
  14. package/fesm2022/ms-data-grid.mjs.map +1 -0
  15. package/index.d.ts +5 -0
  16. package/lib/data-grid/data-grid.component.d.ts +564 -0
  17. package/lib/data-grid/statuses.d.ts +3 -0
  18. package/lib/data-grid.module.d.ts +15 -0
  19. package/lib/directives/cell-render-init.directive.d.ts +18 -0
  20. package/lib/directives/cellHost.directive.d.ts +8 -0
  21. package/lib/pipes/filter.pipe.d.ts +7 -0
  22. package/lib/services/common.service.d.ts +18 -0
  23. package/lib/services/copy-service.service.d.ts +14 -0
  24. package/lib/services/export.service.d.ts +24 -0
  25. package/lib/services/split-columns.service.d.ts +9 -0
  26. package/package.json +51 -38
  27. package/{src/public-api.ts → public-api.d.ts} +2 -6
  28. package/ng-package.json +0 -18
  29. package/src/lib/css/bootstrap.css +0 -12043
  30. package/src/lib/data-grid/animations.ts +0 -267
  31. package/src/lib/data-grid/data-grid.component.html +0 -5724
  32. package/src/lib/data-grid/data-grid.component.scss +0 -2126
  33. package/src/lib/data-grid/data-grid.component.spec.ts +0 -28
  34. package/src/lib/data-grid/data-grid.component.ts +0 -5780
  35. package/src/lib/data-grid/statuses.ts +0 -49
  36. package/src/lib/data-grid.module.ts +0 -21
  37. package/src/lib/data-grid.service.spec.ts +0 -16
  38. package/src/lib/data-grid.service.ts +0 -9
  39. package/src/lib/directives/cell-render-init.directive.spec.ts +0 -11
  40. package/src/lib/directives/cell-render-init.directive.ts +0 -65
  41. package/src/lib/directives/cellHost.directive.spec.ts +0 -11
  42. package/src/lib/directives/cellHost.directive.ts +0 -10
  43. package/src/lib/directives/draggable-header.directive.spec.ts +0 -11
  44. package/src/lib/directives/draggable-header.directive.ts +0 -172
  45. package/src/lib/pipes/filter.pipe.spec.ts +0 -11
  46. package/src/lib/pipes/filter.pipe.ts +0 -22
  47. package/src/lib/services/cell-selection.service.spec.ts +0 -16
  48. package/src/lib/services/cell-selection.service.ts +0 -205
  49. package/src/lib/services/common.service.spec.ts +0 -16
  50. package/src/lib/services/common.service.ts +0 -306
  51. package/src/lib/services/copy-service.service.spec.ts +0 -16
  52. package/src/lib/services/copy-service.service.ts +0 -252
  53. package/src/lib/services/drag-drp.service.spec.ts +0 -16
  54. package/src/lib/services/drag-drp.service.ts +0 -58
  55. package/src/lib/services/export.service.spec.ts +0 -16
  56. package/src/lib/services/export.service.ts +0 -189
  57. package/src/lib/services/split-columns.service.spec.ts +0 -16
  58. package/src/lib/services/split-columns.service.ts +0 -148
  59. package/src/lib/services/swap-columns.service.spec.ts +0 -16
  60. package/src/lib/services/swap-columns.service.ts +0 -162
  61. package/src/typings.d.ts +0 -4
  62. package/tsconfig.lib.json +0 -19
  63. package/tsconfig.lib.prod.json +0 -10
  64. package/tsconfig.spec.json +0 -14
@@ -1,189 +0,0 @@
1
- import { Injectable } from '@angular/core';
2
- import * as XLSX from 'xlsx-js-style';
3
- import { saveAs } from 'file-saver';
4
-
5
- @Injectable({
6
- providedIn: 'root'
7
- })
8
- export class ExportService {
9
-
10
- constructor() {}
11
-
12
- /**
13
- * Exports data to CSV or Excel.
14
- * @param columns List of column definitions (each having name/key/is_visible)
15
- * @param data The array of data objects
16
- * @param fileName Name of the exported file (without extension)
17
- * @param format 'csv' | 'xlsx'
18
- */
19
- exportData(
20
- columns: any[],
21
- data: any[],
22
- fileName: string,
23
- format: 'csv' | 'xlsx' = 'xlsx',
24
- rowSelectedIndexes: Set<number> | null = new Set(),
25
- styleConfig: {
26
- headerBgColor?: string;
27
- headerTextColor?: string;
28
- bodyTextColor?: string;
29
- fontFamily?: string;
30
- fontWeight?: 'normal' | 'bold';
31
- zoomScale?: number;
32
- headerRowHeight?: number;
33
- selectedRowBgColor?: string;
34
- } = {}
35
- ) {
36
- const {
37
- headerBgColor = '#228B22',
38
- headerTextColor = '#FFFFFF',
39
- bodyTextColor = '#000000',
40
- fontFamily = 'Calibri',
41
- fontWeight = 'normal',
42
- zoomScale = 120,
43
- headerRowHeight = 20,
44
- selectedRowBgColor = '#8AC5FF',
45
- } = styleConfig;
46
-
47
- const visibleColumns = columns.filter(
48
- col => col.is_visible && col.type !== 'image' && col.type !== 'logo'
49
- );
50
-
51
- const headers = visibleColumns.map(col => col.header || col.headerName || col.name);
52
-
53
- const flattenValue = (value: any): any => {
54
- if (value == null) return '';
55
- if (Array.isArray(value))
56
- return value.map(v => (typeof v === 'object' ? flattenValue(v) : v)).join(', ');
57
- if (typeof value === 'object')
58
- return Object.entries(value)
59
- .map(([k, v]) => `${k}: ${flattenValue(v)}`)
60
- .join(', ');
61
- return value;
62
- };
63
-
64
- const exportData = data.map(row =>
65
- visibleColumns.reduce((acc: any, col) => {
66
- const header = col.headerName || col.name || col.header;
67
- let value = this.getNestedValue(row, col.field);
68
-
69
- switch (col.type) {
70
- case 'boolean':
71
- value = value ? 'Yes' : 'No';
72
- break;
73
- case 'date':
74
- if (value) {
75
- const date = new Date(value);
76
- if (!isNaN(date.getTime())) {
77
- value = date.toLocaleDateString('en-US', {
78
- day: '2-digit',
79
- month: 'long',
80
- year: 'numeric',
81
- });
82
- }
83
- }
84
- break;
85
- default:
86
- value = flattenValue(value);
87
- }
88
-
89
- acc[header] = value;
90
- return acc;
91
- }, {})
92
- );
93
-
94
- const worksheet: XLSX.WorkSheet = XLSX.utils.json_to_sheet(exportData, { header: headers });
95
-
96
- // ✅ Define a reusable border style
97
- const borderStyle = {
98
- top: { style: 'thin', color: { rgb: 'CCCCCC' } },
99
- bottom: { style: 'thin', color: { rgb: 'CCCCCC' } },
100
- left: { style: 'thin', color: { rgb: 'CCCCCC' } },
101
- right: { style: 'thin', color: { rgb: 'CCCCCC' } },
102
- };
103
-
104
- // ✅ Apply header styles
105
- headers.forEach((header, index) => {
106
- const cellAddress = XLSX.utils.encode_cell({ r: 0, c: index });
107
- if (!worksheet[cellAddress]) return;
108
-
109
- worksheet[cellAddress].s = {
110
- fill: { fgColor: { rgb: headerBgColor.replace('#', '') } },
111
- font: {
112
- name: fontFamily,
113
- sz: 14,
114
- color: { rgb: headerTextColor.replace('#', '') },
115
- bold: fontWeight === 'bold',
116
- },
117
- alignment: { horizontal: 'center', vertical: 'center' },
118
- border: borderStyle, // ✅ Added border here
119
- };
120
- });
121
-
122
- // ✅ Apply body styles + highlight selected rows
123
- for (let r = 1; r <= exportData.length; r++) {
124
- const isSelected = rowSelectedIndexes?.has(r - 1);
125
- const rowBgColor = isSelected ? selectedRowBgColor : '#FFFFFF';
126
-
127
- for (let c = 0; c < headers.length; c++) {
128
- const col = visibleColumns[c];
129
- const cellAddress = XLSX.utils.encode_cell({ r, c });
130
- const cell = worksheet[cellAddress];
131
- if (!cell) continue;
132
-
133
- let horizontalAlign = 'left';
134
- if (['number', 'boolean', 'date'].includes(col.type)) horizontalAlign = 'center';
135
-
136
- cell.s = {
137
- fill: { fgColor: { rgb: rowBgColor.replace('#', '') } },
138
- font: {
139
- name: fontFamily,
140
- sz: 14,
141
- color: { rgb: bodyTextColor.replace('#', '') },
142
- bold: false,
143
- },
144
- alignment: { horizontal: horizontalAlign, vertical: 'center', wrapText: true },
145
- border: borderStyle, // ✅ Added border here too
146
- };
147
- }
148
- }
149
-
150
- // ✅ Adjust column widths
151
- const colWidths = headers.map(header => {
152
- let maxLength = header.length;
153
- exportData.forEach(row => {
154
- const val = row[header];
155
- if (val != null) {
156
- const len = val.toString().length;
157
- if (len > maxLength) maxLength = len;
158
- }
159
- });
160
- return { wch: Math.min(maxLength + 2, 64) };
161
- });
162
- worksheet['!cols'] = colWidths;
163
-
164
- worksheet['!rows'] = [{ hpt: headerRowHeight }];
165
- worksheet['!zoom'] = zoomScale;
166
-
167
- const workbook: XLSX.WorkBook = { Sheets: { Data: worksheet }, SheetNames: ['Data'] };
168
-
169
- if (format === 'csv') {
170
- const csv = XLSX.utils.sheet_to_csv(worksheet);
171
- const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
172
- saveAs(blob, `${fileName}.csv`);
173
- } else {
174
- const excelBuffer: any = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
175
- const blob = new Blob([excelBuffer], {
176
- type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8',
177
- });
178
- saveAs(blob, `${fileName}.xlsx`);
179
- }
180
- }
181
-
182
-
183
-
184
-
185
- private getNestedValue(obj: any, path: string): any {
186
- if (!path || typeof obj !== 'object') return obj;
187
- return path.split('.').reduce((acc, key) => (acc && acc[key] !== undefined ? acc[key] : ''), obj);
188
- }
189
- }
@@ -1,16 +0,0 @@
1
- /* tslint:disable:no-unused-variable */
2
-
3
- import { TestBed, async, inject } from '@angular/core/testing';
4
- import { SplitColumnsService } from './split-columns.service';
5
-
6
- describe('Service: SplitColumns', () => {
7
- beforeEach(() => {
8
- TestBed.configureTestingModule({
9
- providers: [SplitColumnsService]
10
- });
11
- });
12
-
13
- it('should ...', inject([SplitColumnsService], (service: SplitColumnsService) => {
14
- expect(service).toBeTruthy();
15
- }));
16
- });
@@ -1,148 +0,0 @@
1
- import { Injectable } from '@angular/core';
2
-
3
- @Injectable({
4
- providedIn: 'root',
5
- })
6
- export class SplitColumnsService {
7
- prepareColumns(columns: any[], containerWidth: number): any {
8
- const left: any[] = [];
9
- const center: any[] = [];
10
- const right: any[] = [];
11
-
12
- for (const col of columns) {
13
- if (col.children?.length) {
14
- const leftChildren: any[] = [];
15
- const centerChildren: any[] = [];
16
- const rightChildren: any[] = [];
17
-
18
- for (const child of col.children) {
19
- if (child.is_visible === false) continue;
20
-
21
- const pinned = child.pinned ?? col.pinned ?? null;
22
- const childWithPinned = { ...child, pinned };
23
-
24
- if (pinned === 'left') leftChildren.push(childWithPinned);
25
- else if (pinned === 'right') rightChildren.push(childWithPinned);
26
- else centerChildren.push(childWithPinned);
27
- }
28
-
29
- if (leftChildren.length) {
30
- left.push({ header: col.header, children: leftChildren, id: col?.id || col?._id });
31
- }
32
- if (centerChildren.length) {
33
- center.push({
34
- header: col.header,
35
- children: centerChildren,
36
- id: col.id || col._id,
37
- });
38
- }
39
- if (rightChildren.length) {
40
- right.push({
41
- header: col.header,
42
- children: rightChildren,
43
- id: col.id || col._id,
44
- });
45
- }
46
- } else if (col.is_visible !== false) {
47
- const pinned = col.pinned ?? null;
48
- if (pinned === 'left') left.push(col);
49
- else if (pinned === 'right') right.push(col);
50
- else center.push(col);
51
- }
52
- }
53
-
54
- return { left, center, right };
55
- }
56
-
57
- setColumnsQuery(columns: any[]) {
58
- for (const col of columns) {
59
- // if (col.children?.length) {
60
- // for (const child of col.children) {
61
- // if (!child?.query?.firt_value && !child?.query?._ids?.length) {
62
- // child['query'] = {
63
- // first_condition: 'contain',
64
- // first_value: null,
65
- // condition: 'none',
66
- // second_condition: 'contain',
67
- // second_value: null,
68
- // _ids: [],
69
- // };
70
- // }
71
- // }
72
- // }
73
- // if (!col?.query?.firt_value && !col?.query?._ids?.length) {
74
- // col.query = {
75
- // first_condition: 'contain',
76
- // first_value: null,
77
- // condition: 'none',
78
- // second_condition: 'contain',
79
- // second_value: null,
80
- // _ids: [],
81
- // };
82
- // }
83
- }
84
-
85
- console.log('Updated Columns: ', columns);
86
-
87
- return columns;
88
- }
89
-
90
- assignDefaultWidths(columns: any[], containerWidth: number): any[] {
91
- const visibleLeafCols = this.getVisibleLeafColumns(columns);
92
-
93
- if (!visibleLeafCols.length) return columns;
94
-
95
- let defaultWidth = Math.floor(containerWidth / visibleLeafCols.length);
96
- if (defaultWidth < 150) defaultWidth = 150;
97
-
98
- const cloneColumns = (cols: any[]): any[] =>
99
- cols.map((col) => {
100
- if (col.children?.length) {
101
- const newChildren = col.children.map((child: any) => {
102
- // If visible → dynamic default width
103
- // If invisible → fixed 150px
104
- if (!child.width) {
105
- if (child.is_visible === false) {
106
- return { ...child, width: 150 };
107
- } else {
108
- return { ...child, width: defaultWidth };
109
- }
110
- }
111
- return { ...child };
112
- });
113
-
114
- return { ...col, children: newChildren };
115
- }
116
-
117
- if (!col.width) {
118
- if (col.is_visible === false) {
119
- return { ...col, width: 150 };
120
- } else {
121
- return { ...col, width: defaultWidth };
122
- }
123
- }
124
-
125
- return { ...col };
126
- });
127
-
128
- return cloneColumns(columns);
129
- }
130
-
131
-
132
- private getVisibleLeafColumns(columns: any[]): any[] {
133
- const result: any[] = [];
134
-
135
- for (const col of columns) {
136
- if (col.children?.length) {
137
- const visibleChildren = col.children.filter(
138
- (c: any) => c.is_visible !== false
139
- );
140
- result.push(...visibleChildren);
141
- } else if (col.is_visible !== false) {
142
- result.push(col);
143
- }
144
- }
145
-
146
- return result;
147
- }
148
- }
@@ -1,16 +0,0 @@
1
- /* tslint:disable:no-unused-variable */
2
-
3
- import { TestBed, async, inject } from '@angular/core/testing';
4
- import { SwapColumnsService } from './swap-columns.service';
5
-
6
- describe('Service: SwapColumns', () => {
7
- beforeEach(() => {
8
- TestBed.configureTestingModule({
9
- providers: [SwapColumnsService]
10
- });
11
- });
12
-
13
- it('should ...', inject([SwapColumnsService], (service: SwapColumnsService) => {
14
- expect(service).toBeTruthy();
15
- }));
16
- });
@@ -1,162 +0,0 @@
1
- import { Injectable } from '@angular/core';
2
-
3
- @Injectable({
4
- providedIn: 'root',
5
- })
6
- export class SwapColumnsService {
7
- constructor() {}
8
-
9
- deepClone(obj: any) {
10
- return JSON.parse(JSON.stringify(obj));
11
- }
12
-
13
- flattenColumnsWithPaths(columns: any[]): { col: any; path: number[] }[] {
14
- const result: { col: any; path: number[] }[] = [];
15
-
16
- const recurse = (cols: any[], currentPath: number[] = []) => {
17
- cols.forEach((col, index) => {
18
- const path = [...currentPath, index];
19
- result.push({ col, path });
20
-
21
- if (Array.isArray(col.children)) {
22
- recurse(col.children, path);
23
- }
24
- });
25
- };
26
-
27
- recurse(columns);
28
- return result;
29
- }
30
-
31
- findColumnByIndex(
32
- columns: any[],
33
- index: number,
34
- flat: any[],
35
- _path: number[][] = [],
36
- currentPath: number[] = []
37
- ): { column: any; parent: any[]; path: number[] } | null {
38
- for (let i = 0; i < columns.length; i++) {
39
- const col = columns[i];
40
- const nextPath = [...currentPath, i];
41
-
42
- if (flat[index] === col) {
43
- return { column: col, parent: columns, path: nextPath };
44
- }
45
-
46
- if (Array.isArray(col?.children)) {
47
- const result = this.findColumnByIndex(
48
- col?.children,
49
- index,
50
- flat,
51
- _path,
52
- nextPath
53
- );
54
- if (result) return result;
55
- }
56
- }
57
-
58
- return null;
59
- }
60
-
61
- insertAtPath(columns: any[], path: number[], newColumn: any): any[] {
62
- const cloned = this.deepClone(columns);
63
- let current = cloned;
64
-
65
- for (let i = 0; i < path.length - 1; i++) {
66
- if (!current[path[i]]?.children) {
67
- current[path[i]]!.children = [];
68
- }
69
-
70
- current = current[path[i]]?.children;
71
- }
72
-
73
- const insertIndex = path[path.length - 1];
74
- current.splice(insertIndex, 0, newColumn);
75
- return cloned;
76
- }
77
-
78
- removeAtPath(columns: any[], path: number[]): any[] {
79
- const cloned = this.deepClone(columns);
80
- let current = cloned;
81
-
82
- for (let i = 0; i < path.length - 1; i++) {
83
- if (!current[path[i]]?.children) {
84
- return cloned; // Safety: path is invalid
85
- }
86
- current = current[path[i]]?.children;
87
- }
88
-
89
- const removeIndex = path[path.length - 1];
90
- if (Array.isArray(current) && current.length > removeIndex) {
91
- current.splice(removeIndex, 1);
92
- }
93
-
94
- return cloned;
95
- }
96
-
97
- swapColumnsInTree(
98
- currentColumn: any,
99
- columns: any[],
100
- fromIndex: number,
101
- toIndex: number
102
- ): any[] {
103
- const flat = this.flattenColumnsWithPaths(columns);
104
-
105
- if (
106
- fromIndex < 0 ||
107
- toIndex < 0 ||
108
- fromIndex >= flat.length ||
109
- toIndex >= flat.length
110
- ) {
111
- return columns; // invalid indices
112
- }
113
-
114
- const fromInfo = this.findColumnByIndex(columns, fromIndex, flat);
115
- const toInfo = this.findColumnByIndex(columns, toIndex, flat);
116
-
117
- if (!fromInfo || !toInfo) return columns;
118
-
119
- const fromCol = fromInfo.column;
120
- const toCol = toInfo.column;
121
-
122
- let updatedCols = this.removeAtPath(columns, fromInfo.path);
123
-
124
- // Case 1: Same parent
125
- if (
126
- JSON.stringify(fromInfo.path.slice(0, -1)) ===
127
- JSON.stringify(toInfo.path.slice(0, -1))
128
- ) {
129
- return this.insertAtPath(updatedCols, toInfo.path, fromCol);
130
- }
131
-
132
- // Case 2: Drop target is a group header
133
- if (Array.isArray(toCol?.children)) {
134
- const cloned = this.deepClone(updatedCols);
135
- let parent = cloned;
136
-
137
- for (let i = 0; i < toInfo.path.length - 1; i++) {
138
- parent = parent[toInfo.path[i]].children;
139
- }
140
-
141
- const target = parent[toInfo.path[toInfo.path.length - 1]];
142
- if (!target.children) {
143
- target.children = [];
144
- }
145
-
146
- target.children.push(fromCol);
147
- return cloned;
148
- }
149
-
150
- // Case 3: Drop target is a regular column → wrap both into a group
151
- const groupHeader = {
152
- headerName: toCol.headerName || 'Group',
153
- children: [toCol, fromCol],
154
- };
155
-
156
- // Remove target from its original location
157
- updatedCols = this.removeAtPath(updatedCols, toInfo.path);
158
-
159
- // Insert group at target index
160
- return this.insertAtPath(updatedCols, toInfo.path, groupHeader);
161
- }
162
- }
package/src/typings.d.ts DELETED
@@ -1,4 +0,0 @@
1
- declare module 'xlsx-style' {
2
- import * as XLSX from 'xlsx';
3
- export = XLSX;
4
- }
package/tsconfig.lib.json DELETED
@@ -1,19 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.json",
3
- "compilerOptions": {
4
- "outDir": "../../out-tsc/lib",
5
- "declaration": true,
6
- "declarationMap": true,
7
- "inlineSources": true,
8
- "types": [],
9
- "target": "es2019",
10
- "lib": ["es2019", "dom"]
11
- },
12
- "exclude": [
13
- "**/*.spec.ts"
14
- ],
15
- "include": [
16
- "src/**/*.ts",
17
- "src/typings.d.ts"
18
- ]
19
- }
@@ -1,10 +0,0 @@
1
- /* To learn more about this file see: https://angular.io/config/tsconfig. */
2
- {
3
- "extends": "./tsconfig.lib.json",
4
- "compilerOptions": {
5
- "declarationMap": false
6
- },
7
- "angularCompilerOptions": {
8
- "compilationMode": "partial"
9
- }
10
- }
@@ -1,14 +0,0 @@
1
- /* To learn more about this file see: https://angular.io/config/tsconfig. */
2
- {
3
- "extends": "../../tsconfig.json",
4
- "compilerOptions": {
5
- "outDir": "../../out-tsc/spec",
6
- "types": [
7
- "jasmine"
8
- ]
9
- },
10
- "include": [
11
- "**/*.spec.ts",
12
- "**/*.d.ts"
13
- ]
14
- }