@internetarchive/collection-browser 1.14.17-alpha.2 → 1.14.17-alpha.21
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/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/src/app-root.d.ts +1 -0
- package/dist/src/app-root.js +38 -0
- package/dist/src/app-root.js.map +1 -1
- package/dist/src/collection-browser.d.ts +2 -15
- package/dist/src/collection-browser.js +22 -29
- package/dist/src/collection-browser.js.map +1 -1
- package/dist/src/data-source/collection-browser-data-source.d.ts +55 -32
- package/dist/src/data-source/collection-browser-data-source.js +155 -162
- package/dist/src/data-source/collection-browser-data-source.js.map +1 -1
- package/dist/src/data-source/models.d.ts +6 -3
- package/dist/src/data-source/models.js.map +1 -1
- package/dist/src/manage/manage-bar.d.ts +1 -1
- package/dist/src/manage/manage-bar.js.map +1 -1
- package/dist/src/models.d.ts +20 -4
- package/dist/src/models.js +105 -0
- package/dist/src/models.js.map +1 -1
- package/dist/src/sort-filter-bar/sort-filter-bar.js +25 -16
- package/dist/src/sort-filter-bar/sort-filter-bar.js.map +1 -1
- package/dist/src/tiles/grid/item-tile.d.ts +1 -0
- package/dist/src/tiles/grid/item-tile.js +28 -1
- package/dist/src/tiles/grid/item-tile.js.map +1 -1
- package/dist/src/tiles/grid/tile-stats.js +13 -8
- package/dist/src/tiles/grid/tile-stats.js.map +1 -1
- package/dist/src/tiles/list/tile-list-compact.js +1 -1
- package/dist/src/tiles/list/tile-list-compact.js.map +1 -1
- package/dist/src/tiles/list/tile-list.d.ts +1 -0
- package/dist/src/tiles/list/tile-list.js +32 -1
- package/dist/src/tiles/list/tile-list.js.map +1 -1
- package/dist/src/tiles/tile-dispatcher.js +3 -2
- package/dist/src/tiles/tile-dispatcher.js.map +1 -1
- package/dist/src/tiles/tile-display-value-provider.d.ts +6 -2
- package/dist/src/tiles/tile-display-value-provider.js +15 -1
- package/dist/src/tiles/tile-display-value-provider.js.map +1 -1
- package/dist/src/utils/collapse-repeated-quotes.d.ts +11 -0
- package/dist/src/utils/collapse-repeated-quotes.js +14 -0
- package/dist/src/utils/collapse-repeated-quotes.js.map +1 -0
- package/dist/src/utils/resolve-mediatype.d.ts +8 -0
- package/dist/src/utils/resolve-mediatype.js +24 -0
- package/dist/src/utils/resolve-mediatype.js.map +1 -0
- package/dist/test/collection-browser.test.js +39 -19
- package/dist/test/collection-browser.test.js.map +1 -1
- package/dist/test/collection-facets/more-facets-content.test.js +2 -2
- package/dist/test/collection-facets/more-facets-content.test.js.map +1 -1
- package/dist/test/collection-facets.test.js +5 -0
- package/dist/test/collection-facets.test.js.map +1 -1
- package/dist/test/item-image.test.js +33 -34
- package/dist/test/item-image.test.js.map +1 -1
- package/dist/test/mocks/mock-search-responses.d.ts +1 -0
- package/dist/test/mocks/mock-search-responses.js +62 -0
- package/dist/test/mocks/mock-search-responses.js.map +1 -1
- package/dist/test/sort-filter-bar/sort-filter-bar.test.js +41 -4
- package/dist/test/sort-filter-bar/sort-filter-bar.test.js.map +1 -1
- package/dist/test/tiles/hover/hover-pane-controller.test.js +18 -17
- package/dist/test/tiles/hover/hover-pane-controller.test.js.map +1 -1
- package/package.json +2 -2
- package/src/app-root.ts +39 -0
- package/src/collection-browser.ts +24 -40
- package/src/data-source/collection-browser-data-source.ts +160 -132
- package/src/data-source/models.ts +6 -2
- package/src/manage/manage-bar.ts +1 -1
- package/src/models.ts +154 -3
- package/src/sort-filter-bar/sort-filter-bar.ts +26 -16
- package/src/tiles/grid/item-tile.ts +36 -1
- package/src/tiles/grid/tile-stats.ts +12 -7
- package/src/tiles/list/tile-list-compact.ts +1 -1
- package/src/tiles/list/tile-list.ts +43 -5
- package/src/tiles/tile-dispatcher.ts +2 -1
- package/src/tiles/tile-display-value-provider.ts +20 -2
- package/src/utils/collapse-repeated-quotes.ts +13 -0
- package/src/utils/resolve-mediatype.ts +26 -0
- package/test/collection-browser.test.ts +74 -19
- package/test/collection-facets/more-facets-content.test.ts +4 -2
- package/test/collection-facets.test.ts +5 -0
- package/test/item-image.test.ts +34 -36
- package/test/mocks/mock-search-responses.ts +66 -0
- package/test/sort-filter-bar/sort-filter-bar.test.ts +50 -4
- package/test/tiles/hover/hover-pane-controller.test.ts +19 -17
- package/dist/src/data-source/data-source-fetch-provider.d.ts +0 -13
- package/dist/src/data-source/data-source-fetch-provider.js +0 -61
- package/dist/src/data-source/data-source-fetch-provider.js.map +0 -1
- package/dist/src/selected-facets.d.ts +0 -67
- package/dist/src/selected-facets.js +0 -149
- package/dist/src/selected-facets.js.map +0 -1
- package/src/data-source/data-source-fetch-provider.ts +0 -79
- package/src/selected-facets.ts +0 -216
|
@@ -12,13 +12,13 @@ import {
|
|
|
12
12
|
SearchResult,
|
|
13
13
|
SearchType,
|
|
14
14
|
} from '@internetarchive/search-service';
|
|
15
|
-
import type { MediaType } from '@internetarchive/field-parsers';
|
|
16
15
|
import {
|
|
17
16
|
prefixFilterAggregationKeys,
|
|
18
17
|
type FacetBucket,
|
|
19
18
|
type PrefixFilterType,
|
|
20
|
-
|
|
19
|
+
TileModel,
|
|
21
20
|
PrefixFilterCounts,
|
|
21
|
+
RequestKind,
|
|
22
22
|
} from '../models';
|
|
23
23
|
import type {
|
|
24
24
|
CollectionBrowserSearchInterface,
|
|
@@ -27,8 +27,6 @@ import type {
|
|
|
27
27
|
} from './models';
|
|
28
28
|
import { sha1 } from '../utils/sha1';
|
|
29
29
|
|
|
30
|
-
type RequestKind = 'full' | 'hits' | 'aggregations';
|
|
31
|
-
|
|
32
30
|
export interface CollectionBrowserDataSourceInterface
|
|
33
31
|
extends ReactiveController {
|
|
34
32
|
/**
|
|
@@ -44,6 +42,12 @@ export interface CollectionBrowserDataSourceInterface
|
|
|
44
42
|
*/
|
|
45
43
|
readonly canPerformSearch: boolean;
|
|
46
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Whether the end of the set of results for the current query state has been
|
|
47
|
+
* encountered (i.e., the last page of results).
|
|
48
|
+
*/
|
|
49
|
+
readonly endOfDataReached: boolean;
|
|
50
|
+
|
|
47
51
|
/**
|
|
48
52
|
* A string key compactly representing the current full search state, which can
|
|
49
53
|
* be used to determine, e.g., when a new search is required or whether an arriving
|
|
@@ -128,6 +132,20 @@ export interface CollectionBrowserDataSourceInterface
|
|
|
128
132
|
*/
|
|
129
133
|
readonly uncheckedTileModels: TileModel[];
|
|
130
134
|
|
|
135
|
+
/**
|
|
136
|
+
* A Promise which, after each query change, resolves once the fetches for the initial
|
|
137
|
+
* search have completed. Waits for *both* the hits and aggregations fetches to finish.
|
|
138
|
+
*
|
|
139
|
+
* Ensure you await this component's `updateComplete` promise before awaiting this
|
|
140
|
+
* one, to ensure you do not await an obsolete promise from the previous update.
|
|
141
|
+
*/
|
|
142
|
+
readonly initialSearchComplete: Promise<boolean>;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Resets the data source to its empty state, with no result pages, aggregations, etc.
|
|
146
|
+
*/
|
|
147
|
+
reset(): void;
|
|
148
|
+
|
|
131
149
|
/**
|
|
132
150
|
* Adds the given page of tile models to the data source.
|
|
133
151
|
* If the given page number already exists, that page will be overwritten.
|
|
@@ -191,11 +209,6 @@ export interface CollectionBrowserDataSourceInterface
|
|
|
191
209
|
*/
|
|
192
210
|
setPageSize(pageSize: number): void;
|
|
193
211
|
|
|
194
|
-
/**
|
|
195
|
-
* Resets the data source to its empty state, with no result pages, aggregations, etc.
|
|
196
|
-
*/
|
|
197
|
-
reset(): void;
|
|
198
|
-
|
|
199
212
|
/**
|
|
200
213
|
* Notifies the data source that a query change has occurred, which may trigger a data
|
|
201
214
|
* reset & new fetches.
|
|
@@ -242,8 +255,22 @@ export class CollectionBrowserDataSource
|
|
|
242
255
|
*/
|
|
243
256
|
private pageFetchesInProgress: Record<string, Set<number>> = {};
|
|
244
257
|
|
|
258
|
+
/**
|
|
259
|
+
* A record of the query key used for the last search.
|
|
260
|
+
* If this changes, we need to load new results.
|
|
261
|
+
*/
|
|
262
|
+
private previousQueryKey: string = '';
|
|
263
|
+
|
|
264
|
+
private id = Math.random();
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* @inheritdoc
|
|
268
|
+
*/
|
|
245
269
|
totalResults = 0;
|
|
246
270
|
|
|
271
|
+
/**
|
|
272
|
+
* @inheritdoc
|
|
273
|
+
*/
|
|
247
274
|
endOfDataReached = false;
|
|
248
275
|
|
|
249
276
|
/**
|
|
@@ -287,6 +314,26 @@ export class CollectionBrowserDataSource
|
|
|
287
314
|
prefixFilterCountMap: Partial<Record<PrefixFilterType, PrefixFilterCounts>> =
|
|
288
315
|
{};
|
|
289
316
|
|
|
317
|
+
/**
|
|
318
|
+
* Internal property to store the `resolve` function for the most recent
|
|
319
|
+
* `initialSearchComplete` promise, allowing us to resolve it at the appropriate time.
|
|
320
|
+
*/
|
|
321
|
+
private _initialSearchCompleteResolver!: (val: boolean) => void;
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Internal property to store the private value backing the `initialSearchComplete` getter.
|
|
325
|
+
*/
|
|
326
|
+
private _initialSearchCompletePromise: Promise<boolean> = new Promise(res => {
|
|
327
|
+
this._initialSearchCompleteResolver = res;
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* @inheritdoc
|
|
332
|
+
*/
|
|
333
|
+
get initialSearchComplete(): Promise<boolean> {
|
|
334
|
+
return this._initialSearchCompletePromise;
|
|
335
|
+
}
|
|
336
|
+
|
|
290
337
|
constructor(
|
|
291
338
|
/** The host element to which this controller should attach listeners */
|
|
292
339
|
private readonly host: ReactiveControllerHost &
|
|
@@ -297,6 +344,30 @@ export class CollectionBrowserDataSource
|
|
|
297
344
|
this.host.addController(this as CollectionBrowserDataSourceInterface);
|
|
298
345
|
}
|
|
299
346
|
|
|
347
|
+
hostUpdate(): void {
|
|
348
|
+
// This reactive controller hook is run whenever the host component (collection-browser) performs an update.
|
|
349
|
+
// We check whether the host's state has changed in a way which should trigger a reset & new results fetch.
|
|
350
|
+
|
|
351
|
+
// Only the currently-installed data source should react to the update
|
|
352
|
+
if (this.host.dataSource !== this) return;
|
|
353
|
+
|
|
354
|
+
// Can't perform searches without a search service
|
|
355
|
+
if (!this.host.searchService) return;
|
|
356
|
+
|
|
357
|
+
// We should only reset if part of the full query state has changed
|
|
358
|
+
const queryKeyChanged = this.pageFetchQueryKey !== this.previousQueryKey;
|
|
359
|
+
console.log('query keys', this.pageFetchQueryKey, this.previousQueryKey);
|
|
360
|
+
if (!queryKeyChanged) return;
|
|
361
|
+
|
|
362
|
+
// We should only reset if either:
|
|
363
|
+
// (a) our state permits a valid search, or
|
|
364
|
+
// (b) we have a blank query that we want to show empty results for
|
|
365
|
+
const shouldShowEmptyQueryResults = this.host.clearResultsOnEmptyQuery && this.host.baseQuery === '';
|
|
366
|
+
if (!(this.canPerformSearch || shouldShowEmptyQueryResults)) return;
|
|
367
|
+
|
|
368
|
+
this.handleQueryChange();
|
|
369
|
+
}
|
|
370
|
+
|
|
300
371
|
/**
|
|
301
372
|
* @inheritdoc
|
|
302
373
|
*/
|
|
@@ -304,6 +375,26 @@ export class CollectionBrowserDataSource
|
|
|
304
375
|
return this.numTileModels;
|
|
305
376
|
}
|
|
306
377
|
|
|
378
|
+
/**
|
|
379
|
+
* @inheritdoc
|
|
380
|
+
*/
|
|
381
|
+
reset(): void {
|
|
382
|
+
this.pages = {};
|
|
383
|
+
this.aggregations = {};
|
|
384
|
+
this.yearHistogramAggregation = undefined;
|
|
385
|
+
this.pageFetchesInProgress = {};
|
|
386
|
+
this.pageElements = undefined;
|
|
387
|
+
this.parentCollections = [];
|
|
388
|
+
this.prefixFilterCountMap = {};
|
|
389
|
+
|
|
390
|
+
this.offset = 0;
|
|
391
|
+
this.numTileModels = 0;
|
|
392
|
+
this.totalResults = 0;
|
|
393
|
+
this.endOfDataReached = false;
|
|
394
|
+
|
|
395
|
+
this.host.requestUpdate();
|
|
396
|
+
}
|
|
397
|
+
|
|
307
398
|
/**
|
|
308
399
|
* @inheritdoc
|
|
309
400
|
*/
|
|
@@ -343,6 +434,9 @@ export class CollectionBrowserDataSource
|
|
|
343
434
|
return this.pages[pageNum]?.[indexOnPage];
|
|
344
435
|
}
|
|
345
436
|
|
|
437
|
+
/**
|
|
438
|
+
* @inheritdoc
|
|
439
|
+
*/
|
|
346
440
|
indexOf(tile: TileModel): number {
|
|
347
441
|
return Object.values(this.pages).flat().indexOf(tile);
|
|
348
442
|
}
|
|
@@ -355,35 +449,25 @@ export class CollectionBrowserDataSource
|
|
|
355
449
|
this.pageSize = pageSize;
|
|
356
450
|
}
|
|
357
451
|
|
|
358
|
-
/**
|
|
359
|
-
* @inheritdoc
|
|
360
|
-
*/
|
|
361
|
-
reset(): void {
|
|
362
|
-
this.pages = {};
|
|
363
|
-
this.aggregations = {};
|
|
364
|
-
this.yearHistogramAggregation = undefined;
|
|
365
|
-
this.pageFetchesInProgress = {};
|
|
366
|
-
this.pageElements = undefined;
|
|
367
|
-
this.parentCollections = [];
|
|
368
|
-
this.prefixFilterCountMap = {};
|
|
369
|
-
|
|
370
|
-
this.offset = 0;
|
|
371
|
-
this.numTileModels = 0;
|
|
372
|
-
this.totalResults = 0;
|
|
373
|
-
this.endOfDataReached = false;
|
|
374
|
-
|
|
375
|
-
this.host.requestUpdate();
|
|
376
|
-
}
|
|
377
|
-
|
|
378
452
|
/**
|
|
379
453
|
* @inheritdoc
|
|
380
454
|
*/
|
|
381
455
|
async handleQueryChange(): Promise<void> {
|
|
382
456
|
this.reset();
|
|
457
|
+
|
|
458
|
+
// Reset the `initialSearchComplete` promise with a new value for the imminent search
|
|
459
|
+
this._initialSearchCompletePromise = new Promise(res => {
|
|
460
|
+
this._initialSearchCompleteResolver = res;
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
// Fire the initial page & facet requests
|
|
383
464
|
await Promise.all([
|
|
384
465
|
this.doInitialPageFetch(),
|
|
385
466
|
this.host.suppressFacets ? null : this.fetchFacets(),
|
|
386
467
|
]);
|
|
468
|
+
|
|
469
|
+
// Resolve the `initialSearchComplete` promise for this search
|
|
470
|
+
this._initialSearchCompleteResolver(true);
|
|
387
471
|
}
|
|
388
472
|
|
|
389
473
|
/**
|
|
@@ -401,26 +485,35 @@ export class CollectionBrowserDataSource
|
|
|
401
485
|
])
|
|
402
486
|
);
|
|
403
487
|
this.host.requestUpdate();
|
|
488
|
+
this.host.refreshVisibleResults();
|
|
404
489
|
}
|
|
405
490
|
|
|
406
491
|
/**
|
|
407
492
|
* @inheritdoc
|
|
408
493
|
*/
|
|
409
|
-
checkAllTiles(): void {
|
|
410
|
-
this.map(model =>
|
|
411
|
-
|
|
494
|
+
checkAllTiles = (): void => {
|
|
495
|
+
this.map(model => {
|
|
496
|
+
const cloned = model.clone();
|
|
497
|
+
cloned.checked = true;
|
|
498
|
+
return cloned;
|
|
499
|
+
});
|
|
500
|
+
};
|
|
412
501
|
|
|
413
502
|
/**
|
|
414
503
|
* @inheritdoc
|
|
415
504
|
*/
|
|
416
|
-
uncheckAllTiles(): void {
|
|
417
|
-
this.map(model =>
|
|
418
|
-
|
|
505
|
+
uncheckAllTiles = (): void => {
|
|
506
|
+
this.map(model => {
|
|
507
|
+
const cloned = model.clone();
|
|
508
|
+
cloned.checked = false;
|
|
509
|
+
return cloned;
|
|
510
|
+
});
|
|
511
|
+
};
|
|
419
512
|
|
|
420
513
|
/**
|
|
421
514
|
* @inheritdoc
|
|
422
515
|
*/
|
|
423
|
-
removeCheckedTiles(): void {
|
|
516
|
+
removeCheckedTiles = (): void => {
|
|
424
517
|
// To make sure our data source remains page-aligned, we will offset our data source by
|
|
425
518
|
// the number of removed tiles, so that we can just add the offset when the infinite
|
|
426
519
|
// scroller queries for cell contents.
|
|
@@ -458,7 +551,8 @@ export class CollectionBrowserDataSource
|
|
|
458
551
|
this.pages = newPages;
|
|
459
552
|
this.numTileModels -= numChecked;
|
|
460
553
|
this.host.requestUpdate();
|
|
461
|
-
|
|
554
|
+
this.host.refreshVisibleResults();
|
|
555
|
+
};
|
|
462
556
|
|
|
463
557
|
/**
|
|
464
558
|
* @inheritdoc
|
|
@@ -526,15 +620,15 @@ export class CollectionBrowserDataSource
|
|
|
526
620
|
* - Any currently-applied prefix filters
|
|
527
621
|
* - The current sort options
|
|
528
622
|
*
|
|
529
|
-
* This lets us keep track of queries so we don't persist data that's
|
|
530
|
-
* no longer relevant.
|
|
623
|
+
* This lets us internally keep track of queries so we don't persist data that's
|
|
624
|
+
* no longer relevant. Not meant to be human-readable.
|
|
531
625
|
*/
|
|
532
626
|
get pageFetchQueryKey(): string {
|
|
533
|
-
const profileKey =
|
|
627
|
+
const profileKey = `pf;${this.host.withinProfile}--pe;${this.host.profileElement}`;
|
|
534
628
|
const pageTarget = this.host.withinCollection ?? profileKey;
|
|
535
629
|
const sortField = this.host.sortParam?.field ?? 'none';
|
|
536
630
|
const sortDirection = this.host.sortParam?.direction ?? 'none';
|
|
537
|
-
return
|
|
631
|
+
return `fq:${this.fullQuery}-pt:${pageTarget}-st:${this.host.searchType}-sf:${sortField}-sd:${sortDirection}`;
|
|
538
632
|
}
|
|
539
633
|
|
|
540
634
|
/**
|
|
@@ -810,8 +904,10 @@ export class CollectionBrowserDataSource
|
|
|
810
904
|
* the current search state.
|
|
811
905
|
*/
|
|
812
906
|
private async fetchFacets(): Promise<void> {
|
|
907
|
+
console.log('fetchFacets', this.id, this.host.profileElement);
|
|
813
908
|
const trimmedQuery = this.host.baseQuery?.trim();
|
|
814
909
|
if (!this.canPerformSearch) return;
|
|
910
|
+
console.log('will actually fetch facets');
|
|
815
911
|
|
|
816
912
|
const { facetFetchQueryKey } = this;
|
|
817
913
|
|
|
@@ -843,7 +939,10 @@ export class CollectionBrowserDataSource
|
|
|
843
939
|
// likely no longer valid for the newer query.
|
|
844
940
|
const queryChangedSinceFetch =
|
|
845
941
|
facetFetchQueryKey !== this.facetFetchQueryKey;
|
|
846
|
-
if (queryChangedSinceFetch)
|
|
942
|
+
if (queryChangedSinceFetch) {
|
|
943
|
+
console.log('facet query has changed since fetch, returning. new/old:', this.facetFetchQueryKey, facetFetchQueryKey);
|
|
944
|
+
return;
|
|
945
|
+
}
|
|
847
946
|
|
|
848
947
|
if (!success) {
|
|
849
948
|
const errorMsg = searchResponse?.error?.message;
|
|
@@ -857,6 +956,7 @@ export class CollectionBrowserDataSource
|
|
|
857
956
|
);
|
|
858
957
|
}
|
|
859
958
|
|
|
959
|
+
this.host.setFacetsLoading(false);
|
|
860
960
|
return;
|
|
861
961
|
}
|
|
862
962
|
|
|
@@ -897,11 +997,13 @@ export class CollectionBrowserDataSource
|
|
|
897
997
|
async fetchPage(pageNumber: number, numInitialPages = 1): Promise<void> {
|
|
898
998
|
console.log(
|
|
899
999
|
`fetchPage(${pageNumber})`,
|
|
1000
|
+
this.id,
|
|
900
1001
|
this.canPerformSearch,
|
|
901
1002
|
this.hasPage(pageNumber),
|
|
902
1003
|
this.endOfDataReached,
|
|
903
1004
|
this.host.baseQuery,
|
|
904
|
-
JSON.stringify(this.host.selectedFacets)
|
|
1005
|
+
JSON.stringify(this.host.selectedFacets),
|
|
1006
|
+
this.pageFetchQueryKey
|
|
905
1007
|
);
|
|
906
1008
|
const trimmedQuery = this.host.baseQuery?.trim();
|
|
907
1009
|
if (!this.canPerformSearch) return;
|
|
@@ -930,6 +1032,7 @@ export class CollectionBrowserDataSource
|
|
|
930
1032
|
pageFetches.add(pageNumber + i);
|
|
931
1033
|
}
|
|
932
1034
|
this.pageFetchesInProgress[pageFetchQueryKey] = pageFetches;
|
|
1035
|
+
this.previousQueryKey = pageFetchQueryKey;
|
|
933
1036
|
|
|
934
1037
|
const sortParams = this.host.sortParam ? [this.host.sortParam] : [];
|
|
935
1038
|
const params: SearchParams = {
|
|
@@ -990,6 +1093,10 @@ export class CollectionBrowserDataSource
|
|
|
990
1093
|
}
|
|
991
1094
|
|
|
992
1095
|
if (this.host.withinCollection) {
|
|
1096
|
+
console.log(
|
|
1097
|
+
'host is within collection, setting collection info:',
|
|
1098
|
+
success.response.collectionExtraInfo
|
|
1099
|
+
);
|
|
993
1100
|
this.collectionExtraInfo = success.response.collectionExtraInfo;
|
|
994
1101
|
|
|
995
1102
|
// For collections, we want the UI to respect the default sort option
|
|
@@ -1004,10 +1111,17 @@ export class CollectionBrowserDataSource
|
|
|
1004
1111
|
} else if (this.host.withinProfile) {
|
|
1005
1112
|
console.log(
|
|
1006
1113
|
'host is within profile, setting acct info:',
|
|
1007
|
-
success.response.accountExtraInfo
|
|
1114
|
+
success.response.accountExtraInfo,
|
|
1115
|
+
success.response.pageElements
|
|
1008
1116
|
);
|
|
1009
1117
|
this.accountExtraInfo = success.response.accountExtraInfo;
|
|
1010
1118
|
this.pageElements = success.response.pageElements;
|
|
1119
|
+
} else {
|
|
1120
|
+
console.log(
|
|
1121
|
+
'not within profile/collxn',
|
|
1122
|
+
this.host.withinCollection,
|
|
1123
|
+
this.host.withinProfile
|
|
1124
|
+
);
|
|
1011
1125
|
}
|
|
1012
1126
|
|
|
1013
1127
|
const { results, collectionTitles } = success.response;
|
|
@@ -1035,6 +1149,7 @@ export class CollectionBrowserDataSource
|
|
|
1035
1149
|
// temporary estimates based on pages rendered so far).
|
|
1036
1150
|
const resultCountDiscrepancy = numRows - results.length;
|
|
1037
1151
|
if (resultCountDiscrepancy > 0) {
|
|
1152
|
+
console.log('End of data reached');
|
|
1038
1153
|
this.endOfDataReached = true;
|
|
1039
1154
|
this.host.setTileCount(this.totalResults);
|
|
1040
1155
|
}
|
|
@@ -1063,56 +1178,7 @@ export class CollectionBrowserDataSource
|
|
|
1063
1178
|
const tiles: TileModel[] = [];
|
|
1064
1179
|
results?.forEach(result => {
|
|
1065
1180
|
if (!result.identifier) return;
|
|
1066
|
-
|
|
1067
|
-
let loginRequired = false;
|
|
1068
|
-
let contentWarning = false;
|
|
1069
|
-
// Check if item and item in "modifying" collection, setting above flags
|
|
1070
|
-
if (
|
|
1071
|
-
result.collection?.values.length &&
|
|
1072
|
-
result.mediatype?.value !== 'collection'
|
|
1073
|
-
) {
|
|
1074
|
-
for (const collection of result.collection?.values ?? []) {
|
|
1075
|
-
if (collection === 'loggedin') {
|
|
1076
|
-
loginRequired = true;
|
|
1077
|
-
if (contentWarning) break;
|
|
1078
|
-
}
|
|
1079
|
-
if (collection === 'no-preview') {
|
|
1080
|
-
contentWarning = true;
|
|
1081
|
-
if (loginRequired) break;
|
|
1082
|
-
}
|
|
1083
|
-
}
|
|
1084
|
-
}
|
|
1085
|
-
|
|
1086
|
-
tiles.push({
|
|
1087
|
-
averageRating: result.avg_rating?.value,
|
|
1088
|
-
checked: false,
|
|
1089
|
-
collections: result.collection?.values ?? [],
|
|
1090
|
-
collectionFilesCount: result.collection_files_count?.value ?? 0,
|
|
1091
|
-
collectionSize: result.collection_size?.value ?? 0,
|
|
1092
|
-
commentCount: result.num_reviews?.value ?? 0,
|
|
1093
|
-
creator: result.creator?.value,
|
|
1094
|
-
creators: result.creator?.values ?? [],
|
|
1095
|
-
dateAdded: result.addeddate?.value,
|
|
1096
|
-
dateArchived: result.publicdate?.value,
|
|
1097
|
-
datePublished: result.date?.value,
|
|
1098
|
-
dateReviewed: result.reviewdate?.value,
|
|
1099
|
-
description: result.description?.values.join('\n'),
|
|
1100
|
-
favCount: result.num_favorites?.value ?? 0,
|
|
1101
|
-
href: this.collapseRepeatedQuotes(result.__href__?.value),
|
|
1102
|
-
identifier: result.identifier,
|
|
1103
|
-
issue: result.issue?.value,
|
|
1104
|
-
itemCount: result.item_count?.value ?? 0,
|
|
1105
|
-
mediatype: this.getMediatype(result),
|
|
1106
|
-
snippets: result.highlight?.values ?? [],
|
|
1107
|
-
source: result.source?.value,
|
|
1108
|
-
subjects: result.subject?.values ?? [],
|
|
1109
|
-
title: result.title?.value ?? '',
|
|
1110
|
-
volume: result.volume?.value,
|
|
1111
|
-
viewCount: result.downloads?.value ?? 0,
|
|
1112
|
-
weeklyViewCount: result.week?.value,
|
|
1113
|
-
loginRequired,
|
|
1114
|
-
contentWarning,
|
|
1115
|
-
});
|
|
1181
|
+
tiles.push(new TileModel(result));
|
|
1116
1182
|
});
|
|
1117
1183
|
this.addPage(pageNumber, tiles);
|
|
1118
1184
|
const visiblePages = this.host.currentVisiblePageNumbers;
|
|
@@ -1122,44 +1188,6 @@ export class CollectionBrowserDataSource
|
|
|
1122
1188
|
}
|
|
1123
1189
|
}
|
|
1124
1190
|
|
|
1125
|
-
/**
|
|
1126
|
-
* Returns the mediatype string for the given search result, taking into account
|
|
1127
|
-
* the special `favorited_search` hit type.
|
|
1128
|
-
* @param result The search result to extract a mediatype from
|
|
1129
|
-
*/
|
|
1130
|
-
private getMediatype(result: SearchResult): MediaType {
|
|
1131
|
-
/**
|
|
1132
|
-
* hit_type == 'favorited_search' is basically a new hit_type
|
|
1133
|
-
* - we are getting from PPS.
|
|
1134
|
-
* - which gives response for fav- collection
|
|
1135
|
-
* - having favorited items like account/collection/item etc..
|
|
1136
|
-
* - as user can also favorite a search result (a search page)
|
|
1137
|
-
* - so we need to have response (having fav- items and fav- search results)
|
|
1138
|
-
*
|
|
1139
|
-
* if backend hit_type == 'favorited_search'
|
|
1140
|
-
* - let's assume a "search" as new mediatype
|
|
1141
|
-
*/
|
|
1142
|
-
if (result?.rawMetadata?.hit_type === 'favorited_search') {
|
|
1143
|
-
return 'search';
|
|
1144
|
-
}
|
|
1145
|
-
|
|
1146
|
-
return result.mediatype?.value ?? 'data';
|
|
1147
|
-
}
|
|
1148
|
-
|
|
1149
|
-
/**
|
|
1150
|
-
* Returns the input string, but removing one set of quotes from all instances of
|
|
1151
|
-
* ""clauses wrapped in two sets of quotes"". This assumes the quotes are already
|
|
1152
|
-
* URL-encoded.
|
|
1153
|
-
*
|
|
1154
|
-
* This should be a temporary measure to address the fact that the __href__ field
|
|
1155
|
-
* sometimes acquires extra quotation marks during query rewriting. Once there is a
|
|
1156
|
-
* full Lucene parser in place that handles quoted queries correctly, this can likely
|
|
1157
|
-
* be removed.
|
|
1158
|
-
*/
|
|
1159
|
-
private collapseRepeatedQuotes(str?: string): string | undefined {
|
|
1160
|
-
return str?.replace(/%22%22(?!%22%22)(.+?)%22%22/g, '%22$1%22');
|
|
1161
|
-
}
|
|
1162
|
-
|
|
1163
1191
|
/**
|
|
1164
1192
|
* Fetches the aggregation buckets for the given prefix filter type.
|
|
1165
1193
|
*/
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
CollectionExtraInfo,
|
|
3
|
+
PageElementName,
|
|
3
4
|
PageType,
|
|
4
5
|
SearchServiceInterface,
|
|
5
6
|
SearchType,
|
|
@@ -7,6 +8,7 @@ import type {
|
|
|
7
8
|
SortParam,
|
|
8
9
|
} from '@internetarchive/search-service';
|
|
9
10
|
import type { SelectedFacets, SortField } from '../models';
|
|
11
|
+
import type { CollectionBrowserDataSourceInterface } from './collection-browser-data-source';
|
|
10
12
|
|
|
11
13
|
/**
|
|
12
14
|
* A Map from collection identifiers to their corresponding collection titles.
|
|
@@ -30,7 +32,7 @@ export type PageSpecifierParams = {
|
|
|
30
32
|
* Which specific elements of a profile page to fetch. Corresponds to individual tab data
|
|
31
33
|
* (e.g., "uploads", "reviews", ...)
|
|
32
34
|
*/
|
|
33
|
-
pageElements?:
|
|
35
|
+
pageElements?: PageElementName[];
|
|
34
36
|
};
|
|
35
37
|
|
|
36
38
|
/**
|
|
@@ -40,7 +42,7 @@ export interface CollectionBrowserQueryState {
|
|
|
40
42
|
baseQuery?: string;
|
|
41
43
|
withinCollection?: string;
|
|
42
44
|
withinProfile?: string;
|
|
43
|
-
profileElement?:
|
|
45
|
+
profileElement?: PageElementName;
|
|
44
46
|
searchType: SearchType;
|
|
45
47
|
selectedFacets?: SelectedFacets;
|
|
46
48
|
minSelectedDate?: string;
|
|
@@ -63,6 +65,8 @@ export interface CollectionBrowserSearchInterface
|
|
|
63
65
|
readonly suppressFacets?: boolean;
|
|
64
66
|
readonly initialPageNumber: number;
|
|
65
67
|
readonly currentVisiblePageNumbers: number[];
|
|
68
|
+
readonly clearResultsOnEmptyQuery?: boolean;
|
|
69
|
+
readonly dataSource: CollectionBrowserDataSourceInterface;
|
|
66
70
|
|
|
67
71
|
getSessionId(): Promise<string>;
|
|
68
72
|
setSearchResultsLoading(loading: boolean): void;
|