@teselagen/ui 0.7.35 → 0.8.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.
Files changed (128) hide show
  1. package/index.cjs.js +1 -2
  2. package/index.es.js +1 -2
  3. package/package.json +1 -1
  4. package/src/DataTable/Columns.js +1 -1
  5. package/src/DataTable/DisplayOptions.js +1 -1
  6. package/src/DataTable/FilterAndSortMenu.js +30 -27
  7. package/src/DataTable/index.js +14 -3
  8. package/src/DataTable/utils/queryParams.js +771 -64
  9. package/src/DataTable/utils/withTableParams.js +16 -3
  10. package/src/index.js +0 -1
  11. package/src/utils/isBeingCalledExcessively.js +14 -7
  12. package/AdvancedOptions.js +0 -33
  13. package/AssignDefaultsModeContext.js +0 -22
  14. package/CellDragHandle.js +0 -132
  15. package/ColumnFilterMenu.js +0 -62
  16. package/Columns.js +0 -979
  17. package/DataTable/utils/filterLocalEntitiesToHasura.d.ts +0 -5
  18. package/DataTable/utils/initializeHasuraWhereAndFilter.d.ts +0 -2
  19. package/DataTable/utils/tableQueryParamsToHasuraClauses.d.ts +0 -26
  20. package/DisabledLoadingComponent.js +0 -15
  21. package/DisplayOptions.js +0 -199
  22. package/DropdownButton.js +0 -36
  23. package/DropdownCell.js +0 -61
  24. package/EditableCell.js +0 -44
  25. package/FillWindow.css +0 -6
  26. package/FillWindow.js +0 -69
  27. package/FilterAndSortMenu.js +0 -391
  28. package/FormSeparator.js +0 -9
  29. package/LoadingDots.js +0 -14
  30. package/MatchHeaders.js +0 -234
  31. package/PagingTool.js +0 -225
  32. package/RenderCell.js +0 -191
  33. package/SearchBar.js +0 -69
  34. package/SimpleStepViz.js +0 -22
  35. package/SortableColumns.js +0 -100
  36. package/TableFormTrackerContext.js +0 -10
  37. package/Tag.js +0 -112
  38. package/ThComponent.js +0 -44
  39. package/TimelineEvent.js +0 -31
  40. package/UploadCsvWizard.css +0 -4
  41. package/UploadCsvWizard.js +0 -719
  42. package/Uploader.js +0 -1278
  43. package/adHoc.js +0 -10
  44. package/autoTooltip.js +0 -201
  45. package/basicHandleActionsWithFullState.js +0 -14
  46. package/browserUtils.js +0 -3
  47. package/combineReducersWithFullState.js +0 -14
  48. package/commandControls.js +0 -82
  49. package/commandUtils.js +0 -112
  50. package/constants.js +0 -1
  51. package/convertSchema.js +0 -69
  52. package/customIcons.js +0 -361
  53. package/dataTableEnhancer.js +0 -41
  54. package/defaultFormatters.js +0 -32
  55. package/defaultValidators.js +0 -40
  56. package/determineBlackOrWhiteTextColor.js +0 -4
  57. package/editCellHelper.js +0 -44
  58. package/formatPasteData.js +0 -16
  59. package/getAllRows.js +0 -11
  60. package/getCellCopyText.js +0 -7
  61. package/getCellInfo.js +0 -36
  62. package/getCellVal.js +0 -20
  63. package/getDayjsFormatter.js +0 -35
  64. package/getFieldPathToField.js +0 -7
  65. package/getIdOrCodeOrIndex.js +0 -9
  66. package/getLastSelectedEntity.js +0 -11
  67. package/getNewEntToSelect.js +0 -25
  68. package/getNewName.js +0 -31
  69. package/getRowCopyText.js +0 -28
  70. package/getTableConfigFromStorage.js +0 -5
  71. package/getTextFromEl.js +0 -28
  72. package/getVals.js +0 -8
  73. package/handleCopyColumn.js +0 -21
  74. package/handleCopyHelper.js +0 -15
  75. package/handleCopyRows.js +0 -23
  76. package/handleCopyTable.js +0 -16
  77. package/handlerHelpers.js +0 -24
  78. package/hotkeyUtils.js +0 -131
  79. package/index.js +0 -1
  80. package/isBeingCalledExcessively.js +0 -32
  81. package/isBottomRightCornerOfRectangle.js +0 -20
  82. package/isEntityClean.js +0 -15
  83. package/isTruthy.js +0 -12
  84. package/isValueEmpty.js +0 -3
  85. package/itemUpload.js +0 -84
  86. package/menuUtils.js +0 -433
  87. package/popoverOverflowModifiers.js +0 -11
  88. package/primarySelectedValue.js +0 -1
  89. package/pureNoFunc.js +0 -31
  90. package/queryParams.js +0 -1058
  91. package/removeCleanRows.js +0 -22
  92. package/renderOnDoc.js +0 -32
  93. package/rerenderOnWindowResize.js +0 -26
  94. package/rowClick.js +0 -181
  95. package/selection.js +0 -8
  96. package/showAppSpinner.js +0 -12
  97. package/showDialogOnDocBody.js +0 -33
  98. package/showProgressToast.js +0 -22
  99. package/sortify.js +0 -73
  100. package/src/DataTable/utils/filterLocalEntitiesToHasura.js +0 -236
  101. package/src/DataTable/utils/filterLocalEntitiesToHasura.test.js +0 -587
  102. package/src/DataTable/utils/initializeHasuraWhereAndFilter.js +0 -26
  103. package/src/DataTable/utils/tableQueryParamsToHasuraClauses.js +0 -253
  104. package/src/DataTable/utils/tableQueryParamsToHasuraClauses.test.js +0 -206
  105. package/style.css +0 -29
  106. package/tagUtils.js +0 -45
  107. package/tgFormValues.js +0 -35
  108. package/tg_modalState.js +0 -47
  109. package/throwFormError.js +0 -16
  110. package/toastr.js +0 -148
  111. package/tryToMatchSchemas.js +0 -264
  112. package/typeToCommonType.js +0 -6
  113. package/useDeepEqualMemo.js +0 -15
  114. package/useDialog.js +0 -63
  115. package/useStableReference.js +0 -9
  116. package/useTableEntities.js +0 -38
  117. package/useTraceUpdate.js +0 -19
  118. package/utils.js +0 -37
  119. package/validateTableWideErrors.js +0 -160
  120. package/viewColumn.js +0 -97
  121. package/withField.js +0 -20
  122. package/withFields.js +0 -11
  123. package/withLocalStorage.js +0 -11
  124. package/withSelectTableRecords.js +0 -43
  125. package/withSelectedEntities.js +0 -65
  126. package/withStore.js +0 -10
  127. package/withTableParams.js +0 -301
  128. package/wrapDialog.js +0 -116
