@livepreso/api 6.53.0 → 6.54.0

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 (134) hide show
  1. package/.rush/temp/1aebf46f78ad5c45f82f8147751890adb37bef9d.log +10 -0
  2. package/.rush/temp/256021b5963b4c0221d3dec247b697b9691a9b2c.log +10 -0
  3. package/.rush/temp/2a322f00f12cf9d1e64afe81275cc78d01c49050.log +10 -0
  4. package/.rush/temp/30061f1865447dcbb3f20a305061205f3dbe6091.log +10 -0
  5. package/.rush/temp/3cdc82c352e8ed90607952873f3aa4c200490874.log +10 -0
  6. package/.rush/temp/45522aea0dee8cb2be1a53248ba45bd235743b43.log +10 -0
  7. package/.rush/temp/5489ab737e406518983c16c57fc3e1edc07c0341.log +10 -0
  8. package/.rush/temp/58fcbb7f15a76326d40e0839ab179755da82a891.log +10 -0
  9. package/.rush/temp/5bc0bba70b733baa4dd976667ba0a1386e516186.log +10 -0
  10. package/.rush/temp/64f1bb696f8d7d7e72907b80df316b127f72e23e.log +10 -0
  11. package/.rush/temp/6f640f951414ea68adb65c17e4ed7527cde54faf.log +10 -0
  12. package/.rush/temp/7c7b958682d4ab5697530be47d0aac62efe1adf1.log +10 -0
  13. package/.rush/temp/82bfb987463fbcfebf04022e6ed00015c73879c8.log +10 -0
  14. package/.rush/temp/844034aa6e542115075e8f3dc5ffc640973e0064.log +10 -0
  15. package/.rush/temp/8b42957a7c15da1f29cb57bee125f13affa70dca.log +10 -0
  16. package/.rush/temp/924652444ab5a6063f328a2217123a2227058896.log +10 -0
  17. package/.rush/temp/9f2030f96d62f3e38052e35201819a216566f14f.log +10 -0
  18. package/.rush/temp/a769db9d81a23000c0e9b1bf4f1a9a9e721d0d7c.log +10 -0
  19. package/.rush/temp/a87d3a8b4ece87ec66f27c86226a9f205617681f.log +10 -0
  20. package/.rush/temp/bb7a5bdcc4af4ad1507f81f33774b31f5b4e4fb7.log +10 -0
  21. package/.rush/temp/build-cache-tar.log +7 -0
  22. package/.rush/temp/c20e29ccaaa9231b38a28bb24451b4ce7562cdc0.log +10 -0
  23. package/.rush/temp/chunked-rush-logs/api.build.chunks.jsonl +6 -0
  24. package/.rush/temp/chunked-rush-logs/api.test.chunks.jsonl +21 -0
  25. package/.rush/temp/e21303db8f59b4625fd184c9114377d781fd24f8.log +10 -0
  26. package/.rush/temp/e6d303862765b6a5f41dd483d0f9ae083a1fae10.log +10 -0
  27. package/.rush/temp/eaf69fbc059d2f1258d7569136180d4a1d3c7072.log +10 -0
  28. package/.rush/temp/f85d279e2674966daaec83e1c3986a96f86ef304.log +10 -0
  29. package/.rush/temp/fc0a332c5b34c6b90006850cf2d93a48fb4b9a6e.log +10 -0
  30. package/.rush/temp/operation/build/all.log +6 -0
  31. package/.rush/temp/operation/build/log-chunks.jsonl +6 -0
  32. package/.rush/temp/operation/build/state.json +3 -0
  33. package/.rush/temp/operation/test/all.log +21 -0
  34. package/.rush/temp/operation/test/log-chunks.jsonl +21 -0
  35. package/.rush/temp/operation/test/state.json +3 -0
  36. package/.rush/temp/package-deps_build.json +185 -0
  37. package/.rush/temp/shrinkwrap-deps.json +71 -13
  38. package/CHANGELOG.json +35 -0
  39. package/CHANGELOG.md +21 -1
  40. package/api.build.log +9 -0
  41. package/api.test.cache.log +1 -0
  42. package/api.test.log +19 -0
  43. package/cjs/api.js +1 -1
  44. package/cjs/api.js.map +1 -1
  45. package/cjs/collections/auto-adjuncts.js +0 -22
  46. package/cjs/collections/auto-adjuncts.js.map +1 -1
  47. package/cjs/collections/base.js +15 -1
  48. package/cjs/collections/base.js.map +1 -1
  49. package/cjs/collections/base.spec.js +61 -0
  50. package/cjs/collections/base.spec.js.map +1 -1
  51. package/cjs/collections/cms-vals.js +25 -0
  52. package/cjs/collections/cms-vals.js.map +1 -1
  53. package/cjs/collections/cms-vals.spec.js +73 -0
  54. package/cjs/collections/cms-vals.spec.js.map +1 -0
  55. package/cjs/collections/deck-version-screenshots.js +0 -23
  56. package/cjs/collections/deck-version-screenshots.js.map +1 -1
  57. package/cjs/collections/scenarios.js +20 -0
  58. package/cjs/collections/scenarios.js.map +1 -0
  59. package/cjs/collections.js +11 -0
  60. package/cjs/collections.js.map +1 -1
  61. package/cjs/fixtures.js +18 -1
  62. package/cjs/fixtures.js.map +1 -1
  63. package/cjs/models/appointment.js +29 -8
  64. package/cjs/models/appointment.js.map +1 -1
  65. package/cjs/models/auto-adjunct.js +3 -2
  66. package/cjs/models/auto-adjunct.js.map +1 -1
  67. package/cjs/models/base.js +57 -13
  68. package/cjs/models/base.js.map +1 -1
  69. package/cjs/models/base.spec.js +28 -0
  70. package/cjs/models/base.spec.js.map +1 -1
  71. package/cjs/models/cms-val.js +3 -3
  72. package/cjs/models/cms-val.js.map +1 -1
  73. package/cjs/models/deck-version-screenshot.js +2 -2
  74. package/cjs/models/deck-version-screenshot.js.map +1 -1
  75. package/cjs/models/deck-version.js +17 -8
  76. package/cjs/models/deck-version.js.map +1 -1
  77. package/cjs/models/preset.js +8 -6
  78. package/cjs/models/preset.js.map +1 -1
  79. package/cjs/models/scenario.js +41 -0
  80. package/cjs/models/scenario.js.map +1 -0
  81. package/cjs/models.js +11 -0
  82. package/cjs/models.js.map +1 -1
  83. package/cjs/presentation/appointment-presentation.js +2 -2
  84. package/cjs/presentation/appointment-presentation.js.map +1 -1
  85. package/cjs/presentation/base-presentation-model.js +26 -23
  86. package/cjs/presentation/base-presentation-model.js.map +1 -1
  87. package/cjs/presentation/base-presentation-model.spec.js +21 -21
  88. package/cjs/presentation/base-presentation-model.spec.js.map +1 -1
  89. package/cjs/presentation/presentation-section.js +29 -4
  90. package/cjs/presentation/presentation-section.js.map +1 -1
  91. package/cjs/presentation/presentation-section.spec.js +16 -3
  92. package/cjs/presentation/presentation-section.spec.js.map +1 -1
  93. package/cjs/presentation/presentation-slide.js +27 -3
  94. package/cjs/presentation/presentation-slide.js.map +1 -1
  95. package/cjs/presentation/presentation-slide.spec.js +8 -1
  96. package/cjs/presentation/presentation-slide.spec.js.map +1 -1
  97. package/cjs/utils.js +12 -3
  98. package/cjs/utils.js.map +1 -1
  99. package/cjs/utils.spec.js +22 -0
  100. package/cjs/utils.spec.js.map +1 -1
  101. package/package.json +3 -3
  102. package/rush-logs/api.build.cache.log +1 -0
  103. package/rush-logs/api.build.log +6 -0
  104. package/rush-logs/api.test.cache.log +1 -0
  105. package/rush-logs/api.test.log +21 -0
  106. package/src/api.js +1 -1
  107. package/src/collections/auto-adjuncts.js +0 -22
  108. package/src/collections/base.js +13 -2
  109. package/src/collections/base.spec.js +37 -0
  110. package/src/collections/cms-vals.js +28 -0
  111. package/src/collections/cms-vals.spec.js +66 -0
  112. package/src/collections/deck-version-screenshots.js +0 -22
  113. package/src/collections/scenarios.js +18 -0
  114. package/src/collections.js +1 -0
  115. package/src/fixtures.js +17 -1
  116. package/src/models/appointment.js +32 -6
  117. package/src/models/auto-adjunct.js +3 -2
  118. package/src/models/base.js +41 -13
  119. package/src/models/base.spec.js +18 -0
  120. package/src/models/cms-val.js +3 -3
  121. package/src/models/deck-version-screenshot.js +2 -2
  122. package/src/models/deck-version.js +10 -7
  123. package/src/models/preset.js +8 -6
  124. package/src/models/scenario.js +39 -0
  125. package/src/models.js +1 -0
  126. package/src/presentation/appointment-presentation.js +6 -4
  127. package/src/presentation/base-presentation-model.js +29 -23
  128. package/src/presentation/base-presentation-model.spec.js +22 -22
  129. package/src/presentation/presentation-section.js +27 -2
  130. package/src/presentation/presentation-section.spec.js +14 -1
  131. package/src/presentation/presentation-slide.js +26 -2
  132. package/src/presentation/presentation-slide.spec.js +7 -0
  133. package/src/utils.js +13 -3
  134. package/src/utils.spec.js +27 -0
