@internetarchive/collection-browser 1.14.17-alpha.3 → 1.14.17-alpha.31
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/item-image.js +15 -2
- package/dist/src/tiles/item-image.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/item-image.ts +13 -0
- 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
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type { ReactiveController, ReactiveControllerHost } from 'lit';
|
|
2
2
|
import { AccountExtraInfo, Aggregation, CollectionExtraInfo, FilterMap, PageElementMap, SearchParams } from '@internetarchive/search-service';
|
|
3
|
-
import { type PrefixFilterType,
|
|
3
|
+
import { type PrefixFilterType, TileModel, PrefixFilterCounts, RequestKind } from '../models';
|
|
4
4
|
import type { CollectionBrowserSearchInterface, CollectionTitles, PageSpecifierParams } from './models';
|
|
5
|
-
declare type RequestKind = 'full' | 'hits' | 'aggregations';
|
|
6
5
|
export interface CollectionBrowserDataSourceInterface extends ReactiveController {
|
|
7
6
|
/**
|
|
8
7
|
* How many tile models are present in this data source
|
|
@@ -20,6 +19,11 @@ export interface CollectionBrowserDataSourceInterface extends ReactiveController
|
|
|
20
19
|
* encountered (i.e., the last page of results).
|
|
21
20
|
*/
|
|
22
21
|
readonly endOfDataReached: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* True if the initial work for a new query state has been completed (i.e., firing initial
|
|
24
|
+
* page/facet requests). False otherwise.
|
|
25
|
+
*/
|
|
26
|
+
readonly queryInitialized: boolean;
|
|
23
27
|
/**
|
|
24
28
|
* A string key compactly representing the current full search state, which can
|
|
25
29
|
* be used to determine, e.g., when a new search is required or whether an arriving
|
|
@@ -88,6 +92,18 @@ export interface CollectionBrowserDataSourceInterface extends ReactiveController
|
|
|
88
92
|
* An array of all the tile models whose management checkboxes are unchecked
|
|
89
93
|
*/
|
|
90
94
|
readonly uncheckedTileModels: TileModel[];
|
|
95
|
+
/**
|
|
96
|
+
* A Promise which, after each query change, resolves once the fetches for the initial
|
|
97
|
+
* search have completed. Waits for *both* the hits and aggregations fetches to finish.
|
|
98
|
+
*
|
|
99
|
+
* Ensure you await this component's `updateComplete` promise before awaiting this
|
|
100
|
+
* one, to ensure you do not await an obsolete promise from the previous update.
|
|
101
|
+
*/
|
|
102
|
+
readonly initialSearchComplete: Promise<boolean>;
|
|
103
|
+
/**
|
|
104
|
+
* Resets the data source to its empty state, with no result pages, aggregations, etc.
|
|
105
|
+
*/
|
|
106
|
+
reset(): void;
|
|
91
107
|
/**
|
|
92
108
|
* Adds the given page of tile models to the data source.
|
|
93
109
|
* If the given page number already exists, that page will be overwritten.
|
|
@@ -142,10 +158,6 @@ export interface CollectionBrowserDataSourceInterface extends ReactiveController
|
|
|
142
158
|
* @param pageSize
|
|
143
159
|
*/
|
|
144
160
|
setPageSize(pageSize: number): void;
|
|
145
|
-
/**
|
|
146
|
-
* Resets the data source to its empty state, with no result pages, aggregations, etc.
|
|
147
|
-
*/
|
|
148
|
-
reset(): void;
|
|
149
161
|
/**
|
|
150
162
|
* Notifies the data source that a query change has occurred, which may trigger a data
|
|
151
163
|
* reset & new fetches.
|
|
@@ -183,6 +195,12 @@ export declare class CollectionBrowserDataSource implements CollectionBrowserDat
|
|
|
183
195
|
* Maps the full query key to the pages being fetched for that query
|
|
184
196
|
*/
|
|
185
197
|
private pageFetchesInProgress;
|
|
198
|
+
/**
|
|
199
|
+
* A record of the query key used for the last search.
|
|
200
|
+
* If this changes, we need to load new results.
|
|
201
|
+
*/
|
|
202
|
+
private previousQueryKey;
|
|
203
|
+
private id;
|
|
186
204
|
/**
|
|
187
205
|
* @inheritdoc
|
|
188
206
|
*/
|
|
@@ -191,6 +209,10 @@ export declare class CollectionBrowserDataSource implements CollectionBrowserDat
|
|
|
191
209
|
* @inheritdoc
|
|
192
210
|
*/
|
|
193
211
|
endOfDataReached: boolean;
|
|
212
|
+
/**
|
|
213
|
+
* @inheritdoc
|
|
214
|
+
*/
|
|
215
|
+
queryInitialized: boolean;
|
|
194
216
|
/**
|
|
195
217
|
* @inheritdoc
|
|
196
218
|
*/
|
|
@@ -223,15 +245,33 @@ export declare class CollectionBrowserDataSource implements CollectionBrowserDat
|
|
|
223
245
|
* @inheritdoc
|
|
224
246
|
*/
|
|
225
247
|
prefixFilterCountMap: Partial<Record<PrefixFilterType, PrefixFilterCounts>>;
|
|
248
|
+
/**
|
|
249
|
+
* Internal property to store the `resolve` function for the most recent
|
|
250
|
+
* `initialSearchComplete` promise, allowing us to resolve it at the appropriate time.
|
|
251
|
+
*/
|
|
252
|
+
private _initialSearchCompleteResolver;
|
|
253
|
+
/**
|
|
254
|
+
* Internal property to store the private value backing the `initialSearchComplete` getter.
|
|
255
|
+
*/
|
|
256
|
+
private _initialSearchCompletePromise;
|
|
257
|
+
/**
|
|
258
|
+
* @inheritdoc
|
|
259
|
+
*/
|
|
260
|
+
get initialSearchComplete(): Promise<boolean>;
|
|
226
261
|
constructor(
|
|
227
262
|
/** The host element to which this controller should attach listeners */
|
|
228
263
|
host: ReactiveControllerHost & CollectionBrowserSearchInterface,
|
|
229
264
|
/** Default size of result pages */
|
|
230
265
|
pageSize: number);
|
|
266
|
+
hostUpdate(): void;
|
|
231
267
|
/**
|
|
232
268
|
* @inheritdoc
|
|
233
269
|
*/
|
|
234
270
|
get size(): number;
|
|
271
|
+
/**
|
|
272
|
+
* @inheritdoc
|
|
273
|
+
*/
|
|
274
|
+
reset(): void;
|
|
235
275
|
/**
|
|
236
276
|
* @inheritdoc
|
|
237
277
|
*/
|
|
@@ -260,10 +300,6 @@ export declare class CollectionBrowserDataSource implements CollectionBrowserDat
|
|
|
260
300
|
* @inheritdoc
|
|
261
301
|
*/
|
|
262
302
|
setPageSize(pageSize: number): void;
|
|
263
|
-
/**
|
|
264
|
-
* @inheritdoc
|
|
265
|
-
*/
|
|
266
|
-
reset(): void;
|
|
267
303
|
/**
|
|
268
304
|
* @inheritdoc
|
|
269
305
|
*/
|
|
@@ -315,8 +351,8 @@ export declare class CollectionBrowserDataSource implements CollectionBrowserDat
|
|
|
315
351
|
* - Any currently-applied prefix filters
|
|
316
352
|
* - The current sort options
|
|
317
353
|
*
|
|
318
|
-
* This lets us keep track of queries so we don't persist data that's
|
|
319
|
-
* no longer relevant.
|
|
354
|
+
* This lets us internally keep track of queries so we don't persist data that's
|
|
355
|
+
* no longer relevant. Not meant to be human-readable.
|
|
320
356
|
*/
|
|
321
357
|
get pageFetchQueryKey(): string;
|
|
322
358
|
/**
|
|
@@ -416,23 +452,6 @@ export declare class CollectionBrowserDataSource implements CollectionBrowserDat
|
|
|
416
452
|
* @param results
|
|
417
453
|
*/
|
|
418
454
|
private addTilesToDataSource;
|
|
419
|
-
/**
|
|
420
|
-
* Returns the mediatype string for the given search result, taking into account
|
|
421
|
-
* the special `favorited_search` hit type.
|
|
422
|
-
* @param result The search result to extract a mediatype from
|
|
423
|
-
*/
|
|
424
|
-
private getMediatype;
|
|
425
|
-
/**
|
|
426
|
-
* Returns the input string, but removing one set of quotes from all instances of
|
|
427
|
-
* ""clauses wrapped in two sets of quotes"". This assumes the quotes are already
|
|
428
|
-
* URL-encoded.
|
|
429
|
-
*
|
|
430
|
-
* This should be a temporary measure to address the fact that the __href__ field
|
|
431
|
-
* sometimes acquires extra quotation marks during query rewriting. Once there is a
|
|
432
|
-
* full Lucene parser in place that handles quoted queries correctly, this can likely
|
|
433
|
-
* be removed.
|
|
434
|
-
*/
|
|
435
|
-
private collapseRepeatedQuotes;
|
|
436
455
|
/**
|
|
437
456
|
* Fetches the aggregation buckets for the given prefix filter type.
|
|
438
457
|
*/
|
|
@@ -442,4 +461,3 @@ export declare class CollectionBrowserDataSource implements CollectionBrowserDat
|
|
|
442
461
|
*/
|
|
443
462
|
updatePrefixFilterCounts(filterType: PrefixFilterType): Promise<void>;
|
|
444
463
|
}
|
|
445
|
-
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FilterConstraint, FilterMapBuilder, SearchType, } from '@internetarchive/search-service';
|
|
2
|
-
import { prefixFilterAggregationKeys, } from '../models';
|
|
2
|
+
import { prefixFilterAggregationKeys, TileModel, } from '../models';
|
|
3
3
|
import { sha1 } from '../utils/sha1';
|
|
4
4
|
export class CollectionBrowserDataSource {
|
|
5
5
|
constructor(
|
|
@@ -16,6 +16,12 @@ export class CollectionBrowserDataSource {
|
|
|
16
16
|
* Maps the full query key to the pages being fetched for that query
|
|
17
17
|
*/
|
|
18
18
|
this.pageFetchesInProgress = {};
|
|
19
|
+
/**
|
|
20
|
+
* A record of the query key used for the last search.
|
|
21
|
+
* If this changes, we need to load new results.
|
|
22
|
+
*/
|
|
23
|
+
this.previousQueryKey = '';
|
|
24
|
+
this.id = Math.random();
|
|
19
25
|
/**
|
|
20
26
|
* @inheritdoc
|
|
21
27
|
*/
|
|
@@ -24,6 +30,10 @@ export class CollectionBrowserDataSource {
|
|
|
24
30
|
* @inheritdoc
|
|
25
31
|
*/
|
|
26
32
|
this.endOfDataReached = false;
|
|
33
|
+
/**
|
|
34
|
+
* @inheritdoc
|
|
35
|
+
*/
|
|
36
|
+
this.queryInitialized = false;
|
|
27
37
|
/**
|
|
28
38
|
* @inheritdoc
|
|
29
39
|
*/
|
|
@@ -36,17 +46,31 @@ export class CollectionBrowserDataSource {
|
|
|
36
46
|
* @inheritdoc
|
|
37
47
|
*/
|
|
38
48
|
this.prefixFilterCountMap = {};
|
|
49
|
+
/**
|
|
50
|
+
* Internal property to store the private value backing the `initialSearchComplete` getter.
|
|
51
|
+
*/
|
|
52
|
+
this._initialSearchCompletePromise = new Promise(res => {
|
|
53
|
+
this._initialSearchCompleteResolver = res;
|
|
54
|
+
});
|
|
39
55
|
/**
|
|
40
56
|
* @inheritdoc
|
|
41
57
|
*/
|
|
42
58
|
this.checkAllTiles = () => {
|
|
43
|
-
this.map(model =>
|
|
59
|
+
this.map(model => {
|
|
60
|
+
const cloned = model.clone();
|
|
61
|
+
cloned.checked = true;
|
|
62
|
+
return cloned;
|
|
63
|
+
});
|
|
44
64
|
};
|
|
45
65
|
/**
|
|
46
66
|
* @inheritdoc
|
|
47
67
|
*/
|
|
48
68
|
this.uncheckAllTiles = () => {
|
|
49
|
-
this.map(model =>
|
|
69
|
+
this.map(model => {
|
|
70
|
+
const cloned = model.clone();
|
|
71
|
+
cloned.checked = false;
|
|
72
|
+
return cloned;
|
|
73
|
+
});
|
|
50
74
|
};
|
|
51
75
|
/**
|
|
52
76
|
* @inheritdoc
|
|
@@ -87,8 +111,40 @@ export class CollectionBrowserDataSource {
|
|
|
87
111
|
this.pages = newPages;
|
|
88
112
|
this.numTileModels -= numChecked;
|
|
89
113
|
this.host.requestUpdate();
|
|
114
|
+
this.host.refreshVisibleResults();
|
|
90
115
|
};
|
|
91
|
-
|
|
116
|
+
// console.log('adding controller', this.id);
|
|
117
|
+
// this.host.addController(this as CollectionBrowserDataSourceInterface);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* @inheritdoc
|
|
121
|
+
*/
|
|
122
|
+
get initialSearchComplete() {
|
|
123
|
+
return this._initialSearchCompletePromise;
|
|
124
|
+
}
|
|
125
|
+
hostUpdate() {
|
|
126
|
+
console.log('hostUpdate', this.id, this.previousQueryKey, this.pageFetchQueryKey);
|
|
127
|
+
// This reactive controller hook is run whenever the host component (collection-browser) performs an update.
|
|
128
|
+
// We check whether the host's state has changed in a way which should trigger a reset & new results fetch.
|
|
129
|
+
// Only the currently-installed data source should react to the update
|
|
130
|
+
if (this.host.dataSource !== this)
|
|
131
|
+
return;
|
|
132
|
+
// Can't perform searches without a search service
|
|
133
|
+
if (!this.host.searchService)
|
|
134
|
+
return;
|
|
135
|
+
// We should only reset if part of the full query state has changed
|
|
136
|
+
const queryKeyChanged = this.pageFetchQueryKey !== this.previousQueryKey;
|
|
137
|
+
console.log('query keys', this.pageFetchQueryKey, this.previousQueryKey);
|
|
138
|
+
if (!queryKeyChanged)
|
|
139
|
+
return;
|
|
140
|
+
// We should only reset if either:
|
|
141
|
+
// (a) our state permits a valid search, or
|
|
142
|
+
// (b) we have a blank query that we want to show empty results for
|
|
143
|
+
const shouldShowEmptyQueryResults = this.host.clearResultsOnEmptyQuery && this.host.baseQuery === '';
|
|
144
|
+
if (!(this.canPerformSearch || shouldShowEmptyQueryResults))
|
|
145
|
+
return;
|
|
146
|
+
this.host.emitQueryStateChanged();
|
|
147
|
+
this.handleQueryChange();
|
|
92
148
|
}
|
|
93
149
|
/**
|
|
94
150
|
* @inheritdoc
|
|
@@ -96,6 +152,25 @@ export class CollectionBrowserDataSource {
|
|
|
96
152
|
get size() {
|
|
97
153
|
return this.numTileModels;
|
|
98
154
|
}
|
|
155
|
+
/**
|
|
156
|
+
* @inheritdoc
|
|
157
|
+
*/
|
|
158
|
+
reset() {
|
|
159
|
+
this.pages = {};
|
|
160
|
+
this.aggregations = {};
|
|
161
|
+
this.yearHistogramAggregation = undefined;
|
|
162
|
+
this.pageFetchesInProgress = {};
|
|
163
|
+
this.pageElements = undefined;
|
|
164
|
+
this.parentCollections = [];
|
|
165
|
+
this.prefixFilterCountMap = {};
|
|
166
|
+
this.offset = 0;
|
|
167
|
+
this.numTileModels = 0;
|
|
168
|
+
this.totalResults = 0;
|
|
169
|
+
this.endOfDataReached = false;
|
|
170
|
+
this.queryInitialized = false;
|
|
171
|
+
this.host.setTotalResultCount(0);
|
|
172
|
+
this.host.requestUpdate();
|
|
173
|
+
}
|
|
99
174
|
/**
|
|
100
175
|
* @inheritdoc
|
|
101
176
|
*/
|
|
@@ -144,32 +219,23 @@ export class CollectionBrowserDataSource {
|
|
|
144
219
|
this.reset();
|
|
145
220
|
this.pageSize = pageSize;
|
|
146
221
|
}
|
|
147
|
-
/**
|
|
148
|
-
* @inheritdoc
|
|
149
|
-
*/
|
|
150
|
-
reset() {
|
|
151
|
-
this.pages = {};
|
|
152
|
-
this.aggregations = {};
|
|
153
|
-
this.yearHistogramAggregation = undefined;
|
|
154
|
-
this.pageFetchesInProgress = {};
|
|
155
|
-
this.pageElements = undefined;
|
|
156
|
-
this.parentCollections = [];
|
|
157
|
-
this.prefixFilterCountMap = {};
|
|
158
|
-
this.offset = 0;
|
|
159
|
-
this.numTileModels = 0;
|
|
160
|
-
this.totalResults = 0;
|
|
161
|
-
this.endOfDataReached = false;
|
|
162
|
-
this.host.requestUpdate();
|
|
163
|
-
}
|
|
164
222
|
/**
|
|
165
223
|
* @inheritdoc
|
|
166
224
|
*/
|
|
167
225
|
async handleQueryChange() {
|
|
168
226
|
this.reset();
|
|
227
|
+
// Reset the `initialSearchComplete` promise with a new value for the imminent search
|
|
228
|
+
this._initialSearchCompletePromise = new Promise(res => {
|
|
229
|
+
this._initialSearchCompleteResolver = res;
|
|
230
|
+
});
|
|
231
|
+
// Fire the initial page & facet requests
|
|
232
|
+
this.queryInitialized = true;
|
|
169
233
|
await Promise.all([
|
|
170
234
|
this.doInitialPageFetch(),
|
|
171
235
|
this.host.suppressFacets ? null : this.fetchFacets(),
|
|
172
236
|
]);
|
|
237
|
+
// Resolve the `initialSearchComplete` promise for this search
|
|
238
|
+
this._initialSearchCompleteResolver(true);
|
|
173
239
|
}
|
|
174
240
|
/**
|
|
175
241
|
* @inheritdoc
|
|
@@ -237,16 +303,16 @@ export class CollectionBrowserDataSource {
|
|
|
237
303
|
* - Any currently-applied prefix filters
|
|
238
304
|
* - The current sort options
|
|
239
305
|
*
|
|
240
|
-
* This lets us keep track of queries so we don't persist data that's
|
|
241
|
-
* no longer relevant.
|
|
306
|
+
* This lets us internally keep track of queries so we don't persist data that's
|
|
307
|
+
* no longer relevant. Not meant to be human-readable.
|
|
242
308
|
*/
|
|
243
309
|
get pageFetchQueryKey() {
|
|
244
310
|
var _a, _b, _c, _d, _e;
|
|
245
|
-
const profileKey =
|
|
311
|
+
const profileKey = `pf;${this.host.withinProfile}--pe;${this.host.profileElement}`;
|
|
246
312
|
const pageTarget = (_a = this.host.withinCollection) !== null && _a !== void 0 ? _a : profileKey;
|
|
247
313
|
const sortField = (_c = (_b = this.host.sortParam) === null || _b === void 0 ? void 0 : _b.field) !== null && _c !== void 0 ? _c : 'none';
|
|
248
314
|
const sortDirection = (_e = (_d = this.host.sortParam) === null || _d === void 0 ? void 0 : _d.direction) !== null && _e !== void 0 ? _e : 'none';
|
|
249
|
-
return
|
|
315
|
+
return `fq:${this.fullQuery}-pt:${pageTarget}-st:${this.host.searchType}-sf:${sortField}-sd:${sortDirection}`;
|
|
250
316
|
}
|
|
251
317
|
/**
|
|
252
318
|
* Similar to `pageFetchQueryKey` above, but excludes sort fields since they
|
|
@@ -468,9 +534,11 @@ export class CollectionBrowserDataSource {
|
|
|
468
534
|
*/
|
|
469
535
|
async fetchFacets() {
|
|
470
536
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
537
|
+
console.log('fetchFacets', this.id, this.host.profileElement);
|
|
471
538
|
const trimmedQuery = (_a = this.host.baseQuery) === null || _a === void 0 ? void 0 : _a.trim();
|
|
472
539
|
if (!this.canPerformSearch)
|
|
473
540
|
return;
|
|
541
|
+
console.log('will actually fetch facets');
|
|
474
542
|
const { facetFetchQueryKey } = this;
|
|
475
543
|
const sortParams = this.host.sortParam ? [this.host.sortParam] : [];
|
|
476
544
|
const params = {
|
|
@@ -491,8 +559,10 @@ export class CollectionBrowserDataSource {
|
|
|
491
559
|
// If so, we just want to discard this set of aggregations because they are
|
|
492
560
|
// likely no longer valid for the newer query.
|
|
493
561
|
const queryChangedSinceFetch = facetFetchQueryKey !== this.facetFetchQueryKey;
|
|
494
|
-
if (queryChangedSinceFetch)
|
|
562
|
+
if (queryChangedSinceFetch) {
|
|
563
|
+
console.log('facet query has changed since fetch, returning. new/old:', this.facetFetchQueryKey, facetFetchQueryKey);
|
|
495
564
|
return;
|
|
565
|
+
}
|
|
496
566
|
if (!success) {
|
|
497
567
|
const errorMsg = (_c = searchResponse === null || searchResponse === void 0 ? void 0 : searchResponse.error) === null || _c === void 0 ? void 0 : _c.message;
|
|
498
568
|
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;
|
|
@@ -500,6 +570,7 @@ export class CollectionBrowserDataSource {
|
|
|
500
570
|
// @ts-ignore: Property 'Sentry' does not exist on type 'Window & typeof globalThis'
|
|
501
571
|
(_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, 'Missing or malformed facet response from backend', 'error');
|
|
502
572
|
}
|
|
573
|
+
this.host.setFacetsLoading(false);
|
|
503
574
|
return;
|
|
504
575
|
}
|
|
505
576
|
const { aggregations, collectionTitles } = success.response;
|
|
@@ -533,7 +604,6 @@ export class CollectionBrowserDataSource {
|
|
|
533
604
|
*/
|
|
534
605
|
async fetchPage(pageNumber, numInitialPages = 1) {
|
|
535
606
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
536
|
-
console.log(`fetchPage(${pageNumber})`, this.canPerformSearch, this.hasPage(pageNumber), this.endOfDataReached, this.host.baseQuery, JSON.stringify(this.host.selectedFacets));
|
|
537
607
|
const trimmedQuery = (_a = this.host.baseQuery) === null || _a === void 0 ? void 0 : _a.trim();
|
|
538
608
|
if (!this.canPerformSearch)
|
|
539
609
|
return;
|
|
@@ -549,14 +619,14 @@ export class CollectionBrowserDataSource {
|
|
|
549
619
|
// if a fetch is already in progress for this query and page, don't fetch again
|
|
550
620
|
const { pageFetchQueryKey } = this;
|
|
551
621
|
const pageFetches = (_b = this.pageFetchesInProgress[pageFetchQueryKey]) !== null && _b !== void 0 ? _b : new Set();
|
|
552
|
-
if (pageFetches.has(pageNumber))
|
|
553
|
-
console.log(`Skipping fetch for page ${pageNumber} because one is already in progress`);
|
|
622
|
+
if (pageFetches.has(pageNumber))
|
|
554
623
|
return;
|
|
555
|
-
}
|
|
556
624
|
for (let i = 0; i < numPages; i += 1) {
|
|
557
625
|
pageFetches.add(pageNumber + i);
|
|
558
626
|
}
|
|
627
|
+
console.log(`fetchPage(${pageNumber})`, this.id, this.canPerformSearch, this.hasPage(pageNumber), this.endOfDataReached, this.host.baseQuery, JSON.stringify(this.host.selectedFacets), this.pageFetchQueryKey);
|
|
559
628
|
this.pageFetchesInProgress[pageFetchQueryKey] = pageFetches;
|
|
629
|
+
this.previousQueryKey = pageFetchQueryKey;
|
|
560
630
|
const sortParams = this.host.sortParam ? [this.host.sortParam] : [];
|
|
561
631
|
const params = {
|
|
562
632
|
...this.pageSpecifierParams,
|
|
@@ -602,6 +672,7 @@ export class CollectionBrowserDataSource {
|
|
|
602
672
|
this.host.emitEmptyResults();
|
|
603
673
|
}
|
|
604
674
|
if (this.host.withinCollection) {
|
|
675
|
+
console.log('host is within collection, setting collection info:', success.response.collectionExtraInfo);
|
|
605
676
|
this.collectionExtraInfo = success.response.collectionExtraInfo;
|
|
606
677
|
// For collections, we want the UI to respect the default sort option
|
|
607
678
|
// which can be specified in metadata, or otherwise assumed to be week:desc
|
|
@@ -611,10 +682,13 @@ export class CollectionBrowserDataSource {
|
|
|
611
682
|
}
|
|
612
683
|
}
|
|
613
684
|
else if (this.host.withinProfile) {
|
|
614
|
-
console.log('host is within profile, setting acct info:', success.response.accountExtraInfo);
|
|
685
|
+
console.log('host is within profile, setting acct info:', success.response.accountExtraInfo, success.response.pageElements);
|
|
615
686
|
this.accountExtraInfo = success.response.accountExtraInfo;
|
|
616
687
|
this.pageElements = success.response.pageElements;
|
|
617
688
|
}
|
|
689
|
+
else {
|
|
690
|
+
console.log('not within profile/collxn', this.host.withinCollection, this.host.withinProfile);
|
|
691
|
+
}
|
|
618
692
|
const { results, collectionTitles } = success.response;
|
|
619
693
|
if (results && results.length > 0) {
|
|
620
694
|
// Load any collection titles present on the response into the cache,
|
|
@@ -657,57 +731,9 @@ export class CollectionBrowserDataSource {
|
|
|
657
731
|
// const datasource = { ...this.dataSource };
|
|
658
732
|
const tiles = [];
|
|
659
733
|
results === null || results === void 0 ? void 0 : results.forEach(result => {
|
|
660
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13;
|
|
661
734
|
if (!result.identifier)
|
|
662
735
|
return;
|
|
663
|
-
|
|
664
|
-
let contentWarning = false;
|
|
665
|
-
// Check if item and item in "modifying" collection, setting above flags
|
|
666
|
-
if (((_a = result.collection) === null || _a === void 0 ? void 0 : _a.values.length) &&
|
|
667
|
-
((_b = result.mediatype) === null || _b === void 0 ? void 0 : _b.value) !== 'collection') {
|
|
668
|
-
for (const collection of (_d = (_c = result.collection) === null || _c === void 0 ? void 0 : _c.values) !== null && _d !== void 0 ? _d : []) {
|
|
669
|
-
if (collection === 'loggedin') {
|
|
670
|
-
loginRequired = true;
|
|
671
|
-
if (contentWarning)
|
|
672
|
-
break;
|
|
673
|
-
}
|
|
674
|
-
if (collection === 'no-preview') {
|
|
675
|
-
contentWarning = true;
|
|
676
|
-
if (loginRequired)
|
|
677
|
-
break;
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
tiles.push({
|
|
682
|
-
averageRating: (_e = result.avg_rating) === null || _e === void 0 ? void 0 : _e.value,
|
|
683
|
-
checked: false,
|
|
684
|
-
collections: (_g = (_f = result.collection) === null || _f === void 0 ? void 0 : _f.values) !== null && _g !== void 0 ? _g : [],
|
|
685
|
-
collectionFilesCount: (_j = (_h = result.collection_files_count) === null || _h === void 0 ? void 0 : _h.value) !== null && _j !== void 0 ? _j : 0,
|
|
686
|
-
collectionSize: (_l = (_k = result.collection_size) === null || _k === void 0 ? void 0 : _k.value) !== null && _l !== void 0 ? _l : 0,
|
|
687
|
-
commentCount: (_o = (_m = result.num_reviews) === null || _m === void 0 ? void 0 : _m.value) !== null && _o !== void 0 ? _o : 0,
|
|
688
|
-
creator: (_p = result.creator) === null || _p === void 0 ? void 0 : _p.value,
|
|
689
|
-
creators: (_r = (_q = result.creator) === null || _q === void 0 ? void 0 : _q.values) !== null && _r !== void 0 ? _r : [],
|
|
690
|
-
dateAdded: (_s = result.addeddate) === null || _s === void 0 ? void 0 : _s.value,
|
|
691
|
-
dateArchived: (_t = result.publicdate) === null || _t === void 0 ? void 0 : _t.value,
|
|
692
|
-
datePublished: (_u = result.date) === null || _u === void 0 ? void 0 : _u.value,
|
|
693
|
-
dateReviewed: (_v = result.reviewdate) === null || _v === void 0 ? void 0 : _v.value,
|
|
694
|
-
description: (_w = result.description) === null || _w === void 0 ? void 0 : _w.values.join('\n'),
|
|
695
|
-
favCount: (_y = (_x = result.num_favorites) === null || _x === void 0 ? void 0 : _x.value) !== null && _y !== void 0 ? _y : 0,
|
|
696
|
-
href: this.collapseRepeatedQuotes((_z = result.__href__) === null || _z === void 0 ? void 0 : _z.value),
|
|
697
|
-
identifier: result.identifier,
|
|
698
|
-
issue: (_0 = result.issue) === null || _0 === void 0 ? void 0 : _0.value,
|
|
699
|
-
itemCount: (_2 = (_1 = result.item_count) === null || _1 === void 0 ? void 0 : _1.value) !== null && _2 !== void 0 ? _2 : 0,
|
|
700
|
-
mediatype: this.getMediatype(result),
|
|
701
|
-
snippets: (_4 = (_3 = result.highlight) === null || _3 === void 0 ? void 0 : _3.values) !== null && _4 !== void 0 ? _4 : [],
|
|
702
|
-
source: (_5 = result.source) === null || _5 === void 0 ? void 0 : _5.value,
|
|
703
|
-
subjects: (_7 = (_6 = result.subject) === null || _6 === void 0 ? void 0 : _6.values) !== null && _7 !== void 0 ? _7 : [],
|
|
704
|
-
title: (_9 = (_8 = result.title) === null || _8 === void 0 ? void 0 : _8.value) !== null && _9 !== void 0 ? _9 : '',
|
|
705
|
-
volume: (_10 = result.volume) === null || _10 === void 0 ? void 0 : _10.value,
|
|
706
|
-
viewCount: (_12 = (_11 = result.downloads) === null || _11 === void 0 ? void 0 : _11.value) !== null && _12 !== void 0 ? _12 : 0,
|
|
707
|
-
weeklyViewCount: (_13 = result.week) === null || _13 === void 0 ? void 0 : _13.value,
|
|
708
|
-
loginRequired,
|
|
709
|
-
contentWarning,
|
|
710
|
-
});
|
|
736
|
+
tiles.push(new TileModel(result));
|
|
711
737
|
});
|
|
712
738
|
this.addPage(pageNumber, tiles);
|
|
713
739
|
const visiblePages = this.host.currentVisiblePageNumbers;
|
|
@@ -716,42 +742,6 @@ export class CollectionBrowserDataSource {
|
|
|
716
742
|
this.host.refreshVisibleResults();
|
|
717
743
|
}
|
|
718
744
|
}
|
|
719
|
-
/**
|
|
720
|
-
* Returns the mediatype string for the given search result, taking into account
|
|
721
|
-
* the special `favorited_search` hit type.
|
|
722
|
-
* @param result The search result to extract a mediatype from
|
|
723
|
-
*/
|
|
724
|
-
getMediatype(result) {
|
|
725
|
-
var _a, _b, _c;
|
|
726
|
-
/**
|
|
727
|
-
* hit_type == 'favorited_search' is basically a new hit_type
|
|
728
|
-
* - we are getting from PPS.
|
|
729
|
-
* - which gives response for fav- collection
|
|
730
|
-
* - having favorited items like account/collection/item etc..
|
|
731
|
-
* - as user can also favorite a search result (a search page)
|
|
732
|
-
* - so we need to have response (having fav- items and fav- search results)
|
|
733
|
-
*
|
|
734
|
-
* if backend hit_type == 'favorited_search'
|
|
735
|
-
* - let's assume a "search" as new mediatype
|
|
736
|
-
*/
|
|
737
|
-
if (((_a = result === null || result === void 0 ? void 0 : result.rawMetadata) === null || _a === void 0 ? void 0 : _a.hit_type) === 'favorited_search') {
|
|
738
|
-
return 'search';
|
|
739
|
-
}
|
|
740
|
-
return (_c = (_b = result.mediatype) === null || _b === void 0 ? void 0 : _b.value) !== null && _c !== void 0 ? _c : 'data';
|
|
741
|
-
}
|
|
742
|
-
/**
|
|
743
|
-
* Returns the input string, but removing one set of quotes from all instances of
|
|
744
|
-
* ""clauses wrapped in two sets of quotes"". This assumes the quotes are already
|
|
745
|
-
* URL-encoded.
|
|
746
|
-
*
|
|
747
|
-
* This should be a temporary measure to address the fact that the __href__ field
|
|
748
|
-
* sometimes acquires extra quotation marks during query rewriting. Once there is a
|
|
749
|
-
* full Lucene parser in place that handles quoted queries correctly, this can likely
|
|
750
|
-
* be removed.
|
|
751
|
-
*/
|
|
752
|
-
collapseRepeatedQuotes(str) {
|
|
753
|
-
return str === null || str === void 0 ? void 0 : str.replace(/%22%22(?!%22%22)(.+?)%22%22/g, '%22$1%22');
|
|
754
|
-
}
|
|
755
745
|
/**
|
|
756
746
|
* Fetches the aggregation buckets for the given prefix filter type.
|
|
757
747
|
*/
|