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.
@@ -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
+ });
@@ -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.2.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.1.12
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('td');
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('td');
987
+ col = this.createElement('th');
984
988
  names_row.append(col);
985
989
 
986
- col = this.createElement('td');
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.8
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 (Array.isArray(result)) {
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!