@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
@@ -0,0 +1,18 @@
1
+ import "../models/appointment-section-tags.js";
2
+
3
+ import { BaseCollection } from "./base.js";
4
+ import { register } from "../state-register.js";
5
+
6
+ /**
7
+ * @constructor
8
+ * @alias collections.AppointmentSectionTagsCollection
9
+ * @extends collections.BaseCollection
10
+ * @see models.AppointmentSectionTagsModel
11
+ */
12
+ export const AppointmentSectionTagsCollection = BaseCollection.extend(
13
+ /** @lends collections.AppointmentSectionTagsCollection# */ {
14
+ model: "AppointmentSectionTagsModel",
15
+ }
16
+ );
17
+
18
+ register("AppointmentSectionTagsCollection", AppointmentSectionTagsCollection);
@@ -0,0 +1,18 @@
1
+ import "../models/appointment-slide-tags.js";
2
+
3
+ import { BaseCollection } from "./base.js";
4
+ import { register } from "../state-register.js";
5
+
6
+ /**
7
+ * @constructor
8
+ * @alias collections.AppointmentSlideTagsCollection
9
+ * @extends collections.BaseCollection
10
+ * @see models.AppointmentSlideTagsModel
11
+ */
12
+ export const AppointmentSlideTagsCollection = BaseCollection.extend(
13
+ /** @lends collections.AppointmentSlideTagsCollection# */ {
14
+ model: "AppointmentSlideTagsModel",
15
+ }
16
+ );
17
+
18
+ register("AppointmentSlideTagsCollection", AppointmentSlideTagsCollection);
@@ -0,0 +1,136 @@
1
+ import { getState, register } from "../state-register.js";
2
+
3
+ import { BaseCollection } from "./base.js";
4
+ import _ from "lodash";
5
+
6
+ /**
7
+ * @constructor
8
+ * @alias collections.AppointmentTagsCollection
9
+ * @extends collections.BaseCollection
10
+ * @see models.AppointmentTagsModel
11
+ */
12
+ export const AppointmentTagsCollection = BaseCollection.extend(
13
+ /** @lends collections.AppointmentTagsCollection# */ {
14
+ model: "AppointmentTagsModel",
15
+
16
+ tagNameCollectionMapping: {
17
+ deckversion: "AppointmentDeckVersionTagsCollection",
18
+ section: "AppointmentSectionTagsCollection",
19
+ slide: "AppointmentSlideTagsCollection",
20
+ adjunct: "AppointmentAdjunctTagsCollection",
21
+ },
22
+
23
+ _mapResultsToModel(result) {
24
+ // Maps a model from a content specific tag to a more generic one.
25
+ // It's generally the same thing, except instead of something like:
26
+ //
27
+ // slide: "/api/slides/1/"
28
+ //
29
+ // It becomes:
30
+ //
31
+ // content_type: "slide",
32
+ // content_url: "/api/slides/1/"
33
+ //
34
+ // So that we can return the list side by side.
35
+ const AppointmentTagsModel = getState("AppointmentTagsModel");
36
+ const resultType = Object.keys(result).find((key) => {
37
+ return Object.keys(this.tagNameCollectionMapping).includes(key);
38
+ });
39
+ if (!resultType) {
40
+ throw new Error("Unknown type of result found");
41
+ }
42
+ return new AppointmentTagsModel({
43
+ tags: result.tags,
44
+ content_type: resultType,
45
+ content_url: result[resultType],
46
+ appointment: result.appointment,
47
+ user: result.user,
48
+ url: result.url,
49
+ });
50
+ },
51
+
52
+ // These methods don't quite make sense right now, disable it for development.
53
+ async fetchSet() {
54
+ throw new Error("Not implemented");
55
+ },
56
+
57
+ async fetchModels() {
58
+ throw new Error("Not implemented");
59
+ },
60
+
61
+ async delete() {
62
+ throw new Error("Cannot delete using this collection");
63
+ },
64
+
65
+ async save() {
66
+ throw new Error("Not implemented");
67
+ },
68
+
69
+ async fetch(options) {
70
+ const AppointmentModel = getState("AppointmentModel");
71
+
72
+ let hasAppointment =
73
+ this._options?.appointment instanceof AppointmentModel ||
74
+ options?.appointment instanceof AppointmentModel;
75
+
76
+ if (!hasAppointment && this.parent instanceof AppointmentModel) {
77
+ options.appointment = this.parent;
78
+ hasAppointment = true;
79
+ }
80
+
81
+ if (!hasAppointment) {
82
+ throw new Error(
83
+ "Requires an appointment model in collection options to fetch."
84
+ );
85
+ }
86
+
87
+ const tagModels = Object.values(this.tagNameCollectionMapping);
88
+ // Fetch all the separate tag models and combine them into a single collection
89
+ const results = (
90
+ await Promise.all(
91
+ tagModels.map((tagModel) => {
92
+ const Collection = getState(tagModel);
93
+ const tags = new Collection({}, this._options);
94
+ return tags.fetch(options);
95
+ })
96
+ )
97
+ )
98
+ .flatMap((collection) => collection.results)
99
+ .map(this._mapResultsToModel.bind(this));
100
+
101
+ this.add(results);
102
+
103
+ return {
104
+ count: results.length,
105
+ next: null,
106
+ previous: null,
107
+ results: this.toJSON(),
108
+ };
109
+ },
110
+
111
+ // Used by Telepresenter to add the tags in the hostedpreso bundle to
112
+ // the appointment tags collection
113
+ addFromAppointment(appointment) {
114
+ const tagCollectionNames = [
115
+ "appointmentdeckversiontags_set",
116
+ "appointmentsectiontags_set",
117
+ "appointmentslidetags_set",
118
+ "appointmentadjuncttags_set",
119
+ ];
120
+
121
+ // flatMap currently doesn't work in TelePresenter
122
+ const results = _.flatten(
123
+ tagCollectionNames.map((collectionName) => {
124
+ const collection = appointment[collectionName];
125
+ return collection?._data || [];
126
+ })
127
+ ).map(this._mapResultsToModel.bind(this));
128
+
129
+ this.add(results);
130
+ },
131
+ }
132
+ );
133
+
134
+ AppointmentTagsCollection.canBeEmpty = true;
135
+
136
+ register("AppointmentTagsCollection", AppointmentTagsCollection);
@@ -8,6 +8,10 @@ import qs from "qs";
8
8
  import { registeredStates } from "../state-register.js";
