Skip to content

Commit f89b613

Browse files
authored
WEBDEV-7479 Tile updates for TV collections/clips (#447)
* Add quote icon asset * Refactor tile-stats component for readability & add clips stat * Set tv clips props from item-tile * Better naming/formatting * Improve docs/formatting * Handle TV collections appropriately * Wrap title in msg * Upgrade off alpha search-service * Break search condition down into more intermediate vars * Fix capitalization to match existing tests * Further capitalization fix * Update test search type * Reverse capitalization changes, update tests * Add missing unit tests
1 parent 135e30b commit f89b613

17 files changed

+1194
-850
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
"@internetarchive/iaux-item-metadata": "^1.0.4",
3333
"@internetarchive/infinite-scroller": "^1.0.1",
3434
"@internetarchive/modal-manager": "^2.0.1",
35-
"@internetarchive/search-service": "^2.1.0",
35+
"@internetarchive/search-service": "^2.2.0",
3636
"@internetarchive/shared-resize-observer": "^0.2.0",
3737
"@lit/localize": "^0.12.2",
3838
"dompurify": "^3.2.4",

src/assets/img/icons/quote.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { svg } from 'lit';
2+
3+
export const quoteIcon = svg`
4+
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
5+
<path d="m45.3394669 100.000002h7.4385828c6.4511217-.3595144 12.58904-1.9152224 18.4137548-4.6671261s10.8424956-6.3426695 15.0533425-10.7722976c4.2108468-4.429628 7.556034-9.6360206 10.0355616-15.6191778s3.7192914-12.2669975 3.7192914-18.8515208c0-9.0967521-2.2250498-17.4897316-6.6751493-25.1789383-4.4500995-7.6892068-10.5140669-13.7638762-18.1919023-18.22400833-7.6778355-4.46013212-16.0560287-6.68910874-25.1345797-6.68693148-6.8100007 0-13.2915728 1.31603472-19.4447163 3.94810096-6.1531434 2.63206624-11.4699901 6.17816545-15.9505399 10.63829755-4.4805499 4.4601321-8.03453942 9.7863622-10.66196865 15.9786902s-3.94114385 12.7005912-3.94114385 19.5247894c0 12.9271929 4.36092352 24.1624988 13.0827705 33.7059178 8.7218471 9.543419 19.4751667 14.9448198 32.2599589 16.2042045zm-28.136113-51.5246596c2.2707252-7.480036 5.6159125-13.1058597 10.0355616-16.8774711 4.2412972-3.9502783 8.9610997-5.4166529 14.1594076-4.399124.2979783.1786667.1783519.507675-.358879.9870248-.537231.4793498-1.433341 1.2572039-2.6883299 2.3335621-1.254989 1.0763582-2.3000881 2.1538058-3.1352974 3.2323429-1.074462 1.4358706-1.7911325 2.7976598-2.1500114 4.0853677-.358879 1.2877079-.448055 2.214814-.267528 2.7813184.180527.5665043.180527 1.1798542 0 1.8400496 3.1059345-.1786668 5.8236273.5545206 8.1530782 2.199562s3.9726817 3.7095139 4.9296923 6.1934174c.9570107 2.4839036 1.210401 5.2063926.760171 8.1674672-.45023 2.9610745-1.6595435 5.6094822-3.6279404 7.9452231-3.3451872 3.6495952-7.5712592 5.2205552-12.678216 4.7128802s-8.9154242-2.6767329-11.4254021-6.5071737c-1.5529673-2.1548953-2.4490773-4.8479697-2.6883299-8.0792232-.2392527-3.2312535.089176-6.1040841.9852859-8.6184917zm34.7655868 0c2.2098245-7.3013692 5.5854621-12.9271929 10.1269126-16.8774711 4.1825715-3.9502783 8.8719237-5.4166529 14.0680565-4.399124.358879.1786667.2838407.507675-.225115.9870248-.5089556.4793498-1.3898404 1.2572039-2.6426544 2.3335621-1.2528139 1.0763582-2.3283634 2.1538058-3.2266484 3.2323429-1.0744619 1.4358706-1.7911324 2.7976598-2.1500114 4.0853677s-.4632801 2.214814-.3132035 2.7813184c.1500767.5665043.1348515 1.1798542-.0456755 1.8400496 3.1059346-.1786668 5.8236273.5545206 8.1530782 2.199562s3.9726817 3.7095139 4.9296924 6.1934174c.9570106 2.4839036 1.2256261 5.2063926.8058464 8.1674672-.4197796 2.9610745-1.6443183 5.6094822-3.6736158 7.9452231-3.3451873 3.6495952-7.5712593 5.2205552-12.6782161 4.7128802s-8.9154242-2.6767329-11.4254021-6.5071737c-1.4942416-2.1548953-2.3609888-4.8479697-2.6002414-8.0792232-.2392527-3.2312535.0598131-6.1040841.8971975-8.6184917z"/>
6+
</svg>
7+
`;

src/collection-browser.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import {
4848
RestorationStateHandlerInterface,
4949
RestorationStateHandler,
5050
RestorationState,
51+
RestorationStatePersistOptions,
5152
} from './restoration-state-handler';
5253
import { CollectionBrowserDataSource } from './data-source/collection-browser-data-source';
5354
import type {
@@ -95,7 +96,7 @@ export class CollectionBrowser
9596
/**
9697
* Which backend should be targeted by searches (e.g., metadata or FTS)
9798
*/
98-
@property({ type: Number }) searchType: SearchType = SearchType.METADATA;
99+
@property({ type: Number }) searchType: SearchType = SearchType.DEFAULT;
99100

100101
/**
101102
* The identifier of the collection that searches should be performed within
@@ -238,6 +239,11 @@ export class CollectionBrowser
238239

239240
@property({ type: Object }) recaptchaManager?: RecaptchaManagerInterface;
240241

242+
/**
243+
* Whether we are representing a TV collection, needing slightly different tile handling.
244+
*/
245+
@property({ type: Boolean }) isTVCollection = false;
246+
241247
/**
242248
* If item management UI active
243249
*/
@@ -1892,10 +1898,11 @@ export class CollectionBrowser
18921898
selectedTitleFilter: this.selectedTitleFilter ?? undefined,
18931899
selectedCreatorFilter: this.selectedCreatorFilter ?? undefined,
18941900
};
1895-
this.restorationStateHandler.persistState(
1896-
restorationState,
1897-
this.dataSourceInstallInProgress,
1898-
);
1901+
const persistOptions: RestorationStatePersistOptions = {
1902+
forceReplace: this.dataSourceInstallInProgress,
1903+
persistMetadataSearchType: this.isTVCollection,
1904+
};
1905+
this.restorationStateHandler.persistState(restorationState, persistOptions);
18991906
}
19001907