@@ -320,8 +320,19 @@ export const BaseCollection = Collection.extend(
320
320
  return true;
321
321
  },
322
322
 
323
- serialize() {
324
- const collection = Collection.prototype.serialize.call(this);
323
+ serialize(...args) {
324
+ // Don't use the base collection serialize so we can pass in
325
+ // arguments
326
+ const collection = this.map((model) => {
327
+ if (model.serialize) {
328
+ return model.serialize(...args);
329
+ } else {
330
+ const out = {};
331
+ _.assign(out, model);
332
+ delete out.collection;
333
+ return out;
334
+ }
335
+ });
325
336
 
326
337
  if (_.isObject(this._data) && this._data.url && !collection.length) {
327
338
  return this._data.url;
@@ -225,4 +225,41 @@ describe("fetchAll", () => {
225
225
  expect(baseCollection.first().id).toEqual(11);
226
226
  expect(baseCollection.last().id).toEqual(30);
227
227
  });
228
+
229
+ it("should serialize collection models with urls", async () => {
230
+ G(BaseCollection.extend({ model: "TestModel" }), "TestCollection");
231
+ G(
232
+ BaseModel.extend({
233
+ modelName: "bar",
234
+ children: { test: "TestModel" },
235
+ collections: { tests: "TestCollection" },
236
+ }),
237
+ "TestModel",
238
+ );
239
+
240
+ const Collection = G(BaseCollection.extend({ model: "TestModel" }));
241
+ const baseCollection = new Collection([
242
+ {
243
+ id: 1,
244
+ url: "/api/bar/1/",
245
+ test: { id: 1, url: "/api/baz/1/" },
246
+ tests: [{ id: 2, test: { id: 4 } }],
247
+ },
248
+ {
249
+ id: 2,
250
+ url: "/api/bar/2/",
251
+ test: { id: 2, url: "/api/baz/2/" },
252
+ tests: [],
253
+ },
254
+ ]);
255
+ expect(baseCollection.serialize({ urlsOnly: true })).toEqual([
256
+ {
257
+ id: 1,
258
+ test: "/api/bar/1/",
259
+ url: "/api/bar/1/",
260
+ tests: ["/api/bar/2/"],
261
+ },
262
+ { id: 2, test: "/api/bar/2/", url: "/api/bar/2/", tests: [] },
263
+ ]);
264
+ });
228
265
  });
@@ -1,3 +1,4 @@
1
+ import _ from "lodash";
1
2
  import "../models/cms-val.js";
2
3
 
3
4
  import Auth from "../auth.js";
@@ -43,4 +44,31 @@ export const CMSValCollection = BaseCollection.extend(
43
44
 
44
45
  CMSValCollection.canBeEmpty = true;
45
46
 
47
+ CMSValCollection.getPrioritized = (cmsVals, tenancy = Auth.user.tenancy) => {
48
+ const cmsValsGroupedBySlides = _.groupBy(cmsVals, "key");
49
+
50
+ return _.map(cmsValsGroupedBySlides, (group) => {
51
+ const scenarioCmsVal = group.find((cmsValue) => !!cmsValue.scenario);
52
+
53
+ // The first cms val owned by the tenancy you're in
54
+ const tenancyStandardDeckCmsVal = group.find(
55
+ (cmsValue) =>
56
+ !cmsValue.scenario && cmsValue._tenancy?.owner_id === tenancy.id,
57
+ );
58
+
59
+ // The first cms val owned by the parent tenancy.
60
+ const parentTenancyStandardDeckCmsVal = group.find(
61
+ (cmsValue) =>
62
+ !cmsValue.scenario && cmsValue._tenancy?.owner_id !== tenancy.id,
63
+ );
64
+
65
+ // Order of preference: Scenario > Tenancy > Parent Tenancy
66
+ return (
67
+ scenarioCmsVal ||
68
+ tenancyStandardDeckCmsVal ||
69
+ parentTenancyStandardDeckCmsVal
70
+ );
71
+ });
72
+ };
73
+
46
74
  register("CMSValCollection", CMSValCollection);
@@ -0,0 +1,66 @@
1
+ import { CMSValCollection } from "./cms-vals.js";
2
+
3
+ const childTenancy = { id: "66d7572f-85f6-4552-879a-25cf05ae311f" };
4
+ const parentTenancy = { id: "cf5ad5a5-d149-42b4-b09b-e52b7afdf507" };
5
+ const testScenarioURL =
6
+ "http://my/api/scenario/362bddc7-1821-4f43-921c-244e5c3175f7/";
7
+
8
+ describe("#.getPrioritized", () => {
9
+ const scenarioCmsVal = {
10
+ id: 1,
11
+ key: "foo",
12
+ value: "Scenario",
13
+ scenario: testScenarioURL,
14
+ _tenancy: { owner_id: childTenancy.id },
15
+ };
16
+
17
+ const tenancyCmsVal = {
18
+ id: 2,
19
+ key: "foo",
20
+ value: "Tenancy",
21
+ scenario: testScenarioURL,
22
+ _tenancy: { owner_id: childTenancy.id },
23
+ };
24
+
25
+ const parentTenancyCmsVal = {
26
+ id: 3,
27
+ key: "foo",
28
+ value: "Parent Tenancy",
29
+ scenario: testScenarioURL,
30
+ _tenancy: { owner_id: parentTenancy.id },
31
+ };
32
+
33
+ const testFn = (cmsvals, tenancy) =>
34
+ CMSValCollection.getPrioritized(cmsvals, tenancy).filter(
35
+ (c) => c.key === "foo",
36
+ );
37
+
38
+ it("prefer scenario cmsval over others", () => {
39
+ const cmsvals = [scenarioCmsVal, tenancyCmsVal, parentTenancyCmsVal];
40
+ const results = testFn(cmsvals, childTenancy);
41
+ expect(results).toHaveLength(1);
42
+ expect(results[0].value).toEqual("Scenario");
43
+ });
44
+
45
+ it("prefer tenancy cmsval over others", () => {
46
+ const cmsvals = [
47
+ { ...scenarioCmsVal, key: "bar" },
48
+ tenancyCmsVal,
49
+ parentTenancyCmsVal,
50
+ ];
51
+ const results = testFn(cmsvals, childTenancy);
52
+ expect(results).toHaveLength(1);
53
+ expect(results[0].value).toEqual("Tenancy");
54
+ });
55
+
56
+ it("prefer global tenancy cmsval over others", () => {
57
+ const cmsvals = [
58
+ { ...scenarioCmsVal, key: "bar" },
59
+ { ...tenancyCmsVal, key: "baz" },
60
+ parentTenancyCmsVal,
61
+ ];
62
+ const results = testFn(cmsvals, childTenancy);
63
+ expect(results).toHaveLength(1);
64
+ expect(results[0].value).toEqual("Parent Tenancy");
65
+ });
66
+ });
@@ -1,6 +1,5 @@
1
1
  import "../models/deck-version-screenshot.js";
2
2
 
3
- import Auth from "../auth.js";
4
3
  import { BaseCollection } from "./base.js";
5
4
  import { register } from "../state-register.js";
6
5
 
@@ -14,27 +13,6 @@ export const DeckVersionScreenshotCollection = BaseCollection.extend(
14
13
  /** @lends collections.DeckVersionScreenshotCollection# */ {
15
14
  model: "DeckVersionScreenshotModel",
16
15
 
17
- fetch(opts = {}) {
18
- const { user } = Auth;
19
-
20
- if (!opts.data) {
21
- opts.data = {};
22
- }
23
-
24
- // Let's only add this if it's not already being set, in case a global user
25
- // DOES want to see a specific team.
26
- if (user && !opts.data.team) {
27
- //
28
- // Filter all global autoadjuncts, and only query teams that
29
- // the authorized user is a part of. This is mostly for the case where
30
- // a 'global' temp slide admin could end up seeing autoadjuncts for
31
- // many teams - which would be increadibly confusing.
32
- opts.data.team = [null].concat(user.team_set.map((team) => team.id));
33
- }
34
-
35
- return BaseCollection.prototype.fetch.call(this, opts);
36
- },
37
-
38
16
  url() {
39
17
  if (!this._url && this.parent) {
40
18
  this._options.deckversion = this.parent;
@@ -0,0 +1,18 @@
1
+ import "../models/scenario.js";
2
+
3
+ import { BaseCollection } from "./base.js";
4
+ import { register } from "../state-register.js";
5
+
6
+ /**
7
+ * @constructor
8
+ * @alias collections.ScenarioCollection
9
+ * @extends collections.BaseCollection
10
+ * @see models.ScenarioModel
11
+ */
12
+ export const ScenarioCollection = BaseCollection.extend(
13
+ /** @lends collections.ScenarioCollection# */ {
14
+ model: "ScenarioModel",
15
+ },
16
+ );
17
+
18
+ register("ScenarioCollection", ScenarioCollection);
@@ -26,6 +26,7 @@ export * from "./collections/opportunities";
26
26
  export * from "./collections/pack-diffs";
27
27
  export * from "./collections/packs";
28
28
  export * from "./collections/presets";
29
+ export * from "./collections/scenarios";
29
30
  export * from "./collections/section-selections";
30
31
  export * from "./collections/sections";
31
32
  export * from "./collections/signing-backends";
package/src/fixtures.js CHANGED
@@ -22,8 +22,24 @@ const presentationCollections = {
22
22
  PresentationSubSlides: presentation.PresentationSubSlides,
23
23
  };
24
24
 
25
+ function uuid() {
26
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
27
+ const r = (Math.random() * 16) | 0;
28
+ const v = c === "x" ? r : (r & 0x3) | 0x8;
29
+ return v.toString(16);
30
+ });
31
+ }
32
+
25
33
  function makeFactory(name, Model, ignoreFields = []) {
26
- const factory = Factory.define(name, Model).sequence("id");
34
+ const factory = Factory.define(name, Model);
35
+ const { detailType } = Model.prototype;
36
+ if (detailType === "string" || detailType === "number") {
37
+ factory.sequence("id");
38
+ } else if (detailType === "uuid") {
39
+ factory.attr("id", () => uuid());
40
+ } else {
41
+ throw new Error("Unknown detailType " + detailType);
42
+ }
27
43
 
28
44
  const { _definition: definition, _children: children } = Model.prototype;
29
45
 
@@ -3,6 +3,7 @@ import "./snapshot.js";
3
3
  import "./feed-data.js";
4
4
  import "./preset.js";
5
5
  import "./team.js";
6
+ import "./scenario.js";
6
7
  import "./hosted-preso.js";
7
8
  import "./appointment-stats.js";
8
9
  import "./appointment-tags.js";
@@ -122,6 +123,8 @@ export const AppointmentModel = BaseModel.extend(
122
123
  * @property {models.SnapshotModel} latest_snapshot
123
124
  * @property {models.UserModel} user
124
125
  * @property {models.AppointmentStatsModel} appointmentStats
126
+ * @property {models.ScenarioModel} scenario
127
+ * @property {models.TeamModel} team_branding
125
128
  */
126
129
  children: {
127
130
  preset: "PresetModel",
@@ -130,7 +133,8 @@ export const AppointmentModel = BaseModel.extend(
130
133
  user: "UserModel",
131
134
  latest_tele: "HostedPresoModel",
132
135
  stats: "AppointmentStatsModel",
133
- team: "TeamModel",
136
+ scenario: "ScenarioModel",
137
+ team_branding: "TeamModel",
134
138
  },
135
139
 
136
140
  /**
@@ -273,6 +277,14 @@ export const AppointmentModel = BaseModel.extend(
273
277
  this.adjunctSubSlides?.fetch(fetchOptions),
274
278
  this.contact_set?.fetchSet(fetchOptions),
275
279
  this.tags?.fetch(fetchOptions),
280
+ this.team_branding?.fetch(fetchOptions),
281
+ this.scenario?.fetch(fetchOptions)?.catch((e) => {
282
+ if (e.status === 404) {
283
+ this.scenario = null;
284
+ return;
285
+ }
286
+ throw e;
287
+ }),
276
288
  this.user?.fetch(fetchOptions)?.catch((e) => {
277
289
  if (e.status && e.status === 404) {
278
290
  // It's possible for a user to be deactivated, which means they'll
@@ -318,16 +330,29 @@ export const AppointmentModel = BaseModel.extend(
318
330
  return Promise.all(fetches);
319
331
  })
320
332
  .then(() => {
321
- return Promise.all(
322
- this.deckversion_set.map((model) => {
333
+ const scenarioID = this.scenario?.id ?? null;
334
+ const scenarioFilter = [null];
335
+ if (scenarioID) {
336
+ scenarioFilter.push(scenarioID);
337
+ }
338
+
339
+ return Promise.all([
340
+ this.scenario?.owner_team?.fetch?.(fetchOptions),
341
+ ...this.deckversion_set.map((model) => {
323
342
  return Promise.all([
324
- model.screenshots.fetch(fetchOptions),
343
+ model.screenshots.fetch(
344
+ _.merge(fetchOptions, {
345
+ data: {
346
+ scenario: scenarioFilter,
347
+ },
348
+ }),
349
+ ),
325
350
  model.template_set.fetchSet(fetchOptions),
326
351
  model.manifest_json.fetch(fetchOptions),
327
352
  model.deck.fetch(fetchOptions),
328
353
  ]);
329
354
  }),
330
- );
355
+ ]);
331
356
  })
332
357
  .then(() => {
333
358
  const deckversionTemplates =
@@ -385,7 +410,8 @@ export const AppointmentModel = BaseModel.extend(
385
410
  no_edit_after: appointment.no_edit_after,
386
411
  no_share_after: appointment.no_share_after,
387
412
  no_delete_after: appointment.no_delete_after,
388
- team: this._retrieveURL(appointment.team),
413
+ scenario: this._retrieveURL(appointment.scenario),
414
+ team_branding: this._retrieveURL(appointment.team_branding),
389
415
  editors_can_change_editors: appointment.editors_can_change_editors,
390
416
  share_visibility_mode: appointment.share_visibility_mode,
391
417
  };
@@ -1,5 +1,5 @@
1
1
  import "./template.js";
2
- import "./team.js";
2
+ import "./scenario.js";
3
3
  import "./deck.js";
4
4
 
5
5
  import { BaseModel } from "./base.js";
@@ -49,11 +49,12 @@ export const AutoAdjunctModel = BaseModel.extend(
49
49
  /**
50
50
  * @property {models.DeckModel} deck
51
51
  * @property {models.TemplateModel} template
52
+ * @property {models.ScenarioModel} scenario
52
53
  */
53
54
  children: {
54
55
  deck: "DeckModel",
55
56
  template: "TemplateModel",
56
- team: "TeamModel",
57
+ scenario: "ScenarioModel",
57
58
  },
58
59
  },
59
60
  );
@@ -242,7 +242,7 @@ export const BaseModel = Model.extend(
242
242
  getIDFromURL(url, resource = "") {
243
243
  const resourceURL = resource || this.getResourceURL();
244
244
 
245
- if (!url || !resourceURL) {
245
+ if (typeof url !== "string" || !resourceURL) {
246
246
  return null;
247
247
  }
248
248
 
@@ -259,8 +259,9 @@ export const BaseModel = Model.extend(
259
259
  }
260
260
 
261
261
  const idStr = urlEnd.split(resourceEnd).join("");
262
-
263
- if ((idStr.match(/\//g) || []).length === 1) {
262
+ if (this.detailType === "uuid") {
263
+ return idStr.slice(0, -1);
264
+ } else if ((idStr.match(/\//g) || []).length === 1) {
264
265
  return parseInt(idStr.slice(0, -1), 10);
265
266
  }
266
267
 
@@ -693,6 +694,10 @@ export const BaseModel = Model.extend(
693
694
  return {};
694
695
  }
695
696
 
697
+ // Urls only will build a model without its children/collections expanded -
698
+ // it will return urls instead of the full model.
699
+ const { urlsOnly = false } = opts ?? {};
700
+
696
701
  const data = Model.prototype.serialize.apply(this, arguments);
697
702
  data.url = this.url();
698
703
 
@@ -706,24 +711,47 @@ export const BaseModel = Model.extend(
706
711
  return object;
707
712
  }, {});
708
713
 
709
- Object.keys(this._unsetCollections).forEach((key) => {
710
- if (this._unsetCollections[key].canBeEmpty && !this._values[key]) {
714
+ const allCollectionKeys = [
715
+ ...Object.keys(this._unsetCollections),
716
+ ...Object.keys(this._collections),
717
+ ];
718
+
719
+ for (const key of allCollectionKeys) {
720
+ const constructor = this._unsetCollections[key];
721
+
722
+ if (urlsOnly && this[key]) {
723
+ if (typeof this._values[key] === "string") {
724
+ derived[key] = this._values[key];
725
+ } else {
726
+ derived[key] = this[key].map((m) => m.url());
727
+ }
728
+ } else if (!constructor) {
729
+ continue;
730
+ } else if (constructor.canBeEmpty && !this._values[key]) {
711
731
  derived[key] = [];
712
732
  }
713
- });
733
+ }
714
734
 
715
- Object.keys(this._unsetChildren).forEach((key) => {
716
- if (
717
- this._unsetChildren[key].canBeEmpty &&
718
- !this._values[key] &&
719
- this[key]
720
- ) {
735
+ const allChildrenKeys = [
736
+ ...Object.keys(this._unsetChildren),
737
+ ...(urlsOnly ? Object.keys(this._children) : []),
738
+ ];
739
+
740
+ for (const key of allChildrenKeys) {
741
+ const constructor = this._unsetChildren[key];
742
+
743
+ if (urlsOnly && this[key]) {
744
+ derived[key] = this[key].url();
745
+ } else if (!constructor) {
746
+ continue;
747
+ } else if (constructor.canBeEmpty && !this._values[key] && this[key]) {
721
748
  derived[key] = this[key].url();
722
749
  }
723
- });
750
+ }
724
751
 
725
752
  return _.extend(data, derived);
726
753
  },
754
+
727
755
  // Safely retrieve the url from a child or collection that may or may not
728
756
  // be hydrated
729
757
  _retrieveURL(item) {
@@ -426,3 +426,21 @@ describe(".matchesURL", () => {
426
426
  expect(ActivityModel.matchesURL(url)).toEqual(true);
427
427
  });
428
428
  });
429
+
430
+ it("should allow serializing collections with urls only", () => {
431
+ G(BaseModel.extend({ modelName: "baz" }), "TestModel");
432
+ G(BaseCollection.extend({ model: "TestModel" }), "TestCollection");
433
+ const Model = G(
434
+ BaseModel.extend({ collections: { tests: "TestCollection" } }),
435
+ );
436
+ const model = new Model({
437
+ tests: [
438
+ { id: 1, url: "/api/baz/1/" },
439
+ { id: 2, url: "/api/baz/2/" },
440
+ ],
441
+ });
442
+ expect(model.serialize({ urlsOnly: true })).toEqual({
443
+ url: null,
444
+ tests: ["/api/baz/1/", "/api/baz/2/"],
445
+ });
446
+ });
@@ -1,5 +1,5 @@
1
1
  import "./user.js";
2
- import "./team.js";
2
+ import "./scenario.js";
3
3
  import "./deck.js";
4
4
 
5
5
  import { BaseModel } from "../models/base.js";
@@ -28,12 +28,12 @@ export const CMSValModel = BaseModel.extend(
28
28
  /**
29
29
  * @property {models.UserModel} user
30
30
  * @property {models.DeckModel} deck
31
- * @property {models.TeamModel} team
31
+ * @property {models.ScenarioModel} scenario
32
32
  */
33
33
  children: {
34
34
  user: "UserModel",
35
35
  deck: "DeckModel",
36
- team: "TeamModel",
36
+ scenario: "ScenarioModel",
37
37
  },
38
38
 
39
39
  url() {
@@ -1,4 +1,4 @@
1
- import "./team.js";
1
+ import "./scenario.js";
2
2
 
3
3
  import { BaseModel } from "./base.js";
4
4
  import _ from "lodash";
@@ -35,7 +35,7 @@ export const DeckVersionScreenshotModel = BaseModel.extend(
35
35
  },
36
36
 
37
37
  children: {
38
- team: "TeamModel",
38
+ scenario: "ScenarioModel",
39
39
  },
40
40
 
41
41
  serialize() {
@@ -141,7 +141,7 @@ export const DeckVersionModel = BaseModel.extend(
141
141
  Object.keys(this.getSafeAttrs()).length === 1 ||
142
142
  !this.index_asset
143
143
  ) {
144
- return this.fetch();
144
+ return this.fetch({ fetchTemplates: false });
145
145
  }
146
146
  return null;
147
147
  })
@@ -200,14 +200,17 @@ export const DeckVersionModel = BaseModel.extend(
200
200
  return Promise.all(imports);
201
201
  },
202
202
 
203
- fetch() {
204
- const fetch = BaseModel.prototype.fetch.apply(this, arguments);
203
+ fetch(opts, ...other) {
204
+ const fetch = BaseModel.prototype.fetch.apply(this, [opts, ...other]);
205
+ const shouldFetchTemplates = opts?.fetchTemplates ?? true;
205
206
 
206
207
  return Promise.resolve(fetch).tap(() => {
207
208
  // `template_set` used to come on the deckversion response, but we have since
208
209
  // decided to request it separately (this helps with caching). To keep the app
209
210
  // working with minimal changes, we're making the extra request here.
210
- return this.template_set.fetch();
211
+ if (shouldFetchTemplates) {
212
+ return this.template_set.fetch();
213
+ }
211
214
  });
212
215
  },
213
216
 
@@ -222,13 +225,13 @@ export const DeckVersionModel = BaseModel.extend(
222
225
  );
223
226
  },
224
227
 
225
- fetchLayout: function (presetId, teamIds) {
228
+ fetchLayout: function (presetId, scenarioID) {
226
229
  let queryParams = { version: this.version };
227
230
  if (presetId) {
228
231
  queryParams.preset_id = presetId;
229
232
  }
230
- if (teamIds) {
231
- queryParams.team_id = teamIds;
233
+ if (scenarioID) {
234
+ queryParams.scenario_id = scenarioID;
232
235
  }
233
236
 
234
237
  if (!this.id) {
@@ -1,6 +1,7 @@
1
1
  import "./user.js";
2
2
  import "./deck.js";
3
3
  import "./team.js";
4
+ import "./scenario.js";
4
5
 
5
6
  import { BaseModel } from "./base.js";
6
7
  import { register } from "../state-register.js";
@@ -36,13 +37,14 @@ export const PresetModel = BaseModel.extend(
36
37
  /**
37
38
  * @property {models.UserModel} user
38
39
  * @property {models.DeckModel} deck
39
- * @property {models.TeamModel} team
40
+ * @property {models.TeamMode} team
41
+ * @property {models.ScenarioMode} keylist_scenario
40
42
  */
41
43
  children: {
42
44
  user: "UserModel",
43
45
  deck: "DeckModel",
44
46
  team: "TeamModel",
45
- keylist_team: "TeamModel",
47
+ keylist_scenario: "ScenarioModel",
46
48
  },
47
49
 
48
50
  toServer() {
@@ -66,10 +68,10 @@ export const PresetModel = BaseModel.extend(
66
68
  if (teamURL) {
67
69
  data.team = teamURL;
68
70
  }
69
- const keylistTeamURL = this._retrieveURL(this.keylist_team);
71
+ const keylistScenarioURL = this._retrieveURL(this.keylist_scenario);
70
72
 
71
- if (keylistTeamURL) {
72
- data.keylist_team = keylistTeamURL;
73
+ if (keylistScenarioURL) {
74
+ data.keylist_scenario = keylistScenarioURL;
73
75
  }
74
76
 
75
77
  return data;
@@ -79,6 +81,6 @@ export const PresetModel = BaseModel.extend(
79
81
 
80
82
  PresetModel.USER_VISIBILITY = "__user__";
81
83
  PresetModel.GLOBAL_VISIBILITY = "__global__";
82
- PresetModel.STANDARD_SLIDE_SOURCE = "__standard__";
84
+ PresetModel.STANDARD_DECK = "__standard__";
83
85
 
84
86
  register("PresetModel", PresetModel);
@@ -0,0 +1,39 @@
1
+ import _ from "lodash";
2
+ import "./team.js";
3
+ import "./deck.js";
4
+
5
+ import { register } from "../state-register.js";
6
+ import { BaseModel } from "../models/base.js";
7
+
8
+ /**
9
+ * @constructor
10
+ * @alias models.ScenarioModel
11
+ * @extends models.BaseModel
12
+ */
13
+ export const ScenarioModel = BaseModel.extend(
14
+ /** @lends models.ScenarioModel# */ {
15
+ modelName: "scenarios",
16
+ detailType: "uuid",
17
+
18
+ props: {
19
+ name: "string",
20
+ must_use_with_preset_for_this_scenario: "boolean",
21
+ can_use_personal_presets: "boolean",
22
+ },
23
+
24
+ /**
25
+ * @property {models.DeckModel} deck
26
+ * @property {models.TeamModel} owner_team
27
+ */
28
+ children: {
29
+ deck: "DeckModel",
30
+ owner_team: "TeamModel",
31
+ },
32
+
33
+ toServer() {
34
+ return _.omit(this.serialize({ urlsOnly: true }), ["url"]);
35
+ },
36
+ },
37
+ );
38
+
39
+ register("ScenarioModel", ScenarioModel);
package/src/models.js CHANGED
@@ -42,6 +42,7 @@ export * from "./models/preset";
42
42
  export * from "./models/refresh-request";
43
43
  export * from "./models/room";
44
44
  export * from "./models/salesforce-lookup.js";
45
+ export * from "./models/scenario";
45
46
  export * from "./models/section";
46
47
  export * from "./models/section-selection";
47
48
  export * from "./models/signing-backend";