@saltcorn/builder 1.6.0-alpha.1 → 1.6.0-alpha.11
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 +85 -1
- package/dist/builder_bundle.js.LICENSE.txt +18 -51
- package/package.json +31 -27
- package/src/components/Builder.js +445 -155
- package/src/components/Library.js +25 -13
- package/src/components/RenderNode.js +26 -8
- package/src/components/Toolbox.js +333 -269
- package/src/components/elements/Action.js +144 -29
- package/src/components/elements/Aggregation.js +20 -23
- package/src/components/elements/ArrayManager.js +17 -10
- package/src/components/elements/BoxModelEditor.js +19 -17
- package/src/components/elements/Card.js +47 -34
- package/src/components/elements/Clone.js +74 -2
- package/src/components/elements/Column.js +1 -1
- package/src/components/elements/Columns.js +130 -121
- package/src/components/elements/Container.js +185 -92
- package/src/components/elements/DropDownFilter.js +10 -8
- package/src/components/elements/DropMenu.js +18 -9
- package/src/components/elements/Field.js +9 -7
- package/src/components/elements/HTMLCode.js +3 -1
- package/src/components/elements/Image.js +20 -15
- package/src/components/elements/JoinField.js +15 -11
- package/src/components/elements/Link.js +18 -16
- package/src/components/elements/ListColumn.js +7 -3
- package/src/components/elements/ListColumns.js +4 -1
- package/src/components/elements/MonacoEditor.js +4 -2
- package/src/components/elements/Page.js +7 -4
- package/src/components/elements/RelationBadges.js +16 -11
- package/src/components/elements/RelationOnDemandPicker.js +18 -12
- package/src/components/elements/SearchBar.js +37 -10
- package/src/components/elements/Table.js +72 -65
- package/src/components/elements/Tabs.js +18 -15
- package/src/components/elements/Text.js +19 -14
- package/src/components/elements/ToggleFilter.js +28 -25
- package/src/components/elements/View.js +36 -18
- package/src/components/elements/ViewLink.js +15 -11
- package/src/components/elements/utils.js +224 -55
- package/src/components/storage.js +33 -134
- package/src/hooks/useTranslation.js +11 -0
- package/src/index.js +6 -3
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import React, { Fragment, useState, useContext, useEffect } from "react";
|
|
8
|
+
import useTranslation from "../../hooks/useTranslation";
|
|
8
9
|
import { ntimes } from "./Columns";
|
|
9
10
|
import { Column } from "./Column";
|
|
10
11
|
import optionsCtx from "../context";
|
|
@@ -34,6 +35,7 @@ const Tabs = ({
|
|
|
34
35
|
field,
|
|
35
36
|
setting_tab_n,
|
|
36
37
|
}) => {
|
|
38
|
+
const { t } = useTranslation();
|
|
37
39
|
const {
|
|
38
40
|
selected,
|
|
39
41
|
connectors: { connect, drag },
|
|
@@ -121,7 +123,7 @@ const Tabs = ({
|
|
|
121
123
|
(typeof titles[ix].label === "undefined"
|
|
122
124
|
? titles[ix]
|
|
123
125
|
: titles[ix].label === ""
|
|
124
|
-
? "(empty)"
|
|
126
|
+
? t("(empty)")
|
|
125
127
|
: titles[ix].label)}
|
|
126
128
|
</a>
|
|
127
129
|
</li>
|
|
@@ -173,6 +175,7 @@ export /**
|
|
|
173
175
|
* @subcategory components
|
|
174
176
|
*/
|
|
175
177
|
const TabsSettings = () => {
|
|
178
|
+
const { t } = useTranslation();
|
|
176
179
|
const node = useNode((node) => ({
|
|
177
180
|
tabsStyle: node.data.props.tabsStyle,
|
|
178
181
|
ntabs: node.data.props.ntabs,
|
|
@@ -237,11 +240,11 @@ const TabsSettings = () => {
|
|
|
237
240
|
styleOptions.push("Value switch");
|
|
238
241
|
|
|
239
242
|
return (
|
|
240
|
-
<table className="w-100" accordiontitle="Placement">
|
|
243
|
+
<table className="w-100" accordiontitle={t("Placement")}>
|
|
241
244
|
<tbody>
|
|
242
245
|
<tr>
|
|
243
246
|
<th>
|
|
244
|
-
<label>Style</label>
|
|
247
|
+
<label>{t("Style")}</label>
|
|
245
248
|
</th>
|
|
246
249
|
<td>
|
|
247
250
|
<select
|
|
@@ -257,7 +260,7 @@ const TabsSettings = () => {
|
|
|
257
260
|
<Fragment>
|
|
258
261
|
<tr>
|
|
259
262
|
<td>
|
|
260
|
-
<label>Field</label>
|
|
263
|
+
<label>{t("Field")}</label>
|
|
261
264
|
</td>
|
|
262
265
|
<td>
|
|
263
266
|
<select
|
|
@@ -289,7 +292,7 @@ const TabsSettings = () => {
|
|
|
289
292
|
onChange={setAProp("independent", { checked: true })}
|
|
290
293
|
/>
|
|
291
294
|
<label className="form-check-label">
|
|
292
|
-
Open independently
|
|
295
|
+
{t("Open independently")}
|
|
293
296
|
</label>
|
|
294
297
|
</div>
|
|
295
298
|
</td>
|
|
@@ -305,7 +308,7 @@ const TabsSettings = () => {
|
|
|
305
308
|
onChange={setAProp("lazyLoadViews", { checked: true })}
|
|
306
309
|
/>
|
|
307
310
|
<label className="form-check-label">
|
|
308
|
-
Lazy load views
|
|
311
|
+
{t("Lazy load views")}
|
|
309
312
|
</label>
|
|
310
313
|
</div>
|
|
311
314
|
</td>
|
|
@@ -323,7 +326,7 @@ const TabsSettings = () => {
|
|
|
323
326
|
checked={deeplink}
|
|
324
327
|
onChange={setAProp("deeplink", { checked: true })}
|
|
325
328
|
/>
|
|
326
|
-
<label className="form-check-label">Deep link</label>
|
|
329
|
+
<label className="form-check-label">{t("Deep link")}</label>
|
|
327
330
|
</div>
|
|
328
331
|
</td>
|
|
329
332
|
</tr>
|
|
@@ -338,7 +341,7 @@ const TabsSettings = () => {
|
|
|
338
341
|
onChange={setAProp("serverRendered", { checked: true })}
|
|
339
342
|
/>
|
|
340
343
|
<label className="form-check-label">
|
|
341
|
-
Server rendering
|
|
344
|
+
{t("Server rendering")}
|
|
342
345
|
</label>
|
|
343
346
|
</div>
|
|
344
347
|
</td>
|
|
@@ -346,7 +349,7 @@ const TabsSettings = () => {
|
|
|
346
349
|
{serverRendered ? (
|
|
347
350
|
<tr>
|
|
348
351
|
<th>
|
|
349
|
-
<label>Identifier</label>
|
|
352
|
+
<label>{t("Identifier")}</label>
|
|
350
353
|
</th>
|
|
351
354
|
<td>
|
|
352
355
|
<input
|
|
@@ -370,7 +373,7 @@ const TabsSettings = () => {
|
|
|
370
373
|
onChange={setAProp("lazyLoadViews", { checked: true })}
|
|
371
374
|
/>
|
|
372
375
|
<label className="form-check-label">
|
|
373
|
-
Lazy load views
|
|
376
|
+
{t("Lazy load views")}
|
|
374
377
|
</label>
|
|
375
378
|
</div>
|
|
376
379
|
</td>
|
|
@@ -389,7 +392,7 @@ const TabsSettings = () => {
|
|
|
389
392
|
onChange={setAProp("startClosed", { checked: true })}
|
|
390
393
|
/>
|
|
391
394
|
<label className="form-check-label">
|
|
392
|
-
|
|
395
|
+
{t("Initially closed")}
|
|
393
396
|
</label>
|
|
394
397
|
</div>
|
|
395
398
|
</td>
|
|
@@ -407,7 +410,7 @@ const TabsSettings = () => {
|
|
|
407
410
|
onChange={setAProp("disable_inactive", { checked: true })}
|
|
408
411
|
/>
|
|
409
412
|
<label className="form-check-label">
|
|
410
|
-
Disable inactive inputs
|
|
413
|
+
{t("Disable inactive inputs")}
|
|
411
414
|
</label>
|
|
412
415
|
</div>
|
|
413
416
|
</td>
|
|
@@ -427,7 +430,7 @@ const TabsSettings = () => {
|
|
|
427
430
|
</td>
|
|
428
431
|
</tr>
|
|
429
432
|
<tr>
|
|
430
|
-
<th colSpan="2">Title</th>
|
|
433
|
+
<th colSpan="2">{t("Title")}</th>
|
|
431
434
|
</tr>
|
|
432
435
|
<tr>
|
|
433
436
|
<td colSpan={2}>
|
|
@@ -449,7 +452,7 @@ const TabsSettings = () => {
|
|
|
449
452
|
options.mode === "filter" ? (
|
|
450
453
|
<Fragment>
|
|
451
454
|
<tr>
|
|
452
|
-
<th colSpan="2">Show if formula</th>
|
|
455
|
+
<th colSpan="2">{t("Show if formula")}</th>
|
|
453
456
|
</tr>
|
|
454
457
|
<tr>
|
|
455
458
|
<td colSpan={2}>
|
|
@@ -489,7 +492,7 @@ const TabsSettings = () => {
|
|
|
489
492
|
});
|
|
490
493
|
}}
|
|
491
494
|
/>
|
|
492
|
-
<label className="form-check-label">Initially open</label>
|
|
495
|
+
<label className="form-check-label">{t("Initially open")}</label>
|
|
493
496
|
</div>
|
|
494
497
|
</td>
|
|
495
498
|
</tr>
|
|
@@ -21,12 +21,14 @@ import {
|
|
|
21
21
|
} from "./utils";
|
|
22
22
|
import ContentEditable from "react-contenteditable";
|
|
23
23
|
import optionsCtx from "../context";
|
|
24
|
-
import CKEditor from "ckeditor4-react";
|
|
24
|
+
import { CKEditor } from "ckeditor4-react";
|
|
25
25
|
import FontIconPicker from "@fonticonpicker/react-fonticonpicker";
|
|
26
26
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
27
27
|
import fas from "@fortawesome/free-solid-svg-icons";
|
|
28
28
|
import far from "@fortawesome/free-regular-svg-icons";
|
|
29
29
|
import { SingleLineEditor } from "./MonacoEditor";
|
|
30
|
+
import useTranslation from "../../hooks/useTranslation";
|
|
31
|
+
|
|
30
32
|
const ckConfig = {
|
|
31
33
|
toolbarGroups: [
|
|
32
34
|
{ name: "document", groups: ["mode", "document", "doctools"] },
|
|
@@ -109,7 +111,7 @@ const Text = ({
|
|
|
109
111
|
isFormula.text ? "font-monospace" : ""
|
|
110
112
|
} ${selected ? "selected-node" : ""}`}
|
|
111
113
|
ref={(dom) => connect(drag(dom))}
|
|
112
|
-
|
|
114
|
+
onDoubleClick={(e) => selected && setEditable(true)}
|
|
113
115
|
style={{
|
|
114
116
|
...(font ? { fontFamily: font } : {}),
|
|
115
117
|
...reactifyStyles(style || {}),
|
|
@@ -131,7 +133,7 @@ const Text = ({
|
|
|
131
133
|
) : editable ? (
|
|
132
134
|
<ErrorBoundary>
|
|
133
135
|
<CKEditor
|
|
134
|
-
|
|
136
|
+
initData={text || ""}
|
|
135
137
|
style={{ display: "inline" }}
|
|
136
138
|
onChange={(e) =>
|
|
137
139
|
setProp((props) => (props.text = e.editor.getData()))
|
|
@@ -155,7 +157,9 @@ export /**
|
|
|
155
157
|
* @subcategory components
|
|
156
158
|
*/
|
|
157
159
|
const TextSettings = () => {
|
|
160
|
+
const { t } = useTranslation();
|
|
158
161
|
const node = useNode((node) => ({
|
|
162
|
+
id: node.id,
|
|
159
163
|
text: node.data.props.text,
|
|
160
164
|
block: node.data.props.block,
|
|
161
165
|
inline: node.data.props.inline,
|
|
@@ -198,17 +202,18 @@ const TextSettings = () => {
|
|
|
198
202
|
setProp((prop) => (prop.isFormula.text = checked));
|
|
199
203
|
}}
|
|
200
204
|
/>
|
|
201
|
-
<label className="form-check-label">Formula
|
|
205
|
+
<label className="form-check-label">{t("Formula?")}</label>
|
|
202
206
|
</div>
|
|
203
207
|
)}
|
|
204
|
-
|
|
208
|
+
<label>{t("Text to display")}</label>
|
|
205
209
|
{allowFormula && isFormula.text ? (
|
|
206
210
|
<SingleLineEditor setProp={setProp} value={text} propKey="text" />
|
|
207
211
|
) : (
|
|
208
212
|
<ErrorBoundary>
|
|
209
213
|
<div className="border">
|
|
210
214
|
<CKEditor
|
|
211
|
-
|
|
215
|
+
key={node.id}
|
|
216
|
+
initData={text || ""}
|
|
212
217
|
onChange={(e) => {
|
|
213
218
|
if (e.editor) {
|
|
214
219
|
const text = e.editor.getData();
|
|
@@ -223,7 +228,7 @@ const TextSettings = () => {
|
|
|
223
228
|
)}
|
|
224
229
|
{mode === "edit" && (
|
|
225
230
|
<Fragment>
|
|
226
|
-
<label>Label for Field</label>
|
|
231
|
+
<label>{t("Label for Field")}</label>
|
|
227
232
|
<select
|
|
228
233
|
value={labelFor}
|
|
229
234
|
onChange={setAProp("labelFor")}
|
|
@@ -243,7 +248,7 @@ const TextSettings = () => {
|
|
|
243
248
|
<TextStyleRow textStyle={textStyle} setProp={setProp} />
|
|
244
249
|
<tr>
|
|
245
250
|
<td>
|
|
246
|
-
<label>Icon</label>
|
|
251
|
+
<label>{t("Icon")}</label>
|
|
247
252
|
</td>
|
|
248
253
|
<td>
|
|
249
254
|
<FontIconPicker
|
|
@@ -258,7 +263,7 @@ const TextSettings = () => {
|
|
|
258
263
|
<SettingsRow
|
|
259
264
|
field={{
|
|
260
265
|
name: "font",
|
|
261
|
-
label: "Font family",
|
|
266
|
+
label: t("Font family"),
|
|
262
267
|
type: "Font",
|
|
263
268
|
}}
|
|
264
269
|
node={node}
|
|
@@ -267,7 +272,7 @@ const TextSettings = () => {
|
|
|
267
272
|
<SettingsRow
|
|
268
273
|
field={{
|
|
269
274
|
name: "font-size",
|
|
270
|
-
label: "Font size",
|
|
275
|
+
label: t("Font size"),
|
|
271
276
|
type: "DimUnits",
|
|
272
277
|
}}
|
|
273
278
|
node={node}
|
|
@@ -277,7 +282,7 @@ const TextSettings = () => {
|
|
|
277
282
|
<SettingsRow
|
|
278
283
|
field={{
|
|
279
284
|
name: "font-weight",
|
|
280
|
-
label: "Weight",
|
|
285
|
+
label: t("Weight"),
|
|
281
286
|
type: "Integer",
|
|
282
287
|
min: 100,
|
|
283
288
|
max: 900,
|
|
@@ -290,7 +295,7 @@ const TextSettings = () => {
|
|
|
290
295
|
<SettingsRow
|
|
291
296
|
field={{
|
|
292
297
|
name: "line-height",
|
|
293
|
-
label: "Line height",
|
|
298
|
+
label: t("Line height"),
|
|
294
299
|
type: "DimUnits",
|
|
295
300
|
}}
|
|
296
301
|
node={node}
|
|
@@ -298,7 +303,7 @@ const TextSettings = () => {
|
|
|
298
303
|
isStyle={true}
|
|
299
304
|
/>
|
|
300
305
|
<tr>
|
|
301
|
-
<td>Class</td>
|
|
306
|
+
<td>{t("Class")}</td>
|
|
302
307
|
<td>
|
|
303
308
|
<input
|
|
304
309
|
type="text"
|
|
@@ -312,7 +317,7 @@ const TextSettings = () => {
|
|
|
312
317
|
<SettingsRow
|
|
313
318
|
field={{
|
|
314
319
|
name: "color",
|
|
315
|
-
label: "Color",
|
|
320
|
+
label: t("Color"),
|
|
316
321
|
type: "Color",
|
|
317
322
|
}}
|
|
318
323
|
node={node}
|
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
* @subcategory components / elements
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import React, { useContext,
|
|
7
|
+
import React, { Fragment, useState, useContext, useEffect } from "react";
|
|
8
8
|
import { useNode } from "@craftjs/core";
|
|
9
|
+
import useTranslation from "../../hooks/useTranslation";
|
|
9
10
|
import optionsCtx from "../context";
|
|
10
11
|
import { blockProps, BlockSetting, setAPropGen, buildOptions } from "./utils";
|
|
11
12
|
|
|
@@ -32,6 +33,7 @@ const ToggleFilter = ({
|
|
|
32
33
|
size,
|
|
33
34
|
style,
|
|
34
35
|
}) => {
|
|
36
|
+
const { t } = useTranslation();
|
|
35
37
|
const {
|
|
36
38
|
selected,
|
|
37
39
|
connectors: { connect, drag },
|
|
@@ -43,7 +45,7 @@ const ToggleFilter = ({
|
|
|
43
45
|
ref={(dom) => connect(drag(dom))}
|
|
44
46
|
>
|
|
45
47
|
<button className={`btn btn-outline-${style || "primary"} ${size}`}>
|
|
46
|
-
{label || value || preset_value || "Set label"}
|
|
48
|
+
{label || value || preset_value || t("Set label")}
|
|
47
49
|
</button>
|
|
48
50
|
</span>
|
|
49
51
|
);
|
|
@@ -56,6 +58,7 @@ export /**
|
|
|
56
58
|
* @subcategory components
|
|
57
59
|
*/
|
|
58
60
|
const ToggleFilterSettings = () => {
|
|
61
|
+
const { t } = useTranslation();
|
|
59
62
|
const {
|
|
60
63
|
actions: { setProp },
|
|
61
64
|
name,
|
|
@@ -85,7 +88,7 @@ const ToggleFilterSettings = () => {
|
|
|
85
88
|
<tbody>
|
|
86
89
|
<tr>
|
|
87
90
|
<td>
|
|
88
|
-
<label>Field</label>
|
|
91
|
+
<label>{t("Field")}</label>
|
|
89
92
|
</td>
|
|
90
93
|
<td>
|
|
91
94
|
<select
|
|
@@ -115,7 +118,7 @@ const ToggleFilterSettings = () => {
|
|
|
115
118
|
</tr>
|
|
116
119
|
<tr>
|
|
117
120
|
<td>
|
|
118
|
-
<label>Value</label>
|
|
121
|
+
<label>{t("Value")}</label>
|
|
119
122
|
</td>
|
|
120
123
|
<td>
|
|
121
124
|
{isBool ? (
|
|
@@ -124,9 +127,9 @@ const ToggleFilterSettings = () => {
|
|
|
124
127
|
className="w-100 form-select"
|
|
125
128
|
onChange={setAProp("value")}
|
|
126
129
|
>
|
|
127
|
-
<option value="on">True</option>
|
|
128
|
-
<option value="off">False</option>
|
|
129
|
-
<option value="?">Both</option>
|
|
130
|
+
<option value="on">{t("True")}</option>
|
|
131
|
+
<option value="off">{t("False")}</option>
|
|
132
|
+
<option value="?">{t("Both")}</option>
|
|
130
133
|
</select>
|
|
131
134
|
) : (
|
|
132
135
|
<input
|
|
@@ -140,7 +143,7 @@ const ToggleFilterSettings = () => {
|
|
|
140
143
|
{preset_options && preset_options.length > 0 ? (
|
|
141
144
|
<tr>
|
|
142
145
|
<td>
|
|
143
|
-
<label>Preset</label>
|
|
146
|
+
<label>{t("Preset")}</label>
|
|
144
147
|
</td>
|
|
145
148
|
<td>
|
|
146
149
|
<select
|
|
@@ -160,7 +163,7 @@ const ToggleFilterSettings = () => {
|
|
|
160
163
|
) : null}
|
|
161
164
|
<tr>
|
|
162
165
|
<td>
|
|
163
|
-
<label>Label</label>
|
|
166
|
+
<label>{t("Label")}</label>
|
|
164
167
|
</td>
|
|
165
168
|
<td>
|
|
166
169
|
<input
|
|
@@ -172,7 +175,7 @@ const ToggleFilterSettings = () => {
|
|
|
172
175
|
</tr>
|
|
173
176
|
<tr>
|
|
174
177
|
<td>
|
|
175
|
-
<label>Button size</label>
|
|
178
|
+
<label>{t("Button size")}</label>
|
|
176
179
|
</td>
|
|
177
180
|
<td>
|
|
178
181
|
<select
|
|
@@ -180,18 +183,18 @@ const ToggleFilterSettings = () => {
|
|
|
180
183
|
value={size}
|
|
181
184
|
onChange={setAProp("size")}
|
|
182
185
|
>
|
|
183
|
-
<option value="">Standard</option>
|
|
184
|
-
<option value="btn-lg">Large</option>
|
|
185
|
-
<option value="btn-sm">Small</option>
|
|
186
|
-
<option value="btn-block">Block</option>
|
|
187
|
-
<option value="btn-block btn-lg">Large block</option>
|
|
188
|
-
<option value="btn-block btn-sm">Small block</option>
|
|
186
|
+
<option value="">{t("Standard")}</option>
|
|
187
|
+
<option value="btn-lg">{t("Large")}</option>
|
|
188
|
+
<option value="btn-sm">{t("Small")}</option>
|
|
189
|
+
<option value="btn-block">{t("Block")}</option>
|
|
190
|
+
<option value="btn-block btn-lg">{t("Large block")}</option>
|
|
191
|
+
<option value="btn-block btn-sm">{t("Small block")}</option>
|
|
189
192
|
</select>
|
|
190
193
|
</td>
|
|
191
194
|
</tr>
|
|
192
195
|
<tr>
|
|
193
196
|
<td>
|
|
194
|
-
<label>Button style</label>
|
|
197
|
+
<label>{t("Button style")}</label>
|
|
195
198
|
</td>
|
|
196
199
|
<td>
|
|
197
200
|
<select
|
|
@@ -201,14 +204,14 @@ const ToggleFilterSettings = () => {
|
|
|
201
204
|
>
|
|
202
205
|
{buildOptions(
|
|
203
206
|
[
|
|
204
|
-
"primary",
|
|
205
|
-
"secondary",
|
|
206
|
-
"success",
|
|
207
|
-
"danger",
|
|
208
|
-
"warning",
|
|
209
|
-
"info",
|
|
210
|
-
"light",
|
|
211
|
-
"dark",
|
|
207
|
+
t("primary"),
|
|
208
|
+
t("secondary"),
|
|
209
|
+
t("success"),
|
|
210
|
+
t("danger"),
|
|
211
|
+
t("warning"),
|
|
212
|
+
t("info"),
|
|
213
|
+
t("light"),
|
|
214
|
+
t("dark"),
|
|
212
215
|
],
|
|
213
216
|
{ valAttr: true, capitalize: true }
|
|
214
217
|
)}
|
|
@@ -8,6 +8,7 @@ import React, { Fragment, useEffect, useMemo } from "react";
|
|
|
8
8
|
import { useNode } from "@craftjs/core";
|
|
9
9
|
import optionsCtx from "../context";
|
|
10
10
|
import previewCtx from "../preview_context";
|
|
11
|
+
import useTranslation from "../../hooks/useTranslation";
|
|
11
12
|
import relationsCtx from "../relations_context";
|
|
12
13
|
import Select from "react-select";
|
|
13
14
|
|
|
@@ -19,6 +20,8 @@ import {
|
|
|
19
20
|
HelpTopicLink,
|
|
20
21
|
initialRelation,
|
|
21
22
|
buildLayers,
|
|
23
|
+
reactSelectStyles,
|
|
24
|
+
builderSelectClassName,
|
|
22
25
|
} from "./utils";
|
|
23
26
|
|
|
24
27
|
import { RelationBadges } from "./RelationBadges";
|
|
@@ -47,6 +50,7 @@ const View = ({ name, view, configuration, state }) => {
|
|
|
47
50
|
node_id,
|
|
48
51
|
connectors: { connect, drag },
|
|
49
52
|
} = useNode((node) => ({ selected: node.events.selected, node_id: node.id }));
|
|
53
|
+
const { t } = useTranslation();
|
|
50
54
|
const options = React.useContext(optionsCtx);
|
|
51
55
|
|
|
52
56
|
let viewname = view;
|
|
@@ -81,7 +85,7 @@ const View = ({ name, view, configuration, state }) => {
|
|
|
81
85
|
dangerouslySetInnerHTML={{ __html: myPreview }}
|
|
82
86
|
></div>
|
|
83
87
|
) : (
|
|
84
|
-
|
|
88
|
+
`${t("View")}: ${label}`
|
|
85
89
|
)}
|
|
86
90
|
</div>
|
|
87
91
|
);
|
|
@@ -94,6 +98,7 @@ export /**
|
|
|
94
98
|
* @namespace
|
|
95
99
|
*/
|
|
96
100
|
const ViewSettings = () => {
|
|
101
|
+
const { t } = useTranslation();
|
|
97
102
|
const node = useNode((node) => ({
|
|
98
103
|
name: node.data.props.name,
|
|
99
104
|
view: node.data.props.view,
|
|
@@ -157,6 +162,7 @@ const ViewSettings = () => {
|
|
|
157
162
|
}
|
|
158
163
|
if (viewname && viewname.includes(".")) viewname = viewname.split(".")[0];
|
|
159
164
|
|
|
165
|
+
let cacheWasPopulated = false;
|
|
160
166
|
if (
|
|
161
167
|
finder &&
|
|
162
168
|
!(relationsCache[tableName] && relationsCache[tableName][viewname])
|
|
@@ -173,8 +179,13 @@ const ViewSettings = () => {
|
|
|
173
179
|
);
|
|
174
180
|
relationsCache[tableName] = relationsCache[tableName] || {};
|
|
175
181
|
relationsCache[tableName][viewname] = { relations, layers };
|
|
176
|
-
|
|
182
|
+
cacheWasPopulated = true;
|
|
177
183
|
}
|
|
184
|
+
useEffect(() => {
|
|
185
|
+
if (cacheWasPopulated) {
|
|
186
|
+
setRelationsCache({ ...relationsCache });
|
|
187
|
+
}
|
|
188
|
+
});
|
|
178
189
|
const [relationsData, setRelationsData] = finder
|
|
179
190
|
? React.useState(relationsCache[tableName][viewname])
|
|
180
191
|
: [undefined, undefined];
|
|
@@ -188,18 +199,23 @@ const ViewSettings = () => {
|
|
|
188
199
|
subView.display_type
|
|
189
200
|
);
|
|
190
201
|
}
|
|
191
|
-
|
|
202
|
+
const needsInitialRelation =
|
|
192
203
|
options.mode !== "filter" &&
|
|
193
204
|
subView?.table_id &&
|
|
194
205
|
!safeRelation &&
|
|
195
206
|
!hasLegacyRelation &&
|
|
196
|
-
relationsData?.relations.length > 0
|
|
197
|
-
) {
|
|
207
|
+
relationsData?.relations.length > 0;
|
|
208
|
+
if (needsInitialRelation) {
|
|
198
209
|
safeRelation = initialRelation(relationsData.relations);
|
|
199
|
-
setProp((prop) => {
|
|
200
|
-
prop.relation = safeRelation.relationString;
|
|
201
|
-
});
|
|
202
210
|
}
|
|
211
|
+
useEffect(() => {
|
|
212
|
+
if (needsInitialRelation) {
|
|
213
|
+
const rel = initialRelation(relationsData.relations);
|
|
214
|
+
setProp((prop) => {
|
|
215
|
+
prop.relation = rel.relationString;
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
}, [needsInitialRelation]);
|
|
203
219
|
const helpContext = { view_name: viewname };
|
|
204
220
|
if (options.tableName) helpContext.srcTable = options.tableName;
|
|
205
221
|
const set_view_name = (e) => {
|
|
@@ -235,7 +251,7 @@ const ViewSettings = () => {
|
|
|
235
251
|
} else
|
|
236
252
|
window.notifyAlert({
|
|
237
253
|
type: "warning",
|
|
238
|
-
text: `${target_value} has no relations`,
|
|
254
|
+
text: `${target_value} ${t("has no relations")}`,
|
|
239
255
|
});
|
|
240
256
|
}
|
|
241
257
|
}
|
|
@@ -262,11 +278,12 @@ const ViewSettings = () => {
|
|
|
262
278
|
<Select
|
|
263
279
|
options={viewOptions}
|
|
264
280
|
value={selectedView}
|
|
265
|
-
className="react-select view-selector"
|
|
281
|
+
className={builderSelectClassName("react-select view-selector")}
|
|
282
|
+
classNamePrefix="builder-select"
|
|
266
283
|
onChange={set_view_name}
|
|
267
284
|
onBlur={set_view_name}
|
|
268
285
|
menuPortalTarget={document.body}
|
|
269
|
-
styles={
|
|
286
|
+
styles={reactSelectStyles()}
|
|
270
287
|
></Select>
|
|
271
288
|
)}
|
|
272
289
|
</div>
|
|
@@ -304,7 +321,8 @@ const ViewSettings = () => {
|
|
|
304
321
|
<Select
|
|
305
322
|
options={viewOptions}
|
|
306
323
|
value={selectedView}
|
|
307
|
-
className="react-select view-selector"
|
|
324
|
+
className={builderSelectClassName("react-select view-selector")}
|
|
325
|
+
classNamePrefix="builder-select"
|
|
308
326
|
onChange={(e) => {
|
|
309
327
|
const target_value = e?.target?.value || e?.value;
|
|
310
328
|
setProp((prop) => {
|
|
@@ -312,7 +330,7 @@ const ViewSettings = () => {
|
|
|
312
330
|
});
|
|
313
331
|
}}
|
|
314
332
|
menuPortalTarget={document.body}
|
|
315
|
-
styles={
|
|
333
|
+
styles={reactSelectStyles()}
|
|
316
334
|
></Select>
|
|
317
335
|
)}
|
|
318
336
|
</div>
|
|
@@ -322,7 +340,7 @@ const ViewSettings = () => {
|
|
|
322
340
|
theview?.viewtemplate === "Edit" &&
|
|
323
341
|
targetTable ? (
|
|
324
342
|
<div>
|
|
325
|
-
<label>Order field</label>
|
|
343
|
+
<label>{t("Order field")}</label>
|
|
326
344
|
<select
|
|
327
345
|
value={order_field}
|
|
328
346
|
className="form-control form-select"
|
|
@@ -341,7 +359,7 @@ const ViewSettings = () => {
|
|
|
341
359
|
{options.mode !== "edit" && (
|
|
342
360
|
<Fragment>
|
|
343
361
|
<div>
|
|
344
|
-
<label>State</label>
|
|
362
|
+
<label>{t("State")}</label>
|
|
345
363
|
<select
|
|
346
364
|
value={state}
|
|
347
365
|
className="form-control form-select"
|
|
@@ -365,7 +383,7 @@ const ViewSettings = () => {
|
|
|
365
383
|
fixed_state_fields &&
|
|
366
384
|
fixed_state_fields.length > 0 && (
|
|
367
385
|
<Fragment>
|
|
368
|
-
<h6>View state fields</h6>
|
|
386
|
+
<h6>{t("View state fields")}</h6>
|
|
369
387
|
<ConfigForm
|
|
370
388
|
fields={fixed_state_fields}
|
|
371
389
|
configuration={configuration || {}}
|
|
@@ -379,7 +397,7 @@ const ViewSettings = () => {
|
|
|
379
397
|
{
|
|
380
398
|
<Fragment>
|
|
381
399
|
<label>
|
|
382
|
-
Extra state Formula
|
|
400
|
+
{t("Extra state Formula")}
|
|
383
401
|
<HelpTopicLink topic="Extra state formula" {...helpContext} />
|
|
384
402
|
</label>
|
|
385
403
|
<SingleLineEditor
|
|
@@ -401,7 +419,7 @@ const ViewSettings = () => {
|
|
|
401
419
|
target="_blank"
|
|
402
420
|
href={`/viewedit/config/${viewname}`}
|
|
403
421
|
>
|
|
404
|
-
Configure this view
|
|
422
|
+
{t("Configure this view")}
|
|
405
423
|
</a>
|
|
406
424
|
) : null}
|
|
407
425
|
</div>
|