@saltcorn/builder 0.9.3-beta.1 → 0.9.3-beta.3

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,6 +1,6 @@
1
1
  {
2
2
  "name": "@saltcorn/builder",
3
- "version": "0.9.3-beta.1",
3
+ "version": "0.9.3-beta.3",
4
4
  "description": "Drag and drop view builder for Saltcorn, open-source no-code platform",
5
5
  "main": "index.js",
6
6
  "homepage": "https://saltcorn.com",
@@ -336,6 +336,9 @@ const ActionSettings = () => {
336
336
  });
337
337
  }}
338
338
  >
339
+ <option value="" disabled>
340
+ Select action...
341
+ </option>
339
342
  {options.actions
340
343
  .filter((f) => !(options.builtInActions || []).includes(f))
341
344
  .map((f, ix) => (
@@ -344,20 +347,24 @@ const ActionSettings = () => {
344
347
  </option>
345
348
  ))}
346
349
  </select>
347
- <label>Only if... (formula)</label>
348
- <input
349
- type="text"
350
- className="form-control text-to-display"
351
- value={step_only_ifs?.[use_setting_action_n] || ""}
352
- onChange={(e) => {
353
- if (!e.target) return;
354
- const value = e.target.value;
355
- setProp((prop) => {
356
- if (!prop.step_only_ifs) prop.step_only_ifs = [];
357
- prop.step_only_ifs[use_setting_action_n] = value;
358
- });
359
- }}
360
- />
350
+ {options.mode !== "page" ? (
351
+ <Fragment>
352
+ <label>Only if... (formula)</label>
353
+ <input
354
+ type="text"
355
+ className="form-control text-to-display"
356
+ value={step_only_ifs?.[use_setting_action_n] || ""}
357
+ onChange={(e) => {
358
+ if (!e.target) return;
359
+ const value = e.target.value;
360
+ setProp((prop) => {
361
+ if (!prop.step_only_ifs) prop.step_only_ifs = [];
362
+ prop.step_only_ifs[use_setting_action_n] = value;
363
+ });
364
+ }}
365
+ />
366
+ </Fragment>
367
+ ) : null}
361
368
  {stepCfgFields ? (
362
369
  <Fragment>
363
370
  Step configuration:
@@ -97,6 +97,7 @@ const FieldSettings = () => {
97
97
  node_id,
98
98
  click_to_edit,
99
99
  textStyle,
100
+ onchange_action,
100
101
  } = useNode((node) => ({
101
102
  name: node.data.props.name,
102
103
  fieldview: node.data.props.fieldview,
@@ -104,6 +105,7 @@ const FieldSettings = () => {
104
105
  click_to_edit: node.data.props.click_to_edit,
105
106
  inline: node.data.props.inline,
106
107
  textStyle: node.data.props.textStyle,
108
+ onchange_action: node.data.props.onchange_action,
107
109
  configuration: node.data.props.configuration,
108
110
  node_id: node.id,
109
111
  }));
@@ -249,6 +251,38 @@ const FieldSettings = () => {
249
251
  onChange={(k, v) => refetchPreview({ configuration: { [k]: v } })}
250
252
  />
251
253
  ) : null}
254
+ {options.mode === "edit" && options.triggerActions ? (
255
+ <Fragment>
256
+ <label>On change action</label>
257
+ <select
258
+ value={onchange_action}
259
+ className="form-control form-select"
260
+ onChange={(e) => {
261
+ if (!e.target) return;
262
+ const value = e.target.value;
263
+ setProp((prop) => {
264
+ prop.onchange_action = value;
265
+ });
266
+ }}
267
+ >
268
+ <option value="">None</option>
269
+ {options.triggerActions.map((f, ix) => (
270
+ <option key={ix} value={f}>
271
+ {f}
272
+ </option>
273
+ ))}
274
+ </select>
275
+ {onchange_action ? (
276
+ <a
277
+ className="d-block mt-2"
278
+ target="_blank"
279
+ href={`/actions/configure/${onchange_action}`}
280
+ >
281
+ Configure this action
282
+ </a>
283
+ ) : null}
284
+ </Fragment>
285
+ ) : null}
252
286
  </Fragment>
253
287
  );
254
288
  };
@@ -269,6 +303,7 @@ Field.craft = {
269
303
  "block",
270
304
  "inline",
271
305
  "click_to_edit",
306
+ "onchange_action",
272
307
  { name: "configuration", default: {} },
273
308
  ],
274
309
  },
@@ -4,7 +4,7 @@
4
4
  * @subcategory components / elements
5
5
  */
6
6
  /* globals $, _sc_globalCsrf*/
7
- import React, { Fragment, useState } from "react";
7
+ import React, { Fragment, useState, useEffect } from "react";
8
8
  import optionsCtx from "../context";
9
9
  import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
10
10
  import {
@@ -775,13 +775,29 @@ const ConfigField = ({
775
775
  : field.attributes.options;
776
776
  if (!field.required && field.options) field.options.unshift("");
777
777
  }
778
+ const field_type = field.input_type || field.type.name || field.type;
779
+ const hasSelect =
780
+ (field_type === "String" && field.attributes?.options) ||
781
+ field_type === "select";
782
+ const getOptions = () =>
783
+ typeof field?.attributes?.options === "string"
784
+ ? field.attributes.options.split(",").map((s) => s.trim())
785
+ : field?.attributes?.options || field.options;
786
+
787
+ if (hasSelect && typeof value === "undefined") {
788
+ //pick first value to mimic html form behaviour
789
+ const options = getOptions();
790
+ let o;
791
+ if ((o = options[0]))
792
+ useEffect(() => {
793
+ myOnChange(typeof o === "string" ? o : o.value || o.name || o);
794
+ }, []);
795
+ }
796
+
778
797
  const dispatch = {
779
798
  String() {
780
799
  if (field.attributes?.options) {
781
- const options =
782
- typeof field.attributes.options === "string"
783
- ? field.attributes.options.split(",").map((s) => s.trim())
784
- : field.attributes.options;
800
+ const options = getOptions();
785
801
  return (
786
802
  <select
787
803
  className="form-control form-select"
@@ -973,7 +989,7 @@ const ConfigField = ({
973
989
  );
974
990
  },
975
991
  };
976
- const f = dispatch[field.input_type || field.type.name || field.type];
992
+ const f = dispatch[field_type];
977
993
  return f ? f() : null;
978
994
  };
979
995