@livepreso/api 6.42.1 → 6.45.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 (196) hide show
  1. package/.eslintrc.js +3 -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/45522aea0dee8cb2be1a53248ba45bd235743b43.log +10 -0
  6. package/.rush/temp/58fcbb7f15a76326d40e0839ab179755da82a891.log +10 -0
  7. package/.rush/temp/5bc0bba70b733baa4dd976667ba0a1386e516186.log +10 -0
  8. package/.rush/temp/64f1bb696f8d7d7e72907b80df316b127f72e23e.log +10 -0
  9. package/.rush/temp/6f640f951414ea68adb65c17e4ed7527cde54faf.log +10 -0
  10. package/.rush/temp/7c7b958682d4ab5697530be47d0aac62efe1adf1.log +10 -0
  11. package/.rush/temp/82bfb987463fbcfebf04022e6ed00015c73879c8.log +10 -0
  12. package/.rush/temp/844034aa6e542115075e8f3dc5ffc640973e0064.log +10 -0
  13. package/.rush/temp/8b42957a7c15da1f29cb57bee125f13affa70dca.log +10 -0
  14. package/.rush/temp/a769db9d81a23000c0e9b1bf4f1a9a9e721d0d7c.log +10 -0
  15. package/.rush/temp/a87d3a8b4ece87ec66f27c86226a9f205617681f.log +10 -0
  16. package/.rush/temp/bb7a5bdcc4af4ad1507f81f33774b31f5b4e4fb7.log +10 -0
  17. package/.rush/temp/build-cache-tar.log +7 -0
  18. package/.rush/temp/c20e29ccaaa9231b38a28bb24451b4ce7562cdc0.log +10 -0
  19. package/.rush/temp/e21303db8f59b4625fd184c9114377d781fd24f8.log +10 -0
  20. package/.rush/temp/e6d303862765b6a5f41dd483d0f9ae083a1fae10.log +10 -0
  21. package/.rush/temp/eaf69fbc059d2f1258d7569136180d4a1d3c7072.log +10 -0
  22. package/.rush/temp/f85d279e2674966daaec83e1c3986a96f86ef304.log +10 -0
  23. package/.rush/temp/fc0a332c5b34c6b90006850cf2d93a48fb4b9a6e.log +10 -0
  24. package/.rush/temp/package-deps_build.json +152 -134
  25. package/.rush/temp/package-deps_test.json +172 -0
  26. package/.rush/temp/shrinkwrap-deps.json +946 -847
  27. package/CHANGELOG.json +41 -0
  28. package/CHANGELOG.md +22 -1
  29. package/api.build.log +3 -26
  30. package/babel.config.js +1 -1
  31. package/bin/test.sh +0 -1
  32. package/cjs/api.js +1 -1
  33. package/cjs/api.js.map +1 -1
  34. package/cjs/auth.js +38 -11
  35. package/cjs/auth.js.map +1 -1
  36. package/cjs/auth.spec.js +12 -6
  37. package/cjs/auth.spec.js.map +1 -1
  38. package/cjs/caching.js +3 -3
  39. package/cjs/collections/activity.js +2 -2
  40. package/cjs/collections/appointment-adjunct-tags.js +28 -0
  41. package/cjs/collections/appointment-adjunct-tags.js.map +1 -0
  42. package/cjs/collections/appointment-deckversion-tags.js +28 -0
  43. package/cjs/collections/appointment-deckversion-tags.js.map +1 -0
  44. package/cjs/collections/appointment-section-tags.js +28 -0
  45. package/cjs/collections/appointment-section-tags.js.map +1 -0
  46. package/cjs/collections/appointment-slide-tags.js +28 -0
  47. package/cjs/collections/appointment-slide-tags.js.map +1 -0
  48. package/cjs/collections/appointment-tags.js +208 -0
  49. package/cjs/collections/appointment-tags.js.map +1 -0
  50. package/cjs/collections/appointments.js +2 -2
  51. package/cjs/collections/auto-adjuncts.js +2 -2
  52. package/cjs/collections/base.js +84 -3
  53. package/cjs/collections/base.js.map +1 -1
  54. package/cjs/collections/base.spec.js +178 -0
  55. package/cjs/collections/base.spec.js.map +1 -1
  56. package/cjs/collections/deck-version-screenshots.js +62 -0
  57. package/cjs/collections/deck-version-screenshots.js.map +1 -0
  58. package/cjs/collections/deck-versions.js +2 -2
  59. package/cjs/collections/tags.js +28 -0
  60. package/cjs/collections/tags.js.map +1 -0
  61. package/cjs/collections.js +91 -0
  62. package/cjs/collections.js.map +1 -1
  63. package/cjs/models/activity-item.js +5 -3
  64. package/cjs/models/activity-item.js.map +1 -1
  65. package/cjs/models/appointment-adjunct-tags.js +52 -0
  66. package/cjs/models/appointment-adjunct-tags.js.map +1 -0
  67. package/cjs/models/appointment-deckversion-tags.js +52 -0
  68. package/cjs/models/appointment-deckversion-tags.js.map +1 -0
  69. package/cjs/models/appointment-duplicate.js +2 -2
  70. package/cjs/models/appointment-section-tags.js +52 -0
  71. package/cjs/models/appointment-section-tags.js.map +1 -0
  72. package/cjs/models/appointment-slide-tags.js +52 -0
  73. package/cjs/models/appointment-slide-tags.js.map +1 -0
  74. package/cjs/models/appointment-tags.js +16 -15
  75. package/cjs/models/appointment-tags.js.map +1 -1
  76. package/cjs/models/appointment.js +19 -3
  77. package/cjs/models/appointment.js.map +1 -1
  78. package/cjs/models/auto-adjunct.js +3 -1
  79. package/cjs/models/auto-adjunct.js.map +1 -1
  80. package/cjs/models/base.js +19 -1
  81. package/cjs/models/base.js.map +1 -1
  82. package/cjs/models/base.spec.js +9 -0
  83. package/cjs/models/base.spec.js.map +1 -1
  84. package/cjs/models/deck-tags.js +61 -0
  85. package/cjs/models/deck-tags.js.map +1 -0
  86. package/cjs/models/deck-version-screenshot.js +59 -0
  87. package/cjs/models/deck-version-screenshot.js.map +1 -0
  88. package/cjs/models/deck-version.js +30 -5
  89. package/cjs/models/deck-version.js.map +1 -1
  90. package/cjs/models/deck.js +4 -1
  91. package/cjs/models/deck.js.map +1 -1
  92. package/cjs/models/feed-data.js +5 -0
  93. package/cjs/models/feed-data.js.map +1 -1
  94. package/cjs/models/image.js +34 -0
  95. package/cjs/models/image.js.map +1 -1
  96. package/cjs/models/manifest-json.js +56 -13
  97. package/cjs/models/manifest-json.js.map +1 -1
  98. package/cjs/models/preset.js +21 -1
  99. package/cjs/models/preset.js.map +1 -1
  100. package/cjs/models/section.js +3 -1
  101. package/cjs/models/section.js.map +1 -1
  102. package/cjs/models/slide.js +3 -1
  103. package/cjs/models/slide.js.map +1 -1
  104. package/cjs/models/tag.js +54 -0
  105. package/cjs/models/tag.js.map +1 -0
  106. package/cjs/models/template.js +3 -1
  107. package/cjs/models/template.js.map +1 -1
  108. package/cjs/models/token.js +56 -0
  109. package/cjs/models/token.js.map +1 -0
  110. package/cjs/models/user.js +4 -2
  111. package/cjs/models/user.js.map +1 -1
  112. package/cjs/models.js +104 -0
  113. package/cjs/models.js.map +1 -1
  114. package/cjs/presentation/appointment-presentation.js +11 -4
  115. package/cjs/presentation/appointment-presentation.js.map +1 -1
  116. package/cjs/presentation/base-presentation-model.js +167 -9
  117. package/cjs/presentation/base-presentation-model.js.map +1 -1
  118. package/cjs/presentation/base-presentation-model.spec.js +96 -6
  119. package/cjs/presentation/base-presentation-model.spec.js.map +1 -1
  120. package/cjs/presentation/presentation-deck.js +36 -8
  121. package/cjs/presentation/presentation-deck.js.map +1 -1
  122. package/cjs/presentation/presentation-deck.spec.js +53 -0
  123. package/cjs/presentation/presentation-deck.spec.js.map +1 -1
  124. package/cjs/presentation/presentation-section.js +64 -25
  125. package/cjs/presentation/presentation-section.js.map +1 -1
  126. package/cjs/presentation/presentation-section.spec.js +536 -0
  127. package/cjs/presentation/presentation-section.spec.js.map +1 -0
  128. package/cjs/presentation/presentation-slide.js +43 -18
  129. package/cjs/presentation/presentation-slide.js.map +1 -1
  130. package/cjs/presentation/presentation-slide.spec.js +386 -0
  131. package/cjs/presentation/presentation-slide.spec.js.map +1 -0
  132. package/cjs/presentation/presentation-subslide.js +5 -2
  133. package/cjs/presentation/presentation-subslide.js.map +1 -1
  134. package/cjs/presentation/presentation-subslide.spec.js +58 -12
  135. package/cjs/presentation/presentation-subslide.spec.js.map +1 -1
  136. package/cjs/presentation/presentation.js +120 -6
  137. package/cjs/presentation/presentation.js.map +1 -1
  138. package/cjs/state-register.js +11 -1
  139. package/cjs/state-register.js.map +1 -1
  140. package/cjs/sync.js +1 -1
  141. package/cjs/utils.js +5 -5
  142. package/config/rush-project.json +11 -0
  143. package/jest.config.js +1 -0
  144. package/package.json +66 -66
  145. package/src/api.js +1 -1
  146. package/src/auth.js +44 -8
  147. package/src/auth.spec.js +2 -0
  148. package/src/collections/appointment-adjunct-tags.js +18 -0
  149. package/src/collections/appointment-deckversion-tags.js +21 -0
  150. package/src/collections/appointment-section-tags.js +18 -0
  151. package/src/collections/appointment-slide-tags.js +18 -0
  152. package/src/collections/appointment-tags.js +136 -0
  153. package/src/collections/base.js +80 -3
  154. package/src/collections/base.spec.js +108 -1
  155. package/src/collections/deck-version-screenshots.js +48 -0
  156. package/src/collections/tags.js +18 -0
  157. package/src/collections.js +7 -0
  158. package/src/models/activity-item.js +2 -0
  159. package/src/models/appointment-adjunct-tags.js +41 -0
  160. package/src/models/appointment-deckversion-tags.js +41 -0
  161. package/src/models/appointment-section-tags.js +41 -0
  162. package/src/models/appointment-slide-tags.js +41 -0
  163. package/src/models/appointment-tags.js +16 -14
  164. package/src/models/appointment.js +18 -1
  165. package/src/models/auto-adjunct.js +2 -0
  166. package/src/models/base.js +19 -1
  167. package/src/models/base.spec.js +16 -9
  168. package/src/models/deck-tags.js +52 -0
  169. package/src/models/deck-version-screenshot.js +48 -0
  170. package/src/models/deck-version.js +32 -4
  171. package/src/models/deck.js +2 -0
  172. package/src/models/feed-data.js +2 -0
  173. package/src/models/image.js +32 -0
  174. package/src/models/manifest-json.js +55 -7
  175. package/src/models/preset.js +19 -0
  176. package/src/models/section.js +2 -0
  177. package/src/models/slide.js +2 -0
  178. package/src/models/tag.js +42 -0
  179. package/src/models/template.js +2 -0
  180. package/src/models/token.js +47 -0
  181. package/src/models/user.js +4 -0
  182. package/src/models.js +8 -0
  183. package/src/presentation/appointment-presentation.js +13 -2
  184. package/src/presentation/base-presentation-model.js +129 -8
  185. package/src/presentation/base-presentation-model.spec.js +121 -6
  186. package/src/presentation/presentation-deck.js +41 -2
  187. package/src/presentation/presentation-deck.spec.js +53 -0
  188. package/src/presentation/presentation-section.js +57 -14
  189. package/src/presentation/presentation-section.spec.js +496 -0
  190. package/src/presentation/presentation-slide.js +41 -8
  191. package/src/presentation/presentation-slide.spec.js +352 -0
  192. package/src/presentation/presentation-subslide.js +7 -2
  193. package/src/presentation/presentation-subslide.spec.js +32 -3
  194. package/src/presentation/presentation.js +35 -6
  195. package/src/state-register.js +7 -0
  196. package/api.build.error.log +0 -16
