@teselagen/ui 0.8.6 → 0.9.1
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/DataTable/EditabelCell.d.ts +10 -0
- package/DataTable/defaultProps.d.ts +43 -0
- package/DataTable/utils/computePresets.d.ts +1 -0
- package/DataTable/utils/getAllRows.d.ts +1 -1
- package/DataTable/utils/handleCopyColumn.d.ts +1 -1
- package/DataTable/utils/handleCopyTable.d.ts +1 -1
- package/DataTable/utils/initializeHasuraWhereAndFilter.d.ts +0 -1
- package/DataTable/utils/queryParams.d.ts +16 -12
- package/DataTable/utils/tableQueryParamsToHasuraClauses.d.ts +1 -1
- package/README.md +1 -1
- package/index.cjs.js +1139 -1040
- package/index.d.ts +2 -0
- package/index.es.js +1139 -1040
- package/package.json +2 -2
- package/src/DataTable/Columns.js +2 -2
- package/src/DataTable/DisplayOptions.js +1 -1
- package/src/DataTable/EditabelCell.js +55 -0
- package/src/DataTable/FilterAndSortMenu.js +27 -30
- package/src/DataTable/defaultProps.js +45 -0
- package/src/DataTable/index.js +101 -84
- package/src/DataTable/style.css +1 -1
- package/src/DataTable/utils/computePresets.js +42 -0
- package/src/DataTable/utils/filterLocalEntitiesToHasura.js +128 -8
- package/src/DataTable/utils/filterLocalEntitiesToHasura.test.js +719 -21
- package/src/DataTable/utils/getAllRows.js +2 -6
- package/src/DataTable/utils/handleCopyColumn.js +2 -2
- package/src/DataTable/utils/handleCopyTable.js +2 -2
- package/src/DataTable/utils/initializeHasuraWhereAndFilter.js +1 -12
- package/src/DataTable/utils/queryParams.js +153 -770
- package/src/DataTable/utils/tableQueryParamsToHasuraClauses.js +185 -168
- package/src/DataTable/utils/tableQueryParamsToHasuraClauses.test.js +50 -11
- package/src/DataTable/utils/withTableParams.js +3 -16
- package/src/ExcelCell.js +38 -0
- package/src/FormComponents/Uploader.js +5 -1
- package/src/FormComponents/index.js +2 -2
- package/src/TgSelect/index.js +15 -0
- package/src/autoTooltip.js +1 -0
- package/src/index.js +2 -0
- package/src/utils/determineBlackOrWhiteTextColor.js +8 -1
- package/style.css +10537 -0
- package/ui.css +1 -1
- package/utils/determineBlackOrWhiteTextColor.d.ts +1 -2
|
@@ -11,44 +11,57 @@ export function tableQueryParamsToHasuraClauses({
|
|
|
11
11
|
}) {
|
|
12
12
|
const ccFields = getFieldsMappedByCCDisplayName(schema);
|
|
13
13
|
let where = {};
|
|
14
|
-
const order_by =
|
|
14
|
+
const order_by = [];
|
|
15
15
|
const limit = pageSize || 25;
|
|
16
16
|
const offset = page && pageSize ? (page - 1) * pageSize : 0;
|
|
17
17
|
|
|
18
18
|
if (searchTerm) {
|
|
19
19
|
const searchTermFilters = [];
|
|
20
|
+
// Create a map to deduplicate fields by path
|
|
21
|
+
const uniqueFieldsByPath = {};
|
|
22
|
+
|
|
23
|
+
// Split the search term by comma to support multi-term searching
|
|
24
|
+
const searchTerms = searchTerm.split(",");
|
|
25
|
+
|
|
20
26
|
schema.fields.forEach(field => {
|
|
21
27
|
const { type, path, searchDisabled } = field;
|
|
28
|
+
if (uniqueFieldsByPath[path]) return; // Skip if already added
|
|
29
|
+
uniqueFieldsByPath[path] = true;
|
|
22
30
|
if (searchDisabled || field.filterDisabled || type === "color") return;
|
|
23
|
-
const filterValue = searchTerm; // No cleaning needed here, we're using _ilike
|
|
24
31
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
32
|
+
// Process each search term
|
|
33
|
+
searchTerms.forEach(term => {
|
|
34
|
+
const filterValue = term.trim(); // Trim the term to handle spaces after commas
|
|
35
|
+
|
|
36
|
+
if (type === "string" || type === "lookup") {
|
|
37
|
+
const o = set({}, path, { _ilike: `%${filterValue}%` });
|
|
38
|
+
searchTermFilters.push(o);
|
|
39
|
+
} else if (type === "boolean") {
|
|
40
|
+
let regex;
|
|
41
|
+
try {
|
|
42
|
+
regex = new RegExp("^" + filterValue, "ig");
|
|
43
|
+
} catch (error) {
|
|
44
|
+
//ignore
|
|
45
|
+
}
|
|
46
|
+
if (regex) {
|
|
47
|
+
if ("true".replace(regex, "") !== "true") {
|
|
48
|
+
const o = set({}, path, { _eq: true });
|
|
49
|
+
searchTermFilters.push(o);
|
|
50
|
+
} else if ("false".replace(regex, "") !== "false") {
|
|
51
|
+
const o = set({}, path, { _eq: false });
|
|
52
|
+
searchTermFilters.push(o);
|
|
53
|
+
}
|
|
42
54
|
}
|
|
55
|
+
} else if (
|
|
56
|
+
(type === "number" || type === "integer") &&
|
|
57
|
+
!isNaN(filterValue)
|
|
58
|
+
) {
|
|
59
|
+
const o = set({}, path, { _eq: parseFloat(filterValue) });
|
|
60
|
+
searchTermFilters.push(o);
|
|
43
61
|
}
|
|
44
|
-
}
|
|
45
|
-
(type === "number" || type === "integer") &&
|
|
46
|
-
!isNaN(filterValue)
|
|
47
|
-
) {
|
|
48
|
-
const o = set({}, path, { _eq: parseFloat(filterValue) });
|
|
49
|
-
searchTermFilters.push(o);
|
|
50
|
-
}
|
|
62
|
+
});
|
|
51
63
|
});
|
|
64
|
+
|
|
52
65
|
if (searchTermFilters.length > 0) {
|
|
53
66
|
if (Object.keys(where).length > 0) {
|
|
54
67
|
where = { _and: [where, { _or: searchTermFilters }] };
|
|
@@ -59,157 +72,161 @@ export function tableQueryParamsToHasuraClauses({
|
|
|
59
72
|
}
|
|
60
73
|
|
|
61
74
|
if (filters && filters.length > 0) {
|
|
62
|
-
const filterClauses = filters
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const fieldSchema = ccFields[filterOn] || {};
|
|
75
|
+
const filterClauses = filters.map(filter => {
|
|
76
|
+
let { selectedFilter, filterOn, filterValue } = filter;
|
|
77
|
+
const fieldSchema = ccFields[filterOn] || {};
|
|
66
78
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
const { path, reference, type, customColumnFilter } = fieldSchema;
|
|
80
|
+
if (customColumnFilter) {
|
|
81
|
+
return customColumnFilter(filterValue);
|
|
82
|
+
}
|
|
83
|
+
let stringFilterValue =
|
|
84
|
+
filterValue && filterValue.toString
|
|
85
|
+
? filterValue.toString()
|
|
86
|
+
: filterValue;
|
|
87
|
+
if (stringFilterValue === false) {
|
|
88
|
+
// we still want to be able to search for the string "false" which will get parsed to false
|
|
89
|
+
stringFilterValue = "false";
|
|
90
|
+
} else {
|
|
91
|
+
stringFilterValue = stringFilterValue || "";
|
|
92
|
+
}
|
|
93
|
+
const arrayFilterValue = Array.isArray(filterValue)
|
|
94
|
+
? filterValue
|
|
95
|
+
: stringFilterValue.split(";");
|
|
81
96
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
97
|
+
if (type === "number" || type === "integer") {
|
|
98
|
+
filterValue = Array.isArray(filterValue)
|
|
99
|
+
? filterValue.map(val => Number(val))
|
|
100
|
+
: Number(filterValue);
|
|
101
|
+
}
|
|
87
102
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
103
|
+
if (fieldSchema.normalizeFilter) {
|
|
104
|
+
filterValue = fieldSchema.normalizeFilter(
|
|
105
|
+
filterValue,
|
|
106
|
+
selectedFilter,
|
|
107
|
+
filterOn
|
|
108
|
+
);
|
|
109
|
+
}
|
|
95
110
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
{ [filterOn]: { _is_null: true } }
|
|
119
|
-
]
|
|
120
|
-
};
|
|
121
|
-
case "notEmpty":
|
|
122
|
-
return {
|
|
123
|
-
_and: [
|
|
124
|
-
{ [filterOn]: { _neq: "" } },
|
|
125
|
-
{ [filterOn]: { _is_null: false } }
|
|
126
|
-
]
|
|
127
|
-
};
|
|
128
|
-
case "inList":
|
|
129
|
-
return { [filterOn]: { _in: filterValue } };
|
|
130
|
-
case "notInList":
|
|
131
|
-
return { [filterOn]: { _nin: filterValue } };
|
|
132
|
-
case "true":
|
|
133
|
-
return { [filterOn]: { _eq: true } };
|
|
134
|
-
case "false":
|
|
135
|
-
return { [filterOn]: { _eq: false } };
|
|
136
|
-
case "dateIs":
|
|
137
|
-
return { [filterOn]: { _eq: filterValue } };
|
|
138
|
-
case "notBetween":
|
|
139
|
-
return {
|
|
140
|
-
_or: [
|
|
141
|
-
{
|
|
142
|
-
[filterOn]: {
|
|
143
|
-
_lt: new Date(arrayFilterValue[0])
|
|
144
|
-
}
|
|
145
|
-
},
|
|
146
|
-
{
|
|
147
|
-
[filterOn]: {
|
|
148
|
-
_gt: new Date(
|
|
149
|
-
new Date(arrayFilterValue[1]).setHours(23, 59)
|
|
150
|
-
)
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
]
|
|
154
|
-
};
|
|
155
|
-
case "isBetween":
|
|
111
|
+
if (reference) {
|
|
112
|
+
filterOn = reference.sourceField;
|
|
113
|
+
} else {
|
|
114
|
+
filterOn = path || filterOn;
|
|
115
|
+
}
|
|
116
|
+
switch (selectedFilter) {
|
|
117
|
+
case "none":
|
|
118
|
+
return {};
|
|
119
|
+
case "startsWith":
|
|
120
|
+
return { [filterOn]: { _ilike: `${filterValue}%` } };
|
|
121
|
+
case "endsWith":
|
|
122
|
+
return { [filterOn]: { _ilike: `%${filterValue}` } };
|
|
123
|
+
case "contains":
|
|
124
|
+
return { [filterOn]: { _ilike: `%${filterValue}%` } };
|
|
125
|
+
case "notContains":
|
|
126
|
+
return { [filterOn]: { _nilike: `%${filterValue}%` } };
|
|
127
|
+
case "isExactly":
|
|
128
|
+
return { [filterOn]: { _eq: filterValue } };
|
|
129
|
+
case "isEmpty":
|
|
130
|
+
if (filterOn.includes(".")) {
|
|
131
|
+
// if we're filtering on a nested field, like a sequence table with parts.name
|
|
132
|
+
// we really want to just query on the top level field's existence
|
|
156
133
|
return {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
_lte: new Date(new Date(arrayFilterValue[1]).setHours(23, 59))
|
|
134
|
+
_not: {
|
|
135
|
+
[filterOn.split(".")[0]]: {}
|
|
160
136
|
}
|
|
161
137
|
};
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
[filterOn]: {
|
|
173
|
-
|
|
174
|
-
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
_or: [
|
|
141
|
+
{ [filterOn]: { _eq: "" } },
|
|
142
|
+
{ [filterOn]: { _is_null: true } }
|
|
143
|
+
]
|
|
144
|
+
};
|
|
145
|
+
case "notEmpty":
|
|
146
|
+
return {
|
|
147
|
+
_and: [
|
|
148
|
+
{ [filterOn]: { _neq: "" } },
|
|
149
|
+
{ [filterOn]: { _is_null: false } }
|
|
150
|
+
]
|
|
151
|
+
};
|
|
152
|
+
case "inList":
|
|
153
|
+
return { [filterOn]: { _in: filterValue } };
|
|
154
|
+
case "notInList":
|
|
155
|
+
return { [filterOn]: { _nin: filterValue } };
|
|
156
|
+
case "true":
|
|
157
|
+
return { [filterOn]: { _eq: true } };
|
|
158
|
+
case "false":
|
|
159
|
+
return { [filterOn]: { _eq: false } };
|
|
160
|
+
case "dateIs":
|
|
161
|
+
return { [filterOn]: { _eq: filterValue } };
|
|
162
|
+
case "notBetween":
|
|
163
|
+
return {
|
|
164
|
+
_or: [
|
|
165
|
+
{
|
|
166
|
+
[filterOn]: {
|
|
167
|
+
_lt: new Date(arrayFilterValue[0])
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
[filterOn]: {
|
|
172
|
+
_gt: new Date(new Date(arrayFilterValue[1]).setHours(23, 59))
|
|
173
|
+
}
|
|
175
174
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
175
|
+
]
|
|
176
|
+
};
|
|
177
|
+
case "isBetween":
|
|
178
|
+
return {
|
|
179
|
+
[filterOn]: {
|
|
180
|
+
_gte: new Date(arrayFilterValue[0]),
|
|
181
|
+
_lte: new Date(new Date(arrayFilterValue[1]).setHours(23, 59))
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
case "isBefore":
|
|
185
|
+
return { [filterOn]: { _lt: new Date(filterValue) } };
|
|
186
|
+
case "isAfter":
|
|
187
|
+
return { [filterOn]: { _gt: new Date(filterValue) } };
|
|
188
|
+
case "greaterThan":
|
|
189
|
+
return { [filterOn]: { _gt: parseFloat(filterValue) } };
|
|
190
|
+
case "lessThan":
|
|
191
|
+
return { [filterOn]: { _lt: parseFloat(filterValue) } };
|
|
192
|
+
case "inRange":
|
|
193
|
+
return {
|
|
194
|
+
[filterOn]: {
|
|
195
|
+
_gte: parseFloat(arrayFilterValue[0]),
|
|
196
|
+
_lte: parseFloat(arrayFilterValue[1])
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
case "outsideRange":
|
|
200
|
+
return {
|
|
201
|
+
_or: [
|
|
202
|
+
{
|
|
203
|
+
[filterOn]: {
|
|
204
|
+
_lt: parseFloat(arrayFilterValue[0])
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
[filterOn]: {
|
|
209
|
+
_gt: parseFloat(arrayFilterValue[1])
|
|
189
210
|
}
|
|
190
|
-
]
|
|
191
|
-
};
|
|
192
|
-
case "equalTo":
|
|
193
|
-
return {
|
|
194
|
-
[filterOn]: {
|
|
195
|
-
_eq:
|
|
196
|
-
type === "number" || type === "integer"
|
|
197
|
-
? parseFloat(filterValue)
|
|
198
|
-
: filterValue
|
|
199
211
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
212
|
+
]
|
|
213
|
+
};
|
|
214
|
+
case "equalTo":
|
|
215
|
+
return {
|
|
216
|
+
[filterOn]: {
|
|
217
|
+
_eq:
|
|
218
|
+
type === "number" || type === "integer"
|
|
219
|
+
? parseFloat(filterValue)
|
|
220
|
+
: filterValue
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
case "regex":
|
|
224
|
+
return { [filterOn]: { _regex: filterValue } };
|
|
225
|
+
default:
|
|
226
|
+
console.warn(`Unsupported filter type: ${selectedFilter}`);
|
|
227
|
+
return {};
|
|
228
|
+
}
|
|
229
|
+
});
|
|
213
230
|
|
|
214
231
|
if (filterClauses.length > 0) {
|
|
215
232
|
if (Object.keys(where).length > 0) {
|
|
@@ -224,7 +241,7 @@ export function tableQueryParamsToHasuraClauses({
|
|
|
224
241
|
order.forEach(item => {
|
|
225
242
|
const field = item.startsWith("-") ? item.substring(1) : item;
|
|
226
243
|
const direction = item.startsWith("-") ? "desc" : "asc";
|
|
227
|
-
order_by[field]
|
|
244
|
+
order_by.push({ [field]: direction });
|
|
228
245
|
});
|
|
229
246
|
}
|
|
230
247
|
|
|
@@ -14,7 +14,7 @@ describe("tableQueryParamsToHasuraClauses", () => {
|
|
|
14
14
|
const result = tableQueryParamsToHasuraClauses({});
|
|
15
15
|
expect(result).toEqual({
|
|
16
16
|
where: {},
|
|
17
|
-
order_by:
|
|
17
|
+
order_by: [],
|
|
18
18
|
limit: 25,
|
|
19
19
|
offset: 0
|
|
20
20
|
});
|
|
@@ -24,7 +24,7 @@ describe("tableQueryParamsToHasuraClauses", () => {
|
|
|
24
24
|
const result = tableQueryParamsToHasuraClauses({ page: 2, pageSize: 10 });
|
|
25
25
|
expect(result).toEqual({
|
|
26
26
|
where: {},
|
|
27
|
-
order_by:
|
|
27
|
+
order_by: [],
|
|
28
28
|
limit: 10,
|
|
29
29
|
offset: 10
|
|
30
30
|
});
|
|
@@ -39,7 +39,46 @@ describe("tableQueryParamsToHasuraClauses", () => {
|
|
|
39
39
|
where: {
|
|
40
40
|
_or: [{ name: { _ilike: "%test%" } }, { email: { _ilike: "%test%" } }]
|
|
41
41
|
},
|
|
42
|
-
order_by:
|
|
42
|
+
order_by: [],
|
|
43
|
+
limit: 25,
|
|
44
|
+
offset: 0
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
it("should handle searchTerm with string fields with a comma in them", () => {
|
|
48
|
+
const result = tableQueryParamsToHasuraClauses({
|
|
49
|
+
searchTerm: "test,test2",
|
|
50
|
+
schema
|
|
51
|
+
});
|
|
52
|
+
expect(result).toEqual({
|
|
53
|
+
where: {
|
|
54
|
+
_or: [
|
|
55
|
+
{ name: { _ilike: "%test%" } },
|
|
56
|
+
{ name: { _ilike: "%test2%" } },
|
|
57
|
+
{ email: { _ilike: "%test%" } },
|
|
58
|
+
{ email: { _ilike: "%test2%" } }
|
|
59
|
+
]
|
|
60
|
+
},
|
|
61
|
+
order_by: [],
|
|
62
|
+
limit: 25,
|
|
63
|
+
offset: 0
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
it("should flatten queries with dup paths", () => {
|
|
67
|
+
const result = tableQueryParamsToHasuraClauses({
|
|
68
|
+
searchTerm: "test",
|
|
69
|
+
schema: {
|
|
70
|
+
fields: [
|
|
71
|
+
...schema.fields,
|
|
72
|
+
{ path: "name", type: "string" },
|
|
73
|
+
{ path: "name", type: "string" }
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
expect(result).toEqual({
|
|
78
|
+
where: {
|
|
79
|
+
_or: [{ name: { _ilike: "%test%" } }, { email: { _ilike: "%test%" } }]
|
|
80
|
+
},
|
|
81
|
+
order_by: [],
|
|
43
82
|
limit: 25,
|
|
44
83
|
offset: 0
|
|
45
84
|
});
|
|
@@ -58,7 +97,7 @@ describe("tableQueryParamsToHasuraClauses", () => {
|
|
|
58
97
|
{ email: { _ilike: "%30%" } }
|
|
59
98
|
]
|
|
60
99
|
},
|
|
61
|
-
order_by:
|
|
100
|
+
order_by: [],
|
|
62
101
|
limit: 25,
|
|
63
102
|
offset: 0
|
|
64
103
|
});
|
|
@@ -77,7 +116,7 @@ describe("tableQueryParamsToHasuraClauses", () => {
|
|
|
77
116
|
{ email: { _ilike: "%true%" } }
|
|
78
117
|
]
|
|
79
118
|
},
|
|
80
|
-
order_by:
|
|
119
|
+
order_by: [],
|
|
81
120
|
limit: 25,
|
|
82
121
|
offset: 0
|
|
83
122
|
});
|
|
@@ -92,7 +131,7 @@ describe("tableQueryParamsToHasuraClauses", () => {
|
|
|
92
131
|
where: {
|
|
93
132
|
_or: [{ name: { _ilike: "%test%" } }, { email: { _ilike: "%test%" } }]
|
|
94
133
|
},
|
|
95
|
-
order_by:
|
|
134
|
+
order_by: [],
|
|
96
135
|
limit: 25,
|
|
97
136
|
offset: 0
|
|
98
137
|
});
|
|
@@ -110,7 +149,7 @@ describe("tableQueryParamsToHasuraClauses", () => {
|
|
|
110
149
|
});
|
|
111
150
|
expect(result).toEqual({
|
|
112
151
|
where: { _and: [{ name: { _ilike: "%test%" } }] },
|
|
113
|
-
order_by:
|
|
152
|
+
order_by: [],
|
|
114
153
|
limit: 25,
|
|
115
154
|
offset: 0
|
|
116
155
|
});
|
|
@@ -125,7 +164,7 @@ describe("tableQueryParamsToHasuraClauses", () => {
|
|
|
125
164
|
});
|
|
126
165
|
expect(result).toEqual({
|
|
127
166
|
where: { _and: [{ age: { _eq: 30 } }] },
|
|
128
|
-
order_by:
|
|
167
|
+
order_by: [],
|
|
129
168
|
limit: 25,
|
|
130
169
|
offset: 0
|
|
131
170
|
});
|
|
@@ -135,7 +174,7 @@ describe("tableQueryParamsToHasuraClauses", () => {
|
|
|
135
174
|
const result = tableQueryParamsToHasuraClauses({ order: ["name", "-age"] });
|
|
136
175
|
expect(result).toEqual({
|
|
137
176
|
where: {},
|
|
138
|
-
order_by: { name: "asc", age: "desc" },
|
|
177
|
+
order_by: [{ name: "asc" }, { age: "desc" }],
|
|
139
178
|
limit: 25,
|
|
140
179
|
offset: 0
|
|
141
180
|
});
|
|
@@ -168,7 +207,7 @@ describe("tableQueryParamsToHasuraClauses", () => {
|
|
|
168
207
|
{ age: { _gt: 30 } }
|
|
169
208
|
]
|
|
170
209
|
},
|
|
171
|
-
order_by: { name: "asc" },
|
|
210
|
+
order_by: [{ name: "asc" }],
|
|
172
211
|
limit: 10,
|
|
173
212
|
offset: 10
|
|
174
213
|
});
|
|
@@ -198,7 +237,7 @@ describe("tableQueryParamsToHasuraClauses", () => {
|
|
|
198
237
|
{ age: { _gt: 30 } }
|
|
199
238
|
]
|
|
200
239
|
},
|
|
201
|
-
order_by:
|
|
240
|
+
order_by: [],
|
|
202
241
|
limit: 25,
|
|
203
242
|
offset: 0
|
|
204
243
|
});
|
|
@@ -6,13 +6,13 @@ import {
|
|
|
6
6
|
makeDataTableHandlers,
|
|
7
7
|
getQueryParams,
|
|
8
8
|
setCurrentParamsOnUrl,
|
|
9
|
-
getCurrentParamsFromUrl
|
|
10
|
-
getCCDisplayName
|
|
9
|
+
getCurrentParamsFromUrl
|
|
11
10
|
} from "./queryParams";
|
|
12
11
|
import { withRouter } from "react-router-dom";
|
|
13
12
|
import getTableConfigFromStorage from "./getTableConfigFromStorage";
|
|
14
13
|
import { useDeepEqualMemo } from "../../utils/hooks/useDeepEqualMemo";
|
|
15
14
|
import { branch, compose } from "recompose";
|
|
15
|
+
import { getCCDisplayName } from "./tableQueryParamsToHasuraClauses";
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Note all these options can be passed at Design Time or at Runtime (like reduxForm())
|
|
@@ -32,7 +32,6 @@ import { branch, compose } from "recompose";
|
|
|
32
32
|
export const useTableParams = props => {
|
|
33
33
|
const {
|
|
34
34
|
additionalFilter,
|
|
35
|
-
additionalOrFilter,
|
|
36
35
|
controlled_pageSize,
|
|
37
36
|
defaults: _defaults,
|
|
38
37
|
doNotCoercePageSize,
|
|
@@ -166,16 +165,6 @@ export const useTableParams = props => {
|
|
|
166
165
|
);
|
|
167
166
|
|
|
168
167
|
const queryParams = useMemo(() => {
|
|
169
|
-
const additionalFilterToUse =
|
|
170
|
-
typeof additionalFilter === "function"
|
|
171
|
-
? additionalFilter
|
|
172
|
-
: () => additionalFilter;
|
|
173
|
-
|
|
174
|
-
const additionalOrFilterToUse =
|
|
175
|
-
typeof additionalOrFilter === "function"
|
|
176
|
-
? additionalOrFilter
|
|
177
|
-
: () => additionalOrFilter;
|
|
178
|
-
|
|
179
168
|
return getQueryParams({
|
|
180
169
|
doNotCoercePageSize,
|
|
181
170
|
currentParams,
|
|
@@ -185,8 +174,7 @@ export const useTableParams = props => {
|
|
|
185
174
|
schema: convertedSchema,
|
|
186
175
|
isInfinite: isInfinite || (isSimple && !withPaging),
|
|
187
176
|
isLocalCall,
|
|
188
|
-
additionalFilter
|
|
189
|
-
additionalOrFilter: additionalOrFilterToUse,
|
|
177
|
+
additionalFilter,
|
|
190
178
|
noOrderError,
|
|
191
179
|
isCodeModel,
|
|
192
180
|
ownProps: passingProps
|
|
@@ -194,7 +182,6 @@ export const useTableParams = props => {
|
|
|
194
182
|
}, [
|
|
195
183
|
additionalFilter,
|
|
196
184
|
passingProps,
|
|
197
|
-
additionalOrFilter,
|
|
198
185
|
doNotCoercePageSize,
|
|
199
186
|
currentParams,
|
|
200
187
|
entities,
|
package/src/ExcelCell.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/* eslint react/jsx-no-bind: 0 */
|
|
2
|
+
import { Popover } from "@blueprintjs/core";
|
|
3
|
+
import React, { useState } from "react";
|
|
4
|
+
|
|
5
|
+
export default function ExcelCell() {
|
|
6
|
+
const [v, setV] = useState("");
|
|
7
|
+
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
|
|
8
|
+
return (
|
|
9
|
+
<Popover
|
|
10
|
+
onClose={() => {
|
|
11
|
+
setIsPopoverOpen(false);
|
|
12
|
+
}}
|
|
13
|
+
isOpen={isPopoverOpen}
|
|
14
|
+
content={<div>Sum</div>}
|
|
15
|
+
>
|
|
16
|
+
<div
|
|
17
|
+
style={{
|
|
18
|
+
border: "1px solid #ccc",
|
|
19
|
+
padding: 5,
|
|
20
|
+
width: 100,
|
|
21
|
+
height: 30
|
|
22
|
+
}}
|
|
23
|
+
contentEditable
|
|
24
|
+
onInput={e => {
|
|
25
|
+
const text = e.currentTarget.textContent;
|
|
26
|
+
|
|
27
|
+
if (text === "=") {
|
|
28
|
+
// open a popover
|
|
29
|
+
setIsPopoverOpen(true);
|
|
30
|
+
}
|
|
31
|
+
setV(text);
|
|
32
|
+
}}
|
|
33
|
+
>
|
|
34
|
+
{v}
|
|
35
|
+
</div>
|
|
36
|
+
</Popover>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
@@ -788,7 +788,11 @@ const Uploader = ({
|
|
|
788
788
|
.join(", ")
|
|
789
789
|
: undefined
|
|
790
790
|
}
|
|
791
|
-
onDrop={async (_acceptedFiles, rejectedFiles) => {
|
|
791
|
+
onDrop={async (_acceptedFiles, rejectedFiles, e) => {
|
|
792
|
+
const parentDropzone = e.target.closest(".tg-dropzone");
|
|
793
|
+
if (parentDropzone) {
|
|
794
|
+
parentDropzone.blur();
|
|
795
|
+
}
|
|
792
796
|
let acceptedFiles = [];
|
|
793
797
|
for (const file of _acceptedFiles) {
|
|
794
798
|
if ((validateAgainstSchema || autoUnzip) && isZipFile(file)) {
|
|
@@ -114,14 +114,14 @@ function removeUnwantedProps(props) {
|
|
|
114
114
|
|
|
115
115
|
const LabelWithTooltipInfo = ({ label, tooltipInfo, labelStyle }) =>
|
|
116
116
|
tooltipInfo ? (
|
|
117
|
-
<
|
|
117
|
+
<span style={{ display: "flex", alignItems: "center", ...labelStyle }}>
|
|
118
118
|
{label}{" "}
|
|
119
119
|
<InfoHelper
|
|
120
120
|
style={{ marginLeft: "5px", marginTop: "-6px" }}
|
|
121
121
|
size={12}
|
|
122
122
|
content={tooltipInfo}
|
|
123
123
|
/>
|
|
124
|
-
</
|
|
124
|
+
</span>
|
|
125
125
|
) : (
|
|
126
126
|
label || null
|
|
127
127
|
);
|