@darajs/core 1.3.2 → 1.4.0
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/actions/download-variable.d.ts +3 -3
- package/dist/actions/download-variable.d.ts.map +1 -1
- package/dist/actions/download-variable.js +32 -46
- package/dist/actions/download-variable.js.map +1 -1
- package/dist/actions/index.d.ts +0 -4
- package/dist/actions/index.d.ts.map +1 -1
- package/dist/actions/index.js +0 -4
- package/dist/actions/index.js.map +1 -1
- package/dist/actions/navigate-to.d.ts +3 -3
- package/dist/actions/navigate-to.d.ts.map +1 -1
- package/dist/actions/navigate-to.js +16 -57
- package/dist/actions/navigate-to.js.map +1 -1
- package/dist/actions/notify.d.ts +2 -6
- package/dist/actions/notify.d.ts.map +1 -1
- package/dist/actions/notify.js +8 -14
- package/dist/actions/notify.js.map +1 -1
- package/dist/actions/reset-variables.d.ts +2 -2
- package/dist/actions/reset-variables.d.ts.map +1 -1
- package/dist/actions/reset-variables.js +28 -17
- package/dist/actions/reset-variables.js.map +1 -1
- package/dist/actions/trigger-variable.d.ts +2 -2
- package/dist/actions/trigger-variable.d.ts.map +1 -1
- package/dist/actions/trigger-variable.js +7 -18
- package/dist/actions/trigger-variable.js.map +1 -1
- package/dist/actions/update-variable.d.ts +2 -4
- package/dist/actions/update-variable.d.ts.map +1 -1
- package/dist/actions/update-variable.js +17 -83
- package/dist/actions/update-variable.js.map +1 -1
- package/dist/api/websocket.d.ts +22 -2
- package/dist/api/websocket.d.ts.map +1 -1
- package/dist/api/websocket.js +11 -0
- package/dist/api/websocket.js.map +1 -1
- package/dist/auth/auth-wrapper.js +1 -1
- package/dist/auth/auth-wrapper.js.map +1 -1
- package/dist/components/router-content/router-content.d.ts.map +1 -1
- package/dist/components/router-content/router-content.js +1 -1
- package/dist/components/router-content/router-content.js.map +1 -1
- package/dist/{dara_core-1.3.2-py3-none-any.whl → dara_core-1.4.0-py3-none-any.whl} +0 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/shared/index.d.ts +1 -1
- package/dist/shared/index.d.ts.map +1 -1
- package/dist/shared/index.js +1 -1
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/interactivity/index.d.ts +2 -4
- package/dist/shared/interactivity/index.d.ts.map +1 -1
- package/dist/shared/interactivity/index.js +2 -3
- package/dist/shared/interactivity/index.js.map +1 -1
- package/dist/shared/interactivity/store.d.ts +8 -0
- package/dist/shared/interactivity/store.d.ts.map +1 -1
- package/dist/shared/interactivity/store.js +19 -0
- package/dist/shared/interactivity/store.js.map +1 -1
- package/dist/shared/interactivity/use-variable-value.d.ts +19 -7
- package/dist/shared/interactivity/use-variable-value.d.ts.map +1 -1
- package/dist/shared/interactivity/use-variable-value.js +54 -40
- package/dist/shared/interactivity/use-variable-value.js.map +1 -1
- package/dist/shared/private-route/private-route.d.ts +3 -7
- package/dist/shared/private-route/private-route.d.ts.map +1 -1
- package/dist/shared/private-route/private-route.js +12 -22
- package/dist/shared/private-route/private-route.js.map +1 -1
- package/dist/shared/utils/use-action-registry.d.ts +2 -2
- package/dist/shared/utils/use-action-registry.d.ts.map +1 -1
- package/dist/shared/utils/use-action-registry.js +6 -6
- package/dist/shared/utils/use-action-registry.js.map +1 -1
- package/dist/shared/utils/use-action.d.ts +14 -2
- package/dist/shared/utils/use-action.d.ts.map +1 -1
- package/dist/shared/utils/use-action.js +249 -55
- package/dist/shared/utils/use-action.js.map +1 -1
- package/dist/types/core.d.ts +80 -51
- package/dist/types/core.d.ts.map +1 -1
- package/dist/types/core.js.map +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/utils.d.ts +7 -1
- package/dist/types/utils.d.ts.map +1 -1
- package/dist/types/utils.js +8 -0
- package/dist/types/utils.js.map +1 -1
- package/dist/umd/dara.core.umd.js +5955 -6669
- package/package.json +6 -6
- package/dist/actions/download-content.d.ts +0 -8
- package/dist/actions/download-content.d.ts.map +0 -1
- package/dist/actions/download-content.js +0 -47
- package/dist/actions/download-content.js.map +0 -1
- package/dist/actions/logout.d.ts +0 -8
- package/dist/actions/logout.d.ts.map +0 -1
- package/dist/actions/logout.js +0 -25
- package/dist/actions/logout.js.map +0 -1
- package/dist/actions/side-effect.d.ts +0 -8
- package/dist/actions/side-effect.d.ts.map +0 -1
- package/dist/actions/side-effect.js +0 -45
- package/dist/actions/side-effect.js.map +0 -1
- package/dist/actions/utils.d.ts +0 -9
- package/dist/actions/utils.d.ts.map +0 -1
- package/dist/actions/utils.js +0 -38
- package/dist/actions/utils.js.map +0 -1
- package/dist/shared/interactivity/use-reset-variables.d.ts +0 -8
- package/dist/shared/interactivity/use-reset-variables.d.ts.map +0 -1
- package/dist/shared/interactivity/use-reset-variables.js +0 -46
- package/dist/shared/interactivity/use-reset-variables.js.map +0 -1
- package/dist/shared/interactivity/use-trigger-variable.d.ts +0 -9
- package/dist/shared/interactivity/use-trigger-variable.d.ts.map +0 -1
- package/dist/shared/interactivity/use-trigger-variable.js +0 -18
- package/dist/shared/interactivity/use-trigger-variable.js.map +0 -1
|
@@ -3,12 +3,60 @@ import { useContext } from 'react';
|
|
|
3
3
|
import { useLocation } from 'react-router-dom';
|
|
4
4
|
import { useRecoilCallback } from 'recoil';
|
|
5
5
|
import { useDeepCompare } from '@darajs/ui-utils';
|
|
6
|
-
// eslint-disable-next-line import/no-cycle
|
|
7
6
|
import { useSessionToken } from '../../auth/auth-context';
|
|
8
7
|
import { WebSocketCtx, useTaskContext } from '../../shared/context';
|
|
9
8
|
import { normalizeRequest } from '../../shared/utils/normalization';
|
|
10
9
|
import { isDataVariable, isDerivedDataVariable, isDerivedVariable, isResolvedDataVariable, isResolvedDerivedDataVariable, isResolvedDerivedVariable, isVariable, } from '../../types';
|
|
11
10
|
import { fetchDataVariable, fetchDerivedDataVariable, fetchDerivedVariable, formatDerivedVariableRequest, isTaskResponse, resolveVariable, } from './internal';
|
|
11
|
+
/**
|
|
12
|
+
* Helper function that returns the current value of a variable.
|
|
13
|
+
*
|
|
14
|
+
* Plain variables are always resolved to their value.
|
|
15
|
+
* Computed (server-side) variables are resolved to their uid and dependency values, unless shouldFetchVariable is true.
|
|
16
|
+
*/
|
|
17
|
+
export function getVariableValue(variable, shouldFetchVariable = false, ctx) {
|
|
18
|
+
// Using loadable since the resolver is only used for simple atoms and shouldn't cause problems
|
|
19
|
+
const resolved = resolveVariable(variable, ctx.client, ctx.taskContext, ctx.search, ctx.token, (v) => ctx.snapshot.getLoadable(v).getValue());
|
|
20
|
+
// if we're NOT forced to fetch, or if it's not a DV/DDV/data variable, return the resolved value
|
|
21
|
+
// variable is plain/url
|
|
22
|
+
if (!shouldFetchVariable ||
|
|
23
|
+
(!isDerivedVariable(variable) && !isDataVariable(variable) && !isDerivedDataVariable(variable))) {
|
|
24
|
+
return resolved;
|
|
25
|
+
}
|
|
26
|
+
// we're forced to fetch but the resolved variable is not a resolved DV/data var, return the resolved value
|
|
27
|
+
// variable is plain/url
|
|
28
|
+
if (!isResolvedDerivedVariable(resolved) &&
|
|
29
|
+
!isResolvedDataVariable(resolved) &&
|
|
30
|
+
!isResolvedDerivedDataVariable(resolved)) {
|
|
31
|
+
return resolved;
|
|
32
|
+
}
|
|
33
|
+
// data variable
|
|
34
|
+
if (isResolvedDataVariable(resolved)) {
|
|
35
|
+
return fetchDataVariable(resolved.uid, ctx.token, resolved.filters);
|
|
36
|
+
}
|
|
37
|
+
// derived variable
|
|
38
|
+
return fetchDerivedVariable({
|
|
39
|
+
cache: variable.cache,
|
|
40
|
+
force: false,
|
|
41
|
+
token: ctx.token,
|
|
42
|
+
uid: resolved.uid,
|
|
43
|
+
values: normalizeRequest(formatDerivedVariableRequest(resolved.values), variable.variables),
|
|
44
|
+
wsClient: ctx.client,
|
|
45
|
+
}).then((resp) => {
|
|
46
|
+
// This is really only used in DownloadVariable currently; we can add support for tasks
|
|
47
|
+
// if it is requested in the future
|
|
48
|
+
if (isTaskResponse(resp)) {
|
|
49
|
+
throw new Error('Task DerivedVariables are not supported in this context');
|
|
50
|
+
}
|
|
51
|
+
// for derived data variables we need to make another request to retrieve the filtered value
|
|
52
|
+
if (isDerivedDataVariable(variable)) {
|
|
53
|
+
return ctx.client
|
|
54
|
+
.getChannel()
|
|
55
|
+
.then((chan) => fetchDerivedDataVariable(variable.uid, ctx.token, resp.cache_key, chan, variable.filters));
|
|
56
|
+
}
|
|
57
|
+
return resp.value;
|
|
58
|
+
});
|
|
59
|
+
}
|
|
12
60
|
/**
|
|
13
61
|
* A helper hook that turns a Variable class into the actual value.
|
|
14
62
|
* As opposed to the `useVariable` hook, this one returns a callback to retrieve the latest value
|
|
@@ -30,46 +78,12 @@ export default function useVariableValue(variable, shouldFetchVariable = false)
|
|
|
30
78
|
}
|
|
31
79
|
return useRecoilCallback(({ snapshot }) => {
|
|
32
80
|
return () => {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
(!isDerivedVariable(variable) && !isDataVariable(variable) && !isDerivedDataVariable(variable))) {
|
|
39
|
-
return resolved;
|
|
40
|
-
}
|
|
41
|
-
// we're forced to fetch but the resolved variable is not a resolved DV/data var, return the resolved value
|
|
42
|
-
// variable is plain/url
|
|
43
|
-
if (!isResolvedDerivedVariable(resolved) &&
|
|
44
|
-
!isResolvedDataVariable(resolved) &&
|
|
45
|
-
!isResolvedDerivedDataVariable(resolved)) {
|
|
46
|
-
return resolved;
|
|
47
|
-
}
|
|
48
|
-
// data variable
|
|
49
|
-
if (isResolvedDataVariable(resolved)) {
|
|
50
|
-
return fetchDataVariable(resolved.uid, token, resolved.filters);
|
|
51
|
-
}
|
|
52
|
-
// derived variable
|
|
53
|
-
return fetchDerivedVariable({
|
|
54
|
-
cache: variable.cache,
|
|
55
|
-
force: false,
|
|
81
|
+
return getVariableValue(variable, shouldFetchVariable, {
|
|
82
|
+
client,
|
|
83
|
+
search,
|
|
84
|
+
snapshot,
|
|
85
|
+
taskContext,
|
|
56
86
|
token,
|
|
57
|
-
uid: resolved.uid,
|
|
58
|
-
values: normalizeRequest(formatDerivedVariableRequest(resolved.values), variable.variables),
|
|
59
|
-
wsClient: client,
|
|
60
|
-
}).then((resp) => {
|
|
61
|
-
// This is really only used in DownloadVariable currently; we can add support for tasks
|
|
62
|
-
// if it is requested in the future
|
|
63
|
-
if (isTaskResponse(resp)) {
|
|
64
|
-
throw new Error('Task DerivedVariables are not supported in this context');
|
|
65
|
-
}
|
|
66
|
-
// for derived data variables we need to make another request to retrieve the filtered value
|
|
67
|
-
if (isDerivedDataVariable(variable)) {
|
|
68
|
-
return client
|
|
69
|
-
.getChannel()
|
|
70
|
-
.then((chan) => fetchDerivedDataVariable(variable.uid, token, resp.cache_key, chan, variable.filters));
|
|
71
|
-
}
|
|
72
|
-
return resp.value;
|
|
73
87
|
});
|
|
74
88
|
};
|
|
75
89
|
}, [variable.uid, useDeepCompare(taskContext), client, search, token]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-variable-value.js","sourceRoot":"","sources":["../../../js/shared/interactivity/use-variable-value.tsx"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,
|
|
1
|
+
{"version":3,"file":"use-variable-value.js","sourceRoot":"","sources":["../../../js/shared/interactivity/use-variable-value.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { Action } from '../../types';
|
|
3
3
|
interface PrivateRouteProps {
|
|
4
4
|
/** The children to wrap */
|
|
5
5
|
children: ReactNode;
|
|
6
|
-
/** To have exact matching for the route path */
|
|
7
|
-
exact?: boolean;
|
|
8
6
|
/** Name of the page this route links to */
|
|
9
7
|
name?: string;
|
|
10
|
-
/** The route for the private route */
|
|
11
|
-
path: string;
|
|
12
8
|
/** Variables which should be reset upon visiting the page */
|
|
13
|
-
|
|
9
|
+
on_load?: Action;
|
|
14
10
|
}
|
|
15
11
|
/**
|
|
16
12
|
* The PrivateRoute component takes a private route object and checks for authentication.
|
|
@@ -18,6 +14,6 @@ interface PrivateRouteProps {
|
|
|
18
14
|
*
|
|
19
15
|
* @param props - the component props
|
|
20
16
|
*/
|
|
21
|
-
declare function PrivateRoute({ children,
|
|
17
|
+
declare function PrivateRoute({ children, on_load, name }: PrivateRouteProps): ReactNode;
|
|
22
18
|
export default PrivateRoute;
|
|
23
19
|
//# sourceMappingURL=private-route.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"private-route.d.ts","sourceRoot":"","sources":["../../../js/shared/private-route/private-route.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAa,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"private-route.d.ts","sourceRoot":"","sources":["../../../js/shared/private-route/private-route.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAa,MAAM,OAAO,CAAC;AAO7C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,UAAU,iBAAiB;IACvB,2BAA2B;IAC3B,QAAQ,EAAE,SAAS,CAAC;IACpB,2CAA2C;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,iBAAS,YAAY,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,iBAAiB,GAAG,SAAS,CAiB/E;AAED,eAAe,YAAY,CAAC"}
|
|
@@ -1,20 +1,10 @@
|
|
|
1
|
-
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
-
var t = {};
|
|
3
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
-
t[p] = s[p];
|
|
5
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
-
t[p[i]] = s[p[i]];
|
|
9
|
-
}
|
|
10
|
-
return t;
|
|
11
|
-
};
|
|
12
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
13
2
|
/* eslint-disable react-hooks/exhaustive-deps */
|
|
14
3
|
import { useEffect } from 'react';
|
|
15
|
-
import { Redirect
|
|
4
|
+
import { Redirect } from 'react-router-dom';
|
|
16
5
|
import { useSessionToken } from '../../auth/auth-context';
|
|
17
|
-
import
|
|
6
|
+
import DefaultFallback from '../../components/fallback/default';
|
|
7
|
+
import useAction from '../../shared/utils/use-action';
|
|
18
8
|
import useWindowTitle from '../../shared/utils/use-window-title';
|
|
19
9
|
/**
|
|
20
10
|
* The PrivateRoute component takes a private route object and checks for authentication.
|
|
@@ -22,19 +12,19 @@ import useWindowTitle from '../../shared/utils/use-window-title';
|
|
|
22
12
|
*
|
|
23
13
|
* @param props - the component props
|
|
24
14
|
*/
|
|
25
|
-
function PrivateRoute(
|
|
26
|
-
var { children, path, exact, reset_vars_on_load, name } = _a, rest = __rest(_a, ["children", "path", "exact", "reset_vars_on_load", "name"]);
|
|
15
|
+
function PrivateRoute({ children, on_load, name }) {
|
|
27
16
|
const token = useSessionToken();
|
|
28
|
-
const
|
|
17
|
+
const [onLoad, isLoading] = useAction(on_load);
|
|
29
18
|
useWindowTitle(name);
|
|
30
19
|
useEffect(() => {
|
|
31
|
-
// On mount,
|
|
32
|
-
|
|
20
|
+
// On mount, call the on_load action
|
|
21
|
+
onLoad();
|
|
33
22
|
}, []);
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
23
|
+
if (!token) {
|
|
24
|
+
return _jsx(Redirect, { to: "/login" });
|
|
25
|
+
}
|
|
26
|
+
// Show fallback while the onLoad action is in progress
|
|
27
|
+
return isLoading ? _jsx(DefaultFallback, {}) : children;
|
|
38
28
|
}
|
|
39
29
|
export default PrivateRoute;
|
|
40
30
|
//# sourceMappingURL=private-route.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"private-route.js","sourceRoot":"","sources":["../../../js/shared/private-route/private-route.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"private-route.js","sourceRoot":"","sources":["../../../js/shared/private-route/private-route.tsx"],"names":[],"mappings":";AAAA,gDAAgD;AAEhD,OAAO,EAAa,SAAS,EAAE,MAAM,OAAO,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,eAAe,MAAM,+BAA+B,CAAC;AAC5D,OAAO,SAAS,MAAM,2BAA2B,CAAC;AAClD,OAAO,cAAc,MAAM,iCAAiC,CAAC;AAY7D;;;;;GAKG;AACH,SAAS,YAAY,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAqB;IAChE,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAChC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IAE/C,cAAc,CAAC,IAAI,CAAC,CAAC;IAErB,SAAS,CAAC,GAAG,EAAE;QACX,oCAAoC;QACpC,MAAM,EAAE,CAAC;IACb,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,IAAI,CAAC,KAAK,EAAE;QACR,OAAO,KAAC,QAAQ,IAAC,EAAE,EAAC,QAAQ,GAAG,CAAC;KACnC;IAED,uDAAuD;IACvD,OAAO,SAAS,CAAC,CAAC,CAAC,KAAC,eAAe,KAAG,CAAC,CAAC,CAAC,QAAQ,CAAC;AACtD,CAAC;AAED,eAAe,YAAY,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ActionDef,
|
|
1
|
+
import { ActionDef, ActionImpl } from '../../types/core';
|
|
2
2
|
interface ActionRegistryInterface {
|
|
3
|
-
get: (instance:
|
|
3
|
+
get: (instance: ActionImpl) => ActionDef;
|
|
4
4
|
}
|
|
5
5
|
/**
|
|
6
6
|
* The action registry pulls the full list of actions from the backend and then returns a function that allows a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-action-registry.d.ts","sourceRoot":"","sources":["../../../js/shared/utils/use-action-registry.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"use-action-registry.d.ts","sourceRoot":"","sources":["../../../js/shared/utils/use-action-registry.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAErD,UAAU,uBAAuB;IAC7B,GAAG,EAAE,CAAC,QAAQ,EAAE,UAAU,KAAK,SAAS,CAAC;CAC5C;AAED;;;GAGG;AACH,iBAAS,iBAAiB,IAAI,uBAAuB,CAapD;AAED,eAAe,iBAAiB,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useCallback, useContext } from 'react';
|
|
1
|
+
import { useCallback, useContext, useMemo } from 'react';
|
|
2
2
|
import RegistriesCtx from '../../shared/context/registries-context';
|
|
3
3
|
/**
|
|
4
4
|
* The action registry pulls the full list of actions from the backend and then returns a function that allows a
|
|
@@ -6,13 +6,13 @@ import RegistriesCtx from '../../shared/context/registries-context';
|
|
|
6
6
|
*/
|
|
7
7
|
function useActionRegistry() {
|
|
8
8
|
const { actionRegistry: actions } = useContext(RegistriesCtx);
|
|
9
|
-
const get = useCallback((
|
|
10
|
-
if (actions && actions[
|
|
11
|
-
return actions[
|
|
9
|
+
const get = useCallback((impl) => {
|
|
10
|
+
if (actions && actions[impl.name]) {
|
|
11
|
+
return actions[impl.name];
|
|
12
12
|
}
|
|
13
|
-
throw new Error(`Attempted to load an action (${
|
|
13
|
+
throw new Error(`Attempted to load an action (${impl.name}) that is not in the registry`);
|
|
14
14
|
}, [actions]);
|
|
15
|
-
return { get };
|
|
15
|
+
return useMemo(() => ({ get }), [get]);
|
|
16
16
|
}
|
|
17
17
|
export default useActionRegistry;
|
|
18
18
|
//# sourceMappingURL=use-action-registry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-action-registry.js","sourceRoot":"","sources":["../../../js/shared/utils/use-action-registry.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"use-action-registry.js","sourceRoot":"","sources":["../../../js/shared/utils/use-action-registry.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAEzD,OAAO,aAAa,MAAM,qCAAqC,CAAC;AAOhE;;;GAGG;AACH,SAAS,iBAAiB;IACtB,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC,aAAa,CAAC,CAAC;IAE9D,MAAM,GAAG,GAAG,WAAW,CACnB,CAAC,IAAgB,EAAa,EAAE;QAC5B,IAAI,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YAC/B,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;SAC7B;QACD,MAAM,IAAI,KAAK,CAAC,gCAAgC,IAAI,CAAC,IAAI,+BAA+B,CAAC,CAAC;IAC9F,CAAC,EACD,CAAC,OAAO,CAAC,CACZ,CAAC;IACF,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;AAC3C,CAAC;AAED,eAAe,iBAAiB,CAAC"}
|
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
import { Action } from '../../types';
|
|
2
|
+
import { ActionContext, ActionImpl } from '../../types/core';
|
|
3
|
+
interface UseActionOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Callback to invoke when an unhandled action is encountered.
|
|
6
|
+
* When not defined, an error notification will be shown instead.
|
|
7
|
+
*
|
|
8
|
+
* @param action action implementation
|
|
9
|
+
*/
|
|
10
|
+
onUnhandledAction?: (action: ActionImpl, actionCtx: ActionContext) => void | Promise<void>;
|
|
11
|
+
}
|
|
2
12
|
/**
|
|
3
13
|
* Consume an action def from the framework and return a callback function that can be used to trigger it
|
|
4
14
|
* and a loading state boolean indicating whether an action is currently in progress
|
|
5
15
|
*
|
|
6
|
-
* @param
|
|
16
|
+
* @param action the action passed in
|
|
17
|
+
* @param options optional extra options for the hook
|
|
7
18
|
*/
|
|
8
|
-
export default function useAction(action: Action): [(
|
|
19
|
+
export default function useAction(action: Action, options?: UseActionOptions): [(input?: any) => Promise<void>, boolean];
|
|
20
|
+
export {};
|
|
9
21
|
//# sourceMappingURL=use-action.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-action.d.ts","sourceRoot":"","sources":["../../../js/shared/utils/use-action.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use-action.d.ts","sourceRoot":"","sources":["../../../js/shared/utils/use-action.tsx"],"names":[],"mappings":"AAcA,OAAO,EAAE,MAAM,EAAiB,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,aAAa,EAAa,UAAU,EAAmB,MAAM,cAAc,CAAC;AAoOrF,UAAU,gBAAgB;IACtB;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9F;AAED;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,SAAS,CAC7B,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,gBAAgB,GAC3B,CAAC,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CA4F3C"}
|
|
@@ -7,79 +7,273 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
10
|
+
import { useContext, useRef, useState } from 'react';
|
|
11
|
+
import { useHistory, useLocation } from 'react-router-dom';
|
|
12
|
+
import { useRecoilCallback } from 'recoil';
|
|
13
|
+
import { concatMap, takeWhile } from 'rxjs/operators';
|
|
14
|
+
import shortid from 'shortid';
|
|
15
|
+
import { useNotifications } from '@darajs/ui-notifications';
|
|
16
|
+
import { HTTP_METHOD, Status, validateResponse } from '@darajs/ui-utils';
|
|
17
|
+
import { fetchTaskResult } from '../../api';
|
|
18
|
+
import { request } from '../../api/http';
|
|
19
|
+
import { useSessionToken } from '../../auth/auth-context';
|
|
20
|
+
import { ImportersCtx, WebSocketCtx, useTaskContext } from '../../shared/context';
|
|
21
|
+
import { isActionImpl } from '../../types/utils';
|
|
22
|
+
import { resolveVariable } from '../interactivity/resolve-variable';
|
|
23
|
+
import { normalizeRequest } from './normalization';
|
|
14
24
|
import useActionRegistry from './use-action-registry';
|
|
15
|
-
// Disabling rules of hook since the followiing function are willingly breaking the rules, making the assumption that the components call
|
|
16
|
-
// the exported functions with values which don't change the hook order etc
|
|
17
|
-
/* eslint-disable react-hooks/rules-of-hooks */
|
|
18
|
-
/* eslint-disable react-hooks/exhaustive-deps */
|
|
19
25
|
/**
|
|
20
|
-
*
|
|
26
|
+
* Invoke a server-side action.
|
|
27
|
+
* This is used for annotated actions, sends a POST request to the server to start an action execution.
|
|
21
28
|
*
|
|
22
|
-
* @param
|
|
23
|
-
* @param
|
|
29
|
+
* @param input input value for the action
|
|
30
|
+
* @param executionId unique id for the action execution; this should be used to subscribe to action messages **before** calling fetchAction
|
|
31
|
+
* @param annotatedAction annotated action instance
|
|
32
|
+
* @param actionCtx action context
|
|
33
|
+
*/
|
|
34
|
+
function invokeAction(input, executionId, annotatedAction, actionCtx) {
|
|
35
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
36
|
+
// resolve kwargs to primitives, this registers variables if not already registered
|
|
37
|
+
const resolvedKwargs = Object.keys(annotatedAction.dynamic_kwargs).reduce((acc, k) => {
|
|
38
|
+
const value = annotatedAction.dynamic_kwargs[k];
|
|
39
|
+
acc[k] = resolveVariable(value, actionCtx.wsClient, actionCtx.taskCtx, actionCtx.location.search, actionCtx.sessionToken, (v) =>
|
|
40
|
+
// This is only called for primitive variables so it should always resolve successfully
|
|
41
|
+
// hence not using a promise
|
|
42
|
+
actionCtx.snapshot.getLoadable(v).getValue());
|
|
43
|
+
return acc;
|
|
44
|
+
}, {});
|
|
45
|
+
const ws_channel = yield actionCtx.wsClient.getChannel();
|
|
46
|
+
const res = yield request(`/api/core/action/${annotatedAction.definition_uid}`, {
|
|
47
|
+
body: JSON.stringify({
|
|
48
|
+
execution_id: executionId,
|
|
49
|
+
input,
|
|
50
|
+
uid: annotatedAction.uid,
|
|
51
|
+
values: normalizeRequest(resolvedKwargs, annotatedAction.dynamic_kwargs),
|
|
52
|
+
ws_channel,
|
|
53
|
+
}),
|
|
54
|
+
method: HTTP_METHOD.POST,
|
|
55
|
+
}, actionCtx.sessionToken);
|
|
56
|
+
yield validateResponse(res, `Failed to fetch the action value with uid: ${annotatedAction.uid}`);
|
|
57
|
+
const resContent = yield res.json();
|
|
58
|
+
// for tasks, wait for it to finish and fetch the result
|
|
59
|
+
// this is only used to pick up errors in the task execution
|
|
60
|
+
if ('task_id' in resContent) {
|
|
61
|
+
const taskId = resContent.task_id;
|
|
62
|
+
actionCtx.taskCtx.startTask(taskId);
|
|
63
|
+
yield actionCtx.wsClient.waitForTask(taskId);
|
|
64
|
+
actionCtx.taskCtx.endTask(taskId);
|
|
65
|
+
// We don't need the result as the MetaTask will send WS messages with actions as per usual
|
|
66
|
+
// fetchTaskResult will pick up on errors and raise them
|
|
67
|
+
yield fetchTaskResult(taskId, actionCtx.sessionToken);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Global cache of action handlers by name. Used for perf so each action will only have to be
|
|
73
|
+
* resolved once.
|
|
74
|
+
*/
|
|
75
|
+
const ACTION_HANDLER_BY_NAME = {};
|
|
76
|
+
/**
|
|
77
|
+
* Error thrown when an action is not handled by the app.
|
|
78
|
+
*/
|
|
79
|
+
class UnhandledActionError extends Error {
|
|
80
|
+
constructor(message, actionImpl) {
|
|
81
|
+
super(message);
|
|
82
|
+
this.actionImpl = actionImpl;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Resolve an action implementation into an action handler function.
|
|
87
|
+
*
|
|
88
|
+
* @param actionImpl action implementation
|
|
89
|
+
* @param getAction callback to get the action definition from the action implementation
|
|
24
90
|
* @param importers importers available in the app
|
|
25
91
|
*/
|
|
26
|
-
function
|
|
92
|
+
function resolveActionImpl(actionImpl, getAction, importers) {
|
|
27
93
|
return __awaiter(this, void 0, void 0, function* () {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
94
|
+
// cache action handler globally for performance, they are pure functions so it's safe to do so
|
|
95
|
+
if (!ACTION_HANDLER_BY_NAME[actionImpl.name]) {
|
|
96
|
+
// resolve action handler function by name
|
|
97
|
+
let actionDef;
|
|
98
|
+
try {
|
|
99
|
+
actionDef = getAction(actionImpl);
|
|
100
|
+
}
|
|
101
|
+
catch (_a) {
|
|
102
|
+
throw new UnhandledActionError(`Action definition for impl "${actionImpl.name}" not found`, actionImpl);
|
|
103
|
+
}
|
|
104
|
+
const moduleContent = yield importers[actionDef.py_module]();
|
|
105
|
+
ACTION_HANDLER_BY_NAME[actionImpl.name] = moduleContent[actionImpl.name];
|
|
37
106
|
}
|
|
38
|
-
return
|
|
107
|
+
return ACTION_HANDLER_BY_NAME[actionImpl.name];
|
|
39
108
|
});
|
|
40
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* Execute a given action.
|
|
112
|
+
*
|
|
113
|
+
* @param input component input value
|
|
114
|
+
* @param action action implementation or annotated action
|
|
115
|
+
* @param actionCtx action execution context
|
|
116
|
+
* @param getAction callback to get the action definition from the action implementation
|
|
117
|
+
* @param importers available importers in the app
|
|
118
|
+
*/
|
|
119
|
+
function executeAction(input, action, actionCtx, getAction, importers) {
|
|
120
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
121
|
+
// if it's a simple action implementation, run the handler directly
|
|
122
|
+
if (isActionImpl(action)) {
|
|
123
|
+
const handler = yield resolveActionImpl(action, getAction, importers);
|
|
124
|
+
const result = handler(actionCtx, action);
|
|
125
|
+
// handle async handlers
|
|
126
|
+
if (result instanceof Promise) {
|
|
127
|
+
yield result;
|
|
128
|
+
}
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
// otherwise call back to the server to execute the annotated action
|
|
132
|
+
// subscribe to action messages before even calling the action to avoid races
|
|
133
|
+
const executionId = shortid.generate();
|
|
134
|
+
const observable = actionCtx.wsClient.actionMessages$(executionId);
|
|
135
|
+
return new Promise((resolve, reject) => {
|
|
136
|
+
let activeTasks = 0; // Counter to keep track of active tasks
|
|
137
|
+
let streamCompleted = false; // Flag to check if the stream is completed
|
|
138
|
+
let isSettled = false;
|
|
139
|
+
let sub;
|
|
140
|
+
const checkForCompletion = () => {
|
|
141
|
+
if (!isSettled && streamCompleted && activeTasks === 0) {
|
|
142
|
+
isSettled = true;
|
|
143
|
+
sub.unsubscribe();
|
|
144
|
+
resolve();
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
const onError = (error) => {
|
|
148
|
+
// eslint-disable-next-line no-console
|
|
149
|
+
console.error('Error executing action:', error);
|
|
150
|
+
if (!isSettled) {
|
|
151
|
+
isSettled = true;
|
|
152
|
+
sub.unsubscribe();
|
|
153
|
+
reject(error);
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
sub = observable
|
|
157
|
+
.pipe(concatMap((actionImpl) => __awaiter(this, void 0, void 0, function* () {
|
|
158
|
+
if (actionImpl) {
|
|
159
|
+
const handler = yield resolveActionImpl(actionImpl, getAction, importers);
|
|
160
|
+
return [handler, actionImpl];
|
|
161
|
+
}
|
|
162
|
+
return null;
|
|
163
|
+
})), takeWhile((res) => !!res) // stop when falsy is returned from concatMap
|
|
164
|
+
)
|
|
165
|
+
.subscribe({
|
|
166
|
+
complete: () => {
|
|
167
|
+
streamCompleted = true; // Set the flag when the stream is complete
|
|
168
|
+
checkForCompletion();
|
|
169
|
+
},
|
|
170
|
+
error: onError,
|
|
171
|
+
next: ([handler, actionImpl]) => __awaiter(this, void 0, void 0, function* () {
|
|
172
|
+
try {
|
|
173
|
+
activeTasks += 1;
|
|
174
|
+
const result = handler(actionCtx, actionImpl);
|
|
175
|
+
// If it's a promise, await it to ensure sequential execution
|
|
176
|
+
if (result instanceof Promise) {
|
|
177
|
+
yield result;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
catch (error) {
|
|
181
|
+
onError(error);
|
|
182
|
+
}
|
|
183
|
+
finally {
|
|
184
|
+
if (activeTasks > 0) {
|
|
185
|
+
activeTasks -= 1;
|
|
186
|
+
}
|
|
187
|
+
checkForCompletion();
|
|
188
|
+
}
|
|
189
|
+
}),
|
|
190
|
+
});
|
|
191
|
+
// now request the action to be executed
|
|
192
|
+
invokeAction(input, executionId, action, actionCtx).catch(onError);
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
const noop = () => Promise.resolve();
|
|
41
197
|
/**
|
|
42
198
|
* Consume an action def from the framework and return a callback function that can be used to trigger it
|
|
43
199
|
* and a loading state boolean indicating whether an action is currently in progress
|
|
44
200
|
*
|
|
45
|
-
* @param
|
|
201
|
+
* @param action the action passed in
|
|
202
|
+
* @param options optional extra options for the hook
|
|
46
203
|
*/
|
|
47
|
-
export default function useAction(action) {
|
|
48
|
-
|
|
49
|
-
if ((action === null || action === void 0 ? void 0 : action.name) === 'ActionInstance') {
|
|
50
|
-
throw new Error('Expected a registered sub-class of "ActionInstance", base class detected');
|
|
51
|
-
}
|
|
52
|
-
// No action passed - noop
|
|
53
|
-
if (!action || (Array.isArray(action) && action.length === 0)) {
|
|
54
|
-
return [() => Promise.resolve(), false];
|
|
55
|
-
}
|
|
56
|
-
const [loading, setLoading] = useState(false);
|
|
204
|
+
export default function useAction(action, options) {
|
|
205
|
+
const { client: wsClient } = useContext(WebSocketCtx);
|
|
57
206
|
const importers = useContext(ImportersCtx);
|
|
58
|
-
const actionContext = useActionContext();
|
|
59
207
|
const { get: getAction } = useActionRegistry();
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
const
|
|
63
|
-
const
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
208
|
+
const notificationCtx = useNotifications();
|
|
209
|
+
const sessionToken = useSessionToken();
|
|
210
|
+
const history = useHistory();
|
|
211
|
+
const taskCtx = useTaskContext();
|
|
212
|
+
const location = useLocation();
|
|
213
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
214
|
+
// keep actionCtx in a ref to avoid re-creating the callbacks
|
|
215
|
+
const actionCtx = useRef();
|
|
216
|
+
actionCtx.current = {
|
|
217
|
+
history,
|
|
218
|
+
location,
|
|
219
|
+
notificationCtx,
|
|
220
|
+
sessionToken,
|
|
221
|
+
taskCtx,
|
|
222
|
+
wsClient,
|
|
223
|
+
};
|
|
224
|
+
const optionsRef = useRef(options);
|
|
225
|
+
optionsRef.current = options;
|
|
226
|
+
const callback = useRecoilCallback((cbInterface) => (input) => __awaiter(this, void 0, void 0, function* () {
|
|
227
|
+
var _a;
|
|
228
|
+
setIsLoading(true);
|
|
229
|
+
const actionsToExecute = Array.isArray(action) ? action : [action];
|
|
230
|
+
// execute actions sequentially
|
|
231
|
+
for (const actionToExecute of actionsToExecute) {
|
|
232
|
+
// this is redefined for each action to have up-to-date snapshot
|
|
233
|
+
/* eslint-disable sort-keys-fix/sort-keys-fix */
|
|
234
|
+
const fullActionContext = Object.assign(Object.assign({}, actionCtx.current), { input,
|
|
235
|
+
// Recoil callback interface cannot be spread as it is a Proxy
|
|
236
|
+
gotoSnapshot: cbInterface.gotoSnapshot, refresh: cbInterface.refresh, reset: cbInterface.reset, set: cbInterface.set, snapshot: cbInterface.snapshot, transact_UNSTABLE: cbInterface.transact_UNSTABLE });
|
|
237
|
+
/* eslint-enable sort-keys-fix/sort-keys-fix */
|
|
238
|
+
try {
|
|
74
239
|
// eslint-disable-next-line no-await-in-loop
|
|
75
|
-
yield
|
|
240
|
+
yield executeAction(input, actionToExecute, fullActionContext, getAction, importers);
|
|
241
|
+
}
|
|
242
|
+
catch (error) {
|
|
243
|
+
// Handle unhandled action errors separately
|
|
244
|
+
if (error instanceof UnhandledActionError) {
|
|
245
|
+
// there is a callback defined for it, call it
|
|
246
|
+
if ((_a = optionsRef.current) === null || _a === void 0 ? void 0 : _a.onUnhandledAction) {
|
|
247
|
+
const result = optionsRef.current.onUnhandledAction(error.actionImpl, fullActionContext);
|
|
248
|
+
if (result instanceof Promise) {
|
|
249
|
+
// eslint-disable-next-line no-await-in-loop
|
|
250
|
+
yield result;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
actionCtx.current.notificationCtx.pushNotification({
|
|
255
|
+
key: '_actionError',
|
|
256
|
+
message: `Action "${error.actionImpl.name}" not registered`,
|
|
257
|
+
status: Status.ERROR,
|
|
258
|
+
title: 'Error executing action',
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
actionCtx.current.notificationCtx.pushNotification({
|
|
264
|
+
key: '_actionError',
|
|
265
|
+
message: 'Try again or contact the application owner',
|
|
266
|
+
status: Status.ERROR,
|
|
267
|
+
title: 'Error executing action',
|
|
268
|
+
});
|
|
76
269
|
}
|
|
77
270
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
271
|
+
setIsLoading(false);
|
|
272
|
+
}), [action, getAction, importers]);
|
|
273
|
+
// return a noop if no action is passed
|
|
274
|
+
if (!action) {
|
|
275
|
+
return [noop, false];
|
|
276
|
+
}
|
|
277
|
+
return [callback, isLoading];
|
|
84
278
|
}
|
|
85
279
|
//# sourceMappingURL=use-action.js.map
|