@saltcorn/builder 0.5.6-beta.2 → 0.6.0-alpha.0

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.
@@ -1,9 +1,13 @@
1
1
  import React, { Fragment, useContext } from "react";
2
2
  import { useNode } from "@craftjs/core";
3
- import { blockProps, BlockSetting, TextStyleSetting, OrFormula } from "./utils";
3
+ import {
4
+ blockProps,
5
+ BlockSetting,
6
+ TextStyleSetting,
7
+ OrFormula,
8
+ ButtonOrLinkSettingsRows,
9
+ } from "./utils";
4
10
  import optionsCtx from "../context";
5
- import FontIconPicker from "@fonticonpicker/react-fonticonpicker";
6
- import faIcons from "./faicons";
7
11
 
8
12
  export const Link = ({
9
13
  text,
@@ -13,6 +17,9 @@ export const Link = ({
13
17
  link_style,
14
18
  link_size,
15
19
  link_icon,
20
+ link_bgcol,
21
+ link_bordercol,
22
+ link_textcol,
16
23
  }) => {
17
24
  const {
18
25
  selected,
@@ -25,6 +32,15 @@ export const Link = ({
25
32
  } ${isFormula.text ? "text-monospace" : ""} ${link_style} ${link_size}`}
26
33
  {...blockProps(block)}
27
34
  ref={(dom) => connect(drag(dom))}
35
+ style={
36
+ link_style === "btn btn-custom-color"
37
+ ? {
38
+ backgroundColor: link_bgcol || "#000000",
39
+ borderColor: link_bordercol || "#000000",
40
+ color: link_textcol || "#000000",
41
+ }
42
+ : {}
43
+ }
28
44
  >
29
45
  {link_icon ? <i className={`${link_icon} mr-1`}></i> : ""}
30
46
  {isFormula.text ? `=${text}` : text}
@@ -45,6 +61,9 @@ export const LinkSettings = () => {
45
61
  link_style: node.data.props.link_style,
46
62
  link_size: node.data.props.link_size,
47
63
  link_icon: node.data.props.link_icon,
64
+ link_bgcol: node.data.props.link_bgcol,
65
+ link_bordercol: node.data.props.link_bordercol,
66
+ link_textcol: node.data.props.link_textcol,
48
67
  }));
49
68
  const {
50
69
  actions: { setProp },
@@ -56,140 +75,124 @@ export const LinkSettings = () => {
56
75
  nofollow,
57
76
  target_blank,
58
77
  link_src,
59
- link_style,
60
- link_size,
61
- link_icon,
62
78
  } = node;
63
79
  const options = useContext(optionsCtx);
80
+ const setAProp = (key) => (e) => {
81
+ if (e.target) {
82
+ const target_value = e.target.value;
83
+ setProp((prop) => (prop[key] = target_value));
84
+ }
85
+ };
64
86
  return (
65
87
  <div>
66
- <label>Text to display</label>
67
- <OrFormula nodekey="text" {...{ setProp, isFormula, node }}>
68
- <input
69
- type="text"
70
- className="form-control text-to-display"
71
- value={text}
72
- onChange={(e) => setProp((prop) => (prop.text = e.target.value))}
73
- />
74
- </OrFormula>
75
- <label>Link source</label>
76
- <select
77
- value={link_src}
78
- className="form-control"
79
- onChange={(e) =>
80
- setProp((prop) => {
81
- prop.link_src = e.target.value;
82
- if (e.target.value !== "URL") {
83
- prop.isFormula.url = false;
84
- }
85
- })
86
- }
87
- >
88
- <option>URL</option>
89
- {(options.pages || []).length > 0 && <option>Page</option>}
90
- {(options.views || []).length > 0 && options.mode === "page" && (
91
- <option>View</option>
92
- )}
93
- </select>
94
- {link_src === "URL" && (
95
- <Fragment>
96
- {" "}
97
- <label>URL</label>
98
- <OrFormula nodekey="url" {...{ setProp, isFormula, node }}>
99
- <input
100
- type="text"
101
- className="form-control "
102
- value={url}
103
- onChange={(e) => setProp((prop) => (prop.url = e.target.value))}
104
- />
105
- </OrFormula>
106
- </Fragment>
107
- )}
108
- {link_src === "Page" && (
109
- <Fragment>
110
- {" "}
111
- <label>Page</label>
112
- <select
113
- value={url}
114
- className="form-control"
115
- onChange={(e) =>
116
- setProp((prop) => {
117
- prop.url = e.target.value;
118
- })
119
- }
120
- >
121
- <option></option>
122
- {(options.pages || []).map((p) => (
123
- <option value={`/page/${p.name}`}>{p.name}</option>
124
- ))}
125
- </select>
126
- </Fragment>
127
- )}
128
- {link_src === "View" && (
129
- <Fragment>
130
- {" "}
131
- <label>View</label>
132
- <select
133
- value={url}
134
- className="form-control"
135
- onChange={(e) =>
136
- setProp((prop) => {
137
- prop.url = e.target.value;
138
- })
139
- }
140
- >
141
- <option></option>
142
- {(options.views || []).map((p) => (
143
- <option value={`/view/${p.name}`}>
144
- {p.name} [{p.viewtemplate}]
145
- </option>
146
- ))}
147
- </select>
148
- </Fragment>
149
- )}
150
- <div>
151
- <label>Link style</label>
152
- <select
153
- className="form-control"
154
- value={link_style}
155
- onChange={(e) =>
156
- setProp((prop) => (prop.link_style = e.target.value))
157
- }
158
- >
159
- <option value="">Link</option>
160
- <option value="btn btn-primary">Primary button</option>
161
- <option value="btn btn-secondary">Secondary button</option>
162
- <option value="btn btn-success">Success button</option>
163
- <option value="btn btn-danger">Danger button</option>
164
- <option value="btn btn-outline-primary">
165
- Primary outline button
166
- </option>
167
- <option value="btn btn-outline-secondary">
168
- Secondary outline button
169
- </option>
170
- </select>
171
- </div>
172
- <div>
173
- <label>Link size</label>
174
- <select
175
- className="form-control"
176
- value={link_size}
177
- onChange={(e) => setProp((prop) => (prop.link_size = e.target.value))}
178
- >
179
- <option value="">Standard</option>
180
- <option value="btn-lg">Large</option>
181
- <option value="btn-sm">Small</option>
182
- <option value="btn-block">Block</option>
183
- <option value="btn-block btn-lg">Large block</option>
184
- </select>
185
- </div>
186
- <label className="mr-2">Icon</label>
187
- <FontIconPicker
188
- value={link_icon}
189
- icons={faIcons}
190
- onChange={(value) => setProp((prop) => (prop.link_icon = value))}
191
- isMulti={false}
192
- />
88
+ <table className="w-100">
89
+ <tbody>
90
+ <tr>
91
+ <td>
92
+ <label>Text to display</label>
93
+ </td>
94
+ <td>
95
+ <OrFormula nodekey="text" {...{ setProp, isFormula, node }}>
96
+ <input
97
+ type="text"
98
+ className="form-control text-to-display"
99
+ value={text}
100
+ onChange={setAProp("text")}
101
+ />
102
+ </OrFormula>
103
+ </td>
104
+ </tr>
105
+ <tr>
106
+ <td>
107
+ <label>Link source</label>
108
+ </td>
109
+ <td>
110
+ <select
111
+ value={link_src}
112
+ className="form-control"
113
+ onChange={(e) =>
114
+ setProp((prop) => {
115
+ prop.link_src = e.target.value;
116
+ if (e.target.value !== "URL") {
117
+ prop.isFormula.url = false;
118
+ }
119
+ })
120
+ }
121
+ >
122
+ <option>URL</option>
123
+ {(options.pages || []).length > 0 && <option>Page</option>}
124
+ {(options.views || []).length > 0 &&
125
+ options.mode === "page" && <option>View</option>}
126
+ </select>
127
+ </td>
128
+ </tr>
129
+ {link_src === "URL" && (
130
+ <tr>
131
+ <td>
132
+ <label>URL</label>
133
+ </td>
134
+ <td>
135
+ <OrFormula nodekey="url" {...{ setProp, isFormula, node }}>
136
+ <input
137
+ type="text"
138
+ className="form-control "
139
+ value={url}
140
+ onChange={setAProp("url")}
141
+ />
142
+ </OrFormula>
143
+ </td>
144
+ </tr>
145
+ )}
146
+ {link_src === "Page" && (
147
+ <tr>
148
+ <td>
149
+ <label>Page</label>
150
+ </td>
151
+ <td>
152
+ <select
153
+ value={url}
154
+ className="form-control"
155
+ onChange={setAProp("url")}
156
+ >
157
+ <option></option>
158
+ {(options.pages || []).map((p) => (
159
+ <option value={`/page/${p.name}`}>{p.name}</option>
160
+ ))}
161
+ </select>
162
+ </td>
163
+ </tr>
164
+ )}
165
+ {link_src === "View" && (
166
+ <tr>
167
+ <td>
168
+ <label>View</label>
169
+ </td>
170
+ <td>
171
+ <select
172
+ value={url}
173
+ className="form-control"
174
+ onChange={setAProp("url")}
175
+ >
176
+ <option></option>
177
+ {(options.views || []).map((p) => (
178
+ <option value={`/view/${p.name}`}>
179
+ {p.name} [{p.viewtemplate}]
180
+ </option>
181
+ ))}
182
+ </select>
183
+ </td>
184
+ </tr>
185
+ )}
186
+ <ButtonOrLinkSettingsRows
187
+ setProp={setProp}
188
+ keyPrefix="link_"
189
+ btnClass="btn"
190
+ values={node}
191
+ linkFirst={true}
192
+ />
193
+ </tbody>
194
+ </table>
195
+
193
196
  <div className="form-check">
194
197
  <input
195
198
  className="form-check-input"
@@ -246,6 +249,9 @@ Link.craft = {
246
249
  "link_size",
247
250
  "link_icon",
248
251
  "link_style",
252
+ "link_bgcol",
253
+ "link_bordercol",
254
+ "link_textcol",
249
255
  ],
250
256
  },
251
257
  };
@@ -25,7 +25,7 @@ export const SearchBar = ({ has_dropdown, contents, show_badges }) => {
25
25
  >
26
26
  <div className="input-group-prepend">
27
27
  <button className="btn btn-outline-secondary" disabled>
28
- <i class="fas fa-search"></i>
28
+ <i className="fas fa-search"></i>
29
29
  </button>
30
30
  </div>
31
31
  <input
@@ -6,6 +6,7 @@ import {
6
6
  TextStyleSetting,
7
7
  OrFormula,
8
8
  ErrorBoundary,
9
+ TextStyleRow,
9
10
  } from "./utils";
10
11
  import ContentEditable from "react-contenteditable";
11
12
  import optionsCtx from "../context";
@@ -44,7 +45,7 @@ const ckConfig = {
44
45
  function escape_tags(str) {
45
46
  return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
46
47
  }
47
- export const Text = ({ text, block, isFormula, textStyle, icon }) => {
48
+ export const Text = ({ text, block, isFormula, textStyle, icon, font }) => {
48
49
  const {
49
50
  connectors: { connect, drag },
50
51
  selected,
@@ -66,6 +67,7 @@ export const Text = ({ text, block, isFormula, textStyle, icon }) => {
66
67
  {...blockProps(block)}
67
68
  ref={(dom) => connect(drag(dom))}
68
69
  onClick={(e) => selected && setEditable(true)}
70
+ style={font ? { fontFamily: font } : {}}
69
71
  >
70
72
  {icon ? <i className={`${icon} mr-1`}></i> : ""}
71
73
  {isFormula.text ? (
@@ -106,6 +108,7 @@ export const TextSettings = () => {
106
108
  textStyle: node.data.props.textStyle,
107
109
  labelFor: node.data.props.labelFor,
108
110
  icon: node.data.props.icon,
111
+ font: node.data.props.font,
109
112
  }));
110
113
  const {
111
114
  actions: { setProp },
@@ -115,8 +118,15 @@ export const TextSettings = () => {
115
118
  isFormula,
116
119
  labelFor,
117
120
  icon,
121
+ font,
118
122
  } = node;
119
123
  const { mode, fields } = useContext(optionsCtx);
124
+ const setAProp = (key) => (e) => {
125
+ if (e.target) {
126
+ const target_value = e.target.value;
127
+ setProp((prop) => (prop[key] = target_value));
128
+ }
129
+ };
120
130
  return (
121
131
  <div>
122
132
  {mode === "show" && (
@@ -132,35 +142,35 @@ export const TextSettings = () => {
132
142
  <label className="form-check-label">Formula?</label>
133
143
  </div>
134
144
  )}
135
- <label>Text to display:</label>
145
+ <label>Text to display</label>
136
146
  {mode === "show" && isFormula.text ? (
137
147
  <input
138
148
  type="text"
139
149
  className="text-to-display form-control"
140
150
  value={text}
141
- onChange={(e) => setProp((prop) => (prop.text = e.target.value))}
151
+ onChange={setAProp("text")}
142
152
  />
143
153
  ) : (
144
154
  <ErrorBoundary>
145
- <CKEditor
146
- data={text}
147
- onChange={(e) =>
148
- setProp((props) => (props.text = e.editor.getData()))
149
- }
150
- config={ckConfig}
151
- type="inline"
152
- />
155
+ <div className="border">
156
+ <CKEditor
157
+ data={text}
158
+ onChange={(e) => {
159
+ if (e.editor) {
160
+ const text = e.editor.getData();
161
+ setProp((props) => (props.text = text));
162
+ }
163
+ }}
164
+ config={ckConfig}
165
+ type="inline"
166
+ />
167
+ </div>
153
168
  </ErrorBoundary>
154
169
  )}
155
170
  {mode === "edit" && (
156
171
  <Fragment>
157
172
  <label>Label for Field</label>
158
- <select
159
- value={labelFor}
160
- onChange={(e) => {
161
- setProp((prop) => (prop.labelFor = e.target.value));
162
- }}
163
- >
173
+ <select value={labelFor} onChange={setAProp("labelFor")}>
164
174
  <option value={""}></option>
165
175
  {fields.map((f, ix) => (
166
176
  <option key={ix} value={f.name}>
@@ -170,16 +180,39 @@ export const TextSettings = () => {
170
180
  </select>
171
181
  </Fragment>
172
182
  )}
173
- <br />
174
- <label>Icon</label>
175
- <FontIconPicker
176
- value={icon}
177
- icons={faIcons}
178
- onChange={(value) => setProp((prop) => (prop.icon = value))}
179
- isMulti={false}
180
- />
183
+ <table className="w-100 mt-2">
184
+ <tbody>
185
+ <TextStyleRow textStyle={textStyle} setProp={setProp} />
186
+ <tr>
187
+ <td>
188
+ <label>Icon</label>
189
+ </td>
190
+ <td>
191
+ <FontIconPicker
192
+ className="w-100"
193
+ value={icon}
194
+ icons={faIcons}
195
+ onChange={(value) => setProp((prop) => (prop.icon = value))}
196
+ isMulti={false}
197
+ />
198
+ </td>
199
+ </tr>
200
+ <tr>
201
+ <td>
202
+ <label>Font</label>
203
+ </td>
204
+ <td>
205
+ <input
206
+ type="text"
207
+ className="form-control"
208
+ value={font}
209
+ onChange={setAProp("font")}
210
+ />
211
+ </td>
212
+ </tr>
213
+ </tbody>
214
+ </table>
181
215
  <BlockSetting block={block} setProp={setProp} />
182
- <TextStyleSetting textStyle={textStyle} setProp={setProp} />
183
216
  </div>
184
217
  );
185
218
  };
@@ -191,6 +224,7 @@ Text.craft = {
191
224
  isFormula: {},
192
225
  textStyle: "",
193
226
  labelFor: "",
227
+ font: "",
194
228
  },
195
229
  displayName: "Text",
196
230
  related: {
@@ -52,6 +52,12 @@ export const ToggleFilterSettings = () => {
52
52
  const field = options.fields.find((f) => f.name === name);
53
53
  const preset_options = field.preset_options;
54
54
  const isBool = field && field.type.name === "Bool";
55
+ const setAProp = (key) => (e) => {
56
+ if (e.target) {
57
+ const target_value = e.target.value;
58
+ setProp((prop) => (prop[key] = target_value));
59
+ }
60
+ };
55
61
  return (
56
62
  <table className="w-100">
57
63
  <tbody>
@@ -90,9 +96,7 @@ export const ToggleFilterSettings = () => {
90
96
  <select
91
97
  value={value}
92
98
  className="w-100"
93
- onChange={(e) =>
94
- setProp((prop) => (prop.value = e.target.value))
95
- }
99
+ onChange={setAProp("value")}
96
100
  >
97
101
  <option value="on">True</option>
98
102
  <option value="off">False</option>
@@ -102,9 +106,7 @@ export const ToggleFilterSettings = () => {
102
106
  <input
103
107
  value={value}
104
108
  className="w-100"
105
- onChange={(e) =>
106
- setProp((prop) => (prop.value = e.target.value))
107
- }
109
+ onChange={setAProp("value")}
108
110
  />
109
111
  )}
110
112
  </td>
@@ -118,9 +120,7 @@ export const ToggleFilterSettings = () => {
118
120
  <select
119
121
  value={preset_value}
120
122
  className="form-control"
121
- onChange={(e) => {
122
- setProp((prop) => (prop.preset_value = e.target.value));
123
- }}
123
+ onChange={setAProp("preset_value")}
124
124
  >
125
125
  <option value=""></option>
126
126
  {preset_options.map((po, ix) => (
@@ -140,7 +140,7 @@ export const ToggleFilterSettings = () => {
140
140
  <input
141
141
  value={label}
142
142
  className="w-100"
143
- onChange={(e) => setProp((prop) => (prop.label = e.target.value))}
143
+ onChange={setAProp("label")}
144
144
  />
145
145
  </td>
146
146
  </tr>
@@ -149,11 +149,10 @@ export const ToggleFilterSettings = () => {
149
149
  <label>Button size</label>
150
150
  </td>
151
151
  <td>
152
- {" "}
153
152
  <select
154
153
  className="form-control"
155
154
  value={size}
156
- onChange={(e) => setProp((prop) => (prop.size = e.target.value))}
155
+ onChange={setAProp("size")}
157
156
  >
158
157
  <option value="">Standard</option>
159
158
  <option value="btn-lg">Large</option>
@@ -169,11 +168,10 @@ export const ToggleFilterSettings = () => {
169
168
  <label>Button style</label>
170
169
  </td>
171
170
  <td>
172
- {" "}
173
171
  <select
174
172
  className="form-control"
175
173
  value={style}
176
- onChange={(e) => setProp((prop) => (prop.style = e.target.value))}
174
+ onChange={setAProp("style")}
177
175
  >
178
176
  <option value="primary">Primary</option>
179
177
  <option value="secondary">Secondary</option>
@@ -1,4 +1,4 @@
1
- import React, { useContext, useEffect } from "react";
1
+ import React, { Fragment, useContext, useEffect } from "react";
2
2
  import { useNode } from "@craftjs/core";
3
3
  import optionsCtx from "../context";
4
4
  import previewCtx from "../preview_context";
@@ -8,6 +8,7 @@ import {
8
8
  BlockSetting,
9
9
  MinRoleSetting,
10
10
  fetchViewPreview,
11
+ ConfigForm,
11
12
  } from "./utils";
12
13
 
13
14
  export const View = ({ name, view, state }) => {
@@ -51,20 +52,26 @@ export const View = ({ name, view, state }) => {
51
52
  };
52
53
 
53
54
  export const ViewSettings = () => {
55
+ const node = useNode((node) => ({
56
+ name: node.data.props.name,
57
+ view: node.data.props.view,
58
+ state: node.data.props.state,
59
+ configuration: node.data.props.configuration, // fixed states
60
+ node_id: node.id,
61
+ }));
62
+
54
63
  const {
55
64
  actions: { setProp },
56
65
  name,
57
66
  view,
58
67
  state,
59
68
  node_id,
60
- } = useNode((node) => ({
61
- name: node.data.props.name,
62
- view: node.data.props.view,
63
- state: node.data.props.state,
64
- node_id: node.id,
65
- }));
69
+ configuration,
70
+ } = node;
66
71
  const options = useContext(optionsCtx);
67
72
  const views = options.views;
73
+ const fixed_state_fields =
74
+ options.fixed_state_fields && options.fixed_state_fields[view];
68
75
  const { setPreviews } = useContext(previewCtx);
69
76
  const refetchPreview = fetchViewPreview({
70
77
  options,
@@ -72,7 +79,12 @@ export const ViewSettings = () => {
72
79
  setPreviews,
73
80
  node_id,
74
81
  });
75
- //console.log(options)
82
+ const setAProp = (key) => (e) => {
83
+ if (e.target) {
84
+ const target_value = e.target.value;
85
+ setProp((prop) => (prop[key] = target_value));
86
+ }
87
+ };
76
88
  return (
77
89
  <div>
78
90
  <div>
@@ -93,17 +105,32 @@ export const ViewSettings = () => {
93
105
  </select>
94
106
  </div>
95
107
  {options.mode === "page" && (
96
- <div>
97
- <label>State</label>
98
- <select
99
- value={state}
100
- className="form-control"
101
- onChange={(e) => setProp((prop) => (prop.state = e.target.value))}
102
- >
103
- <option value="shared">Shared</option>
104
- <option value="fixed">Fixed</option>
105
- </select>
106
- </div>
108
+ <Fragment>
109
+ <div>
110
+ <label>State</label>
111
+ <select
112
+ value={state}
113
+ className="form-control"
114
+ onChange={setAProp("state")}
115
+ >
116
+ <option value="shared">Shared</option>
117
+ <option value="fixed">Fixed</option>
118
+ </select>
119
+ </div>
120
+ {state === "fixed" &&
121
+ fixed_state_fields &&
122
+ fixed_state_fields.length > 0 && (
123
+ <Fragment>
124
+ <h6>View state fields</h6>
125
+ <ConfigForm
126
+ fields={fixed_state_fields}
127
+ configuration={configuration || {}}
128
+ setProp={setProp}
129
+ node={node}
130
+ />
131
+ </Fragment>
132
+ )}
133
+ </Fragment>
107
134
  )}
108
135
  </div>
109
136
  );