@truedat/qx 5.12.2 → 5.12.7

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 (52) hide show
  1. package/package.json +8 -3
  2. package/src/api.js +3 -1
  3. package/src/components/QxContext.js +3 -0
  4. package/src/components/QxRoutes.js +6 -1
  5. package/src/components/common/DescriptionInput.js +47 -0
  6. package/src/components/common/TestFormWrapper.js +33 -0
  7. package/src/components/common/TypeSelector.js +33 -0
  8. package/src/components/common/index.js +4 -0
  9. package/src/components/functions/FunctionEditor.js +200 -0
  10. package/src/components/functions/FunctionParams.js +122 -0
  11. package/src/components/functions/Functions.js +152 -0
  12. package/src/components/functions/__tests__/FunctionEditor.spec.js +195 -0
  13. package/src/components/functions/__tests__/FunctionParams.spec.js +108 -0
  14. package/src/components/functions/__tests__/Functions.spec.js +95 -0
  15. package/src/components/functions/__tests__/__snapshots__/FunctionEditor.spec.js.snap +1563 -0
  16. package/src/components/functions/__tests__/__snapshots__/FunctionParams.spec.js.snap +228 -0
  17. package/src/components/functions/__tests__/__snapshots__/Functions.spec.js.snap +86 -0
  18. package/src/components/functions/__tests__/useWatchParams.spec.js +23 -0
  19. package/src/components/functions/expressions/ConstantSelector.js +26 -0
  20. package/src/components/functions/expressions/Expression.js +40 -0
  21. package/src/components/functions/expressions/FieldSelector.js +56 -0
  22. package/src/components/functions/expressions/FunctionArgs.js +49 -0
  23. package/src/components/functions/expressions/FunctionSelector.js +95 -0
  24. package/src/components/functions/expressions/ParamSelector.js +51 -0
  25. package/src/components/functions/expressions/ShapeSelector.js +74 -0
  26. package/src/components/functions/expressions/__tests__/ConstantSelector.spec.js +64 -0
  27. package/src/components/functions/expressions/__tests__/Expression.spec.js +131 -0
  28. package/src/components/functions/expressions/__tests__/FunctionArgs.spec.js +86 -0
  29. package/src/components/functions/expressions/__tests__/FunctionSelector.spec.js +69 -0
  30. package/src/components/functions/expressions/__tests__/ParamSelector.spec.js +115 -0
  31. package/src/components/functions/expressions/__tests__/ShapeSelector.spec.js +107 -0
  32. package/src/components/functions/expressions/__tests__/__snapshots__/ConstantSelector.spec.js.snap +149 -0
  33. package/src/components/functions/expressions/__tests__/__snapshots__/Expression.spec.js.snap +904 -0
  34. package/src/components/functions/expressions/__tests__/__snapshots__/FunctionArgs.spec.js.snap +392 -0
  35. package/src/components/functions/expressions/__tests__/__snapshots__/FunctionSelector.spec.js.snap +377 -0
  36. package/src/components/functions/expressions/__tests__/__snapshots__/ParamSelector.spec.js.snap +95 -0
  37. package/src/components/functions/expressions/__tests__/__snapshots__/ShapeSelector.spec.js.snap +290 -0
  38. package/src/components/functions/expressions/constantInputs/AnySelector.js +29 -0
  39. package/src/components/functions/expressions/constantInputs/BooleanSelector.js +37 -0
  40. package/src/components/functions/expressions/constantInputs/DefaultSelector.js +34 -0
  41. package/src/components/functions/expressions/constantInputs/__tests__/AnySelector.spec.js +63 -0
  42. package/src/components/functions/expressions/constantInputs/__tests__/BooleanSelector.spec.js +51 -0
  43. package/src/components/functions/expressions/constantInputs/__tests__/DefaultSelector.spec.js +56 -0
  44. package/src/components/functions/expressions/constantInputs/__tests__/__snapshots__/AnySelector.spec.js.snap +236 -0
  45. package/src/components/functions/expressions/constantInputs/__tests__/__snapshots__/BooleanSelector.spec.js.snap +101 -0
  46. package/src/components/functions/expressions/constantInputs/__tests__/__snapshots__/DefaultSelector.spec.js.snap +39 -0
  47. package/src/components/functions/expressions/constantInputs/index.js +5 -0
  48. package/src/components/functions/useWatchParams.js +13 -0
  49. package/src/hooks/__tests__/useFunctions.spec.js +101 -0
  50. package/src/hooks/useFunctions.js +33 -0
  51. package/src/styles/Expression.less +102 -0
  52. package/src/types.js +38 -0
