@nascentdigital/funnel-editor 4.6.7 → 5.0.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.
Files changed (185) hide show
  1. package/dist/EditorApp.js +1 -1
  2. package/dist/EditorRoutes.js +7 -5
  3. package/dist/changesets/screens/ChangeSetViewer.js +1 -1
  4. package/dist/changesets/screens/ChangeSetsExplorer.js +1 -2
  5. package/dist/collection/hooks/CollectionController.d.ts +5 -16
  6. package/dist/collection/hooks/CollectionController.js +18 -37
  7. package/dist/collection/hooks/ICollectionController.d.ts +24 -0
  8. package/dist/collection/hooks/ICollectionController.js +20 -0
  9. package/dist/collection/hooks/index.d.ts +1 -0
  10. package/dist/collection/hooks/index.js +1 -0
  11. package/dist/collection/hooks/useCollectionController.d.ts +3 -3
  12. package/dist/collection/screens/CollectionEditor.js +2 -2
  13. package/dist/components.d.ts +15 -3
  14. package/dist/components.js +18 -3
  15. package/dist/core/components/feedback/dialog/MinimalDialogLayout.js +1 -1
  16. package/dist/core/components/fields/BooleanField.d.ts +2 -1
  17. package/dist/core/components/fields/BooleanField.js +2 -2
  18. package/dist/core/components/fields/DateField.d.ts +2 -1
  19. package/dist/core/components/fields/DateField.js +2 -2
  20. package/dist/core/components/fields/DynamicPagesEditor.d.ts +2 -1
  21. package/dist/core/components/fields/DynamicPagesEditor.js +1 -1
  22. package/dist/core/components/fields/EnumField.d.ts +2 -1
  23. package/dist/core/components/fields/EnumField.js +2 -2
  24. package/dist/core/components/fields/FieldCard.d.ts +1 -0
  25. package/dist/core/components/fields/FieldCard.js +8 -1
  26. package/dist/core/components/fields/FieldEditor.d.ts +2 -1
  27. package/dist/core/components/fields/FieldEditor.js +11 -11
  28. package/dist/core/components/fields/FieldLayout.d.ts +2 -1
  29. package/dist/core/components/fields/FieldLayout.js +3 -3
  30. package/dist/core/components/fields/ListEditor.d.ts +2 -1
  31. package/dist/core/components/fields/ListEditor.js +5 -6
  32. package/dist/core/components/fields/OptInField.d.ts +2 -1
  33. package/dist/core/components/fields/OptInField.js +43 -3
  34. package/dist/core/components/fields/RichTextEditor.js +1 -1
  35. package/dist/core/components/fields/RichTextField.d.ts +2 -1
  36. package/dist/core/components/fields/RichTextField.js +3 -5
  37. package/dist/core/components/fields/TextField.d.ts +2 -0
  38. package/dist/core/components/fields/TextField.js +2 -2
  39. package/dist/core/components/fields/TimestampField.d.ts +2 -1
  40. package/dist/core/components/fields/TimestampField.js +3 -3
  41. package/dist/core/components/fields/asset/AssetEditor.d.ts +1 -2
  42. package/dist/core/components/fields/asset/AssetEditor.js +29 -49
  43. package/dist/core/components/fields/asset/AssetPicker.js +6 -6
  44. package/dist/core/components/fields/asset/AssetUploader.d.ts +1 -2
  45. package/dist/core/components/fields/asset/AssetUploader.js +39 -35
  46. package/dist/core/components/fields/asset/preview/VideoPreview.js +16 -11
  47. package/dist/core/components/fields/asset/useAssetFields.d.ts +2 -17
  48. package/dist/core/components/fields/asset/useAssetFields.js +0 -21
  49. package/dist/core/components/fields/collection/CollectionEditor.d.ts +2 -1
  50. package/dist/core/components/fields/collection/CollectionEditor.js +18 -4
  51. package/dist/core/components/fields/collection/CollectionPicker.d.ts +2 -2
  52. package/dist/core/components/fields/collection/CollectionPicker.js +3 -4
  53. package/dist/core/components/fields/dynamicPages/PagePriorityDialog.js +1 -1
  54. package/dist/core/components/fields/embed/EmbeddedVideoEditor.d.ts +2 -2
  55. package/dist/core/components/fields/embed/EmbeddedVideoEditor.js +50 -31
  56. package/dist/core/components/fields/factories/AssetFactory.d.ts +3 -3
  57. package/dist/core/components/fields/factories/AssetFactory.js +18 -13
  58. package/dist/core/components/fields/factories/CollectionFactory.d.ts +3 -3
  59. package/dist/core/components/fields/factories/CollectionFactory.js +20 -13
  60. package/dist/core/components/fields/factories/EmbeddedVideoFactory.d.ts +3 -3
  61. package/dist/core/components/fields/factories/EmbeddedVideoFactory.js +17 -8
  62. package/dist/core/components/fields/factories/FieldValueFactory.d.ts +7 -5
  63. package/dist/core/components/fields/factories/FieldValueFactory.js +57 -13
  64. package/dist/core/components/fields/factories/LinkFactory.d.ts +3 -3
  65. package/dist/core/components/fields/factories/LinkFactory.js +17 -8
  66. package/dist/core/components/fields/factories/MediaFactory.d.ts +13 -0
  67. package/dist/core/components/fields/factories/MediaFactory.js +212 -0
  68. package/dist/core/components/fields/factories/ObjectFactory.d.ts +3 -2
  69. package/dist/core/components/fields/factories/ObjectFactory.js +16 -2
  70. package/dist/core/components/fields/factories/TextFactory.d.ts +3 -3
  71. package/dist/core/components/fields/factories/TextFactory.js +16 -10
  72. package/dist/core/components/fields/link/LinkEditor.d.ts +2 -2
  73. package/dist/core/components/fields/link/LinkEditor.js +18 -6
  74. package/dist/core/components/fields/list/CreateFieldButton.js +1 -1
  75. package/dist/core/components/fields/media/MediaCard.d.ts +7 -0
  76. package/dist/core/components/fields/media/MediaCard.js +92 -0
  77. package/dist/core/components/fields/media/MediaEditor.d.ts +36 -0
  78. package/dist/core/components/fields/media/MediaEditor.js +264 -0
  79. package/dist/core/components/fields/media/index.d.ts +2 -0
  80. package/dist/core/components/fields/media/index.js +18 -0
  81. package/dist/core/components/fields/object/ObjectEditor.d.ts +2 -1
  82. package/dist/core/components/fields/object/ObjectEditor.js +16 -2
  83. package/dist/core/components/fields/page/PagePicker.js +1 -1
  84. package/dist/core/components/interaction/Combobox.js +1 -1
  85. package/dist/core/components/interaction/MultiSelectControls.js +2 -5
  86. package/dist/core/components/interaction/Popup.d.ts +11 -7
  87. package/dist/core/components/interaction/Popup.js +8 -6
  88. package/dist/core/components/interaction/QuickEditor.js +1 -1
  89. package/dist/core/components/interaction/QuickInput.d.ts +2 -4
  90. package/dist/core/components/interaction/QuickInput.js +6 -2
  91. package/dist/core/components/interaction/QuickPicker.js +1 -1
  92. package/dist/core/components/interaction/SideSheet.js +1 -1
  93. package/dist/core/components/interaction/centersheet/CenterSheet.js +7 -1
  94. package/dist/core/components/interaction/centersheet/CenterSheetContainer.js +3 -1
  95. package/dist/core/components/interaction/menu/Menu.d.ts +8 -19
  96. package/dist/core/components/interaction/menu/Menu.js +26 -60
  97. package/dist/core/components/interaction/menu/useMenuController.d.ts +4 -2
  98. package/dist/core/components/interaction/menu/useMenuController.js +4 -1
  99. package/dist/core/components/transitions/FadeIn.js +1 -1
  100. package/dist/core/components/visuals/Icon.d.ts +1 -1
  101. package/dist/core/components/visuals/Icon.js +3 -0
  102. package/dist/core/containers/AssetRepositoryContainer.d.ts +2 -0
  103. package/dist/core/containers/AssetRepositoryContainer.js +18 -0
  104. package/dist/core/containers/CollectionRepositoryContainer.d.ts +2 -0
  105. package/dist/core/containers/CollectionRepositoryContainer.js +18 -0
  106. package/dist/core/containers/PageRepositoryContainer.d.ts +2 -0
  107. package/dist/core/containers/PageRepositoryContainer.js +18 -0
  108. package/dist/core/containers/index.d.ts +3 -0
  109. package/dist/core/containers/index.js +19 -0
  110. package/dist/core/domain/Block.js +2 -1
  111. package/dist/core/domain/BlockConfiguration.d.ts +4 -1
  112. package/dist/core/domain/BlockConfiguration.js +59 -3
  113. package/dist/core/domain/Collection.d.ts +7 -25
  114. package/dist/core/domain/Collection.js +2 -16
  115. package/dist/core/domain/CollectionBrowser.d.ts +3 -2
  116. package/dist/core/domain/CollectionBrowser.js +3 -3
  117. package/dist/core/domain/CollectionFieldProxy.d.ts +12 -8
  118. package/dist/core/domain/CollectionFieldProxy.js +15 -9
  119. package/dist/core/domain/CollectionGroup.d.ts +0 -5
  120. package/dist/core/domain/CollectionGroup.js +0 -7
  121. package/dist/core/domain/CollectionSummary.d.ts +2 -2
  122. package/dist/core/domain/Collections.d.ts +3 -3
  123. package/dist/core/domain/Collections.js +4 -6
  124. package/dist/core/domain/ICollection.d.ts +72 -0
  125. package/dist/core/domain/ICollection.js +20 -0
  126. package/dist/core/domain/IPage.d.ts +16 -1
  127. package/dist/core/domain/Page.js +2 -2
  128. package/dist/core/domain/Pages.js +4 -6
  129. package/dist/core/domain/SectionBlock.js +2 -1
  130. package/dist/core/domain/Site.d.ts +4 -4
  131. package/dist/core/domain/Site.js +3 -5
  132. package/dist/core/domain/index.d.ts +1 -1
  133. package/dist/core/domain/index.js +1 -1
  134. package/dist/core/hooks/index.d.ts +4 -3
  135. package/dist/core/hooks/index.js +4 -3
  136. package/dist/core/hooks/useAssetRepository.d.ts +3 -0
  137. package/dist/core/hooks/useAssetRepository.js +11 -0
  138. package/dist/core/hooks/useCollection.d.ts +4 -4
  139. package/dist/core/hooks/useCollectionRepository.d.ts +3 -2
  140. package/dist/core/hooks/useCollectionRepository.js +4 -4
  141. package/dist/core/hooks/useCollections.js +4 -0
  142. package/dist/core/hooks/usePageRepository.d.ts +3 -2
  143. package/dist/core/hooks/usePageRepository.js +4 -4
  144. package/dist/core/hooks/useSite.js +4 -0
  145. package/dist/core/hooks/useTempFields.d.ts +2 -3
  146. package/dist/core/index.d.ts +1 -0
  147. package/dist/core/index.js +1 -0
  148. package/dist/core/repository/AssetRepository.d.ts +10 -0
  149. package/dist/core/repository/AssetRepository.js +22 -0
  150. package/dist/core/repository/CollectionRepository.d.ts +22 -21
  151. package/dist/core/repository/CollectionRepository.js +23 -161
  152. package/dist/core/repository/CollectionSerializer.d.ts +4 -1
  153. package/dist/core/repository/CollectionSerializer.js +3 -3
  154. package/dist/core/repository/IAssetRepository.d.ts +25 -0
  155. package/dist/core/repository/ICollectionRepository.d.ts +61 -0
  156. package/dist/core/repository/ICollectionRepository.js +2 -0
  157. package/dist/core/repository/IPageRepository.d.ts +40 -0
  158. package/dist/core/repository/IPageRepository.js +2 -0
  159. package/dist/core/repository/PageRepository.d.ts +5 -8
  160. package/dist/core/repository/PageRepository.js +7 -280
  161. package/dist/core/repository/SerializeCollectionUpdate.d.ts +8 -0
  162. package/dist/core/repository/SerializeCollectionUpdate.js +168 -0
  163. package/dist/core/repository/SerializePageUpdate.d.ts +10 -0
  164. package/dist/core/repository/SerializePageUpdate.js +292 -0
  165. package/dist/core/repository/index.d.ts +4 -0
  166. package/dist/core/repository/index.js +4 -0
  167. package/dist/core/splash/SplashContainer.d.ts +4 -2
  168. package/dist/core/splash/SplashContainer.js +3 -3
  169. package/dist/dashboard/screens/Dashboard.js +1 -1
  170. package/dist/devtools/screens/Devtools.js +1 -1
  171. package/dist/explore/components/CreatePageDialog.d.ts +2 -2
  172. package/dist/explore/screens/CollectionExplorer.js +1 -1
  173. package/dist/explore/screens/CollectionsExplorer.js +1 -1
  174. package/dist/explore/screens/PageExplorer.js +1 -1
  175. package/dist/explore/screens/SiteExplorer.js +1 -1
  176. package/dist/page/components/BlockEditor.js +1 -1
  177. package/dist/page/components/SettingsEditor.js +0 -7
  178. package/dist/page/components/config/BlockConfigButton.js +71 -14
  179. package/dist/page/screens/PageEditor.js +1 -1
  180. package/dist/styles/index.css +24 -20
  181. package/dist/styles/tailwind.js +1 -0
  182. package/dist/users/screens/UserExplorer.js +1 -1
  183. package/package.json +2 -2
  184. package/dist/core/domain/TranslateSchema.d.ts +0 -7
  185. /package/dist/core/{domain/TranslateSchema.js → repository/IAssetRepository.js} +0 -0
