@internetarchive/collection-browser 0.0.1-alpha.8 → 0.1.1

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 (261) hide show
  1. package/README.md +8 -11
  2. package/demo/app-root.ts +16 -92
  3. package/dist/demo/app-root.d.ts +3 -5
  4. package/dist/demo/app-root.js +13 -83
  5. package/dist/demo/app-root.js.map +1 -1
  6. package/dist/index.d.ts +6 -0
  7. package/dist/index.js +6 -0
  8. package/dist/index.js.map +1 -1
  9. package/dist/src/assets/img/icons/chevron.d.ts +2 -0
  10. package/dist/src/assets/img/icons/chevron.js +4 -0
  11. package/dist/src/assets/img/icons/chevron.js.map +1 -0
  12. package/dist/src/assets/img/icons/mediatype/account.d.ts +1 -2
  13. package/dist/src/assets/img/icons/mediatype/account.js +6 -4
  14. package/dist/src/assets/img/icons/mediatype/account.js.map +1 -1
  15. package/dist/src/assets/img/icons/mediatype/audio.js +7 -4
  16. package/dist/src/assets/img/icons/mediatype/audio.js.map +1 -1
  17. package/dist/src/assets/img/icons/mediatype/collection.js +7 -4
  18. package/dist/src/assets/img/icons/mediatype/collection.js.map +1 -1
  19. package/dist/src/assets/img/icons/mediatype/data.d.ts +1 -0
  20. package/dist/src/assets/img/icons/mediatype/data.js +15 -0
  21. package/dist/src/assets/img/icons/mediatype/data.js.map +1 -0
  22. package/dist/src/assets/img/icons/mediatype/etree.js +10 -5
  23. package/dist/src/assets/img/icons/mediatype/etree.js.map +1 -1
  24. package/dist/src/assets/img/icons/mediatype/film.js +2 -1
  25. package/dist/src/assets/img/icons/mediatype/film.js.map +1 -1
  26. package/dist/src/assets/img/icons/mediatype/images.js +9 -6
  27. package/dist/src/assets/img/icons/mediatype/images.js.map +1 -1
  28. package/dist/src/assets/img/icons/mediatype/radio.d.ts +1 -0
  29. package/dist/src/assets/img/icons/mediatype/radio.js +15 -0
  30. package/dist/src/assets/img/icons/mediatype/radio.js.map +1 -0
  31. package/dist/src/assets/img/icons/mediatype/software.js +9 -6
  32. package/dist/src/assets/img/icons/mediatype/software.js.map +1 -1
  33. package/dist/src/assets/img/icons/mediatype/texts.js +9 -6
  34. package/dist/src/assets/img/icons/mediatype/texts.js.map +1 -1
  35. package/dist/src/assets/img/icons/mediatype/tv.js +10 -5
  36. package/dist/src/assets/img/icons/mediatype/tv.js.map +1 -1
  37. package/dist/src/assets/img/icons/mediatype/video.js +10 -6
  38. package/dist/src/assets/img/icons/mediatype/video.js.map +1 -1
  39. package/dist/src/assets/img/icons/mediatype/web.js +9 -6
  40. package/dist/src/assets/img/icons/mediatype/web.js.map +1 -1
  41. package/dist/src/collection-browser.d.ts +53 -31
  42. package/dist/src/collection-browser.js +504 -166
  43. package/dist/src/collection-browser.js.map +1 -1
  44. package/dist/src/collection-facets.d.ts +28 -13
  45. package/dist/src/collection-facets.js +276 -160
  46. package/dist/src/collection-facets.js.map +1 -1
  47. package/dist/src/helpers.d.ts +1 -0
  48. package/dist/src/helpers.js +20 -0
  49. package/dist/src/helpers.js.map +1 -0
  50. package/dist/src/language-code-handler/language-code-handler.d.ts +37 -0
  51. package/dist/src/language-code-handler/language-code-handler.js +27 -0
  52. package/dist/src/language-code-handler/language-code-handler.js.map +1 -0
  53. package/dist/src/language-code-handler/language-code-mapping.d.ts +1 -0
  54. package/dist/src/language-code-handler/language-code-mapping.js +563 -0
  55. package/dist/src/language-code-handler/language-code-mapping.js.map +1 -0
  56. package/dist/src/mediatype/mediatype-color.d.ts +3 -0
  57. package/dist/src/mediatype/mediatype-color.js +15 -0
  58. package/dist/src/mediatype/mediatype-color.js.map +1 -0
  59. package/dist/src/mediatype/mediatype-config.d.ts +3 -0
  60. package/dist/src/mediatype/mediatype-config.js +86 -0
  61. package/dist/src/mediatype/mediatype-config.js.map +1 -0
  62. package/dist/src/mediatype/mediatype-display.d.ts +3 -0
  63. package/dist/src/mediatype/mediatype-display.js +86 -0
  64. package/dist/src/mediatype/mediatype-display.js.map +1 -0
  65. package/dist/src/mediatype/mediatype-icon.d.ts +10 -0
  66. package/dist/src/mediatype/mediatype-icon.js +105 -0
  67. package/dist/src/mediatype/mediatype-icon.js.map +1 -0
  68. package/dist/src/mediatype/mediatype-text.d.ts +3 -0
  69. package/dist/src/mediatype/mediatype-text.js +17 -0
  70. package/dist/src/mediatype/mediatype-text.js.map +1 -0
  71. package/dist/src/mediatype/mediatypeConfig.d.ts +3 -0
  72. package/dist/src/mediatype/mediatypeConfig.js +86 -0
  73. package/dist/src/mediatype/mediatypeConfig.js.map +1 -0
  74. package/dist/src/mediatype-icon.d.ts +2 -2
  75. package/dist/src/mediatype-icon.js +35 -46
  76. package/dist/src/mediatype-icon.js.map +1 -1
  77. package/dist/src/models.d.ts +72 -13
  78. package/dist/src/models.js +57 -1
  79. package/dist/src/models.js.map +1 -1
  80. package/dist/src/restoration-state-handler.d.ts +38 -0
  81. package/dist/src/restoration-state-handler.js +204 -0
  82. package/dist/src/restoration-state-handler.js.map +1 -0
  83. package/dist/src/sort-filter-bar/alpha-bar.d.ts +1 -1
  84. package/dist/src/sort-filter-bar/alpha-bar.js +9 -2
  85. package/dist/src/sort-filter-bar/alpha-bar.js.map +1 -1
  86. package/dist/src/sort-filter-bar/img/compact.d.ts +1 -0
  87. package/dist/src/sort-filter-bar/img/compact.js +5 -0
  88. package/dist/src/sort-filter-bar/img/compact.js.map +1 -0
  89. package/dist/src/sort-filter-bar/img/list.js +1 -1
  90. package/dist/src/sort-filter-bar/img/list.js.map +1 -1
  91. package/dist/src/sort-filter-bar/img/tile.d.ts +1 -0
  92. package/dist/src/sort-filter-bar/img/tile.js +5 -0
  93. package/dist/src/sort-filter-bar/img/tile.js.map +1 -0
  94. package/dist/src/sort-filter-bar/sort-filter-bar.d.ts +71 -14
  95. package/dist/src/sort-filter-bar/sort-filter-bar.js +499 -216
  96. package/dist/src/sort-filter-bar/sort-filter-bar.js.map +1 -1
  97. package/dist/src/tiles/collection-browser-loading-tile.d.ts +5 -0
  98. package/dist/src/tiles/collection-browser-loading-tile.js +32 -0
  99. package/dist/src/tiles/collection-browser-loading-tile.js.map +1 -0
  100. package/dist/src/tiles/grid/account-tile.d.ts +1 -1
  101. package/dist/src/tiles/grid/account-tile.js +5 -5
  102. package/dist/src/tiles/grid/account-tile.js.map +1 -1
  103. package/dist/src/tiles/grid/collection-tile.js +1 -2
  104. package/dist/src/tiles/grid/collection-tile.js.map +1 -1
  105. package/dist/src/tiles/grid/icons/views.d.ts +1 -1
  106. package/dist/src/tiles/grid/icons/views.js +2 -2
  107. package/dist/src/tiles/grid/icons/views.js.map +1 -1
  108. package/dist/src/tiles/grid/item-tile.d.ts +2 -2
  109. package/dist/src/tiles/grid/item-tile.js +58 -150
  110. package/dist/src/tiles/grid/item-tile.js.map +1 -1
  111. package/dist/src/tiles/item-image.d.ts +21 -0
  112. package/dist/src/tiles/item-image.js +215 -0
  113. package/dist/src/tiles/item-image.js.map +1 -0
  114. package/dist/src/tiles/list/account-label.d.ts +1 -0
  115. package/dist/src/tiles/list/account-label.js +7 -0
  116. package/dist/src/tiles/list/account-label.js.map +1 -0
  117. package/dist/src/tiles/list/date-label.d.ts +1 -0
  118. package/dist/src/tiles/list/date-label.js +13 -0
  119. package/dist/src/tiles/list/date-label.js.map +1 -0
  120. package/dist/src/tiles/list/tile-list-compact-header.d.ts +12 -0
  121. package/dist/src/tiles/list/tile-list-compact-header.js +84 -0
  122. package/dist/src/tiles/list/tile-list-compact-header.js.map +1 -0
  123. package/dist/src/tiles/list/tile-list-compact.d.ts +12 -0
  124. package/dist/src/tiles/list/tile-list-compact.js +203 -6
  125. package/dist/src/tiles/list/tile-list-compact.js.map +1 -1
  126. package/dist/src/tiles/list/tile-list.d.ts +35 -10
  127. package/dist/src/tiles/list/tile-list.js +368 -104
  128. package/dist/src/tiles/list/tile-list.js.map +1 -1
  129. package/dist/src/tiles/loading-tile.js +1 -42
  130. package/dist/src/tiles/loading-tile.js.map +1 -1
  131. package/dist/src/tiles/mediatype-icon.d.ts +9 -0
  132. package/dist/src/tiles/mediatype-icon.js +78 -0
  133. package/dist/src/tiles/mediatype-icon.js.map +1 -0
  134. package/dist/src/tiles/tile-dispatcher.d.ts +11 -4
  135. package/dist/src/tiles/tile-dispatcher.js +56 -19
  136. package/dist/src/tiles/tile-dispatcher.js.map +1 -1
  137. package/dist/src/utils/format-date.js +2 -2
  138. package/dist/src/utils/format-date.js.map +1 -1
  139. package/dist/src/waveform-thumbnail.d.ts +7 -0
  140. package/dist/src/waveform-thumbnail.js +106 -0
  141. package/dist/src/waveform-thumbnail.js.map +1 -0
  142. package/dist/{demo/icon-provider-icon.d.ts → src/waveform-view.d.ts} +0 -0
  143. package/dist/src/waveform-view.js +2 -0
  144. package/dist/src/waveform-view.js.map +1 -0
  145. package/dist/src/your-webcomponent.d.ts +8 -0
  146. package/dist/src/your-webcomponent.js +38 -0
  147. package/dist/src/your-webcomponent.js.map +1 -0
  148. package/dist/test/collection-browser.test.d.ts +1 -0
  149. package/dist/test/collection-browser.test.js +16 -2
  150. package/dist/test/collection-browser.test.js.map +1 -1
  151. package/dist/test/mediatype-config.test.d.ts +1 -0
  152. package/dist/test/mediatype-config.test.js +17 -0
  153. package/dist/test/mediatype-config.test.js.map +1 -0
  154. package/dist/{src/assets/img/icons/eye-hidden.d.ts → test/mediatype-icon.test.d.ts} +0 -0
  155. package/dist/test/mediatype-icon.test.js +3 -0
  156. package/dist/test/mediatype-icon.test.js.map +1 -0
  157. package/dist/test/mediatypeConfig.test.d.ts +1 -0
  158. package/dist/test/mediatypeConfig.test.js +17 -0
  159. package/dist/test/mediatypeConfig.test.js.map +1 -0
  160. package/dist/test/utils/format-date.test.js +1 -1
  161. package/dist/test/utils/format-date.test.js.map +1 -1
  162. package/dist/test/your-webcomponent.test.d.ts +1 -0
  163. package/dist/test/your-webcomponent.test.js +23 -0
  164. package/dist/test/your-webcomponent.test.js.map +1 -0
  165. package/index.ts +6 -0
  166. package/local.archive.org.cert +86 -0
  167. package/local.archive.org.key +27 -0
  168. package/package.json +9 -5
  169. package/src/assets/img/icons/chevron.ts +4 -0
  170. package/src/assets/img/icons/mediatype/account.ts +6 -4
  171. package/src/assets/img/icons/mediatype/audio.ts +7 -4
  172. package/src/assets/img/icons/mediatype/collection.ts +7 -4
  173. package/src/assets/img/icons/mediatype/data.ts +15 -0
  174. package/src/assets/img/icons/mediatype/etree.ts +10 -5
  175. package/src/assets/img/icons/mediatype/film.ts +2 -1
  176. package/src/assets/img/icons/mediatype/images.ts +9 -6
  177. package/src/assets/img/icons/mediatype/radio.ts +15 -0
  178. package/src/assets/img/icons/mediatype/software.ts +9 -6
  179. package/src/assets/img/icons/mediatype/texts.ts +9 -6
  180. package/src/assets/img/icons/mediatype/tv.ts +10 -5
  181. package/src/assets/img/icons/mediatype/video.ts +10 -6
  182. package/src/assets/img/icons/mediatype/web.ts +9 -6
  183. package/src/collection-browser.ts +529 -163
  184. package/src/collection-facets.ts +307 -205
  185. package/src/language-code-handler/language-code-handler.ts +64 -0
  186. package/src/language-code-handler/language-code-mapping.ts +564 -0
  187. package/src/mediatype/mediatype-config.ts +86 -0
  188. package/src/models.ts +141 -13
  189. package/src/restoration-state-handler.ts +266 -0
  190. package/src/sort-filter-bar/alpha-bar.ts +9 -3
  191. package/src/sort-filter-bar/img/compact.ts +5 -0
  192. package/src/sort-filter-bar/img/list.ts +1 -1
  193. package/src/sort-filter-bar/img/tile.ts +5 -0
  194. package/src/sort-filter-bar/sort-filter-bar.ts +557 -225
  195. package/src/tiles/collection-browser-loading-tile.ts +29 -0
  196. package/src/tiles/grid/account-tile.ts +1 -1
  197. package/src/tiles/grid/collection-tile.ts +1 -2
  198. package/src/tiles/grid/icons/views.ts +2 -2
  199. package/src/tiles/grid/item-tile.ts +57 -162
  200. package/src/tiles/item-image.ts +218 -0
  201. package/src/tiles/list/account-label.ts +6 -0
  202. package/src/tiles/list/date-label.ts +12 -0
  203. package/src/tiles/list/tile-list-compact-header.ts +77 -0
  204. package/src/tiles/list/tile-list-compact.ts +218 -0
  205. package/src/tiles/list/tile-list.ts +412 -107
  206. package/src/tiles/mediatype-icon.ts +75 -0
  207. package/src/tiles/tile-dispatcher.ts +66 -18
  208. package/src/utils/format-date.ts +2 -2
  209. package/test/collection-browser.test.ts +20 -1
  210. package/test/mediatype-config.test.ts +18 -0
  211. package/test/utils/format-date.test.ts +1 -1
  212. package/web-dev-server.config.mjs +3 -1
  213. package/dist/demo/icon-provider/icon-provider-icon.d.ts +0 -10
  214. package/dist/demo/icon-provider/icon-provider-icon.js +0 -32
  215. package/dist/demo/icon-provider/icon-provider-icon.js.map +0 -1
  216. package/dist/demo/icon-provider/icon-provider.d.ts +0 -10
  217. package/dist/demo/icon-provider/icon-provider.js +0 -9
  218. package/dist/demo/icon-provider/icon-provider.js.map +0 -1
  219. package/dist/demo/icon-provider-icon.js +0 -2
  220. package/dist/demo/icon-provider-icon.js.map +0 -1
  221. package/dist/demo/icon-provider.d.ts +0 -10
  222. package/dist/demo/icon-provider.js +0 -12
  223. package/dist/demo/icon-provider.js.map +0 -1
  224. package/dist/src/assets/img/icons/audio.d.ts +0 -1
  225. package/dist/src/assets/img/icons/audio.js +0 -9
  226. package/dist/src/assets/img/icons/audio.js.map +0 -1
  227. package/dist/src/assets/img/icons/collection.d.ts +0 -1
  228. package/dist/src/assets/img/icons/collection.js +0 -9
  229. package/dist/src/assets/img/icons/collection.js.map +0 -1
  230. package/dist/src/assets/img/icons/etree.d.ts +0 -1
  231. package/dist/src/assets/img/icons/etree.js +0 -9
  232. package/dist/src/assets/img/icons/etree.js.map +0 -1
  233. package/dist/src/assets/img/icons/eye-hidden.js +0 -2
  234. package/dist/src/assets/img/icons/eye-hidden.js.map +0 -1
  235. package/dist/src/assets/img/icons/images.d.ts +0 -1
  236. package/dist/src/assets/img/icons/images.js +0 -10
  237. package/dist/src/assets/img/icons/images.js.map +0 -1
  238. package/dist/src/assets/img/icons/mediatype/etree copy.d.ts +0 -1
  239. package/dist/src/assets/img/icons/mediatype/etree copy.js +0 -9
  240. package/dist/src/assets/img/icons/mediatype/etree copy.js.map +0 -1
  241. package/dist/src/assets/img/icons/software.d.ts +0 -1
  242. package/dist/src/assets/img/icons/software.js +0 -10
  243. package/dist/src/assets/img/icons/software.js.map +0 -1
  244. package/dist/src/assets/img/icons/texts.d.ts +0 -1
  245. package/dist/src/assets/img/icons/texts.js +0 -10
  246. package/dist/src/assets/img/icons/texts.js.map +0 -1
  247. package/dist/src/assets/img/icons/tv.d.ts +0 -1
  248. package/dist/src/assets/img/icons/tv.js +0 -9
  249. package/dist/src/assets/img/icons/tv.js.map +0 -1
  250. package/dist/src/assets/img/icons/video.d.ts +0 -1
  251. package/dist/src/assets/img/icons/video.js +0 -10
  252. package/dist/src/assets/img/icons/video.js.map +0 -1
  253. package/dist/src/assets/img/icons/web.d.ts +0 -1
  254. package/dist/src/assets/img/icons/web.js +0 -10
  255. package/dist/src/assets/img/icons/web.js.map +0 -1
  256. package/dist/src/search-handler.d.ts +0 -11
  257. package/dist/src/search-handler.js +0 -34
  258. package/dist/src/search-handler.js.map +0 -1
  259. package/src/mediatype-icon.ts +0 -83
  260. package/src/sort-filter-bar/img/grid.ts +0 -5
  261. package/src/tiles/loading-tile.ts +0 -70
