This repository has been archived by the owner on Jan 16, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 11
/
filters.ts
158 lines (153 loc) · 4.98 KB
/
filters.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
import { BcFilter, BcSorter, FilterType } from '../interfaces/filters'
import { DataValue } from '../interfaces/data'
import qs from 'query-string'
import { FieldType } from '../interfaces/view'
/**
* Maps an input array of BcFilter objects into a dictionary of GET-request params
*
* Name of the param formed as field name and filter type, separated by dot,
* e.g. `${filter.fieldName}.${filter.type}`
*
* Value of the param is:
* - for non-array values, stringified filter value
* - for array values, a comma-separated list of stringified elements with each element enclosed in double quotes
*
* @see {@link parseFilters} Reverse function
*
* @param filters Filters for business components
* @returns Dictionary of query-params for GET-request
* @category Utils
*/
export function getFilters(filters: BcFilter[]) {
if (!filters || !filters.length) {
return null
}
const result: Record<string, string> = {}
filters.forEach(item => {
if (item.type === FilterType.range) {
const values = item.value as DataValue[]
if (values[0]) {
result[`${item.fieldName}.${FilterType.greaterOrEqualThan}`] = String(values[0])
}
if (values[1]) {
result[`${item.fieldName}.${FilterType.lessOrEqualThan}`] = String(values[1])
}
} else {
let value = String(item.value)
if (Array.isArray(item.value)) {
const values = (item.value as DataValue[]).map(val => `"${val}"`)
value = `[${values}]`
}
result[`${item.fieldName}.${item.type}`] = value
}
})
return result
}
/**
* Maps an input array of business component sorters into a dictionary of query params for
* Tesler API, where values are field names and keys follows the template:
* `_sort.${index}.${item.direction}`
*
* @param sorters Array of business component sorters
* @returns Dictionary of query-params for GET-request
* @category Utils
*/
export function getSorters(sorters: BcSorter[]) {
if (!sorters || !sorters.length) {
return null
}
const result: Record<string, string> = {}
sorters.forEach((item, index) => {
result[`_sort.${index}.${item.direction}`] = item.fieldName
})
return result
}
/**
* Function for parsing filters from string into BcFilter type
*
* @see {@link getFilters} Reverse function
* @param defaultFilters string representation of filters
* @category Utils
*/
export function parseFilters(defaultFilters: string) {
const result: BcFilter[] = []
const urlParams = qs.parse(defaultFilters)
Object.keys(urlParams).forEach(param => {
const [fieldName, type] = param.split('.')
if (fieldName && type && urlParams[param]) {
let value = urlParams[param]
if (type === FilterType.containsOneOf || type === FilterType.equalsOneOf) {
try {
value = JSON.parse(value)
} catch (e) {
console.warn(e)
}
value = Array.isArray(value) ? value : []
}
result.push({
fieldName,
type: type as FilterType,
value
})
}
})
return result.length ? result : null
}
/**
* Parse sorter string into separate sorter objects.
* String representation of sorters is url based:
* "_sort.{order}.{direction}={fieldKey}&_sort.{order}.{direction}"
*
* @param fieldKey Sort by field
* @param order Priority of this specfic sorter
* @param direction "asc" or "desc"
*
* i.e. "_sort.0.asc=firstName"
*
* @param sorters string representation of sorters
* @category Utils
*/
export function parseSorters(sorters: string) {
if (!sorters || !sorters.length) {
return null
}
const result: BcSorter[] = []
const dictionary = qs.parse(sorters)
Object.entries(dictionary)
.map(([sort, fieldKey]) => {
const [order, direction] = sort.split('.').slice(1)
return { fieldName: fieldKey as string, order: Number.parseInt(order, 10), direction }
})
.sort((a, b) => a.order - b.order)
.forEach(item => {
result.push({ fieldName: item.fieldName, direction: item.direction as 'asc' | 'desc' })
})
return result
}
/**
* Returns appropriate filtration type for specified field type.
*
* - Text-based fields use `contains`
* - Checkbox fields use `specified` (boolean)
* - Dictionary fiels use `equalsOneOf`
*
* All other field types use strict `equals`
*
* @param fieldType Field type
*/
export function getFilterType(fieldType: FieldType) {
switch (fieldType) {
case FieldType.dictionary: {
return FilterType.equalsOneOf
}
case FieldType.checkbox: {
return FilterType.specified
}
case FieldType.input:
case FieldType.text: {
return FilterType.contains
}
default:
return FilterType.equals
}
}