@internetarchive/collection-browser 2.17.1-alpha-webdev7713.0 → 2.18.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 (76) hide show
  1. package/dist/src/app-root.d.ts +0 -3
  2. package/dist/src/app-root.js +0 -91
  3. package/dist/src/app-root.js.map +1 -1
  4. package/dist/src/collection-browser.d.ts +20 -0
  5. package/dist/src/collection-browser.js +74 -0
  6. package/dist/src/collection-browser.js.map +1 -1
  7. package/dist/src/models.d.ts +9 -0
  8. package/dist/src/models.js.map +1 -1
  9. package/dist/src/tiles/base-tile-component.d.ts +1 -0
  10. package/dist/src/tiles/base-tile-component.js +4 -0
  11. package/dist/src/tiles/base-tile-component.js.map +1 -1
  12. package/dist/src/tiles/grid/account-tile.js +2 -0
  13. package/dist/src/tiles/grid/account-tile.js.map +1 -1
  14. package/dist/src/tiles/grid/collection-tile.js +2 -0
  15. package/dist/src/tiles/grid/collection-tile.js.map +1 -1
  16. package/dist/src/tiles/grid/item-tile.js +2 -0
  17. package/dist/src/tiles/grid/item-tile.js.map +1 -1
  18. package/dist/src/tiles/grid/search-tile.js +2 -0
  19. package/dist/src/tiles/grid/search-tile.js.map +1 -1
  20. package/dist/src/tiles/hover/hover-pane-controller.d.ts +1 -0
  21. package/dist/src/tiles/hover/hover-pane-controller.js +4 -3
  22. package/dist/src/tiles/hover/hover-pane-controller.js.map +1 -1
  23. package/dist/src/tiles/hover/tile-hover-pane.d.ts +1 -0
  24. package/dist/src/tiles/hover/tile-hover-pane.js +5 -0
  25. package/dist/src/tiles/hover/tile-hover-pane.js.map +1 -1
  26. package/dist/src/tiles/image-block.d.ts +1 -0
  27. package/dist/src/tiles/image-block.js +7 -0
  28. package/dist/src/tiles/image-block.js.map +1 -1
  29. package/dist/src/tiles/item-image.d.ts +1 -0
  30. package/dist/src/tiles/item-image.js +7 -2
  31. package/dist/src/tiles/item-image.js.map +1 -1
  32. package/dist/src/tiles/list/tile-list-compact-header.js +1 -0
  33. package/dist/src/tiles/list/tile-list-compact-header.js.map +1 -1
  34. package/dist/src/tiles/list/tile-list-compact.js +2 -0
  35. package/dist/src/tiles/list/tile-list-compact.js.map +1 -1
  36. package/dist/src/tiles/list/tile-list.js +2 -0
  37. package/dist/src/tiles/list/tile-list.js.map +1 -1
  38. package/dist/src/tiles/tile-dispatcher.js +7 -0
  39. package/dist/src/tiles/tile-dispatcher.js.map +1 -1
  40. package/dist/test/collection-browser.test.js +58 -3
  41. package/dist/test/collection-browser.test.js.map +1 -1
  42. package/dist/test/image-block.test.js +21 -0
  43. package/dist/test/image-block.test.js.map +1 -1
  44. package/dist/test/item-image.test.js +73 -0
  45. package/dist/test/item-image.test.js.map +1 -1
  46. package/dist/test/mocks/mock-search-responses.d.ts +2 -0
  47. package/dist/test/mocks/mock-search-responses.js +96 -0
  48. package/dist/test/mocks/mock-search-responses.js.map +1 -1
  49. package/dist/test/mocks/mock-search-service.d.ts +1 -0
  50. package/dist/test/mocks/mock-search-service.js +7 -1
  51. package/dist/test/mocks/mock-search-service.js.map +1 -1
  52. package/dist/test/tiles/hover/hover-pane-controller.test.js +1 -0
  53. package/dist/test/tiles/hover/hover-pane-controller.test.js.map +1 -1
  54. package/package.json +3 -3
  55. package/src/app-root.ts +0 -97
  56. package/src/collection-browser.ts +76 -0
  57. package/src/models.ts +10 -0
  58. package/src/tiles/base-tile-component.ts +2 -0
  59. package/src/tiles/grid/account-tile.ts +2 -0
  60. package/src/tiles/grid/collection-tile.ts +2 -0
  61. package/src/tiles/grid/item-tile.ts +2 -0
  62. package/src/tiles/grid/search-tile.ts +2 -0
  63. package/src/tiles/hover/hover-pane-controller.ts +2 -0
  64. package/src/tiles/hover/tile-hover-pane.ts +3 -0
  65. package/src/tiles/image-block.ts +5 -0
  66. package/src/tiles/item-image.ts +7 -2
  67. package/src/tiles/list/tile-list-compact-header.ts +1 -0
  68. package/src/tiles/list/tile-list-compact.ts +2 -0
  69. package/src/tiles/list/tile-list.ts +2 -0
  70. package/src/tiles/tile-dispatcher.ts +7 -0
  71. package/test/collection-browser.test.ts +86 -2
  72. package/test/image-block.test.ts +24 -0
  73. package/test/item-image.test.ts +86 -0
  74. package/test/mocks/mock-search-responses.ts +104 -0
  75. package/test/mocks/mock-search-service.ts +11 -0
  76. package/test/tiles/hover/hover-pane-controller.test.ts +1 -0
