diff options
Diffstat (limited to 'web/react/components')
-rw-r--r-- | web/react/components/access_history_modal.jsx | 2 | ||||
-rw-r--r-- | web/react/components/activity_log_modal.jsx | 2 | ||||
-rw-r--r-- | web/react/components/center_panel.jsx | 3 | ||||
-rw-r--r-- | web/react/components/invite_member_modal.jsx | 2 | ||||
-rw-r--r-- | web/react/components/more_direct_channels.jsx | 2 | ||||
-rw-r--r-- | web/react/components/post.jsx | 9 | ||||
-rw-r--r-- | web/react/components/post_header.jsx | 12 | ||||
-rw-r--r-- | web/react/components/post_info.jsx | 81 | ||||
-rw-r--r-- | web/react/components/posts_view.jsx | 8 | ||||
-rw-r--r-- | web/react/components/rhs_root_post.jsx | 20 | ||||
-rw-r--r-- | web/react/components/search_results_item.jsx | 2 | ||||
-rw-r--r-- | web/react/components/suggestion/suggestion_box.jsx | 2 | ||||
-rw-r--r-- | web/react/components/team_members_modal.jsx | 2 | ||||
-rw-r--r-- | web/react/components/user_profile.jsx | 9 | ||||
-rw-r--r-- | web/react/components/user_settings/user_settings_modal.jsx | 2 |
15 files changed, 114 insertions, 44 deletions
diff --git a/web/react/components/access_history_modal.jsx b/web/react/components/access_history_modal.jsx index 165d32339..deef92a54 100644 --- a/web/react/components/access_history_modal.jsx +++ b/web/react/components/access_history_modal.jsx @@ -32,7 +32,7 @@ export default class AccessHistoryModal extends React.Component { onShow() { AsyncClient.getAudits(); - $(ReactDOM.findDOMNode(this.refs.modalBody)).css('max-height', $(window).height() - 300); + $(ReactDOM.findDOMNode(this.refs.modalBody)).css('max-height', $(window).height() - 50); if ($(window).width() > 768) { $(ReactDOM.findDOMNode(this.refs.modalBody)).perfectScrollbar(); } diff --git a/web/react/components/activity_log_modal.jsx b/web/react/components/activity_log_modal.jsx index 869d648d2..200f4d724 100644 --- a/web/react/components/activity_log_modal.jsx +++ b/web/react/components/activity_log_modal.jsx @@ -51,7 +51,7 @@ export default class ActivityLogModal extends React.Component { onShow() { AsyncClient.getSessions(); - $(ReactDOM.findDOMNode(this.refs.modalBody)).css('max-height', $(window).height() - 300); + $(ReactDOM.findDOMNode(this.refs.modalBody)).css('max-height', $(window).height() - 50); if ($(window).width() > 768) { $(ReactDOM.findDOMNode(this.refs.modalBody)).perfectScrollbar(); } diff --git a/web/react/components/center_panel.jsx b/web/react/components/center_panel.jsx index 848e8952e..a1043431d 100644 --- a/web/react/components/center_panel.jsx +++ b/web/react/components/center_panel.jsx @@ -71,7 +71,8 @@ export default class CenterPanel extends React.Component { href='' onClick={handleClick} > - {'You are viewing the Archives. Click here to jump to recent messages.'} + {'You are viewing the Archives. Click here to jump to recent messages. '} + {<i className='fa fa-arrow-down'></i>} </a> </div> ); diff --git a/web/react/components/invite_member_modal.jsx b/web/react/components/invite_member_modal.jsx index 76f52faa9..25a915e22 100644 --- a/web/react/components/invite_member_modal.jsx +++ b/web/react/components/invite_member_modal.jsx @@ -143,7 +143,7 @@ export default class InviteMemberModal extends React.Component { componentDidUpdate(prevProps, prevState) { if (!prevState.show && this.state.show) { - $(ReactDOM.findDOMNode(this.refs.modalBody)).css('max-height', $(window).height() - 300); + $(ReactDOM.findDOMNode(this.refs.modalBody)).css('max-height', $(window).height() - 50); if ($(window).width() > 768) { $(ReactDOM.findDOMNode(this.refs.modalBody)).perfectScrollbar(); } diff --git a/web/react/components/more_direct_channels.jsx b/web/react/components/more_direct_channels.jsx index 9116dc8f1..cf40af6ae 100644 --- a/web/react/components/more_direct_channels.jsx +++ b/web/react/components/more_direct_channels.jsx @@ -166,7 +166,7 @@ export default class MoreDirectChannels extends React.Component { componentDidUpdate(prevProps) { if (!prevProps.show && this.props.show) { - $(ReactDOM.findDOMNode(this.refs.userList)).css('max-height', $(window).height() - 300); + $(ReactDOM.findDOMNode(this.refs.userList)).css('max-height', $(window).height() - 50); if ($(window).width() > 768) { $(ReactDOM.findDOMNode(this.refs.userList)).perfectScrollbar(); } diff --git a/web/react/components/post.jsx b/web/react/components/post.jsx index b32656bfc..786a4a325 100644 --- a/web/react/components/post.jsx +++ b/web/react/components/post.jsx @@ -173,6 +173,11 @@ export default class Post extends React.Component { shouldHighlightClass = 'post--highlight'; } + let systemMessageClass = ''; + if (utils.isSystemMessage(post)) { + systemMessageClass = 'post--system'; + } + let profilePic = null; if (!this.props.hideProfilePic) { let src = '/api/v1/users/' + post.user_id + '/image?time=' + timestamp + '&' + utils.getSessionIndex(); @@ -180,6 +185,8 @@ export default class Post extends React.Component { if (post.props.override_icon_url) { src = post.props.override_icon_url; } + } else if (utils.isSystemMessage(post)) { + src = Constants.SYSTEM_MESSAGE_PROFILE_IMAGE; } profilePic = ( @@ -195,7 +202,7 @@ export default class Post extends React.Component { <div> <div id={'post_' + post.id} - className={'post ' + sameUserClass + ' ' + rootUser + ' ' + postType + ' ' + currentUserCss + ' ' + shouldHighlightClass} + className={'post ' + sameUserClass + ' ' + rootUser + ' ' + postType + ' ' + currentUserCss + ' ' + shouldHighlightClass + ' ' + systemMessageClass} > <div className='post__content'> <div className='post__img'>{profilePic}</div> diff --git a/web/react/components/post_header.jsx b/web/react/components/post_header.jsx index ffc32f82c..76b3a64be 100644 --- a/web/react/components/post_header.jsx +++ b/web/react/components/post_header.jsx @@ -3,6 +3,9 @@ import UserProfile from './user_profile.jsx'; import PostInfo from './post_info.jsx'; +import * as Utils from '../utils/utils.jsx'; + +import Constants from '../utils/constants.jsx'; export default class PostHeader extends React.Component { constructor(props) { @@ -27,6 +30,15 @@ export default class PostHeader extends React.Component { } botIndicator = <li className='col col__name bot-indicator'>{'BOT'}</li>; + } else if (Utils.isSystemMessage(post)) { + userProfile = ( + <UserProfile + userId={''} + overwriteName={''} + overwriteImage={Constants.SYSTEM_MESSAGE_PROFILE_IMAGE} + disablePopover={true} + /> + ); } return ( diff --git a/web/react/components/post_info.jsx b/web/react/components/post_info.jsx index cedb2b59b..0b8b07d8c 100644 --- a/web/react/components/post_info.jsx +++ b/web/react/components/post_info.jsx @@ -9,14 +9,15 @@ import * as EventHelpers from '../dispatcher/event_helpers.jsx'; import Constants from '../utils/constants.jsx'; -const OverlayTrigger = ReactBootstrap.OverlayTrigger; +const Overlay = ReactBootstrap.Overlay; const Popover = ReactBootstrap.Popover; export default class PostInfo extends React.Component { constructor(props) { super(props); this.state = { - copiedLink: false + copiedLink: false, + show: false }; this.handlePermalinkCopy = this.handlePermalinkCopy.bind(this); @@ -41,30 +42,37 @@ export default class PostInfo extends React.Component { dataComments = this.props.commentCount; } - if (isOwner) { + if (this.props.allowReply === 'true') { dropdownContents.push( <li - key='editPost' + key='replyLink' role='presentation' > <a + className='link__reply theme' href='#' - role='menuitem' - data-toggle='modal' - data-target='#edit_post' - data-refocusid='#post_textbox' - data-title={type} - data-message={post.message} - data-postid={post.id} - data-channelid={post.channel_id} - data-comments={dataComments} + onClick={this.props.handleCommentClick} > - {'Edit'} + {'Reply'} </a> </li> ); } + dropdownContents.push( + <li + key='copyLink' + role='presentation' + > + <a + href='#' + onClick={(e) => this.setState({target: e.target, show: !this.state.show})} + > + {'Permalink'} + </a> + </li> + ); + if (isOwner || isAdmin) { dropdownContents.push( <li @@ -82,18 +90,25 @@ export default class PostInfo extends React.Component { ); } - if (this.props.allowReply === 'true') { + if (isOwner) { dropdownContents.push( <li - key='replyLink' + key='editPost' role='presentation' > <a - className='link__reply theme' href='#' - onClick={this.props.handleCommentClick} + role='menuitem' + data-toggle='modal' + data-target='#edit_post' + data-refocusid='#post_textbox' + data-title={type} + data-message={post.message} + data-postid={post.id} + data-channelid={post.channel_id} + data-comments={dataComments} > - {'Reply'} + {'Edit'} </a> </li> ); @@ -121,6 +136,7 @@ export default class PostInfo extends React.Component { </div> ); } + handlePermalinkCopy() { const textBox = $(ReactDOM.findDOMNode(this.refs.permalinkbox)); textBox.select(); @@ -128,7 +144,7 @@ export default class PostInfo extends React.Component { try { const successful = document.execCommand('copy'); if (successful) { - this.setState({copiedLink: true}); + this.setState({copiedLink: true, show: false}); } else { this.setState({copiedLink: false}); } @@ -197,6 +213,8 @@ export default class PostInfo extends React.Component { </Popover> ); + const containerPadding = 20; + return ( <ul className='post__header post__header--info'> <li className='col'> @@ -206,18 +224,23 @@ export default class PostInfo extends React.Component { </li> <li className='col col__reply'> {comments} - <OverlayTrigger - trigger='click' - placement='left' - rootClose={true} - overlay={permalinkOverlay} + <div + className='dropdown' + ref='dotMenu' > - <i className={'permalink-icon fa fa-link ' + showCommentClass}/> - </OverlayTrigger> - - <div className='dropdown'> {dropdown} </div> + <Overlay + show={this.state.show} + target={() => ReactDOM.findDOMNode(this.refs.dotMenu)} + onHide={() => this.setState({show: false})} + placement='left' + container={this} + containerPadding={containerPadding} + rootClose={true} + > + {permalinkOverlay} + </Overlay> </li> </ul> ); diff --git a/web/react/components/posts_view.jsx b/web/react/components/posts_view.jsx index d0eee5a23..740ce04f6 100644 --- a/web/react/components/posts_view.jsx +++ b/web/react/components/posts_view.jsx @@ -87,6 +87,7 @@ export default class PostsView extends React.Component { const post = posts[order[i]]; const parentPost = posts[post.parent_id]; const prevPost = posts[order[i + 1]]; + const postUserId = Utils.isSystemMessage(post) ? '' : post.user_id; // If the post is a comment whose parent has been deleted, don't add it to the list. if (parentPost && parentPost.state === Constants.POST_DELETED) { @@ -102,6 +103,7 @@ export default class PostsView extends React.Component { const prevPostIsComment = Utils.isComment(prevPost); const postFromWebhook = Boolean(post.props && post.props.from_webhook); const prevPostFromWebhook = Boolean(prevPost.props && prevPost.props.from_webhook); + const prevPostUserId = Utils.isSystemMessage(prevPost) ? '' : prevPostUserId; let prevWebhookName = ''; if (prevPost.props && prevPost.props.override_username) { prevWebhookName = prevPost.props.override_username; @@ -116,7 +118,7 @@ export default class PostsView extends React.Component { // the previous post was made within 5 minutes of the current post, // the previous post and current post are both from webhooks or both not, // the previous post and current post have the same webhook usernames - if (prevPost.user_id === post.user_id && + if (prevPostUserId === postUserId && post.create_at - prevPost.create_at <= 1000 * 60 * 5 && postFromWebhook === prevPostFromWebhook && prevWebhookName === curWebhookName) { @@ -144,7 +146,7 @@ export default class PostsView extends React.Component { // the current post is not a comment, // the previous post and current post are both from webhooks or both not, // the previous post and current post have the same webhook usernames - if (prevPost.user_id === post.user_id && + if (prevPostUserId === postUserId && !prevPostIsComment && !postIsComment && postFromWebhook === prevPostFromWebhook && @@ -191,7 +193,7 @@ export default class PostsView extends React.Component { ); } - if (post.user_id !== userId && + if (postUserId !== userId && this.props.messageSeparatorTime !== 0 && post.create_at > this.props.messageSeparatorTime && !renderedLastViewed) { diff --git a/web/react/components/rhs_root_post.jsx b/web/react/components/rhs_root_post.jsx index 0dd969ad0..0a37a6803 100644 --- a/web/react/components/rhs_root_post.jsx +++ b/web/react/components/rhs_root_post.jsx @@ -12,6 +12,8 @@ import twemoji from 'twemoji'; import PostBodyAdditionalContent from './post_body_additional_content.jsx'; import * as EventHelpers from '../dispatcher/event_helpers.jsx'; +import Constants from '../utils/constants.jsx'; + export default class RhsRootPost extends React.Component { constructor(props) { super(props); @@ -58,6 +60,11 @@ export default class RhsRootPost extends React.Component { currentUserCss = 'current--user'; } + var systemMessageClass = ''; + if (utils.isSystemMessage(post)) { + systemMessageClass = 'post--system'; + } + var channelName; if (channel) { if (channel.type === 'D') { @@ -156,6 +163,15 @@ export default class RhsRootPost extends React.Component { } botIndicator = <li className='col col__name bot-indicator'>{'BOT'}</li>; + } else if (utils.isSystemMessage(post)) { + userProfile = ( + <UserProfile + userId={''} + overwriteName={''} + overwriteImage={Constants.SYSTEM_MESSAGE_PROFILE_IMAGE} + disablePopover={true} + /> + ); } let src = '/api/v1/users/' + post.user_id + '/image?time=' + timestamp + '&' + utils.getSessionIndex(); @@ -163,6 +179,8 @@ export default class RhsRootPost extends React.Component { if (post.props.override_icon_url) { src = post.props.override_icon_url; } + } else if (utils.isSystemMessage(post)) { + src = Constants.SYSTEM_MESSAGE_PROFILE_IMAGE; } const profilePic = ( @@ -175,7 +193,7 @@ export default class RhsRootPost extends React.Component { ); return ( - <div className={'post post--root ' + currentUserCss}> + <div className={'post post--root ' + currentUserCss + ' ' + systemMessageClass}> <div className='post-right-channel__name'>{channelName}</div> <div className='post__content'> <div className='post__img'> diff --git a/web/react/components/search_results_item.jsx b/web/react/components/search_results_item.jsx index 6e17cfe32..1d4983026 100644 --- a/web/react/components/search_results_item.jsx +++ b/web/react/components/search_results_item.jsx @@ -65,7 +65,7 @@ export default class SearchResultsItem extends React.Component { className='search-item__jump' onClick={this.handleClick} > - {'[Jump]'} + {<i className='fa fa-mail-reply'></i>} </a> </li> </ul> diff --git a/web/react/components/suggestion/suggestion_box.jsx b/web/react/components/suggestion/suggestion_box.jsx index 4cfb38f8e..ad8ad1e9e 100644 --- a/web/react/components/suggestion/suggestion_box.jsx +++ b/web/react/components/suggestion/suggestion_box.jsx @@ -94,7 +94,7 @@ export default class SuggestionBox extends React.Component { } else if (e.which === KeyCodes.DOWN) { EventHelpers.emitSelectNextSuggestion(this.suggestionId); e.preventDefault(); - } else if (e.which === KeyCodes.ENTER || (e.which === KeyCodes.SPACE && SuggestionStore.shouldCompleteOnSpace(this.suggestionId))) { + } else if (e.which === KeyCodes.ENTER || e.which === KeyCodes.TAB || (e.which === KeyCodes.SPACE && SuggestionStore.shouldCompleteOnSpace(this.suggestionId))) { EventHelpers.emitCompleteWordSuggestion(this.suggestionId); e.preventDefault(); } else if (this.props.onKeyDown) { diff --git a/web/react/components/team_members_modal.jsx b/web/react/components/team_members_modal.jsx index 0a30a2202..eed4a1f19 100644 --- a/web/react/components/team_members_modal.jsx +++ b/web/react/components/team_members_modal.jsx @@ -26,7 +26,7 @@ export default class TeamMembersModal extends React.Component { } onShow() { - $(ReactDOM.findDOMNode(this.refs.modalBody)).css('max-height', $(window).height() - 300); + $(ReactDOM.findDOMNode(this.refs.modalBody)).css('max-height', $(window).height() - 50); if ($(window).width() > 768) { $(ReactDOM.findDOMNode(this.refs.modalBody)).perfectScrollbar(); } diff --git a/web/react/components/user_profile.jsx b/web/react/components/user_profile.jsx index ea104fedb..385cd0f52 100644 --- a/web/react/components/user_profile.jsx +++ b/web/react/components/user_profile.jsx @@ -65,11 +65,16 @@ export default class UserProfile extends React.Component { return <div>{name}</div>; } + var profileImg = '/api/v1/users/' + this.state.profile.id + '/image?time=' + this.state.profile.update_at + '&' + Utils.getSessionIndex(); + if (this.props.overwriteImage) { + profileImg = this.props.overwriteImage; + } + var dataContent = []; dataContent.push( <img className='user-popover__image' - src={'/api/v1/users/' + this.state.profile.id + '/image?time=' + this.state.profile.update_at + '&' + Utils.getSessionIndex()} + src={profileImg} height='128' width='128' key='user-popover-image' @@ -130,10 +135,12 @@ export default class UserProfile extends React.Component { UserProfile.defaultProps = { userId: '', overwriteName: '', + overwriteImage: '', disablePopover: false }; UserProfile.propTypes = { userId: React.PropTypes.string, overwriteName: React.PropTypes.string, + overwriteImage: React.PropTypes.string, disablePopover: React.PropTypes.bool }; diff --git a/web/react/components/user_settings/user_settings_modal.jsx b/web/react/components/user_settings/user_settings_modal.jsx index f9d03f56d..97c601b5e 100644 --- a/web/react/components/user_settings/user_settings_modal.jsx +++ b/web/react/components/user_settings/user_settings_modal.jsx @@ -47,7 +47,7 @@ export default class UserSettingsModal extends React.Component { } handleShow() { - $(ReactDOM.findDOMNode(this.refs.modalBody)).css('max-height', $(window).height() - 300); + $(ReactDOM.findDOMNode(this.refs.modalBody)).css('max-height', $(window).height() - 50); if ($(window).width() > 768) { $(ReactDOM.findDOMNode(this.refs.modalBody)).perfectScrollbar(); } |