Add [...] menu to search results list (#6663)

* Add [...] menu to search results list

* fix updates on search results when post is pinned or edited

* remove app dispatcher from component
This commit is contained in:
Saturnino Abril
2017-07-22 07:02:14 +08:00
committed by Joram Wilander
parent 816bfbeb91
commit 58c6a70d3e
6 changed files with 116 additions and 183 deletions

View File

@@ -326,7 +326,8 @@ export function pinPost(postId) {
await PostActions.pinPost(postId)(doDispatch, doGetState);
AppDispatcher.handleServerAction({
type: ActionTypes.RECEIVED_POST_PINNED
type: ActionTypes.RECEIVED_POST_PINNED,
postId
});
};
}
@@ -336,7 +337,8 @@ export function unpinPost(postId) {
await PostActions.unpinPost(postId)(doDispatch, doGetState);
AppDispatcher.handleServerAction({
type: ActionTypes.RECEIVED_POST_UNPINNED
type: ActionTypes.RECEIVED_POST_UNPINNED,
postId
});
};
}

View File

@@ -261,6 +261,12 @@ function handlePostEditEvent(msg) {
viewChannel(ChannelStore.getCurrentId())(dispatch, getState);
}
}
// Needed for search store
AppDispatcher.handleViewAction({
type: Constants.ActionTypes.POST_UPDATED,
post
});
}
function handlePostDeleteEvent(msg) {

View File

@@ -1,25 +1,20 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
import PostMessageContainer from 'components/post_view/post_message_view';
import UserProfile from './user_profile.jsx';
import FileAttachmentListContainer from 'components/file_attachment_list';
import ProfilePicture from './profile_picture.jsx';
import CommentIcon from 'components/common/comment_icon.jsx';
import DotMenu from 'components/dot_menu';
import PostFlagIcon from 'components/post_view/post_flag_icon.jsx';
import TeamStore from 'stores/team_store.jsx';
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
import * as GlobalActions from 'actions/global_actions.jsx';
import {flagPost, unflagPost} from 'actions/post_actions.jsx';
import PostFlagIcon from 'components/post_view/post_flag_icon.jsx';
import * as Utils from 'utils/utils.jsx';
import * as PostUtils from 'utils/post_utils.jsx';
import Constants from 'utils/constants.jsx';
const ActionTypes = Constants.ActionTypes;
import React from 'react';
import PropTypes from 'prop-types';
@@ -31,17 +26,34 @@ export default class SearchResultsItem extends React.Component {
super(props);
this.handleFocusRHSClick = this.handleFocusRHSClick.bind(this);
this.handleJumpClick = this.handleJumpClick.bind(this);
this.handleDropdownOpened = this.handleDropdownOpened.bind(this);
this.shrinkSidebar = this.shrinkSidebar.bind(this);
this.unflagPost = this.unflagPost.bind(this);
this.flagPost = this.flagPost.bind(this);
this.state = {
currentTeamDisplayName: TeamStore.getCurrent().name,
width: '',
height: ''
height: '',
dropdownOpened: false
};
}
shouldComponentUpdate(nextProps, nextState) {
if (!Utils.areObjectsEqual(nextState.post, this.props.post)) {
return true;
}
if (nextProps.isFlagged !== this.props.isFlagged) {
return true;
}
if (nextState.dropdownOpened !== this.state.dropdownOpened) {
return true;
}
return false;
}
componentDidMount() {
window.addEventListener('resize', () => {
Utils.updateWindowDimensions(this);
@@ -54,10 +66,6 @@ export default class SearchResultsItem extends React.Component {
});
}
hideSidebar() {
$('.sidebar--right').removeClass('move--left');
}
shrinkSidebar() {
setTimeout(() => {
this.props.shrink();
@@ -69,14 +77,19 @@ export default class SearchResultsItem extends React.Component {
GlobalActions.emitPostFocusRightHandSideFromSearch(this.props.post, this.props.isMentionSearch);
}
flagPost(e) {
e.preventDefault();
flagPost(this.props.post.id);
handleJumpClick() {
if (Utils.isMobile()) {
GlobalActions.toggleSideBarAction(false);
}
this.shrinkSidebar();
browserHistory.push(TeamStore.getCurrentTeamRelativeUrl() + '/pl/' + this.props.post.id);
}
unflagPost(e) {
e.preventDefault();
unflagPost(this.props.post.id);
handleDropdownOpened = (isOpened) => {
this.setState({
dropdownOpened: isOpened
});
}
timeTag(post) {
@@ -109,6 +122,20 @@ export default class SearchResultsItem extends React.Component {
);
}
getClassName = () => {
let className = 'post post--thread';
if (this.props.compactDisplay) {
className = ' post--compact';
}
if (this.state.dropdownOpened) {
className += ' post--hovered';
}
return className;
}
render() {
let channelName = null;
const channel = this.props.channel;
@@ -160,11 +187,7 @@ export default class SearchResultsItem extends React.Component {
);
let compactClass = '';
const profilePicContainer = (<div className='post__img'>{profilePic}</div>);
if (this.props.compactDisplay) {
compactClass = ' post--compact';
}
let postClass = '';
if (PostUtils.isEdited(this.props.post)) {
@@ -205,6 +228,13 @@ export default class SearchResultsItem extends React.Component {
rhsControls = (
<div className='col__controls'>
<DotMenu
idPrefix={Constants.SEARCH_POST}
idCount={idCount}
post={post}
isFlagged={this.props.isFlagged}
handleDropdownOpened={this.handleDropdownOpened}
/>
<CommentIcon
idPrefix={'searchCommentIcon'}
idCount={idCount}
@@ -212,32 +242,7 @@ export default class SearchResultsItem extends React.Component {
searchStyle={'search-item__comment'}
/>
<a
onClick={
() => {
if (Utils.isMobile()) {
AppDispatcher.handleServerAction({
type: ActionTypes.RECEIVED_SEARCH,
results: null
});
AppDispatcher.handleServerAction({
type: ActionTypes.RECEIVED_SEARCH_TERM,
term: null,
do_search: false,
is_mention_search: false
});
AppDispatcher.handleServerAction({
type: ActionTypes.RECEIVED_POST_SELECTED,
postId: null
});
this.hideSidebar();
}
this.shrinkSidebar();
browserHistory.push(TeamStore.getCurrentTeamRelativeUrl() + '/pl/' + post.id);
}
}
onClick={this.handleJumpClick}
className='search-item__jump'
>
<FormattedMessage
@@ -284,28 +289,23 @@ export default class SearchResultsItem extends React.Component {
/>
</div>
</div>
<div
className={'post post--thread ' + compactClass}
>
<div
id={idCount === -1 ? null : Utils.createSafeId('searchChannelName' + idCount)}
className='search-channel__name'
>
{channelName}
</div>
<div className={this.getClassName()}>
<div className='search-channel__name'>{channelName}</div>
<div className='post__content'>
{profilePicContainer}
<div>
<div className='post__header'>
<div className='col col__name'><strong>
<UserProfile
user={user}
overwriteName={overrideUsername}
disablePopover={disableProfilePopover}
status={this.props.status}
isBusy={this.props.isBusy}
/>
</strong></div>
<div className='col col__name'>
<strong>
<UserProfile
user={user}
overwriteName={overrideUsername}
disablePopover={disableProfilePopover}
status={this.props.status}
isBusy={this.props.isBusy}
/>
</strong>
</div>
{botIndicator}
<div className='col'>
{this.renderTimeTag(post)}

View File

@@ -120,6 +120,17 @@ class SearchStoreClass extends EventEmitter {
}
}
updatePost(post) {
const results = this.getSearchResults();
if (results == null) {
return;
}
if (post.id in results.posts) {
results.posts[post.id] = Object.assign({}, post);
}
}
togglePinPost(postId, isPinned) {
const results = this.getSearchResults();
if (results == null || results.posts == null) {
@@ -176,12 +187,16 @@ SearchStore.dispatchToken = AppDispatcher.register((payload) => {
SearchStore.deletePost(action.post);
SearchStore.emitSearchChange();
break;
case ActionTypes.POST_UPDATED:
SearchStore.updatePost(action.post);
SearchStore.emitSearchChange();
break;
case ActionTypes.RECEIVED_POST_PINNED:
SearchStore.togglePinPost(action.reaction, true);
SearchStore.togglePinPost(action.postId, true);
SearchStore.emitSearchChange();
break;
case ActionTypes.RECEIVED_POST_UNPINNED:
SearchStore.togglePinPost(action.reaction, false);
SearchStore.togglePinPost(action.postId, false);
SearchStore.emitSearchChange();
break;
case ActionTypes.REMOVE_POST:

View File

@@ -965,7 +965,8 @@ export const Constants = {
SHOW_USERNAME: 'username',
SHOW_NICKNAME_FULLNAME: 'nickname_full_name',
SHOW_FULLNAME: 'full_name'
}
},
SEARCH_POST: 'searchpost'
};
export default Constants;

View File

@@ -111,13 +111,7 @@ ansi-styles@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
ansi-styles@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.0.0.tgz#5404e93a544c4fec7f048262977bebfe3155e0c1"
dependencies:
color-convert "^1.0.0"
ansi-styles@^3.1.0:
ansi-styles@^3.0.0, ansi-styles@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.1.0.tgz#09c202d5c917ec23188caa5c9cb9179cd9547750"
dependencies:
@@ -274,13 +268,7 @@ async@^1.4.0:
version "1.5.2"
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
async@^2.1.2, async@^2.1.4, async@^2.1.5:
version "2.3.0"
resolved "https://registry.yarnpkg.com/async/-/async-2.3.0.tgz#1013d1051047dd320fe24e494d5c66ecaf6147d9"
dependencies:
lodash "^4.14.0"
async@^2.4.1:
async@^2.1.2, async@^2.1.4, async@^2.1.5, async@^2.4.1:
version "2.5.0"
resolved "https://registry.yarnpkg.com/async/-/async-2.5.0.tgz#843190fd6b7357a0b9e1c956edddd5ec8462b54d"
dependencies:
@@ -342,7 +330,7 @@ babel-code-frame@^6.11.0, babel-code-frame@^6.16.0, babel-code-frame@^6.22.0:
esutils "^2.0.2"
js-tokens "^3.0.0"
babel-core@6.25.0:
babel-core@6.25.0, babel-core@^6.0.0, babel-core@^6.24.1:
version "6.25.0"
resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.25.0.tgz#7dd42b0463c742e9d5296deb3ec67a9322dad729"
dependencies:
@@ -366,30 +354,6 @@ babel-core@6.25.0:
slash "^1.0.0"
source-map "^0.5.0"
babel-core@^6.0.0, babel-core@^6.24.1:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.24.1.tgz#8c428564dce1e1f41fb337ec34f4c3b022b5ad83"
dependencies:
babel-code-frame "^6.22.0"
babel-generator "^6.24.1"
babel-helpers "^6.24.1"
babel-messages "^6.23.0"
babel-register "^6.24.1"
babel-runtime "^6.22.0"
babel-template "^6.24.1"
babel-traverse "^6.24.1"
babel-types "^6.24.1"
babylon "^6.11.0"
convert-source-map "^1.1.0"
debug "^2.1.1"
json5 "^0.5.0"
lodash "^4.2.0"
minimatch "^3.0.2"
path-is-absolute "^1.0.0"
private "^0.1.6"
slash "^1.0.0"
source-map "^0.5.0"
babel-eslint@7.1.1:
version "7.1.1"
resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-7.1.1.tgz#8a6a884f085aa7060af69cfc77341c2f99370fb2"
@@ -400,20 +364,7 @@ babel-eslint@7.1.1:
babylon "^6.13.0"
lodash.pickby "^4.6.0"
babel-generator@^6.18.0, babel-generator@^6.24.1:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.24.1.tgz#e715f486c58ded25649d888944d52aa07c5d9497"
dependencies:
babel-messages "^6.23.0"
babel-runtime "^6.22.0"
babel-types "^6.24.1"
detect-indent "^4.0.0"
jsesc "^1.3.0"
lodash "^4.2.0"
source-map "^0.5.0"
trim-right "^1.0.1"
babel-generator@^6.25.0:
babel-generator@^6.18.0, babel-generator@^6.25.0:
version "6.25.0"
resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.25.0.tgz#33a1af70d5f2890aeb465a4a7793c1df6a9ea9fc"
dependencies:
@@ -1071,17 +1022,7 @@ babel-runtime@^6.11.6, babel-runtime@^6.18.0, babel-runtime@^6.22.0:
core-js "^2.4.0"
regenerator-runtime "^0.10.0"
babel-template@^6.16.0, babel-template@^6.24.1:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.24.1.tgz#04ae514f1f93b3a2537f2a0f60a5a45fb8308333"
dependencies:
babel-runtime "^6.22.0"
babel-traverse "^6.24.1"
babel-types "^6.24.1"
babylon "^6.11.0"
lodash "^4.2.0"
babel-template@^6.25.0:
babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.25.0:
version "6.25.0"
resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.25.0.tgz#665241166b7c2aa4c619d71e192969552b10c071"
dependencies:
@@ -1091,21 +1032,7 @@ babel-template@^6.25.0:
babylon "^6.17.2"
lodash "^4.2.0"
babel-traverse@^6.15.0, babel-traverse@^6.18.0, babel-traverse@^6.24.1:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.24.1.tgz#ab36673fd356f9a0948659e7b338d5feadb31695"
dependencies:
babel-code-frame "^6.22.0"
babel-messages "^6.23.0"
babel-runtime "^6.22.0"
babel-types "^6.24.1"
babylon "^6.15.0"
debug "^2.2.0"
globals "^9.0.0"
invariant "^2.2.0"
lodash "^4.2.0"
babel-traverse@^6.25.0:
babel-traverse@^6.15.0, babel-traverse@^6.18.0, babel-traverse@^6.24.1, babel-traverse@^6.25.0:
version "6.25.0"
resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.25.0.tgz#2257497e2fcd19b89edc13c4c91381f9512496f1"
dependencies:
@@ -1119,16 +1046,7 @@ babel-traverse@^6.25.0:
invariant "^2.2.0"
lodash "^4.2.0"
babel-types@^6.15.0, babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24.1:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.24.1.tgz#a136879dc15b3606bda0d90c1fc74304c2ff0975"
dependencies:
babel-runtime "^6.22.0"
esutils "^2.0.2"
lodash "^4.2.0"
to-fast-properties "^1.0.1"
babel-types@^6.25.0:
babel-types@^6.15.0, babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.25.0:
version "6.25.0"
resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.25.0.tgz#70afb248d5660e5d18f811d91c8303b54134a18e"
dependencies:
@@ -1137,11 +1055,7 @@ babel-types@^6.25.0:
lodash "^4.2.0"
to-fast-properties "^1.0.1"
babylon@^6.11.0, babylon@^6.13.0, babylon@^6.15.0:
version "6.17.0"
resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.0.tgz#37da948878488b9c4e3c4038893fa3314b3fc932"
babylon@^6.17.2:
babylon@^6.13.0, babylon@^6.17.2:
version "6.17.4"
resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.4.tgz#3e8b7402b88d22c3423e137a1577883b15ff869a"
@@ -2098,13 +2012,13 @@ debug@2.6.1:
dependencies:
ms "0.7.2"
debug@2.6.7, debug@^2.6.3:
debug@2.6.7:
version "2.6.7"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.7.tgz#92bad1f6d05bbb6bba22cca88bcd0ec894c2861e"
dependencies:
ms "2.0.0"
debug@^2.1.1, debug@^2.2.0:
debug@^2.1.1, debug@^2.2.0, debug@^2.6.3:
version "2.6.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.4.tgz#7586a9b3c39741c0282ae33445c4e8ac74734fe0"
dependencies:
@@ -5095,7 +5009,6 @@ mattermost-redux@mattermost/mattermost-redux#master:
deep-equal "1.0.1"
harmony-reflect "1.5.1"
isomorphic-fetch "2.2.1"
key-mirror "1.0.1"
mime-db "1.27.0"
redux "3.6.0"
redux-action-buffer "1.0.1"
@@ -5488,11 +5401,7 @@ number-is-nan@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
"nwmatcher@>= 1.3.9 < 2.0.0":
version "1.3.9"
resolved "https://registry.yarnpkg.com/nwmatcher/-/nwmatcher-1.3.9.tgz#8bab486ff7fa3dfd086656bbe8b17116d3692d2a"
nwmatcher@^1.4.1:
"nwmatcher@>= 1.3.9 < 2.0.0", nwmatcher@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/nwmatcher/-/nwmatcher-1.4.1.tgz#7ae9b07b0ea804db7e25f05cb5fe4097d4e4949f"
@@ -7656,18 +7565,18 @@ ua-parser-js@^0.7.9:
version "0.7.12"
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.12.tgz#04c81a99bdd5dc52263ea29d24c6bf8d4818a4bb"
uglify-js@^2.6, uglify-js@~2.8.22:
version "2.8.22"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.22.tgz#d54934778a8da14903fa29a326fb24c0ab51a1a0"
uglify-js@^2.6, uglify-js@^2.8.29:
version "2.8.29"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"
dependencies:
source-map "~0.5.1"
yargs "~3.10.0"
optionalDependencies:
uglify-to-browserify "~1.0.0"
uglify-js@^2.8.29:
version "2.8.29"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd"
uglify-js@~2.8.22:
version "2.8.22"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.22.tgz#d54934778a8da14903fa29a326fb24c0ab51a1a0"
dependencies:
source-map "~0.5.1"
yargs "~3.10.0"
@@ -7816,7 +7725,7 @@ utils-merge@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.0.tgz#0294fb922bb9375153541c4f7096231f287c8af8"
uuid@3.0.1, uuid@^3.0.0:
uuid@3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1"
@@ -7824,7 +7733,7 @@ uuid@^2.0.1:
version "2.0.3"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a"
uuid@^3.0.1:
uuid@^3.0.0, uuid@^3.0.1:
version "3.1.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04"