@saltcorn/data 1.5.0-beta.9 → 1.5.0-rc.1

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 (146) hide show
  1. package/dist/base-plugin/actions.d.ts +221 -145
  2. package/dist/base-plugin/actions.d.ts.map +1 -1
  3. package/dist/base-plugin/actions.js +80 -12
  4. package/dist/base-plugin/actions.js.map +1 -1
  5. package/dist/base-plugin/fileviews.d.ts +3 -3
  6. package/dist/base-plugin/fileviews.js +20 -9
  7. package/dist/base-plugin/fileviews.js.map +1 -1
  8. package/dist/base-plugin/index.d.ts +2 -2
  9. package/dist/base-plugin/index.d.ts.map +1 -1
  10. package/dist/base-plugin/types.d.ts.map +1 -1
  11. package/dist/base-plugin/types.js +8 -5
  12. package/dist/base-plugin/types.js.map +1 -1
  13. package/dist/base-plugin/viewtemplates/edit.d.ts +6 -2
  14. package/dist/base-plugin/viewtemplates/edit.d.ts.map +1 -1
  15. package/dist/base-plugin/viewtemplates/edit.js +17 -341
  16. package/dist/base-plugin/viewtemplates/edit.js.map +1 -1
  17. package/dist/base-plugin/viewtemplates/filter.d.ts.map +1 -1
  18. package/dist/base-plugin/viewtemplates/filter.js +9 -3
  19. package/dist/base-plugin/viewtemplates/filter.js.map +1 -1
  20. package/dist/base-plugin/viewtemplates/show.d.ts.map +1 -1
  21. package/dist/base-plugin/viewtemplates/show.js +1 -0
  22. package/dist/base-plugin/viewtemplates/show.js.map +1 -1
  23. package/dist/base-plugin/viewtemplates/viewable_fields.d.ts +16 -0
  24. package/dist/base-plugin/viewtemplates/viewable_fields.d.ts.map +1 -1
  25. package/dist/base-plugin/viewtemplates/viewable_fields.js +340 -3
  26. package/dist/base-plugin/viewtemplates/viewable_fields.js.map +1 -1
  27. package/dist/base-plugin/viewtemplates/workflow-room.d.ts.map +1 -1
  28. package/dist/base-plugin/viewtemplates/workflow-room.js +1 -1
  29. package/dist/base-plugin/viewtemplates/workflow-room.js.map +1 -1
  30. package/dist/db/connect.d.ts.map +1 -1
  31. package/dist/db/connect.js +4 -1
  32. package/dist/db/connect.js.map +1 -1
  33. package/dist/db/state.d.ts +11 -7
  34. package/dist/db/state.d.ts.map +1 -1
  35. package/dist/db/state.js +78 -12
  36. package/dist/db/state.js.map +1 -1
  37. package/dist/mobile-mocks/npm/dockerode.d.ts +1 -0
  38. package/dist/mobile-mocks/npm/dockerode.d.ts.map +1 -0
  39. package/dist/mobile-mocks/npm/dockerode.js +2 -0
  40. package/dist/mobile-mocks/npm/dockerode.js.map +1 -0
  41. package/dist/models/config.d.ts.map +1 -1
  42. package/dist/models/config.js +55 -12
  43. package/dist/models/config.js.map +1 -1
  44. package/dist/models/email.js.map +1 -1
  45. package/dist/models/expression.d.ts.map +1 -1
  46. package/dist/models/expression.js +29 -0
  47. package/dist/models/expression.js.map +1 -1
  48. package/dist/models/field.d.ts +5 -3
  49. package/dist/models/field.d.ts.map +1 -1
  50. package/dist/models/field.js +8 -2
  51. package/dist/models/field.js.map +1 -1
  52. package/dist/models/file.d.ts +18 -1
  53. package/dist/models/file.d.ts.map +1 -1
  54. package/dist/models/file.js +361 -43
  55. package/dist/models/file.js.map +1 -1
  56. package/dist/models/form.d.ts.map +1 -1
  57. package/dist/models/form.js.map +1 -1
  58. package/dist/models/index.d.ts.map +1 -1
  59. package/dist/models/internal/push_message_helper.d.ts +42 -12
  60. package/dist/models/internal/push_message_helper.d.ts.map +1 -1
  61. package/dist/models/internal/push_message_helper.js +117 -50
  62. package/dist/models/internal/push_message_helper.js.map +1 -1
  63. package/dist/models/internal/s3_helpers.d.ts +54 -0
  64. package/dist/models/internal/s3_helpers.d.ts.map +1 -0
  65. package/dist/models/internal/s3_helpers.js +561 -0
  66. package/dist/models/internal/s3_helpers.js.map +1 -0
  67. package/dist/models/model.d.ts +1 -1
  68. package/dist/models/model.d.ts.map +1 -1
  69. package/dist/models/model.js.map +1 -1
  70. package/dist/models/notification.d.ts.map +1 -1
  71. package/dist/models/notification.js +2 -5
  72. package/dist/models/notification.js.map +1 -1
  73. package/dist/models/page.d.ts +1 -0
  74. package/dist/models/page.d.ts.map +1 -1
  75. package/dist/models/page.js +27 -24
  76. package/dist/models/page.js.map +1 -1
  77. package/dist/models/plugin.d.ts +11 -3
  78. package/dist/models/plugin.d.ts.map +1 -1
  79. package/dist/models/plugin.js +51 -12
  80. package/dist/models/plugin.js.map +1 -1
  81. package/dist/models/s3_helpers.d.ts +54 -0
  82. package/dist/models/s3_helpers.d.ts.map +1 -0
  83. package/dist/models/s3_helpers.js +505 -0
  84. package/dist/models/s3_helpers.js.map +1 -0
  85. package/dist/models/scheduler.d.ts.map +1 -1
  86. package/dist/models/scheduler.js +4 -1
  87. package/dist/models/scheduler.js.map +1 -1
  88. package/dist/models/table.d.ts +8 -3
  89. package/dist/models/table.d.ts.map +1 -1
  90. package/dist/models/table.js +121 -32
  91. package/dist/models/table.js.map +1 -1
  92. package/dist/models/user.d.ts +4 -4
  93. package/dist/models/user.d.ts.map +1 -1
  94. package/dist/models/user.js.map +1 -1
  95. package/dist/models/view.js +1 -1
  96. package/dist/models/view.js.map +1 -1
  97. package/dist/models/workflow_run.d.ts +1 -1
  98. package/dist/models/workflow_run.d.ts.map +1 -1
  99. package/dist/models/workflow_run.js +8 -2
  100. package/dist/models/workflow_run.js.map +1 -1
  101. package/dist/models/workflow_step.js +1 -1
  102. package/dist/models/workflow_step.js.map +1 -1
  103. package/dist/plugin-helper.d.ts.map +1 -1
  104. package/dist/plugin-helper.js +139 -15
  105. package/dist/plugin-helper.js.map +1 -1
  106. package/dist/standard-menu.js +2 -2
  107. package/dist/standard-menu.js.map +1 -1
  108. package/dist/test-utils/mocks.d.ts +203 -0
  109. package/dist/test-utils/mocks.d.ts.map +1 -0
  110. package/dist/test-utils/mocks.js +329 -0
  111. package/dist/test-utils/mocks.js.map +1 -0
  112. package/dist/tests/assertions.d.ts.map +1 -1
  113. package/dist/tests/assertions.js +10 -9
  114. package/dist/tests/assertions.js.map +1 -1
  115. package/dist/tests/auth.test.js +0 -68
  116. package/dist/tests/auth.test.js.map +1 -1
  117. package/dist/tests/calc.test.js +3 -62
  118. package/dist/tests/calc.test.js.map +1 -1
  119. package/dist/tests/exact_views.test.js +14 -14
  120. package/dist/tests/exact_views.test.js.map +1 -1
  121. package/dist/tests/show.test.js +1 -1
  122. package/dist/tests/show.test.js.map +1 -1
  123. package/dist/tests/table.test.js +0 -37
  124. package/dist/tests/table.test.js.map +1 -1
  125. package/dist/tests/table_sync_info.test.d.ts +2 -0
  126. package/dist/tests/table_sync_info.test.d.ts.map +1 -0
  127. package/dist/tests/table_sync_info.test.js +62 -0
  128. package/dist/tests/table_sync_info.test.js.map +1 -0
  129. package/dist/tests/user.test.js +4 -29
  130. package/dist/tests/user.test.js.map +1 -1
  131. package/dist/tests/view.test.js +0 -3
  132. package/dist/tests/view.test.js.map +1 -1
  133. package/dist/utils.d.ts +11 -1
  134. package/dist/utils.d.ts.map +1 -1
  135. package/dist/utils.js +33 -3
  136. package/dist/utils.js.map +1 -1
  137. package/dist/viewable_fields.d.ts +172 -0
  138. package/dist/viewable_fields.d.ts.map +1 -0
  139. package/dist/viewable_fields.js +1562 -0
  140. package/dist/viewable_fields.js.map +1 -0
  141. package/dist/web-mobile-commons.d.ts +1 -1
  142. package/dist/web-mobile-commons.d.ts.map +1 -1
  143. package/dist/web-mobile-commons.js +19 -3
  144. package/dist/web-mobile-commons.js.map +1 -1
  145. package/package.json +14 -9
  146. package/webpack.config.js +3 -0
