@livepreso/api 6.56.1 → 6.57.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.
Files changed (92) hide show
  1. package/.rush/temp/chunked-rush-logs/api.build.chunks.jsonl +5 -15
  2. package/.rush/temp/operation/build/all.log +5 -15
  3. package/.rush/temp/operation/build/error.log +3 -13
  4. package/.rush/temp/operation/build/log-chunks.jsonl +5 -15
  5. package/.rush/temp/operation/build/state.json +1 -1
  6. package/CHANGELOG.json +35 -0
  7. package/CHANGELOG.md +17 -1
  8. package/cjs/collections/adjunct-sub-slides.js +13 -1
  9. package/cjs/collections/adjunct-sub-slides.js.map +1 -1
  10. package/cjs/fixtures.js +13 -2
  11. package/cjs/fixtures.js.map +1 -1
  12. package/cjs/models/base.js +12 -3
  13. package/cjs/models/base.js.map +1 -1
  14. package/cjs/models/deck-version.js +2 -0
  15. package/cjs/models/deck-version.js.map +1 -1
  16. package/cjs/models/dispatch-preview.js +0 -2
  17. package/cjs/models/dispatch-preview.js.map +1 -1
  18. package/cjs/models/dispatch.js +1 -1
  19. package/cjs/models/dispatch.js.map +1 -1
  20. package/cjs/models/manifest-json.js +0 -2
  21. package/cjs/models/manifest-json.js.map +1 -1
  22. package/cjs/models/room.js +4 -0
  23. package/cjs/models/room.js.map +1 -1
  24. package/cjs/models/user.js +1 -1
  25. package/cjs/models/user.js.map +1 -1
  26. package/cjs/presentation/base-presentation-model.js +6 -6
  27. package/cjs/presentation/base-presentation-model.js.map +1 -1
  28. package/cjs/presentation/presentation-deck.js +82 -27
  29. package/cjs/presentation/presentation-deck.js.map +1 -1
  30. package/cjs/presentation/presentation-section.js +42 -47
  31. package/cjs/presentation/presentation-section.js.map +1 -1
  32. package/cjs/presentation/presentation-slide.js +35 -39
  33. package/cjs/presentation/presentation-slide.js.map +1 -1
  34. package/cjs/sync.js +3 -3
  35. package/cjs/sync.js.map +1 -1
  36. package/cjs/utils.js +9 -6
  37. package/cjs/utils.js.map +1 -1
  38. package/package.json +2 -2
  39. package/rush-logs/api.build.error.log +3 -13
  40. package/rush-logs/api.build.log +5 -15
  41. package/src/collections/adjunct-sub-slides.js +13 -0
  42. package/src/fixtures.js +16 -2
  43. package/src/models/base.js +16 -3
  44. package/src/models/deck-version.js +2 -0
  45. package/src/models/dispatch-preview.js +0 -3
  46. package/src/models/dispatch.js +1 -1
  47. package/src/models/manifest-json.js +7 -12
  48. package/src/models/room.js +5 -0
  49. package/src/models/user.js +4 -4
  50. package/src/presentation/base-presentation-model.js +14 -6
  51. package/src/presentation/presentation-deck.js +63 -24
  52. package/src/presentation/presentation-section.js +31 -50
  53. package/src/presentation/presentation-slide.js +36 -43
  54. package/src/sync.js +3 -4
  55. package/src/utils.js +9 -6
  56. package/.rush/temp/1aebf46f78ad5c45f82f8147751890adb37bef9d.log +0 -10
  57. package/.rush/temp/256021b5963b4c0221d3dec247b697b9691a9b2c.log +0 -10
  58. package/.rush/temp/2a322f00f12cf9d1e64afe81275cc78d01c49050.log +0 -10
  59. package/.rush/temp/30061f1865447dcbb3f20a305061205f3dbe6091.log +0 -10
  60. package/.rush/temp/3cdc82c352e8ed90607952873f3aa4c200490874.log +0 -10
  61. package/.rush/temp/45522aea0dee8cb2be1a53248ba45bd235743b43.log +0 -10
  62. package/.rush/temp/5489ab737e406518983c16c57fc3e1edc07c0341.log +0 -10
  63. package/.rush/temp/58fcbb7f15a76326d40e0839ab179755da82a891.log +0 -10
  64. package/.rush/temp/5bc0bba70b733baa4dd976667ba0a1386e516186.log +0 -10
  65. package/.rush/temp/64f1bb696f8d7d7e72907b80df316b127f72e23e.log +0 -10
  66. package/.rush/temp/6f640f951414ea68adb65c17e4ed7527cde54faf.log +0 -10
  67. package/.rush/temp/7c7b958682d4ab5697530be47d0aac62efe1adf1.log +0 -10
  68. package/.rush/temp/82bfb987463fbcfebf04022e6ed00015c73879c8.log +0 -10
  69. package/.rush/temp/844034aa6e542115075e8f3dc5ffc640973e0064.log +0 -10
  70. package/.rush/temp/8b42957a7c15da1f29cb57bee125f13affa70dca.log +0 -10
  71. package/.rush/temp/924652444ab5a6063f328a2217123a2227058896.log +0 -10
  72. package/.rush/temp/9f2030f96d62f3e38052e35201819a216566f14f.log +0 -10
  73. package/.rush/temp/a769db9d81a23000c0e9b1bf4f1a9a9e721d0d7c.log +0 -10
  74. package/.rush/temp/a87d3a8b4ece87ec66f27c86226a9f205617681f.log +0 -10
  75. package/.rush/temp/bb7a5bdcc4af4ad1507f81f33774b31f5b4e4fb7.log +0 -10
  76. package/.rush/temp/build-cache-tar.log +0 -7
  77. package/.rush/temp/c20e29ccaaa9231b38a28bb24451b4ce7562cdc0.log +0 -10
  78. package/.rush/temp/chunked-rush-logs/api.test.chunks.jsonl +0 -1
  79. package/.rush/temp/e21303db8f59b4625fd184c9114377d781fd24f8.log +0 -10
  80. package/.rush/temp/e6d303862765b6a5f41dd483d0f9ae083a1fae10.log +0 -10
  81. package/.rush/temp/eaf69fbc059d2f1258d7569136180d4a1d3c7072.log +0 -10
  82. package/.rush/temp/f85d279e2674966daaec83e1c3986a96f86ef304.log +0 -10
  83. package/.rush/temp/fc0a332c5b34c6b90006850cf2d93a48fb4b9a6e.log +0 -10
  84. package/.rush/temp/operation/test/all.log +0 -21
  85. package/.rush/temp/operation/test/log-chunks.jsonl +0 -21
  86. package/.rush/temp/operation/test/state.json +0 -3
  87. package/.rush/temp/package-deps_build.json +0 -185
  88. package/api.build.log +0 -9
  89. package/api.test.cache.log +0 -1
  90. package/api.test.log +0 -19
  91. package/rush-logs/api.test.cache.log +0 -1
  92. package/rush-logs/api.test.log +0 -1
