@saltcorn/server 0.8.6-beta.4 → 0.8.6-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@saltcorn/server",
3
- "version": "0.8.6-beta.4",
3
+ "version": "0.8.6-beta.5",
4
4
  "description": "Server app for Saltcorn, open-source no-code platform",
5
5
  "homepage": "https://saltcorn.com",
6
6
  "main": "index.js",
7
7
  "license": "MIT",
8
8
  "dependencies": {
9
- "@saltcorn/base-plugin": "0.8.6-beta.4",
10
- "@saltcorn/builder": "0.8.6-beta.4",
11
- "@saltcorn/data": "0.8.6-beta.4",
12
- "@saltcorn/admin-models": "0.8.6-beta.4",
13
- "@saltcorn/filemanager": "0.8.6-beta.4",
14
- "@saltcorn/markup": "0.8.6-beta.4",
15
- "@saltcorn/sbadmin2": "0.8.6-beta.4",
9
+ "@saltcorn/base-plugin": "0.8.6-beta.5",
10
+ "@saltcorn/builder": "0.8.6-beta.5",
11
+ "@saltcorn/data": "0.8.6-beta.5",
12
+ "@saltcorn/admin-models": "0.8.6-beta.5",
13
+ "@saltcorn/filemanager": "0.8.6-beta.5",
14
+ "@saltcorn/markup": "0.8.6-beta.5",
15
+ "@saltcorn/sbadmin2": "0.8.6-beta.5",
16
16
  "@socket.io/cluster-adapter": "^0.2.1",
17
17
  "@socket.io/sticky": "^1.0.1",
18
18
  "adm-zip": "0.5.10",
@@ -435,6 +435,7 @@ function reload_on_init() {
435
435
  localStorage.setItem("reload_on_init", true);
436
436
  }
437
437
  function initialize_page() {
438
+ const isNode = typeof parent?.saltcorn?.data?.state === "undefined";
438
439
  //console.log("init page");
439
440
  $(".blur-on-enter-keypress").bind("keyup", function (e) {
440
441
  if (e.keyCode === 13) e.target.blur();
@@ -480,7 +481,9 @@ function initialize_page() {
480
481
  if ($(this).find(".editicon").length === 0) {
481
482
  var current = $(this).html();
482
483
  $(this).html(
483
- `<span class="current">${current}</span><i class="editicon fas fa-edit ms-1"></i>`
484
+ `<span class="current">${current}</span><i class="editicon ${
485
+ !isNode ? "visible" : ""
486
+ } fas fa-edit ms-1"></i>`
484
487
  );
485
488
  }
486
489
  });
@@ -546,12 +549,20 @@ function initialize_page() {
546
549
  } else
547
550
  $(this).replaceWith(
548
551
  `<form method="post" action="${url}" ${
549
- ajax ? `onsubmit="inline_ajax_submit(event, '${opts}')"` : ""
552
+ ajax
553
+ ? `onsubmit="inline_${
554
+ isNode ? "ajax" : "local"
555
+ }_submit(event, '${opts}')"`
556
+ : ""
550
557
  }>
551
- <input type="hidden" name="_csrf" value="${_sc_globalCsrf}">
552
- <input type="${
553
- type === "Integer" || type === "Float" ? "number" : "text"
554
- }" name="${key}" value="${escapeHtml(current)}">
558
+ ${
559
+ isNode
560
+ ? `<input type="hidden" name="_csrf" value="${_sc_globalCsrf}"></input>`
561
+ : ""
562
+ }
563
+ <input type="${
564
+ type === "Integer" || type === "Float" ? "number" : "text"
565
+ }" name="${key}" value="${escapeHtml(current)}">
555
566
  <button type="submit" class="btn btn-sm btn-primary">OK</button>
556
567
  <button onclick="cancel_inline_edit(event, '${opts}')" type="button" class="btn btn-sm btn-danger"><i class="fas fa-times"></i></button>
557
568
  </form>`
@@ -641,6 +652,7 @@ function initialize_page() {
641
652
  $(initialize_page);
642
653
 
643
654
  function cancel_inline_edit(e, opts1) {
655
+ const isNode = typeof parent?.saltcorn?.data?.state === "undefined";
644
656
  var opts = JSON.parse(decodeURIComponent(opts1 || "") || "{}");
645
657
  var form = $(e.target).closest("form");
646
658
  var json_fk_opt;
@@ -668,17 +680,47 @@ function cancel_inline_edit(e, opts1) {
668
680
  <span class="current">${
669
681
  json_fk_opt || opts.current_label || opts.current
670
682
  }</span>
671
- <i class="editicon fas fa-edit ms-1"></i>
683
+ <i class="editicon ${!isNode ? "visible" : ""} fas fa-edit ms-1"></i>
672
684
  </div>`);