@@ -24,7 +24,7 @@ const { InvalidConfiguration, isNode, isWeb, isTest, mergeIntoWhere, dollarizeOb
24
24
  const Library = require("../../models/library");
25
25
  const { check_view_columns } = require("../../plugin-testing");
26
26
  const { initial_config_all_fields, calcfldViewOptions, calcfldViewConfig, get_parent_views, picked_fields_to_query, stateFieldsToWhere, stateFieldsToQuery, getActionConfigFields, run_action_column, add_free_variables_to_joinfields, readState, stateToQueryString, pathToState, displayType, runCollabEvents, } = require("../../plugin-helper");
27
- const { splitUniques, getForm, fill_presets, parse_view_select, get_view_link_query, objToQueryString, action_url, action_link, view_linker, edit_build_in_actions, } = require("./viewable_fields");
27
+ const { splitUniques, getForm, setDateLocales, transformForm, fill_presets, parse_view_select, get_view_link_query, objToQueryString, action_url, action_link, view_linker, edit_build_in_actions, updateViewSelect, } = require("./viewable_fields");
28
28
  const { traverse, getStringsForI18n, translateLayout, traverseSync, splitLayoutContainerFields, findLayoutBranchWith, } = require("../../models/layout");
29
29
  const { extractFromLayout } = require("../../diagram/node_extract_utils");
30
30
  const db = require("../../db");
@@ -398,28 +398,6 @@ const get_state_fields = async (table_id, viewname, { columns }) => [
398
398
  * @param {Form} form
399
399
  * @param {string} locale
400
400
  */
401
- const setDateLocales = (form, locale) => {
402
- form.fields.forEach((f) => {
403
- if (f.type && f.type.name === "Date") {
404
- f.attributes.locale = locale;
405
- }
406
- });
407
- };
408
- /**
409
- * update viewSelect so that it looks like a normal ChildList
410
- */
411
- const updateViewSelect = (viewSelect) => {
412
- if (viewSelect.path.length === 1) {
413
- viewSelect.field_name = viewSelect.path[0].inboundKey;
414
- viewSelect.table_name = viewSelect.path[0].table;
415
- }
416
- else if (viewSelect.path.length === 2) {
417
- viewSelect.field_name = viewSelect.path[1].inboundKey;
418
- viewSelect.table_name = viewSelect.path[1].table;
419
- viewSelect.throughTable = viewSelect.path[0].inboundKey;
420
- viewSelect.through = viewSelect.path[0].table;
421
- }
422
- };
423
401
  /** @type {function} */
424
402
  const initial_config = initial_config_all_fields(true);
425
403
  /**
@@ -494,311 +472,6 @@ const runMany = async (table_id, viewname, { columns, layout, auto_save, split_p
494
472
  * @throws {InvalidConfiguration}
495
473
  * @returns {Promise<void>}
496
474
  */
497
- const transformForm = async ({ form, table, req, row, res, getRowQuery, viewname, optionsQuery, state, }) => {
498
- let originalState = state;
499
- let pseudo_row = {};
500
- if (!row) {
501
- table.fields.forEach((f) => {
502
- pseudo_row[f.name] = undefined;
503
- });
504
- }
505
- await traverse(form.layout, {
506
- container(segment) {
507
- if (segment.click_action) {
508
- segment.url = `javascript:view_post(this, 'run_action', {click_action: '${segment.click_action}', ...get_form_record(this) })`;
509
- }
510
- },
511
- async action(segment) {
512
- if (segment.action_style === "on_page_load") {
513
- segment.type = "blank";
514
- segment.style = {};
515
- if (segment.minRole && segment.minRole != 100) {
516
- const minRole = +segment.minRole;
517
- const userRole = req?.user?.role_id || 100;
518
- if (minRole < userRole)
519
- return;
520
- }
521
- if (req.method === "POST")
522
- return;
523
- //run action
524
- try {
525
- const actionResult = await run_action_column({
526
- col: { ...segment },
527
- referrer: req?.get?.("Referrer"),
528
- req,
529
- res,
530
- table,
531
- row: row || pseudo_row,
532
- });
533
- if (actionResult)
534
- segment.contents = script(domReady(`common_done(${JSON.stringify(actionResult)}, "${viewname}")`));
535
- }
536
- catch (e) {
537
- getState().log(5, `Error in Edit ${viewname} on page load action: ${e.message}`);
538
- e.message = `Error in evaluating Run on Page Load action in view ${viewname}: ${e.message}`;
539
- throw e;
540
- }
541
- }
542
- if (segment.action_name === "Delete") {
543
- if (form.values && form.values[table.pk_name]) {
544
- segment.action_url = table.delete_url(form.values);
545
- }
546
- else {
547
- segment.type = "blank";
548
- segment.contents = "";
549
- }
550
- }
551
- else if (segment.action_name === "form_action" &&
552
- segment.configuration?.form_action === "Save" &&
553
- table.fields.some((f) => f.type === "File")) {
554
- let url = action_url(viewname, table, segment.action_name, row, segment.rndid, "rndid", segment.confirm);
555
- if (url.javascript) {
556
- //redo to include dynamic row
557
- const confirmStr = segment.confirm
558
- ? `if(confirm('Are you sure?'))`
559
- : "";
560
- url.javascript = `${confirmStr}view_post(this, 'run_action', get_form_data(this, '${segment.rndid}') );`;
561
- }
562
- segment.action_link = action_link(url, req, segment);
563
- }
564
- else if (!["Sign up", ...edit_build_in_actions].includes(segment.action_name) &&
565
- !segment.action_name.startsWith("Login")) {
566
- let url = action_url(viewname, table, segment.action_name, row, segment.rndid, "rndid", segment.confirm, undefined, segment.run_async);
567
- if (url.javascript) {
568
- //redo to include dynamic row
569
- const confirmStr = segment.confirm
570
- ? `if(confirm('Are you sure?'))`
571
- : "";
572
- // If this is a Multi-step action or the form/table contains File fields,
573
- // post multipart FormData so req.files is populated server-side.
574
- const hasFileFields = table.fields?.some((f) => f.type === "File");
575
- if (segment.action_name === "Multi-step action" || hasFileFields) {
576
- url.javascript = `${confirmStr}view_post(this, 'run_action', get_form_data(this, '${segment.rndid}') );`;
577
- }
578
- else {
579
- url.javascript = `${confirmStr}view_post(this, 'run_action', {rndid:'${segment.rndid}', ...get_form_record(this)});`;
580
- }
581
- }
582
- segment.action_link = action_link(url, req, segment);
583
- }
584
- },
585
- join_field(segment) {
586
- const qs = objToQueryString(segment.configuration);
587
- segment.sourceURL = `/field/show-calculated/${table.name}/${segment.join_field}/${segment.fieldview}?${qs}`;
588
- },
589
- tabs(segment) {
590
- const to_delete = new Set();
591
- (segment.showif || []).forEach((sif, ix) => {
592
- if (sif) {
593
- const showit = eval_expression(sif, row || pseudo_row, req.user, "Tab show if formula");
594
- if (!showit)
595
- to_delete.add(ix);
596
- }
597
- });
598
- segment.titles = segment.titles.filter((v, ix) => !to_delete.has(ix));
599
- segment.contents = segment.contents.filter((v, ix) => !to_delete.has(ix));
600
- (segment.titles || []).forEach((t, ix) => {
601
- if (typeof t === "string" && t.includes("{{")) {
602
- segment.titles[ix] = interpolate(t, row, req.user, "Tab titles");
603
- }
604
- });
605
- },
606
- view_link(segment) {
607
- segment.type = "blank";
608
- const view_select = parse_view_select(segment.view);
609
- if (!row && view_select.type !== "Independent") {
610
- segment.contents = "";
611
- }
612
- else {
613
- const prefix = req.generate_email && req.get_base_url ? req.get_base_url() : "";
614
- const { key } = view_linker(segment, table.fields, (s) => s, isWeb(req), req.user, prefix, req.query, req, viewname);
615
- segment.contents = key(row || {});
616
- }
617
- },
618
- async view(segment) {
619
- //console.log(segment);
620
- const view_select = parse_view_select(segment.view, segment.relation);
621
- //console.log({ view_select });
622
- const view = View.findOne({ name: view_select.viewname });
623
- if (!view)
624
- throw new InvalidConfiguration(`Cannot find embedded view: ${view_select.viewname}`);
625
- // check if the relation path matches a ChildList relations
626
- let childListRelPath = false;
627
- if (segment.relation && view.table_id) {
628
- const targetTbl = Table.findOne({ id: view.table_id });
629
- const relation = new Relation(segment.relation, targetTbl.name, displayType(await view.get_state_fields()));
630
- childListRelPath = relation.type === RelationType.CHILD_LIST;
631
- }
632
- // Edit-in-edit
633
- if (view.viewtemplate === "Edit" &&
634
- (view_select.type === "ChildList" || childListRelPath)) {
635
- if (childListRelPath)
636
- updateViewSelect(view_select);
637
- const childTable = Table.findOne({ id: view.table_id });
638
- const childForm = await getForm(childTable, view.name, view.configuration.columns, view.configuration.layout, row?.id, req, !isWeb(req));
639
- traverseSync(childForm.layout, {
640
- field(segment) {
641
- segment.field_name = `${view_select.field_name}.${segment.field_name}`;
642
- },
643
- });
644
- for (const field of childForm.fields) {
645
- if (field.name === childTable.pk_name) {
646
- field.class = field.class
647
- ? `${field.class} omit-repeater-clone`
648
- : "omit-repeater-clone";
649
- }
650
- }
651
- await childForm.fill_fkey_options(false, optionsQuery, req.user);
652
- const fr = new FieldRepeat({
653
- name: view_select.field_name,
654
- label: view_select.field_name,
655
- fields: childForm.fields,
656
- layout: childForm.layout,
657
- metadata: {
658
- table_id: childTable.id,
659
- view: segment.view,
660
- relation: view_select.field_name,
661
- relation_path: segment.relation,
662
- order_field: segment.order_field,
663
- },
664
- });
665
- if (row?.id) {
666
- const childRows = getRowQuery
667
- ? await getRowQuery(view.table_id, view_select, row.id, segment.order_field)
668
- : await childTable.getRows({
669
- [view_select.field_name]: row.id,
670
- }, segment.order_field ? { orderBy: segment.order_field } : {});
671
- fr.metadata.rows = childRows;
672
- if (!fr.fields.map((f) => f.name).includes(childTable.pk_name))
673
- fr.fields.push({
674
- name: childTable.pk_name,
675
- input_type: "hidden",
676
- });
677
- }
678
- form.fields.push(fr);
679
- segment.type = "field_repeat";
680
- segment.field_repeat = fr;
681
- return;
682
- } // end edit in edit
683
- const outerState = {};
684
- Object.entries(originalState || {}).forEach(([k, v]) => {
685
- if (k.startsWith("_"))
686
- outerState[k] = v;
687
- });
688
- let state = {};
689
- let urlFormula;
690
- let needFields = new Set();
691
- if (view_select.type === "RelationPath" && view.table_id) {
692
- const pathToUrlFormula = (relation) => {
693
- const st = pathToState(relation, (k) => `row.` + k);
694
- return Object.entries(st)
695
- .map(([k, v]) => {
696
- needFields.add(v.split(".")[1]);
697
- return `${k}='+${v}+'`;
698
- })
699
- .join("&");
700
- };
701
- const targetTbl = Table.findOne({ id: view.table_id });
702
- if (targetTbl) {
703
- const relation = new Relation(segment.relation, targetTbl.name, displayType(await view.get_state_fields()));
704
- const relFmlQS = pathToUrlFormula(relation);
705
- const type = relation.type;
706
- if (!row && type == RelationType.OWN) {
707
- segment.type = "blank";
708
- urlFormula = `add_extra_state('/view/${view.name}/?${relFmlQS}', ${JSON.stringify(segment.extra_state_fml)}, row, ${JSON.stringify(outerState)})`;
709
- segment.contents = segment.contents = div({
710
- class: "d-inline",
711
- "data-sc-embed-viewname": view.name,
712
- "data-view-source-need-fields": [...needFields].join(","),
713
- "data-view-source": encodeURIComponent(urlFormula),
714
- });
715
- return;
716
- }
717
- else if (!row &&
718
- type !== RelationType.INDEPENDENT &&
719
- !relation.isFixedRelation()) {
720
- urlFormula = `add_extra_state('/view/${view.name}/?${relFmlQS}', ${JSON.stringify(segment.extra_state_fml)}, row, ${JSON.stringify(outerState)})`;
721
- segment.contents = segment.contents = div({
722
- class: "d-inline",
723
- "data-sc-embed-viewname": view.name,
724
- "data-view-source-need-fields": [...needFields].join(","),
725
- "data-view-source": encodeURIComponent(urlFormula),
726
- });
727
- return;
728
- }
729
- const userId = req?.user?.id;
730
- state = pathToState(relation, relation.isFixedRelation() ? () => userId : (k) => row[k]);
731
- urlFormula = `add_extra_state('/view/${view.name}?${relFmlQS}', ${JSON.stringify(segment.extra_state_fml)}, row, ${JSON.stringify(outerState)})`;
732
- }
733
- }
734
- else {
735
- const isIndependent = view_select.type === "Independent";
736
- // legacy none check ?
737
- if (!view)
738
- throw new InvalidConfiguration(`Edit view incorrectly configured: cannot find embedded view ${view_select.viewname}`);
739
- switch (view_select.type) {
740
- case "Own":
741
- state = { id: row?.id };
742
- urlFormula = `add_extra_state('/view/${view.name}/?id='+row.id, ${JSON.stringify(segment.extra_state_fml)}, row, ${JSON.stringify(outerState)})`;
743
- needFields.add("id");
744
- break;
745
- case "Independent":
746
- state = {};
747
- urlFormula = `add_extra_state('/view/${view.name}/?id='+row.id, ${JSON.stringify(segment.extra_state_fml)}, row, ${JSON.stringify(outerState)})`;
748
- needFields.add("id");
749
- break;
750
- case "ChildList":
751
- case "OneToOneShow":
752
- state = { [view_select.field_name]: row?.id };
753
- urlFormula = `add_extra_state('/view/${view.name}/?${view_select.field_name}='+row.id, ${JSON.stringify(segment.extra_state_fml)}, row, ${JSON.stringify(outerState)})`;
754
- needFields.add("id");
755
- break;
756
- case "ParentShow":
757
- state = { id: row?.[view_select.field_name] };
758
- urlFormula = `add_extra_state('/view/${view.name}/?id='+row.${view_select.field_name}, ${JSON.stringify(segment.extra_state_fml)}, row, ${JSON.stringify(outerState)})`;
759
- needFields.add(view_select.field_name);
760
- break;
761
- }
762
- if (!row && !isIndependent) {
763
- segment.type = "blank";
764
- segment.contents = div({
765
- class: "d-inline",
766
- "data-sc-embed-viewname": view.name,
767
- "data-view-source-need-fields": [...needFields].join(","),
768
- "data-view-source": encodeURIComponent(urlFormula),
769
- });
770
- return;
771
- }
772
- }
773
- const extra_state = segment.extra_state_fml
774
- ? eval_expression(segment.extra_state_fml, {
775
- ...dollarizeObject(req.query),
776
- session_id: getSessionId(req),
777
- ...(row || pseudo_row),
778
- }, req.user, `Extra state formula for embedding view ${view.name}`)
779
- : {};
780
- const qs = stateToQueryString({ ...state, ...outerState, ...extra_state }, true);
781
- segment.contents = div({
782
- class: "d-inline",
783
- "data-sc-embed-viewname": view.name,
784
- "data-sc-view-source": `/view/${view.name}${qs}`,
785
- "data-view-source-current": `/view/${view.name}${qs}`,
786
- "data-view-source-need-fields": [...needFields].join(","),
787
- "data-view-source": encodeURIComponent(urlFormula),
788
- }, view.renderLocally()
789
- ? await view.run({ ...state, ...outerState, ...extra_state }, { req, res }, view.isRemoteTable())
790
- : await renderServerSide(view.name, {
791
- ...state,
792
- ...outerState,
793
- ...extra_state,
794
- }));
795
- },
796
- });
797
- translateLayout(form.layout, req.getLocale());
798
- if (req.headers?.saltcornmodalrequest)
799
- form.xhrSubmit = true;
800
- setDateLocales(form, req.getLocale());
801
- };
802
475
  const realTimeScript = (viewname, table_id, row, scriptId) => {
803
476
  const view = View.findOne({ name: viewname });
804
477
  const table = Table.findOne({ id: table_id });
@@ -1176,11 +849,12 @@ const runPost = async (table_id, viewname, { columns, layout, fixed, view_when_d
1176
849
  childRow[order_field] = row_ix;
1177
850
  for (const file_field of field.fields.filter((f) => f.type === "File")) {
1178
851
  const key = `${file_field.name}_${repeatIx}`;
1179
- if (req.files?.[key]) {
852
+ if (req.files?.[key] &&
853
+ (!file_field.fieldviewObj || file_field.fieldviewObj.isEdit)) {
1180
854
  const file = await File.from_req_files(req.files[key], req.user ? req.user.id : null, (file_field.attributes &&
1181
855
  +file_field.attributes.min_role_read) ||
1182
856
  1, file_field?.attributes?.folder);
1183
- childRow[file_field.name] = file.path_to_serve;
857
+ childRow[file_field.name] = file.field_value;
1184
858
  }
1185
859
  }
1186
860
  getState().log(6, `Edit POST ready to insert/update Child row into ${childTable.name} Row=${JSON.stringify(childRow)} ID=${childRow[childTable.pk_name]} Ajax=${!!req.xhr}`);
@@ -1559,16 +1233,18 @@ const prepare = async (viewname, table, fields, { columns, layout, fixed, auto_s
1559
1233
  if (body[field.name]) {
1560
1234
  if (body[field.name].startsWith("data:")) {
1561
1235
  const path_to_serve = await saveFileQuery(body[field.name], field.id, field.fieldview, row);
1562
- row[field.name] = path_to_serve;
1563
- form.values[field.name] = path_to_serve;
1236
+ const storedValue = File.fieldValueFromRelative(path_to_serve);
1237
+ row[field.name] = storedValue;
1238
+ form.values[field.name] = storedValue;
1564
1239
  }
1565
1240
  }
1566
1241
  }
1567
1242
  else if (field.fieldviewObj?.editContent) {
1568
1243
  if (body[field.name]) {
1569
1244
  const path_to_serve = await saveFileFromContentsQuery(body[`_content_${field.name}`], field.id, field.fieldview, row, body[field.name], "utf8");
1570
- row[field.name] = path_to_serve;
1571
- form.values[field.name] = path_to_serve;
1245
+ const storedValue = File.fieldValueFromRelative(path_to_serve);
1246
+ row[field.name] = storedValue;
1247
+ form.values[field.name] = storedValue;
1572
1248
  }
1573
1249
  }
1574
1250
  else if (req.files && req.files[field.name]) {
@@ -1577,20 +1253,20 @@ const prepare = async (viewname, table, fields, { columns, layout, fixed, auto_s
1577
1253
  }
1578
1254
  if (isWeb(req)) {
1579
1255
  const file = await File.from_req_files(req.files[field.name], req.user ? req.user.id : null, (field.attributes && +field.attributes.min_role_read) || 1, field?.attributes?.folder);
1580
- row[field.name] = file.path_to_serve;
1581
- form.values[field.name] = file.path_to_serve;
1256
+ row[field.name] = file.field_value;
1257
+ form.values[field.name] = file.field_value;
1582
1258
  }
1583
1259
  else {
1584
1260
  const file = req.files[field.name];
1585
1261
  if (file) {
1586
1262
  const serverResp = await File.upload(req.files[field.name]);
1587
1263
  if (serverResp?.location)
1588
- row[field.name] = serverResp.location;
1264
+ row[field.name] = File.normalizeFieldValueInput(serverResp.location);
1589
1265
  }
1590
1266
  }
1591
1267
  }
1592
1268
  else if (typeof body[`__exisiting_file_${field.name}`] === "string") {
1593
- row[field.name] = File.normalise(body[`__exisiting_file_${field.name}`]);
1269
+ row[field.name] = File.normalizeFieldValueInput(body[`__exisiting_file_${field.name}`]);
1594
1270
  form.values[field.name] = row[field.name];
1595
1271
  }
1596
1272
  else {
@@ -2071,7 +1747,7 @@ module.exports = {
2071
1747
  ...(column?.configuration || {}),
2072
1748
  });
2073
1749
  const file = await File.from_contents(filename, mimetype, buffer, req.user?.id, field.attributes.min_role_read || 1, folder);
2074
- return file.path_to_serve;
1750
+ return File.fieldValueFromRelative(file.path_to_serve);
2075
1751
  },
2076
1752
  async saveFileFromContentsQuery(fieldVal, fieldId, fieldView, row, filename, encoding = "base64") {
2077
1753
  const field = await Field.findOne({ id: fieldId });
@@ -2095,13 +1771,13 @@ module.exports = {
2095
1771
  if (existing_file) {
2096
1772
  if (existing_file.min_role_read >= (req.user?.role_id || 100)) {
2097
1773
  await existing_file.overwrite_contents(buffer);
2098
- return existing_file.path_to_serve;
1774
+ return File.fieldValueFromRelative(existing_file.path_to_serve);
2099
1775
  }
2100
1776
  else
2101
1777
  throw new Error("Not authorized to write file");
2102
1778
  }
2103
1779
  const file = await File.from_contents(filename1, mimetype, buffer, req.user?.id, field.attributes.min_role_read || 1);
2104
- return file.path_to_serve;
1780
+ return File.fieldValueFromRelative(file.path_to_serve);
2105
1781
  },
2106
1782
  async authorizePostQuery(body, table_id /*overwrites*/) {
2107
1783
  return await doAuthPost({ body, table_id, req });