@builttocreate/engine-utils 2.9.1-beta.758 → 2.9.1-beta.758.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.
@@ -0,0 +1,936 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.sortPages = exports.sortFieldPositionsByXAndYCoordinates = exports.removeOrphanedFieldsFromJoydoc = exports.mergeAssoicatedFieldPositionsForMobilePage = exports.getPageOrder = exports.getMobileViewFromFile = exports.getDocumentFromTemplate = exports.getDefaultTemplate = exports.getDefaultJoyDocPage = exports.getDefaultJoyDocFile = exports.getDefaultJoyDoc = exports.getDefaultDocument = exports.getCleanedJoyDocPages = exports.getCleanedJoyDoc = exports.generateMobileViewFromFile = exports.generateMobilePageFieldPositions = exports.generateMobilePage = exports.formatTableFieldPositions = exports.duplicateDocumentPage = exports.duplicate = exports["default"] = exports.cleanPageOrder = void 0;
8
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
9
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
10
+ var _generateObjectId = _interopRequireDefault(require("./generateObjectId"));
11
+ var _validateObjectId = _interopRequireDefault(require("./validateObjectId"));
12
+ var _PageLayoutModes = _interopRequireDefault(require("./constants/PageLayoutModes"));
13
+ var _FieldPresentationModes = _interopRequireDefault(require("./constants/FieldPresentationModes"));
14
+ var _DocumentTypes = _interopRequireDefault(require("./constants/DocumentTypes"));
15
+ var _PageTypes = _interopRequireDefault(require("./constants/PageTypes"));
16
+ var _FieldTypes = _interopRequireDefault(require("./constants/FieldTypes"));
17
+ var _FieldDisplayTypes = _interopRequireDefault(require("./constants/FieldDisplayTypes"));
18
+ var _FileViews = _interopRequireDefault(require("./constants/FileViews"));
19
+ var _FormStyleOptions = _interopRequireDefault(require("./constants/FormStyleOptions"));
20
+ var _tableHelper = require("./tableHelper");
21
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
22
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
23
+ /**
24
+ * Create default page
25
+ *
26
+ * @param {Object} defaults
27
+ * @return {Object}
28
+ */
29
+ var getDefaultJoyDocPage = exports.getDefaultJoyDocPage = function getDefaultJoyDocPage() {
30
+ var defaults = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
31
+ return _objectSpread({
32
+ _id: (0, _generateObjectId["default"])(),
33
+ name: 'New Page',
34
+ width: 816,
35
+ height: 1056,
36
+ rowHeight: 8,
37
+ cols: 8,
38
+ fieldPositions: [],
39
+ layout: _PageLayoutModes["default"].grid,
40
+ presentation: _FieldPresentationModes["default"].normal,
41
+ padding: 24
42
+ }, defaults);
43
+ };
44
+
45
+ /**
46
+ * Create default file
47
+ *
48
+ * @param {Object} defaults
49
+ * @param {Object} pageDefaults
50
+ * @return {Object}
51
+ */
52
+ var getDefaultJoyDocFile = exports.getDefaultJoyDocFile = function getDefaultJoyDocFile() {
53
+ var defaults = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
54
+ var pageDefaults = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
55
+ var page = getDefaultJoyDocPage(pageDefaults);
56
+ return _objectSpread({
57
+ _id: (0, _generateObjectId["default"])(),
58
+ name: 'New File',
59
+ pageOrder: [page._id],
60
+ pages: [page],
61
+ styles: {
62
+ margin: 4
63
+ }
64
+ }, defaults);
65
+ };
66
+
67
+ /**
68
+ * Create default document
69
+ *
70
+ * @param {Object} defaults
71
+ * @param {Object} pageDefaults
72
+ * @return {Object}
73
+ */
74
+ var getDefaultJoyDoc = exports.getDefaultJoyDoc = function getDefaultJoyDoc() {
75
+ var defaults = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
76
+ var fileDefaults = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
77
+ var pageDefaults = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
78
+ var id = (0, _generateObjectId["default"])();
79
+ return _objectSpread({
80
+ _id: id,
81
+ identifier: "doc_".concat(id),
82
+ name: 'New Doc',
83
+ files: [getDefaultJoyDocFile(fileDefaults, pageDefaults)],
84
+ fields: []
85
+ }, defaults);
86
+ };
87
+
88
+ /**
89
+ * Get Clean JoyDoc Format
90
+ *
91
+ * Solves Issue: https://app.zenhub.com/workspaces/joyfill-platform-5f07262b507391001f56c7f9/issues/gh/zionlabs/issues/2105
92
+ *
93
+ * This selector ensures a couple of things:
94
+ * 1. Valid file inside the document.
95
+ * 2. Valid page inside document file.
96
+ * 3. All _id's (page, file, page, fieldPosition, field) are in a valid format
97
+ * 4. Row order of table field is free from duplicate/deletedRow Ids
98
+ *
99
+ * @param {Object} doc
100
+ * @returns {Object}
101
+ */
102
+ var getCleanedJoyDoc = exports.getCleanedJoyDoc = function getCleanedJoyDoc(doc) {
103
+ if (!doc) return getDefaultJoyDoc();
104
+ var _removeOrphanedFields = removeOrphanedFieldsFromJoydoc(doc),
105
+ nextDoc = _removeOrphanedFields.nextDoc;
106
+
107
+ /**
108
+ * Step 1.1: Replace doc._id if it is not valid
109
+ */
110
+ if (nextDoc._id && !(0, _validateObjectId["default"])(nextDoc._id)) nextDoc._id = (0, _generateObjectId["default"])();
111
+ if (nextDoc.files && nextDoc.files.length > 0) {
112
+ nextDoc.files = nextDoc.files.map(function (file) {
113
+ var _nextFile$views;
114
+ var nextFile = _objectSpread({}, file);
115
+
116
+ /**
117
+ * Step 1.2: Replace files[x]._id if it is not valid
118
+ */
119
+ if (nextFile._id && !(0, _validateObjectId["default"])(nextFile._id)) nextFile._id = (0, _generateObjectId["default"])();
120
+
121
+ /**
122
+ * Step 1.3: Replace page ids and field ids if they are not valid
123
+ */
124
+ nextFile.pages = getCleanedJoyDocPages(nextFile.pages);
125
+ nextFile.pageOrder = cleanPageOrder(getPageOrder(nextFile.pageOrder, nextFile.pages), nextFile.pages);
126
+
127
+ /**
128
+ * Step 1.4: Replace view page ids and field ids if they are not valid
129
+ */
130
+ if ((nextFile === null || nextFile === void 0 ? void 0 : (_nextFile$views = nextFile.views) === null || _nextFile$views === void 0 ? void 0 : _nextFile$views.length) > 0) {
131
+ nextFile.views = nextFile.views.map(function (view) {
132
+ var nextView = _objectSpread({}, view);
133
+ nextView.pages = getCleanedJoyDocPages(nextView.pages);
134
+ nextView.pageOrder = cleanPageOrder(getPageOrder(nextView.pageOrder, nextView.pages), nextView.pages);
135
+ return nextView;
136
+ });
137
+ }
138
+ return nextFile;
139
+ });
140
+ } else {
141
+ nextDoc.files = [getDefaultJoyDocFile()];
142
+ }
143
+
144
+ /**
145
+ * Logic below is used to clean the table field rowOrder by removing the
146
+ * deletedRowIds / duplicateRowIds from the rowOrder.
147
+ **/
148
+ if (nextDoc.fields && nextDoc.fields.length > 0) {
149
+ nextDoc.fields = nextDoc.fields.map(function (field) {
150
+ var nextField = _objectSpread({}, field);
151
+ if (field.type === _FieldTypes["default"].table) {
152
+ var cleanedRoworder = (0, _tableHelper.getCleanedRowOrder)(field.rowOrder, field.value);
153
+ nextField.rowOrder = cleanedRoworder;
154
+ }
155
+ return nextField;
156
+ });
157
+ }
158
+ return nextDoc;
159
+ };
160
+
161
+ /**
162
+ * Remove orphaned fields from doc
163
+ */
164
+
165
+ var removeOrphanedFieldsFromJoydoc = exports.removeOrphanedFieldsFromJoydoc = function removeOrphanedFieldsFromJoydoc(doc) {
166
+ var _nextDoc$files;
167
+ if (!doc) return getDefaultJoyDoc();
168
+ var nextDoc = _objectSpread({}, doc);
169
+ var associatedFieldIdLookup = {};
170
+ nextDoc === null || nextDoc === void 0 ? void 0 : (_nextDoc$files = nextDoc.files) === null || _nextDoc$files === void 0 ? void 0 : _nextDoc$files.forEach(function (file) {
171
+ var _file$views;
172
+ /**
173
+ * Primary view
174
+ */
175
+ file.pages.forEach(function (page) {
176
+ page === null || page === void 0 ? void 0 : page.fieldPositions.forEach(function (fieldPosition) {
177
+ return associatedFieldIdLookup[fieldPosition.field] = true;
178
+ });
179
+ });
180
+
181
+ /**
182
+ * Alternative view
183
+ */
184
+ (_file$views = file.views) === null || _file$views === void 0 ? void 0 : _file$views.forEach(function (view) {
185
+ var _view$pages;
186
+ view === null || view === void 0 ? void 0 : (_view$pages = view.pages) === null || _view$pages === void 0 ? void 0 : _view$pages.forEach(function (page) {
187
+ page === null || page === void 0 ? void 0 : page.fieldPositions.forEach(function (fieldPosition) {
188
+ return associatedFieldIdLookup[fieldPosition.field] = true;
189
+ });
190
+ });
191
+ });
192
+ });
193
+
194
+ /**
195
+ * Logic below removes orphaned fields (ie fields without fieldPositions)
196
+ */
197
+ var validFields = [];
198
+ var deletedFields = [];
199
+ nextDoc.fields.forEach(function (field) {
200
+ if (associatedFieldIdLookup[field._id]) validFields.push(field);else deletedFields.push(field);
201
+ });
202
+ nextDoc.fields = validFields;
203
+ return {
204
+ nextDoc: nextDoc,
205
+ deletedFields: deletedFields
206
+ };
207
+ };
208
+
209
+ /**
210
+ * Get Cleaned JoyDoc Pages
211
+ *
212
+ * Solves Issue: https://app.zenhub.com/workspaces/joyfill-platform-5f07262b507391001f56c7f9/issues/gh/zionlabs/issues/2105
213
+ *
214
+ * This selector ensures a couple of things:
215
+ * 1. Valid page inside document file.pages array.
216
+ * 2. All id's in pages and fieldPositions are valid format
217
+ *
218
+ * @param {Object} doc
219
+ * @returns {Object}
220
+ */
221
+ var getCleanedJoyDocPages = exports.getCleanedJoyDocPages = function getCleanedJoyDocPages(pages) {
222
+ if ((pages === null || pages === void 0 ? void 0 : pages.length) > 0) {
223
+ return pages.map(function (page) {
224
+ /**
225
+ * Step 1: Replace pages[x]._id if it is not valid
226
+ */
227
+ var nextPage = _objectSpread({}, page);
228
+ if (nextPage._id && !(0, _validateObjectId["default"])(nextPage._id)) nextPage._id = (0, _generateObjectId["default"])();
229
+ if (nextPage.fieldPositions && nextPage.fieldPositions.length > 0) {
230
+ nextPage.fieldPositions = nextPage.fieldPositions.map(function (fieldPosition) {
231
+ /**
232
+ * Step 1.2: Replace fieldPosition _id and field reference if they are not valid
233
+ */
234
+ var nextFieldPosition = _objectSpread({}, fieldPosition);
235
+ if (nextFieldPosition._id && !(0, _validateObjectId["default"])(nextFieldPosition._id)) nextFieldPosition._id = (0, _generateObjectId["default"])();
236
+ if (nextFieldPosition.field && !(0, _validateObjectId["default"])(nextFieldPosition.field)) nextFieldPosition.field = (0, _generateObjectId["default"])();
237
+ return nextFieldPosition;
238
+ });
239
+ } else {
240
+ nextPage.fieldPositions = [];
241
+ }
242
+ return nextPage;
243
+ });
244
+ } else {
245
+ return [getDefaultJoyDocPage()];
246
+ }
247
+ };
248
+
249
+ /**
250
+ * Get page order
251
+ *
252
+ * @param {Array} pages
253
+ * @param {Array} pageOrder
254
+ * @return {Array}
255
+ */
256
+ var getPageOrder = exports.getPageOrder = function getPageOrder(pageOrder, pages) {
257
+ return pageOrder || pages.map(function (page) {
258
+ return page._id;
259
+ });
260
+ };
261
+
262
+ /**
263
+ *
264
+ * Clean pageOrder
265
+ *
266
+ * 1. Remove any pageIds associated with a missing page.
267
+ * 2. Remove any underfined or invalid pageIds
268
+ * 3. Remove any duplicate pageIds
269
+ *
270
+ * @param {Array} pageOrder //[string, string, ...]
271
+ * @param {Array} pages //[object, object, ...]
272
+ * @returns {Array}
273
+ */
274
+ var cleanPageOrder = exports.cleanPageOrder = function cleanPageOrder(pageOrder, pages) {
275
+ var pageLookup = {};
276
+ pages.forEach(function (page) {
277
+ return pageLookup[page._id] = page && !page.deleted;
278
+ });
279
+ return pageOrder.filter(function (pageId, index) {
280
+ return pageLookup[pageId] && pageId && pageOrder.indexOf(pageId) === index;
281
+ });
282
+ };
283
+
284
+ /**
285
+ * Sort pages based on pageOrder
286
+ */
287
+ var sortPages = exports.sortPages = function sortPages(pages, pageOrder) {
288
+ if (!pageOrder) return pages;
289
+ var pageLookup = {};
290
+ pages.forEach(function (page) {
291
+ pageLookup[page._id] = page;
292
+ });
293
+ var sortedPages = [];
294
+ pageOrder.forEach(function (pageId) {
295
+ if (pageLookup[pageId]) sortedPages.push(pageLookup[pageId]);
296
+ });
297
+ return sortedPages;
298
+ };
299
+
300
+ /**
301
+ * Get a properly formatted Document JoyDoc
302
+ *
303
+ * @returns {Object}
304
+ */
305
+ var getDefaultDocument = exports.getDefaultDocument = function getDefaultDocument() {
306
+ var type = _DocumentTypes["default"].document;
307
+ var _id = (0, _generateObjectId["default"])();
308
+ var identifier = "doc_".concat(_id);
309
+ var name = 'New Doc';
310
+ return getDefaultJoyDoc({
311
+ type: type,
312
+ _id: _id,
313
+ identifier: identifier,
314
+ name: name
315
+ });
316
+ };
317
+
318
+ /**
319
+ * Get a properly formatted Template JoyDoc
320
+ *
321
+ * @returns {Object}
322
+ */
323
+ var getDefaultTemplate = exports.getDefaultTemplate = function getDefaultTemplate() {
324
+ var type = _DocumentTypes["default"].template;
325
+ var _id = (0, _generateObjectId["default"])();
326
+ var identifier = "template_".concat(_id);
327
+ var name = 'New Template';
328
+ return getDefaultJoyDoc({
329
+ type: type,
330
+ _id: _id,
331
+ identifier: identifier,
332
+ name: name
333
+ });
334
+ };
335
+
336
+ /**
337
+ * Get a properly formatted duplicate of a Template or Document
338
+ *
339
+ * @returns {Object}
340
+ */
341
+ var duplicate = exports.duplicate = function duplicate(original, defaults) {
342
+ //Remove all references to original template object
343
+ var origin = JSON.parse(JSON.stringify(original));
344
+ var _id = (0, _generateObjectId["default"])();
345
+ var identifier = origin.type === _DocumentTypes["default"].template ? "template_".concat(_id) : "doc_".concat(_id);
346
+ return _objectSpread(_objectSpread({}, origin), {}, {
347
+ _id: _id,
348
+ identifier: identifier,
349
+ createdOn: new Date().getTime(),
350
+ source: origin.identifier
351
+ }, defaults);
352
+ };
353
+
354
+ /**
355
+ * Get a properly formatted Document JoyDoc from Template JoyDoc
356
+ *
357
+ * @param {Object} template
358
+ * @returns {Object}
359
+ */
360
+ var getDocumentFromTemplate = exports.getDocumentFromTemplate = function getDocumentFromTemplate(template) {
361
+ var _id = (0, _generateObjectId["default"])();
362
+ var identifier = "doc_".concat(_id);
363
+
364
+ //Remove all references to original template object
365
+ var temp = JSON.parse(JSON.stringify(template));
366
+ return {
367
+ _id: _id,
368
+ identifier: identifier,
369
+ type: _DocumentTypes["default"].document,
370
+ name: temp.name,
371
+ template: temp.identifier,
372
+ source: temp.identifier,
373
+ files: temp.files,
374
+ fields: temp.fields
375
+ };
376
+ };
377
+
378
+ /**
379
+ * Handle Page Duplication for JoyDoc
380
+ *
381
+ * @param {Object} doc //Full JoyDoc Payload for Template or Document
382
+ * @param {String} fileId //File ID that contains the page we are duplicating
383
+ * @param {String} pageId
384
+ * @param {Object} pageDefaults
385
+ * @returns {Object}
386
+ */
387
+ var duplicateDocumentPage = exports.duplicateDocumentPage = function duplicateDocumentPage(doc, fileId, pageId) {
388
+ var _nextDoc$fields;
389
+ var pageDefaults = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
390
+ var changelogInfo = {
391
+ primaryPages: {
392
+ targetIndex: 0,
393
+ page: null
394
+ },
395
+ viewPages: [],
396
+ fields: []
397
+ };
398
+ var nextDoc = JSON.parse(JSON.stringify(doc));
399
+ var fileIndex = nextDoc.files.findIndex(function (file) {
400
+ return file._id === fileId;
401
+ });
402
+ var newPageId = (0, _generateObjectId["default"])();
403
+ var fieldLookup = {};
404
+ (_nextDoc$fields = nextDoc.fields) === null || _nextDoc$fields === void 0 ? void 0 : _nextDoc$fields.forEach(function (field) {
405
+ if (field.file === fileId) fieldLookup[field._id] = field;
406
+ });
407
+
408
+ /**
409
+ * Step 1: Duplicate fields associated with target page
410
+ */
411
+ var fieldIdsToDuplicate = [];
412
+
413
+ //Step 1.1 Get all field Ids from primary page
414
+ var targetPageIndex = nextDoc.files[fileIndex].pages.findIndex(function (page) {
415
+ return page._id === pageId;
416
+ });
417
+ if (targetPageIndex !== -1) nextDoc.files[fileIndex].pages[targetPageIndex].fieldPositions.forEach(function (fieldPosition) {
418
+ return fieldIdsToDuplicate.push(fieldPosition.field);
419
+ });
420
+
421
+ //Step 1.2 Get all field Ids from view page
422
+ if (nextDoc.files[fileIndex].views && nextDoc.files[fileIndex].views.length > 0) {
423
+ nextDoc.files[fileIndex].views.forEach(function (view) {
424
+ var viewPageIndex = view.pages.findIndex(function (page) {
425
+ return page._id === pageId;
426
+ });
427
+ if (viewPageIndex !== -1) {
428
+ view.pages[viewPageIndex].fieldPositions.forEach(function (fieldPosition) {
429
+ if (fieldIdsToDuplicate.indexOf(fieldPosition.field) === -1) fieldIdsToDuplicate.push(fieldPosition.field);
430
+ });
431
+ }
432
+ });
433
+ }
434
+ var newFieldsLookupByOldId = {};
435
+ var duplicatedFields = [];
436
+ fieldIdsToDuplicate.forEach(function (fieldId) {
437
+ /**
438
+ * Why do we check if a new field has already been created?
439
+ *
440
+ * That is because multiple field positions can be associated with the same
441
+ * field. If a field has already been created by a previous field position
442
+ * that is linked to the same field as the current target then do not create
443
+ * again.
444
+ */
445
+ if (newFieldsLookupByOldId[fieldId]) return;
446
+ var field = fieldLookup[fieldId];
447
+ var duplicateField = _objectSpread(_objectSpread({}, field), {}, {
448
+ _id: (0, _generateObjectId["default"])()
449
+ });
450
+ duplicatedFields.push(duplicateField);
451
+
452
+ /**
453
+ * Add to lookup so it can be used with other associated field positions
454
+ */
455
+ newFieldsLookupByOldId[field._id] = duplicateField;
456
+ });
457
+
458
+ /**
459
+ * Step 2: Update newly duplicated fields logic properties
460
+ *
461
+ * This step can only be done after all fields have been properly duplicated.
462
+ *
463
+ * We only need to update logic conditions that referenced the target page
464
+ * that we are duplicating. We do this by checking the logic.condition[x].page
465
+ * property of the condition.
466
+ */
467
+ duplicatedFields = duplicatedFields.map(function (duplicatedField) {
468
+ if (!duplicatedField.logic || !duplicatedField.logic.conditions || duplicatedField.logic.conditions.length < 1) return duplicatedField;
469
+ var nextField = _objectSpread(_objectSpread({}, duplicatedField), {}, {
470
+ logic: _objectSpread({}, duplicatedField.logic)
471
+ });
472
+ nextField.logic.conditions = nextField.logic.conditions.map(function (condition) {
473
+ /**
474
+ * 1. Only update conditions associated with the current page being duplicated.
475
+ * 2. Only update conditions associated with a field that was duplicated.
476
+ */
477
+ if (condition.page === pageId && newFieldsLookupByOldId[condition.field]) {
478
+ return _objectSpread(_objectSpread({}, condition), {}, {
479
+ page: newPageId,
480
+ field: newFieldsLookupByOldId[condition.field]._id
481
+ });
482
+ } else {
483
+ return condition;
484
+ }
485
+ });
486
+ return nextField;
487
+ });
488
+
489
+ /**
490
+ * Step 3: Add newly duplicated fields changelogs and update doucment
491
+ */
492
+ duplicatedFields.forEach(function (duplicateField) {
493
+ changelogInfo.fields.push(duplicateField);
494
+ nextDoc.fields.push(duplicateField);
495
+ });
496
+
497
+ /**
498
+ * Step 4: Update Primary View Page Order
499
+ *
500
+ * IMPORTANT NOTE: Page order update must go before page object creation.
501
+ */
502
+ var pageOrder = getPageOrder(nextDoc.files[fileIndex].pageOrder, nextDoc.files[fileIndex].pages);
503
+ var primaryPageOrderIndex = pageOrder.findIndex(function (id) {
504
+ return id === pageId;
505
+ });
506
+ var primaryPageOrderTargetIndex = primaryPageOrderIndex + 1;
507
+ nextDoc.files[fileIndex].pageOrder = pageOrder;
508
+ nextDoc.files[fileIndex].pageOrder.splice(primaryPageOrderTargetIndex, 0, newPageId);
509
+
510
+ /**
511
+ * Step 5: Generate Primary View Page
512
+ */
513
+ var primaryPageIndex = nextDoc.files[fileIndex].pages.findIndex(function (page) {
514
+ return page._id === pageId;
515
+ });
516
+ var newPrimaryPage = primaryPageIndex === -1 ? null : _objectSpread(_objectSpread({}, nextDoc.files[fileIndex].pages[primaryPageIndex]), {}, {
517
+ _id: newPageId,
518
+ fieldPositions: []
519
+ }, pageDefaults);
520
+ nextDoc.files[fileIndex].pages[primaryPageIndex].fieldPositions.forEach(function (fieldPosition) {
521
+ var newField = newFieldsLookupByOldId[fieldPosition.field];
522
+ newPrimaryPage.fieldPositions.push(_objectSpread(_objectSpread({}, fieldPosition), {}, {
523
+ field: newField._id
524
+ }));
525
+ });
526
+ nextDoc.files[fileIndex].pages.splice(primaryPageIndex + 1, 0, newPrimaryPage);
527
+
528
+ /**
529
+ * Step 6: Update Primary Page Changelog
530
+ */
531
+ changelogInfo.primaryPages.targetIndex = primaryPageOrderTargetIndex;
532
+ changelogInfo.primaryPages.page = newPrimaryPage;
533
+
534
+ /**
535
+ * Step 7: Update Views
536
+ */
537
+ if (nextDoc.files[fileIndex].views && nextDoc.files[fileIndex].views.length > 0) {
538
+ nextDoc.files[fileIndex].views = nextDoc.files[fileIndex].views.map(function (view) {
539
+ var nextView = _objectSpread({}, view);
540
+ var viewPageIndex = nextView.pages.findIndex(function (page) {
541
+ return page._id === pageId;
542
+ });
543
+ if (viewPageIndex === -1) return view;
544
+
545
+ /**
546
+ * Step 7.1 Update View Page Order.
547
+ *
548
+ * IMPORTANT NOTE: Page order update must go before page object creation.
549
+ */
550
+ var nextViewPageOrder = getPageOrder(nextView.pageOrder, nextView.pages);
551
+ var nextViewPageOrderIndex = nextViewPageOrder.findIndex(function (id) {
552
+ return id === pageId;
553
+ });
554
+ var nextViewTargetPageOrderIndex = nextViewPageOrderIndex + 1;
555
+ nextView.pageOrder = nextViewPageOrder;
556
+ nextView.pageOrder.splice(nextViewTargetPageOrderIndex, 0, newPageId);
557
+
558
+ /**
559
+ * Step 7.2 Update View Pages
560
+ */
561
+ var newViewPage = _objectSpread(_objectSpread({}, nextView.pages[viewPageIndex]), {}, {
562
+ _id: newPageId,
563
+ fieldPositions: []
564
+ }, pageDefaults);
565
+ nextView.pages[viewPageIndex].fieldPositions.forEach(function (fieldPosition) {
566
+ var newField = newFieldsLookupByOldId[fieldPosition.field];
567
+ newViewPage.fieldPositions.push(_objectSpread(_objectSpread({}, fieldPosition), {}, {
568
+ field: newField._id
569
+ }));
570
+ });
571
+ nextView.pages.splice(viewPageIndex + 1, 0, newViewPage);
572
+
573
+ /**
574
+ * Step 7.3 Add View Page Changelog Info
575
+ */
576
+ changelogInfo.viewPages.push({
577
+ viewId: view._id,
578
+ view: view.type,
579
+ targetIndex: nextViewTargetPageOrderIndex,
580
+ page: newViewPage
581
+ });
582
+ return nextView;
583
+ });
584
+ }
585
+ return {
586
+ changelogInfo: changelogInfo,
587
+ doc: nextDoc
588
+ };
589
+ };
590
+
591
+ /**
592
+ * Generate the mobile view and add specific mobile view properties
593
+ *
594
+ * @param {Object} file //Full file object
595
+ * @returns {Object}
596
+ */
597
+ var getMobileViewFromFile = exports.getMobileViewFromFile = function getMobileViewFromFile(file) {
598
+ var _file$views2;
599
+ var mobileViewIndex = file !== null && file !== void 0 && file.views && (file === null || file === void 0 ? void 0 : (_file$views2 = file.views) === null || _file$views2 === void 0 ? void 0 : _file$views2.length) > 0 ? file.views.findIndex(function (view) {
600
+ return view.type === _FileViews["default"].mobile;
601
+ }) : -1;
602
+ if (mobileViewIndex !== -1) {
603
+ /**
604
+ * Why do we do this? Early versions of alternative views did not contain pageOrder so
605
+ * we ensure it's populated here.
606
+ */
607
+ var mobileView = file.views[mobileViewIndex];
608
+ var mobileViewPageOrder = cleanPageOrder(getPageOrder(mobileView.pageOrder, mobileView.pages), mobileView.pages);
609
+ return _objectSpread(_objectSpread({}, mobileView), {}, {
610
+ pageOrder: mobileViewPageOrder
611
+ });
612
+ } else {
613
+ return generateMobileViewFromFile(file);
614
+ }
615
+ };
616
+
617
+ /**
618
+ * Generates the alternative mobile view from the default file view.
619
+ *
620
+ * @param {Object} file //Full file object
621
+ * @returns {Object}
622
+ */
623
+ var generateMobileViewFromFile = exports.generateMobileViewFromFile = function generateMobileViewFromFile(file) {
624
+ var pages = file.pages || [];
625
+ var pageOrder = cleanPageOrder(getPageOrder(file.pageOrder, file.pages), file.pages);
626
+ return {
627
+ _id: (0, _generateObjectId["default"])(),
628
+ type: _FileViews["default"].mobile,
629
+ pages: (0, _toConsumableArray2["default"])(pages).map(function (page) {
630
+ var _id = page._id,
631
+ name = page.name,
632
+ identifier = page.identifier,
633
+ fieldPositions = page.fieldPositions,
634
+ rowHeight = page.rowHeight;
635
+ return generateMobilePage({
636
+ _id: _id,
637
+ identifier: identifier,
638
+ name: name,
639
+ fieldPositions: fieldPositions,
640
+ rowHeight: rowHeight
641
+ });
642
+ }),
643
+ pageOrder: (0, _toConsumableArray2["default"])(pageOrder)
644
+ };
645
+ };
646
+
647
+ /**
648
+ * Apply the pr
649
+ *
650
+ * @param {Object} page
651
+ * @returns {Objectg}
652
+ */
653
+ var generateMobilePage = exports.generateMobilePage = function generateMobilePage(page) {
654
+ return _objectSpread(_objectSpread({}, page), {}, {
655
+ fieldPositions: page.fieldPositions ? generateMobilePageFieldPositions(page.fieldPositions, page.rowHeight) : [],
656
+ type: _PageTypes["default"].mobile,
657
+ rowHeight: 1,
658
+ cols: 1,
659
+ padding: 12,
660
+ width: 816,
661
+ height: 1056,
662
+ layout: _PageLayoutModes["default"].grid,
663
+ presentation: _FieldPresentationModes["default"].normal
664
+ });
665
+ };
666
+ var generateMobilePageFieldPositions = exports.generateMobilePageFieldPositions = function generateMobilePageFieldPositions(fieldPositions, originalRowHeight) {
667
+ var mobileFieldPositions = [];
668
+
669
+ /**
670
+ * Step 1: Sort fieldPositions
671
+ */
672
+ var sortedFieldPositions = sortFieldPositionsByXAndYCoordinates(fieldPositions);
673
+ sortedFieldPositions.forEach(function (joySpecFieldPosition) {
674
+ var mobileFieldPositionData = _objectSpread(_objectSpread({}, joySpecFieldPosition), {}, {
675
+ titleDisplay: _FormStyleOptions["default"].displayInline,
676
+ displayType: _FieldDisplayTypes["default"].original,
677
+ height: joySpecFieldPosition.height * (originalRowHeight || 1),
678
+ width: 1,
679
+ x: 0
680
+ });
681
+
682
+ /**
683
+ * Step 1.2 Hide chart lines on mobile
684
+ */
685
+ if (joySpecFieldPosition.type === _FieldTypes["default"].chart) mobileFieldPositionData.primaryDisplayOnly = true;
686
+ mobileFieldPositions.push(mobileFieldPositionData);
687
+ });
688
+ return mergeAssoicatedFieldPositionsForMobilePage(mobileFieldPositions);
689
+ };
690
+
691
+ /**
692
+ * Merge Field Positions assoicated with the same Field.
693
+ *
694
+ * Why do duplicate fields get created from fieldPositions
695
+ *
696
+ * The same field can get added twice because we may have multiple fieldPositions belonging
697
+ * to the same field. This can happen with dropdown, multiSelect, and table fields.
698
+ *
699
+ * Since the fields get generated by looping over the fieldPositions and not regular fields
700
+ * we may encounter the the same field multiple times because it has multiple fieldPositions.
701
+ *
702
+ * @param {Array} fields
703
+ * @returns {Array}
704
+ */
705
+ var mergeAssoicatedFieldPositionsForMobilePage = exports.mergeAssoicatedFieldPositionsForMobilePage = function mergeAssoicatedFieldPositionsForMobilePage(fieldPositions) {
706
+ var filteredFieldPositions = [];
707
+ fieldPositions === null || fieldPositions === void 0 ? void 0 : fieldPositions.forEach(function (fieldPosition) {
708
+ var fieldPositionIndex = filteredFieldPositions.findIndex(function (filtered) {
709
+ var _filtered$field, _fieldPosition$field;
710
+ return (filtered === null || filtered === void 0 ? void 0 : (_filtered$field = filtered.field) === null || _filtered$field === void 0 ? void 0 : _filtered$field.toString()) === (fieldPosition === null || fieldPosition === void 0 ? void 0 : (_fieldPosition$field = fieldPosition.field) === null || _fieldPosition$field === void 0 ? void 0 : _fieldPosition$field.toString());
711
+ });
712
+
713
+ //Only add field to the list if it hasn't already been added
714
+ if (fieldPositionIndex === -1) filteredFieldPositions.push(fieldPosition);
715
+ });
716
+ return filteredFieldPositions;
717
+ };
718
+
719
+ /**
720
+ * Sort fields by their y and x coordinates
721
+ *
722
+ * For example:
723
+ * [
724
+ * { "y": 3, "x": 4 },
725
+ * { "y": 3, "x": 1 },
726
+ * { "y": 2, "x": 0 },
727
+ * { "y": 1, "x": 5.22 },
728
+ * { "y": 1, "x": 10 },
729
+ * { "y": 1, "x": 0 },
730
+ * ]
731
+ * will become the following after sort
732
+ * [
733
+ * { "y": 1, "x": 0 },
734
+ * { "y": 1, "x": 5.22 },
735
+ * { "y": 1, "x": 10 },
736
+ * { "y": 2, "x": 0 },
737
+ * { "y": 3, "x": 1 },
738
+ * { "y": 3, "x": 4 }
739
+ * ];
740
+ *
741
+ * @param {Array} fieldPositions
742
+ * @returns {Array}
743
+ */
744
+ var sortFieldPositionsByXAndYCoordinates = exports.sortFieldPositionsByXAndYCoordinates = function sortFieldPositionsByXAndYCoordinates(fieldPositions) {
745
+ var sortedFieldPositions = (0, _toConsumableArray2["default"])(fieldPositions);
746
+ sortedFieldPositions.sort(function (a, b) {
747
+ if (a.y === b.y) {
748
+ return a.x - b.x;
749
+ } else if (a.y > b.y) {
750
+ return 1;
751
+ } else if (a.y < b.y) {
752
+ return -1;
753
+ } else {
754
+ return 0;
755
+ }
756
+ });
757
+ return sortedFieldPositions;
758
+ };
759
+
760
+ /**
761
+ * Formats individual table cell field positions that have already been merged with their associated field.
762
+ * This additional information is added and used for rendering the fieldPositions on the form.
763
+ *
764
+ * For instance, adds properties like columnType, calculatedCellValue, options, etc.
765
+ *
766
+ * @param {Array} fieldPositions
767
+ * @returns {Array}
768
+ */
769
+ var formatTableFieldPositions = exports.formatTableFieldPositions = function formatTableFieldPositions(fieldPositions) {
770
+ /**
771
+ * We only want to generate the table value calculated lookup for each table field once.
772
+ * We use these lookups because multiple table fieldPositions belonging to the same table
773
+ * field will all use the same table value calculated lookup.
774
+ */
775
+ var tableFieldLookup = {};
776
+ var nextFieldPositions = [];
777
+ (0, _toConsumableArray2["default"])(fieldPositions).forEach(function (fieldPosition) {
778
+ var nextFieldPosition = _objectSpread({}, fieldPosition);
779
+ if (fieldPosition.type === _FieldTypes["default"].table) {
780
+ var field = fieldPosition.field,
781
+ column = fieldPosition.column,
782
+ rowIndex = fieldPosition.rowIndex,
783
+ tableColumns = fieldPosition.tableColumns,
784
+ value = fieldPosition.value,
785
+ rowOrder = fieldPosition.rowOrder,
786
+ tableColumnOrder = fieldPosition.tableColumnOrder;
787
+
788
+ /**
789
+ * Step 1: Generate rows, rowOrder, tableColumns, etc. lookups for associated field. We only have to
790
+ * do this once per-field. This increases performance if there are multiple form positions associated
791
+ * with the same form.
792
+ */
793
+ if (!tableFieldLookup[field]) {
794
+ /**
795
+ * Step 1.1 Handle rows
796
+ */
797
+ var nextRows = (0, _tableHelper.getRows)(value);
798
+ var nextRowOrder = (0, _tableHelper.getCleanedRowOrder)(rowOrder, nextRows);
799
+ var nextSortedRows = (0, _tableHelper.sortRows)(nextRows, nextRowOrder);
800
+
801
+ /**
802
+ * Step 1.2 Handle columns
803
+ */
804
+ var nextTableColumnOrder = (0, _tableHelper.getCleanedColumnOrder)(tableColumnOrder, tableColumns);
805
+ var nextSortedTableColumns = (0, _tableHelper.sortColumns)(tableColumns, nextTableColumnOrder);
806
+ var nextTableColumns = (0, _tableHelper.getColumns)(nextSortedTableColumns);
807
+ var nextTableColumnLookup = {};
808
+ nextTableColumns.forEach(function (column) {
809
+ return nextTableColumnLookup[column._id] = column;
810
+ });
811
+
812
+ /**
813
+ * Step 1.3 Handle cell calculations
814
+ */
815
+ var calculatedValue = (0, _tableHelper.generateTableLookup)(nextSortedRows, nextSortedTableColumns);
816
+ tableFieldLookup[field] = {
817
+ value: nextSortedRows,
818
+ rowOrder: nextRowOrder,
819
+ tableColumns: nextTableColumns,
820
+ tableColumnOrder: nextTableColumnOrder,
821
+ tableColumnLookup: nextTableColumnLookup,
822
+ calculatedValue: calculatedValue
823
+ };
824
+ }
825
+
826
+ /**
827
+ * Ensure each table field has a properly formatted properties
828
+ */
829
+ nextFieldPosition.value = tableFieldLookup[field].value;
830
+ nextFieldPosition.rowOrder = tableFieldLookup[field].rowOrder;
831
+ nextFieldPosition.tableColumns = tableFieldLookup[field].tableColumns;
832
+ nextFieldPosition.tableColumnOrder = tableFieldLookup[field].tableColumnOrder;
833
+
834
+ /**
835
+ * Add calculated value lookup. For instance, { A1: '', B1: '', C1: '', ... }
836
+ */
837
+ nextFieldPosition.calculatedValue = tableFieldLookup[field].calculatedValue;
838
+
839
+ /**
840
+ * Individual Table Cell vs Entire Table
841
+ *
842
+ * Only add cellValue, calculatedCellValue, columnType, and column options to
843
+ * individually mapped table cell fieldPositions. Regular table fields (entire table)
844
+ * just simply use the fieldPositions.value parameter so we don't need the calculated
845
+ * values, etc.
846
+ *
847
+ * We determine an individual table cell fieldPosition vs an entire table
848
+ * fieldPosition by checking for column and rowIndex. Individual cells have
849
+ * column and rowIndex but regular tables do not.
850
+ *
851
+ * Note:
852
+ * rowIndex + 1 is used while calculating cell value since column operands
853
+ * start from 1 instead of zero in the table lookups
854
+ * (ie: [A1:{}, B1:{}] instead of [A0:{}, B0:{}])
855
+ *
856
+ * If tableRowIndex associated with a cell doesn't have a table row associated
857
+ * with it (ie rows[rowIndex] is undefined) it means that particular row is deleted
858
+ */
859
+ if (tableFieldLookup[field] && column && typeof rowIndex === 'number') {
860
+ var _tableFieldLookup$fie;
861
+ /**
862
+ * What is the difference between rowIndex and targetRowIndex?
863
+ *
864
+ * - The rowIndex on the fieldPosition is the saved index of where the rowId lives inside of the rowOrder.
865
+ * - The targetRowIndex is the actual index of the row object inside the value (array of row data) of the field.
866
+ *
867
+ * We use the fieldPosition.rowIndex to get the rowId from the rowOrder. Then we use the rowId to locate
868
+ * the assoicated row object data in the value property. The rowOrder and value (rows) do not follow the same
869
+ * order. The rowOrder is updated when users insert rows, move rows up or down, etc. it manages where rows
870
+ * are at in the list and how they should be rendered. This is why the rowIndex uses the rowOrder.
871
+ */
872
+ var targetColumn = tableFieldLookup[field].tableColumnLookup[column];
873
+ var targetRowId = tableFieldLookup[field].rowOrder[rowIndex];
874
+ var targetRowIndex = tableFieldLookup[field].value.findIndex(function (row) {
875
+ return (row === null || row === void 0 ? void 0 : row._id) === targetRowId;
876
+ });
877
+
878
+ /**
879
+ * Add proper rowId to the field position so that it can be used
880
+ * inside the element for change handlers;
881
+ */
882
+ nextFieldPosition.rowId = targetRowId;
883
+
884
+ /**
885
+ * If rows[rowIndex] is undefined, it means the row that was present
886
+ * at the particular rowIndex was deleted
887
+ */
888
+ nextFieldPosition.cellValue = ((_tableFieldLookup$fie = tableFieldLookup[field].value[targetRowIndex]) === null || _tableFieldLookup$fie === void 0 ? void 0 : _tableFieldLookup$fie.cells[column]) || '';
889
+
890
+ /**
891
+ * Skip any individual field position that is associated with a deleted column.
892
+ * targetColumn will appear as undefined if a column is deleted
893
+ */
894
+ if (targetColumn) {
895
+ nextFieldPosition.calculatedCellValue = tableFieldLookup[field].calculatedValue["".concat(targetColumn.operand).concat(targetRowIndex + 1)];
896
+ nextFieldPosition.columnType = targetColumn.type;
897
+ nextFieldPosition.options = targetColumn.options;
898
+ nextFieldPosition.columnIdentifier = targetColumn.identifier;
899
+
900
+ /**
901
+ * IMPORTANT NOTE: We only add individual table cell field position into
902
+ * the fieldPosition list if the associated column is not deleted.
903
+ */
904
+ nextFieldPositions.push(nextFieldPosition);
905
+ }
906
+ } else {
907
+ //Push table fields with original display type
908
+ nextFieldPositions.push(nextFieldPosition);
909
+ }
910
+ } else {
911
+ //Push other fields
912
+ nextFieldPositions.push(nextFieldPosition);
913
+ }
914
+ });
915
+ return nextFieldPositions;
916
+ };
917
+ var _default = exports["default"] = {
918
+ getDefaultJoyDocPage: getDefaultJoyDocPage,
919
+ getDefaultJoyDocFile: getDefaultJoyDocFile,
920
+ getDefaultJoyDoc: getDefaultJoyDoc,
921
+ getCleanedJoyDoc: getCleanedJoyDoc,
922
+ getCleanedJoyDocPages: getCleanedJoyDocPages,
923
+ getDefaultDocument: getDefaultDocument,
924
+ getDefaultTemplate: getDefaultTemplate,
925
+ getDocumentFromTemplate: getDocumentFromTemplate,
926
+ duplicate: duplicate,
927
+ duplicateDocumentPage: duplicateDocumentPage,
928
+ getPageOrder: getPageOrder,
929
+ sortPages: sortPages,
930
+ sortFieldPositionsByXAndYCoordinates: sortFieldPositionsByXAndYCoordinates,
931
+ mergeAssoicatedFieldPositionsForMobilePage: mergeAssoicatedFieldPositionsForMobilePage,
932
+ generateMobileViewFromFile: generateMobileViewFromFile,
933
+ generateMobilePage: generateMobilePage,
934
+ generateMobilePageFieldPositions: generateMobilePageFieldPositions,
935
+ formatTableFieldPositions: formatTableFieldPositions
936
+ };