@@ -1,22 +0,0 @@
1
- import { isEntityClean } from "./isEntityClean";
2
- import { getIdOrCodeOrIndex } from "./getIdOrCodeOrIndex";
3
-
4
- export const removeCleanRows = (entities, cellValidation) => {
5
- const toFilterOut = {};
6
- const entsToUse = (entities || []).filter(e => {
7
- if (!(e._isClean || isEntityClean(e))) return true;
8
- else {
9
- toFilterOut[getIdOrCodeOrIndex(e)] = true;
10
- return false;
11
- }
12
- });
13
-
14
- const validationToUse = {};
15
- Object.entries(cellValidation || {}).forEach(([k, v]) => {
16
- const [rowId] = k.split(":");
17
- if (!toFilterOut[rowId]) {
18
- validationToUse[k] = v;
19
- }
20
- });
21
- return { entsToUse, validationToUse };
22
- };
package/renderOnDoc.js DELETED
@@ -1,32 +0,0 @@
1
- import { createRoot } from "react-dom/client";
2
-
3
- export function renderOnDoc(fn) {
4
- const elemDiv = document.createElement("div");
5
- elemDiv.style.cssText =
6
- "position:absolute;width:100%;height:100%;top:0px;opacity:0.3;z-index:0;";
7
- document.body.appendChild(elemDiv);
8
- const root = createRoot(elemDiv);
9
- const handleClose = () => {
10
- setTimeout(() => {
11
- root.unmount(elemDiv);
12
- document.body.removeChild(elemDiv);
13
- });
14
- };
15
- root.render(fn(handleClose));
16
- }
17
-
18
- export function renderOnDocSimple(el) {
19
- const elemDiv = document.createElement("div");
20
- elemDiv.style.cssText =
21
- "position:absolute;width:100%;height:100%;top:0px;opacity:1;z-index:10000;";
22
- document.body.appendChild(elemDiv);
23
- const root = createRoot(elemDiv);
24
- root.render(el);
25
- const handleClose = () => {
26
- setTimeout(() => {
27
- root.unmount();
28
- document.body.removeChild(elemDiv);
29
- });
30
- };
31
- return handleClose;
32
- }
@@ -1,26 +0,0 @@
1
- import { throttle } from "lodash-es";
2
- // use like this within a react component:
3
-
4
- // constructor(props){
5
- // super(props)
6
- // rerenderOnWindowResize(this)
7
- // }
8
-
9
- export default function rerenderOnWindowResize(that) {
10
- that.updateDimensions = throttle(() => {
11
- if (that.props.disabled) return;
12
- that.forceUpdate();
13
- }, 250);
14
- const componentDidMount = that.componentDidMount;
15
- const componentWillUnmount = that.componentWillUnmount;
16
-
17
- that.componentDidMount = (...args) => {
18
- componentDidMount && componentDidMount.bind(that)(...args);
19
- window.addEventListener("resize", that.updateDimensions);
20
- };
21
-
22
- that.componentWillUnmount = (...args) => {
23
- componentWillUnmount && componentWillUnmount.bind(that)(...args);
24
- window.removeEventListener("resize", that.updateDimensions);
25
- };
26
- }
package/rowClick.js DELETED
@@ -1,181 +0,0 @@
1
- import { isEmpty, forEach, range } from "lodash-es";
2
- import { getSelectedRowsFromEntities } from "./selection";
3
- import { getIdOrCodeOrIndex } from "./getIdOrCodeOrIndex";
4
- import { getRecordsFromIdMap } from "./withSelectedEntities";
5
-
6
- export default function rowClick(
7
- e,
8
- rowInfo,
9
- entities,
10
- {
11
- reduxFormSelectedEntityIdMap,
12
- isSingleSelect,
13
- noSelect,
14
- onRowClick,
15
- isEntityDisabled,
16
- withCheckboxes,
17
- onDeselect,
18
- onSingleRowSelect,
19
- onMultiRowSelect,
20
- noDeselectAll,
21
- onRowSelect,
22
- change
23
- }
24
- ) {
25
- const entity = rowInfo.original;
26
- onRowClick(e, entity, rowInfo);
27
- if (noSelect || isEntityDisabled(entity)) return;
28
- const rowId = getIdOrCodeOrIndex(entity, rowInfo.index);
29
- if (rowId === undefined) return;
30
- const ctrl = e.metaKey || e.ctrlKey || (withCheckboxes && !e.shiftKey);
31
- const oldIdMap = reduxFormSelectedEntityIdMap || {};
32
- const rowSelected = oldIdMap[rowId];
33
- let newIdMap = {
34
- [rowId]: {
35
- time: Date.now(),
36
- entity
37
- }
38
- };
39
-
40
- if (isSingleSelect) {
41
- if (rowSelected) newIdMap = {};
42
- } else if (rowSelected && e.shiftKey) return;
43
- else if (rowSelected && ctrl) {
44
- newIdMap = {
45
- ...oldIdMap
46
- };
47
- delete newIdMap[rowId];
48
- } else if (rowSelected) {
49
- newIdMap = {};
50
- } else if (ctrl) {
51
- newIdMap = {
52
- ...oldIdMap,
53
- ...newIdMap
54
- };
55
- } else if (e.shiftKey && !isEmpty(oldIdMap)) {
56
- newIdMap = {
57
- [rowId]: {
58
- entity,
59
- time: Date.now()
60
- }
61
- };
62
- const currentlySelectedRowIndices = getSelectedRowsFromEntities(
63
- entities,
64
- oldIdMap
65
- );
66
- if (currentlySelectedRowIndices.length) {
67
- let timeToBeat = {
68
- id: null,
69
- time: null
70
- };
71
- forEach(oldIdMap, ({ time }, key) => {
72
- if (time && time > timeToBeat.time)
73
- timeToBeat = {
74
- id: key,
75
- time
76
- };
77
- });
78
- const mostRecentlySelectedIndex = entities.findIndex((e, i) => {
79
- let id = getIdOrCodeOrIndex(e, i);
80
- if (!id && id !== 0) id = "";
81
- return id.toString() === timeToBeat.id;
82
- });
83
-
84
- if (mostRecentlySelectedIndex !== -1) {
85
- const highRange =
86
- rowInfo.index < mostRecentlySelectedIndex
87
- ? mostRecentlySelectedIndex - 1
88
- : rowInfo.index;
89
- const lowRange =
90
- rowInfo.index > mostRecentlySelectedIndex
91
- ? mostRecentlySelectedIndex + 1
92
- : rowInfo.index;
93
- range(lowRange, highRange + 1).forEach(i => {
94
- if (isEntityDisabled && isEntityDisabled(entities[i])) {
95
- return;
96
- }
97
- const recordId = entities[i] && getIdOrCodeOrIndex(entities[i], i);
98
- if (recordId || recordId === 0)
99
- // newIdMap[recordId] = { entity: entities[i] };
100
- newIdMap[recordId] = { entity: entities[i], time: Date.now() };
101
- });
102
- newIdMap = {
103
- ...oldIdMap,
104
- ...newIdMap
105
- };
106
- if (newIdMap[rowId]) {
107
- //the entity we just clicked on should have the "freshest" time
108
- newIdMap[rowId].time = Date.now() + 1;
109
- }
110
- }
111
- }
112
- }
113
-
114
- finalizeSelection({
115
- idMap: newIdMap,
116
- entities,
117
- props: {
118
- onDeselect,
119
- onSingleRowSelect,
120
- onMultiRowSelect,
121
- noDeselectAll,
122
- onRowSelect,
123
- noSelect,
124
- change
125
- }
126
- });
127
- }
128
-
129
- export function changeSelectedEntities({ idMap, entities = [], change }) {
130
- const newIdMap = { ...idMap };
131
- const entityIdToIndex = {};
132
- entities.forEach((e, i) => {
133
- entityIdToIndex[getIdOrCodeOrIndex(e, 0)] = i;
134
- });
135
- // we want to store the index of the entity so that it can be used to preserve order in selection
136
- Object.keys(newIdMap).forEach(key => {
137
- if (!newIdMap[key]) return;
138
- const rowIndex =
139
- entityIdToIndex[getIdOrCodeOrIndex(newIdMap[key].entity, 0)];
140
- newIdMap[key] = {
141
- ...newIdMap[key],
142
- rowIndex: rowIndex === undefined ? 10000000 : rowIndex
143
- };
144
- });
145
-
146
- change("reduxFormSelectedEntityIdMap", newIdMap);
147
- }
148
-
149
- export function finalizeSelection({
150
- idMap,
151
- entities,
152
- props: {
153
- onDeselect,
154
- onSingleRowSelect,
155
- onMultiRowSelect,
156
- noDeselectAll,
157
- onRowSelect,
158
- noSelect,
159
- change
160
- }
161
- }) {
162
- if (noSelect) return;
163
- if (
164
- noDeselectAll &&
165
- Object.keys(idMap).filter(id => {
166
- return idMap[id];
167
- }).length === 0
168
- ) {
169
- return;
170
- }
171
-
172
- changeSelectedEntities({ idMap, entities, change });
173
- const selectedRecords = getRecordsFromIdMap(idMap);
174
- onRowSelect(selectedRecords);
175
-
176
- selectedRecords.length === 0
177
- ? onDeselect()
178
- : selectedRecords.length > 1
179
- ? onMultiRowSelect(selectedRecords)
180
- : onSingleRowSelect(selectedRecords[0]);
181
- }
package/selection.js DELETED
@@ -1,8 +0,0 @@
1
- import { getIdOrCodeOrIndex } from "./getIdOrCodeOrIndex";
2
-
3
- export const getSelectedRowsFromEntities = (entities, idMap) => {
4
- if (!idMap) return [];
5
- return entities.reduce((acc, entity, i) => {
6
- return idMap[getIdOrCodeOrIndex(entity, i)] ? acc.concat(i) : acc;
7
- }, []);
8
- };
package/showAppSpinner.js DELETED
@@ -1,12 +0,0 @@
1
- import React from "react";
2
- import { Overlay } from "@blueprintjs/core";
3
- import { renderOnDocSimple } from "./utils/renderOnDoc";
4
- import Loading from "./Loading";
5
-
6
- export default function showAppSpinner() {
7
- return renderOnDocSimple(
8
- <Overlay isOpen={true}>
9
- <Loading centeredInPage loading></Loading>
10
- </Overlay>
11
- );
12
- }
@@ -1,33 +0,0 @@
1
- import { createRoot } from "react-dom/client";
2
- import React from "react";
3
- // import withDialog from "./enhancers/withDialog";
4
- import { Dialog } from "@blueprintjs/core";
5
- import { nanoid } from "nanoid";
6
-
7
- //this is only really useful for unconnected standalone simple dialogs
8
- //remember to pass usePortal={false} to the <Dialog/> component so it will close properly
9
- export default function showDialogOnDocBody(DialogComp, options = {}) {
10
- const dialogHolder = document.createElement("div");
11
- const className = "myDialog" + nanoid();
12
- dialogHolder.className = className;
13
- document.body.appendChild(dialogHolder);
14
- const onClose = () => {
15
- document.querySelector("." + className).remove();
16
- };
17
- let DialogCompToUse;
18
- if (options.addDialogContainer) {
19
- DialogCompToUse = props => {
20
- return (
21
- <Dialog usePortal={false} title="pass a {title} prop" isOpen {...props}>
22
- <DialogComp {...props} hideModal={onClose} onClose={onClose} />
23
- </Dialog>
24
- );
25
- };
26
- } else {
27
- DialogCompToUse = DialogComp;
28
- }
29
- const root = createRoot(dialogHolder);
30
- root.render(
31
- <DialogCompToUse hideModal={onClose} onClose={onClose} {...options} />
32
- );
33
- }
@@ -1,22 +0,0 @@
1
- /* Copyright (C) 2018 TeselaGen Biotechnology, Inc. */
2
- import React from "react";
3
- import { ProgressBar } from "@blueprintjs/core";
4
-
5
- export default (message, value, key, opts) => {
6
- return window.toastr.default(
7
- <div>
8
- <div style={{ marginBottom: 10 }}>{message}</div>
9
- <ProgressBar
10
- intent={value >= 1 ? "success" : "primary"}
11
- animate={value < 1 || !value}
12
- stripes={value < 1 || !value}
13
- value={value}
14
- />
15
- </div>,
16
- {
17
- timeout: value >= 1 ? 3000 : 100000,
18
- key,
19
- ...opts
20
- }
21
- );
22
- };
package/sortify.js DELETED
@@ -1,73 +0,0 @@
1
- /*!
2
- * Copyright 2015-2016 Thomas Rosenau
3
- *
4
- * Licensed under the Apache License, Version 2.0 (the "License");
5
- * you may not use this file except in compliance with the License.
6
- * You may obtain a copy of the License at
7
- *
8
- * http://www.apache.org/licenses/LICENSE-2.0
9
- *
10
- * Unless required by applicable law or agreed to in writing, software
11
- * distributed under the License is distributed on an "AS IS" BASIS,
12
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- * See the License for the specific language governing permissions and
14
- * limitations under the License.
15
- */
16
-
17
- /**
18
- * Create a “sorted” version of an object.
19
- *
20
- * JS engines internally keep track of an object's keys in the order of
21
- * creation time, i.e. {a:1,b:2} is treated differently from {b:2,a:1}.
22
- * That difference can be seen when JSON.stringify is called on that object.
23
- * This function normalizes any kind of object by rearranging the keys in
24
- * alphabetical order (numerical keys first, since v8 does so, and there's
25
- * nothing we can do about it).
26
- * @param {*} o The object to be sorted
27
- */
28
-
29
- /* eslint-disable */
30
- const sortKeys = o => {
31
- if (Array.isArray(o)) {
32
- return o.map(sortKeys);
33
- } else if (o instanceof Object) {
34
- // put numeric keys first
35
- let numeric = [];
36
- let nonNumeric = [];
37
- Object.keys(o).forEach(key => {
38
- if (/^(0|[1-9][0-9]*)$/.test(key)) {
39
- numeric.push(+key);
40
- } else {
41
- nonNumeric.push(key);
42
- }
43
- });
44
- // do the rearrangement
45
- return numeric
46
- .sort(function (a, b) {
47
- return a - b;
48
- })
49
- .concat(nonNumeric.sort())
50
- .reduce((result, key) => {
51
- result[key] = sortKeys(o[key]); // recurse!
52
- return result;
53
- }, {});
54
- }
55
- return o;
56
- };
57
-
58
- const jsonStringify = JSON.stringify.bind(JSON);
59
-
60
- const sortify = (value, replacer, space) => {
61
- // replacer, toJSON(), cyclic references and other stuff is better handled by native stringifier.
62
- // So we do JSON.stringify(sortKeys( JSON.parse(JSON.stringify()) )).
63
- // This approach is slightly slower but much safer than a manual stringification.
64
- let nativeJson = jsonStringify(value, replacer, 0);
65
- if (!nativeJson || (nativeJson[0] !== "{" && nativeJson[0] !== "[")) {
66
- // if value is not an Object or Array
67
- return nativeJson;
68
- }
69
- let cleanObj = JSON.parse(nativeJson);
70
- return jsonStringify(sortKeys(cleanObj), null, space);
71
- };
72
-
73
- export default sortify;
@@ -1,236 +0,0 @@
1
- import {
2
- isEmpty,
3
- every,
4
- some,
5
- isEqual,
6
- isString,
7
- isNull,
8
- isArray,
9
- includes,
10
- isObject,
11
- has,
12
- orderBy
13
- } from "lodash-es";
14
-
15
- export function filterLocalEntitiesToHasura(
16
- records,
17
- { where, order_by, limit, offset, isInfinite } = {}
18
- ) {
19
- let filteredRecords = [...records];
20
-
21
- // Apply where clause if it exists
22
- if (where) {
23
- filteredRecords = applyWhereClause(filteredRecords, where);
24
- }
25
-
26
- // Apply order_by if it exists
27
- if (order_by) {
28
- filteredRecords = applyOrderBy(filteredRecords, order_by);
29
- }
30
-
31
- // Store the complete filtered and ordered records for pagination info
32
- const allFilteredRecords = [...filteredRecords];
33
-
34
- // Apply limit and offset
35
- if (!isInfinite && offset !== undefined) {
36
- filteredRecords = filteredRecords.slice(offset);
37
- }
38
-
39
- if (!isInfinite && limit !== undefined) {
40
- filteredRecords = filteredRecords.slice(0, limit);
41
- }
42
-
43
- // For consistency, always return an object with entities, entitiesAcrossPages, and entityCount
44
- return {
45
- entities: filteredRecords,
46
- entitiesAcrossPages: allFilteredRecords,
47
- entityCount: allFilteredRecords.length
48
- };
49
- }
50
-
51
- function applyWhereClause(records, where) {
52
- function applyFilter(record, filter) {
53
- if (isEmpty(filter)) {
54
- return true; // No filter, all records pass
55
- }
56
-
57
- for (const key in filter) {
58
- if (key === "_and") {
59
- if (isEmpty(filter[key])) {
60
- continue;
61
- }
62
- if (!every(filter[key], subFilter => applyFilter(record, subFilter))) {
63
- return false;
64
- }
65
- } else if (key === "_or") {
66
- if (isEmpty(filter[key])) {
67
- continue;
68
- }
69
- if (!some(filter[key], subFilter => applyFilter(record, subFilter))) {
70
- return false;
71
- }
72
- } else if (key === "_not") {
73
- if (applyFilter(record, filter[key])) {
74
- return false;
75
- }
76
- } else {
77
- const value = record[key];
78
- const conditions = filter[key];
79
-
80
- // Handle nested object properties
81
- if (
82
- isObject(value) &&
83
- isObject(conditions) &&
84
- !hasOperator(conditions)
85
- ) {
86
- return applyFilter(value, conditions);
87
- }
88
-
89
- for (const operator in conditions) {
90
- const conditionValue = conditions[operator];
91
-
92
- // Handle range conditions (_gt/_lt or _gte/_lte combinations)
93
- if (operator === "_gt" && conditions._lt) {
94
- if (!(value > conditionValue && value < conditions._lt))
95
- return false;
96
- continue;
97
- }
98
- if (operator === "_gte" && conditions._lte) {
99
- if (!(value >= conditionValue && value <= conditions._lte))
100
- return false;
101
- continue;
102
- }
103
-
104
- switch (operator) {
105
- case "_eq":
106
- if (!isEqual(value, conditionValue)) return false;
107
- break;
108
- case "_neq":
109
- if (isEqual(value, conditionValue)) return false;
110
- break;
111
- case "_gt":
112
- if (!(value > conditionValue)) return false;
113
- break;
114
- case "_gte":
115
- if (!(value >= conditionValue)) return false;
116
- break;
117
- case "_lt":
118
- if (!(value < conditionValue)) return false;
119
- break;
120
- case "_lte":
121
- if (!(value <= conditionValue)) return false;
122
- break;
123
- case "_like":
124
- if (
125
- !isString(value) ||
126
- !new RegExp(conditionValue.replace(/%/g, ".*")).test(value)
127
- )
128
- return false;
129
- break;
130
- case "_ilike":
131
- if (
132
- !isString(value) ||
133
- !new RegExp(conditionValue.replace(/%/g, ".*"), "i").test(value)
134
- )
135
- return false;
136
- break;
137
- case "_nlike":
138
- if (
139
- !isString(value) ||
140
- new RegExp(conditionValue.replace(/%/g, ".*")).test(value)
141
- )
142
- return false;
143
- break;
144
- case "_nilike":
145
- if (
146
- !isString(value) ||
147
- new RegExp(conditionValue.replace(/%/g, ".*"), "i").test(value)
148
- )
149
- return false;
150
- break;
151
- case "_starts_with":
152
- if (!isString(value) || !value.startsWith(conditionValue))
153
- return false;
154
- break;
155
- case "_ends_with":
156
- if (!isString(value) || !value.endsWith(conditionValue))
157
- return false;
158
- break;
159
- case "_is_null":
160
- if (
161
- (conditionValue && !isNull(value)) ||
162
- (!conditionValue && isNull(value))
163
- )
164
- return false;
165
- break;
166
- case "_contains":
167
- if (
168
- !isArray(value) ||
169
- !every(conditionValue, item => includes(value, item))
170
- )
171
- return false;
172
- break;
173
- case "_contained_in":
174
- if (
175
- !isArray(value) ||
176
- !every(value, item => includes(conditionValue, item))
177
- )
178
- return false;
179
- break;
180
- case "_has_key":
181
- if (!isObject(value) || !has(value, conditionValue)) return false;
182
- break;
183
- case "_has_keys_any":
184
- if (
185
- !isObject(value) ||
186
- !some(conditionValue, item => has(value, item))
187
- )
188
- return false;
189
- break;
190
- case "_has_keys_all":
191
- if (
192
- !isObject(value) ||
193
- !every(conditionValue, item => has(value, item))
194
- )
195
- return false;
196
- break;
197
- case "_similar":
198
- if (
199
- !isString(value) ||
200
- !new RegExp(conditionValue.replace(/%/g, ".*")).test(value)
201
- )
202
- return false;
203
- break;
204
- default:
205
- if (operator.startsWith("_")) {
206
- console.warn(`Unsupported operator: ${operator}`);
207
- return false;
208
- } else {
209
- console.warn(`Unsupported operator: ${operator}`);
210
- return false;
211
- }
212
- }
213
- }
214
- }
215
- }
216
-
217
- return true;
218
- }
219
-
220
- // Helper to check if an object contains any Hasura operators
221
- function hasOperator(obj) {
222
- return Object.keys(obj).some(key => key.startsWith("_"));
223
- }
224
-
225
- return records.filter(record => applyFilter(record, where));
226
- }
227
-
228
- function applyOrderBy(records, order_by) {
229
- const keys = Object.keys(order_by);
230
- if (keys.length > 0) {
231
- const field = keys[0];
232
- const direction = order_by[field] === "asc" ? "asc" : "desc";
233
- return orderBy(records, [field], [direction]);
234
- }
235
- return records;
236
- }