@saltcorn/data 1.5.0 → 1.5.2

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.
Files changed (44) hide show
  1. package/dist/migrations/202603101553.d.ts +4 -0
  2. package/dist/migrations/202603101553.d.ts.map +1 -0
  3. package/dist/migrations/202603101553.js +22 -0
  4. package/dist/migrations/202603101553.js.map +1 -0
  5. package/dist/mobile-mocks/node/assert.d.ts +1 -0
  6. package/dist/mobile-mocks/node/assert.d.ts.map +1 -0
  7. package/dist/mobile-mocks/node/assert.js +2 -0
  8. package/dist/mobile-mocks/node/assert.js.map +1 -0
  9. package/dist/mobile-mocks/npm/apns2.d.ts +1 -0
  10. package/dist/mobile-mocks/npm/apns2.d.ts.map +1 -0
  11. package/dist/mobile-mocks/npm/apns2.js +2 -0
  12. package/dist/mobile-mocks/npm/apns2.js.map +1 -0
  13. package/dist/mobile-mocks/npm/vm2.d.ts +1 -0
  14. package/dist/mobile-mocks/npm/vm2.d.ts.map +1 -0
  15. package/dist/mobile-mocks/npm/vm2.js +2 -0
  16. package/dist/mobile-mocks/npm/vm2.js.map +1 -0
  17. package/dist/mobile-mocks/npm/xml2js.d.ts +1 -0
  18. package/dist/mobile-mocks/npm/xml2js.d.ts.map +1 -0
  19. package/dist/mobile-mocks/npm/xml2js.js +2 -0
  20. package/dist/mobile-mocks/npm/xml2js.js.map +1 -0
  21. package/dist/models/expression.d.ts.map +1 -1
  22. package/dist/models/expression.js +1 -1
  23. package/dist/models/expression.js.map +1 -1
  24. package/dist/viewable_fields.d.ts +151 -96
  25. package/dist/viewable_fields.d.ts.map +1 -1
  26. package/dist/viewable_fields.js +465 -99
  27. package/dist/viewable_fields.js.map +1 -1
  28. package/package.json +8 -8
  29. package/dist/models/s3_helpers.d.ts +0 -54
  30. package/dist/models/s3_helpers.d.ts.map +0 -1
  31. package/dist/models/s3_helpers.js +0 -505
  32. package/dist/models/s3_helpers.js.map +0 -1
  33. package/dist/test-utils/mocks.d.ts +0 -203
  34. package/dist/test-utils/mocks.d.ts.map +0 -1
  35. package/dist/test-utils/mocks.js +0 -329
  36. package/dist/test-utils/mocks.js.map +0 -1
  37. package/dist/tests/mail_queue.test.d.ts +0 -2
  38. package/dist/tests/mail_queue.test.d.ts.map +0 -1
  39. package/dist/tests/mail_queue.test.js +0 -122
  40. package/dist/tests/mail_queue.test.js.map +0 -1
  41. package/dist/tests/table_sync_info.test.d.ts +0 -2
  42. package/dist/tests/table_sync_info.test.d.ts.map +0 -1
  43. package/dist/tests/table_sync_info.test.js +0 -62
  44. package/dist/tests/table_sync_info.test.js.map +0 -1
@@ -1,21 +1,27 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.updateViewSelect = exports.transformForm = exports.setDateLocales = exports.standardLayoutRowVisitor = exports.standardBlockDispatch = exports.edit_build_in_actions = exports.make_link = exports.get_view_link_query = exports.fill_presets = exports.getForm = exports.splitUniques = exports.parse_view_select = exports.view_linker = exports.action_link = exports.objToQueryString = exports.action_url = exports.get_viewable_fields_from_layout = exports.get_viewable_fields = void 0;
2
7
  /**
3
8
  * @category saltcorn-data
4
9
  * @module base-plugin/viewtemplates/viewable_fields
5
10
  * @subcategory base-plugin
6
11
  */
12
+ const table_1 = __importDefault(require("./models/table"));
13
+ const field_1 = __importDefault(require("./models/field"));
14
+ const view_1 = __importDefault(require("./models/view"));
7
15
  const { post_btn } = require("@saltcorn/markup");
8
16
  const { text, a, i, div, button, span, script, domReady, input, } = require("@saltcorn/markup/tags");
9
17
  const { getState, getReq__ } = require("./db/state");
10
- const { link_view, displayType, run_action_column, } = require("./plugin-helper");
18
+ const plugin_helper_1 = require("./plugin-helper");
11
19
  const { eval_expression, freeVariables, get_expression_function, } = require("./models/expression");
12
- const Field = require("./models/field");
20
+ const FieldRepeat = require("./models/fieldrepeat");
13
21
  const Form = require("./models/form");
14
- const { traverseSync } = require("./models/layout");
15
- const { structuredClone, isWeb, isOfflineMode, getSessionId, interpolate, objectToQueryString, validSqlId, } = require("./utils");
22
+ const { traverseSync, traverse, translateLayout } = require("./models/layout");
23
+ const { structuredClone, isWeb, isOfflineMode, getSessionId, interpolate, objectToQueryString, validSqlId, InvalidConfiguration, renderServerSide, } = require("./utils");
16
24
  const db = require("./db");
17
- const View = require("./models/view");
18
- const Table = require("./models/table");
19
25
  const { isNode, dollarizeObject, getSafeBaseUrl } = require("./utils");
20
26
  const { bool, date } = require("./base-plugin/types");
21
27
  const _ = require("underscore");
@@ -63,6 +69,7 @@ const action_url = (viewname, table, action_name, r, colId, colIdNm, confirm, co
63
69
  javascript: `${confirmStr}view_post('${viewname}', 'run_action', {${colIdNm}:'${colId}'${r ? `, ${pk_name}:'${r?.[pk_name]}'` : ""}${columnIndex(colIndex)}}${runAsync ? `,{runAsync:true}` : ""});`,
64
70
  };
65
71
  };
72
+ exports.action_url = action_url;
66
73
  /**
67
74
  * @param {string} url
68
75
  * @param {object} req
@@ -80,15 +87,15 @@ const action_url = (viewname, table, action_name, r, colId, colIdNm, confirm, co
80
87
  * @param {*} __
81
88
  * @returns {object}
82
89
  */
