@teselagen/ui 0.10.4 → 0.10.6

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.
@@ -1,4 +1,4 @@
1
- import { camelCase, set } from "lodash-es";
1
+ import { camelCase, flatMap, set } from "lodash-es";
2
2
 
3
3
  export function tableQueryParamsToHasuraClauses({
4
4
  page,
@@ -24,42 +24,62 @@ export function tableQueryParamsToHasuraClauses({
24
24
  const searchTerms = searchTerm.split(",");
25
25
 
26
26
  schema.fields.forEach(field => {
27
- const { type, path, searchDisabled, isHidden } = field;
28
- if (uniqueFieldsByPath[path]) return; // Skip if already added
29
- uniqueFieldsByPath[path] = true;
30
- if (searchDisabled || field.filterDisabled || type === "color" || isHidden) return;
27
+ const {
28
+ type,
29
+ path,
30
+ additionalSearchPaths = [],
31
+ searchDisabled,
32
+ isHidden
33
+ } = field;
34
+ const allPaths = [path, ...additionalSearchPaths];
35
+ allPaths.forEach(path => {
36
+ addSearchTermFilters(path);
37
+ });
31
38
 
32
- // Process each search term
33
- searchTerms.forEach(term => {
34
- const filterValue = term.trim(); // Trim the term to handle spaces after commas
39
+ function addSearchTermFilters(path) {
40
+ if (uniqueFieldsByPath[path]) return; // Skip if already added
41
+ uniqueFieldsByPath[path] = true;
42
+ if (
43
+ searchDisabled ||
44
+ field.filterDisabled ||
45
+ type === "color" ||
46
+ isHidden ||
47
+ !path
48
+ )
49
+ return;
35
50
 
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);
51
+ // Process each search term
52
+ searchTerms.forEach(term => {
53
+ const filterValue = term.trim(); // Trim the term to handle spaces after commas
54
+
55
+ if (type === "string" || type === "lookup") {
56
+ const o = set({}, path, { _ilike: `%${filterValue}%` });
57
+ searchTermFilters.push(o);
58
+ } else if (type === "boolean") {
59
+ let regex;
60
+ try {
61
+ regex = new RegExp("^" + filterValue, "ig");
62
+ } catch (error) {
63
+ //ignore
64
+ }
65
+ if (regex) {
66
+ if ("true".replace(regex, "") !== "true") {
67
+ const o = set({}, path, { _eq: true });
68
+ searchTermFilters.push(o);
69
+ } else if ("false".replace(regex, "") !== "false") {
70
+ const o = set({}, path, { _eq: false });
71
+ searchTermFilters.push(o);
72
+ }
53
73
  }
74
+ } else if (
75
+ (type === "number" || type === "integer") &&
76
+ !isNaN(filterValue)
77
+ ) {
78
+ const o = set({}, path, { _eq: parseFloat(filterValue) });
79
+ searchTermFilters.push(o);
54
80
  }
55
- } else if (
56
- (type === "number" || type === "integer") &&
57
- !isNaN(filterValue)
58
- ) {
59
- const o = set({}, path, { _eq: parseFloat(filterValue) });
60
- searchTermFilters.push(o);
61
- }
62
- });
81
+ });
82
+ }
63
83
  });
64
84
 
65
85
  if (searchTermFilters.length > 0) {
@@ -72,11 +92,18 @@ export function tableQueryParamsToHasuraClauses({
72
92
  }
73
93
 
74
94
  if (filters && filters.length > 0) {
75
- const filterClauses = filters.map(filter => {
95
+ const filterClauses = flatMap(filters, filter => {
76
96
  let { selectedFilter, filterOn, filterValue } = filter;
77
97
  const fieldSchema = ccFields[filterOn] || {};
78
98
 
79
- const { path, reference, type, customColumnFilter } = fieldSchema;
99
+ const {
100
+ path,
101
+ additionalSearchPaths = [],
102
+ reference,
103
+ type,
104
+ customColumnFilter
105
+ } = fieldSchema;
106
+
80
107
  if (customColumnFilter) {
81
108
  return customColumnFilter(filterValue);
82
109
  }
@@ -110,121 +137,132 @@ export function tableQueryParamsToHasuraClauses({
110
137
 
111
138
  if (reference) {
112
139
  filterOn = reference.sourceField;
140
+ return addColumnFilters(filterOn);
113
141
  } else {
114
- filterOn = path || filterOn;
142
+ if (path) {
143
+ const allPaths = [path, ...additionalSearchPaths];
144
+ return allPaths.map(p => addColumnFilters(p));
145
+ } else {
146
+ return addColumnFilters(filterOn);
147
+ }
115
148
  }
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
149
+
150
+ function addColumnFilters(filterOn) {
151
+ switch (selectedFilter) {
152
+ case "none":
153
+ return {};
154
+ case "startsWith":
155
+ return { [filterOn]: { _ilike: `${filterValue}%` } };
156
+ case "endsWith":
157
+ return { [filterOn]: { _ilike: `%${filterValue}` } };
158
+ case "contains":
159
+ return { [filterOn]: { _ilike: `%${filterValue}%` } };
160
+ case "notContains":
161
+ return { [filterOn]: { _nilike: `%${filterValue}%` } };
162
+ case "isExactly":
163
+ return { [filterOn]: { _eq: filterValue } };
164
+ case "isEmpty":
165
+ if (filterOn.includes(".")) {
166
+ // if we're filtering on a nested field, like a sequence table with parts.name
167
+ // we really want to just query on the top level field's existence
168
+ return {
169
+ _not: {
170
+ [filterOn.split(".")[0]]: {}
171
+ }
172
+ };
173
+ }
133
174
  return {
134
- _not: {
135
- [filterOn.split(".")[0]]: {}
136
- }
175
+ _or: [
176
+ { [filterOn]: { _eq: "" } },
177
+ { [filterOn]: { _is_null: true } }
178
+ ]
137
179
  };
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))
180
+ case "notEmpty":
181
+ return {
182
+ _and: [
183
+ { [filterOn]: { _neq: "" } },
184
+ { [filterOn]: { _is_null: false } }
185
+ ]
186
+ };
187
+ case "inList":
188
+ return { [filterOn]: { _in: filterValue } };
189
+ case "notInList":
190
+ return { [filterOn]: { _nin: filterValue } };
191
+ case "true":
192
+ return { [filterOn]: { _eq: true } };
193
+ case "false":
194
+ return { [filterOn]: { _eq: false } };
195
+ case "dateIs":
196
+ return { [filterOn]: { _eq: filterValue } };
197
+ case "notBetween":
198
+ return {
199
+ _or: [
200
+ {
201
+ [filterOn]: {
202
+ _lt: new Date(arrayFilterValue[0])
203
+ }
204
+ },
205
+ {
206
+ [filterOn]: {
207
+ _gt: new Date(
208
+ new Date(arrayFilterValue[1]).setHours(23, 59)
209
+ )
210
+ }
173
211
  }
212
+ ]
213
+ };
214
+ case "isBetween":
215
+ return {
216
+ [filterOn]: {
217
+ _gte: new Date(arrayFilterValue[0]),
218
+ _lte: new Date(new Date(arrayFilterValue[1]).setHours(23, 59))
174
219
  }
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])
220
+ };
221
+ case "isBefore":
222
+ return { [filterOn]: { _lt: new Date(filterValue) } };
223
+ case "isAfter":
224
+ return { [filterOn]: { _gt: new Date(filterValue) } };
225
+ case "greaterThan":
226
+ return { [filterOn]: { _gt: parseFloat(filterValue) } };
227
+ case "lessThan":
228
+ return { [filterOn]: { _lt: parseFloat(filterValue) } };
229
+ case "inRange":
230
+ return {
231
+ [filterOn]: {
232
+ _gte: parseFloat(arrayFilterValue[0]),
233
+ _lte: parseFloat(arrayFilterValue[1])
234
+ }
235
+ };
236
+ case "outsideRange":
237
+ return {
238
+ _or: [
239
+ {
240
+ [filterOn]: {
241
+ _lt: parseFloat(arrayFilterValue[0])
242
+ }
243
+ },
244
+ {
245
+ [filterOn]: {
246
+ _gt: parseFloat(arrayFilterValue[1])
247
+ }
210
248
  }
249
+ ]
250
+ };
251
+ case "equalTo":
252
+ return {
253
+ [filterOn]: {
254
+ _eq:
255
+ type === "number" || type === "integer"
256
+ ? parseFloat(filterValue)
257
+ : filterValue
211
258
  }
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 {};
259
+ };
260
+ case "regex":
261
+ return { [filterOn]: { _regex: filterValue } };
262
+ default:
263
+ console.warn(`Unsupported filter type: ${selectedFilter}`);
264
+ return {};
265
+ }
228
266
  }
229
267
  });
230
268
 
@@ -49,7 +49,6 @@ export const useTableParams = props => {
49
49
  orderByFirstColumn,
50
50
  pageSize,
51
51
  schema,
52
- syncDisplayOptionsToDb,
53
52
  tableParams: _tableParams,
54
53
  urlConnected,
55
54
  withDisplayOptions,
@@ -164,13 +163,13 @@ export const useTableParams = props => {
164
163
  _tableConfig?.userSetPageSize &&
165
164
  parseInt(_tableConfig.userSetPageSize, 10);
166
165
  let _defaultsToUse = defaults;
167
- if (!syncDisplayOptionsToDb && userSetPageSize) {
166
+ if (userSetPageSize) {
168
167
  _defaultsToUse = _defaultsToUse || {};
169
168
  _defaultsToUse.pageSize = userSetPageSize;
170
169
  }
171
170
 
172
171
  return _defaultsToUse;
173
- }, [defaults, formName, syncDisplayOptionsToDb]);
172
+ }, [defaults, formName]);
174
173
 
175
174
  const passingProps = useMemo(
176
175
  () => ({
@@ -5,7 +5,6 @@ import { reduce } from "lodash-es";
5
5
  export const viewColumn = {
6
6
  width: 35,
7
7
  noEllipsis: true,
8
- hideInMenu: true,
9
8
  immovable: true,
10
9
  type: "action",
11
10
  render: () => {
@@ -429,6 +429,8 @@ class TgSelect extends React.Component {
429
429
  }
430
430
  },
431
431
  inputProps: {
432
+ autoComplete: "off",
433
+ name: "tg-multiselect-input",
432
434
  autoFocus: autoFocus || autoOpen,
433
435
  onBlur,
434
436
  ...(tagInputProps && tagInputProps.inputProps)
package/ui.css CHANGED
@@ -9721,7 +9721,11 @@ body:not(.drag-active)
9721
9721
  user-select: none;
9722
9722
  background: #f7f7f7;
9723
9723
  }
9724
-
9724
+ /* disable the table header interactions while the table is loading */
9725
+ .ReactTable.loading .rt-thead {
9726
+ opacity: 0.7;
9727
+ pointer-events: none;
9728
+ }
9725
9729
  .ReactTable .rt-thead {
9726
9730
  box-shadow: none;
9727
9731
  border-bottom: 1px solid rgba(0, 0, 0, 0.05);
@@ -9889,10 +9893,6 @@ body:not(.drag-active)
9889
9893
  padding-left: 2px;
9890
9894
  }
9891
9895
 
9892
- .ReactTable .-loading.disabled {
9893
- cursor: not-allowed;
9894
- }
9895
-
9896
9896
  /* to get the height to resize based on its container: */
9897
9897
  .ReactTable {
9898
9898
  height: 100%;
@@ -10008,14 +10008,6 @@ body:not(.drag-active)
10008
10008
  color: inherit !important;
10009
10009
  }
10010
10010
 
10011
- .bp3-dark .ReactTable .-loading {
10012
- background: #30404d !important;
10013
- }
10014
-
10015
- .bp3-dark .ReactTable .-loading > div {
10016
- color: #f5f8fa !important;
10017
- }
10018
-
10019
10011
  .bp3-dark .ReactTable .rt-tr-group.selected {
10020
10012
  background: #26738cb0 !important;
10021
10013
  }
@@ -10074,6 +10066,19 @@ body:not(.drag-active)
10074
10066
  display: flex;
10075
10067
  flex-direction: column;
10076
10068
  }
10069
+ .th-dragging {
10070
+ z-index: 999 !important;
10071
+ cursor: grabbing !important;
10072
+ opacity: 0.8;
10073
+ background-color: #f5f8fa;
10074
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
10075
+ }
10076
+
10077
+ .bp3-dark .th-dragging {
10078
+ background-color: #30404d;
10079
+ box-shadow: 0 2px 8px rgba(250, 245, 245, 0.15);
10080
+ outline: 1px solid #48aff0;
10081
+ }
10077
10082
  .dna-loader {
10078
10083
  display: inline-block;
10079
10084
  position: relative;