@internetarchive/collection-browser 0.2.22 → 0.3.0-alpha.2

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 (220) hide show
  1. package/.editorconfig +29 -29
  2. package/.github/workflows/ci.yml +26 -26
  3. package/.github/workflows/gh-pages-main.yml +39 -39
  4. package/.github/workflows/npm-publish.yml +39 -39
  5. package/.github/workflows/pr-preview.yml +38 -38
  6. package/.husky/pre-commit +4 -4
  7. package/LICENSE +661 -661
  8. package/README.md +83 -83
  9. package/dist/index.d.ts +9 -9
  10. package/dist/index.js +9 -9
  11. package/dist/src/app-root.d.ts +42 -39
  12. package/dist/src/app-root.js +236 -203
  13. package/dist/src/app-root.js.map +1 -1
  14. package/dist/src/assets/img/icons/arrow-left.d.ts +2 -2
  15. package/dist/src/assets/img/icons/arrow-left.js +2 -2
  16. package/dist/src/assets/img/icons/arrow-right.d.ts +2 -2
  17. package/dist/src/assets/img/icons/arrow-right.js +2 -2
  18. package/dist/src/assets/img/icons/chevron.d.ts +2 -2
  19. package/dist/src/assets/img/icons/chevron.js +2 -2
  20. package/dist/src/assets/img/icons/empty-query.d.ts +2 -2
  21. package/dist/src/assets/img/icons/empty-query.js +2 -2
  22. package/dist/src/assets/img/icons/eye-closed.d.ts +2 -2
  23. package/dist/src/assets/img/icons/eye-closed.js +2 -2
  24. package/dist/src/assets/img/icons/eye.d.ts +2 -2
  25. package/dist/src/assets/img/icons/eye.js +2 -2
  26. package/dist/src/assets/img/icons/favorite-filled.d.ts +1 -1
  27. package/dist/src/assets/img/icons/favorite-filled.js +2 -2
  28. package/dist/src/assets/img/icons/login-required.d.ts +1 -1
  29. package/dist/src/assets/img/icons/login-required.js +2 -2
  30. package/dist/src/assets/img/icons/mediatype/account.d.ts +1 -1
  31. package/dist/src/assets/img/icons/mediatype/account.js +2 -2
  32. package/dist/src/assets/img/icons/mediatype/audio.d.ts +1 -1
  33. package/dist/src/assets/img/icons/mediatype/audio.js +2 -2
  34. package/dist/src/assets/img/icons/mediatype/collection.d.ts +1 -1
  35. package/dist/src/assets/img/icons/mediatype/collection.js +2 -2
  36. package/dist/src/assets/img/icons/mediatype/data.d.ts +1 -1
  37. package/dist/src/assets/img/icons/mediatype/data.js +2 -2
  38. package/dist/src/assets/img/icons/mediatype/etree.d.ts +1 -1
  39. package/dist/src/assets/img/icons/mediatype/etree.js +2 -2
  40. package/dist/src/assets/img/icons/mediatype/film.d.ts +1 -1
  41. package/dist/src/assets/img/icons/mediatype/film.js +2 -2
  42. package/dist/src/assets/img/icons/mediatype/images.d.ts +1 -1
  43. package/dist/src/assets/img/icons/mediatype/images.js +2 -2
  44. package/dist/src/assets/img/icons/mediatype/radio.d.ts +1 -1
  45. package/dist/src/assets/img/icons/mediatype/radio.js +2 -2
  46. package/dist/src/assets/img/icons/mediatype/software.d.ts +1 -1
  47. package/dist/src/assets/img/icons/mediatype/software.js +2 -2
  48. package/dist/src/assets/img/icons/mediatype/texts.d.ts +1 -1
  49. package/dist/src/assets/img/icons/mediatype/texts.js +2 -2
  50. package/dist/src/assets/img/icons/mediatype/tv.d.ts +1 -1
  51. package/dist/src/assets/img/icons/mediatype/tv.js +2 -2
  52. package/dist/src/assets/img/icons/mediatype/video.d.ts +1 -1
  53. package/dist/src/assets/img/icons/mediatype/video.js +2 -2
  54. package/dist/src/assets/img/icons/mediatype/web.d.ts +1 -1
  55. package/dist/src/assets/img/icons/mediatype/web.js +2 -2
  56. package/dist/src/assets/img/icons/null-result.d.ts +2 -2
  57. package/dist/src/assets/img/icons/null-result.js +2 -2
  58. package/dist/src/assets/img/icons/restricted.d.ts +1 -1
  59. package/dist/src/assets/img/icons/restricted.js +2 -2
  60. package/dist/src/assets/img/icons/reviews.d.ts +1 -1
  61. package/dist/src/assets/img/icons/reviews.js +2 -2
  62. package/dist/src/assets/img/icons/upload.d.ts +1 -1
  63. package/dist/src/assets/img/icons/upload.js +2 -2
  64. package/dist/src/assets/img/icons/views.d.ts +1 -1
  65. package/dist/src/assets/img/icons/views.js +2 -2
  66. package/dist/src/circular-activity-indicator.d.ts +5 -5
  67. package/dist/src/circular-activity-indicator.js +17 -17
  68. package/dist/src/collection-browser.d.ts +235 -233
  69. package/dist/src/collection-browser.js +1032 -1046
  70. package/dist/src/collection-browser.js.map +1 -1
  71. package/dist/src/collection-facets/facets-template.d.ts +16 -16
  72. package/dist/src/collection-facets/facets-template.js +125 -125
  73. package/dist/src/collection-facets/facets-util.d.ts +10 -10
  74. package/dist/src/collection-facets/facets-util.js +19 -19
  75. package/dist/src/collection-facets/more-facets-content.d.ts +84 -83
  76. package/dist/src/collection-facets/more-facets-content.js +353 -351
  77. package/dist/src/collection-facets/more-facets-content.js.map +1 -1
  78. package/dist/src/collection-facets/more-facets-pagination.d.ts +36 -36
  79. package/dist/src/collection-facets/more-facets-pagination.js +192 -192
  80. package/dist/src/collection-facets.d.ts +71 -79
  81. package/dist/src/collection-facets.js +325 -338
  82. package/dist/src/collection-facets.js.map +1 -1
  83. package/dist/src/empty-placeholder.d.ts +11 -11
  84. package/dist/src/empty-placeholder.js +42 -42
  85. package/dist/src/language-code-handler/language-code-handler.d.ts +37 -37
  86. package/dist/src/language-code-handler/language-code-handler.js +26 -26
  87. package/dist/src/language-code-handler/language-code-mapping.d.ts +1 -1
  88. package/dist/src/language-code-handler/language-code-mapping.js +562 -562
  89. package/dist/src/mediatype/mediatype-config.d.ts +3 -3
  90. package/dist/src/mediatype/mediatype-config.js +85 -85
  91. package/dist/src/models.d.ts +90 -89
  92. package/dist/src/models.js +85 -85
  93. package/dist/src/models.js.map +1 -1
  94. package/dist/src/restoration-state-handler.d.ts +38 -38
  95. package/dist/src/restoration-state-handler.js +202 -202
  96. package/dist/src/sort-filter-bar/alpha-bar.d.ts +9 -9
  97. package/dist/src/sort-filter-bar/alpha-bar.js +41 -41
  98. package/dist/src/sort-filter-bar/img/compact.d.ts +1 -1
  99. package/dist/src/sort-filter-bar/img/compact.js +2 -2
  100. package/dist/src/sort-filter-bar/img/list.d.ts +1 -1
  101. package/dist/src/sort-filter-bar/img/list.js +2 -2
  102. package/dist/src/sort-filter-bar/img/sort-triangle.d.ts +1 -1
  103. package/dist/src/sort-filter-bar/img/sort-triangle.js +2 -2
  104. package/dist/src/sort-filter-bar/img/tile.d.ts +1 -1
  105. package/dist/src/sort-filter-bar/img/tile.js +2 -2
  106. package/dist/src/sort-filter-bar/sort-filter-bar.d.ts +107 -107
  107. package/dist/src/sort-filter-bar/sort-filter-bar.js +423 -423
  108. package/dist/src/styles/item-image-styles.d.ts +8 -8
  109. package/dist/src/styles/item-image-styles.js +9 -9
  110. package/dist/src/tiles/collection-browser-loading-tile.d.ts +5 -5
  111. package/dist/src/tiles/collection-browser-loading-tile.js +15 -15
  112. package/dist/src/tiles/grid/account-tile.d.ts +8 -8
  113. package/dist/src/tiles/grid/account-tile.js +20 -20
  114. package/dist/src/tiles/grid/collection-tile.d.ts +7 -7
  115. package/dist/src/tiles/grid/collection-tile.js +23 -23
  116. package/dist/src/tiles/grid/item-tile.d.ts +24 -24
  117. package/dist/src/tiles/grid/item-tile.js +87 -87
  118. package/dist/src/tiles/grid/tile-stats.d.ts +10 -10
  119. package/dist/src/tiles/grid/tile-stats.js +35 -35
  120. package/dist/src/tiles/image-block.d.ts +17 -17
  121. package/dist/src/tiles/image-block.js +73 -73
  122. package/dist/src/tiles/item-image.d.ts +31 -31
  123. package/dist/src/tiles/item-image.js +103 -103
  124. package/dist/src/tiles/list/account-label.d.ts +1 -1
  125. package/dist/src/tiles/list/account-label.js +6 -6
  126. package/dist/src/tiles/list/date-label.d.ts +1 -1
  127. package/dist/src/tiles/list/date-label.js +12 -12
  128. package/dist/src/tiles/list/tile-list-compact-header.d.ts +12 -12
  129. package/dist/src/tiles/list/tile-list-compact-header.js +41 -41
  130. package/dist/src/tiles/list/tile-list-compact.d.ts +20 -20
  131. package/dist/src/tiles/list/tile-list-compact.js +87 -87
  132. package/dist/src/tiles/list/tile-list.d.ts +50 -50
  133. package/dist/src/tiles/list/tile-list.js +263 -263
  134. package/dist/src/tiles/mediatype-icon.d.ts +9 -9
  135. package/dist/src/tiles/mediatype-icon.js +47 -47
  136. package/dist/src/tiles/overlay/icon-overlay.d.ts +7 -7
  137. package/dist/src/tiles/overlay/icon-overlay.js +31 -31
  138. package/dist/src/tiles/overlay/text-overlay.d.ts +8 -8
  139. package/dist/src/tiles/overlay/text-overlay.js +31 -31
  140. package/dist/src/tiles/text-snippet-block.d.ts +29 -29
  141. package/dist/src/tiles/text-snippet-block.js +81 -81
  142. package/dist/src/tiles/text-snippet-block.js.map +1 -1
  143. package/dist/src/tiles/tile-dispatcher.d.ts +36 -36
  144. package/dist/src/tiles/tile-dispatcher.js +128 -128
  145. package/dist/src/utils/analytics-events.d.ts +18 -18
  146. package/dist/src/utils/analytics-events.js +20 -20
  147. package/dist/src/utils/format-count.d.ts +7 -7
  148. package/dist/src/utils/format-count.js +75 -75
  149. package/dist/src/utils/format-date.d.ts +2 -2
  150. package/dist/src/utils/format-date.js +23 -23
  151. package/dist/test/collection-browser.test.d.ts +1 -1
  152. package/dist/test/collection-browser.test.js +328 -200
  153. package/dist/test/collection-browser.test.js.map +1 -1
  154. package/dist/test/collection-facets/facets-template.test.d.ts +1 -1
  155. package/dist/test/collection-facets/facets-template.test.js +62 -62
  156. package/dist/test/collection-facets/facets-util.test.d.ts +1 -1
  157. package/dist/test/collection-facets/facets-util.test.js +12 -12
  158. package/dist/test/collection-facets/more-facets-content.test.d.ts +1 -1
  159. package/dist/test/collection-facets/more-facets-content.test.js +92 -91
  160. package/dist/test/collection-facets/more-facets-content.test.js.map +1 -1
  161. package/dist/test/collection-facets/more-facets-pagination.test.d.ts +1 -1
  162. package/dist/test/collection-facets/more-facets-pagination.test.js +117 -117
  163. package/dist/test/collection-facets.test.d.ts +2 -2
  164. package/dist/test/collection-facets.test.js +182 -181
  165. package/dist/test/collection-facets.test.js.map +1 -1
  166. package/dist/test/empty-placeholder.test.d.ts +1 -1
  167. package/dist/test/empty-placeholder.test.js +33 -33
  168. package/dist/test/icon-overlay.test.d.ts +1 -1
  169. package/dist/test/icon-overlay.test.js +24 -24
  170. package/dist/test/item-image.test.d.ts +1 -1
  171. package/dist/test/item-image.test.js +56 -56
  172. package/dist/test/mediatype-config.test.d.ts +1 -1
  173. package/dist/test/mediatype-config.test.js +16 -16
  174. package/dist/test/mocks/mock-analytics-handler.d.ts +10 -10
  175. package/dist/test/mocks/mock-analytics-handler.js +15 -15
  176. package/dist/test/mocks/mock-collection-name-cache.d.ts +7 -7
  177. package/dist/test/mocks/mock-collection-name-cache.js +13 -13
  178. package/dist/test/mocks/mock-search-responses.d.ts +5 -4
  179. package/dist/test/mocks/mock-search-responses.js +103 -57
  180. package/dist/test/mocks/mock-search-responses.js.map +1 -1
  181. package/dist/test/mocks/mock-search-service.d.ts +13 -8
  182. package/dist/test/mocks/mock-search-service.js +25 -19
  183. package/dist/test/mocks/mock-search-service.js.map +1 -1
  184. package/dist/test/sort-filter-bar/sort-filter-bar.test.d.ts +1 -1
  185. package/dist/test/sort-filter-bar/sort-filter-bar.test.js +113 -113
  186. package/dist/test/text-overlay.test.d.ts +1 -1
  187. package/dist/test/text-overlay.test.js +41 -41
  188. package/dist/test/text-snippet-block.test.d.ts +1 -1
  189. package/dist/test/text-snippet-block.test.js +57 -45
  190. package/dist/test/text-snippet-block.test.js.map +1 -1
  191. package/dist/test/tile-stats.test.d.ts +1 -1
  192. package/dist/test/tile-stats.test.js +33 -33
  193. package/dist/test/tiles/grid/item-tile.test.d.ts +1 -1
  194. package/dist/test/tiles/grid/item-tile.test.js +107 -107
  195. package/dist/test/tiles/list/tile-list.test.d.ts +1 -1
  196. package/dist/test/tiles/list/tile-list.test.js +36 -36
  197. package/dist/test/utils/format-count.test.d.ts +1 -1
  198. package/dist/test/utils/format-count.test.js +23 -23
  199. package/dist/test/utils/format-date.test.d.ts +1 -1
  200. package/dist/test/utils/format-date.test.js +17 -17
  201. package/index.html +24 -24
  202. package/local.archive.org.cert +86 -86
  203. package/local.archive.org.key +27 -27
  204. package/package.json +115 -115
  205. package/renovate.json +6 -6
  206. package/src/app-root.ts +49 -11
  207. package/src/collection-browser.ts +76 -86
  208. package/src/collection-facets/more-facets-content.ts +35 -27
  209. package/src/collection-facets.ts +9 -26
  210. package/src/models.ts +2 -0
  211. package/src/tiles/text-snippet-block.ts +1 -1
  212. package/test/collection-browser.test.ts +192 -0
  213. package/test/collection-facets/more-facets-content.test.ts +5 -5
  214. package/test/collection-facets.test.ts +16 -15
  215. package/test/mocks/mock-search-responses.ts +83 -34
  216. package/test/mocks/mock-search-service.ts +27 -17
  217. package/test/text-snippet-block.test.ts +17 -0
  218. package/tsconfig.json +21 -21
  219. package/web-dev-server.config.mjs +30 -30
  220. package/web-test-runner.config.mjs +41 -41
