@saltcorn/builder 0.9.4-beta.8 → 0.9.4
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/builder_bundle.js +20 -12
- package/package.json +3 -1
- package/src/components/Builder.js +51 -58
- package/src/components/Library.js +40 -8
- package/src/components/RenderNode.js +5 -0
- package/src/components/Toolbox.js +61 -2
- package/src/components/elements/Action.js +12 -0
- package/src/components/elements/Aggregation.js +200 -104
- package/src/components/elements/BoxModelEditor.js +8 -8
- package/src/components/elements/Column.js +16 -2
- package/src/components/elements/Columns.js +3 -3
- package/src/components/elements/Container.js +25 -1
- package/src/components/elements/DropMenu.js +31 -2
- package/src/components/elements/Field.js +22 -20
- package/src/components/elements/HTMLCode.js +1 -1
- package/src/components/elements/JoinField.js +25 -1
- package/src/components/elements/Link.js +1 -0
- package/src/components/elements/ListColumn.js +177 -0
- package/src/components/elements/ListColumns.js +62 -0
- package/src/components/elements/RelationBadges.js +53 -44
- package/src/components/elements/Tabs.js +29 -1
- package/src/components/elements/Text.js +4 -2
- package/src/components/elements/View.js +119 -68
- package/src/components/elements/ViewLink.js +100 -48
- package/src/components/elements/utils.js +188 -101
- package/src/components/storage.js +65 -5
- package/tests/relations_finder.test.js +58 -92
- package/tests/test_data.js +0 -163
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saltcorn/builder",
|
|
3
|
-
"version": "0.9.4
|
|
3
|
+
"version": "0.9.4",
|
|
4
4
|
"description": "Drag and drop view builder for Saltcorn, open-source no-code platform",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"homepage": "https://saltcorn.com",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"@babel/preset-react": "7.9.4",
|
|
21
21
|
"@craftjs/core": "0.1.0-beta.20",
|
|
22
22
|
"@craftjs/utils": "0.1.0-beta.20",
|
|
23
|
+
"@saltcorn/common-code": "0.9.4",
|
|
23
24
|
"saltcorn-craft-layers-noeye": "0.1.0-beta.22",
|
|
24
25
|
"@fonticonpicker/react-fonticonpicker": "1.2.0",
|
|
25
26
|
"@fortawesome/fontawesome-svg-core": "1.2.34",
|
|
@@ -38,6 +39,7 @@
|
|
|
38
39
|
"react-bootstrap-icons": "1.5.0",
|
|
39
40
|
"react-contenteditable": "3.3.5",
|
|
40
41
|
"react-dom": "16.13.1",
|
|
42
|
+
"react-select": "4.3.1",
|
|
41
43
|
"react-test-renderer": "16.13.1",
|
|
42
44
|
"react-transition-group": "4.4.1",
|
|
43
45
|
"@tippyjs/react": "4.2.6",
|
|
@@ -18,7 +18,7 @@ import { JoinField } from "./elements/JoinField";
|
|
|
18
18
|
import { Aggregation } from "./elements/Aggregation";
|
|
19
19
|
import { LineBreak } from "./elements/LineBreak";
|
|
20
20
|
import { ViewLink } from "./elements/ViewLink";
|
|
21
|
-
import { Columns } from "./elements/Columns";
|
|
21
|
+
import { Columns, ntimes } from "./elements/Columns";
|
|
22
22
|
import { SearchBar } from "./elements/SearchBar";
|
|
23
23
|
import { HTMLCode } from "./elements/HTMLCode";
|
|
24
24
|
import { Action } from "./elements/Action";
|
|
@@ -37,6 +37,7 @@ import {
|
|
|
37
37
|
ToolboxEdit,
|
|
38
38
|
ToolboxPage,
|
|
39
39
|
ToolboxFilter,
|
|
40
|
+
ToolboxList,
|
|
40
41
|
} from "./Toolbox";
|
|
41
42
|
import { craftToSaltcorn, layoutToNodes } from "./storage";
|
|
42
43
|
import { Card } from "./elements/Card";
|
|
@@ -52,6 +53,8 @@ import {
|
|
|
52
53
|
faRedo,
|
|
53
54
|
faTrashAlt,
|
|
54
55
|
faSave,
|
|
56
|
+
faExclamationTriangle,
|
|
57
|
+
faPlus,
|
|
55
58
|
} from "@fortawesome/free-solid-svg-icons";
|
|
56
59
|
import {
|
|
57
60
|
faCaretSquareLeft,
|
|
@@ -64,6 +67,8 @@ import {
|
|
|
64
67
|
} from "./elements/utils";
|
|
65
68
|
import { InitNewElement, Library } from "./Library";
|
|
66
69
|
import { RenderNode } from "./RenderNode";
|
|
70
|
+
import { ListColumn } from "./elements/ListColumn";
|
|
71
|
+
import { ListColumns } from "./elements/ListColumns";
|
|
67
72
|
const { Provider } = optionsCtx;
|
|
68
73
|
|
|
69
74
|
/**
|
|
@@ -252,58 +257,20 @@ const SettingsPanel = () => {
|
|
|
252
257
|
);
|
|
253
258
|
};
|
|
254
259
|
|
|
255
|
-
|
|
256
|
-
* @returns {button}
|
|
257
|
-
* @category saltcorn-builder
|
|
258
|
-
* @subcategory components
|
|
259
|
-
* @namespace
|
|
260
|
-
*/
|
|
261
|
-
const SaveButton = () => {
|
|
260
|
+
const AddColumnButton = () => {
|
|
262
261
|
const { query, actions } = useEditor(() => {});
|
|
263
262
|
const options = useContext(optionsCtx);
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
const data = craftToSaltcorn(JSON.parse(query.serialize()));
|
|
270
|
-
const urlroot = options.page_id ? "pageedit" : "viewedit";
|
|
271
|
-
fetch(`/${urlroot}/savebuilder/${options.page_id || options.view_id}`, {
|
|
272
|
-
method: "POST", // or 'PUT'
|
|
273
|
-
headers: {
|
|
274
|
-
"Content-Type": "application/json",
|
|
275
|
-
"CSRF-Token": options.csrfToken,
|
|
276
|
-
},
|
|
277
|
-
body: JSON.stringify(data),
|
|
278
|
-
});
|
|
263
|
+
const addColumn = () => {
|
|
264
|
+
actions.addNodeTree(
|
|
265
|
+
query.parseReactElement(<ListColumn />).toNodeTree(),
|
|
266
|
+
"ROOT"
|
|
267
|
+
);
|
|
279
268
|
};
|
|
280
|
-
return
|
|
281
|
-
<button
|
|
282
|
-
className="
|
|
283
|
-
|
|
284
|
-
>
|
|
285
|
-
Save
|
|
269
|
+
return (
|
|
270
|
+
<button className="btn btn-primary mt-2" onClick={addColumn}>
|
|
271
|
+
<FontAwesomeIcon icon={faPlus} className="me-2" />
|
|
272
|
+
Add column
|
|
286
273
|
</button>
|
|
287
|
-
) : (
|
|
288
|
-
""
|
|
289
|
-
);
|
|
290
|
-
};
|
|
291
|
-
|
|
292
|
-
/**
|
|
293
|
-
* @returns {a|""}
|
|
294
|
-
* @category saltcorn-builder
|
|
295
|
-
* @subcategory components
|
|
296
|
-
* @namespace
|
|
297
|
-
*/
|
|
298
|
-
const ViewPageLink = () => {
|
|
299
|
-
const { query, actions } = useEditor(() => {});
|
|
300
|
-
const options = useContext(optionsCtx);
|
|
301
|
-
return options.page_id ? (
|
|
302
|
-
<a target="_blank" className="d-block" href={`/page/${options.page_name}`}>
|
|
303
|
-
View page in new tab »
|
|
304
|
-
</a>
|
|
305
|
-
) : (
|
|
306
|
-
""
|
|
307
274
|
);
|
|
308
275
|
};
|
|
309
276
|
|
|
@@ -356,14 +323,18 @@ const NextButton = ({ layout }) => {
|
|
|
356
323
|
const options = useContext(optionsCtx);
|
|
357
324
|
|
|
358
325
|
useEffect(() => {
|
|
359
|
-
layoutToNodes(layout, query, actions);
|
|
326
|
+
layoutToNodes(layout, query, actions, "ROOT", options);
|
|
360
327
|
}, []);
|
|
361
328
|
|
|
362
329
|
/**
|
|
363
330
|
* @returns {void}
|
|
364
331
|
*/
|
|
365
332
|
const onClick = () => {
|
|
366
|
-
const { columns, layout } = craftToSaltcorn(
|
|
333
|
+
const { columns, layout } = craftToSaltcorn(
|
|
334
|
+
JSON.parse(query.serialize()),
|
|
335
|
+
"ROOT",
|
|
336
|
+
options
|
|
337
|
+
);
|
|
367
338
|
document
|
|
368
339
|
.querySelector("form#scbuildform input[name=columns]")
|
|
369
340
|
.setAttribute("value", encodeURIComponent(JSON.stringify(columns)));
|
|
@@ -394,7 +365,7 @@ const Builder = ({ options, layout, mode }) => {
|
|
|
394
365
|
const [previews, setPreviews] = useState({});
|
|
395
366
|
const [uploadedFiles, setUploadedFiles] = useState([]);
|
|
396
367
|
const nodekeys = useRef([]);
|
|
397
|
-
const [
|
|
368
|
+
const [savingState, setSavingState] = useState({ isSaving: false });
|
|
398
369
|
const [isEnlarged, setIsEnlarged] = useState(false);
|
|
399
370
|
const [isLeftEnlarged, setIsLeftEnlarged] = useState(false);
|
|
400
371
|
const [relationsCache, setRelationsCache] = useState({});
|
|
@@ -422,12 +393,14 @@ const Builder = ({ options, layout, mode }) => {
|
|
|
422
393
|
<div className="componets-and-library-accordion toolbox-card">
|
|
423
394
|
<InitNewElement
|
|
424
395
|
nodekeys={nodekeys}
|
|
425
|
-
|
|
396
|
+
setSavingState={setSavingState}
|
|
397
|
+
savingState={savingState}
|
|
426
398
|
/>
|
|
427
399
|
<Accordion>
|
|
428
400
|
<div className="card mt-1" accordiontitle="Components">
|
|
429
401
|
{{
|
|
430
402
|
show: <ToolboxShow expanded={isLeftEnlarged} />,
|
|
403
|
+
list: <ToolboxList expanded={isLeftEnlarged} />,
|
|
431
404
|
edit: <ToolboxEdit expanded={isLeftEnlarged} />,
|
|
432
405
|
page: <ToolboxPage expanded={isLeftEnlarged} />,
|
|
433
406
|
filter: <ToolboxFilter expanded={isLeftEnlarged} />,
|
|
@@ -440,7 +413,7 @@ const Builder = ({ options, layout, mode }) => {
|
|
|
440
413
|
</div>
|
|
441
414
|
<div
|
|
442
415
|
className="card toolbox-card pe-0"
|
|
443
|
-
style={isLeftEnlarged ? { width: "
|
|
416
|
+
style={isLeftEnlarged ? { width: "13.4rem" } : {}}
|
|
444
417
|
>
|
|
445
418
|
<div className="card-header p-2 d-flex justify-content-between">
|
|
446
419
|
<div>Layers</div>
|
|
@@ -464,7 +437,9 @@ const Builder = ({ options, layout, mode }) => {
|
|
|
464
437
|
</div>
|
|
465
438
|
<div
|
|
466
439
|
id="builder-main-canvas"
|
|
467
|
-
className={`col builder-mode-${options.mode}
|
|
440
|
+
className={`col builder-mode-${options.mode} ${
|
|
441
|
+
options.mode !== "list" ? "emptymsg" : ""
|
|
442
|
+
}`}
|
|
468
443
|
>
|
|
469
444
|
<div>
|
|
470
445
|
<Frame
|
|
@@ -491,10 +466,17 @@ const Builder = ({ options, layout, mode }) => {
|
|
|
491
466
|
Tabs,
|
|
492
467
|
Table,
|
|
493
468
|
ToggleFilter,
|
|
469
|
+
ListColumn,
|
|
470
|
+
ListColumns,
|
|
494
471
|
}}
|
|
495
472
|
>
|
|
496
|
-
|
|
473
|
+
{options.mode === "list" ? (
|
|
474
|
+
<Element canvas is={ListColumns}></Element>
|
|
475
|
+
) : (
|
|
476
|
+
<Element canvas is={Column}></Element>
|
|
477
|
+
)}
|
|
497
478
|
</Frame>
|
|
479
|
+
{options.mode === "list" ? <AddColumnButton /> : null}
|
|
498
480
|
</div>
|
|
499
481
|
</div>
|
|
500
482
|
<div className="col-sm-auto builder-sidebar">
|
|
@@ -503,7 +485,12 @@ const Builder = ({ options, layout, mode }) => {
|
|
|
503
485
|
<HistoryPanel />
|
|
504
486
|
<FontAwesomeIcon
|
|
505
487
|
icon={faSave}
|
|
506
|
-
className={isSaving ? "d-inline" : "d-none"}
|
|
488
|
+
className={savingState.isSaving ? "d-inline" : "d-none"}
|
|
489
|
+
/>
|
|
490
|
+
<FontAwesomeIcon
|
|
491
|
+
icon={faExclamationTriangle}
|
|
492
|
+
color="#ff0033"
|
|
493
|
+
className={savingState.error ? "d-inline" : "d-none"}
|
|
507
494
|
/>
|
|
508
495
|
<FontAwesomeIcon
|
|
509
496
|
icon={isEnlarged ? faCaretSquareRight : faCaretSquareLeft}
|
|
@@ -511,7 +498,13 @@ const Builder = ({ options, layout, mode }) => {
|
|
|
511
498
|
onClick={() => setIsEnlarged(!isEnlarged)}
|
|
512
499
|
title={isEnlarged ? "Shrink" : "Enlarge"}
|
|
513
500
|
/>
|
|
514
|
-
|
|
501
|
+
<div
|
|
502
|
+
className={` ${
|
|
503
|
+
savingState.error ? "d-block" : "d-none"
|
|
504
|
+
} my-2 fw-bold`}
|
|
505
|
+
>
|
|
506
|
+
your work is not being saved
|
|
507
|
+
</div>
|
|
515
508
|
<SettingsPanel />
|
|
516
509
|
</div>
|
|
517
510
|
</div>
|
|
@@ -83,7 +83,7 @@ export /**
|
|
|
83
83
|
* @subcategory components
|
|
84
84
|
* @namespace
|
|
85
85
|
*/
|
|
86
|
-
const InitNewElement = ({ nodekeys,
|
|
86
|
+
const InitNewElement = ({ nodekeys, savingState, setSavingState }) => {
|
|
87
87
|
const [saveTimeout, setSaveTimeout] = useState(false);
|
|
88
88
|
const savedData = useRef(false);
|
|
89
89
|
const { actions, query, connectors } = useEditor((state, query) => {
|
|
@@ -93,7 +93,11 @@ const InitNewElement = ({ nodekeys, setIsSaving }) => {
|
|
|
93
93
|
const doSave = (query) => {
|
|
94
94
|
if (!query.serialize) return;
|
|
95
95
|
|
|
96
|
-
const data = craftToSaltcorn(
|
|
96
|
+
const data = craftToSaltcorn(
|
|
97
|
+
JSON.parse(query.serialize()),
|
|
98
|
+
"ROOT",
|
|
99
|
+
options
|
|
100
|
+
);
|
|
97
101
|
const urlroot = options.page_id ? "pageedit" : "viewedit";
|
|
98
102
|
if (savedData.current === false) {
|
|
99
103
|
//do not save on first call
|
|
@@ -103,7 +107,7 @@ const InitNewElement = ({ nodekeys, setIsSaving }) => {
|
|
|
103
107
|
}
|
|
104
108
|
if (isEqual(savedData.current, JSON.stringify(data.layout))) return;
|
|
105
109
|
savedData.current = JSON.stringify(data.layout);
|
|
106
|
-
|
|
110
|
+
setSavingState({ isSaving: true });
|
|
107
111
|
|
|
108
112
|
fetch(`/${urlroot}/savebuilder/${options.page_id || options.view_id}`, {
|
|
109
113
|
method: "POST", // or 'PUT'
|
|
@@ -112,9 +116,32 @@ const InitNewElement = ({ nodekeys, setIsSaving }) => {
|
|
|
112
116
|
"CSRF-Token": options.csrfToken,
|
|
113
117
|
},
|
|
114
118
|
body: JSON.stringify(data),
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
|
|
119
|
+
})
|
|
120
|
+
.then((response) => {
|
|
121
|
+
response.json().then((data) => {
|
|
122
|
+
if (typeof data?.error === "string") {
|
|
123
|
+
// don't log duplicates
|
|
124
|
+
if (!savingState.error)
|
|
125
|
+
window.notifyAlert({ type: "danger", text: data.error });
|
|
126
|
+
setSavingState({ isSaving: false, error: data.error });
|
|
127
|
+
} else setSavingState({ isSaving: false });
|
|
128
|
+
});
|
|
129
|
+
})
|
|
130
|
+
.catch((e) => {
|
|
131
|
+
const text =
|
|
132
|
+
e.message === "Failed to fetch"
|
|
133
|
+
? "Network connection lost"
|
|
134
|
+
: e || "Unable to save";
|
|
135
|
+
// don't log duplicates
|
|
136
|
+
if (savingState.error) setSavingState({ isSaving: false, error: text });
|
|
137
|
+
else {
|
|
138
|
+
window.notifyAlert({ type: "danger", text: text });
|
|
139
|
+
setSavingState({
|
|
140
|
+
isSaving: false,
|
|
141
|
+
error: text,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
});
|
|
118
145
|
};
|
|
119
146
|
const throttledSave = useThrottle(() => {
|
|
120
147
|
doSave(query);
|
|
@@ -137,7 +164,8 @@ const InitNewElement = ({ nodekeys, setIsSaving }) => {
|
|
|
137
164
|
layout.layout ? layout.layout : layout,
|
|
138
165
|
query,
|
|
139
166
|
actions,
|
|
140
|
-
node.parent
|
|
167
|
+
node.parent,
|
|
168
|
+
options
|
|
141
169
|
);
|
|
142
170
|
setTimeout(() => {
|
|
143
171
|
actions.delete(id);
|
|
@@ -189,7 +217,11 @@ const Library = ({ expanded }) => {
|
|
|
189
217
|
* @returns {void}
|
|
190
218
|
*/
|
|
191
219
|
const addSelected = () => {
|
|
192
|
-
const layout = craftToSaltcorn(
|
|
220
|
+
const layout = craftToSaltcorn(
|
|
221
|
+
JSON.parse(query.serialize()),
|
|
222
|
+
selected,
|
|
223
|
+
options
|
|
224
|
+
);
|
|
193
225
|
const data = { layout, icon, name: newName };
|
|
194
226
|
fetch(`/library/savefrombuilder`, {
|
|
195
227
|
method: "POST", // or 'PUT'
|
|
@@ -80,6 +80,11 @@ const RenderNode = ({ render }) => {
|
|
|
80
80
|
currentDOM.style.left = left;
|
|
81
81
|
}, [dom, getPos]);
|
|
82
82
|
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
if (name === "Column" && parent && parent !== "ROOT")
|
|
85
|
+
actions.selectNode(parent);
|
|
86
|
+
}, [isActive]);
|
|
87
|
+
|
|
83
88
|
useEffect(() => {
|
|
84
89
|
document
|
|
85
90
|
.getElementById("builder-main-canvas")
|
|
@@ -490,7 +490,7 @@ const AggregationElem = ({ connectors, child_field_list, agg_field_opts }) => (
|
|
|
490
490
|
>
|
|
491
491
|
<Aggregation
|
|
492
492
|
agg_relation={child_field_list[0]}
|
|
493
|
-
agg_field={headOr(agg_field_opts[child_field_list[0]], "")}
|
|
493
|
+
agg_field={headOr(agg_field_opts[child_field_list[0]], "")?.name}
|
|
494
494
|
stat={"Count"}
|
|
495
495
|
textStyle={""}
|
|
496
496
|
aggwhere={""}
|
|
@@ -570,6 +570,54 @@ const ToolboxShow = ({ expanded }) => {
|
|
|
570
570
|
expanded
|
|
571
571
|
);
|
|
572
572
|
};
|
|
573
|
+
export /**
|
|
574
|
+
* @returns {Fragment}
|
|
575
|
+
* @category saltcorn-builder
|
|
576
|
+
* @subcategory components / Toolbox
|
|
577
|
+
* @namespace
|
|
578
|
+
*/
|
|
579
|
+
const ToolboxList = ({ expanded }) => {
|
|
580
|
+
const { connectors, query } = useEditor();
|
|
581
|
+
const options = useContext(optionsCtx);
|
|
582
|
+
const {
|
|
583
|
+
fields,
|
|
584
|
+
field_view_options,
|
|
585
|
+
child_field_list,
|
|
586
|
+
agg_field_opts,
|
|
587
|
+
views,
|
|
588
|
+
images,
|
|
589
|
+
} = options;
|
|
590
|
+
return chunkToolBox(
|
|
591
|
+
[
|
|
592
|
+
<TextElem connectors={connectors} />,
|
|
593
|
+
<FieldElem
|
|
594
|
+
connectors={connectors}
|
|
595
|
+
fields={fields}
|
|
596
|
+
field_view_options={field_view_options}
|
|
597
|
+
/>,
|
|
598
|
+
<JoinFieldElem connectors={connectors} options={options} />,
|
|
599
|
+
<ViewLinkElem connectors={connectors} options={options} />,
|
|
600
|
+
<ActionElem connectors={connectors} options={options} />,
|
|
601
|
+
<LinkElem connectors={connectors} />,
|
|
602
|
+
<AggregationElem
|
|
603
|
+
connectors={connectors}
|
|
604
|
+
child_field_list={child_field_list}
|
|
605
|
+
agg_field_opts={agg_field_opts}
|
|
606
|
+
/>,
|
|
607
|
+
// <ViewElem connectors={connectors} views={views} />,
|
|
608
|
+
// <ContainerElem connectors={connectors} />,
|
|
609
|
+
// <CardElem connectors={connectors} />,
|
|
610
|
+
// <TabsElem connectors={connectors} />,
|
|
611
|
+
<HTMLElem connectors={connectors} />,
|
|
612
|
+
<DropMenuElem connectors={connectors} />,
|
|
613
|
+
// <TableElem connectors={connectors} />,
|
|
614
|
+
...(options.allowMultipleElementsPerColumn
|
|
615
|
+
? [<LineBreakElem connectors={connectors} />]
|
|
616
|
+
: []),
|
|
617
|
+
],
|
|
618
|
+
expanded
|
|
619
|
+
);
|
|
620
|
+
};
|
|
573
621
|
|
|
574
622
|
export /**
|
|
575
623
|
* @returns {Fragment}
|
|
@@ -580,7 +628,13 @@ export /**
|
|
|
580
628
|
const ToolboxFilter = ({ expanded }) => {
|
|
581
629
|
const { connectors, query } = useEditor();
|
|
582
630
|
const options = useContext(optionsCtx);
|
|
583
|
-
const {
|
|
631
|
+
const {
|
|
632
|
+
fields,
|
|
633
|
+
views,
|
|
634
|
+
field_view_options,
|
|
635
|
+
child_field_list,
|
|
636
|
+
agg_field_opts,
|
|
637
|
+
} = options;
|
|
584
638
|
return chunkToolBox(
|
|
585
639
|
[
|
|
586
640
|
<TextElem connectors={connectors} />,
|
|
@@ -595,6 +649,11 @@ const ToolboxFilter = ({ expanded }) => {
|
|
|
595
649
|
<ToggleFilterElem connectors={connectors} fields={fields} />,
|
|
596
650
|
<SearchElem connectors={connectors} />,
|
|
597
651
|
<ActionElem connectors={connectors} options={options} />,
|
|
652
|
+
<AggregationElem
|
|
653
|
+
connectors={connectors}
|
|
654
|
+
child_field_list={child_field_list}
|
|
655
|
+
agg_field_opts={agg_field_opts}
|
|
656
|
+
/>,
|
|
598
657
|
<ContainerElem connectors={connectors} />,
|
|
599
658
|
<CardElem connectors={connectors} />,
|
|
600
659
|
<TabsElem connectors={connectors} />,
|
|
@@ -110,6 +110,7 @@ const ActionSettings = () => {
|
|
|
110
110
|
step_only_ifs: node.data.props.step_only_ifs,
|
|
111
111
|
step_action_names: node.data.props.step_action_names,
|
|
112
112
|
setting_action_n: node.data.props.setting_action_n,
|
|
113
|
+
spinner: node.data.props.spinner,
|
|
113
114
|
}));
|
|
114
115
|
const {
|
|
115
116
|
actions: { setProp },
|
|
@@ -127,6 +128,7 @@ const ActionSettings = () => {
|
|
|
127
128
|
setting_action_n,
|
|
128
129
|
step_only_ifs,
|
|
129
130
|
step_action_names,
|
|
131
|
+
spinner,
|
|
130
132
|
} = node;
|
|
131
133
|
const options = useContext(optionsCtx);
|
|
132
134
|
const getCfgFields = (fv) => (options.actionConfigForms || {})[fv];
|
|
@@ -278,6 +280,16 @@ const ActionSettings = () => {
|
|
|
278
280
|
/>
|
|
279
281
|
<label className="form-check-label">User confirmation?</label>
|
|
280
282
|
</div>
|
|
283
|
+
<div className="form-check">
|
|
284
|
+
<input
|
|
285
|
+
className="form-check-input"
|
|
286
|
+
name="block"
|
|
287
|
+
type="checkbox"
|
|
288
|
+
checked={spinner}
|
|
289
|
+
onChange={setAProp("spinner", { checked: true })}
|
|
290
|
+
/>
|
|
291
|
+
<label className="form-check-label">Spinner on click</label>
|
|
292
|
+
</div>
|
|
281
293
|
{action_style !== "on_page_load" ? (
|
|
282
294
|
<BlockSetting block={block} setProp={setProp} />
|
|
283
295
|
) : null}
|