diff --git a/src/collection-browser.ts b/src/collection-browser.ts index 2ccf06aa1..3a2c9d53a 100644 --- a/src/collection-browser.ts +++ b/src/collection-browser.ts @@ -47,6 +47,9 @@ import { tvFacetDisplayOrder, TvClipFilterType, TileBlurOverrideState, + defaultSortAvailability, + favoritesSortAvailability, + tvSortAvailability, } from './models'; import { RestorationStateHandlerInterface, @@ -788,14 +791,37 @@ export class CollectionBrowser private get sortFilterBarTemplate(): TemplateResult | typeof nothing { if (this.suppressSortBar) return nothing; + // Determine the set of sortable fields that should be shown in the sort bar + let defaultViewSort = SortField.weeklyview; + let defaultDateSort = SortField.date; + let sortFieldAvailability = defaultSortAvailability; + + // We adjust the sort options for a couple of special cases... + if (this.withinCollection?.startsWith('fav-')) { + // When viewing a fav- collection, we include the Date Favorited option and show + // it as the default in the date dropdown. + defaultDateSort = SortField.datefavorited; + sortFieldAvailability = favoritesSortAvailability; + } else if (!this.withinCollection && this.searchType === SearchType.TV) { + // When viewing TV search results, we default the views dropdown to All-time Views + // and exclude several of the usual date sort options. + defaultViewSort = SortField.alltimeview; + defaultDateSort = SortField.datearchived; + sortFieldAvailability = tvSortAvailability; + } + + // We only show relevance sort if a search query is currently defined + sortFieldAvailability.relevance = this.isRelevanceSortAvailable; + return html` = { + [SortField.relevance]: true, + [SortField.weeklyview]: true, + [SortField.alltimeview]: true, + [SortField.title]: true, + [SortField.datefavorited]: false, + [SortField.date]: true, + [SortField.datearchived]: true, + [SortField.datereviewed]: true, + [SortField.dateadded]: true, + [SortField.creator]: true, + [SortField.default]: false, + [SortField.unrecognized]: false, +}; + +export const favoritesSortAvailability: Record = { + ...defaultSortAvailability, + [SortField.datefavorited]: true, +}; + +export const tvSortAvailability: Record = { + ...defaultSortAvailability, + [SortField.date]: false, + [SortField.datereviewed]: false, + [SortField.dateadded]: false, +}; + export const defaultProfileElementSorts: Record< string, Exclude diff --git a/src/sort-filter-bar/sort-filter-bar.ts b/src/sort-filter-bar/sort-filter-bar.ts index 2d682e907..f00dafd25 100644 --- a/src/sort-filter-bar/sort-filter-bar.ts +++ b/src/sort-filter-bar/sort-filter-bar.ts @@ -16,11 +16,16 @@ import '@internetarchive/ia-dropdown'; import type { IaDropdown, optionInterface } from '@internetarchive/ia-dropdown'; import type { SortDirection } from '@internetarchive/search-service'; import { + ALL_DATE_SORT_FIELDS, + ALL_VIEWS_SORT_FIELDS, CollectionDisplayMode, + DateSortField, + defaultSortAvailability, PrefixFilterCounts, PrefixFilterType, SORT_OPTIONS, SortField, + ViewsSortField, } from '../models'; import './alpha-bar'; @@ -51,6 +56,13 @@ export class SortFilterBar SortField.default > = SortField.relevance; + /** Which view sort option to expose by default. */ + @property({ type: String }) defaultViewSort: ViewsSortField = + SortField.weeklyview; + + /** Which date sort option to expose by default */ + @property({ type: String }) defaultDateSort: DateSortField = SortField.date; + /** The current sort direction (asc/desc), or null if none is set */ @property({ type: String }) sortDirection: SortDirection | null = null; @@ -63,11 +75,20 @@ export class SortFilterBar /** The currently selected creator letter filter, or null if none is set */ @property({ type: String }) selectedCreatorFilter: string | null = null; - /** Whether to show the Relevance sort option (default `true`) */ - @property({ type: Boolean }) showRelevance: boolean = true; - - /** Whether to show the Date Favorited sort option instead of Date Published/Archived/Reviewed (default `false`) */ - @property({ type: Boolean }) showDateFavorited: boolean = false; + /** + * Map defining which sortable fields should be included on the sort bar. + * + * E.g., + * ``` + * { + * [SortField.relevance]: true, + * [SortField.date]: false, + * [SortField.title]: true, + * ... + * } + * ``` + */ + @property({ type: Object }) sortFieldAvailability = defaultSortAvailability; /** Whether to replace the default sort options with a slot for customization (default `false`) */ @property({ type: Boolean, reflect: true }) enableSortOptionsSlot: boolean = @@ -88,12 +109,12 @@ export class SortFilterBar /** * The Views sort option that was most recently selected (or the default, if none has been selected yet) */ - @state() private lastSelectedViewSort = SortField.weeklyview; + @state() private lastSelectedViewSort = this.defaultViewSort; /** * The Date sort option that was most recently selected (or the default, if none has been selected yet) */ - @state() private lastSelectedDateSort = this.defaultDateSortField; + @state() private lastSelectedDateSort = this.defaultDateSort; /** * Which of the alphabet bars (title/creator) should be shown, or null if one @@ -135,11 +156,11 @@ export class SortFilterBar /** The dropdown component containing options for weekly and all-time views */ @query('#views-dropdown') - private viewsDropdown!: IaDropdown; + private viewsDropdown?: IaDropdown; - /** The dropdown component containing the four date options */ + /** The dropdown component containing all the available date options */ @query('#date-dropdown') - private dateDropdown!: IaDropdown; + private dateDropdown?: IaDropdown; /** The single, consolidated dropdown component shown in mobile view */ @query('#mobile-dropdown') @@ -193,19 +214,18 @@ export class SortFilterBar } if (this.viewOptionSelected) { - this.lastSelectedViewSort = this.finalizedSortField; + this.lastSelectedViewSort = this.finalizedSortField as ViewsSortField; } else if (this.dateOptionSelected) { - this.lastSelectedDateSort = this.finalizedSortField; + this.lastSelectedDateSort = this.finalizedSortField as DateSortField; } } - // If we change which dropdown options are available, ensure the correct default becomes selected. - // Currently, Date Favorited is the only dropdown option whose presence/absence can change. - if ( - changed.has('showDateFavorited') && - changed.get('showDateFavorited') !== this.showDateFavorited - ) { - this.lastSelectedDateSort = this.defaultDateSortField; + // If we change which dropdown options are defaulted, update the default selections + if (changed.has('defaultViewSort')) { + this.lastSelectedViewSort = this.defaultViewSort; + } + if (changed.has('defaultDateSort')) { + this.lastSelectedDateSort = this.defaultDateSort; } } @@ -378,47 +398,11 @@ export class SortFilterBar class=${this.mobileSelectorVisible ? 'hidden' : 'visible'} >
    - ${this.showRelevance - ? html`
  • - ${this.getSortDisplayOption(SortField.relevance, { - onClick: () => { - this.dropdownBackdropVisible = false; - if (this.finalizedSortField !== SortField.relevance) { - this.clearAlphaBarFilters(); - this.setSelectedSort(SortField.relevance); - } - }, - })} -
  • ` - : nothing} -
  • ${this.viewsDropdownTemplate}
  • -
  • - ${this.getSortDisplayOption(SortField.title, { - onClick: () => { - this.dropdownBackdropVisible = false; - if (this.finalizedSortField !== SortField.title) { - this.alphaSelectorVisible = 'title'; - this.selectedCreatorFilter = null; - this.setSelectedSort(SortField.title); - this.emitCreatorLetterChangedEvent(); - } - }, - })} -
  • -
  • ${this.dateDropdownTemplate}
  • -
  • - ${this.getSortDisplayOption(SortField.creator, { - onClick: () => { - this.dropdownBackdropVisible = false; - if (this.finalizedSortField !== SortField.creator) { - this.alphaSelectorVisible = 'creator'; - this.selectedTitleFilter = null; - this.setSelectedSort(SortField.creator); - this.emitTitleLetterChangedEvent(); - } - }, - })} -
  • +
  • ${this.relevanceSortSelectorTemplate}
  • +
  • ${this.allViewsSortOptionsTemplate}
  • +
  • ${this.titleSortSelectorTemplate}
  • +
  • ${this.allDateSortOptionsTemplate}
  • +
  • ${this.creatorSortSelectorTemplate}
`; @@ -426,12 +410,9 @@ export class SortFilterBar /** The template to render all the sort options in mobile view */ private get mobileSortSelectorTemplate() { - const displayedOptions = Object.values(SORT_OPTIONS) - .filter(opt => opt.shownInSortBar) - .filter(opt => this.showRelevance || opt.field !== SortField.relevance) - .filter( - opt => this.showDateFavorited || opt.field !== SortField.datefavorited, - ); + const displayedOptions = Object.values(SORT_OPTIONS).filter( + opt => opt.shownInSortBar && this.sortFieldAvailability[opt.field], + ); return html`
${this.getSortDropdown({ - displayName: html`${SORT_OPTIONS[this.finalizedSortField].displayName}`, + displayName: SORT_OPTIONS[this.finalizedSortField].displayName, id: 'mobile-dropdown', selected: true, dropdownOptions: displayedOptions.map(opt => @@ -460,37 +441,37 @@ export class SortFilterBar } /** - * This generates each of the non-dropdown sort option links. + * This generates each of the non-dropdown sort option buttons. * * It manages the display value and the selected state of the option. * - * @param sortField - * @param options { - * onClick?: (e: Event) => void; If this is provided, it will also be called when the option is clicked. - * displayName?: TemplateResult; The name to display for the option. Defaults to the sortField display name. - * selected?: boolean; true if the option is selected. Defaults to the selectedSort === sortField. - * } - * @returns + * @param sortField Which sort field the button represents + * @param options Additional options: + * - `onSelected?: (e: Event) => void;` If this is provided, it will also be called when the option is selected. + * Default is to clear any selected alphabetical filters. */ - private getSortDisplayOption( + private getSortSelectorButton( sortField: SortField, options?: { - displayName?: TemplateResult; - selected?: boolean; - onClick?: (e: Event) => void; + onSelected?: (e: Event) => void; }, ): TemplateResult { - const isSelected = - options?.selected ?? this.finalizedSortField === sortField; - const displayName = - options?.displayName ?? SORT_OPTIONS[sortField].displayName; + const isSelected = this.finalizedSortField === sortField; + const displayName = SORT_OPTIONS[sortField].displayName; + const onSelected = + options?.onSelected ?? (() => this.clearAlphaBarFilters()); + return html`