Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 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 @@ -28,7 +28,7 @@
"@internetarchive/field-parsers": "^1.0.0",
"@internetarchive/histogram-date-range": "^1.4.0",
"@internetarchive/ia-activity-indicator": "^0.0.6",
"@internetarchive/ia-dropdown": "^1.3.10",
"@internetarchive/ia-dropdown": "1.3.11-alpha-webdev-7768.0",
"@internetarchive/iaux-item-metadata": "^1.0.5",
"@internetarchive/infinite-scroller": "^1.0.1",
"@internetarchive/modal-manager": "^2.0.1",
Expand Down
21 changes: 17 additions & 4 deletions src/collection-browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,16 @@ export class CollectionBrowser
*/
@property({ type: Object }) internalFilters?: SelectedFacets;

/**
* Whether to show smart facets (bubbles) along the top of the component
*/
@property({ type: Boolean }) showSmartFacetBar = false;

/**
* Sets the label that is shown in front of the smart facets, if present.
*/
@property({ type: String }) smartFacetBarLabel?: string;

/**
* Whether to show the date picker (above the facets)
*/
Expand Down Expand Up @@ -503,6 +511,10 @@ export class CollectionBrowser
this.sortDirection = null;
this.selectedSort = SortField.default;
}

if (this.smartFacetBar) {
this.smartFacetBar.deselectAll();
}
}

