@saltcorn/builder 0.7.0-beta.2 → 0.7.0-beta.3

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saltcorn/builder",
3
- "version": "0.7.0-beta.2",
3
+ "version": "0.7.0-beta.3",
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",
@@ -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
  };
@@ -135,8 +135,8 @@ const DropMenuSettings = () => {
135
135
  DropMenu.craft = {
136
136
  displayName: "DropMenu",
137
137
  props: {
138
- label: "",
139
- show_badges: false,
138
+ label: "Menu",
139
+ block: false,
140
140
  },
141
141
  related: {
142
142
  settings: DropMenuSettings,
@@ -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
- <tr>
166
- <th>
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
- <input
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
- </tr>
198
- ))}
199
- {tabsStyle === "Accordion" ? (
200
- <tr>
201
- <td colSpan="2">
202
- <div className="form-check">
203
- <input
204
- className="form-check-input"
205
- name="block"
206
- type="checkbox"
207
- checked={independent}
208
- onChange={(e) => {
209
- if (e.target) {
210
- setProp((prop) => (prop.independent = e.target.checked));
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
- <tr>
220
- <td colSpan="2">
221
- <div className="form-check">
219
+ <Fragment>
220
+ <tr>
221
+ <th>
222
+ <label>Number of sections</label>
223
+ </th>
224
+ <td>
222
225
  <input
223
- className="form-check-input"
224
- name="block"
225
- type="checkbox"
226
- checked={deeplink}
227
- onChange={(e) => {
228
- if (e.target) {
229
- setProp((prop) => (prop.deeplink = e.target.checked));
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
- <label className="form-check-label">Deep link</label>
234
- </div>
235
- </td>
236
- </tr>
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,