@@ -1,19 +1,30 @@
1
- import { css, html, LitElement } from 'lit';
2
- import { customElement, property } from 'lit/decorators.js';
1
+ /* eslint-disable import/no-duplicates */
2
+ import {
3
+ css,
4
+ html,
5
+ LitElement,
6
+ PropertyValues,
7
+ nothing,
8
+ TemplateResult,
9
+ } from 'lit';
10
+ import { customElement, property, state } from 'lit/decorators.js';
3
11
  import { repeat } from 'lit/directives/repeat.js';
4
12
  import { Aggregation, Bucket } from '@internetarchive/search-service';
5
13
  import '@internetarchive/histogram-date-range';
6
14
  import '@internetarchive/feature-feedback';
15
+ import '@internetarchive/collection-name-cache';
16
+ import { CollectionNameCacheInterface } from '@internetarchive/collection-name-cache';
7
17
  import eyeIcon from './assets/img/icons/eye';
8
18
  import eyeClosedIcon from './assets/img/icons/eye-closed';
9
-
10
- type FacetOption =
11
- | 'subject'
12
- | 'mediatype'
13
- | 'language'
14
- | 'creator'
15
- | 'collection'
16
- | 'year';
19
+ import chevronIcon from './assets/img/icons/chevron';
20
+ import {
21
+ FacetOption,
22
+ SelectedFacets,
23
+ FacetGroup,
24
+ FacetBucket,
25
+ defaultSelectedFacets,
26
+ } from './models';
27
+ import { LanguageCodeHandlerInterface } from './language-code-handler/language-code-handler';
17
28
 
