@saltcorn/builder 0.6.1-beta.3 → 0.6.2-beta.2
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 +2 -2
- package/package.json +4 -2
- package/src/components/Builder.js +8 -8
- package/src/components/Toolbox.js +20 -14
- package/src/components/elements/Container.js +13 -10
- package/src/components/elements/Tabs.js +45 -5
- package/src/components/elements/View.js +13 -9
- package/src/components/elements/utils.js +37 -27
- package/src/components/storage.js +15 -13
- package/src/index.js +45 -0
package/package.json
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saltcorn/builder",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2-beta.2",
|
|
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",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"build": "webpack --mode production",
|
|
9
9
|
"builddev": "webpack --mode none",
|
|
10
|
-
"test": "echo \"Error: no test specified\""
|
|
10
|
+
"test": "echo \"Error: no test specified\"",
|
|
11
|
+
"tsc": "echo \"Error: no TypeScript support yet\"",
|
|
12
|
+
"clean": "echo \"Error: no TypeScript support yet\""
|
|
11
13
|
},
|
|
12
14
|
"repository": "github:saltcorn/saltcorn",
|
|
13
15
|
"author": "Tom Nielsen",
|
|
@@ -59,7 +59,7 @@ import { RenderNode } from "./RenderNode";
|
|
|
59
59
|
const { Provider } = optionsCtx;
|
|
60
60
|
|
|
61
61
|
/**
|
|
62
|
-
*
|
|
62
|
+
*
|
|
63
63
|
* @returns {div}
|
|
64
64
|
* @category saltcorn-builder
|
|
65
65
|
* @subcategory components
|
|
@@ -99,7 +99,7 @@ const SettingsPanel = () => {
|
|
|
99
99
|
};
|
|
100
100
|
|
|
101
101
|
/**
|
|
102
|
-
* @param {number} offset
|
|
102
|
+
* @param {number} offset
|
|
103
103
|
* @returns {NodeId}
|
|
104
104
|
*/
|
|
105
105
|
const otherSibling = (offset) => {
|
|
@@ -109,7 +109,7 @@ const SettingsPanel = () => {
|
|
|
109
109
|
};
|
|
110
110
|
|
|
111
111
|
/**
|
|
112
|
-
* @param {object} event
|
|
112
|
+
* @param {object} event
|
|
113
113
|
*/
|
|
114
114
|
const handleUserKeyPress = (event) => {
|
|
115
115
|
const { keyCode, target } = event;
|
|
@@ -168,8 +168,8 @@ const SettingsPanel = () => {
|
|
|
168
168
|
}, [handleUserKeyPress]);
|
|
169
169
|
const hasChildren =
|
|
170
170
|
selected && selected.children && selected.children.length > 0;
|
|
171
|
-
|
|
172
|
-
/**
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
173
|
* @returns {void}
|
|
174
174
|
*/
|
|
175
175
|
const deleteChildren = () => {
|
|
@@ -178,7 +178,7 @@ const SettingsPanel = () => {
|
|
|
178
178
|
});
|
|
179
179
|
};
|
|
180
180
|
|
|
181
|
-
/**
|
|
181
|
+
/**
|
|
182
182
|
* @returns {void}
|
|
183
183
|
*/
|
|
184
184
|
const duplicate = () => {
|
|
@@ -255,7 +255,7 @@ const SaveButton = () => {
|
|
|
255
255
|
const options = useContext(optionsCtx);
|
|
256
256
|
|
|
257
257
|
/**
|
|
258
|
-
* @returns {void}
|
|
258
|
+
* @returns {void}
|
|
259
259
|
*/
|
|
260
260
|
const onClick = () => {
|
|
261
261
|
const data = craftToSaltcorn(JSON.parse(query.serialize()));
|
|
@@ -351,7 +351,7 @@ const NextButton = ({ layout }) => {
|
|
|
351
351
|
layoutToNodes(layout, query, actions);
|
|
352
352
|
}, []);
|
|
353
353
|
|
|
354
|
-
/**
|
|
354
|
+
/**
|
|
355
355
|
* @returns {void}
|
|
356
356
|
*/
|
|
357
357
|
const onClick = () => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @category saltcorn-builder
|
|
3
|
-
* @module components
|
|
3
|
+
* @module components/Toolbox
|
|
4
4
|
* @subcategory components
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -34,9 +34,9 @@ import {
|
|
|
34
34
|
} from "react-bootstrap-icons";
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
|
-
*
|
|
38
|
-
* @param {object[]} xs
|
|
39
|
-
* @param {object} def
|
|
37
|
+
*
|
|
38
|
+
* @param {object[]} xs
|
|
39
|
+
* @param {object} def
|
|
40
40
|
* @returns {object}
|
|
41
41
|
*/
|
|
42
42
|
const headOr = (xs, def) => (xs && xs.length > 0 ? xs[0] : def);
|
|
@@ -349,7 +349,7 @@ const DropDownFilterElem = ({ connectors, fields }) => (
|
|
|
349
349
|
/**
|
|
350
350
|
* @param {object} props
|
|
351
351
|
* @param {object} props.connectors
|
|
352
|
-
* @returns {WrapElem}
|
|
352
|
+
* @returns {WrapElem}
|
|
353
353
|
* @category saltcorn-builder
|
|
354
354
|
* @subcategory components / Toolbox
|
|
355
355
|
* @namespace
|
|
@@ -448,7 +448,7 @@ const ActionElem = ({ connectors, options }) => (
|
|
|
448
448
|
* @returns {WrapElem}
|
|
449
449
|
* @category saltcorn-builder
|
|
450
450
|
* @subcategory components / Toolbox
|
|
451
|
-
* @namespace
|
|
451
|
+
* @namespace
|
|
452
452
|
*/
|
|
453
453
|
const AggregationElem = ({ connectors, child_field_list, agg_field_opts }) => (
|
|
454
454
|
<WrapElem
|
|
@@ -533,9 +533,7 @@ const ToolboxShow = () => {
|
|
|
533
533
|
);
|
|
534
534
|
};
|
|
535
535
|
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
export /**
|
|
536
|
+
export /**
|
|
539
537
|
* @returns {Fragment}
|
|
540
538
|
* @category saltcorn-builder
|
|
541
539
|
* @subcategory components / Toolbox
|
|
@@ -544,7 +542,7 @@ export /**
|
|
|
544
542
|
const ToolboxFilter = () => {
|
|
545
543
|
const { connectors, query } = useEditor();
|
|
546
544
|
const options = useContext(optionsCtx);
|
|
547
|
-
const { fields, views } = options;
|
|
545
|
+
const { fields, views, field_view_options } = options;
|
|
548
546
|
return (
|
|
549
547
|
<Fragment>
|
|
550
548
|
<div className="toolbar-row">
|
|
@@ -552,23 +550,31 @@ const ToolboxFilter = () => {
|
|
|
552
550
|
<ColumnsElem connectors={connectors} />
|
|
553
551
|
</div>
|
|
554
552
|
<div className="toolbar-row">
|
|
553
|
+
<FieldElem
|
|
554
|
+
connectors={connectors}
|
|
555
|
+
fields={fields}
|
|
556
|
+
field_view_options={field_view_options}
|
|
557
|
+
/>
|
|
555
558
|
<LineBreakElem connectors={connectors} />
|
|
556
|
-
<DropDownFilterElem connectors={connectors} fields={fields} />
|
|
557
559
|
</div>
|
|
558
560
|
<div className="toolbar-row">
|
|
561
|
+
<DropDownFilterElem connectors={connectors} fields={fields} />
|
|
559
562
|
<ToggleFilterElem connectors={connectors} fields={fields} />
|
|
560
|
-
<SearchElem connectors={connectors} />
|
|
561
563
|
</div>
|
|
562
564
|
<div className="toolbar-row">
|
|
565
|
+
<SearchElem connectors={connectors} />
|
|
563
566
|
<ActionElem connectors={connectors} options={options} />
|
|
564
|
-
<ContainerElem connectors={connectors} />
|
|
565
567
|
</div>
|
|
566
568
|
<div className="toolbar-row">
|
|
569
|
+
<ContainerElem connectors={connectors} />
|
|
570
|
+
|
|
567
571
|
<CardElem connectors={connectors} />
|
|
568
|
-
<TabsElem connectors={connectors} />
|
|
569
572
|
</div>
|
|
570
573
|
<div className="toolbar-row">
|
|
574
|
+
<TabsElem connectors={connectors} />
|
|
571
575
|
<ViewElem connectors={connectors} views={views} />
|
|
576
|
+
</div>
|
|
577
|
+
<div className="toolbar-row">
|
|
572
578
|
<HTMLElem connectors={connectors} />
|
|
573
579
|
</div>
|
|
574
580
|
</Fragment>
|
|
@@ -46,8 +46,8 @@ import { BoxModelEditor } from "./BoxModelEditor";
|
|
|
46
46
|
import previewCtx from "../preview_context";
|
|
47
47
|
|
|
48
48
|
/**
|
|
49
|
-
*
|
|
50
|
-
* @param {string} string
|
|
49
|
+
*
|
|
50
|
+
* @param {string} string
|
|
51
51
|
* @returns {string}
|
|
52
52
|
*/
|
|
53
53
|
function capitalizeFirstLetter(string) {
|
|
@@ -55,7 +55,7 @@ function capitalizeFirstLetter(string) {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
export /**
|
|
58
|
-
* @param {object} props
|
|
58
|
+
* @param {object} props
|
|
59
59
|
* @param {*} props.children
|
|
60
60
|
* @param {*} props.minHeight
|
|
61
61
|
* @param {*} props.height
|
|
@@ -185,7 +185,6 @@ const Container = ({
|
|
|
185
185
|
);
|
|
186
186
|
};
|
|
187
187
|
|
|
188
|
-
|
|
189
188
|
export /**
|
|
190
189
|
* @returns {div}
|
|
191
190
|
* @returns {Accordion}
|
|
@@ -265,7 +264,7 @@ const ContainerSettings = () => {
|
|
|
265
264
|
const ownership = !!options.ownership;
|
|
266
265
|
|
|
267
266
|
/**
|
|
268
|
-
* @param {string} key
|
|
267
|
+
* @param {string} key
|
|
269
268
|
* @returns {function}
|
|
270
269
|
*/
|
|
271
270
|
const setAProp = (key) => (e) => {
|
|
@@ -763,9 +762,13 @@ const ContainerSettings = () => {
|
|
|
763
762
|
: showForRole[id]
|
|
764
763
|
}
|
|
765
764
|
onChange={(e) =>
|
|
766
|
-
setProp(
|
|
767
|
-
(prop
|
|
768
|
-
|
|
765
|
+
setProp((prop) => {
|
|
766
|
+
if (!prop.showForRole || prop.showForRole.length === 0)
|
|
767
|
+
options.roles.forEach(
|
|
768
|
+
(r) => (prop.showForRole[r.id] = true)
|
|
769
|
+
);
|
|
770
|
+
prop.showForRole[id] = e.target.checked;
|
|
771
|
+
})
|
|
769
772
|
}
|
|
770
773
|
/>
|
|
771
774
|
<label className="form-check-label">{role}</label>
|
|
@@ -882,8 +885,8 @@ const ContainerSettings = () => {
|
|
|
882
885
|
);
|
|
883
886
|
};
|
|
884
887
|
|
|
885
|
-
/**
|
|
886
|
-
* @type {object}
|
|
888
|
+
/**
|
|
889
|
+
* @type {object}
|
|
887
890
|
*/
|
|
888
891
|
Container.craft = {
|
|
889
892
|
displayName: "Container",
|
|
@@ -21,23 +21,36 @@ export /**
|
|
|
21
21
|
* @category saltcorn-builder
|
|
22
22
|
* @subcategory components
|
|
23
23
|
*/
|
|
24
|
-
const Tabs = ({ contents, titles, tabsStyle, ntabs }) => {
|
|
24
|
+
const Tabs = ({ contents, titles, tabsStyle, ntabs, independent }) => {
|
|
25
25
|
const {
|
|
26
26
|
selected,
|
|
27
27
|
connectors: { connect, drag },
|
|
28
28
|
} = useNode((node) => ({ selected: node.events.selected }));
|
|
29
29
|
const [showTab, setShowTab] = useState(0);
|
|
30
|
+
const [showTabs, setShowTabs] = useState([true]);
|
|
31
|
+
|
|
30
32
|
if (tabsStyle === "Accordion")
|
|
31
33
|
return (
|
|
32
34
|
<div className="accordion">
|
|
33
35
|
{ntimes(ntabs, (ix) => (
|
|
34
|
-
<div className="card">
|
|
36
|
+
<div key={ix} className="card">
|
|
35
37
|
<div className="card-header">
|
|
36
38
|
<h2 className="mb-0">
|
|
37
39
|
<button
|
|
38
40
|
className="btn btn-link btn-block text-left"
|
|
39
41
|
type="button"
|
|
40
|
-
onClick={() =>
|
|
42
|
+
onClick={() => {
|
|
43
|
+
setShowTab(ix);
|
|
44
|
+
if (!independent) {
|
|
45
|
+
let newArr = [];
|
|
46
|
+
newArr[ix] = true;
|
|
47
|
+
setShowTabs(newArr);
|
|
48
|
+
} else {
|
|
49
|
+
let newArr = [...showTabs];
|
|
50
|
+
newArr[ix] = !newArr[ix];
|
|
51
|
+
setShowTabs(newArr);
|
|
52
|
+
}
|
|
53
|
+
}}
|
|
41
54
|
>
|
|
42
55
|
{titles[ix]}
|
|
43
56
|
</button>
|
|
@@ -45,8 +58,12 @@ const Tabs = ({ contents, titles, tabsStyle, ntabs }) => {
|
|
|
45
58
|
</div>
|
|
46
59
|
|
|
47
60
|
<div
|
|
48
|
-
id=
|
|
49
|
-
className={`collapse ${
|
|
61
|
+
id={`collapse${ix}`}
|
|
62
|
+
className={`collapse ${
|
|
63
|
+
(independent && showTabs[ix]) || (!independent && showTab == ix)
|
|
64
|
+
? "show"
|
|
65
|
+
: ""
|
|
66
|
+
}`}
|
|
50
67
|
aria-labelledby="headingOne"
|
|
51
68
|
data-parent="#accordionExample"
|
|
52
69
|
>
|
|
@@ -110,12 +127,14 @@ const TabsSettings = () => {
|
|
|
110
127
|
const node = useNode((node) => ({
|
|
111
128
|
tabsStyle: node.data.props.tabsStyle,
|
|
112
129
|
ntabs: node.data.props.ntabs,
|
|
130
|
+
independent: node.data.props.independent,
|
|
113
131
|
titles: node.data.props.titles,
|
|
114
132
|
}));
|
|
115
133
|
const {
|
|
116
134
|
actions: { setProp },
|
|
117
135
|
titles,
|
|
118
136
|
tabsStyle,
|
|
137
|
+
independent,
|
|
119
138
|
ntabs,
|
|
120
139
|
} = node;
|
|
121
140
|
return (
|
|
@@ -175,6 +194,26 @@ const TabsSettings = () => {
|
|
|
175
194
|
</td>
|
|
176
195
|
</tr>
|
|
177
196
|
))}
|
|
197
|
+
{tabsStyle === "Accordion" && (
|
|
198
|
+
<tr>
|
|
199
|
+
<td colSpan="2">
|
|
200
|
+
<div className="form-check">
|
|
201
|
+
<input
|
|
202
|
+
className="form-check-input"
|
|
203
|
+
name="block"
|
|
204
|
+
type="checkbox"
|
|
205
|
+
checked={independent}
|
|
206
|
+
onChange={(e) => {
|
|
207
|
+
if (e.target) {
|
|
208
|
+
setProp((prop) => (prop.independent = e.target.checked));
|
|
209
|
+
}
|
|
210
|
+
}}
|
|
211
|
+
/>
|
|
212
|
+
<label className="form-check-label">Open independently</label>
|
|
213
|
+
</div>
|
|
214
|
+
</td>
|
|
215
|
+
</tr>
|
|
216
|
+
)}
|
|
178
217
|
</tbody>
|
|
179
218
|
</table>
|
|
180
219
|
);
|
|
@@ -188,6 +227,7 @@ Tabs.craft = {
|
|
|
188
227
|
titles: ["Tab1", "Tab2"],
|
|
189
228
|
ntabs: 2,
|
|
190
229
|
tabsStyle: "Tabs",
|
|
230
|
+
independent: false,
|
|
191
231
|
},
|
|
192
232
|
displayName: "Tabs",
|
|
193
233
|
related: {
|
|
@@ -27,7 +27,7 @@ export /**
|
|
|
27
27
|
* @subcategory components
|
|
28
28
|
* @namespace
|
|
29
29
|
*/
|
|
30
|
-
const View = ({ name, view, state }) => {
|
|
30
|
+
const View = ({ name, view, configuration, state }) => {
|
|
31
31
|
const {
|
|
32
32
|
selected,
|
|
33
33
|
node_id,
|
|
@@ -45,9 +45,10 @@ const View = ({ name, view, state }) => {
|
|
|
45
45
|
options,
|
|
46
46
|
view,
|
|
47
47
|
setPreviews,
|
|
48
|
+
configuration,
|
|
48
49
|
node_id,
|
|
49
50
|
})();
|
|
50
|
-
}, []);
|
|
51
|
+
}, [view, configuration, state]);
|
|
51
52
|
return (
|
|
52
53
|
<div
|
|
53
54
|
ref={(dom) => connect(drag(dom))}
|
|
@@ -95,12 +96,7 @@ const ViewSettings = () => {
|
|
|
95
96
|
const fixed_state_fields =
|
|
96
97
|
options.fixed_state_fields && options.fixed_state_fields[view];
|
|
97
98
|
const { setPreviews } = useContext(previewCtx);
|
|
98
|
-
|
|
99
|
-
options,
|
|
100
|
-
view,
|
|
101
|
-
setPreviews,
|
|
102
|
-
node_id,
|
|
103
|
-
});
|
|
99
|
+
|
|
104
100
|
const setAProp = (key) => (e) => {
|
|
105
101
|
if (e.target) {
|
|
106
102
|
const target_value = e.target.value;
|
|
@@ -116,7 +112,6 @@ const ViewSettings = () => {
|
|
|
116
112
|
className="form-control"
|
|
117
113
|
onChange={(e) => {
|
|
118
114
|
setProp((prop) => (prop.view = e.target.value));
|
|
119
|
-
refetchPreview({ view: e.target.value });
|
|
120
115
|
}}
|
|
121
116
|
>
|
|
122
117
|
{views.map((f, ix) => (
|
|
@@ -154,6 +149,15 @@ const ViewSettings = () => {
|
|
|
154
149
|
)}
|
|
155
150
|
</Fragment>
|
|
156
151
|
)}
|
|
152
|
+
{view ? (
|
|
153
|
+
<a
|
|
154
|
+
className="d-block mt-2"
|
|
155
|
+
target="_blank"
|
|
156
|
+
href={`/viewedit/config/${view}`}
|
|
157
|
+
>
|
|
158
|
+
Configure this view
|
|
159
|
+
</a>
|
|
160
|
+
) : null}
|
|
157
161
|
</div>
|
|
158
162
|
);
|
|
159
163
|
};
|
|
@@ -22,7 +22,7 @@ export const DynamicFontAwesomeIcon = ({ icon, className }) => {
|
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
export /**
|
|
25
|
-
* @param {boolean} is_block
|
|
25
|
+
* @param {boolean} is_block
|
|
26
26
|
* @returns {object}
|
|
27
27
|
*/
|
|
28
28
|
const blockProps = (is_block) =>
|
|
@@ -390,12 +390,12 @@ export const fetchFieldPreview = (args = {}) => (changes = {}) => {
|
|
|
390
390
|
* @return {function}
|
|
391
391
|
*/
|
|
392
392
|
export const fetchViewPreview = (args = {}) => (changes = {}) => {
|
|
393
|
-
const { node_id, options, view, setPreviews } = {
|
|
393
|
+
const { node_id, options, view, setPreviews, configuration } = {
|
|
394
394
|
...args,
|
|
395
395
|
...changes,
|
|
396
396
|
};
|
|
397
397
|
let viewname,
|
|
398
|
-
body = {};
|
|
398
|
+
body = configuration ? { ...configuration } : {};
|
|
399
399
|
if (view.includes(":")) {
|
|
400
400
|
const [reltype, rest] = view.split(":");
|
|
401
401
|
const [vnm] = rest.split(".");
|
|
@@ -463,9 +463,9 @@ export const parseStyles = (styles) =>
|
|
|
463
463
|
|
|
464
464
|
/**
|
|
465
465
|
* @function
|
|
466
|
-
* @param {object} styles
|
|
466
|
+
* @param {object} styles
|
|
467
467
|
* @returns {object}
|
|
468
|
-
*/
|
|
468
|
+
*/
|
|
469
469
|
export const reactifyStyles = (styles) => {
|
|
470
470
|
const toCamel = (s) => {
|
|
471
471
|
return s.replace(/([-][a-z])/gi, ($1) => {
|
|
@@ -480,7 +480,7 @@ export const reactifyStyles = (styles) => {
|
|
|
480
480
|
};
|
|
481
481
|
|
|
482
482
|
/**
|
|
483
|
-
* @param {object} f
|
|
483
|
+
* @param {object} f
|
|
484
484
|
* @returns {boolean}
|
|
485
485
|
*/
|
|
486
486
|
const isCheckbox = (f) =>
|
|
@@ -488,8 +488,8 @@ const isCheckbox = (f) =>
|
|
|
488
488
|
|
|
489
489
|
/**
|
|
490
490
|
* @function
|
|
491
|
-
* @param {function} setProp
|
|
492
|
-
* @param {*} fieldview
|
|
491
|
+
* @param {function} setProp
|
|
492
|
+
* @param {*} fieldview
|
|
493
493
|
* @param {object[]} [fields]
|
|
494
494
|
* @returns {void}
|
|
495
495
|
*/
|
|
@@ -540,14 +540,8 @@ export /**
|
|
|
540
540
|
* @category saltcorn-builder
|
|
541
541
|
* @subcategory components / elements / utils
|
|
542
542
|
* @namespace
|
|
543
|
-
*/
|
|
544
|
-
const ConfigForm = ({
|
|
545
|
-
fields,
|
|
546
|
-
configuration,
|
|
547
|
-
setProp,
|
|
548
|
-
node,
|
|
549
|
-
onChange,
|
|
550
|
-
}) => (
|
|
543
|
+
*/
|
|
544
|
+
const ConfigForm = ({ fields, configuration, setProp, node, onChange }) => (
|
|
551
545
|
<div>
|
|
552
546
|
{fields.map((f, ix) => {
|
|
553
547
|
if (f.showIf && node && node.configuration) {
|
|
@@ -579,13 +573,12 @@ const ConfigForm = ({
|
|
|
579
573
|
);
|
|
580
574
|
|
|
581
575
|
/**
|
|
582
|
-
* @param {object|undefined} x
|
|
583
|
-
* @param {object} y
|
|
576
|
+
* @param {object|undefined} x
|
|
577
|
+
* @param {object} y
|
|
584
578
|
* @returns {object}
|
|
585
579
|
*/
|
|
586
580
|
const or_if_undef = (x, y) => (typeof x === "undefined" ? y : x);
|
|
587
581
|
|
|
588
|
-
|
|
589
582
|
export /**
|
|
590
583
|
* @param {object} props
|
|
591
584
|
* @param {object} props.field
|
|
@@ -598,7 +591,7 @@ export /**
|
|
|
598
591
|
* @category saltcorn-builder
|
|
599
592
|
* @subcategory components / elements / utils
|
|
600
593
|
* @namespace
|
|
601
|
-
*/
|
|
594
|
+
*/
|
|
602
595
|
const ConfigField = ({
|
|
603
596
|
field,
|
|
604
597
|
configuration,
|
|
@@ -608,7 +601,7 @@ const ConfigField = ({
|
|
|
608
601
|
isStyle,
|
|
609
602
|
}) => {
|
|
610
603
|
/**
|
|
611
|
-
* @param {object} v
|
|
604
|
+
* @param {object} v
|
|
612
605
|
* @returns {void}
|
|
613
606
|
*/
|
|
614
607
|
const myOnChange = (v) => {
|
|
@@ -928,15 +921,15 @@ const SettingsRow = ({ field, node, setProp, onChange, isStyle }) => {
|
|
|
928
921
|
export class ErrorBoundary extends React.Component {
|
|
929
922
|
/**
|
|
930
923
|
* ErrorBoundary constructor
|
|
931
|
-
* @param {object} props
|
|
924
|
+
* @param {object} props
|
|
932
925
|
*/
|
|
933
926
|
constructor(props) {
|
|
934
927
|
super(props);
|
|
935
|
-
this.state = { hasError: false };
|
|
928
|
+
this.state = { hasError: false, reported: false };
|
|
936
929
|
}
|
|
937
930
|
|
|
938
931
|
/**
|
|
939
|
-
* @param {*} error
|
|
932
|
+
* @param {*} error
|
|
940
933
|
* @returns {object}
|
|
941
934
|
*/
|
|
942
935
|
static getDerivedStateFromError(error) {
|
|
@@ -945,8 +938,8 @@ export class ErrorBoundary extends React.Component {
|
|
|
945
938
|
}
|
|
946
939
|
|
|
947
940
|
/**
|
|
948
|
-
* @param {object} error
|
|
949
|
-
* @param {object} errorInfo
|
|
941
|
+
* @param {object} error
|
|
942
|
+
* @param {object} errorInfo
|
|
950
943
|
* @returns {void}
|
|
951
944
|
*/
|
|
952
945
|
componentDidCatch(error, errorInfo) {
|
|
@@ -957,6 +950,23 @@ export class ErrorBoundary extends React.Component {
|
|
|
957
950
|
JSON.stringify(error),
|
|
958
951
|
JSON.stringify(errorInfo)
|
|
959
952
|
);
|
|
953
|
+
|
|
954
|
+
if (!this.state.reported) {
|
|
955
|
+
const data = {
|
|
956
|
+
message: error.message,
|
|
957
|
+
stack: (error && error.stack) || "",
|
|
958
|
+
};
|
|
959
|
+
|
|
960
|
+
fetch("/crashlog/", {
|
|
961
|
+
method: "POST",
|
|
962
|
+
headers: {
|
|
963
|
+
"Content-Type": "application/json",
|
|
964
|
+
"CSRF-Token": _sc_globalCsrf,
|
|
965
|
+
},
|
|
966
|
+
body: JSON.stringify(data),
|
|
967
|
+
});
|
|
968
|
+
this.setState({ reported: true });
|
|
969
|
+
}
|
|
960
970
|
}
|
|
961
971
|
|
|
962
972
|
/**
|
|
@@ -1107,7 +1117,7 @@ const ButtonOrLinkSettingsRows = ({
|
|
|
1107
1117
|
|
|
1108
1118
|
/**
|
|
1109
1119
|
* @function
|
|
1110
|
-
* @param {string} style
|
|
1120
|
+
* @param {string} style
|
|
1111
1121
|
* @returns {object}
|
|
1112
1122
|
*/
|
|
1113
1123
|
export const bstyleopt = (style) => ({
|
|
@@ -27,7 +27,7 @@ import { DropDownFilter } from "./elements/DropDownFilter";
|
|
|
27
27
|
import { ToggleFilter } from "./elements/ToggleFilter";
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
|
-
* @param {object} segment
|
|
30
|
+
* @param {object} segment
|
|
31
31
|
* @returns {number}
|
|
32
32
|
*/
|
|
33
33
|
const getColWidths = (segment) => {
|
|
@@ -43,7 +43,7 @@ const getColWidths = (segment) => {
|
|
|
43
43
|
};
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
|
-
* @param {object} segment
|
|
46
|
+
* @param {object} segment
|
|
47
47
|
* @returns {object[]}
|
|
48
48
|
*/
|
|
49
49
|
const default_breakpoints = (segment) =>
|
|
@@ -72,9 +72,9 @@ const allElements = [
|
|
|
72
72
|
];
|
|
73
73
|
|
|
74
74
|
export /**
|
|
75
|
-
* @param {object} layout
|
|
76
|
-
* @param {object} query
|
|
77
|
-
* @param {object} actions
|
|
75
|
+
* @param {object} layout
|
|
76
|
+
* @param {object} query
|
|
77
|
+
* @param {object} actions
|
|
78
78
|
* @param {string} [parent = "ROOT"]
|
|
79
79
|
* @returns {Text|View|Action|Element|Tabs|Columns}
|
|
80
80
|
* @category saltcorn-builder
|
|
@@ -84,8 +84,8 @@ export /**
|
|
|
84
84
|
const layoutToNodes = (layout, query, actions, parent = "ROOT") => {
|
|
85
85
|
//console.log("layoutToNodes", JSON.stringify(layout));
|
|
86
86
|
/**
|
|
87
|
-
* @param {object} segment
|
|
88
|
-
* @param {string} ix
|
|
87
|
+
* @param {object} segment
|
|
88
|
+
* @param {string} ix
|
|
89
89
|
* @returns {Element|Text|View|Action|Tabs|Columns}
|
|
90
90
|
*/
|
|
91
91
|
function toTag(segment, ix) {
|
|
@@ -223,6 +223,7 @@ const layoutToNodes = (layout, query, actions, parent = "ROOT") => {
|
|
|
223
223
|
key={ix}
|
|
224
224
|
titles={segment.titles}
|
|
225
225
|
ntabs={segment.ntabs}
|
|
226
|
+
independent={segment.independent}
|
|
226
227
|
tabsStyle={segment.tabsStyle}
|
|
227
228
|
contents={segment.contents.map(toTag)}
|
|
228
229
|
/>
|
|
@@ -243,8 +244,8 @@ const layoutToNodes = (layout, query, actions, parent = "ROOT") => {
|
|
|
243
244
|
}
|
|
244
245
|
|
|
245
246
|
/**
|
|
246
|
-
* @param {object} segment
|
|
247
|
-
* @param {object} parent
|
|
247
|
+
* @param {object} segment
|
|
248
|
+
* @param {object} parent
|
|
248
249
|
* @returns {void}
|
|
249
250
|
*/
|
|
250
251
|
function go(segment, parent) {
|
|
@@ -285,7 +286,7 @@ const layoutToNodes = (layout, query, actions, parent = "ROOT") => {
|
|
|
285
286
|
const rand_ident = () => Math.floor(Math.random() * 16777215).toString(16);
|
|
286
287
|
|
|
287
288
|
export /**
|
|
288
|
-
* @param {object[]} nodes
|
|
289
|
+
* @param {object[]} nodes
|
|
289
290
|
* @param {string} [startFrom = "ROOT" ]
|
|
290
291
|
* @returns {object}
|
|
291
292
|
* @category saltcorn-builder
|
|
@@ -295,9 +296,9 @@ export /**
|
|
|
295
296
|
const craftToSaltcorn = (nodes, startFrom = "ROOT") => {
|
|
296
297
|
//console.log(JSON.stringify(nodes, null, 2));
|
|
297
298
|
var columns = [];
|
|
298
|
-
|
|
299
|
+
|
|
299
300
|
/**
|
|
300
|
-
* @param {object} node
|
|
301
|
+
* @param {object} node
|
|
301
302
|
* @returns {void|object}
|
|
302
303
|
*/
|
|
303
304
|
const get_nodes = (node) => {
|
|
@@ -307,7 +308,7 @@ const craftToSaltcorn = (nodes, startFrom = "ROOT") => {
|
|
|
307
308
|
};
|
|
308
309
|
|
|
309
310
|
/**
|
|
310
|
-
* @param {object} node
|
|
311
|
+
* @param {object} node
|
|
311
312
|
* @returns {object}
|
|
312
313
|
*/
|
|
313
314
|
const go = (node) => {
|
|
@@ -410,6 +411,7 @@ const craftToSaltcorn = (nodes, startFrom = "ROOT") => {
|
|
|
410
411
|
),
|
|
411
412
|
titles: node.props.titles,
|
|
412
413
|
tabsStyle: node.props.tabsStyle,
|
|
414
|
+
independent: node.props.independent,
|
|
413
415
|
ntabs: node.props.ntabs,
|
|
414
416
|
};
|
|
415
417
|
}
|