@saltcorn/builder 0.9.3-beta.8 → 0.9.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.
@@ -32,28 +32,29 @@ export /**
32
32
  * @category saltcorn-builder
33
33
  * @subcategory components
34
34
  */
35
- const Image = ({ fileid, block, srctype, url, alt, style }) => {
36
- const {
37
- selected,
38
- connectors: { connect, drag },
39
- } = useNode((node) => ({ selected: node.events.selected }));
40
- const theurl = srctype === "File" ? `/files/serve/${fileid}` : url;
41
- return (
42
- <span {...blockProps(block)} ref={(dom) => connect(drag(dom))}>
43
- {fileid === 0 ? (
44
- "No images Available"
45
- ) : (
46
- <img
47
- className={`${style && style.width ? "" : "w-100"} image-widget ${selected ? "selected-node" : ""
48
- }`}
49
- style={reactifyStyles(style || {})}
50
- src={theurl}
51
- alt={alt}
52
- ></img>
53
- )}
54
- </span>
55
- );
56
- };
35
+ const Image = ({ fileid, block, srctype, url, alt, style }) => {
36
+ const {
37
+ selected,
38
+ connectors: { connect, drag },
39
+ } = useNode((node) => ({ selected: node.events.selected }));
40
+ const theurl = srctype === "File" ? `/files/serve/${fileid}` : url;
41
+ return (
42
+ <span {...blockProps(block)} ref={(dom) => connect(drag(dom))}>
43
+ {fileid === 0 ? (
44
+ "No images Available"
45
+ ) : (
46
+ <img
47
+ className={`${style && style.width ? "" : "w-100"} image-widget ${
48
+ selected ? "selected-node" : ""
49
+ }`}
50
+ style={reactifyStyles(style || {})}
51
+ src={theurl}
52
+ alt={alt}
53
+ ></img>
54
+ )}
55
+ </span>
56
+ );
57
+ };
57
58
 
58
59
  export /**
59
60
  * @returns {table}
@@ -61,232 +62,233 @@ export /**
61
62
  * @category saltcorn-builder
62
63
  * @subcategory components
63
64
  */