@@ -36,6 +36,7 @@ export class TileList extends BaseTileComponent {
36
36
  * - creatorFilter?: string;
37
37
  * - mobileBreakpoint?: number;
38
38
  * - loggedIn = false;
39
+ * - suppressBlurring = false;
39
40
  */
40
41
 
41
42
  @property({ type: Object })
@@ -101,6 +102,7 @@ export class TileList extends BaseTileComponent {
101
102
  .isListTile=${true}
102
103
  .viewSize=${this.classSize}
103
104
  .loggedIn=${this.loggedIn}
105
+ .suppressBlurring=${this.suppressBlurring}
104
106
  >
105
107
  </image-block>
106
108
  </a> `;
@@ -46,6 +46,7 @@ export class TileDispatcher
46
46
  * - creatorFilter?: string;
47
47
  * - mobileBreakpoint?: number;
48
48
  * - loggedIn = false;
49
+ * - suppressTileBlurring = false;
49
50
  */
50
51
 
51
52
  @property({ type: String }) tileDisplayMode?: TileDisplayMode;
@@ -303,6 +304,7 @@ export class TileDispatcher
303
304
  .currentWidth=${currentWidth}
304
305
  .currentHeight=${currentHeight}
305
306
  .creatorFilter=${creatorFilter}
307
+ .suppressBlurring=${this.suppressBlurring}
306
308
  .isManageView=${this.isManageView}
307
309
  ?showInfoButton=${!this.isHoverEnabled}
308
310
  @infoButtonPressed=${this.tileInfoButtonPressed}
@@ -316,6 +318,7 @@ export class TileDispatcher
316
318
  .currentWidth=${currentWidth}
317
319
  .currentHeight=${currentHeight}
318
320
  .creatorFilter=${creatorFilter}
321
+ .suppressBlurring=${this.suppressBlurring}
319
322
  .isManageView=${this.isManageView}
320
323
  ?showInfoButton=${!this.isHoverEnabled}
321
324
  @infoButtonPressed=${this.tileInfoButtonPressed}
@@ -329,6 +332,7 @@ export class TileDispatcher
329
332
  .currentWidth=${currentWidth}
330
333
  .currentHeight=${currentHeight}
331
334
  .creatorFilter=${creatorFilter}
335
+ .suppressBlurring=${this.suppressBlurring}
332
336
  .isManageView=${this.isManageView}
333
337
  ?showInfoButton=${false}
334
338
  @infoButtonPressed=${this.tileInfoButtonPressed}
@@ -345,6 +349,7 @@ export class TileDispatcher
345
349
  .defaultSortParam=${defaultSortParam}
346
350
  .creatorFilter=${creatorFilter}
347
351
  .loggedIn=${this.loggedIn}
352
+ .suppressBlurring=${this.suppressBlurring}
348
353
  .isManageView=${this.isManageView}
349
354
  .simpleLayoutType=${this.simpleLayoutType}
350
355
  ?showTvClips=${this.showTvClips}
@@ -366,6 +371,7 @@ export class TileDispatcher
366
371
  .mobileBreakpoint=${mobileBreakpoint}
367
372
  .baseImageUrl=${this.baseImageUrl}
368
373
  .loggedIn=${this.loggedIn}
374
+ .suppressBlurring=${this.suppressBlurring}
369
375
  >
370
376
  </tile-list-compact>`;
371
377
  case 'list-detail':
@@ -382,6 +388,7 @@ export class TileDispatcher
382
388
  .mobileBreakpoint=${mobileBreakpoint}
383
389
  .baseImageUrl=${this.baseImageUrl}
384
390
  .loggedIn=${this.loggedIn}
391
+ .suppressBlurring=${this.suppressBlurring}
385
392
  >
386
393
  </tile-list>`;
387
394
  default:
@@ -895,8 +895,7 @@ describe('Collection Browser', () => {
895
895
  expect(sortSelector, 'sort bar').to.exist;
896
896
 
897
897
  // Click the title sorter
898
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
899
- [...(sortSelector?.children as HTMLCollection & Iterable<any>)] // tsc doesn't know children is iterable
898
+ Array.from(sortSelector!.children)
900
899
  .find(child => child.textContent?.trim() === 'Title')
901
900
  ?.querySelector('button')
902
901
  ?.click();
@@ -904,6 +903,16 @@ describe('Collection Browser', () => {
904
903
  await el.updateComplete;
905
904
 
906
905
  expect(el.selectedSort).to.equal(SortField.title);
906
+
907
+ // Click the creator sorter
908
+ Array.from(sortSelector!.children)
909
+ .find(child => child.textContent?.trim() === 'Creator')
910
+ ?.querySelector('button')
911
+ ?.click();
912
+
913
+ await el.updateComplete;
914
+
915
+ expect(el.selectedSort).to.equal(SortField.creator);
907
916
  });
908
917
 
909
918
  it('sets sort filter properties when user selects title filter', async () => {
@@ -1072,9 +1081,11 @@ describe('Collection Browser', () => {
1072
1081
 
1073
1082
  it('sets date range query when date picker selection changed', async () => {
1074
1083
  const searchService = new MockSearchService();
1084
+ const mockAnalyticsHandler = new MockAnalyticsHandler();
1075
1085
  const el = await fixture<CollectionBrowser>(
1076
1086
  html`<collection-browser
1077
1087
  .searchService=${searchService}
1088
+ .analyticsHandler=${mockAnalyticsHandler}
1078
1089
  .suppressPlaceholders=${true}
1079
1090
  >
1080
1091
  </collection-browser>`,
@@ -2145,6 +2156,79 @@ describe('Collection Browser', () => {
2145
2156
  .exist;
2146
2157
  });
2147
2158
 
2159
+ it('shows Blurring checkbox for admin users', async () => {
2160
+ const searchService = new MockSearchService();
2161
+ const el = await fixture<CollectionBrowser>(
2162
+ html`<collection-browser
2163
+ .baseNavigationUrl=${''}
2164
+ .searchService=${searchService}
2165
+ >
2166
+ </collection-browser>`,
2167
+ );
2168
+
2169
+ el.baseQuery = 'archive-org-user-loggedin';
2170
+ await el.updateComplete;
2171
+ await el.initialSearchComplete;
2172
+
2173
+ const blurringCheck = el.shadowRoot?.querySelector(
2174
+ '#tile-blur-check',
2175
+ ) as HTMLInputElement;
2176
+ expect(blurringCheck).to.exist;
2177
+ expect(blurringCheck.checked).to.be.true;
2178
+ });
2179
+
2180
+ it('unchecks Blurring checkbox for admin users with blurring preference off', async () => {
2181
+ const searchService = new MockSearchService();
2182
+ const el = await fixture<CollectionBrowser>(
2183
+ html`<collection-browser
2184
+ .baseNavigationUrl=${''}
2185
+ .searchService=${searchService}
2186
+ >
2187
+ </collection-browser>`,
2188
+ );
2189
+
2190
+ el.baseQuery = 'archive-org-user-loggedin-noblur';
2191
+ await el.updateComplete;
2192
+ await el.initialSearchComplete;
2193
+
2194
+ const blurringCheck = el.shadowRoot?.querySelector(
2195
+ '#tile-blur-check',
2196
+ ) as HTMLInputElement;
2197
+ expect(blurringCheck).to.exist;
2198
+ expect(blurringCheck.checked).to.be.false;
2199
+ });
2200
+
2201
+ it('toggles blur state when Blurring checkbox is toggled', async () => {
2202
+ const searchService = new MockSearchService();
2203
+ const el = await fixture<CollectionBrowser>(
2204
+ html`<collection-browser
2205
+ .baseNavigationUrl=${''}
2206
+ .searchService=${searchService}
2207
+ >
2208
+ </collection-browser>`,
2209
+ );
2210
+
2211
+ el.baseQuery = 'archive-org-user-loggedin';
2212
+ await el.updateComplete;
2213
+ await el.initialSearchComplete;
2214
+
2215
+ const blurringCheck = el.shadowRoot?.querySelector(
2216
+ '#tile-blur-check',
2217
+ ) as HTMLInputElement;
2218
+ expect(blurringCheck).to.exist;
2219
+
2220
+ blurringCheck.dispatchEvent(new PointerEvent('click'));
2221
+ await el.updateComplete;
2222
+
2223
+ const infiniteScroller = el.shadowRoot?.querySelector(
2224
+ 'infinite-scroller',
2225
+ ) as InfiniteScroller;
2226
+ const firstTile = infiniteScroller?.shadowRoot?.querySelector(
2227
+ 'tile-dispatcher',
2228
+ ) as TileDispatcher;
2229
+ expect(firstTile.suppressBlurring).to.be.true;
2230
+ });
2231
+
2148
2232
  it('applies loans tab properties to sort bar', async () => {
2149
2233
  const searchService = new MockSearchService();
2150
2234
  const el = await fixture<CollectionBrowser>(
@@ -220,4 +220,28 @@ describe('Image block component', () => {
220
220
  ) as TextOverlay;
221
221
  expect(textOverlay).not.to.exist;
222
222
  });
223
+
224
+ it('should render no overlay if blurring is suppressed', async () => {
225
+ const el = await fixture<ImageBlock>(html`
226
+ <image-block
227
+ .model=${{
228
+ loginRequired: true,
229
+ contentWarning: true,
230
+ identifier: 'goody',
231
+ }}
232
+ .baseImageUrl=${'https://archive.org'}
233
+ .isCompactTile=${false}
234
+ .isListTile=${false}
235
+ .viewSize=${'desktop'}
236
+ .loggedIn=${true}
237
+ suppressBlurring
238
+ >
239
+ </image-block>
240
+ `);
241
+
242
+ const textOverlay = el.shadowRoot?.querySelector(
243
+ 'text-overlay',
244
+ ) as TextOverlay;
245
+ expect(textOverlay).not.to.exist;
246
+ });
223
247
  });
@@ -5,6 +5,7 @@ import { TileModel } from '../src/models';
5
5
  import type { ItemImage } from '../src/tiles/item-image';
6
6
 
7
7
  import '../src/tiles/item-image';
8
+ import { MediaType } from '@internetarchive/field-parsers';
8
9
 
9
10
  const baseImageUrl = 'https://archive.org';
10
11
  const testBookModel: TileModel = new TileModel({});
@@ -131,4 +132,89 @@ describe('ItemImage component', () => {
131
132
  expect(img).to.exist;
132
133
  expect(img?.getAttribute('src')).not.to.exist;
133
134
  });
135
+
136
+ it('should blur image if login required flag set', async () => {
137
+ const model = new TileModel({ identifier: 'foo' });
138
+ model.loginRequired = true;
139
+
140
+ const el = await fixture<ItemImage>(html`
141
+ <item-image
142
+ .isListTile=${false}
143
+ .isCompactTile=${false}
144
+ .model=${model}
145
+ .baseImageUrl=${baseImageUrl}
146
+ >
147
+ </item-image>
148
+ `);
149
+
150
+ const dropShadow = el.shadowRoot?.querySelector('.drop-shadow');
151
+ expect(dropShadow).to.exist;
152
+
153
+ const imgClasses = dropShadow?.querySelector('img')?.classList;
154
+ expect(imgClasses?.contains('blur')).to.be.true;
155
+ });
156
+
157
+ it('should blur image if content warning flag set', async () => {
158
+ const model = new TileModel({ identifier: 'foo' });
159
+ model.contentWarning = true;
160
+
161
+ const el = await fixture<ItemImage>(html`
162
+ <item-image
163
+ .isListTile=${false}
164
+ .isCompactTile=${false}
165
+ .model=${model}
166
+ .baseImageUrl=${baseImageUrl}
167
+ >
168
+ </item-image>
169
+ `);
170
+
171
+ const dropShadow = el.shadowRoot?.querySelector('.drop-shadow');
172
+ expect(dropShadow).to.exist;
173
+
174
+ const imgClasses = dropShadow?.querySelector('img')?.classList;
175
+ expect(imgClasses?.contains('blur')).to.be.true;
176
+ });
177
+
178
+ it('should not blur image if no login required nor content warning', async () => {
179
+ const model = new TileModel({ identifier: 'foo' });
180
+
181
+ const el = await fixture<ItemImage>(html`
182
+ <item-image
183
+ .isListTile=${false}
184
+ .isCompactTile=${false}
185
+ .model=${model}
186
+ .baseImageUrl=${baseImageUrl}
187
+ >
188
+ </item-image>
189
+ `);
190
+
191
+ const dropShadow = el.shadowRoot?.querySelector('.drop-shadow');
192
+ expect(dropShadow).to.exist;
193
+
194
+ const imgClasses = dropShadow?.querySelector('img')?.classList;
195
+ expect(imgClasses?.contains('blur')).to.be.false;
196
+ });
197
+
198
+ it('should not blur image if blurring is suppressed, regardless of content flags', async () => {
199
+ const model = new TileModel({ identifier: 'foo' });
200
+ model.loginRequired = true;
201
+ model.contentWarning = true;
202
+
203
+ const el = await fixture<ItemImage>(html`
204
+ <item-image
205
+ .isListTile=${false}
206
+ .isCompactTile=${false}
207
+ .model=${model}
208
+ .baseImageUrl=${baseImageUrl}
209
+ suppressBlurring
210
+ >
211
+ </item-image>
212
+ `);
213
+
214
+ const dropShadow = el.shadowRoot?.querySelector('.drop-shadow');
215
+ expect(dropShadow).to.exist;
216
+
217
+ const imgClasses = dropShadow?.querySelector('img')?.classList;
218
+ expect(imgClasses?.contains('blur')).to.be.false;
219
+ });
134
220
  });
@@ -291,6 +291,110 @@ export const getMockSuccessWithDateHistogramAggs: () => Result<
291
291
  },
292
292
  });
293
293
 
294
+ export const getMockSuccessArchiveOrgUserResult: () => Result<
295
+ SearchResponse,
296
+ SearchServiceError
297
+ > = () => ({
298
+ success: {
299
+ request: {
300
+ kind: 'hits',
301
+ clientParameters: {
302
+ user_query: 'archive-org-user-loggedin',
303
+ sort: [],
304
+ },
305
+ backendRequests: {
306
+ primary: {
307
+ kind: 'hits',
308
+ finalized_parameters: {
309
+ user_query: 'archive-org-user-loggedin',
310
+ sort: [],
311
+ },
312
+ },
313
+ },
314
+ },
315
+ rawResponse: {},
316
+ sessionContext: {
317
+ is_archive_user: true,
318
+ pps_relevant_user_preferences: {
319
+ display__blur_moderated_content: 'on',
320
+ },
321
+ },
322
+ response: {
323
+ totalResults: 2,
324
+ returnedCount: 2,
325
+ results: [
326
+ new ItemHit({
327
+ fields: {
328
+ identifier: 'foo',
329
+ collection: ['foo', 'loggedin', 'bar'],
330
+ __href__: '/foo',
331
+ },
332
+ }),
333
+ new ItemHit({
334
+ fields: {
335
+ identifier: 'bar',
336
+ collection: ['baz', 'boop'],
337
+ __href__: '/bar',
338
+ },
339
+ }),
340
+ ],
341
+ },
342
+ responseHeader: {
343
+ succeeded: true,
344
+ query_time: 0,
345
+ },
346
+ },
347
+ });
348
+
349
+ export const getMockSuccessArchiveOrgUserNoBlurResult: () => Result<
350
+ SearchResponse,
351
+ SearchServiceError
352
+ > = () => ({
353
+ success: {
354
+ request: {
355
+ kind: 'hits',
356
+ clientParameters: {
357
+ user_query: 'archive-org-user-loggedin-noblur',
358
+ sort: [],
359
+ },
360
+ backendRequests: {
361
+ primary: {
362
+ kind: 'hits',
363
+ finalized_parameters: {
364
+ user_query: 'archive-org-user-loggedin-noblur',
365
+ sort: [],
366
+ },
367
+ },
368
+ },
369
+ },
370
+ rawResponse: {},
371
+ sessionContext: {
372
+ is_archive_user: true,
373
+ pps_relevant_user_preferences: {
374
+ display__blur_moderated_content: 'off',
375
+ },
376
+ },
377
+ response: {
378
+ totalResults: 1,
379
+ returnedCount: 1,
380
+ results: [
381
+ new ItemHit({
382
+ fields: {
383
+ identifier: 'foo',
384
+ collection: ['loggedin'],
385
+ title: 'foo',
386
+ mediatype: 'texts',
387
+ },
388
+ }),
389
+ ],
390
+ },
391
+ responseHeader: {
392
+ succeeded: true,
393
+ query_time: 0,
394
+ },
395
+ },
396
+ });
397
+
294
398
  export const getMockSuccessLoggedInResult: () => Result<
295
399
  SearchResponse,
296
400
  SearchServiceError
@@ -34,6 +34,8 @@ import {
34
34
  getMockSuccessWithWebArchiveHits,
35
35
  getMockSuccessWithManyAggregations,
36
36
  getMockSuccessTvFields,
37
+ getMockSuccessArchiveOrgUserResult,
38
+ getMockSuccessArchiveOrgUserNoBlurResult,
37
39
  } from './mock-search-responses';
38
40
 
39
41
  const responses: Record<
@@ -47,6 +49,8 @@ const responses: Record<
47
49
  loggedin: getMockSuccessLoggedInResult,
48
50
  'no-preview': getMockSuccessNoPreviewResult,
49
51
  'loggedin-no-preview': getMockSuccessLoggedInAndNoPreviewResult,
52
+ 'archive-org-user-loggedin': getMockSuccessArchiveOrgUserResult,
53
+ 'archive-org-user-loggedin-noblur': getMockSuccessArchiveOrgUserNoBlurResult,
50
54
  'first-title': getMockSuccessFirstTitleResult,
51
55
  'first-creator': getMockSuccessFirstCreatorResult,
52
56
  'collection-titles': getMockSuccessWithCollectionTitles,
@@ -120,4 +124,11 @@ export class MockSearchService implements SearchServiceInterface {
120
124
 
121
125
  return result;
122
126
  }
127
+
128
+ async itemDetails(
129
+ _: string,
130
+ ): Promise<Result<SearchResponse, SearchServiceError>> {
131
+ // We don't currently use the itemDetails method in collection-browser
132
+ throw new Error('not implemented');
133
+ }
123
134
  }
@@ -54,6 +54,7 @@ class HostElement extends LitElement implements HoverPaneProviderInterface {
54
54
  return {
55
55
  model: tileModel,
56
56
  loggedIn: false,
57
+ suppressBlurring: false,
57
58
  sortParam: null,
58
59
  };
59
60
  }