Skip to content

Commit

Permalink
WEBDEV-6333 Don't move facets around when clicked in More... dialog (#…
Browse files Browse the repository at this point in the history
…381)

* Create several facet utils to simplify facet merges/updates

* Adjust facet components to separate sorting behavior b/w sidebar & dialog

* Additional cleanup to improve code clarity & remove obsolete bits

* Update tests to account for new data flows

* Added missing documentation & example for facet util fn

* Remove some log stmts

* Only show selected/hidden facets on first page(s), not every page

* Update doc comments for bucket sorting

* Cleanup & dead code elimination

* Add some missing comments/documentation

* Update unit tests
  • Loading branch information
latonv authored Jul 10, 2024
1 parent cb17d54 commit bfb8eb0
Show file tree
Hide file tree
Showing 12 changed files with 716 additions and 362 deletions.
125 changes: 106 additions & 19 deletions src/collection-browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -351,11 +351,6 @@ export class CollectionBrowser
return this.pagesToRender * this.pageSize;
}

/**
* How many tiles to offset the data source by, to account for any removed tiles.
*/
private tileModelOffset = 0;

@query('infinite-scroller')
private infiniteScroller?: InfiniteScroller;

Expand Down Expand Up @@ -492,8 +487,11 @@ export class CollectionBrowser
);
}

render() {
willUpdate(): void {
this.setPlaceholderType();
}

render() {
return html`
<div
id="content-container"
Expand All @@ -506,6 +504,14 @@ export class CollectionBrowser
`;
}

/**
* Determines what type of placeholder content should be shown instead of result tiles, if applicable.
* The placeholders indicate states where we have no results to show, which could be the result of:
* - No query is set (on the search page)
* - No results were returned for the most recent search
* - The collection being searched within has no viewable items
* - An error occurred on the most recent search attempt
*/
private setPlaceholderType() {
const hasQuery = !!this.baseQuery?.trim();
const isCollection = !!this.withinCollection;
Expand All @@ -532,6 +538,9 @@ export class CollectionBrowser
}
}

/**
* Template for the placeholder content to show when no results are available.
*/
private get emptyPlaceholderTemplate() {
return html`
<empty-placeholder
Expand Down Expand Up @@ -658,6 +667,9 @@ export class CollectionBrowser
`;
}

/**
* Template for the infinite scroller widget that contains the result tiles.
*/
private get infiniteScrollerTemplate() {
return html`<infinite-scroller
class=${this.infiniteScrollerClasses}
Expand All @@ -673,13 +685,20 @@ export class CollectionBrowser
</infinite-scroller>`;
}

/**
* Produces a `classMap` indicating which classes the infinite scroller should have
* given the current display mode & placeholder case.
*/
private get infiniteScrollerClasses() {
return classMap({
[this.displayMode ?? '']: !!this.displayMode,
hidden: !!this.placeholderType,
});
}

/**
* Template for the sort & filtering bar that appears atop the search results.
*/
private get sortFilterBarTemplate(): TemplateResult | typeof nothing {
if (this.suppressSortBar) return nothing;

Expand Down Expand Up @@ -710,6 +729,10 @@ export class CollectionBrowser
`;
}

/**
* Template for the manage bar UI that appears atop the search results when we are
* showing the management view. This generally replaces the sort bar when present.
*/
private get manageBarTemplate(): TemplateResult {
return html`
<manage-bar
Expand Down Expand Up @@ -754,6 +777,9 @@ export class CollectionBrowser
this.dataSource.removeCheckedTiles();
}

/**
* Handler for when the user changes the selected sort option or direction.
*/
private userChangedSort(
e: CustomEvent<{
selectedSort: SortField;
Expand All @@ -770,6 +796,10 @@ export class CollectionBrowser
this.currentPage = 1;
}

/**
* Fires an analytics event for sorting changes.
* @param prevSortDirection Which sort direction was previously set.
*/
private sendSortByAnalytics(prevSortDirection: SortDirection | null): void {
const directionCleared = prevSortDirection && !this.sortDirection;

Expand All @@ -782,11 +812,18 @@ export class CollectionBrowser
});
}

/**
* Handler for when the selected sort option is updated, whether by the user
* themselves or programmatically.
*/
private selectedSortChanged(): void {
// Lazy-load the alphabet counts for title/creator sort bar as needed
this.dataSource.updatePrefixFiltersForCurrentSort();
}

