@internetarchive/collection-browser 1.14.17-alpha.4 → 1.14.17-alpha.41
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.d.ts +3 -2
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/src/collection-browser.d.ts +6 -13
- package/dist/src/collection-browser.js +56 -30
- package/dist/src/collection-browser.js.map +1 -1
- package/dist/src/data-source/collection-browser-data-source-interface.d.ts +194 -0
- package/dist/src/data-source/collection-browser-data-source-interface.js +2 -0
- package/dist/src/data-source/collection-browser-data-source-interface.js.map +1 -0
- package/dist/src/data-source/collection-browser-data-source.d.ts +62 -174
- package/dist/src/data-source/collection-browser-data-source.js +185 -64
- package/dist/src/data-source/collection-browser-data-source.js.map +1 -1
- package/dist/src/data-source/collection-browser-query-state.d.ts +42 -0
- package/dist/src/data-source/collection-browser-query-state.js +2 -0
- package/dist/src/data-source/collection-browser-query-state.js.map +1 -0
- package/dist/src/data-source/models.d.ts +1 -39
- package/dist/src/data-source/models.js.map +1 -1
- package/dist/src/models.d.ts +3 -2
- package/dist/src/models.js +24 -22
- 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.d.ts +3 -0
- package/dist/src/tiles/item-image.js +30 -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 +30 -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 +5 -1
- 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/test/collection-browser.test.js +2 -6
- package/dist/test/collection-browser.test.js.map +1 -1
- package/index.ts +3 -5
- package/package.json +2 -2
- package/src/collection-browser.ts +70 -49
- package/src/data-source/collection-browser-data-source-interface.ts +245 -0
- package/src/data-source/collection-browser-data-source.ts +237 -281
- package/src/data-source/collection-browser-query-state.ts +53 -0
- package/src/data-source/models.ts +0 -47
- package/src/models.ts +7 -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 +28 -0
- package/src/tiles/list/tile-list.ts +37 -1
- package/src/tiles/tile-dispatcher.ts +2 -1
- package/src/tiles/tile-display-value-provider.ts +19 -1
- package/test/collection-browser.test.ts +2 -8
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
CollectionExtraInfo,
|
|
3
|
+
PageElementName,
|
|
4
|
+
SearchServiceInterface,
|
|
5
|
+
SearchType,
|
|
6
|
+
SortDirection,
|
|
7
|
+
SortParam,
|
|
8
|
+
} from '@internetarchive/search-service';
|
|
9
|
+
import type { SelectedFacets, SortField } from '../models';
|
|
10
|
+
import type { CollectionBrowserDataSourceInterface } from './collection-browser-data-source-interface';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Properties of collection browser that affect the overall search query
|
|
14
|
+
*/
|
|
15
|
+
export interface CollectionBrowserQueryState {
|
|
16
|
+
baseQuery?: string;
|
|
17
|
+
withinCollection?: string;
|
|
18
|
+
withinProfile?: string;
|
|
19
|
+
profileElement?: PageElementName;
|
|
20
|
+
searchType: SearchType;
|
|
21
|
+
selectedFacets?: SelectedFacets;
|
|
22
|
+
minSelectedDate?: string;
|
|
23
|
+
maxSelectedDate?: string;
|
|
24
|
+
selectedTitleFilter: string | null;
|
|
25
|
+
selectedCreatorFilter: string | null;
|
|
26
|
+
selectedSort?: SortField;
|
|
27
|
+
sortDirection: SortDirection | null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Interface representing search-related state and operations required by the
|
|
32
|
+
* data source on its host component.
|
|
33
|
+
*/
|
|
34
|
+
export interface CollectionBrowserSearchInterface
|
|
35
|
+
extends CollectionBrowserQueryState {
|
|
36
|
+
searchService?: SearchServiceInterface;
|
|
37
|
+
readonly sortParam: SortParam | null;
|
|
38
|
+
readonly suppressFacets?: boolean;
|
|
39
|
+
readonly initialPageNumber: number;
|
|
40
|
+
readonly currentVisiblePageNumbers: number[];
|
|
41
|
+
readonly clearResultsOnEmptyQuery?: boolean;
|
|
42
|
+
readonly dataSource?: CollectionBrowserDataSourceInterface;
|
|
43
|
+
|
|
44
|
+
getSessionId(): Promise<string>;
|
|
45
|
+
setSearchResultsLoading(loading: boolean): void;
|
|
46
|
+
setFacetsLoading(loading: boolean): void;
|
|
47
|
+
setTotalResultCount(count: number): void;
|
|
48
|
+
setTileCount(count: number): void;
|
|
49
|
+
applyDefaultCollectionSort(collectionInfo?: CollectionExtraInfo): void;
|
|
50
|
+
emitEmptyResults(): void;
|
|
51
|
+
emitQueryStateChanged(): void;
|
|
52
|
+
refreshVisibleResults(): void;
|
|
53
|
+
}
|
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
CollectionExtraInfo,
|
|
3
2
|
PageElementName,
|
|
4
3
|
PageType,
|
|
5
|
-
SearchServiceInterface,
|
|
6
|
-
SearchType,
|
|
7
|
-
SortDirection,
|
|
8
|
-
SortParam,
|
|
9
4
|
} from '@internetarchive/search-service';
|
|
10
|
-
import type { SelectedFacets, SortField } from '../models';
|
|
11
5
|
|
|
12
6
|
/**
|
|
13
7
|
* A Map from collection identifiers to their corresponding collection titles.
|
|
@@ -33,44 +27,3 @@ export type PageSpecifierParams = {
|
|
|
33
27
|
*/
|
|
34
28
|
pageElements?: PageElementName[];
|
|
35
29
|
};
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Properties of collection browser that affect the overall search query
|
|
39
|
-
*/
|
|
40
|
-
export interface CollectionBrowserQueryState {
|
|
41
|
-
baseQuery?: string;
|
|
42
|
-
withinCollection?: string;
|
|
43
|
-
withinProfile?: string;
|
|
44
|
-
profileElement?: PageElementName;
|
|
45
|
-
searchType: SearchType;
|
|
46
|
-
selectedFacets?: SelectedFacets;
|
|
47
|
-
minSelectedDate?: string;
|
|
48
|
-
maxSelectedDate?: string;
|
|
49
|
-
selectedTitleFilter: string | null;
|
|
50
|
-
selectedCreatorFilter: string | null;
|
|
51
|
-
selectedSort?: SortField;
|
|
52
|
-
sortDirection: SortDirection | null;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Interface representing search-related state and operations required by the
|
|
57
|
-
* data source on its host component.
|
|
58
|
-
*/
|
|
59
|
-
export interface CollectionBrowserSearchInterface
|
|
60
|
-
extends CollectionBrowserQueryState {
|
|
61
|
-
searchService?: SearchServiceInterface;
|
|
62
|
-
queryErrorMessage?: string;
|
|
63
|
-
readonly sortParam: SortParam | null;
|
|
64
|
-
readonly suppressFacets?: boolean;
|
|
65
|
-
readonly initialPageNumber: number;
|
|
66
|
-
readonly currentVisiblePageNumbers: number[];
|
|
67
|
-
|
|
68
|
-
getSessionId(): Promise<string>;
|
|
69
|
-
setSearchResultsLoading(loading: boolean): void;
|
|
70
|
-
setFacetsLoading(loading: boolean): void;
|
|
71
|
-
setTotalResultCount(count: number): void;
|
|
72
|
-
setTileCount(count: number): void;
|
|
73
|
-
applyDefaultCollectionSort(collectionInfo?: CollectionExtraInfo): void;
|
|
74
|
-
emitEmptyResults(): void;
|
|
75
|
-
refreshVisibleResults(): void;
|
|
76
|
-
}
|
package/src/models.ts
CHANGED
|
@@ -21,6 +21,8 @@ interface TileFlags {
|
|
|
21
21
|
export class TileModel {
|
|
22
22
|
averageRating?: number;
|
|
23
23
|
|
|
24
|
+
captureDates?: Date[]; // List of capture dates for a URL, used on profile Web Archives tiles
|
|
25
|
+
|
|
24
26
|
checked: boolean; // Whether this tile is currently checked for item management functions
|
|
25
27
|
|
|
26
28
|
collectionIdentifier?: string;
|
|
@@ -71,7 +73,7 @@ export class TileModel {
|
|
|
71
73
|
|
|
72
74
|
title: string;
|
|
73
75
|
|
|
74
|
-
viewCount
|
|
76
|
+
viewCount?: number;
|
|
75
77
|
|
|
76
78
|
volume?: string;
|
|
77
79
|
|
|
@@ -85,6 +87,7 @@ export class TileModel {
|
|
|
85
87
|
const flags = this.getFlags(result);
|
|
86
88
|
|
|
87
89
|
this.averageRating = result.avg_rating?.value;
|
|
90
|
+
this.captureDates = result.capture_dates?.values;
|
|
88
91
|
this.checked = false;
|
|
89
92
|
this.collections = result.collection?.values ?? [];
|
|
90
93
|
this.collectionFilesCount = result.collection_files_count?.value ?? 0;
|
|
@@ -108,18 +111,19 @@ export class TileModel {
|
|
|
108
111
|
this.subjects = result.subject?.values ?? [];
|
|
109
112
|
this.title = result.title?.value ?? '';
|
|
110
113
|
this.volume = result.volume?.value;
|
|
111
|
-
this.viewCount = result.downloads?.value
|
|
114
|
+
this.viewCount = result.downloads?.value;
|
|
112
115
|
this.weeklyViewCount = result.week?.value;
|
|
113
116
|
this.loginRequired = flags.loginRequired;
|
|
114
117
|
this.contentWarning = flags.contentWarning;
|
|
115
118
|
}
|
|
116
119
|
|
|
117
120
|
/**
|
|
118
|
-
*
|
|
121
|
+
* Copies the contents of this TileModel onto a new instance
|
|
119
122
|
*/
|
|
120
123
|
clone(): TileModel {
|
|
121
124
|
const cloned = new TileModel({});
|
|
122
125
|
cloned.averageRating = this.averageRating;
|
|
126
|
+
cloned.captureDates = this.captureDates;
|
|
123
127
|
cloned.checked = this.checked;
|
|
124
128
|
cloned.collections = this.collections;
|
|
125
129
|
cloned.collectionFilesCount = this.collectionFilesCount;
|
|
@@ -1116,6 +1116,7 @@ export class SortFilterBar
|
|
|
1116
1116
|
height: 100%;
|
|
1117
1117
|
padding-left: 5px;
|
|
1118
1118
|
font-size: 1.4rem;
|
|
1119
|
+
font-family: var(--ia-theme-base-font-family);
|
|
1119
1120
|
line-height: 2;
|
|
1120
1121
|
color: var(--ia-theme-primary-text-color, #2c2c2c);
|
|
1121
1122
|
white-space: nowrap;
|
|
@@ -4,6 +4,7 @@ import { customElement, property } from 'lit/decorators.js';
|
|
|
4
4
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
5
5
|
import { msg } from '@lit/localize';
|
|
6
6
|
|
|
7
|
+
import { map } from 'lit/directives/map.js';
|
|
7
8
|
import { DateFormat, formatDate } from '../../utils/format-date';
|
|
8
9
|
import { isFirstMillisecondOfUTCYear } from '../../utils/local-date-from-utc';
|
|
9
10
|
import { BaseTileComponent } from '../base-tile-component';
|
|
@@ -57,7 +58,7 @@ export class ItemTile extends BaseTileComponent {
|
|
|
57
58
|
${this.isSortedByDate
|
|
58
59
|
? this.sortedDateInfoTemplate
|
|
59
60
|
: this.creatorTemplate}
|
|
60
|
-
${this.textSnippetsTemplate}
|
|
61
|
+
${this.webArchivesCaptureDatesTemplate} ${this.textSnippetsTemplate}
|
|
61
62
|
</div>
|
|
62
63
|
|
|
63
64
|
<tile-stats
|
|
@@ -172,6 +173,26 @@ export class ItemTile extends BaseTileComponent {
|
|
|
172
173
|
`;
|
|
173
174
|
}
|
|
174
175
|
|
|
176
|
+
private get webArchivesCaptureDatesTemplate():
|
|
177
|
+
| TemplateResult
|
|
178
|
+
| typeof nothing {
|
|
179
|
+
if (!this.model?.captureDates || !this.model?.title) return nothing;
|
|
180
|
+
|
|
181
|
+
return html`
|
|
182
|
+
<ul class="capture-dates">
|
|
183
|
+
${map(
|
|
184
|
+
this.model.captureDates,
|
|
185
|
+
date => html`<li>
|
|
186
|
+
${this.displayValueProvider.webArchivesCaptureLink(
|
|
187
|
+
this.model!.title,
|
|
188
|
+
date
|
|
189
|
+
)}
|
|
190
|
+
</li>`
|
|
191
|
+
)}
|
|
192
|
+
</ul>
|
|
193
|
+
`;
|
|
194
|
+
}
|
|
195
|
+
|
|
175
196
|
private get isSortedByDate(): boolean {
|
|
176
197
|
return ['date', 'reviewdate', 'addeddate', 'publicdate'].includes(
|
|
177
198
|
this.sortParam?.field as string
|
|
@@ -200,10 +221,24 @@ export class ItemTile extends BaseTileComponent {
|
|
|
200
221
|
return [
|
|
201
222
|
baseTileStyles,
|
|
202
223
|
css`
|
|
224
|
+
a:link {
|
|
225
|
+
text-decoration: none;
|
|
226
|
+
color: var(--ia-theme-link-color, #4b64ff);
|
|
227
|
+
}
|
|
228
|
+
a:hover {
|
|
229
|
+
text-decoration: underline;
|
|
230
|
+
}
|
|
231
|
+
|
|
203
232
|
.container {
|
|
204
233
|
border: 1px solid ${tileBorderColor};
|
|
205
234
|
}
|
|
206
235
|
|
|
236
|
+
.capture-dates {
|
|
237
|
+
margin: 0;
|
|
238
|
+
padding: 0 5px;
|
|
239
|
+
list-style-type: none;
|
|
240
|
+
}
|
|
241
|
+
|
|
207
242
|
text-snippet-block {
|
|
208
243
|
--containerLeftMargin: 5px;
|
|
209
244
|
--containerTopMargin: 5px;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { css, CSSResultGroup, html, LitElement } from 'lit';
|
|
2
2
|
import { customElement, property } from 'lit/decorators.js';
|
|
3
3
|
|
|
4
|
+
import { msg } from '@lit/localize';
|
|
4
5
|
import { favoriteFilledIcon } from '../../assets/img/icons/favorite-filled';
|
|
5
6
|
import { reviewsIcon } from '../../assets/img/icons/reviews';
|
|
6
7
|
import { uploadIcon } from '../../assets/img/icons/upload';
|
|
@@ -33,8 +34,8 @@ export class TileStats extends LitElement {
|
|
|
33
34
|
|
|
34
35
|
const uploadsOrViewsTitle =
|
|
35
36
|
this.mediatype === 'account'
|
|
36
|
-
? `${this.itemCount} uploads`
|
|
37
|
-
: `${this.viewCount} ${this.viewLabel ?? 'all-time views'}`;
|
|
37
|
+
? `${this.itemCount ?? 0} uploads`
|
|
38
|
+
: `${this.viewCount ?? 0} ${this.viewLabel ?? 'all-time views'}`;
|
|
38
39
|
|
|
39
40
|
return html`
|
|
40
41
|
<div class="item-stats">
|
|
@@ -43,17 +44,21 @@ export class TileStats extends LitElement {
|
|
|
43
44
|
</p>
|
|
44
45
|
<ul id="stats-row">
|
|
45
46
|
<li class="col">
|
|
46
|
-
<p class="sr-only"
|
|
47
|
+
<p class="sr-only">${msg('Mediatype:')}</p>
|
|
47
48
|
<mediatype-icon .mediatype=${this.mediatype}></mediatype-icon>
|
|
48
49
|
</li>
|
|
49
50
|
<li class="col" title="${uploadsOrViewsTitle}">
|
|
50
51
|
${this.mediatype === 'account' ? uploadIcon : viewsIcon}
|
|
51
52
|
<p class="status-text">
|
|
52
53
|
<span class="sr-only">
|
|
53
|
-
${this.mediatype === 'account'
|
|
54
|
+
${this.mediatype === 'account'
|
|
55
|
+
? msg('Uploads:')
|
|
56
|
+
: msg('Views:')}
|
|
54
57
|
</span>
|
|
55
58
|
${formatCount(
|
|
56
|
-
this.mediatype === 'account'
|
|
59
|
+
this.mediatype === 'account'
|
|
60
|
+
? this.itemCount ?? 0
|
|
61
|
+
: this.viewCount ?? 0,
|
|
57
62
|
'short',
|
|
58
63
|
'short'
|
|
59
64
|
)}
|
|
@@ -62,14 +67,14 @@ export class TileStats extends LitElement {
|
|
|
62
67
|
<li class="col" title="${formattedFavCount} favorites">
|
|
63
68
|
${favoriteFilledIcon}
|
|
64
69
|
<p class="status-text">
|
|
65
|
-
<span class="sr-only"
|
|
70
|
+
<span class="sr-only">${msg('Favorites:')}</span>
|
|
66
71
|
${formattedFavCount}
|
|
67
72
|
</p>
|
|
68
73
|
</li>
|
|
69
74
|
<li class="col reviews" title="${formattedReviewCount} reviews">
|
|
70
75
|
${reviewsIcon}
|
|
71
76
|
<p class="status-text">
|
|
72
|
-
<span class="sr-only"
|
|
77
|
+
<span class="sr-only">${msg('Reviews:')}</span>
|
|
73
78
|
${formattedReviewCount}
|
|
74
79
|
</p>
|
|
75
80
|
</li>
|
package/src/tiles/item-image.ts
CHANGED
|
@@ -24,6 +24,8 @@ export class ItemImage extends LitElement {
|
|
|
24
24
|
|
|
25
25
|
@state() private isWaveform = false;
|
|
26
26
|
|
|
27
|
+
@state() private isNotFound = false;
|
|
28
|
+
|
|
27
29
|
@query('img') private baseImage!: HTMLImageElement;
|
|
28
30
|
|
|
29
31
|
render() {
|
|
@@ -43,6 +45,7 @@ export class ItemImage extends LitElement {
|
|
|
43
45
|
src="${this.imageSrc}"
|
|
44
46
|
alt=""
|
|
45
47
|
@load=${this.onLoad}
|
|
48
|
+
@error=${this.onError}
|
|
46
49
|
/>
|
|
47
50
|
`;
|
|
48
51
|
}
|
|
@@ -51,12 +54,33 @@ export class ItemImage extends LitElement {
|
|
|
51
54
|
* Helpers
|
|
52
55
|
*/
|
|
53
56
|
private get imageSrc() {
|
|
57
|
+
if (this.isNotFound) return this.notFoundSrc;
|
|
58
|
+
|
|
59
|
+
// Use the correct image for web capture tiles, if possible
|
|
60
|
+
if (this.model?.captureDates && this.model.identifier) {
|
|
61
|
+
try {
|
|
62
|
+
const url = new URL(this.model.identifier);
|
|
63
|
+
const domain = encodeURIComponent(url.hostname);
|
|
64
|
+
return this.baseImageUrl
|
|
65
|
+
? `https://web.archive.org/thumb/${domain}?generate=1`
|
|
66
|
+
: nothing;
|
|
67
|
+
} catch (err) {
|
|
68
|
+
return `${this.baseImageUrl}/images/notfound.png`;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
54
72
|
// Don't try to load invalid image URLs
|
|
55
73
|
return this.baseImageUrl && this.model?.identifier
|
|
56
74
|
? `${this.baseImageUrl}/services/img/${this.model.identifier}`
|
|
57
75
|
: nothing;
|
|
58
76
|
}
|
|
59
77
|
|
|
78
|
+
private get notFoundSrc() {
|
|
79
|
+
return this.baseImageUrl
|
|
80
|
+
? `${this.baseImageUrl}/images/notfound.png`
|
|
81
|
+
: nothing;
|
|
82
|
+
}
|
|
83
|
+
|
|
60
84
|
private get hashBasedGradient() {
|
|
61
85
|
if (!this.model?.identifier) {
|
|
62
86
|
return 'waveform-grad0';
|
|
@@ -120,6 +144,10 @@ export class ItemImage extends LitElement {
|
|
|
120
144
|
}
|
|
121
145
|
}
|
|
122
146
|
|
|
147
|
+
private onError() {
|
|
148
|
+
this.isNotFound = true;
|
|
149
|
+
}
|
|
150
|
+
|
|
123
151
|
/**
|
|
124
152
|
* CSS
|
|
125
153
|
*/
|
|
@@ -107,6 +107,7 @@ export class TileList extends BaseTileComponent {
|
|
|
107
107
|
${this.itemLineTemplate} ${this.creatorTemplate}
|
|
108
108
|
<div id="dates-line">
|
|
109
109
|
${this.datePublishedTemplate} ${this.dateSortByTemplate}
|
|
110
|
+
${this.webArchivesCaptureDatesTemplate}
|
|
110
111
|
</div>
|
|
111
112
|
<div id="views-line">
|
|
112
113
|
${this.viewsTemplate} ${this.ratingTemplate} ${this.reviewsTemplate}
|
|
@@ -238,6 +239,7 @@ export class TileList extends BaseTileComponent {
|
|
|
238
239
|
this.sortParam?.field === 'week'
|
|
239
240
|
? this.model?.weeklyViewCount // weekly views
|
|
240
241
|
: this.model?.viewCount; // all-time views
|
|
242
|
+
if (viewCount == null) return nothing;
|
|
241
243
|
|
|
242
244
|
// when its a search-tile, we don't have any stats to show
|
|
243
245
|
if (this.model?.mediatype === 'search') {
|
|
@@ -245,7 +247,7 @@ export class TileList extends BaseTileComponent {
|
|
|
245
247
|
}
|
|
246
248
|
|
|
247
249
|
return this.metadataTemplate(
|
|
248
|
-
`${formatCount(viewCount
|
|
250
|
+
`${formatCount(viewCount, this.formatSize)}`,
|
|
249
251
|
msg('Views')
|
|
250
252
|
);
|
|
251
253
|
}
|
|
@@ -309,6 +311,26 @@ export class TileList extends BaseTileComponent {
|
|
|
309
311
|
return !!this.model?.snippets?.length;
|
|
310
312
|
}
|
|
311
313
|
|
|
314
|
+
private get webArchivesCaptureDatesTemplate():
|
|
315
|
+
| TemplateResult
|
|
316
|
+
| typeof nothing {
|
|
317
|
+
if (!this.model?.captureDates || !this.model?.title) return nothing;
|
|
318
|
+
|
|
319
|
+
return html`
|
|
320
|
+
<ul class="capture-dates">
|
|
321
|
+
${map(
|
|
322
|
+
this.model.captureDates,
|
|
323
|
+
date => html`<li>
|
|
324
|
+
${this.displayValueProvider.webArchivesCaptureLink(
|
|
325
|
+
this.model!.title,
|
|
326
|
+
date
|
|
327
|
+
)}
|
|
328
|
+
</li>`
|
|
329
|
+
)}
|
|
330
|
+
</ul>
|
|
331
|
+
`;
|
|
332
|
+
}
|
|
333
|
+
|
|
312
334
|
// Utility functions
|
|
313
335
|
// eslint-disable-next-line default-param-last
|
|
314
336
|
private metadataTemplate(text: any, label = '', id?: string) {
|
|
@@ -624,6 +646,20 @@ export class TileList extends BaseTileComponent {
|
|
|
624
646
|
#views-line {
|
|
625
647
|
flex-wrap: wrap;
|
|
626
648
|
}
|
|
649
|
+
|
|
650
|
+
.capture-dates {
|
|
651
|
+
margin: 0;
|
|
652
|
+
padding: 0;
|
|
653
|
+
list-style-type: none;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
.capture-dates a:link {
|
|
657
|
+
text-decoration: none;
|
|
658
|
+
color: var(--ia-theme-link-color, #4b64ff);
|
|
659
|
+
}
|
|
660
|
+
.capture-dates a:hover {
|
|
661
|
+
text-decoration: underline;
|
|
662
|
+
}
|
|
627
663
|
`;
|
|
628
664
|
}
|
|
629
665
|
}
|
|
@@ -184,7 +184,8 @@ export class TileDispatcher
|
|
|
184
184
|
this.enableHoverPane &&
|
|
185
185
|
!!this.tileDisplayMode &&
|
|
186
186
|
TileDispatcher.HOVER_PANE_DISPLAY_MODES[this.tileDisplayMode] &&
|
|
187
|
-
this.model?.mediatype !== 'search' // don't show hover panes on search tiles
|
|
187
|
+
this.model?.mediatype !== 'search' && // don't show hover panes on search tiles
|
|
188
|
+
!this.model?.captureDates // don't show hover panes on web archive tiles
|
|
188
189
|
);
|
|
189
190
|
}
|
|
190
191
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { nothing } from 'lit';
|
|
1
|
+
import { TemplateResult, html, nothing } from 'lit';
|
|
2
2
|
import { msg, str } from '@lit/localize';
|
|
3
3
|
import type { SortParam } from '@internetarchive/search-service';
|
|
4
4
|
import type { TileModel } from '../models';
|
|
5
|
+
import { formatDate } from '../utils/format-date';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* A class encapsulating shared logic for converting model values into display values
|
|
@@ -103,4 +104,21 @@ export class TileDisplayValueProvider {
|
|
|
103
104
|
const basePath = isCollection ? this.collectionPagePath : '/details/';
|
|
104
105
|
return `${this.baseNavigationUrl}${basePath}${identifier}`;
|
|
105
106
|
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Produces a template for a link to a single web capture of the given URL and date
|
|
110
|
+
*/
|
|
111
|
+
webArchivesCaptureLink(url: string, date: Date): TemplateResult {
|
|
112
|
+
// Convert the date into the format used to identify wayback captures (e.g., '20150102124550')
|
|
113
|
+
const captureDateStr = date
|
|
114
|
+
.toISOString()
|
|
115
|
+
.replace(/[TZ:-]/g, '')
|
|
116
|
+
.replace(/\..*/, '');
|
|
117
|
+
const captureHref = `https://web.archive.org/web/${captureDateStr}/${encodeURIComponent(
|
|
118
|
+
url
|
|
119
|
+
)}`;
|
|
120
|
+
const captureText = formatDate(date, 'long');
|
|
121
|
+
|
|
122
|
+
return html` <a href=${captureHref}> ${captureText} </a> `;
|
|
123
|
+
}
|
|
106
124
|
}
|
|
@@ -917,7 +917,7 @@ describe('Collection Browser', () => {
|
|
|
917
917
|
el.sortDirection = 'asc';
|
|
918
918
|
el.selectedCreatorFilter = 'X';
|
|
919
919
|
await el.updateComplete;
|
|
920
|
-
await
|
|
920
|
+
await nextTick();
|
|
921
921
|
|
|
922
922
|
expect(searchService.searchParams?.query).to.equal('first-creator');
|
|
923
923
|
expect(searchService.searchParams?.filters?.firstCreator?.X).to.equal(
|
|
@@ -926,7 +926,7 @@ describe('Collection Browser', () => {
|
|
|
926
926
|
|
|
927
927
|
el.baseQuery = 'collection:foo';
|
|
928
928
|
await el.updateComplete;
|
|
929
|
-
await
|
|
929
|
+
await nextTick();
|
|
930
930
|
|
|
931
931
|
expect(searchService.searchParams?.query).to.equal('collection:foo');
|
|
932
932
|
expect(searchService.searchParams?.filters?.firstCreator).not.to.exist;
|
|
@@ -1446,9 +1446,6 @@ describe('Collection Browser', () => {
|
|
|
1446
1446
|
</collection-browser>`
|
|
1447
1447
|
);
|
|
1448
1448
|
|
|
1449
|
-
await el.initialSearchComplete;
|
|
1450
|
-
await el.updateComplete;
|
|
1451
|
-
|
|
1452
1449
|
el.baseQuery = 'bar';
|
|
1453
1450
|
await el.updateComplete;
|
|
1454
1451
|
|
|
@@ -1484,9 +1481,6 @@ describe('Collection Browser', () => {
|
|
|
1484
1481
|
</collection-browser>`
|
|
1485
1482
|
);
|
|
1486
1483
|
|
|
1487
|
-
await el.initialSearchComplete;
|
|
1488
|
-
await el.updateComplete;
|
|
1489
|
-
|
|
1490
1484
|
el.withinCollection = 'bar';
|
|
1491
1485
|
await el.updateComplete;
|
|
1492
1486
|
|