@saltcorn/builder 0.9.4-beta.8 → 0.9.4
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 +20 -12
- package/package.json +3 -1
- package/src/components/Builder.js +51 -58
- package/src/components/Library.js +40 -8
- package/src/components/RenderNode.js +5 -0
- package/src/components/Toolbox.js +61 -2
- package/src/components/elements/Action.js +12 -0
- package/src/components/elements/Aggregation.js +200 -104
- package/src/components/elements/BoxModelEditor.js +8 -8
- package/src/components/elements/Column.js +16 -2
- package/src/components/elements/Columns.js +3 -3
- package/src/components/elements/Container.js +25 -1
- package/src/components/elements/DropMenu.js +31 -2
- package/src/components/elements/Field.js +22 -20
- package/src/components/elements/HTMLCode.js +1 -1
- package/src/components/elements/JoinField.js +25 -1
- package/src/components/elements/Link.js +1 -0
- package/src/components/elements/ListColumn.js +177 -0
- package/src/components/elements/ListColumns.js +62 -0
- package/src/components/elements/RelationBadges.js +53 -44
- package/src/components/elements/Tabs.js +29 -1
- package/src/components/elements/Text.js +4 -2
- package/src/components/elements/View.js +119 -68
- package/src/components/elements/ViewLink.js +100 -48
- package/src/components/elements/utils.js +188 -101
- package/src/components/storage.js +65 -5
- package/tests/relations_finder.test.js +58 -92
- package/tests/test_data.js +0 -163
|
@@ -18,6 +18,8 @@ import FontIconPicker from "@fonticonpicker/react-fonticonpicker";
|
|
|
18
18
|
import faIcons from "./faicons";
|
|
19
19
|
import { Columns, ntimes } from "./Columns";
|
|
20
20
|
import Tippy from "@tippyjs/react";
|
|
21
|
+
import { RelationType } from "@saltcorn/common-code";
|
|
22
|
+
import Select from "react-select";
|
|
21
23
|
|
|
22
24
|
export const DynamicFontAwesomeIcon = ({ icon, className }) => {
|
|
23
25
|
if (!icon) return null;
|
|
@@ -138,7 +140,7 @@ export /**
|
|
|
138
140
|
*/
|
|
139
141
|
const OrFormula = ({ setProp, isFormula, node, nodekey, children }) => {
|
|
140
142
|
const { mode } = React.useContext(optionsCtx);
|
|
141
|
-
|
|
143
|
+
const allowFormula = mode === "show" || mode === "list";
|
|
142
144
|
/**
|
|
143
145
|
* @returns {void}
|
|
144
146
|
*/
|
|
@@ -159,14 +161,14 @@ const OrFormula = ({ setProp, isFormula, node, nodekey, children }) => {
|
|
|
159
161
|
});
|
|
160
162
|
};
|
|
161
163
|
let errorString = false;
|
|
162
|
-
if (
|
|
164
|
+
if (allowFormula && isFormula[nodekey]) {
|
|
163
165
|
try {
|
|
164
166
|
Function("return " + node[nodekey]);
|
|
165
167
|
} catch (error) {
|
|
166
168
|
errorString = error.message;
|
|
167
169
|
}
|
|
168
170
|
}
|
|
169
|
-
return
|
|
171
|
+
return !allowFormula ? (
|
|
170
172
|
children
|
|
171
173
|
) : (
|
|
172
174
|
<Fragment>
|
|
@@ -445,6 +447,10 @@ const fetchPreview = ({ url, body, options, setPreviews, node_id, isView }) => {
|
|
|
445
447
|
}
|
|
446
448
|
const newHtml = $(".preview-scratchpad").html();
|
|
447
449
|
setPreviews((prevState) => ({ ...prevState, [node_id]: newHtml }));
|
|
450
|
+
})
|
|
451
|
+
.catch((e) => {
|
|
452
|
+
console.log("Unable to fetch the preview:");
|
|
453
|
+
console.log(e);
|
|
448
454
|
});
|
|
449
455
|
};
|
|
450
456
|
|
|
@@ -487,6 +493,7 @@ export const fetchViewPreview =
|
|
|
487
493
|
};
|
|
488
494
|
let viewname,
|
|
489
495
|
body = configuration ? { ...configuration } : {};
|
|
496
|
+
if (!view) return "";
|
|
490
497
|
if (view.includes(":")) {
|
|
491
498
|
const [prefix, rest] = view.split(":");
|
|
492
499
|
const tokens = rest.split(".");
|
|
@@ -897,24 +904,51 @@ const ConfigField = ({
|
|
|
897
904
|
spellCheck={false}
|
|
898
905
|
/>
|
|
899
906
|
),
|
|
900
|
-
select: () =>
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
907
|
+
select: () => {
|
|
908
|
+
if (field.class?.includes?.("selectizable")) {
|
|
909
|
+
const seloptions = field.options.map((o, ix) =>
|
|
910
|
+
o.name && o.label
|
|
911
|
+
? { value: o.name, label: o.label }
|
|
912
|
+
: { value: o, label: o }
|
|
913
|
+
);
|
|
914
|
+
return (
|
|
915
|
+
<Select
|
|
916
|
+
options={seloptions}
|
|
917
|
+
value={seloptions.find((so) => value === so.value)}
|
|
918
|
+
onChange={(e) =>
|
|
919
|
+
(e.name && myOnChange(e.name)) ||
|
|
920
|
+
(e.value && myOnChange(e.value)) ||
|
|
921
|
+
(typeof e === "string" && myOnChange(e))
|
|
922
|
+
}
|
|
923
|
+
onBlur={(e) =>
|
|
924
|
+
(e.name && myOnChange(e.name)) ||
|
|
925
|
+
(e.value && myOnChange(e.value)) ||
|
|
926
|
+
(typeof e === "string" && myOnChange(e))
|
|
927
|
+
}
|
|
928
|
+
menuPortalTarget={document.body}
|
|
929
|
+
styles={{ menuPortal: (base) => ({ ...base, zIndex: 19999 }) }}
|
|
930
|
+
></Select>
|
|
931
|
+
);
|
|
932
|
+
} else
|
|
933
|
+
return (
|
|
934
|
+
<select
|
|
935
|
+
className="form-control form-select"
|
|
936
|
+
value={value || ""}
|
|
937
|
+
onChange={(e) => e.target && myOnChange(e.target.value)}
|
|
938
|
+
onBlur={(e) => e.target && myOnChange(e.target.value)}
|
|
939
|
+
>
|
|
940
|
+
{field.options.map((o, ix) =>
|
|
941
|
+
o.name && o.label ? (
|
|
942
|
+
<option key={ix} value={o.name}>
|
|
943
|
+
{o.label}
|
|
944
|
+
</option>
|
|
945
|
+
) : (
|
|
946
|
+
<option key={ix}>{o}</option>
|
|
947
|
+
)
|
|
948
|
+
)}
|
|
949
|
+
</select>
|
|
950
|
+
);
|
|
951
|
+
},
|
|
918
952
|
btn_select: () => (
|
|
919
953
|
<div className="btn-group w-100" role="group">
|
|
920
954
|
{field.options.map((o, ix) => (
|
|
@@ -1012,8 +1046,15 @@ export /**
|
|
|
1012
1046
|
* @returns {table}
|
|
1013
1047
|
*/
|
|
1014
1048
|
const SettingsFromFields =
|
|
1015
|
-
(
|
|
1049
|
+
(fieldsIn, opts = {}) =>
|
|
1016
1050
|
() => {
|
|
1051
|
+
const fields = [...fieldsIn];
|
|
1052
|
+
if (opts.additionalFieldsOptionKey) {
|
|
1053
|
+
const options = React.useContext(optionsCtx);
|
|
1054
|
+
|
|
1055
|
+
const addFields = options[opts.additionalFieldsOptionKey];
|
|
1056
|
+
fields.push(...(addFields || []));
|
|
1057
|
+
}
|
|
1017
1058
|
const node = useNode((node) => {
|
|
1018
1059
|
const ps = {};
|
|
1019
1060
|
fields.forEach((f) => {
|
|
@@ -1253,9 +1294,12 @@ const ButtonOrLinkSettingsRows = ({
|
|
|
1253
1294
|
<option value={addBtnClass("btn-outline-secondary")}>
|
|
1254
1295
|
Secondary outline button
|
|
1255
1296
|
</option>
|
|
1297
|
+
<option value={addBtnClass("btn-outline-danger")}>
|
|
1298
|
+
Danger outline button
|
|
1299
|
+
</option>
|
|
1256
1300
|
<option value={addBtnClass("btn-outline-warning")}>
|
|
1257
1301
|
Warning outline button
|
|
1258
|
-
</option>
|
|
1302
|
+
</option>
|
|
1259
1303
|
<option value={addBtnClass("btn-outline-info")}>
|
|
1260
1304
|
Info outline button
|
|
1261
1305
|
</option>
|
|
@@ -1265,7 +1309,7 @@ const ButtonOrLinkSettingsRows = ({
|
|
|
1265
1309
|
{!linkFirst ? (
|
|
1266
1310
|
<option value={addBtnClass("btn-link")}>Link</option>
|
|
1267
1311
|
) : null}
|
|
1268
|
-
{!linkFirst ? (
|
|
1312
|
+
{!linkFirst && allowRunOnLoad ? (
|
|
1269
1313
|
<option value="on_page_load">Run on Page Load</option>
|
|
1270
1314
|
) : null}
|
|
1271
1315
|
</select>
|
|
@@ -1285,6 +1329,7 @@ const ButtonOrLinkSettingsRows = ({
|
|
|
1285
1329
|
<option value="">Standard</option>
|
|
1286
1330
|
<option value="btn-lg">Large</option>
|
|
1287
1331
|
<option value="btn-sm">Small</option>
|
|
1332
|
+
<option value="btn-sm btn-xs">Extra Small</option>
|
|
1288
1333
|
<option value="btn-block">Block</option>
|
|
1289
1334
|
<option value="btn-block btn-lg">Large block</option>
|
|
1290
1335
|
</select>
|
|
@@ -1447,22 +1492,6 @@ const Tooltip = ({ children }) => {
|
|
|
1447
1492
|
);
|
|
1448
1493
|
};
|
|
1449
1494
|
|
|
1450
|
-
export const buildTableCaches = (allTables) => {
|
|
1451
|
-
const tableIdCache = {};
|
|
1452
|
-
const tableNameCache = {};
|
|
1453
|
-
const fieldCache = {};
|
|
1454
|
-
for (const table of allTables) {
|
|
1455
|
-
tableIdCache[table.id] = table;
|
|
1456
|
-
tableNameCache[table.name] = table;
|
|
1457
|
-
for (const field of table.foreign_keys) {
|
|
1458
|
-
if (!fieldCache[field.reftable_name])
|
|
1459
|
-
fieldCache[field.reftable_name] = [];
|
|
1460
|
-
fieldCache[field.reftable_name].push(field);
|
|
1461
|
-
}
|
|
1462
|
-
}
|
|
1463
|
-
return { tableIdCache, tableNameCache, fieldCache };
|
|
1464
|
-
};
|
|
1465
|
-
|
|
1466
1495
|
export const removeWhitespaces = (str) => {
|
|
1467
1496
|
return str.replace(/\s/g, "X");
|
|
1468
1497
|
};
|
|
@@ -1513,79 +1542,137 @@ export const arrayChunks = (xs, n) => {
|
|
|
1513
1542
|
return arrayOfArrays;
|
|
1514
1543
|
};
|
|
1515
1544
|
|
|
1516
|
-
export const prepCacheAndFinder = ({
|
|
1517
|
-
tables,
|
|
1518
|
-
views,
|
|
1519
|
-
max_relations_layer_depth,
|
|
1520
|
-
}) => {
|
|
1521
|
-
if (tables && views) {
|
|
1522
|
-
const caches = buildTableCaches(tables);
|
|
1523
|
-
const finder = new relationHelpers.RelationsFinder(
|
|
1524
|
-
caches,
|
|
1525
|
-
views,
|
|
1526
|
-
max_relations_layer_depth || 6
|
|
1527
|
-
);
|
|
1528
|
-
return { caches, finder };
|
|
1529
|
-
} else return { caches: null, finder: null };
|
|
1530
|
-
};
|
|
1531
|
-
|
|
1532
1545
|
/**
|
|
1533
|
-
* @param {string[]}
|
|
1546
|
+
* @param {string[]} relations
|
|
1534
1547
|
* @param {string} sourceTbl name of the topview table
|
|
1535
1548
|
* @returns either a same table relation, a parent relation, a child relation, or the first relation
|
|
1536
1549
|
*/
|
|
1537
|
-
export const initialRelation = (
|
|
1550
|
+
export const initialRelation = (relations) => {
|
|
1538
1551
|
let sameTblRel = null;
|
|
1539
1552
|
let parentRel = null;
|
|
1540
1553
|
let childRel = null;
|
|
1541
|
-
for (const
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
const lastToken = tokens[tokens.length - 1];
|
|
1554
|
-
if (
|
|
1555
|
-
lastToken.indexOf("$") > 0 &&
|
|
1556
|
-
(!childRel || childRel.split(".").length > tokens.length)
|
|
1557
|
-
)
|
|
1558
|
-
childRel = path;
|
|
1559
|
-
}
|
|
1554
|
+
for (const relation of relations) {
|
|
1555
|
+
switch (relation.type) {
|
|
1556
|
+
case RelationType.OWN:
|
|
1557
|
+
sameTblRel = relation;
|
|
1558
|
+
break;
|
|
1559
|
+
case RelationType.PARENT_SHOW:
|
|
1560
|
+
parentRel = relation;
|
|
1561
|
+
break;
|
|
1562
|
+
case RelationType.CHILD_LIST:
|
|
1563
|
+
case RelationType.ONE_TO_ONE_SHOW:
|
|
1564
|
+
childRel = relation;
|
|
1565
|
+
break;
|
|
1560
1566
|
}
|
|
1561
1567
|
}
|
|
1562
|
-
return sameTblRel || parentRel || childRel ||
|
|
1568
|
+
return sameTblRel || parentRel || childRel || relations[0];
|
|
1563
1569
|
};
|
|
1564
1570
|
|
|
1565
1571
|
/**
|
|
1566
|
-
*
|
|
1567
|
-
*
|
|
1568
|
-
* @param
|
|
1569
|
-
* @
|
|
1570
|
-
* @param {any} options builder options
|
|
1571
|
-
* @param {RelationsFinder} finder
|
|
1572
|
-
* @param {string} viewname subview name
|
|
1572
|
+
* builder intern path method
|
|
1573
|
+
* @param path
|
|
1574
|
+
* @param tableNameCache
|
|
1575
|
+
* @returns
|
|
1573
1576
|
*/
|
|
1574
|
-
export const
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
)
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1577
|
+
export const buildRelationArray = (path, tableNameCache) => {
|
|
1578
|
+
if (path === ".")
|
|
1579
|
+
return [{ type: "Independent", table: "None (no relation)" }];
|
|
1580
|
+
const tokens = path.split(".");
|
|
1581
|
+
if (tokens.length === 2)
|
|
1582
|
+
return [{ type: "Own", table: `${tokens[1]} (same table)` }];
|
|
1583
|
+
else if (tokens.length >= 3) {
|
|
1584
|
+
const result = [];
|
|
1585
|
+
let currentTbl = tokens[1];
|
|
1586
|
+
for (const relation of tokens.slice(2)) {
|
|
1587
|
+
if (relation.indexOf("$") > 0) {
|
|
1588
|
+
const [inboundTbl, inboundKey] = relation.split("$");
|
|
1589
|
+
result.push({ type: "Inbound", table: inboundTbl, key: inboundKey });
|
|
1590
|
+
currentTbl = inboundTbl;
|
|
1591
|
+
} else {
|
|
1592
|
+
const srcTbl = tableNameCache[currentTbl];
|
|
1593
|
+
const fk = srcTbl.foreign_keys.find((fk) => fk.name === relation);
|
|
1594
|
+
if (fk) {
|
|
1595
|
+
const targetTbl = tableNameCache[fk.reftable_name];
|
|
1596
|
+
result.push({
|
|
1597
|
+
type: "Foreign",
|
|
1598
|
+
table: targetTbl.name,
|
|
1599
|
+
key: relation,
|
|
1600
|
+
});
|
|
1601
|
+
currentTbl = targetTbl.name;
|
|
1602
|
+
}
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
return result;
|
|
1606
|
+
}
|
|
1607
|
+
};
|
|
1608
|
+
|
|
1609
|
+
export const buildLayers = (relations, tableName, tableNameCache) => {
|
|
1610
|
+
const result = { table: tableName, inboundKeys: [], fkeys: [] };
|
|
1611
|
+
for (const relation of relations) {
|
|
1612
|
+
const relType = relation.type;
|
|
1613
|
+
let currentLevel = result;
|
|
1614
|
+
if (relType === RelationType.INDEPENDENT) {
|
|
1615
|
+
currentLevel.fkeys.push({
|
|
1616
|
+
name: "none (no relation)",
|
|
1617
|
+
table: "",
|
|
1618
|
+
inboundKeys: [],
|
|
1619
|
+
fkeys: [],
|
|
1620
|
+
relPath: relation.relationString,
|
|
1621
|
+
});
|
|
1622
|
+
} else if (relType === RelationType.OWN) {
|
|
1623
|
+
currentLevel.fkeys.push({
|
|
1624
|
+
name: "same table",
|
|
1625
|
+
table: relation.targetTblName,
|
|
1626
|
+
inboundKeys: [],
|
|
1627
|
+
fkeys: [],
|
|
1628
|
+
relPath: relation.relationString,
|
|
1629
|
+
});
|
|
1630
|
+
} else {
|
|
1631
|
+
let currentTbl = relation.sourceTblName;
|
|
1632
|
+
for (const pathElement of relation.path) {
|
|
1633
|
+
if (pathElement.inboundKey) {
|
|
1634
|
+
currentTbl = pathElement.table;
|
|
1635
|
+
const existing = currentLevel.inboundKeys.find(
|
|
1636
|
+
(key) =>
|
|
1637
|
+
key.name === pathElement.inboundKey && key.table === currentTbl
|
|
1638
|
+
);
|
|
1639
|
+
if (existing) {
|
|
1640
|
+
currentLevel = existing;
|
|
1641
|
+
} else {
|
|
1642
|
+
const nextLevel = {
|
|
1643
|
+
name: pathElement.inboundKey,
|
|
1644
|
+
table: currentTbl,
|
|
1645
|
+
inboundKeys: [],
|
|
1646
|
+
fkeys: [],
|
|
1647
|
+
};
|
|
1648
|
+
currentLevel.inboundKeys.push(nextLevel);
|
|
1649
|
+
currentLevel = nextLevel;
|
|
1650
|
+
}
|
|
1651
|
+
} else if (pathElement.fkey) {
|
|
1652
|
+
const tblObj = tableNameCache[currentTbl];
|
|
1653
|
+
const fkey = tblObj.foreign_keys.find(
|
|
1654
|
+
(key) => key.name === pathElement.fkey
|
|
1655
|
+
);
|
|
1656
|
+
currentTbl = fkey.reftable_name;
|
|
1657
|
+
const existing = currentLevel.fkeys.find(
|
|
1658
|
+
(key) => key.name === pathElement.fkey
|
|
1659
|
+
);
|
|
1660
|
+
if (existing) {
|
|
1661
|
+
currentLevel = existing;
|
|
1662
|
+
} else {
|
|
1663
|
+
const nextLevel = {
|
|
1664
|
+
name: pathElement.fkey,
|
|
1665
|
+
table: currentTbl,
|
|
1666
|
+
inboundKeys: [],
|
|
1667
|
+
fkeys: [],
|
|
1668
|
+
};
|
|
1669
|
+
currentLevel.fkeys.push(nextLevel);
|
|
1670
|
+
currentLevel = nextLevel;
|
|
1671
|
+
}
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1675
|
+
currentLevel.relPath = relation.relationString;
|
|
1590
1676
|
}
|
|
1677
|
+
return result;
|
|
1591
1678
|
};
|
|
@@ -12,6 +12,8 @@ import { Empty } from "./elements/Empty";
|
|
|
12
12
|
import { Columns, ntimes, sum } from "./elements/Columns";
|
|
13
13
|
import { JoinField } from "./elements/JoinField";
|
|
14
14
|
import { Tabs } from "./elements/Tabs";
|
|
15
|
+
import { ListColumns } from "./elements/ListColumns";
|
|
16
|
+
import { ListColumn } from "./elements/ListColumn";
|
|
15
17
|
import { Table } from "./elements/Table";
|
|
16
18
|
import { Aggregation } from "./elements/Aggregation";
|
|
17
19
|
import { LineBreak } from "./elements/LineBreak";
|
|
@@ -76,6 +78,8 @@ const allElements = [
|
|
|
76
78
|
DropMenu,
|
|
77
79
|
Page,
|
|
78
80
|
Table,
|
|
81
|
+
ListColumn,
|
|
82
|
+
ListColumns,
|
|
79
83
|
];
|
|
80
84
|
|
|
81
85
|
export /**
|
|
@@ -88,7 +92,7 @@ export /**
|
|
|
88
92
|
* @subcategory components
|
|
89
93
|
* @namespace
|
|
90
94
|
*/
|
|
91
|
-
const layoutToNodes = (layout, query, actions, parent = "ROOT") => {
|
|
95
|
+
const layoutToNodes = (layout, query, actions, parent = "ROOT", options) => {
|
|
92
96
|
//console.log("layoutToNodes", JSON.stringify(layout));
|
|
93
97
|
/**
|
|
94
98
|
* @param {object} segment
|
|
@@ -129,7 +133,6 @@ const layoutToNodes = (layout, query, actions, parent = "ROOT") => {
|
|
|
129
133
|
);
|
|
130
134
|
else return <MatchElement key={ix} {...props} />;
|
|
131
135
|
}
|
|
132
|
-
|
|
133
136
|
if (segment.type === "blank") {
|
|
134
137
|
return (
|
|
135
138
|
<Text
|
|
@@ -177,6 +180,7 @@ const layoutToNodes = (layout, query, actions, parent = "ROOT") => {
|
|
|
177
180
|
step_only_ifs={segment.step_only_ifs || ""}
|
|
178
181
|
step_action_names={segment.step_action_names || ""}
|
|
179
182
|
confirm={segment.confirm}
|
|
183
|
+
spinner={segment.spinner}
|
|
180
184
|
configuration={segment.configuration || {}}
|
|
181
185
|
block={segment.block || false}
|
|
182
186
|
minRole={segment.minRole || 10}
|
|
@@ -200,6 +204,7 @@ const layoutToNodes = (layout, query, actions, parent = "ROOT") => {
|
|
|
200
204
|
minHeight={segment.minHeight}
|
|
201
205
|
height={segment.height}
|
|
202
206
|
width={segment.width}
|
|
207
|
+
click_action={segment.click_action}
|
|
203
208
|
url={segment.url}
|
|
204
209
|
hoverColor={segment.hoverColor}
|
|
205
210
|
minHeightUnit={segment.minHeightUnit || "px"}
|
|
@@ -258,6 +263,7 @@ const layoutToNodes = (layout, query, actions, parent = "ROOT") => {
|
|
|
258
263
|
independent={segment.independent}
|
|
259
264
|
startClosed={segment.startClosed}
|
|
260
265
|
deeplink={segment.deeplink}
|
|
266
|
+
acc_init_opens={segment.acc_init_opens}
|
|
261
267
|
disable_inactive={segment.disable_inactive}
|
|
262
268
|
serverRendered={segment.serverRendered}
|
|
263
269
|
tabId={segment.tabId}
|
|
@@ -283,6 +289,27 @@ const layoutToNodes = (layout, query, actions, parent = "ROOT") => {
|
|
|
283
289
|
)}
|
|
284
290
|
/>
|
|
285
291
|
);
|
|
292
|
+
} else if (segment.besides && segment.list_columns) {
|
|
293
|
+
const addFields = options.additionalColumnFields;
|
|
294
|
+
|
|
295
|
+
return segment.besides.map((col, jx) => {
|
|
296
|
+
const addProps = {};
|
|
297
|
+
(addFields || []).forEach((f) => {
|
|
298
|
+
addProps[f.name] = col[f.name];
|
|
299
|
+
});
|
|
300
|
+
return (
|
|
301
|
+
<ListColumn
|
|
302
|
+
key={jx}
|
|
303
|
+
alignment={col.alignment}
|
|
304
|
+
header_label={col.header_label}
|
|
305
|
+
col_width={col.col_width}
|
|
306
|
+
showif={col.showif}
|
|
307
|
+
col_width_units={col.col_width_units}
|
|
308
|
+
contents={toTag(col.contents)}
|
|
309
|
+
{...addProps}
|
|
310
|
+
></ListColumn>
|
|
311
|
+
);
|
|
312
|
+
});
|
|
286
313
|
} else if (segment.besides) {
|
|
287
314
|
return (
|
|
288
315
|
<Columns
|
|
@@ -317,7 +344,7 @@ const layoutToNodes = (layout, query, actions, parent = "ROOT") => {
|
|
|
317
344
|
segment.above.forEach((child) => {
|
|
318
345
|
if (child) go(child, parent);
|
|
319
346
|
});
|
|
320
|
-
} else if (segment.besides) {
|
|
347
|
+
} else if (segment.besides && !segment.list_columns) {
|
|
321
348
|
const node = query
|
|
322
349
|
.parseReactElement(
|
|
323
350
|
<Columns
|
|
@@ -339,7 +366,13 @@ const layoutToNodes = (layout, query, actions, parent = "ROOT") => {
|
|
|
339
366
|
actions.addNodeTree(node, parent);
|
|
340
367
|
} else {
|
|
341
368
|
const tag = toTag(segment);
|
|
342
|
-
if (tag) {
|
|
369
|
+
if (Array.isArray(tag)) {
|
|
370
|
+
tag.forEach((t) => {
|
|
371
|
+
const node = query.parseReactElement(t).toNodeTree();
|
|
372
|
+
//console.log("other", node);
|
|
373
|
+
actions.addNodeTree(node, parent);
|
|
374
|
+
});
|
|
375
|
+
} else if (tag) {
|
|
343
376
|
const node = query.parseReactElement(tag).toNodeTree();
|
|
344
377
|
//console.log("other", node);
|
|
345
378
|
actions.addNodeTree(node, parent);
|
|
@@ -363,7 +396,7 @@ export /**
|
|
|
363
396
|
* @subcategory components
|
|
364
397
|
* @namespace
|
|
365
398
|
*/
|
|
366
|
-
const craftToSaltcorn = (nodes, startFrom = "ROOT") => {
|
|
399
|
+
const craftToSaltcorn = (nodes, startFrom = "ROOT", options) => {
|
|
367
400
|
//console.log(JSON.stringify(nodes, null, 2));
|
|
368
401
|
var columns = [];
|
|
369
402
|
/**
|
|
@@ -415,10 +448,33 @@ const craftToSaltcorn = (nodes, startFrom = "ROOT") => {
|
|
|
415
448
|
related.fields.forEach((f) => {
|
|
416
449
|
c[f.column_name || f.name || f] = node.props[f.name || f];
|
|
417
450
|
});
|
|
451
|
+
if (s.isFormula) c.isFormula = s.isFormula;
|
|
418
452
|
columns.push(c);
|
|
419
453
|
}
|
|
420
454
|
return s;
|
|
421
455
|
}
|
|
456
|
+
if (node.displayName === ListColumns.craft.displayName) {
|
|
457
|
+
return {
|
|
458
|
+
besides: node.nodes.map((nm) => go(nodes[nm])),
|
|
459
|
+
list_columns: true,
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
if (node.displayName === ListColumn.craft.displayName) {
|
|
463
|
+
const contents = go(nodes[node.linkedNodes.listcol]);
|
|
464
|
+
const addFields = options.additionalColumnFields;
|
|
465
|
+
const lc = {
|
|
466
|
+
contents,
|
|
467
|
+
col_width: node.props.col_width,
|
|
468
|
+
col_width_units: node.props.col_width_units,
|
|
469
|
+
alignment: node.props.alignment,
|
|
470
|
+
header_label: node.props.header_label,
|
|
471
|
+
showif: node.props.showif,
|
|
472
|
+
};
|
|
473
|
+
(addFields || []).forEach((f) => {
|
|
474
|
+
lc[f.name] = node.props[f.name];
|
|
475
|
+
});
|
|
476
|
+
return lc;
|
|
477
|
+
}
|
|
422
478
|
if (node.isCanvas) {
|
|
423
479
|
if (node.displayName === Container.craft.displayName)
|
|
424
480
|
return {
|
|
@@ -458,6 +514,7 @@ const craftToSaltcorn = (nodes, startFrom = "ROOT") => {
|
|
|
458
514
|
gradStartColor: node.props.gradStartColor,
|
|
459
515
|
gradEndColor: node.props.gradEndColor,
|
|
460
516
|
gradDirection: node.props.gradDirection,
|
|
517
|
+
click_action: node.props.click_action,
|
|
461
518
|
rotate: node.props.rotate,
|
|
462
519
|
style: node.props.style,
|
|
463
520
|
};
|
|
@@ -535,6 +592,7 @@ const craftToSaltcorn = (nodes, startFrom = "ROOT") => {
|
|
|
535
592
|
field: node.props.field,
|
|
536
593
|
independent: node.props.independent,
|
|
537
594
|
startClosed: node.props.startClosed,
|
|
595
|
+
acc_init_opens: node.props.acc_init_opens,
|
|
538
596
|
deeplink: node.props.deeplink,
|
|
539
597
|
disable_inactive: node.props.disable_inactive,
|
|
540
598
|
serverRendered: node.props.serverRendered,
|
|
@@ -575,6 +633,7 @@ const craftToSaltcorn = (nodes, startFrom = "ROOT") => {
|
|
|
575
633
|
action_textcol: node.props.action_textcol,
|
|
576
634
|
minRole: node.props.minRole,
|
|
577
635
|
confirm: node.props.confirm,
|
|
636
|
+
spinner: node.props.spinner,
|
|
578
637
|
nsteps: node.props.nsteps,
|
|
579
638
|
step_only_ifs: node.props.step_only_ifs,
|
|
580
639
|
step_action_names: node.props.step_action_names,
|
|
@@ -587,6 +646,7 @@ const craftToSaltcorn = (nodes, startFrom = "ROOT") => {
|
|
|
587
646
|
block: node.props.block,
|
|
588
647
|
configuration: node.props.configuration,
|
|
589
648
|
confirm: node.props.confirm,
|
|
649
|
+
spinner: node.props.spinner,
|
|
590
650
|
action_name: node.props.name,
|
|
591
651
|
...(node.props.name !== "Clear" && node.props.action_row_variable
|
|
592
652
|
? {
|