Skip to content

WEBDEV-7479 Tile updates for TV collections/clips #447

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Jun 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"@internetarchive/iaux-item-metadata": "^1.0.4",
"@internetarchive/infinite-scroller": "^1.0.1",
"@internetarchive/modal-manager": "^2.0.1",
"@internetarchive/search-service": "^2.1.0",
"@internetarchive/search-service": "^2.2.0",
"@internetarchive/shared-resize-observer": "^0.2.0",
"@lit/localize": "^0.12.2",
"dompurify": "^3.2.4",
Expand Down
7 changes: 7 additions & 0 deletions src/assets/img/icons/quote.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { svg } from 'lit';

export const quoteIcon = svg`
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<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"/>
</svg>
`;
18 changes: 13 additions & 5 deletions src/collection-browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import {
RestorationStateHandlerInterface,
RestorationStateHandler,
RestorationState,
RestorationStatePersistOptions,
} from './restoration-state-handler';
import { CollectionBrowserDataSource } from './data-source/collection-browser-data-source';
import type {
Expand Down Expand Up @@ -95,7 +96,7 @@ export class CollectionBrowser
/**
* Which backend should be targeted by searches (e.g., metadata or FTS)
*/
@property({ type: Number }) searchType: SearchType = SearchType.METADATA;
@property({ type: Number }) searchType: SearchType = SearchType.DEFAULT;

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

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

/**
* Whether we are representing a TV collection, needing slightly different tile handling.
*/
@property({ type: Boolean }) isTVCollection = false;

/**
* If item management UI active
*/
Expand Down Expand Up @@ -1892,10 +1898,11 @@ export class CollectionBrowser
selectedTitleFilter: this.selectedTitleFilter ?? undefined,
selectedCreatorFilter: this.selectedCreatorFilter ?? undefined,
};
this.restorationStateHandler.persistState(
restorationState,
this.dataSourceInstallInProgress,
);
const persistOptions: RestorationStatePersistOptions = {
forceReplace: this.dataSourceInstallInProgress,
persistMetadataSearchType: this.isTVCollection,
};
this.restorationStateHandler.persistState(restorationState, persistOptions);
}

