Merge branch 'search-no-results' into 'develop'

Search results improvements

See merge request soapbox-pub/soapbox-fe!665
merge-requests/637/merge
Alex Gleason 3 years ago
commit a54be925f6

@ -37,7 +37,7 @@ export function submitSearch() {
return; return;
} }
dispatch(fetchSearchRequest()); dispatch(fetchSearchRequest(value));
api(getState).get('/api/v2/search', { api(getState).get('/api/v2/search', {
params: { params: {
@ -62,9 +62,10 @@ export function submitSearch() {
}; };
} }
export function fetchSearchRequest() { export function fetchSearchRequest(value) {
return { return {
type: SEARCH_FETCH_REQUEST, type: SEARCH_FETCH_REQUEST,
value,
}; };
} }

@ -1,5 +1,6 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import AccountContainer from '../../../containers/account_container'; import AccountContainer from '../../../containers/account_container';
import StatusContainer from '../../../containers/status_container'; import StatusContainer from '../../../containers/status_container';
@ -13,6 +14,7 @@ import classNames from 'classnames';
export default class SearchResults extends ImmutablePureComponent { export default class SearchResults extends ImmutablePureComponent {
static propTypes = { static propTypes = {
value: ImmutablePropTypes.string,
results: ImmutablePropTypes.map.isRequired, results: ImmutablePropTypes.map.isRequired,
submitted: PropTypes.bool, submitted: PropTypes.bool,
expandSearch: PropTypes.func.isRequired, expandSearch: PropTypes.func.isRequired,
@ -24,7 +26,7 @@ export default class SearchResults extends ImmutablePureComponent {
handleSelectFilter = newActiveFilter => this.props.selectFilter(newActiveFilter); handleSelectFilter = newActiveFilter => this.props.selectFilter(newActiveFilter);
render() { render() {
const { results, submitted, selectedFilter } = this.props; const { value, results, submitted, selectedFilter } = this.props;
if (submitted && results.isEmpty()) { if (submitted && results.isEmpty()) {
return ( return (
@ -37,33 +39,57 @@ export default class SearchResults extends ImmutablePureComponent {
let searchResults; let searchResults;
let hasMore = false; let hasMore = false;
if (selectedFilter === 'accounts' && results.get('accounts') && results.get('accounts').size > 0) { if (selectedFilter === 'accounts' && results.get('accounts')) {
hasMore = results.get('accountsHasMore'); hasMore = results.get('accountsHasMore');
searchResults = ( searchResults = results.get('accounts').size > 0 ? (
<div className={classNames('search-results__section', { 'has-more': hasMore })}> <div className={classNames('search-results__section', { 'has-more': hasMore })}>
{results.get('accounts').map(accountId => <AccountContainer key={accountId} id={accountId} />)} {results.get('accounts').map(accountId => <AccountContainer key={accountId} id={accountId} />)}
</div> </div>
) : (
<div className='empty-column-indicator'>
<FormattedMessage
id='empty_column.search.accounts'
defaultMessage='There are no people results for "{term}"'
values={{ term: value }}
/>
</div>
); );
} }
if (selectedFilter === 'statuses' && results.get('statuses') && results.get('statuses').size > 0) { if (selectedFilter === 'statuses' && results.get('statuses')) {
hasMore = results.get('statusesHasMore'); hasMore = results.get('statusesHasMore');
searchResults = ( searchResults = results.get('statuses').size > 0 ? (
<div className={classNames('search-results__section', { 'has-more': hasMore })}> <div className={classNames('search-results__section', { 'has-more': hasMore })}>
{results.get('statuses').map(statusId => <StatusContainer key={statusId} id={statusId} />)} {results.get('statuses').map(statusId => <StatusContainer key={statusId} id={statusId} />)}
</div> </div>
) : (
<div className='empty-column-indicator'>
<FormattedMessage
id='empty_column.search.statuses'
defaultMessage='There are no posts results for "{term}"'
values={{ term: value }}
/>
</div>
); );
} }
if (selectedFilter === 'hashtags' && results.get('hashtags') && results.get('hashtags').size > 0) { if (selectedFilter === 'hashtags' && results.get('hashtags')) {
hasMore = results.get('hashtagsHasMore'); hasMore = results.get('hashtagsHasMore');
searchResults = ( searchResults = results.get('hashtags').size > 0 ? (
<div className={classNames('search-results__section', { 'has-more': hasMore })}> <div className={classNames('search-results__section', { 'has-more': hasMore })}>
{results.get('hashtags').map(hashtag => <Hashtag key={hashtag.get('name')} hashtag={hashtag} />)} {results.get('hashtags').map(hashtag => <Hashtag key={hashtag.get('name')} hashtag={hashtag} />)}
</div> </div>
) : (
<div className='empty-column-indicator'>
<FormattedMessage
id='empty_column.search.hashtags'
defaultMessage='There are no hashtags results for "{term}"'
values={{ term: value }}
/>
</div>
); );
} }

@ -5,6 +5,7 @@ import { expandSearch, setFilter } from '../../../actions/search';
const mapStateToProps = state => { const mapStateToProps = state => {
return { return {
value: state.getIn(['search', 'submittedValue']),
results: state.getIn(['search', 'results']), results: state.getIn(['search', 'results']),
suggestions: state.getIn(['suggestions', 'items']), suggestions: state.getIn(['suggestions', 'items']),
submitted: state.getIn(['search', 'submitted']), submitted: state.getIn(['search', 'submitted']),

@ -326,6 +326,9 @@
"empty_column.public": "Tu nic nie ma! Napisz coś publicznie, lub dodaj ludzi z innych serwerów, aby to wyświetlić", "empty_column.public": "Tu nic nie ma! Napisz coś publicznie, lub dodaj ludzi z innych serwerów, aby to wyświetlić",
"empty_column.remote": "Tu nic nie ma! Zaobserwuj użytkowników {instance}, aby wypełnić tę oś.", "empty_column.remote": "Tu nic nie ma! Zaobserwuj użytkowników {instance}, aby wypełnić tę oś.",
"empty_column.scheduled_statuses": "Nie masz żadnych zaplanowanych wpisów. Kiedy dodasz jakiś, pojawi się on tutaj.", "empty_column.scheduled_statuses": "Nie masz żadnych zaplanowanych wpisów. Kiedy dodasz jakiś, pojawi się on tutaj.",
"empty_column.search.accounts": "Brak wyników wyszukiwania osób dla „{term}”",
"empty_column.search.hashtags": "Brak wyników wyszukiwania hashtagów dla „{term}”",
"empty_column.search.statuses": "Brak wyników wyszukiwania wpisów dla „{term}”",
"federation_restriction.federated_timeline_removal": "Usunięcie z osi czasu Fediwersum", "federation_restriction.federated_timeline_removal": "Usunięcie z osi czasu Fediwersum",
"federation_restriction.followers_only": "Ukryte z wyjątkiem obserwujących", "federation_restriction.followers_only": "Ukryte z wyjątkiem obserwujących",
"federation_restriction.full_media_removal": "Pełne usunięcie mediów", "federation_restriction.full_media_removal": "Pełne usunięcie mediów",

@ -6,6 +6,7 @@ describe('search reducer', () => {
expect(reducer(undefined, {})).toEqual(ImmutableMap({ expect(reducer(undefined, {})).toEqual(ImmutableMap({
value: '', value: '',
submitted: false, submitted: false,
submittedValue: '',
hidden: false, hidden: false,
results: ImmutableMap(), results: ImmutableMap(),
filter: 'accounts', filter: 'accounts',

@ -17,6 +17,7 @@ import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable';
const initialState = ImmutableMap({ const initialState = ImmutableMap({
value: '', value: '',
submitted: false, submitted: false,
submittedValue: '',
hidden: false, hidden: false,
results: ImmutableMap(), results: ImmutableMap(),
filter: 'accounts', filter: 'accounts',
@ -47,6 +48,7 @@ export default function search(state = initialState, action) {
return state.withMutations(map => { return state.withMutations(map => {
map.set('results', ImmutableMap()); map.set('results', ImmutableMap());
map.set('submitted', true); map.set('submitted', true);
map.set('submittedValue', action.value);
}); });
case SEARCH_FETCH_SUCCESS: case SEARCH_FETCH_SUCCESS:
return state.set('results', ImmutableMap({ return state.set('results', ImmutableMap({
@ -56,7 +58,13 @@ export default function search(state = initialState, action) {
accountsHasMore: action.results.accounts.length >= 20, accountsHasMore: action.results.accounts.length >= 20,
statusesHasMore: action.results.statuses.length >= 20, statusesHasMore: action.results.statuses.length >= 20,
hashtagsHasMore: action.results.hashtags.length >= 20, hashtagsHasMore: action.results.hashtags.length >= 20,
})).set('submitted', true).set('filter', 'accounts'); })).set('submitted', true).set('filter', action.results.accounts.length > 0
? 'accounts'
: action.results.statuses.length > 0
? 'statuses'
: action.results.hashtags.length > 0
? 'hashtags'
: 'accounts');
case SEARCH_FILTER_SET: case SEARCH_FILTER_SET:
return state.set('filter', action.value); return state.set('filter', action.value);
case SEARCH_EXPAND_SUCCESS: case SEARCH_EXPAND_SUCCESS:

Loading…
Cancel
Save