@@ -13,6 +13,19 @@ export const AdjunctSubSlideCollection = DuplicateIdCollection.extend(
13
13
  /** @lends collections.AdjunctSubSlideCollection# */ {
14
14
  comparator: "sequence",
15
15
  model: "AdjunctSubSlideModel",
16
+
17
+ /**
18
+ * Fetch a collection of adjunct slides related to an appointment
19
+ * @param {Integer} id - The id of the appointment
20
+ * @return {Promise} - A collection of AdjunctSlide models
21
+ */
22
+ fetchByAppointmentID(id) {
23
+ return this.fetch({
24
+ data: {
25
+ appointment: id,
26
+ },
27
+ });
28
+ },
16
29
  },
17
30
  );
18
31
 
package/src/fixtures.js CHANGED
@@ -22,6 +22,8 @@ const presentationCollections = {
22
22
  PresentationSubSlides: presentation.PresentationSubSlides,
23
23
  };
24
24
 
25
+ const _buildStack = new Set();
26
+
25
27
  function uuid() {
26
28
  return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
27
29
  const r = (Math.random() * 16) | 0;
@@ -70,7 +72,17 @@ function makeFactory(name, Model, ignoreFields = []) {
70
72
  continue;
71
73
  }
72
74
  factory.attr(key, () => {
73
- return Factory.build(value);
75
+ if (_buildStack.has(value)) {
76
+ throw new Error(
77
+ `Recursion detected: ${[..._buildStack].join(" -> ")} -> ${value}`,
78
+ );
79
+ }
80
+ _buildStack.add(value);
81
+ try {
82
+ return Factory.build(value);
83
+ } finally {
84
+ _buildStack.delete(value);
85
+ }
74
86
  });
75
87
  }
76
88
  }