19011908
/**
@@ -2113,6 +2120,7 @@ export class CollectionBrowser
21132120
.mobileBreakpoint=${this.mobileBreakpoint}
21142121
.loggedIn=${this.loggedIn}
21152122
.isManageView=${this.isManageView}
2123+
?showTvClips=${this.isTVCollection}
21162124
?enableHoverPane=${true}
21172125
@resultSelected=${(e: CustomEvent) => this.resultSelected(e)}
21182126
>

src/data-source/collection-browser-data-source.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -586,14 +586,23 @@ export class CollectionBrowserDataSource
586586
const isCollectionSearch = !!this.host.withinCollection;
587587
const isProfileSearch = !!this.host.withinProfile;
588588
const hasProfileElement = !!this.host.profileElement;
589+
const isDefaultedSearch = this.host.searchType === SearchType.DEFAULT;
589590
const isMetadataSearch = this.host.searchType === SearchType.METADATA;
591+
const isTvSearch = this.host.searchType === SearchType.TV;
592+
593+
// Metadata/tv searches within a collection are allowed to have no query.
594+
const isValidForCollectionSearch =
595+
isDefaultedSearch || isMetadataSearch || isTvSearch;
596+
597+
// Searches within a profile page may also be performed without a query, provided the profile element is set.
598+
const isValidForProfileSearch =
599+
hasProfileElement && (isDefaultedSearch || isMetadataSearch);
590600

591-
// Metadata searches within a collection/profile are allowed to have no query.
592601
// Otherwise, a non-empty query must be set.
593602
return (
594603
hasNonEmptyQuery ||
595-
(isCollectionSearch && isMetadataSearch) ||
596-
(isProfileSearch && hasProfileElement && isMetadataSearch)
604+
(isCollectionSearch && isValidForCollectionSearch) ||
605+
(isProfileSearch && isValidForProfileSearch)
597606
);
598607
}
599608

@@ -1132,6 +1141,14 @@ export class CollectionBrowserDataSource
11321141
this.parentCollections = [].concat(
11331142
this.collectionExtraInfo.public_metadata?.collection ?? [],
11341143
);
1144+
1145+
// Update the TV collection status now that we know the parent collections
1146+
this.host.isTVCollection =
1147+
this.host.withinCollection?.startsWith('TV-') ||
1148+
this.host.withinCollection === 'tvnews' ||
1149+
this.host.withinCollection === 'tvarchive' ||
1150+
this.parentCollections.includes('tvnews') ||
1151+
this.parentCollections.includes('tvarchive');
11351152
}
11361153
} else if (withinProfile) {
11371154
this.accountExtraInfo = success.response.accountExtraInfo;

src/data-source/collection-browser-query-state.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export interface CollectionBrowserQueryState {
3434
export interface CollectionBrowserSearchInterface
3535
extends CollectionBrowserQueryState {
3636
searchService?: SearchServiceInterface;
37+
isTVCollection: boolean;
3738
readonly sortParam: SortParam | null;
3839
readonly defaultSortField: SortField | null;
3940
readonly facetLoadStrategy: FacetLoadStrategy;

src/models.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,12 @@ export class TileModel {
9494

9595
subjects: string[];
9696

97+
thumbnailUrl?: string;
98+
9799
title: string;
98100

101+
tvClipCount?: number;
102+
99103
viewCount?: number;
100104

101105
volume?: string;
@@ -135,7 +139,9 @@ export class TileModel {
135139
this.snippets = result.highlight?.values ?? [];
136140
this.source = result.source?.value;
137141
this.subjects = result.subject?.values ?? [];
142+
this.thumbnailUrl = result.__img__?.value;
138143
this.title = result.title?.value ?? '';
144+
this.tvClipCount = result.num_clips?.value ?? 0;
139145
this.volume = result.volume?.value;
140146
this.viewCount = result.downloads?.value;
141147
this.weeklyViewCount = result.week?.value;
@@ -172,7 +178,9 @@ export class TileModel {
172178
cloned.snippets = this.snippets;
173179
cloned.source = this.source;
174180
cloned.subjects = this.subjects;
181+
cloned.thumbnailUrl = this.thumbnailUrl;
175182
cloned.title = this.title;
183+
cloned.tvClipCount = this.tvClipCount;
176184
cloned.volume = this.volume;
177185
cloned.viewCount = this.viewCount;
178186
cloned.weeklyViewCount = this.weeklyViewCount;

src/restoration-state-handler.ts

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,16 @@ export interface RestorationState {
3030
selectedCreatorFilter?: string;
3131
}
3232

33+
export interface RestorationStatePersistOptions {
34+
forceReplace?: boolean;
35+
persistMetadataSearchType?: boolean;
36+
}
37+
3338
export interface RestorationStateHandlerInterface {
34-
persistState(state: RestorationState, forceReplace?: boolean): void;
39+
persistState(
40+
state: RestorationState,
41+
options?: RestorationStatePersistOptions,
42+
): void;
3543
getRestorationState(): RestorationState;
3644
}
3745

@@ -50,9 +58,12 @@ export class RestorationStateHandler
5058
this.context = options.context;
5159
}
5260

53-
persistState(state: RestorationState, forceReplace = false): void {
61+
persistState(
62+
state: RestorationState,
63+
options: RestorationStatePersistOptions = {},
64+
): void {
5465
if (state.displayMode) this.persistViewStateToCookies(state.displayMode);
55-
this.persistQueryStateToUrl(state, forceReplace);
66+
this.persistQueryStateToUrl(state, options);
5667
}
5768

5869
getRestorationState(): RestorationState {
@@ -87,7 +98,7 @@ export class RestorationStateHandler
8798

8899
private persistQueryStateToUrl(
89100
state: RestorationState,
90-
forceReplace = false,
101+
options: RestorationStatePersistOptions = {},
91102
) {
92103
const url = new URL(window.location.href);
93104
const oldParams = new URLSearchParams(url.searchParams);
@@ -99,11 +110,24 @@ export class RestorationStateHandler
99110
newParams.set('query', state.baseQuery);
100111
}
101112

102-
if (state.searchType === SearchType.FULLTEXT) {
103-
newParams.set('sin', 'TXT');
104-
} else if (state.searchType === SearchType.RADIO) {
105-
newParams.set('sin', 'RADIO');
113+
switch (state.searchType) {
114+
case SearchType.FULLTEXT:
115+
newParams.set('sin', 'TXT');
116+
break;
117+
case SearchType.RADIO:
118+
newParams.set('sin', 'RADIO');
119+
break;
120+
case SearchType.TV:
121+
newParams.set('sin', 'TV');
122+
break;
123+
case SearchType.METADATA:
124+
// Only write the param for metadata when it isn't already the default.
125+
// Currently this is only the case within TV collections.
126+
if (options.persistMetadataSearchType || oldParams.get('sin') === 'MD')
127+
newParams.set('sin', 'MD');
128+
break;
106129
}
130+
107131
if (oldParams.get('sin') === '') {
108132
// Treat empty sin the same as no sin at all
109133
oldParams.delete('sin');
@@ -180,7 +204,7 @@ export class RestorationStateHandler
180204
// - If the state has changed, we push a new history entry.
181205
// - If only the page number has changed, we replace the current history entry.
182206
// - If the state hasn't changed, then do nothing.
183-
let historyMethod: 'pushState' | 'replaceState' = forceReplace
207+
let historyMethod: 'pushState' | 'replaceState' = options.forceReplace
184208
? 'replaceState'
185209
: 'pushState';
186210
const nonQueryParamsMatch = this.paramsMatch(oldParams, newParams, [
@@ -261,16 +285,21 @@ export class RestorationStateHandler
261285
}
262286

263287
switch (searchInside) {
264-
// Eventually there will be TV/Radio search types here too.
265288
case 'TXT':
266289
restorationState.searchType = SearchType.FULLTEXT;
267290
break;
268291
case 'RADIO':
269292
restorationState.searchType = SearchType.RADIO;
270293
break;
271-
default:
294+
case 'TV':
295+
restorationState.searchType = SearchType.TV;
296+
break;
297+
case 'MD':
272298
restorationState.searchType = SearchType.METADATA;
273299
break;
300+
default:
301+
restorationState.searchType = SearchType.DEFAULT;
302+
break;
274303
}
275304

276305
if (pageNumber) {

src/tiles/grid/item-tile.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ export class ItemTile extends BaseTileComponent {
3636

3737
@property({ type: Boolean }) showInfoButton = false;
3838

39+
@property({ type: Boolean }) showTvClips = false;
40+
3941
render() {
4042
const itemTitle = this.model?.title;
4143
const effectiveSort = this.sortParam ?? this.defaultSortParam;
@@ -71,6 +73,8 @@ export class ItemTile extends BaseTileComponent {
7173
.viewLabel=${viewLabel}
7274
.favCount=${this.model?.favCount}
7375
.commentCount=${this.model?.commentCount}
76+
.tvClipCount=${this.model?.tvClipCount}
77+
.showTvClips=${this.showTvClips}
7478
>
7579
</tile-stats>
7680
</div>

0 commit comments

Comments
 (0)