9
9
  import { sync } from "../sync.js";
10
10
 
11
+ // Current hardcoded limit for maximum number of pages fetched
12
+ // automatically by fetchAll
13
+ const pageLimit = 20;
14
+
11
15
  /**
12
16
  * @constructor
13
17
  * @alias collections.BaseCollection
@@ -34,7 +38,8 @@ export const BaseCollection = Collection.extend(
34
38
  per_page: 1000,
35
39
  },
36
40
 
37
- constructor(data = {}, opts = {}) {
41
+ constructor(_data = {}, opts = {}) {
42
+ let data = _data;
38
43
  const options = _.defaults(opts, {
39
44
  data: {},
40
45
  });
@@ -220,8 +225,75 @@ export const BaseCollection = Collection.extend(
220
225
  });
221
226
  },
222
227
 
228
+ fetchAll(opts = {}) {
229
+ const options = _.cloneDeep(opts);
230
+
231
+ // Add default params to the fetch (ie ?per_page=1000)
232
+ options.data = _.extend({}, this.queryData, options.data || {});
233
+ this._options = _.extend({}, this._options, options);
234
+
235
+ this.queryData = { ...this._options.data };
236
+
237
+ if (this._options.url) {
238
+ this._url = options.url;
239
+ }
240
+
241
+ const checkPages = (response) => {
242
+ const notLastPage = response.total_pages > response.page;
243
+ const belowPageLimit = response.page < pageLimit;
244
+
245
+ if (notLastPage && belowPageLimit) {
246
+ const options = {
247
+ ...this._options,
248
+ data: {
249
+ ...this._options.data,
250
+ page: response.page + 1,
251
+ },
252
+ };
253
+
254
+ // Update the collection with the new data & page number
255
+ this._options = options;
256
+ this.queryData = { ...options.data };
257
+
258
+ return this.fetchPage().then((response) => {
259
+ return checkPages(response);
260
+ });
261
+ } else {
262
+ // The collection's models are replaced with the latest
263
+ // batch of models every time a new page is fetched.
264
+ // Here we add back all of the previously-fetched models.
265
+ this.add(this._data.results);
266
+ return this._data;
267
+ }
268
+ };
269
+
270
+ return this.fetchPage().then((response) => {
271
+ return checkPages(response);
272
+ });
273
+ },
274
+
275
+ fetchPage() {
276
+ return Collection.prototype.fetch
277
+ .call(this, this._options)
278
+ .then((response) => {
279
+ // Add the response data to this._data - if we're fetching
280
+ // multiple pages, this._data.results will contain all of the
281
+ // results fetched from all pages so far
282
+ if (this._data.results?.length) {
283
+ this._data = {
284
+ ...response,
285
+ results: [...this._data.results, ...response.results],
286
+ };
287
+ } else {
288
+ this._data = response;
289
+ }
290
+
291
+ return response;
292
+ });
293
+ },
294
+
223
295
  toServer() {
224
- return this.map(function (model) {
296
+ return this.map((model) => {
225
297
  if (model.toServer) {
226
298
  return model.toServer();
227
299
  } else if (model.serialize) {
@@ -235,6 +307,11 @@ export const BaseCollection = Collection.extend(
235
307
  });
236
308
  },
237
309
 
310
+ // Returns "true" if all child models have been fetched
311
+ areModelsFetched() {
312
+ return this.map((model) => model.isFetched()).every(Boolean);
313
+ },
314
+
238
315
  isNew() {
239
316
  return true;
240
317
  },
@@ -292,7 +369,7 @@ export const BaseCollection = Collection.extend(
292
369
  // can be passed to the model.
293
370
  //
294
371
  // TODO: Regex match for URLs
295
- return results.map(function (attr) {
372
+ return results.map((attr) => {
296
373
  return { url: attr };
297
374
  });
298
375
  }
@@ -1,6 +1,8 @@
1
+ import AmpersandCollection from "ampersand-rest-collection";
1
2
  import { BaseCollection } from "./base.js";
2
3
  import { BaseModel } from "../models/base.js";
3
4
  import { G } from "sp-test/api";
5
+ import Promise from "bluebird";
4
6
  import td from "testdouble";
5
7
 
6
8
  it("should parse an array of urls into models", () => {
@@ -12,7 +14,7 @@ it("should parse an array of urls into models", () => {
12
14
  expect(collection.models).toHaveLength(2);
13
15
  });
14
16
 
15
- it("should fetch the individual models in the collection", async function () {
17
+ it("should fetch the individual models in the collection", async () => {
16
18
  G(BaseModel, "TestModel");
17
19
  const Collection = G(BaseCollection).extend({ model: "TestModel" });
18
20
  const collection = new Collection([{ id: 1 }, { id: 2 }]);
@@ -119,3 +121,108 @@ it("should be empty on initialize", () => {
119
121
  const collection = new Collection();
120
122
  expect(collection.length).toEqual(0);
121
123
  });
124
+
125
+ it("should be not 'areModelsFetched' if all models are just a url or integer", () => {
126
+ const AppointmentCollection = G("AppointmentCollection");
127
+ // A string or an integer should be considered not fetched
128
+ const collection = new AppointmentCollection(["/api/appointments/1/", 2]);
129
+ expect(collection.areModelsFetched()).toBe(false);
130
+ });
131
+
132
+ it("should be 'areModelsFetched' if models are objects", () => {
133
+ G(BaseModel, "TestModel");
134
+ const Collection = G(BaseCollection.extend({ model: "TestModel" }));
135
+ const collection = new Collection([{ id: 1 }, { id: 2 }]);
136
+ expect(collection.areModelsFetched()).toBe(true);
137
+ });
138
+
139
+ const mockFetchResults = (dataFn) => {
140
+ jest
141
+ .spyOn(AmpersandCollection.prototype, "fetch")
142
+ .mockImplementation((opts) => {
143
+ const fetchResults = dataFn(opts);
144
+ return Promise.resolve(fetchResults);
145
+ });
146
+ };
147
+
148
+ describe("fetchAll", () => {
149
+ it("calls Collection.prototype.fetch", async () => {
150
+ mockFetchResults(() => {
151
+ return {
152
+ results: [{ id: 20 }, { id: 21 }, { id: 22 }],
153
+ };
154
+ });
155
+
156
+ G(BaseModel, "TestModel");
157
+ const Collection = G(BaseCollection.extend({ model: "TestModel" }));
158
+ const baseCollection = new Collection();
159
+
160
+ await baseCollection.fetchAll();
161
+
162
+ expect(baseCollection.length).toEqual(3);
163
+ expect(baseCollection.first().id).toEqual(20);
164
+ });
165
+
166
+ it("adds results to existing results", async () => {
167
+ mockFetchResults(() => {
168
+ return {
169
+ results: [{ id: 22 }],
170
+ };
171
+ });
172
+
173
+ G(BaseModel, "TestModel");
174
+ const Collection = G(BaseCollection.extend({ model: "TestModel" }));
175
+ const baseCollection = new Collection([{ id: 15 }]);
176
+
177
+ await baseCollection.fetchAll();
178
+
179
+ expect(baseCollection.length).toEqual(2);
180
+ // The models are sorted by ID
181
+ expect(baseCollection.first().id).toEqual(15);
182
+ expect(baseCollection.last().id).toEqual(22);
183
+ });
184
+
185
+ it("fetches multiple pages", async () => {
186
+ mockFetchResults((opts) => {
187
+ const page = opts.data.page || 1;
188
+ const fetchResults = {
189
+ total_pages: 5,
190
+ page,
191
+ results: [{ id: page + 10 }],
192
+ };
193
+ return Promise.resolve(fetchResults);
194
+ });
195
+
196
+ G(BaseModel, "TestModel");
197
+ const Collection = G(BaseCollection.extend({ model: "TestModel" }));
198
+ const baseCollection = new Collection();
199
+
200
+ await baseCollection.fetchAll();
201
+
202
+ expect(baseCollection.length).toEqual(5);
203
+ expect(baseCollection.first().id).toEqual(11);
204
+ expect(baseCollection.last().id).toEqual(15);
205
+ });
206
+
207
+ it("stops fetching pages at the hardcoded limit", async () => {
208
+ mockFetchResults((opts) => {
209
+ const page = opts.data.page || 1;
210
+ const fetchResults = {
211
+ total_pages: 50,
212
+ page,
213
+ results: [{ id: page + 10 }],
214
+ };
215
+ return Promise.resolve(fetchResults);
216
+ });
217
+
218
+ G(BaseModel, "TestModel");
219
+ const Collection = G(BaseCollection.extend({ model: "TestModel" }));
220
+ const baseCollection = new Collection();
221
+
222
+ await baseCollection.fetchAll();
223
+
224
+ expect(baseCollection.length).toEqual(20);
225
+ expect(baseCollection.first().id).toEqual(11);
226
+ expect(baseCollection.last().id).toEqual(30);
227
+ });
228
+ });
@@ -0,0 +1,48 @@
1
+ import "../models/deck-version-screenshot.js";
2
+
3
+ import Auth from "../auth.js";
4
+ import { BaseCollection } from "./base.js";
5
+ import { register } from "../state-register.js";
6
+
7
+ /**
8
+ * @constructor
9
+ * @alias collections.DeckVersionScreenshotCollection
10
+ * @extends collections.BaseCollection
11
+ * @see models.DeckVersionScreenshotModel
12
+ */
13
+ export const DeckVersionScreenshotCollection = BaseCollection.extend(
14
+ /** @lends collections.DeckVersionScreenshotCollection# */ {
15
+ model: "DeckVersionScreenshotModel",
16
+
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
+ url() {
39
+ if (!this._url && this.parent) {
40
+ this._options.deckversion = this.parent;
41
+ }
42
+
43
+ return BaseCollection.prototype.url.call(this);
44
+ },
45
+ }
46
+ );
47
+
48
+ register("DeckVersionScreenshotCollection", DeckVersionScreenshotCollection);
@@ -0,0 +1,18 @@
1
+ import "../models/tag.js";
2
+
3
+ import { BaseCollection } from "./base.js";
4
+ import { register } from "../state-register.js";
5
+
6
+ /**
7
+ * @constructor
8
+ * @alias collections.TagCollection
9
+ * @extends collections.BaseCollection
10
+ * @see models.TagModel
11
+ */
12
+ export const TagCollection = BaseCollection.extend(
13
+ /** @lends collections.TagCollection# */ {
14
+ model: "TagModel",
15
+ }
16
+ );
17
+
18
+ register("TagCollection", TagCollection);
@@ -14,6 +14,7 @@ export * from "./collections/contacts";
14
14
  export * from "./collections/created-assets";