/**
Expand Down Expand Up @@ -2113,6 +2120,7 @@ export class CollectionBrowser
.mobileBreakpoint=${this.mobileBreakpoint}
.loggedIn=${this.loggedIn}
.isManageView=${this.isManageView}
?showTvClips=${this.isTVCollection}
?enableHoverPane=${true}
@resultSelected=${(e: CustomEvent) => this.resultSelected(e)}
>
Expand Down
23 changes: 20 additions & 3 deletions src/data-source/collection-browser-data-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -586,14 +586,23 @@ export class CollectionBrowserDataSource
const isCollectionSearch = !!this.host.withinCollection;
const isProfileSearch = !!this.host.withinProfile;
const hasProfileElement = !!this.host.profileElement;
const isDefaultedSearch = this.host.searchType === SearchType.DEFAULT;
const isMetadataSearch = this.host.searchType === SearchType.METADATA;
const isTvSearch = this.host.searchType === SearchType.TV;

// Metadata/tv searches within a collection are allowed to have no query.
const isValidForCollectionSearch =
isDefaultedSearch || isMetadataSearch || isTvSearch;

// Searches within a profile page may also be performed without a query, provided the profile element is set.
const isValidForProfileSearch =
hasProfileElement && (isDefaultedSearch || isMetadataSearch);

// Metadata searches within a collection/profile are allowed to have no query.
// Otherwise, a non-empty query must be set.
return (
hasNonEmptyQuery ||
(isCollectionSearch && isMetadataSearch) ||
(isProfileSearch && hasProfileElement && isMetadataSearch)
(isCollectionSearch && isValidForCollectionSearch) ||
(isProfileSearch && isValidForProfileSearch)
);
}

Expand Down Expand Up @@ -1132,6 +1141,14 @@ export class CollectionBrowserDataSource
this.parentCollections = [].concat(
this.collectionExtraInfo.public_metadata?.collection ?? [],
);

// Update the TV collection status now that we know the parent collections
this.host.isTVCollection =
this.host.withinCollection?.startsWith('TV-') ||
this.host.withinCollection === 'tvnews' ||
this.host.withinCollection === 'tvarchive' ||
this.parentCollections.includes('tvnews') ||
this.parentCollections.includes('tvarchive');
}
} else if (withinProfile) {
this.accountExtraInfo = success.response.accountExtraInfo;
Expand Down
1 change: 1 addition & 0 deletions src/data-source/collection-browser-query-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export interface CollectionBrowserQueryState {
export interface CollectionBrowserSearchInterface
extends CollectionBrowserQueryState {
searchService?: SearchServiceInterface;
isTVCollection: boolean;
readonly sortParam: SortParam | null;
readonly defaultSortField: SortField | null;
readonly facetLoadStrategy: FacetLoadStrategy;
Expand Down
8 changes: 8 additions & 0 deletions src/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,12 @@ export class TileModel {

subjects: string[];

thumbnailUrl?: string;

title: string;

tvClipCount?: number;

viewCount?: number;

volume?: string;
Expand Down Expand Up @@ -135,7 +139,9 @@ export class TileModel {
this.snippets = result.highlight?.values ?? [];
this.source = result.source?.value;
this.subjects = result.subject?.values ?? [];
this.thumbnailUrl = result.__img__?.value;
this.title = result.title?.value ?? '';
this.tvClipCount = result.num_clips?.value ?? 0;
this.volume = result.volume?.value;
this.viewCount = result.downloads?.value;
this.weeklyViewCount = result.week?.value;
Expand Down Expand Up @@ -172,7 +178,9 @@ export class TileModel {
cloned.snippets = this.snippets;
cloned.source = this.source;
cloned.subjects = this.subjects;
cloned.thumbnailUrl = this.thumbnailUrl;
cloned.title = this.title;
cloned.tvClipCount = this.tvClipCount;
cloned.volume = this.volume;
cloned.viewCount = this.viewCount;
cloned.weeklyViewCount = this.weeklyViewCount;
Expand Down
51 changes: 40 additions & 11 deletions src/restoration-state-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,16 @@ export interface RestorationState {
selectedCreatorFilter?: string;
}

export interface RestorationStatePersistOptions {
forceReplace?: boolean;
persistMetadataSearchType?: boolean;
}

export interface RestorationStateHandlerInterface {
persistState(state: RestorationState, forceReplace?: boolean): void;
persistState(
state: RestorationState,
options?: RestorationStatePersistOptions,
): void;
getRestorationState(): RestorationState;
}

Expand All @@ -50,9 +58,12 @@ export class RestorationStateHandler
this.context = options.context;
}

persistState(state: RestorationState, forceReplace = false): void {
persistState(
state: RestorationState,
options: RestorationStatePersistOptions = {},
): void {
if (state.displayMode) this.persistViewStateToCookies(state.displayMode);
this.persistQueryStateToUrl(state, forceReplace);
this.persistQueryStateToUrl(state, options);
}

getRestorationState(): RestorationState {
Expand Down Expand Up @@ -87,7 +98,7 @@ export class RestorationStateHandler

private persistQueryStateToUrl(
state: RestorationState,
forceReplace = false,
options: RestorationStatePersistOptions = {},
) {
const url = new URL(window.location.href);
const oldParams = new URLSearchParams(url.searchParams);
Expand All @@ -99,11 +110,24 @@ export class RestorationStateHandler
newParams.set('query', state.baseQuery);
}

if (state.searchType === SearchType.FULLTEXT) {
newParams.set('sin', 'TXT');
} else if (state.searchType === SearchType.RADIO) {
newParams.set('sin', 'RADIO');
switch (state.searchType) {
case SearchType.FULLTEXT:
newParams.set('sin', 'TXT');
break;
case SearchType.RADIO:
newParams.set('sin', 'RADIO');
break;
case SearchType.TV:
newParams.set('sin', 'TV');
break;
case SearchType.METADATA:
// Only write the param for metadata when it isn't already the default.
// Currently this is only the case within TV collections.
if (options.persistMetadataSearchType || oldParams.get('sin') === 'MD')
newParams.set('sin', 'MD');
break;
}

if (oldParams.get('sin') === '') {
// Treat empty sin the same as no sin at all
oldParams.delete('sin');
Expand Down Expand Up @@ -180,7 +204,7 @@ export class RestorationStateHandler
// - If the state has changed, we push a new history entry.
// - If only the page number has changed, we replace the current history entry.
// - If the state hasn't changed, then do nothing.
let historyMethod: 'pushState' | 'replaceState' = forceReplace
let historyMethod: 'pushState' | 'replaceState' = options.forceReplace
? 'replaceState'
: 'pushState';
const nonQueryParamsMatch = this.paramsMatch(oldParams, newParams, [
Expand Down Expand Up @@ -261,16 +285,21 @@ export class RestorationStateHandler
}

switch (searchInside) {
// Eventually there will be TV/Radio search types here too.
case 'TXT':
restorationState.searchType = SearchType.FULLTEXT;
break;
case 'RADIO':
restorationState.searchType = SearchType.RADIO;
break;
default:
case 'TV':
restorationState.searchType = SearchType.TV;
break;
case 'MD':
restorationState.searchType = SearchType.METADATA;
break;
default:
restorationState.searchType = SearchType.DEFAULT;
break;
}

if (pageNumber) {
Expand Down
4 changes: 4 additions & 0 deletions src/tiles/grid/item-tile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ export class ItemTile extends BaseTileComponent {

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

@property({ type: Boolean }) showTvClips = false;

render() {
const itemTitle = this.model?.title;
const effectiveSort = this.sortParam ?? this.defaultSortParam;
Expand Down Expand Up @@ -71,6 +73,8 @@ export class ItemTile extends BaseTileComponent {
.viewLabel=${viewLabel}
.favCount=${this.model?.favCount}
.commentCount=${this.model?.commentCount}
.tvClipCount=${this.model?.tvClipCount}
.showTvClips=${this.showTvClips}
>
</tile-stats>
</div>
Expand Down
Loading
Loading