@internetarchive/collection-browser 0.4.16-alpha.8 → 0.4.16
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.
- package/dist/src/app-root.js +12 -0
- package/dist/src/app-root.js.map +1 -1
- package/dist/src/collection-browser.d.ts +53 -14
- package/dist/src/collection-browser.js +262 -116
- package/dist/src/collection-browser.js.map +1 -1
- package/dist/src/collection-facets/facets-template.d.ts +3 -0
- package/dist/src/collection-facets/facets-template.js +20 -1
- package/dist/src/collection-facets/facets-template.js.map +1 -1
- package/dist/src/collection-facets/more-facets-content.js +7 -4
- package/dist/src/collection-facets/more-facets-content.js.map +1 -1
- package/dist/src/collection-facets.d.ts +0 -2
- package/dist/src/collection-facets.js +1 -4
- package/dist/src/collection-facets.js.map +1 -1
- package/dist/src/empty-placeholder.js +1 -0
- package/dist/src/empty-placeholder.js.map +1 -1
- package/dist/src/models.d.ts +5 -0
- package/dist/src/models.js.map +1 -1
- package/dist/src/tiles/grid/item-tile.js +10 -3
- package/dist/src/tiles/grid/item-tile.js.map +1 -1
- package/dist/src/tiles/list/tile-list-compact.d.ts +1 -0
- package/dist/src/tiles/list/tile-list-compact.js +13 -1
- package/dist/src/tiles/list/tile-list-compact.js.map +1 -1
- package/dist/src/tiles/list/tile-list.js +10 -1
- package/dist/src/tiles/list/tile-list.js.map +1 -1
- package/dist/src/utils/format-date.d.ts +1 -1
- package/dist/src/utils/format-date.js +3 -0
- package/dist/src/utils/format-date.js.map +1 -1
- package/dist/src/utils/local-date-from-utc.d.ts +9 -0
- package/dist/src/utils/local-date-from-utc.js +16 -0
- package/dist/src/utils/local-date-from-utc.js.map +1 -0
- package/dist/test/collection-browser.test.js +41 -10
- package/dist/test/collection-browser.test.js.map +1 -1
- package/dist/test/collection-facets/facets-template.test.js +80 -0
- package/dist/test/collection-facets/facets-template.test.js.map +1 -1
- package/dist/test/tiles/grid/item-tile.test.js +124 -3
- package/dist/test/tiles/grid/item-tile.test.js.map +1 -1
- package/dist/test/tiles/list/tile-list-compact.test.js +65 -20
- package/dist/test/tiles/list/tile-list-compact.test.js.map +1 -1
- package/dist/test/tiles/list/tile-list.test.js +106 -4
- package/dist/test/tiles/list/tile-list.test.js.map +1 -1
- package/dist/test/utils/local-date-from-utc.test.d.ts +1 -0
- package/dist/test/utils/local-date-from-utc.test.js +27 -0
- package/dist/test/utils/local-date-from-utc.test.js.map +1 -0
- package/index.html +1 -0
- package/package.json +1 -1
- package/src/app-root.ts +12 -0
- package/src/collection-browser.ts +300 -126
- package/src/collection-facets/facets-template.ts +32 -1
- package/src/collection-facets/more-facets-content.ts +4 -1
- package/src/collection-facets.ts +1 -8
- package/src/empty-placeholder.ts +1 -0
- package/src/models.ts +6 -0
- package/src/tiles/grid/item-tile.ts +11 -4
- package/src/tiles/list/tile-list-compact.ts +16 -2
- package/src/tiles/list/tile-list.ts +12 -5
- package/src/utils/format-date.ts +4 -0
- package/src/utils/local-date-from-utc.ts +15 -0
- package/test/collection-browser.test.ts +57 -12
- package/test/collection-facets/facets-template.test.ts +98 -0
- package/test/tiles/grid/item-tile.test.ts +145 -3
- package/test/tiles/list/tile-list-compact.test.ts +70 -19
- package/test/tiles/list/tile-list.test.ts +118 -4
- package/test/utils/local-date-from-utc.test.ts +37 -0
|
@@ -82,6 +82,30 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
82
82
|
* for the previous/next page, we'll fetch the next/previous page to populate it
|
|
83
83
|
*/
|
|
84
84
|
this.dataSource = {};
|
|
85
|
+
/**
|
|
86
|
+
* Updates the height of the left column according to its position on the page.
|
|
87
|
+
* Arrow function ensures proper `this` binding.
|
|
88
|
+
*/
|
|
89
|
+
this.updateLeftColumnHeight = () => {
|
|
90
|
+
var _a, _b, _c, _d, _e;
|
|
91
|
+
if (this.mobileView) {
|
|
92
|
+
(_b = (_a = this.leftColumn) === null || _a === void 0 ? void 0 : _a.style) === null || _b === void 0 ? void 0 : _b.removeProperty('height');
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
const clientTop = (_c = this.leftColumn) === null || _c === void 0 ? void 0 : _c.getBoundingClientRect().top;
|
|
96
|
+
(_e = (_d = this.leftColumn) === null || _d === void 0 ? void 0 : _d.style) === null || _e === void 0 ? void 0 : _e.setProperty('height', `${window.innerHeight - (clientTop !== null && clientTop !== void 0 ? clientTop : 0) - 3}px`);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Toggles whether the fade-out is visible at the bottom of the facets.
|
|
101
|
+
* It should only be visible if the facets are not scrolled to the bottom.
|
|
102
|
+
* Arrow function ensures proper `this` binding.
|
|
103
|
+
*/
|
|
104
|
+
this.updateFacetFadeOut = (entries) => {
|
|
105
|
+
var _a, _b;
|
|
106
|
+
const fadeElmt = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.getElementById('facets-bottom-fade');
|
|
107
|
+
fadeElmt === null || fadeElmt === void 0 ? void 0 : fadeElmt.classList.toggle('hidden', (_b = entries === null || entries === void 0 ? void 0 : entries[0]) === null || _b === void 0 ? void 0 : _b.isIntersecting);
|
|
108
|
+
};
|
|
85
109
|
// we only want to scroll on the very first query change
|
|
86
110
|
// so this keeps track of whether we've already set the initial query
|
|
87
111
|
this.initialQueryChangeHappened = false;
|
|
@@ -150,8 +174,6 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
150
174
|
if (letterFilters) {
|
|
151
175
|
this.selectedTitleFilter = null;
|
|
152
176
|
this.selectedCreatorFilter = null;
|
|
153
|
-
this.titleQuery = undefined;
|
|
154
|
-
this.creatorQuery = undefined;
|
|
155
177
|
}
|
|
156
178
|
if (sort) {
|
|
157
179
|
this.sortParam = null;
|
|
@@ -193,8 +215,8 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
193
215
|
if (!((_a = this.baseQuery) === null || _a === void 0 ? void 0 : _a.trim())) {
|
|
194
216
|
this.placeholderType = 'empty-query';
|
|
195
217
|
}
|
|
196
|
-
if (
|
|
197
|
-
!this.searchService) {
|
|
218
|
+
else if (!this.searchResultsLoading &&
|
|
219
|
+
(this.totalResults === 0 || !this.searchService)) {
|
|
198
220
|
this.placeholderType = 'null-result';
|
|
199
221
|
}
|
|
200
222
|
if (this.queryErrorMessage) {
|
|
@@ -218,7 +240,8 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
218
240
|
const shouldShowSearching = this.searchResultsLoading || this.totalResults === undefined;
|
|
219
241
|
const resultsCount = (_a = this.totalResults) === null || _a === void 0 ? void 0 : _a.toLocaleString();
|
|
220
242
|
const resultsLabel = this.totalResults === 1 ? 'Result' : 'Results';
|
|
221
|
-
return html
|
|
243
|
+
return html ` <div id="left-column-scroll-sentinel"></div>
|
|
244
|
+
<div
|
|
222
245
|
id="left-column"
|
|
223
246
|
class="column${this.isResizeToMobile ? ' preload' : ''}"
|
|
224
247
|
>
|
|
@@ -240,7 +263,9 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
240
263
|
: ''}
|
|
241
264
|
>
|
|
242
265
|
${this.facetsTemplate}
|
|
266
|
+
<div id="facets-scroll-sentinel"></div>
|
|
243
267
|
</div>
|
|
268
|
+
${this.mobileView ? nothing : html `<div id="facets-bottom-fade"></div>`}
|
|
244
269
|
</div>
|
|
245
270
|
<div id="right-column" class="column">
|
|
246
271
|
${this.sortFilterBarTemplate}
|
|
@@ -305,7 +330,6 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
305
330
|
});
|
|
306
331
|
}
|
|
307
332
|
selectedSortChanged() {
|
|
308
|
-
console.log('selectedSortChanged');
|
|
309
333
|
if (this.selectedSort === 'relevance') {
|
|
310
334
|
this.sortParam = null;
|
|
311
335
|
return;
|
|
@@ -317,7 +341,6 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
317
341
|
return;
|
|
318
342
|
this.sortParam = { field: sortField, direction: this.sortDirection };
|
|
319
343
|
// Lazy-load the alphabet counts for title/creator sort bar as needed
|
|
320
|
-
console.log('will update prefix filters for current sort');
|
|
321
344
|
this.updatePrefixFiltersForCurrentSort();
|
|
322
345
|
}
|
|
323
346
|
displayModeChanged(e) {
|
|
@@ -331,9 +354,28 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
331
354
|
});
|
|
332
355
|
}
|
|
333
356
|
}
|
|
334
|
-
/**
|
|
357
|
+
/**
|
|
358
|
+
* Returns a query clause identifying the currently selected title filter,
|
|
359
|
+
* e.g., `firstTitle:X`.
|
|
360
|
+
*/
|
|
361
|
+
get titleQuery() {
|
|
362
|
+
return this.selectedTitleFilter
|
|
363
|
+
? `firstTitle:${this.selectedTitleFilter}`
|
|
364
|
+
: undefined;
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Returns a query clause identifying the currently selected creator filter,
|
|
368
|
+
* e.g., `firstCreator:X`.
|
|
369
|
+
*/
|
|
370
|
+
get creatorQuery() {
|
|
371
|
+
return this.selectedCreatorFilter
|
|
372
|
+
? `firstCreator:${this.selectedCreatorFilter}`
|
|
373
|
+
: undefined;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Send Analytics when sorting by title's first letter
|
|
335
377
|
* labels: 'start-<ToLetter>' | 'clear-<FromLetter>' | '<FromLetter>-<ToLetter>'
|
|
336
|
-
|
|
378
|
+
*/
|
|
337
379
|
sendFilterByTitleAnalytics(prevSelectedLetter) {
|
|
338
380
|
var _a;
|
|
339
381
|
if (!prevSelectedLetter && !this.selectedTitleFilter) {
|
|
@@ -348,14 +390,10 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
348
390
|
: `${prevSelectedLetter || 'start'}-${this.selectedTitleFilter}`,
|
|
349
391
|
});
|
|
350
392
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
? `firstTitle:${this.selectedTitleFilter}`
|
|
354
|
-
: undefined;
|
|
355
|
-
}
|
|
356
|
-
/** Send Analytics when filtering by creator's first letter
|
|
393
|
+
/**
|
|
394
|
+
* Send Analytics when filtering by creator's first letter
|
|
357
395
|
* labels: 'start-<ToLetter>' | 'clear-<FromLetter>' | '<FromLetter>-<ToLetter>'
|
|
358
|
-
|
|
396
|
+
*/
|
|
359
397
|
sendFilterByCreatorAnalytics(prevSelectedLetter) {
|
|
360
398
|
var _a;
|
|
361
399
|
if (!prevSelectedLetter && !this.selectedCreatorFilter) {
|
|
@@ -370,20 +408,19 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
370
408
|
: `${prevSelectedLetter || 'start'}-${this.selectedCreatorFilter}`,
|
|
371
409
|
});
|
|
372
410
|
}
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
: undefined;
|
|
377
|
-
}
|
|
411
|
+
/**
|
|
412
|
+
* Handler for changes to which letter is selected in the title alphabet bar.
|
|
413
|
+
*/
|
|
378
414
|
titleLetterSelected(e) {
|
|
379
415
|
this.selectedCreatorFilter = null;
|
|
380
416
|
this.selectedTitleFilter = e.detail.selectedLetter;
|
|
381
|
-
this.selectedTitleLetterChanged();
|
|
382
417
|
}
|
|
418
|
+
/**
|
|
419
|
+
* Handler for changes to which letter is selected in the creator alphabet bar.
|
|
420
|
+
*/
|
|
383
421
|
creatorLetterSelected(e) {
|
|
384
422
|
this.selectedTitleFilter = null;
|
|
385
423
|
this.selectedCreatorFilter = e.detail.selectedLetter;
|
|
386
|
-
this.selectedCreatorLetterChanged();
|
|
387
424
|
}
|
|
388
425
|
get mobileFacetsTemplate() {
|
|
389
426
|
return html `
|
|
@@ -424,13 +461,13 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
424
461
|
.selectedFacets=${this.selectedFacets}
|
|
425
462
|
.collectionNameCache=${this.collectionNameCache}
|
|
426
463
|
.showHistogramDatePicker=${this.showHistogramDatePicker}
|
|
427
|
-
.query=${this.
|
|
464
|
+
.query=${this.baseQuery}
|
|
428
465
|
.filterMap=${this.filterMap}
|
|
429
466
|
.modalManager=${this.modalManager}
|
|
430
467
|
?collapsableFacets=${this.mobileView}
|
|
431
468
|
?facetsLoading=${this.facetsLoading}
|
|
432
469
|
?fullYearAggregationLoading=${this.facetsLoading}
|
|
433
|
-
|
|
470
|
+
@facetClick=${this.facetClickHandler}
|
|
434
471
|
.analyticsHandler=${this.analyticsHandler}
|
|
435
472
|
>
|
|
436
473
|
</collection-facets>
|
|
@@ -479,7 +516,15 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
479
516
|
}
|
|
480
517
|
updated(changed) {
|
|
481
518
|
var _a;
|
|
482
|
-
|
|
519
|
+
if (changed.has('placeholderType') && this.placeholderType === null) {
|
|
520
|
+
if (!this.leftColIntersectionObserver) {
|
|
521
|
+
this.setupLeftColumnScrollListeners();
|
|
522
|
+
}
|
|
523
|
+
if (!this.facetsIntersectionObserver) {
|
|
524
|
+
this.setupFacetsScrollListeners();
|
|
525
|
+
}
|
|
526
|
+
this.updateLeftColumnHeight();
|
|
527
|
+
}
|
|
483
528
|
if (changed.has('displayMode') ||
|
|
484
529
|
changed.has('baseNavigationUrl') ||
|
|
485
530
|
changed.has('baseImageUrl') ||
|
|
@@ -524,11 +569,9 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
524
569
|
}
|
|
525
570
|
if (changed.has('selectedTitleFilter')) {
|
|
526
571
|
this.sendFilterByTitleAnalytics(changed.get('selectedTitleFilter'));
|
|
527
|
-
this.selectedTitleLetterChanged();
|
|
528
572
|
}
|
|
529
573
|
if (changed.has('selectedCreatorFilter')) {
|
|
530
574
|
this.sendFilterByCreatorAnalytics(changed.get('selectedCreatorFilter'));
|
|
531
|
-
this.selectedCreatorLetterChanged();
|
|
532
575
|
}
|
|
533
576
|
if (changed.has('baseQuery') ||
|
|
534
577
|
changed.has('searchType') ||
|
|
@@ -554,12 +597,16 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
554
597
|
}
|
|
555
598
|
}
|
|
556
599
|
disconnectedCallback() {
|
|
600
|
+
var _a, _b;
|
|
557
601
|
if (this.resizeObserver) {
|
|
558
602
|
this.disconnectResizeObserver(this.resizeObserver);
|
|
559
603
|
}
|
|
560
604
|
if (this.boundNavigationHandler) {
|
|
561
605
|
window.removeEventListener('popstate', this.boundNavigationHandler);
|
|
562
606
|
}
|
|
607
|
+
(_a = this.leftColIntersectionObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
608
|
+
(_b = this.facetsIntersectionObserver) === null || _b === void 0 ? void 0 : _b.disconnect();
|
|
609
|
+
window.removeEventListener('resize', this.updateLeftColumnHeight);
|
|
563
610
|
}
|
|
564
611
|
handleResize(entry) {
|
|
565
612
|
const previousView = this.mobileView;
|
|
@@ -570,6 +617,41 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
570
617
|
this.isResizeToMobile = true;
|
|
571
618
|
}
|
|
572
619
|
}
|
|
620
|
+
// Ensure the facet sidebar remains sized correctly
|
|
621
|
+
this.updateLeftColumnHeight();
|
|
622
|
+
}
|
|
623
|
+
/**
|
|
624
|
+
* Sets up listeners for events that may require updating the left column height.
|
|
625
|
+
*/
|
|
626
|
+
setupLeftColumnScrollListeners() {
|
|
627
|
+
var _a;
|
|
628
|
+
// We observe intersections between the left column's scroll sentinel and
|
|
629
|
+
// the viewport, so that we can ensure the left column is always sized to
|
|
630
|
+
// match the _available_ viewport height. This should generally be more
|
|
631
|
+
// performant than listening to scroll events on the page or column.
|
|
632
|
+
const leftColumnSentinel = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#left-column-scroll-sentinel');
|
|
633
|
+
if (leftColumnSentinel) {
|
|
634
|
+
this.leftColIntersectionObserver = new IntersectionObserver(this.updateLeftColumnHeight, {
|
|
635
|
+
threshold: [...Array(101).keys()].map(n => n / 100), // Threshold every 1%
|
|
636
|
+
});
|
|
637
|
+
this.leftColIntersectionObserver.observe(leftColumnSentinel);
|
|
638
|
+
}
|
|
639
|
+
// We also listen for window resize events, as they are not always captured
|
|
640
|
+
// by the resize observer and can affect the desired height of the left column.
|
|
641
|
+
window.addEventListener('resize', this.updateLeftColumnHeight);
|
|
642
|
+
}
|
|
643
|
+
/**
|
|
644
|
+
* Sets up listeners to control whether the facet sidebar shows its bottom fade-out.
|
|
645
|
+
* Note this uses a separate IntersectionObserver from the left column, because we
|
|
646
|
+
* don't need granular intersection thresholds for this.
|
|
647
|
+
*/
|
|
648
|
+
setupFacetsScrollListeners() {
|
|
649
|
+
var _a;
|
|
650
|
+
const facetsSentinel = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('#facets-scroll-sentinel');
|
|
651
|
+
if (facetsSentinel) {
|
|
652
|
+
this.facetsIntersectionObserver = new IntersectionObserver(this.updateFacetFadeOut);
|
|
653
|
+
this.facetsIntersectionObserver.observe(facetsSentinel);
|
|
654
|
+
}
|
|
573
655
|
}
|
|
574
656
|
emitBaseQueryChanged() {
|
|
575
657
|
this.dispatchEvent(new CustomEvent('baseQueryChanged', {
|
|
@@ -706,6 +788,11 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
706
788
|
await this.fetchPage(this.initialPageNumber);
|
|
707
789
|
this.searchResultsLoading = false;
|
|
708
790
|
}
|
|
791
|
+
/**
|
|
792
|
+
* Constructs a search service FilterMap object from the combination of
|
|
793
|
+
* all the currently-applied filters. This includes any facets, letter
|
|
794
|
+
* filters, and date range.
|
|
795
|
+
*/
|
|
709
796
|
get filterMap() {
|
|
710
797
|
const builder = new FilterMapBuilder();
|
|
711
798
|
// Add the date range, if applicable
|
|
@@ -733,20 +820,16 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
733
820
|
}
|
|
734
821
|
}
|
|
735
822
|
}
|
|
823
|
+
// Add any letter filters
|
|
824
|
+
if (this.selectedTitleFilter) {
|
|
825
|
+
builder.addFilter('firstTitle', this.selectedTitleFilter, FilterConstraint.INCLUDE);
|
|
826
|
+
}
|
|
827
|
+
if (this.selectedCreatorFilter) {
|
|
828
|
+
builder.addFilter('firstCreator', this.selectedCreatorFilter, FilterConstraint.INCLUDE);
|
|
829
|
+
}
|
|
736
830
|
const filterMap = builder.build();
|
|
737
831
|
return filterMap;
|
|
738
832
|
}
|
|
739
|
-
/** The base query joined with any title/creator letter filters */
|
|
740
|
-
get filteredQuery() {
|
|
741
|
-
if (!this.baseQuery)
|
|
742
|
-
return undefined;
|
|
743
|
-
let filteredQuery = this.baseQuery.trim();
|
|
744
|
-
const { sortFilterQueries } = this;
|
|
745
|
-
if (sortFilterQueries) {
|
|
746
|
-
filteredQuery += ` AND ${sortFilterQueries}`;
|
|
747
|
-
}
|
|
748
|
-
return filteredQuery.trim();
|
|
749
|
-
}
|
|
750
833
|
/** The full query, including year facets and date range clauses */
|
|
751
834
|
get fullQuery() {
|
|
752
835
|
if (!this.baseQuery)
|
|
@@ -764,20 +847,6 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
764
847
|
}
|
|
765
848
|
return fullQuery.trim();
|
|
766
849
|
}
|
|
767
|
-
/** The full query without any title/creator letter filters */
|
|
768
|
-
get fullQueryWithoutAlphaFilters() {
|
|
769
|
-
if (!this.baseQuery)
|
|
770
|
-
return undefined;
|
|
771
|
-
let fullQuery = this.baseQuery.trim();
|
|
772
|
-
const { facetQuery, dateRangeQueryClause } = this;
|
|
773
|
-
if (facetQuery) {
|
|
774
|
-
fullQuery += ` AND ${facetQuery}`;
|
|
775
|
-
}
|
|
776
|
-
if (dateRangeQueryClause) {
|
|
777
|
-
fullQuery += ` AND ${dateRangeQueryClause}`;
|
|
778
|
-
}
|
|
779
|
-
return fullQuery.trim();
|
|
780
|
-
}
|
|
781
850
|
/**
|
|
782
851
|
* Generates a query string for the given facets
|
|
783
852
|
*
|
|
@@ -849,33 +918,37 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
849
918
|
facetsChanged(e) {
|
|
850
919
|
this.selectedFacets = e.detail;
|
|
851
920
|
}
|
|
852
|
-
facetClickHandler(
|
|
921
|
+
facetClickHandler({ detail: { key, state: facetState, negative }, }) {
|
|
853
922
|
var _a, _b;
|
|
854
923
|
if (negative) {
|
|
855
924
|
(_a = this.analyticsHandler) === null || _a === void 0 ? void 0 : _a.sendEvent({
|
|
856
925
|
category: this.searchContext,
|
|
857
|
-
action:
|
|
926
|
+
action: facetState !== 'none'
|
|
858
927
|
? analyticsActions.facetNegativeSelected
|
|
859
928
|
: analyticsActions.facetNegativeDeselected,
|
|
860
|
-
label:
|
|
929
|
+
label: key,
|
|
861
930
|
});
|
|
862
931
|
}
|
|
863
932
|
else {
|
|
864
933
|
(_b = this.analyticsHandler) === null || _b === void 0 ? void 0 : _b.sendEvent({
|
|
865
934
|
category: this.searchContext,
|
|
866
|
-
action:
|
|
935
|
+
action: facetState !== 'none'
|
|
867
936
|
? analyticsActions.facetSelected
|
|
868
937
|
: analyticsActions.facetDeselected,
|
|
869
|
-
label:
|
|
938
|
+
label: key,
|
|
870
939
|
});
|
|
871
940
|
}
|
|
872
941
|
}
|
|
873
942
|
async fetchFacets() {
|
|
874
943
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
875
|
-
|
|
944
|
+
const trimmedQuery = (_a = this.baseQuery) === null || _a === void 0 ? void 0 : _a.trim();
|
|
945
|
+
if (!trimmedQuery)
|
|
876
946
|
return;
|
|
947
|
+
if (!this.searchService)
|
|
948
|
+
return;
|
|
949
|
+
const { facetFetchQueryKey } = this;
|
|
877
950
|
const params = {
|
|
878
|
-
query:
|
|
951
|
+
query: trimmedQuery,
|
|
879
952
|
rows: 0,
|
|
880
953
|
filters: this.filterMap,
|
|
881
954
|
// Fetch a few extra buckets beyond the 6 we show, in case some get suppressed
|
|
@@ -885,9 +958,14 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
885
958
|
uid: this.facetFetchQueryKey,
|
|
886
959
|
};
|
|
887
960
|
this.facetsLoading = true;
|
|
888
|
-
const searchResponse = await
|
|
961
|
+
const searchResponse = await this.searchService.search(params, this.searchType);
|
|
889
962
|
const success = searchResponse === null || searchResponse === void 0 ? void 0 : searchResponse.success;
|
|
890
|
-
|
|
963
|
+
// This is checking to see if the query has changed since the data was fetched.
|
|
964
|
+
// If so, we just want to discard this set of aggregations because they are
|
|
965
|
+
// likely no longer valid for the newer query.
|
|
966
|
+
const queryChangedSinceFetch = facetFetchQueryKey !== this.facetFetchQueryKey;
|
|
967
|
+
if (queryChangedSinceFetch)
|
|
968
|
+
return;
|
|
891
969
|
if (!success) {
|
|
892
970
|
const errorMsg = (_b = searchResponse === null || searchResponse === void 0 ? void 0 : searchResponse.error) === null || _b === void 0 ? void 0 : _b.message;
|
|
893
971
|
const detailMsg = (_d = (_c = searchResponse === null || searchResponse === void 0 ? void 0 : searchResponse.error) === null || _c === void 0 ? void 0 : _c.details) === null || _d === void 0 ? void 0 : _d.message;
|
|
@@ -897,16 +975,10 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
897
975
|
}
|
|
898
976
|
return;
|
|
899
977
|
}
|
|
900
|
-
// This is checking to see if the query has changed since the data was fetched.
|
|
901
|
-
// If so, we just want to discard this set of aggregations because they are
|
|
902
|
-
// likely no longer valid for the newer query.
|
|
903
|
-
const returnedUid = success.request.clientParameters.uid;
|
|
904
|
-
const queryChangedSinceFetch = returnedUid !== this.facetFetchQueryKey;
|
|
905
|
-
if (queryChangedSinceFetch)
|
|
906
|
-
return;
|
|
907
978
|
this.aggregations = success === null || success === void 0 ? void 0 : success.response.aggregations;
|
|
908
979
|
this.fullYearsHistogramAggregation =
|
|
909
980
|
(_h = (_g = success === null || success === void 0 ? void 0 : success.response) === null || _g === void 0 ? void 0 : _g.aggregations) === null || _h === void 0 ? void 0 : _h.year_histogram;
|
|
981
|
+
this.facetsLoading = false;
|
|
910
982
|
}
|
|
911
983
|
scrollToPage(pageNumber) {
|
|
912
984
|
return new Promise(resolve => {
|
|
@@ -957,8 +1029,11 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
957
1029
|
return `${this.fullQuery}-${this.searchType}`;
|
|
958
1030
|
}
|
|
959
1031
|
async fetchPage(pageNumber) {
|
|
960
|
-
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
961
|
-
|
|
1032
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
1033
|
+
const trimmedQuery = (_a = this.baseQuery) === null || _a === void 0 ? void 0 : _a.trim();
|
|
1034
|
+
if (!trimmedQuery)
|
|
1035
|
+
return;
|
|
1036
|
+
if (!this.searchService)
|
|
962
1037
|
return;
|
|
963
1038
|
// if we already have data, don't fetch again
|
|
964
1039
|
if (this.dataSource[pageNumber])
|
|
@@ -967,14 +1042,14 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
967
1042
|
return;
|
|
968
1043
|
// if a fetch is already in progress for this query and page, don't fetch again
|
|
969
1044
|
const { pageFetchQueryKey } = this;
|
|
970
|
-
const pageFetches = (
|
|
1045
|
+
const pageFetches = (_b = this.pageFetchesInProgress[pageFetchQueryKey]) !== null && _b !== void 0 ? _b : new Set();
|
|
971
1046
|
if (pageFetches.has(pageNumber))
|
|
972
1047
|
return;
|
|
973
1048
|
pageFetches.add(pageNumber);
|
|
974
1049
|
this.pageFetchesInProgress[pageFetchQueryKey] = pageFetches;
|
|
975
1050
|
const sortParams = this.sortParam ? [this.sortParam] : [];
|
|
976
1051
|
const params = {
|
|
977
|
-
query:
|
|
1052
|
+
query: trimmedQuery,
|
|
978
1053
|
page: pageNumber,
|
|
979
1054
|
rows: this.pageSize,
|
|
980
1055
|
sort: sortParams,
|
|
@@ -982,8 +1057,14 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
982
1057
|
aggregations: { omit: true },
|
|
983
1058
|
uid: this.pageFetchQueryKey,
|
|
984
1059
|
};
|
|
985
|
-
const searchResponse = await
|
|
1060
|
+
const searchResponse = await this.searchService.search(params, this.searchType);
|
|
986
1061
|
const success = searchResponse === null || searchResponse === void 0 ? void 0 : searchResponse.success;
|
|
1062
|
+
// This is checking to see if the query has changed since the data was fetched.
|
|
1063
|
+
// If so, we just want to discard the data since there should be a new query
|
|
1064
|
+
// right behind it.
|
|
1065
|
+
const queryChangedSinceFetch = pageFetchQueryKey !== this.pageFetchQueryKey;
|
|
1066
|
+
if (queryChangedSinceFetch)
|
|
1067
|
+
return;
|
|
987
1068
|
if (!success) {
|
|
988
1069
|
const errorMsg = (_c = searchResponse === null || searchResponse === void 0 ? void 0 : searchResponse.error) === null || _c === void 0 ? void 0 : _c.message;
|
|
989
1070
|
const detailMsg = (_e = (_d = searchResponse === null || searchResponse === void 0 ? void 0 : searchResponse.error) === null || _d === void 0 ? void 0 : _d.details) === null || _e === void 0 ? void 0 : _e.message;
|
|
@@ -993,15 +1074,10 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
993
1074
|
// @ts-ignore: Property 'Sentry' does not exist on type 'Window & typeof globalThis'
|
|
994
1075
|
(_g = (_f = window === null || window === void 0 ? void 0 : window.Sentry) === null || _f === void 0 ? void 0 : _f.captureMessage) === null || _g === void 0 ? void 0 : _g.call(_f, this.queryErrorMessage, 'error');
|
|
995
1076
|
}
|
|
1077
|
+
(_h = this.pageFetchesInProgress[pageFetchQueryKey]) === null || _h === void 0 ? void 0 : _h.delete(pageNumber);
|
|
1078
|
+
this.searchResultsLoading = false;
|
|
996
1079
|
return;
|
|
997
1080
|
}
|
|
998
|
-
// This is checking to see if the query has changed since the data was fetched.
|
|
999
|
-
// If so, we just want to discard the data since there should be a new query
|
|
1000
|
-
// right behind it.
|
|
1001
|
-
const returnedUid = success.request.clientParameters.uid;
|
|
1002
|
-
const queryChangedSinceFetch = returnedUid !== this.pageFetchQueryKey;
|
|
1003
|
-
if (queryChangedSinceFetch)
|
|
1004
|
-
return;
|
|
1005
1081
|
this.totalResults = success.response.totalResults;
|
|
1006
1082
|
const { results } = success.response;
|
|
1007
1083
|
if (results && results.length > 0) {
|
|
@@ -1017,7 +1093,7 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
1017
1093
|
this.infiniteScroller.itemCount = this.totalResults;
|
|
1018
1094
|
}
|
|
1019
1095
|
}
|
|
1020
|
-
(
|
|
1096
|
+
(_j = this.pageFetchesInProgress[pageFetchQueryKey]) === null || _j === void 0 ? void 0 : _j.delete(pageNumber);
|
|
1021
1097
|
this.searchResultsLoading = false;
|
|
1022
1098
|
}
|
|
1023
1099
|
preloadCollectionNames(results) {
|
|
@@ -1119,29 +1195,32 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
1119
1195
|
}
|
|
1120
1196
|
/** Fetches the aggregation buckets for the given prefix filter type. */
|
|
1121
1197
|
async fetchPrefixFilterBuckets(filterType) {
|
|
1122
|
-
var _a, _b, _c, _d, _e, _f;
|
|
1123
|
-
|
|
1124
|
-
if (!
|
|
1198
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
1199
|
+
const trimmedQuery = (_a = this.baseQuery) === null || _a === void 0 ? void 0 : _a.trim();
|
|
1200
|
+
if (!trimmedQuery)
|
|
1125
1201
|
return [];
|
|
1126
1202
|
const filterAggregationKey = prefixFilterAggregationKeys[filterType];
|
|
1127
1203
|
const params = {
|
|
1128
|
-
query:
|
|
1204
|
+
query: trimmedQuery,
|
|
1129
1205
|
rows: 0,
|
|
1206
|
+
filters: this.filterMap,
|
|
1130
1207
|
// Only fetch the firstTitle or firstCreator aggregation
|
|
1131
1208
|
aggregations: { simpleParams: [filterAggregationKey] },
|
|
1132
1209
|
// Fetch all 26 letter buckets
|
|
1133
1210
|
aggregationsSize: 26,
|
|
1134
1211
|
};
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
console.log('response', searchResponse);
|
|
1138
|
-
return ((_f = (_e = (_d = (_c = (_b = searchResponse === null || searchResponse === void 0 ? void 0 : searchResponse.success) === null || _b === void 0 ? void 0 : _b.response) === null || _c === void 0 ? void 0 : _c.aggregations) === null || _d === void 0 ? void 0 : _d[filterAggregationKey]) === null || _e === void 0 ? void 0 : _e.buckets) !== null && _f !== void 0 ? _f : []);
|
|
1212
|
+
const searchResponse = await ((_b = this.searchService) === null || _b === void 0 ? void 0 : _b.search(params, this.searchType));
|
|
1213
|
+
return ((_g = (_f = (_e = (_d = (_c = searchResponse === null || searchResponse === void 0 ? void 0 : searchResponse.success) === null || _c === void 0 ? void 0 : _c.response) === null || _d === void 0 ? void 0 : _d.aggregations) === null || _e === void 0 ? void 0 : _e[filterAggregationKey]) === null || _f === void 0 ? void 0 : _f.buckets) !== null && _g !== void 0 ? _g : []);
|
|
1139
1214
|
}
|
|
1140
1215
|
/** Fetches and caches the prefix filter counts for the given filter type. */
|
|
1141
1216
|
async updatePrefixFilterCounts(filterType) {
|
|
1142
|
-
|
|
1217
|
+
const { facetFetchQueryKey } = this;
|
|
1143
1218
|
const buckets = await this.fetchPrefixFilterBuckets(filterType);
|
|
1144
|
-
|
|
1219
|
+
// Don't update the filter counts for an outdated query (if it has been changed
|
|
1220
|
+
// since we sent the request)
|
|
1221
|
+
const queryChangedSinceFetch = facetFetchQueryKey !== this.facetFetchQueryKey;
|
|
1222
|
+
if (queryChangedSinceFetch)
|
|
1223
|
+
return;
|
|
1145
1224
|
// Unpack the aggregation buckets into a simple map like { 'A': 50, 'B': 25, ... }
|
|
1146
1225
|
this.prefixFilterCountMap = { ...this.prefixFilterCountMap }; // Clone the object to trigger an update
|
|
1147
1226
|
this.prefixFilterCountMap[filterType] = buckets.reduce((acc, bucket) => {
|
|
@@ -1154,12 +1233,9 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
1154
1233
|
* provided it is one that permits prefix filtering. (If not, this does nothing).
|
|
1155
1234
|
*/
|
|
1156
1235
|
async updatePrefixFiltersForCurrentSort() {
|
|
1157
|
-
console.log('updatePrefixFiltersForCurrentSort');
|
|
1158
1236
|
if (['title', 'creator'].includes(this.selectedSort)) {
|
|
1159
|
-
console.log('sort is title or creator - will update');
|
|
1160
1237
|
const filterType = this.selectedSort;
|
|
1161
1238
|
if (!this.prefixFilterCountMap[filterType]) {
|
|
1162
|
-
console.log('need new filters, updating');
|
|
1163
1239
|
this.updatePrefixFilterCounts(filterType);
|
|
1164
1240
|
}
|
|
1165
1241
|
}
|
|
@@ -1172,7 +1248,6 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
1172
1248
|
* Call this whenever the counts are invalidated (e.g., by a query change).
|
|
1173
1249
|
*/
|
|
1174
1250
|
refreshLetterCounts() {
|
|
1175
|
-
console.log('refreshLetterCounts');
|
|
1176
1251
|
if (Object.keys(this.prefixFilterCountMap).length > 0) {
|
|
1177
1252
|
this.prefixFilterCountMap = {};
|
|
1178
1253
|
}
|
|
@@ -1229,6 +1304,9 @@ let CollectionBrowser = class CollectionBrowser extends LitElement {
|
|
|
1229
1304
|
CollectionBrowser.styles = css `
|
|
1230
1305
|
:host {
|
|
1231
1306
|
display: block;
|
|
1307
|
+
|
|
1308
|
+
--leftColumnWidth: 18rem;
|
|
1309
|
+
--leftColumnPaddingRight: 2.5rem;
|
|
1232
1310
|
}
|
|
1233
1311
|
|
|
1234
1312
|
/**
|
|
@@ -1289,15 +1367,91 @@ CollectionBrowser.styles = css `
|
|
|
1289
1367
|
}
|
|
1290
1368
|
|
|
1291
1369
|
#left-column {
|
|
1292
|
-
width: 18rem;
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
padding-
|
|
1370
|
+
width: var(--leftColumnWidth, 18rem);
|
|
1371
|
+
/* Prevents Safari from shrinking col at first draw */
|
|
1372
|
+
min-width: var(--leftColumnWidth, 18rem);
|
|
1373
|
+
padding-top: 0;
|
|
1374
|
+
/* Reduced padding by 0.2rem to add the invisible border in the rule below */
|
|
1375
|
+
padding-right: calc(var(--leftColumnPaddingRight, 2.5rem) - 0.2rem);
|
|
1376
|
+
border-right: 0.2rem solid transparent; /* Pads to the right of the scrollbar a bit */
|
|
1296
1377
|
z-index: 1;
|
|
1297
1378
|
}
|
|
1298
1379
|
|
|
1380
|
+
.desktop #left-column {
|
|
1381
|
+
top: 0;
|
|
1382
|
+
position: sticky;
|
|
1383
|
+
height: calc(100vh - 2rem);
|
|
1384
|
+
max-height: calc(100vh - 2rem);
|
|
1385
|
+
overflow-x: hidden;
|
|
1386
|
+
overflow-y: scroll;
|
|
1387
|
+
|
|
1388
|
+
/*
|
|
1389
|
+
* Firefox doesn't support any of the -webkit-scrollbar stuff below, but
|
|
1390
|
+
* does at least give us a tiny bit of control over width & color.
|
|
1391
|
+
*/
|
|
1392
|
+
scrollbar-width: thin;
|
|
1393
|
+
scrollbar-color: transparent transparent;
|
|
1394
|
+
}
|
|
1395
|
+
.desktop #left-column:hover {
|
|
1396
|
+
scrollbar-color: auto;
|
|
1397
|
+
}
|
|
1299
1398
|
.desktop #left-column::-webkit-scrollbar {
|
|
1300
|
-
|
|
1399
|
+
appearance: none;
|
|
1400
|
+
width: 6px;
|
|
1401
|
+
}
|
|
1402
|
+
.desktop #left-column::-webkit-scrollbar-button {
|
|
1403
|
+
height: 3px;
|
|
1404
|
+
background: transparent;
|
|
1405
|
+
}
|
|
1406
|
+
.desktop #left-column::-webkit-scrollbar-corner {
|
|
1407
|
+
background: transparent;
|
|
1408
|
+
}
|
|
1409
|
+
.desktop #left-column::-webkit-scrollbar-thumb {
|
|
1410
|
+
border-radius: 4px;
|
|
1411
|
+
}
|
|
1412
|
+
.desktop #left-column:hover::-webkit-scrollbar-thumb {
|
|
1413
|
+
background: rgba(0, 0, 0, 0.15);
|
|
1414
|
+
}
|
|
1415
|
+
.desktop #left-column:hover::-webkit-scrollbar-thumb:hover {
|
|
1416
|
+
background: rgba(0, 0, 0, 0.2);
|
|
1417
|
+
}
|
|
1418
|
+
.desktop #left-column:hover::-webkit-scrollbar-thumb:active {
|
|
1419
|
+
background: rgba(0, 0, 0, 0.3);
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
#facets-bottom-fade {
|
|
1423
|
+
background: linear-gradient(
|
|
1424
|
+
to bottom,
|
|
1425
|
+
#f5f5f700 0%,
|
|
1426
|
+
#f5f5f7c0 50%,
|
|
1427
|
+
#f5f5f7 80%,
|
|
1428
|
+
#f5f5f7 100%
|
|
1429
|
+
);
|
|
1430
|
+
position: fixed;
|
|
1431
|
+
bottom: 0;
|
|
1432
|
+
height: 50px;
|
|
1433
|
+
/* Wide enough to cover the content, but leave the scrollbar uncovered */
|
|
1434
|
+
width: calc(
|
|
1435
|
+
var(--leftColumnWidth) + var(--leftColumnPaddingRight) - 10px
|
|
1436
|
+
);
|
|
1437
|
+
z-index: 2;
|
|
1438
|
+
pointer-events: none;
|
|
1439
|
+
transition: height 0.1s ease;
|
|
1440
|
+
}
|
|
1441
|
+
#facets-bottom-fade.hidden {
|
|
1442
|
+
height: 0;
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
.desktop #left-column-scroll-sentinel {
|
|
1446
|
+
width: 1px;
|
|
1447
|
+
height: 100vh;
|
|
1448
|
+
background: transparent;
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
.desktop #facets-scroll-sentinel {
|
|
1452
|
+
width: 1px;
|
|
1453
|
+
height: 1px;
|
|
1454
|
+
background: transparent;
|
|
1301
1455
|
}
|
|
1302
1456
|
|
|
1303
1457
|
.mobile #left-column {
|
|
@@ -1305,21 +1459,16 @@ CollectionBrowser.styles = css `
|
|
|
1305
1459
|
padding: 0;
|
|
1306
1460
|
}
|
|
1307
1461
|
|
|
1308
|
-
.desktop #left-column {
|
|
1309
|
-
top: 0;
|
|
1310
|
-
position: sticky;
|
|
1311
|
-
max-height: 100vh;
|
|
1312
|
-
overflow: scroll;
|
|
1313
|
-
-ms-overflow-style: none; /* hide scrollbar IE and Edge */
|
|
1314
|
-
scrollbar-width: none; /* hide scrollbar Firefox */
|
|
1315
|
-
}
|
|
1316
|
-
|
|
1317
1462
|
#mobile-header-container {
|
|
1318
1463
|
display: flex;
|
|
1319
1464
|
justify-content: space-between;
|
|
1320
1465
|
align-items: center;
|
|
1321
1466
|
}
|
|
1322
1467
|
|
|
1468
|
+
.desktop #mobile-header-container {
|
|
1469
|
+
padding-top: 2rem;
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1323
1472
|
#facets-container {
|
|
1324
1473
|
position: relative;
|
|
1325
1474
|
max-height: 0;
|
|
@@ -1493,12 +1642,6 @@ __decorate([
|
|
|
1493
1642
|
__decorate([
|
|
1494
1643
|
property({ type: Object })
|
|
1495
1644
|
], CollectionBrowser.prototype, "resizeObserver", void 0);
|
|
1496
|
-
__decorate([
|
|
1497
|
-
property({ type: String })
|
|
1498
|
-
], CollectionBrowser.prototype, "titleQuery", void 0);
|
|
1499
|
-
__decorate([
|
|
1500
|
-
property({ type: String })
|
|
1501
|
-
], CollectionBrowser.prototype, "creatorQuery", void 0);
|
|
1502
1645
|
__decorate([
|
|
1503
1646
|
property({ type: Number })
|
|
1504
1647
|
], CollectionBrowser.prototype, "currentPage", void 0);
|
|
@@ -1583,6 +1726,9 @@ __decorate([
|
|
|
1583
1726
|
__decorate([
|
|
1584
1727
|
query('#content-container')
|
|
1585
1728
|
], CollectionBrowser.prototype, "contentContainer", void 0);
|
|
1729
|
+
__decorate([
|
|
1730
|
+
query('#left-column')
|
|
1731
|
+
], CollectionBrowser.prototype, "leftColumn", void 0);
|
|
1586
1732
|
__decorate([
|
|
1587
1733
|
property({ type: Object, attribute: false })
|
|
1588
1734
|
], CollectionBrowser.prototype, "analyticsHandler", void 0);
|