@internetarchive/collection-browser 1.14.17-alpha.3 → 1.14.17-alpha.30
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/collection-browser.d.ts +6 -13
- package/dist/src/collection-browser.js +54 -25
- package/dist/src/collection-browser.js.map +1 -1
- package/dist/src/data-source/collection-browser-data-source.d.ts +48 -30
- package/dist/src/data-source/collection-browser-data-source.js +106 -116
- package/dist/src/data-source/collection-browser-data-source.js.map +1 -1
- package/dist/src/data-source/models.d.ts +7 -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 +1 -0
- 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.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 +37 -25
- 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/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/collection-browser.ts +62 -42
- package/src/data-source/collection-browser-data-source.ts +170 -140
- package/src/data-source/models.ts +7 -2
- package/src/manage/manage-bar.ts +1 -1
- package/src/models.ts +154 -3
- package/src/sort-filter-bar/sort-filter-bar.ts +1 -0
- package/src/tiles/grid/item-tile.ts +36 -1
- package/src/tiles/grid/tile-stats.ts +12 -7
- 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 +72 -27
- package/test/collection-facets/more-facets-content.test.ts +4 -2
- 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
|
@@ -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
|
/**
|
|
@@ -50,6 +48,12 @@ export interface CollectionBrowserDataSourceInterface
|
|
|
50
48
|
*/
|
|
51
49
|
readonly endOfDataReached: boolean;
|
|
52
50
|
|
|
51
|
+
/**
|
|
52
|
+
* True if the initial work for a new query state has been completed (i.e., firing initial
|
|
53
|
+
* page/facet requests). False otherwise.
|
|
54
|
+
*/
|
|
55
|
+
readonly queryInitialized: boolean;
|
|
56
|
+
|
|
53
57
|
/**
|
|
54
58
|
* A string key compactly representing the current full search state, which can
|
|
55
59
|
* be used to determine, e.g., when a new search is required or whether an arriving
|
|
@@ -134,6 +138,20 @@ export interface CollectionBrowserDataSourceInterface
|
|
|
134
138
|
*/
|
|
135
139
|
readonly uncheckedTileModels: TileModel[];
|
|
136
140
|
|
|
141
|
+
/**
|
|
142
|
+
* A Promise which, after each query change, resolves once the fetches for the initial
|
|
143
|
+
* search have completed. Waits for *both* the hits and aggregations fetches to finish.
|
|
144
|
+
*
|
|
145
|
+
* Ensure you await this component's `updateComplete` promise before awaiting this
|
|
146
|
+
* one, to ensure you do not await an obsolete promise from the previous update.
|
|
147
|
+
*/
|
|
148
|
+
readonly initialSearchComplete: Promise<boolean>;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Resets the data source to its empty state, with no result pages, aggregations, etc.
|
|
152
|
+
*/
|
|
153
|
+
reset(): void;
|
|
154
|
+
|
|
137
155
|
/**
|
|
138
156
|
* Adds the given page of tile models to the data source.
|
|
139
157
|
* If the given page number already exists, that page will be overwritten.
|
|
@@ -197,11 +215,6 @@ export interface CollectionBrowserDataSourceInterface
|
|
|
197
215
|
*/
|
|
198
216
|
setPageSize(pageSize: number): void;
|
|
199
217
|
|
|
200
|
-
/**
|
|
201
|
-
* Resets the data source to its empty state, with no result pages, aggregations, etc.
|
|
202
|
-
*/
|
|
203
|
-
reset(): void;
|
|
204
|
-
|
|
205
218
|
/**
|
|
206
219
|
* Notifies the data source that a query change has occurred, which may trigger a data
|
|
207
220
|
* reset & new fetches.
|
|
@@ -248,6 +261,14 @@ export class CollectionBrowserDataSource
|
|
|
248
261
|
*/
|
|
249
262
|
private pageFetchesInProgress: Record<string, Set<number>> = {};
|
|
250
263
|
|
|
264
|
+
/**
|
|
265
|
+
* A record of the query key used for the last search.
|
|
266
|
+
* If this changes, we need to load new results.
|
|
267
|
+
*/
|
|
268
|
+
private previousQueryKey: string = '';
|
|
269
|
+
|
|
270
|
+
private id = Math.random();
|
|
271
|
+
|
|
251
272
|
/**
|
|
252
273
|
* @inheritdoc
|
|
253
274
|
*/
|
|
@@ -258,6 +279,11 @@ export class CollectionBrowserDataSource
|
|
|
258
279
|
*/
|
|
259
280
|
endOfDataReached = false;
|
|
260
281
|
|
|
282
|
+
/**
|
|
283
|
+
* @inheritdoc
|
|
284
|
+
*/
|
|
285
|
+
queryInitialized = false;
|
|
286
|
+
|
|
261
287
|
/**
|
|
262
288
|
* @inheritdoc
|
|
263
289
|
*/
|
|
@@ -299,6 +325,26 @@ export class CollectionBrowserDataSource
|
|
|
299
325
|
prefixFilterCountMap: Partial<Record<PrefixFilterType, PrefixFilterCounts>> =
|
|
300
326
|
{};
|
|
301
327
|
|
|
328
|
+
/**
|
|
329
|
+
* Internal property to store the `resolve` function for the most recent
|
|
330
|
+
* `initialSearchComplete` promise, allowing us to resolve it at the appropriate time.
|
|
331
|
+
*/
|
|
332
|
+
private _initialSearchCompleteResolver!: (val: boolean) => void;
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Internal property to store the private value backing the `initialSearchComplete` getter.
|
|
336
|
+
*/
|
|
337
|
+
private _initialSearchCompletePromise: Promise<boolean> = new Promise(res => {
|
|
338
|
+
this._initialSearchCompleteResolver = res;
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* @inheritdoc
|
|
343
|
+
*/
|
|
344
|
+
get initialSearchComplete(): Promise<boolean> {
|
|
345
|
+
return this._initialSearchCompletePromise;
|
|
346
|
+
}
|
|
347
|
+
|
|
302
348
|
constructor(
|
|
303
349
|
/** The host element to which this controller should attach listeners */
|
|
304
350
|
private readonly host: ReactiveControllerHost &
|
|
@@ -306,7 +352,35 @@ export class CollectionBrowserDataSource
|
|
|
306
352
|
/** Default size of result pages */
|
|
307
353
|
private pageSize: number
|
|
308
354
|
) {
|
|
309
|
-
|
|
355
|
+
// console.log('adding controller', this.id);
|
|
356
|
+
// this.host.addController(this as CollectionBrowserDataSourceInterface);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
hostUpdate(): void {
|
|
360
|
+
console.log('hostUpdate', this.id, this.previousQueryKey, this.pageFetchQueryKey);
|
|
361
|
+
// This reactive controller hook is run whenever the host component (collection-browser) performs an update.
|
|
362
|
+
// We check whether the host's state has changed in a way which should trigger a reset & new results fetch.
|
|
363
|
+
|
|
364
|
+
// Only the currently-installed data source should react to the update
|
|
365
|
+
if (this.host.dataSource !== this) return;
|
|
366
|
+
|
|
367
|
+
// Can't perform searches without a search service
|
|
368
|
+
if (!this.host.searchService) return;
|
|
369
|
+
|
|
370
|
+
// We should only reset if part of the full query state has changed
|
|
371
|
+
const queryKeyChanged = this.pageFetchQueryKey !== this.previousQueryKey;
|
|
372
|
+
console.log('query keys', this.pageFetchQueryKey, this.previousQueryKey);
|
|
373
|
+
if (!queryKeyChanged) return;
|
|
374
|
+
|
|
375
|
+
// We should only reset if either:
|
|
376
|
+
// (a) our state permits a valid search, or
|
|
377
|
+
// (b) we have a blank query that we want to show empty results for
|
|
378
|
+
const shouldShowEmptyQueryResults =
|
|
379
|
+
this.host.clearResultsOnEmptyQuery && this.host.baseQuery === '';
|
|
380
|
+
if (!(this.canPerformSearch || shouldShowEmptyQueryResults)) return;
|
|
381
|
+
|
|
382
|
+
this.host.emitQueryStateChanged();
|
|
383
|
+
this.handleQueryChange();
|
|
310
384
|
}
|
|
311
385
|
|
|
312
386
|
/**
|
|
@@ -316,6 +390,29 @@ export class CollectionBrowserDataSource
|
|
|
316
390
|
return this.numTileModels;
|
|
317
391
|
}
|
|
318
392
|
|
|
393
|
+
/**
|
|
394
|
+
* @inheritdoc
|
|
395
|
+
*/
|
|
396
|
+
reset(): void {
|
|
397
|
+
this.pages = {};
|
|
398
|
+
this.aggregations = {};
|
|
399
|
+
this.yearHistogramAggregation = undefined;
|
|
400
|
+
this.pageFetchesInProgress = {};
|
|
401
|
+
this.pageElements = undefined;
|
|
402
|
+
this.parentCollections = [];
|
|
403
|
+
this.prefixFilterCountMap = {};
|
|
404
|
+
|
|
405
|
+
this.offset = 0;
|
|
406
|
+
this.numTileModels = 0;
|
|
407
|
+
this.totalResults = 0;
|
|
408
|
+
this.endOfDataReached = false;
|
|
409
|
+
this.queryInitialized = false;
|
|
410
|
+
|
|
411
|
+
this.host.setTotalResultCount(0);
|
|
412
|
+
|
|
413
|
+
this.host.requestUpdate();
|
|
414
|
+
}
|
|
415
|
+
|
|
319
416
|
/**
|
|
320
417
|
* @inheritdoc
|
|
321
418
|
*/
|
|
@@ -370,35 +467,26 @@ export class CollectionBrowserDataSource
|
|
|
370
467
|
this.pageSize = pageSize;
|
|
371
468
|
}
|
|
372
469
|
|
|
373
|
-
/**
|
|
374
|
-
* @inheritdoc
|
|
375
|
-
*/
|
|
376
|
-
reset(): void {
|
|
377
|
-
this.pages = {};
|
|
378
|
-
this.aggregations = {};
|
|
379
|
-
this.yearHistogramAggregation = undefined;
|
|
380
|
-
this.pageFetchesInProgress = {};
|
|
381
|
-
this.pageElements = undefined;
|
|
382
|
-
this.parentCollections = [];
|
|
383
|
-
this.prefixFilterCountMap = {};
|
|
384
|
-
|
|
385
|
-
this.offset = 0;
|
|
386
|
-
this.numTileModels = 0;
|
|
387
|
-
this.totalResults = 0;
|
|
388
|
-
this.endOfDataReached = false;
|
|
389
|
-
|
|
390
|
-
this.host.requestUpdate();
|
|
391
|
-
}
|
|
392
|
-
|
|
393
470
|
/**
|
|
394
471
|
* @inheritdoc
|
|
395
472
|
*/
|
|
396
473
|
async handleQueryChange(): Promise<void> {
|
|
397
474
|
this.reset();
|
|
475
|
+
|
|
476
|
+
// Reset the `initialSearchComplete` promise with a new value for the imminent search
|
|
477
|
+
this._initialSearchCompletePromise = new Promise(res => {
|
|
478
|
+
this._initialSearchCompleteResolver = res;
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
// Fire the initial page & facet requests
|
|
482
|
+
this.queryInitialized = true;
|
|
398
483
|
await Promise.all([
|
|
399
484
|
this.doInitialPageFetch(),
|
|
400
485
|
this.host.suppressFacets ? null : this.fetchFacets(),
|
|
401
486
|
]);
|
|
487
|
+
|
|
488
|
+
// Resolve the `initialSearchComplete` promise for this search
|
|
489
|
+
this._initialSearchCompleteResolver(true);
|
|
402
490
|
}
|
|
403
491
|
|
|
404
492
|
/**
|
|
@@ -423,14 +511,22 @@ export class CollectionBrowserDataSource
|
|
|
423
511
|
* @inheritdoc
|
|
424
512
|
*/
|
|
425
513
|
checkAllTiles = (): void => {
|
|
426
|
-
this.map(model =>
|
|
514
|
+
this.map(model => {
|
|
515
|
+
const cloned = model.clone();
|
|
516
|
+
cloned.checked = true;
|
|
517
|
+
return cloned;
|
|
518
|
+
});
|
|
427
519
|
};
|
|
428
520
|
|
|
429
521
|
/**
|
|
430
522
|
* @inheritdoc
|
|
431
523
|
*/
|
|
432
524
|
uncheckAllTiles = (): void => {
|
|
433
|
-
this.map(model =>
|
|
525
|
+
this.map(model => {
|
|
526
|
+
const cloned = model.clone();
|
|
527
|
+
cloned.checked = false;
|
|
528
|
+
return cloned;
|
|
529
|
+
});
|
|
434
530
|
};
|
|
435
531
|
|
|
436
532
|
/**
|
|
@@ -474,6 +570,7 @@ export class CollectionBrowserDataSource
|
|
|
474
570
|
this.pages = newPages;
|
|
475
571
|
this.numTileModels -= numChecked;
|
|
476
572
|
this.host.requestUpdate();
|
|
573
|
+
this.host.refreshVisibleResults();
|
|
477
574
|
};
|
|
478
575
|
|
|
479
576
|
/**
|
|
@@ -542,15 +639,15 @@ export class CollectionBrowserDataSource
|
|
|
542
639
|
* - Any currently-applied prefix filters
|
|
543
640
|
* - The current sort options
|
|
544
641
|
*
|
|
545
|
-
* This lets us keep track of queries so we don't persist data that's
|
|
546
|
-
* no longer relevant.
|
|
642
|
+
* This lets us internally keep track of queries so we don't persist data that's
|
|
643
|
+
* no longer relevant. Not meant to be human-readable.
|
|
547
644
|
*/
|
|
548
645
|
get pageFetchQueryKey(): string {
|
|
549
|
-
const profileKey =
|
|
646
|
+
const profileKey = `pf;${this.host.withinProfile}--pe;${this.host.profileElement}`;
|
|
550
647
|
const pageTarget = this.host.withinCollection ?? profileKey;
|
|
551
648
|
const sortField = this.host.sortParam?.field ?? 'none';
|
|
552
649
|
const sortDirection = this.host.sortParam?.direction ?? 'none';
|
|
553
|
-
return
|
|
650
|
+
return `fq:${this.fullQuery}-pt:${pageTarget}-st:${this.host.searchType}-sf:${sortField}-sd:${sortDirection}`;
|
|
554
651
|
}
|
|
555
652
|
|
|
556
653
|
/**
|
|
@@ -826,8 +923,10 @@ export class CollectionBrowserDataSource
|
|
|
826
923
|
* the current search state.
|
|
827
924
|
*/
|
|
828
925
|
private async fetchFacets(): Promise<void> {
|
|
926
|
+
console.log('fetchFacets', this.id, this.host.profileElement);
|
|
829
927
|
const trimmedQuery = this.host.baseQuery?.trim();
|
|
830
928
|
if (!this.canPerformSearch) return;
|
|
929
|
+
console.log('will actually fetch facets');
|
|
831
930
|
|
|
832
931
|
const { facetFetchQueryKey } = this;
|
|
833
932
|
|
|
@@ -859,7 +958,14 @@ export class CollectionBrowserDataSource
|
|
|
859
958
|
// likely no longer valid for the newer query.
|
|
860
959
|
const queryChangedSinceFetch =
|
|
861
960
|
facetFetchQueryKey !== this.facetFetchQueryKey;
|
|
862
|
-
if (queryChangedSinceFetch)
|
|
961
|
+
if (queryChangedSinceFetch) {
|
|
962
|
+
console.log(
|
|
963
|
+
'facet query has changed since fetch, returning. new/old:',
|
|
964
|
+
this.facetFetchQueryKey,
|
|
965
|
+
facetFetchQueryKey
|
|
966
|
+
);
|
|
967
|
+
return;
|
|
968
|
+
}
|
|
863
969
|
|
|
864
970
|
if (!success) {
|
|
865
971
|
const errorMsg = searchResponse?.error?.message;
|
|
@@ -873,6 +979,7 @@ export class CollectionBrowserDataSource
|
|
|
873
979
|
);
|
|
874
980
|
}
|
|
875
981
|
|
|
982
|
+
this.host.setFacetsLoading(false);
|
|
876
983
|
return;
|
|
877
984
|
}
|
|
878
985
|
|
|
@@ -911,14 +1018,6 @@ export class CollectionBrowserDataSource
|
|
|
911
1018
|
* if `pageNumber != 1`, defaulting to a single page.
|
|
912
1019
|
*/
|
|
913
1020
|
async fetchPage(pageNumber: number, numInitialPages = 1): Promise<void> {
|
|
914
|
-
console.log(
|
|
915
|
-
`fetchPage(${pageNumber})`,
|
|
916
|
-
this.canPerformSearch,
|
|
917
|
-
this.hasPage(pageNumber),
|
|
918
|
-
this.endOfDataReached,
|
|
919
|
-
this.host.baseQuery,
|
|
920
|
-
JSON.stringify(this.host.selectedFacets)
|
|
921
|
-
);
|
|
922
1021
|
const trimmedQuery = this.host.baseQuery?.trim();
|
|
923
1022
|
if (!this.canPerformSearch) return;
|
|
924
1023
|
|
|
@@ -936,16 +1035,23 @@ export class CollectionBrowserDataSource
|
|
|
936
1035
|
const { pageFetchQueryKey } = this;
|
|
937
1036
|
const pageFetches =
|
|
938
1037
|
this.pageFetchesInProgress[pageFetchQueryKey] ?? new Set();
|
|
939
|
-
if (pageFetches.has(pageNumber))
|
|
940
|
-
|
|
941
|
-
`Skipping fetch for page ${pageNumber} because one is already in progress`
|
|
942
|
-
);
|
|
943
|
-
return;
|
|
944
|
-
}
|
|
1038
|
+
if (pageFetches.has(pageNumber)) return;
|
|
1039
|
+
|
|
945
1040
|
for (let i = 0; i < numPages; i += 1) {
|
|
946
1041
|
pageFetches.add(pageNumber + i);
|
|
947
1042
|
}
|
|
1043
|
+
console.log(
|
|
1044
|
+
`fetchPage(${pageNumber})`,
|
|
1045
|
+
this.id,
|
|
1046
|
+
this.canPerformSearch,
|
|
1047
|
+
this.hasPage(pageNumber),
|
|
1048
|
+
this.endOfDataReached,
|
|
1049
|
+
this.host.baseQuery,
|
|
1050
|
+
JSON.stringify(this.host.selectedFacets),
|
|
1051
|
+
this.pageFetchQueryKey
|
|
1052
|
+
);
|
|
948
1053
|
this.pageFetchesInProgress[pageFetchQueryKey] = pageFetches;
|
|
1054
|
+
this.previousQueryKey = pageFetchQueryKey;
|
|
949
1055
|
|
|
950
1056
|
const sortParams = this.host.sortParam ? [this.host.sortParam] : [];
|
|
951
1057
|
const params: SearchParams = {
|
|
@@ -1006,6 +1112,10 @@ export class CollectionBrowserDataSource
|
|
|
1006
1112
|
}
|
|
1007
1113
|
|
|
1008
1114
|
if (this.host.withinCollection) {
|
|
1115
|
+
console.log(
|
|
1116
|
+
'host is within collection, setting collection info:',
|
|
1117
|
+
success.response.collectionExtraInfo
|
|
1118
|
+
);
|
|
1009
1119
|
this.collectionExtraInfo = success.response.collectionExtraInfo;
|
|
1010
1120
|
|
|
1011
1121
|
// For collections, we want the UI to respect the default sort option
|
|
@@ -1020,10 +1130,17 @@ export class CollectionBrowserDataSource
|
|
|
1020
1130
|
} else if (this.host.withinProfile) {
|
|
1021
1131
|
console.log(
|
|
1022
1132
|
'host is within profile, setting acct info:',
|
|
1023
|
-
success.response.accountExtraInfo
|
|
1133
|
+
success.response.accountExtraInfo,
|
|
1134
|
+
success.response.pageElements
|
|
1024
1135
|
);
|
|
1025
1136
|
this.accountExtraInfo = success.response.accountExtraInfo;
|
|
1026
1137
|
this.pageElements = success.response.pageElements;
|
|
1138
|
+
} else {
|
|
1139
|
+
console.log(
|
|
1140
|
+
'not within profile/collxn',
|
|
1141
|
+
this.host.withinCollection,
|
|
1142
|
+
this.host.withinProfile
|
|
1143
|
+
);
|
|
1027
1144
|
}
|
|
1028
1145
|
|
|
1029
1146
|
const { results, collectionTitles } = success.response;
|
|
@@ -1080,56 +1197,7 @@ export class CollectionBrowserDataSource
|
|
|
1080
1197
|
const tiles: TileModel[] = [];
|
|
1081
1198
|
results?.forEach(result => {
|
|
1082
1199
|
if (!result.identifier) return;
|
|
1083
|
-
|
|
1084
|
-
let loginRequired = false;
|
|
1085
|
-
let contentWarning = false;
|
|
1086
|
-
// Check if item and item in "modifying" collection, setting above flags
|
|
1087
|
-
if (
|
|
1088
|
-
result.collection?.values.length &&
|
|
1089
|
-
result.mediatype?.value !== 'collection'
|
|
1090
|
-
) {
|
|
1091
|
-
for (const collection of result.collection?.values ?? []) {
|
|
1092
|
-
if (collection === 'loggedin') {
|
|
1093
|
-
loginRequired = true;
|
|
1094
|
-
if (contentWarning) break;
|
|
1095
|
-
}
|
|
1096
|
-
if (collection === 'no-preview') {
|
|
1097
|
-
contentWarning = true;
|
|
1098
|
-
if (loginRequired) break;
|
|
1099
|
-
}
|
|
1100
|
-
}
|
|
1101
|
-
}
|
|
1102
|
-
|
|
1103
|
-
tiles.push({
|
|
1104
|
-
averageRating: result.avg_rating?.value,
|
|
1105
|
-
checked: false,
|
|
1106
|
-
collections: result.collection?.values ?? [],
|
|
1107
|
-
collectionFilesCount: result.collection_files_count?.value ?? 0,
|
|
1108
|
-
collectionSize: result.collection_size?.value ?? 0,
|
|
1109
|
-
commentCount: result.num_reviews?.value ?? 0,
|
|
1110
|
-
creator: result.creator?.value,
|
|
1111
|
-
creators: result.creator?.values ?? [],
|
|
1112
|
-
dateAdded: result.addeddate?.value,
|
|
1113
|
-
dateArchived: result.publicdate?.value,
|
|
1114
|
-
datePublished: result.date?.value,
|
|
1115
|
-
dateReviewed: result.reviewdate?.value,
|
|
1116
|
-
description: result.description?.values.join('\n'),
|
|
1117
|
-
favCount: result.num_favorites?.value ?? 0,
|
|
1118
|
-
href: this.collapseRepeatedQuotes(result.__href__?.value),
|
|
1119
|
-
identifier: result.identifier,
|
|
1120
|
-
issue: result.issue?.value,
|
|
1121
|
-
itemCount: result.item_count?.value ?? 0,
|
|
1122
|
-
mediatype: this.getMediatype(result),
|
|
1123
|
-
snippets: result.highlight?.values ?? [],
|
|
1124
|
-
source: result.source?.value,
|
|
1125
|
-
subjects: result.subject?.values ?? [],
|
|
1126
|
-
title: result.title?.value ?? '',
|
|
1127
|
-
volume: result.volume?.value,
|
|
1128
|
-
viewCount: result.downloads?.value ?? 0,
|
|
1129
|
-
weeklyViewCount: result.week?.value,
|
|
1130
|
-
loginRequired,
|
|
1131
|
-
contentWarning,
|
|
1132
|
-
});
|
|
1200
|
+
tiles.push(new TileModel(result));
|
|
1133
1201
|
});
|
|
1134
1202
|
this.addPage(pageNumber, tiles);
|
|
1135
1203
|
const visiblePages = this.host.currentVisiblePageNumbers;
|
|
@@ -1139,44 +1207,6 @@ export class CollectionBrowserDataSource
|
|
|
1139
1207
|
}
|
|
1140
1208
|
}
|
|
1141
1209
|
|
|
1142
|
-
/**
|
|
1143
|
-
* Returns the mediatype string for the given search result, taking into account
|
|
1144
|
-
* the special `favorited_search` hit type.
|
|
1145
|
-
* @param result The search result to extract a mediatype from
|
|
1146
|
-
*/
|
|
1147
|
-
private getMediatype(result: SearchResult): MediaType {
|
|
1148
|
-
/**
|
|
1149
|
-
* hit_type == 'favorited_search' is basically a new hit_type
|
|
1150
|
-
* - we are getting from PPS.
|
|
1151
|
-
* - which gives response for fav- collection
|
|
1152
|
-
* - having favorited items like account/collection/item etc..
|
|
1153
|
-
* - as user can also favorite a search result (a search page)
|
|
1154
|
-
* - so we need to have response (having fav- items and fav- search results)
|
|
1155
|
-
*
|
|
1156
|
-
* if backend hit_type == 'favorited_search'
|
|
1157
|
-
* - let's assume a "search" as new mediatype
|
|
1158
|
-
*/
|
|
1159
|
-
if (result?.rawMetadata?.hit_type === 'favorited_search') {
|
|
1160
|
-
return 'search';
|
|
1161
|
-
}
|
|
1162
|
-
|
|
1163
|
-
return result.mediatype?.value ?? 'data';
|
|
1164
|
-
}
|
|
1165
|
-
|
|
1166
|
-
/**
|
|
1167
|
-
* Returns the input string, but removing one set of quotes from all instances of
|
|
1168
|
-
* ""clauses wrapped in two sets of quotes"". This assumes the quotes are already
|
|
1169
|
-
* URL-encoded.
|
|
1170
|
-
*
|
|
1171
|
-
* This should be a temporary measure to address the fact that the __href__ field
|
|
1172
|
-
* sometimes acquires extra quotation marks during query rewriting. Once there is a
|
|
1173
|
-
* full Lucene parser in place that handles quoted queries correctly, this can likely
|
|
1174
|
-
* be removed.
|
|
1175
|
-
*/
|
|
1176
|
-
private collapseRepeatedQuotes(str?: string): string | undefined {
|
|
1177
|
-
return str?.replace(/%22%22(?!%22%22)(.+?)%22%22/g, '%22$1%22');
|
|
1178
|
-
}
|
|
1179
|
-
|
|
1180
1210
|
/**
|
|
1181
1211
|
* Fetches the aggregation buckets for the given prefix filter type.
|
|
1182
1212
|
*/
|
|
@@ -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;
|
|
@@ -71,5 +75,6 @@ export interface CollectionBrowserSearchInterface
|
|
|
71
75
|
setTileCount(count: number): void;
|
|
72
76
|
applyDefaultCollectionSort(collectionInfo?: CollectionExtraInfo): void;
|
|
73
77
|
emitEmptyResults(): void;
|
|
78
|
+
emitQueryStateChanged(): void;
|
|
74
79
|
refreshVisibleResults(): void;
|
|
75
80
|
}
|