ag-grid-url-sync 0.2.1 → 0.2.2
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/LICENSE +7 -0
- package/README.md +113 -94
- package/dist/core/grid-integration.d.ts +5 -0
- package/dist/core/grid-integration.js +114 -24
- package/dist/core/grid-integration.js.map +1 -1
- package/dist/core/types.d.ts +51 -56
- package/dist/core/types.js +83 -45
- package/dist/core/types.js.map +1 -1
- package/dist/core/url-generator.js +57 -11
- package/dist/core/url-generator.js.map +1 -1
- package/dist/core/url-parser.js +86 -7
- package/dist/core/url-parser.js.map +1 -1
- package/dist/core/validation.d.ts +30 -1
- package/dist/core/validation.js +60 -1
- package/dist/core/validation.js.map +1 -1
- package/package.json +4 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright 2025 NearForm
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
# AG Grid URL Sync
|
|
4
4
|
|
|
5
|
-
A lightweight TypeScript library for synchronizing AG Grid text filters with URL parameters, enabling shareable filter states through clean, human-readable URLs.
|
|
5
|
+
A lightweight TypeScript library for synchronizing AG Grid text and number filters with URL parameters, enabling shareable filter states through clean, human-readable URLs.
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
9
|
- 🔍 **Complete text filter support** - All 8 AG Grid text operations (contains, equals, not contains, not equal, starts with, ends with, blank, not blank)
|
|
10
|
+
- 🔢 **Complete number filter support** - All 9 AG Grid number operations (equals, not equal, greater than, greater than or equal, less than, less than or equal, in range, blank, not blank)
|
|
10
11
|
- 🔗 Manual URL generation for sharing filter states
|
|
11
12
|
- ↔️ Bidirectional sync between grid and URL
|
|
12
13
|
- 🛠️ Framework agnostic - works with any AG Grid setup
|
|
@@ -21,7 +22,9 @@ A lightweight TypeScript library for synchronizing AG Grid text filters with URL
|
|
|
21
22
|
|
|
22
23
|
## Supported Filter Types
|
|
23
24
|
|
|
24
|
-
Supports **all AG Grid text filter operations** (
|
|
25
|
+
Supports **all AG Grid text and number filter operations** (17 total) with clean, human-readable URL parameters:
|
|
26
|
+
|
|
27
|
+
### Text Filters (8 operations)
|
|
25
28
|
|
|
26
29
|
| Filter Type | Operation | URL Format | Example | Description |
|
|
27
30
|
| ----------- | ------------ | ---------------------------- | -------------------------- | --------------------------- |
|
|
@@ -34,41 +37,76 @@ Supports **all AG Grid text filter operations** (8 total) with clean, human-read
|
|
|
34
37
|
| **Text** | Blank | `f_column_blank=true` | `f_optional_blank=true` | Field is empty/null |
|
|
35
38
|
| **Text** | Not Blank | `f_column_notBlank=true` | `f_required_notBlank=true` | Field has any value |
|
|
36
39
|
|
|
40
|
+
### Number Filters (9 operations)
|
|
41
|
+
|
|
42
|
+
| Filter Type | Operation | URL Format | Example | Description |
|
|
43
|
+
| ----------- | --------------------- | ------------------------ | ------------------------ | ----------------------------- |
|
|
44
|
+
| **Number** | Equals | `f_column_eq=value` | `f_age_eq=30` | Number equals value exactly |
|
|
45
|
+
| **Number** | Not Equal | `f_column_neq=value` | `f_salary_neq=50000` | Number does not equal value |
|
|
46
|
+
| **Number** | Greater Than | `f_column_gt=value` | `f_experience_gt=5` | Number is greater than value |
|
|
47
|
+
| **Number** | Greater Than or Equal | `f_column_gte=value` | `f_score_gte=85` | Number is ≥ value |
|
|
48
|
+
| **Number** | Less Than | `f_column_lt=value` | `f_budget_lt=10000` | Number is less than value |
|
|
49
|
+
| **Number** | Less Than or Equal | `f_column_lte=value` | `f_hours_lte=40` | Number is ≤ value |
|
|
50
|
+
| **Number** | In Range | `f_column_range=min,max` | `f_age_range=25,45` | Number is between min and max |
|
|
51
|
+
| **Number** | Blank | `f_column_blank=true` | `f_bonus_blank=true` | Field is empty/null |
|
|
52
|
+
| **Number** | Not Blank | `f_column_notBlank=true` | `f_salary_notBlank=true` | Field has any numeric value |
|
|
53
|
+
|
|
37
54
|
> **💡 Naming Convention Note**: URL parameters use short, clean names for better readability (`eq` for equals, `neq` for not equal). These are automatically converted to the proper AG Grid operation names (`equals`, `notEqual`) internally. This design keeps URLs concise while maintaining full compatibility with AG Grid's filter API.
|
|
38
55
|
|
|
39
56
|
### Filter Detection
|
|
40
57
|
|
|
41
58
|
The library automatically works with:
|
|
42
59
|
|
|
43
|
-
-
|
|
60
|
+
- **Text columns** configured with `filter: 'agTextColumnFilter'`
|
|
61
|
+
- **Number columns** configured with `filter: 'agNumberColumnFilter'`
|
|
62
|
+
- **Auto-detection** based on `cellDataType: 'number'` configuration
|
|
44
63
|
- Columns with `filter: true` (AG Grid's default text filter)
|
|
45
|
-
- Any column where users apply text-based filters
|
|
46
|
-
- All AG Grid text filter operations through the filter menu
|
|
64
|
+
- Any column where users apply text or number-based filters
|
|
65
|
+
- All AG Grid text and number filter operations through the filter menu
|
|
66
|
+
- **Mixed filter types** - combine text and number filters in the same URL
|
|
47
67
|
|
|
48
68
|
### URL Examples
|
|
49
69
|
|
|
50
|
-
**Simple filter:**
|
|
70
|
+
**Simple text filter:**
|
|
51
71
|
|
|
52
72
|
```
|
|
53
73
|
https://app.com/data?f_name_contains=john
|
|
54
74
|
```
|
|
55
75
|
|
|
56
|
-
**
|
|
76
|
+
**Simple number filter:**
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
https://app.com/data?f_salary_gt=75000
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Mixed text and number filters:**
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
https://app.com/data?f_name_contains=john&f_department_eq=Engineering&f_salary_gte=80000&f_age_range=25,45
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**Complex filtering with range operations:**
|
|
57
89
|
|
|
58
90
|
```
|
|
59
|
-
https://app.com/data?f_name_contains=
|
|
91
|
+
https://app.com/data?f_name_contains=manager&f_salary_range=60000,100000&f_experience_gte=5&f_status_eq=active
|
|
60
92
|
```
|
|
61
93
|
|
|
62
|
-
**
|
|
94
|
+
**All text operations:**
|
|
63
95
|
|
|
64
96
|
```
|
|
65
97
|
https://app.com/data?f_name_contains=john&f_email_startsWith=admin&f_status_neq=inactive&f_description_endsWith=test&f_optional_blank=true&f_required_notBlank=true&f_tags_notContains=spam&f_title_eq=manager
|
|
66
98
|
```
|
|
67
99
|
|
|
68
|
-
**
|
|
100
|
+
**All number operations:**
|
|
69
101
|
|
|
70
102
|
```
|
|
71
|
-
https://app.com/data?
|
|
103
|
+
https://app.com/data?f_age_eq=30&f_salary_neq=50000&f_experience_gt=5&f_score_gte=85&f_budget_lt=10000&f_hours_lte=40&f_age_range=25,45&f_bonus_blank=true&f_salary_notBlank=true
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**Blank operations (both text and number):**
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
https://app.com/data?f_comments_blank=true&f_bonus_blank=true&f_name_notBlank=true&f_salary_notBlank=true
|
|
72
110
|
```
|
|
73
111
|
|
|
74
112
|
## Installation
|
|
@@ -177,13 +215,23 @@ import { createUrlSync } from 'ag-grid-url-sync'
|
|
|
177
215
|
// Initialize with AG Grid API
|
|
178
216
|
const urlSync = createUrlSync(gridApi)
|
|
179
217
|
|
|
180
|
-
// Generate shareable URL with current filters
|
|
218
|
+
// Generate shareable URL with current filters (text and number)
|
|
181
219
|
const shareableUrl = urlSync.generateUrl()
|
|
220
|
+
// Result: https://app.com/data?f_name_contains=john&f_salary_gte=80000&f_age_range=25,45
|
|
182
221
|
|
|
183
|
-
// Apply filters from URL
|
|
184
|
-
urlSync.applyFromUrl(
|
|
222
|
+
// Apply filters from URL (automatically detects text vs number columns)
|
|
223
|
+
urlSync.applyFromUrl(
|
|
224
|
+
'https://app.com/data?f_name_contains=manager&f_salary_gt=75000'
|
|
225
|
+
)
|
|
185
226
|
|
|
186
|
-
//
|
|
227
|
+
// Apply specific filter programmatically
|
|
228
|
+
urlSync.applyFilters({
|
|
229
|
+
name: { filterType: 'text', type: 'contains', filter: 'john' },
|
|
230
|
+
salary: { filterType: 'number', type: 'greaterThan', filter: 75000 },
|
|
231
|
+
age: { filterType: 'number', type: 'inRange', filter: 25, filterTo: 45 }
|
|
232
|
+
})
|
|
233
|
+
|
|
234
|
+
// Clear all text and number filters
|
|
187
235
|
urlSync.clearFilters()
|
|
188
236
|
```
|
|
189
237
|
|
|
@@ -241,10 +289,32 @@ function GridComponent() {
|
|
|
241
289
|
<AgGridReact
|
|
242
290
|
onGridReady={params => setGridApi(params.api)}
|
|
243
291
|
rowData={rowData}
|
|
244
|
-
columnDefs={
|
|
292
|
+
columnDefs={[
|
|
293
|
+
{
|
|
294
|
+
field: 'name',
|
|
295
|
+
filter: 'agTextColumnFilter',
|
|
296
|
+
floatingFilter: true
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
field: 'email',
|
|
300
|
+
filter: 'agTextColumnFilter',
|
|
301
|
+
floatingFilter: true
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
field: 'salary',
|
|
305
|
+
filter: 'agNumberColumnFilter',
|
|
306
|
+
floatingFilter: true
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
field: 'age',
|
|
310
|
+
filter: 'agNumberColumnFilter',
|
|
311
|
+
floatingFilter: true
|
|
312
|
+
}
|
|
313
|
+
]}
|
|
245
314
|
defaultColDef={{
|
|
246
|
-
|
|
247
|
-
|
|
315
|
+
flex: 1,
|
|
316
|
+
sortable: true,
|
|
317
|
+
resizable: true
|
|
248
318
|
}}
|
|
249
319
|
/>
|
|
250
320
|
</div>
|
|
@@ -253,65 +323,6 @@ function GridComponent() {
|
|
|
253
323
|
}
|
|
254
324
|
```
|
|
255
325
|
|
|
256
|
-
### React Router Integration
|
|
257
|
-
|
|
258
|
-
For single-page applications using React Router, you can sync filters with the browser URL:
|
|
259
|
-
|
|
260
|
-
```tsx
|
|
261
|
-
import React, { useState } from 'react'
|
|
262
|
-
import { useNavigate, useLocation } from 'react-router-dom'
|
|
263
|
-
import { useAGGridUrlSync } from 'ag-grid-url-sync/react'
|
|
264
|
-
|
|
265
|
-
function RouterGridComponent() {
|
|
266
|
-
const [gridApi, setGridApi] = useState(null)
|
|
267
|
-
const navigate = useNavigate()
|
|
268
|
-
const location = useLocation()
|
|
269
|
-
|
|
270
|
-
const { shareUrl, clearFilters, hasFilters, isReady } = useAGGridUrlSync(
|
|
271
|
-
gridApi,
|
|
272
|
-
{
|
|
273
|
-
autoApplyOnMount: true, // Automatically apply filters from URL on mount
|
|
274
|
-
paramPrefix: 'f_'
|
|
275
|
-
}
|
|
276
|
-
)
|
|
277
|
-
|
|
278
|
-
// Update browser URL with current filters
|
|
279
|
-
const updateUrlWithFilters = () => {
|
|
280
|
-
const url = shareUrl()
|
|
281
|
-
const urlParams = new URL(url).searchParams
|
|
282
|
-
const currentParams = new URLSearchParams(location.search)
|
|
283
|
-
|
|
284
|
-
// Clear existing filter params
|
|
285
|
-
for (const [key] of currentParams) {
|
|
286
|
-
if (key.startsWith('f_')) {
|
|
287
|
-
currentParams.delete(key)
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
// Add current filter params
|
|
292
|
-
for (const [key, value] of urlParams) {
|
|
293
|
-
currentParams.set(key, value)
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
navigate(`${location.pathname}?${currentParams.toString()}`, {
|
|
297
|
-
replace: true
|
|
298
|
-
})
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
return (
|
|
302
|
-
<div>
|
|
303
|
-
<button onClick={updateUrlWithFilters} disabled={!isReady}>
|
|
304
|
-
Update URL with Filters
|
|
305
|
-
</button>
|
|
306
|
-
<button onClick={clearFilters} disabled={!hasFilters}>
|
|
307
|
-
Clear All Filters
|
|
308
|
-
</button>
|
|
309
|
-
{/* Grid component */}
|
|
310
|
-
</div>
|
|
311
|
-
)
|
|
312
|
-
}
|
|
313
|
-
```
|
|
314
|
-
|
|
315
326
|
### React Hook API
|
|
316
327
|
|
|
317
328
|
#### `useAGGridUrlSync(gridApi, options?)`
|
|
@@ -449,16 +460,20 @@ The library generates clean, human-readable URLs:
|
|
|
449
460
|
|
|
450
461
|
```
|
|
451
462
|
Base URL: https://app.com/page
|
|
452
|
-
With filters: https://app.com/page?f_name_contains=john&f_status_eq=active
|
|
463
|
+
With text filters: https://app.com/page?f_name_contains=john&f_status_eq=active
|
|
464
|
+
With number filters: https://app.com/page?f_salary_gte=75000&f_age_range=25,45
|
|
465
|
+
Mixed filters: https://app.com/page?f_name_contains=john&f_salary_gte=75000&f_age_lt=50
|
|
453
466
|
```
|
|
454
467
|
|
|
455
468
|
Parameter structure:
|
|
456
469
|
|
|
457
470
|
- Prefix: `f_` (configurable - useful for multi-grid scenarios)
|
|
458
471
|
- Format: `f_{columnName}_{operation}={value}`
|
|
459
|
-
- Operations
|
|
472
|
+
- **Text Operations**: `contains`, `eq`, `neq`, `startsWith`, `endsWith`, `notContains`, `blank`, `notBlank`
|
|
473
|
+
- **Number Operations**: `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `range`, `blank`, `notBlank`
|
|
474
|
+
- **Range Format**: `f_column_range=min,max` (comma-separated values)
|
|
460
475
|
- Standard URL encoding for special characters
|
|
461
|
-
- Supports column names with underscores (e.g., `user_id`, `created_date`)
|
|
476
|
+
- Supports column names with underscores (e.g., `user_id`, `salary_base`, `created_date`)
|
|
462
477
|
|
|
463
478
|
## API Reference
|
|
464
479
|
|
|
@@ -568,32 +583,36 @@ Check out the [examples](./examples) directory for comprehensive working demos:
|
|
|
568
583
|
Comprehensive demonstration showcasing all features:
|
|
569
584
|
|
|
570
585
|
- **Complete text filter support** - All 8 AG Grid text operations (contains, equals, not contains, not equal, starts with, ends with, blank, not blank)
|
|
571
|
-
- **
|
|
572
|
-
- **
|
|
586
|
+
- **Complete number filter support** - All 9 AG Grid number operations (equals, not equal, greater than, greater than or equal, less than, less than or equal, in range, blank, not blank)
|
|
587
|
+
- **Mixed filter scenarios** - Text and number filters working together (Sales team + salary filters, Engineering + experience, Executive view with high salaries)
|
|
588
|
+
- **Number operation demos** - Dedicated buttons for salary ranges, age filtering, experience thresholds, and blank number fields
|
|
573
589
|
- **URL sharing workflow** - Copy to clipboard, email, and Slack integration
|
|
574
|
-
- **Performance monitoring** - Real-time benchmarks and stress testing
|
|
575
|
-
- **Error handling** - Malformed URL and invalid filter testing
|
|
576
|
-
- **Complete API showcase** - Generate URLs, apply filters, clear filters
|
|
590
|
+
- **Performance monitoring** - Real-time benchmarks and stress testing with mixed filter types
|
|
591
|
+
- **Error handling** - Malformed URL and invalid filter testing for both text and numbers
|
|
592
|
+
- **Complete API showcase** - Generate URLs, apply filters, clear filters with comprehensive examples
|
|
577
593
|
|
|
578
594
|
### ⚛️ [React Integration](./examples/react-basic/basic-grid.tsx)
|
|
579
595
|
|
|
580
596
|
Clean React component showing the `useAGGridUrlSync` hook:
|
|
581
597
|
|
|
582
|
-
- React hook integration with AG Grid
|
|
583
|
-
- Automatic filter state management
|
|
598
|
+
- React hook integration with AG Grid for text and number filters
|
|
599
|
+
- Automatic filter state management for mixed filter types
|
|
584
600
|
- Share button with clipboard functionality
|
|
585
601
|
- Filter status indicators and controls
|
|
586
|
-
- Auto-apply filters on component mount
|
|
587
|
-
-
|
|
602
|
+
- Auto-apply filters on component mount with both text and number support
|
|
603
|
+
- Enhanced employee data with salary, age, and experience columns
|
|
604
|
+
- Full TypeScript support with comprehensive type coverage
|
|
588
605
|
|
|
589
606
|
### 📊 [Shared Data](./examples/shared-data.js)
|
|
590
607
|
|
|
591
608
|
Common data and column definitions used across examples:
|
|
592
609
|
|
|
593
|
-
-
|
|
594
|
-
- Project data with
|
|
595
|
-
- Column definitions with complete text filter support
|
|
596
|
-
- All 8 text filter operations
|
|
610
|
+
- Enhanced employee data with salary, age, and experience number fields
|
|
611
|
+
- Project data with budget and numeric fields for comprehensive testing
|
|
612
|
+
- Column definitions with complete text and number filter support
|
|
613
|
+
- All 8 text filter operations and 9 number filter operations enabled
|
|
614
|
+
- Realistic data ranges for demonstrating number filters (salaries $58K-$95K, ages 26-42, experience 3-15 years)
|
|
615
|
+
- Includes null values for demonstrating blank/notBlank operations
|
|
597
616
|
|
|
598
617
|
All examples work out-of-the-box and demonstrate the complete functionality. The HTML demo can be opened directly in your browser, while the React example shows clean integration patterns.
|
|
599
618
|
|
|
@@ -607,6 +626,6 @@ All examples work out-of-the-box and demonstrate the complete functionality. The
|
|
|
607
626
|
|
|
608
627
|
## License
|
|
609
628
|
|
|
610
|
-
This project is licensed under the
|
|
629
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
611
630
|
|
|
612
631
|
[](https://www.nearform.com/contact/?utm_source=open-source&utm_medium=banner&utm_campaign=os-project-pages)
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import type { FilterState, InternalConfig } from './types.js';
|
|
2
|
+
import type { GridApi } from 'ag-grid-community';
|
|
3
|
+
/**
|
|
4
|
+
* Detects the expected filter type for a column based on AG Grid configuration
|
|
5
|
+
*/
|
|
6
|
+
export declare function detectColumnFilterType(gridApi: GridApi, columnId: string): 'text' | 'number' | null;
|
|
2
7
|
/**
|
|
3
8
|
* Gets the current filter model from AG Grid
|
|
4
9
|
*/
|
|
@@ -1,4 +1,42 @@
|
|
|
1
|
-
import { AG_GRID_OPERATION_NAMES, REVERSE_AG_GRID_OPERATION_NAMES } from './types.js';
|
|
1
|
+
import { AG_GRID_OPERATION_NAMES, REVERSE_AG_GRID_OPERATION_NAMES, TEXT_FILTER_OPERATIONS, NUMBER_FILTER_OPERATIONS } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Type predicate to check if an operation is a valid text filter operation
|
|
4
|
+
*/
|
|
5
|
+
function isTextFilterOperation(operation) {
|
|
6
|
+
return TEXT_FILTER_OPERATIONS.includes(operation);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Type predicate to check if an operation is a valid number filter operation
|
|
10
|
+
*/
|
|
11
|
+
function isNumberFilterOperation(operation) {
|
|
12
|
+
return NUMBER_FILTER_OPERATIONS.includes(operation);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Detects the expected filter type for a column based on AG Grid configuration
|
|
16
|
+
*/
|
|
17
|
+
export function detectColumnFilterType(gridApi, columnId) {
|
|
18
|
+
try {
|
|
19
|
+
const column = gridApi.getColumn(columnId);
|
|
20
|
+
if (!column)
|
|
21
|
+
return null;
|
|
22
|
+
const colDef = column.getColDef();
|
|
23
|
+
// 1. Explicit filter configuration takes priority
|
|
24
|
+
if (colDef.filter === 'agNumberColumnFilter')
|
|
25
|
+
return 'number';
|
|
26
|
+
if (colDef.filter === 'agTextColumnFilter')
|
|
27
|
+
return 'text';
|
|
28
|
+
// 2. Cell data type configuration
|
|
29
|
+
if (colDef.cellDataType === 'number')
|
|
30
|
+
return 'number';
|
|
31
|
+
if (colDef.cellDataType === 'text')
|
|
32
|
+
return 'text';
|
|
33
|
+
// 3. Default to text for backward compatibility
|
|
34
|
+
return 'text';
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return 'text'; // Safe fallback
|
|
38
|
+
}
|
|
39
|
+
}
|
|
2
40
|
/**
|
|
3
41
|
* Gets the current filter model from AG Grid
|
|
4
42
|
*/
|
|
@@ -12,17 +50,37 @@ export function getFilterModel(config) {
|
|
|
12
50
|
for (const [column, filter] of Object.entries(model)) {
|
|
13
51
|
if (!filter || typeof filter !== 'object')
|
|
14
52
|
continue;
|
|
15
|
-
const { filterType, type, filter: value } = filter;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
53
|
+
const { filterType, type, filter: value, filterTo } = filter;
|
|
54
|
+
// Handle both text and number filters
|
|
55
|
+
if (filterType === 'text') {
|
|
56
|
+
// Map AG Grid operations back to our internal operations using centralized mapping
|
|
57
|
+
const internalOperation = REVERSE_AG_GRID_OPERATION_NAMES[type];
|
|
58
|
+
// Use type predicate to validate and narrow the type
|
|
59
|
+
if (internalOperation && isTextFilterOperation(internalOperation)) {
|
|
60
|
+
filterState[column] = {
|
|
61
|
+
filterType: 'text',
|
|
62
|
+
type: internalOperation, // Now properly typed as TextFilterOperation
|
|
63
|
+
filter: value || ''
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else if (filterType === 'number') {
|
|
68
|
+
// Map AG Grid number operations back to our internal operations
|
|
69
|
+
const internalOperation = REVERSE_AG_GRID_OPERATION_NAMES[type];
|
|
70
|
+
// Use type predicate to validate and narrow the type
|
|
71
|
+
if (internalOperation && isNumberFilterOperation(internalOperation)) {
|
|
72
|
+
const numberFilter = {
|
|
73
|
+
filterType: 'number',
|
|
74
|
+
type: internalOperation, // Now properly typed as NumberFilterOperation
|
|
75
|
+
filter: typeof value === 'number' ? value : 0
|
|
76
|
+
};
|
|
77
|
+
// Handle range operations
|
|
78
|
+
if (internalOperation === 'inRange' && typeof filterTo === 'number') {
|
|
79
|
+
;
|
|
80
|
+
numberFilter.filterTo = filterTo;
|
|
81
|
+
}
|
|
82
|
+
filterState[column] = numberFilter;
|
|
83
|
+
}
|
|
26
84
|
}
|
|
27
85
|
}
|
|
28
86
|
return filterState;
|
|
@@ -34,6 +92,37 @@ export function getFilterModel(config) {
|
|
|
34
92
|
return {};
|
|
35
93
|
}
|
|
36
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Converts internal filter to AG Grid filter format
|
|
97
|
+
*/
|
|
98
|
+
function convertToAGGridFilter(filter) {
|
|
99
|
+
if (filter.filterType === 'number') {
|
|
100
|
+
const agGridOperation = AG_GRID_OPERATION_NAMES[filter.type];
|
|
101
|
+
if (filter.type === 'inRange') {
|
|
102
|
+
const baseFilter = {
|
|
103
|
+
filterType: 'number',
|
|
104
|
+
type: agGridOperation,
|
|
105
|
+
filter: filter.filter
|
|
106
|
+
};
|
|
107
|
+
// Only include filterTo if it's defined
|
|
108
|
+
return filter.filterTo !== undefined
|
|
109
|
+
? { ...baseFilter, filterTo: filter.filterTo }
|
|
110
|
+
: baseFilter;
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
filterType: 'number',
|
|
114
|
+
type: agGridOperation,
|
|
115
|
+
filter: filter.filter
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
// Text filter handling
|
|
119
|
+
const agGridOperation = AG_GRID_OPERATION_NAMES[filter.type];
|
|
120
|
+
return {
|
|
121
|
+
filterType: 'text',
|
|
122
|
+
type: agGridOperation,
|
|
123
|
+
filter: filter.filter
|
|
124
|
+
};
|
|
125
|
+
}
|
|
37
126
|
/**
|
|
38
127
|
* Applies a filter state to AG Grid
|
|
39
128
|
*/
|
|
@@ -41,18 +130,19 @@ export function applyFilterModel(filterState, config) {
|
|
|
41
130
|
try {
|
|
42
131
|
const model = {};
|
|
43
132
|
for (const [column, filter] of Object.entries(filterState)) {
|
|
44
|
-
if (filter
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
133
|
+
if (!filter || typeof filter !== 'object')
|
|
134
|
+
continue;
|
|
135
|
+
// Detect expected filter type for this column
|
|
136
|
+
const expectedType = detectColumnFilterType(config.gridApi, column);
|
|
137
|
+
// Validate filter type compatibility
|
|
138
|
+
if (filter.filterType === 'number' && expectedType !== 'number') {
|
|
139
|
+
console.warn(`Column '${column}' expects a text filter but received a number filter. This may indicate a configuration mismatch in the column definition or filter application.`);
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
// Convert to AG Grid filter model
|
|
143
|
+
const agGridFilter = convertToAGGridFilter(filter);
|
|
144
|
+
if (agGridFilter) {
|
|
145
|
+
model[column] = agGridFilter;
|
|
56
146
|
}
|
|
57
147
|
}
|
|
58
148
|
config.gridApi.setFilterModel(model);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grid-integration.js","sourceRoot":"","sources":["../../src/core/grid-integration.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"grid-integration.js","sourceRoot":"","sources":["../../src/core/grid-integration.ts"],"names":[],"mappings":"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"}
|
package/dist/core/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { GridApi as AGGridApi } from 'ag-grid-community';
|
|
1
|
+
import type { GridApi as AGGridApi, TextFilterModel, NumberFilterModel } from 'ag-grid-community';
|
|
2
2
|
/**
|
|
3
3
|
* Configuration options for AG Grid URL Sync
|
|
4
4
|
*/
|
|
@@ -17,17 +17,52 @@ export interface AGGridUrlSyncConfig {
|
|
|
17
17
|
onParseError?: (error: Error) => void;
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
|
-
* Supported filter operations
|
|
20
|
+
* Supported filter operations for both text and number filters
|
|
21
21
|
*/
|
|
22
|
-
export type FilterOperation = 'contains' | 'eq' | 'notContains' | 'notEqual' | 'startsWith' | 'endsWith' | 'blank' | 'notBlank';
|
|
22
|
+
export type FilterOperation = 'contains' | 'eq' | 'notContains' | 'notEqual' | 'startsWith' | 'endsWith' | 'blank' | 'notBlank' | 'lessThan' | 'lessThanOrEqual' | 'greaterThan' | 'greaterThanOrEqual' | 'inRange';
|
|
23
23
|
/**
|
|
24
|
-
*
|
|
24
|
+
* Valid text filter operations as const array
|
|
25
25
|
*/
|
|
26
|
-
export
|
|
27
|
-
|
|
26
|
+
export declare const TEXT_FILTER_OPERATIONS: readonly ["contains", "eq", "notContains", "notEqual", "startsWith", "endsWith", "blank", "notBlank"];
|
|
27
|
+
/**
|
|
28
|
+
* Valid number filter operations as const array
|
|
29
|
+
*/
|
|
30
|
+
export declare const NUMBER_FILTER_OPERATIONS: readonly ["eq", "notEqual", "lessThan", "lessThanOrEqual", "greaterThan", "greaterThanOrEqual", "inRange", "blank", "notBlank"];
|
|
31
|
+
/**
|
|
32
|
+
* Text-specific filter operations
|
|
33
|
+
*/
|
|
34
|
+
export type TextFilterOperation = (typeof TEXT_FILTER_OPERATIONS)[number];
|
|
35
|
+
/**
|
|
36
|
+
* Number-specific filter operations
|
|
37
|
+
*/
|
|
38
|
+
export type NumberFilterOperation = (typeof NUMBER_FILTER_OPERATIONS)[number];
|
|
39
|
+
/**
|
|
40
|
+
* Base interface for column filters
|
|
41
|
+
*/
|
|
42
|
+
interface BaseColumnFilter {
|
|
28
43
|
type: FilterOperation;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Text filter configuration
|
|
47
|
+
*/
|
|
48
|
+
export interface TextColumnFilter extends BaseColumnFilter {
|
|
49
|
+
filterType: 'text';
|
|
50
|
+
type: TextFilterOperation;
|
|
29
51
|
filter: string;
|
|
30
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Number filter configuration
|
|
55
|
+
*/
|
|
56
|
+
export interface NumberColumnFilter extends BaseColumnFilter {
|
|
57
|
+
filterType: 'number';
|
|
58
|
+
type: NumberFilterOperation;
|
|
59
|
+
filter: number;
|
|
60
|
+
filterTo?: number;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Filter state for a single column (union of text and number filters)
|
|
64
|
+
*/
|
|
65
|
+
export type ColumnFilter = TextColumnFilter | NumberColumnFilter;
|
|
31
66
|
/**
|
|
32
67
|
* Complete filter state mapping
|
|
33
68
|
*/
|
|
@@ -55,58 +90,18 @@ export declare class InvalidURLError extends URLSyncError {
|
|
|
55
90
|
export type ParsedFilterParam = {
|
|
56
91
|
columnName: string;
|
|
57
92
|
operation: FilterOperation;
|
|
58
|
-
|
|
93
|
+
filterType: 'text' | 'number' | 'auto';
|
|
94
|
+
value: string | number;
|
|
95
|
+
filterTo?: number;
|
|
59
96
|
action: 'apply' | 'remove';
|
|
60
97
|
};
|
|
61
98
|
export type GridApi = AGGridApi;
|
|
62
99
|
/**
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
* We use three different naming conventions for better user experience:
|
|
66
|
-
*
|
|
67
|
-
* 1. URL Parameters: Short, clean names for URLs (e.g., 'eq', 'neq')
|
|
68
|
-
* 2. Internal Types: Consistent naming for our FilterOperation type
|
|
69
|
-
* 3. AG Grid Operations: Exact names expected by AG Grid API (e.g., 'equals', 'notEqual')
|
|
70
|
-
*
|
|
71
|
-
* This approach keeps URLs readable while maintaining compatibility with AG Grid.
|
|
100
|
+
* Union type for AG Grid filters using official AG Grid types
|
|
72
101
|
*/
|
|
73
|
-
export
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
readonly endsWith: "endsWith";
|
|
80
|
-
readonly blank: "blank";
|
|
81
|
-
readonly notBlank: "notBlank";
|
|
82
|
-
};
|
|
83
|
-
export declare const INTERNAL_TO_URL_OPERATION_MAP: {
|
|
84
|
-
readonly contains: "contains";
|
|
85
|
-
readonly eq: "eq";
|
|
86
|
-
readonly notContains: "notContains";
|
|
87
|
-
readonly notEqual: "neq";
|
|
88
|
-
readonly startsWith: "startsWith";
|
|
89
|
-
readonly endsWith: "endsWith";
|
|
90
|
-
readonly blank: "blank";
|
|
91
|
-
readonly notBlank: "notBlank";
|
|
92
|
-
};
|
|
93
|
-
export declare const AG_GRID_OPERATION_NAMES: {
|
|
94
|
-
readonly contains: "contains";
|
|
95
|
-
readonly eq: "equals";
|
|
96
|
-
readonly notContains: "notContains";
|
|
97
|
-
readonly notEqual: "notEqual";
|
|
98
|
-
readonly startsWith: "startsWith";
|
|
99
|
-
readonly endsWith: "endsWith";
|
|
100
|
-
readonly blank: "blank";
|
|
101
|
-
readonly notBlank: "notBlank";
|
|
102
|
-
};
|
|
103
|
-
export declare const REVERSE_AG_GRID_OPERATION_NAMES: {
|
|
104
|
-
readonly contains: "contains";
|
|
105
|
-
readonly equals: "eq";
|
|
106
|
-
readonly notContains: "notContains";
|
|
107
|
-
readonly notEqual: "notEqual";
|
|
108
|
-
readonly startsWith: "startsWith";
|
|
109
|
-
readonly endsWith: "endsWith";
|
|
110
|
-
readonly blank: "blank";
|
|
111
|
-
readonly notBlank: "notBlank";
|
|
112
|
-
};
|
|
102
|
+
export type AGGridFilter = TextFilterModel | NumberFilterModel;
|
|
103
|
+
export declare const OPERATION_MAP: Record<string, FilterOperation>;
|
|
104
|
+
export declare const INTERNAL_TO_URL_OPERATION_MAP: Record<FilterOperation, string>;
|
|
105
|
+
export declare const AG_GRID_OPERATION_NAMES: Record<FilterOperation, string>;
|
|
106
|
+
export declare const REVERSE_AG_GRID_OPERATION_NAMES: Record<string, FilterOperation>;
|
|
107
|
+
export {};
|
package/dist/core/types.js
CHANGED
|
@@ -1,3 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Valid text filter operations as const array
|
|
3
|
+
*/
|
|
4
|
+
export const TEXT_FILTER_OPERATIONS = [
|
|
5
|
+
'contains',
|
|
6
|
+
'eq',
|
|
7
|
+
'notContains',
|
|
8
|
+
'notEqual',
|
|
9
|
+
'startsWith',
|
|
10
|
+
'endsWith',
|
|
11
|
+
'blank',
|
|
12
|
+
'notBlank'
|
|
13
|
+
];
|
|
14
|
+
/**
|
|
15
|
+
* Valid number filter operations as const array
|
|
16
|
+
*/
|
|
17
|
+
export const NUMBER_FILTER_OPERATIONS = [
|
|
18
|
+
'eq',
|
|
19
|
+
'notEqual',
|
|
20
|
+
'lessThan',
|
|
21
|
+
'lessThanOrEqual',
|
|
22
|
+
'greaterThan',
|
|
23
|
+
'greaterThanOrEqual',
|
|
24
|
+
'inRange',
|
|
25
|
+
'blank',
|
|
26
|
+
'notBlank'
|
|
27
|
+
];
|
|
1
28
|
/**
|
|
2
29
|
* Error types for URL sync operations
|
|
3
30
|
*/
|
|
@@ -24,56 +51,67 @@ export class InvalidURLError extends URLSyncError {
|
|
|
24
51
|
*
|
|
25
52
|
* We use three different naming conventions for better user experience:
|
|
26
53
|
*
|
|
27
|
-
* 1. URL Parameters: Short, clean names for URLs (e.g., 'eq', 'neq')
|
|
54
|
+
* 1. URL Parameters: Short, clean names for URLs (e.g., 'eq', 'neq', 'lt', 'gt')
|
|
28
55
|
* 2. Internal Types: Consistent naming for our FilterOperation type
|
|
29
56
|
* 3. AG Grid Operations: Exact names expected by AG Grid API (e.g., 'equals', 'notEqual')
|
|
30
57
|
*
|
|
31
58
|
* This approach keeps URLs readable while maintaining compatibility with AG Grid.
|
|
32
59
|
*/
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
};
|
|
45
|
-
// Internal operation types to URL parameter names
|
|
46
|
-
export const INTERNAL_TO_URL_OPERATION_MAP = {
|
|
47
|
-
contains: 'contains',
|
|
48
|
-
eq: 'eq',
|
|
49
|
-
notContains: 'notContains',
|
|
50
|
-
notEqual: 'neq', // Internal 'notEqual' -> URL 'neq'
|
|
51
|
-
startsWith: 'startsWith',
|
|
52
|
-
endsWith: 'endsWith',
|
|
53
|
-
blank: 'blank',
|
|
54
|
-
notBlank: 'notBlank'
|
|
55
|
-
};
|
|
56
|
-
// Internal operation types to AG Grid operation names
|
|
57
|
-
// AG Grid expects 'equals' not 'eq', 'notEqual' not 'neq'
|
|
58
|
-
export const AG_GRID_OPERATION_NAMES = {
|
|
59
|
-
contains: 'contains',
|
|
60
|
-
eq: 'equals', // Internal 'eq' -> AG Grid 'equals'
|
|
61
|
-
notContains: 'notContains',
|
|
62
|
-
notEqual: 'notEqual',
|
|
63
|
-
startsWith: 'startsWith',
|
|
64
|
-
endsWith: 'endsWith',
|
|
65
|
-
blank: 'blank',
|
|
66
|
-
notBlank: 'notBlank'
|
|
60
|
+
/**
|
|
61
|
+
* Define special URL shorthand mappings (internal -> URL)
|
|
62
|
+
* Operations not listed here use their internal name as URL param
|
|
63
|
+
*/
|
|
64
|
+
const URL_SHORTHAND_MAPPINGS = {
|
|
65
|
+
notEqual: 'neq',
|
|
66
|
+
lessThan: 'lt',
|
|
67
|
+
lessThanOrEqual: 'lte',
|
|
68
|
+
greaterThan: 'gt',
|
|
69
|
+
greaterThanOrEqual: 'gte',
|
|
70
|
+
inRange: 'range'
|
|
67
71
|
};
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
startsWith: 'startsWith',
|
|
75
|
-
endsWith: 'endsWith',
|
|
76
|
-
blank: 'blank',
|
|
77
|
-
notBlank: 'notBlank'
|
|
72
|
+
/**
|
|
73
|
+
* Define special AG Grid name mappings (internal -> AG Grid)
|
|
74
|
+
* Operations not listed here use their internal name for AG Grid
|
|
75
|
+
*/
|
|
76
|
+
const AG_GRID_NAME_MAPPINGS = {
|
|
77
|
+
eq: 'equals'
|
|
78
78
|
};
|
|
79
|
+
/**
|
|
80
|
+
* Helper function to create operation mappings dynamically
|
|
81
|
+
*/
|
|
82
|
+
function createOperationMaps() {
|
|
83
|
+
const allOperations = [...TEXT_FILTER_OPERATIONS, ...NUMBER_FILTER_OPERATIONS];
|
|
84
|
+
// Remove duplicates (like 'eq', 'blank', etc. that appear in both arrays)
|
|
85
|
+
const uniqueOperations = [...new Set(allOperations)];
|
|
86
|
+
// Generate URL mappings
|
|
87
|
+
const operationMap = {};
|
|
88
|
+
const internalToUrlMap = {};
|
|
89
|
+
uniqueOperations.forEach(operation => {
|
|
90
|
+
const urlName = URL_SHORTHAND_MAPPINGS[operation] || operation;
|
|
91
|
+
operationMap[urlName] = operation;
|
|
92
|
+
internalToUrlMap[operation] = urlName;
|
|
93
|
+
});
|
|
94
|
+
// Generate AG Grid mappings
|
|
95
|
+
const agGridMap = {};
|
|
96
|
+
const reverseAgGridMap = {};
|
|
97
|
+
uniqueOperations.forEach(operation => {
|
|
98
|
+
const agGridName = AG_GRID_NAME_MAPPINGS[operation] ||
|
|
99
|
+
operation;
|
|
100
|
+
agGridMap[operation] = agGridName;
|
|
101
|
+
reverseAgGridMap[agGridName] = operation;
|
|
102
|
+
});
|
|
103
|
+
return {
|
|
104
|
+
operationMap,
|
|
105
|
+
internalToUrlMap,
|
|
106
|
+
agGridMap,
|
|
107
|
+
reverseAgGridMap
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
// Generate all mappings dynamically
|
|
111
|
+
const { operationMap, internalToUrlMap, agGridMap, reverseAgGridMap } = createOperationMaps();
|
|
112
|
+
// Export the dynamically generated maps
|
|
113
|
+
export const OPERATION_MAP = operationMap;
|
|
114
|
+
export const INTERNAL_TO_URL_OPERATION_MAP = internalToUrlMap;
|
|
115
|
+
export const AG_GRID_OPERATION_NAMES = agGridMap;
|
|
116
|
+
export const REVERSE_AG_GRID_OPERATION_NAMES = reverseAgGridMap;
|
|
79
117
|
//# sourceMappingURL=types.js.map
|
package/dist/core/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,25 +1,71 @@
|
|
|
1
1
|
import { validateFilterValue } from './validation.js';
|
|
2
2
|
import { INTERNAL_TO_URL_OPERATION_MAP } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Serializes a single column filter to URL parameter
|
|
5
|
+
*/
|
|
6
|
+
function serializeColumnFilter(columnName, filter, paramPrefix) {
|
|
7
|
+
const urlOperation = INTERNAL_TO_URL_OPERATION_MAP[filter.type];
|
|
8
|
+
if (!urlOperation)
|
|
9
|
+
return '';
|
|
10
|
+
const paramName = `${paramPrefix}${columnName}_${urlOperation}`;
|
|
11
|
+
// Handle range operations
|
|
12
|
+
if (filter.type === 'inRange' && filter.filterType === 'number') {
|
|
13
|
+
// Type guard: ensure this is a NumberColumnFilter with inRange operation
|
|
14
|
+
if ('filterTo' in filter && filter.filterTo !== undefined) {
|
|
15
|
+
// Don't encode the comma for range values - handle this directly
|
|
16
|
+
return `${paramName}=${filter.filter},${filter.filterTo}`;
|
|
17
|
+
}
|
|
18
|
+
return '';
|
|
19
|
+
}
|
|
20
|
+
// Handle blank operations
|
|
21
|
+
if (filter.type === 'blank' || filter.type === 'notBlank') {
|
|
22
|
+
return `${paramName}=true`;
|
|
23
|
+
}
|
|
24
|
+
// Handle number operations
|
|
25
|
+
if (filter.filterType === 'number') {
|
|
26
|
+
return `${paramName}=${filter.filter}`;
|
|
27
|
+
}
|
|
28
|
+
// Handle text operations (existing logic)
|
|
29
|
+
if (filter.filterType === 'text' && filter.filter) {
|
|
30
|
+
// Note: Validation should be done at the serializeFilters level, not here
|
|
31
|
+
return `${paramName}=${encodeURIComponent(filter.filter.toString())}`;
|
|
32
|
+
}
|
|
33
|
+
return '';
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Helper function to append a serialized parameter to URLSearchParams
|
|
37
|
+
*/
|
|
38
|
+
function appendSerializedParam(serialized, params) {
|
|
39
|
+
const [paramName, paramValue] = serialized.split('=');
|
|
40
|
+
if (paramName && paramValue) {
|
|
41
|
+
// Decode the parameter value to handle commas correctly
|
|
42
|
+
params.append(paramName, decodeURIComponent(paramValue));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
3
45
|
/**
|
|
4
46
|
* Converts a filter state object into URL search parameters
|
|
5
47
|
*/
|
|
6
48
|
export function serializeFilters(filterState, config) {
|
|
7
49
|
const params = new URLSearchParams();
|
|
8
50
|
for (const [column, filter] of Object.entries(filterState)) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const operation = INTERNAL_TO_URL_OPERATION_MAP[filter.type];
|
|
12
|
-
if (!operation)
|
|
51
|
+
// Support both text and number filters
|
|
52
|
+
if (filter.filterType !== 'text' && filter.filterType !== 'number')
|
|
13
53
|
continue;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
54
|
+
// Apply validation for text filters before serialization
|
|
55
|
+
if (filter.filterType === 'text') {
|
|
56
|
+
const validatedValue = validateFilterValue(filter.filter, config, filter.type);
|
|
57
|
+
const updatedFilter = { ...filter, filter: validatedValue };
|
|
58
|
+
const serialized = serializeColumnFilter(column, updatedFilter, config.paramPrefix);
|
|
59
|
+
if (serialized) {
|
|
60
|
+
appendSerializedParam(serialized, params);
|
|
61
|
+
}
|
|
18
62
|
}
|
|
19
63
|
else {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
64
|
+
// Number filters don't need additional validation as they're already validated
|
|
65
|
+
const serialized = serializeColumnFilter(column, filter, config.paramPrefix);
|
|
66
|
+
if (serialized) {
|
|
67
|
+
appendSerializedParam(serialized, params);
|
|
68
|
+
}
|
|
23
69
|
}
|
|
24
70
|
}
|
|
25
71
|
return params;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url-generator.js","sourceRoot":"","sources":["../../src/core/url-generator.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AACrD,OAAO,EAAE,6BAA6B,EAAE,MAAM,YAAY,CAAA;AAE1D;;GAEG;AACH,
|
|
1
|
+
{"version":3,"file":"url-generator.js","sourceRoot":"","sources":["../../src/core/url-generator.ts"],"names":[],"mappings":"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"}
|
package/dist/core/url-parser.js
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
import { InvalidFilterError, InvalidURLError, OPERATION_MAP } from './types.js';
|
|
2
|
-
import { validateFilterValue, DEFAULT_CONFIG } from './validation.js';
|
|
2
|
+
import { validateFilterValue, validateAndParseNumber, validateNumberRange, validateNumberFilter, DEFAULT_CONFIG } from './validation.js';
|
|
3
|
+
/**
|
|
4
|
+
* Detects if an operation is number-specific
|
|
5
|
+
*/
|
|
6
|
+
function isNumberOperation(operation) {
|
|
7
|
+
return [
|
|
8
|
+
'lessThan',
|
|
9
|
+
'lessThanOrEqual',
|
|
10
|
+
'greaterThan',
|
|
11
|
+
'greaterThanOrEqual',
|
|
12
|
+
'inRange'
|
|
13
|
+
].includes(operation);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Detects if an operation works with both text and number filters
|
|
17
|
+
*/
|
|
18
|
+
function isSharedOperation(operation) {
|
|
19
|
+
return ['eq', 'notEqual', 'blank', 'notBlank'].includes(operation);
|
|
20
|
+
}
|
|
3
21
|
/**
|
|
4
22
|
* Extracts column name and operation from a filter parameter
|
|
5
23
|
*/
|
|
@@ -34,7 +52,35 @@ export function parseFilterParam(param, value, expectedPrefix) {
|
|
|
34
52
|
if (!filterOp) {
|
|
35
53
|
throw new InvalidFilterError(`Unsupported filter operation: ${operation}`);
|
|
36
54
|
}
|
|
37
|
-
//
|
|
55
|
+
// Handle range operations
|
|
56
|
+
if (filterOp === 'inRange') {
|
|
57
|
+
const rangeParts = value.split(',');
|
|
58
|
+
if (rangeParts.length !== 2) {
|
|
59
|
+
throw new InvalidFilterError('Range operation requires exactly two values separated by comma');
|
|
60
|
+
}
|
|
61
|
+
const min = validateAndParseNumber(rangeParts[0] || '');
|
|
62
|
+
const max = validateAndParseNumber(rangeParts[1] || '');
|
|
63
|
+
const rangeValidation = validateNumberRange(min, max);
|
|
64
|
+
if (!rangeValidation.valid) {
|
|
65
|
+
throw new InvalidFilterError(rangeValidation.error || 'Invalid range values');
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
filterType: 'number',
|
|
69
|
+
type: filterOp,
|
|
70
|
+
filter: min,
|
|
71
|
+
filterTo: max
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
// Handle number operations
|
|
75
|
+
if (isNumberOperation(filterOp)) {
|
|
76
|
+
const numValue = validateAndParseNumber(value);
|
|
77
|
+
return {
|
|
78
|
+
filterType: 'number',
|
|
79
|
+
type: filterOp,
|
|
80
|
+
filter: numValue
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
// Handle blank operations first (work for both text and number but default to text)
|
|
38
84
|
if (filterOp === 'blank' || filterOp === 'notBlank') {
|
|
39
85
|
return {
|
|
40
86
|
filterType: 'text',
|
|
@@ -42,6 +88,32 @@ export function parseFilterParam(param, value, expectedPrefix) {
|
|
|
42
88
|
filter: '' // Blank operations don't use the value
|
|
43
89
|
};
|
|
44
90
|
}
|
|
91
|
+
// Handle shared operations (eq, notEqual) - detect if they should be number based on value
|
|
92
|
+
if (isSharedOperation(filterOp)) {
|
|
93
|
+
// Try to parse as number first
|
|
94
|
+
try {
|
|
95
|
+
const numValue = parseFloat(value);
|
|
96
|
+
if (!isNaN(numValue) && Number.isFinite(numValue)) {
|
|
97
|
+
const validation = validateNumberFilter(numValue);
|
|
98
|
+
if (validation.valid) {
|
|
99
|
+
return {
|
|
100
|
+
filterType: 'number',
|
|
101
|
+
type: filterOp,
|
|
102
|
+
filter: numValue
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
// Fall through to text handling
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
filterType: 'text',
|
|
112
|
+
type: filterOp,
|
|
113
|
+
filter: value || ''
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
// Handle text operations (existing logic)
|
|
45
117
|
return {
|
|
46
118
|
filterType: 'text',
|
|
47
119
|
type: filterOp,
|
|
@@ -62,11 +134,18 @@ export function parseUrlFilters(url, config) {
|
|
|
62
134
|
// Extract column name and parse the filter parameter
|
|
63
135
|
const { column: columnName } = extractColumnAndOperation(param, config.paramPrefix);
|
|
64
136
|
const filterParam = parseFilterParam(param, value, config.paramPrefix);
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
137
|
+
// Apply validation based on filter type
|
|
138
|
+
if (filterParam.filterType === 'text') {
|
|
139
|
+
const validatedValue = validateFilterValue(value, config, filterParam.type);
|
|
140
|
+
filterState[columnName] = {
|
|
141
|
+
...filterParam,
|
|
142
|
+
filter: validatedValue
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
// Number filters are already validated in parseFilterParam
|
|
147
|
+
filterState[columnName] = filterParam;
|
|
148
|
+
}
|
|
70
149
|
}
|
|
71
150
|
catch (err) {
|
|
72
151
|
if (config.onParseError) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"url-parser.js","sourceRoot":"","sources":["../../src/core/url-parser.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC/E,OAAO,
|
|
1
|
+
{"version":3,"file":"url-parser.js","sourceRoot":"","sources":["../../src/core/url-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,7 +7,14 @@ export declare const DEFAULT_CONFIG: {
|
|
|
7
7
|
readonly maxValueLength: 200;
|
|
8
8
|
};
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* Validation result interface
|
|
11
|
+
*/
|
|
12
|
+
export interface ValidationResult {
|
|
13
|
+
valid: boolean;
|
|
14
|
+
error?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Validates a text filter value against configuration constraints
|
|
11
18
|
*
|
|
12
19
|
* @param value - The filter value to validate
|
|
13
20
|
* @param config - Internal configuration with validation rules
|
|
@@ -16,3 +23,25 @@ export declare const DEFAULT_CONFIG: {
|
|
|
16
23
|
* @throws InvalidFilterError if value exceeds maximum length
|
|
17
24
|
*/
|
|
18
25
|
export declare function validateFilterValue(value: string, config: InternalConfig, operation?: FilterOperation): string;
|
|
26
|
+
/**
|
|
27
|
+
* Validates a number filter value
|
|
28
|
+
*
|
|
29
|
+
* @param value - The number value to validate
|
|
30
|
+
* @returns Validation result
|
|
31
|
+
*/
|
|
32
|
+
export declare function validateNumberFilter(value: number): ValidationResult;
|
|
33
|
+
/**
|
|
34
|
+
* Validates a number range filter
|
|
35
|
+
*
|
|
36
|
+
* @param min - The minimum value
|
|
37
|
+
* @param max - The maximum value
|
|
38
|
+
* @returns Validation result
|
|
39
|
+
*/
|
|
40
|
+
export declare function validateNumberRange(min: number, max: number): ValidationResult;
|
|
41
|
+
/**
|
|
42
|
+
* Validates a parsed number from string input
|
|
43
|
+
*
|
|
44
|
+
* @param value - String representation of number
|
|
45
|
+
* @returns Parsed number or throws InvalidFilterError
|
|
46
|
+
*/
|
|
47
|
+
export declare function validateAndParseNumber(value: string): number;
|
package/dist/core/validation.js
CHANGED
|
@@ -7,7 +7,7 @@ export const DEFAULT_CONFIG = {
|
|
|
7
7
|
maxValueLength: 200
|
|
8
8
|
};
|
|
9
9
|
/**
|
|
10
|
-
* Validates a filter value against configuration constraints
|
|
10
|
+
* Validates a text filter value against configuration constraints
|
|
11
11
|
*
|
|
12
12
|
* @param value - The filter value to validate
|
|
13
13
|
* @param config - Internal configuration with validation rules
|
|
@@ -25,4 +25,63 @@ export function validateFilterValue(value, config, operation) {
|
|
|
25
25
|
}
|
|
26
26
|
return value;
|
|
27
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Validates a number filter value
|
|
30
|
+
*
|
|
31
|
+
* @param value - The number value to validate
|
|
32
|
+
* @returns Validation result
|
|
33
|
+
*/
|
|
34
|
+
export function validateNumberFilter(value) {
|
|
35
|
+
// Basic number validation
|
|
36
|
+
if (!Number.isFinite(value)) {
|
|
37
|
+
return { valid: false, error: 'Filter value must be a finite number' };
|
|
38
|
+
}
|
|
39
|
+
// Range validation for precision
|
|
40
|
+
if (Math.abs(value) > Number.MAX_SAFE_INTEGER) {
|
|
41
|
+
return { valid: false, error: 'Number value exceeds safe integer range' };
|
|
42
|
+
}
|
|
43
|
+
return { valid: true };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Validates a number range filter
|
|
47
|
+
*
|
|
48
|
+
* @param min - The minimum value
|
|
49
|
+
* @param max - The maximum value
|
|
50
|
+
* @returns Validation result
|
|
51
|
+
*/
|
|
52
|
+
export function validateNumberRange(min, max) {
|
|
53
|
+
const minResult = validateNumberFilter(min);
|
|
54
|
+
if (!minResult.valid)
|
|
55
|
+
return minResult;
|
|
56
|
+
const maxResult = validateNumberFilter(max);
|
|
57
|
+
if (!maxResult.valid)
|
|
58
|
+
return maxResult;
|
|
59
|
+
if (min > max) {
|
|
60
|
+
return {
|
|
61
|
+
valid: false,
|
|
62
|
+
error: 'Range minimum must be less than or equal to maximum'
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
return { valid: true };
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Validates a parsed number from string input
|
|
69
|
+
*
|
|
70
|
+
* @param value - String representation of number
|
|
71
|
+
* @returns Parsed number or throws InvalidFilterError
|
|
72
|
+
*/
|
|
73
|
+
export function validateAndParseNumber(value) {
|
|
74
|
+
if (!value || value.trim() === '') {
|
|
75
|
+
throw new InvalidFilterError('Number filter value cannot be empty');
|
|
76
|
+
}
|
|
77
|
+
const numValue = parseFloat(value);
|
|
78
|
+
if (isNaN(numValue)) {
|
|
79
|
+
throw new InvalidFilterError(`Invalid number format: ${value}`);
|
|
80
|
+
}
|
|
81
|
+
const validation = validateNumberFilter(numValue);
|
|
82
|
+
if (!validation.valid) {
|
|
83
|
+
throw new InvalidFilterError(validation.error || 'Invalid number value');
|
|
84
|
+
}
|
|
85
|
+
return numValue;
|
|
86
|
+
}
|
|
28
87
|
//# sourceMappingURL=validation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/core/validation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAE/C;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,WAAW,EAAE,IAAI;IACjB,cAAc,EAAE,GAAG;CACX,CAAA;
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/core/validation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAE/C;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,WAAW,EAAE,IAAI;IACjB,cAAc,EAAE,GAAG;CACX,CAAA;AAUV;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CACjC,KAAa,EACb,MAAsB,EACtB,SAA2B;IAE3B,kDAAkD;IAClD,IAAI,SAAS,KAAK,OAAO,IAAI,SAAS,KAAK,UAAU,EAAE,CAAC;QACtD,OAAO,EAAE,CAAA;IACX,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,cAAc,EAAE,CAAC;QACzC,MAAM,IAAI,kBAAkB,CAC1B,0CAA0C,MAAM,CAAC,cAAc,aAAa,CAC7E,CAAA;IACH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,0BAA0B;IAC1B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,sCAAsC,EAAE,CAAA;IACxE,CAAC;IAED,iCAAiC;IACjC,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,gBAAgB,EAAE,CAAC;QAC9C,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,yCAAyC,EAAE,CAAA;IAC3E,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAA;AACxB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CACjC,GAAW,EACX,GAAW;IAEX,MAAM,SAAS,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAA;IAC3C,IAAI,CAAC,SAAS,CAAC,KAAK;QAAE,OAAO,SAAS,CAAA;IAEtC,MAAM,SAAS,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAA;IAC3C,IAAI,CAAC,SAAS,CAAC,KAAK;QAAE,OAAO,SAAS,CAAA;IAEtC,IAAI,GAAG,GAAG,GAAG,EAAE,CAAC;QACd,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,KAAK,EAAE,qDAAqD;SAC7D,CAAA;IACH,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAA;AACxB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAa;IAClD,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAClC,MAAM,IAAI,kBAAkB,CAAC,qCAAqC,CAAC,CAAA;IACrE,CAAC;IAED,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,CAAA;IAClC,IAAI,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpB,MAAM,IAAI,kBAAkB,CAAC,0BAA0B,KAAK,EAAE,CAAC,CAAA;IACjE,CAAC;IAED,MAAM,UAAU,GAAG,oBAAoB,CAAC,QAAQ,CAAC,CAAA;IACjD,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QACtB,MAAM,IAAI,kBAAkB,CAAC,UAAU,CAAC,KAAK,IAAI,sBAAsB,CAAC,CAAA;IAC1E,CAAC;IAED,OAAO,QAAQ,CAAA;AACjB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ag-grid-url-sync",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "AG Grid URL Sync - Synchronize AG Grid text filters with URL parameters",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
"react"
|
|
99
99
|
],
|
|
100
100
|
"author": "NearForm",
|
|
101
|
-
"license": "
|
|
101
|
+
"license": "MIT",
|
|
102
102
|
"bugs": {
|
|
103
103
|
"url": "https://github.com/nearform/ag-grid-url-state-sync/issues"
|
|
104
104
|
},
|
|
@@ -111,11 +111,11 @@
|
|
|
111
111
|
"@commitlint/cli": "^19.8.1",
|
|
112
112
|
"@commitlint/config-conventional": "^19.8.1",
|
|
113
113
|
"@eslint/js": "^9.29.0",
|
|
114
|
-
"@testing-library/react": "^
|
|
114
|
+
"@testing-library/react": "^16.3.0",
|
|
115
115
|
"@types/jsdom": "^21.1.7",
|
|
116
116
|
"@types/react": "^18.0.0",
|
|
117
117
|
"@vitest/coverage-v8": "^3.2.4",
|
|
118
|
-
"ag-grid-community": "^
|
|
118
|
+
"ag-grid-community": "^34.0.0",
|
|
119
119
|
"bundlesize": "^0.18.2",
|
|
120
120
|
"eslint": "^9.29.0",
|
|
121
121
|
"eslint-config-prettier": "^10.1.5",
|