@ea-lab/reactive-json 0.0.20 → 0.0.22
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/README.md +1 -1
- package/dist/esm/types/component/action/HashChangeListener.d.ts +9 -0
- package/{lib/component/action/Hide.jsx → dist/esm/types/component/action/Hide.d.ts} +2 -6
- package/dist/esm/types/component/action/MessageListener.d.ts +9 -0
- package/dist/esm/types/component/action/Popover.d.ts +5 -0
- package/dist/esm/types/component/action/ReactOnEvent.d.ts +26 -0
- package/dist/esm/types/component/action/Redirect.d.ts +9 -0
- package/dist/esm/types/component/action/Tooltip.d.ts +5 -0
- package/{lib/component/action/VisuallyHide.jsx → dist/esm/types/component/action/VisuallyHide.d.ts} +1 -4
- package/dist/esm/types/component/element/form/CheckBoxField.d.ts +7 -0
- package/dist/esm/types/component/element/form/DateField.d.ts +2 -0
- package/dist/esm/types/component/element/form/NumberField.d.ts +7 -0
- package/dist/esm/types/component/element/form/SelectField.d.ts +7 -0
- package/dist/esm/types/component/element/form/TextAreaField.d.ts +6 -0
- package/dist/esm/types/component/element/form/TextField.d.ts +6 -0
- package/dist/esm/types/component/element/form/formElementsCommon.d.ts +23 -0
- package/dist/esm/types/component/element/html/AccordionItem.d.ts +16 -0
- package/dist/esm/types/component/element/html/FolderSortableTree.d.ts +6 -0
- package/dist/esm/types/component/element/html/FormatNumeral.d.ts +7 -0
- package/dist/esm/types/component/element/html/Html.d.ts +8 -0
- package/dist/esm/types/component/element/html/LabelFromValue.d.ts +22 -0
- package/dist/esm/types/component/element/html/Modal.d.ts +6 -0
- package/dist/esm/types/component/element/html/ModalForm.d.ts +9 -0
- package/dist/esm/types/component/element/html/Paragraph.d.ts +5 -0
- package/dist/esm/types/component/element/html/PreformattedMarkup.d.ts +7 -0
- package/dist/esm/types/component/element/html/SortableTreeItemCollapseButton.d.ts +9 -0
- package/dist/esm/types/component/element/html/Tabs.d.ts +18 -0
- package/dist/esm/types/component/element/special/BootstrapElement.d.ts +10 -0
- package/dist/esm/types/component/element/special/Count.d.ts +13 -0
- package/dist/esm/types/component/element/special/DataFilter.d.ts +11 -0
- package/dist/esm/types/component/element/special/DelayedActions.d.ts +25 -0
- package/dist/esm/types/component/element/special/PageControls.d.ts +9 -0
- package/dist/esm/types/component/element/special/Phantom.d.ts +17 -0
- package/dist/esm/types/component/element/special/Switch.d.ts +6 -0
- package/dist/esm/types/component/hook/usePagination.d.ts +30 -0
- package/dist/esm/types/component/index.d.ts +5 -0
- package/dist/esm/types/component/reaction/addData.d.ts +6 -0
- package/dist/esm/types/component/reaction/fetchData.d.ts +8 -0
- package/dist/esm/types/component/reaction/moveData.d.ts +6 -0
- package/dist/esm/types/component/reaction/postMessage.d.ts +6 -0
- package/dist/esm/types/component/reaction/redirectNow.d.ts +6 -0
- package/dist/esm/types/component/reaction/removeData.d.ts +6 -0
- package/dist/esm/types/component/reaction/setClipboardData.d.ts +6 -0
- package/dist/esm/types/component/reaction/setData.d.ts +6 -0
- package/dist/esm/types/component/reaction/submitData.d.ts +8 -0
- package/dist/esm/types/component/reaction/triggerEvent.d.ts +6 -0
- package/dist/esm/types/component/utility/formatString.d.ts +17 -0
- package/dist/esm/types/engine/Actions.d.ts +19 -0
- package/dist/esm/types/engine/ComponentCollector.d.ts +12 -0
- package/{lib/engine/EventDispatcherContext.jsx → dist/esm/types/engine/EventDispatcherContext.d.ts} +4 -7
- package/dist/esm/types/engine/EventDispatcherProvider.d.ts +16 -0
- package/{lib/engine/GlobalDataContext.jsx → dist/esm/types/engine/GlobalDataContext.d.ts} +1 -4
- package/dist/esm/types/engine/GlobalDataContextProvider.d.ts +11 -0
- package/{lib/engine/PaginationContext.jsx → dist/esm/types/engine/PaginationContext.d.ts} +3 -4
- package/dist/esm/types/engine/PaginationProvider.d.ts +12 -0
- package/dist/esm/types/engine/ReactiveJsonRoot.d.ts +28 -0
- package/{lib/engine/TemplateContext.jsx → dist/esm/types/engine/TemplateContext.d.ts} +1 -4
- package/dist/esm/types/engine/TemplateSystem.d.ts +89 -0
- package/dist/esm/types/engine/View.d.ts +7 -0
- package/dist/esm/types/index.d.ts +6 -0
- package/dist/esm/types/main.d.ts +10 -0
- package/dist/index.cjs.js +9201 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.esm.js +9180 -0
- package/dist/index.esm.js.map +1 -0
- package/package.json +26 -15
- package/dist/reactive-json.css +0 -5
- package/dist/reactive-json.js +0 -47707
- package/dist/reactive-json.js.map +0 -1
- package/dist/reactive-json.umd.cjs +0 -366
- package/dist/reactive-json.umd.cjs.map +0 -1
- package/lib/component/action/HashChangeListener.jsx +0 -66
- package/lib/component/action/MessageListener.jsx +0 -62
- package/lib/component/action/Popover.jsx +0 -53
- package/lib/component/action/ReactOnEvent.jsx +0 -118
- package/lib/component/action/Redirect.jsx +0 -26
- package/lib/component/action/Tooltip.jsx +0 -27
- package/lib/component/element/form/CheckBoxField.jsx +0 -215
- package/lib/component/element/form/DateField.jsx +0 -42
- package/lib/component/element/form/NumberField.jsx +0 -29
- package/lib/component/element/form/SelectField.jsx +0 -130
- package/lib/component/element/form/TextAreaField.jsx +0 -48
- package/lib/component/element/form/TextField.jsx +0 -65
- package/lib/component/element/form/formElementsCommon.jsx +0 -54
- package/lib/component/element/html/AccordionItem.jsx +0 -42
- package/lib/component/element/html/FolderSortableTree.jsx +0 -307
- package/lib/component/element/html/FormatNumeral.jsx +0 -118
- package/lib/component/element/html/Html.jsx +0 -107
- package/lib/component/element/html/LabelFromValue.jsx +0 -89
- package/lib/component/element/html/Modal.jsx +0 -77
- package/lib/component/element/html/ModalForm.jsx +0 -30
- package/lib/component/element/html/Paragraph.jsx +0 -10
- package/lib/component/element/html/PreformattedMarkup.jsx +0 -54
- package/lib/component/element/html/SortableTreeItemCollapseButton.jsx +0 -20
- package/lib/component/element/html/Tabs.jsx +0 -55
- package/lib/component/element/special/BootstrapElement.jsx +0 -32
- package/lib/component/element/special/Count.jsx +0 -46
- package/lib/component/element/special/DataFilter.jsx +0 -156
- package/lib/component/element/special/DelayedActions.jsx +0 -119
- package/lib/component/element/special/PageControls.jsx +0 -19
- package/lib/component/element/special/Phantom.jsx +0 -25
- package/lib/component/element/special/Switch.jsx +0 -131
- package/lib/component/hook/usePagination.jsx +0 -184
- package/lib/component/reaction/addData.jsx +0 -23
- package/lib/component/reaction/fetchData.jsx +0 -83
- package/lib/component/reaction/moveData.jsx +0 -52
- package/lib/component/reaction/postMessage.jsx +0 -43
- package/lib/component/reaction/redirectNow.jsx +0 -17
- package/lib/component/reaction/removeData.jsx +0 -48
- package/lib/component/reaction/setClipboardData.jsx +0 -20
- package/lib/component/reaction/setData.jsx +0 -23
- package/lib/component/reaction/submitData.jsx +0 -136
- package/lib/component/reaction/triggerEvent.jsx +0 -62
- package/lib/component/utility/formatString.jsx +0 -59
- package/lib/engine/Actions.jsx +0 -392
- package/lib/engine/ComponentCollector.js +0 -28
- package/lib/engine/EventDispatcherProvider.jsx +0 -80
- package/lib/engine/GlobalDataContextProvider.jsx +0 -33
- package/lib/engine/PaginationProvider.jsx +0 -61
- package/lib/engine/ReactiveJsonRoot.jsx +0 -318
- package/lib/engine/TemplateSystem.jsx +0 -302
- package/lib/engine/View.jsx +0 -248
- package/lib/main.jsx +0 -52
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import axios from "axios";
|
|
2
|
-
import {evaluateTemplateValue} from "../../engine/TemplateSystem";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Fetches data. Similar to submitData, but for GET requests.
|
|
6
|
-
*
|
|
7
|
-
* Will reload the app content if refreshAppOnResponse is true.
|
|
8
|
-
*
|
|
9
|
-
* @param {{args: {refreshAppOnResponse, url}, event, globalDataContext, templateContext}} props Reaction function props.
|
|
10
|
-
*/
|
|
11
|
-
export const fetchData = (props) => {
|
|
12
|
-
// Prevent multiple submits / fetches.
|
|
13
|
-
const reactionEvent = props?.event;
|
|
14
|
-
|
|
15
|
-
// Check in realtime if we are already submitting.
|
|
16
|
-
// With this system, only 1 submit can be made concurrently for all roots.
|
|
17
|
-
const body = document.body;
|
|
18
|
-
|
|
19
|
-
if (body.dataset.htmlBuilderIsSubmitting === "true") {
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// This will block any attempts to resubmit until receiving the response.
|
|
24
|
-
body.dataset.htmlBuilderIsSubmitting = "true";
|
|
25
|
-
|
|
26
|
-
const currentTarget = reactionEvent.currentTarget;
|
|
27
|
-
|
|
28
|
-
if (currentTarget?.dataset) {
|
|
29
|
-
// Useful for styling.
|
|
30
|
-
currentTarget.dataset.isSubmitting = "true";
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const {globalDataContext: _globalDataContext, templateContext} = props;
|
|
34
|
-
|
|
35
|
-
// Use the root context when submitting data,
|
|
36
|
-
// not the maybe-filtered one that the DataFilter component may have edited.
|
|
37
|
-
// This could be made configurable if ever needed.
|
|
38
|
-
const globalDataContext = _globalDataContext.getRootContext ? _globalDataContext.getRootContext() : _globalDataContext;
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Tells if the response content will replace the current app content.
|
|
42
|
-
*
|
|
43
|
-
* @type {boolean}
|
|
44
|
-
*/
|
|
45
|
-
const refreshAppOnResponse = props?.args?.refreshAppOnResponse ?? true;
|
|
46
|
-
|
|
47
|
-
const url = evaluateTemplateValue({
|
|
48
|
-
valueToEvaluate: props?.args?.url, globalDataContext, templateContext
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
if (!url) {
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const headers = globalDataContext.headersForData ?? {};
|
|
56
|
-
|
|
57
|
-
const {setRawAppData} = globalDataContext;
|
|
58
|
-
|
|
59
|
-
axios
|
|
60
|
-
.get(
|
|
61
|
-
url,
|
|
62
|
-
{
|
|
63
|
-
headers
|
|
64
|
-
})
|
|
65
|
-
.then((value) => {
|
|
66
|
-
if (!refreshAppOnResponse) {
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// This will trigger a complete re-render.
|
|
71
|
-
setRawAppData(value.data);
|
|
72
|
-
})
|
|
73
|
-
.catch((reason) => {
|
|
74
|
-
console.log("reactionFunction:fetchData : Could not fetch. Reason: " + reason.message);
|
|
75
|
-
})
|
|
76
|
-
.finally(() => {
|
|
77
|
-
delete body.dataset.htmlBuilderIsSubmitting;
|
|
78
|
-
|
|
79
|
-
if (currentTarget?.dataset) {
|
|
80
|
-
delete currentTarget.dataset.isSubmitting;
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
};
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import {dataLocationToPath} from "../../engine/TemplateSystem";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Moves data at the specified path.
|
|
5
|
-
*
|
|
6
|
-
* @param {{}} props
|
|
7
|
-
*/
|
|
8
|
-
export const moveData = (props) => {
|
|
9
|
-
const {globalDataContext, templateContext} = props;
|
|
10
|
-
const {path, target} = props.args;
|
|
11
|
-
|
|
12
|
-
if (path === undefined && target !== "currentTemplateData") {
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
let dataAbsolutePath;
|
|
17
|
-
|
|
18
|
-
if (path) {
|
|
19
|
-
dataAbsolutePath = dataLocationToPath({
|
|
20
|
-
currentPath: templateContext.templatePath,
|
|
21
|
-
dataLocation: path,
|
|
22
|
-
globalDataContext,
|
|
23
|
-
templateContext
|
|
24
|
-
});
|
|
25
|
-
} else {
|
|
26
|
-
// Target mode.
|
|
27
|
-
dataAbsolutePath = templateContext.templatePath;
|
|
28
|
-
|
|
29
|
-
// Dev note: could this be interesting for the other mode?
|
|
30
|
-
let parentLevel = props.args.parentLevel ?? 0;
|
|
31
|
-
|
|
32
|
-
while (parentLevel > 0) {
|
|
33
|
-
--parentLevel;
|
|
34
|
-
|
|
35
|
-
// Remove a level from the path.
|
|
36
|
-
const lastIndex = dataAbsolutePath.lastIndexOf('.');
|
|
37
|
-
|
|
38
|
-
if (lastIndex < 1) {
|
|
39
|
-
// No valid path to remove. Is there a valid use case where we should remove everything?
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
dataAbsolutePath = dataAbsolutePath.substring(0, lastIndex);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const {increment} = props.args;
|
|
48
|
-
|
|
49
|
-
globalDataContext?.updateData({
|
|
50
|
-
increment,
|
|
51
|
-
}, dataAbsolutePath, "move");
|
|
52
|
-
};
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import {evaluateTemplateValueCollection} from "../../engine/TemplateSystem";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Posts a message to the specified target.
|
|
5
|
-
*
|
|
6
|
-
* @param {{args: {includeChangedValue, message, messageTarget, on, targetOrigin}, event, globalDataContext, templateContext}} props
|
|
7
|
-
*/
|
|
8
|
-
export const postMessage = (props) => {
|
|
9
|
-
const messageTargets = {
|
|
10
|
-
parent: window.parent,
|
|
11
|
-
self: window,
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
const messageTarget = messageTargets[props?.args?.messageTarget ?? "parent"] ?? window;
|
|
15
|
-
|
|
16
|
-
// The targetOrigin must match the schema and domain where the message will be sent.
|
|
17
|
-
// Otherwise, the message will be discarded for security reasons.
|
|
18
|
-
// When not set, the target will be the current location's origin by default.
|
|
19
|
-
const messageTargetOrigin = props?.args?.targetOrigin ?? window.location.origin;
|
|
20
|
-
|
|
21
|
-
const message_evaluated = evaluateTemplateValueCollection({
|
|
22
|
-
globalDataContext: props.globalDataContext,
|
|
23
|
-
templateContext: props.templateContext,
|
|
24
|
-
valueToEvaluate: props?.args?.message
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
if (props?.args?.on === "change" && typeof message_evaluated === "object" && props?.args?.includeChangedValue && props?.event?.target?.nodeName === "INPUT") {
|
|
28
|
-
let changedValue;
|
|
29
|
-
|
|
30
|
-
switch (props?.event?.target?.type) {
|
|
31
|
-
case "checkbox":
|
|
32
|
-
changedValue = props?.event?.target?.checked;
|
|
33
|
-
break;
|
|
34
|
-
|
|
35
|
-
default:
|
|
36
|
-
// TODO: support other types.
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
message_evaluated["changedValue"] = changedValue;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
(messageTarget && messageTargetOrigin) && messageTarget.postMessage(message_evaluated, messageTargetOrigin);
|
|
43
|
-
};
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import {evaluateTemplateValue} from "../../engine/TemplateSystem";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Redirects to the specified URL.
|
|
5
|
-
*
|
|
6
|
-
* @param {{}} props
|
|
7
|
-
*/
|
|
8
|
-
export const redirectNow = (props) => {
|
|
9
|
-
const {globalDataContext, templateContext} = props;
|
|
10
|
-
const {to} = props.args;
|
|
11
|
-
|
|
12
|
-
if (!to || typeof to !== "string") {
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
window.location.href = evaluateTemplateValue({valueToEvaluate: to, globalDataContext, templateContext});
|
|
17
|
-
};
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import {dataLocationToPath} from "../../engine/TemplateSystem";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Removes data at the specified path.
|
|
5
|
-
*
|
|
6
|
-
* @param {{}} props
|
|
7
|
-
*/
|
|
8
|
-
export const removeData = (props) => {
|
|
9
|
-
const {globalDataContext, templateContext} = props;
|
|
10
|
-
const {path, target} = props.args;
|
|
11
|
-
|
|
12
|
-
if (path === undefined && target !== "currentTemplateData") {
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
let dataAbsolutePath;
|
|
17
|
-
|
|
18
|
-
if (path) {
|
|
19
|
-
dataAbsolutePath = dataLocationToPath({
|
|
20
|
-
currentPath: templateContext.templatePath,
|
|
21
|
-
dataLocation: path,
|
|
22
|
-
globalDataContext,
|
|
23
|
-
templateContext
|
|
24
|
-
});
|
|
25
|
-
} else {
|
|
26
|
-
// Target mode.
|
|
27
|
-
dataAbsolutePath = templateContext.templatePath;
|
|
28
|
-
|
|
29
|
-
// Dev note: could this be interesting for the other mode?
|
|
30
|
-
let parentLevel = props.args.parentLevel ?? 0;
|
|
31
|
-
|
|
32
|
-
while (parentLevel > 0) {
|
|
33
|
-
--parentLevel;
|
|
34
|
-
|
|
35
|
-
// Remove a level from the path.
|
|
36
|
-
const lastIndex = dataAbsolutePath.lastIndexOf('.');
|
|
37
|
-
|
|
38
|
-
if (lastIndex < 1) {
|
|
39
|
-
// No valid path to remove. Is there a valid use case where we should remove everything?
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
dataAbsolutePath = dataAbsolutePath.substring(0, lastIndex);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
globalDataContext?.updateData(undefined, dataAbsolutePath, "remove");
|
|
48
|
-
};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import {evaluateTemplateValue} from "../../engine/TemplateSystem";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Copies data to the clipboard.
|
|
5
|
-
*
|
|
6
|
-
* @param {{}} props
|
|
7
|
-
*/
|
|
8
|
-
export const setClipboardData = async (props) => {
|
|
9
|
-
const {globalDataContext, templateContext} = props;
|
|
10
|
-
const evaluatedValue = evaluateTemplateValue({valueToEvaluate: props?.args?.value, globalDataContext, templateContext});
|
|
11
|
-
|
|
12
|
-
if (typeof evaluatedValue === 'string') {
|
|
13
|
-
try {
|
|
14
|
-
// Attempt to copy to clipboard.
|
|
15
|
-
await navigator.clipboard.writeText(evaluatedValue.toString());
|
|
16
|
-
} catch (error) {
|
|
17
|
-
console.error('Failed to copy data to the clipboard:', error);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
};
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import {dataLocationToPath, evaluateTemplateValue} from "../../engine/TemplateSystem";
|
|
2
|
-
import {cloneDeep} from "lodash";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Sets data at the specified path.
|
|
6
|
-
*
|
|
7
|
-
* @param {{}} props
|
|
8
|
-
*/
|
|
9
|
-
export const setData = (props) => {
|
|
10
|
-
const {globalDataContext, templateContext} = props;
|
|
11
|
-
const {path, value} = props.args;
|
|
12
|
-
|
|
13
|
-
if (path === undefined) {
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const dataAbsolutePath = dataLocationToPath({currentPath: templateContext.templatePath, dataLocation: path, globalDataContext, templateContext});
|
|
18
|
-
|
|
19
|
-
const evaluatedValue = evaluateTemplateValue({valueToEvaluate: value, globalDataContext, templateContext});
|
|
20
|
-
|
|
21
|
-
// We clone the value to have distinct instances when the value is an object.
|
|
22
|
-
globalDataContext?.updateData(typeof evaluatedValue !== "object" ? evaluatedValue : cloneDeep(evaluatedValue), dataAbsolutePath);
|
|
23
|
-
};
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
import axios from "axios";
|
|
2
|
-
import {evaluateTemplateValue} from "../../engine/TemplateSystem";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Submits the current state of this app data.
|
|
6
|
-
*
|
|
7
|
-
* Will reload the app content if refreshAppOnResponse is true.
|
|
8
|
-
*
|
|
9
|
-
* @param {{args: {data, httpMethod, refreshAppOnResponse, submitSilently, url}, event, globalDataContext, templateContext}} props Reaction function props.
|
|
10
|
-
*/
|
|
11
|
-
export const submitData = (props) => {
|
|
12
|
-
// Prevent multiple submits.
|
|
13
|
-
const reactionEvent = props?.event;
|
|
14
|
-
|
|
15
|
-
// Check in realtime if we are already submitting.
|
|
16
|
-
// With this system, only 1 submit can be made concurrently for all roots.
|
|
17
|
-
const body = document.body;
|
|
18
|
-
|
|
19
|
-
if (body.dataset.htmlBuilderIsSubmitting === "true") {
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// This will block any attempts to resubmit until receiving the response.
|
|
24
|
-
body.dataset.htmlBuilderIsSubmitting = "true";
|
|
25
|
-
|
|
26
|
-
if (props?.args?.submitSilently) {
|
|
27
|
-
// This will prevent CSS from visually disabling the fields if true.
|
|
28
|
-
body.dataset.htmlBuilderIsSubmittingSilently = "true";
|
|
29
|
-
} else {
|
|
30
|
-
delete body.dataset.htmlBuilderIsSubmittingSilently;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const currentTarget = reactionEvent?.currentTarget;
|
|
34
|
-
|
|
35
|
-
if (currentTarget?.dataset) {
|
|
36
|
-
// Useful for styling.
|
|
37
|
-
currentTarget.dataset.isSubmitting = "true";
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const {globalDataContext: _globalDataContext, templateContext} = props;
|
|
41
|
-
|
|
42
|
-
// Use the root context when submitting data,
|
|
43
|
-
// not the maybe-filtered one that the DataFilter component may have edited.
|
|
44
|
-
// This could be made configurable if ever needed.
|
|
45
|
-
const globalDataContext = _globalDataContext.getRootContext ? _globalDataContext.getRootContext() : _globalDataContext;
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Tells if the response content will replace the current app content.
|
|
49
|
-
*
|
|
50
|
-
* @type {boolean}
|
|
51
|
-
*/
|
|
52
|
-
const refreshAppOnResponse = props?.args?.refreshAppOnResponse ?? true;
|
|
53
|
-
|
|
54
|
-
const url = evaluateTemplateValue({
|
|
55
|
-
valueToEvaluate: props?.args?.url, globalDataContext, templateContext
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
if (!url) {
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
let payload = {};
|
|
63
|
-
|
|
64
|
-
if (props?.args?.hasOwnProperty("data")) {
|
|
65
|
-
payload = props.args.data;
|
|
66
|
-
|
|
67
|
-
// Evaluate the data on the first level.
|
|
68
|
-
function applyFilter(value, filterFn) {
|
|
69
|
-
if (Array.isArray(value)) {
|
|
70
|
-
return value.map(filterFn);
|
|
71
|
-
} else if (typeof value === 'object' && value !== null) {
|
|
72
|
-
const entries = Object.entries(value).map(([key, val]) => {
|
|
73
|
-
return [key, filterFn(val)];
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
return Object.fromEntries(
|
|
77
|
-
entries
|
|
78
|
-
);
|
|
79
|
-
} else {
|
|
80
|
-
return filterFn(value) ? value : null;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
payload = applyFilter(payload, (value) => {
|
|
85
|
-
return evaluateTemplateValue({valueToEvaluate: value, globalDataContext, templateContext})
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
if (globalDataContext.templateData.__state !== undefined) {
|
|
89
|
-
// Append the special data.__state value.
|
|
90
|
-
payload.__state = globalDataContext.templateData.__state;
|
|
91
|
-
}
|
|
92
|
-
} else {
|
|
93
|
-
payload.data = globalDataContext.templateData;
|
|
94
|
-
|
|
95
|
-
if (globalDataContext.templateData.__state !== undefined) {
|
|
96
|
-
// Append the special data.__state value.
|
|
97
|
-
payload.data.__state = globalDataContext.templateData.__state;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const headers = globalDataContext.headersForData ?? {};
|
|
102
|
-
|
|
103
|
-
const {setRawAppData} = globalDataContext;
|
|
104
|
-
|
|
105
|
-
const config = {
|
|
106
|
-
method: props?.args?.httpMethod ?? "post",
|
|
107
|
-
url: url,
|
|
108
|
-
data: payload,
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
if (headers) {
|
|
112
|
-
// Override headers only when explicitly set.
|
|
113
|
-
config.headers = headers;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
axios(config)
|
|
117
|
-
.then((value) => {
|
|
118
|
-
if (!refreshAppOnResponse) {
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// This will trigger a complete re-render.
|
|
123
|
-
setRawAppData(value.data);
|
|
124
|
-
})
|
|
125
|
-
.catch((reason) => {
|
|
126
|
-
console.log("reactionFunction:submitData : Could not submit. Reason: " + reason.message);
|
|
127
|
-
})
|
|
128
|
-
.finally(() => {
|
|
129
|
-
delete body.dataset.htmlBuilderIsSubmitting;
|
|
130
|
-
delete body.dataset.htmlBuilderIsSubmittingSilently;
|
|
131
|
-
|
|
132
|
-
if (currentTarget?.dataset) {
|
|
133
|
-
delete currentTarget.dataset.isSubmitting;
|
|
134
|
-
}
|
|
135
|
-
});
|
|
136
|
-
};
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Reaction function which will trigger an event on an element identified by the given selector.
|
|
3
|
-
*
|
|
4
|
-
* @param {{args:{selector, selectorBase, eventName}, event}} props Reaction function props.
|
|
5
|
-
*/
|
|
6
|
-
export const triggerEvent = (props) => {
|
|
7
|
-
const selector = props?.args?.selector;
|
|
8
|
-
|
|
9
|
-
if (!selector || typeof selector !== "string" || selector.length === 0) {
|
|
10
|
-
return;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const selectorBase = props?.args?.selectorBase;
|
|
14
|
-
let selectorBase_real;
|
|
15
|
-
|
|
16
|
-
if (typeof selectorBase === "undefined") {
|
|
17
|
-
selectorBase_real = document;
|
|
18
|
-
} else if (selectorBase === "currentEventTarget") {
|
|
19
|
-
selectorBase_real = props?.event?.target;
|
|
20
|
-
} else {
|
|
21
|
-
// Find the closest element matching the selectorBase as selector.
|
|
22
|
-
selectorBase_real = props?.event?.target?.closest(selectorBase);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if (!selectorBase_real) {
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const eventName = props?.args?.eventName;
|
|
30
|
-
|
|
31
|
-
if (!eventName || typeof eventName !== "string" || eventName.length === 0) {
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const elements = selectorBase_real.querySelectorAll(selector);
|
|
36
|
-
|
|
37
|
-
// Prepare the events in a promise system to handle successive synchronous events.
|
|
38
|
-
// If not doing this, only the last synchronous event will fire.
|
|
39
|
-
const elements_asArray = Object.entries(elements);
|
|
40
|
-
|
|
41
|
-
const consumeSingleEvent = () => {
|
|
42
|
-
const element = elements_asArray.splice(0, 1)?.[0]?.[1] ?? undefined;
|
|
43
|
-
|
|
44
|
-
if (!element) {
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const event = new Event(eventName, {
|
|
49
|
-
bubbles: true,
|
|
50
|
-
cancelable: false,
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
element.dispatchEvent(event);
|
|
54
|
-
|
|
55
|
-
// We use promises to make multiple clicks on different targets work.
|
|
56
|
-
// Without this, only the last will receive the event (tested on Firefox).
|
|
57
|
-
// This is undocumented online.
|
|
58
|
-
Promise.resolve().then(consumeSingleEvent);
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
consumeSingleEvent();
|
|
62
|
-
};
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import {evaluateTemplateValue} from "../../engine/TemplateSystem";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Pseudo sprintf implementation.
|
|
5
|
-
*
|
|
6
|
-
* Taken from https://stackoverflow.com/a/43718864
|
|
7
|
-
*
|
|
8
|
-
* @licence CC-BY-SA 3.0
|
|
9
|
-
* @author https://stackoverflow.com/users/6314667/7vujy0f0hy and community.
|
|
10
|
-
*
|
|
11
|
-
* @param {string} str The string to format.
|
|
12
|
-
* @param {...string} argv The replacement arguments.
|
|
13
|
-
*
|
|
14
|
-
* @returns {*}
|
|
15
|
-
*/
|
|
16
|
-
const sprintf = (str, ...argv) => !argv.length
|
|
17
|
-
? str
|
|
18
|
-
: sprintf(str = str.replace(sprintf.token || "$token", argv.shift()), ...argv);
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Formats the given string with replacement arguments.
|
|
22
|
-
*
|
|
23
|
-
* @param {{globalDataContext: {}, templateContext: {}}} templateContexts Template contexts.
|
|
24
|
-
* @param {string} toFormat The string to format.
|
|
25
|
-
* @param {...string} argv The replacement arguments.
|
|
26
|
-
*/
|
|
27
|
-
export const formatString = ({templateContexts}, toFormat, ...argv) => {
|
|
28
|
-
const evaluatedArgs = argv.map(
|
|
29
|
-
(toEvaluate) => {
|
|
30
|
-
return evaluateTemplateValue({
|
|
31
|
-
globalDataContext: templateContexts.globalDataContext,
|
|
32
|
-
templateContext: templateContexts.templateContext,
|
|
33
|
-
valueToEvaluate: toEvaluate
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
)
|
|
37
|
-
return sprintf(toFormat, ...evaluatedArgs);
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Formats the given data with replacement arguments if possible.
|
|
42
|
-
*
|
|
43
|
-
* @param {{templateContexts: {globalDataContext: {}, templateContext: {}}}} options Template contexts.
|
|
44
|
-
* @param {*} toFormat The data to format.
|
|
45
|
-
*/
|
|
46
|
-
export const maybeFormatString = (options, toFormat) => {
|
|
47
|
-
if (typeof toFormat === "string") {
|
|
48
|
-
return toFormat;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (Array.isArray(toFormat)) {
|
|
52
|
-
const [toFormatReal, ...args] = toFormat;
|
|
53
|
-
|
|
54
|
-
return formatString(options, toFormatReal, ...args);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Unsupported data to format.
|
|
58
|
-
return "";
|
|
59
|
-
};
|