summaryrefslogtreecommitdiffstats
path: root/webapp
diff options
context:
space:
mode:
authorSaturnino Abril <saturnino.abril@gmail.com>2017-08-03 14:29:31 +0800
committerGitHub <noreply@github.com>2017-08-03 14:29:31 +0800
commitf3934bc7e1e8ef555e1c2e1fe0ece3dbd88ea687 (patch)
tree8555be93795821a35dfe64ec6c8e749d235bbd4d /webapp
parent345bb2236f1f34c2b1ddfec0024ea47c4b1b8950 (diff)
downloadchat-f3934bc7e1e8ef555e1c2e1fe0ece3dbd88ea687.tar.gz
chat-f3934bc7e1e8ef555e1c2e1fe0ece3dbd88ea687.tar.bz2
chat-f3934bc7e1e8ef555e1c2e1fe0ece3dbd88ea687.zip
[PLT-1249] Add close button 'x' to the right of a link preview (#7017)
* add close button 'x' to the right of a link preview * Updating webhook UI * UI improvements for close button * Adding hover state * Making the close button visible on mobile * previews are permanently disabled/closed for that link * make post as required props * fix JS error of undefined * fix update issue both at center and RHS view
Diffstat (limited to 'webapp')
-rw-r--r--webapp/components/post_view/post_attachment_opengraph/index.js4
-rw-r--r--webapp/components/post_view/post_attachment_opengraph/post_attachment_opengraph.jsx73
-rw-r--r--webapp/components/post_view/post_body_additional_content.jsx1
-rw-r--r--webapp/sass/layout/_webhooks.scss49
-rw-r--r--webapp/sass/responsive/_mobile.scss10
-rw-r--r--webapp/utils/constants.jsx3
-rw-r--r--webapp/utils/utils.jsx2
7 files changed, 132 insertions, 10 deletions
diff --git a/webapp/components/post_view/post_attachment_opengraph/index.js b/webapp/components/post_view/post_attachment_opengraph/index.js
index e0bec8f36..1f889f1d6 100644
--- a/webapp/components/post_view/post_attachment_opengraph/index.js
+++ b/webapp/components/post_view/post_attachment_opengraph/index.js
@@ -2,6 +2,7 @@
// See License.txt for license information.
import {connect} from 'react-redux';
+import {getCurrentUser} from 'mattermost-redux/selectors/entities/users';
import {bindActionCreators} from 'redux';
import {getOpenGraphMetadata} from 'mattermost-redux/actions/posts';
import {getOpenGraphMetadataForUrl} from 'mattermost-redux/selectors/entities/posts';
@@ -11,7 +12,8 @@ import PostAttachmentOpenGraph from './post_attachment_opengraph.jsx';
function mapStateToProps(state, ownProps) {
return {
...ownProps,
- openGraphData: getOpenGraphMetadataForUrl(state, ownProps.link)
+ openGraphData: getOpenGraphMetadataForUrl(state, ownProps.link),
+ currentUser: getCurrentUser(state),
};
}
diff --git a/webapp/components/post_view/post_attachment_opengraph/post_attachment_opengraph.jsx b/webapp/components/post_view/post_attachment_opengraph/post_attachment_opengraph.jsx
index 743d7a22a..04738fdcc 100644
--- a/webapp/components/post_view/post_attachment_opengraph/post_attachment_opengraph.jsx
+++ b/webapp/components/post_view/post_attachment_opengraph/post_attachment_opengraph.jsx
@@ -5,9 +5,11 @@ import React from 'react';
import PropTypes from 'prop-types';
import {postListScrollChange} from 'actions/global_actions.jsx';
+import {updatePost} from 'actions/post_actions.jsx';
import * as Utils from 'utils/utils.jsx';
import * as CommonUtils from 'utils/commons.jsx';
+import {PostTypes} from 'utils/constants.jsx';
export default class PostAttachmentOpenGraph extends React.PureComponent {
static propTypes = {
@@ -18,6 +20,16 @@ export default class PostAttachmentOpenGraph extends React.PureComponent {
link: PropTypes.string.isRequired,
/**
+ * The current user viewing the post
+ */
+ currentUser: PropTypes.object,
+
+ /**
+ * The post where this link is included
+ */
+ post: PropTypes.object,
+
+ /**
* The open graph data to render
*/
openGraphData: PropTypes.object,
@@ -62,18 +74,28 @@ export default class PostAttachmentOpenGraph extends React.PureComponent {
this.toggleImageVisibility = this.toggleImageVisibility.bind(this);
this.onImageLoad = this.onImageLoad.bind(this);
this.onImageError = this.onImageError.bind(this);
+ this.handleRemovePreview = this.handleRemovePreview.bind(this);
}
componentWillMount() {
+ const removePreview = this.isRemovePreview(this.props.post, this.props.currentUser);
+
this.setState({
imageLoaded: this.IMAGE_LOADED.LOADING,
imageVisible: this.props.previewCollapsed.startsWith('false'),
- hasLargeImage: false
+ hasLargeImage: false,
+ removePreview
});
this.fetchData(this.props.link);
}
componentWillReceiveProps(nextProps) {
+ if (!Utils.areObjectsEqual(nextProps.post, this.props.post)) {
+ const removePreview = this.isRemovePreview(nextProps.post, nextProps.currentUser);
+ this.setState({
+ removePreview
+ });
+ }
if (nextProps.link !== this.props.link) {
this.fetchData(nextProps.link);
}
@@ -94,12 +116,12 @@ export default class PostAttachmentOpenGraph extends React.PureComponent {
}
}
- getBestImageUrl() {
- if (Utils.isEmptyObject(this.props.openGraphData.images)) {
+ getBestImageUrl(data) {
+ if (Utils.isEmptyObject(data.images)) {
return null;
}
- const bestImage = CommonUtils.getNearestPoint(this.imageDimentions, this.props.openGraphData.images, 'width', 'height');
+ const bestImage = CommonUtils.getNearestPoint(this.imageDimentions, data.images, 'width', 'height');
return bestImage.secure_url || bestImage.url;
}
@@ -208,14 +230,50 @@ export default class PostAttachmentOpenGraph extends React.PureComponent {
return text;
}
+ handleRemovePreview() {
+ const props = Object.assign({}, this.props.post.props);
+ props[PostTypes.REMOVE_LINK_PREVIEW] = 'true';
+
+ const patchedPost = ({
+ id: this.props.post.id,
+ props
+ });
+
+ updatePost(patchedPost, () => {
+ this.setState({removePreview: true});
+ });
+ }
+
+ isRemovePreview(post, currentUser) {
+ if (post && post.props && currentUser.id === post.user_id) {
+ return post.props[PostTypes.REMOVE_LINK_PREVIEW] && post.props[PostTypes.REMOVE_LINK_PREVIEW] === 'true';
+ }
+
+ return false;
+ }
+
render() {
- if (!this.props.openGraphData || Utils.isEmptyObject(this.props.openGraphData.description)) {
+ const data = this.props.openGraphData;
+ if (!data || Utils.isEmptyObject(data.description) || this.state.removePreview) {
return null;
}
- const data = this.props.openGraphData;
- const imageUrl = this.getBestImageUrl();
+ let removePreviewButton;
+ if (this.props.currentUser.id === this.props.post.user_id) {
+ removePreviewButton = (
+ <button
+ id='removePreviewButton'
+ type='button'
+ className='btn-close'
+ aria-label='Close'
+ onClick={this.handleRemovePreview}
+ >
+ <span aria-hidden='true'>{'×'}</span>
+ </button>
+ );
+ }
+ const imageUrl = this.getBestImageUrl(data);
if (imageUrl) {
this.loadImage(imageUrl);
}
@@ -233,6 +291,7 @@ export default class PostAttachmentOpenGraph extends React.PureComponent {
className={'attachment__body__wrap attachment__body__wrap--opengraph'}
>
<span className='sitename'>{this.truncateText(data.site_name)}</span>
+ {removePreviewButton}
<h1
className={'attachment__title attachment__title--opengraph' + (data.title ? '' : ' is-url')}
>
diff --git a/webapp/components/post_view/post_body_additional_content.jsx b/webapp/components/post_view/post_body_additional_content.jsx
index be9e37827..1d900018a 100644
--- a/webapp/components/post_view/post_body_additional_content.jsx
+++ b/webapp/components/post_view/post_body_additional_content.jsx
@@ -162,6 +162,7 @@ export default class PostBodyAdditionalContent extends React.PureComponent {
<PostAttachmentOpenGraph
link={link}
previewCollapsed={this.props.previewCollapsed}
+ post={this.props.post}
/>
);
}
diff --git a/webapp/sass/layout/_webhooks.scss b/webapp/sass/layout/_webhooks.scss
index 6f6ab0c90..edb4cbd93 100644
--- a/webapp/sass/layout/_webhooks.scss
+++ b/webapp/sass/layout/_webhooks.scss
@@ -38,6 +38,17 @@
.post {
.attachment {
+ margin-left: -20px;
+ position: relative;
+
+ &:hover {
+ .attachment__body__wrap {
+ .btn-close {
+ visibility: visible;
+ }
+ }
+ }
+
&.attachment--opengraph {
max-width: 800px;
}
@@ -46,7 +57,7 @@
border-radius: 4px;
border-style: solid;
border-width: 1px;
- margin: 5px 0;
+ margin: 5px 0 5px 20px;
padding: 2px 5px;
}
@@ -99,6 +110,42 @@
vertical-align: top;
width: 100%;
}
+
+ .btn-close {
+ @include opacity(.4);
+ background: transparent;
+ border: none;
+ color: inherit;
+ font-size: 21px;
+ font-weight: 500;
+ height: 20px;
+ left: -7px;
+ line-height: 20px;
+ outline: none;
+ padding: 0;
+ position: absolute;
+ text-align: center;
+ text-decoration: none;
+ text-shadow: none;
+ visibility: hidden;
+ width: 20px;
+ z-index: 5;
+
+ span {
+ font-family: 'Open Sans', sans-serif;
+ line-height: 10px;
+ }
+
+ &:hover {
+ @include opacity(.9);
+ }
+ }
+
+ &:hover {
+ .btn-close {
+ visibility: visible;
+ }
+ }
}
.attachment__body {
diff --git a/webapp/sass/responsive/_mobile.scss b/webapp/sass/responsive/_mobile.scss
index d39797efb..de453f93f 100644
--- a/webapp/sass/responsive/_mobile.scss
+++ b/webapp/sass/responsive/_mobile.scss
@@ -1349,6 +1349,16 @@
.post {
.attachment {
+ .attachment__body__wrap {
+ .btn-close {
+ height: 30px;
+ left: -15px;
+ top: 7px;
+ visibility: visible;
+ width: 30px;
+ }
+ }
+
.attachment__image {
&.attachment__image--openraph {
max-width: 200px;
diff --git a/webapp/utils/constants.jsx b/webapp/utils/constants.jsx
index a36a518d8..e9246fdaf 100644
--- a/webapp/utils/constants.jsx
+++ b/webapp/utils/constants.jsx
@@ -270,7 +270,8 @@ export const PostTypes = {
DISPLAYNAME_CHANGE: 'system_displayname_change',
PURPOSE_CHANGE: 'system_purpose_change',
CHANNEL_DELETED: 'system_channel_deleted',
- EPHEMERAL: 'system_ephemeral'
+ EPHEMERAL: 'system_ephemeral',
+ REMOVE_LINK_PREVIEW: 'remove_link_preview'
};
export const StatTypes = keyMirror({
diff --git a/webapp/utils/utils.jsx b/webapp/utils/utils.jsx
index 94a2cf286..94f6ca91f 100644
--- a/webapp/utils/utils.jsx
+++ b/webapp/utils/utils.jsx
@@ -653,6 +653,8 @@ export function applyTheme(theme) {
changeCss('.app__body .post.post--comment.other--root.current--user .post-comment, .app__body .more-modal__list .more-modal__row, .app__body .member-div:first-child, .app__body .member-div, .app__body .access-history__table .access__report, .app__body .activity-log__table', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.1));
changeCss('@media(max-width: 1800px){.app__body .inner-wrap.move--left .post.post--comment.same--root', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.07));
changeCss('.app__body .post.post--hovered', 'background:' + changeOpacity(theme.centerChannelColor, 0.08));
+ changeCss('.app__body .attachment__body__wrap.btn-close', 'background:' + changeOpacity(theme.centerChannelColor, 0.08));
+ changeCss('.app__body .attachment__body__wrap.btn-close', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2));
changeCss('@media(min-width: 768px){.app__body .post:hover, .app__body .more-modal__list .more-modal__row:hover, .app__body .modal .settings-modal .settings-table .settings-content .section-min:hover', 'background:' + changeOpacity(theme.centerChannelColor, 0.08));
changeCss('.app__body .more-modal__row.more-modal__row--selected, .app__body .date-separator.hovered--before:after, .app__body .date-separator.hovered--after:before, .app__body .new-separator.hovered--after:before, .app__body .new-separator.hovered--before:after', 'background:' + changeOpacity(theme.centerChannelColor, 0.07));
changeCss('@media(min-width: 768px){.app__body .suggestion-list__content .command:hover, .app__body .mentions__name:hover, .app__body .dropdown-menu>li>a:focus, .app__body .dropdown-menu>li>a:hover', 'background:' + changeOpacity(theme.centerChannelColor, 0.15));