83
- const action_link = (url, req, { action_name, action_label, confirm, rndid, action_style, action_size, action_icon, action_bgcol, action_title, action_class, action_bordercol, action_textcol, spinner, block, }, __ = (s) => s) => {
84
- const label = action_label === " " ? "" : __(action_label) || action_name;
90
+ const action_link = (url, req, { action_name, action_label, confirm, rndid, action_style, action_size, action_icon, action_bgcol, action_title, action_class, action_bordercol, action_textcol, spinner, block, }, __ = (s) => s, in_row_click) => {
91
+ const label = action_label === " " ? "" : __(action_label || "") || action_name;
85
92
  let style = action_style === "btn-custom-color"
86
93
  ? `background-color: ${action_bgcol || "#000000"};border-color: ${action_bordercol || "#000000"}; color: ${action_textcol || "#000000"}`
87
94
  : null;
88
- if (url.javascript)
95
+ if (typeof url !== "string" && url.javascript)
89
96
  return a({
90
97
  href: "javascript:void(0)",
91
- onclick: `${spinner ? "spin_action_link(this);" : ""}${url.javascript}`,
98
+ onclick: `${spinner ? "spin_action_link(this);" : ""}${url.javascript}${in_row_click ? ";event.stopPropagation()" : ""}`,
92
99
  class: [
93
100
  action_style === "btn-link"
94
101
  ? ""
@@ -107,10 +114,11 @@ const action_link = (url, req, { action_name, action_label, confirm, rndid, acti
107
114
  icon: action_icon,
108
115
  style,
109
116
  spinner,
110
- btnClass: `${action_style || "btn-primary"} ${action_size || ""}`,
117
+ btnClass: `${action_style || "btn-primary"} ${action_size || ""}${action_class ? " " + action_class : ""}`,
111
118
  formClass: !block && "d-inline",
112
119
  });
113
120
  };
121
+ exports.action_link = action_link;
114
122
  const slug_transform = (row) => (step) => step.transform === "slugify"
115
123
  ? `/${db.slugify(row[step.field])}`
116
124
  : `/${row[step.field]}`;
@@ -126,6 +134,7 @@ const get_view_link_query = (fields, view) => {
126
134
  const pk_name = fields.find((f) => f.primary_key).name;
127
135
  return (r) => `?${pk_name}=${r[pk_name]}`;
128
136
  };
137
+ exports.get_view_link_query = get_view_link_query;
129
138
  /**
130
139
  * @function
131
140
  * @param {object} opts
@@ -137,7 +146,7 @@ const get_view_link_query = (fields, view) => {
137
146
  * @param {Field[]} fields
138
147
  * @returns {object}
139
148
  */
140
- const make_link = ({ link_text, link_text_formula, link_url, link_url_formula, link_target_blank, in_dropdown, in_modal, link_icon, icon, link_style, link_size, }, fields, __ = (s) => s, in_row_click) => {
149
+ const make_link = ({ link_text, link_text_formula, link_url, link_url_formula, link_target_blank, in_dropdown, in_modal, link_icon, icon, link_style, link_size, link_title, }, fields, __ = (s) => s, in_row_click) => {
141
150
  return {
142
151
  label: "",
143
152
  key: (r) => {
@@ -164,6 +173,8 @@ const make_link = ({ link_text, link_text_formula, link_url, link_url_formula, l
164
173
  attrs.class = [...(attrs.class || []), link_size];
165
174
  if (in_row_click)
166
175
  attrs.onclick = "event.stopPropagation()";
176
+ if (link_title)
177
+ attrs.title = link_title;
167
178
  if (in_modal)
168
179
  return a({
169
180
  ...attrs,
@@ -176,6 +187,7 @@ const make_link = ({ link_text, link_text_formula, link_url, link_url_formula, l
176
187
  },
177
188
  };
178
189
  };
190
+ exports.make_link = make_link;
179
191
  /**
180
192
  * @param {string} view name of the view or a legacy relation (type:telation)
181
193
  * @param {string} relation new relation path syntax
@@ -221,6 +233,7 @@ const parse_view_select = (view, relation) => {
221
233
  }
222
234
  }
223
235
  };
236
+ exports.parse_view_select = parse_view_select;
224
237
  const pathToQuery = (relation, srcTable, subTable, row) => {
225
238
  const path = relation.path;
226
239
  switch (relation.type) {
@@ -251,6 +264,7 @@ const pathToQuery = (relation, srcTable, subTable, row) => {
251
264
  : row[idName]?.id || row[idName];
252
265
  return `?${relation.relationString}=${srcId}`;
253
266
  }
267
+ return null;
254
268
  };
255
269
  //todo: use above to simplify code
256
270
  /**
@@ -297,10 +311,10 @@ in_row_click) => {
297
311
  .join("&");
298
312
  };
299
313
  if (relation) {
300
- const topview = View.findOne({ name: srcViewName });
301
- const srcTable = Table.findOne({ id: topview.table_id });
302
- const subview = View.findOne({ name: view });
303
- const subTable = Table.findOne({ id: subview.table_id });
314
+ const topview = view_1.default.findOne({ name: srcViewName });
315
+ const srcTable = table_1.default.findOne({ id: topview.table_id });
316
+ const subview = view_1.default.findOne({ name: view });
317
+ const subTable = table_1.default.findOne({ id: subview.table_id });
304
318
  const relObj = new Relation(relation, subTable ? subTable.name : "", ViewDisplayType.NO_ROW_LIMIT);
305
319
  relObj.subView = subview;
306
320
  const type = relObj.type;
@@ -319,7 +333,7 @@ in_row_click) => {
319
333
  else
320
334
  label = get_label(view, r);
321
335
  const target = `${safePrefix}/view/${encodeURIComponent(view)}${query}`;
322
- return link_view(isWeb || in_modal ? target : `javascript:execLink('${target}')`, label, in_modal && srcViewName && { reload_view: srcViewName }, link_style, link_size, link_icon || icon, textStyle, link_bgcol, link_bordercol, link_textcol, in_dropdown && "dropdown-item", get_extra_state(r), link_target_blank, label_attr, link_title, link_class, req, in_row_click);
336
+ return (0, plugin_helper_1.link_view)(isWeb || in_modal ? target : `javascript:execLink('${target}')`, label, in_modal && srcViewName && { reload_view: srcViewName }, link_style, link_size, link_icon || icon, textStyle, link_bgcol, link_bordercol, link_textcol, in_dropdown && "dropdown-item", get_extra_state(r), link_target_blank, label_attr, link_title, link_class, req, in_row_click);
323
337
  }
324
338
  },
325
339
  };
@@ -330,13 +344,13 @@ in_row_click) => {
330
344
  switch (vtype) {
331
345
  case "Own":
332
346
  const vnm = vrest;
333
- const viewrow = View.findOne({ name: vnm });
347
+ const viewrow = view_1.default.findOne({ name: vnm });
334
348
  const get_query = get_view_link_query(fields, viewrow || {});
335
349
  return {
336
350
  label: vnm,
337
351
  key: (r) => {
338
352
  const target = `${safePrefix}/view/${encodeURIComponent(vnm)}${get_query(r)}`;
339
- return link_view(isWeb || in_modal ? target : `javascript:execLink('${target}')`, get_label(vnm, r), in_modal && srcViewName && { reload_view: srcViewName }, link_style, link_size, link_icon || icon, textStyle, link_bgcol, link_bordercol, link_textcol, in_dropdown && "dropdown-item", get_extra_state(r), link_target_blank, label_attr, link_title, link_class, req, in_row_click);
353
+ return (0, plugin_helper_1.link_view)(isWeb || in_modal ? target : `javascript:execLink('${target}')`, get_label(vnm, r), in_modal && srcViewName && { reload_view: srcViewName }, link_style, link_size, link_icon || icon, textStyle, link_bgcol, link_bordercol, link_textcol, in_dropdown && "dropdown-item", get_extra_state(r), link_target_blank, label_attr, link_title, link_class, req, in_row_click);
340
354
  },
341
355
  };
342
356
  case "Independent":
@@ -345,7 +359,7 @@ in_row_click) => {
345
359
  label: ivnm,
346
360
  key: (r) => {
347
361
  const target = `${safePrefix}/view/${encodeURIComponent(ivnm)}`;
348
- return link_view(isWeb || in_modal ? target : `javascript:execLink('${target}')`, get_label(ivnm, r), in_modal && srcViewName && { reload_view: srcViewName }, link_style, link_size, link_icon || icon, textStyle, link_bgcol, link_bordercol, link_textcol, in_dropdown && "dropdown-item", get_extra_state(r), link_target_blank, label_attr, link_title, link_class, req, in_row_click);
362
+ return (0, plugin_helper_1.link_view)(isWeb || in_modal ? target : `javascript:execLink('${target}')`, get_label(ivnm, r), in_modal && srcViewName && { reload_view: srcViewName }, link_style, link_size, link_icon || icon, textStyle, link_bgcol, link_bordercol, link_textcol, in_dropdown && "dropdown-item", get_extra_state(r), link_target_blank, label_attr, link_title, link_class, req, in_row_click);
349
363
  },
350
364
  };
351
365
  case "ChildList":
@@ -356,7 +370,7 @@ in_row_click) => {
356
370
  label: viewnm,
357
371
  key: (r) => {
358
372
  const target = `${safePrefix}/view/${encodeURIComponent(viewnm)}?${varPath}=${r.id}`;
359
- return link_view(isWeb || in_modal ? target : `javascript:execLink('${target}')`, get_label(viewnm, r), in_modal && srcViewName && { reload_view: srcViewName }, link_style, link_size, link_icon || icon, textStyle, link_bgcol, link_bordercol, link_textcol, in_dropdown && "dropdown-item", get_extra_state(r), link_target_blank, label_attr, link_title, link_class, req, in_row_click);
373
+ return (0, plugin_helper_1.link_view)(isWeb || in_modal ? target : `javascript:execLink('${target}')`, get_label(viewnm, r), in_modal && srcViewName && { reload_view: srcViewName }, link_style, link_size, link_icon || icon, textStyle, link_bgcol, link_bordercol, link_textcol, in_dropdown && "dropdown-item", get_extra_state(r), link_target_blank, label_attr, link_title, link_class, req, in_row_click);
360
374
  },
361
375
  };
362
376
  case "ParentShow":
@@ -369,7 +383,7 @@ in_row_click) => {
369
383
  const summary_field = r[`summary_field_${ptbl.toLowerCase()}`];
370
384
  if (r[pfld]) {
371
385
  const target = `${safePrefix}/view/${encodeURIComponent(pviewnm)}?${reffield.refname}=${typeof r[pfld] === "object" ? r[pfld].id : r[pfld]}`;
372
- return link_view(isWeb || in_modal ? target : `javascript:execLink('${target}')`, get_label(typeof summary_field === "undefined"
386
+ return (0, plugin_helper_1.link_view)(isWeb || in_modal ? target : `javascript:execLink('${target}')`, get_label(typeof summary_field === "undefined"
373
387
  ? pviewnm
374
388
  : summary_field, r), in_modal && srcViewName && { reload_view: srcViewName }, link_style, link_size, link_icon || icon, textStyle, link_bgcol, link_bordercol, link_textcol, in_dropdown && "dropdown-item", get_extra_state(r), link_target_blank, label_attr, link_title, link_class, req, in_row_click);
375
389
  }
@@ -382,6 +396,7 @@ in_row_click) => {
382
396
  }
383
397
  }
384
398
  };
399
+ exports.view_linker = view_linker;
385
400
  /**
386
401
  * @param {string} nm
387
402
  * @returns {boolean}
@@ -407,7 +422,7 @@ const flapMapish = (xs, f) => {
407
422
  }
408
423
  return res;
409
424
  };
410
- const get_viewable_fields_from_layout = (viewname, statehash, table, fields, columns, isShow, req, __, state = {}, srcViewName, layoutCols, viewResults, in_row_click) => {
425
+ const get_viewable_fields_from_layout = (viewname, statehash, table, fields, columns, isShow, req, __, state = {}, srcViewName, layoutCols, viewResults, in_row_click, disable_join_agg_sort) => {
411
426
  const typeMap = {
412
427
  field: "Field",
413
428
  join_field: "JoinField",
@@ -422,7 +437,7 @@ const get_viewable_fields_from_layout = (viewname, statehash, table, fields, col
422
437
  };
423
438
  const toArray = (x) => !x ? [] : Array.isArray(x) ? x : x.above ? x.above : [x];
424
439
  //console.log("layout cols", layoutCols);
425
- const newCols = layoutCols.map(({ contents, ...rest }) => {
440
+ const newCols = (layoutCols || []).map(({ contents, ...rest }) => {
426
441
  if (!contents)
427
442
  contents = rest;
428
443
  if (contents.above) {
@@ -463,8 +478,9 @@ const get_viewable_fields_from_layout = (viewname, statehash, table, fields, col
463
478
  return col;
464
479
  });
465
480
  //console.log("newCols", newCols);
466
- return get_viewable_fields(viewname, statehash, table, fields, newCols, isShow, req, __, state, srcViewName, viewResults, in_row_click);
481
+ return get_viewable_fields(viewname, statehash, table, fields, newCols, isShow, req, __, state, srcViewName, viewResults, in_row_click, disable_join_agg_sort);
467
482
  };
483
+ exports.get_viewable_fields_from_layout = get_viewable_fields_from_layout;
468
484
  /**
469
485
  * @function
470
486
  * @param {string} viewname
@@ -476,7 +492,7 @@ const get_viewable_fields_from_layout = (viewname, statehash, table, fields, col
476
492
  * @param {*} __
477
493
  * @returns {object[]}
478
494
  */
479
- const get_viewable_fields = (viewname, statehash, table, fields, columns, isShow, req, __, state = {}, srcViewName, viewResults, in_row_click) => {
495
+ const get_viewable_fields = (viewname, statehash, table, fields, columns, isShow, req, __, state = {}, srcViewName, viewResults, in_row_click, disable_join_agg_sort) => {
480
496
  const dropdown_actions = [];
481
497
  const checkShowIf = (tFieldGenF) => (column, index) => {
482
498
  const tfield = tFieldGenF(column, index);
@@ -529,9 +545,9 @@ const get_viewable_fields = (viewname, statehash, table, fields, columns, isShow
529
545
  traverseSync(layout, standardLayoutRowVisitor(viewname, state, table, r, req));
530
546
  return renderLayout({
531
547
  blockDispatch: {
532
- ...standardBlockDispatch(viewname, state, table, { req }, r),
548
+ ...standardBlockDispatch(viewname, state, table, { req }, r, in_row_click),
533
549
  view(column) {
534
- return viewResults[column.view + column.relation]?.(r);
550
+ return viewResults?.[column.view + column.relation]?.(r);
535
551
  },
536
552
  },
537
553
  layout,
@@ -595,7 +611,7 @@ const get_viewable_fields = (viewname, statehash, table, fields, columns, isShow
595
611
  ? eval_expression(column.action_label, r, req.user, "Action label formula")
596
612
  : __(column.action_label) || __(column.action_name);
597
613
  const icon = column.action_icon || column.icon || undefined;
598
- if (url.javascript)
614
+ if (typeof url !== "string" && url.javascript)
599
615
  return a({
600
616
  href: "javascript:void(0)",
601
617
  class: [
@@ -638,7 +654,7 @@ const get_viewable_fields = (viewname, statehash, table, fields, columns, isShow
638
654
  else if (column.type === "View") {
639
655
  return {
640
656
  label: column.header_label ? __(column.header_label) : "",
641
- key: (r) => viewResults[column.view + column.relation]?.(r),
657
+ key: (r) => viewResults?.[column.view + column.relation]?.(r),
642
658
  };
643
659
  }
644
660
  else if (column.type === "ViewLink") {
@@ -710,7 +726,8 @@ const get_viewable_fields = (viewname, statehash, table, fields, columns, isShow
710
726
  else {
711
727
  if (field && field.type === "File")
712
728
  column.field_type = "File";
713
- else if (field?.type.name && field?.type?.fieldviews[fieldview]) {
729
+ else if (field?.type?.name &&
730
+ field?.type?.fieldviews?.[fieldview]) {
714
731
  column.field_type = field.type.name;
715
732
  type = getState().types[column.field_type];
716
733
  }
@@ -725,7 +742,7 @@ const get_viewable_fields = (viewname, statehash, table, fields, columns, isShow
725
742
  let statekey;
726
743
  if (!column.join_field.includes("->") && keypath.length == 2) {
727
744
  statekey = `${refNm}.${table.getField(refNm).reftable_name}->${targetNm}`;
728
- header_filter = headerFilterForField(field, state, statekey);
745
+ header_filter = headerFilterForField(field || null, state, statekey);
729
746
  }
730
747
  let gofv = fieldview && type && type.fieldviews && type.fieldviews[fieldview]
731
748
  ? (row) => type.fieldviews[fieldview].run(row[key], req, {
@@ -752,11 +769,15 @@ const get_viewable_fields = (viewname, statehash, table, fields, columns, isShow
752
769
  statekey,
753
770
  header_filter,
754
771
  key: gofv ? gofv : (row) => text(row[key]),
755
- sortlink: sortlinkForName(key, req, viewname, statehash),
772
+ sortlink: disable_join_agg_sort
773
+ ? undefined
774
+ : sortlinkForName(key, req, viewname, statehash),
756
775
  };
757
776
  if (column.click_to_edit) {
758
777
  const reffield = fields.find((f) => f.name === refNm);
759
- const oldkey = typeof fvrun.key === "function" ? fvrun.key : (r) => r[fvrun.key];
778
+ const oldkey = typeof fvrun.key === "function"
779
+ ? fvrun.key
780
+ : (r) => r[fvrun.key];
760
781
  const newkey = (row) => div({
761
782
  "data-inline-edit-fielddata": encodeURIComponent(JSON.stringify({
762
783
  field_name: keypath[0],
@@ -813,7 +834,7 @@ const get_viewable_fields = (viewname, statehash, table, fields, columns, isShow
813
834
  showValue = (x) => type.fieldviews[column.agg_fieldview].run(x, req, column);
814
835
  }
815
836
  else if (column.agg_fieldview) {
816
- const aggField = Table.findOne(table)?.getField?.(column.agg_field);
837
+ const aggField = table_1.default.findOne(table)?.getField?.(column.agg_field);
817
838
  const outcomeType = column.stat === "Percent true" || column.stat === "Percent false"
818
839
  ? "Float"
819
840
  : column.stat === "Count" || column.stat === "CountUnique"
@@ -840,7 +861,9 @@ const get_viewable_fields = (viewname, statehash, table, fields, columns, isShow
840
861
  ? column.header_label
841
862
  : column.stat + " " + table, targetNm, req, __, statehash),
842
863
  key,
843
- sortlink: sortlinkForName(targetNm, req, viewname, statehash),
864
+ sortlink: disable_join_agg_sort
865
+ ? undefined
866
+ : sortlinkForName(targetNm, req, viewname, statehash),
844
867
  };
845
868
  }
846
869
  else if (column.type === "Field") {
@@ -852,14 +875,15 @@ const get_viewable_fields = (viewname, statehash, table, fields, columns, isShow
852
875
  const localized_fld_nm = f.attributes.localized_by[locale];
853
876
  f_with_val = fields.find((fld) => fld.name === localized_fld_nm) || f;
854
877
  }
855
- const isNum = f && f.type && f.type.name === "Integer";
878
+ const ftype = f?.type;
879
+ const isNum = f && ftype && ftype.name === "Integer";
856
880
  if (isNum && !setWidth.align)
857
881
  setWidth.align = "right";
858
882
  let fvrun;
859
- let header_filter = headerFilterForField(f, state);
883
+ let header_filter = headerFilterForField(f || null, state);
860
884
  if (column.fieldview &&
861
- f?.type?.fieldviews?.[column.fieldview]?.expandColumns) {
862
- fvrun = f.type.fieldviews[column.fieldview].expandColumns(f, {
885
+ ftype?.fieldviews?.[column.fieldview]?.expandColumns) {
886
+ fvrun = ftype.fieldviews[column.fieldview].expandColumns(f, {
863
887
  ...f.attributes,
864
888
  ...column.configuration,
865
889
  }, column);
@@ -874,12 +898,12 @@ const get_viewable_fields = (viewname, statehash, table, fields, columns, isShow
874
898
  ? (row) => row[f.name] &&
875
899
  getState().fileviews[column.fieldview].run(row[f.name], row[`${f.name}__filename`], { row, ...column, ...(column?.configuration || {}) })
876
900
  : column.fieldview &&
877
- f.type.fieldviews &&
878
- f.type.fieldviews[column.fieldview]
879
- ? (row) => f.type.fieldviews[column.fieldview].run(row[f_with_val.name], req, { row, ...f.attributes, ...column.configuration })
901
+ ftype.fieldviews &&
902
+ ftype.fieldviews[column.fieldview]
903
+ ? (row) => ftype.fieldviews[column.fieldview].run(row[f_with_val.name], req, { row, ...f.attributes, ...column.configuration })
880
904
  : isShow
881
- ? f.type.showAs
882
- ? (row) => f.type.showAs(row[f_with_val.name])
905
+ ? ftype.showAs
906
+ ? (row) => ftype.showAs(row[f_with_val.name])
883
907
  : (row) => text(row[f_with_val.name])
884
908
  : f.listKey,
885
909
  header_filter,
@@ -945,8 +969,12 @@ const get_viewable_fields = (viewname, statehash, table, fields, columns, isShow
945
969
  }
946
970
  return tfields;
947
971
  };
972
+ exports.get_viewable_fields = get_viewable_fields;
948
973
  const headerFilterForField = (f, state, path) => (id) => {
949
- if (f?.type?.name === "Date") {
974
+ const ftype = f?.type;
975
+ if (!f)
976
+ return "";
977
+ if (ftype?.name === "Date") {
950
978
  const set_initial = state[`_fromdate_${f.name}`] && state[`_todate_${f.name}`]
951
979
  ? `defaultDate: ["${state[`_fromdate_${f.name}`]}", "${state[`_todate_${f.name}`]}"],`
952
980
  : "";
@@ -963,33 +991,33 @@ const headerFilterForField = (f, state, path) => (id) => {
963
991
  script(domReady(`ensure_script_loaded("/static_assets/${db.connectObj.version_tag}/flatpickr.min.js");
964
992
  ensure_css_loaded("/static_assets/${db.connectObj.version_tag}/flatpickr.min.css");
965
993
  $('#daterangefilter${f.name}').flatpickr({mode:'range',
966
- dateFormat: "Y-m-d",${set_initial}
994
+ dateFormat: "Y-m-d",${set_initial}
967
995
  onChange: function(selectedDates, dateStr, instance) {
968
996
  set_header_filter($(instance.element));
969
997
  if(selectedDates.length==2) {
970
-
998
+
971
999
  set_state_fields({_fromdate_${f.name}: selectedDates[0].toLocaleDateString('en-CA'), _todate_${f.name}: selectedDates[1].toLocaleDateString('en-CA') }, false, ${id ? `document.getElementById('${id}')` : "this"})
972
-
973
-
974
- }
1000
+
1001
+
1002
+ }
975
1003
  },
976
1004
  });`)));
977
1005
  }
978
1006
  let fieldviewObjs;
979
1007
  /*if (f.is_fkey) {
980
- fieldviewObjs = [getState().keyFieldviews.select];
981
- } else */
1008
+ fieldviewObjs = [getState().keyFieldviews.select];
1009
+ } else */
982
1010
  let extraAttrs = {};
983
- if (f?.type?.name === "Bool") {
984
- fieldviewObjs = [f.type.fieldviews.tristate];
1011
+ if (ftype?.name === "Bool") {
1012
+ fieldviewObjs = [ftype.fieldviews.tristate];
985
1013
  extraAttrs.outline_buttons = true;
986
1014
  }
987
- else if (f?.type?.name === "String")
988
- fieldviewObjs = [f.type.fieldviews.edit];
989
- else if (f?.type?.name === "Integer" || f?.type?.name === "Float")
1015
+ else if (ftype?.name === "String")
1016
+ fieldviewObjs = [ftype.fieldviews.edit];
1017
+ else if (ftype?.name === "Integer" || ftype?.name === "Float")
990
1018
  fieldviewObjs = [
991
- f.type.fieldviews.above_input,
992
- f.type.fieldviews.below_input,
1019
+ ftype.fieldviews.above_input,
1020
+ ftype.fieldviews.below_input,
993
1021
  ];
994
1022
  if (!fieldviewObjs)
995
1023
  return "";
@@ -1023,7 +1051,7 @@ const standardLayoutRowVisitor = (viewname, state, table, row, req) => {
1023
1051
  const locale = req.getLocale();
1024
1052
  const fields = table.fields;
1025
1053
  const evalMaybeExpr = (segment, key, fmlkey) => {
1026
- if (segment.isFormula && segment.isFormula[fmlkey || key]) {
1054
+ if (segment.isFormula && segment.isFormula[fmlkey || key] && segment[key]) {
1027
1055
  segment[key] = eval_expression(segment[key], { session_id, locale, ...row }, req.user, `property ${key} in segment of type ${segment.type}`);
1028
1056
  }
1029
1057
  };
@@ -1057,8 +1085,8 @@ const standardLayoutRowVisitor = (viewname, state, table, row, req) => {
1057
1085
  }
1058
1086
  });
1059
1087
  // TODO mutation here - potential issue with renderRows
1060
- segment.titles = segment.titles.filter((v, ix) => !to_delete.has(ix));
1061
- segment.contents = segment.contents.filter((v, ix) => !to_delete.has(ix));
1088
+ segment.titles = segment.titles.filter((_v, ix) => !to_delete.has(ix));
1089
+ segment.contents = segment.contents.filter((_v, ix) => !to_delete.has(ix));
1062
1090
  (segment.titles || []).forEach((t, ix) => {
1063
1091
  if (typeof t === "string" && t.includes("{{")) {
1064
1092
  segment.titles[ix] = interpolate(t, row, req.user, "Tab titles");
@@ -1080,9 +1108,10 @@ const standardLayoutRowVisitor = (viewname, state, table, row, req) => {
1080
1108
  const field = fields.find((f) => f.name === segment.field);
1081
1109
  if (!field)
1082
1110
  return;
1083
- if (field.type.name === "String")
1111
+ const ftype = field.type;
1112
+ if (ftype?.name === "String")
1084
1113
  segment.url = row[segment.field];
1085
- if (field.type === "File") {
1114
+ if (ftype === "File") {
1086
1115
  segment.url = `/files/serve/${row[segment.field]}`;
1087
1116
  segment.fileid = row[segment.field];
1088
1117
  }
@@ -1110,7 +1139,8 @@ const standardLayoutRowVisitor = (viewname, state, table, row, req) => {
1110
1139
  },
1111
1140
  };
1112
1141
  };
1113
- const standardBlockDispatch = (viewname, state, table, extra, row) => {
1142
+ exports.standardLayoutRowVisitor = standardLayoutRowVisitor;
1143
+ const standardBlockDispatch = (viewname, state, table, extra, row, in_row_click) => {
1114
1144
  const req = extra.req;
1115
1145
  const fields = table.fields;
1116
1146
  const locale = req.getLocale();
@@ -1120,6 +1150,7 @@ const standardBlockDispatch = (viewname, state, table, extra, row) => {
1120
1150
  let field = fields.find((fld) => fld.name === field_name);
1121
1151
  if (!field)
1122
1152
  return "";
1153
+ const ftype = field.type;
1123
1154
  let val = row[field_name];
1124
1155
  let fvrun;
1125
1156
  if (field &&
@@ -1134,7 +1165,7 @@ const standardBlockDispatch = (viewname, state, table, extra, row) => {
1134
1165
  ...field.attributes,
1135
1166
  ...configuration,
1136
1167
  };
1137
- if (fieldview && field.type === "File") {
1168
+ if (fieldview && ftype === "File") {
1138
1169
  if (req.generate_email)
1139
1170
  cfg.targetPrefix = getSafeBaseUrl();
1140
1171
  fvrun = val
@@ -1142,10 +1173,10 @@ const standardBlockDispatch = (viewname, state, table, extra, row) => {
1142
1173
  : "";
1143
1174
  }
1144
1175
  else if (fieldview &&
1145
- field.type &&
1146
- field.type.fieldviews &&
1147
- field.type.fieldviews[fieldview])
1148
- fvrun = field.type.fieldviews[fieldview].run(val, req, cfg);
1176
+ ftype &&
1177
+ ftype.fieldviews &&
1178
+ ftype.fieldviews[fieldview])
1179
+ fvrun = ftype.fieldviews[fieldview].run(val, req, cfg);
1149
1180
  else
1150
1181
  fvrun = text(val);
1151
1182
  if (click_to_edit &&
@@ -1166,7 +1197,7 @@ const standardBlockDispatch = (viewname, state, table, extra, row) => {
1166
1197
  return fvrun;
1167
1198
  },
1168
1199
  join_field(jf) {
1169
- const { join_field, field_type, fieldview, configuration, target_field_attributes, click_to_edit, } = jf;
1200
+ let { join_field, field_type, fieldview, configuration, target_field_attributes, click_to_edit, } = jf;
1170
1201
  const keypath = join_field.split(".");
1171
1202
  let value;
1172
1203
  if (join_field.includes("->")) {
@@ -1185,6 +1216,11 @@ const standardBlockDispatch = (viewname, state, table, extra, row) => {
1185
1216
  : "";
1186
1217
  }
1187
1218
  let fvRes;
1219
+ if (!field_type) {
1220
+ const field = table.getField(join_field);
1221
+ if (field)
1222
+ field_type = field?.type?.name;
1223
+ }
1188
1224
  if (field_type && fieldview) {
1189
1225
  const type = getState().types[field_type];
1190
1226
  if (type && getState().types[field_type]) {
@@ -1248,12 +1284,12 @@ const standardBlockDispatch = (viewname, state, table, extra, row) => {
1248
1284
  if (stat.toLowerCase() === "array_agg" && Array.isArray(val))
1249
1285
  return val.map((v) => text(v?.toString?.())).join(", ");
1250
1286
  else if (column.agg_fieldview) {
1251
- const aggField = Table.findOne(table)?.getField?.(column.agg_field);
1287
+ const aggField = table_1.default.findOne(table)?.getField?.(column.agg_field);
1252
1288
  const outcomeType = stat === "Percent true" || stat === "Percent false"
1253
1289
  ? "Float"
1254
1290
  : stat === "Count" || stat === "CountUnique"
1255
1291
  ? "Integer"
1256
- : aggField.type?.name;
1292
+ : aggField?.type?.name;
1257
1293
  const type = getState().types[outcomeType];
1258
1294
  if (type?.fieldviews[column.agg_fieldview]) {
1259
1295
  const readval = type.read(val);
@@ -1266,7 +1302,7 @@ const standardBlockDispatch = (viewname, state, table, extra, row) => {
1266
1302
  if (segment.action_style === "on_page_load") {
1267
1303
  if (extra?.isPreview)
1268
1304
  return "";
1269
- run_action_column({
1305
+ (0, plugin_helper_1.run_action_column)({
1270
1306
  col: { ...segment },
1271
1307
  referrer: req?.get?.("Referrer"),
1272
1308
  req: req,
@@ -1283,11 +1319,11 @@ const standardBlockDispatch = (viewname, state, table, extra, row) => {
1283
1319
  }
1284
1320
  else if (segment.action_name === "Delete")
1285
1321
  url = `${table.delete_url(row, `redirect=${encodeURIComponent(interpolate(segment.configuration?.after_delete_url || "/", row, req?.user, "delete action: after delete URL"))}`)}`;
1286
- return action_link(url, req, segment);
1322
+ return action_link(url, req, segment, undefined, in_row_click);
1287
1323
  },
1288
1324
  view_link(view) {
1289
1325
  const prefix = req.generate_email && req.get_base_url ? req.get_base_url() : "";
1290
- const { key } = view_linker(view, fields, (s) => s, isWeb(req), req.user, prefix, state, req, viewname);
1326
+ const { key } = view_linker(view, fields, (s) => s, isWeb(req), req.user, prefix, state, req, viewname, undefined, in_row_click);
1291
1327
  return key(row);
1292
1328
  },
1293
1329
  tabs(segment, go) {
@@ -1311,6 +1347,7 @@ const standardBlockDispatch = (viewname, state, table, extra, row) => {
1311
1347
  },
1312
1348
  };
1313
1349
  };
1350
+ exports.standardBlockDispatch = standardBlockDispatch;
1314
1351
  /**
1315
1352
  * @param {object} column
1316
1353
  * @param {object} f
@@ -1350,12 +1387,15 @@ const splitUniques = (fields, state, fuzzyStrings) => {
1350
1387
  field.type.name === "String")
1351
1388
  uniques[k] = { ilike: v };
1352
1389
  else if (field && (field.is_unique || field.primary_key))
1353
- uniques[k] = field.type.read ? field.type.read(v, field.attributes) : v;
1390
+ uniques[k] = field.type.read
1391
+ ? field.type.read(v, field.attributes)
1392
+ : v;
1354
1393
  else
1355
1394
  nonUniques[k] = v;
1356
1395
  });
1357
1396
  return { uniques, nonUniques };
1358
1397
  };
1398
+ exports.splitUniques = splitUniques;
1359
1399
  /**
1360
1400
  * @param {object} table
1361
1401
  * @param {string} viewname
@@ -1374,7 +1414,7 @@ const getForm = async (table, viewname, columns, layout0, id, req, isRemote) =>
1374
1414
  if (column.type === "Field") {
1375
1415
  const f0 = fields.find((fld) => fld.name === column.field_name);
1376
1416
  if (f0) {
1377
- const f = new Field(f0);
1417
+ const f = new field_1.default(f0);
1378
1418
  f.fieldview = column.fieldview;
1379
1419
  if (f.type === "Key") {
1380
1420
  if (state.keyFieldviews[column.fieldview])
@@ -1404,7 +1444,7 @@ const getForm = async (table, viewname, columns, layout0, id, req, isRemote) =>
1404
1444
  return f;
1405
1445
  }
1406
1446
  else if (table.name === "users" && column.field_name === "password") {
1407
- return new Field({
1447
+ return new field_1.default({
1408
1448
  name: "password",
1409
1449
  fieldview: column.fieldview,
1410
1450
  type: "String",
@@ -1412,14 +1452,14 @@ const getForm = async (table, viewname, columns, layout0, id, req, isRemote) =>
1412
1452
  }
1413
1453
  else if (table.name === "users" &&
1414
1454
  column.field_name === "passwordRepeat") {
1415
- return new Field({
1455
+ return new field_1.default({
1416
1456
  name: "passwordRepeat",
1417
1457
  fieldview: column.fieldview,
1418
1458
  type: "String",
1419
1459
  });
1420
1460
  }
1421
1461
  else if (table.name === "users" && column.field_name === "remember") {
1422
- return new Field({
1462
+ return new field_1.default({
1423
1463
  name: "remember",
1424
1464
  fieldview: column.fieldview,
1425
1465
  type: "Bool",
@@ -1451,6 +1491,7 @@ const getForm = async (table, viewname, columns, layout0, id, req, isRemote) =>
1451
1491
  ref: ref.replace("?", ""),
1452
1492
  target,
1453
1493
  refTable: refField.reftable_name,
1494
+ refTablePK: table_1.default.findOne(refField.reftable_name).pk_name,
1454
1495
  };
1455
1496
  })
1456
1497
  .filter(Boolean);
@@ -1490,6 +1531,345 @@ const getForm = async (table, viewname, columns, layout0, id, req, isRemote) =>
1490
1531
  form.hidden(form.pk_name);
1491
1532
  return form;
1492
1533
  };
1534
+ exports.getForm = getForm;
1535
+ const transformForm = async ({ form, table, req, row, res, getRowQuery, viewname, optionsQuery, state, }) => {
1536
+ let originalState = state;
1537
+ let pseudo_row = {};
1538
+ if (!row) {
1539
+ table.fields.forEach((f) => {
1540
+ pseudo_row[f.name] = undefined;
1541
+ });
1542
+ }
1543
+ const appState = getState();
1544
+ const __ = db.is_node && appState
1545
+ ? (s) => appState.i18n.__({ phrase: s, locale: req.getLocale() }) || s
1546
+ : (s) => {
1547
+ return s;
1548
+ };
1549
+ await traverse(form.layout, {
1550
+ container(segment) {
1551
+ if (segment.click_action) {
1552
+ segment.url = `javascript:view_post(this, 'run_action', {click_action: '${segment.click_action}', ...get_form_record(this) })`;
1553
+ }
1554
+ },
1555
+ async action(segment) {
1556
+ if (segment.action_style === "on_page_load") {
1557
+ segment.type = "blank";
1558
+ segment.style = {};
1559
+ if (segment.minRole && segment.minRole != 100) {
1560
+ const minRole = +segment.minRole;
1561
+ const userRole = req?.user?.role_id || 100;
1562
+ if (minRole < userRole)
1563
+ return;
1564
+ }
1565
+ if (req.method === "POST")
1566
+ return;
1567
+ //run action
1568
+ try {
1569
+ const actionResult = await (0, plugin_helper_1.run_action_column)({
1570
+ col: { ...segment },
1571
+ referrer: req?.get?.("Referrer"),
1572
+ req,
1573
+ res,
1574
+ table,
1575
+ row: row || pseudo_row,
1576
+ });
1577
+ if (actionResult)
1578
+ segment.contents = script(domReady(`common_done(${JSON.stringify(actionResult)}, "${viewname}")`));
1579
+ }
1580
+ catch (e) {
1581
+ const err = e;
1582
+ appState.log(5, `Error in Edit ${viewname} on page load action: ${err.message}`);
1583
+ err.message = `Error in evaluating Run on Page Load action in view ${viewname}: ${err.message}`;
1584
+ throw err;
1585
+ }
1586
+ }
1587
+ if (segment.action_name === "Delete") {
1588
+ if (form.values && form.values[table.pk_name]) {
1589
+ segment.action_url = table.delete_url(form.values);
1590
+ }
1591
+ else {
1592
+ segment.type = "blank";
1593
+ segment.contents = "";
1594
+ }
1595
+ }
1596
+ else if (segment.action_name === "form_action" &&
1597
+ segment.configuration?.form_action === "Save" &&
1598
+ table.fields.some((f) => f.type === "File")) {
1599
+ let url = action_url(viewname, table, segment.action_name, row || pseudo_row, segment.rndid, "rndid", segment.confirm);
1600
+ if (typeof url !== "string" && url.javascript) {
1601
+ //redo to include dynamic row
1602
+ const confirmStr = segment.confirm
1603
+ ? `if(confirm('Are you sure?'))`
1604
+ : "";
1605
+ url.javascript = `${confirmStr}view_post(this, 'run_action', get_form_data(this, '${segment.rndid}') );`;
1606
+ }
1607
+ segment.action_link = action_link(url, req, segment, __);
1608
+ }
1609
+ else if (!["Sign up", ...edit_build_in_actions].includes(segment.action_name) &&
1610
+ !segment.action_name.startsWith("Login")) {
1611
+ let url = action_url(viewname, table, segment.action_name, row || pseudo_row, segment.rndid, "rndid", segment.confirm, undefined, segment.run_async);
1612
+ if (typeof url !== "string" && url.javascript) {
1613
+ //redo to include dynamic row
1614
+ const confirmStr = segment.confirm
1615
+ ? `if(confirm('Are you sure?'))`
1616
+ : "";
1617
+ // If this is a Multi-step action or the form/table contains File fields,
1618
+ // post multipart FormData so req.files is populated server-side.
1619
+ const hasFileFields = table.fields?.some((f) => f.type === "File");
1620
+ if (segment.action_name === "Multi-step action" || hasFileFields) {
1621
+ url.javascript = `${confirmStr}view_post(this, 'run_action', get_form_data(this, '${segment.rndid}') );`;
1622
+ }
1623
+ else {
1624
+ url.javascript = `${confirmStr}view_post(this, 'run_action', {rndid:'${segment.rndid}', ...get_form_record(this)});`;
1625
+ }
1626
+ }
1627
+ segment.action_link = action_link(url, req, segment, __);
1628
+ }
1629
+ },
1630
+ join_field(segment) {
1631
+ const qs = objToQueryString(segment.configuration);
1632
+ segment.sourceURL = `/field/show-calculated/${table.name}/${segment.join_field}/${segment.fieldview}?${qs}`;
1633
+ },
1634
+ tabs(segment) {
1635
+ const to_delete = new Set();
1636
+ (segment.showif || []).forEach((sif, ix) => {
1637
+ if (sif) {
1638
+ const showit = eval_expression(sif, row || pseudo_row, req.user, "Tab show if formula");
1639
+ if (!showit)
1640
+ to_delete.add(ix);
1641
+ }
1642
+ });
1643
+ segment.titles = segment.titles.filter((_v, ix) => !to_delete.has(ix));
1644
+ segment.contents = segment.contents.filter((_v, ix) => !to_delete.has(ix));
1645
+ (segment.titles || []).forEach((t, ix) => {
1646
+ if (typeof t === "string" && t.includes("{{")) {
1647
+ segment.titles[ix] = interpolate(t, row, req.user, "Tab titles");
1648
+ }
1649
+ });
1650
+ },
1651
+ view_link(segment) {
1652
+ segment.type = "blank";
1653
+ const view_select = parse_view_select(segment.view);
1654
+ if (!row && view_select.type !== "Independent") {
1655
+ segment.contents = "";
1656
+ }
1657
+ else {
1658
+ const prefix = req.generate_email && req.get_base_url ? req.get_base_url() : "";
1659
+ const { key } = view_linker(segment, table.fields, (s) => s, isWeb(req), req.user, prefix, req.query, req, viewname);
1660
+ segment.contents = key(row || {});
1661
+ }
1662
+ },
1663
+ async view(segment) {
1664
+ //console.log(segment);
1665
+ const view_select = parse_view_select(segment.view, segment.relation);
1666
+ //console.log({ view_select });
1667
+ const view = view_1.default.findOne({ name: view_select.viewname });
1668
+ if (!view)
1669
+ throw new InvalidConfiguration(`Cannot find embedded view: ${view_select.viewname}`);
1670
+ // check if the relation path matches a ChildList relations
1671
+ let childListRelPath = false;
1672
+ if (segment.relation && view.table_id) {
1673
+ const targetTbl = table_1.default.findOne({ id: view.table_id });
1674
+ const relation = new Relation(segment.relation, targetTbl.name, (0, plugin_helper_1.displayType)(await view.get_state_fields()));
1675
+ childListRelPath = relation.type === RelationType.CHILD_LIST;
1676
+ }
1677
+ // Edit-in-edit
1678
+ if (view.viewtemplate === "Edit" &&
1679
+ (view_select.type === "ChildList" || childListRelPath)) {
1680
+ if (childListRelPath)
1681
+ updateViewSelect(view_select);
1682
+ const childTable = table_1.default.findOne({ id: view.table_id });
1683
+ const childForm = await getForm(childTable, view.name, view.configuration.columns, view.configuration.layout, row?.id, req, !isWeb(req));
1684
+ traverseSync(childForm.layout, {
1685
+ field(segment) {
1686
+ segment.field_name = `${view_select.field_name}.${segment.field_name}`;
1687
+ },
1688
+ });
1689
+ for (const field of childForm.fields) {
1690
+ if (field.name === childTable.pk_name) {
1691
+ field.class = field.class
1692
+ ? `${field.class} omit-repeater-clone`
1693
+ : "omit-repeater-clone";
1694
+ }
1695
+ }
1696
+ await childForm.fill_fkey_options(false, optionsQuery, req.user);
1697
+ const fr = new FieldRepeat({
1698
+ name: view_select.field_name,
1699
+ label: view_select.field_name,
1700
+ fields: childForm.fields,
1701
+ layout: childForm.layout,
1702
+ metadata: {
1703
+ table_id: childTable.id,
1704
+ view: segment.view,
1705
+ relation: view_select.field_name,
1706
+ relation_path: segment.relation,
1707
+ order_field: segment.order_field,
1708
+ },
1709
+ });
1710
+ if (row?.id) {
1711
+ const childRows = getRowQuery
1712
+ ? await getRowQuery(view.table_id, view_select, row.id, segment.order_field)
1713
+ : await childTable.getRows({
1714
+ [view_select.field_name]: row.id,
1715
+ }, segment.order_field ? { orderBy: segment.order_field } : {});
1716
+ fr.metadata.rows = childRows;
1717
+ if (!fr.fields.map((f) => f.name).includes(childTable.pk_name))
1718
+ fr.fields.push({
1719
+ name: childTable.pk_name,
1720
+ input_type: "hidden",
1721
+ });
1722
+ }
1723
+ form.fields.push(fr);
1724
+ segment.type = "field_repeat";
1725
+ segment.field_repeat = fr;
1726
+ return;
1727
+ } // end edit in edit
1728
+ const outerState = {};
1729
+ Object.entries(originalState || {}).forEach(([k, v]) => {
1730
+ if (k.startsWith("_"))
1731
+ outerState[k] = v;
1732
+ });
1733
+ let state = {};
1734
+ let urlFormula;
1735
+ let needFields = new Set();
1736
+ if (view_select.type === "RelationPath" && view.table_id) {
1737
+ const pathToUrlFormula = (relation) => {
1738
+ const st = (0, plugin_helper_1.pathToState)(relation, (k) => `row.` + k);
1739
+ return Object.entries(st)
1740
+ .map(([k, v]) => {
1741
+ needFields.add(v.split(".")[1]);
1742
+ return `${k}='+${v}+'`;
1743
+ })
1744
+ .join("&");
1745
+ };
1746
+ const targetTbl = table_1.default.findOne({ id: view.table_id });
1747
+ if (targetTbl) {
1748
+ const relation = new Relation(segment.relation, targetTbl.name, (0, plugin_helper_1.displayType)(await view.get_state_fields()));
1749
+ const relFmlQS = pathToUrlFormula(relation);
1750
+ const type = relation.type;
1751
+ if (!row && type == RelationType.OWN) {
1752
+ segment.type = "blank";
1753
+ urlFormula = `add_extra_state('/view/${view.name}/?${relFmlQS}', ${JSON.stringify(segment.extra_state_fml)}, row, ${JSON.stringify(outerState)})`;
1754
+ segment.contents = segment.contents = div({
1755
+ class: "d-inline",
1756
+ "data-sc-embed-viewname": view.name,
1757
+ "data-view-source-need-fields": [...needFields].join(","),
1758
+ "data-view-source": encodeURIComponent(urlFormula),
1759
+ });
1760
+ return;
1761
+ }
1762
+ else if (!row &&
1763
+ type !== RelationType.INDEPENDENT &&
1764
+ !relation.isFixedRelation()) {
1765
+ urlFormula = `add_extra_state('/view/${view.name}/?${relFmlQS}', ${JSON.stringify(segment.extra_state_fml)}, row, ${JSON.stringify(outerState)})`;
1766
+ segment.contents = segment.contents = div({
1767
+ class: "d-inline",
1768
+ "data-sc-embed-viewname": view.name,
1769
+ "data-view-source-need-fields": [...needFields].join(","),
1770
+ "data-view-source": encodeURIComponent(urlFormula),
1771
+ });
1772
+ return;
1773
+ }
1774
+ const userId = req?.user?.id;
1775
+ state = (0, plugin_helper_1.pathToState)(relation, relation.isFixedRelation() ? () => userId : (k) => row[k]);
1776
+ urlFormula = `add_extra_state('/view/${view.name}?${relFmlQS}', ${JSON.stringify(segment.extra_state_fml)}, row, ${JSON.stringify(outerState)})`;
1777
+ }
1778
+ }
1779
+ else {
1780
+ const isIndependent = view_select.type === "Independent";
1781
+ // legacy none check ?
1782
+ if (!view)
1783
+ throw new InvalidConfiguration(`Edit view incorrectly configured: cannot find embedded view ${view_select.viewname}`);
1784
+ switch (view_select.type) {
1785
+ case "Own":
1786
+ state = { id: row?.id };
1787
+ urlFormula = `add_extra_state('/view/${view.name}/?id='+row.id, ${JSON.stringify(segment.extra_state_fml)}, row, ${JSON.stringify(outerState)})`;
1788
+ needFields.add("id");
1789
+ break;
1790
+ case "Independent":
1791
+ state = {};
1792
+ urlFormula = `add_extra_state('/view/${view.name}/?id='+row.id, ${JSON.stringify(segment.extra_state_fml)}, row, ${JSON.stringify(outerState)})`;
1793
+ needFields.add("id");
1794
+ break;
1795
+ case "ChildList":
1796
+ case "OneToOneShow":
1797
+ state = { [view_select.field_name]: row?.id };
1798
+ urlFormula = `add_extra_state('/view/${view.name}/?${view_select.field_name}='+row.id, ${JSON.stringify(segment.extra_state_fml)}, row, ${JSON.stringify(outerState)})`;
1799
+ needFields.add("id");
1800
+ break;
1801
+ case "ParentShow":
1802
+ state = { id: row?.[view_select.field_name] };
1803
+ urlFormula = `add_extra_state('/view/${view.name}/?id='+row.${view_select.field_name}, ${JSON.stringify(segment.extra_state_fml)}, row, ${JSON.stringify(outerState)})`;
1804
+ needFields.add(view_select.field_name);
1805
+ break;
1806
+ }
1807
+ if (!row && !isIndependent) {
1808
+ segment.type = "blank";
1809
+ segment.contents = div({
1810
+ class: "d-inline",
1811
+ "data-sc-embed-viewname": view.name,
1812
+ "data-view-source-need-fields": [...needFields].join(","),
1813
+ "data-view-source": encodeURIComponent(urlFormula),
1814
+ });
1815
+ return;
1816
+ }
1817
+ }
1818
+ const extra_state = segment.extra_state_fml
1819
+ ? eval_expression(segment.extra_state_fml, {
1820
+ ...dollarizeObject(req.query),
1821
+ session_id: getSessionId(req),
1822
+ ...(row || pseudo_row),
1823
+ }, req.user, `Extra state formula for embedding view ${view.name}`)
1824
+ : {};
1825
+ const qs = (0, plugin_helper_1.stateToQueryString)({ ...state, ...outerState, ...extra_state }, true);
1826
+ segment.contents = div({
1827
+ class: "d-inline",
1828
+ "data-sc-embed-viewname": view.name,
1829
+ "data-sc-view-source": `/view/${view.name}${qs}`,
1830
+ "data-view-source-current": `/view/${view.name}${qs}`,
1831
+ "data-view-source-need-fields": [...needFields].join(","),
1832
+ "data-view-source": encodeURIComponent(urlFormula),
1833
+ }, view.renderLocally()
1834
+ ? await view.run({ ...state, ...outerState, ...extra_state }, { req, res }, view.isRemoteTable())
1835
+ : await renderServerSide(view.name, {
1836
+ ...state,
1837
+ ...outerState,
1838
+ ...extra_state,
1839
+ }));
1840
+ },
1841
+ });
1842
+ translateLayout(form.layout, req.getLocale());
1843
+ if (req.headers?.saltcornmodalrequest)
1844
+ form.xhrSubmit = true;
1845
+ setDateLocales(form, req.getLocale());
1846
+ };
1847
+ exports.transformForm = transformForm;
1848
+ const setDateLocales = (form, locale) => {
1849
+ form.fields.forEach((f) => {
1850
+ const ftype = f.type;
1851
+ if (ftype && ftype.name === "Date") {
1852
+ f.attributes.locale = locale;
1853
+ }
1854
+ });
1855
+ };
1856
+ exports.setDateLocales = setDateLocales;
1857
+ /**
1858
+ * update viewSelect so that it looks like a normal ChildList
1859
+ */
1860
+ const updateViewSelect = (viewSelect) => {
1861
+ if (viewSelect.path.length === 1) {
1862
+ viewSelect.field_name = viewSelect.path[0].inboundKey;
1863
+ viewSelect.table_name = viewSelect.path[0].table;
1864
+ }
1865
+ else if (viewSelect.path.length === 2) {
1866
+ viewSelect.field_name = viewSelect.path[1].inboundKey;
1867
+ viewSelect.table_name = viewSelect.path[1].table;
1868
+ viewSelect.throughTable = viewSelect.path[0].inboundKey;
1869
+ viewSelect.through = viewSelect.path[0].table;
1870
+ }
1871
+ };
1872
+ exports.updateViewSelect = updateViewSelect;
1493
1873
  /**
1494
1874
  * @param {object} table
1495
1875
  * @param {object} req
@@ -1528,9 +1908,11 @@ const fill_presets = async (table, req, fixed) => {
1528
1908
  });
1529
1909
  return fixed;
1530
1910
  };
1911
+ exports.fill_presets = fill_presets;
1531
1912
  const objToQueryString = (o) => Object.entries(o || {})
1532
1913
  .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
1533
1914
  .join("&");
1915
+ exports.objToQueryString = objToQueryString;
1534
1916
  // edit template build in actions
1535
1917
  const edit_build_in_actions = [
1536
1918
  "Save",
@@ -1542,21 +1924,5 @@ const edit_build_in_actions = [
1542
1924
  "Delete",
1543
1925
  "Cancel",
1544
1926
  ];
1545
- module.exports = {
1546
- get_viewable_fields,
1547
- get_viewable_fields_from_layout,
1548
- action_url,
1549
- objToQueryString,
1550
- action_link,
1551
- view_linker,
1552
- parse_view_select,
1553
- splitUniques,
1554
- getForm,
1555
- fill_presets,
1556
- get_view_link_query,
1557
- make_link,
1558
- edit_build_in_actions,
1559
- standardBlockDispatch,
1560
- standardLayoutRowVisitor,
1561
- };
1927
+ exports.edit_build_in_actions = edit_build_in_actions;
1562
1928
  //# sourceMappingURL=viewable_fields.js.map