Skip to content

Commit

Permalink
feat: Display collections in search results [PT-188117039]
Browse files Browse the repository at this point in the history
Splits out collections from resources and displays them at the top of the page.
  • Loading branch information
dougmartin committed Aug 30, 2024
1 parent a52d137 commit da507ea
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 14 deletions.
22 changes: 22 additions & 0 deletions rails/react-components/src/library/components/collections.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
@import '../../shared/styles/variables/_variables.scss';

.finderResultsCollections {
margin-bottom: 30px;

.finderResultsCollectionsHeader {
margin-bottom: 10px;

.finderResultsCollectionsCount {
display: flex;
justify-content: space-between;
}
}

.findResultsCollectionsShowMore {
background: $col-orange;
color: $white;
padding: 5px 10px;
display: inline-block;
border-radius: 4px;
}
}
60 changes: 60 additions & 0 deletions rails/react-components/src/library/components/collections.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React from "react";
import StemFinderResult from "./stem-finder-result";
import pluralize from "../helpers/pluralize";

import css from "./collections.scss";

interface Props {
collections: any[]
numTotalCollections: number;
}

interface State {
displayCount: number
}

export default class Collections extends React.Component<Props, State> {
constructor (props: Props) {
super(props);

this.state = {
displayCount: Math.min(2, props.numTotalCollections)
};
}

UNSAFE_componentWillReceiveProps (nextProps: any) {
this.setState((prev) => ({displayCount: Math.min(prev.displayCount, nextProps.numTotalCollections)}));
}

handleShowMore = () => {
this.setState((prev) => ({displayCount: Math.min(prev.displayCount + 2, this.props.numTotalCollections)}));
};

render () {
const { displayCount } = this.state;
const { collections, numTotalCollections } = this.props;
const showingAll = displayCount >= numTotalCollections;
const collectionCount = showingAll ? numTotalCollections : displayCount + " of " + numTotalCollections;

const displayCollections = collections.slice(0, displayCount);

return (
<div className={css.finderResultsCollections}>
<div className={css.finderResultsCollectionsHeader}>
<h2>Collections</h2>
<div className={css.finderResultsCollectionsCount}>
<div>
Showing <strong>{ collectionCount + " " + pluralize(collectionCount, "Collection", "Collections") }</strong> matching your search
</div>
</div>
</div>
<div className={css.finderResultsContainer}>
{ displayCollections.map((collection: any, index: any) => {
return <StemFinderResult key={`${collection.external_url}-${index}`} resource={collection} index={index} opacity={1} />;
}) }
</div>
{!showingAll && <button className={css.findResultsCollectionsShowMore} onClick={this.handleShowMore}>Show More</button>}
</div>
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@
}
}
.previewLink {
width: 130px;
width: 140px;

.previewLinkButton {
background: #fff;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ const StemFinderResult = Component({
},

render () {
const { resource, index } = this.props;
const { resource, index, opacity } = this.props;
const resourceTypeClass = resource.material_type.toLowerCase();
const finderResultClasses = this.state.isOpen ? `resourceItem ${css.finderResult} ${css.open} ${css[resourceTypeClass]}` : `resourceItem ${css.finderResult} ${css[resourceTypeClass]}`;
const resourceName = resource.name;
Expand All @@ -367,9 +367,14 @@ const StemFinderResult = Component({
const projectNameRegex = / |-|\./g;
const projectClass = projectName ? projectName.replace(projectNameRegex, "").toLowerCase() : null;
const transitionDelay = 100 * index;
const style: React.CSSProperties = { transitionDelay: transitionDelay + "ms" };

if (opacity !== undefined) {
style.opacity = opacity;
}

return (
<div className={finderResultClasses} style={{ transitionDelay: transitionDelay + "ms" }}>
<div className={finderResultClasses} style={style}>
<div className={css.finderResultImagePreview}>
<img alt={resource.name} src={resource.icon.url} />
</div>
Expand All @@ -389,10 +394,9 @@ const StemFinderResult = Component({
<div className={css.previewLink}>
{ resource.material_type !== "Collection"
? <a className={css.previewLinkButton} href={resource.links.preview.url} target="_blank" onClick={this.handlePreviewClick} rel="noreferrer">{ resource.links.preview.text }</a>
: <a className={css.previewLinkButton} href={resource.links.preview.url} target="_blank" onClick={this.handleViewCollectionClick} rel="noreferrer">View Collection</a>
: <a className={css.previewLinkButton} href={resource.links.preview.url} target="_blank" onClick={this.handleViewCollectionClick} rel="noreferrer">Go to Collection</a>
}
{ resource.material_type !== "Collection" &&
<div className={`${css.projectLabel} ${css[projectClass]}`}>
{ <div className={`${css.projectLabel} ${css[projectClass]}`}>
{ projectName }
</div>
}
Expand Down
47 changes: 39 additions & 8 deletions rails/react-components/src/library/components/stem-finder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import filters from "../helpers/filters";
import portalObjectHelpers from "../helpers/portal-object-helpers";
import AutoSuggest from "./search/auto-suggest";
import FeaturedCollections from "./featured-collections/featured-collections";
import Collections from "./collections";

import css from "./stem-finder.scss";

Expand Down Expand Up @@ -53,6 +54,7 @@ interface State {
lastSearchResultCount: number,
noResourcesFound: boolean,
numTotalResources: number,
numTotalCollections: number;
opacity: number,
resources: any[],
searching: boolean,
Expand Down Expand Up @@ -139,6 +141,7 @@ class StemFinder extends React.Component<Props, State> {
lastSearchResultCount: 0,
noResourcesFound: false,
numTotalResources: 0,
numTotalCollections: 0,
opacity: 1,
resources: [],
searching: false,
Expand Down Expand Up @@ -286,6 +289,7 @@ class StemFinder extends React.Component<Props, State> {
let resources = incremental ? this.state.resources.slice(0) : [];
const searchPage = incremental ? this.state.searchPage + 1 : 1;
const keyword = jQuery.trim(this.state.searchInput);
const collections: any[] = incremental ? this.state.collections.slice(0) : [];
/* eslint-enable react/no-access-state-in-setstate */

// short circuit further incremental searches when all data has been downloaded
Expand Down Expand Up @@ -317,20 +321,30 @@ class StemFinder extends React.Component<Props, State> {
dataType: "json"
}).done((result1: any) => {
let numTotalResources = 0;
let numTotalCollections = 0;
const results = result1.results;
const usersAuthoredResourcesCount = result1.filters.number_authored_resources;
let lastSearchResultCount = 0;

results.forEach((result: any) => {
result.materials.forEach((material: any) => {
portalObjectHelpers.processResource(material);
resources.push(material);
if (material.material_type === "Collection") {
featuredCollections.push(material);
// only set collections on initial search
if (!incremental) {
collections.push(material);
}
} else {
resources.push(material);
lastSearchResultCount++;
}
lastSearchResultCount++;
});
numTotalResources += result.pagination.total_items;
if (result.type === "collections") {
numTotalCollections = collections.length;
} else {
numTotalResources += result.pagination.total_items;
}
});

if (featuredCollections.length > 1) {
Expand All @@ -345,8 +359,10 @@ class StemFinder extends React.Component<Props, State> {
this.setState({
firstSearch: false,
featuredCollections,
collections,
resources,
numTotalResources,
numTotalCollections,
searchPage,
displayLimit,
searching: false,
Expand Down Expand Up @@ -739,6 +755,25 @@ class StemFinder extends React.Component<Props, State> {
}, 500);
}

renderCollections () {
const { collections, searchInput, numTotalCollections } = this.state;
const showCollections = (searchInput.trim().length > 0 || !this.noOptionsSelected()) && collections.length > 0;

if (showCollections) {
return <Collections collections={collections} numTotalCollections={numTotalCollections} />;
}

let featuredCollections = this.state.featuredCollections;
featuredCollections = featuredCollections.sort(() => Math.random() - Math.random()).slice(0, 3);
const showFeaturedCollections = !this.state.hideFeatured && this.state.initPage && this.noOptionsSelected() && featuredCollections.length > 0;

if (showFeaturedCollections) {
return <FeaturedCollections featuredCollections={featuredCollections} />;
}

return null;
}

renderResults () {
if (this.state.firstSearch) {
return (
Expand All @@ -748,14 +783,10 @@ class StemFinder extends React.Component<Props, State> {
);
}

let featuredCollections = this.state.featuredCollections;
featuredCollections = featuredCollections.sort(() => Math.random() - Math.random()).slice(0, 3);
const resources = this.state.resources.slice(0, this.state.displayLimit);
return (
<>
{ (!this.state.hideFeatured && this.state.initPage && this.noOptionsSelected() && featuredCollections.length > 0) &&
<FeaturedCollections featuredCollections={featuredCollections} />
}
{ this.renderCollections() }
{ this.renderResultsHeader() }
<div className={css.finderResultsContainer}>
{ resources.map((resource: any, index: any) => {
Expand Down

0 comments on commit da507ea

Please sign in to comment.