@@ -1,178 +1,180 @@
1
- import { __decorate } from "tslib";
2
- /* eslint-disable import/no-duplicates */
3
- import { html, css, LitElement, nothing, } from 'lit';
4
- import { customElement, property, query, state } from 'lit/decorators.js';
5
- import { ifDefined } from 'lit/directives/if-defined.js';
6
- import '@internetarchive/infinite-scroller';
7
- import './tiles/tile-dispatcher';
8
- import './tiles/collection-browser-loading-tile';
9
- import './sort-filter-bar/sort-filter-bar';
10
- import './collection-facets';
11
- import './circular-activity-indicator';
12
- import './sort-filter-bar/sort-filter-bar';
13
- import { SortField, SortFieldToMetadataField, defaultSelectedFacets, } from './models';
14
- import { RestorationStateHandler, } from './restoration-state-handler';
15
- import chevronIcon from './assets/img/icons/chevron';
16
- import { LanguageCodeHandler } from './language-code-handler/language-code-handler';
17
- import './empty-placeholder';
18
- import { analyticsActions, analyticsCategories, } from './utils/analytics-events';
19
- let CollectionBrowser = class CollectionBrowser extends LitElement {
20
- constructor() {
21
- super(...arguments);
22
- this.baseImageUrl = 'https://archive.org';
23
- this.sortParam = null;
24
- this.selectedSort = SortField.relevance;
25
- this.selectedTitleFilter = null;
26
- this.selectedCreatorFilter = null;
27
- this.sortDirection = null;
28
- this.pageSize = 50;
29
- this.showHistogramDatePicker = false;
30
- /** describes where this component is being used */
31
- this.searchContext = analyticsCategories.default;
32
- this.pageContext = 'search';
33
- this.restorationStateHandler = new RestorationStateHandler({
34
- context: this.pageContext,
35
- });
36
- this.mobileBreakpoint = 600;
37
- this.loggedIn = false;
38
- this.modalManager = undefined;
39
- /**
40
- * If item management UI active
41
- */
42
- this.isManageView = false;
43
- /**
44
- * The page that the consumer wants to load.
45
- */
46
- this.initialPageNumber = 1;
47
- /**
48
- * This the the number of pages that we want to show.
49
- *
50
- * The data isn't necessarily loaded for all of the pages, but this lets us
51
- * know how many cells we should render.
52
- */
53
- this.pagesToRender = this.initialPageNumber;
54
- this.searchResultsLoading = false;
55
- this.facetsLoading = false;
56
- this.fullYearAggregationLoading = false;
57
- this.mobileView = false;
58
- this.mobileFacetsVisible = false;
59
- this.placeholderType = null;
60
- this.languageCodeHandler = new LanguageCodeHandler();
61
- /**
62
- * When we're animated scrolling to the page, we don't want to fetch
63
- * all of the pages as it scrolls so this lets us know if we're scrolling
64
- */
65
- this.isScrollingToCell = false;
66
- /**
67
- * When we've reached the end of the data, stop trying to fetch more
68
- */
69
- this.endOfDataReached = false;
70
- /**
71
- * When page width resizes from desktop to mobile, set true to
72
- * disable expand/collapse transition when loading.
73
- */
74
- this.isResizeToMobile = false;
75
- this.placeholderCellTemplate = html `<collection-browser-loading-tile></collection-browser-loading-tile>`;
76
- /**
77
- * The results per page so we can paginate.
78
- *
79
- * This allows us to start in the middle of the search results and
80
- * fetch data before or after the current page. If we don't have a key
81
- * for the previous/next page, we'll fetch the next/previous page to populate it
82
- */
83
- this.dataSource = {};
84
- // we only want to scroll on the very first query change
85
- // so this keeps track of whether we've already set the initial query
86
- this.initialQueryChangeHappened = false;
87
- this.historyPopOccurred = false;
88
- // this maps the query to the pages being fetched for that query
89
- this.pageFetchesInProgress = {};
90
- }
91
- tileModelAtCellIndex(index) {
92
- var _a;
93
- const pageNumber = Math.floor(index / this.pageSize) + 1;
94
- const itemIndex = index % this.pageSize;
95
- const model = (_a = this.dataSource[pageNumber]) === null || _a === void 0 ? void 0 : _a[itemIndex];
96
- /**
97
- * If we encounter a model we don't have yet and we're not in the middle of an
98
- * automated scroll, fetch the page and just return undefined.
99
- * The datasource will be updated once the page is loaded and the cell will be rendered.
100
- *
101
- * We disable it during the automated scroll since we may fetch pages for cells the
102
- * user may never see.
103
- */
104
- if (!model && !this.isScrollingToCell) {
105
- this.fetchPage(pageNumber);
106
- }
107
- return model;
108
- }
109
- get sortFilterQueries() {
110
- const queries = [this.titleQuery, this.creatorQuery];
111
- return queries.filter(q => q).join(' AND ');
112
- }
113
- // this is the total number of tiles we expect if
114
- // the data returned is a full page worth
115
- // this is useful for putting in placeholders for the expected number of tiles
116
- get estimatedTileCount() {
117
- return this.pagesToRender * this.pageSize;
118
- }
119
- // this is the actual number of tiles in the datasource,
120
- // which is useful for removing excess placeholder tiles
121
- // once we reached the end of the data
122
- get actualTileCount() {
123
- return Object.keys(this.dataSource).reduce((acc, page) => acc + this.dataSource[page].length, 0);
124
- }
125
- /**
126
- * Go to the given page of results
127
- *
128
- * @param pageNumber
129
- */
130
- goToPage(pageNumber) {
131
- this.initialPageNumber = pageNumber;
132
- this.pagesToRender = pageNumber;
133
- this.scrollToPage(pageNumber);
134
- }
135
- clearFilters() {
136
- this.selectedFacets = defaultSelectedFacets;
137
- this.sortParam = null;
138
- this.selectedTitleFilter = null;
139
- this.selectedCreatorFilter = null;
140
- this.titleQuery = undefined;
141
- this.creatorQuery = undefined;
142
- this.selectedSort = SortField.relevance;
143
- this.sortDirection = null;
144
- }
145
- render() {
146
- this.setPlaceholderType();
1
+ import { __decorate } from "tslib";
2
+ /* eslint-disable import/no-duplicates */
3
+ import { html, css, LitElement, nothing, } from 'lit';
4
+ import { customElement, property, query, state } from 'lit/decorators.js';
5
+ import { ifDefined } from 'lit/directives/if-defined.js';
6
+ import { SearchType, } from '@internetarchive/search-service';
7
+ import '@internetarchive/infinite-scroller';
8
+ import './tiles/tile-dispatcher';
9
+ import './tiles/collection-browser-loading-tile';
10
+ import './sort-filter-bar/sort-filter-bar';
11
+ import './collection-facets';
12
+ import './circular-activity-indicator';
13
+ import './sort-filter-bar/sort-filter-bar';
14
+ import { SortField, SortFieldToMetadataField, defaultSelectedFacets, } from './models';
15
+ import { RestorationStateHandler, } from './restoration-state-handler';
16
+ import chevronIcon from './assets/img/icons/chevron';
17
+ import { LanguageCodeHandler } from './language-code-handler/language-code-handler';
18
+ import './empty-placeholder';
19
+ import { analyticsActions, analyticsCategories, } from './utils/analytics-events';
20
+ let CollectionBrowser = class CollectionBrowser extends LitElement {
21
+ constructor() {
22
+ super(...arguments);
23
+ this.baseImageUrl = 'https://archive.org';
24
+ this.searchTarget = 'metadata';
25
+ this.sortParam = null;
26
+ this.selectedSort = SortField.relevance;
27
+ this.selectedTitleFilter = null;
28
+ this.selectedCreatorFilter = null;
29
+ this.sortDirection = null;
30
+ this.pageSize = 50;
31
+ this.showHistogramDatePicker = false;
32
+ /** describes where this component is being used */
33
+ this.searchContext = analyticsCategories.default;
34
+ this.pageContext = 'search';
35
+ this.restorationStateHandler = new RestorationStateHandler({
36
+ context: this.pageContext,
37
+ });
38
+ this.mobileBreakpoint = 600;
39
+ this.loggedIn = false;
40
+ this.modalManager = undefined;
41
+ /**
42
+ * If item management UI active
43
+ */
44
+ this.isManageView = false;
45
+ /**
46
+ * The page that the consumer wants to load.
47
+ */
48
+ this.initialPageNumber = 1;
49
+ /**
50
+ * This the the number of pages that we want to show.
51
+ *
52
+ * The data isn't necessarily loaded for all of the pages, but this lets us
53
+ * know how many cells we should render.
54
+ */
55
+ this.pagesToRender = this.initialPageNumber;
56
+ this.searchResultsLoading = false;
57
+ this.facetsLoading = false;
58
+ this.fullYearAggregationLoading = false;
59
+ this.mobileView = false;
60
+ this.mobileFacetsVisible = false;
61
+ this.placeholderType = null;
62
+ this.languageCodeHandler = new LanguageCodeHandler();
63
+ /**
64
+ * When we're animated scrolling to the page, we don't want to fetch
65
+ * all of the pages as it scrolls so this lets us know if we're scrolling
66
+ */
67
+ this.isScrollingToCell = false;
68
+ /**
69
+ * When we've reached the end of the data, stop trying to fetch more
70
+ */
71
+ this.endOfDataReached = false;
72
+ /**
73
+ * When page width resizes from desktop to mobile, set true to
74
+ * disable expand/collapse transition when loading.
75
+ */
76
+ this.isResizeToMobile = false;
77
+ this.placeholderCellTemplate = html `<collection-browser-loading-tile></collection-browser-loading-tile>`;
78
+ /**
79
+ * The results per page so we can paginate.
80
+ *
81
+ * This allows us to start in the middle of the search results and
82
+ * fetch data before or after the current page. If we don't have a key
83
+ * for the previous/next page, we'll fetch the next/previous page to populate it
84
+ */
85
+ this.dataSource = {};
86
+ // we only want to scroll on the very first query change
87
+ // so this keeps track of whether we've already set the initial query
88
+ this.initialQueryChangeHappened = false;
89
+ this.historyPopOccurred = false;
90
+ // this maps the query to the pages being fetched for that query
91
+ this.pageFetchesInProgress = {};
92
+ }
93
+ tileModelAtCellIndex(index) {
94
+ var _a;
95
+ const pageNumber = Math.floor(index / this.pageSize) + 1;
96
+ const itemIndex = index % this.pageSize;
97
+ const model = (_a = this.dataSource[pageNumber]) === null || _a === void 0 ? void 0 : _a[itemIndex];
98
+ /**
99
+ * If we encounter a model we don't have yet and we're not in the middle of an
100
+ * automated scroll, fetch the page and just return undefined.
101
+ * The datasource will be updated once the page is loaded and the cell will be rendered.
102
+ *
103
+ * We disable it during the automated scroll since we may fetch pages for cells the
104
+ * user may never see.
105
+ */
106
+ if (!model && !this.isScrollingToCell) {
107
+ this.fetchPage(pageNumber);
108
+ }
109
+ return model;
110
+ }
111
+ get sortFilterQueries() {
112
+ const queries = [this.titleQuery, this.creatorQuery];
113
+ return queries.filter(q => q).join(' AND ');
114
+ }
115
+ // this is the total number of tiles we expect if
116
+ // the data returned is a full page worth
117
+ // this is useful for putting in placeholders for the expected number of tiles
118
+ get estimatedTileCount() {
119
+ return this.pagesToRender * this.pageSize;
120
+ }
121
+ // this is the actual number of tiles in the datasource,
122
+ // which is useful for removing excess placeholder tiles
123
+ // once we reached the end of the data
124
+ get actualTileCount() {
125
+ return Object.keys(this.dataSource).reduce((acc, page) => acc + this.dataSource[page].length, 0);
126
+ }
127
+ /**
128
+ * Go to the given page of results
129
+ *
130
+ * @param pageNumber
131
+ */
132
+ goToPage(pageNumber) {
133
+ this.initialPageNumber = pageNumber;
134
+ this.pagesToRender = pageNumber;
135
+ this.scrollToPage(pageNumber);
136
+ }
137
+ clearFilters() {
138
+ this.selectedFacets = defaultSelectedFacets;
139
+ this.sortParam = null;
140
+ this.selectedTitleFilter = null;
141
+ this.selectedCreatorFilter = null;
142
+ this.titleQuery = undefined;
143
+ this.creatorQuery = undefined;
144
+ this.selectedSort = SortField.relevance;
145
+ this.sortDirection = null;
146
+ }
147
+ render() {
148
+ this.setPlaceholderType();
147
149
  return html `
148
150
  <div
149
151
  id="content-container"
150
152
  class=${this.mobileView ? 'mobile' : 'desktop'}
151
153
  >
152
- ${this.placeholderType
153
- ? this.emptyPlaceholderTemplate
154
+ ${this.placeholderType
155
+ ? this.emptyPlaceholderTemplate
154
156
  : this.collectionBrowserTemplate}
155
157
  </div>
156
- `;
157
- }
158
- setPlaceholderType() {
159
- this.placeholderType = null;
160
- if (!this.baseQuery) {
161
- this.placeholderType = 'empty-query';
162
- }
163
- if (!this.searchResultsLoading && this.totalResults === 0) {
164
- this.placeholderType = 'null-result';
165
- }
166
- }
167
- get emptyPlaceholderTemplate() {
158
+ `;
159
+ }
160
+ setPlaceholderType() {
161
+ this.placeholderType = null;
162
+ if (!this.baseQuery) {
163
+ this.placeholderType = 'empty-query';
164
+ }
165
+ if (!this.searchResultsLoading && this.totalResults === 0) {
166
+ this.placeholderType = 'null-result';
167
+ }
168
+ }
169
+ get emptyPlaceholderTemplate() {
168
170
  return html `
169
171
  <empty-placeholder
170
172
  .placeholderType=${this.placeholderType}
171
173
  ?isMobileView=${this.mobileView}
172
174
  ></empty-placeholder>
173
- `;
174
- }
175
- get collectionBrowserTemplate() {
175
+ `;
176
+ }
177
+ get collectionBrowserTemplate() {
176
178
  return html `<div
177
179
  id="left-column"
178
180
  class="column${this.isResizeToMobile ? ' preload' : ''}"
@@ -181,8 +183,8 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
181
183
  ${this.mobileView ? this.mobileFacetsTemplate : nothing}
182
184
  <div id="results-total">
183
185
  <span id="big-results-count">
184
- ${this.totalResults !== undefined
185
- ? this.totalResults.toLocaleString()
186
+ ${this.totalResults !== undefined
187
+ ? this.totalResults.toLocaleString()
186
188
  : '-'}
187
189
  </span>
188
190
  <span id="big-results-label">
@@ -192,8 +194,8 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
192
194
  </div>
193
195
  <div
194
196
  id="facets-container"
195
- class=${!this.mobileView || this.mobileFacetsVisible
196
- ? 'expanded'
197
+ class=${!this.mobileView || this.mobileFacetsVisible
198
+ ? 'expanded'
197
199
  : ''}
198
200
  >
199
201
  ${this.facetsTemplate}
@@ -202,22 +204,22 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
202
204
  <div id="right-column" class="column">
203
205
  ${this.searchResultsLoading ? this.loadingTemplate : nothing}
204
206
  ${this.sortFilterBarTemplate}
205
- ${this.displayMode === `list-compact`
206
- ? this.listHeaderTemplate
207
+ ${this.displayMode === `list-compact`
208
+ ? this.listHeaderTemplate
207
209
  : nothing}
208
210
  ${this.infiniteScrollerTemplate}
209
- </div>`;
210
- }
211
- get infiniteScrollerTemplate() {
211
+ </div>`;
212
+ }
213
+ get infiniteScrollerTemplate() {
212
214
  return html `<infinite-scroller
213
215
  class="${ifDefined(this.displayMode)}"
214
216
  .cellProvider=${this}
215
217
  .placeholderCellTemplate=${this.placeholderCellTemplate}
216
218
  @scrollThresholdReached=${this.scrollThresholdReached}
217
219
  @visibleCellsChanged=${this.visibleCellsChanged}
218
- ></infinite-scroller>`;
219
- }
220
- get sortFilterBarTemplate() {
220
+ ></infinite-scroller>`;
221
+ }
222
+ get sortFilterBarTemplate() {
221
223
  return html `
222
224
  <sort-filter-bar
223
225
  .selectedSort=${this.selectedSort}
@@ -232,114 +234,114 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
232
234
  @creatorLetterChanged=${this.creatorLetterSelected}
233
235
  >
234
236
  </sort-filter-bar>
235
- `;
236
- }
237
- userChangedSort(e) {
238
- var _a;
239
- const { selectedSort, sortDirection } = e.detail;
240
- this.selectedSort = selectedSort;
241
- this.sortDirection = sortDirection;
242
- if (((_a = this.currentPage) !== null && _a !== void 0 ? _a : 1) > 1) {
243
- this.goToPage(1);
244
- }
245
- this.currentPage = 1;
246
- }
247
- sendSortByAnalytics(prevSortDirection) {
248
- var _a;
249
- const directionCleared = prevSortDirection && !this.sortDirection;
250
- (_a = this.analyticsHandler) === null || _a === void 0 ? void 0 : _a.sendEventNoSampling({
251
- category: this.searchContext,
252
- action: analyticsActions.sortBy,
253
- label: `${this.selectedSort}${this.sortDirection || directionCleared ? `-${this.sortDirection}` : ''}`,
254
- });
255
- }
256
- selectedSortChanged() {
257
- if (this.selectedSort === 'relevance' || this.sortDirection === null) {
258
- this.sortParam = null;
259
- return;
260
- }
261
- const sortField = SortFieldToMetadataField[this.selectedSort];
262
- if (!sortField)
263
- return;
264
- this.sortParam = { field: sortField, direction: this.sortDirection };
265
- }
266
- displayModeChanged(e) {
267
- var _a;
268
- this.displayMode = e.detail.displayMode;
269
- if (this.displayMode) {
270
- (_a = this.analyticsHandler) === null || _a === void 0 ? void 0 : _a.sendEventNoSampling({
271
- category: this.searchContext,
272
- action: analyticsActions.displayMode,
273
- label: this.displayMode,
274
- });
275
- }
276
- }
277
- /** Send Analytics when sorting by title's first letter
278
- * labels: 'start-<ToLetter>' | 'clear-<FromLetter>' | '<FromLetter>-<ToLetter>'
279
- * */
280
- sendFilterByTitleAnalytics(prevSelectedLetter) {
281
- var _a;
282
- if (!prevSelectedLetter && !this.selectedTitleFilter) {
283
- return;
284
- }
285
- const cleared = prevSelectedLetter && this.selectedTitleFilter === null;
286
- (_a = this.analyticsHandler) === null || _a === void 0 ? void 0 : _a.sendEventNoSampling({
287
- category: this.searchContext,
288
- action: analyticsActions.filterByTitle,
289
- label: cleared
290
- ? `clear-${prevSelectedLetter}`
291
- : `${prevSelectedLetter || 'start'}-${this.selectedTitleFilter}`,
292
- });
293
- }
294
- selectedTitleLetterChanged() {
295
- this.titleQuery = this.selectedTitleFilter
296
- ? `firstTitle:${this.selectedTitleFilter}`
297
- : undefined;
298
- }
299
- /** Send Analytics when filtering by creator's first letter
300
- * labels: 'start-<ToLetter>' | 'clear-<FromLetter>' | '<FromLetter>-<ToLetter>'
301
- * */
302
- sendFilterByCreatorAnalytics(prevSelectedLetter) {
303
- var _a;
304
- if (!prevSelectedLetter && !this.selectedCreatorFilter) {
305
- return;
306
- }
307
- const cleared = prevSelectedLetter && this.selectedCreatorFilter === null;
308
- (_a = this.analyticsHandler) === null || _a === void 0 ? void 0 : _a.sendEventNoSampling({
309
- category: this.searchContext,
310
- action: analyticsActions.filterByCreator,
311
- label: cleared
312
- ? `clear-${prevSelectedLetter}`
313
- : `${prevSelectedLetter || 'start'}-${this.selectedCreatorFilter}`,
314
- });
315
- }
316
- selectedCreatorLetterChanged() {
317
- this.creatorQuery = this.selectedCreatorFilter
318
- ? `firstCreator:${this.selectedCreatorFilter}`
319
- : undefined;
320
- }
321
- titleLetterSelected(e) {
322
- this.selectedCreatorFilter = null;
323
- this.selectedTitleFilter = e.detail.selectedLetter;
324
- }
325
- creatorLetterSelected(e) {
326
- this.selectedTitleFilter = null;
327
- this.selectedCreatorFilter = e.detail.selectedLetter;
328
- }
329
- get facetDataLoading() {
330
- return this.facetsLoading || this.fullYearAggregationLoading;
331
- }
332
- get mobileFacetsTemplate() {
237
+ `;
238
+ }
239
+ userChangedSort(e) {
240
+ var _a;
241
+ const { selectedSort, sortDirection } = e.detail;
242
+ this.selectedSort = selectedSort;
243
+ this.sortDirection = sortDirection;
244
+ if (((_a = this.currentPage) !== null && _a !== void 0 ? _a : 1) > 1) {
245
+ this.goToPage(1);
246
+ }
247
+ this.currentPage = 1;
248
+ }
249
+ sendSortByAnalytics(prevSortDirection) {
250
+ var _a;
251
+ const directionCleared = prevSortDirection && !this.sortDirection;
252
+ (_a = this.analyticsHandler) === null || _a === void 0 ? void 0 : _a.sendEventNoSampling({
253
+ category: this.searchContext,
254
+ action: analyticsActions.sortBy,
255
+ label: `${this.selectedSort}${this.sortDirection || directionCleared ? `-${this.sortDirection}` : ''}`,
256
+ });
257
+ }
258
+ selectedSortChanged() {
259
+ if (this.selectedSort === 'relevance' || this.sortDirection === null) {
260
+ this.sortParam = null;
261
+ return;
262
+ }
263
+ const sortField = SortFieldToMetadataField[this.selectedSort];
264
+ if (!sortField)
265
+ return;
266
+ this.sortParam = { field: sortField, direction: this.sortDirection };
267
+ }
268
+ displayModeChanged(e) {
269
+ var _a;
270
+ this.displayMode = e.detail.displayMode;
271
+ if (this.displayMode) {
272
+ (_a = this.analyticsHandler) === null || _a === void 0 ? void 0 : _a.sendEventNoSampling({
273
+ category: this.searchContext,
274
+ action: analyticsActions.displayMode,
275
+ label: this.displayMode,
276
+ });
277
+ }
278
+ }
279
+ /** Send Analytics when sorting by title's first letter
280
+ * labels: 'start-<ToLetter>' | 'clear-<FromLetter>' | '<FromLetter>-<ToLetter>'
281
+ * */
282
+ sendFilterByTitleAnalytics(prevSelectedLetter) {
283
+ var _a;
284
+ if (!prevSelectedLetter && !this.selectedTitleFilter) {
285
+ return;
286
+ }
287
+ const cleared = prevSelectedLetter && this.selectedTitleFilter === null;
288
+ (_a = this.analyticsHandler) === null || _a === void 0 ? void 0 : _a.sendEventNoSampling({
289
+ category: this.searchContext,
290
+ action: analyticsActions.filterByTitle,
291
+ label: cleared
292
+ ? `clear-${prevSelectedLetter}`
293
+ : `${prevSelectedLetter || 'start'}-${this.selectedTitleFilter}`,
294
+ });
295
+ }
296
+ selectedTitleLetterChanged() {
297
+ this.titleQuery = this.selectedTitleFilter
298
+ ? `firstTitle:${this.selectedTitleFilter}`
299
+ : undefined;
300
+ }
301
+ /** Send Analytics when filtering by creator's first letter
302
+ * labels: 'start-<ToLetter>' | 'clear-<FromLetter>' | '<FromLetter>-<ToLetter>'
303
+ * */
304
+ sendFilterByCreatorAnalytics(prevSelectedLetter) {
305
+ var _a;
306
+ if (!prevSelectedLetter && !this.selectedCreatorFilter) {
307
+ return;
308
+ }
309
+ const cleared = prevSelectedLetter && this.selectedCreatorFilter === null;
310
+ (_a = this.analyticsHandler) === null || _a === void 0 ? void 0 : _a.sendEventNoSampling({
311
+ category: this.searchContext,
312
+ action: analyticsActions.filterByCreator,
313
+ label: cleared
314
+ ? `clear-${prevSelectedLetter}`
315
+ : `${prevSelectedLetter || 'start'}-${this.selectedCreatorFilter}`,
316
+ });
317
+ }
318
+ selectedCreatorLetterChanged() {
319
+ this.creatorQuery = this.selectedCreatorFilter
320
+ ? `firstCreator:${this.selectedCreatorFilter}`
321
+ : undefined;
322
+ }
323
+ titleLetterSelected(e) {
324
+ this.selectedCreatorFilter = null;
325
+ this.selectedTitleFilter = e.detail.selectedLetter;
326
+ }
327
+ creatorLetterSelected(e) {
328
+ this.selectedTitleFilter = null;
329
+ this.selectedCreatorFilter = e.detail.selectedLetter;
330
+ }
331
+ get facetDataLoading() {
332
+ return this.facetsLoading || this.fullYearAggregationLoading;
333
+ }
334
+ get mobileFacetsTemplate() {
333
335
  return html `
334
336
  <div id="mobile-filter-collapse">
335
337
  <h1
336
- @click=${() => {
337
- this.isResizeToMobile = false;
338
- this.mobileFacetsVisible = !this.mobileFacetsVisible;
338
+ @click=${() => {
339
+ this.isResizeToMobile = false;
340
+ this.mobileFacetsVisible = !this.mobileFacetsVisible;
339
341
  }}
340
- @keyup=${() => {
341
- this.isResizeToMobile = false;
342
- this.mobileFacetsVisible = !this.mobileFacetsVisible;
342
+ @keyup=${() => {
343
+ this.isResizeToMobile = false;
344
+ this.mobileFacetsVisible = !this.mobileFacetsVisible;
343
345
  }}
344
346
  >
345
347
  <span class="collapser ${this.mobileFacetsVisible ? 'open' : ''}">
@@ -348,15 +350,16 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
348
350
  Filters
349
351
  </h1>
350
352
  </div>
351
- `;
352
- }
353
- get facetsTemplate() {
353
+ `;
354
+ }
355
+ get facetsTemplate() {
354
356
  return html `
355
357
  ${this.facetsLoading ? this.loadingTemplate : nothing}
356
358
  <collection-facets
357
359
  @facetsChanged=${this.facetsChanged}
358
360
  @histogramDateRangeUpdated=${this.histogramDateRangeUpdated}
359
361
  .searchService=${this.searchService}
362
+ .searchTarget=${this.searchTarget}
360
363
  .aggregations=${this.aggregations}
361
364
  .fullYearsHistogramAggregation=${this.fullYearsHistogramAggregation}
362
365
  .minSelectedDate=${this.minSelectedDate}
@@ -374,16 +377,16 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
374
377
  .analyticsHandler=${this.analyticsHandler}
375
378
  >
376
379
  </collection-facets>
377
- `;
378
- }
379
- get loadingTemplate() {
380
+ `;
381
+ }
382
+ get loadingTemplate() {
380
383
  return html `
381
384
  <div class="loading-cover">
382
385
  <circular-activity-indicator></circular-activity-indicator>
383
386
  </div>
384
- `;
385
- }
386
- get listHeaderTemplate() {
387
+ `;
388
+ }
389
+ get listHeaderTemplate() {
387
390
  return html `
388
391
  <div id="list-header">
389
392
  <tile-dispatcher
@@ -395,10 +398,10 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
395
398
  >
396
399
  </tile-dispatcher>
397
400
  </div>
398
- `;
399
- }
400
- get queryDebuggingTemplate() {
401
- var _a, _b;
401
+ `;
402
+ }
403
+ get queryDebuggingTemplate() {
404
+ var _a, _b;
402
405
  return html `
403
406
  <div>
404
407
  <ul>
@@ -410,621 +413,601 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
410
413
  <li>Full Query: ${this.fullQuery}</li>
411
414
  </ul>
412
415
  </div>
413
- `;
414
- }
415
- histogramDateRangeUpdated(e) {
416
- var _a;
417
- const { minDate, maxDate } = e.detail;
418
- this.dateRangeQueryClause = `year:[${minDate} TO ${maxDate}]`;
419
- if (this.dateRangeQueryClause) {
420
- (_a = this.analyticsHandler) === null || _a === void 0 ? void 0 : _a.sendEventNoSampling({
421
- category: this.searchContext,
422
- action: analyticsActions.histogramChanged,
423
- label: this.dateRangeQueryClause,
424
- });
425
- }
426
- }
427
- firstUpdated() {
428
- this.setupStateRestorationObserver();
429
- this.restoreState();
430
- }
431
- updated(changed) {
432
- var _a;
433
- if (changed.has('displayMode') ||
434
- changed.has('baseNavigationUrl') ||
435
- changed.has('baseImageUrl') ||
436
- changed.has('loggedIn')) {
437
- (_a = this.infiniteScroller) === null || _a === void 0 ? void 0 : _a.reload();
438
- }
439
- if (changed.has('baseQuery')) {
440
- this.emitBaseQueryChanged();
441
- }
442
- if (changed.has('currentPage') || changed.has('displayMode')) {
443
- this.persistState();
444
- }
445
- if (changed.has('baseQuery') ||
446
- changed.has('titleQuery') ||
447
- changed.has('creatorQuery') ||
448
- changed.has('dateRangeQueryClause') ||
449
- changed.has('sortParam') ||
450
- changed.has('selectedFacets') ||
451
- changed.has('searchService')) {
452
- this.handleQueryChange();
453
- }
454
- if (changed.has('selectedSort') || changed.has('sortDirection')) {
455
- const prevSortDirection = changed.get('sortDirection');
456
- this.sendSortByAnalytics(prevSortDirection);
457
- this.selectedSortChanged();
458
- }
459
- if (changed.has('selectedTitleFilter')) {
460
- this.sendFilterByTitleAnalytics(changed.get('selectedTitleFilter'));
461
- this.selectedTitleLetterChanged();
462
- }
463
- if (changed.has('selectedCreatorFilter')) {
464
- this.sendFilterByCreatorAnalytics(changed.get('selectedCreatorFilter'));
465
- this.selectedCreatorLetterChanged();
466
- }
467
- if (changed.has('pagesToRender')) {
468
- if (!this.endOfDataReached && this.infiniteScroller) {
469
- this.infiniteScroller.itemCount = this.estimatedTileCount;
470
- }
471
- }
472
- if (changed.has('resizeObserver')) {
473
- const oldObserver = changed.get('resizeObserver');
474
- if (oldObserver)
475
- this.disconnectResizeObserver(oldObserver);
476
- this.setupResizeObserver();
477
- }
478
- }
479
- disconnectedCallback() {
480
- if (this.resizeObserver) {
481
- this.disconnectResizeObserver(this.resizeObserver);
482
- }
483
- if (this.boundNavigationHandler) {
484
- window.removeEventListener('popstate', this.boundNavigationHandler);
485
- }
486
- }
487
- handleResize(entry) {
488
- const previousView = this.mobileView;
489
- if (entry.target === this.contentContainer) {
490
- this.mobileView = entry.contentRect.width < this.mobileBreakpoint;
491
- // If changing from desktop to mobile disable transition
492
- if (this.mobileView && !previousView) {
493
- this.isResizeToMobile = true;
494
- }
495
- }
496
- }
497
- emitBaseQueryChanged() {
498
- this.dispatchEvent(new CustomEvent('baseQueryChanged', {
499
- detail: {
500
- baseQuery: this.baseQuery,
501
- },
502
- }));
503
- }
504
- disconnectResizeObserver(resizeObserver) {
505
- resizeObserver.removeObserver({
506
- target: this.contentContainer,
507
- handler: this,
508
- });
509
- }
510
- setupResizeObserver() {
511
- if (!this.resizeObserver)
512
- return;
513
- this.resizeObserver.addObserver({
514
- target: this.contentContainer,
515
- handler: this,
516
- });
517
- }
518
- /**
519
- * When the visible cells change from the infinite scroller, we want to emit
520
- * which page is currently visible so the consumer can update its UI or the URL
521
- *
522
- * @param e
523
- * @returns
524
- */
525
- visibleCellsChanged(e) {
526
- if (this.isScrollingToCell)
527
- return;
528
- const { visibleCellIndices } = e.detail;
529
- if (visibleCellIndices.length === 0)
530
- return;
531
- const lastVisibleCellIndex = visibleCellIndices[visibleCellIndices.length - 1];
532
- const lastVisibleCellPage = Math.floor(lastVisibleCellIndex / this.pageSize) + 1;
533
- if (this.currentPage !== lastVisibleCellPage) {
534
- this.currentPage = lastVisibleCellPage;
535
- }
536
- const event = new CustomEvent('visiblePageChanged', {
537
- detail: {
538
- pageNumber: lastVisibleCellPage,
539
- },
540
- });
541
- this.dispatchEvent(event);
542
- }
543
- async handleQueryChange() {
544
- // only reset if the query has actually changed
545
- if (!this.searchService || this.pageFetchQueryKey === this.previousQueryKey)
546
- return;
547
- this.previousQueryKey = this.pageFetchQueryKey;
548
- this.dataSource = {};
549
- this.pageFetchesInProgress = {};
550
- this.endOfDataReached = false;
551
- this.pagesToRender = this.initialPageNumber;
552
- if (!this.initialQueryChangeHappened && this.initialPageNumber > 1) {
553
- this.scrollToPage(this.initialPageNumber);
554
- }
555
- this.initialQueryChangeHappened = true;
556
- // if the query changed as part of a window.history pop event, we don't want to
557
- // persist the state because it overwrites the forward history
558
- if (!this.historyPopOccurred) {
559
- this.persistState();
560
- this.historyPopOccurred = false;
561
- }
562
- await Promise.all([
563
- this.doInitialPageFetch(),
564
- this.fetchFacets(),
565
- this.fetchFullYearHistogram(),
566
- ]);
567
- }
568
- setupStateRestorationObserver() {
569
- if (this.boundNavigationHandler)
570
- return;
571
- this.boundNavigationHandler = this.historyNavigationHandler.bind(this);
572
- // when the user navigates back, we want to update the UI to match the URL
573
- window.addEventListener('popstate', this.boundNavigationHandler);
574
- }
575
- historyNavigationHandler() {
576
- this.historyPopOccurred = true;
577
- this.restoreState();
578
- }
579
- restoreState() {
580
- var _a, _b, _c, _d, _e, _f;
581
- const restorationState = this.restorationStateHandler.getRestorationState();
582
- this.displayMode = restorationState.displayMode;
583
- this.selectedSort = (_a = restorationState.selectedSort) !== null && _a !== void 0 ? _a : SortField.relevance;
584
- this.sortDirection = (_b = restorationState.sortDirection) !== null && _b !== void 0 ? _b : null;
585
- this.selectedTitleFilter = (_c = restorationState.selectedTitleFilter) !== null && _c !== void 0 ? _c : null;
586
- this.selectedCreatorFilter = (_d = restorationState.selectedCreatorFilter) !== null && _d !== void 0 ? _d : null;
587
- this.selectedFacets = restorationState.selectedFacets;
588
- this.baseQuery = restorationState.baseQuery;
589
- this.titleQuery = restorationState.titleQuery;
590
- this.creatorQuery = restorationState.creatorQuery;
591
- this.dateRangeQueryClause = restorationState.dateRangeQueryClause;
592
- this.sortParam = (_e = restorationState.sortParam) !== null && _e !== void 0 ? _e : null;
593
- this.currentPage = (_f = restorationState.currentPage) !== null && _f !== void 0 ? _f : 1;
594
- this.minSelectedDate = restorationState.minSelectedDate;
595
- this.maxSelectedDate = restorationState.maxSelectedDate;
596
- if (this.currentPage > 1) {
597
- this.goToPage(this.currentPage);
598
- }
599
- }
600
- persistState() {
601
- var _a, _b, _c, _d, _e;
602
- const restorationState = {
603
- displayMode: this.displayMode,
604
- sortParam: (_a = this.sortParam) !== null && _a !== void 0 ? _a : undefined,
605
- selectedSort: this.selectedSort,
606
- sortDirection: (_b = this.sortDirection) !== null && _b !== void 0 ? _b : undefined,
607
- selectedFacets: (_c = this.selectedFacets) !== null && _c !== void 0 ? _c : defaultSelectedFacets,
608
- baseQuery: this.baseQuery,
609
- currentPage: this.currentPage,
610
- dateRangeQueryClause: this.dateRangeQueryClause,
611
- titleQuery: this.titleQuery,
612
- creatorQuery: this.creatorQuery,
613
- minSelectedDate: this.minSelectedDate,
614
- maxSelectedDate: this.maxSelectedDate,
615
- selectedTitleFilter: (_d = this.selectedTitleFilter) !== null && _d !== void 0 ? _d : undefined,
616
- selectedCreatorFilter: (_e = this.selectedCreatorFilter) !== null && _e !== void 0 ? _e : undefined,
617
- };
618
- this.restorationStateHandler.persistState(restorationState);
619
- }
620
- async doInitialPageFetch() {
621
- this.searchResultsLoading = true;
622
- await this.fetchPage(this.initialPageNumber);
623
- this.searchResultsLoading = false;
624
- }
625
- get fullQuery() {
626
- let { fullQueryWithoutDate } = this;
627
- const { dateRangeQueryClause } = this;
628
- if (dateRangeQueryClause) {
629
- fullQueryWithoutDate += ` AND ${dateRangeQueryClause}`;
630
- }
631
- return fullQueryWithoutDate;
632
- }
633
- get fullQueryWithoutDate() {
634
- if (!this.baseQuery)
635
- return undefined;
636
- let fullQuery = this.baseQuery;
637
- const { facetQuery, sortFilterQueries } = this;
638
- if (facetQuery) {
639
- fullQuery += ` AND ${facetQuery}`;
640
- }
641
- if (sortFilterQueries) {
642
- fullQuery += ` AND ${sortFilterQueries}`;
643
- }
644
- return fullQuery;
645
- }
646
- /**
647
- * Generates a query string for the given facets
648
- *
649
- * Example: `mediatype:("collection" OR "audio" OR -"etree") AND year:("2000" OR "2001")`
650
- */
651
- get facetQuery() {
652
- if (!this.selectedFacets)
653
- return undefined;
654
- const facetQuery = [];
655
- for (const [facetName, facetValues] of Object.entries(this.selectedFacets)) {
656
- const facetEntries = Object.entries(facetValues);
657
- // eslint-disable-next-line no-continue
658
- if (facetEntries.length === 0)
659
- continue;
660
- const facetValuesArray = [];
661
- for (const [key, facetData] of facetEntries) {
662
- const plusMinusPrefix = facetData.state === 'hidden' ? '-' : '';
663
- if (facetName === 'language') {
664
- const languages = this.languageCodeHandler.getCodeArrayFromCodeString(key);
665
- for (const language of languages) {
666
- facetValuesArray.push(`${plusMinusPrefix}"${language}"`);
667
- }
668
- }
669
- else {
670
- facetValuesArray.push(`${plusMinusPrefix}"${key}"`);
671
- }
672
- }
673
- const valueQuery = facetValuesArray.join(` OR `);
674
- facetQuery.push(`${facetName}:(${valueQuery})`);
675
- }
676
- return facetQuery.length > 0 ? `(${facetQuery.join(' AND ')})` : undefined;
677
- }
678
- facetsChanged(e) {
679
- this.selectedFacets = e.detail;
680
- }
681
- facetClickHandler(name, facetSelected, negative) {
682
- var _a, _b;
683
- if (negative) {
684
- (_a = this.analyticsHandler) === null || _a === void 0 ? void 0 : _a.sendEventNoSampling({
685
- category: this.searchContext,
686
- action: facetSelected
687
- ? analyticsActions.facetNegativeSelected
688
- : analyticsActions.facetNegativeDeselected,
689
- label: name,
690
- });
691
- }
692
- else {
693
- (_b = this.analyticsHandler) === null || _b === void 0 ? void 0 : _b.sendEventNoSampling({
694
- category: this.searchContext,
695
- action: facetSelected
696
- ? analyticsActions.facetSelected
697
- : analyticsActions.facetDeselected,
698
- label: name,
699
- });
700
- }
701
- }
702
- async fetchFacets() {
703
- var _a, _b;
704
- if (!this.fullQuery)
705
- return;
706
- const aggregations = {
707
- advancedParams: [
708
- {
709
- field: 'subjectSorter',
710
- size: 6,
711
- },
712
- {
713
- field: 'mediatypeSorter',
714
- size: 6,
715
- },
716
- {
717
- field: 'languageSorter',
718
- size: 6,
719
- },
720
- {
721
- field: 'creatorSorter',
722
- size: 6,
723
- },
724
- {
725
- field: 'collection',
726
- size: 12,
727
- },
728
- {
729
- field: 'year',
730
- size: 50,
731
- },
732
- ],
733
- };
734
- const params = {
735
- query: this.fullQuery,
736
- fields: ['identifier'],
737
- aggregations,
738
- rows: 1,
739
- };
740
- this.facetsLoading = true;
741
- const results = await ((_a = this.searchService) === null || _a === void 0 ? void 0 : _a.search(params));
742
- this.facetsLoading = false;
743
- this.aggregations = (_b = results === null || results === void 0 ? void 0 : results.success) === null || _b === void 0 ? void 0 : _b.response.aggregations;
744
- }
745
- /**
746
- * The query key is a string that uniquely identifies the current query
747
- * without the date range.
748
- *
749
- * If this doesn't change, we don't need to re-fetch the histogram date range
750
- */
751
- get fullQueryNoDateKey() {
752
- var _a, _b;
753
- return `${this.fullQueryWithoutDate}-${(_a = this.sortParam) === null || _a === void 0 ? void 0 : _a.field}-${(_b = this.sortParam) === null || _b === void 0 ? void 0 : _b.direction}`;
754
- }
755
- /**
756
- * This method is similar to fetching the facets above,
757
- * but only fetching the year histogram. There is a subtle difference
758
- * in how you have to fetch the year histogram where you can't use the
759
- * advanced JSON syntax like the other aggregations. It's a special
760
- * case that @ximm put it place.
761
- */
762
- async fetchFullYearHistogram() {
763
- var _a, _b, _c, _d;
764
- const { fullQueryNoDateKey } = this;
765
- if (!this.fullQueryWithoutDate ||
766
- fullQueryNoDateKey === this.previousFullQueryNoDate)
767
- return;
768
- this.previousFullQueryNoDate = fullQueryNoDateKey;
769
- const aggregations = {
770
- simpleParams: ['year'],
771
- };
772
- const params = {
773
- query: this.fullQueryWithoutDate,
774
- fields: ['identifier'],
775
- aggregations,
776
- rows: 1,
777
- };
778
- this.fullYearAggregationLoading = true;
779
- const results = await ((_a = this.searchService) === null || _a === void 0 ? void 0 : _a.search(params));
780
- this.fullYearAggregationLoading = false;
781
- this.fullYearsHistogramAggregation =
782
- (_d = (_c = (_b = results === null || results === void 0 ? void 0 : results.success) === null || _b === void 0 ? void 0 : _b.response) === null || _c === void 0 ? void 0 : _c.aggregations) === null || _d === void 0 ? void 0 : _d.year_histogram;
783
- }
784
- scrollToPage(pageNumber) {
785
- const cellIndexToScrollTo = this.pageSize * (pageNumber - 1);
786
- // without this setTimeout, Safari just pauses until the `fetchPage` is complete
787
- // then scrolls to the cell
788
- setTimeout(() => {
789
- this.isScrollingToCell = true;
790
- this.infiniteScroller.scrollToCell(cellIndexToScrollTo, true);
791
- // This timeout is to give the scroll animation time to finish
792
- // then updating the infinite scroller once we're done scrolling
793
- // There's no scroll animation completion callback so we're
794
- // giving it 0.5s to finish.
795
- setTimeout(() => {
796
- this.isScrollingToCell = false;
797
- this.infiniteScroller.reload();
798
- }, 500);
799
- }, 0);
800
- }
801
- /**
802
- * The query key is a string that uniquely identifies the current query
803
- *
804
- * This lets us keep track of queries so we don't persist data that's
805
- * no longer relevant.
806
- */
807
- get pageFetchQueryKey() {
808
- var _a, _b;
809
- return `${this.fullQuery}-${(_a = this.sortParam) === null || _a === void 0 ? void 0 : _a.field}-${(_b = this.sortParam) === null || _b === void 0 ? void 0 : _b.direction}`;
810
- }
811
- async fetchPage(pageNumber) {
812
- var _a, _b, _c, _d, _e;
813
- if (!this.fullQuery)
814
- return;
815
- // if we already have data, don't fetch again
816
- if (this.dataSource[pageNumber])
817
- return;
818
- if (this.endOfDataReached)
819
- return;
820
- // if a fetch is already in progress for this query and page, don't fetch again
821
- const { pageFetchQueryKey } = this;
822
- const pageFetches = (_a = this.pageFetchesInProgress[pageFetchQueryKey]) !== null && _a !== void 0 ? _a : new Set();
823
- if (pageFetches.has(pageNumber))
824
- return;
825
- pageFetches.add(pageNumber);
826
- this.pageFetchesInProgress[pageFetchQueryKey] = pageFetches;
827
- const sortParams = this.sortParam ? [this.sortParam] : [];
828
- const params = {
829
- query: this.fullQuery,
830
- fields: [
831
- 'addeddate',
832
- 'avg_rating',
833
- 'collections_raw',
834
- 'creator',
835
- 'date',
836
- 'description',
837
- 'downloads',
838
- 'identifier',
839
- 'issue',
840
- 'item_count',
841
- 'mediatype',
842
- 'num_favorites',
843
- 'num_reviews',
844
- 'publicdate',
845
- 'reviewdate',
846
- 'source',
847
- 'subject',
848
- 'title',
849
- 'volume',
850
- ],
851
- page: pageNumber,
852
- rows: this.pageSize,
853
- sort: sortParams,
854
- };
855
- const results = await ((_b = this.searchService) === null || _b === void 0 ? void 0 : _b.search(params));
856
- const success = results === null || results === void 0 ? void 0 : results.success;
857
- if (!success)
858
- return;
859
- this.totalResults = success.response.numFound;
860
- // this is checking to see if the query has changed since the data was fetched
861
- // if so, we just want to discard the data since there should be a new query
862
- // right behind it
863
- const searchQuery = success.responseHeader.params.qin;
864
- const searchSort = success.responseHeader.params.sort;
865
- let sortChanged = false;
866
- if (!searchSort) {
867
- // if we went from no sort to sort, the sort has changed
868
- if (this.sortParam) {
869
- sortChanged = true;
870
- }
871
- }
872
- else {
873
- // check if the sort has changed
874
- const split = searchSort.split(' ');
875
- if (split.length > 1) {
876
- const field = searchSort.split(' ')[0];
877
- const direction = searchSort.split(' ')[1];
878
- if (field !== ((_c = this.sortParam) === null || _c === void 0 ? void 0 : _c.field) ||
879
- direction !== ((_d = this.sortParam) === null || _d === void 0 ? void 0 : _d.direction)) {
880
- sortChanged = true;
881
- }
882
- }
883
- }
884
- const queryChangedSinceFetch = searchQuery !== this.fullQuery || sortChanged;
885
- if (queryChangedSinceFetch)
886
- return;
887
- const { docs } = success.response;
888
- if (docs && docs.length > 0) {
889
- this.preloadCollectionNames(docs);
890
- this.updateDataSource(pageNumber, docs);
891
- }
892
- if (docs.length < this.pageSize) {
893
- this.endOfDataReached = true;
894
- // this updates the infinite scroller to show the actual size
895
- if (this.infiniteScroller) {
896
- this.infiniteScroller.itemCount = this.actualTileCount;
897
- }
898
- }
899
- (_e = this.pageFetchesInProgress[pageFetchQueryKey]) === null || _e === void 0 ? void 0 : _e.delete(pageNumber);
900
- this.searchResultsLoading = false;
901
- }
902
- preloadCollectionNames(docs) {
903
- var _a;
904
- const collectionIds = docs.map(doc => { var _a; return (_a = doc.collections_raw) === null || _a === void 0 ? void 0 : _a.values; }).flat();
905
- const collectionIdsArray = Array.from(new Set(collectionIds));
906
- (_a = this.collectionNameCache) === null || _a === void 0 ? void 0 : _a.preloadIdentifiers(collectionIdsArray);
907
- }
908
- /**
909
- * This is useful for determining whether we need to reload the scroller.
910
- *
911
- * When the fetch completes, we need to reload the scroller if the cells for that
912
- * page are visible, but if the page is not currenlty visible, we don't need to reload
913
- */
914
- get currentVisiblePageNumbers() {
915
- const visibleCells = this.infiniteScroller.getVisibleCellIndices();
916
- const visiblePages = new Set();
917
- visibleCells.forEach(cellIndex => {
918
- const visiblePage = Math.floor(cellIndex / this.pageSize) + 1;
919
- visiblePages.add(visiblePage);
920
- });
921
- return Array.from(visiblePages);
922
- }
923
- /**
924
- * Update the datasource from the fetch response
925
- *
926
- * @param pageNumber
927
- * @param docs
928
- */
929
- updateDataSource(pageNumber, docs) {
930
- // copy our existing datasource so when we set it below, it gets set
931
- // instead of modifying the existing dataSource since object changes
932
- // don't trigger a re-render
933
- const datasource = { ...this.dataSource };
934
- const tiles = [];
935
- docs === null || docs === void 0 ? void 0 : docs.forEach(doc => {
936
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9;
937
- if (!doc.identifier)
938
- return;
939
- let loginRequired = false;
940
- let contentWarning = false;
941
- // Check if item and item in "modifying" collection, setting above flags
942
- if (((_a = doc.collections_raw) === null || _a === void 0 ? void 0 : _a.values.length) &&
943
- ((_b = doc.mediatype) === null || _b === void 0 ? void 0 : _b.value) !== 'collection') {
944
- for (const collection of (_c = doc.collections_raw) === null || _c === void 0 ? void 0 : _c.values) {
945
- if (collection === 'loggedin') {
946
- loginRequired = true;
947
- if (contentWarning)
948
- break;
949
- }
950
- if (collection === 'no-preview') {
951
- contentWarning = true;
952
- if (loginRequired)
953
- break;
954
- }
955
- }
956
- }
957
- tiles.push({
958
- averageRating: (_d = doc.avg_rating) === null || _d === void 0 ? void 0 : _d.value,
959
- collections: (_f = (_e = doc.collections_raw) === null || _e === void 0 ? void 0 : _e.values) !== null && _f !== void 0 ? _f : [],
960
- commentCount: (_h = (_g = doc.num_reviews) === null || _g === void 0 ? void 0 : _g.value) !== null && _h !== void 0 ? _h : 0,
961
- creator: (_j = doc.creator) === null || _j === void 0 ? void 0 : _j.value,
962
- creators: (_l = (_k = doc.creator) === null || _k === void 0 ? void 0 : _k.values) !== null && _l !== void 0 ? _l : [],
963
- dateAdded: (_m = doc.addeddate) === null || _m === void 0 ? void 0 : _m.value,
964
- dateArchived: (_o = doc.publicdate) === null || _o === void 0 ? void 0 : _o.value,
965
- datePublished: (_p = doc.date) === null || _p === void 0 ? void 0 : _p.value,
966
- dateReviewed: (_q = doc.reviewdate) === null || _q === void 0 ? void 0 : _q.value,
967
- description: (_r = doc.description) === null || _r === void 0 ? void 0 : _r.value,
968
- favCount: (_t = (_s = doc.num_favorites) === null || _s === void 0 ? void 0 : _s.value) !== null && _t !== void 0 ? _t : 0,
969
- identifier: doc.identifier,
970
- issue: (_u = doc.issue) === null || _u === void 0 ? void 0 : _u.value,
971
- itemCount: (_w = (_v = doc.item_count) === null || _v === void 0 ? void 0 : _v.value) !== null && _w !== void 0 ? _w : 0,
972
- mediatype: (_y = (_x = doc.mediatype) === null || _x === void 0 ? void 0 : _x.value) !== null && _y !== void 0 ? _y : 'data',
973
- snippets: (_0 = (_z = doc.snippets) === null || _z === void 0 ? void 0 : _z.values) !== null && _0 !== void 0 ? _0 : [],
974
- source: (_1 = doc.source) === null || _1 === void 0 ? void 0 : _1.value,
975
- subjects: (_3 = (_2 = doc.subject) === null || _2 === void 0 ? void 0 : _2.values) !== null && _3 !== void 0 ? _3 : [],
976
- title: this.etreeTitle((_4 = doc.title) === null || _4 === void 0 ? void 0 : _4.value, (_5 = doc.mediatype) === null || _5 === void 0 ? void 0 : _5.value, (_6 = doc.collection) === null || _6 === void 0 ? void 0 : _6.values),
977
- volume: (_7 = doc.volume) === null || _7 === void 0 ? void 0 : _7.value,
978
- viewCount: (_9 = (_8 = doc.downloads) === null || _8 === void 0 ? void 0 : _8.value) !== null && _9 !== void 0 ? _9 : 0,
979
- loginRequired,
980
- contentWarning,
981
- });
982
- });
983
- datasource[pageNumber] = tiles;
984
- this.dataSource = datasource;
985
- const visiblePages = this.currentVisiblePageNumbers;
986
- const needsReload = visiblePages.includes(pageNumber);
987
- if (needsReload) {
988
- this.infiniteScroller.reload();
989
- }
990
- }
991
- /*
992
- * Convert etree titles
993
- * "[Creator] Live at [Place] on [Date]" => "[Date]: [Place]"
994
- *
995
- * Todo: Check collection(s) for etree, need to get as array.
996
- * Current search-service only returns first collection as string.
997
- */
998
- etreeTitle(title, mediatype, collections) {
999
- if (mediatype === 'etree' || (collections === null || collections === void 0 ? void 0 : collections.includes('etree'))) {
1000
- const regex = /^(.*) Live at (.*) on (\d\d\d\d-\d\d-\d\d)$/;
1001
- const newTitle = title === null || title === void 0 ? void 0 : title.replace(regex, '$3: $2');
1002
- if (newTitle) {
1003
- return `${newTitle}`;
1004
- }
1005
- }
1006
- return title !== null && title !== void 0 ? title : '';
1007
- }
1008
- /**
1009
- * Callback when a result is selected
1010
- */
1011
- resultSelected(event) {
1012
- var _a, _b;
1013
- (_a = this.analyticsHandler) === null || _a === void 0 ? void 0 : _a.sendEventNoSampling({
1014
- category: this.searchContext,
1015
- action: analyticsActions.resultSelected,
1016
- label: event.detail.mediatype,
1017
- });
1018
- (_b = this.analyticsHandler) === null || _b === void 0 ? void 0 : _b.sendEventNoSampling({
1019
- category: this.searchContext,
1020
- action: analyticsActions.resultSelected,
1021
- label: `page-${this.currentPage}`,
1022
- });
1023
- }
1024
- cellForIndex(index) {
1025
- const model = this.tileModelAtCellIndex(index);
1026
- if (!model)
1027
- return undefined;
416
+ `;
417
+ }
418
+ histogramDateRangeUpdated(e) {
419
+ var _a;
420
+ const { minDate, maxDate } = e.detail;
421
+ this.dateRangeQueryClause = `year:[${minDate} TO ${maxDate}]`;
422
+ if (this.dateRangeQueryClause) {
423
+ (_a = this.analyticsHandler) === null || _a === void 0 ? void 0 : _a.sendEventNoSampling({
424
+ category: this.searchContext,
425
+ action: analyticsActions.histogramChanged,
426
+ label: this.dateRangeQueryClause,
427
+ });
428
+ }
429
+ }
430
+ firstUpdated() {
431
+ this.setupStateRestorationObserver();
432
+ this.restoreState();
433
+ }
434
+ updated(changed) {
435
+ var _a;
436
+ if (changed.has('displayMode') ||
437
+ changed.has('baseNavigationUrl') ||
438
+ changed.has('baseImageUrl') ||
439
+ changed.has('loggedIn')) {
440
+ (_a = this.infiniteScroller) === null || _a === void 0 ? void 0 : _a.reload();
441
+ }
442
+ if (changed.has('baseQuery')) {
443
+ this.emitBaseQueryChanged();
444
+ }
445
+ if (changed.has('currentPage') || changed.has('displayMode')) {
446
+ this.persistState();
447
+ }
448
+ if (changed.has('baseQuery') ||
449
+ changed.has('titleQuery') ||
450
+ changed.has('creatorQuery') ||
451
+ changed.has('dateRangeQueryClause') ||
452
+ changed.has('sortParam') ||
453
+ changed.has('selectedFacets') ||
454
+ changed.has('searchService')) {
455
+ this.handleQueryChange();
456
+ }
457
+ if (changed.has('selectedSort') || changed.has('sortDirection')) {
458
+ const prevSortDirection = changed.get('sortDirection');
459
+ this.sendSortByAnalytics(prevSortDirection);
460
+ this.selectedSortChanged();
461
+ }
462
+ if (changed.has('selectedTitleFilter')) {
463
+ this.sendFilterByTitleAnalytics(changed.get('selectedTitleFilter'));
464
+ this.selectedTitleLetterChanged();
465
+ }
466
+ if (changed.has('selectedCreatorFilter')) {
467
+ this.sendFilterByCreatorAnalytics(changed.get('selectedCreatorFilter'));
468
+ this.selectedCreatorLetterChanged();
469
+ }
470
+ if (changed.has('pagesToRender')) {
471
+ if (!this.endOfDataReached && this.infiniteScroller) {
472
+ this.infiniteScroller.itemCount = this.estimatedTileCount;
473
+ }
474
+ }
475
+ if (changed.has('resizeObserver')) {
476
+ const oldObserver = changed.get('resizeObserver');
477
+ if (oldObserver)
478
+ this.disconnectResizeObserver(oldObserver);
479
+ this.setupResizeObserver();
480
+ }
481
+ }
482
+ disconnectedCallback() {
483
+ if (this.resizeObserver) {
484
+ this.disconnectResizeObserver(this.resizeObserver);
485
+ }
486
+ if (this.boundNavigationHandler) {
487
+ window.removeEventListener('popstate', this.boundNavigationHandler);
488
+ }
489
+ }
490
+ handleResize(entry) {
491
+ const previousView = this.mobileView;
492
+ if (entry.target === this.contentContainer) {
493
+ this.mobileView = entry.contentRect.width < this.mobileBreakpoint;
494
+ // If changing from desktop to mobile disable transition
495
+ if (this.mobileView && !previousView) {
496
+ this.isResizeToMobile = true;
497
+ }
498
+ }
499
+ }
500
+ emitBaseQueryChanged() {
501
+ this.dispatchEvent(new CustomEvent('baseQueryChanged', {
502
+ detail: {
503
+ baseQuery: this.baseQuery,
504
+ },
505
+ }));
506
+ }
507
+ disconnectResizeObserver(resizeObserver) {
508
+ resizeObserver.removeObserver({
509
+ target: this.contentContainer,
510
+ handler: this,
511
+ });
512
+ }
513
+ setupResizeObserver() {
514
+ if (!this.resizeObserver)
515
+ return;
516
+ this.resizeObserver.addObserver({
517
+ target: this.contentContainer,
518
+ handler: this,
519
+ });
520
+ }
521
+ /**
522
+ * When the visible cells change from the infinite scroller, we want to emit
523
+ * which page is currently visible so the consumer can update its UI or the URL
524
+ *
525
+ * @param e
526
+ * @returns
527
+ */
528
+ visibleCellsChanged(e) {
529
+ if (this.isScrollingToCell)
530
+ return;
531
+ const { visibleCellIndices } = e.detail;
532
+ if (visibleCellIndices.length === 0)
533
+ return;
534
+ const lastVisibleCellIndex = visibleCellIndices[visibleCellIndices.length - 1];
535
+ const lastVisibleCellPage = Math.floor(lastVisibleCellIndex / this.pageSize) + 1;
536
+ if (this.currentPage !== lastVisibleCellPage) {
537
+ this.currentPage = lastVisibleCellPage;
538
+ }
539
+ const event = new CustomEvent('visiblePageChanged', {
540
+ detail: {
541
+ pageNumber: lastVisibleCellPage,
542
+ },
543
+ });
544
+ this.dispatchEvent(event);
545
+ }
546
+ async handleQueryChange() {
547
+ // only reset if the query has actually changed
548
+ if (!this.searchService || this.pageFetchQueryKey === this.previousQueryKey)
549
+ return;
550
+ this.previousQueryKey = this.pageFetchQueryKey;
551
+ this.dataSource = {};
552
+ this.pageFetchesInProgress = {};
553
+ this.endOfDataReached = false;
554
+ this.pagesToRender = this.initialPageNumber;
555
+ if (!this.initialQueryChangeHappened && this.initialPageNumber > 1) {
556
+ this.scrollToPage(this.initialPageNumber);
557
+ }
558
+ this.initialQueryChangeHappened = true;
559
+ // if the query changed as part of a window.history pop event, we don't want to
560
+ // persist the state because it overwrites the forward history
561
+ if (!this.historyPopOccurred) {
562
+ this.persistState();
563
+ this.historyPopOccurred = false;
564
+ }
565
+ await Promise.all([
566
+ this.doInitialPageFetch(),
567
+ this.fetchFacets(),
568
+ this.fetchFullYearHistogram(),
569
+ ]);
570
+ }
571
+ setupStateRestorationObserver() {
572
+ if (this.boundNavigationHandler)
573
+ return;
574
+ this.boundNavigationHandler = this.historyNavigationHandler.bind(this);
575
+ // when the user navigates back, we want to update the UI to match the URL
576
+ window.addEventListener('popstate', this.boundNavigationHandler);
577
+ }
578
+ historyNavigationHandler() {
579
+ this.historyPopOccurred = true;
580
+ this.restoreState();
581
+ }
582
+ restoreState() {
583
+ var _a, _b, _c, _d, _e, _f;
584
+ const restorationState = this.restorationStateHandler.getRestorationState();
585
+ this.displayMode = restorationState.displayMode;
586
+ this.selectedSort = (_a = restorationState.selectedSort) !== null && _a !== void 0 ? _a : SortField.relevance;
587
+ this.sortDirection = (_b = restorationState.sortDirection) !== null && _b !== void 0 ? _b : null;
588
+ this.selectedTitleFilter = (_c = restorationState.selectedTitleFilter) !== null && _c !== void 0 ? _c : null;
589
+ this.selectedCreatorFilter = (_d = restorationState.selectedCreatorFilter) !== null && _d !== void 0 ? _d : null;
590
+ this.selectedFacets = restorationState.selectedFacets;
591
+ this.baseQuery = restorationState.baseQuery;
592
+ this.titleQuery = restorationState.titleQuery;
593
+ this.creatorQuery = restorationState.creatorQuery;
594
+ this.dateRangeQueryClause = restorationState.dateRangeQueryClause;
595
+ this.sortParam = (_e = restorationState.sortParam) !== null && _e !== void 0 ? _e : null;
596
+ this.currentPage = (_f = restorationState.currentPage) !== null && _f !== void 0 ? _f : 1;
597
+ this.minSelectedDate = restorationState.minSelectedDate;
598
+ this.maxSelectedDate = restorationState.maxSelectedDate;
599
+ if (this.currentPage > 1) {
600
+ this.goToPage(this.currentPage);
601
+ }
602
+ }
603
+ persistState() {
604
+ var _a, _b, _c, _d, _e;
605
+ const restorationState = {
606
+ displayMode: this.displayMode,
607
+ sortParam: (_a = this.sortParam) !== null && _a !== void 0 ? _a : undefined,
608
+ selectedSort: this.selectedSort,
609
+ sortDirection: (_b = this.sortDirection) !== null && _b !== void 0 ? _b : undefined,
610
+ selectedFacets: (_c = this.selectedFacets) !== null && _c !== void 0 ? _c : defaultSelectedFacets,
611
+ baseQuery: this.baseQuery,
612
+ currentPage: this.currentPage,
613
+ dateRangeQueryClause: this.dateRangeQueryClause,
614
+ titleQuery: this.titleQuery,
615
+ creatorQuery: this.creatorQuery,
616
+ minSelectedDate: this.minSelectedDate,
617
+ maxSelectedDate: this.maxSelectedDate,
618
+ selectedTitleFilter: (_d = this.selectedTitleFilter) !== null && _d !== void 0 ? _d : undefined,
619
+ selectedCreatorFilter: (_e = this.selectedCreatorFilter) !== null && _e !== void 0 ? _e : undefined,
620
+ };
621
+ this.restorationStateHandler.persistState(restorationState);
622
+ }
623
+ async doInitialPageFetch() {
624
+ this.searchResultsLoading = true;
625
+ await this.fetchPage(this.initialPageNumber);
626
+ this.searchResultsLoading = false;
627
+ }
628
+ get searchType() {
629
+ return this.searchTarget === 'fulltext'
630
+ ? SearchType.FULLTEXT
631
+ : SearchType.METADATA;
632
+ }
633
+ get fullQuery() {
634
+ let { fullQueryWithoutDate } = this;
635
+ const { dateRangeQueryClause } = this;
636
+ if (dateRangeQueryClause) {
637
+ fullQueryWithoutDate += ` AND ${dateRangeQueryClause}`;
638
+ }
639
+ return fullQueryWithoutDate;
640
+ }
641
+ get fullQueryWithoutDate() {
642
+ if (!this.baseQuery)
643
+ return undefined;
644
+ let fullQuery = this.baseQuery;
645
+ const { facetQuery, sortFilterQueries } = this;
646
+ if (facetQuery) {
647
+ fullQuery += ` AND ${facetQuery}`;
648
+ }
649
+ if (sortFilterQueries) {
650
+ fullQuery += ` AND ${sortFilterQueries}`;
651
+ }
652
+ return fullQuery;
653
+ }
654
+ /**
655
+ * Generates a query string for the given facets
656
+ *
657
+ * Example: `mediatype:("collection" OR "audio" OR -"etree") AND year:("2000" OR "2001")`
658
+ */
659
+ get facetQuery() {
660
+ if (!this.selectedFacets)
661
+ return undefined;
662
+ const facetQuery = [];
663
+ for (const [facetName, facetValues] of Object.entries(this.selectedFacets)) {
664
+ const facetEntries = Object.entries(facetValues);
665
+ // eslint-disable-next-line no-continue
666
+ if (facetEntries.length === 0)
667
+ continue;
668
+ const facetValuesArray = [];
669
+ for (const [key, facetData] of facetEntries) {
670
+ const plusMinusPrefix = facetData.state === 'hidden' ? '-' : '';
671
+ if (facetName === 'language') {
672
+ const languages = this.languageCodeHandler.getCodeArrayFromCodeString(key);
673
+ for (const language of languages) {
674
+ facetValuesArray.push(`${plusMinusPrefix}"${language}"`);
675
+ }
676
+ }
677
+ else {
678
+ facetValuesArray.push(`${plusMinusPrefix}"${key}"`);
679
+ }
680
+ }
681
+ const valueQuery = facetValuesArray.join(` OR `);
682
+ facetQuery.push(`${facetName}:(${valueQuery})`);
683
+ }
684
+ return facetQuery.length > 0 ? `(${facetQuery.join(' AND ')})` : undefined;
685
+ }
686
+ facetsChanged(e) {
687
+ this.selectedFacets = e.detail;
688
+ }
689
+ facetClickHandler(name, facetSelected, negative) {
690
+ var _a, _b;
691
+ if (negative) {
692
+ (_a = this.analyticsHandler) === null || _a === void 0 ? void 0 : _a.sendEventNoSampling({
693
+ category: this.searchContext,
694
+ action: facetSelected
695
+ ? analyticsActions.facetNegativeSelected
696
+ : analyticsActions.facetNegativeDeselected,
697
+ label: name,
698
+ });
699
+ }
700
+ else {
701
+ (_b = this.analyticsHandler) === null || _b === void 0 ? void 0 : _b.sendEventNoSampling({
702
+ category: this.searchContext,
703
+ action: facetSelected
704
+ ? analyticsActions.facetSelected
705
+ : analyticsActions.facetDeselected,
706
+ label: name,
707
+ });
708
+ }
709
+ }
710
+ async fetchFacets() {
711
+ var _a, _b;
712
+ if (!this.fullQuery)
713
+ return;
714
+ const params = {
715
+ query: this.fullQuery,
716
+ rows: 0,
717
+ // Note: we don't need an aggregations param to fetch the default aggregations from the PPS.
718
+ // The default aggregations for the search_results page type should be what we need here.
719
+ };
720
+ this.facetsLoading = true;
721
+ const results = await ((_a = this.searchService) === null || _a === void 0 ? void 0 : _a.search(params, this.searchType));
722
+ this.facetsLoading = false;
723
+ this.aggregations = (_b = results === null || results === void 0 ? void 0 : results.success) === null || _b === void 0 ? void 0 : _b.response.aggregations;
724
+ }
725
+ /**
726
+ * The query key is a string that uniquely identifies the current query
727
+ * without the date range.
728
+ *
729
+ * If this doesn't change, we don't need to re-fetch the histogram date range
730
+ */
731
+ get fullQueryNoDateKey() {
732
+ var _a, _b;
733
+ return `${this.fullQueryWithoutDate}-${(_a = this.sortParam) === null || _a === void 0 ? void 0 : _a.field}-${(_b = this.sortParam) === null || _b === void 0 ? void 0 : _b.direction}`;
734
+ }
735
+ /**
736
+ * This method is similar to fetching the facets above,
737
+ * but only fetching the year histogram. There is a subtle difference
738
+ * in how you have to fetch the year histogram where you can't use the
739
+ * advanced JSON syntax like the other aggregations. It's a special
740
+ * case that @ximm put it place.
741
+ */
742
+ async fetchFullYearHistogram() {
743
+ var _a, _b, _c, _d;
744
+ const { fullQueryNoDateKey } = this;
745
+ if (!this.fullQueryWithoutDate ||
746
+ fullQueryNoDateKey === this.previousFullQueryNoDate)
747
+ return;
748
+ this.previousFullQueryNoDate = fullQueryNoDateKey;
749
+ const aggregations = {
750
+ simpleParams: ['year'],
751
+ };
752
+ const params = {
753
+ query: this.fullQueryWithoutDate,
754
+ aggregations,
755
+ rows: 0,
756
+ };
757
+ this.fullYearAggregationLoading = true;
758
+ const results = await ((_a = this.searchService) === null || _a === void 0 ? void 0 : _a.search(params, this.searchType));
759
+ this.fullYearAggregationLoading = false;
760
+ this.fullYearsHistogramAggregation =
761
+ (_d = (_c = (_b = results === null || results === void 0 ? void 0 : results.success) === null || _b === void 0 ? void 0 : _b.response) === null || _c === void 0 ? void 0 : _c.aggregations) === null || _d === void 0 ? void 0 : _d.year_histogram;
762
+ }
763
+ scrollToPage(pageNumber) {
764
+ const cellIndexToScrollTo = this.pageSize * (pageNumber - 1);
765
+ // without this setTimeout, Safari just pauses until the `fetchPage` is complete
766
+ // then scrolls to the cell
767
+ setTimeout(() => {
768
+ this.isScrollingToCell = true;
769
+ this.infiniteScroller.scrollToCell(cellIndexToScrollTo, true);
770
+ // This timeout is to give the scroll animation time to finish
771
+ // then updating the infinite scroller once we're done scrolling
772
+ // There's no scroll animation completion callback so we're
773
+ // giving it 0.5s to finish.
774
+ setTimeout(() => {
775
+ this.isScrollingToCell = false;
776
+ this.infiniteScroller.reload();
777
+ }, 500);
778
+ }, 0);
779
+ }
780
+ /**
781
+ * The query key is a string that uniquely identifies the current query
782
+ *
783
+ * This lets us keep track of queries so we don't persist data that's
784
+ * no longer relevant.
785
+ */
786
+ get pageFetchQueryKey() {
787
+ var _a, _b;
788
+ return `${this.fullQuery}-${(_a = this.sortParam) === null || _a === void 0 ? void 0 : _a.field}-${(_b = this.sortParam) === null || _b === void 0 ? void 0 : _b.direction}`;
789
+ }
790
+ async fetchPage(pageNumber) {
791
+ var _a, _b, _c, _d, _e;
792
+ if (!this.fullQuery)
793
+ return;
794
+ // if we already have data, don't fetch again
795
+ if (this.dataSource[pageNumber])
796
+ return;
797
+ if (this.endOfDataReached)
798
+ return;
799
+ // if a fetch is already in progress for this query and page, don't fetch again
800
+ const { pageFetchQueryKey } = this;
801
+ const pageFetches = (_a = this.pageFetchesInProgress[pageFetchQueryKey]) !== null && _a !== void 0 ? _a : new Set();
802
+ if (pageFetches.has(pageNumber))
803
+ return;
804
+ pageFetches.add(pageNumber);
805
+ this.pageFetchesInProgress[pageFetchQueryKey] = pageFetches;
806
+ const sortParams = this.sortParam ? [this.sortParam] : [];
807
+ const params = {
808
+ query: this.fullQuery,
809
+ fields: [
810
+ 'addeddate',
811
+ 'avg_rating',
812
+ 'collections_raw',
813
+ 'creator',
814
+ 'date',
815
+ 'description',
816
+ 'downloads',
817
+ 'identifier',
818
+ 'issue',
819
+ 'item_count',
820
+ 'mediatype',
821
+ 'num_favorites',
822
+ 'num_reviews',
823
+ 'publicdate',
824
+ 'reviewdate',
825
+ 'source',
826
+ 'subject',
827
+ 'title',
828
+ 'volume',
829
+ ],
830
+ page: pageNumber,
831
+ rows: this.pageSize,
832
+ sort: sortParams,
833
+ aggregations: { omit: true },
834
+ };
835
+ const searchResponse = await ((_b = this.searchService) === null || _b === void 0 ? void 0 : _b.search(params, this.searchType));
836
+ const success = searchResponse === null || searchResponse === void 0 ? void 0 : searchResponse.success;
837
+ if (!success)
838
+ return;
839
+ this.totalResults = success.response.totalResults;
840
+ // this is checking to see if the query has changed since the data was fetched
841
+ // if so, we just want to discard the data since there should be a new query
842
+ // right behind it
843
+ const searchQuery = success.request.clientParameters.user_query;
844
+ const searchSort = success.request.clientParameters.sort;
845
+ let sortChanged = false;
846
+ if (!searchSort || searchSort.length === 0) {
847
+ // if we went from no sort to sort, the sort has changed
848
+ if (this.sortParam) {
849
+ sortChanged = true;
850
+ }
851
+ }
852
+ else {
853
+ // check if the sort has changed
854
+ for (const sortType of searchSort) {
855
+ const [field, direction] = sortType.split(':');
856
+ if (field !== ((_c = this.sortParam) === null || _c === void 0 ? void 0 : _c.field) ||
857
+ direction !== ((_d = this.sortParam) === null || _d === void 0 ? void 0 : _d.direction)) {
858
+ sortChanged = true;
859
+ break;
860
+ }
861
+ }
862
+ }
863
+ const queryChangedSinceFetch = searchQuery !== this.fullQuery || sortChanged;
864
+ if (queryChangedSinceFetch)
865
+ return;
866
+ const { results } = success.response;
867
+ if (results && results.length > 0) {
868
+ this.preloadCollectionNames(results);
869
+ this.updateDataSource(pageNumber, results);
870
+ }
871
+ if (results.length < this.pageSize) {
872
+ this.endOfDataReached = true;
873
+ // this updates the infinite scroller to show the actual size
874
+ if (this.infiniteScroller) {
875
+ this.infiniteScroller.itemCount = this.actualTileCount;
876
+ }
877
+ }
878
+ (_e = this.pageFetchesInProgress[pageFetchQueryKey]) === null || _e === void 0 ? void 0 : _e.delete(pageNumber);
879
+ this.searchResultsLoading = false;
880
+ }
881
+ preloadCollectionNames(results) {
882
+ var _a;
883
+ const collectionIds = results
884
+ .map(result => { var _a; return (_a = result.collection) === null || _a === void 0 ? void 0 : _a.values; })
885
+ .flat();
886
+ const collectionIdsArray = Array.from(new Set(collectionIds));
887
+ (_a = this.collectionNameCache) === null || _a === void 0 ? void 0 : _a.preloadIdentifiers(collectionIdsArray);
888
+ }
889
+ /**
890
+ * This is useful for determining whether we need to reload the scroller.
891
+ *
892
+ * When the fetch completes, we need to reload the scroller if the cells for that
893
+ * page are visible, but if the page is not currenlty visible, we don't need to reload
894
+ */
895
+ get currentVisiblePageNumbers() {
896
+ const visibleCells = this.infiniteScroller.getVisibleCellIndices();
897
+ const visiblePages = new Set();
898
+ visibleCells.forEach(cellIndex => {
899
+ const visiblePage = Math.floor(cellIndex / this.pageSize) + 1;
900
+ visiblePages.add(visiblePage);
901
+ });
902
+ return Array.from(visiblePages);
903
+ }
904
+ /**
905
+ * Update the datasource from the fetch response
906
+ *
907
+ * @param pageNumber
908
+ * @param results
909
+ */
910
+ updateDataSource(pageNumber, results) {
911
+ // copy our existing datasource so when we set it below, it gets set
912
+ // instead of modifying the existing dataSource since object changes
913
+ // don't trigger a re-render
914
+ const datasource = { ...this.dataSource };
915
+ const tiles = [];
916
+ results === null || results === void 0 ? void 0 : results.forEach(result => {
917
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4;
918
+ if (!result.identifier)
919
+ return;
920
+ let loginRequired = false;
921
+ let contentWarning = false;
922
+ // Check if item and item in "modifying" collection, setting above flags
923
+ if (((_a = result.collection) === null || _a === void 0 ? void 0 : _a.values.length) &&
924
+ ((_b = result.mediatype) === null || _b === void 0 ? void 0 : _b.value) !== 'collection') {
925
+ for (const collection of (_d = (_c = result.collection) === null || _c === void 0 ? void 0 : _c.values) !== null && _d !== void 0 ? _d : []) {
926
+ if (collection === 'loggedin') {
927
+ loginRequired = true;
928
+ if (contentWarning)
929
+ break;
930
+ }
931
+ if (collection === 'no-preview') {
932
+ contentWarning = true;
933
+ if (loginRequired)
934
+ break;
935
+ }
936
+ }
937
+ }
938
+ tiles.push({
939
+ // TODO the commented items are not currently being returned by the PPS and
940
+ // we will need to have them added to the PPS hit schemas where appropriate
941
+ // averageRating: result.avg_rating?.value,
942
+ collections: (_f = (_e = result.collection) === null || _e === void 0 ? void 0 : _e.values) !== null && _f !== void 0 ? _f : [],
943
+ commentCount: (_h = (_g = result.num_reviews) === null || _g === void 0 ? void 0 : _g.value) !== null && _h !== void 0 ? _h : 0,
944
+ creator: (_j = result.creator) === null || _j === void 0 ? void 0 : _j.value,
945
+ creators: (_l = (_k = result.creator) === null || _k === void 0 ? void 0 : _k.values) !== null && _l !== void 0 ? _l : [],
946
+ // dateAdded: result.addeddate?.value,
947
+ dateArchived: (_m = result.publicdate) === null || _m === void 0 ? void 0 : _m.value,
948
+ datePublished: (_o = result.date) === null || _o === void 0 ? void 0 : _o.value,
949
+ dateReviewed: (_p = result.reviewdate) === null || _p === void 0 ? void 0 : _p.value,
950
+ description: (_q = result.description) === null || _q === void 0 ? void 0 : _q.value,
951
+ favCount: (_s = (_r = result.num_favorites) === null || _r === void 0 ? void 0 : _r.value) !== null && _s !== void 0 ? _s : 0,
952
+ identifier: result.identifier,
953
+ // issue: result.issue?.value,
954
+ itemCount: 0,
955
+ mediatype: (_u = (_t = result.mediatype) === null || _t === void 0 ? void 0 : _t.value) !== null && _u !== void 0 ? _u : 'data',
956
+ snippets: (_w = (_v = result.highlight) === null || _v === void 0 ? void 0 : _v.values) !== null && _w !== void 0 ? _w : [],
957
+ // source: result.source?.value,
958
+ subjects: (_y = (_x = result.subject) === null || _x === void 0 ? void 0 : _x.values) !== null && _y !== void 0 ? _y : [],
959
+ title: this.etreeTitle((_z = result.title) === null || _z === void 0 ? void 0 : _z.value, (_0 = result.mediatype) === null || _0 === void 0 ? void 0 : _0.value, (_1 = result.collection) === null || _1 === void 0 ? void 0 : _1.values),
960
+ volume: (_2 = result.volume) === null || _2 === void 0 ? void 0 : _2.value,
961
+ viewCount: (_4 = (_3 = result.downloads) === null || _3 === void 0 ? void 0 : _3.value) !== null && _4 !== void 0 ? _4 : 0,
962
+ loginRequired,
963
+ contentWarning,
964
+ });
965
+ });
966
+ datasource[pageNumber] = tiles;
967
+ this.dataSource = datasource;
968
+ const visiblePages = this.currentVisiblePageNumbers;
969
+ const needsReload = visiblePages.includes(pageNumber);
970
+ if (needsReload) {
971
+ this.infiniteScroller.reload();
972
+ }
973
+ }
974
+ /*
975
+ * Convert etree titles
976
+ * "[Creator] Live at [Place] on [Date]" => "[Date]: [Place]"
977
+ *
978
+ * Todo: Check collection(s) for etree, need to get as array.
979
+ * Current search-service only returns first collection as string.
980
+ */
981
+ etreeTitle(title, mediatype, collections) {
982
+ if (mediatype === 'etree' || (collections === null || collections === void 0 ? void 0 : collections.includes('etree'))) {
983
+ const regex = /^(.*) Live at (.*) on (\d\d\d\d-\d\d-\d\d)$/;
984
+ const newTitle = title === null || title === void 0 ? void 0 : title.replace(regex, '$3: $2');
985
+ if (newTitle) {
986
+ return `${newTitle}`;
987
+ }
988
+ }
989
+ return title !== null && title !== void 0 ? title : '';
990
+ }
991
+ /**
992
+ * Callback when a result is selected
993
+ */
994
+ resultSelected(event) {
995
+ var _a, _b;
996
+ (_a = this.analyticsHandler) === null || _a === void 0 ? void 0 : _a.sendEventNoSampling({
997
+ category: this.searchContext,
998
+ action: analyticsActions.resultSelected,
999
+ label: event.detail.mediatype,
1000
+ });
1001
+ (_b = this.analyticsHandler) === null || _b === void 0 ? void 0 : _b.sendEventNoSampling({
1002
+ category: this.searchContext,
1003
+ action: analyticsActions.resultSelected,
1004
+ label: `page-${this.currentPage}`,
1005
+ });
1006
+ }
1007
+ cellForIndex(index) {
1008
+ const model = this.tileModelAtCellIndex(index);
1009
+ if (!model)
1010
+ return undefined;
1028
1011
  return html `
1029
1012
  <tile-dispatcher
1030
1013
  .baseNavigationUrl=${this.baseNavigationUrl}
@@ -1039,17 +1022,17 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
1039
1022
  @resultSelected=${(e) => this.resultSelected(e)}
1040
1023
  >
1041
1024
  </tile-dispatcher>
1042
- `;
1043
- }
1044
- /**
1045
- * When the user scrolls near to the bottom of the page, fetch the next page
1046
- * increase the number of pages to render and start fetching data for the new page
1047
- */
1048
- scrollThresholdReached() {
1049
- this.pagesToRender += 1;
1050
- this.fetchPage(this.pagesToRender);
1051
- }
1052
- };
1025
+ `;
1026
+ }
1027
+ /**
1028
+ * When the user scrolls near to the bottom of the page, fetch the next page
1029
+ * increase the number of pages to render and start fetching data for the new page
1030
+ */
1031
+ scrollThresholdReached() {
1032
+ this.pagesToRender += 1;
1033
+ this.fetchPage(this.pagesToRender);
1034
+ }
1035
+ };
1053
1036
  CollectionBrowser.styles = css `
1054
1037
  :host {
1055
1038
  display: block;
@@ -1256,132 +1239,135 @@ CollectionBrowser.styles = css `
1256
1239
  29rem
1257
1240
  );
1258
1241
  }
1259
- `;
1260
- __decorate([
1261
- property({ type: String })
1262
- ], CollectionBrowser.prototype, "baseNavigationUrl", void 0);
1263
- __decorate([
1264
- property({ type: String })
1265
- ], CollectionBrowser.prototype, "baseImageUrl", void 0);
1266
- __decorate([
1267
- property({ type: Object })
1268
- ], CollectionBrowser.prototype, "searchService", void 0);
1269
- __decorate([
1270
- property({ type: String })
1271
- ], CollectionBrowser.prototype, "baseQuery", void 0);
1272
- __decorate([
1273
- property({ type: String })
1274
- ], CollectionBrowser.prototype, "displayMode", void 0);
1275
- __decorate([
1276
- property({ type: Object })
1277
- ], CollectionBrowser.prototype, "sortParam", void 0);
1278
- __decorate([
1279
- property({ type: String })
1280
- ], CollectionBrowser.prototype, "selectedSort", void 0);
1281
- __decorate([
1282
- property({ type: String })
1283
- ], CollectionBrowser.prototype, "selectedTitleFilter", void 0);
1284
- __decorate([
1285
- property({ type: String })
1286
- ], CollectionBrowser.prototype, "selectedCreatorFilter", void 0);
1287
- __decorate([
1288
- property({ type: String })
1289
- ], CollectionBrowser.prototype, "sortDirection", void 0);
1290
- __decorate([
1291
- property({ type: String })
1292
- ], CollectionBrowser.prototype, "dateRangeQueryClause", void 0);
1293
- __decorate([
1294
- property({ type: Number })
1295
- ], CollectionBrowser.prototype, "pageSize", void 0);
1296
- __decorate([
1297
- property({ type: Object })
1298
- ], CollectionBrowser.prototype, "resizeObserver", void 0);
1299
- __decorate([
1300
- property({ type: String })
1301
- ], CollectionBrowser.prototype, "titleQuery", void 0);
1302
- __decorate([
1303
- property({ type: String })
1304
- ], CollectionBrowser.prototype, "creatorQuery", void 0);
1305
- __decorate([
1306
- property({ type: Number })
1307
- ], CollectionBrowser.prototype, "currentPage", void 0);
1308
- __decorate([
1309
- property({ type: String })
1310
- ], CollectionBrowser.prototype, "minSelectedDate", void 0);
1311
- __decorate([
1312
- property({ type: String })
1313
- ], CollectionBrowser.prototype, "maxSelectedDate", void 0);
1314
- __decorate([
1315
- property({ type: Object })
1316
- ], CollectionBrowser.prototype, "selectedFacets", void 0);
1317
- __decorate([
1318
- property({ type: Boolean })
1319
- ], CollectionBrowser.prototype, "showHistogramDatePicker", void 0);
1320
- __decorate([
1321
- property({ type: String, reflect: true })
1322
- ], CollectionBrowser.prototype, "searchContext", void 0);
1323
- __decorate([
1324
- property({ type: Object })
1325
- ], CollectionBrowser.prototype, "collectionNameCache", void 0);
1326
- __decorate([
1327
- property({ type: String })
1328
- ], CollectionBrowser.prototype, "pageContext", void 0);
1329
- __decorate([
1330
- property({ type: Object })
1331
- ], CollectionBrowser.prototype, "restorationStateHandler", void 0);
1332
- __decorate([
1333
- property({ type: Number })
1334
- ], CollectionBrowser.prototype, "mobileBreakpoint", void 0);
1335
- __decorate([
1336
- property({ type: Boolean })
1337
- ], CollectionBrowser.prototype, "loggedIn", void 0);
1338
- __decorate([
1339
- property({ type: Object })
1340
- ], CollectionBrowser.prototype, "modalManager", void 0);
1341
- __decorate([
1342
- property({ type: Boolean })
1343
- ], CollectionBrowser.prototype, "isManageView", void 0);
1344
- __decorate([
1345
- state()
1346
- ], CollectionBrowser.prototype, "pagesToRender", void 0);
1347
- __decorate([
1348
- state()
1349
- ], CollectionBrowser.prototype, "searchResultsLoading", void 0);
1350
- __decorate([
1351
- state()
1352
- ], CollectionBrowser.prototype, "facetsLoading", void 0);
1353
- __decorate([
1354
- state()
1355
- ], CollectionBrowser.prototype, "fullYearAggregationLoading", void 0);
1356
- __decorate([
1357
- state()
1358
- ], CollectionBrowser.prototype, "aggregations", void 0);
1359
- __decorate([
1360
- state()
1361
- ], CollectionBrowser.prototype, "fullYearsHistogramAggregation", void 0);
1362
- __decorate([
1363
- state()
1364
- ], CollectionBrowser.prototype, "totalResults", void 0);
1365
- __decorate([
1366
- state()
1367
- ], CollectionBrowser.prototype, "mobileView", void 0);
1368
- __decorate([
1369
- state()
1370
- ], CollectionBrowser.prototype, "mobileFacetsVisible", void 0);
1371
- __decorate([
1372
- state()
1373
- ], CollectionBrowser.prototype, "placeholderType", void 0);
1374
- __decorate([
1375
- query('#content-container')
1376
- ], CollectionBrowser.prototype, "contentContainer", void 0);
1377
- __decorate([
1378
- property({ type: Object, attribute: false })
1379
- ], CollectionBrowser.prototype, "analyticsHandler", void 0);
1380
- __decorate([
1381
- query('infinite-scroller')
1382
- ], CollectionBrowser.prototype, "infiniteScroller", void 0);
1383
- CollectionBrowser = __decorate([
1384
- customElement('collection-browser')
1385
- ], CollectionBrowser);
1386
- export { CollectionBrowser };
1242
+ `;
1243
+ __decorate([
1244
+ property({ type: String })
1245
+ ], CollectionBrowser.prototype, "baseNavigationUrl", void 0);
1246
+ __decorate([
1247
+ property({ type: String })
1248
+ ], CollectionBrowser.prototype, "baseImageUrl", void 0);
1249
+ __decorate([
1250
+ property({ type: Object })
1251
+ ], CollectionBrowser.prototype, "searchService", void 0);
1252
+ __decorate([
1253
+ property({ type: String })
1254
+ ], CollectionBrowser.prototype, "searchTarget", void 0);
1255
+ __decorate([
1256
+ property({ type: String })
1257
+ ], CollectionBrowser.prototype, "baseQuery", void 0);
1258
+ __decorate([
1259
+ property({ type: String })
1260
+ ], CollectionBrowser.prototype, "displayMode", void 0);
1261
+ __decorate([
1262
+ property({ type: Object })
1263
+ ], CollectionBrowser.prototype, "sortParam", void 0);
1264
+ __decorate([
1265
+ property({ type: String })
1266
+ ], CollectionBrowser.prototype, "selectedSort", void 0);
1267
+ __decorate([
1268
+ property({ type: String })
1269
+ ], CollectionBrowser.prototype, "selectedTitleFilter", void 0);
1270
+ __decorate([
1271
+ property({ type: String })
1272
+ ], CollectionBrowser.prototype, "selectedCreatorFilter", void 0);
1273
+ __decorate([
1274
+ property({ type: String })
1275
+ ], CollectionBrowser.prototype, "sortDirection", void 0);
1276
+ __decorate([
1277
+ property({ type: String })
1278
+ ], CollectionBrowser.prototype, "dateRangeQueryClause", void 0);
1279
+ __decorate([
1280
+ property({ type: Number })
1281
+ ], CollectionBrowser.prototype, "pageSize", void 0);
1282
+ __decorate([
1283
+ property({ type: Object })
1284
+ ], CollectionBrowser.prototype, "resizeObserver", void 0);
1285
+ __decorate([
1286
+ property({ type: String })
1287
+ ], CollectionBrowser.prototype, "titleQuery", void 0);
1288
+ __decorate([
1289
+ property({ type: String })
1290
+ ], CollectionBrowser.prototype, "creatorQuery", void 0);
1291
+ __decorate([
1292
+ property({ type: Number })
1293
+ ], CollectionBrowser.prototype, "currentPage", void 0);
1294
+ __decorate([
1295
+ property({ type: String })
1296
+ ], CollectionBrowser.prototype, "minSelectedDate", void 0);
1297
+ __decorate([
1298
+ property({ type: String })
1299
+ ], CollectionBrowser.prototype, "maxSelectedDate", void 0);
1300
+ __decorate([
1301
+ property({ type: Object })
1302
+ ], CollectionBrowser.prototype, "selectedFacets", void 0);
1303
+ __decorate([
1304
+ property({ type: Boolean })
1305
+ ], CollectionBrowser.prototype, "showHistogramDatePicker", void 0);
1306
+ __decorate([
1307
+ property({ type: String, reflect: true })
1308
+ ], CollectionBrowser.prototype, "searchContext", void 0);
1309
+ __decorate([
1310
+ property({ type: Object })
1311
+ ], CollectionBrowser.prototype, "collectionNameCache", void 0);
1312
+ __decorate([
1313
+ property({ type: String })
1314
+ ], CollectionBrowser.prototype, "pageContext", void 0);
1315
+ __decorate([
1316
+ property({ type: Object })
1317
+ ], CollectionBrowser.prototype, "restorationStateHandler", void 0);
1318
+ __decorate([
1319
+ property({ type: Number })
1320
+ ], CollectionBrowser.prototype, "mobileBreakpoint", void 0);
1321
+ __decorate([
1322
+ property({ type: Boolean })
1323
+ ], CollectionBrowser.prototype, "loggedIn", void 0);
1324
+ __decorate([
1325
+ property({ type: Object })
1326
+ ], CollectionBrowser.prototype, "modalManager", void 0);
1327
+ __decorate([
1328
+ property({ type: Boolean })
1329
+ ], CollectionBrowser.prototype, "isManageView", void 0);
1330
+ __decorate([
1331
+ state()
1332
+ ], CollectionBrowser.prototype, "pagesToRender", void 0);
1333
+ __decorate([
1334
+ state()
1335
+ ], CollectionBrowser.prototype, "searchResultsLoading", void 0);
1336
+ __decorate([
1337
+ state()
1338
+ ], CollectionBrowser.prototype, "facetsLoading", void 0);
1339
+ __decorate([
1340
+ state()
1341
+ ], CollectionBrowser.prototype, "fullYearAggregationLoading", void 0);
1342
+ __decorate([
1343
+ state()
1344
+ ], CollectionBrowser.prototype, "aggregations", void 0);
1345
+ __decorate([
1346
+ state()
1347
+ ], CollectionBrowser.prototype, "fullYearsHistogramAggregation", void 0);
1348
+ __decorate([
1349
+ state()
1350
+ ], CollectionBrowser.prototype, "totalResults", void 0);
1351
+ __decorate([
1352
+ state()
1353
+ ], CollectionBrowser.prototype, "mobileView", void 0);
1354
+ __decorate([
1355
+ state()
1356
+ ], CollectionBrowser.prototype, "mobileFacetsVisible", void 0);
1357
+ __decorate([
1358
+ state()
1359
+ ], CollectionBrowser.prototype, "placeholderType", void 0);
1360
+ __decorate([
1361
+ query('#content-container')
1362
+ ], CollectionBrowser.prototype, "contentContainer", void 0);
1363
+ __decorate([
1364
+ property({ type: Object, attribute: false })
1365
+ ], CollectionBrowser.prototype, "analyticsHandler", void 0);
1366
+ __decorate([
1367
+ query('infinite-scroller')
1368
+ ], CollectionBrowser.prototype, "infiniteScroller", void 0);
1369
+ CollectionBrowser = __decorate([
1370
+ customElement('collection-browser')
1371
+ ], CollectionBrowser);
1372
+ export { CollectionBrowser };
1387
1373
  //# sourceMappingURL=collection-browser.js.map