@saltcorn/builder 0.7.0-beta.2 → 0.7.0-beta.5
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/package.json
CHANGED
|
@@ -355,7 +355,7 @@ const DropMenuElem = ({ connectors }) => (
|
|
|
355
355
|
title="Dropdown menu"
|
|
356
356
|
label="DropMenu"
|
|
357
357
|
>
|
|
358
|
-
<DropMenu
|
|
358
|
+
<Element canvas is={DropMenu}></Element>
|
|
359
359
|
</WrapElem>
|
|
360
360
|
);
|
|
361
361
|
|
|
@@ -638,6 +638,7 @@ const ToolboxEdit = () => {
|
|
|
638
638
|
</div>
|
|
639
639
|
<div className="toolbar-row">
|
|
640
640
|
<JoinFieldElem connectors={connectors} options={options} />
|
|
641
|
+
<DropMenuElem connectors={connectors} />
|
|
641
642
|
</div>
|
|
642
643
|
</Fragment>
|
|
643
644
|
);
|
|
@@ -679,6 +680,9 @@ const ToolboxPage = () => {
|
|
|
679
680
|
<ContainerElem connectors={connectors} />
|
|
680
681
|
<TabsElem connectors={connectors} />
|
|
681
682
|
</div>
|
|
683
|
+
<div className="toolbar-row">
|
|
684
|
+
<DropMenuElem connectors={connectors} />
|
|
685
|
+
</div>
|
|
682
686
|
</Fragment>
|
|
683
687
|
);
|
|
684
688
|
};
|
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
* @subcategory components / elements
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import React, { Fragment, useState } from "react";
|
|
7
|
+
import React, { Fragment, useState, useContext, useEffect } from "react";
|
|
8
8
|
import { ntimes } from "./Columns";
|
|
9
9
|
import { Column } from "./Column";
|
|
10
|
+
import optionsCtx from "../context";
|
|
10
11
|
|
|
11
12
|
import { Element, useNode } from "@craftjs/core";
|
|
12
13
|
|
|
@@ -21,14 +22,13 @@ export /**
|
|
|
21
22
|
* @category saltcorn-builder
|
|
22
23
|
* @subcategory components
|
|
23
24
|
*/
|
|
24
|
-
const Tabs = ({ contents, titles, tabsStyle, ntabs, independent }) => {
|
|
25
|
+
const Tabs = ({ contents, titles, tabsStyle, ntabs, independent, field }) => {
|
|
25
26
|
const {
|
|
26
27
|
selected,
|
|
27
28
|
connectors: { connect, drag },
|
|
28
29
|
} = useNode((node) => ({ selected: node.events.selected }));
|
|
29
30
|
const [showTab, setShowTab] = useState(0);
|
|
30
31
|
const [showTabs, setShowTabs] = useState([true]);
|
|
31
|
-
|
|
32
32
|
if (tabsStyle === "Accordion")
|
|
33
33
|
return (
|
|
34
34
|
<div className="accordion">
|
|
@@ -94,7 +94,12 @@ const Tabs = ({ contents, titles, tabsStyle, ntabs, independent }) => {
|
|
|
94
94
|
className={`nav-link ${ix === showTab ? `active` : ""}`}
|
|
95
95
|
onClick={() => setShowTab(ix)}
|
|
96
96
|
>
|
|
97
|
-
{titles[ix]
|
|
97
|
+
{titles[ix] &&
|
|
98
|
+
(typeof titles[ix].label === "undefined"
|
|
99
|
+
? titles[ix]
|
|
100
|
+
: titles[ix].label === ""
|
|
101
|
+
? "(empty)"
|
|
102
|
+
: titles[ix].label)}
|
|
98
103
|
</a>
|
|
99
104
|
</li>
|
|
100
105
|
))}
|
|
@@ -130,6 +135,7 @@ const TabsSettings = () => {
|
|
|
130
135
|
independent: node.data.props.independent,
|
|
131
136
|
deeplink: node.data.props.deeplink,
|
|
132
137
|
titles: node.data.props.titles,
|
|
138
|
+
field: node.data.props.field,
|
|
133
139
|
}));
|
|
134
140
|
const {
|
|
135
141
|
actions: { setProp },
|
|
@@ -138,7 +144,30 @@ const TabsSettings = () => {
|
|
|
138
144
|
deeplink,
|
|
139
145
|
independent,
|
|
140
146
|
ntabs,
|
|
147
|
+
field,
|
|
141
148
|
} = node;
|
|
149
|
+
const options = useContext(optionsCtx);
|
|
150
|
+
useEffect(() => {
|
|
151
|
+
if (field)
|
|
152
|
+
fetch(`/api/${options.tableName}/distinct/${field}`, {
|
|
153
|
+
method: "GET",
|
|
154
|
+
headers: {
|
|
155
|
+
"Content-Type": "application/json",
|
|
156
|
+
"CSRF-Token": options.csrfToken,
|
|
157
|
+
},
|
|
158
|
+
})
|
|
159
|
+
.then(function (response) {
|
|
160
|
+
if (response.status < 399) return response.json();
|
|
161
|
+
else return "";
|
|
162
|
+
})
|
|
163
|
+
.then(function (data) {
|
|
164
|
+
if (data.success) {
|
|
165
|
+
const len = data.success.length;
|
|
166
|
+
setProp((prop) => (prop.ntabs = len));
|
|
167
|
+
setProp((prop) => (prop.titles = data.success));
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
}, [field]);
|
|
142
171
|
return (
|
|
143
172
|
<table className="w-100" accordiontitle="Placement">
|
|
144
173
|
<tbody>
|
|
@@ -159,81 +188,115 @@ const TabsSettings = () => {
|
|
|
159
188
|
<option>Tabs</option>
|
|
160
189
|
<option>Pills</option>
|
|
161
190
|
<option>Accordion</option>
|
|
191
|
+
{["show", "edit"].includes(options.mode) && (
|
|
192
|
+
<option>Value switch</option>
|
|
193
|
+
)}
|
|
162
194
|
</select>
|
|
163
195
|
</td>
|
|
164
196
|
</tr>
|
|
165
|
-
|
|
166
|
-
<
|
|
167
|
-
<label>Number of sections</label>
|
|
168
|
-
</th>
|
|
169
|
-
<td>
|
|
170
|
-
<input
|
|
171
|
-
type="number"
|
|
172
|
-
className="form-control"
|
|
173
|
-
value={ntabs}
|
|
174
|
-
step="1"
|
|
175
|
-
min="0"
|
|
176
|
-
max="20"
|
|
177
|
-
onChange={(e) => setProp((prop) => (prop.ntabs = e.target.value))}
|
|
178
|
-
/>
|
|
179
|
-
</td>
|
|
180
|
-
</tr>
|
|
181
|
-
<tr>
|
|
182
|
-
<th colSpan="2">Titles</th>
|
|
183
|
-
</tr>
|
|
184
|
-
{ntimes(ntabs, (ix) => (
|
|
185
|
-
<tr key={ix}>
|
|
186
|
-
<th>{ix + 1}</th>
|
|
197
|
+
{tabsStyle === "Value switch" ? (
|
|
198
|
+
<tr>
|
|
187
199
|
<td>
|
|
188
|
-
<
|
|
189
|
-
type="text"
|
|
190
|
-
className="form-control text-to-display"
|
|
191
|
-
value={titles[ix]}
|
|
192
|
-
onChange={(e) =>
|
|
193
|
-
setProp((prop) => (prop.titles[ix] = e.target.value))
|
|
194
|
-
}
|
|
195
|
-
/>
|
|
200
|
+
<label>Field</label>
|
|
196
201
|
</td>
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
}
|
|
212
|
-
}}
|
|
213
|
-
/>
|
|
214
|
-
<label className="form-check-label">Open independently</label>
|
|
215
|
-
</div>
|
|
202
|
+
<td>
|
|
203
|
+
<select
|
|
204
|
+
value={field}
|
|
205
|
+
className="form-control form-select"
|
|
206
|
+
onChange={(e) => {
|
|
207
|
+
setProp((prop) => (prop.field = e.target.value));
|
|
208
|
+
}}
|
|
209
|
+
>
|
|
210
|
+
{options.fields.map((f, ix) => (
|
|
211
|
+
<option key={ix} value={f.name}>
|
|
212
|
+
{f.label}
|
|
213
|
+
</option>
|
|
214
|
+
))}
|
|
215
|
+
</select>
|
|
216
216
|
</td>
|
|
217
217
|
</tr>
|
|
218
218
|
) : (
|
|
219
|
-
<
|
|
220
|
-
<
|
|
221
|
-
<
|
|
219
|
+
<Fragment>
|
|
220
|
+
<tr>
|
|
221
|
+
<th>
|
|
222
|
+
<label>Number of sections</label>
|
|
223
|
+
</th>
|
|
224
|
+
<td>
|
|
222
225
|
<input
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
}
|
|
226
|
+
type="number"
|
|
227
|
+
className="form-control"
|
|
228
|
+
value={ntabs}
|
|
229
|
+
step="1"
|
|
230
|
+
min="0"
|
|
231
|
+
max="20"
|
|
232
|
+
onChange={(e) =>
|
|
233
|
+
setProp((prop) => (prop.ntabs = e.target.value))
|
|
234
|
+
}
|
|
232
235
|
/>
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
236
|
+
</td>
|
|
237
|
+
</tr>
|
|
238
|
+
<tr>
|
|
239
|
+
<th colSpan="2">Titles</th>
|
|
240
|
+
</tr>
|
|
241
|
+
{ntimes(ntabs, (ix) => (
|
|
242
|
+
<tr key={ix}>
|
|
243
|
+
<th>{ix + 1}</th>
|
|
244
|
+
<td>
|
|
245
|
+
<input
|
|
246
|
+
type="text"
|
|
247
|
+
className="form-control text-to-display"
|
|
248
|
+
value={titles[ix]}
|
|
249
|
+
onChange={(e) =>
|
|
250
|
+
setProp((prop) => (prop.titles[ix] = e.target.value))
|
|
251
|
+
}
|
|
252
|
+
/>
|
|
253
|
+
</td>
|
|
254
|
+
</tr>
|
|
255
|
+
))}
|
|
256
|
+
{tabsStyle === "Accordion" ? (
|
|
257
|
+
<tr>
|
|
258
|
+
<td colSpan="2">
|
|
259
|
+
<div className="form-check">
|
|
260
|
+
<input
|
|
261
|
+
className="form-check-input"
|
|
262
|
+
name="block"
|
|
263
|
+
type="checkbox"
|
|
264
|
+
checked={independent}
|
|
265
|
+
onChange={(e) => {
|
|
266
|
+
if (e.target) {
|
|
267
|
+
setProp(
|
|
268
|
+
(prop) => (prop.independent = e.target.checked)
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
}}
|
|
272
|
+
/>
|
|
273
|
+
<label className="form-check-label">
|
|
274
|
+
Open independently
|
|
275
|
+
</label>
|
|
276
|
+
</div>
|
|
277
|
+
</td>
|
|
278
|
+
</tr>
|
|
279
|
+
) : (
|
|
280
|
+
<tr>
|
|
281
|
+
<td colSpan="2">
|
|
282
|
+
<div className="form-check">
|
|
283
|
+
<input
|
|
284
|
+
className="form-check-input"
|
|
285
|
+
name="block"
|
|
286
|
+
type="checkbox"
|
|
287
|
+
checked={deeplink}
|
|
288
|
+
onChange={(e) => {
|
|
289
|
+
if (e.target) {
|
|
290
|
+
setProp((prop) => (prop.deeplink = e.target.checked));
|
|
291
|
+
}
|
|
292
|
+
}}
|
|
293
|
+
/>
|
|
294
|
+
<label className="form-check-label">Deep link</label>
|
|
295
|
+
</div>
|
|
296
|
+
</td>
|
|
297
|
+
</tr>
|
|
298
|
+
)}
|
|
299
|
+
</Fragment>
|
|
237
300
|
)}
|
|
238
301
|
</tbody>
|
|
239
302
|
</table>
|
|
@@ -229,6 +229,7 @@ const layoutToNodes = (layout, query, actions, parent = "ROOT") => {
|
|
|
229
229
|
ntabs={segment.ntabs}
|
|
230
230
|
independent={segment.independent}
|
|
231
231
|
deeplink={segment.deeplink}
|
|
232
|
+
field={segment.field}
|
|
232
233
|
tabsStyle={segment.tabsStyle}
|
|
233
234
|
contents={segment.contents.map(toTag)}
|
|
234
235
|
/>
|
|
@@ -421,6 +422,7 @@ const craftToSaltcorn = (nodes, startFrom = "ROOT") => {
|
|
|
421
422
|
),
|
|
422
423
|
titles: node.props.titles,
|
|
423
424
|
tabsStyle: node.props.tabsStyle,
|
|
425
|
+
field: node.props.field,
|
|
424
426
|
independent: node.props.independent,
|
|
425
427
|
deeplink: node.props.deeplink,
|
|
426
428
|
ntabs: node.props.ntabs,
|