argent-grid 0.2.0 → 0.3.0
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/AGENTS.md +70 -27
- package/e2e/advanced.spec.ts +1 -1
- package/e2e/benchmark.spec.ts +7 -7
- package/e2e/cell-renderers.spec.ts +152 -0
- package/e2e/debug-streaming.spec.ts +31 -0
- package/e2e/dnd.spec.ts +73 -0
- package/e2e/screenshots.spec.ts +1 -1
- package/e2e/visual.spec.ts +30 -9
- package/e2e/visual.spec.ts-snapshots/checkbox-renderer-mixed.png +0 -0
- package/e2e/visual.spec.ts-snapshots/debug.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-column-group-headers.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-default.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-empty-state.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-filter-popup.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-scroll-borders.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-sidebar-buttons.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-text-filter.png +0 -0
- package/e2e/visual.spec.ts-snapshots/grid-with-selection.png +0 -0
- package/e2e/visual.spec.ts-snapshots/rating-renderer-varied.png +0 -0
- package/package.json +5 -5
- package/plan.md +30 -34
- package/src/lib/components/argent-grid.component.css +258 -549
- package/src/lib/components/argent-grid.component.html +272 -306
- package/src/lib/components/argent-grid.component.ts +585 -135
- package/src/lib/components/argent-grid.regressions.spec.ts +301 -0
- package/src/lib/components/argent-grid.selection.spec.ts +2 -2
- package/src/lib/components/set-filter/set-filter.component.spec.ts +191 -0
- package/src/lib/components/set-filter/set-filter.component.ts +7 -2
- package/src/lib/rendering/canvas-renderer.spec.ts +148 -1
- package/src/lib/rendering/canvas-renderer.ts +177 -286
- package/src/lib/rendering/render/cells.ts +122 -5
- package/src/lib/rendering/render/column-utils.ts +27 -5
- package/src/lib/rendering/render/hit-test.ts +6 -11
- package/src/lib/rendering/render/index.ts +15 -6
- package/src/lib/rendering/render/lines.ts +12 -6
- package/src/lib/rendering/render/primitives.ts +269 -7
- package/src/lib/rendering/render/types.ts +2 -1
- package/src/lib/rendering/render/walk.ts +39 -19
- package/src/lib/services/grid.service.spec.ts +76 -0
- package/src/lib/services/grid.service.ts +451 -114
- package/src/lib/themes/theme-quartz.ts +2 -2
- package/src/lib/types/ag-grid-types.ts +500 -0
- package/src/stories/Advanced.stories.ts +78 -17
- package/src/stories/ArgentGrid.stories.ts +50 -26
- package/src/stories/Benchmark.stories.ts +17 -15
- package/src/stories/CellRenderers.stories.ts +205 -31
- package/src/stories/Filtering.stories.ts +56 -16
- package/src/stories/Grouping.stories.ts +86 -13
- package/src/stories/Streaming.stories.ts +57 -0
- package/src/stories/Theming.stories.ts +23 -10
- package/src/stories/Tooltips.stories.ts +381 -0
- package/src/stories/benchmark-wrapper.component.ts +69 -29
- package/src/stories/story-utils.ts +88 -0
- package/src/stories/streaming-wrapper.component.ts +441 -0
- package/tsconfig.json +1 -0
|
@@ -1,313 +1,285 @@
|
|
|
1
1
|
<div class="argent-grid-container" [style.height]="height" [style.width]="width" (click)="onContainerClick($event)">
|
|
2
|
-
<div class="argent-grid-main-layout">
|
|
2
|
+
<div class="argent-grid-main-layout" cdkDropListGroup>
|
|
3
3
|
<div class="argent-grid-content-area">
|
|
4
|
+
<!-- Row Group Panel -->
|
|
5
|
+
<div class="argent-grid-row-group-panel"
|
|
6
|
+
*ngIf="isRowGroupPanelVisible()"
|
|
7
|
+
cdkDropList
|
|
8
|
+
id="row-group-panel"
|
|
9
|
+
cdkDropListOrientation="horizontal"
|
|
10
|
+
(cdkDropListDropped)="onRowGroupDropped($event)">
|
|
11
|
+
<div class="row-group-placeholder" *ngIf="getRowGroupColumns().length === 0">
|
|
12
|
+
Drag columns here to group
|
|
13
|
+
</div>
|
|
14
|
+
<div *ngFor="let col of getRowGroupColumns(); trackBy: trackByRowGroup" class="row-group-pill">
|
|
15
|
+
<span class="pill-text">{{ getHeaderName(col) }}</span>
|
|
16
|
+
<span class="pill-close" (click)="removeRowGroup(col)">✕</span>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
4
20
|
<!-- Header Layer (DOM-based for accessibility) -->
|
|
5
21
|
<div class="argent-grid-header">
|
|
6
|
-
<!-- Main Header Row -->
|
|
7
|
-
<div class="argent-grid-header-row">
|
|
8
|
-
|
|
9
22
|
|
|
10
|
-
|
|
23
|
+
<div class="argent-grid-header-main">
|
|
24
|
+
<!-- Left Pinned Header -->
|
|
11
25
|
<div class="argent-grid-header-pinned-left-container"
|
|
26
|
+
*ngIf="getLeftPinnedColumns().length > 0"
|
|
27
|
+
[style.display]="'grid'"
|
|
28
|
+
[style.grid-template-rows]="'repeat(' + gridApi.getHeaderDepth() + ', ' + effectiveHeaderHeight + 'px)'"
|
|
29
|
+
[style.grid-template-columns]="getGridTemplateColumns('left')"
|
|
12
30
|
cdkDropList
|
|
13
|
-
id="left-pinned"
|
|
14
|
-
[cdkDropListConnectedTo]="['scrollable', 'right-pinned']"
|
|
31
|
+
id="left-pinned-list"
|
|
15
32
|
cdkDropListOrientation="horizontal"
|
|
16
33
|
(cdkDropListDropped)="onColumnDropped($event, 'left')">
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class="argent-grid-header-cell argent-grid-header-cell-pinned-left"
|
|
20
|
-
[class.center-content]="col.colId === 'ag-Grid-SelectionColumn'"
|
|
21
|
-
[style.width.px]="getColumnWidth(col)"
|
|
22
|
-
[class.sortable]="isSortable(col)"
|
|
23
|
-
(click)="onHeaderClick(col)"
|
|
24
|
-
cdkDrag
|
|
25
|
-
[cdkDragDisabled]="col.colId === 'ag-Grid-SelectionColumn'"
|
|
26
|
-
[cdkDragData]="col">
|
|
27
|
-
<div class="argent-grid-header-content" cdkDragHandle>
|
|
28
|
-
<div *ngIf="hasHeaderCheckbox(col)" class="argent-grid-header-checkbox">
|
|
29
|
-
<input type="checkbox"
|
|
30
|
-
[checked]="isAllSelected"
|
|
31
|
-
[indeterminate]="isIndeterminateSelection"
|
|
32
|
-
(click)="$event.stopPropagation()"
|
|
33
|
-
(change)="onSelectionHeaderChange($event)" />
|
|
34
|
-
</div>
|
|
35
|
-
<span class="header-text">{{ getHeaderName(col) }}</span>
|
|
36
|
-
<span class="sort-indicator" *ngIf="getSortIndicator(col)">{{ getSortIndicator(col) }}</span>
|
|
37
|
-
</div>
|
|
38
|
-
<div class="argent-grid-header-menu-icon" (click)="onHeaderMenuClick($event, col)" *ngIf="hasHeaderMenu(col)">
|
|
39
|
-
⋮
|
|
40
|
-
</div>
|
|
41
|
-
<div class="argent-grid-header-resize-handle"
|
|
42
|
-
*ngIf="isResizable(col)"
|
|
43
|
-
[class.resizing]="isResizing && resizeColumn === col"
|
|
44
|
-
(mousedown)="onResizeMouseDown($event, col)">
|
|
45
|
-
</div>
|
|
46
|
-
</div>
|
|
47
|
-
</div>
|
|
48
|
-
|
|
49
|
-
<!-- Scrollable Columns -->
|
|
50
|
-
<div class="argent-grid-header-scrollable"
|
|
51
|
-
#headerScrollable
|
|
52
|
-
cdkDropList
|
|
53
|
-
id="scrollable"
|
|
54
|
-
[cdkDropListConnectedTo]="['left-pinned', 'right-pinned']"
|
|
55
|
-
cdkDropListOrientation="horizontal"
|
|
56
|
-
(cdkDropListDropped)="onColumnDropped($event, 'none')">
|
|
57
|
-
<div class="argent-grid-header-row">
|
|
34
|
+
|
|
35
|
+
<ng-container *ngFor="let entry of getSectionHeaderItems('left'); trackBy: trackByHeaderItem">
|
|
58
36
|
<div
|
|
59
|
-
*
|
|
60
|
-
class="argent-grid-header-cell"
|
|
61
|
-
[class.
|
|
62
|
-
[
|
|
63
|
-
[
|
|
64
|
-
|
|
37
|
+
*ngIf="isColumnVisible(entry.item)"
|
|
38
|
+
class="argent-grid-header-cell argent-grid-header-cell-pinned-left"
|
|
39
|
+
[class.argent-grid-header-group-cell]="isColumnGroup(entry.item)"
|
|
40
|
+
[class.center-content]="!isColumnGroup(entry.item) && entry.item.colId === 'ag-Grid-SelectionColumn'"
|
|
41
|
+
[style.grid-column]="getLeftPinnedColIndex(entry.item) + ' / span ' + getItemColSpan(entry.item)"
|
|
42
|
+
[style.grid-row]="(entry.rowIndex + 1) + ' / span ' + getItemRowSpan(entry.item, entry.rowIndex)"
|
|
43
|
+
[style.width.px]="getItemWidth(entry.item)"
|
|
44
|
+
[style.height.px]="getItemRowSpan(entry.item, entry.rowIndex) * effectiveHeaderHeight"
|
|
45
|
+
[class.sortable]="!isColumnGroup(entry.item) && isSortable(entry.item)"
|
|
46
|
+
(click)="!isColumnGroup(entry.item) && onHeaderClick(entry.item)"
|
|
65
47
|
cdkDrag
|
|
66
|
-
[cdkDragDisabled]="
|
|
67
|
-
[cdkDragData]="
|
|
48
|
+
[cdkDragDisabled]="isColumnGroup(entry.item) || entry.item.colId === 'ag-Grid-SelectionColumn'"
|
|
49
|
+
[cdkDragData]="entry.item">
|
|
68
50
|
<div class="argent-grid-header-content" cdkDragHandle>
|
|
69
|
-
<div *ngIf="hasHeaderCheckbox(
|
|
51
|
+
<div *ngIf="!isColumnGroup(entry.item) && hasHeaderCheckbox(entry.item)" class="argent-grid-header-checkbox">
|
|
70
52
|
<input type="checkbox"
|
|
71
53
|
[checked]="isAllSelected"
|
|
72
54
|
[indeterminate]="isIndeterminateSelection"
|
|
73
55
|
(click)="$event.stopPropagation()"
|
|
74
56
|
(change)="onSelectionHeaderChange($event)" />
|
|
75
57
|
</div>
|
|
76
|
-
<span class="header-text">{{ getHeaderName(
|
|
77
|
-
<span class="
|
|
58
|
+
<span class="header-text">{{ getHeaderName(entry.item) }}</span>
|
|
59
|
+
<span class="group-toggle" *ngIf="isColumnGroup(entry.item) && hasExpansionToggle(entry.item)" (click)="toggleGroup(entry.item, $event)">
|
|
60
|
+
{{ entry.item.expanded ? '−' : '+' }}
|
|
61
|
+
</span>
|
|
62
|
+
<span class="sort-indicator" *ngIf="!isColumnGroup(entry.item) && getSortIndicator(entry.item)">{{ getSortIndicator(entry.item) }}</span>
|
|
63
|
+
</div>
|
|
64
|
+
<div class="argent-grid-header-filter-icon"
|
|
65
|
+
[class.active]="isColumnFiltered(entry.item)"
|
|
66
|
+
(click)="onHeaderFilterClick($event, entry.item)"
|
|
67
|
+
*ngIf="!isColumnGroup(entry.item) && hasHeaderFilterButton(entry.item)"
|
|
68
|
+
title="Filter">
|
|
69
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 10 10" fill="currentColor"><path d="M0.5 1.5h9L6 6V9H4V6Z"/></svg>
|
|
78
70
|
</div>
|
|
79
|
-
<div class="argent-grid-header-menu-icon" (click)="onHeaderMenuClick($event,
|
|
71
|
+
<div class="argent-grid-header-menu-icon" (click)="onHeaderMenuClick($event, entry.item)" *ngIf="!isColumnGroup(entry.item) && hasHeaderMenu(entry.item)">
|
|
80
72
|
⋮
|
|
81
73
|
</div>
|
|
82
74
|
<div class="argent-grid-header-resize-handle"
|
|
83
|
-
*ngIf="isResizable(
|
|
84
|
-
[class.resizing]="isResizing &&
|
|
85
|
-
(mousedown)="onResizeMouseDown($event,
|
|
75
|
+
*ngIf="isResizable(entry.item)"
|
|
76
|
+
[class.resizing]="isResizing && resizeItem === entry.item"
|
|
77
|
+
(mousedown)="onResizeMouseDown($event, entry.item)">
|
|
86
78
|
</div>
|
|
87
79
|
</div>
|
|
80
|
+
</ng-container>
|
|
81
|
+
</div>
|
|
82
|
+
|
|
83
|
+
<!-- Scrollable Header -->
|
|
84
|
+
<div class="argent-grid-header-scrollable" #headerScrollable>
|
|
85
|
+
<div class="argent-grid-header-scrollable-content"
|
|
86
|
+
[style.display]="'grid'"
|
|
87
|
+
[style.grid-template-rows]="'repeat(' + gridApi.getHeaderDepth() + ', ' + effectiveHeaderHeight + 'px)'"
|
|
88
|
+
[style.grid-template-columns]="getGridTemplateColumns('none')"
|
|
89
|
+
[style.width.px]="getScrollableHeaderWidth()"
|
|
90
|
+
cdkDropList
|
|
91
|
+
id="scrollable-list"
|
|
92
|
+
cdkDropListOrientation="horizontal"
|
|
93
|
+
(cdkDropListDropped)="onColumnDropped($event, 'none')">
|
|
94
|
+
|
|
95
|
+
<ng-container *ngFor="let entry of getSectionHeaderItems('none'); trackBy: trackByHeaderItem">
|
|
96
|
+
<div
|
|
97
|
+
*ngIf="isColumnVisible(entry.item)"
|
|
98
|
+
class="argent-grid-header-cell"
|
|
99
|
+
[class.argent-grid-header-group-cell]="isColumnGroup(entry.item)"
|
|
100
|
+
[style.grid-column]="getScrollableColIndex(entry.item) + ' / span ' + getItemColSpan(entry.item)"
|
|
101
|
+
[style.grid-row]="(entry.rowIndex + 1) + ' / span ' + getItemRowSpan(entry.item, entry.rowIndex)"
|
|
102
|
+
[style.width.px]="getItemWidth(entry.item)"
|
|
103
|
+
[style.height.px]="getItemRowSpan(entry.item, entry.rowIndex) * effectiveHeaderHeight"
|
|
104
|
+
[class.sortable]="!isColumnGroup(entry.item) && isSortable(entry.item)"
|
|
105
|
+
(click)="!isColumnGroup(entry.item) && onHeaderClick(entry.item)"
|
|
106
|
+
cdkDrag
|
|
107
|
+
[cdkDragDisabled]="isColumnGroup(entry.item) || entry.item.colId === 'ag-Grid-SelectionColumn'"
|
|
108
|
+
[cdkDragData]="entry.item">
|
|
109
|
+
<div class="argent-grid-header-content" cdkDragHandle>
|
|
110
|
+
<span class="header-text">{{ getHeaderName(entry.item) }}</span>
|
|
111
|
+
<span class="group-toggle" *ngIf="isColumnGroup(entry.item) && hasExpansionToggle(entry.item)" (click)="toggleGroup(entry.item, $event)">
|
|
112
|
+
{{ entry.item.expanded ? '−' : '+' }}
|
|
113
|
+
</span>
|
|
114
|
+
<span class="sort-indicator" *ngIf="!isColumnGroup(entry.item) && getSortIndicator(entry.item)">{{ getSortIndicator(entry.item) }}</span>
|
|
115
|
+
</div>
|
|
116
|
+
<div class="argent-grid-header-filter-icon"
|
|
117
|
+
[class.active]="isColumnFiltered(entry.item)"
|
|
118
|
+
(click)="onHeaderFilterClick($event, entry.item)"
|
|
119
|
+
*ngIf="!isColumnGroup(entry.item) && hasHeaderFilterButton(entry.item)"
|
|
120
|
+
title="Filter">
|
|
121
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 10 10" fill="currentColor"><path d="M0.5 1.5h9L6 6V9H4V6Z"/></svg>
|
|
122
|
+
</div>
|
|
123
|
+
<div class="argent-grid-header-menu-icon" (click)="onHeaderMenuClick($event, entry.item)" *ngIf="!isColumnGroup(entry.item) && hasHeaderMenu(entry.item)">
|
|
124
|
+
⋮
|
|
125
|
+
</div>
|
|
126
|
+
<div class="argent-grid-header-resize-handle"
|
|
127
|
+
*ngIf="isResizable(entry.item)"
|
|
128
|
+
[class.resizing]="isResizing && resizeItem === entry.item"
|
|
129
|
+
(mousedown)="onResizeMouseDown($event, entry.item)">
|
|
130
|
+
</div>
|
|
131
|
+
</div>
|
|
132
|
+
</ng-container>
|
|
88
133
|
</div>
|
|
89
134
|
</div>
|
|
90
135
|
|
|
91
|
-
<!-- Right Pinned
|
|
136
|
+
<!-- Right Pinned Header -->
|
|
92
137
|
<div class="argent-grid-header-pinned-right-container"
|
|
138
|
+
*ngIf="getRightPinnedColumns().length > 0"
|
|
139
|
+
[style.display]="'grid'"
|
|
140
|
+
[style.grid-template-rows]="'repeat(' + gridApi.getHeaderDepth() + ', ' + effectiveHeaderHeight + 'px)'"
|
|
141
|
+
[style.grid-template-columns]="getGridTemplateColumns('right')"
|
|
93
142
|
cdkDropList
|
|
94
|
-
id="right-pinned"
|
|
95
|
-
[cdkDropListConnectedTo]="['left-pinned', 'scrollable']"
|
|
143
|
+
id="right-pinned-list"
|
|
96
144
|
cdkDropListOrientation="horizontal"
|
|
97
145
|
(cdkDropListDropped)="onColumnDropped($event, 'right')">
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
146
|
+
|
|
147
|
+
<ng-container *ngFor="let entry of getSectionHeaderItems('right'); trackBy: trackByHeaderItem">
|
|
148
|
+
<div
|
|
149
|
+
*ngIf="isColumnVisible(entry.item)"
|
|
150
|
+
class="argent-grid-header-cell argent-grid-header-cell-pinned-right"
|
|
151
|
+
[class.argent-grid-header-group-cell]="isColumnGroup(entry.item)"
|
|
152
|
+
[style.grid-column]="getRightPinnedColIndex(entry.item) + ' / span ' + getItemColSpan(entry.item)"
|
|
153
|
+
[style.grid-row]="(entry.rowIndex + 1) + ' / span ' + getItemRowSpan(entry.item, entry.rowIndex)"
|
|
154
|
+
[style.width.px]="getItemWidth(entry.item)"
|
|
155
|
+
[style.height.px]="getItemRowSpan(entry.item, entry.rowIndex) * effectiveHeaderHeight"
|
|
156
|
+
[class.sortable]="!isColumnGroup(entry.item) && isSortable(entry.item)"
|
|
157
|
+
(click)="!isColumnGroup(entry.item) && onHeaderClick(entry.item)"
|
|
158
|
+
cdkDrag
|
|
159
|
+
[cdkDragDisabled]="isColumnGroup(entry.item) || entry.item.colId === 'ag-Grid-SelectionColumn'"
|
|
160
|
+
[cdkDragData]="entry.item">
|
|
161
|
+
<div class="argent-grid-header-content" cdkDragHandle>
|
|
162
|
+
<span class="header-text">{{ getHeaderName(entry.item) }}</span>
|
|
163
|
+
<span class="group-toggle" *ngIf="isColumnGroup(entry.item) && hasExpansionToggle(entry.item)" (click)="toggleGroup(entry.item, $event)">
|
|
164
|
+
{{ entry.item.expanded ? '−' : '+' }}
|
|
165
|
+
</span>
|
|
166
|
+
<span class="sort-indicator" *ngIf="!isColumnGroup(entry.item) && getSortIndicator(entry.item)">{{ getSortIndicator(entry.item) }}</span>
|
|
167
|
+
</div>
|
|
168
|
+
<div class="argent-grid-header-filter-icon"
|
|
169
|
+
[class.active]="isColumnFiltered(entry.item)"
|
|
170
|
+
(click)="onHeaderFilterClick($event, entry.item)"
|
|
171
|
+
*ngIf="!isColumnGroup(entry.item) && hasHeaderFilterButton(entry.item)"
|
|
172
|
+
title="Filter">
|
|
173
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 10 10" fill="currentColor"><path d="M0.5 1.5h9L6 6V9H4V6Z"/></svg>
|
|
174
|
+
</div>
|
|
175
|
+
<div class="argent-grid-header-menu-icon" (click)="onHeaderMenuClick($event, entry.item)" *ngIf="!isColumnGroup(entry.item) && hasHeaderMenu(entry.item)">
|
|
176
|
+
⋮
|
|
177
|
+
</div>
|
|
178
|
+
<div class="argent-grid-header-resize-handle"
|
|
179
|
+
*ngIf="isResizable(entry.item)"
|
|
180
|
+
[class.resizing]="isResizing && resizeItem === entry.item"
|
|
181
|
+
(mousedown)="onResizeMouseDown($event, entry.item)">
|
|
115
182
|
</div>
|
|
116
|
-
<span class="header-text">{{ getHeaderName(col) }}</span>
|
|
117
|
-
<span class="sort-indicator" *ngIf="getSortIndicator(col)">{{ getSortIndicator(col) }}</span>
|
|
118
|
-
</div>
|
|
119
|
-
<div class="argent-grid-header-menu-icon" (click)="onHeaderMenuClick($event, col)" *ngIf="hasHeaderMenu(col)">
|
|
120
|
-
⋮
|
|
121
|
-
</div>
|
|
122
|
-
<div class="argent-grid-header-resize-handle"
|
|
123
|
-
*ngIf="isResizable(col)"
|
|
124
|
-
[class.resizing]="isResizing && resizeColumn === col"
|
|
125
|
-
(mousedown)="onResizeMouseDown($event, col)">
|
|
126
183
|
</div>
|
|
127
|
-
</
|
|
184
|
+
</ng-container>
|
|
185
|
+
</div>
|
|
186
|
+
|
|
187
|
+
<!-- Vertical Scrollbar Spacer -->
|
|
188
|
+
<div class="argent-grid-header-scrollbar-spacer"
|
|
189
|
+
*ngIf="scrollbarWidth > 0"
|
|
190
|
+
[style.width.px]="scrollbarWidth">
|
|
128
191
|
</div>
|
|
129
192
|
</div>
|
|
130
193
|
|
|
131
194
|
<!-- Floating Filter Row -->
|
|
132
|
-
<div class="
|
|
133
|
-
|
|
134
|
-
|
|
195
|
+
<div class="floating-filter-row" *ngIf="hasFloatingFilters()">
|
|
135
196
|
<!-- Left Pinned Filters -->
|
|
136
|
-
<div class="argent-grid-header-pinned-left-container">
|
|
137
|
-
<
|
|
138
|
-
*
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
<div class="floating-filter-container" *ngIf="isFloatingFilterEnabled(col)">
|
|
143
|
-
<!-- Set Filter Button -->
|
|
144
|
-
<button *ngIf="isSetFilter(col)"
|
|
145
|
-
type="button"
|
|
146
|
-
class="floating-filter-btn"
|
|
147
|
-
(click)="openSetFilter($event, col)"
|
|
148
|
-
[class.active]="hasSetFilterValue(col)">
|
|
149
|
-
🔽 {{ getSetFilterCount(col) }}
|
|
150
|
-
</button>
|
|
151
|
-
<!-- Text/Number/Date Filter Input -->
|
|
152
|
-
<ng-container *ngIf="!isSetFilter(col)">
|
|
197
|
+
<div class="argent-grid-header-pinned-left-container" *ngIf="getLeftPinnedColumns().length > 0">
|
|
198
|
+
<ng-container *ngFor="let col of getLeftPinnedColumns()">
|
|
199
|
+
<div *ngIf="isColumnVisible(col)"
|
|
200
|
+
class="argent-grid-floating-filter-cell"
|
|
201
|
+
[style.width.px]="getItemWidth(col)">
|
|
202
|
+
<div class="floating-filter-container" *ngIf="isFloatingFilterEnabled(col)">
|
|
153
203
|
<input #filterInput
|
|
154
204
|
class="floating-filter-input"
|
|
155
205
|
[type]="getFilterInputType(col)"
|
|
156
206
|
[value]="getFloatingFilterValue(col)"
|
|
157
207
|
(input)="onFloatingFilterInput($event, col)"
|
|
158
208
|
[placeholder]="'Filter...'" />
|
|
159
|
-
<span class="floating-filter-clear"
|
|
209
|
+
<span class="floating-filter-clear"
|
|
160
210
|
*ngIf="hasFilterValue(col, filterInput)"
|
|
161
211
|
(click)="clearFloatingFilter(col, filterInput)">✕</span>
|
|
162
|
-
</
|
|
212
|
+
</div>
|
|
163
213
|
</div>
|
|
164
|
-
</
|
|
214
|
+
</ng-container>
|
|
165
215
|
</div>
|
|
166
|
-
|
|
167
216
|
<!-- Scrollable Filters -->
|
|
168
217
|
<div class="argent-grid-header-scrollable" #headerScrollableFilter>
|
|
169
|
-
<div class="argent-grid-header-row">
|
|
170
|
-
<
|
|
171
|
-
*
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
(click)="clearFloatingFilter(col, filterInput)">✕</span>
|
|
195
|
-
</ng-container>
|
|
218
|
+
<div class="argent-grid-header-row" [style.width.px]="getScrollableHeaderWidth()">
|
|
219
|
+
<ng-container *ngFor="let col of getNonPinnedColumns()">
|
|
220
|
+
<div *ngIf="isColumnVisible(col)"
|
|
221
|
+
class="argent-grid-floating-filter-cell"
|
|
222
|
+
[style.width.px]="getItemWidth(col)">
|
|
223
|
+
<div class="floating-filter-container" *ngIf="isFloatingFilterEnabled(col)">
|
|
224
|
+
<button class="floating-filter-btn"
|
|
225
|
+
*ngIf="isSetFilter(col)"
|
|
226
|
+
[class.active]="hasSetFilterValue(col)"
|
|
227
|
+
(click)="openSetFilter($event, col)">
|
|
228
|
+
<span class="filter-label">{{ getFloatingFilterValue(col) || 'All' }}</span>
|
|
229
|
+
<span class="filter-count" *ngIf="hasSetFilterValue(col)">🔽 {{ getSetFilterCount(col) }}</span>
|
|
230
|
+
</button>
|
|
231
|
+
<ng-container *ngIf="!isSetFilter(col)">
|
|
232
|
+
<input #filterInput
|
|
233
|
+
class="floating-filter-input"
|
|
234
|
+
[type]="getFilterInputType(col)"
|
|
235
|
+
[value]="getFloatingFilterValue(col)"
|
|
236
|
+
(input)="onFloatingFilterInput($event, col)"
|
|
237
|
+
[placeholder]="'Filter...'" />
|
|
238
|
+
<span class="floating-filter-clear"
|
|
239
|
+
*ngIf="hasFilterValue(col, filterInput)"
|
|
240
|
+
(click)="clearFloatingFilter(col, filterInput)">✕</span>
|
|
241
|
+
</ng-container>
|
|
242
|
+
</div>
|
|
196
243
|
</div>
|
|
197
|
-
</
|
|
244
|
+
</ng-container>
|
|
198
245
|
</div>
|
|
199
246
|
</div>
|
|
200
|
-
|
|
201
247
|
<!-- Right Pinned Filters -->
|
|
202
|
-
<div class="argent-grid-header-pinned-right-container">
|
|
203
|
-
<
|
|
204
|
-
*
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
<div class="floating-filter-container" *ngIf="isFloatingFilterEnabled(col)">
|
|
209
|
-
<!-- Set Filter Button -->
|
|
210
|
-
<button *ngIf="isSetFilter(col)"
|
|
211
|
-
type="button"
|
|
212
|
-
class="floating-filter-btn"
|
|
213
|
-
(click)="openSetFilter($event, col)"
|
|
214
|
-
[class.active]="hasSetFilterValue(col)">
|
|
215
|
-
🔽 {{ getSetFilterCount(col) }}
|
|
216
|
-
</button>
|
|
217
|
-
<!-- Text/Number/Date Filter Input -->
|
|
218
|
-
<ng-container *ngIf="!isSetFilter(col)">
|
|
248
|
+
<div class="argent-grid-header-pinned-right-container" *ngIf="getRightPinnedColumns().length > 0">
|
|
249
|
+
<ng-container *ngFor="let col of getRightPinnedColumns()">
|
|
250
|
+
<div *ngIf="isColumnVisible(col)"
|
|
251
|
+
class="argent-grid-floating-filter-cell"
|
|
252
|
+
[style.width.px]="getItemWidth(col)">
|
|
253
|
+
<div class="floating-filter-container" *ngIf="isFloatingFilterEnabled(col)">
|
|
219
254
|
<input #filterInput
|
|
220
255
|
class="floating-filter-input"
|
|
221
256
|
[type]="getFilterInputType(col)"
|
|
222
257
|
[value]="getFloatingFilterValue(col)"
|
|
223
258
|
(input)="onFloatingFilterInput($event, col)"
|
|
224
259
|
[placeholder]="'Filter...'" />
|
|
225
|
-
<span class="floating-filter-clear"
|
|
260
|
+
<span class="floating-filter-clear"
|
|
226
261
|
*ngIf="hasFilterValue(col, filterInput)"
|
|
227
262
|
(click)="clearFloatingFilter(col, filterInput)">✕</span>
|
|
228
|
-
</
|
|
263
|
+
</div>
|
|
229
264
|
</div>
|
|
230
|
-
</
|
|
231
|
-
</div>
|
|
232
|
-
</div>
|
|
233
|
-
</div>
|
|
234
|
-
|
|
235
|
-
<!-- Set Filter Popup -->
|
|
236
|
-
<div *ngIf="activeSetFilter"
|
|
237
|
-
class="set-filter-popup"
|
|
238
|
-
[style.left.px]="setFilterPosition.x"
|
|
239
|
-
[style.top.px]="setFilterPosition.y"
|
|
240
|
-
(clickOutside)="closeSetFilter()"
|
|
241
|
-
clickOutside>
|
|
242
|
-
<argent-set-filter
|
|
243
|
-
[values]="setFilterValues"
|
|
244
|
-
[valueFormatter]="setFilterValueFormatter"
|
|
245
|
-
(filterChanged)="onSetFilterChanged($event)">
|
|
246
|
-
</argent-set-filter>
|
|
247
|
-
</div>
|
|
248
|
-
|
|
249
|
-
<!-- Text/Number Filter Popup -->
|
|
250
|
-
<div *ngIf="activeFilterPopup"
|
|
251
|
-
class="filter-popup"
|
|
252
|
-
[style.left.px]="filterPopupPosition.x"
|
|
253
|
-
[style.top.px]="filterPopupPosition.y"
|
|
254
|
-
(clickOutside)="closeFilterPopup()"
|
|
255
|
-
clickOutside>
|
|
256
|
-
<div class="filter-popup-header">
|
|
257
|
-
<span>Filter {{ getHeaderName(activeFilterPopupColumn!) }}</span>
|
|
258
|
-
<span class="filter-popup-close" (click)="closeFilterPopup()">✕</span>
|
|
259
|
-
</div>
|
|
260
|
-
<div class="filter-popup-body">
|
|
261
|
-
<!-- Operator Select -->
|
|
262
|
-
<div class="filter-popup-row">
|
|
263
|
-
<select class="filter-popup-select"
|
|
264
|
-
[value]="activeFilterOperator"
|
|
265
|
-
(change)="onFilterPopupOperatorChange($any($event.target).value)">
|
|
266
|
-
<ng-container *ngIf="activeFilterPopupType === 'text'">
|
|
267
|
-
<option *ngFor="let op of textFilterOperators" [value]="op.value">{{ op.label }}</option>
|
|
268
|
-
</ng-container>
|
|
269
|
-
<ng-container *ngIf="activeFilterPopupType === 'number'">
|
|
270
|
-
<option *ngFor="let op of numberFilterOperators" [value]="op.value">{{ op.label }}</option>
|
|
271
|
-
</ng-container>
|
|
272
|
-
</select>
|
|
265
|
+
</ng-container>
|
|
273
266
|
</div>
|
|
274
267
|
|
|
275
|
-
<!--
|
|
276
|
-
<
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
[type]="activeFilterPopupType === 'number' ? 'number' : 'text'"
|
|
280
|
-
class="filter-popup-input"
|
|
281
|
-
[value]="filterValue1"
|
|
282
|
-
(input)="onFilterPopupInput($event)"
|
|
283
|
-
(keydown.enter)="closeFilterPopup()"
|
|
284
|
-
[placeholder]="activeFilterOperator === 'inRange' ? 'From...' : 'Filter value...'"
|
|
285
|
-
autofocus />
|
|
286
|
-
</div>
|
|
287
|
-
|
|
288
|
-
<div class="filter-popup-row" *ngIf="activeFilterOperator === 'inRange'">
|
|
289
|
-
<input type="number"
|
|
290
|
-
class="filter-popup-input"
|
|
291
|
-
[value]="filterValue2"
|
|
292
|
-
(input)="onFilterPopupInput($event, true)"
|
|
293
|
-
(keydown.enter)="closeFilterPopup()"
|
|
294
|
-
[placeholder]="'To...'" />
|
|
295
|
-
</div>
|
|
296
|
-
</ng-container>
|
|
297
|
-
|
|
298
|
-
<div class="filter-popup-footer">
|
|
299
|
-
<button class="filter-popup-btn clear-btn" (click)="clearColumnFilter(activeFilterPopupColumn!)">Clear</button>
|
|
300
|
-
<button class="filter-popup-btn apply-btn" (click)="closeFilterPopup()">Apply</button>
|
|
268
|
+
<!-- Vertical Scrollbar Spacer -->
|
|
269
|
+
<div class="argent-grid-header-scrollbar-spacer"
|
|
270
|
+
*ngIf="scrollbarWidth > 0"
|
|
271
|
+
[style.width.px]="scrollbarWidth">
|
|
301
272
|
</div>
|
|
302
273
|
</div>
|
|
303
274
|
</div>
|
|
304
275
|
|
|
305
|
-
<!-- Canvas Layer for Data Viewport
|
|
276
|
+
<!-- Canvas Layer for Data Viewport -->
|
|
306
277
|
<div class="argent-grid-viewport" #viewport>
|
|
307
|
-
<!-- Spacer to create scrollbars for virtual scrolling -->
|
|
308
278
|
<div class="argent-grid-scroll-spacer" [style.height.px]="totalHeight" [style.width.px]="totalWidth"></div>
|
|
309
|
-
|
|
310
|
-
|
|
279
|
+
<canvas #gridCanvas class="argent-grid-canvas"
|
|
280
|
+
(contextmenu)="onCanvasContextMenu($event)"
|
|
281
|
+
(mousemove)="onCanvasMouseMove($event)"
|
|
282
|
+
(mouseleave)="onCanvasMouseLeave()"></canvas>
|
|
311
283
|
|
|
312
284
|
<!-- Cell Editor Overlay -->
|
|
313
285
|
<div class="argent-grid-cell-editor"
|
|
@@ -329,48 +301,29 @@
|
|
|
329
301
|
</div>
|
|
330
302
|
</div>
|
|
331
303
|
|
|
332
|
-
<!-- Side Bar
|
|
304
|
+
<!-- Side Bar -->
|
|
333
305
|
<div class="argent-grid-side-bar" *ngIf="sideBarVisible" [class.has-active-panel]="!!activeToolPanel">
|
|
334
306
|
<div class="side-bar-buttons">
|
|
335
307
|
<div class="side-bar-button" [class.active]="activeToolPanel === 'columns'" (click)="toggleToolPanel('columns')">
|
|
336
308
|
Columns
|
|
337
309
|
</div>
|
|
338
|
-
|
|
310
|
+
<!-- Hide Filters tool panel for now as it is not functional yet -->
|
|
311
|
+
<!-- <div class="side-bar-button" [class.active]="activeToolPanel === 'filters'" (click)="toggleToolPanel('filters')">
|
|
339
312
|
Filters
|
|
340
|
-
</div>
|
|
313
|
+
</div> -->
|
|
341
314
|
</div>
|
|
342
315
|
|
|
343
316
|
<div class="tool-panel-content" *ngIf="activeToolPanel">
|
|
344
|
-
<!-- Columns Tool Panel -->
|
|
345
317
|
<div class="columns-tool-panel" *ngIf="activeToolPanel === 'columns'">
|
|
346
318
|
<h3>Columns</h3>
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
(cdkDropListDropped)="onSidebarColumnDropped($event)">
|
|
350
|
-
<div *ngFor="let col of getAllColumns()"
|
|
351
|
-
class="column-item"
|
|
352
|
-
cdkDrag
|
|
353
|
-
[cdkDragData]="col">
|
|
354
|
-
<div *cdkDragPreview class="sidebar-drag-preview">
|
|
355
|
-
<span class="column-drag-handle">⠿</span>
|
|
356
|
-
<span>{{ getHeaderName(col) }}</span>
|
|
357
|
-
</div>
|
|
358
|
-
<div *cdkDragPlaceholder class="sidebar-drag-placeholder"></div>
|
|
359
|
-
|
|
319
|
+
<div class="column-list" cdkDropList (cdkDropListDropped)="onSidebarColumnDropped($event)">
|
|
320
|
+
<div *ngFor="let col of getAllColumns()" class="column-item" cdkDrag [cdkDragData]="col">
|
|
360
321
|
<span class="column-drag-handle" cdkDragHandle>⠿</span>
|
|
361
322
|
<input type="checkbox" [checked]="col.visible" (change)="toggleColumnVisibility(col)" />
|
|
362
323
|
<span class="column-label">{{ getHeaderName(col) }}</span>
|
|
363
324
|
</div>
|
|
364
325
|
</div>
|
|
365
326
|
</div>
|
|
366
|
-
|
|
367
|
-
<!-- Filters Tool Panel -->
|
|
368
|
-
<div class="filters-tool-panel" *ngIf="activeToolPanel === 'filters'">
|
|
369
|
-
<h3>Filters</h3>
|
|
370
|
-
<div class="filter-placeholder">
|
|
371
|
-
Filters coming soon...
|
|
372
|
-
</div>
|
|
373
|
-
</div>
|
|
374
327
|
</div>
|
|
375
328
|
</div>
|
|
376
329
|
</div>
|
|
@@ -380,63 +333,76 @@
|
|
|
380
333
|
<ng-content select="[overlay]"></ng-content>
|
|
381
334
|
</div>
|
|
382
335
|
|
|
383
|
-
<!--
|
|
384
|
-
<div class="argent-grid-header-menu"
|
|
385
|
-
*ngIf="activeHeaderMenu"
|
|
386
|
-
[style.top.px]="headerMenuPosition.y"
|
|
387
|
-
[style.left.px]="headerMenuPosition.x"
|
|
388
|
-
(click)="$event.stopPropagation()">
|
|
336
|
+
<!-- Menus and Popups -->
|
|
337
|
+
<div class="argent-grid-header-menu" *ngIf="activeHeaderMenu" [style.top.px]="headerMenuPosition.y" [style.left.px]="headerMenuPosition.x" (click)="$event.stopPropagation()">
|
|
389
338
|
<ng-container *ngFor="let item of headerMenuItems">
|
|
390
339
|
<div *ngIf="item.separator" class="menu-divider"></div>
|
|
391
|
-
<div *ngIf="!item.separator"
|
|
392
|
-
class="menu-item"
|
|
393
|
-
[class.disabled]="item.disabled"
|
|
394
|
-
[class.has-submenu]="item.subMenu && item.subMenu.length > 0"
|
|
395
|
-
(click)="!item.disabled && item.action(); !item.subMenu && closeHeaderMenu()">
|
|
340
|
+
<div *ngIf="!item.separator" class="menu-item" (click)="!item.disabled && item.action(); !item.subMenu && closeHeaderMenu()">
|
|
396
341
|
<span class="menu-icon" *ngIf="item.icon">{{ item.icon }}</span>
|
|
397
342
|
<span class="menu-text">{{ item.name }}</span>
|
|
398
|
-
<span class="menu-arrow" *ngIf="item.subMenu && item.subMenu.length > 0">▶</span>
|
|
399
|
-
|
|
400
|
-
<!-- Sub-menu -->
|
|
401
|
-
<div class="argent-grid-header-menu sub-menu" *ngIf="item.subMenu && item.subMenu.length > 0">
|
|
402
|
-
<div *ngFor="let subItem of item.subMenu"
|
|
403
|
-
class="menu-item"
|
|
404
|
-
(click)="subItem.action(); closeHeaderMenu(); $event.stopPropagation()">
|
|
405
|
-
<span class="menu-icon" *ngIf="subItem.icon">{{ subItem.icon }}</span>
|
|
406
|
-
<span class="menu-text">{{ subItem.name }}</span>
|
|
407
|
-
</div>
|
|
408
|
-
</div>
|
|
409
343
|
</div>
|
|
410
344
|
</ng-container>
|
|
411
345
|
</div>
|
|
412
346
|
|
|
413
|
-
<!--
|
|
414
|
-
<div class="
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
347
|
+
<!-- Set Filter Popup -->
|
|
348
|
+
<div *ngIf="activeSetFilter" class="set-filter-popup" [style.left.px]="setFilterPosition.x" [style.top.px]="setFilterPosition.y" (clickOutside)="closeSetFilter()" clickOutside>
|
|
349
|
+
<argent-set-filter [values]="setFilterValues" [initialSelectedValues]="setFilterSelectedValues" [valueFormatter]="setFilterValueFormatter" (filterChanged)="onSetFilterChanged($event)"></argent-set-filter>
|
|
350
|
+
</div>
|
|
351
|
+
|
|
352
|
+
<!-- Context Menu -->
|
|
353
|
+
<div class="context-menu-popup" *ngIf="activeContextMenu" [style.top.px]="contextMenuPosition.y" [style.left.px]="contextMenuPosition.x" (click)="$event.stopPropagation()">
|
|
419
354
|
<ng-container *ngFor="let item of contextMenuItems">
|
|
420
355
|
<div *ngIf="item.separator" class="menu-divider"></div>
|
|
421
|
-
<div *ngIf="!item.separator"
|
|
422
|
-
|
|
423
|
-
[class.disabled]="item.disabled"
|
|
424
|
-
[class.has-submenu]="item.subMenu && item.subMenu.length > 0"
|
|
425
|
-
(click)="!item.disabled && item.action(); !item.subMenu && closeContextMenu()">
|
|
356
|
+
<div *ngIf="!item.separator" class="menu-item" [class.disabled]="item.disabled" [class.has-submenu]="item.subMenu"
|
|
357
|
+
(click)="!item.disabled && !item.subMenu && item.action(); !item.subMenu && closeContextMenu()">
|
|
426
358
|
<span class="menu-icon" *ngIf="item.icon">{{ item.icon }}</span>
|
|
427
359
|
<span class="menu-text">{{ item.name }}</span>
|
|
428
|
-
<span class="menu-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
(click)="subItem.action(); closeContextMenu(); $event.stopPropagation()">
|
|
435
|
-
<span class="menu-icon" *ngIf="subItem.icon">{{ subItem.icon }}</span>
|
|
436
|
-
<span class="menu-text">{{ subItem.name }}</span>
|
|
360
|
+
<span class="menu-chevron" *ngIf="item.subMenu">▶</span>
|
|
361
|
+
<div class="sub-menu" *ngIf="item.subMenu">
|
|
362
|
+
<div *ngFor="let sub of item.subMenu" class="menu-item"
|
|
363
|
+
(click)="!sub.disabled && sub.action(); closeContextMenu(); $event.stopPropagation()">
|
|
364
|
+
<span class="menu-icon" *ngIf="sub.icon">{{ sub.icon }}</span>
|
|
365
|
+
<span class="menu-text">{{ sub.name }}</span>
|
|
437
366
|
</div>
|
|
438
367
|
</div>
|
|
439
368
|
</div>
|
|
440
369
|
</ng-container>
|
|
441
370
|
</div>
|
|
371
|
+
|
|
372
|
+
<!-- Tooltip -->
|
|
373
|
+
<div class="ag-tooltip" *ngIf="tooltipVisible"
|
|
374
|
+
[style.left.px]="tooltipPosition.x"
|
|
375
|
+
[style.top.px]="tooltipPosition.y">{{ tooltipText }}</div>
|
|
376
|
+
|
|
377
|
+
<!-- Filter Popup -->
|
|
378
|
+
<div *ngIf="activeFilterPopup" class="filter-popup" [style.left.px]="filterPopupPosition.x" [style.top.px]="filterPopupPosition.y" (clickOutside)="closeFilterPopup()" clickOutside (click)="$event.stopPropagation()">
|
|
379
|
+
<div class="filter-popup-content">
|
|
380
|
+
<div class="filter-popup-header">
|
|
381
|
+
Filter {{ getHeaderName(activeFilterPopupColumn!) }}
|
|
382
|
+
</div>
|
|
383
|
+
<select class="filter-operator-select" [value]="activeFilterOperator" (change)="onFilterPopupOperatorChange($any($event.target).value)">
|
|
384
|
+
<option *ngFor="let op of (activeFilterPopupType === 'number' ? numberFilterOperators : textFilterOperators)" [value]="op.value">{{ op.label }}</option>
|
|
385
|
+
</select>
|
|
386
|
+
|
|
387
|
+
<div class="filter-input-container">
|
|
388
|
+
<input class="filter-input"
|
|
389
|
+
[type]="activeFilterPopupType === 'number' ? 'number' : 'text'"
|
|
390
|
+
[value]="filterValue1"
|
|
391
|
+
(input)="onFilterPopupInput($event, false)"
|
|
392
|
+
placeholder="Filter..." />
|
|
393
|
+
</div>
|
|
394
|
+
|
|
395
|
+
<div class="filter-input-container" *ngIf="activeFilterOperator === 'inRange'">
|
|
396
|
+
<input class="filter-input"
|
|
397
|
+
[type]="activeFilterPopupType === 'number' ? 'number' : 'text'"
|
|
398
|
+
[value]="filterValue2"
|
|
399
|
+
(input)="onFilterPopupInput($event, true)"
|
|
400
|
+
placeholder="to..." />
|
|
401
|
+
</div>
|
|
402
|
+
|
|
403
|
+
<div class="filter-popup-footer">
|
|
404
|
+
<button class="filter-clear-btn" (click)="clearColumnFilter(activeFilterPopupColumn!)">Clear Filter</button>
|
|
405
|
+
</div>
|
|
406
|
+
</div>
|
|
407
|
+
</div>
|
|
442
408
|
</div>
|