@saltcorn/builder 0.9.4-beta.1 → 0.9.4-beta.10

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.
@@ -1,33 +1,49 @@
1
1
  import React from "react";
2
2
  import { removeWhitespaces } from "./utils";
3
+ import { parseLegacyRelation, RelationType } from "@saltcorn/common-code";
3
4
 
4
- const buildBadgeCfgs = (parsed, parentTbl) => {
5
- const result = [];
6
- let currentCfg = null;
7
- for (const { type, table, key } of parsed) {
8
- if (type === "Inbound") {
9
- if (currentCfg) result.push(currentCfg);
10
- currentCfg = { up: key, table };
11
- } else {
12
- if (!currentCfg && key) result.push({ down: key, table: parentTbl });
13
- else if (currentCfg) {
14
- currentCfg.down = key;
15
- result.push(currentCfg);
5
+ const buildBadgeCfgs = (sourceTblName, type, path, caches) => {
6
+ if (type === RelationType.OWN)
7
+ return [{ table: `${sourceTblName} (same table)` }];
8
+ else if (type === RelationType.INDEPENDENT)
9
+ return [{ table: "None (no relation)" }];
10
+ else if (path.length === 0) return [{ table: "invalid relation" }];
11
+ else {
12
+ const result = [];
13
+ let currentCfg = null;
14
+ let currentTbl = sourceTblName;
15
+ for (const pathElement of path) {
16
+ if (pathElement.inboundKey) {
17
+ if (currentCfg) result.push(currentCfg);
18
+ currentTbl = pathElement.table;
19
+ currentCfg = { up: pathElement.inboundKey, table: currentTbl };
20
+ } else if (pathElement.fkey) {
21
+ if (!currentCfg)
22
+ result.push({ down: pathElement.fkey, table: currentTbl });
23
+ else {
24
+ currentCfg.down = pathElement.fkey;
25
+ result.push(currentCfg);
26
+ }
27
+ const tblObj = caches.tableNameCache[currentTbl];
28
+ const fkey = tblObj.foreign_keys.find(
29
+ (key) => key.name === pathElement.fkey
30
+ );
31
+ currentTbl = fkey.reftable_name;
32
+ currentCfg = { table: currentTbl };
16
33
  }
17
- currentCfg = { table };
18
34
  }
19
- }
20
- if (
21
- currentCfg &&
22
- !result.find(
23
- ({ down, table, up }) =>
24
- down === currentCfg.down &&
25
- table === currentCfg.table &&
26
- up === currentCfg.up
35
+ if (
36
+ currentCfg &&
37
+ !result.find(
38
+ ({ down, table, up }) =>
39
+ down === currentCfg.down &&
40
+ table === currentCfg.table &&
41
+ up === currentCfg.up
42
+ )
27
43
  )
28
- )
29
- result.push(currentCfg);
30
- return result;
44
+ result.push(currentCfg);
45
+ return result;
46
+ }
31
47
  };
32
48
 
33
49
  const buildBadge = ({ up, table, down }, index) => {
@@ -59,41 +75,34 @@ const buildBadge = ({ up, table, down }, index) => {
59
75
  );
60
76
  };
61
77
 
62
- export const RelationBadges = ({
63
- view,
64
- relation,
65
- parentTbl,
66
- tableNameCache,
67
- }) => {
78
+ export const RelationBadges = ({ view, relation, parentTbl, caches }) => {
68
79
  if (relation) {
69
- const parsed = relationHelpers.parseRelationPath(relation, tableNameCache);
70
-
71
80
  return (
72
81
  <div className="overflow-scroll">
73
- {parsed.length > 0
74
- ? buildBadgeCfgs(parsed, parentTbl).map(buildBadge)
75
- : buildBadge({ table: "invalid relation" }, 0)}
82
+ {buildBadgeCfgs(
83
+ relation.sourceTblName,
84
+ relation.type,
85
+ relation.path,
86
+ caches
87
+ ).map(buildBadge)}
76
88
  </div>
77
89
  );
78
90
  } else {
79
91
  if (!view) return buildBadge({ table: "invalid relation" }, 0);
80
92
  const [prefix, rest] = view.split(":");
81
- const parsed = relationHelpers.parseLegacyRelation(prefix, rest, parentTbl);
82
- if (parsed.length === 0)
83
- return buildBadge({ table: "invalid relation" }, 0);
84
- else if (
85
- parsed.length === 1 &&
86
- (parsed[0].type === "Independent" || parsed[0].type === "Own")
87
- )
93
+ if (!rest) return buildBadge({ table: "invalid relation" }, 0);
94
+ const { type, path } = parseLegacyRelation(prefix, rest, parentTbl);
95
+ if (path.length === 0) return buildBadge({ table: "invalid relation" }, 0);
96
+ else if (path.length === 1 && (type === "Independent" || type === "Own"))
88
97
  return (
89
98
  <div className="overflow-scroll">
90
- {buildBadge({ table: parsed[0].table }, 0)}
99
+ {buildBadge({ table: path[0].table }, 0)}
91
100
  </div>
92
101
  );
93
102
  else
94
103
  return (
95
104
  <div className="overflow-scroll">
96
- {buildBadgeCfgs(parsed, parentTbl).map(buildBadge)}
105
+ {buildBadgeCfgs(parentTbl, type, path, caches).map(buildBadge)}
97
106
  </div>
98
107
  );
99
108
  }
@@ -8,7 +8,7 @@ import React, { Fragment, useState, useContext, useEffect } from "react";
8
8
  import { ntimes } from "./Columns";
9
9
  import { Column } from "./Column";
10
10
  import optionsCtx from "../context";
11
- import { setAPropGen, buildOptions } from "./utils";
11
+ import { setAPropGen, buildOptions, ConfigField } from "./utils";
12
12
 
13
13
  import { Element, useNode } from "@craftjs/core";
14
14
 
@@ -31,14 +31,16 @@ const Tabs = ({
31
31
  independent,
32
32
  startClosed,
33
33
  field,
34
+ setting_tab_n,
34
35
  }) => {
35
36
  const {
36
37
  selected,
37
38
  connectors: { connect, drag },
39
+ actions: { setProp },
38
40
  } = useNode((node) => ({ selected: node.events.selected }));
39
- const [showTab, setShowTab] = useState(
40
- tabsStyle === "Accordion" && startClosed ? false : 0
41
- );
41
+
42
+ const showTab = setting_tab_n;
43
+ const setShowTab = (n) => setProp((prop) => (prop.setting_tab_n = n));
42
44
  const [showTabs, setShowTabs] = useState(
43
45
  tabsStyle === "Accordion" && startClosed ? [] : [true]
44
46
  );
@@ -178,8 +180,10 @@ const TabsSettings = () => {
178
180
  deeplink: node.data.props.deeplink,
179
181
  disable_inactive: node.data.props.disable_inactive,
180
182
  serverRendered: node.data.props.serverRendered,
183
+ setting_tab_n: node.data.props.setting_tab_n,
181
184
  tabId: node.data.props.tabId,
182
185
  titles: node.data.props.titles,
186
+ showif: node.data.props.showif,
183
187
  field: node.data.props.field,
184
188
  }));
185
189
  const {
@@ -194,7 +198,10 @@ const TabsSettings = () => {
194
198
  field,
195
199
  serverRendered,
196
200
  tabId,
201
+ showif,
202
+ setting_tab_n,
197
203
  } = node;
204
+ const use_setting_tab_n = setting_tab_n || 0;
198
205
  const options = useContext(optionsCtx);
199
206
  useEffect(() => {
200
207
  if (field)
@@ -263,42 +270,6 @@ const TabsSettings = () => {
263
270
  </Fragment>
264
271
  ) : (
265
272
  <Fragment>
266
- <tr>
267
- <th>
268
- <label>Number of sections</label>
269
- </th>
270
- <td>
271
- <input
272
- type="number"
273
- className="form-control"
274
- value={ntabs}
275
- step="1"
276
- min="0"
277
- max="20"
278
- onChange={setAProp("ntabs")}
279
- />
280
- </td>
281
- </tr>
282
- <tr>
283
- <th colSpan="2">Titles</th>
284
- </tr>
285
- {ntimes(ntabs, (ix) => (
286
- <tr key={ix}>
287
- <th>{ix + 1}</th>
288
- <td>
289
- <input
290
- type="text"
291
- className="form-control text-to-display"
292
- value={titles[ix]}
293
- onChange={(e) => {
294
- if (!e.target) return;
295
- const value = e.target.value;
296
- setProp((prop) => (prop.titles[ix] = value));
297
- }}
298
- />
299
- </td>
300
- </tr>
301
- ))}
302
273
  {tabsStyle === "Accordion" ? (
303
274
  <tr>
304
275
  <td colSpan="2">
@@ -401,6 +372,84 @@ const TabsSettings = () => {
401
372
  </td>
402
373
  </tr>
403
374
  ) : null}
375
+ <tr>
376
+ <th>
377
+ <label>Number of sections</label>
378
+ </th>
379
+ <td>
380
+ <input
381
+ type="number"
382
+ className="form-control"
383
+ value={ntabs}
384
+ step="1"
385
+ min="1"
386
+ max="20"
387
+ onChange={setAProp("ntabs")}
388
+ />
389
+ </td>
390
+ </tr>
391
+ <tr>
392
+ <td colSpan={2}>
393
+ <ConfigField
394
+ field={{
395
+ name: "setting_tab_n",
396
+ label: "Tab number",
397
+ type: "btn_select",
398
+ options: ntimes(ntabs, (i) => ({
399
+ value: i,
400
+ title: `${i + 1}`,
401
+ label: `${i + 1}`,
402
+ })),
403
+ }}
404
+ node={node}
405
+ setProp={setProp}
406
+ props={node}
407
+ ></ConfigField>
408
+ </td>
409
+ </tr>
410
+ <tr>
411
+ <th colSpan="2">Title</th>
412
+ </tr>
413
+ <tr>
414
+ <td colSpan={2}>
415
+ <input
416
+ type="text"
417
+ className="form-control text-to-display"
418
+ value={titles[use_setting_tab_n] || ""}
419
+ onChange={(e) => {
420
+ if (!e.target) return;
421
+ const value = e.target.value;
422
+ setProp((prop) => (prop.titles[use_setting_tab_n] = value));
423
+ }}
424
+ />
425
+ </td>
426
+ </tr>
427
+ {options.mode === "show" ||
428
+ options.mode === "edit" ||
429
+ options.mode === "filter" ? (
430
+ <Fragment>
431
+ <tr>
432
+ <th colSpan="2">Show if formula</th>
433
+ </tr>
434
+ <tr>
435
+ <td colSpan={2}>
436
+ <input
437
+ type="text"
438
+ className="form-control text-to-display"
439
+ value={showif?.[use_setting_tab_n] || ""}
440
+ onChange={(e) => {
441
+ if (!e.target) return;
442
+ const value = e.target.value;
443
+ setProp((prop) => {
444
+ if (!prop.showif) prop.showif = [];
445
+ prop.showif[use_setting_tab_n] = value;
446
+ });
447
+ }}
448
+ />
449
+ </td>
450
+ </tr>
451
+ </Fragment>
452
+ ) : null}
404
453
  </Fragment>
405
454
  )}
406
455
  </tbody>
@@ -414,6 +463,7 @@ const TabsSettings = () => {
414
463
  Tabs.craft = {
415
464
  props: {
416
465
  titles: ["Tab1", "Tab2"],
466
+ showif: [],
417
467
  ntabs: 2,
418
468
  tabsStyle: "Tabs",
419
469
  independent: false,
@@ -421,8 +471,10 @@ Tabs.craft = {
421
471
  deeplink: true,
422
472
  disable_inactive: false,
423
473
  serverRendered: false,
474
+ setting_tab_n: 0,
424
475
  tabId: "",
425
476
  },
477
+ defaultProps: { setting_tab_n: 0, ntabs: 2 },
426
478
  displayName: "Tabs",
427
479
  related: {
428
480
  settings: TabsSettings,
@@ -17,13 +17,18 @@ import {
17
17
  buildOptions,
18
18
  HelpTopicLink,
19
19
  initialRelation,
20
- prepCacheAndFinder,
21
- updateRelationsCache,
20
+ buildLayers,
22
21
  } from "./utils";
23
22
 
24
23
  import { RelationBadges } from "./RelationBadges";
25
24
  import { RelationOnDemandPicker } from "./RelationOnDemandPicker";
26
25
 
26
+ import {
27
+ RelationsFinder,
28
+ Relation,
29
+ buildTableCaches,
30
+ } from "@saltcorn/common-code";
31
+
27
32
  export /**
28
33
  * @param {object} props
29
34
  * @param {*} props.name
@@ -48,7 +53,6 @@ const View = ({ name, view, configuration, state }) => {
48
53
  if (rest.startsWith(".")) viewname = prefix;
49
54
  else viewname = rest;
50
55
  }
51
-
52
56
  const theview = options.views.find((v) => v.name === viewname);
53
57
  const label = theview ? theview.label : view;
54
58
  const { previews, setPreviews } = React.useContext(previewCtx);
@@ -109,10 +113,23 @@ const ViewSettings = () => {
109
113
  extra_state_fml,
110
114
  } = node;
111
115
  const options = React.useContext(optionsCtx);
112
- const { caches, finder } = useMemo(
113
- () => prepCacheAndFinder(options),
114
- [undefined]
115
- );
116
+ const {
117
+ tables,
118
+ views,
119
+ max_relations_layer_depth,
120
+ tableName,
121
+ excluded_subview_templates,
122
+ } = options;
123
+ // not needed in page editor
124
+ let finder = null;
125
+ let tableCaches = null;
126
+ if (tables && views) {
127
+ finder = useMemo(
128
+ () => new RelationsFinder(tables, views, max_relations_layer_depth),
129
+ [undefined]
130
+ );
131
+ tableCaches = useMemo(() => buildTableCaches(tables), [undefined]);
132
+ }
116
133
  const fixed_state_fields =
117
134
  options.fixed_state_fields && options.fixed_state_fields[view];
118
135
  const { setPreviews } = React.useContext(previewCtx);
@@ -135,27 +152,48 @@ const ViewSettings = () => {
135
152
  else viewname = rest;
136
153
  }
137
154
  if (viewname.includes(".")) viewname = viewname.split(".")[0];
138
- if (finder)
139
- updateRelationsCache(
140
- relationsCache,
141
- setRelationsCache,
142
- options,
143
- finder,
144
- viewname
155
+
156
+ if (
157
+ finder &&
158
+ !(relationsCache[tableName] && relationsCache[tableName][viewname])
159
+ ) {
160
+ const relations = finder.findRelations(
161
+ tableName,
162
+ viewname,
163
+ excluded_subview_templates
145
164
  );
146
- const [relations, setRelations] = finder
147
- ? React.useState(relationsCache[options.tableName][viewname])
165
+ const layers = buildLayers(
166
+ relations,
167
+ tableName,
168
+ tableCaches.tableNameCache
169
+ );
170
+ relationsCache[tableName] = relationsCache[tableName] || {};
171
+ relationsCache[tableName][viewname] = { relations, layers };
172
+ setRelationsCache({ ...relationsCache });
173
+ }
174
+ const [relationsData, setRelationsData] = finder
175
+ ? React.useState(relationsCache[tableName][viewname])
148
176
  : [undefined, undefined];
149
- let safeRelation = relation;
177
+ let safeRelation = null;
178
+ const subView = views.find((view) => view.name === viewname);
179
+ if (relation) {
180
+ const subTbl = tables.find((tbl) => tbl.id === subView.table_id);
181
+ safeRelation = new Relation(
182
+ relation,
183
+ subTbl ? subTbl.name : "",
184
+ subView.display_type
185
+ );
186
+ }
150
187
  if (
151
188
  options.mode !== "filter" &&
189
+ subView.table_id &&
152
190
  !safeRelation &&
153
191
  !hasLegacyRelation &&
154
- relations?.paths.length > 0
192
+ relationsData?.relations.length > 0
155
193
  ) {
156
- safeRelation = initialRelation(relations.paths, options.tableName);
194
+ safeRelation = initialRelation(relationsData.relations);
157
195
  setProp((prop) => {
158
- prop.relation = safeRelation;
196
+ prop.relation = safeRelation.relationString;
159
197
  });
160
198
  }
161
199
  const helpContext = { view_name: viewname };
@@ -169,24 +207,32 @@ const ViewSettings = () => {
169
207
  prop.view = target_value;
170
208
  });
171
209
  } else {
172
- updateRelationsCache(
173
- relationsCache,
174
- setRelationsCache,
175
- options,
176
- finder,
177
- target_value
210
+ const newRelations = finder.findRelations(
211
+ tableName,
212
+ target_value,
213
+ excluded_subview_templates
178
214
  );
179
- const newRelations = relationsCache[options.tableName][target_value];
180
- if (newRelations.paths.length > 0) {
215
+ const layers = buildLayers(
216
+ newRelations,
217
+ tableName,
218
+ tableCaches.tableNameCache
219
+ );
220
+ relationsCache[tableName] = relationsCache[tableName] || {};
221
+ relationsCache[tableName][target_value] = {
222
+ relations: newRelations,
223
+ layers,
224
+ };
225
+ if (newRelations.length > 0) {
181
226
  setProp((prop) => {
182
227
  prop.view = target_value;
183
- prop.relation = initialRelation(
184
- newRelations.paths,
185
- options.tableName
186
- );
228
+ prop.relation = initialRelation(newRelations).relationString;
229
+ });
230
+ setRelationsData({ relations: newRelations, layers });
231
+ } else
232
+ window.notifyAlert({
233
+ type: "warning",
234
+ text: `${target_value} has no relations`,
187
235
  });
188
- setRelations(newRelations);
189
- }
190
236
  }
191
237
  }
192
238
  }
@@ -194,7 +240,7 @@ const ViewSettings = () => {
194
240
 
195
241
  return (
196
242
  <div>
197
- {relations ? (
243
+ {relationsData ? (
198
244
  <Fragment>
199
245
  <div>
200
246
  <label>View to {options.mode === "show" ? "embed" : "show"}</label>
@@ -214,7 +260,7 @@ const ViewSettings = () => {
214
260
  {options.mode !== "filter" && (
215
261
  <div>
216
262
  <RelationOnDemandPicker
217
- relations={relations.layers}
263
+ relations={relationsData.layers}
218
264
  update={(relPath) => {
219
265
  if (relPath.startsWith(".")) {
220
266
  setProp((prop) => {
@@ -232,8 +278,8 @@ const ViewSettings = () => {
232
278
  <RelationBadges
233
279
  view={view}
234
280
  relation={safeRelation}
235
- parentTbl={options.tableName}
236
- tableNameCache={caches.tableNameCache}
281
+ parentTbl={tableName}
282
+ caches={tableCaches}
237
283
  />
238
284
  </div>
239
285
  )}
@@ -18,14 +18,19 @@ import {
18
18
  setAPropGen,
19
19
  FormulaTooltip,
20
20
  HelpTopicLink,
21
- prepCacheAndFinder,
22
21
  initialRelation,
23
- updateRelationsCache,
22
+ buildLayers,
24
23
  } from "./utils";
25
24
 
26
25
  import { RelationBadges } from "./RelationBadges";
27
26
  import { RelationOnDemandPicker } from "./RelationOnDemandPicker";
28
27
 
28
+ import {
29
+ RelationsFinder,
30
+ Relation,
31
+ buildTableCaches,
32
+ } from "@saltcorn/common-code";
33
+
29
34
  export /**
30
35
  * @param {object} props
31
36
  * @param {string} props.name
@@ -127,10 +132,18 @@ const ViewLinkSettings = () => {
127
132
  link_target_blank,
128
133
  } = node;
129
134
  const options = React.useContext(optionsCtx);
130
- const { caches, finder } = useMemo(
131
- () => prepCacheAndFinder(options),
135
+ const {
136
+ tables,
137
+ views,
138
+ tableName,
139
+ excluded_subview_templates,
140
+ max_relations_layer_depth,
141
+ } = options;
142
+ const finder = useMemo(
143
+ () => new RelationsFinder(tables, views, max_relations_layer_depth),
132
144
  [undefined]
133
145
  );
146
+ const tableCaches = useMemo(() => buildTableCaches(tables), [undefined]);
134
147
  const { relationsCache, setRelationsCache } = React.useContext(relationsCtx);
135
148
  let errorString = false;
136
149
  try {
@@ -147,50 +160,82 @@ const ViewLinkSettings = () => {
147
160
  const safeViewName = use_view_name?.includes(".")
148
161
  ? use_view_name.split(".")[0]
149
162
  : use_view_name;
150
- updateRelationsCache(
151
- relationsCache,
152
- setRelationsCache,
153
- options,
154
- finder,
155
- safeViewName
156
- );
157
- const [relations, setRelations] = React.useState(
163
+ const subView = views.find((view) => view.name === safeViewName);
164
+ const hasTableId = subView?.table_id !== undefined;
165
+ if (!(relationsCache[tableName] && relationsCache[tableName][safeViewName])) {
166
+ const relations = finder.findRelations(
167
+ tableName,
168
+ safeViewName,
169
+ excluded_subview_templates
170
+ );
171
+ const layers = buildLayers(
172
+ relations,
173
+ tableName,
174
+ tableCaches.tableNameCache
175
+ );
176
+ relationsCache[tableName] = relationsCache[tableName] || {};
177
+ relationsCache[tableName][safeViewName] = { relations, layers };
178
+ setRelationsCache({ ...relationsCache });
179
+ }
180
+ const [relationsData, setRelationsData] = React.useState(
158
181
  relationsCache[options.tableName][safeViewName]
159
182
  );
160
- let safeRelation = relation;
161
- if (!safeRelation && !hasLegacyRelation && relations?.paths.length > 0) {
162
- safeRelation = initialRelation(relations.paths, options.tableName);
183
+ let safeRelation = null;
184
+ if (relation) {
185
+ const subView = views.find((view) => view.name === safeViewName);
186
+ const subTbl = tables.find((tbl) => tbl.id === subView.table_id);
187
+ safeRelation = new Relation(
188
+ relation,
189
+ subTbl ? subTbl.name : "",
190
+ subView.display_type
191
+ );
192
+ }
193
+ if (
194
+ !safeRelation &&
195
+ !hasLegacyRelation &&
196
+ relationsData?.relations.length > 0
197
+ ) {
198
+ safeRelation = initialRelation(relationsData.relations);
163
199
  setProp((prop) => {
164
- prop.relation = safeRelation;
200
+ prop.relation = safeRelation.relationString;
165
201
  });
166
202
  }
167
203
  const set_view_name = (e) => {
168
204
  if (e.target) {
169
205
  const target_value = e.target.value;
170
206
  if (target_value !== use_view_name) {
171
- updateRelationsCache(
172
- relationsCache,
173
- setRelationsCache,
174
- options,
175
- finder,
176
- target_value
207
+ const newRelations = finder.findRelations(
208
+ tableName,
209
+ target_value,
210
+ excluded_subview_templates
211
+ );
212
+ const layers = buildLayers(
213
+ newRelations,
214
+ tableName,
215
+ tableCaches.tableNameCache
177
216
  );
178
- const newRelations = relationsCache[options.tableName][target_value];
179
- if (newRelations.paths.length > 0) {
217
+
218
+ relationsCache[tableName] = relationsCache[tableName] || {};
219
+ relationsCache[tableName][target_value] = {
220
+ relations: newRelations,
221
+ layers,
222
+ };
223
+ if (newRelations.length > 0) {
180
224
  setProp((prop) => {
181
225
  prop.name = target_value;
182
- prop.relation = initialRelation(
183
- newRelations.paths,
184
- options.tableName
185
- );
226
+ prop.relation = initialRelation(newRelations).relationString;
227
+ });
228
+ setRelationsData({ relations: newRelations, layers });
229
+ } else
230
+ window.notifyAlert({
231
+ type: "warning",
232
+ text: `${target_value} has no relations`,
186
233
  });
187
- setRelations(newRelations);
188
- }
189
234
  }
190
235
  }
191
236
  };
192
237
  const helpContext = { view_name: use_view_name };
193
- if (options.tableName) helpContext.srcTable = options.tableName;
238
+ if (tableName) helpContext.srcTable = tableName;
194
239
  return (
195
240
  <div>
196
241
  <table className="w-100">
@@ -215,7 +260,7 @@ const ViewLinkSettings = () => {
215
260
  <tr>
216
261
  <td colSpan="2">
217
262
  <RelationOnDemandPicker
218
- relations={relations.layers}
263
+ relations={relationsData.layers}
219
264
  update={(relPath) => {
220
265
  if (relPath.startsWith(".")) {
221
266
  setProp((prop) => {
@@ -233,8 +278,8 @@ const ViewLinkSettings = () => {
233
278
  <RelationBadges
234
279
  view={name}
235
280
  relation={safeRelation}
236
- parentTbl={options.tableName}
237
- tableNameCache={caches.tableNameCache}
281
+ parentTbl={tableName}
282
+ caches={tableCaches}
238
283
  />
239
284
  </td>
240
285
  </tr>