alchemy-form 0.2.9 → 0.3.0-alpha.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.
- package/CHANGELOG.md +15 -0
- package/assets/stylesheets/form/elements/_code_input.scss +0 -1
- package/assets/stylesheets/form/elements/_field.scss +15 -0
- package/assets/stylesheets/form/elements/_settings_editor.scss +62 -0
- package/assets/stylesheets/form/elements/_table.scss +0 -1
- package/assets/stylesheets/form/elements/_virtual_scroll.scss +19 -0
- package/assets/stylesheets/form/elements/index.scss +3 -1
- package/config/routes.js +3 -3
- package/controller/form_api_controller.js +2 -4
- package/element/00_form_base.js +21 -0
- package/element/al_code_input.js +51 -13
- package/element/al_field.js +25 -24
- package/element/al_form.js +12 -4
- package/element/al_select.js +2 -1
- package/element/al_settings_editor.js +367 -0
- package/element/al_table.js +13 -7
- package/element/al_virtual_scroll.js +873 -0
- package/package.json +3 -3
- package/view/form/elements/al_settings_editor.hwk +36 -0
- package/view/form/inputs/edit/object.hwk +9 -0
- package/view/form/inputs/edit/settings.hwk +5 -0
- package/view/form/inputs/view/string.hwk +14 -1
- package/view/form/wrappers/default/default.hwk +18 -2
- /package/element/{al_string_input.js → 50-al_string_input.js} +0 -0
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The settings editor
|
|
3
|
+
*
|
|
4
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
5
|
+
* @since 0.3.0
|
|
6
|
+
* @version 0.3.0
|
|
7
|
+
*/
|
|
8
|
+
const SettingsEditor = Function.inherits('Alchemy.Element.Form.Base', 'SettingsEditor');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The template to use for the content of this element
|
|
12
|
+
*
|
|
13
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
14
|
+
* @since 0.3.0
|
|
15
|
+
* @version 0.3.0
|
|
16
|
+
*/
|
|
17
|
+
SettingsEditor.setTemplateFile('form/elements/al_settings_editor');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* The actual settings and their values
|
|
21
|
+
*
|
|
22
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
23
|
+
* @since 0.3.0
|
|
24
|
+
* @version 0.3.0
|
|
25
|
+
*/
|
|
26
|
+
SettingsEditor.setAssignedProperty('settings_config');
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Address to send updates t
|
|
30
|
+
*
|
|
31
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
32
|
+
* @since 0.3.0
|
|
33
|
+
* @version 0.3.0
|
|
34
|
+
*/
|
|
35
|
+
SettingsEditor.setAttribute('src');
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Get the current value
|
|
39
|
+
*
|
|
40
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
41
|
+
* @since 1.3.0
|
|
42
|
+
* @version 1.3.0
|
|
43
|
+
*/
|
|
44
|
+
SettingsEditor.setProperty(function value() {
|
|
45
|
+
|
|
46
|
+
let result = {};
|
|
47
|
+
|
|
48
|
+
let root_key,
|
|
49
|
+
elements = this.querySelectorAll('.al-settings-setting'),
|
|
50
|
+
element,
|
|
51
|
+
field,
|
|
52
|
+
i;
|
|
53
|
+
|
|
54
|
+
for (i = 0; i < elements.length; i++) {
|
|
55
|
+
element = elements[i];
|
|
56
|
+
|
|
57
|
+
field = element.querySelector('al-field');
|
|
58
|
+
|
|
59
|
+
if (!field) {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (!root_key) {
|
|
64
|
+
root_key = element.dataset.id.split('.')[0];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
Object.setPath(result, element.dataset.id, field.value);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return result[root_key];
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Populate the settings container
|
|
75
|
+
*
|
|
76
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
77
|
+
* @since 1.3.0
|
|
78
|
+
* @version 1.3.0
|
|
79
|
+
*/
|
|
80
|
+
SettingsEditor.setMethod(function populateSettingsContainer(container) {
|
|
81
|
+
|
|
82
|
+
if (!container) {
|
|
83
|
+
container = this.querySelector('.al-settings-container');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
Hawkejs.removeChildren(container);
|
|
87
|
+
|
|
88
|
+
this._addGroupToContainer(container, this.settings_config);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Create an id
|
|
93
|
+
*
|
|
94
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
95
|
+
* @since 1.3.0
|
|
96
|
+
* @version 1.3.0
|
|
97
|
+
*
|
|
98
|
+
* @param {string} suffix
|
|
99
|
+
*
|
|
100
|
+
* @return {string}
|
|
101
|
+
*/
|
|
102
|
+
SettingsEditor.setMethod(function createId(suffix) {
|
|
103
|
+
|
|
104
|
+
let id = this.id;
|
|
105
|
+
|
|
106
|
+
if (!id) {
|
|
107
|
+
id = 'settings-editor';
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
id += '-' + suffix.slug().underscore();
|
|
111
|
+
|
|
112
|
+
return id;
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Add the given group to the container
|
|
117
|
+
*
|
|
118
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
119
|
+
* @since 1.3.0
|
|
120
|
+
* @version 1.3.0
|
|
121
|
+
*
|
|
122
|
+
* @param {HTMLElement} container
|
|
123
|
+
* @param {Object} group
|
|
124
|
+
*/
|
|
125
|
+
SettingsEditor.setMethod(function _addGroupToContainer(container, group) {
|
|
126
|
+
|
|
127
|
+
if (!group) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (!container) {
|
|
132
|
+
throw new Error('No container given');
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
let add_group = false;
|
|
136
|
+
|
|
137
|
+
if (group.settings?.length) {
|
|
138
|
+
add_group = true;
|
|
139
|
+
} else if (group.children?.length) {
|
|
140
|
+
// If the root group has no settings, don't add it
|
|
141
|
+
if (!group.is_root) {
|
|
142
|
+
add_group = true;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (add_group) {
|
|
147
|
+
let group_element = this.createElement('div');
|
|
148
|
+
group_element.classList.add('al-settings-group');
|
|
149
|
+
group_element.dataset.id = group.group_id;
|
|
150
|
+
group_element.id = this.createId(group.group_id);
|
|
151
|
+
|
|
152
|
+
let header_element = this.createElement('header');
|
|
153
|
+
header_element.classList.add('al-settings-group-header');
|
|
154
|
+
|
|
155
|
+
let title_element = this.createElement('div');
|
|
156
|
+
title_element.classList.add('al-settings-group-title');
|
|
157
|
+
title_element.dataset.toc_level = group.group_id.count('.');
|
|
158
|
+
|
|
159
|
+
let group_title_microcopy = this.createElement('micro-copy');
|
|
160
|
+
group_title_microcopy.key = 'settings.title.group:' + group.group_id;
|
|
161
|
+
group_title_microcopy.fallback = group.name.titleize();
|
|
162
|
+
|
|
163
|
+
title_element.append(group_title_microcopy);
|
|
164
|
+
header_element.append(title_element);
|
|
165
|
+
group_element.append(header_element);
|
|
166
|
+
|
|
167
|
+
let settings_container = this.createElement('div');
|
|
168
|
+
settings_container.classList.add('al-settings-settings-container');
|
|
169
|
+
|
|
170
|
+
for (let setting of group.settings) {
|
|
171
|
+
this._addSettingToGroupElement(settings_container, setting);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
group_element.append(settings_container);
|
|
175
|
+
container.append(group_element);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
for (let child_group of group.children) {
|
|
179
|
+
this._addGroupToContainer(container, child_group);
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Add the given setting to the container
|
|
185
|
+
*
|
|
186
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
187
|
+
* @since 1.3.0
|
|
188
|
+
* @version 1.3.0
|
|
189
|
+
*
|
|
190
|
+
* @param {HTMLElement} settings_container_element
|
|
191
|
+
* @param {Object} setting
|
|
192
|
+
*/
|
|
193
|
+
SettingsEditor.setMethod(function _addSettingToGroupElement(settings_container_element, setting) {
|
|
194
|
+
|
|
195
|
+
if (!setting?.schema) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
let value_field = setting.schema.get('value');
|
|
200
|
+
|
|
201
|
+
if (!value_field) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
let settings_element = this.createElement('div');
|
|
206
|
+
|
|
207
|
+
let id = this.createId(setting.setting_id);
|
|
208
|
+
|
|
209
|
+
// Set the IDs
|
|
210
|
+
settings_element.dataset.id = setting.setting_id;
|
|
211
|
+
settings_element.id = id;
|
|
212
|
+
|
|
213
|
+
// Add the CSS class
|
|
214
|
+
settings_element.classList.add('al-settings-setting');
|
|
215
|
+
|
|
216
|
+
// Create the title element
|
|
217
|
+
let header_element = this.createElement('header');
|
|
218
|
+
header_element.classList.add('al-settings-setting-header');
|
|
219
|
+
|
|
220
|
+
let title_element = this.createElement('div');
|
|
221
|
+
title_element.classList.add('al-settings-setting-title');
|
|
222
|
+
|
|
223
|
+
let title_microcopy = this.createElement('micro-copy');
|
|
224
|
+
title_microcopy.key = 'settings.title:' + setting.setting_id;
|
|
225
|
+
title_microcopy.fallback = setting.name.titleize();
|
|
226
|
+
|
|
227
|
+
header_element.append(title_element);
|
|
228
|
+
title_element.append(title_microcopy);
|
|
229
|
+
|
|
230
|
+
if (setting.show_description !== false) {
|
|
231
|
+
let description_element = this.createElement('div');
|
|
232
|
+
description_element.classList.add('al-settings-setting-description');
|
|
233
|
+
|
|
234
|
+
let description_microcopy = this.createElement('micro-copy');
|
|
235
|
+
description_microcopy.key = 'settings.description:' + setting.setting_id;
|
|
236
|
+
description_microcopy.fallback = setting.description || '';
|
|
237
|
+
|
|
238
|
+
header_element.append(description_element);
|
|
239
|
+
description_element.append(description_microcopy);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
settings_element.append(header_element);
|
|
243
|
+
|
|
244
|
+
let input_wrapper = this.createElement('div');
|
|
245
|
+
|
|
246
|
+
let al_field = this.createElement('al-field');
|
|
247
|
+
al_field.id = 'af-' + id;
|
|
248
|
+
al_field.config = value_field;
|
|
249
|
+
al_field.value = setting.current_value;
|
|
250
|
+
al_field.mode = 'inline';
|
|
251
|
+
|
|
252
|
+
this.hawkejs_view.registerElementInstance(al_field);
|
|
253
|
+
|
|
254
|
+
if (setting.locked) {
|
|
255
|
+
al_field.readonly = true;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
input_wrapper.append(al_field);
|
|
259
|
+
|
|
260
|
+
settings_element.append(input_wrapper);
|
|
261
|
+
|
|
262
|
+
settings_container_element.append(settings_element);
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* This element has been added to the DOM for the first time
|
|
267
|
+
*
|
|
268
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
269
|
+
* @since 1.3.0
|
|
270
|
+
* @version 1.3.0
|
|
271
|
+
*/
|
|
272
|
+
SettingsEditor.setMethod(function introduced() {
|
|
273
|
+
|
|
274
|
+
let save_button = this.querySelector('.save-changes');
|
|
275
|
+
|
|
276
|
+
save_button.addEventListener('activate', async e => {
|
|
277
|
+
|
|
278
|
+
let old_state = save_button.state;
|
|
279
|
+
|
|
280
|
+
save_button.setState('saving');
|
|
281
|
+
|
|
282
|
+
try {
|
|
283
|
+
await this.save();
|
|
284
|
+
} catch (err) {
|
|
285
|
+
save_button.setState('error', 2500, old_state);
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
save_button.setState('saved', 1000, old_state);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
save_button.hidden = !this.src;
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Get the changes
|
|
297
|
+
*
|
|
298
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
299
|
+
* @since 1.3.0
|
|
300
|
+
* @version 1.3.0
|
|
301
|
+
*/
|
|
302
|
+
SettingsEditor.setMethod(function getChanges() {
|
|
303
|
+
|
|
304
|
+
let result = {};
|
|
305
|
+
|
|
306
|
+
let new_value,
|
|
307
|
+
original_value,
|
|
308
|
+
elements = this.querySelectorAll('.al-settings-setting'),
|
|
309
|
+
element,
|
|
310
|
+
field,
|
|
311
|
+
i;
|
|
312
|
+
|
|
313
|
+
for (i = 0; i < elements.length; i++) {
|
|
314
|
+
element = elements[i];
|
|
315
|
+
|
|
316
|
+
field = element.querySelector('al-field');
|
|
317
|
+
|
|
318
|
+
if (!field) {
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
new_value = field.value;
|
|
323
|
+
original_value = field.original_value;
|
|
324
|
+
|
|
325
|
+
if (Object.alike(new_value, original_value) || new_value == original_value) {
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Ignore empty values that were not set before
|
|
330
|
+
if (new_value === '' && original_value == null) {
|
|
331
|
+
continue;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// Ignore empty values that were not set before
|
|
335
|
+
if (new_value === false && original_value == null) {
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
result[element.dataset.id] = new_value;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
return result;
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Save the changes
|
|
347
|
+
*
|
|
348
|
+
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
349
|
+
* @since 1.3.0
|
|
350
|
+
* @version 1.3.0
|
|
351
|
+
*/
|
|
352
|
+
SettingsEditor.setMethod(async function save() {
|
|
353
|
+
|
|
354
|
+
if (!this.src) {
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
let changes = this.getChanges();
|
|
359
|
+
|
|
360
|
+
let result;
|
|
361
|
+
|
|
362
|
+
try {
|
|
363
|
+
result = await alchemy.fetch(this.src, {post: changes});
|
|
364
|
+
} catch (err) {
|
|
365
|
+
throw err;
|
|
366
|
+
}
|
|
367
|
+
});
|
package/element/al_table.js
CHANGED
|
@@ -677,7 +677,7 @@ Table.setMethod(function addDataRow(entry) {
|
|
|
677
677
|
*
|
|
678
678
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
679
679
|
* @since 0.1.0
|
|
680
|
-
* @version 0.
|
|
680
|
+
* @version 0.3.0
|
|
681
681
|
*
|
|
682
682
|
* @param {Object} entry
|
|
683
683
|
*
|
|
@@ -705,6 +705,10 @@ Table.setMethod(function createDataRow(entry) {
|
|
|
705
705
|
tr.dataset.pk = id;
|
|
706
706
|
}
|
|
707
707
|
|
|
708
|
+
if (!this.fieldset) {
|
|
709
|
+
throw new Error('No fieldset has been defined for this table yet');
|
|
710
|
+
}
|
|
711
|
+
|
|
708
712
|
for (field_set_config of this.fieldset) {
|
|
709
713
|
|
|
710
714
|
let create_new_contents = true,
|
|
@@ -907,7 +911,7 @@ Table.setMethod(function attachContextMenus() {
|
|
|
907
911
|
*
|
|
908
912
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
909
913
|
* @since 0.1.0
|
|
910
|
-
* @version 0.
|
|
914
|
+
* @version 0.3.0
|
|
911
915
|
*/
|
|
912
916
|
Table.setMethod(function onFieldsetAssignment(value, old_value) {
|
|
913
917
|
|
|
@@ -935,7 +939,7 @@ Table.setMethod(function onFieldsetAssignment(value, old_value) {
|
|
|
935
939
|
}
|
|
936
940
|
|
|
937
941
|
for (field of value) {
|
|
938
|
-
col = this.createElement('
|
|
942
|
+
col = this.createElement('th');
|
|
939
943
|
span = this.createElement('span');
|
|
940
944
|
span.textContent = field.title;
|
|
941
945
|
|
|
@@ -980,10 +984,10 @@ Table.setMethod(function onFieldsetAssignment(value, old_value) {
|
|
|
980
984
|
}
|
|
981
985
|
|
|
982
986
|
if (this.has_actions) {
|
|
983
|
-
col = this.createElement('
|
|
987
|
+
col = this.createElement('th');
|
|
984
988
|
names_row.append(col);
|
|
985
989
|
|
|
986
|
-
col = this.createElement('
|
|
990
|
+
col = this.createElement('th');
|
|
987
991
|
filter_row.append(col);
|
|
988
992
|
}
|
|
989
993
|
|
|
@@ -1121,7 +1125,7 @@ Table.setMethod(function getRemoteFetchConfig() {
|
|
|
1121
1125
|
*
|
|
1122
1126
|
* @author Jelle De Loecker <jelle@elevenways.be>
|
|
1123
1127
|
* @since 0.2.0
|
|
1124
|
-
* @version 0.2.
|
|
1128
|
+
* @version 0.2.10
|
|
1125
1129
|
*/
|
|
1126
1130
|
Table.setMethod(function applyFetchedData(err, result, config) {
|
|
1127
1131
|
|
|
@@ -1132,7 +1136,9 @@ Table.setMethod(function applyFetchedData(err, result, config) {
|
|
|
1132
1136
|
|
|
1133
1137
|
let records;
|
|
1134
1138
|
|
|
1135
|
-
if (
|
|
1139
|
+
if (!result) {
|
|
1140
|
+
records = [];
|
|
1141
|
+
} else if (Array.isArray(result)) {
|
|
1136
1142
|
records = result;
|
|
1137
1143
|
} else if (result.length) {
|
|
1138
1144
|
// This way we keep `DocumentList` instances as they are!
|