/**
Expand Down Expand Up @@ -549,7 +561,9 @@ export class CollectionBrowser
.aggregations=${this.dataSource.aggregations}
.selectedFacets=${this.selectedFacets}
.collectionTitles=${this.dataSource.collectionTitles}
.filterToggleShown=${!this.mobileView}
.filterToggleActive=${this.facetPaneVisible}
.label=${this.smartFacetBarLabel}
@facetsChanged=${this.facetsChanged}
@filtersToggled=${() => {
this.facetPaneVisible = !this.facetPaneVisible;
Expand Down Expand Up @@ -2507,7 +2521,7 @@ export class CollectionBrowser
.mobile #left-column {
width: 100%;
min-width: 0;
padding: 0;
padding: 5px 0;
border: 0;
}

Expand Down Expand Up @@ -2580,9 +2594,8 @@ export class CollectionBrowser
}

.mobile #results-total {
float: right;
margin-bottom: 0;
margin-right: 5px;
position: absolute;
right: 10px;
}

#big-results-count {
Expand Down
127 changes: 98 additions & 29 deletions src/collection-facets/smart-facets/smart-facet-bar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@ import {
} from 'lit';
import { repeat } from 'lit/directives/repeat.js';
import { customElement, property, state } from 'lit/decorators.js';
import { msg } from '@lit/localize';
import type { Aggregation, Bucket } from '@internetarchive/search-service';
import type { CollectionTitles } from '../../data-source/models';
import type { FacetOption, SelectedFacets } from '../../models';
import type {
FacetEventDetails,
FacetOption,
FacetState,
SelectedFacets,
} from '../../models';
import { updateSelectedFacetBucket } from '../../utils/facet-utils';
import { SmartQueryHeuristicGroup } from './smart-facet-heuristics';
import type { SmartFacetDropdown } from './smart-facet-dropdown';
Expand Down Expand Up @@ -47,8 +51,12 @@ export class SmartFacetBar extends LitElement {
@property({ type: Object })
collectionTitles?: CollectionTitles;

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

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

@property({ type: String }) label?: string;

@state() private heuristicRecs: SmartFacet[] = [];

@state() private smartFacets: SmartFacet[][] = [];
Expand All @@ -62,9 +70,13 @@ export class SmartFacetBar extends LitElement {
render() {
if (!this.query) return nothing;

const shouldShowLabel = !!this.label && this.smartFacets.length > 0;
return html`
<div id="smart-facets-container">
${this.filtersToggleTemplate}
${shouldShowLabel
? html`<p id="filters-label">${this.label}</p>`
: nothing}
${repeat(
this.smartFacets,
f =>
Expand Down Expand Up @@ -106,6 +118,15 @@ export class SmartFacetBar extends LitElement {
this.updateSmartFacets();
}

deselectAll(): void {
for (const sf of this.smartFacets) {
for (const facet of sf) {
facet.selected = false;
}
}
this.requestUpdate();
}

private async updateSmartFacets(): Promise<void> {
log('updating smart facets');
if (this.query) {
Expand Down Expand Up @@ -148,13 +169,15 @@ export class SmartFacetBar extends LitElement {
.facetInfo=${facets}
.labelPrefix=${fieldPrefixes[facets[0].facets[0].facetType]}
.activeFacetRef=${facets[0].facets[0]}
@facetClick=${this.facetDropdownClicked}
@dropdownClick=${this.onDropdownClick}
@facetClick=${this.dropdownOptionClicked}
@dropdownClick=${this.dropdownClicked}
></smart-facet-dropdown>
`;
}

private get filtersToggleTemplate(): TemplateResult {
private get filtersToggleTemplate(): TemplateResult | typeof nothing {
if (!this.filterToggleShown) return nothing;

return html`
<button
id="filters-toggle"
Expand Down Expand Up @@ -255,15 +278,48 @@ export class SmartFacetBar extends LitElement {
} as SmartFacet;
}

private facetClicked(e: CustomEvent<SmartFacetEvent>): void {
if (!e.detail.smartFacet.selected) {
/**
* Toggles the state of the given smart facet, and updates the selected facets accordingly.
*/
private toggleSmartFacet(
facet: SmartFacet,
details: FacetEventDetails[],
): void {
let newState: FacetState;
if (facet.selected) {
// When deselected, leave the smart facet where it is
newState = 'none';
this.smartFacets = this.smartFacets.map(f => {
if (f[0] === facet) return [{ ...facet, selected: false }];
return f;
});
} else {
// When selected, move the toggled smart facet to the front of the list
newState = 'selected';
this.smartFacets = [
[{ ...e.detail.smartFacet, selected: true }],
...this.smartFacets.filter(f => f[0] !== e.detail.smartFacet),
[{ ...facet, selected: true }],
...this.smartFacets.filter(f => f[0] !== facet),
];
}

for (const facet of e.detail.details) {
this.updateSelectedFacets(
details.map(facet => ({
...facet,
bucket: {
...facet.bucket,
state: newState,
},
})),
);
}

/**
* Updates the selected facet buckets for each of the given facets,
* and emits a `facetsChanged` event to notify parent components of
* the new state.
*/
private updateSelectedFacets(facets: FacetEventDetails[]): void {
for (const facet of facets) {
this.selectedFacets = updateSelectedFacetBucket(
this.selectedFacets,
facet.facetType,
Expand All @@ -278,34 +334,39 @@ export class SmartFacetBar extends LitElement {
this.dispatchEvent(event);
}

private facetDropdownClicked(e: CustomEvent<SmartFacetEvent>): void {
if (
this.smartFacets.find(sf => smartFacetEquals(sf[0], e.detail.smartFacet))
) {
/**
* Handler for when a smart facet button is clicked
*/
private facetClicked(e: CustomEvent<SmartFacetEvent>): void {
this.toggleSmartFacet(e.detail.smartFacet, e.detail.details);
}

/**
* Handler for when an option in a smart facet dropdown menu is selected
*/
private dropdownOptionClicked(e: CustomEvent<SmartFacetEvent>): void {
const existingFacet = this.smartFacets.find(
sf => sf.length === 1 && smartFacetEquals(sf[0], e.detail.smartFacet),
);
if (existingFacet) {
// The facet already exists outside the dropdown, so just select it there
this.toggleSmartFacet(existingFacet[0], e.detail.details);
return;
}

// Otherwise, prepend a new smart facet for the selected option
this.smartFacets = [
[{ ...e.detail.smartFacet, selected: true }],
...this.smartFacets,
];

for (const facet of e.detail.details) {
this.selectedFacets = updateSelectedFacetBucket(
this.selectedFacets,
facet.facetType,
facet.bucket,
true,
);
}

const event = new CustomEvent<SelectedFacets>('facetsChanged', {
detail: this.selectedFacets,
});
this.dispatchEvent(event);
this.updateSelectedFacets(e.detail.details);
}

private onDropdownClick(e: CustomEvent<SmartFacetDropdown>): void {
/**
* Handler for when any dropdown is clicked (whether button, caret, or menu item)
*/
private dropdownClicked(e: CustomEvent<SmartFacetDropdown>): void {
log('smart bar: onDropdownClick', e.detail);
this.shadowRoot
?.querySelectorAll('smart-facet-dropdown')
Expand All @@ -330,9 +391,11 @@ export class SmartFacetBar extends LitElement {
#smart-facets-container {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 5px 10px;
padding: 10px 0;
white-space: nowrap;
overflow: scroll hidden;
scrollbar-width: none;
}

#filters-toggle {
Expand Down Expand Up @@ -363,6 +426,12 @@ export class SmartFacetBar extends LitElement {
#filters-toggle.active > svg {
filter: invert(1);
}

#filters-label {
font-size: 1.4rem;
font-weight: var(--smartFacetLabelFontWeight, normal);
margin: 0 -5px 0 0;
}
`;
}
}
30 changes: 26 additions & 4 deletions src/collection-facets/smart-facets/smart-facet-dropdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,21 @@ export class SmartFacetDropdown extends LitElement {
<ia-dropdown
class="dropdown"
displayCaret
openViaButton
closeOnSelect
closeOnEscape
closeOnBackdropClick
includeSelectedOption
usePopover
.options=${this.dropdownOptions}
.selectedOption=${this.activeDropdownOption}
.openViaButton=${false}
@optionSelected=${this.optionSelected}
@click=${this.onDropdownClick}
>
<span class="dropdown-label" slot="dropdown-label"
<span
class="dropdown-label"
slot="dropdown-label"
@click=${this.defaultOptionSelected}
>${this.labelPrefix ?? nothing} ${displayText}</span
>
</ia-dropdown>
Expand Down Expand Up @@ -76,13 +80,31 @@ export class SmartFacetDropdown extends LitElement {
);
}

/**
* Handler for when the default option on the dropdown button is clicked
*/
private defaultOptionSelected(): void {
this.handleSelection(this.activeFacetRef?.bucketKey);
}

/**
* Handler for when an option in the dropdown menu is selected
*/
private optionSelected(e: CustomEvent<{ option: optionInterface }>): void {
if (!this.facetInfo || !this.activeFacetRef) return;
this.handleSelection(e.detail.option.id);
}

/**
* Responds to a dropdown selection by emitting a `facetClick` event with
* the appropriate facet details.
*/
private handleSelection(bucketKey?: string): void {
if (!bucketKey || !this.facetInfo || !this.activeFacetRef) return;

let selectedSmartFacet;
for (const smartFacet of this.facetInfo) {
const selectedRef = smartFacet.facets.find(
b => b.bucketKey === e.detail.option.id,
b => b.bucketKey === bucketKey,
);
if (selectedRef) {
this.activeFacetRef = selectedRef;
Expand Down
2 changes: 1 addition & 1 deletion src/tiles/grid/styles/tile-grid-shared-styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const baseTileStyles = css`
background-color: ${tileBackgroundColor};
border: 1px #2c2c2c;
border-radius: ${tileCornerRadius};
box-shadow: 1px 1px 2px 0;
box-shadow: var(--tileBoxShadow, 1px 1px 2px 0);
box-sizing: border-box;
height: 100%;
display: flex;
Expand Down
2 changes: 1 addition & 1 deletion src/tiles/tile-dispatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ export class TileDispatcher
}

#container.hoverable:hover {
box-shadow: 0 0 6px 2px rgba(8, 8, 32, 0.8);
box-shadow: var(--tileHoverBoxShadow, 0 0 6px 2px rgba(8, 8, 32, 0.8));
transition: box-shadow 0.1s ease;
}

Expand Down
Loading
Loading