64
- const ImageSettings = () => {
65
- const node = useNode((node) => ({
66
- fileid: node.data.props.fileid,
67
- field: node.data.props.field,
68
- url: node.data.props.url,
69
- filepath: node.data.props.filepath,
70
- srctype: node.data.props.srctype,
71
- alt: node.data.props.alt,
72
- block: node.data.props.block,
73
- style: node.data.props.style,
74
- isFormula: node.data.props.isFormula,
75
- imgResponsiveWidths: node.data.props.imgResponsiveWidths,
76
- }));
77
- const {
78
- actions: { setProp },
79
- fileid,
80
- srctype,
81
- field,
82
- url,
83
- alt,
84
- block,
85
- isFormula,
86
- filepath,
87
- imgResponsiveWidths,
88
- style,
89
- } = node;
90
- const options = useContext(optionsCtx);
91
- const { uploadedFiles, setUploadedFiles } = useContext(previewCtx);
65
+ const ImageSettings = () => {
66
+ const node = useNode((node) => ({
67
+ fileid: node.data.props.fileid,
68
+ field: node.data.props.field,
69
+ url: node.data.props.url,
70
+ filepath: node.data.props.filepath,
71
+ srctype: node.data.props.srctype,
72
+ alt: node.data.props.alt,
73
+ block: node.data.props.block,
74
+ style: node.data.props.style,
75
+ isFormula: node.data.props.isFormula,
76
+ imgResponsiveWidths: node.data.props.imgResponsiveWidths,
77
+ }));
78
+ const {
79
+ actions: { setProp },
80
+ fileid,
81
+ srctype,
82
+ field,
83
+ url,
84
+ alt,
85
+ block,
86
+ isFormula,
87
+ filepath,
88
+ imgResponsiveWidths,
89
+ style,
90
+ } = node;
91
+ const options = useContext(optionsCtx);
92
+ const { uploadedFiles, setUploadedFiles } = useContext(previewCtx);
92
93
 
93
- const handleUpload = (e) => {
94
- if (e.target.files && e.target.files.length > 0) {
95
- const formData = new FormData();
94
+ const handleUpload = (e) => {
95
+ if (e.target.files && e.target.files.length > 0) {
96
+ const formData = new FormData();
96
97
 
97
- formData.append("file", e.target.files[0]);
98
- formData.append("min_role_read", options.min_role || 1);
98
+ formData.append("file", e.target.files[0]);
99
+ formData.append("min_role_read", options.min_role || 1);
99
100
 
100
- fetch("/files/upload", {
101
- method: "POST",
102
- body: formData,
103
- headers: {
104
- "X-Requested-With": "XMLHttpRequest",
105
- "CSRF-Token": options.csrfToken,
106
- },
107
- })
108
- .then((response) => response.json())
109
- .then((result) => {
110
- setUploadedFiles((upFls) => [
111
- ...upFls,
112
- { id: result.success.location, filename: result.success.filename },
113
- ]);
114
- setProp((prop) => {
115
- prop.fileid = result.success.location;
116
- prop.srctype = "File";
117
- });
118
- })
119
- .catch((error) => {
120
- console.error("Error:", error);
101
+ fetch("/files/upload", {
102
+ method: "POST",
103
+ body: formData,
104
+ headers: {
105
+ "X-Requested-With": "XMLHttpRequest",
106
+ "CSRF-Token": options.csrfToken,
107
+ },
108
+ })
109
+ .then((response) => response.json())
110
+ .then((result) => {
111
+ setUploadedFiles((upFls) => [
112
+ ...upFls,
113
+ { id: result.success.location, filename: result.success.filename },
114
+ ]);
115
+ setProp((prop) => {
116
+ prop.fileid = result.success.location;
117
+ prop.srctype = "File";
121
118
  });
122
- }
123
- };
124
- const setAProp = setAPropGen(setProp);
125
- const sourceOpts = ["File", "URL", "Upload"];
126
- if (options.mode === "show") sourceOpts.push("Field");
127
- return (
128
- <Accordion>
129
- <table accordiontitle="Select image">
130
- <tbody>
131
- <tr>
132
- <td colSpan="2">
133
- <i>
134
- <small>Preview shown in canvas is indicative</small>
135
- </i>
136
- </td>
137
- </tr>
119
+ })
120
+ .catch((error) => {
121
+ console.error("Error:", error);
122
+ });
123
+ }
124
+ };
125
+ const setAProp = setAPropGen(setProp);
126
+ const sourceOpts = ["File", "URL", "Upload"];
127
+ if (options.mode === "show") sourceOpts.push("Field");
128
+ return (
129
+ <Accordion>
130
+ <table accordiontitle="Select image">
131
+ <tbody>
132
+ <tr>
133
+ <td colSpan="2">
134
+ <i>
135
+ <small>Preview shown in canvas is indicative</small>
136
+ </i>
137
+ </td>
138
+ </tr>
139
+ <tr>
140
+ <td>
141
+ <label>Source</label>
142
+ </td>
143
+ <td>
144
+ <select
145
+ value={srctype}
146
+ className="form-control form-select"
147
+ onChange={setAProp("srctype")}
148
+ >
149
+ {buildOptions(sourceOpts)}
150
+ </select>
151
+ </td>
152
+ </tr>
153
+ {srctype === "File" && (
138
154
  <tr>
139
155
  <td>
140
- <label>Source</label>
156
+ <label>File</label>
141
157
  </td>
142
158
  <td>
143
159
  <select
144
- value={srctype}
160
+ value={fileid}
145
161
  className="form-control form-select"
146
- onChange={setAProp("srctype")}
162
+ onChange={setAProp("fileid")}
163
+ onBlur={setAProp("fileid")}
147
164
  >
148
- {buildOptions(sourceOpts)}
165
+ {options.images.map((f, ix) => (
166
+ <option key={ix} value={f.id}>
167
+ {f.filename}
168
+ </option>
169
+ ))}
170
+ {(uploadedFiles || []).map((uf, ix) => (
171
+ <option key={ix} value={uf.id}>
172
+ {uf.filename}
173
+ </option>
174
+ ))}
149
175
  </select>
150
176
  </td>
151
177
  </tr>
152
- {srctype === "File" && (
153
- <tr>
154
- <td>
155
- <label>File</label>
156
- </td>
157
- <td>
158
- <select
159
- value={fileid}
160
- className="form-control form-select"
161
- onChange={setAProp("fileid")}
162
- onBlur={setAProp("fileid")}
163
- >
164
- {options.images.map((f, ix) => (
165
- <option key={ix} value={f.id}>
166
- {f.filename}
167
- </option>
168
- ))}
169
- {(uploadedFiles || []).map((uf, ix) => (
170
- <option key={ix} value={uf.id}>
171
- {uf.filename}
172
- </option>
173
- ))}
174
- </select>
175
- </td>
176
- </tr>
177
- )}
178
- {srctype === "URL" && (
179
- <tr>
180
- <td>
181
- <label>URL</label>
182
- </td>
183
- <td>
184
- <OrFormula nodekey="url" {...{ setProp, isFormula, node }}>
185
- <input
186
- type="text"
187
- className="form-control"
188
- value={url}
189
- onChange={setAProp("url")}
190
- />
191
- </OrFormula>
192
- </td>
193
- </tr>
194
- )}
195
- {srctype === "Upload" && (
196
- <tr>
197
- <td>
198
- <label>File</label>
199
- </td>
200
- <td>
178
+ )}
179
+ {srctype === "URL" && (
180
+ <tr>
181
+ <td>
182
+ <label>URL</label>
183
+ </td>
184
+ <td>
185
+ <OrFormula nodekey="url" {...{ setProp, isFormula, node }}>
201
186
  <input
202
- type="file"
187
+ type="text"
203
188
  className="form-control"
204
- value={filepath}
205
- onChange={handleUpload}
189
+ value={url}
190
+ onChange={setAProp("url")}
206
191
  />
207
- </td>
208
- </tr>
209
- )}
210
- {srctype === "Field" && (
211
- <tr>
212
- <td>
213
- <label>Field</label>
214
- </td>
215
- <td>
216
- <select
217
- value={field}
218
- className="form-control form-select"
219
- onChange={setAProp("field")}
220
- >
221
- <option value=""></option>
222
- {options.fields
223
- .filter(
224
- (f) =>
225
- (f.type && f.type.name === "String") ||
226
- (f.type && f.type === "File")
227
- )
228
- .map((f, ix) => (
229
- <option key={ix} value={f.name}>
230
- {f.label}
231
- </option>
232
- ))}
233
- </select>
234
- </td>
235
- </tr>
236
- )}
237
- {srctype !== "Upload" && (
238
- <tr>
239
- <td>
240
- <label>Alt text</label>
241
- </td>
242
- <td>
243
- <OrFormula nodekey="alt" {...{ setProp, isFormula, node }}>
244
- <input
245
- type="text"
246
- className="form-control"
247
- value={alt}
248
- onChange={setAProp("alt")}
249
- />
250
- </OrFormula>
251
- </td>
252
- </tr>
253
- )}
254
- {srctype !== "Upload" && (
255
- <tr>
256
- <td style={{ verticalAlign: "top" }}>
257
- <label>Responsive widths</label>
258
- </td>
259
-
260
- <td>
192
+ </OrFormula>
193
+ </td>
194
+ </tr>
195
+ )}
196
+ {srctype === "Upload" && (
197
+ <tr>
198
+ <td>
199
+ <label>File</label>
200
+ </td>
201
+ <td>
202
+ <input
203
+ type="file"
204
+ className="form-control"
205
+ value={filepath}
206
+ onChange={handleUpload}
207
+ />
208
+ </td>
209
+ </tr>
210
+ )}
211
+ {srctype === "Field" && (
212
+ <tr>
213
+ <td>
214
+ <label>Field</label>
215
+ </td>
216
+ <td>
217
+ <select
218
+ value={field}
219
+ className="form-control form-select"
220
+ onChange={setAProp("field")}
221
+ >
222
+ <option value=""></option>
223
+ {options.fields
224
+ .filter(
225
+ (f) =>
226
+ f.type === "String" ||
227
+ (f.type && f.type.name === "String") ||
228
+ (f.type && f.type === "File")
229
+ )
230
+ .map((f, ix) => (
231
+ <option key={ix} value={f.name}>
232
+ {f.label}
233
+ </option>
234
+ ))}
235
+ </select>
236
+ </td>
237
+ </tr>
238
+ )}
239
+ {srctype !== "Upload" && (
240
+ <tr>
241
+ <td>
242
+ <label>Alt text</label>
243
+ </td>
244
+ <td>
245
+ <OrFormula nodekey="alt" {...{ setProp, isFormula, node }}>
261
246
  <input
262
247
  type="text"
263
- value={imgResponsiveWidths}
264
248
  className="form-control"
265
- onChange={setAProp("imgResponsiveWidths")}
249
+ value={alt}
250
+ onChange={setAProp("alt")}
266
251
  />
267
- <small>
268
- <i>
269
- List of widths to serve resized images, e.g. 300, 400, 600
270
- </i>
271
- </small>
272
- </td>
273
- </tr>
274
- )}
275
- {srctype !== "Upload" && (
276
- <tr>
277
- <td colSpan="2">
278
- <BlockSetting block={block} setProp={setProp} />
279
- </td>
280
- </tr>
281
- )}
282
- </tbody>
283
- </table>
284
- <div accordiontitle="Box" className="w-100">
285
- <BoxModelEditor setProp={setProp} node={node} sizeWithStyle={true} />
286
- </div>
287
- </Accordion>
288
- );
289
- };
252
+ </OrFormula>
253
+ </td>
254
+ </tr>
255
+ )}
256
+ {srctype !== "Upload" && (
257
+ <tr>
258
+ <td style={{ verticalAlign: "top" }}>
259
+ <label>Responsive widths</label>
260
+ </td>
261
+
262
+ <td>
263
+ <input
264
+ type="text"
265
+ value={imgResponsiveWidths}
266
+ className="form-control"
267
+ onChange={setAProp("imgResponsiveWidths")}
268
+ />
269
+ <small>
270
+ <i>
271
+ List of widths to serve resized images, e.g. 300, 400, 600
272
+ </i>
273
+ </small>
274
+ </td>
275
+ </tr>
276
+ )}
277
+ {srctype !== "Upload" && (
278
+ <tr>
279
+ <td colSpan="2">
280
+ <BlockSetting block={block} setProp={setProp} />
281
+ </td>
282
+ </tr>
283
+ )}
284
+ </tbody>
285
+ </table>
286
+ <div accordiontitle="Box" className="w-100">
287
+ <BoxModelEditor setProp={setProp} node={node} sizeWithStyle={true} />
288
+ </div>
289
+ </Accordion>
290
+ );
291
+ };
290
292
 
291
293
  /**
292
294
  * @type {object}
@@ -5,7 +5,7 @@
5
5
  */
6
6
  /* eslint-env jquery */
7
7
 
8
- import React, { useContext, useEffect, Fragment } from "react";
8
+ import React, { useContext, useEffect, useState, Fragment } from "react";
9
9
  import { useNode } from "@craftjs/core";
10
10
  import optionsCtx from "../context";
11
11
  import {
@@ -390,9 +390,30 @@ const JoinFieldSettings = () => {
390
390
  const { setPreviews } = useContext(previewCtx);
391
391
 
392
392
  const fvs = options.field_view_options[name];
393
- const getCfgFields = (fv) =>
394
- ((options.fieldViewConfigForms || {})[name] || {})[fv];
395
- const cfgFields = getCfgFields(fieldview);
393
+
394
+ const [fetchedCfgFields, setFetchedCfgFields] = useState([]);
395
+ const cfgFields = fetchedCfgFields;
396
+ useEffect(() => {
397
+ fetch(`/field/fieldviewcfgform/${options.tableName}?accept=json`, {
398
+ method: "POST",
399
+ headers: {
400
+ "Content-Type": "application/json",
401
+ "CSRF-Token": options.csrfToken,
402
+ "X-Requested-With": "XMLHttpRequest",
403
+ },
404
+ body: JSON.stringify({
405
+ join_field: name,
406
+ join_fieldview: fieldview,
407
+ type: "JoinField",
408
+ }),
409
+ })
410
+ .then(function (response) {
411
+ if (response.status < 399) return response.json();
412
+ else return [];
413
+ })
414
+ .then(setFetchedCfgFields);
415
+ }, [name, fieldview]);
416
+
396
417
  const refetchPreview = fetchFieldPreview({
397
418
  options,
398
419
  name,
@@ -7,12 +7,7 @@
7
7
  import React, { useContext, Fragment } from "react";
8
8
  import { useNode } from "@craftjs/core";
9
9
  import optionsCtx from "../context";
10
- import {
11
- blockProps,
12
- BlockSetting,
13
- setAPropGen,
14
- buildOptions,
15
- } from "./utils";
10
+ import { blockProps, BlockSetting, setAPropGen, buildOptions } from "./utils";
16
11
 
17
12
  export /**
18
13
  * @param {object} props
@@ -82,7 +77,8 @@ const ToggleFilterSettings = () => {
82
77
  const options = useContext(optionsCtx);
83
78
  const field = options.fields.find((f) => f.name === name);
84
79
  const preset_options = field.preset_options;
85
- const isBool = field && field.type.name === "Bool";
80
+ const isBool =
81
+ field && (field.type?.name === "Bool" || field.type === "Bool");
86
82
  const setAProp = setAPropGen(setProp);
87
83
  return (
88
84
  <table className="w-100">
@@ -101,7 +97,9 @@ const ToggleFilterSettings = () => {
101
97
  const value = e.target.value;
102
98
  setProp((prop) => (prop.name = value));
103
99
  const field = options.fields.find((f) => f.name === value);
104
- const isBool = field && field.type.name === "Bool";
100
+ const isBool =
101
+ field &&
102
+ (field.type?.name === "Bool" || field.type === "Bool");
105
103
  if (isBool) setProp((prop) => (prop.value = "on"));
106
104
  setProp((prop) => (prop.preset_value = ""));
107
105
  }