@@ -187,6 +199,8 @@ factories.UserModel.attr("first_name", () => faker.name.firstName()).attr(
187
199
 
188
200
  factories.TenancyModel.attr("administrator", null);
189
201
 
202
+ factories.RoomModel.attr("hostedpreso", null);
203
+
190
204
  factories.TemplateModel.sequence("sequence")
191
205
  // Prevent max call stack overflow
192
206
  .attr("original_template", null)
@@ -201,7 +215,7 @@ factories.ContactModel.attr("customer", null)
201
215
  .attr("name_first", () => faker.name.firstName())
202
216
  .attr("name_last", () => faker.name.lastName())
203
217
  .attr("email", () => faker.internet.email())
204
- .after((contact, options) => {
218
+ .after((contact) => {
205
219
  if (!contact.customer) {
206
220
  contact.customer = M("CustomerModel", {
207
221
  contact_set: [contact],
@@ -12,6 +12,8 @@ import qs from "qs";
12
12
  import { registeredStates } from "../state-register.js";
13
13
  import { sync } from "../sync.js";
14
14
 
15
+ const URL_TEMPLATE_RE = /(\{(?:\w+\.?)+\})/g;
16
+
15
17
  /**
16
18
  * @constructor
17
19
  * @alias models.BaseModel
@@ -154,7 +156,11 @@ export const BaseModel = Model.extend(
154
156
 
155
157
  // Internal function. Used by collection as well.
156
158
  _matchesURL(url, matchesDetail = true) {
157
- if (!this.modelName || this.urlRoot() === Api.getURL()) {
159
+ if (
160
+ typeof url !== "string" ||
161
+ !this.modelName ||
162
+ this.urlRoot() === Api.getURL()
163
+ ) {
158
164
  return false;
159
165
  }
160
166
 
@@ -435,6 +441,13 @@ export const BaseModel = Model.extend(
435
441
  save() {
436
442
  return Model.prototype.save.apply(this, arguments).tap((response) => {
437
443
  this._updateResponse(response);
444
+ // Sort events after server response to ensure ascending order
445
+ // since the server may return them in a different order
446
+ if (this.events && this.events.length > 1) {
447
+ this.events.sort((a, b) => {
448
+ return new Date(a.timestamp) - new Date(b.timestamp);
449
+ });
450
+ }
438
451
  });
439
452
  },
440
453
 
@@ -653,8 +666,8 @@ export const BaseModel = Model.extend(
653
666
  // So if you have /path/to/{model.id}/
654
667
  // It will check the model from "this.model.id" and replace
655
668
  // it in the url
656
- const re = /(\{(?:\w+\.?)+\})/g;
657
- const matches = resp.match(re) || [];
669
+ URL_TEMPLATE_RE.lastIndex = 0;
670
+ const matches = resp.match(URL_TEMPLATE_RE) || [];
658
671
  for (const match of matches) {
659
672
  const path = match.slice(1, -1);
660
673
  const replacement = _.get(this, path);
@@ -50,6 +50,8 @@ export const DeckVersionModel = BaseModel.extend(
50
50
  image_256_archive: "string",
51
51
  image_512_archive: "string",
52
52
  namespaced_key: "string",
53
+ created_date: "date",
54
+ modified_date: "date",
53
55
  creation_status: "string",
54
56
  creation_percent: "number",
55
57
  update_description: "string",
@@ -23,9 +23,6 @@ export const DispatchPreviewModel = BaseModel.extend(
23
23
  .then((resp) => {
24
24
  this.content = resp.text;
25
25
  return resp.text;
26
- })
27
- .catch(superagent.SuperagentPromiseError, (e) => {
28
- throw e;
29
26
  });
30
27
  },
31
28
  },
@@ -109,7 +109,7 @@ export const DispatchModel = BaseModel.extend(
109
109
  data.snapshot = this._retrieveURL(this.snapshot);
110
110
  }
111
111
 
112
- return data;
112
+ return _.omit(data, ["contentModel"]);
113
113
  },
114
114
 
115
115
  serialize() {
@@ -197,18 +197,13 @@ export const ManifestJSONModel = BaseModel.extend(
197
197
  const imports = _.map(fixturePaths, (fixture, key) => {
198
198
  const path = `${rootAssetUrl}${fixture}`;
199
199
 
200
- return superagent
201
- .get(path)
202
- .then((response) => {
203
- if (response.text) {
204
- fixtures[key] = JSON.parse(response.text);
205
- } else {
206
- fixtures[key] = response.body || {};
207
- }
208
- })
209
- .catch(superagent.SuperagentPromiseError, (e) => {
210
- throw e;
211
- });
200
+ return superagent.get(path).then((response) => {
201
+ if (response.text) {
202
+ fixtures[key] = JSON.parse(response.text);
203
+ } else {
204
+ fixtures[key] = response.body || {};
205
+ }
206
+ });
212
207
  });
213
208
 
214
209
  await Promise.all(imports);
@@ -1,5 +1,6 @@
1
1
  import { BaseModel } from "./base.js";
2
2
  import { register } from "../state-register.js";
3
+ import "./hosted-preso.js";
3
4
 
4
5
  /**
5
6
  * @constructor
@@ -38,6 +39,10 @@ export const RoomModel = BaseModel.extend(
38
39
  wamp_version: "string",
39
40
  websocket_server_uri: "string",
40
41
  },
42
+
43
+ children: {
44
+ hostedpreso: "HostedPresoModel",
45
+ },
41
46
  },
42
47
  );
43
48
 
@@ -143,15 +143,15 @@ export const UserModel = BaseModel.extend(
143
143
  presomanager.isGlobalTemporarySlideManager ||
144
144
  presomanager.isTeamTemporarySlideManager;
145
145
 
146
+ presomanager.canModifyContent =
147
+ this.actions.indexOf("Create Content") > -1 ||
148
+ this.actions.indexOf("Manage Team Editable Text") > -1;
149
+
146
150
  presomanager.isPresoManagerUser =
147
151
  presomanager.canModifyTemporarySlides ||
148
152
  presomanager.canModifyNotes ||
149
153
  presomanager.canModifyContent;
150
154
 
151
- presomanager.canModifyContent =
152
- this.actions.indexOf("Create Content") > -1 ||
153
- this.actions.indexOf("Manage Team Editable Text") > -1;
154
-
155
155
  const appointments = {
156
156
  canUploadCustomSlides:
157
157
  this.actions.indexOf("Upload Custom Slides") > -1 &&
@@ -128,10 +128,14 @@ BasePresentationModel.getVisibilityAndSequence = function (
128
128
  if (choicelist) {
129
129
  // All items should have a choicelist entry - if it's not in
130
130
  // the choicelist, it's not in the preso
131
- const choice = choicelist.find((item) => item.url === url);
131
+ const choice = options.choicelistMap
132
+ ? options.choicelistMap.get(url)
133
+ : choicelist.find((item) => item.url === url);
132
134
 
133
135
  if (choice) {
134
- config.sequence = choicelist.indexOf(choice);
136
+ config.sequence = options.choicelistMap
137
+ ? choice._idx
138
+ : choicelist.indexOf(choice);
135
139
  config.visible = choice.visible;
136
140
  } else {
137
141
  config.visible = false;
@@ -140,7 +144,9 @@ BasePresentationModel.getVisibilityAndSequence = function (
140
144
  // Non-adjunct subslides and adjunct sections/slides/subslides
141
145
  // have no selections - they fall through here using their
142
146
  // model's values
143
- const selection = selections.find((selection) => selection.url === url);
147
+ const selection = options.selectionsMap
148
+ ? options.selectionsMap.get(url)
149
+ : selections.find((selection) => selection.url === url);
144
150
 
145
151
  if (selection) {
146
152
  config.visible = selection.visible;
@@ -155,9 +161,11 @@ BasePresentationModel.getVisibilityAndSequence = function (
155
161
  return config;
156
162
  };
157
163
 
158
- const getAppointmentTags = function (model, tags) {
164
+ const getAppointmentTags = function (model, tags, options) {
159
165
  const url = model.adjunct?.url() || model.url();
160
- const tagItem = tags.find((tag) => tag.content_url === url);
166
+ const tagItem = options?.appointmentTagsMap
167
+ ? options.appointmentTagsMap.get(url)
168
+ : tags.find((tag) => tag.content_url === url);
161
169
 
162
170
  if (tagItem) {
163
171
  return tagItem.tags || [];
@@ -204,7 +212,7 @@ const getDeckTags = function (model, tags) {
204
212
  // references to model.tags should be removed.
205
213
  BasePresentationModel.getTags = function (model, options = {}) {
206
214
  if (options.appointmentTags) {
207
- return getAppointmentTags(model, options.appointmentTags);
215
+ return getAppointmentTags(model, options.appointmentTags, options);
208
216
  }
209
217
 
210
218
  if (options.deckTags) {
@@ -120,21 +120,19 @@ PresentationDeck.createFromDeckVersion = function (
120
120
  deckVersionModel,
121
121
  options = {},
122
122
  ) {
123
- _.defaults(options, {
124
- index: 0,
125
- autoAdjuncts: new collections.AutoAdjunctCollection(),
126
- adjunctSections: new collections.AdjunctSectionCollection(),
127
- adjunctSlides: new collections.AdjunctSlideCollection(),
128
- adjunctSubSlides: new collections.AdjunctSubSlideCollection(),
129
- sectionSelections: new collections.SectionSelectionCollection(),
130
- slideSelections: new collections.SlideSelectionCollection(),
131
- screenshots: new collections.DeckVersionScreenshotCollection(),
132
- rootAssetPath: null,
133
- templates: null,
134
- choicelist: null,
135
- });
136
-
137
- options.screenshots = PresentationDeck.screenshotsToMap(options.screenshots);
123
+ options.index ??= 0;
124
+ options.autoAdjuncts ??= new collections.AutoAdjunctCollection();
125
+ options.adjunctSections ??= new collections.AdjunctSectionCollection();
126
+ options.adjunctSlides ??= new collections.AdjunctSlideCollection();
127
+ options.adjunctSubSlides ??= new collections.AdjunctSubSlideCollection();
128
+ options.sectionSelections ??= new collections.SectionSelectionCollection();
129
+ options.slideSelections ??= new collections.SlideSelectionCollection();
130
+ options.rootAssetPath ??= null;
131
+ options.templates ??= null;
132
+ options.choicelist ??= null;
133
+ options.screenshots = PresentationDeck.screenshotsToMap(
134
+ options.screenshots ?? new collections.DeckVersionScreenshotCollection(),
135
+ );
138
136
 
139
137
  const assetRoot = getAssetRoot(deckVersionModel.index_asset.url());
140
138
  let html;
@@ -210,6 +208,38 @@ PresentationDeck.createFromDeckVersion = function (
210
208
  }),
211
209
  );
212
210
 
211
+ options.selectionsMap = new Map(options.selections.map((s) => [s.url, s]));
212
+
213
+ if (options.appointmentTags) {
214
+ options.appointmentTagsMap = new Map(
215
+ options.appointmentTags.map((t) => [t.content_url, t]),
216
+ );
217
+ }
218
+
219
+ if (options.rootAssetPath) {
220
+ options.baseRoot = getAssetRoot(deckVersionModel.index_asset.url());
221
+ }
222
+
223
+ options.adjunctSlidesBySection = new Map();
224
+ for (const slide of options.adjunctSlides.models) {
225
+ if (slide.section) {
226
+ const key = slide.section.id;
227
+ if (!options.adjunctSlidesBySection.has(key)) {
228
+ options.adjunctSlidesBySection.set(key, []);
229
+ }
230
+ options.adjunctSlidesBySection.get(key).push(slide);
231
+ }
232
+ }
233
+
234
+ options.adjunctSubSlidesBySlide = new Map();
235
+ for (const subslide of options.adjunctSubSlides.models) {
236
+ const key = subslide.slide.id;
237
+ if (!options.adjunctSubSlidesBySlide.has(key)) {
238
+ options.adjunctSubSlidesBySlide.set(key, []);
239
+ }
240
+ options.adjunctSubSlidesBySlide.get(key).push(subslide);
241
+ }
242
+
213
243
  // We want all adjuncts to have fake ids that can't possibly overlap with the ids of
214
244
  // normal sections, slides and subslides, so we make a base ID that is larger than
215
245
  // all existing IDs then use the getUniqueAdjunctID function to retrieve an incremented ID
@@ -239,11 +269,11 @@ PresentationDeck.createFromDeckVersion = function (
239
269
  );
240
270
 
241
271
  section.addSlides(sectionModel.slide_set, options);
272
+
242
273
  deck.sections.add(section);
243
274
 
244
- const adjunctSlides = options.adjunctSlides.filter((slide) => {
245
- return slide.section && slide.section.id === section.id;
246
- });
275
+ const adjunctSlides =
276
+ options.adjunctSlidesBySection.get(section.id) ?? [];
247
277
 
248
278
  section.addSlides(adjunctSlides, options);
249
279
  });
@@ -315,10 +345,18 @@ PresentationDeck.createFromDeckVersion = function (
315
345
  // slides with the sequence > 110 then I know that all slides with a sequence > 110
316
346
  // are valid. I then remove those slides from the slides array and move down to the
317
347
  // next section.
348
+ slides.sort((a, b) => b.sequence - a.sequence);
349
+
350
+ let slideIdx = 0;
318
351
  deck.sections.models.reverse().forEach((section) => {
319
- const sectionSlides = slides.filter(
320
- (slide) => slide.sequence > section.sequence,
321
- );
352
+ const sectionSlides = [];
353
+ while (
354
+ slideIdx < slides.length &&
355
+ slides[slideIdx].sequence > section.sequence
356
+ ) {
357
+ sectionSlides.push(slides[slideIdx]);
358
+ slideIdx++;
359
+ }
322
360
 
323
361
  section.slides.add(sectionSlides);
324
362
 
@@ -331,8 +369,9 @@ PresentationDeck.createFromDeckVersion = function (
331
369
  section.slides.forEach((slide) => {
332
370
  slide.section = section.id;
333
371
  });
334
-
335
- slides = slides.filter((slide) => slide.sequence <= section.sequence);
372
+ sectionSlides.forEach((slide) => {
373
+ slide._values.section = section.id;
374
+ });
336
375
  });
337
376
 
338
377
  // Average the adjunct slide limit used across the entire deck over each section
@@ -509,7 +548,7 @@ PresentationDeck.createFromManifestJSON = function (manifestJSON, project) {
509
548
  };
510
549
  });
511
550
 
512
- const minID = _.max(_.map(deck.sections.toJSON(), "id"));
551
+ const minID = Math.max(...deck.sections.map((s) => s.id));
513
552
 
514
553
  deck.sections.add(
515
554
  templates.map((template, index) => {
@@ -124,14 +124,10 @@ export const PresentationSection = BasePresentationModel.extend(
124
124
  },
125
125
 
126
126
  addSlides(slides, options = {}) {
127
- _.defaults(options, {
128
- rootAssetPath: null,
129
- templates: null,
130
- choicelist: null,
131
- getUniqueAdjunctID: () => {
132
- return parseInt(_.uniqueId(), 10);
133
- },
134
- });
127
+ options.rootAssetPath ??= null;
128
+ options.templates ??= null;
129
+ options.choicelist ??= null;
130
+ options.getUniqueAdjunctID ??= () => parseInt(_.uniqueId(), 10);
135
131
 
136
132
  if (this.createdByTemplate) {
137
133
  throw new Error("Can not add slides to a template");
@@ -181,15 +177,11 @@ export const PresentationSection = BasePresentationModel.extend(
181
177
  * @returns {presentation.PresentationSection}
182
178
  */
183
179
  PresentationSection.createFromSection = function (sectionModel, options = {}) {
184
- _.defaults(options, {
185
- rootAssetPath: null,
186
- selections: null,
187
- choicelist: null,
188
- screenshots: new collections.DeckVersionScreenshotCollection(),
189
- });
190
-
180
+ options.rootAssetPath ??= null;
181
+ options.selections ??= null;
182
+ options.choicelist ??= null;
191
183
  options.screenshots = PresentationSection.screenshotsToMap(
192
- options.screenshots,
184
+ options.screenshots ?? new collections.DeckVersionScreenshotCollection(),
193
185
  );
194
186
 
195
187
  let html;
@@ -198,7 +190,9 @@ PresentationSection.createFromSection = function (sectionModel, options = {}) {
198
190
  const assetRoot = getAssetRoot(sectionModel.index_asset.url());
199
191
 
200
192
  if (options.rootAssetPath) {
201
- const baseRoot = getAssetRoot(sectionModel.deckversion.index_asset.url());
193
+ const baseRoot =
194
+ options.baseRoot ??
195
+ getAssetRoot(sectionModel.deckversion.index_asset.url());
202
196
  const sectionPath = assetRoot.slice(baseRoot.length);
203
197
 
204
198
  html = `${options.rootAssetPath}${sectionPath}index.html`;
@@ -261,18 +255,12 @@ PresentationSection.createFromAdjunctSection = function (
261
255
  deckVersionModel,
262
256
  options = {},
263
257
  ) {
264
- _.defaults(options, {
265
- rootAssetPath: null,
266
- selections: null,
267
- choicelist: null,
268
- getUniqueAdjunctID: () => {
269
- return parseInt(_.uniqueId(), 10);
270
- },
271
- screenshots: new collections.DeckVersionScreenshotCollection(),
272
- });
273
-
258
+ options.rootAssetPath ??= null;
259
+ options.selections ??= null;
260
+ options.choicelist ??= null;
261
+ options.getUniqueAdjunctID ??= () => parseInt(_.uniqueId(), 10);
274
262
  options.screenshots = PresentationSection.screenshotsToMap(
275
- options.screenshots,
263
+ options.screenshots ?? new collections.DeckVersionScreenshotCollection(),
276
264
  );
277
265
 
278
266
  const keyID =
@@ -366,15 +354,11 @@ PresentationSection.createFromImpostorSection = function (
366
354
  slideModel,
367
355
  options = {},
368
356
  ) {
369
- _.defaults(options, {
370
- rootAssetPath: null,
371
- selections: null,
372
- choicelist: null,
373
- screenshots: new collections.DeckVersionScreenshotCollection(),
374
- });
375
-
357
+ options.rootAssetPath ??= null;
358
+ options.selections ??= null;
359
+ options.choicelist ??= null;
376
360
  options.screenshots = PresentationSection.screenshotsToMap(
377
- options.screenshots,
361
+ options.screenshots ?? new collections.DeckVersionScreenshotCollection(),
378
362
  );
379
363
 
380
364
  let html;
@@ -383,9 +367,9 @@ PresentationSection.createFromImpostorSection = function (
383
367
  const assetRoot = getAssetRoot(slideModel.index_asset.url());
384
368
 
385
369
  if (options.rootAssetPath) {
386
- const baseRoot = getAssetRoot(
387
- slideModel.section.deckversion.index_asset.url(),
388
- );
370
+ const baseRoot =
371
+ options.baseRoot ??
372
+ getAssetRoot(slideModel.section.deckversion.index_asset.url());
389
373
  const sectionPath = assetRoot.slice(baseRoot.length);
390
374
 
391
375
  html = `${options.rootAssetPath}${sectionPath}index.html`;
@@ -522,18 +506,15 @@ PresentationSection.createFromAutoAdjunct = function (model, opts = {}) {
522
506
  }
523
507
  }
524
508
 
525
- const options = _.defaults(opts, {
526
- allowConvert: true,
527
- visible: true,
528
- index: -1,
529
- deckversionID: -1,
530
- sequence: opts.index,
531
- impostor: false,
532
- screenshots: new collections.DeckVersionScreenshotCollection(),
533
- });
534
-
509
+ const options = opts;
510
+ options.allowConvert ??= true;
511
+ options.visible ??= true;
512
+ options.index ??= -1;
513
+ options.deckversionID ??= -1;
514
+ options.sequence ??= opts.index;
515
+ options.impostor ??= false;
535
516
  options.screenshots = PresentationSection.screenshotsToMap(
536
- options.screenshots,
517
+ options.screenshots ?? new collections.DeckVersionScreenshotCollection(),
537
518
  );
538
519
 
539
520
  const tags = PresentationSection.getTags(
@@ -133,18 +133,14 @@ export const PresentationSlide = BasePresentationModel.extend(
133
133
  * @returns {presentation.PresentationSlide}
134
134
  */
135
135
  PresentationSlide.createFromSlide = function (slideModel, options = {}) {
136
- _.defaults(options, {
137
- adjunctSubSlides: new collections.AdjunctSubSlideCollection(),
138
- screenshots: new collections.DeckVersionScreenshotCollection(),
139
- rootAssetPath: null,
140
- selections: null,
141
- choicelist: null,
142
- getUniqueAdjunctID: () => {
143
- return parseInt(_.uniqueId(), 10);
144
- },
145
- });
146
-
147
- options.screenshots = PresentationSlide.screenshotsToMap(options.screenshots);
136
+ options.adjunctSubSlides ??= new collections.AdjunctSubSlideCollection();
137
+ options.rootAssetPath ??= null;
138
+ options.selections ??= null;
139
+ options.choicelist ??= null;
140
+ options.getUniqueAdjunctID ??= () => parseInt(_.uniqueId(), 10);
141
+ options.screenshots = PresentationSlide.screenshotsToMap(
142
+ options.screenshots ?? new collections.DeckVersionScreenshotCollection(),
143
+ );
148
144
 
149
145
  let html;
150
146
  let css;
@@ -152,9 +148,9 @@ PresentationSlide.createFromSlide = function (slideModel, options = {}) {
152
148
  const assetRoot = getAssetRoot(slideModel.index_asset.url());
153
149
 
154
150
  if (options.rootAssetPath) {
155
- const baseRoot = getAssetRoot(
156
- slideModel.section.deckversion.index_asset.url(),
157
- );
151
+ const baseRoot =
152
+ options.baseRoot ??
153
+ getAssetRoot(slideModel.section.deckversion.index_asset.url());
158
154
  const slidePath = assetRoot.slice(baseRoot.length);
159
155
  html = `${options.rootAssetPath}${slidePath}index.html`;
160
156
  css = `${options.rootAssetPath}${slidePath}slide.css`;
@@ -202,9 +198,11 @@ PresentationSlide.createFromSlide = function (slideModel, options = {}) {
202
198
  }),
203
199
  );
204
200
 
205
- const adjunctSubslides = options.adjunctSubSlides.filter((model) => {
206
- return model.slide.id === slideModel.id;
207
- });
201
+ const adjunctSubslides = options.adjunctSubSlidesBySlide
202
+ ? (options.adjunctSubSlidesBySlide.get(slideModel.id) ?? [])
203
+ : options.adjunctSubSlides.filter(
204
+ (model) => model.slide.id === slideModel.id,
205
+ );
208
206
 
209
207
  // If the slide's content is entirely adjunct and does not have a distinct
210
208
  // first subslide, we need to create one based on the slide.
@@ -220,7 +218,7 @@ PresentationSlide.createFromSlide = function (slideModel, options = {}) {
220
218
 
221
219
  let maxID = 0;
222
220
  if (slide.subslides.length) {
223
- maxID = _.max(slide.subslides.pluck("id"));
221
+ maxID = Math.max(...slide.subslides.map((s) => s.id));
224
222
  }
225
223
 
226
224
  // Add any adjunct subslides to the list
@@ -251,18 +249,14 @@ PresentationSlide.createFromAdjunctSlide = function (
251
249
  section = null,
252
250
  options = {},
253
251
  ) {
254
- _.defaults(options, {
255
- id: null,
256
- rootAssetPath: null,
257
- selections: null,
258
- choicelist: null,
259
- getUniqueAdjunctID: () => {
260
- return parseInt(_.uniqueId(), 10);
261
- },
262
- screenshots: new collections.DeckVersionScreenshotCollection(),
263
- });
264
-
265
- options.screenshots = PresentationSlide.screenshotsToMap(options.screenshots);
252
+ options.id ??= null;
253
+ options.rootAssetPath ??= null;
254
+ options.selections ??= null;
255
+ options.choicelist ??= null;
256
+ options.getUniqueAdjunctID ??= () => parseInt(_.uniqueId(), 10);
257
+ options.screenshots = PresentationSlide.screenshotsToMap(
258
+ options.screenshots ?? new collections.DeckVersionScreenshotCollection(),
259
+ );
266
260
 
267
261
  const keyID =
268
262
  adjunctSlideModel.id ||
@@ -454,18 +448,17 @@ PresentationSlide.createFromAutoAdjunct = function (model, opts = {}) {
454
448
  }
455
449
  }
456
450
 
457
- const options = _.defaults(opts, {
458
- allowConvert: true,
459
- visible: true,
460
- index: -1,
461
- deckversionID: -1,
462
- sectionKey: "",
463
- sequence: opts.index,
464
- impostor: false,
465
- screenshots: new collections.DeckVersionScreenshotCollection(),
466
- });
467
-
468
- options.screenshots = PresentationSlide.screenshotsToMap(options.screenshots);
451
+ const options = opts;
452
+ options.allowConvert ??= true;
453
+ options.visible ??= true;
454
+ options.index ??= -1;
455
+ options.deckversionID ??= -1;
456
+ options.sectionKey ??= "";
457
+ options.sequence ??= opts.index;
458
+ options.impostor ??= false;
459
+ options.screenshots = PresentationSlide.screenshotsToMap(
460
+ options.screenshots ?? new collections.DeckVersionScreenshotCollection(),
461
+ );
469
462
 
470
463
  const tags = PresentationSlide.getTags(
471
464
  {
package/src/sync.js CHANGED
@@ -3,7 +3,6 @@ import SuperAgentRequest from "superagent-bluebird-promise";
3
3
  import _ from "lodash";
4
4
  import log from "./log.js";
5
5
  import { middlewares } from "./middleware.js";
6
- import superagent from "superagent";
7
6
 
8
7
  const defaults = _.defaults;
9
8
  const assign = _.assign;
@@ -227,10 +226,10 @@ export const ajaxSync = function (method, model, options) {
227
226
  return data;
228
227
  });
229
228
  })
230
- .catch(superagent.SuperagentPromiseError, (e) => {
229
+ .catch((e) => {
231
230
  if (
232
- e.res &&
233
- e.res.body &&
231
+ typeof e.status !== "undefined" &&
232
+ e.res?.body &&
234
233
  ((e.status >= 400 && e.status < 500) || e.status === 503)
235
234
  ) {
236
235
  e.message += `\nBody: ${JSON.stringify(e.res.body)}`;