/**
* An object representing the current sort field & direction.
*/
get sortParam(): SortParam | null {
const sortOption = SORT_OPTIONS[this.selectedSort];
if (!sortOption?.handledBySearchService) {
Expand All @@ -806,6 +843,9 @@ export class CollectionBrowser
return { field: sortField, direction: this.sortDirection };
}

/**
* Handler for when the display mode option is changed (grid/list/compact-list views).
*/
private displayModeChanged(
e: CustomEvent<{ displayMode?: CollectionDisplayMode }>
): void {
Expand Down Expand Up @@ -1033,14 +1073,9 @@ export class CollectionBrowser
`;
}

private get loadingTemplate() {
return html`
<div class="loading-cover">
<circular-activity-indicator></circular-activity-indicator>
</div>
`;
}

/**
* Template for the table header content that appears atop the compact list view.
*/
private get listHeaderTemplate() {
return html`
<div id="list-header">
Expand All @@ -1057,6 +1092,9 @@ export class CollectionBrowser
`;
}

/**
* Handler for when the date picker's date range is changed.
*/
private histogramDateRangeUpdated(
e: CustomEvent<{
minDate: string;
Expand All @@ -1073,6 +1111,9 @@ export class CollectionBrowser
});
}

/**
* The Lucene query corresponding to the current date range.
*/
private get dateRangeQueryClause() {
if (!this.minSelectedDate || !this.maxSelectedDate) {
return undefined;
Expand All @@ -1092,6 +1133,19 @@ export class CollectionBrowser
);
}

/**
* Installs a new data source component and associated query state parameters into
* this component, causing it to efficiently update its views to represent the
* newly-provided data. In this way, one can reuse a single instance of
* <collection-browser> to handle multiple different sets of search results on
* a single page, each set of results being loaded & updated by its own data
* source.
*
* @param dataSource The data source component containing (or prepared to fetch)
* the tile data to be displayed.
* @param queryState The new query-related state that this component should
* represent, such as the search query, sort option, and any filters applied.
*/
async installDataSourceAndQueryState(
dataSource: CollectionBrowserDataSourceInterface,
queryState: CollectionBrowserQueryState
Expand Down Expand Up @@ -1133,13 +1187,21 @@ export class CollectionBrowser
this.setInitialSize();
}

/**
* Determines the initial size of the content container and whether or not
* the mobile layout should be used.
*/
setInitialSize(): void {
this.contentWidth = this.contentContainer.getBoundingClientRect().width;
this.mobileView =
this.contentWidth > 0 && this.contentWidth < this.mobileBreakpoint;
this.sendLayoutSizeAnalytics();
}

/**
* Fires an analytics event indicating which type of layout was rendered:
* mobile or desktop.
*/
private sendLayoutSizeAnalytics(): void {
if (this.analyticsHandler) {
this.layoutSizeAnalyticsSent = true;
Expand Down Expand Up @@ -1432,6 +1494,9 @@ export class CollectionBrowser
fadeElmt?.classList.toggle('hidden', entries?.[0]?.isIntersecting);
};

/**
* Emits a `baseQueryChanged` event indicating an update to the search query.
*/
private emitBaseQueryChanged() {
this.dispatchEvent(
new CustomEvent<{ baseQuery?: string }>('baseQueryChanged', {
Expand All @@ -1442,6 +1507,10 @@ export class CollectionBrowser
);
}

/**
* Emits a `searchTypeChanged` event indicating an update to the search type
* (e.g., metadata vs. full-text).
*/
private emitSearchTypeChanged() {
this.dispatchEvent(
new CustomEvent<SearchType>('searchTypeChanged', {
Expand All @@ -1450,6 +1519,10 @@ export class CollectionBrowser
);
}

/**
* Emits a `queryStateChanged` event indicating that one or more of this component's
* properties have changed in a way that could affect the set of search results.
*/
emitQueryStateChanged() {
this.dispatchEvent(
new CustomEvent<CollectionBrowserQueryState>('queryStateChanged', {
Expand All @@ -1471,6 +1544,10 @@ export class CollectionBrowser
);
}

/**
* Emits an `emptyResults` event indicating that we have received an empty result set
* for the most recent query.
*/
emitEmptyResults() {
this.dispatchEvent(new Event('emptyResults'));
}
Expand Down Expand Up @@ -1545,6 +1622,10 @@ export class CollectionBrowser
return this.dataSource.initialSearchComplete;
}

/**
* Handler for whenever the component's properties change in a way that may require
* fetching new results.
*/
private async handleQueryChange() {
// only reset if the query has actually changed
if (
Expand All @@ -1561,9 +1642,7 @@ export class CollectionBrowser
return;

this.previousQueryKey = this.dataSource.pageFetchQueryKey;
// this.emitQueryStateChanged();

this.tileModelOffset = 0;
this.totalResults = undefined;
this.pagesToRender =
this.initialPageNumber === 1
Expand Down Expand Up @@ -1593,9 +1672,6 @@ export class CollectionBrowser
this.persistState();
}
this.historyPopOccurred = false;

// Fire the initial page and facets requests
// await this.dataSource.handleQueryChange();
}

private setupStateRestorationObserver() {
Expand Down Expand Up @@ -1654,6 +1730,10 @@ export class CollectionBrowser
);
}

/**
* Emits a `searchResultsLoadingChanged` event indicating that our loading state has
* changed (either we have started loading new results, or we have finished loading them).
*/
private emitSearchResultsLoadingChanged(): void {
this.dispatchEvent(
new CustomEvent<{ loading: boolean }>('searchResultsLoadingChanged', {
Expand All @@ -1664,10 +1744,17 @@ export class CollectionBrowser
);
}

/**
* Handler for when the set of selected facets changes.
*/
facetsChanged(e: CustomEvent<SelectedFacets>) {
this.selectedFacets = e.detail;
}

/**
* Handler for when any facet is selected/unselected/hidden/unhidden.
* Fires analytics indicating the type of facet event that took place.
*/
facetClickHandler({
detail: { facetType, bucket, negative },
}: CustomEvent<FacetEventDetails>): void {
Expand Down
Loading

0 comments on commit bfb8eb0

Please sign in to comment.