@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
@@ -5,7 +5,7 @@ import "../models/user.js";
5
5
  import "../collections/opportunities.js";
6
6
  import "../collections/contacts.js";
7
7
 
8
- import { AppointmentModel, TeamModel } from "../models.js";
8
+ import { AppointmentModel, ScenarioModel } from "../models.js";
9
9
 
10
10
  import { BaseModel } from "../models/base.js";
11
11
  import { PresentationDeck } from "./presentation-deck.js";
@@ -59,16 +59,18 @@ export const AppointmentPresentation = BaseModel.extend(
59
59
 
60
60
  const createFromAppointment = function (appointment, options) {
61
61
  const appointmentPresentation = new AppointmentPresentation();
62
- const team = appointment.team ? new TeamModel(appointment.team).id : null;
62
+ const scenario = appointment.scenario
63
+ ? new ScenarioModel(appointment.scenario).id
64
+ : null;
63
65
 
64
66
  // Note that we're not passing through tags if appointment.tags is empty.
65
67
  // This is because tags currently aren't available in the telepresenter
66
68
  // bundle and we want to fall back on the model tags for now.
67
69
  appointmentPresentation.presentation.decks.add(
68
70
  appointment.deckversion_set.map((model, index) => {
69
- const screenshots = PresentationDeck.filterScreenshotsByTeam(
71
+ const screenshots = PresentationDeck.filterScreenshotsByScenario(
70
72
  model.screenshots,
71
- team,
73
+ scenario,
72
74
  );
73
75
 
74
76
  return PresentationDeck.createFromDeckVersion(model, {
@@ -1,6 +1,6 @@
1
1
  import { BaseModel } from "../models/base.js";
2
2
  import { DeckVersionScreenshotCollection } from "../collections/deck-version-screenshots.js";
3
- import { TeamModel } from "../models/team.js";
3
+ import { ScenarioModel } from "../models/scenario.js";
4
4
  import _ from "lodash";
5
5
 
6
6
  /**
@@ -24,7 +24,7 @@ BasePresentationModel.screenshotsToMap = function (screenshots) {
24
24
  return screenshots.reduce((result, model) => {
25
25
  if (result[model.subject]) {
26
26
  throw new Error(`
27
- Found multiple screenshots that could match this subject. If there is a team
27
+ Found multiple screenshots that could match this subject. If there is a scenario
28
28
  and a global, be sure to remove the screenshot that you don't need.
29
29
  `);
30
30
  }
@@ -50,52 +50,58 @@ BasePresentationModel.getThumbnail = function (model, screenshots) {
50
50
  };
51
51
 
52
52
  /**
53
- * Takes a list of screenshots and filters it to only be a list used by a single team
53
+ * Takes a list of screenshots and filters it to only be a list used by a single scenario
54
54
  * (or company wide).
55
55
  *
56
56
  * The logic should be like this:
57
57
  *
58
- * * If the team is null, we just return all global screenshots (team = null)
59
- * * If we select a team, we take those global screenshots and replace any that have a
60
- * team specific version of that screenshot. If none is found, the team will want to
61
- * see the same global version. Obviously only one team's screenshots should be available.
58
+ * * If the scenario is null, we just return all global screenshots (scenario = null)
59
+ * * If we select a scenario, we take those global screenshots and replace any that have a
60
+ * scenario specific version of that screenshot. If none is found, the
61
+ * scenario will want to see the same global version. Obviously only one
62
+ * scenario's screenshots should be available.
62
63
  */
63
- BasePresentationModel.filterScreenshotsByTeam = function (
64
+ BasePresentationModel.filterScreenshotsByScenario = function (
64
65
  _screenshots,
65
- _team = null,
66
+ _scenario = null,
66
67
  ) {
67
68
  const screenshots = new DeckVersionScreenshotCollection(_screenshots);
68
- const team = _team ? new TeamModel(_team) : null;
69
+ const scenario = _scenario ? new ScenarioModel({ id: _scenario }) : null;
69
70
 
70
71
  const globalScreenshots = screenshots
71
- .filter((screen) => screen.team === null)
72
+ .filter((screen) => screen.scenario === null)
72
73
  .map((screen) => screen.toJSON());
73
74
 
74
75
  const result = globalScreenshots;
75
76
 
76
- if (team) {
77
- const teamScreenshots = screenshots
78
- .filter((screen) => screen.team && screen.team.url() === team.url())
79
- .map((screen) => ({ ...screen.toJSON(), team: screen.team.url() }));
80
-
81
- for (const teamScreen of teamScreenshots) {
77
+ if (scenario) {
78
+ const scenarioScreenshots = screenshots
79
+ .filter(
80
+ (screen) => screen.scenario && screen.scenario.url() === scenario.url(),
81
+ )
82
+ .map((screen) => ({
83
+ ...screen.toJSON(),
84
+ scenario: screen.scenario.url(),
85
+ }));
86
+
87
+ for (const scenarioScreen of scenarioScreenshots) {
82
88
  const existingGlobalIndex = _.findIndex(result, {
83
- subject: teamScreen.subject,
89
+ subject: scenarioScreen.subject,
84
90
  });
85
91
 
86
92
  if (existingGlobalIndex === -1) {
87
- // If there isn't an existing global version, just add the team
93
+ // If there isn't an existing global version, just add the scenario
88
94
  // screenshot to the list
89
- result.push(teamScreen);
95
+ result.push(scenarioScreen);
90
96
  } else {
91
- // Otherwise we should use the team version instead of the global version
92
- result[existingGlobalIndex] = teamScreen;
97
+ // Otherwise we should use the scenario version instead of the global version
98
+ result[existingGlobalIndex] = scenarioScreen;
93
99
  }
94
100
  }
95
101
  }
96
102
 
97
103
  // Try to return it in the same order every time
98
- const ordered = _.orderBy(result, ["team", "subject"], ["desc", "asc"]);
104
+ const ordered = _.orderBy(result, ["scenario", "subject"], ["desc", "asc"]);
99
105
  return new DeckVersionScreenshotCollection(ordered);
100
106
  };
101
107
 
@@ -229,38 +229,38 @@ describe("#getTags", () => {
229
229
  });
230
230
  });
231
231
 
232
- describe("#filterScreenshotsByTeam", () => {
232
+ describe("#filterScreenshotsByScenario", () => {
233
233
  const screenshots = new DeckVersionScreenshotCollection([
234
234
  {
235
235
  subject: "/api/slides/1/",
236
236
  image_256: "global-screenshot-1.png",
237
- team: null,
237
+ scenario: null,
238
238
  },
239
239
  {
240
240
  subject: "/api/slides/2/",
241
241
  image_256: "global-screenshot-2.png",
242
- team: null,
242
+ scenario: null,
243
243
  },
244
244
  {
245
245
  subject: "/api/slides/1/",
246
- image_256: "team-1-screenshot.png",
247
- team: "/api/teams/1/",
246
+ image_256: "scenario-1-screenshot.png",
247
+ scenario: "/api/scenarios/50465ccb-8887-4e1c-bb01-84c91a58c7ea/",
248
248
  },
249
249
  {
250
250
  subject: "/api/sections/2/",
251
- image_256: "team-1-screenshot.png",
252
- team: "/api/teams/1/",
251
+ image_256: "scenario-1-screenshot.png",
252
+ scenario: "/api/scenarios/50465ccb-8887-4e1c-bb01-84c91a58c7ea/",
253
253
  },
254
- // Just for testing that the team filters don't get cross-contaminated
254
+ // Just for testing that the scenario filters don't get cross-contaminated
255
255
  {
256
256
  subject: "/api/sections/2/",
257
- image_256: "team-2-screenshot.png",
258
- team: "/api/teams/2/",
257
+ image_256: "scenario-2-screenshot.png",
258
+ scenario: "/api/scenarios/9d35f335-efe7-4e5b-8365-f2afa229469d/",
259
259
  },
260
260
  ]);
261
261
 
262
- it("should just return global screenshots if team is null", () => {
263
- const filtered = BasePresentationModel.filterScreenshotsByTeam(
262
+ it("should just return global screenshots if scenario is null", () => {
263
+ const filtered = BasePresentationModel.filterScreenshotsByScenario(
264
264
  screenshots,
265
265
  null,
266
266
  ).toJSON();
@@ -269,37 +269,37 @@ describe("#filterScreenshotsByTeam", () => {
269
269
  {
270
270
  subject: "/api/slides/1/",
271
271
  image_256: "global-screenshot-1.png",
272
- team: null,
272
+ scenario: null,
273
273
  },
274
274
  {
275
275
  subject: "/api/slides/2/",
276
276
  image_256: "global-screenshot-2.png",
277
- team: null,
277
+ scenario: null,
278
278
  },
279
279
  ]);
280
280
  });
281
281
 
282
- it("should return globals with team override", () => {
283
- const filtered = BasePresentationModel.filterScreenshotsByTeam(
282
+ it("should return globals with scenario override", () => {
283
+ const filtered = BasePresentationModel.filterScreenshotsByScenario(
284
284
  screenshots,
285
- 1,
285
+ "50465ccb-8887-4e1c-bb01-84c91a58c7ea",
286
286
  ).toJSON();
287
287
 
288
288
  expect(filtered).toEqual([
289
289
  {
290
290
  image_256: "global-screenshot-2.png",
291
291
  subject: "/api/slides/2/",
292
- team: null,
292
+ scenario: null,
293
293
  },
294
294
  {
295
- image_256: "team-1-screenshot.png",
295
+ image_256: "scenario-1-screenshot.png",
296
296
  subject: "/api/sections/2/",
297
- team: "/api/teams/1/",
297
+ scenario: "/api/scenarios/50465ccb-8887-4e1c-bb01-84c91a58c7ea/",
298
298
  },
299
299
  {
300
- image_256: "team-1-screenshot.png",
300
+ image_256: "scenario-1-screenshot.png",
301
301
  subject: "/api/slides/1/",
302
- team: "/api/teams/1/",
302
+ scenario: "/api/scenarios/50465ccb-8887-4e1c-bb01-84c91a58c7ea/",
303
303
  },
304
304
  ]);
305
305
  });
@@ -49,7 +49,10 @@ export const PresentationSection = BasePresentationModel.extend(
49
49
  * @property {boolean} visible
50
50
  * @property {number} deckversion
51
51
  * @property {number} selectionID
52
- * @property {boolean} editable
52
+ * @property {bool} editable
53
+ * @property {bool} titleEditable
54
+ * @property {bool} notesEditable
55
+ * @property {bool} tagsEditable
53
56
  * @property {array} tags
54
57
  * @property {boolean} impostor
55
58
  * @property {boolean} isWelcome
@@ -94,6 +97,9 @@ export const PresentationSection = BasePresentationModel.extend(
94
97
  deckversion: "number",
95
98
  selectionID: "number",
96
99
  editable: "boolean",
100
+ titleEditable: "boolean",
101
+ notesEditable: "boolean",
102
+ tagsEditable: "boolean",
97
103
  tags: "array",
98
104
  impostor: "boolean",
99
105
  isWelcome: {
@@ -226,6 +232,11 @@ PresentationSection.createFromSection = function (sectionModel, options = {}) {
226
232
  title: sectionModel.title,
227
233
  deckversion: sectionModel.deckversion.id,
228
234
  editable: tags.indexOf("editable") > -1,
235
+ // By default this is true for a deck slide. These can be changed later in PM depending
236
+ // on the logged in user and properties of an AutoAdjunct
237
+ titleEditable: false,
238
+ notesEditable: true,
239
+ tagsEditable: true,
229
240
  tags,
230
241
  index: config.sequence,
231
242
  sequence: config.sequence,
@@ -304,6 +315,9 @@ PresentationSection.createFromAdjunctSection = function (
304
315
  title: adjunctSectionModel.title,
305
316
  deckversion: deckVersionModel.id,
306
317
  editable: false,
318
+ titleEditable: false,
319
+ notesEditable: false,
320
+ tagsEditable: false,
307
321
  index: config.sequence,
308
322
  sequence: config.sequence,
309
323
  visible: config.visible,
@@ -404,6 +418,9 @@ PresentationSection.createFromImpostorSection = function (
404
418
  title: slideModel.title,
405
419
  deckversion: slideModel.section.deckversion.id,
406
420
  editable: tags.indexOf("editable") > -1,
421
+ titleEditable: false,
422
+ notesEditable: false,
423
+ tagsEditable: false,
407
424
  tags,
408
425
  index: config.sequence,
409
426
  sequence: config.sequence,
@@ -467,7 +484,7 @@ PresentationSection.createFromManifestImpostor = function (
467
484
  const slides = section.slides || [];
468
485
  section.slides = null;
469
486
 
470
- const projectSection = project?.sections.find((s) => s.key === section.key);
487
+ const projectSection = project?.sections.find((s) => s.key === project.key);
471
488
 
472
489
  const presentationSection = new PresentationSection({
473
490
  id: parseInt(_.uniqueId(), 10),
@@ -554,6 +571,10 @@ PresentationSection.createFromAutoAdjunct = function (model, opts = {}) {
554
571
  tags,
555
572
  cmsvalkey_set: autoAdjunct.cmsvalkey_set,
556
573
  namespacedKey: autoAdjunct.namespaced_key,
574
+ editable: true,
575
+ titleEditable: true,
576
+ notesEditable: true,
577
+ tagsEditable: true,
557
578
  });
558
579
 
559
580
  if (autoAdjunct.template) {
@@ -608,6 +629,10 @@ PresentationSection.createFromTemplate = function (template, index, minID = 0) {
608
629
  index,
609
630
  cmsvalkey_set: [],
610
631
  namespacedKey: templateModel.namespaced_key,
632
+ editable: false,
633
+ titleEditable: false,
634
+ notesEditable: false,
635
+ tagsEditable: false,
611
636
  });
612
637
 
613
638
  return presentationSection;
@@ -56,6 +56,9 @@ describe("#createFromSection", () => {
56
56
  custom: false,
57
57
  deckversion: 408,
58
58
  editable: false,
59
+ titleEditable: false,
60
+ notesEditable: true,
61
+ tagsEditable: true,
59
62
  html: "https://staging-test-cdn.salespreso.com/media/pack/409/assets/sections/agenda/index.html",
60
63
  id: 1728,
61
64
  impostor: false,
@@ -184,7 +187,6 @@ describe("#createFromAdjunctSection", () => {
184
187
  createdByTemplate: false,
185
188
  custom: false,
186
189
  deckversion: 1,
187
- editable: false,
188
190
  id: 1,
189
191
  image:
190
192
  "https://staging-test-cdn.salespreso.com/media/autoadjunct/123.png",
@@ -204,6 +206,10 @@ describe("#createFromAdjunctSection", () => {
204
206
  url: "/api/adjunctsections/1737/",
205
207
  visible: true,
206
208
  cmsvalkey_set: [],
209
+ editable: false,
210
+ titleEditable: false,
211
+ notesEditable: false,
212
+ tagsEditable: false,
207
213
  };
208
214
 
209
215
  expect(presentationSection.toJSON()).toEqual(expected);
@@ -312,6 +318,9 @@ describe("#createFromImpostorSection", () => {
312
318
  custom: false,
313
319
  deckversion: 3,
314
320
  editable: false,
321
+ titleEditable: false,
322
+ notesEditable: false,
323
+ tagsEditable: false,
315
324
  html: "https://staging-test-cdn.salespreso.com/media/pack/427/assets/sections/test-deck/slides/agenda/index.html",
316
325
  id: 23898,
317
326
  impostor: true,
@@ -441,6 +450,10 @@ describe("#createFromAutoAdjunct", () => {
441
450
  title: "Five",
442
451
  url: "/api/adjunctsections/545/",
443
452
  visible: true,
453
+ editable: true,
454
+ titleEditable: true,
455
+ tagsEditable: true,
456
+ notesEditable: true,
444
457
  };
445
458
  expect(presentationSection.toJSON()).toEqual(expected);
446
459
  });
@@ -41,6 +41,9 @@ export const PresentationSlide = BasePresentationModel.extend(
41
41
  * @property {string} thumbnail
42
42
  * @property {number} selectionID
43
43
  * @property {bool} editable
44
+ * @property {bool} titleEditable
45
+ * @property {bool} notesEditable
46
+ * @property {bool} tagsEditable
44
47
  * @property {array} tags
45
48
  * @property {string[]} cmsvalkey_set
46
49
  */
@@ -80,6 +83,9 @@ export const PresentationSlide = BasePresentationModel.extend(
80
83
  thumbnail: "string",
81
84
  selectionID: "number",
82
85
  editable: "boolean",
86
+ titleEditable: "boolean",
87
+ notesEditable: "boolean",
88
+ tagsEditable: "boolean",
83
89
  tags: "array",
84
90
  cmsvalkey_set: "array",
85
91
  },
@@ -170,6 +176,11 @@ PresentationSlide.createFromSlide = function (slideModel, options = {}) {
170
176
  thumbnail: PresentationSlide.getThumbnail(slideModel, options.screenshots),
171
177
  custom: false,
172
178
  editable: tags.indexOf("editable") > -1,
179
+ // By default this is true for a deck slide. These can be changed later in PM depending
180
+ // on the logged in user and properties of an AutoAdjunct
181
+ titleEditable: false,
182
+ notesEditable: true,
183
+ tagsEditable: true,
173
184
  title: slideModel.title,
174
185
  section: slideModel.section.id,
175
186
  sectionKey: slideModel.section.key,
@@ -358,6 +369,9 @@ PresentationSlide.createFromManifestJSON = function (
358
369
  css: url2.resolve(manifestJSON.getAssetPath(key), "slide.css"),
359
370
  key: slideKey,
360
371
  editable: false,
372
+ titleEditable: false,
373
+ notesEditable: false,
374
+ tagsEditable: false,
361
375
  sequence: manifestJSON.ordering[key],
362
376
  thumbnail: null,
363
377
  custom: false,
@@ -372,13 +386,13 @@ PresentationSlide.createFromManifestJSON = function (
372
386
 
373
387
  PresentationSlide.createFromManifestImpostor = function (
374
388
  slide,
375
- section,
389
+ _section,
376
390
  project,
377
391
  index,
378
392
  sectionID,
379
393
  ) {
380
394
  const projectSection = project?.sections?.find?.(
381
- (s) => s.key === section.key,
395
+ (s) => s.key === project.key,
382
396
  );
383
397
  const projectSlide = projectSection?.slides?.find?.(
384
398
  (s) => s.key === slide.key,
@@ -387,6 +401,9 @@ PresentationSlide.createFromManifestImpostor = function (
387
401
  const presentationSlide = new PresentationSlide({
388
402
  id: parseInt(_.uniqueId(), 10),
389
403
  editable: slide.tags.indexOf("editable") !== -1,
404
+ titleEditable: false,
405
+ notesEditable: true,
406
+ tagsEditable: true,
390
407
  thumbnail: null,
391
408
  custom: false,
392
409
  visible: true,
@@ -409,6 +426,9 @@ PresentationSlide.createFromTemplate = function (
409
426
  ...template,
410
427
  id: minID + parseInt(_.uniqueId(), 10),
411
428
  editable: false,
429
+ titleEditable: false,
430
+ notesEditable: false,
431
+ tagsEditable: false,
412
432
  thumbnail: null,
413
433
  custom: false,
414
434
  visible: true,
@@ -479,6 +499,10 @@ PresentationSlide.createFromAutoAdjunct = function (model, opts = {}) {
479
499
  tags,
480
500
  cmsvalkey_set: autoAdjunct.cmsvalkey_set,
481
501
  namespacedKey: autoAdjunct.namespaced_key,
502
+ editable: true,
503
+ titleEditable: true,
504
+ notesEditable: true,
505
+ tagsEditable: true,
482
506
  });
483
507
 
484
508
  if (autoAdjunct.template) {
@@ -46,6 +46,9 @@ describe("#createFromSlide", () => {
46
46
  css: "https://staging-test-cdn.salespreso.com/media/pack/410/assets/sections/test-deck/slides/slide-key/slide.css",
47
47
  custom: false,
48
48
  editable: false,
49
+ titleEditable: false,
50
+ tagsEditable: true,
51
+ notesEditable: true,
49
52
  html: "https://staging-test-cdn.salespreso.com/media/pack/410/assets/sections/test-deck/slides/slide-key/index.html",
50
53
  id: 23219,
51
54
  index: 13,
@@ -294,6 +297,10 @@ describe("#createFromAutoAdjunct", () => {
294
297
  title: "Three",
295
298
  url: "/api/adjunctslides/525/",
296
299
  visible: true,
300
+ editable: true,
301
+ titleEditable: true,
302
+ notesEditable: true,
303
+ tagsEditable: true,
297
304
  };
298
305
 
299
306
  expect(presentationSlide.toJSON()).toEqual(expected);
package/src/utils.js CHANGED
@@ -149,9 +149,19 @@ export function sanitizeBase64(obj, conditionFn = () => true) {
149
149
  return { ...acc, [key]: sanitizeBase64(obj[key], conditionFn) };
150
150
  }, {});
151
151
  } else if (typeof obj === "string") {
152
- const re = /^data:image\/[a-zA-Z]+;base64,[A-Za-z0-9+/=]+$/;
153
- if (re.test(obj) && conditionFn(obj)) {
154
- return "";
152
+ // Catch anything that looks like base64, or base64%2C (which is the encoded version)
153
+ // and strip it. This is a last resort, we'd prefer not to be in this position!
154
+ const re = /base64(,|(%2C))/;
155
+
156
+ if (re.test(obj)) {
157
+ // If you're a developer, let's throw an error.
158
+ if (process.env.NODE_ENV === "development" && !window.Cypress) {
159
+ throw new Error("Tried to save a base64 string. Figure out why!");
160
+ }
161
+
162
+ if (conditionFn?.(obj) ?? true) {
163
+ return "";
164
+ }
155
165
  }
156
166
  }
157
167
  return obj;
package/src/utils.spec.js CHANGED
@@ -3,6 +3,7 @@ import {
3
3
  getShortURL,
4
4
  removeMultiByteChars,
5
5
  replaceHostname,
6
+ sanitizeBase64,
6
7
  } from "./utils.js";
7
8
 
8
9
  describe("getShortURL()", () => {
@@ -160,3 +161,29 @@ describe("replaceHostname()", () => {
160
161
  expect(actual).toEqual(expected);
161
162
  });
162
163
  });
164
+
165
+ describe.only("sanitizeBase64()", () => {
166
+ ["data:image/webp;base64,", "data%3Aimage%2Fwebp%3Bbase64%2C"].forEach(
167
+ (base64) => {
168
+ it("should strip base64 from string", () => {
169
+ expect(sanitizeBase64(base64)).toEqual("");
170
+ });
171
+
172
+ it("should strip base64 from array", () => {
173
+ expect(sanitizeBase64([base64])).toEqual([""]);
174
+ });
175
+
176
+ it("should strip base64 from nested object", () => {
177
+ expect(
178
+ sanitizeBase64({
179
+ foo: [base64],
180
+ }),
181
+ ).toEqual({ foo: [""] });
182
+ });
183
+
184
+ it("should not strip if condition says not to", () => {
185
+ expect(sanitizeBase64(base64, () => false)).toEqual(base64);
186
+ });
187
+ },
188
+ );
189
+ });