@saltcorn/builder 0.8.1-beta.5 → 0.8.1-rc.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saltcorn/builder",
3
- "version": "0.8.1-beta.5",
3
+ "version": "0.8.1-rc.2",
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",
@@ -467,8 +467,7 @@ const Builder = ({ options, layout, mode }) => {
467
467
  <HistoryPanel />
468
468
  <FontAwesomeIcon
469
469
  icon={faSave}
470
- title={isSaving ? "Saving..." : "All changes saved"}
471
- className={isSaving ? "text-muted" : ""}
470
+ className={isSaving ? "d-inline" : "d-none"}
472
471
  />
473
472
  <ViewPageLink />
474
473
  <SettingsPanel />
@@ -26,6 +26,7 @@ import { Image } from "./elements/Image";
26
26
  import { View } from "./elements/View";
27
27
  import { SearchBar } from "./elements/SearchBar";
28
28
  import { Link } from "./elements/Link";
29
+ import { Page } from "./elements/Page";
29
30
  import optionsCtx from "./context";
30
31
  import {
31
32
  BoundingBox,
@@ -359,6 +360,20 @@ const DropMenuElem = ({ connectors }) => (
359
360
  </WrapElem>
360
361
  );
361
362
 
363
+ const PageElem = ({connectors, pages}) => (
364
+ <WrapElem
365
+ connectors={connectors}
366
+ icon="fa-fw far fa-file"
367
+ title="Embed a page"
368
+ label="Page"
369
+ disable={pages.length <= 1}
370
+ >
371
+ <Page
372
+ page={pages.length > 0 ? pages[0].name : "page"}
373
+ />
374
+ </WrapElem>
375
+ );
376
+
362
377
  /**
363
378
  * @param {object} props
364
379
  * @param {object} props.connectors
@@ -654,7 +669,7 @@ export /**
654
669
  const ToolboxPage = () => {
655
670
  const { connectors, query } = useEditor();
656
671
  const options = useContext(optionsCtx);
657
- const { views, images } = options;
672
+ const { views, pages, images } = options;
658
673
  return (
659
674
  <Fragment>
660
675
  <div className="toolbar-row">
@@ -683,6 +698,7 @@ const ToolboxPage = () => {
683
698
  </div>
684
699
  <div className="toolbar-row">
685
700
  <DropMenuElem connectors={connectors} />
701
+ <PageElem connectors={connectors} pages={pages} />
686
702
  </div>
687
703
  </Fragment>
688
704
  );
@@ -104,6 +104,15 @@ const CardSettings = () => {
104
104
  node={node}
105
105
  setProp={setProp}
106
106
  />
107
+ <SettingsRow
108
+ field={{
109
+ label: "Save indicator",
110
+ name: "titleAjaxIndicator",
111
+ type: "Bool",
112
+ }}
113
+ node={node}
114
+ setProp={setProp}
115
+ />
107
116
  <SettingsRow
108
117
  field={{ label: "No padding", name: "noPadding", type: "Bool" }}
109
118
  node={node}
@@ -127,6 +136,7 @@ const fields = [
127
136
  },
128
137
  { label: "URL", name: "url", type: "String", canBeFormula: true },
129
138
  { label: "Shadow", name: "shadow", type: "Bool" },
139
+ { label: "Save indicator", name: "titleAjaxIndicator", type: "Bool" },
130
140
  { label: "No padding", name: "noPadding", type: "Bool" },
131
141
  { name: "style", default: {} },
132
142
  ];
@@ -0,0 +1,102 @@
1
+ import React, { Fragment, useContext, useEffect } from "react";
2
+ import { useNode } from "@craftjs/core";
3
+ import optionsCtx from "../context";
4
+ import previewCtx from "../preview_context";
5
+ import { fetchPagePreview, setAPropGen } from "./utils";
6
+
7
+ export const Page = ({ page }) => {
8
+ const {
9
+ selected,
10
+ node_id,
11
+ connectors: { connect, drag },
12
+ } = useNode((node) => ({ selected: node.events.selected, node_id: node.id }));
13
+ const options = useContext(optionsCtx);
14
+ const { previews, setPreviews } = useContext(previewCtx);
15
+ const myPreview = previews[node_id];
16
+ useEffect(() => {
17
+ fetchPagePreview({
18
+ options,
19
+ page,
20
+ setPreviews,
21
+ node_id,
22
+ })();
23
+ }, [page]);
24
+
25
+ return (
26
+ <div
27
+ ref={(dom) => connect(drag(dom))}
28
+ className={`${myPreview ? "" : "builder-embed-view"} ${
29
+ selected ? "selected-node" : ""
30
+ }`}
31
+ >
32
+ {myPreview ? (
33
+ <div
34
+ className="d-inline"
35
+ dangerouslySetInnerHTML={{ __html: myPreview }}
36
+ ></div>
37
+ ) : (
38
+ `Page: ${page}`
39
+ )}
40
+ </div>
41
+ );
42
+ };
43
+
44
+ export const PageSettings = () => {
45
+ const node = useNode((node) => ({
46
+ page: node.data.props.page,
47
+ node_id: node.id,
48
+ }));
49
+ const {
50
+ actions: { setProp },
51
+ page,
52
+ node_id,
53
+ } = node;
54
+ const options = useContext(optionsCtx);
55
+ const pages = options.pages;
56
+ const setAProp = setAPropGen(setProp);
57
+ return (
58
+ <div>
59
+ <Fragment>
60
+ <div>
61
+ <label>Page to embed</label>
62
+ <select
63
+ value={page}
64
+ className="form-control form-select"
65
+ onChange={setAProp("page")}
66
+ onBlur={setAProp("page")}
67
+ >
68
+ {pages
69
+ .filter((p) =>
70
+ options.page_name ? p.name !== options.page_name : true
71
+ )
72
+ .map((p, ix) => (
73
+ <option key={ix} value={p.name}>
74
+ {p.name}
75
+ </option>
76
+ ))}
77
+ </select>
78
+ </div>
79
+ </Fragment>
80
+ {page ? (
81
+ <a
82
+ className="d-block mt-2"
83
+ target="_blank"
84
+ href={`/pageedit/edit/${page}`}
85
+ >
86
+ Edit this page
87
+ </a>
88
+ ) : null}
89
+ </div>
90
+ );
91
+ };
92
+
93
+ Page.craft = {
94
+ displayName: "Page",
95
+ related: {
96
+ settings: PageSettings,
97
+ segment_type: "page",
98
+ fields: [
99
+ "page",
100
+ ],
101
+ },
102
+ };
@@ -405,6 +405,7 @@ const fetchPreview = ({ url, body, options, setPreviews, node_id, isView }) => {
405
405
  headers: {
406
406
  "Content-Type": "application/json",
407
407
  "CSRF-Token": options.csrfToken,
408
+ "X-Requested-With": "XMLHttpRequest",
408
409
  },
409
410
  body: JSON.stringify(body),
410
411
  })
@@ -487,6 +488,23 @@ export const fetchViewPreview =
487
488
  });
488
489
  };
489
490
 
491
+ export const fetchPagePreview =
492
+ (args = {}) =>
493
+ (changes = {}) => {
494
+ const { node_id, options, page, setPreviews } = {
495
+ ...args,
496
+ ...changes,
497
+ };
498
+ fetchPreview({
499
+ options,
500
+ node_id,
501
+ setPreviews,
502
+ url: `/page/${page}/preview`,
503
+ body: {},
504
+ isView: true, // disables inputs
505
+ });
506
+ };
507
+
490
508
  export /**
491
509
  * @param {object} props
492
510
  * @param {boolean} props.vert
@@ -21,6 +21,7 @@ import { Card } from "./elements/Card";
21
21
  import { Image } from "./elements/Image";
22
22
  import { Link } from "./elements/Link";
23
23
  import { View } from "./elements/View";
24
+ import { Page } from "./elements/Page";
24
25
  import { SearchBar } from "./elements/SearchBar";
25
26
  import { Container } from "./elements/Container";
26
27
  import { DropDownFilter } from "./elements/DropDownFilter";
@@ -71,6 +72,7 @@ const allElements = [
71
72
  Tabs,
72
73
  ToggleFilter,
73
74
  DropMenu,
75
+ Page,
74
76
  ];
75
77
 
76
78
  export /**
@@ -147,7 +149,8 @@ export /**
147
149
  configuration={segment.configuration || {}}
148
150
  />
149
151
  );
150
- } else if (segment.type === "action") {
152
+ }
153
+ else if (segment.type === "action") {
151
154
  return (
152
155
  <Action
153
156
  key={ix}
@@ -461,7 +464,6 @@ export /**
461
464
  extra_state_fml: node.props.extra_state_fml,
462
465
  };
463
466
  }
464
-
465
467
  if (node.displayName === Action.craft.displayName) {
466
468
  const newid = rand_ident();
467
469
  columns.push({