673
685
  initialize_page();
674
686
  }
675
687
 
688
+ function inline_submit_success(e, form, opts) {
689
+ const isNode = typeof parent?.saltcorn?.data?.state === "undefined";
690
+ const formDataArray = form.serializeArray();
691
+ if (opts) {
692
+ let rawVal = formDataArray.find((f) => f.name == opts.key).value;
693
+ let val =
694
+ opts.is_key || (opts.schema && opts.schema.type.startsWith("Key to "))
695
+ ? form.find("select").find("option:selected").text()
696
+ : rawVal;
697
+
698
+ $(e.target).replaceWith(`<div
699
+ data-inline-edit-field="${opts.key}"
700
+ ${opts.ajax ? `data-inline-edit-ajax="true"` : ""}
701
+ ${opts.type ? `data-inline-edit-type="${opts.type}"` : ""}
702
+ ${opts.current ? `data-inline-edit-current="${rawVal}"` : ""}
703
+ ${
704
+ opts.schema
705
+ ? `data-inline-edit-schema="${encodeURIComponent(
706
+ JSON.stringify(opts.schema)
707
+ )}"`
708
+ : ""
709
+ }
710
+ ${opts.current_label ? `data-inline-edit-current-label="${val}"` : ""}
711
+ data-inline-edit-dest-url="${opts.url}">
712
+ <span class="current">${val}</span>
713
+ <i class="editicon ${!isNode ? "visible" : ""} fas fa-edit ms-1"></i>
714
+ </div>`);
715
+ initialize_page();
716
+ } else location.reload();
717
+ }
718
+
676
719
  function inline_ajax_submit(e, opts1) {
677
720
  var opts = JSON.parse(decodeURIComponent(opts1 || "") || "{}");
678
721
  e.preventDefault();
679
722
  var form = $(e.target).closest("form");
680
723
  var form_data = form.serialize();
681
- var formDataArray = form.serializeArray();
682
724
  var url = form.attr("action");
683
725
  $.ajax(url, {
684
726
  type: "POST",
@@ -687,32 +729,7 @@ function inline_ajax_submit(e, opts1) {
687
729
  },
688
730
  data: form_data,
689
731
  success: function (res) {
690
- if (opts) {
691
- let rawVal = formDataArray.find((f) => f.name == opts.key).value;
692
- let val =
693
- opts.is_key || (opts.schema && opts.schema.type.startsWith("Key to "))
694
- ? form.find("select").find("option:selected").text()
695
- : rawVal;
696
-
697
- $(e.target).replaceWith(`<div
698
- data-inline-edit-field="${opts.key}"
699
- ${opts.ajax ? `data-inline-edit-ajax="true"` : ""}
700
- ${opts.type ? `data-inline-edit-type="${opts.type}"` : ""}
701
- ${opts.current ? `data-inline-edit-current="${rawVal}"` : ""}
702
- ${
703
- opts.schema
704
- ? `data-inline-edit-schema="${encodeURIComponent(
705
- JSON.stringify(opts.schema)
706
- )}"`
707
- : ""
708
- }
709
- ${opts.current_label ? `data-inline-edit-current-label="${val}"` : ""}
710
- data-inline-edit-dest-url="${opts.url}">
711
- <span class="current">${val}</span>
712
- <i class="editicon fas fa-edit ms-1"></i>
713
- </div>`);
714
- initialize_page();
715
- } else location.reload();
732
+ inline_submit_success(e, form, opts);
716
733
  },
717
734
  error: function (e) {
718
735
  ajax_done(
@@ -402,3 +402,20 @@ table.table-inner-grid td {
402
402
  div.unread-notify {
403
403
  border-left: 4px solid green;
404
404
  }
405
+
406
+ .mobile-data-inline-edit {
407
+ position: relative;
408
+ }
409
+
410
+ .mobile-data-inline-edit::after {
411
+ content: "";
412
+ position: absolute;
413
+ top: -25%;
414
+ left: 0%;
415
+ width: 100%;
416
+ height: 150%;
417
+ }
418
+
419
+ .mt-6 {
420
+ margin-top: 5rem;
421
+ }
package/routes/admin.js CHANGED
@@ -990,6 +990,9 @@ router.post(
990
990
  child.stdout.on("data", (data) => {
991
991
  res.write(data);
992
992
  });
993
+ child.stderr.on("data", (data) => {
994
+ res.write(data);
995
+ });
993
996
  child.on("exit", function (code, signal) {
994
997
  res.end(
995
998
  req.__(
package/routes/api.js CHANGED
@@ -19,6 +19,7 @@ const Router = require("express-promise-router");
19
19
  const { error_catcher } = require("./utils.js");
20
20
  //const { mkTable, renderForm, link, post_btn } = require("@saltcorn/markup");
21
21
  const { getState } = require("@saltcorn/data/db/state");
22
+ const { prepare_update_row } = require("@saltcorn/data/web-mobile-commons");
22
23
  const Table = require("@saltcorn/data/models/table");
23
24
  const View = require("@saltcorn/data/models/view");
24
25
  //const Field = require("@saltcorn/data/models/field");
@@ -460,39 +461,15 @@ router.post(
460
461
  return;
461
462
  }
462
463
  await passport.authenticate(
463
- "api-bearer",
464
+ ["api-bearer", "jwt"],
464
465
  { session: false },
465
466
  async function (err, user, info) {
466
467
  if (accessAllowedWrite(req, user, table)) {
467
468
  const { _versions, ...row } = req.body;
468
469
  const fields = table.getFields();
469
470
  readState(row, fields, req);
470
- let errors = [];
471
- let hasErrors = false;
472
- for (const k of Object.keys(row)) {
473
- const field = fields.find((f) => f.name === k);
474
- if (!field && k.includes(".")) {
475
- const [fnm, jkey] = k.split(".");
476
- const jfield = fields.find((f) => f.name === fnm);
477
- if (jfield?.type?.name === "JSON") {
478
- if (typeof row[fnm] === "undefined") {
479
- const dbrow = await table.getRow({ [table.pk_name]: id });
480
- row[fnm] = dbrow[fnm] || {};
481
- }
482
- row[fnm][jkey] = row[k];
483
- delete row[k];
484
- }
485
- } else if (!field || field.calculated) {
486
- delete row[k];
487
- } else if (field?.type && field.type.validate) {
488
- const vres = field.type.validate(field.attributes || {})(row[k]);
489
- if (vres.error) {
490
- hasErrors = true;
491
- errors.push(`${k}: ${vres.error}`);
492
- }
493
- }
494
- }
495
- if (hasErrors) {
471
+ const errors = await prepare_update_row(table, row, id);
472
+ if (errors.length > 0) {
496
473
  getState().log(
497
474
  2,
498
475
  `API POST ${table.name} error: ${errors.join(", ")}`
@@ -493,14 +493,22 @@ router.post(
493
493
  * @param {object} res
494
494
  * @returns {void}
495
495
  */
496
- const respondWorkflow = (view, wf, wfres, req, res) => {
496
+ const respondWorkflow = (view, wf, wfres, req, res, table) => {
497
497
  const wrap = (contents, noCard, previewURL) => ({
498
498
  above: [
499
499
  {
500
500
  type: "breadcrumbs",
501
501
  crumbs: [
502
502
  { text: req.__("Views"), href: "/viewedit" },
503
- { href: `/view/${view.name}`, text: view.name },
503
+ {
504
+ href: `/view/${view.name}`,
505
+ text: view.name,
506
+ postLinkText: `[${view.viewtemplate}${
507
+ table
508
+ ? ` on ${a({ href: `/table/` + table.name }, table.name)}`
509
+ : ""
510
+ }]`,
511
+ },
504
512
  { workflow: wf, step: wfres },
505
513
  ],
506
514
  },
@@ -584,6 +592,9 @@ router.get(
584
592
  (view.configuration?.columns || []).forEach((c) => {
585
593
  c._columndef = JSON.stringify(c);
586
594
  });
595
+ let table;
596
+ if (view.table_id) table = Table.findOne({ id: view.table_id });
597
+ if (view.exttable_name) table = Table.findOne({ name: view.exttable_name });
587
598
  const configFlow = await view.get_config_flow(req);
588
599
  const hasConfig =
589
600
  view.configuration && Object.keys(view.configuration).length > 0;
@@ -598,7 +609,7 @@ router.get(
598
609
  },
599
610
  req
600
611
  );
601
- respondWorkflow(view, configFlow, wfres, req, res);
612
+ respondWorkflow(view, configFlow, wfres, req, res, table);
602
613
  })
603
614
  );
604
615
 
@@ -617,7 +628,11 @@ router.post(
617
628
  const view = await View.findOne({ name });
618
629
  const configFlow = await view.get_config_flow(req);
619
630
  const wfres = await configFlow.run(req.body, req);
620
- respondWorkflow(view, configFlow, wfres, req, res);
631
+
632
+ let table;
633
+ if (view.table_id) table = Table.findOne({ id: view.table_id });
634
+ if (view.exttable_name) table = Table.findOne({ name: view.exttable_name });
635
+ respondWorkflow(view, configFlow, wfres, req, res, table);
621
636
  })
622
637
  );
623
638