15
15
  export * from "./collections/customers";
16
16
  export * from "./collections/deck-versions";
17
+ export * from "./collections/deck-version-screenshots";
17
18
  export * from "./collections/decks";
18
19
  export * from "./collections/deleted-assets";
19
20
  export * from "./collections/dispatches";
@@ -36,5 +37,11 @@ export * from "./collections/users";
36
37
  export * from "./collections/uploads";
37
38
  export * from "./collections/appointment-editors.js";
38
39
  export * from "./collections/appointment-duplicates.js";
40
+ export * from "./collections/tags.js";
39
41
  export * from "./collections/teams.js";
40
42
  export * from "./collections/templates.js";
43
+ export * from "./collections/appointment-tags.js";
44
+ export * from "./collections/appointment-deckversion-tags.js";
45
+ export * from "./collections/appointment-section-tags.js";
46
+ export * from "./collections/appointment-slide-tags.js";
47
+ export * from "./collections/appointment-adjunct-tags.js";
@@ -38,6 +38,8 @@ export const ActivityItemModel = BaseModel.extend(
38
38
  notyours: "boolean",
39
39
  onshare: "boolean",
40
40
  view_type: "string",
41
+ is_muted: "boolean",
42
+ appointment_is_deleted: "boolean",
41
43
  },
