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,49 +0,0 @@
|
|
|
1
|
-
export const STATUSES_BADGE_MAP: { [key: string]: string } = {
|
|
2
|
-
// Success – Green
|
|
3
|
-
'active': 'badge badge-success',
|
|
4
|
-
'approved': 'badge badge-success',
|
|
5
|
-
'accepted': 'badge badge-success',
|
|
6
|
-
'completed': 'badge badge-success',
|
|
7
|
-
'evaluated': 'badge badge-success',
|
|
8
|
-
'assigned': 'badge badge-success',
|
|
9
|
-
'scrap': 'badge badge-success',
|
|
10
|
-
'move-available': 'badge badge-success',
|
|
11
|
-
'move-assigned': 'badge badge-success',
|
|
12
|
-
|
|
13
|
-
// Warning – Yellow/Amber
|
|
14
|
-
'contract': 'badge badge-warning',
|
|
15
|
-
'warranty': 'badge badge-warning',
|
|
16
|
-
'scheduled': 'badge badge-warning',
|
|
17
|
-
'leased': 'badge badge-warning',
|
|
18
|
-
'disposed': 'badge badge-warning',
|
|
19
|
-
'maintenance': 'badge badge-warning',
|
|
20
|
-
'assigning start': 'badge badge-warning',
|
|
21
|
-
'evaluation start': 'badge badge-warning',
|
|
22
|
-
'to be start assigning': 'badge badge-warning',
|
|
23
|
-
'pending': 'badge badge-warning',
|
|
24
|
-
'leave': 'badge badge-warning',
|
|
25
|
-
|
|
26
|
-
// Danger – Red
|
|
27
|
-
'inactive': 'badge badge-danger',
|
|
28
|
-
'rejected': 'badge badge-danger',
|
|
29
|
-
'unassigned': 'badge badge-danger',
|
|
30
|
-
'trashed': 'badge badge-danger',
|
|
31
|
-
'onhold': 'badge badge-danger',
|
|
32
|
-
'assigning stop': 'badge badge-danger',
|
|
33
|
-
'evaluation stop': 'badge badge-danger',
|
|
34
|
-
'unavailable': 'badge badge-danger',
|
|
35
|
-
'move-error': 'badge badge-danger',
|
|
36
|
-
'failed': 'badge badge-danger',
|
|
37
|
-
'absent': 'badge badge-danger',
|
|
38
|
-
|
|
39
|
-
// Info – Blue
|
|
40
|
-
'insurance': 'badge badge-info',
|
|
41
|
-
'pastdue': 'badge badge-info',
|
|
42
|
-
|
|
43
|
-
// Dark – Neutral/Other
|
|
44
|
-
'expired': 'badge badge-dark',
|
|
45
|
-
'draft': 'badge badge-dark',
|
|
46
|
-
'present': 'badge badge-success',
|
|
47
|
-
|
|
48
|
-
'todo': 'badge badge-secondary',
|
|
49
|
-
};
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { NgModule } from '@angular/core';
|
|
2
|
-
import { DataGridComponent } from './data-grid/data-grid.component';
|
|
3
|
-
import { CommonModule } from '@angular/common';
|
|
4
|
-
import { FormsModule } from '@angular/forms';
|
|
5
|
-
import { FilterPipe } from './pipes/filter.pipe';
|
|
6
|
-
import { DragDropModule } from '@angular/cdk/drag-drop';
|
|
7
|
-
import { InlineSVGModule } from 'ng-inline-svg';
|
|
8
|
-
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
|
9
|
-
import { ScrollingModule } from '@angular/cdk/scrolling';
|
|
10
|
-
import { CellHostDirective } from './directives/cellHost.directive';
|
|
11
|
-
import { CellRenderInitDirective } from './directives/cell-render-init.directive';
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@NgModule({
|
|
16
|
-
declarations: [DataGridComponent, FilterPipe, CellHostDirective, CellRenderInitDirective ],
|
|
17
|
-
imports: [CommonModule, FormsModule, DragDropModule, InlineSVGModule.forRoot(), ScrollingModule],
|
|
18
|
-
exports: [DataGridComponent],
|
|
19
|
-
providers: [],
|
|
20
|
-
})
|
|
21
|
-
export class DataGridModule {}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { TestBed } from '@angular/core/testing';
|
|
2
|
-
|
|
3
|
-
import { DataGridService } from './data-grid.service';
|
|
4
|
-
|
|
5
|
-
describe('DataGridService', () => {
|
|
6
|
-
let service: DataGridService;
|
|
7
|
-
|
|
8
|
-
beforeEach(() => {
|
|
9
|
-
TestBed.configureTestingModule({});
|
|
10
|
-
service = TestBed.inject(DataGridService);
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it('should be created', () => {
|
|
14
|
-
expect(service).toBeTruthy();
|
|
15
|
-
});
|
|
16
|
-
});
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/* tslint:disable:no-unused-variable */
|
|
2
|
-
|
|
3
|
-
import { TestBed, async } from '@angular/core/testing';
|
|
4
|
-
import { CellRenderInitDirective } from './cell-render-init.directive';
|
|
5
|
-
|
|
6
|
-
describe('Directive: CellRenderInit', () => {
|
|
7
|
-
it('should create an instance', () => {
|
|
8
|
-
const directive = new CellRenderInitDirective();
|
|
9
|
-
expect(directive).toBeTruthy();
|
|
10
|
-
});
|
|
11
|
-
});
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Directive,
|
|
3
|
-
Input,
|
|
4
|
-
OnInit,
|
|
5
|
-
ViewContainerRef,
|
|
6
|
-
Injector,
|
|
7
|
-
ComponentRef,
|
|
8
|
-
Type,
|
|
9
|
-
EventEmitter,
|
|
10
|
-
Output
|
|
11
|
-
} from '@angular/core';
|
|
12
|
-
|
|
13
|
-
@Directive({
|
|
14
|
-
selector: '[cellRenderInit]'
|
|
15
|
-
})
|
|
16
|
-
export class CellRenderInitDirective implements OnInit {
|
|
17
|
-
@Input('cellRenderInit') componentType!: Type<any>;
|
|
18
|
-
@Input() rowData: any;
|
|
19
|
-
@Input() colData: any;
|
|
20
|
-
@Input() cellValue: any;
|
|
21
|
-
|
|
22
|
-
@Output() cellEvent = new EventEmitter<{ eventName: string; data: any }>();
|
|
23
|
-
|
|
24
|
-
constructor(private vcr: ViewContainerRef, private injector: Injector) { }
|
|
25
|
-
|
|
26
|
-
ngOnInit(): void {
|
|
27
|
-
if (!this.componentType) return;
|
|
28
|
-
|
|
29
|
-
// ✅ Dynamically create the component
|
|
30
|
-
const componentRef: ComponentRef<any> = this.vcr.createComponent(this.componentType, {
|
|
31
|
-
injector: Injector.create({
|
|
32
|
-
providers: [
|
|
33
|
-
{ provide: 'rowData', useValue: this.rowData },
|
|
34
|
-
{ provide: 'colData', useValue: this.colData },
|
|
35
|
-
{ provide: 'cellValue', useValue: this.cellValue }
|
|
36
|
-
],
|
|
37
|
-
parent: this.injector
|
|
38
|
-
})
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
// ✅ Automatically call custom lifecycle hook if present
|
|
42
|
-
if (typeof componentRef.instance.gridInit === 'function') {
|
|
43
|
-
componentRef.instance.gridInit({
|
|
44
|
-
row: this.rowData,
|
|
45
|
-
col: this.colData,
|
|
46
|
-
value: this.cellValue
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
for (const key of Object.keys(componentRef.instance)) {
|
|
50
|
-
const property = componentRef.instance[key];
|
|
51
|
-
if (property instanceof EventEmitter) {
|
|
52
|
-
property.subscribe((value: any) => {
|
|
53
|
-
this.cellEvent.emit({
|
|
54
|
-
eventName: key,
|
|
55
|
-
data: {
|
|
56
|
-
row: this.rowData,
|
|
57
|
-
col: this.colData,
|
|
58
|
-
value,
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/* tslint:disable:no-unused-variable */
|
|
2
|
-
|
|
3
|
-
import { TestBed, async } from '@angular/core/testing';
|
|
4
|
-
import { CellHostDirective } from './cellHost.directive';
|
|
5
|
-
|
|
6
|
-
describe('Directive: CellHost', () => {
|
|
7
|
-
it('should create an instance', () => {
|
|
8
|
-
const directive = new CellHostDirective();
|
|
9
|
-
expect(directive).toBeTruthy();
|
|
10
|
-
});
|
|
11
|
-
});
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/* tslint:disable:no-unused-variable */
|
|
2
|
-
|
|
3
|
-
import { TestBed, async } from '@angular/core/testing';
|
|
4
|
-
import { DraggableHeaderDirective } from './draggable-header.directive';
|
|
5
|
-
|
|
6
|
-
describe('Directive: DraggableHeader', () => {
|
|
7
|
-
it('should create an instance', () => {
|
|
8
|
-
const directive = new DraggableHeaderDirective();
|
|
9
|
-
expect(directive).toBeTruthy();
|
|
10
|
-
});
|
|
11
|
-
});
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Directive,
|
|
3
|
-
ElementRef,
|
|
4
|
-
EventEmitter,
|
|
5
|
-
HostListener,
|
|
6
|
-
Input,
|
|
7
|
-
Output,
|
|
8
|
-
Renderer2,
|
|
9
|
-
} from '@angular/core';
|
|
10
|
-
|
|
11
|
-
export interface DragMoveEvent {
|
|
12
|
-
event: MouseEvent;
|
|
13
|
-
data: any;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
@Directive({
|
|
17
|
-
selector: '[appDraggableHeader]',
|
|
18
|
-
})
|
|
19
|
-
export class DraggableHeaderDirective {
|
|
20
|
-
@Input() column: any;
|
|
21
|
-
@Input() headerName: string = '';
|
|
22
|
-
|
|
23
|
-
@Output() dragStart = new EventEmitter<any>();
|
|
24
|
-
@Output() dragMove = new EventEmitter<any>();
|
|
25
|
-
@Output() dragEnd = new EventEmitter<any>();
|
|
26
|
-
|
|
27
|
-
private isDragging = false;
|
|
28
|
-
private placeholderEl: HTMLElement | null = null;
|
|
29
|
-
private previewEl: HTMLElement | null = null;
|
|
30
|
-
|
|
31
|
-
constructor(private el: ElementRef, private renderer: Renderer2) {}
|
|
32
|
-
|
|
33
|
-
startX = 0;
|
|
34
|
-
startY = 0;
|
|
35
|
-
|
|
36
|
-
@HostListener('mousedown', ['$event'])
|
|
37
|
-
onMouseDown(event: MouseEvent) {
|
|
38
|
-
if (event.button !== 0) return;
|
|
39
|
-
let target = event.target as HTMLElement;
|
|
40
|
-
const classes = target.classList;
|
|
41
|
-
debugger
|
|
42
|
-
if ((event.target as HTMLElement).classList.contains('three-dots')) return;
|
|
43
|
-
this.startX = event.clientX;
|
|
44
|
-
this.startY = event.clientY;
|
|
45
|
-
this.isDragging = false;
|
|
46
|
-
|
|
47
|
-
document.addEventListener('mousemove', this.onMouseMove);
|
|
48
|
-
document.addEventListener('mouseup', this.onMouseUp);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
onMouseMove = (event: MouseEvent) => {
|
|
52
|
-
debugger
|
|
53
|
-
const moveX = Math.abs(event.clientX - this.startX - 10);
|
|
54
|
-
const moveY = Math.abs(event.clientY - this.startY - 10);
|
|
55
|
-
if (!this.isDragging && (moveX > 1 || moveY > 1)) {
|
|
56
|
-
this.startDragging(event);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (this.isDragging && this.previewEl) {
|
|
60
|
-
this.renderer.setStyle(this.previewEl, 'top', `${event.pageY + 10}px`);
|
|
61
|
-
this.renderer.setStyle(this.previewEl, 'left', `${event.pageX + 10}px`);
|
|
62
|
-
|
|
63
|
-
// Find the element under cursor (hovered element)
|
|
64
|
-
const hoveredElement = document.elementFromPoint(
|
|
65
|
-
event.clientX,
|
|
66
|
-
event.clientY
|
|
67
|
-
);
|
|
68
|
-
|
|
69
|
-
this.dragMove.emit({
|
|
70
|
-
event,
|
|
71
|
-
column: this.column,
|
|
72
|
-
hoveredElement,
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
onMouseUp = (event: MouseEvent) => {
|
|
78
|
-
if (!this.isDragging) return;
|
|
79
|
-
this.isDragging = false;
|
|
80
|
-
|
|
81
|
-
this.dragEnd.emit({ column: this.column, event });
|
|
82
|
-
|
|
83
|
-
if (this.previewEl) {
|
|
84
|
-
this.renderer.removeChild(document.body, this.previewEl);
|
|
85
|
-
this.previewEl = null;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (this.placeholderEl) {
|
|
89
|
-
const parent = this.placeholderEl.parentNode;
|
|
90
|
-
if (parent) {
|
|
91
|
-
parent.replaceChild(this.el.nativeElement, this.placeholderEl);
|
|
92
|
-
}
|
|
93
|
-
this.placeholderEl = null;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Reset the cursor
|
|
97
|
-
this.resetCursor();
|
|
98
|
-
|
|
99
|
-
document.removeEventListener('mousemove', this.onMouseMove);
|
|
100
|
-
document.removeEventListener('mouseup', this.onMouseUp);
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
private originalCursor: string | null = null;
|
|
104
|
-
|
|
105
|
-
private setCursor(cursorStyle: string) {
|
|
106
|
-
this.renderer.setStyle(document.body, 'cursor', cursorStyle);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
private resetCursor() {
|
|
110
|
-
this.renderer.setStyle(document.body, 'cursor', this.originalCursor || '');
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
private startDragging(event: MouseEvent) {
|
|
114
|
-
this.isDragging = true;
|
|
115
|
-
|
|
116
|
-
// Store original cursor (optional fallback)
|
|
117
|
-
this.originalCursor = getComputedStyle(document.body).cursor;
|
|
118
|
-
|
|
119
|
-
// Set cursor to grabbing
|
|
120
|
-
this.setCursor('move');
|
|
121
|
-
|
|
122
|
-
// --- Clone the element as a placeholder ---
|
|
123
|
-
this.placeholderEl = this.el.nativeElement.cloneNode(true) as HTMLElement;
|
|
124
|
-
this.renderer.setStyle(this.placeholderEl, 'opacity', '0.5');
|
|
125
|
-
this.renderer.setStyle(this.placeholderEl, 'pointer-events', 'none');
|
|
126
|
-
this.renderer.addClass(this.placeholderEl, 'drag-placeholder');
|
|
127
|
-
|
|
128
|
-
const parent = this.el.nativeElement.parentNode;
|
|
129
|
-
parent.replaceChild(this.placeholderEl, this.el.nativeElement);
|
|
130
|
-
|
|
131
|
-
// --- Create floating preview ---
|
|
132
|
-
this.previewEl = this.renderer.createElement('div');
|
|
133
|
-
this.renderer.setStyle(this.previewEl, 'position', 'absolute');
|
|
134
|
-
this.renderer.setStyle(this.previewEl, 'top', `${event.pageY + 10}px`);
|
|
135
|
-
this.renderer.setStyle(this.previewEl, 'left', `${event.pageX + 10}px`);
|
|
136
|
-
this.renderer.setStyle(this.previewEl, 'pointer-events', 'none');
|
|
137
|
-
this.renderer.setStyle(this.previewEl, 'z-index', '1000');
|
|
138
|
-
this.renderer.setStyle(this.previewEl, 'max-width', '200px');
|
|
139
|
-
this.renderer.setStyle(this.previewEl, 'padding', '8px');
|
|
140
|
-
this.renderer.setStyle(this.previewEl, 'border', '1px solid #ccc');
|
|
141
|
-
this.renderer.setStyle(this.previewEl, 'background-color', '#fff');
|
|
142
|
-
this.renderer.setStyle(
|
|
143
|
-
this.previewEl,
|
|
144
|
-
'box-shadow',
|
|
145
|
-
'0 2px 6px rgba(0,0,0,0.2)'
|
|
146
|
-
);
|
|
147
|
-
this.renderer.setStyle(this.previewEl, 'border-radius', '4px');
|
|
148
|
-
this.renderer.setStyle(this.previewEl, 'display', 'flex');
|
|
149
|
-
this.renderer.setStyle(this.previewEl, 'align-items', 'center');
|
|
150
|
-
this.renderer.setStyle(this.previewEl, 'gap', '8px');
|
|
151
|
-
this.renderer.setStyle(this.previewEl, 'font-weight', '500');
|
|
152
|
-
this.renderer.setStyle(this.previewEl, 'white-space', 'nowrap');
|
|
153
|
-
|
|
154
|
-
const icon = this.renderer.createElement('span');
|
|
155
|
-
this.renderer.setStyle(icon, 'font-size', '16px');
|
|
156
|
-
this.renderer.setStyle(icon, 'user-select', 'none');
|
|
157
|
-
this.renderer.setProperty(icon, 'innerText', '≡');
|
|
158
|
-
|
|
159
|
-
const text = this.renderer.createElement('span');
|
|
160
|
-
this.renderer.setProperty(text, 'innerText', this.headerName || 'Dragging');
|
|
161
|
-
|
|
162
|
-
this.renderer.appendChild(this.previewEl, icon);
|
|
163
|
-
this.renderer.appendChild(this.previewEl, text);
|
|
164
|
-
this.renderer.appendChild(document.body, this.previewEl);
|
|
165
|
-
|
|
166
|
-
this.dragStart.emit({ column: this.column, event });
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
public overrideCursor(style: string) {
|
|
170
|
-
this.setCursor(style);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/* tslint:disable:no-unused-variable */
|
|
2
|
-
|
|
3
|
-
import { TestBed, async } from '@angular/core/testing';
|
|
4
|
-
import { FilterPipe } from './filter.pipe';
|
|
5
|
-
|
|
6
|
-
describe('Pipe: Filtere', () => {
|
|
7
|
-
it('create an instance', () => {
|
|
8
|
-
let pipe = new FilterPipe();
|
|
9
|
-
expect(pipe).toBeTruthy();
|
|
10
|
-
});
|
|
11
|
-
});
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { Pipe, PipeTransform } from '@angular/core';
|
|
2
|
-
|
|
3
|
-
@Pipe({
|
|
4
|
-
name: 'filter',
|
|
5
|
-
})
|
|
6
|
-
export class FilterPipe implements PipeTransform {
|
|
7
|
-
transform(items: any[], searchText: string, key?: string): any[] {
|
|
8
|
-
if (!items || !searchText) return items;
|
|
9
|
-
|
|
10
|
-
const lowerSearch = searchText.toLowerCase();
|
|
11
|
-
|
|
12
|
-
return items.filter(item => {
|
|
13
|
-
if (key && item && typeof item === 'object') {
|
|
14
|
-
const value = item[key];
|
|
15
|
-
return value?.toString().toLowerCase().includes(lowerSearch);
|
|
16
|
-
}
|
|
17
|
-
if (typeof item === 'string' || typeof item === 'number') {
|
|
18
|
-
return item.toString().toLowerCase().includes(lowerSearch);
|
|
19
|
-
}
|
|
20
|
-
return false;
|
|
21
|
-
});
|
|
22
|
-
}}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
// /* tslint:disable:no-unused-variable */
|
|
2
|
-
|
|
3
|
-
// import { TestBed, async, inject } from '@angular/core/testing';
|
|
4
|
-
// import { CellSelectionService } from './cell-selection.service';
|
|
5
|
-
|
|
6
|
-
// describe('Service: CellSelection', () => {
|
|
7
|
-
// beforeEach(() => {
|
|
8
|
-
// TestBed.configureTestingModule({
|
|
9
|
-
// providers: [CellSelectionService]
|
|
10
|
-
// });
|
|
11
|
-
// });
|
|
12
|
-
|
|
13
|
-
// it('should ...', inject([CellSelectionService], (service: CellSelectionService) => {
|
|
14
|
-
// expect(service).toBeTruthy();
|
|
15
|
-
// }));
|
|
16
|
-
// });
|
|
@@ -1,205 +0,0 @@
|
|
|
1
|
-
// selection.service.ts
|
|
2
|
-
import { Injectable } from '@angular/core';
|
|
3
|
-
|
|
4
|
-
export interface SelectionRange {
|
|
5
|
-
startRow: number;
|
|
6
|
-
startGroupIndex: number;
|
|
7
|
-
startSubColIndex: number;
|
|
8
|
-
startField: string;
|
|
9
|
-
endRow: number;
|
|
10
|
-
endGroupIndex: number;
|
|
11
|
-
endSubColIndex: number;
|
|
12
|
-
endField: string;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface ActiveCell {
|
|
16
|
-
row: number;
|
|
17
|
-
groupIndex: number;
|
|
18
|
-
subColIndex: number;
|
|
19
|
-
field: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
@Injectable({
|
|
23
|
-
providedIn: 'root'
|
|
24
|
-
})
|
|
25
|
-
export class CellSelectionService {
|
|
26
|
-
private selectionRange: SelectionRange | null = null;
|
|
27
|
-
private activeCell: ActiveCell | null = null;
|
|
28
|
-
private isSelecting = false;
|
|
29
|
-
getSelection(): SelectionRange | null {
|
|
30
|
-
return this.selectionRange;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
getActiveCell(): ActiveCell | null {
|
|
34
|
-
return this.activeCell;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
isSelected(row: number, groupIndex: number, subColIndex: number, field: string): boolean {
|
|
38
|
-
if (!this.selectionRange) return false;
|
|
39
|
-
|
|
40
|
-
const {
|
|
41
|
-
startRow,
|
|
42
|
-
startGroupIndex,
|
|
43
|
-
startSubColIndex,
|
|
44
|
-
startField,
|
|
45
|
-
endRow,
|
|
46
|
-
endGroupIndex,
|
|
47
|
-
endSubColIndex,
|
|
48
|
-
endField
|
|
49
|
-
} = this.selectionRange;
|
|
50
|
-
|
|
51
|
-
const minRow = Math.min(startRow, endRow);
|
|
52
|
-
const maxRow = Math.max(startRow, endRow);
|
|
53
|
-
|
|
54
|
-
const isSameGroup = startGroupIndex === endGroupIndex;
|
|
55
|
-
const isSameField = startField === endField;
|
|
56
|
-
|
|
57
|
-
if (isSameGroup && isSameField) {
|
|
58
|
-
const minSubCol = Math.min(startSubColIndex, endSubColIndex);
|
|
59
|
-
const maxSubCol = Math.max(startSubColIndex, endSubColIndex);
|
|
60
|
-
|
|
61
|
-
return row >= minRow &&
|
|
62
|
-
row <= maxRow &&
|
|
63
|
-
groupIndex === startGroupIndex &&
|
|
64
|
-
field === startField &&
|
|
65
|
-
subColIndex >= minSubCol &&
|
|
66
|
-
subColIndex <= maxSubCol;
|
|
67
|
-
} else if (isSameGroup) {
|
|
68
|
-
|
|
69
|
-
const fieldsInGroup = this.getFieldsInGroup(groupIndex);
|
|
70
|
-
const startFieldIndex = fieldsInGroup.indexOf(startField);
|
|
71
|
-
const endFieldIndex = fieldsInGroup.indexOf(endField);
|
|
72
|
-
const minFieldIndex = Math.min(startFieldIndex, endFieldIndex);
|
|
73
|
-
const maxFieldIndex = Math.max(startFieldIndex, endFieldIndex);
|
|
74
|
-
const currentFieldIndex = fieldsInGroup.indexOf(field);
|
|
75
|
-
|
|
76
|
-
return row >= minRow &&
|
|
77
|
-
row <= maxRow &&
|
|
78
|
-
groupIndex === startGroupIndex &&
|
|
79
|
-
currentFieldIndex >= minFieldIndex &&
|
|
80
|
-
currentFieldIndex <= maxFieldIndex;
|
|
81
|
-
} else {
|
|
82
|
-
const minGroup = Math.min(startGroupIndex, endGroupIndex);
|
|
83
|
-
const maxGroup = Math.max(startGroupIndex, endGroupIndex);
|
|
84
|
-
|
|
85
|
-
if (groupIndex === startGroupIndex) {
|
|
86
|
-
const fieldsInGroup = this.getFieldsInGroup(groupIndex);
|
|
87
|
-
const startFieldIndex = fieldsInGroup.indexOf(startField);
|
|
88
|
-
const currentFieldIndex = fieldsInGroup.indexOf(field);
|
|
89
|
-
|
|
90
|
-
return row >= minRow &&
|
|
91
|
-
row <= maxRow &&
|
|
92
|
-
currentFieldIndex >= (startGroupIndex === minGroup ? startFieldIndex : 0) &&
|
|
93
|
-
currentFieldIndex <= (startGroupIndex === maxGroup ? startFieldIndex : fieldsInGroup.length - 1);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if (groupIndex === endGroupIndex) {
|
|
97
|
-
const fieldsInGroup = this.getFieldsInGroup(groupIndex);
|
|
98
|
-
const endFieldIndex = fieldsInGroup.indexOf(endField);
|
|
99
|
-
const currentFieldIndex = fieldsInGroup.indexOf(field);
|
|
100
|
-
|
|
101
|
-
return row >= minRow &&
|
|
102
|
-
row <= maxRow &&
|
|
103
|
-
currentFieldIndex >= (endGroupIndex === minGroup ? endFieldIndex : 0) &&
|
|
104
|
-
currentFieldIndex <= (endGroupIndex === maxGroup ? endFieldIndex : fieldsInGroup.length - 1);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return row >= minRow &&
|
|
108
|
-
row <= maxRow &&
|
|
109
|
-
groupIndex > minGroup &&
|
|
110
|
-
groupIndex < maxGroup;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
isActiveCell(row: number, groupIndex: number, subColIndex: number, field: string): boolean {
|
|
115
|
-
return this.activeCell?.row === row &&
|
|
116
|
-
this.activeCell?.groupIndex === groupIndex &&
|
|
117
|
-
this.activeCell?.subColIndex === subColIndex &&
|
|
118
|
-
this.activeCell?.field === field;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
startSelection(row: number, groupIndex: number, subColIndex: number, field: string): void {
|
|
122
|
-
this.isSelecting = true;
|
|
123
|
-
this.selectionRange = {
|
|
124
|
-
startRow: row,
|
|
125
|
-
startGroupIndex: groupIndex,
|
|
126
|
-
startSubColIndex: subColIndex,
|
|
127
|
-
startField: field,
|
|
128
|
-
endRow: row,
|
|
129
|
-
endGroupIndex: groupIndex,
|
|
130
|
-
endSubColIndex: subColIndex,
|
|
131
|
-
endField: field
|
|
132
|
-
};
|
|
133
|
-
this.activeCell = { row, groupIndex, subColIndex, field };
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
extendSelection(row: number, groupIndex: number, subColIndex: number, field: string): void {
|
|
137
|
-
if (this.isSelecting && this.selectionRange) {
|
|
138
|
-
this.selectionRange.endRow = row;
|
|
139
|
-
this.selectionRange.endGroupIndex = groupIndex;
|
|
140
|
-
this.selectionRange.endSubColIndex = subColIndex;
|
|
141
|
-
this.selectionRange.endField = field;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
endSelection(): void {
|
|
146
|
-
this.isSelecting = false;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
clearSelection(): void {
|
|
150
|
-
this.selectionRange = null;
|
|
151
|
-
this.activeCell = null;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
moveSelection(direction: 'up' | 'down' | 'left' | 'right', columnStructure: any[]): void {
|
|
155
|
-
if (!this.activeCell) return;
|
|
156
|
-
|
|
157
|
-
let { row, groupIndex, subColIndex, field } = this.activeCell;
|
|
158
|
-
|
|
159
|
-
switch (direction) {
|
|
160
|
-
case 'up':
|
|
161
|
-
row--;
|
|
162
|
-
break;
|
|
163
|
-
case 'down':
|
|
164
|
-
row++;
|
|
165
|
-
break;
|
|
166
|
-
case 'left':
|
|
167
|
-
if (subColIndex > 0) {
|
|
168
|
-
subColIndex--;
|
|
169
|
-
field = this.getFieldFromIndices(groupIndex, subColIndex, columnStructure);
|
|
170
|
-
} else if (groupIndex > 0) {
|
|
171
|
-
groupIndex--;
|
|
172
|
-
subColIndex = columnStructure[groupIndex].children.length - 1;
|
|
173
|
-
field = this.getFieldFromIndices(groupIndex, subColIndex, columnStructure);
|
|
174
|
-
}
|
|
175
|
-
break;
|
|
176
|
-
case 'right':
|
|
177
|
-
if (subColIndex < columnStructure[groupIndex].children.length - 1) {
|
|
178
|
-
subColIndex++;
|
|
179
|
-
field = this.getFieldFromIndices(groupIndex, subColIndex, columnStructure);
|
|
180
|
-
} else if (groupIndex < columnStructure.length - 1) {
|
|
181
|
-
groupIndex++;
|
|
182
|
-
subColIndex = 0;
|
|
183
|
-
field = this.getFieldFromIndices(groupIndex, subColIndex, columnStructure);
|
|
184
|
-
}
|
|
185
|
-
break;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
this.startSelection(row, groupIndex, subColIndex, field);
|
|
189
|
-
this.endSelection();
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
private getFieldFromIndices(groupIndex: number, subColIndex: number, columnStructure: any[]): string {
|
|
193
|
-
if (groupIndex >= 0 &&
|
|
194
|
-
groupIndex < columnStructure.length &&
|
|
195
|
-
subColIndex >= 0 &&
|
|
196
|
-
subColIndex < columnStructure[groupIndex].children.length) {
|
|
197
|
-
return columnStructure[groupIndex].children[subColIndex].field;
|
|
198
|
-
}
|
|
199
|
-
return '';
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
private getFieldsInGroup(groupIndex: number): string[] {
|
|
203
|
-
return [];
|
|
204
|
-
}
|
|
205
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/* tslint:disable:no-unused-variable */
|
|
2
|
-
|
|
3
|
-
import { TestBed, async, inject } from '@angular/core/testing';
|
|
4
|
-
import { CommonService } from './common.service';
|
|
5
|
-
|
|
6
|
-
describe('Service: Common', () => {
|
|
7
|
-
beforeEach(() => {
|
|
8
|
-
TestBed.configureTestingModule({
|
|
9
|
-
providers: [CommonService]
|
|
10
|
-
});
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it('should ...', inject([CommonService], (service: CommonService) => {
|
|
14
|
-
expect(service).toBeTruthy();
|
|
15
|
-
}));
|
|
16
|
-
});
|