18
29
  const facetDisplayOrder: FacetOption[] = [
19
30
  'mediatype',
@@ -42,81 +53,84 @@ const facetTitles: Record<FacetOption, string> = {
42
53
  year: 'Year',
43
54
  };
44
55
 
45
- interface FacetBucket {
46
- // for some facets, we augment the key with a display value
47
- displayText?: string;
48
- key: string;
49
- count: number;
50
- selected: boolean;
51
- hidden: boolean;
52
- }
53
-
54
- interface FacetGroup {
55
- title: string;
56
- key: string;
57
- buckets: FacetBucket[];
58
- }
59
-
60
56
  @customElement('collection-facets')
61
57
  export class CollectionFacets extends LitElement {
62
58
  @property({ type: Object }) aggregations?: Record<string, Aggregation>;
63
59
 
64
60
  @property({ type: Object }) fullYearsHistogramAggregation?: Aggregation;
65
61
 
66
- @property({ type: Object }) selectedFacets: Record<string, string[]> = {};
62
+ @property({ type: String }) minSelectedDate?: string;
67
63
 
68
- @property({ type: Object }) hiddenFacets: Record<string, string[]> = {};
64
+ @property({ type: String }) maxSelectedDate?: string;
69
65
 
70
66
  @property({ type: Boolean }) facetsLoading = false;
71
67
 
72
68
  @property({ type: Boolean }) fullYearAggregationLoading = false;
73
69
 
74
- private get hydratedSelectedFacets(): Record<string, string[]> {
75
- const { selectedFacets } = this;
76
- const hydratedSelectedFacets: Record<string, string[]> = {};
77
- Object.entries(selectedFacets).forEach(([key]) => {
78
- const values = hydratedSelectedFacets[key];
79
- const title = facetTitles[key as FacetOption];
80
- hydratedSelectedFacets[title] = values || [];
81
- delete hydratedSelectedFacets[key];
82
- });
83
- return hydratedSelectedFacets;
84
- }
70
+ @property({ type: Object }) selectedFacets?: SelectedFacets;
71
+
72
+ @property({ type: Boolean }) collapsableFacets = false;
73
+
74
+ @property({ type: Boolean }) showHistogramDatePicker = false;
75
+
76
+ @property({ type: Object })
77
+ languageCodeHandler?: LanguageCodeHandlerInterface;
78
+
79
+ @property({ type: Object })
80
+ collectionNameCache?: CollectionNameCacheInterface;
81
+
82
+ @state() openFacets: Record<FacetOption, boolean> = {
83
+ subject: false,
84
+ mediatype: false,
85
+ language: false,
86
+ creator: false,
87
+ collection: false,
88
+ year: false,
89
+ };
85
90
 
86
91
  render() {
87
92
  return html`
88
93
  <div id="container" class="${this.facetsLoading ? 'loading' : ''}">
89
- <div class="facet-group">
90
- <h1>Year Published <feature-feedback></feature-feedback></h1>
91
- ${this.histogramTemplate}
92
- </div>
93
-
94
- ${this.mergedFacets.map(
95
- facetGroup =>
96
- html`
94
+ ${this.showHistogramDatePicker && this.fullYearsHistogramAggregation
95
+ ? html`
97
96
  <div class="facet-group">
98
- <h1>${facetGroup.title}</h1>
99
- ${this.getFacetTemplate(facetGroup)}
97
+ <h1>Year Published <feature-feedback></feature-feedback></h1>
98
+ ${this.histogramTemplate}
100
99
  </div>
101
100
  `
101
+ : nothing}
102
+ ${this.mergedFacets.map(facetGroup =>
103
+ this.getFacetGroupTemplate(facetGroup)
102
104
  )}
103
105
  </div>
104
106
  `;
105
107
  }
106
108
 
109
+ updated(changed: PropertyValues) {
110
+ if (changed.has('selectedFacets')) {
111
+ this.dispatchFacetsChangedEvent();
112
+ }
113
+ }
114
+
115
+ private dispatchFacetsChangedEvent() {
116
+ const event = new CustomEvent<SelectedFacets>('facetsChanged', {
117
+ detail: this.selectedFacets,
118
+ });
119
+ this.dispatchEvent(event);
120
+ }
121
+
107
122
  private get currentYearsHistogramAggregation(): Aggregation | undefined {
108
123
  return this.aggregations?.year_histogram;
109
124
  }
110
125
 
111
126
  private get histogramTemplate() {
112
- const { currentYearsHistogramAggregation, fullYearsHistogramAggregation } =
113
- this;
127
+ const { fullYearsHistogramAggregation } = this;
114
128
  return html`
115
129
  <histogram-date-range
116
130
  .minDate=${fullYearsHistogramAggregation?.first_bucket_key}
117
131
  .maxDate=${fullYearsHistogramAggregation?.last_bucket_key}
118
- .minSelectedDate=${currentYearsHistogramAggregation?.first_bucket_key}
119
- .maxSelectedDate=${currentYearsHistogramAggregation?.last_bucket_key}
132
+ .minSelectedDate=${this.minSelectedDate}
133
+ .maxSelectedDate=${this.maxSelectedDate}
120
134
  .updateDelay=${100}
121
135
  missingDataMessage="..."
122
136
  .width=${180}
@@ -140,7 +154,7 @@ export class CollectionFacets extends LitElement {
140
154
  }
141
155
 
142
156
  /**
143
- * Combines the selected and hidden facets with the aggregations to create a single list of facets
157
+ * Combines the selected facets with the aggregations to create a single list of facets
144
158
  */
145
159
  private get mergedFacets(): FacetGroup[] {
146
160
  const facetGroups: FacetGroup[] = [];
@@ -149,9 +163,6 @@ export class CollectionFacets extends LitElement {
149
163
  const selectedFacetGroup = this.selectedFacetGroups.find(
150
164
  group => group.key === facetKey
151
165
  );
152
- const hiddenFacetGroup = this.hiddenFacetGroups.find(
153
- group => group.key === facetKey
154
- );
155
166
  const aggregateFacetGroup = this.aggregationFacetGroups.find(
156
167
  group => group.key === facetKey
157
168
  );
@@ -162,17 +173,11 @@ export class CollectionFacets extends LitElement {
162
173
  return;
163
174
  }
164
175
 
165
- if (hiddenFacetGroup && !aggregateFacetGroup) {
166
- facetGroups.push(hiddenFacetGroup);
167
- return;
168
- }
169
-
170
176
  // if we don't have an aggregate facet group, don't add this to the list
171
177
  if (!aggregateFacetGroup) return;
172
178
 
173
179
  // start with either the selected group if we have one, or the aggregate group
174
- const facetGroup =
175
- selectedFacetGroup ?? hiddenFacetGroup ?? aggregateFacetGroup;
180
+ const facetGroup = selectedFacetGroup ?? aggregateFacetGroup;
176
181
 
177
182
  // attach the counts to the selected buckets
178
183
  const bucketsWithCount =
@@ -180,27 +185,13 @@ export class CollectionFacets extends LitElement {
180
185
  const selectedBucket = aggregateFacetGroup.buckets.find(
181
186
  b => b.key === bucket.key
182
187
  );
183
- if (selectedBucket) {
184
- return {
185
- ...bucket,
186
- count: selectedBucket.count,
187
- };
188
- }
189
- return bucket;
190
- }) ??
191
- hiddenFacetGroup?.buckets.map(bucket => {
192
- const selectedBucket = aggregateFacetGroup.buckets.find(
193
- b => b.key === bucket.key
194
- );
195
- if (selectedBucket) {
196
- return {
197
- ...bucket,
198
- count: selectedBucket.count,
199
- };
200
- }
201
- return bucket;
202
- }) ??
203
- [];
188
+ return selectedBucket
189
+ ? {
190
+ ...bucket,
191
+ count: selectedBucket.count,
192
+ }
193
+ : bucket;
194
+ }) ?? [];
204
195
 
205
196
  // append any additional buckets that were not selected
206
197
  aggregateFacetGroup.buckets.forEach(bucket => {
@@ -210,8 +201,6 @@ export class CollectionFacets extends LitElement {
210
201
  });
211
202
  facetGroup.buckets = bucketsWithCount.splice(0, 5);
212
203
 
213
- // if (facetGroup.buckets.length === 0) return;
214
-
215
204
  facetGroups.push(facetGroup);
216
205
  });
217
206
 
@@ -219,35 +208,45 @@ export class CollectionFacets extends LitElement {
219
208
  }
220
209
 
221
210
  /**
222
- * Converts the raw `selectedFacets` to `FacetGroups`, which are easier to use
211
+ * Converts the selected facets to a `FacetGroup` array,
212
+ * which is easier to work with
223
213
  */
224
214
  private get selectedFacetGroups(): FacetGroup[] {
225
- return this.getFacetGroups(this.selectedFacets, false);
226
- }
215
+ if (!this.selectedFacets) return [];
216
+
217
+ const facetGroups: FacetGroup[] = Object.entries(this.selectedFacets).map(
218
+ ([key, selectedFacets]) => {
219
+ const option = key as FacetOption;
220
+ const title = facetTitles[option];
221
+
222
+ const buckets: FacetBucket[] = Object.entries(selectedFacets).map(
223
+ ([value, facetState]) => {
224
+ let displayText = value;
225
+ // for selected languages, we store the language code instead of the
226
+ // display name, so look up the name from the mapping
227
+ if (option === 'language') {
228
+ displayText =
229
+ this.languageCodeHandler?.getLanguageNameFromCodeString(
230
+ value
231
+ ) ?? value;
232
+ }
233
+ return {
234
+ displayText,
235
+ key: value,
236
+ count: 0,
237
+ state: facetState,
238
+ };
239
+ }
240
+ );
227
241
 
228
- private get hiddenFacetGroups(): FacetGroup[] {
229
- return this.getFacetGroups(this.hiddenFacets, true);
230
- }
242
+ return {
243
+ title,
244
+ key: option,
245
+ buckets,
246
+ };
247
+ }
248
+ );
231
249
 
232
- private getFacetGroups(
233
- facets: Record<string, string[]>,
234
- hidden: boolean
235
- ): FacetGroup[] {
236
- const facetGroups: FacetGroup[] = [];
237
- Object.entries(facets).forEach(([key, buckets]) => {
238
- const title = facetTitles[key as FacetOption];
239
- const group = {
240
- title,
241
- key,
242
- buckets: buckets.map(bucket => ({
243
- key: bucket,
244
- count: 0,
245
- selected: !hidden,
246
- hidden,
247
- })),
248
- };
249
- facetGroups.push(group);
250
- });
251
250
  return facetGroups;
252
251
  }
253
252
 
@@ -257,16 +256,30 @@ export class CollectionFacets extends LitElement {
257
256
  private get aggregationFacetGroups(): FacetGroup[] {
258
257
  const facetGroups: FacetGroup[] = [];
259
258
  Object.entries(this.aggregations ?? []).forEach(([key, buckets]) => {
259
+ // the year_histogram data is in a different format so can't be handled here
260
260
  if (key === 'year_histogram') return;
261
261
  const option = this.getFacetOptionFromKey(key);
262
262
  const title = facetTitles[option];
263
263
  const castedBuckets = buckets.buckets as Bucket[];
264
- const facetBuckets: FacetBucket[] = castedBuckets.map(bucket => ({
265
- key: `${bucket.key}`,
266
- count: bucket.doc_count,
267
- selected: false,
268
- hidden: false,
269
- }));
264
+ const facetBuckets: FacetBucket[] = castedBuckets.map(bucket => {
265
+ let bucketKey = bucket.key;
266
+ // for languages, we need to search by language code instead of the
267
+ // display name, which is what we get from the search engine result
268
+ if (option === 'language') {
269
+ // const languageCodeKey = languageToCodeMap[bucket.key];
270
+ bucketKey =
271
+ this.languageCodeHandler?.getCodeStringFromLanguageName(
272
+ `${bucket.key}`
273
+ ) ?? bucket.key;
274
+ // bucketKey = languageCodeKey ?? bucket.key;
275
+ }
276
+ return {
277
+ displayText: `${bucket.key}`,
278
+ key: `${bucketKey}`,
279
+ count: bucket.doc_count,
280
+ state: 'none',
281
+ };
282
+ });
270
283
  const group: FacetGroup = {
271
284
  title,
272
285
  key: option,
@@ -277,42 +290,133 @@ export class CollectionFacets extends LitElement {
277
290
  return facetGroups;
278
291
  }
279
292
 
280
- private getFacetTemplate(facetGroup: FacetGroup) {
293
+ /**
294
+ * Generate the template for a facet group with a header and the collapsible
295
+ * chevron for the mobile view
296
+ */
297
+ private getFacetGroupTemplate(
298
+ facetGroup: FacetGroup
299
+ ): TemplateResult | typeof nothing {
300
+ if (facetGroup.buckets.length === 0) return nothing;
301
+ const { key } = facetGroup;
302
+ const isOpen = this.openFacets[key];
303
+ const collapser = html`
304
+ <span class="collapser ${isOpen ? 'open' : ''}"> ${chevronIcon} </span>
305
+ `;
306
+
307
+ return html`
308
+ <div class="facet-group ${this.collapsableFacets ? 'mobile' : ''}">
309
+ <h1
310
+ @click=${() => {
311
+ const newOpenFacets = { ...this.openFacets };
312
+ newOpenFacets[key] = !isOpen;
313
+ this.openFacets = newOpenFacets;
314
+ }}
315
+ @keyup=${() => {
316
+ const newOpenFacets = { ...this.openFacets };
317
+ newOpenFacets[key] = !isOpen;
318
+ this.openFacets = newOpenFacets;
319
+ }}
320
+ >
321
+ ${this.collapsableFacets ? collapser : nothing} ${facetGroup.title}
322
+ </h1>
323
+ <div class="facet-group-content ${isOpen ? 'open' : ''}">
324
+ ${this.getFacetTemplate(facetGroup)}
325
+ </div>
326
+ </div>
327
+ `;
328
+ }
329
+
330
+ /**
331
+ * Generate the list template for each bucket in a facet group
332
+ */
333
+ private getFacetTemplate(facetGroup: FacetGroup): TemplateResult {
334
+ const bucketsNoFavorites = facetGroup.buckets.filter(
335
+ bucket => bucket.key.startsWith('fav-') === false
336
+ );
337
+ const bucketsMaxSix = bucketsNoFavorites.slice(0, 6);
338
+
281
339
  return html`
282
340
  <ul class="facet-list">
283
341
  ${repeat(
284
- facetGroup.buckets,
342
+ bucketsMaxSix,
285
343
  bucket => `${facetGroup.key}:${bucket.key}`,
286
344
  bucket => {
287
- const hiddenCheckboxId = `${facetGroup.key}:${bucket.key}-hidden`;
345
+ const showOnlyCheckboxId = `${facetGroup.key}:${bucket.key}-show-only`;
346
+ const negativeCheckboxId = `${facetGroup.key}:${bucket.key}-negative`;
347
+
348
+ // for collections, we need to asynchronously load the collection name
349
+ // so we use the `async-collection-name` widget and for the rest, we have
350
+ // a static value to use
351
+ const bucketTextDisplay =
352
+ facetGroup.key !== 'collection'
353
+ ? html`${bucket.displayText ?? bucket.key}`
354
+ : html`
355
+ <async-collection-name
356
+ .collectionNameCache=${this.collectionNameCache}
357
+ .identifier=${bucket.key}
358
+ placeholder="-"
359
+ ></async-collection-name>
360
+ `;
361
+
362
+ const facetHidden = bucket.state === 'hidden';
363
+ const facetSelected = bucket.state === 'selected';
364
+
365
+ const titleText = `${facetGroup.key}: ${
366
+ bucket.displayText ?? bucket.key
367
+ }`;
368
+ const onlyShowText = facetSelected
369
+ ? `Show all ${facetGroup.key}s`
370
+ : `Only show ${titleText}`;
371
+ const hideText = `Hide ${titleText}`;
372
+ const unhideText = `Unhide ${titleText}`;
373
+ const showHideText = facetHidden ? unhideText : hideText;
374
+
288
375
  return html`
289
376
  <li>
290
- <label class="facet-row">
377
+ <div class="facet-row">
291
378
  <div class="facet-checkbox">
292
379
  <input
293
380
  type="checkbox"
294
381
  .name=${facetGroup.key}
295
382
  .value=${bucket.key}
296
- @click=${this.facetToggled}
297
- ?checked=${bucket.selected}
383
+ @click=${(e: Event) => {
384
+ this.facetClicked(e, bucket, false);
385
+ }}
386
+ .checked=${facetSelected}
298
387
  class="select-facet-checkbox"
388
+ title=${onlyShowText}
389
+ id=${showOnlyCheckboxId}
299
390
  />
300
391
  <input
301
392
  type="checkbox"
302
- id=${hiddenCheckboxId}
393
+ id=${negativeCheckboxId}
303
394
  .name=${facetGroup.key}
304
395
  .value=${bucket.key}
305
- @click=${this.hideFacetToggled}
306
- ?checked=${bucket.hidden}
396
+ @click=${(e: Event) => {
397
+ this.facetClicked(e, bucket, true);
398
+ }}
399
+ .checked=${facetHidden}
307
400
  class="hide-facet-checkbox"
308
401
  />
309
- <label for=${hiddenCheckboxId} class="hide-facet-icon">
310
- ${bucket.hidden ? eyeClosedIcon : eyeIcon}
402
+ <label
403
+ for=${negativeCheckboxId}
404
+ class="hide-facet-icon"
405
+ title=${showHideText}
406
+ >
407
+ ${facetHidden ? eyeClosedIcon : eyeIcon}
311
408
  </label>
312
409
  </div>
313
- <div class="facet-title">${bucket.key}</div>
314
- <div class="facet-count">${bucket.count}</div>
315
- </label>
410
+
411
+ <label
412
+ for=${showOnlyCheckboxId}
413
+ class="facet-info-display"
414
+ title=${onlyShowText}
415
+ >
416
+ <div class="facet-title">${bucketTextDisplay}</div>
417
+ <div class="facet-count">${bucket.count}</div>
418
+ </label>
419
+ </div>
316
420
  </li>
317
421
  `;
318
422
  }
@@ -321,91 +425,42 @@ export class CollectionFacets extends LitElement {
321
425
  `;
322
426
  }
323
427
 
324
- private facetChecked(name: string, value: string) {
325
- const { selectedFacets } = this;
326
- const facetClone = { ...selectedFacets };
327
- const currentFacetValues = facetClone[name];
328
- if (currentFacetValues) {
329
- currentFacetValues.push(value);
330
- facetClone[name] = currentFacetValues;
331
- } else {
332
- facetClone[name] = [value];
333
- }
334
- this.selectedFacets = facetClone;
335
- }
336
-
337
- private facetUnchecked(name: string, value: string) {
338
- const { selectedFacets } = this;
339
- const facetClone = { ...selectedFacets };
340
- let currentFacetValues = selectedFacets[name];
341
- if (currentFacetValues) {
342
- currentFacetValues = currentFacetValues.filter(el => el !== value);
343
- facetClone[name] = currentFacetValues;
344
- if (currentFacetValues.length === 0) {
345
- delete facetClone[name];
346
- }
347
- }
348
- this.selectedFacets = facetClone;
349
- }
350
-
351
- private facetToggled(e: Event) {
428
+ private facetClicked(e: Event, bucket: FacetBucket, negative: boolean) {
352
429
  const target = e.target as HTMLInputElement;
353
430
  const { checked, name, value } = target;
354
431
  if (checked) {
355
- this.facetChecked(name, value);
432
+ this.facetChecked(name as FacetOption, value, negative);
356
433
  } else {
357
- this.facetUnchecked(name, value);
434
+ this.facetUnchecked(name as FacetOption, value);
358
435
  }
359
-
360
- const event = new CustomEvent<Record<string, string[]>>('facetsChanged', {
361
- detail: this.selectedFacets,
362
- });
363
- this.dispatchEvent(event);
364
436
  }
365
437
 
366
- private hideFacetToggled(e: Event) {
367
- const target = e.target as HTMLInputElement;
368
- const { checked, name, value } = target;
369
- if (checked) {
370
- this.facetHidden(name, value);
438
+ private facetChecked(key: FacetOption, value: string, negative: boolean) {
439
+ const { selectedFacets } = this;
440
+ let newFacets: SelectedFacets;
441
+ if (selectedFacets) {
442
+ newFacets = {
443
+ ...selectedFacets,
444
+ };
371
445
  } else {
372
- this.facetUnhidden(name, value);
446
+ newFacets = defaultSelectedFacets;
373
447
  }
374
-
375
- const event = new CustomEvent<Record<string, string[]>>(
376
- 'hiddenFacetsChanged',
377
- {
378
- detail: this.hiddenFacets,
379
- }
380
- );
381
- this.dispatchEvent(event);
448
+ newFacets[key][value] = negative ? 'hidden' : 'selected';
449
+ this.selectedFacets = newFacets;
382
450
  }
383
451
 
384
- private facetHidden(name: string, value: string) {
385
- const { hiddenFacets } = this;
386
- const facetClone = { ...hiddenFacets };
387
- const currentFacetValues = facetClone[name];
388
- if (currentFacetValues) {
389
- currentFacetValues.push(value);
390
- facetClone[name] = currentFacetValues;
452
+ private facetUnchecked(key: FacetOption, value: string) {
453
+ const { selectedFacets } = this;
454
+ let newFacets: SelectedFacets;
455
+ if (selectedFacets) {
456
+ newFacets = {
457
+ ...selectedFacets,
458
+ };
391
459
  } else {
392
- facetClone[name] = [value];
393
- }
394
- this.hiddenFacets = facetClone;
395
- }
396
-
397
- private facetUnhidden(name: string, value: string) {
398
- const { hiddenFacets } = this;
399
- const facetClone = { ...hiddenFacets };
400
- let currentFacetValues = hiddenFacets[name];
401
- if (currentFacetValues) {
402
- currentFacetValues = currentFacetValues.filter(el => el !== value);
403
- facetClone[name] = currentFacetValues;
404
- if (currentFacetValues.length === 0) {
405
- delete facetClone[name];
406
- }
460
+ newFacets = defaultSelectedFacets;
407
461
  }
408
- this.hiddenFacets = facetClone;
462
+ delete newFacets[key][value];
463
+ this.selectedFacets = newFacets;
409
464
  }
410
465
 
411
466
  /**
@@ -434,12 +489,52 @@ export class CollectionFacets extends LitElement {
434
489
  opacity: 0.5;
435
490
  }
436
491
 
492
+ .collapser {
493
+ display: inline-block;
494
+ cursor: pointer;
495
+ width: 10px;
496
+ height: 10px;
497
+ }
498
+
499
+ .collapser svg {
500
+ transition: transform 0.2s ease-in-out;
501
+ }
502
+
503
+ .collapser.open svg {
504
+ transform: rotate(90deg);
505
+ }
506
+
507
+ .facet-group {
508
+ margin-bottom: 2rem;
509
+ }
510
+
511
+ .facet-group h1 {
512
+ margin-bottom: 0.7rem;
513
+ }
514
+
515
+ .facet-group.mobile h1 {
516
+ cursor: pointer;
517
+ }
518
+
519
+ .facet-group-content {
520
+ transition: max-height 0.2s ease-in-out;
521
+ }
522
+
523
+ .facet-group.mobile .facet-group-content {
524
+ max-height: 0;
525
+ overflow: hidden;
526
+ }
527
+
528
+ .facet-group.mobile .facet-group-content.open {
529
+ max-height: 2000px;
530
+ }
531
+
437
532
  h1 {
438
533
  font-size: 1.4rem;
439
534
  font-weight: 200;
440
535
  border-bottom: 1px solid rgb(232, 232, 232);
441
536
  padding-bottom: 3px;
442
- margin: 24px 0 14px 0;
537
+ margin: 0;
443
538
  }
444
539
 
445
540
  ul.facet-list {
@@ -460,11 +555,17 @@ export class CollectionFacets extends LitElement {
460
555
 
461
556
  .facet-row {
462
557
  display: flex;
463
- align-items: center;
558
+ align-items: start;
464
559
  font-weight: 500;
465
560
  font-size: 1.2rem;
466
561
  }
467
562
 
563
+ .facet-info-display {
564
+ display: flex;
565
+ flex: 1;
566
+ cursor: pointer;
567
+ }
568
+
468
569
  .facet-title {
469
570
  flex: 1;
470
571
  }
@@ -474,6 +575,7 @@ export class CollectionFacets extends LitElement {
474
575
  }
475
576
 
476
577
  .select-facet-checkbox {
578
+ cursor: pointer;
477
579
  margin-right: 5px;
478
580
  }
479
581