@qoretechnologies/reqraft 0.10.10 → 0.10.12
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/dist/providers/StorageProvider.d.ts.map +1 -1
- package/dist/providers/StorageProvider.js +14 -4
- package/dist/providers/StorageProvider.js.map +1 -1
- package/package.json +1 -1
- package/src/components/dpqlEditor/DpqlEditor.stories.tsx +74 -2
- package/src/components/form/engine/FormEngine.stories.tsx +654 -32
- package/src/components/form/engine/FormEngineRemote.stories.tsx +48 -0
- package/src/components/form/engine/_structuredData/StructuredDataView.stories.tsx +8 -0
- package/src/components/form/engine/variants/FormEngineVariants.stories.tsx +40 -0
- package/src/components/form/expressions/ExpressionField.stories.tsx +74 -2
- package/src/components/form/expressions/builder/ExpressionBuilder.stories.tsx +187 -0
- package/src/components/form/fields/Field.stories.tsx +40 -0
- package/src/components/form/fields/array/ArrayAutoField.stories.tsx +64 -0
- package/src/components/form/fields/auto/AutoFormField.stories.tsx +136 -0
- package/src/components/form/fields/binary/Binary.stories.tsx +32 -0
- package/src/components/form/fields/boolean/Boolean.stories.tsx +24 -0
- package/src/components/form/fields/byte-size/ByteSize.stories.tsx +24 -0
- package/src/components/form/fields/color/Color.stories.tsx +30 -0
- package/src/components/form/fields/cron/Cron.stories.tsx +8 -0
- package/src/components/form/fields/date/Date.stories.tsx +22 -0
- package/src/components/form/fields/file/File.stories.tsx +48 -0
- package/src/components/form/fields/long-string/LongString.stories.tsx +24 -0
- package/src/components/form/fields/markdown/Markdown.stories.tsx +8 -0
- package/src/components/form/fields/number/Number.stories.tsx +31 -0
- package/src/components/form/fields/object/Object.stories.tsx +88 -0
- package/src/components/form/fields/radio-group/RadioGroup.stories.tsx +24 -0
- package/src/components/form/fields/rich-text/RichText.stories.tsx +23 -0
- package/src/components/form/fields/schema-definition/SchemaDefinitionField.stories.tsx +72 -0
- package/src/components/form/fields/select/Select.stories.tsx +104 -0
- package/src/components/form/fields/string/String.stories.tsx +16 -0
- package/src/components/form/fields/template/TemplateField.stories.tsx +160 -0
- package/src/components/form/fields/url/Url.stories.tsx +24 -0
- package/src/components/log/Log.stories.tsx +96 -0
- package/src/components/menu/Menu.stories.tsx +54 -0
- package/src/components/qonsoleSmartInput/QonsoleSmartInput.stories.tsx +14 -0
- package/src/components/smartEditor/SmartEditor.stories.tsx +32 -0
- package/src/hooks/useFetch/useFetch.stories.tsx +30 -0
- package/src/hooks/useStorage/useStorage.stories.tsx +82 -0
- package/src/hooks/useWebSocket/useWebsocket.stories.tsx +127 -1
- package/src/providers/StorageProvider.tsx +12 -4
- package/src/stores/currentUser/currentUser.stories.tsx +17 -0
|
@@ -106,8 +106,25 @@ const meta = {
|
|
|
106
106
|
export default meta;
|
|
107
107
|
export type Story = StoryObj<typeof meta>;
|
|
108
108
|
|
|
109
|
-
export const Default: Story = {
|
|
109
|
+
export const Default: Story = {
|
|
110
|
+
parameters: {
|
|
111
|
+
docs: {
|
|
112
|
+
description: {
|
|
113
|
+
story:
|
|
114
|
+
'Renders the useReqraftWebSocket demo with no lifecycle options — the socket stays CLOSED until the operator clicks Connect.',
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
};
|
|
110
119
|
export const OpenManually: Story = {
|
|
120
|
+
parameters: {
|
|
121
|
+
docs: {
|
|
122
|
+
description: {
|
|
123
|
+
story:
|
|
124
|
+
'Renders the useReqraftWebSocket demo and clicks the Connect action — the socket opens and the onOpen callback fires.',
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
},
|
|
111
128
|
play: async ({ args }) => {
|
|
112
129
|
await testsClickButton({ label: 'Connect' });
|
|
113
130
|
await testsWaitForText('Websocket Status: OPEN');
|
|
@@ -118,6 +135,14 @@ export const OpenOnMount: Story = {
|
|
|
118
135
|
args: {
|
|
119
136
|
openOnMount: true,
|
|
120
137
|
},
|
|
138
|
+
parameters: {
|
|
139
|
+
docs: {
|
|
140
|
+
description: {
|
|
141
|
+
story:
|
|
142
|
+
'Renders the useReqraftWebSocket demo with openOnMount enabled — the socket opens immediately after mount without any user action.',
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
},
|
|
121
146
|
play: async ({ args }) => {
|
|
122
147
|
await testsWaitForText('Websocket Status: OPEN');
|
|
123
148
|
await expect(args.onOpen).toHaveBeenCalled();
|
|
@@ -126,6 +151,15 @@ export const OpenOnMount: Story = {
|
|
|
126
151
|
|
|
127
152
|
export const CloseManually: Story = {
|
|
128
153
|
...OpenOnMount,
|
|
154
|
+
parameters: {
|
|
155
|
+
...OpenOnMount.parameters,
|
|
156
|
+
docs: {
|
|
157
|
+
description: {
|
|
158
|
+
story:
|
|
159
|
+
'Renders the useReqraftWebSocket demo opened on mount. When Disconnect is clicked, the socket transitions to CLOSED and the onClose callback fires.',
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
},
|
|
129
163
|
play: async ({ args, ...rest }) => {
|
|
130
164
|
await OpenOnMount.play({ args, ...rest });
|
|
131
165
|
await testsClickButton({ label: 'Disconnect' });
|
|
@@ -141,6 +175,14 @@ export const Reconnects: Story = {
|
|
|
141
175
|
maxReconnectTries: 5,
|
|
142
176
|
openOnMount: true,
|
|
143
177
|
},
|
|
178
|
+
parameters: {
|
|
179
|
+
docs: {
|
|
180
|
+
description: {
|
|
181
|
+
story:
|
|
182
|
+
'Renders the useReqraftWebSocket demo with reconnect enabled. When the server is killed, the socket transitions to CONNECTING and then back to OPEN once the server returns.',
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
},
|
|
144
186
|
play: async ({ args, ...rest }) => {
|
|
145
187
|
await OpenOnMount.play({ args, ...rest });
|
|
146
188
|
await testsClickButton({ label: 'Kill' });
|
|
@@ -159,6 +201,12 @@ export const ReconnectFails: Story = {
|
|
|
159
201
|
reconnectInterval: 500,
|
|
160
202
|
},
|
|
161
203
|
parameters: {
|
|
204
|
+
docs: {
|
|
205
|
+
description: {
|
|
206
|
+
story:
|
|
207
|
+
'Renders the useReqraftWebSocket demo with a low maxReconnectTries. When the server never returns, the socket exhausts its reconnect attempts and fires onReconnectFailed.',
|
|
208
|
+
},
|
|
209
|
+
},
|
|
162
210
|
jest: {
|
|
163
211
|
timeout: 60000,
|
|
164
212
|
},
|
|
@@ -178,6 +226,14 @@ export const SendMessage: Story = {
|
|
|
178
226
|
includeSentMessagesInState: true,
|
|
179
227
|
useState: true,
|
|
180
228
|
},
|
|
229
|
+
parameters: {
|
|
230
|
+
docs: {
|
|
231
|
+
description: {
|
|
232
|
+
story:
|
|
233
|
+
'Renders the useReqraftWebSocket demo with useState enabled. When Send is clicked, the message is dispatched and the echoed reply appears in the accumulated message list.',
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
},
|
|
181
237
|
play: async ({ args, ...rest }) => {
|
|
182
238
|
await OpenOnMount.play({ args, ...rest });
|
|
183
239
|
await testsClickButton({ label: 'Send' });
|
|
@@ -197,6 +253,14 @@ export const WithLogs: Story = {
|
|
|
197
253
|
useState: true,
|
|
198
254
|
reconnectInterval: 1500,
|
|
199
255
|
},
|
|
256
|
+
parameters: {
|
|
257
|
+
docs: {
|
|
258
|
+
description: {
|
|
259
|
+
story:
|
|
260
|
+
'Renders the useReqraftWebSocket demo with includeLogMessagesInState. Connect / disconnect / reconnect lifecycle events are captured as log entries alongside regular messages.',
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
},
|
|
200
264
|
play: async ({ args, ...rest }) => {
|
|
201
265
|
await Reconnects.play({ args, ...rest });
|
|
202
266
|
|
|
@@ -206,6 +270,15 @@ export const WithLogs: Story = {
|
|
|
206
270
|
|
|
207
271
|
export const ClearsMessages: Story = {
|
|
208
272
|
...SendMessage,
|
|
273
|
+
parameters: {
|
|
274
|
+
...SendMessage.parameters,
|
|
275
|
+
docs: {
|
|
276
|
+
description: {
|
|
277
|
+
story:
|
|
278
|
+
'Renders the useReqraftWebSocket demo after sending a message. When Clear is clicked, the accumulated message list is emptied.',
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
},
|
|
209
282
|
play: async ({ args, ...rest }) => {
|
|
210
283
|
await SendMessage.play({ args, ...rest });
|
|
211
284
|
await testsClickButton({ label: 'Clear' });
|
|
@@ -353,6 +426,14 @@ export const MultipleConnections: Story = {
|
|
|
353
426
|
includeLogMessagesInState: true,
|
|
354
427
|
useState: true,
|
|
355
428
|
},
|
|
429
|
+
parameters: {
|
|
430
|
+
docs: {
|
|
431
|
+
description: {
|
|
432
|
+
story:
|
|
433
|
+
'Renders three panels that each call useReqraftWebSocket against the same URL — proves the connections share one pooled underlying WebSocket while keeping independent message state.',
|
|
434
|
+
},
|
|
435
|
+
},
|
|
436
|
+
},
|
|
356
437
|
// @ts-expect-error customprops
|
|
357
438
|
render: (args: IUseReqraftWebSocketOptions) => {
|
|
358
439
|
const [conectionStatus, setConnectionStatus] = useState<string>('CLOSED');
|
|
@@ -405,6 +486,15 @@ export const MultipleConnectionsOpenOnMount: Story = {
|
|
|
405
486
|
...MultipleConnections.args,
|
|
406
487
|
openOnMount: true,
|
|
407
488
|
},
|
|
489
|
+
parameters: {
|
|
490
|
+
...MultipleConnections.parameters,
|
|
491
|
+
docs: {
|
|
492
|
+
description: {
|
|
493
|
+
story:
|
|
494
|
+
'Renders three pooled useReqraftWebSocket panels with openOnMount — all three transition to OPEN over the shared underlying socket without any user action.',
|
|
495
|
+
},
|
|
496
|
+
},
|
|
497
|
+
},
|
|
408
498
|
play: async ({ args }) => {
|
|
409
499
|
await testsWaitForText('First Connection Status: OPEN');
|
|
410
500
|
await testsWaitForText('Second Connection Status: OPEN');
|
|
@@ -420,6 +510,15 @@ export const MultipleConnectionsClosedAtOnce: Story = {
|
|
|
420
510
|
...MultipleConnections.args,
|
|
421
511
|
openOnMount: true,
|
|
422
512
|
},
|
|
513
|
+
parameters: {
|
|
514
|
+
...MultipleConnections.parameters,
|
|
515
|
+
docs: {
|
|
516
|
+
description: {
|
|
517
|
+
story:
|
|
518
|
+
'Renders three pooled useReqraftWebSocket panels. When Close All closes the shared socket, every consumer transitions to CLOSED at once and each panel logs its close handler.',
|
|
519
|
+
},
|
|
520
|
+
},
|
|
521
|
+
},
|
|
423
522
|
play: async (args) => {
|
|
424
523
|
await MultipleConnectionsOpenOnMount.play(args);
|
|
425
524
|
|
|
@@ -436,6 +535,15 @@ export const ConnectionIsClosedWhenAllUsersAreClosed: Story = {
|
|
|
436
535
|
...MultipleConnections.args,
|
|
437
536
|
openOnMount: true,
|
|
438
537
|
},
|
|
538
|
+
parameters: {
|
|
539
|
+
...MultipleConnections.parameters,
|
|
540
|
+
docs: {
|
|
541
|
+
description: {
|
|
542
|
+
story:
|
|
543
|
+
'Renders three pooled useReqraftWebSocket panels. Closing them one by one keeps the shared socket OPEN until the last consumer unmounts, then it closes.',
|
|
544
|
+
},
|
|
545
|
+
},
|
|
546
|
+
},
|
|
439
547
|
play: async (args) => {
|
|
440
548
|
await MultipleConnectionsOpenOnMount.play(args);
|
|
441
549
|
|
|
@@ -454,6 +562,15 @@ export const MultipleConnectionsHaveCustomHandlers: Story = {
|
|
|
454
562
|
...MultipleConnections.args,
|
|
455
563
|
openOnMount: true,
|
|
456
564
|
},
|
|
565
|
+
parameters: {
|
|
566
|
+
...MultipleConnections.parameters,
|
|
567
|
+
docs: {
|
|
568
|
+
description: {
|
|
569
|
+
story:
|
|
570
|
+
'Renders three pooled useReqraftWebSocket panels. Each panel attaches its own message handler, and sending a message triggers the handlers of only the connections still open.',
|
|
571
|
+
},
|
|
572
|
+
},
|
|
573
|
+
},
|
|
457
574
|
play: async (args) => {
|
|
458
575
|
const canvas = within(args.canvasElement);
|
|
459
576
|
|
|
@@ -480,6 +597,15 @@ export const MultipleConnectionsHaveCustomHandlers: Story = {
|
|
|
480
597
|
|
|
481
598
|
export const MultipleConnectionsCanBeDisconnectedAndReconnected: Story = {
|
|
482
599
|
...MultipleConnectionsHaveCustomHandlers,
|
|
600
|
+
parameters: {
|
|
601
|
+
...MultipleConnectionsHaveCustomHandlers.parameters,
|
|
602
|
+
docs: {
|
|
603
|
+
description: {
|
|
604
|
+
story:
|
|
605
|
+
'Renders three pooled useReqraftWebSocket panels after custom handlers have fired. Disconnecting one and reconnecting another proves individual consumers can toggle without disturbing peers.',
|
|
606
|
+
},
|
|
607
|
+
},
|
|
608
|
+
},
|
|
483
609
|
play: async (args) => {
|
|
484
610
|
await MultipleConnectionsHaveCustomHandlers.play(args);
|
|
485
611
|
|
|
@@ -53,26 +53,34 @@ export const ReqraftUserProvider = ({ children, waitForStorage }: IReqraftStorag
|
|
|
53
53
|
includeAppPrefix: boolean = true
|
|
54
54
|
) {
|
|
55
55
|
const _path = includeAppPrefix ? `${appName}.${path}` : path;
|
|
56
|
-
|
|
56
|
+
// Base the write on the LATEST storage read straight from the store, not
|
|
57
|
+
// the blob captured in this callback's closure. A caller holding a stale
|
|
58
|
+
// updater — e.g. an imperative store subscription created on mount, before
|
|
59
|
+
// other keys had loaded — would otherwise persist an out-of-date blob and
|
|
60
|
+
// wipe every key written to storage since its closure was captured.
|
|
61
|
+
const latestStorage = currentUserStore.getState().currentUser?.storage;
|
|
62
|
+
const updatedStorage = set(cloneDeep(latestStorage), _path, value);
|
|
57
63
|
|
|
58
64
|
updateCurrentUserStorage(updatedStorage);
|
|
59
65
|
|
|
60
66
|
load({ body: { storage: updatedStorage } });
|
|
61
67
|
},
|
|
62
|
-
[appName,
|
|
68
|
+
[appName, load, updateCurrentUserStorage]
|
|
63
69
|
);
|
|
64
70
|
|
|
65
71
|
const removeStorageValue = useCallback(
|
|
66
72
|
function (path: string, includeAppPrefix: boolean = true) {
|
|
67
73
|
const _path = includeAppPrefix ? `${appName}.${path}` : path;
|
|
68
74
|
|
|
69
|
-
|
|
75
|
+
// Same as `updateStorage`: mutate the latest blob, never a stale closure copy.
|
|
76
|
+
const latestStorage = currentUserStore.getState().currentUser?.storage;
|
|
77
|
+
const updatedStorage = set(cloneDeep(latestStorage), _path, null);
|
|
70
78
|
|
|
71
79
|
updateCurrentUserStorage(updatedStorage);
|
|
72
80
|
|
|
73
81
|
load({ body: { storage_path: _path } });
|
|
74
82
|
},
|
|
75
|
-
[appName,
|
|
83
|
+
[appName, load, updateCurrentUserStorage]
|
|
76
84
|
);
|
|
77
85
|
|
|
78
86
|
const contextValue = useMemo(
|
|
@@ -26,6 +26,14 @@ export default meta;
|
|
|
26
26
|
export type Story = StoryObj<typeof meta>;
|
|
27
27
|
|
|
28
28
|
export const CurrentUserCanBeLoaded: Story = {
|
|
29
|
+
parameters: {
|
|
30
|
+
docs: {
|
|
31
|
+
description: {
|
|
32
|
+
story:
|
|
33
|
+
'Renders a demo that reads currentUserStore — the store loads /users?action=current and the returned user object is displayed as a tree.',
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
29
37
|
play: async () => {
|
|
30
38
|
await testsWaitForText('"David Nichols"');
|
|
31
39
|
},
|
|
@@ -33,6 +41,15 @@ export const CurrentUserCanBeLoaded: Story = {
|
|
|
33
41
|
|
|
34
42
|
export const CurrentUserHasPermissions: Story = {
|
|
35
43
|
...CurrentUserCanBeLoaded,
|
|
44
|
+
parameters: {
|
|
45
|
+
...CurrentUserCanBeLoaded.parameters,
|
|
46
|
+
docs: {
|
|
47
|
+
description: {
|
|
48
|
+
story:
|
|
49
|
+
'Renders a demo that calls currentUserStore().hasAnyPermission — the affirmative message renders because the loaded user carries at least one of the requested permissions.',
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
},
|
|
36
53
|
render: () => {
|
|
37
54
|
const { hasAnyPermission } = currentUserStore();
|
|
38
55
|
|