New: Search by Tag

pull/6/head
Qstick 7 years ago
parent ef93ae3792
commit d79139976c

@ -1,4 +1,3 @@
import _ from 'lodash';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, { Component } from 'react'; import React, { Component } from 'react';
import Autosuggest from 'react-autosuggest'; import Autosuggest from 'react-autosuggest';
@ -71,6 +70,7 @@ class ArtistSearchInput extends Component {
return ( return (
<ArtistSearchResult <ArtistSearchResult
query={query} query={query}
cleanQuery={jdu.replace(query).toLowerCase()}
{...item} {...item}
/> />
); );
@ -138,14 +138,15 @@ class ArtistSearchInput extends Component {
onSuggestionsFetchRequested = ({ value }) => { onSuggestionsFetchRequested = ({ value }) => {
const lowerCaseValue = jdu.replace(value).toLowerCase(); const lowerCaseValue = jdu.replace(value).toLowerCase();
const suggestions = _.filter(this.props.artist, (artist) => { const suggestions = this.props.artist.filter((artist) => {
// Check the title first and if there isn't a match fallback to the alternate titles // Check the title first and if there isn't a match fallback to
// the alternate titles and finally the tags.
const titleMatch = jdu.replace(artist.artistName).toLowerCase().contains(lowerCaseValue); return (
artist.cleanName.contains(lowerCaseValue) ||
return titleMatch || _.some(artist.alternateTitles, (alternateTitle) => { // artist.alternateTitles.some((alternateTitle) => alternateTitle.cleanTitle.contains(lowerCaseValue)) ||
return jdu.replace(alternateTitle.title).toLowerCase().contains(lowerCaseValue); artist.tags.some((tag) => tag.cleanLabel.contains(lowerCaseValue))
}); );
}); });
this.setState({ suggestions }); this.setState({ suggestions });

@ -1,16 +1,80 @@
import _ from 'lodash';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { push } from 'react-router-redux'; import { push } from 'react-router-redux';
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import jdu from 'jdu';
import createAllArtistSelector from 'Store/Selectors/createAllArtistSelector'; import createAllArtistSelector from 'Store/Selectors/createAllArtistSelector';
import createTagsSelector from 'Store/Selectors/createTagsSelector';
import ArtistSearchInput from './ArtistSearchInput'; import ArtistSearchInput from './ArtistSearchInput';
function createMapStateToProps() { function createCleanTagsSelector() {
return createSelector(
createTagsSelector(),
(tags) => {
return tags.map((tag) => {
const {
id,
label
} = tag;
return {
id,
label,
cleanLabel: jdu.replace(label).toLowerCase()
};
});
}
);
}
function createCleanArtistSelector() {
return createSelector( return createSelector(
createAllArtistSelector(), createAllArtistSelector(),
createCleanTagsSelector(),
(allArtists, allTags) => {
return allArtists.map((artist) => {
const {
artistName,
sortName,
images,
// alternateTitles,
tags
} = artist;
return {
artistName,
sortName,
images,
cleanName: jdu.replace(artistName).toLowerCase(),
// alternateTitles: alternateTitles.map((alternateTitle) => {
// return {
// title: alternateTitle.title,
// cleanTitle: jdu.replace(alternateTitle.title).toLowerCase()
// };
// }),
tags: tags.map((id) => {
return allTags.find((tag) => tag.id === id);
})
};
}).sort((a, b) => {
if (a.cleanName < b.cleanName) {
return -1;
}
if (a.cleanName > b.cleanName) {
return 1;
}
return 0;
});
}
);
}
function createMapStateToProps() {
return createSelector(
createCleanArtistSelector(),
(artist) => { (artist) => {
return { return {
artist: _.sortBy(artist, 'sortName') artist
}; };
} }
); );

@ -19,12 +19,16 @@
} }
.alternateTitle { .alternateTitle {
flex: 1 1 1px; composes: title;
margin-left: 5px;
color: $disabledColor; color: $disabledColor;
font-size: $smallFontSize; font-size: $smallFontSize;
} }
.tagContainer {
composes: title;
}
@media only screen and (max-width: $breakpointSmall) { @media only screen and (max-width: $breakpointSmall) {
.titles, .titles,
.title, .title,

@ -1,27 +1,43 @@
import _ from 'lodash';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import { kinds } from 'Helpers/Props';
import Label from 'Components/Label';
import ArtistPoster from 'Artist/ArtistPoster'; import ArtistPoster from 'Artist/ArtistPoster';
import styles from './ArtistSearchResult.css'; import styles from './ArtistSearchResult.css';
function getMatchingAlternateTile(alternateTitles, query) { // function findMatchingAlternateTitle(alternateTitles, cleanQuery) {
return _.first(alternateTitles, (alternateTitle) => { // return alternateTitles.find((alternateTitle) => {
return alternateTitle.title.toLowerCase().contains(query.toLowerCase()); // return alternateTitle.cleanTitle.contains(cleanQuery);
// });
// }
function getMatchingTag(tags, cleanQuery) {
return tags.find((tag) => {
return tag.cleanLabel.contains(cleanQuery);
}); });
} }
function ArtistSearchResult(props) { function ArtistSearchResult(props) {
const { const {
query, cleanQuery,
artistName, artistName,
cleanName,
images,
// alternateTitles, // alternateTitles,
images tags
} = props; } = props;
const index = artistName.toLowerCase().indexOf(query.toLowerCase()); const titleContains = cleanName.contains(cleanQuery);
// const alternateTitle = index === -1 ? // let alternateTitle = null;
// getMatchingAlternateTile(alternateTitles, query) : let tag = null;
// null;
// if (!titleContains) {
// alternateTitle = findMatchingAlternateTitle(alternateTitles, cleanQuery);
// }
if (!titleContains) { // && !alternateTitle) {
tag = getMatchingTag(tags, cleanQuery);
}
return ( return (
<div className={styles.result}> <div className={styles.result}>
@ -44,16 +60,30 @@ function ArtistSearchResult(props) {
// {alternateTitle.title} // {alternateTitle.title}
// </div> // </div>
} }
{
!!tag &&
<div className={styles.tagContainer}>
<Label
key={tag.id}
kind={kinds.INFO}
>
{tag.label}
</Label>
</div>
}
</div> </div>
</div> </div>
); );
} }
ArtistSearchResult.propTypes = { ArtistSearchResult.propTypes = {
query: PropTypes.string.isRequired, cleanQuery: PropTypes.string.isRequired,
artistName: PropTypes.string.isRequired, artistName: PropTypes.string.isRequired,
// alternateTitles: PropTypes.arrayOf(PropTypes.object).isRequired, // alternateTitles: PropTypes.arrayOf(PropTypes.object).isRequired,
images: PropTypes.arrayOf(PropTypes.object).isRequired cleanName: PropTypes.string.isRequired,
images: PropTypes.arrayOf(PropTypes.object).isRequired,
tags: PropTypes.arrayOf(PropTypes.object).isRequired
}; };
export default ArtistSearchResult; export default ArtistSearchResult;

Loading…
Cancel
Save