@@ -34,6 +34,7 @@ export const SectionModel = BaseModel.extend(
34
34
  * @property {string} title
35
35
  * @property {boolean} uploaded
36
36
  * @property {boolean} visible
37
+ * @property {string[]} cmsvalkey_set
37
38
  */
38
39
  props: {
39
40
  adjunctslide_limit: "number",
@@ -62,6 +63,7 @@ export const SectionModel = BaseModel.extend(
62
63
  type: "array",
63
64
  default: () => [],
64
65
  },
66
+ cmsvalkey_set: "array",
65
67
  },
66
68
 
67
69
  /**
@@ -35,6 +35,7 @@ export const SlideModel = BaseModel.extend(
35
35
  * @property {boolean} uploaded
36
36
  * @property {boolean} visible
37
37
  * @property {array} tags
38
+ * @property {string[]} cmsvalkey_set
38
39
  */
39
40
  props: {
40
41
  adjunctslide_limit: "number",
@@ -63,6 +64,7 @@ export const SlideModel = BaseModel.extend(
63
64
  type: "array",
64
65
  default: () => [],
65
66
  },
67
+ cmsvalkey_set: "array",
66
68
  },
67
69
 
68
70
  /**
@@ -0,0 +1,42 @@
1
+ import "./user.js";
2
+ import "./team.js";
3
+ import "./deck.js";
4
+
5
+ import { BaseModel } from "./base.js";
6
+ import { register } from "../state-register.js";
7
+
8
+ /**
9
+ * @constructor
10
+ * @alias models.TagModel
11
+ * @extends models.BaseModel
12
+ */
13
+ export const TagModel = BaseModel.extend(
14
+ /** @lends models.TagModel# */ {
15
+ modelName: "tags",
16
+
17
+ /**
18
+ * @property {string} scope
19
+ * @property {string} key
20
+ * @property {string} description
21
+ */
22
+ props: {
23
+ scope: "string",
24
+ key: "string",
25
+ description: "string",
26
+ visible: "boolean",
27
+ },
28
+
29
+ /**
30
+ * @property {models.UserModel} user
31
+ * @property {models.TeamModel} team
32
+ * @property {models.DeckModel} deck
33
+ */
34
+ children: {
35
+ user: "UserModel",
36
+ team: "TeamModel",
37
+ deck: "DeckModel",
38
+ },
39
+ }
40
+ );
41
+
42
+ register("TagModel", TagModel);
@@ -23,6 +23,7 @@ export const TemplateModel = BaseModel.extend(
23
23
  * @property {string} image_128
24
24
  * @property {string} image_256
25
25
  * @property {string} image_512
26
+ * @property {string[]} cmsvalkey_set
26
27
  */
27
28
  props: {
28
29
  created_date: "date",
@@ -33,6 +34,7 @@ export const TemplateModel = BaseModel.extend(
33
34
  image_128: "string",
34
35
  image_256: "string",
35
36
  image_512: "string",
37
+ cmsvalkey_set: "array",
36
38
  },
37
39
 
38
40
  /**
@@ -0,0 +1,47 @@
1
+ import "./user.js";
2
+
3
+ import { BaseModel } from "./base.js";
4
+ import { register } from "../state-register.js";
5
+
6
+ /**
7
+ * @constructor
8
+ * @alias models.TokenModel
9
+ * @extends models.BaseModel
10
+ */
11
+ export const TokenModel = BaseModel.extend(
12
+ /** @lends models.TokenModel# */ {
13
+ modelName: "tokens",
14
+
15
+ /**
16
+ * @property {date} created_date
17
+ * @property {boolean} expired
18
+ * @property {date} expires_at
19
+ * @property {string} key
20
+ * @property {number} seconds_to_expiry
21
+ * @property {string} agent
22
+ * @property {string} agent_version
23
+ */
24
+ props: {
25
+ created_date: "date",
26
+ expired: "boolean",
27
+ expires_at: "date",
28
+ key: "string",
29
+ seconds_to_expiry: "number",
30
+ agent: "string",
31
+ agent_version: "string",
32
+ },
33
+
34
+ /**
35
+ * @property {models.UserModel} user
36
+ */
37
+ children: {
38
+ user: "UserModel",
39
+ },
40
+
41
+ url() {
42
+ return `${this.urlRoot()}${this.key}/`;
43
+ },
44
+ }
45
+ );
46
+
47
+ register("TokenModel", TokenModel);
@@ -109,6 +109,8 @@ export const UserModel = BaseModel.extend(
109
109
  const presets = {
110
110
  canCreateCompanyPresets:
111
111
  this.actions.indexOf("Manage Deck Presets") > -1,
112
+ canCreateTeamPresets:
113
+ this.actions.indexOf("Manage Team Presets") > -1,
112
114
  };
113
115
 
114
116
  const presomanager = {
@@ -155,6 +157,8 @@ export const UserModel = BaseModel.extend(
155
157
  this.actions.indexOf("Allow Teamless Appointments") > -1,
156
158
  canUseClosedCaptions:
157
159
  this.actions.indexOf("Use Closed Captions") > -1,
160
+ canCreateMutedAppointments:
161
+ this.actions.indexOf("Create Muted Appointments") > -1,
158
162
  };
159
163
 
160
164
  const customers = {
package/src/models.js CHANGED
@@ -17,7 +17,9 @@ export * from "./models/cms-val";
17
17
  export * from "./models/contact";
18
18
  export * from "./models/customer";
19
19
  export * from "./models/deck";
20
+ export * from "./models/deck-tags";
20
21
  export * from "./models/deck-version";
22
+ export * from "./models/deck-version-screenshot";
21
23
  export * from "./models/dispatch";
22
24
  export * from "./models/dispatch-preview";
23
25
  export * from "./models/envs.js";
@@ -46,6 +48,7 @@ export * from "./models/slide-selection";
46
48
  export * from "./models/snapshot";
47
49
  export * from "./models/sub-slide";
48
50
  export * from "./models/support-ticket.js";
51
+ export * from "./models/tag.js";
49
52
  export * from "./models/tenancy.js";
50
53
  export * from "./models/timing-log.js";
51
54
  export * from "./models/upload.js";
@@ -55,7 +58,12 @@ export * from "./models/appointment-editor.js";
55
58
  export * from "./models/appointment-duplicate.js";
56
59
  export * from "./models/appointment-stats.js";
57
60
  export * from "./models/appointment-viewing.js";
61
+ export * from "./models/appointment-deckversion-tags.js";
62
+ export * from "./models/appointment-section-tags.js";
63
+ export * from "./models/appointment-slide-tags.js";
64
+ export * from "./models/appointment-adjunct-tags.js";
58
65
  export * from "./models/team.js";
59
66
  export * from "./models/template.js";
60
67
  export * from "./models/auto-adjunct-key-check.js";
61
68
  export * from "./models/transcribe-socket.js";
69
+ export * from "./models/token.js";
@@ -5,7 +5,8 @@ import "../models/user.js";
5
5
  import "../collections/opportunities.js";
6
6
  import "../collections/contacts.js";
7
7
 
8
- import { AppointmentModel } from "../models.js";
8
+ import { AppointmentModel, TeamModel } from "../models.js";
9
+
9
10
  import { BaseModel } from "../models/base.js";
10
11
  import { PresentationDeck } from "./presentation-deck.js";
11
12
  import { register } from "../state-register.js";
@@ -58,17 +59,27 @@ export const AppointmentPresentation = BaseModel.extend(
58
59
 
59
60
  const createFromAppointment = function (appointment, options) {
60
61
  const appointmentPresentation = new AppointmentPresentation();
62
+ const team = appointment.team ? new TeamModel(appointment.team).id : null;
61
63
 
64
+ // Note that we're not passing through tags if appointment.tags is empty.
65
+ // This is because tags currently aren't available in the telepresenter
66
+ // bundle and we want to fall back on the model tags for now.
62
67
  appointmentPresentation.presentation.decks.add(
63
68
  appointment.deckversion_set.map((model, index) => {
69
+ const screenshots = PresentationDeck.filterScreenshotsByTeam(
70
+ model.screenshots,
71
+ team
72
+ );
73
+
64
74
  return PresentationDeck.createFromDeckVersion(model, {
65
75
  adjunctSections: appointment.adjunctSections,
66
76
  adjunctSlides: appointment.adjunctSlides,
67
77
  adjunctSubSlides: appointment.adjunctSubSlides,
68
78
  sectionSelections: appointment.appointmentssection_set,
69
79
  slideSelections: appointment.appointmentsslide_set,
80
+ appointmentTags: appointment.tags.length ? appointment.tags : null,
81
+ screenshots,
70
82
  index,
71
- tags: appointment.tags.items,
72
83
  ...options,
73
84
  });
74
85
  })
@@ -1,4 +1,7 @@
1
1
  import { BaseModel } from "../models/base.js";
2
+ import { DeckVersionScreenshotCollection } from "../collections/deck-version-screenshots.js";
3
+ import { TeamModel } from "../models/team.js";
4
+ import _ from "lodash";
2
5
 
3
6
  /**
4
7
  * @constructor
@@ -13,6 +16,80 @@ export const BasePresentationModel = BaseModel.extend(
13
16
  }
14
17
  );
15
18
 
19
+ /**
20
+ * Logic to pick a thumbnail based on either the model itself or from
21
+ * and overriding screenshot if one exists.
22
+ */
23
+ BasePresentationModel.getThumbnail = function (model, screenshots) {
24
+ const overrideScreenshot =
25
+ screenshots?.filter((screen) => {
26
+ return screen.subject === model.url();
27
+ }) ?? [];
28
+
29
+ if (overrideScreenshot.length) {
30
+ if (overrideScreenshot.length > 1) {
31
+ throw new Error(`
32
+ Found multiple screenshots that could match this subject. If there is a team
33
+ and a global, be sure to remove the screenshot that you don't need.
34
+ `);
35
+ }
36
+
37
+ return overrideScreenshot[0].image_256;
38
+ }
39
+
40
+ return model.image_256;
41
+ };
42
+
43
+ /**
44
+ * Takes a list of screenshots and filters it to only be a list used by a single team
45
+ * (or company wide).
46
+ *
47
+ * The logic should be like this:
48
+ *
49
+ * * If the team is null, we just return all global screenshots (team = null)
50
+ * * If we select a team, we take those global screenshots and replace any that have a
51
+ * team specific version of that screenshot. If none is found, the team will want to
52
+ * see the same global version. Obviously only one team's screenshots should be available.
53
+ */
54
+ BasePresentationModel.filterScreenshotsByTeam = function (
55
+ _screenshots,
56
+ _team = null
57
+ ) {
58
+ const screenshots = new DeckVersionScreenshotCollection(_screenshots);
59
+ const team = _team ? new TeamModel(_team) : null;
60
+
61
+ const globalScreenshots = screenshots
62
+ .filter((screen) => screen.team === null)
63
+ .map((screen) => screen.toJSON());
64
+
65
+ const result = globalScreenshots;
66
+
67
+ if (team) {
68
+ const teamScreenshots = screenshots
69
+ .filter((screen) => screen.team && screen.team.url() === team.url())
70
+ .map((screen) => ({ ...screen.toJSON(), team: screen.team.url() }));
71
+
72
+ for (const teamScreen of teamScreenshots) {
73
+ const existingGlobalIndex = _.findIndex(result, {
74
+ subject: teamScreen.subject,
75
+ });
76
+
77
+ if (existingGlobalIndex === -1) {
78
+ // If there isn't an existing global version, just add the team
79
+ // screenshot to the list
80
+ result.push(teamScreen);
81
+ } else {
82
+ // Otherwise we should use the team version instead of the global version
83
+ result[existingGlobalIndex] = teamScreen;
84
+ }
85
+ }
86
+ }
87
+
88
+ // Try to return it in the same order every time
89
+ const ordered = _.orderBy(result, ["team", "subject"], ["desc", "asc"]);
90
+ return new DeckVersionScreenshotCollection(ordered);
91
+ };
92
+
16
93
  /**
17
94
  * Standard function for retrieving the visibility and sequence of a model
18
95
  * from a choicelist or section & slide selections. If a choicelist is
@@ -20,7 +97,6 @@ export const BasePresentationModel = BaseModel.extend(
20
97
  * Adjuncts are included in choicelists but not in selections so we use the
21
98
  * model's state to determine sequence & vis when selections are used.
22
99
  */
23
-
24
100
  BasePresentationModel.getVisibilityAndSequence = function (
25
101
  model,
26
102
  options = {}
@@ -64,15 +140,60 @@ BasePresentationModel.getVisibilityAndSequence = function (
64
140
  return config;
65
141
  };
66
142
 
143
+ const getAppointmentTags = function (model, tags) {
144
+ const url = model.adjunct?.url() || model.url();
145
+ const tagItem = tags.find((tag) => tag.content_url === url);
146
+
147
+ if (tagItem) {
148
+ return tagItem.tags || [];
149
+ }
150
+
151
+ // Subslide tags currently aren't included in the
152
+ // appointmentTags data.
153
+ return model.tags || [];
154
+ };
155
+
156
+ const getDeckTags = function (model, tags) {
157
+ // All non-adjunct sections, slides and subslides have namespaced_key
158
+ if (model.namespaced_key) {
159
+ return tags[model.namespaced_key] || model.tags || [];
160
+ } else if (model.adjunct || model.isAutoAdjunct) {
161
+ // Autoadjunct keys are unique and move around so we search for them
162
+ // and ignore the rest of the namespaced key
163
+ const keys = Object.keys(tags).filter((key) => {
164
+ if (key.includes("/")) {
165
+ const splitKey = key.split("/");
166
+
167
+ return splitKey[splitKey.length - 1] === model.key;
168
+ }
169
+ return key === model.key;
170
+ });
171
+ return keys.length ? tags[keys[0]] : [];
172
+ } else if (model.deck) {
173
+ // The deck's namespaced key is always "" - this is because the
174
+ // namespaced key format is section-key/slide-key, but the
175
+ // deck sits above sections.
176
+ return tags[""] || model.tags || [];
177
+ }
178
+
179
+ return model.tags || [];
180
+ };
181
+
182
+ // Retrieve the tags for the model.
183
+ // If appointmentTags is passed through in the options, we call the
184
+ // getAppointmentTags function above to retrieve the appointment tags
185
+ // for the model.
186
+ // if there are no appointmentTags but deckTags are passed
187
+ // through then we call the getDeckTags function.
188
+ // In the future we will always use one of these two methods and
189
+ // references to model.tags should be removed.
67
190
  BasePresentationModel.getTags = function (model, options = {}) {
68
- if (options.tags) {
69
- if (model.namespaced_key) {
70
- return options.tags[model.namespaced_key] || [];
71
- } else if (model.deck) {
72
- return options.tags[""];
73
- }
191
+ if (options.appointmentTags) {
192
+ return getAppointmentTags(model, options.appointmentTags);
193
+ }
74
194
 
75
- return [];
195
+ if (options.deckTags) {
196
+ return getDeckTags(model, options.deckTags);
76
197
  }
77
198
 
78
199
  return model.tags || [];
@@ -1,4 +1,5 @@
1
1
  import { BasePresentationModel } from "./base-presentation-model.js";
2
+ import { DeckVersionScreenshotCollection } from "../collections/deck-version-screenshots.js";
2
3
 
3
4
  describe("#getVisibilityAndSequence", () => {
4
5
  it("should return model defaults when no options", () => {
@@ -137,14 +138,14 @@ describe("#getVisibilityAndSequence", () => {
137
138
  });
138
139
 
139
140
  describe("#getTags", () => {
140
- it("should return empty array when no options or model.tags", () => {
141
+ it("should return empty array when no options or model tags", () => {
141
142
  const tags = BasePresentationModel.getTags({});
142
143
 
143
144
  expect(typeof tags).toEqual("object");
144
145
  expect(tags.length).toEqual(0);
145
146
  });
146
147
 
147
- it("should return model.tags when no tags passed in options", () => {
148
+ it("should return tags when no tags passed in options", () => {
148
149
  const model = {
149
150
  tags: ["model-tag-1", "model-tag-2"],
150
151
  };
@@ -153,14 +154,14 @@ describe("#getTags", () => {
153
154
  expect(tags).toEqual(model.tags);
154
155
  });
155
156
 
156
- it("should return options.tags for slide when tags passed in options", () => {
157
+ it("should return tags for slide when tags passed in options", () => {
157
158
  const model = {
158
159
  namespaced_key: "slide-key",
159
160
  tags: ["model-tag-1", "model-tag-2"],
160
161
  };
161
162
 
162
163
  const options = {
163
- tags: {
164
+ deckTags: {
164
165
  "": ["deck-tags"],
165
166
  "slide-key": ["slide-tags"],
166
167
  },
@@ -171,14 +172,14 @@ describe("#getTags", () => {
171
172
  expect(tags).toEqual(["slide-tags"]);
172
173
  });
173
174
 
174
- it("should return options.tags[''] for welcome slide ", () => {
175
+ it("should return tags for welcome slide when tags passed in options", () => {
175
176
  const model = {
176
177
  deck: {},
177
178
  tags: ["model-tag-1", "model-tag-2"],
178
179
  };
179
180
 
180
181
  const options = {
181
- tags: {
182
+ deckTags: {
182
183
  "": ["deck-tags"],
183
184
  "slide-key": ["slide-tags"],
184
185
  },
@@ -188,4 +189,118 @@ describe("#getTags", () => {
188
189
 
189
190
  expect(tags).toEqual(["deck-tags"]);
190
191
  });
192
+
193
+ it("should return tags for an adjunct section when tags passed in options", () => {
194
+ const model = {
195
+ adjunct: true,
196
+ key: "adjunctsection-key",
197
+ tags: ["old-tag-1", "old-tag-2"],
198
+ };
199
+
200
+ const options = {
201
+ deckTags: {
202
+ "": ["deck-tags"],
203
+ "adjunctsection-key": ["adjunctsection-tags"],
204
+ },
205
+ };
206
+
207
+ const tags = BasePresentationModel.getTags(model, options);
208
+
209
+ expect(tags).toEqual(["adjunctsection-tags"]);
210
+ });
211
+
212
+ it("should return tags for an adjunct slide when tags passed in options", () => {
213
+ const model = {
214
+ adjunct: true,
215
+ key: "adjunctslide-key",
216
+ tags: ["old-tag-1", "old-tag-2"],
217
+ };
218
+
219
+ const options = {
220
+ deckTags: {
221
+ "": ["deck-tags"],
222
+ "section-key/adjunctslide-key": ["adjunctslide-tags"],
223
+ },
224
+ };
225
+
226
+ const tags = BasePresentationModel.getTags(model, options);
227
+
228
+ expect(tags).toEqual(["adjunctslide-tags"]);
229
+ });
230
+ });
231
+
232
+ describe("#filterScreenshotsByTeam", () => {
233
+ const screenshots = new DeckVersionScreenshotCollection([
234
+ {
235
+ subject: "/api/slides/1/",
236
+ image_256: "global-screenshot-1.png",
237
+ team: null,
238
+ },
239
+ {
240
+ subject: "/api/slides/2/",
241
+ image_256: "global-screenshot-2.png",
242
+ team: null,
243
+ },
244
+ {
245
+ subject: "/api/slides/1/",
246
+ image_256: "team-1-screenshot.png",
247
+ team: "/api/teams/1/",
248
+ },
249
+ {
250
+ subject: "/api/sections/2/",
251
+ image_256: "team-1-screenshot.png",
252
+ team: "/api/teams/1/",
253
+ },
254
+ // Just for testing that the team filters don't get cross-contaminated
255
+ {
256
+ subject: "/api/sections/2/",
257
+ image_256: "team-2-screenshot.png",
258
+ team: "/api/teams/2/",
259
+ },
260
+ ]);
261
+
262
+ it("should just return global screenshots if team is null", () => {
263
+ const filtered = BasePresentationModel.filterScreenshotsByTeam(
264
+ screenshots,
265
+ null
266
+ ).toJSON();
267
+
268
+ expect(filtered).toEqual([
269
+ {
270
+ subject: "/api/slides/1/",
271
+ image_256: "global-screenshot-1.png",
272
+ team: null,
273
+ },
274
+ {
275
+ subject: "/api/slides/2/",
276
+ image_256: "global-screenshot-2.png",
277
+ team: null,
278
+ },
279
+ ]);
280
+ });
281
+
282
+ it("should return globals with team override", () => {
283
+ const filtered = BasePresentationModel.filterScreenshotsByTeam(
284
+ screenshots,
285
+ 1
286
+ ).toJSON();
287
+
288
+ expect(filtered).toEqual([
289
+ {
290
+ image_256: "global-screenshot-2.png",
291
+ subject: "/api/slides/2/",
292
+ team: null,
293
+ },
294
+ {
295
+ image_256: "team-1-screenshot.png",
296
+ subject: "/api/sections/2/",
297
+ team: "/api/teams/1/",
298
+ },
299
+ {
300
+ image_256: "team-1-screenshot.png",
301
+ subject: "/api/slides/1/",
302
+ team: "/api/teams/1/",
303
+ },
304
+ ]);
305
+ });
191
306
  });
@@ -41,6 +41,7 @@ export const PresentationDeck = BasePresentationModel.extend(
41
41
  * @property {boolean} editable
42
42
  * @property {array} tags
43
43
  * @property {number} version
44
+ * @property {string[]} cmsvalkey_set
44
45
  */
45
46
  props: {
46
47
  html: "string",
@@ -57,6 +58,7 @@ export const PresentationDeck = BasePresentationModel.extend(
57
58
  editable: "boolean",
58
59
  tags: "array",
59
60
  version: "number",
61
+ cmsvalkey_set: "array",
60
62
  },
61
63
 
62
64
  /**
@@ -109,11 +111,13 @@ PresentationDeck.createFromDeckVersion = function (
109
111
  ) {
110
112
  _.defaults(options, {
111
113
  index: 0,
114
+ autoAdjuncts: new collections.AutoAdjunctCollection(),
112
115
  adjunctSections: new collections.AdjunctSectionCollection(),
113
116
  adjunctSlides: new collections.AdjunctSlideCollection(),
114
117
  adjunctSubSlides: new collections.AdjunctSubSlideCollection(),
115
118
  sectionSelections: new collections.SectionSelectionCollection(),
116
119
  slideSelections: new collections.SlideSelectionCollection(),
120
+ screenshots: new collections.DeckVersionScreenshotCollection(),
117
121
  rootAssetPath: null,
118
122
  templates: null,
119
123
  choicelist: null,
@@ -138,7 +142,10 @@ PresentationDeck.createFromDeckVersion = function (
138
142
  css,
139
143
  id: deckVersionModel.id,
140
144
  index: options.index,
141
- thumbnail: deckVersionModel.image_256,
145
+ thumbnail: PresentationDeck.getThumbnail(
146
+ deckVersionModel,
147
+ options.screenshots
148
+ ),
142
149
  deckID: deckVersionModel.deck.id,
143
150
  visible: true,
144
151
  key: deckVersionModel.deck.key,
@@ -148,6 +155,7 @@ PresentationDeck.createFromDeckVersion = function (
148
155
  tags,
149
156
  version: deckVersionModel.version,
150
157
  usesImpostorSections: isImpostorDeck(deckVersionModel),
158
+ cmsvalkey_set: deckVersionModel.cmsvalkey_set || [],
151
159
  });
152
160
 
153
161
  if (!deck.key) {
@@ -342,13 +350,41 @@ PresentationDeck.createFromDeckVersion = function (
342
350
  options.templates.map((template, index) => {
343
351
  return PresentationSection.createFromTemplate(
344
352
  template,
345
- index,
353
+ deck.sections.length + index,
346
354
  options.getUniqueAdjunctID()
347
355
  );
348
356
  })
349
357
  );
350
358
  }
351
359
 
360
+ // This is generally only used by screenshots
361
+ if (options.autoAdjuncts) {
362
+ const autoSections = options.autoAdjuncts.map((auto, index) => {
363
+ // We already have the template on the deckversion, so we can find it here.
364
+ if (!auto.template) {
365
+ throw new Error(
366
+ "Attempted to use an autoadjunct that has no template."
367
+ );
368
+ }
369
+
370
+ const section = PresentationSection.createFromTemplate(
371
+ auto.template,
372
+ deck.sections.length + index,
373
+ options.getUniqueAdjunctID()
374
+ );
375
+
376
+ // We've just borrowed the "from template" method above. We want to add
377
+ // back some of the specific keys about the auto.
378
+ section.autoAdjunctID = auto.id;
379
+ section.key = auto.key;
380
+ section.title = auto.name;
381
+
382
+ return section;
383
+ });
384
+
385
+ deck.sections.add(autoSections);
386
+ }
387
+
352
388
  setSequentialSequences(deck);
353
389
 
354
390
  return deck;
@@ -367,6 +403,8 @@ PresentationDeck.createFromManifestJSON = function (manifestJSON) {
367
403
  deckID: 1,
368
404
  title: "Local",
369
405
  version: 1,
406
+ tags: manifestJSON.tags[""] || [],
407
+ cmsvalkey_set: [],
370
408
  });
371
409
 
372
410
  const usesImpostorSections = _.some(
@@ -390,6 +428,7 @@ PresentationDeck.createFromManifestJSON = function (manifestJSON) {
390
428
  css: url2.resolve(manifestJSON.getAssetPath(key), "slide.css"),
391
429
  title: manifestJSON.titles[key],
392
430
  tags: manifestJSON.tags[key] || [],
431
+ cmsvalkey_set: [],
393
432
  };
394
433
  });
395
434