Add flagging functionality to search results (#3803)
Этот коммит содержится в:
коммит произвёл
Corey Hulen
родитель
a820b1640b
Коммит
4a2fbcaf98
@@ -1,18 +1,21 @@
|
|||||||
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
|
||||||
// See License.txt for license information.
|
// See License.txt for license information.
|
||||||
|
|
||||||
import $ from 'jquery';
|
import SearchResultsHeader from './search_results_header.jsx';
|
||||||
|
import SearchResultsItem from './search_results_item.jsx';
|
||||||
|
import SearchBox from './search_bar.jsx';
|
||||||
|
|
||||||
import ChannelStore from 'stores/channel_store.jsx';
|
import ChannelStore from 'stores/channel_store.jsx';
|
||||||
import SearchStore from 'stores/search_store.jsx';
|
import SearchStore from 'stores/search_store.jsx';
|
||||||
import UserStore from 'stores/user_store.jsx';
|
import UserStore from 'stores/user_store.jsx';
|
||||||
import PreferenceStore from 'stores/preference_store.jsx';
|
import PreferenceStore from 'stores/preference_store.jsx';
|
||||||
import SearchBox from './search_bar.jsx';
|
|
||||||
import * as Utils from 'utils/utils.jsx';
|
import * as Utils from 'utils/utils.jsx';
|
||||||
import Constants from 'utils/constants.jsx';
|
import Constants from 'utils/constants.jsx';
|
||||||
const Preferences = Constants.Preferences;
|
const Preferences = Constants.Preferences;
|
||||||
import SearchResultsHeader from './search_results_header.jsx';
|
|
||||||
import SearchResultsItem from './search_results_item.jsx';
|
|
||||||
|
|
||||||
|
import $ from 'jquery';
|
||||||
|
import React from 'react';
|
||||||
import {FormattedMessage, FormattedHTMLMessage} from 'react-intl';
|
import {FormattedMessage, FormattedHTMLMessage} from 'react-intl';
|
||||||
|
|
||||||
function getStateFromStores() {
|
function getStateFromStores() {
|
||||||
@@ -34,12 +37,11 @@ function getStateFromStores() {
|
|||||||
return {
|
return {
|
||||||
results,
|
results,
|
||||||
channels,
|
channels,
|
||||||
searchTerm: SearchStore.getSearchTerm()
|
searchTerm: SearchStore.getSearchTerm(),
|
||||||
|
flaggedPosts: PreferenceStore.getCategory(Constants.Preferences.CATEGORY_FLAGGED_POST)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
export default class SearchResults extends React.Component {
|
export default class SearchResults extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
@@ -48,6 +50,7 @@ export default class SearchResults extends React.Component {
|
|||||||
|
|
||||||
this.onChange = this.onChange.bind(this);
|
this.onChange = this.onChange.bind(this);
|
||||||
this.onUserChange = this.onUserChange.bind(this);
|
this.onUserChange = this.onUserChange.bind(this);
|
||||||
|
this.onPreferenceChange = this.onPreferenceChange.bind(this);
|
||||||
this.resize = this.resize.bind(this);
|
this.resize = this.resize.bind(this);
|
||||||
this.onPreferenceChange = this.onPreferenceChange.bind(this);
|
this.onPreferenceChange = this.onPreferenceChange.bind(this);
|
||||||
this.handleResize = this.handleResize.bind(this);
|
this.handleResize = this.handleResize.bind(this);
|
||||||
@@ -62,10 +65,13 @@ export default class SearchResults extends React.Component {
|
|||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.mounted = true;
|
this.mounted = true;
|
||||||
|
|
||||||
SearchStore.addSearchChangeListener(this.onChange);
|
SearchStore.addSearchChangeListener(this.onChange);
|
||||||
ChannelStore.addChangeListener(this.onChange);
|
ChannelStore.addChangeListener(this.onChange);
|
||||||
PreferenceStore.addChangeListener(this.onPreferenceChange);
|
PreferenceStore.addChangeListener(this.onPreferenceChange);
|
||||||
UserStore.addChangeListener(this.onUserChange);
|
UserStore.addChangeListener(this.onUserChange);
|
||||||
|
PreferenceStore.addChangeListener(this.onPreferenceChange);
|
||||||
|
|
||||||
this.resize();
|
this.resize();
|
||||||
window.addEventListener('resize', this.handleResize);
|
window.addEventListener('resize', this.handleResize);
|
||||||
if (!Utils.isMobile()) {
|
if (!Utils.isMobile()) {
|
||||||
@@ -94,11 +100,14 @@ export default class SearchResults extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
this.mounted = false;
|
||||||
|
|
||||||
SearchStore.removeSearchChangeListener(this.onChange);
|
SearchStore.removeSearchChangeListener(this.onChange);
|
||||||
ChannelStore.removeChangeListener(this.onChange);
|
ChannelStore.removeChangeListener(this.onChange);
|
||||||
PreferenceStore.removeChangeListener(this.onPreferenceChange);
|
PreferenceStore.removeChangeListener(this.onPreferenceChange);
|
||||||
UserStore.removeChangeListener(this.onUserChange);
|
UserStore.removeChangeListener(this.onUserChange);
|
||||||
this.mounted = false;
|
PreferenceStore.removeChangeListener(this.onPreferenceChange);
|
||||||
|
|
||||||
window.removeEventListener('resize', this.handleResize);
|
window.removeEventListener('resize', this.handleResize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +120,8 @@ export default class SearchResults extends React.Component {
|
|||||||
|
|
||||||
onPreferenceChange() {
|
onPreferenceChange() {
|
||||||
this.setState({
|
this.setState({
|
||||||
compactDisplay: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.MESSAGE_DISPLAY, Preferences.MESSAGE_DISPLAY_DEFAULT) === Preferences.MESSAGE_DISPLAY_COMPACT
|
compactDisplay: PreferenceStore.get(Preferences.CATEGORY_DISPLAY_SETTINGS, Preferences.MESSAGE_DISPLAY, Preferences.MESSAGE_DISPLAY_DEFAULT) === Preferences.MESSAGE_DISPLAY_COMPACT,
|
||||||
|
flaggedPosts: PreferenceStore.getCategory(Constants.Preferences.CATEGORY_FLAGGED_POST)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,6 +223,11 @@ export default class SearchResults extends React.Component {
|
|||||||
} else {
|
} else {
|
||||||
profile = profiles[post.user_id];
|
profile = profiles[post.user_id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isFlagged = false;
|
||||||
|
if (this.state.flaggedPosts) {
|
||||||
|
isFlagged = this.state.flaggedPosts.get(post.id) === 'true';
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<SearchResultsItem
|
<SearchResultsItem
|
||||||
key={post.id}
|
key={post.id}
|
||||||
@@ -222,9 +237,10 @@ export default class SearchResults extends React.Component {
|
|||||||
user={profile}
|
user={profile}
|
||||||
term={searchTerm}
|
term={searchTerm}
|
||||||
isMentionSearch={this.props.isMentionSearch}
|
isMentionSearch={this.props.isMentionSearch}
|
||||||
|
isFlaggedSearch={this.props.isFlaggedPosts}
|
||||||
useMilitaryTime={this.props.useMilitaryTime}
|
useMilitaryTime={this.props.useMilitaryTime}
|
||||||
shrink={this.props.shrink}
|
shrink={this.props.shrink}
|
||||||
isFlagged={this.props.isFlaggedPosts}
|
isFlagged={isFlagged}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}, this);
|
}, this);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import UserStore from 'stores/user_store.jsx';
|
|||||||
|
|
||||||
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
|
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
|
||||||
import * as GlobalActions from 'actions/global_actions.jsx';
|
import * as GlobalActions from 'actions/global_actions.jsx';
|
||||||
import {unflagPost, getFlaggedPosts} from 'actions/post_actions.jsx';
|
import {flagPost, unflagPost} from 'actions/post_actions.jsx';
|
||||||
|
|
||||||
import * as TextFormatting from 'utils/text_formatting.jsx';
|
import * as TextFormatting from 'utils/text_formatting.jsx';
|
||||||
import * as Utils from 'utils/utils.jsx';
|
import * as Utils from 'utils/utils.jsx';
|
||||||
@@ -30,6 +30,7 @@ export default class SearchResultsItem extends React.Component {
|
|||||||
this.handleFocusRHSClick = this.handleFocusRHSClick.bind(this);
|
this.handleFocusRHSClick = this.handleFocusRHSClick.bind(this);
|
||||||
this.shrinkSidebar = this.shrinkSidebar.bind(this);
|
this.shrinkSidebar = this.shrinkSidebar.bind(this);
|
||||||
this.unflagPost = this.unflagPost.bind(this);
|
this.unflagPost = this.unflagPost.bind(this);
|
||||||
|
this.flagPost = this.flagPost.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
hideSidebar() {
|
hideSidebar() {
|
||||||
@@ -47,11 +48,14 @@ export default class SearchResultsItem extends React.Component {
|
|||||||
GlobalActions.emitPostFocusRightHandSideFromSearch(this.props.post, this.props.isMentionSearch);
|
GlobalActions.emitPostFocusRightHandSideFromSearch(this.props.post, this.props.isMentionSearch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flagPost(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
flagPost(this.props.post.id);
|
||||||
|
}
|
||||||
|
|
||||||
unflagPost(e) {
|
unflagPost(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
unflagPost(this.props.post.id,
|
unflagPost(this.props.post.id);
|
||||||
() => getFlaggedPosts()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@@ -110,6 +114,7 @@ export default class SearchResultsItem extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let flag;
|
let flag;
|
||||||
|
let flagFunc;
|
||||||
let flagVisible = '';
|
let flagVisible = '';
|
||||||
let flagTooltip = (
|
let flagTooltip = (
|
||||||
<Tooltip id='flagTooltip'>
|
<Tooltip id='flagTooltip'>
|
||||||
@@ -129,24 +134,21 @@ export default class SearchResultsItem extends React.Component {
|
|||||||
/>
|
/>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
);
|
);
|
||||||
|
flagFunc = this.unflagPost;
|
||||||
flag = (
|
flag = (
|
||||||
<OverlayTrigger
|
|
||||||
delayShow={Constants.OVERLAY_TIME_DELAY}
|
|
||||||
placement='top'
|
|
||||||
overlay={flagTooltip}
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
href='#'
|
|
||||||
className={'flag-icon__container ' + flagVisible}
|
|
||||||
onClick={this.unflagPost}
|
|
||||||
>
|
|
||||||
<span
|
<span
|
||||||
className='icon'
|
className='icon'
|
||||||
dangerouslySetInnerHTML={{__html: flagIcon}}
|
dangerouslySetInnerHTML={{__html: flagIcon}}
|
||||||
/>
|
/>
|
||||||
</a>
|
|
||||||
</OverlayTrigger>
|
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
flag = (
|
||||||
|
<span
|
||||||
|
className='icon'
|
||||||
|
dangerouslySetInnerHTML={{__html: flagIcon}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
flagFunc = this.flagPost;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -187,7 +189,19 @@ export default class SearchResultsItem extends React.Component {
|
|||||||
minute='2-digit'
|
minute='2-digit'
|
||||||
/>
|
/>
|
||||||
</time>
|
</time>
|
||||||
|
<OverlayTrigger
|
||||||
|
delayShow={Constants.OVERLAY_TIME_DELAY}
|
||||||
|
placement='top'
|
||||||
|
overlay={flagTooltip}
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href='#'
|
||||||
|
className={'flag-icon__container ' + flagVisible}
|
||||||
|
onClick={flagFunc}
|
||||||
|
>
|
||||||
{flag}
|
{flag}
|
||||||
|
</a>
|
||||||
|
</OverlayTrigger>
|
||||||
</li>
|
</li>
|
||||||
<li className='col__controls'>
|
<li className='col__controls'>
|
||||||
<a
|
<a
|
||||||
@@ -256,6 +270,7 @@ SearchResultsItem.propTypes = {
|
|||||||
channel: React.PropTypes.object,
|
channel: React.PropTypes.object,
|
||||||
compactDisplay: React.PropTypes.bool,
|
compactDisplay: React.PropTypes.bool,
|
||||||
isMentionSearch: React.PropTypes.bool,
|
isMentionSearch: React.PropTypes.bool,
|
||||||
|
isFlaggedSearch: React.PropTypes.bool,
|
||||||
term: React.PropTypes.string,
|
term: React.PropTypes.string,
|
||||||
useMilitaryTime: React.PropTypes.bool.isRequired,
|
useMilitaryTime: React.PropTypes.bool.isRequired,
|
||||||
shrink: React.PropTypes.function,
|
shrink: React.PropTypes.function,
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user