Skip to content

Commit

Permalink
Added component to conditionally render empty state of search results (
Browse files Browse the repository at this point in the history
  • Loading branch information
nashvail authored and borisyankov committed Aug 6, 2017
1 parent 0b5dcba commit af5be82
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 4 deletions.
45 changes: 45 additions & 0 deletions src/common/SearchEmptyState.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/* @flow */
import React from 'react';
import { StyleSheet, View } from 'react-native';
import { ZulipButton, Label } from './';

const styles = StyleSheet.create({
container: {
flex: 1,
padding: 16,
marginTop: 10,
},
text: {
fontSize: 18,
textAlign: 'center',
},
button: {
marginTop: 15,
fontSize: 12,
},
});

export default class SearchEmptyState extends React.PureComponent {
props: {
text?: string,
buttonText?: string,
buttonAction?: () => void,
};

static defaultProps = {
text: 'No Results',
buttonText: 'Show All',
};

render() {
const { text, buttonText, buttonAction } = this.props;

return (
<View style={styles.container}>
<Label style={styles.text} text={text} />
{buttonAction &&
<ZulipButton style={styles.button} secondary text={buttonText} onPress={buttonAction} />}
</View>
);
}
}
1 change: 1 addition & 0 deletions src/common/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ export { default as ZulipButton } from './ZulipButton';
export { default as ZulipStatusBar } from './ZulipStatusBar';
export { default as ZulipSwitch } from './ZulipSwitch';
export { default as SlideAnimationView } from './SlideAnimationView';
export { default as SearchEmptyState } from './SearchEmptyState';
4 changes: 3 additions & 1 deletion src/i18n/translations/messages_en.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,7 @@
"Notifications when online": "Notifications when online",
"Notifications when offline": "Notifications when offline",
"Unread": "Unread",
"Subscribed": "Subscribed"
"Subscribed": "Subscribed",
"No users found": "No users found",
"No streams found": "No streams found"
}
7 changes: 5 additions & 2 deletions src/search/SearchMessagesCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import throttle from 'lodash.throttle';
import { ActionSheetProvider } from '@expo/react-native-action-sheet';

import type { Actions, Auth } from '../types';
import { Label } from '../common';
import { SearchEmptyState } from '../common';
import { BRAND_COLOR } from '../styles';
import { searchNarrow } from '../utils/narrow';
import MessageList from '../message/MessageList';
Expand Down Expand Up @@ -73,11 +73,14 @@ export default class SearchMessagesCard extends PureComponent {
const { actions, auth, subscriptions, twentyFourHourTime, flags } = this.props;
const noResults = !!query && !isFetching && !messages.length;

if (noResults) {
return <SearchEmptyState text="No results" />;
}

return (
<View style={styles.results}>
{isFetching &&
<ActivityIndicator style={styles.activity} color={BRAND_COLOR} size="large" />}
{noResults && <Label style={styles.empty} text="No results" />}
<ActionSheetProvider>
<MessageList
actions={actions}
Expand Down
14 changes: 14 additions & 0 deletions src/streams/StreamList.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { FlatList, StyleSheet } from 'react-native';
import type { Stream } from '../types';
import { caseInsensitiveCompareObjFunc } from '../utils/misc';
import StreamItem from './StreamItem';
import { SearchEmptyState } from '../common';

const styles = StyleSheet.create({
list: {
Expand All @@ -22,6 +23,7 @@ export default class StreamList extends PureComponent {
unreadByStream: number[],
onPress?: (streamName: string) => void,
onSwitch?: (streamName: string, newValue: boolean) => void,
clearInput?: () => void,
};

static defaultProps = {
Expand All @@ -40,8 +42,20 @@ export default class StreamList extends PureComponent {
unreadByStream,
onPress,
onSwitch,
clearInput,
} = this.props;
const sortedStreams = streams.sort(caseInsensitiveCompareObjFunc('name'));
const noResults = streams.length === 0;

if (noResults) {
return (
<SearchEmptyState
text="No streams found"
buttonText="All streams"
buttonAction={clearInput}
/>
);
}

return (
<FlatList
Expand Down
5 changes: 5 additions & 0 deletions src/subscriptions/SubscriptionsCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ export default class SubscriptionsCard extends PureComponent {
}
};

clearInput = () => {
this.setState({ filter: '' });
};

render() {
const { streams, subscriptions } = this.props;
const filteredStreams = streams.filter(x => x.name.includes(this.state.filter));
Expand All @@ -48,6 +52,7 @@ export default class SubscriptionsCard extends PureComponent {
showDescriptions
onSwitch={this.handleSwitchChange}
onPress={nullFunction}
clearInput={this.clearInput}
/>
);
}
Expand Down
7 changes: 6 additions & 1 deletion src/users/UserList.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import React, { PureComponent } from 'react';
import { StyleSheet, SectionList } from 'react-native';

import { RawLabel } from '../common';
import { RawLabel, SearchEmptyState } from '../common';
import UserItem from './UserItem';
import { sortUserList, filterUserList, groupUsersByInitials } from '../selectors';
import { User } from '../types';
Expand Down Expand Up @@ -32,6 +32,11 @@ export default class UserList extends PureComponent {
const shownUsers = sortUserList(filterUserList(users, filter));
const groupedUsers = groupUsersByInitials(shownUsers);
const sections = Object.keys(groupedUsers).map(key => ({ key, data: groupedUsers[key] }));
const noResults = shownUsers.length === 0;

if (noResults) {
return <SearchEmptyState text="No users found" />;
}

return (
<SectionList
Expand Down

0 comments on commit af5be82

Please sign in to comment.