@@ -0,0 +1,236 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`<AnySelector /> matches the latest snapshot 1`] = `
4
+ <div>
5
+ <div
6
+ aria-expanded="false"
7
+ class="ui basic button dropdown"
8
+ name="type"
9
+ role="listbox"
10
+ tabindex="0"
11
+ >
12
+ <i
13
+ aria-hidden="true"
14
+ class="dropdown icon"
15
+ />
16
+ <div
17
+ class="menu transition"
18
+ >
19
+ <div
20
+ aria-checked="false"
21
+ aria-selected="true"
22
+ class="selected item"
23
+ role="option"
24
+ style="pointer-events: all;"
25
+ >
26
+ <i
27
+ aria-hidden="true"
28
+ class="adjust icon"
29
+ />
30
+ <span
31
+ class="text"
32
+ >
33
+ boolean
34
+ </span>
35
+ </div>
36
+ <div
37
+ aria-checked="false"
38
+ aria-selected="false"
39
+ class="item"
40
+ role="option"
41
+ style="pointer-events: all;"
42
+ >
43
+ <i
44
+ aria-hidden="true"
45
+ class="font icon"
46
+ />
47
+ <span
48
+ class="text"
49
+ >
50
+ string
51
+ </span>
52
+ </div>
53
+ <div
54
+ aria-checked="false"
55
+ aria-selected="false"
56
+ class="item"
57
+ role="option"
58
+ style="pointer-events: all;"
59
+ >
60
+ <i
61
+ aria-hidden="true"
62
+ class="hashtag icon"
63
+ />
64
+ <span
65
+ class="text"
66
+ >
67
+ numeric
68
+ </span>
69
+ </div>
70
+ <div
71
+ aria-checked="false"
72
+ aria-selected="false"
73
+ class="item"
74
+ role="option"
75
+ style="pointer-events: all;"
76
+ >
77
+ <i
78
+ aria-hidden="true"
79
+ class="calendar alternate outline icon"
80
+ />
81
+ <span
82
+ class="text"
83
+ >
84
+ date
85
+ </span>
86
+ </div>
87
+ <div
88
+ aria-checked="false"
89
+ aria-selected="false"
90
+ class="item"
91
+ role="option"
92
+ style="pointer-events: all;"
93
+ >
94
+ <i
95
+ aria-hidden="true"
96
+ class="clock outline icon"
97
+ />
98
+ <span
99
+ class="text"
100
+ >
101
+ timestamp
102
+ </span>
103
+ </div>
104
+ </div>
105
+ </div>
106
+ </div>
107
+ `;
108
+
109
+ exports[`<AnySelector /> user interaction 1`] = `
110
+ <div>
111
+ <div
112
+ aria-expanded="false"
113
+ class="ui basic button dropdown"
114
+ name="type"
115
+ role="listbox"
116
+ style=""
117
+ tabindex="0"
118
+ >
119
+ <div
120
+ aria-atomic="true"
121
+ aria-live="polite"
122
+ class="divider text"
123
+ role="alert"
124
+ >
125
+ string
126
+ </div>
127
+ <i
128
+ aria-hidden="true"
129
+ class="dropdown icon"
130
+ />
131
+ <div
132
+ class="menu transition"
133
+ >
134
+ <div
135
+ aria-checked="false"
136
+ aria-selected="false"
137
+ class="item"
138
+ role="option"
139
+ style="pointer-events: all;"
140
+ >
141
+ <i
142
+ aria-hidden="true"
143
+ class="adjust icon"
144
+ />
145
+ <span
146
+ class="text"
147
+ >
148
+ boolean
149
+ </span>
150
+ </div>
151
+ <div
152
+ aria-checked="true"
153
+ aria-selected="true"
154
+ class="active selected item"
155
+ role="option"
156
+ style="pointer-events: all;"
157
+ >
158
+ <i
159
+ aria-hidden="true"
160
+ class="font icon"
161
+ />
162
+ <span
163
+ class="text"
164
+ >
165
+ string
166
+ </span>
167
+ </div>
168
+ <div
169
+ aria-checked="false"
170
+ aria-selected="false"
171
+ class="item"
172
+ role="option"
173
+ style="pointer-events: all;"
174
+ >
175
+ <i
176
+ aria-hidden="true"
177
+ class="hashtag icon"
178
+ />
179
+ <span
180
+ class="text"
181
+ >
182
+ numeric
183
+ </span>
184
+ </div>
185
+ <div
186
+ aria-checked="false"
187
+ aria-selected="false"
188
+ class="item"
189
+ role="option"
190
+ style="pointer-events: all;"
191
+ >
192
+ <i
193
+ aria-hidden="true"
194
+ class="calendar alternate outline icon"
195
+ />
196
+ <span
197
+ class="text"
198
+ >
199
+ date
200
+ </span>
201
+ </div>
202
+ <div
203
+ aria-checked="false"
204
+ aria-selected="false"
205
+ class="item"
206
+ role="option"
207
+ style="pointer-events: all;"
208
+ >
209
+ <i
210
+ aria-hidden="true"
211
+ class="clock outline icon"
212
+ />
213
+ <span
214
+ class="text"
215
+ >
216
+ timestamp
217
+ </span>
218
+ </div>
219
+ </div>
220
+ </div>
221
+ <div
222
+ class="required field"
223
+ >
224
+ <div
225
+ class="ui input"
226
+ >
227
+ <input
228
+ autocomplete="off"
229
+ required=""
230
+ type="text"
231
+ value=""
232
+ />
233
+ </div>
234
+ </div>
235
+ </div>
236
+ `;
@@ -0,0 +1,101 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`<BooleanSelector /> matches the latest snapshot 1`] = `
4
+ <div>
5
+ <div
6
+ aria-expanded="false"
7
+ class="ui fluid selection dropdown"
8
+ role="listbox"
9
+ tabindex="0"
10
+ >
11
+ <i
12
+ aria-hidden="true"
13
+ class="dropdown icon"
14
+ />
15
+ <div
16
+ class="menu transition"
17
+ >
18
+ <div
19
+ aria-checked="false"
20
+ aria-selected="true"
21
+ class="selected item"
22
+ role="option"
23
+ style="pointer-events: all;"
24
+ >
25
+ <span
26
+ class="text"
27
+ >
28
+ true
29
+ </span>
30
+ </div>
31
+ <div
32
+ aria-checked="false"
33
+ aria-selected="false"
34
+ class="item"
35
+ role="option"
36
+ style="pointer-events: all;"
37
+ >
38
+ <span
39
+ class="text"
40
+ >
41
+ false
42
+ </span>
43
+ </div>
44
+ </div>
45
+ </div>
46
+ </div>
47
+ `;
48
+
49
+ exports[`<BooleanSelector /> user interaction 1`] = `
50
+ <div>
51
+ <div
52
+ aria-expanded="false"
53
+ class="ui fluid selection dropdown"
54
+ role="listbox"
55
+ tabindex="0"
56
+ >
57
+ <div
58
+ aria-atomic="true"
59
+ aria-live="polite"
60
+ class="divider text"
61
+ role="alert"
62
+ >
63
+ true
64
+ </div>
65
+ <i
66
+ aria-hidden="true"
67
+ class="dropdown icon"
68
+ />
69
+ <div
70
+ class="menu transition"
71
+ >
72
+ <div
73
+ aria-checked="true"
74
+ aria-selected="true"
75
+ class="active selected item"
76
+ role="option"
77
+ style="pointer-events: all;"
78
+ >
79
+ <span
80
+ class="text"
81
+ >
82
+ true
83
+ </span>
84
+ </div>
85
+ <div
86
+ aria-checked="false"
87
+ aria-selected="false"
88
+ class="item"
89
+ role="option"
90
+ style="pointer-events: all;"
91
+ >
92
+ <span
93
+ class="text"
94
+ >
95
+ false
96
+ </span>
97
+ </div>
98
+ </div>
99
+ </div>
100
+ </div>
101
+ `;
@@ -0,0 +1,39 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`<DefaultSelector /> matches the latest snapshot 1`] = `
4
+ <div>
5
+ <div
6
+ class="required field"
7
+ >
8
+ <div
9
+ class="ui input"
10
+ >
11
+ <input
12
+ autocomplete="off"
13
+ required=""
14
+ type="text"
15
+ value=""
16
+ />
17
+ </div>
18
+ </div>
19
+ </div>
20
+ `;
21
+
22
+ exports[`<DefaultSelector /> user interaction 1`] = `
23
+ <div>
24
+ <div
25
+ class="required field"
26
+ >
27
+ <div
28
+ class="ui input"
29
+ >
30
+ <input
31
+ autocomplete="off"
32
+ required=""
33
+ type="text"
34
+ value="text"
35
+ />
36
+ </div>
37
+ </div>
38
+ </div>
39
+ `;
@@ -0,0 +1,5 @@
1
+ import AnySelector from "./AnySelector";
2
+ import BooleanSelector from "./BooleanSelector";
3
+ import DefaultSelector from "./DefaultSelector";
4
+
5
+ export { AnySelector, BooleanSelector, DefaultSelector };
@@ -0,0 +1,13 @@
1
+ import { useFormContext } from "react-hook-form";
2
+
3
+ export default function useWatchParams() {
4
+ const { watch } = useFormContext();
5
+ const params = watch("params");
6
+
7
+ params.map((_, idx) => {
8
+ watch(`params[${idx}].name`);
9
+ watch(`params[${idx}].type`);
10
+ });
11
+
12
+ return params;
13
+ }
@@ -0,0 +1,101 @@
1
+ import _ from "lodash/fp";
2
+ import { compile } from "path-to-regexp";
3
+ import useSWR from "swr";
4
+ import useSWRMutations from "swr/mutation";
5
+ import { renderHook } from "@testing-library/react-hooks";
6
+ import {
7
+ apiJson,
8
+ apiJsonPost,
9
+ apiJsonPatch,
10
+ apiJsonDelete,
11
+ } from "@truedat/core/services/api";
12
+ import { API_FUNCTIONS, API_FUNCTION } from "../../api";
13
+ import {
14
+ useFunctions,
15
+ useFunctionCreate,
16
+ useFunctionUpdate,
17
+ useFunctionDelete,
18
+ } from "../useFunctions";
19
+
20
+ jest.mock("swr", () => ({
21
+ __esModule: true,
22
+ ...jest.requireActual("swr"),
23
+ default: jest.fn(() => ({
24
+ data: { data: "data" },
25
+ error: null,
26
+ mutate: jest.fn(),
27
+ })),
28
+ }));
29
+
30
+ jest.mock("swr/mutation", () => ({
31
+ __esModule: true,
32
+ ...jest.requireActual("swr/mutation"),
33
+ default: jest.fn(),
34
+ }));
35
+
36
+ jest.mock("@truedat/core/services/api", () => ({
37
+ __esModule: true,
38
+ ...jest.requireActual("@truedat/core/services/api"),
39
+ apiJsonPost: jest.fn(),
40
+ apiJsonPatch: jest.fn(),
41
+ apiJsonDelete: jest.fn(),
42
+ }));
43
+
44
+ describe("useFunctions", () => {
45
+ it("useFunctions calls useSWR with correct api route", () => {
46
+ const { result } = renderHook(() => useFunctions());
47
+
48
+ expect(result.current).toMatchObject({
49
+ data: "data",
50
+ error: null,
51
+ loading: false,
52
+ });
53
+
54
+ expect(useSWR).toHaveBeenCalledWith(API_FUNCTIONS, apiJson);
55
+ });
56
+ it("useFunctionCreate calls useSWRMutations with correct api route", () => {
57
+ renderHook(() => useFunctionCreate());
58
+ const [url, func] = _.last(useSWRMutations.mock.calls);
59
+ const arg = { some: "arg" };
60
+ expect(url).toBe(API_FUNCTIONS);
61
+ func(url, { arg });
62
+
63
+ expect(apiJsonPost).toHaveBeenCalledWith(url, arg);
64
+ });
65
+ it("useFunctionUpdate calls useSWRMutations with correct api route", () => {
66
+ const id = 8;
67
+ renderHook(() => useFunctionUpdate({ id }));
68
+ const [url, func] = _.last(useSWRMutations.mock.calls);
69
+ const arg = { some: "arg" };
70
+ expect(url).toBe(compile(API_FUNCTION)({ id }));
71
+ func(url, { arg });
72
+
73
+ expect(apiJsonPatch).toHaveBeenCalledWith(url, arg);
74
+ });
75
+ it("useFunctionUpdate without args will render id 0", () => {
76
+ renderHook(() => useFunctionUpdate());
77
+ const [url, func] = _.last(useSWRMutations.mock.calls);
78
+ const arg = { some: "arg" };
79
+ expect(url).toBe(compile(API_FUNCTION)({ id: 0 }));
80
+ func(url, { arg });
81
+ expect(apiJsonPatch).toHaveBeenCalledWith(url, arg);
82
+ });
83
+ it("useFunctionDelete calls useSWRMutations with correct api route", () => {
84
+ const id = 8;
85
+ renderHook(() => useFunctionDelete({ id }));
86
+ const [url, func] = _.last(useSWRMutations.mock.calls);
87
+ const arg = { some: "arg" };
88
+ expect(url).toBe(compile(API_FUNCTION)({ id }));
89
+ func(url, { arg });
90
+
91
+ expect(apiJsonDelete).toHaveBeenCalledWith(url, arg);
92
+ });
93
+ it("useFunctionDelete without args will render id 0", () => {
94
+ renderHook(() => useFunctionDelete());
95
+ const [url, func] = _.last(useSWRMutations.mock.calls);
96
+ const arg = { some: "arg" };
97
+ expect(url).toBe(compile(API_FUNCTION)({ id: 0 }));
98
+ func(url, { arg });
99
+ expect(apiJsonDelete).toHaveBeenCalledWith(url, arg);
100
+ });
101
+ });
@@ -0,0 +1,33 @@
1
+ import { compile } from "path-to-regexp";
2
+ import useSWR from "swr";
3
+ import useSWRMutations from "swr/mutation";
4
+ import {
5
+ apiJson,
6
+ apiJsonPost,
7
+ apiJsonPatch,
8
+ apiJsonDelete,
9
+ } from "@truedat/core/services/api";
10
+ import { API_FUNCTIONS, API_FUNCTION } from "../api";
11
+
12
+ export const useFunctions = () => {
13
+ const { data, error, mutate } = useSWR(API_FUNCTIONS, apiJson);
14
+ return { data: data?.data, error, loading: !error && !data, mutate };
15
+ };
16
+
17
+ export const useFunctionCreate = () => {
18
+ return useSWRMutations(API_FUNCTIONS, (url, { arg }) =>
19
+ apiJsonPost(url, arg)
20
+ );
21
+ };
22
+
23
+ export const useFunctionUpdate = (func) => {
24
+ const id = func?.id || 0;
25
+ const url = compile(API_FUNCTION)({ id });
26
+ return useSWRMutations(url, (url, { arg }) => apiJsonPatch(url, arg));
27
+ };
28
+
29
+ export const useFunctionDelete = (func) => {
30
+ const id = func?.id || 0;
31
+ const url = compile(API_FUNCTION)({ id });
32
+ return useSWRMutations(url, (url, { arg }) => apiJsonDelete(url, arg));
33
+ };
@@ -0,0 +1,102 @@
1
+ .no-padding {
2
+ padding: 0;
3
+ }
4
+
5
+ .no-margin {
6
+ margin: 0 !important;
7
+ }
8
+
9
+ .flex-center {
10
+ display: flex;
11
+ align-items: center;
12
+ }
13
+ .flex-column {
14
+ display: flex;
15
+ flex-direction: column;
16
+ }
17
+
18
+ .expression-container {
19
+ flex-grow: 1;
20
+ display: flex;
21
+ flex-direction: row;
22
+ align-items: flex-start;
23
+ }
24
+
25
+ .shape-selector-trigger {
26
+ width: 38px;
27
+ height: 38px;
28
+ border: 1px solid rgba(34, 36, 38, 0.15);
29
+ border-radius: 4px;
30
+ font-size: 12px;
31
+ font-weight: bold;
32
+ font-family: monospace;
33
+ display: flex;
34
+ align-items: center;
35
+ justify-content: center;
36
+ }
37
+
38
+ .function-params-label {
39
+ display: flex;
40
+ flex: 1;
41
+ justify-content: right;
42
+ }
43
+
44
+ .param-label-header {
45
+ display: flex;
46
+ flex-direction: row;
47
+ flex-wrap: wrap;
48
+ align-items: center;
49
+ padding: 4px 0;
50
+ }
51
+
52
+ .param-label-description {
53
+ font-style: italic;
54
+ color: gray;
55
+ font-size: 13;
56
+ padding-left: 5px;
57
+ }
58
+
59
+ ul.function-tree {
60
+ list-style-type: none;
61
+ padding: 0;
62
+ margin-left: 2.18em;
63
+ margin-top: -0.2em;
64
+ transition: max-height 0.3s ease-out;
65
+ }
66
+
67
+ .function-tree li {
68
+ margin: 0;
69
+ padding: 0;
70
+ box-sizing: border-box;
71
+ }
72
+
73
+ .function-tree li {
74
+ list-style-type: none;
75
+ margin: 10px 0 10px 10px;
76
+ position: relative;
77
+ }
78
+ .function-tree li:before {
79
+ content: "";
80
+ position: absolute;
81
+ top: -10px;
82
+ left: -20px;
83
+ border-left: 1px solid #ddd;
84
+ border-bottom: 1px solid #ddd;
85
+ width: 20px;
86
+ height: 15px;
87
+ height: 30px;
88
+ }
89
+ .function-tree li:after {
90
+ position: absolute;
91
+ content: "";
92
+ top: 5px;
93
+ top: 19px;
94
+ left: -20px;
95
+ border-left: 1px solid #ddd;
96
+ border-top: 1px solid #ddd;
97
+ width: 20px;
98
+ height: 100%;
99
+ }
100
+ .function-tree li:last-child:after {
101
+ display: none;
102
+ }
package/src/types.js ADDED
@@ -0,0 +1,38 @@
1
+ import _ from "lodash/fp";
2
+
3
+ export const types = [
4
+ "boolean",
5
+ "string",
6
+ "numeric",
7
+ "date",
8
+ "timestamp",
9
+ "any",
10
+ ];
11
+ export default types;
12
+
13
+ export const typeToIcon = (value) => {
14
+ return _.pathOr(
15
+ "question circle outline",
16
+ value
17
+ )({
18
+ string: "font",
19
+ numeric: "hashtag",
20
+ date: "calendar alternate outline",
21
+ timestamp: "clock outline",
22
+ // "any": "asterisk",
23
+ boolean: "adjust",
24
+ });
25
+ };
26
+
27
+ export const typeToColor = (value) => {
28
+ return _.pathOr(
29
+ "grey",
30
+ value
31
+ )({
32
+ boolean: "teal",
33
+ string: "purple",
34
+ numeric: "blue",
35
+ date: "olive",
36
+ timestamp: "brown",
37
+ });
38
+ };