@@ -15,6 +15,7 @@ exports.PageRepository = void 0;
15
15
  const funnel_core_1 = require("@nascentdigital/funnel-core");
16
16
  const domain_1 = require("../domain");
17
17
  const PageSerializer_1 = require("./PageSerializer");
18
+ const SerializePageUpdate_1 = require("./SerializePageUpdate");
18
19
  // class
19
20
  class PageRepository {
20
21
  constructor(editorApi) {
@@ -91,6 +92,9 @@ class PageRepository {
91
92
  // unpublish page
92
93
  await this.editorApi.unpublishPage(page.id);
93
94
  }
95
+ async getOverview(args) {
96
+ return this.editorApi.getPagesOverview(Object.assign(Object.assign({}, args), { version: 'draft' }));
97
+ }
94
98
  serializePageUpdate(page, savables) {
95
99
  var _a, _b;
96
100
  // root page updates
@@ -158,18 +162,18 @@ class PageRepository {
158
162
  ...rootPageUpdates,
159
163
  ...discover.reduce((updates, block) => {
160
164
  // try to update block
161
- this.serializeBlockUpdate(updates, block, 'discover', savables);
165
+ SerializePageUpdate_1.SerializePageUpdate.serializeBlockUpdate(updates, block, 'discover', savables);
162
166
  // keep reducing
163
167
  return updates;
164
168
  }, []),
165
169
  ...content.reduce((updates, item) => {
166
170
  // handle block
167
171
  if (item instanceof domain_1.Block) {
168
- this.serializeBlockUpdate(updates, item, 'content', savables);
172
+ SerializePageUpdate_1.SerializePageUpdate.serializeBlockUpdate(updates, item, 'content', savables);
169
173
  }
170
174
  // or section
171
175
  else {
172
- this.serializeSectionUpdate(updates, item, 'content', savables);
176
+ SerializePageUpdate_1.SerializePageUpdate.serializeSectionUpdate(updates, item, 'content', savables);
173
177
  }
174
178
  // keep reducing
175
179
  return updates;
@@ -181,282 +185,5 @@ class PageRepository {
181
185
  ]
182
186
  };
183
187
  }
184
- serializeSectionUpdate(updates, section, parentPath, savables) {
185
- // track insert/update
186
- let sectionChanged = false;
187
- const path = [parentPath, section.key];
188
- const { blocks, initialBlocks = [] } = section;
189
- const blockIds = [];
190
- blocks.forEach((sectionBlock, index) => {
191
- // track id
192
- const { id, block } = sectionBlock;
193
- blockIds.push(id);
194
- // track insert
195
- const originalIndex = initialBlocks.findIndex(item => item.id === id);
196
- if (originalIndex < 0) {
197
- // add as insertion
198
- updates.push({
199
- type: 'section.insert',
200
- path,
201
- index,
202
- section: {
203
- type: 'section',
204
- version: section.schema.version
205
- },
206
- block: sectionBlock.value
207
- });
208
- // mark changed
209
- sectionChanged = true;
210
- // track nested savables for section-block insertion
211
- const fields = [...block.config, ...block.fields];
212
- fields.forEach(field => {
213
- if (field.modified) {
214
- savables.push(field);
215
- }
216
- });
217
- }
218
- // recurse update if it's set
219
- else if (block.modified) {
220
- // track name field
221
- if (block.nameField.modified) {
222
- // send update
223
- updates.push({
224
- type: 'section.blockName',
225
- path,
226
- id,
227
- value: funnel_core_1.Schema.TextField.Value.fromData(block.nameField.value) || null
228
- });
229
- // track change
230
- savables.push(block.nameField);
231
- }
232
- // serialize config fields
233
- this.serializeFieldsUpdate(updates, block.config, [...path, id, 'config'], savables);
234
- // serialize content fields
235
- this.serializeFieldsUpdate(updates, block.fields, [...path, id, 'fields'], savables);
236
- }
237
- });
238
- // track delete/reorder
239
- let reordered = false;
240
- initialBlocks.forEach(({ id }, index) => {
241
- // add to deleted list if the original doesn't exist anymore
242
- const blockIndex = blockIds.findIndex(blockId => blockId === id);
243
- if (blockIndex < 0) {
244
- // delete
245
- updates.push({
246
- type: 'section.delete',
247
- path,
248
- id
249
- });
250
- // track reorder
251
- sectionChanged = true;
252
- }
253
- // or mark reorder if index isn't the same
254
- else if (blockIndex !== index) {
255
- reordered = true;
256
- sectionChanged = true;
257
- }
258
- });
259
- // track reorder
260
- if (reordered) {
261
- updates.push({
262
- type: 'section.reorder',
263
- path,
264
- ids: blockIds
265
- });
266
- }
267
- // track section change (if any)
268
- if (sectionChanged) {
269
- savables.push(section);
270
- }
271
- }
272
- serializeBlockUpdate(updates, block, parentPath, savables) {
273
- // ignore if block isn't activated
274
- if (!block.activated) {
275
- return;
276
- }
277
- // create a new block if it's new
278
- else if (block.isNew) {
279
- // create update
280
- updates.push({
281
- type: 'block.create',
282
- path: [parentPath, block.key],
283
- block: block.value
284
- });
285
- // track block
286
- savables.push(block);
287
- // track nested savables for block insertion
288
- const fields = [...block.config, ...block.fields];
289
- fields.forEach(field => {
290
- if (field.modified) {
291
- savables.push(field);
292
- }
293
- });
294
- }
295
- // or just track updated fields
296
- else {
297
- // serialize config fields
298
- this.serializeFieldsUpdate(updates, block.config, [parentPath, block.key, 'config'], savables);
299
- // serialize content fields
300
- this.serializeFieldsUpdate(updates, block.fields, [parentPath, block.key, 'fields'], savables);
301
- }
302
- }
303
- serializeFieldsUpdate(updates, fields, parentPath, savables) {
304
- // handle fields in block
305
- fields.forEach(field => {
306
- if (field instanceof funnel_core_1.Field) {
307
- this.serializeFieldUpdate(updates, field, parentPath, savables);
308
- }
309
- else if (field instanceof funnel_core_1.ObjectField) {
310
- this.serializeObjectFieldUpdate(updates, field, parentPath, savables);
311
- }
312
- else {
313
- this.serializeListUpdate(updates, field, parentPath, savables);
314
- }
315
- });
316
- // return changes (for chaining)
317
- return updates;
318
- }
319
- serializeObjectFieldUpdate(updates, field, parentPath, savables) {
320
- var _a;
321
- // create object if it's new
322
- if (field.isNew) {
323
- // add insert
324
- updates.push({
325
- type: 'object.insert',
326
- path: [...parentPath, field.id],
327
- value: (_a = field.value) !== null && _a !== void 0 ? _a : null
328
- });
329
- // track save
330
- savables.push(field);
331
- }
332
- // or process subfields
333
- else if (field.exists) {
334
- // save fields
335
- this.serializeFieldsUpdate(updates, field.fields, [...parentPath, field.id], savables);
336
- // track save
337
- savables.push(field);
338
- }
339
- // or process opted out field
340
- else if (field.optedOut) {
341
- // remove field
342
- updates.push({
343
- type: 'value',
344
- path: [...parentPath, field.id],
345
- value: null
346
- });
347
- // track save
348
- savables.push(field);
349
- }
350
- }
351
- serializeFieldUpdate(updates, field, parentPath, savables) {
352
- var _a;
353
- // track change if modified (ignore if field is sandboxed)
354
- if (field.modified && !field.sandboxed) {
355
- // set field
356
- updates.push({
357
- type: 'value',
358
- path: [...parentPath, field.id],
359
- value: ((_a = field.value) !== null && _a !== void 0 ? _a : null)
360
- });
361
- // track save
362
- savables.push(field);
363
- }
364
- }
365
- serializeListUpdate(updates, list, parentPath, savables) {
366
- var _a, _b;
367
- // create list if it's new
368
- if (list.isNew) {
369
- // add new list
370
- updates.push({
371
- type: 'value',
372
- path: [...parentPath, list.id],
373
- value: funnel_core_1.Schema.Field.Data.newValue('list')
374
- });
375
- // track save
376
- savables.push(list);
377
- }
378
- // or drop list on opt-out
379
- else if (list.optedOut) {
380
- // drop list
381
- updates.push({
382
- type: 'value',
383
- path: [...parentPath, list.id],
384
- value: null
385
- });
386
- // track save
387
- savables.push(list);
388
- }
389
- // or if it is modified (otherwise ignore)
390
- else if (list.modified) {
391
- // add new list if there's nothing and it's new
392
- const path = [...parentPath, list.id];
393
- const { value: currentValue, items: fields, initialValue } = list;
394
- const currentItems = (_a = currentValue === null || currentValue === void 0 ? void 0 : currentValue.value) !== null && _a !== void 0 ? _a : [];
395
- const initialItems = (_b = initialValue === null || initialValue === void 0 ? void 0 : initialValue.value) !== null && _b !== void 0 ? _b : [];
396
- const fieldIds = [];
397
- // track inserts/updates of elements
398
- currentItems.forEach((item, index) => {
399
- // track id
400
- const { id, field } = fields[index];
401
- fieldIds.push(item.id);
402
- // track insert
403
- const originalIndex = initialItems.findIndex(initialItem => initialItem.id === id);
404
- if (originalIndex < 0) {
405
- updates.push({
406
- type: 'array.insert',
407
- path,
408
- index,
409
- id,
410
- value: item
411
- });
412
- }
413
- // track update
414
- else if (field.modified) {
415
- // object field updates should be recursed and indexed
416
- if (field instanceof funnel_core_1.ObjectField) {
417
- this.serializeFieldsUpdate(updates, field.fields, [...path, id], savables);
418
- }
419
- // basic field updates can be done inline
420
- else {
421
- updates.push({
422
- type: 'value',
423
- path: [...path, id],
424
- value: item
425
- });
426
- }
427
- }
428
- });
429
- // track delete/reorder
430
- let reordered = false;
431
- let deleted = 0;
432
- initialItems.forEach(({ id }, index) => {
433
- // add to deleted list if the original doesn't exist anymore
434
- const fieldIndex = fieldIds.findIndex(fieldId => fieldId === id) + deleted;
435
- if (fieldIndex < 0) {
436
- updates.push({
437
- type: 'array.delete',
438
- path,
439
- id
440
- });
441
- // track deletion
442
- ++deleted;
443
- }
444
- // or mark reorder if index isn't the same
445
- else if (fieldIndex !== index) {
446
- reordered = true;
447
- }
448
- });
449
- // track reorder
450
- if (reordered) {
451
- updates.push({
452
- type: 'array.reorder',
453
- path,
454
- ids: fieldIds
455
- });
456
- }
457
- // track save
458
- savables.push(list);
459
- }
460
- }
461
188
  }
462
189
  exports.PageRepository = PageRepository;
@@ -0,0 +1,8 @@
1
+ import { Field, FieldList, FieldModel, ObjectField, Schema } from '@nascentdigital/funnel-core';
2
+ import { ICollection } from '../domain';
3
+ export declare namespace SerializeCollectionUpdate {
4
+ function serializeFieldsUpdate(updates: Schema.Collection.Update[], fields: ReadonlyArray<FieldModel>, parentPath: ReadonlyArray<string>, savables: ICollection.Savable[]): Schema.Collection.Update[];
5
+ function serializeObjectFieldUpdate(updates: Schema.Collection.Update[], field: ObjectField, parentPath: ReadonlyArray<string>, savables: ICollection.Savable[]): void;
6
+ function serializeFieldUpdate(updates: Schema.Collection.Update[], field: Field, parentPath: ReadonlyArray<string>, savables: ICollection.Savable[]): void;
7
+ function serializeListUpdate(updates: Schema.Collection.Update[], list: FieldList, parentPath: ReadonlyArray<string>, savables: ICollection.Savable[]): void;
8
+ }
@@ -0,0 +1,168 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SerializeCollectionUpdate = void 0;
4
+ const funnel_core_1 = require("@nascentdigital/funnel-core");
5
+ // namespace
6
+ var SerializeCollectionUpdate;
7
+ (function (SerializeCollectionUpdate) {
8
+ // helper
9
+ function serializeFieldsUpdate(updates, fields, parentPath, savables) {
10
+ // handle fields in block
11
+ fields.forEach(field => {
12
+ if (field instanceof funnel_core_1.Field) {
13
+ serializeFieldUpdate(updates, field, parentPath, savables);
14
+ }
15
+ else if (field instanceof funnel_core_1.ObjectField) {
16
+ serializeObjectFieldUpdate(updates, field, parentPath, savables);
17
+ }
18
+ else {
19
+ serializeListUpdate(updates, field, parentPath, savables);
20
+ }
21
+ });
22
+ // return changes (for chaining)
23
+ return updates;
24
+ }
25
+ SerializeCollectionUpdate.serializeFieldsUpdate = serializeFieldsUpdate;
26
+ function serializeObjectFieldUpdate(updates, field, parentPath, savables) {
27
+ var _a;
28
+ // create object if it's new
29
+ if (field.isNew) {
30
+ updates.push({
31
+ type: 'object.insert',
32
+ path: [...parentPath, field.id],
33
+ value: (_a = field.value) !== null && _a !== void 0 ? _a : null
34
+ });
35
+ // track save
36
+ savables.push(field);
37
+ }
38
+ // or process subfields
39
+ else if (field.exists) {
40
+ // save fields
41
+ serializeFieldsUpdate(updates, field.fields, [...parentPath, field.id], savables);
42
+ // track save
43
+ savables.push(field);
44
+ }
45
+ // or process opted out field
46
+ else if (field.optedOut) {
47
+ updates.push({
48
+ type: 'value',
49
+ path: [...parentPath, field.id],
50
+ value: null
51
+ });
52
+ // track save
53
+ savables.push(field);
54
+ }
55
+ }
56
+ SerializeCollectionUpdate.serializeObjectFieldUpdate = serializeObjectFieldUpdate;
57
+ function serializeFieldUpdate(updates, field, parentPath, savables) {
58
+ var _a;
59
+ // track change if modified (ignore if field is sandboxed)
60
+ if (field.modified && !field.sandboxed) {
61
+ // set field
62
+ updates.push({
63
+ type: 'value',
64
+ path: [...parentPath, field.id],
65
+ value: ((_a = field.value) !== null && _a !== void 0 ? _a : null)
66
+ });
67
+ // track save
68
+ savables.push(field);
69
+ }
70
+ }
71
+ SerializeCollectionUpdate.serializeFieldUpdate = serializeFieldUpdate;
72
+ function serializeListUpdate(updates, list, parentPath, savables) {
73
+ var _a, _b;
74
+ // create list if it's new
75
+ if (list.isNew) {
76
+ // add new list
77
+ updates.push({
78
+ type: 'value',
79
+ path: [...parentPath, list.id],
80
+ value: funnel_core_1.Schema.Field.Data.newValue('list')
81
+ });
82
+ // track save
83
+ savables.push(list);
84
+ }
85
+ // or drop list on opt-out
86
+ else if (list.optedOut) {
87
+ // drop list
88
+ updates.push({
89
+ type: 'value',
90
+ path: [...parentPath, list.id],
91
+ value: null
92
+ });
93
+ // track save
94
+ savables.push(list);
95
+ }
96
+ // or skip if not modified
97
+ else if (list.modified) {
98
+ // track insert/update
99
+ const path = [...parentPath, list.id];
100
+ const { value: currentValue, items: fields, initialValue } = list;
101
+ const currentItems = (_a = currentValue === null || currentValue === void 0 ? void 0 : currentValue.value) !== null && _a !== void 0 ? _a : [];
102
+ const initialItems = (_b = initialValue === null || initialValue === void 0 ? void 0 : initialValue.value) !== null && _b !== void 0 ? _b : [];
103
+ const fieldIds = [];
104
+ currentItems.forEach((item, index) => {
105
+ // track id
106
+ const { id, field } = fields[index];
107
+ fieldIds.push(item.id);
108
+ // track insert
109
+ const originalIndex = initialItems.findIndex(initialItem => initialItem.id === id);
110
+ if (originalIndex < 0) {
111
+ updates.push({
112
+ type: 'array.insert',
113
+ path,
114
+ index,
115
+ id,
116
+ value: item
117
+ });
118
+ }
119
+ // track update
120
+ else if (field.modified) {
121
+ // object field updates should be recursed and indexed
122
+ if (field instanceof funnel_core_1.ObjectField) {
123
+ serializeFieldsUpdate(updates, field.fields, [...path, id], savables);
124
+ }
125
+ // basic field updates can be done inline
126
+ else {
127
+ updates.push({
128
+ type: 'value',
129
+ path: [...path, id],
130
+ value: item
131
+ });
132
+ }
133
+ }
134
+ });
135
+ // track delete/reorder
136
+ let reordered = false;
137
+ let deleted = 0;
138
+ initialItems.forEach(({ id }, index) => {
139
+ // add to deleted list if the original doesn't exist anymore
140
+ const fieldIndex = fieldIds.findIndex(fieldId => fieldId === id) + deleted;
141
+ if (fieldIndex < 0) {
142
+ updates.push({
143
+ type: 'array.delete',
144
+ path,
145
+ id
146
+ });
147
+ // track deletion
148
+ ++deleted;
149
+ }
150
+ // or mark reorder if index isn't the same
151
+ else if (fieldIndex !== index) {
152
+ reordered = true;
153
+ }
154
+ });
155
+ // track reorder
156
+ if (reordered) {
157
+ updates.push({
158
+ type: 'array.reorder',
159
+ path,
160
+ ids: fieldIds
161
+ });
162
+ }
163
+ // track save
164
+ savables.push(list);
165
+ }
166
+ }
167
+ SerializeCollectionUpdate.serializeListUpdate = serializeListUpdate;
168
+ })(SerializeCollectionUpdate || (exports.SerializeCollectionUpdate = SerializeCollectionUpdate = {}));
@@ -0,0 +1,10 @@
1
+ import { Field, FieldList, FieldModel, ObjectField, Schema } from '@nascentdigital/funnel-core';
2
+ import { Block, IPage, Section } from '../domain';
3
+ export declare namespace SerializePageUpdate {
4
+ function serializeSectionUpdate(updates: Schema.Page.Update[], section: Section, parentPath: string, savables: IPage.Savable[]): void;
5
+ function serializeBlockUpdate(updates: Schema.Page.Update[], block: Block, parentPath: string, savables: IPage.Savable[]): void;
6
+ function serializeFieldsUpdate(updates: Schema.Page.Update[], fields: ReadonlyArray<FieldModel>, parentPath: ReadonlyArray<string>, savables: IPage.Savable[]): Schema.Page.Update[];
7
+ function serializeObjectFieldUpdate(updates: Schema.Page.Update[], field: ObjectField, parentPath: ReadonlyArray<string>, savables: IPage.Savable[]): void;
8
+ function serializeFieldUpdate(updates: Schema.Page.Update[], field: Field, parentPath: ReadonlyArray<string>, savables: IPage.Savable[]): void;
9
+ function serializeListUpdate(updates: Schema.Page.Update[], list: FieldList, parentPath: ReadonlyArray<string>, savables: IPage.Savable[]): void;
10
+ }