@saltcorn/builder 0.7.1-beta.3 → 0.7.2-beta.10
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 +7 -7
- package/package.json +1 -1
- package/src/components/Toolbox.js +1 -1
- package/src/components/elements/Action.js +1 -1
- package/src/components/elements/Card.js +1 -1
- package/src/components/elements/Container.js +22 -0
- package/src/components/elements/Field.js +19 -13
- package/src/components/elements/Image.js +24 -0
- package/src/components/elements/Link.js +17 -2
- package/src/components/elements/Tabs.js +53 -27
- package/src/components/elements/View.js +16 -0
- package/src/components/elements/ViewLink.js +18 -1
- package/src/components/elements/utils.js +48 -41
- package/src/components/storage.js +25 -4
package/package.json
CHANGED
|
@@ -165,7 +165,7 @@ const ActionSettings = () => {
|
|
|
165
165
|
<MinRoleSettingRow minRole={minRole} setProp={setProp} />
|
|
166
166
|
</tbody>
|
|
167
167
|
</table>
|
|
168
|
-
{options.mode === "show" ? (
|
|
168
|
+
{options.mode === "show" || name === "Delete" || name === "Reset" ? (
|
|
169
169
|
<div className="form-check">
|
|
170
170
|
<input
|
|
171
171
|
className="form-check-input"
|
|
@@ -41,7 +41,7 @@ const Card = ({ children, isFormula, title, shadow, noPadding, style }) => {
|
|
|
41
41
|
>
|
|
42
42
|
{title && title.length > 0 && (
|
|
43
43
|
<div className="card-header">
|
|
44
|
-
{isFormula
|
|
44
|
+
{isFormula?.title ? (
|
|
45
45
|
<span className="font-monospace">={title}</span>
|
|
46
46
|
) : (
|
|
47
47
|
title
|
|
@@ -229,6 +229,7 @@ const ContainerSettings = () => {
|
|
|
229
229
|
rotate: node.data.props.rotate,
|
|
230
230
|
display: node.data.props.display,
|
|
231
231
|
style: node.data.props.style,
|
|
232
|
+
imgResponsiveWidths: node.data.props.imgResponsiveWidths,
|
|
232
233
|
}));
|
|
233
234
|
const {
|
|
234
235
|
actions: { setProp },
|
|
@@ -257,6 +258,7 @@ const ContainerSettings = () => {
|
|
|
257
258
|
fullPageWidth,
|
|
258
259
|
overflow,
|
|
259
260
|
htmlElement,
|
|
261
|
+
imgResponsiveWidths,
|
|
260
262
|
} = node;
|
|
261
263
|
const options = useContext(optionsCtx);
|
|
262
264
|
const { uploadedFiles } = useContext(previewCtx);
|
|
@@ -520,6 +522,26 @@ const ContainerSettings = () => {
|
|
|
520
522
|
</select>
|
|
521
523
|
</td>
|
|
522
524
|
</tr>
|
|
525
|
+
{imageSize !== "repeat" && (
|
|
526
|
+
<tr>
|
|
527
|
+
<td>
|
|
528
|
+
<label>Responsive widths</label>
|
|
529
|
+
</td>
|
|
530
|
+
|
|
531
|
+
<td>
|
|
532
|
+
<input
|
|
533
|
+
type="text"
|
|
534
|
+
value={imgResponsiveWidths}
|
|
535
|
+
className="form-control"
|
|
536
|
+
onChange={setAProp("imgResponsiveWidths")}
|
|
537
|
+
/>
|
|
538
|
+
<small>
|
|
539
|
+
<i>List of widths to serve resized images,
|
|
540
|
+
e.g. 300, 400, 600</i>
|
|
541
|
+
</small>
|
|
542
|
+
</td>
|
|
543
|
+
</tr>
|
|
544
|
+
)}
|
|
523
545
|
</Fragment>
|
|
524
546
|
)}
|
|
525
547
|
{bgType === "Color" && (
|
|
@@ -46,7 +46,8 @@ const Field = ({
|
|
|
46
46
|
const { previews, setPreviews } = useContext(previewCtx);
|
|
47
47
|
const myPreview = previews[node_id];
|
|
48
48
|
const options = useContext(optionsCtx);
|
|
49
|
-
|
|
49
|
+
const blockDisplays = (options.blockDisplay || {})[name];
|
|
50
|
+
const blockDisplay = blockDisplays && blockDisplays.includes(fieldview);
|
|
50
51
|
useEffect(() => {
|
|
51
52
|
fetchFieldPreview({
|
|
52
53
|
options,
|
|
@@ -60,7 +61,9 @@ const Field = ({
|
|
|
60
61
|
return (
|
|
61
62
|
<div
|
|
62
63
|
className={`${textStyle} ${selected ? "selected-node" : ""} ${
|
|
63
|
-
isBlock(block, inline, textStyle)
|
|
64
|
+
isBlock(block, inline, textStyle) || blockDisplay
|
|
65
|
+
? "d-block"
|
|
66
|
+
: "d-inline-block"
|
|
64
67
|
}`}
|
|
65
68
|
ref={(dom) => connect(drag(dom))}
|
|
66
69
|
>
|
|
@@ -106,6 +109,7 @@ const FieldSettings = () => {
|
|
|
106
109
|
|
|
107
110
|
const fvs = options.field_view_options[name];
|
|
108
111
|
const handlesTextStyle = (options.handlesTextStyle || {})[name];
|
|
112
|
+
const blockDisplay = (options.blockDisplay || {})[name];
|
|
109
113
|
const getCfgFields = (fv) =>
|
|
110
114
|
((options.fieldViewConfigForms || {})[name] || {})[fv];
|
|
111
115
|
const cfgFields = getCfgFields(fieldview);
|
|
@@ -184,17 +188,19 @@ const FieldSettings = () => {
|
|
|
184
188
|
</td>
|
|
185
189
|
</tr>
|
|
186
190
|
)}
|
|
187
|
-
|
|
188
|
-
<
|
|
189
|
-
|
|
190
|
-
<
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
191
|
+
{!(blockDisplay && blockDisplay.includes(fieldview)) && (
|
|
192
|
+
<tr>
|
|
193
|
+
<td></td>
|
|
194
|
+
<td>
|
|
195
|
+
<BlockOrInlineSetting
|
|
196
|
+
block={block}
|
|
197
|
+
inline={inline}
|
|
198
|
+
textStyle={textStyle}
|
|
199
|
+
setProp={setProp}
|
|
200
|
+
/>
|
|
201
|
+
</td>
|
|
202
|
+
</tr>
|
|
203
|
+
)}
|
|
198
204
|
{!(handlesTextStyle && handlesTextStyle.includes(fieldview)) && (
|
|
199
205
|
<TextStyleRow textStyle={textStyle} setProp={setProp} />
|
|
200
206
|
)}
|
|
@@ -71,6 +71,7 @@ const ImageSettings = () => {
|
|
|
71
71
|
block: node.data.props.block,
|
|
72
72
|
style: node.data.props.style,
|
|
73
73
|
isFormula: node.data.props.isFormula,
|
|
74
|
+
imgResponsiveWidths: node.data.props.imgResponsiveWidths,
|
|
74
75
|
}));
|
|
75
76
|
const {
|
|
76
77
|
actions: { setProp },
|
|
@@ -82,6 +83,7 @@ const ImageSettings = () => {
|
|
|
82
83
|
block,
|
|
83
84
|
isFormula,
|
|
84
85
|
filepath,
|
|
86
|
+
imgResponsiveWidths,
|
|
85
87
|
style,
|
|
86
88
|
} = node;
|
|
87
89
|
const options = useContext(optionsCtx);
|
|
@@ -252,6 +254,27 @@ const ImageSettings = () => {
|
|
|
252
254
|
</td>
|
|
253
255
|
</tr>
|
|
254
256
|
)}
|
|
257
|
+
{srctype !== "Upload" && (
|
|
258
|
+
<tr>
|
|
259
|
+
<td>
|
|
260
|
+
<label>Responsive widths</label>
|
|
261
|
+
</td>
|
|
262
|
+
|
|
263
|
+
<td>
|
|
264
|
+
<input
|
|
265
|
+
type="text"
|
|
266
|
+
value={imgResponsiveWidths}
|
|
267
|
+
className="form-control"
|
|
268
|
+
onChange={setAProp("imgResponsiveWidths")}
|
|
269
|
+
/>
|
|
270
|
+
<small>
|
|
271
|
+
<i>
|
|
272
|
+
List of widths to serve resized images, e.g. 300, 400, 600
|
|
273
|
+
</i>
|
|
274
|
+
</small>
|
|
275
|
+
</td>
|
|
276
|
+
</tr>
|
|
277
|
+
)}
|
|
255
278
|
{srctype !== "Upload" && (
|
|
256
279
|
<tr>
|
|
257
280
|
<td colSpan="2">
|
|
@@ -290,6 +313,7 @@ Image.craft = {
|
|
|
290
313
|
{ name: "fileid", default: 0 },
|
|
291
314
|
"field",
|
|
292
315
|
"block",
|
|
316
|
+
"imgResponsiveWidths",
|
|
293
317
|
{ name: "style", default: {} },
|
|
294
318
|
],
|
|
295
319
|
},
|
|
@@ -53,7 +53,7 @@ const Link = ({
|
|
|
53
53
|
<span
|
|
54
54
|
className={`${textStyle} is-builder-link ${
|
|
55
55
|
selected ? "selected-node" : ""
|
|
56
|
-
} ${isFormula
|
|
56
|
+
} ${isFormula?.text ? "font-monospace" : ""} ${link_style} ${link_size}`}
|
|
57
57
|
{...blockProps(block)}
|
|
58
58
|
ref={(dom) => connect(drag(dom))}
|
|
59
59
|
style={
|
|
@@ -67,7 +67,7 @@ const Link = ({
|
|
|
67
67
|
}
|
|
68
68
|
>
|
|
69
69
|
<DynamicFontAwesomeIcon icon={link_icon} className="me-1" />
|
|
70
|
-
{isFormula
|
|
70
|
+
{isFormula?.text ? `=${text}` : text}
|
|
71
71
|
</span>
|
|
72
72
|
);
|
|
73
73
|
};
|
|
@@ -86,6 +86,7 @@ const LinkSettings = () => {
|
|
|
86
86
|
isFormula: node.data.props.isFormula,
|
|
87
87
|
textStyle: node.data.props.textStyle,
|
|
88
88
|
nofollow: node.data.props.nofollow,
|
|
89
|
+
in_modal: node.data.props.in_modal,
|
|
89
90
|
link_src: node.data.props.link_src,
|
|
90
91
|
target_blank: node.data.props.target_blank,
|
|
91
92
|
link_style: node.data.props.link_style,
|
|
@@ -105,6 +106,7 @@ const LinkSettings = () => {
|
|
|
105
106
|
nofollow,
|
|
106
107
|
target_blank,
|
|
107
108
|
link_src,
|
|
109
|
+
in_modal,
|
|
108
110
|
} = node;
|
|
109
111
|
const options = useContext(optionsCtx);
|
|
110
112
|
const setAProp = (key) => (e) => {
|
|
@@ -247,6 +249,18 @@ const LinkSettings = () => {
|
|
|
247
249
|
/>
|
|
248
250
|
<label className="form-check-label">Open in new tab</label>
|
|
249
251
|
</div>
|
|
252
|
+
<div className="form-check">
|
|
253
|
+
<input
|
|
254
|
+
className="form-check-input"
|
|
255
|
+
name="block"
|
|
256
|
+
type="checkbox"
|
|
257
|
+
checked={in_modal}
|
|
258
|
+
onChange={(e) =>
|
|
259
|
+
setProp((prop) => (prop.in_modal = e.target.checked))
|
|
260
|
+
}
|
|
261
|
+
/>
|
|
262
|
+
<label className="form-check-label">Open in popup modal?</label>
|
|
263
|
+
</div>
|
|
250
264
|
<BlockSetting block={block} setProp={setProp} />
|
|
251
265
|
<TextStyleSetting textStyle={textStyle} setProp={setProp} />
|
|
252
266
|
</div>
|
|
@@ -285,6 +299,7 @@ Link.craft = {
|
|
|
285
299
|
"link_bgcol",
|
|
286
300
|
"link_bordercol",
|
|
287
301
|
"link_textcol",
|
|
302
|
+
"in_modal",
|
|
288
303
|
],
|
|
289
304
|
},
|
|
290
305
|
};
|
|
@@ -88,35 +88,60 @@ const Tabs = ({ contents, titles, tabsStyle, ntabs, independent, field }) => {
|
|
|
88
88
|
} builder ${selected ? "selected-node" : ""}`}
|
|
89
89
|
ref={(dom) => connect(drag(dom))}
|
|
90
90
|
>
|
|
91
|
-
{ntimes(ntabs, (ix) =>
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
>
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
91
|
+
{ntimes(ntabs, (ix) => {
|
|
92
|
+
if (!titles[ix]) return null;
|
|
93
|
+
const targetIx =
|
|
94
|
+
typeof titles[ix].value === "undefined" ? ix : titles[ix].value;
|
|
95
|
+
return (
|
|
96
|
+
<li key={ix} className="nav-item" role="presentation">
|
|
97
|
+
<a
|
|
98
|
+
className={`nav-link ${targetIx === showTab ? `active` : ""}`}
|
|
99
|
+
onClick={() => setShowTab(targetIx)}
|
|
100
|
+
>
|
|
101
|
+
{titles[ix] &&
|
|
102
|
+
(typeof titles[ix].label === "undefined"
|
|
103
|
+
? titles[ix]
|
|
104
|
+
: titles[ix].label === ""
|
|
105
|
+
? "(empty)"
|
|
106
|
+
: titles[ix].label)}
|
|
107
|
+
</a>
|
|
108
|
+
</li>
|
|
109
|
+
);
|
|
110
|
+
})}
|
|
106
111
|
</ul>
|
|
107
112
|
<div className="tab-content" id="myTabContent">
|
|
108
|
-
{ntimes(ntabs, (ix) =>
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
{
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
113
|
+
{ntimes(ntabs, (ix) => {
|
|
114
|
+
if (!titles[ix]) return null;
|
|
115
|
+
|
|
116
|
+
const useIx =
|
|
117
|
+
typeof titles[ix].value === "undefined" ? ix : titles[ix].value;
|
|
118
|
+
|
|
119
|
+
if (useIx !== showTab)
|
|
120
|
+
return (
|
|
121
|
+
<div className="d-none" key={ix}>
|
|
122
|
+
<Element canvas id={`Tab${useIx}`} is={Column}>
|
|
123
|
+
{contents[useIx]}
|
|
124
|
+
</Element>
|
|
125
|
+
</div>
|
|
126
|
+
);
|
|
127
|
+
//d-none display of useIx is bug workaround? needed
|
|
128
|
+
else
|
|
129
|
+
return (
|
|
130
|
+
<div
|
|
131
|
+
key={ix}
|
|
132
|
+
className={`tab-pane fade ${
|
|
133
|
+
useIx === showTab ? `show active` : ""
|
|
134
|
+
}`}
|
|
135
|
+
role="tabpanel"
|
|
136
|
+
aria-labelledby="home-tab"
|
|
137
|
+
>
|
|
138
|
+
<div className="d-none">{useIx}</div>
|
|
139
|
+
<Element canvas id={`Tab${useIx}`} is={Column}>
|
|
140
|
+
{contents[useIx]}
|
|
141
|
+
</Element>
|
|
142
|
+
</div>
|
|
143
|
+
);
|
|
144
|
+
})}
|
|
120
145
|
</div>
|
|
121
146
|
</Fragment>
|
|
122
147
|
);
|
|
@@ -163,6 +188,7 @@ const TabsSettings = () => {
|
|
|
163
188
|
.then(function (data) {
|
|
164
189
|
if (data.success) {
|
|
165
190
|
const len = data.success.length;
|
|
191
|
+
|
|
166
192
|
setProp((prop) => (prop.ntabs = len));
|
|
167
193
|
setProp((prop) => (prop.titles = data.success));
|
|
168
194
|
}
|
|
@@ -79,6 +79,7 @@ const ViewSettings = () => {
|
|
|
79
79
|
name: node.data.props.name,
|
|
80
80
|
view: node.data.props.view,
|
|
81
81
|
state: node.data.props.state,
|
|
82
|
+
extra_state_fml: node.data.props.extra_state_fml,
|
|
82
83
|
configuration: node.data.props.configuration, // fixed states
|
|
83
84
|
node_id: node.id,
|
|
84
85
|
}));
|
|
@@ -90,6 +91,7 @@ const ViewSettings = () => {
|
|
|
90
91
|
state,
|
|
91
92
|
node_id,
|
|
92
93
|
configuration,
|
|
94
|
+
extra_state_fml,
|
|
93
95
|
} = node;
|
|
94
96
|
const options = useContext(optionsCtx);
|
|
95
97
|
const views = options.views;
|
|
@@ -149,6 +151,20 @@ const ViewSettings = () => {
|
|
|
149
151
|
)}
|
|
150
152
|
</Fragment>
|
|
151
153
|
)}
|
|
154
|
+
{(state === "shared" || options.mode === "page") && (
|
|
155
|
+
<Fragment>
|
|
156
|
+
{" "}
|
|
157
|
+
<label>Extra state Formula</label>
|
|
158
|
+
<input
|
|
159
|
+
type="text"
|
|
160
|
+
className="viewlink-label form-control"
|
|
161
|
+
value={extra_state_fml}
|
|
162
|
+
onChange={(e) =>
|
|
163
|
+
setProp((prop) => (prop.extra_state_fml = e.target.value))
|
|
164
|
+
}
|
|
165
|
+
/>
|
|
166
|
+
</Fragment>
|
|
167
|
+
)}
|
|
152
168
|
{view ? (
|
|
153
169
|
<a
|
|
154
170
|
className="d-block mt-2"
|
|
@@ -33,7 +33,7 @@ export /**
|
|
|
33
33
|
* @returns {tr}
|
|
34
34
|
* @category saltcorn-builder
|
|
35
35
|
* @subcategory components
|
|
36
|
-
* @namespace
|
|
36
|
+
* @namespace
|
|
37
37
|
*/
|
|
38
38
|
const ViewLink = ({
|
|
39
39
|
name,
|
|
@@ -99,6 +99,7 @@ const ViewLinkSettings = () => {
|
|
|
99
99
|
link_bgcol: node.data.props.link_bgcol,
|
|
100
100
|
link_bordercol: node.data.props.link_bordercol,
|
|
101
101
|
link_textcol: node.data.props.link_textcol,
|
|
102
|
+
extra_state_fml: node.data.props.extra_state_fml,
|
|
102
103
|
}));
|
|
103
104
|
const {
|
|
104
105
|
actions: { setProp },
|
|
@@ -109,6 +110,7 @@ const ViewLinkSettings = () => {
|
|
|
109
110
|
isFormula,
|
|
110
111
|
inModal,
|
|
111
112
|
textStyle,
|
|
113
|
+
extra_state_fml,
|
|
112
114
|
} = node;
|
|
113
115
|
const options = useContext(optionsCtx);
|
|
114
116
|
return (
|
|
@@ -148,6 +150,20 @@ const ViewLinkSettings = () => {
|
|
|
148
150
|
</OrFormula>
|
|
149
151
|
</td>
|
|
150
152
|
</tr>
|
|
153
|
+
<tr>
|
|
154
|
+
<td colSpan="2">
|
|
155
|
+
<label>Extra state Formula</label>
|
|
156
|
+
<input
|
|
157
|
+
type="text"
|
|
158
|
+
className="viewlink-label form-control"
|
|
159
|
+
value={extra_state_fml}
|
|
160
|
+
onChange={(e) =>
|
|
161
|
+
setProp((prop) => (prop.extra_state_fml = e.target.value))
|
|
162
|
+
}
|
|
163
|
+
/>
|
|
164
|
+
</td>
|
|
165
|
+
</tr>
|
|
166
|
+
|
|
151
167
|
<ButtonOrLinkSettingsRows
|
|
152
168
|
setProp={setProp}
|
|
153
169
|
keyPrefix="link_"
|
|
@@ -203,6 +219,7 @@ ViewLink.craft = {
|
|
|
203
219
|
"link_bgcol",
|
|
204
220
|
"link_bordercol",
|
|
205
221
|
"link_textcol",
|
|
222
|
+
"extra_state_fml",
|
|
206
223
|
],
|
|
207
224
|
},
|
|
208
225
|
};
|
|
@@ -387,53 +387,57 @@ const fetchPreview = ({ url, body, options, setPreviews, node_id, isView }) => {
|
|
|
387
387
|
* @param {object} [args = {}]
|
|
388
388
|
* @return {function}
|
|
389
389
|
*/
|
|
390
|
-
export const fetchFieldPreview =
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
390
|
+
export const fetchFieldPreview =
|
|
391
|
+
(args = {}) =>
|
|
392
|
+
(changes = {}) => {
|
|
393
|
+
const { node_id, options, name, fieldview, setPreviews } = {
|
|
394
|
+
...args,
|
|
395
|
+
...changes,
|
|
396
|
+
};
|
|
397
|
+
const configuration = {
|
|
398
|
+
...(args.configuration || {}),
|
|
399
|
+
...(changes.configuration || {}),
|
|
400
|
+
};
|
|
401
|
+
fetchPreview({
|
|
402
|
+
options,
|
|
403
|
+
node_id,
|
|
404
|
+
setPreviews,
|
|
405
|
+
url: `/field/preview/${options.tableName}/${name}/${fieldview}`,
|
|
406
|
+
body: { configuration },
|
|
407
|
+
});
|
|
398
408
|
};
|
|
399
|
-
fetchPreview({
|
|
400
|
-
options,
|
|
401
|
-
node_id,
|
|
402
|
-
setPreviews,
|
|
403
|
-
url: `/field/preview/${options.tableName}/${name}/${fieldview}`,
|
|
404
|
-
body: { configuration },
|
|
405
|
-
});
|
|
406
|
-
};
|
|
407
409
|
|
|
408
410
|
/**
|
|
409
411
|
* @function
|
|
410
412
|
* @param {object} [args = {}]
|
|
411
413
|
* @return {function}
|
|
412
414
|
*/
|
|
413
|
-
export const fetchViewPreview =
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
415
|
+
export const fetchViewPreview =
|
|
416
|
+
(args = {}) =>
|
|
417
|
+
(changes = {}) => {
|
|
418
|
+
const { node_id, options, view, setPreviews, configuration } = {
|
|
419
|
+
...args,
|
|
420
|
+
...changes,
|
|
421
|
+
};
|
|
422
|
+
let viewname,
|
|
423
|
+
body = configuration ? { ...configuration } : {};
|
|
424
|
+
if (view.includes(":")) {
|
|
425
|
+
const [reltype, rest] = view.split(":");
|
|
426
|
+
const [vnm] = rest.split(".");
|
|
427
|
+
viewname = vnm;
|
|
428
|
+
body.reltype = reltype;
|
|
429
|
+
body.path = rest;
|
|
430
|
+
} else viewname = view;
|
|
427
431
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
};
|
|
432
|
+
fetchPreview({
|
|
433
|
+
options,
|
|
434
|
+
node_id,
|
|
435
|
+
setPreviews,
|
|
436
|
+
url: `/view/${viewname}/preview`,
|
|
437
|
+
body,
|
|
438
|
+
isView: true,
|
|
439
|
+
});
|
|
440
|
+
};
|
|
437
441
|
|
|
438
442
|
export /**
|
|
439
443
|
* @param {object} props
|
|
@@ -650,8 +654,11 @@ const ConfigField = ({
|
|
|
650
654
|
if (field.input_type === "fromtype") field.input_type = null;
|
|
651
655
|
if (field.type && field.type.name === "String" && field.attributes.options) {
|
|
652
656
|
field.input_type = "select";
|
|
653
|
-
field.options =
|
|
654
|
-
|
|
657
|
+
field.options =
|
|
658
|
+
typeof field.attributes.options === "string"
|
|
659
|
+
? field.attributes.options.split(",").map((s) => s.trim())
|
|
660
|
+
: field.attributes.options;
|
|
661
|
+
if (!field.required && field.options) field.options.unshift("");
|
|
655
662
|
}
|
|
656
663
|
const dispatch = {
|
|
657
664
|
String() {
|
|
@@ -142,6 +142,7 @@ const layoutToNodes = (layout, query, actions, parent = "ROOT") => {
|
|
|
142
142
|
view={segment.view}
|
|
143
143
|
name={segment.name}
|
|
144
144
|
state={segment.state}
|
|
145
|
+
extra_state_fml={segment.extra_state_fml}
|
|
145
146
|
configuration={segment.configuration || {}}
|
|
146
147
|
/>
|
|
147
148
|
);
|
|
@@ -205,6 +206,7 @@ const layoutToNodes = (layout, query, actions, parent = "ROOT") => {
|
|
|
205
206
|
}
|
|
206
207
|
bgFileId={segment.bgFileId}
|
|
207
208
|
imageSize={segment.imageSize || "contain"}
|
|
209
|
+
imgResponsiveWidths={segment.imgResponsiveWidths}
|
|
208
210
|
bgType={segment.bgType || "None"}
|
|
209
211
|
style={segment.style || {}}
|
|
210
212
|
bgColor={segment.bgColor || "#ffffff"}
|
|
@@ -222,6 +224,14 @@ const layoutToNodes = (layout, query, actions, parent = "ROOT") => {
|
|
|
222
224
|
</Element>
|
|
223
225
|
);
|
|
224
226
|
} else if (segment.type === "tabs") {
|
|
227
|
+
let contentsArray = segment.contents.map(toTag);
|
|
228
|
+
let contents;
|
|
229
|
+
if (segment.tabsStyle === "Value switch") {
|
|
230
|
+
contents = {};
|
|
231
|
+
segment.titles.forEach(({ label, value }, ix) => {
|
|
232
|
+
contents[value] = contentsArray[ix];
|
|
233
|
+
});
|
|
234
|
+
} else contents = contentsArray;
|
|
225
235
|
return (
|
|
226
236
|
<Tabs
|
|
227
237
|
key={ix}
|
|
@@ -231,7 +241,7 @@ const layoutToNodes = (layout, query, actions, parent = "ROOT") => {
|
|
|
231
241
|
deeplink={segment.deeplink}
|
|
232
242
|
field={segment.field}
|
|
233
243
|
tabsStyle={segment.tabsStyle}
|
|
234
|
-
contents={
|
|
244
|
+
contents={contents}
|
|
235
245
|
/>
|
|
236
246
|
);
|
|
237
247
|
} else if (segment.besides) {
|
|
@@ -320,6 +330,7 @@ const craftToSaltcorn = (nodes, startFrom = "ROOT") => {
|
|
|
320
330
|
* @returns {object}
|
|
321
331
|
*/
|
|
322
332
|
const go = (node) => {
|
|
333
|
+
if (!node) return;
|
|
323
334
|
const matchElement = allElements.find(
|
|
324
335
|
(e) =>
|
|
325
336
|
e.craft.related &&
|
|
@@ -372,6 +383,7 @@ const craftToSaltcorn = (nodes, startFrom = "ROOT") => {
|
|
|
372
383
|
bgFileId: node.props.bgFileId,
|
|
373
384
|
bgType: node.props.bgType,
|
|
374
385
|
imageSize: node.props.imageSize,
|
|
386
|
+
imgResponsiveWidths: node.props.imgResponsiveWidths,
|
|
375
387
|
bgColor: node.props.bgColor,
|
|
376
388
|
setTextColor: node.props.setTextColor,
|
|
377
389
|
textColor: node.props.textColor,
|
|
@@ -415,11 +427,19 @@ const craftToSaltcorn = (nodes, startFrom = "ROOT") => {
|
|
|
415
427
|
};
|
|
416
428
|
}
|
|
417
429
|
if (node.displayName === Tabs.craft.displayName) {
|
|
430
|
+
let contents;
|
|
431
|
+
if (node.props.tabsStyle === "Value switch") {
|
|
432
|
+
contents = node.props.titles.map(({ value }, ix) => {
|
|
433
|
+
const useIx = typeof value === "undefined" ? ix : value;
|
|
434
|
+
return go(nodes[node.linkedNodes["Tab" + useIx]]);
|
|
435
|
+
});
|
|
436
|
+
} else
|
|
437
|
+
contents = ntimes(node.props.ntabs, (ix) =>
|
|
438
|
+
go(nodes[node.linkedNodes["Tab" + ix]])
|
|
439
|
+
);
|
|
418
440
|
return {
|
|
419
441
|
type: "tabs",
|
|
420
|
-
contents
|
|
421
|
-
go(nodes[node.linkedNodes["Tab" + ix]])
|
|
422
|
-
),
|
|
442
|
+
contents,
|
|
423
443
|
titles: node.props.titles,
|
|
424
444
|
tabsStyle: node.props.tabsStyle,
|
|
425
445
|
field: node.props.field,
|
|
@@ -437,6 +457,7 @@ const craftToSaltcorn = (nodes, startFrom = "ROOT") => {
|
|
|
437
457
|
node.props.name === "not_assigned" ? rand_ident() : node.props.name,
|
|
438
458
|
state: node.props.state,
|
|
439
459
|
configuration: node.props.configuration,
|
|
460
|
+
extra_state_fml: node.props.extra_state_fml,
|
|
440
461
|
};
|
|
441
462
|
}
|
|
442
463
|
|