42
44
 
43
45
  children: {
@@ -0,0 +1,41 @@
1
+ import "./appointment.js";
2
+ import "./user.js";
3
+ import "./adjunct.js";
4
+
5
+ import { BaseModel } from "./base.js";
6
+ import { register } from "../state-register.js";
7
+
8
+ /**
9
+ * @constructor
10
+ * @alias models.AppointmentAdjunctTagsModel
11
+ * @extends models.BaseModel
12
+ */
13
+ export const AppointmentAdjunctTagsModel = BaseModel.extend(
14
+ /** @lends models.AppointmentAdjunctTagsModel# */ {
15
+ modelName: "appointment-adjunct-tags",
16
+
17
+ urlMatchKeys: {
18
+ "appointment.id": "number",
19
+ },
20
+
21
+ /**
22
+ * @property {string[]} tags
23
+ */
24
+ props: {
25
+ tags: "array",
26
+ },
27
+
28
+ /**
29
+ * @property {models.AppointmentModel} appointment
30
+ * @property {models.AdjunctModel} adjunct
31
+ * @property {models.UserModel} user
32
+ */
33
+ children: {
34
+ appointment: "AppointmentModel",
35
+ adjunct: "AdjunctModel",
36
+ user: "UserModel",
37
+ },
38
+ }
39
+ );
40
+
41
+ register("AppointmentAdjunctTagsModel", AppointmentAdjunctTagsModel);
@@ -0,0 +1,41 @@
1
+ import "./appointment.js";
2
+ import "./user.js";
3
+ import "./deck-version.js";
4
+
5
+ import { BaseModel } from "./base.js";
6
+ import { register } from "../state-register.js";
7
+
8
+ /**
9
+ * @constructor
10
+ * @alias models.AppointmentDeckVersionTagsModel
11
+ * @extends models.BaseModel
12
+ */
13
+ export const AppointmentDeckVersionTagsModel = BaseModel.extend(
14
+ /** @lends models.AppointmentDeckVersionTagsModel# */ {
15
+ modelName: "appointment-deckversion-tags",
16
+
17
+ urlMatchKeys: {
18
+ "appointment.id": "number",
19
+ },
20
+
21
+ /**
22
+ * @property {string[]} tags
23
+ */
24
+ props: {
25
+ tags: "array",
26
+ },
27
+
28
+ /**
29
+ * @property {models.AppointmentModel} appointment
30
+ * @property {models.DeckVersionModel} deckversion
31
+ * @property {models.UserModel} user
32
+ */
33
+ children: {
34
+ appointment: "AppointmentModel",
35
+ deckversion: "DeckVersionModel",
36
+ user: "UserModel",
37
+ },
38
+ }
39
+ );
40
+
41
+ register("AppointmentDeckVersionTagsModel", AppointmentDeckVersionTagsModel);
@@ -0,0 +1,41 @@
1
+ import "./appointment.js";
2
+ import "./user.js";
3
+ import "./slide.js";
4
+
5
+ import { BaseModel } from "./base.js";
6
+ import { register } from "../state-register.js";
7
+
8
+ /**
9
+ * @constructor
10
+ * @alias models.AppointmentSectionTagsModel
11
+ * @extends models.BaseModel
12
+ */
13
+ export const AppointmentSectionTagsModel = BaseModel.extend(
14
+ /** @lends models.AppointmentSectionTagsModel# */ {
15
+ modelName: "appointment-section-tags",
16
+
17
+ urlMatchKeys: {
18
+ "appointment.id": "number",
19
+ },
20
+
21
+ /**
22
+ * @property {string[]} tags
23
+ */
24
+ props: {
25
+ tags: "array",
26
+ },
27
+
28
+ /**
29
+ * @property {models.AppointmentModel} appointment
30
+ * @property {models.SectionModel} slide
31
+ * @property {models.UserModel} user
32
+ */
33
+ children: {
34
+ appointment: "AppointmentModel",
35
+ section: "SectionModel",
36
+ user: "UserModel",
37
+ },
38
+ }
39
+ );
40
+
41
+ register("AppointmentSectionTagsModel", AppointmentSectionTagsModel);
@@ -0,0 +1,41 @@
1
+ import "./appointment.js";
2
+ import "./user.js";
3
+ import "./slide.js";
4
+
5
+ import { BaseModel } from "./base.js";
6
+ import { register } from "../state-register.js";
7
+
8
+ /**
9
+ * @constructor
10
+ * @alias models.AppointmentSlideTagsModel
11
+ * @extends models.BaseModel
12
+ */
13
+ export const AppointmentSlideTagsModel = BaseModel.extend(
14
+ /** @lends models.AppointmentSlideTagsModel# */ {
15
+ modelName: "appointment-slide-tags",
16
+
17
+ urlMatchKeys: {
18
+ "appointment.id": "number",
19
+ },
20
+
21
+ /**
22
+ * @property {string[]} tags
23
+ */
24
+ props: {
25
+ tags: "array",
26
+ },
27
+
28
+ /**
29
+ * @property {models.AppointmentModel} appointment
30
+ * @property {models.SlideModel} slide
31
+ * @property {models.UserModel} user
32
+ */
33
+ children: {
34
+ appointment: "AppointmentModel",
35
+ slide: "SlideModel",
36
+ user: "UserModel",
37
+ },
38
+ }
39
+ );
40
+
41
+ register("AppointmentSlideTagsModel", AppointmentSlideTagsModel);