diff options
-rw-r--r-- | webapp/components/pending_post_actions.jsx | 92 | ||||
-rw-r--r-- | webapp/components/post.jsx | 37 | ||||
-rw-r--r-- | webapp/components/post_body.jsx | 18 | ||||
-rw-r--r-- | webapp/components/rhs_comment.jsx | 50 | ||||
-rw-r--r-- | webapp/i18n/en.json | 4 | ||||
-rw-r--r-- | webapp/i18n/es.json | 4 | ||||
-rw-r--r-- | webapp/i18n/fr.json | 4 | ||||
-rw-r--r-- | webapp/i18n/ja.json | 4 | ||||
-rw-r--r-- | webapp/i18n/pt.json | 4 | ||||
-rw-r--r-- | webapp/sass/layout/_post.scss | 15 |
10 files changed, 121 insertions, 111 deletions
diff --git a/webapp/components/pending_post_actions.jsx b/webapp/components/pending_post_actions.jsx new file mode 100644 index 000000000..7528ef207 --- /dev/null +++ b/webapp/components/pending_post_actions.jsx @@ -0,0 +1,92 @@ +// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import PostStore from 'stores/post_store.jsx'; +import ChannelStore from 'stores/channel_store.jsx'; + +import AppDispatcher from '../dispatcher/app_dispatcher.jsx'; + +import Client from 'utils/web_client.jsx'; +import * as AsyncClient from 'utils/async_client.jsx'; + +import Constants from 'utils/constants.jsx'; +const ActionTypes = Constants.ActionTypes; + +import {FormattedMessage} from 'react-intl'; + +import React from 'react'; + +export default class PendingPostActions extends React.Component { + constructor(props) { + super(props); + this.retryPost = this.retryPost.bind(this); + this.cancelPost = this.cancelPost.bind(this); + this.state = {}; + } + retryPost(e) { + e.preventDefault(); + + var post = this.props.post; + Client.createPost(post, + (data) => { + AsyncClient.getPosts(post.channel_id); + + var channel = ChannelStore.get(post.channel_id); + var member = ChannelStore.getMember(post.channel_id); + member.msg_count = channel.total_msg_count; + member.last_viewed_at = (new Date()).getTime(); + ChannelStore.setChannelMember(member); + + AppDispatcher.handleServerAction({ + type: ActionTypes.RECEIVED_POST, + post: data + }); + }, + () => { + post.state = Constants.POST_FAILED; + PostStore.updatePendingPost(post); + this.forceUpdate(); + } + ); + + post.state = Constants.POST_LOADING; + PostStore.updatePendingPost(post); + this.forceUpdate(); + } + cancelPost(e) { + e.preventDefault(); + + var post = this.props.post; + PostStore.removePendingPost(post.channel_id, post.pending_post_id); + this.forceUpdate(); + } + render() { + return (<span className='pending-post-actions'> + <a + className='post-retry' + href='#' + onClick={this.retryPost} + > + <FormattedMessage + id='pending_post_actions.retry' + defaultMessage='Retry' + /> + </a> + {' - '} + <a + className='post-cancel' + href='#' + onClick={this.cancelPost} + > + <FormattedMessage + id='pending_post_actions.cancel' + defaultMessage='Cancel' + /> + </a> + </span>); + } +} + +PendingPostActions.propTypes = { + post: React.PropTypes.object +}; diff --git a/webapp/components/post.jsx b/webapp/components/post.jsx index 084fb9171..2b28d442c 100644 --- a/webapp/components/post.jsx +++ b/webapp/components/post.jsx @@ -4,14 +4,9 @@ import PostHeader from './post_header.jsx'; import PostBody from './post_body.jsx'; -import PostStore from 'stores/post_store.jsx'; -import ChannelStore from 'stores/channel_store.jsx'; - import Constants from 'utils/constants.jsx'; const ActionTypes = Constants.ActionTypes; -import Client from 'utils/web_client.jsx'; -import * as AsyncClient from 'utils/async_client.jsx'; import * as Utils from 'utils/utils.jsx'; import AppDispatcher from '../dispatcher/app_dispatcher.jsx'; @@ -23,7 +18,6 @@ export default class Post extends React.Component { this.handleCommentClick = this.handleCommentClick.bind(this); this.forceUpdateInfo = this.forceUpdateInfo.bind(this); - this.retryPost = this.retryPost.bind(this); this.state = {}; } @@ -44,36 +38,6 @@ export default class Post extends React.Component { this.refs.info.forceUpdate(); this.refs.header.forceUpdate(); } - retryPost(e) { - e.preventDefault(); - - var post = this.props.post; - Client.createPost(post, - (data) => { - AsyncClient.getPosts(); - - var channel = ChannelStore.get(post.channel_id); - var member = ChannelStore.getMember(post.channel_id); - member.msg_count = channel.total_msg_count; - member.last_viewed_at = Utils.getTimestamp(); - ChannelStore.setChannelMember(member); - - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_POST, - post: data - }); - }, - () => { - post.state = Constants.POST_FAILED; - PostStore.updatePendingPost(post); - this.forceUpdate(); - } - ); - - post.state = Constants.POST_LOADING; - PostStore.updatePendingPost(post); - this.forceUpdate(); - } shouldComponentUpdate(nextProps) { if (!Utils.areObjectsEqual(nextProps.post, this.props.post)) { return true; @@ -245,7 +209,6 @@ export default class Post extends React.Component { parentPost={parentPost} posts={posts} handleCommentClick={this.handleCommentClick} - retryPost={this.retryPost} compactDisplay={this.props.compactDisplay} /> </div> diff --git a/webapp/components/post_body.jsx b/webapp/components/post_body.jsx index ed0a133b3..415052d96 100644 --- a/webapp/components/post_body.jsx +++ b/webapp/components/post_body.jsx @@ -7,6 +7,7 @@ import * as Utils from 'utils/utils.jsx'; import Constants from 'utils/constants.jsx'; import * as TextFormatting from 'utils/text_formatting.jsx'; import PostBodyAdditionalContent from './post_body_additional_content.jsx'; +import PendingPostActions from './pending_post_actions.jsx'; import {FormattedMessage} from 'react-intl'; @@ -28,10 +29,6 @@ export default class PostBody extends React.Component { return true; } - if (nextProps.retryPost.toString() !== this.props.retryPost.toString()) { - return true; - } - if (nextProps.handleCommentClick.toString() !== this.props.handleCommentClick.toString()) { return true; } @@ -114,18 +111,7 @@ export default class PostBody extends React.Component { let loading; if (post.state === Constants.POST_FAILED) { postClass += ' post--fail'; - loading = ( - <a - className='theme post-retry pull-right' - href='#' - onClick={this.props.retryPost} - > - <FormattedMessage - id='post_body.retry' - defaultMessage='Retry' - /> - </a> - ); + loading = <PendingPostActions post={this.props.post}/>; } else if (post.state === Constants.POST_LOADING) { postClass += ' post-waiting'; loading = ( diff --git a/webapp/components/rhs_comment.jsx b/webapp/components/rhs_comment.jsx index 5bd138732..e25e3b524 100644 --- a/webapp/components/rhs_comment.jsx +++ b/webapp/components/rhs_comment.jsx @@ -3,22 +3,18 @@ import UserProfile from './user_profile.jsx'; import FileAttachmentList from './file_attachment_list.jsx'; +import PendingPostActions from './pending_post_actions.jsx'; -import PostStore from 'stores/post_store.jsx'; -import ChannelStore from 'stores/channel_store.jsx'; import TeamStore from 'stores/team_store.jsx'; import UserStore from 'stores/user_store.jsx'; import * as GlobalActions from 'action_creators/global_actions.jsx'; -import AppDispatcher from '../dispatcher/app_dispatcher.jsx'; import * as TextFormatting from 'utils/text_formatting.jsx'; import * as Utils from 'utils/utils.jsx'; import Client from 'utils/web_client.jsx'; -import * as AsyncClient from 'utils/async_client.jsx'; import Constants from 'utils/constants.jsx'; -const ActionTypes = Constants.ActionTypes; import {FormattedMessage, FormattedDate} from 'react-intl'; @@ -30,41 +26,10 @@ export default class RhsComment extends React.Component { constructor(props) { super(props); - this.retryComment = this.retryComment.bind(this); this.handlePermalink = this.handlePermalink.bind(this); this.state = {}; } - retryComment(e) { - e.preventDefault(); - - var post = this.props.post; - Client.createPost(post, - (data) => { - AsyncClient.getPosts(post.channel_id); - - var channel = ChannelStore.get(post.channel_id); - var member = ChannelStore.getMember(post.channel_id); - member.msg_count = channel.total_msg_count; - member.last_viewed_at = (new Date()).getTime(); - ChannelStore.setChannelMember(member); - - AppDispatcher.handleServerAction({ - type: ActionTypes.RECEIVED_POST, - post: data - }); - }, - () => { - post.state = Constants.POST_FAILED; - PostStore.updatePendingPost(post); - this.forceUpdate(); - } - ); - - post.state = Constants.POST_LOADING; - PostStore.updatePendingPost(post); - this.forceUpdate(); - } handlePermalink(e) { e.preventDefault(); GlobalActions.showGetPostLinkModal(this.props.post); @@ -198,18 +163,7 @@ export default class RhsComment extends React.Component { if (post.state === Constants.POST_FAILED) { postClass += ' post-fail'; - loading = ( - <a - className='theme post-retry pull-right' - href='#' - onClick={this.retryComment} - > - <FormattedMessage - id='rhs_comment.retry' - defaultMessage='Retry' - /> - </a> - ); + loading = <PendingPostActions post={this.props.post}/>; } else if (post.state === Constants.POST_LOADING) { postClass += ' post-waiting'; loading = ( diff --git a/webapp/i18n/en.json b/webapp/i18n/en.json index 00958904c..d912576a8 100644 --- a/webapp/i18n/en.json +++ b/webapp/i18n/en.json @@ -1063,6 +1063,8 @@ "password_send.link": "<p>A password reset link has been sent to <b>{email}</b></p>", "password_send.reset": "Reset my password", "password_send.title": "Password Reset", + "pending_post_actions.retry": "Retry", + "pending_post_actions.cancel": "Cancel", "permalink.error.access": "Permalink belongs to a channel you do not have access to", "post_attachment.collapse": "▲ collapse text", "post_attachment.more": "▼ read more", @@ -1070,7 +1072,6 @@ "post_body.deleted": "(message deleted)", "post_body.plusMore": " plus {count} other files", "post_body.plusOne": " plus 1 other file", - "post_body.retry": "Retry", "post_delete.notPosted": "Comment could not be posted", "post_delete.okay": "Okay", "post_delete.someone": "Someone deleted the message on which you tried to post a comment.", @@ -1120,7 +1121,6 @@ "rhs_comment.del": "Delete", "rhs_comment.edit": "Edit", "rhs_comment.permalink": "Permalink", - "rhs_comment.retry": "Retry", "rhs_header.details": "Message Details", "rhs_root.del": "Delete", "rhs_root.direct": "Direct Message", diff --git a/webapp/i18n/es.json b/webapp/i18n/es.json index 8eb40444f..550cc2f02 100644 --- a/webapp/i18n/es.json +++ b/webapp/i18n/es.json @@ -1063,6 +1063,8 @@ "password_send.link": "<p>Se ha enviado un enlace para restablecer la contraseña a <b>{email}</b></p>", "password_send.reset": "Restablecer mi contraseña", "password_send.title": "Restablecer Contraseña", + "pending_post_actions.retry": "Reintentar", + "pending_post_actions.cancel": "Cancelar", "permalink.error.access": "El enlace permanente pertenece a un canal al cual no tienes acceso", "post_attachment.collapse": "▲ colapsar texto", "post_attachment.more": "▼ leer más", @@ -1070,7 +1072,6 @@ "post_body.deleted": "(mensaje eliminado)", "post_body.plusMore": " más {count} otros archivos", "post_body.plusOne": " más 1 archivo", - "post_body.retry": "Reintentar", "post_delete.notPosted": "No se pudo enviar el comentario", "post_delete.okay": "Ok", "post_delete.someone": "Alguien borró el mensaje que querías comentar.", @@ -1120,7 +1121,6 @@ "rhs_comment.del": "Borrar", "rhs_comment.edit": "Editar", "rhs_comment.permalink": "Enlace permanente", - "rhs_comment.retry": "Reintentar", "rhs_header.details": "Detalles del Mensaje", "rhs_root.del": "Borrar", "rhs_root.direct": "Mensaje Directo", diff --git a/webapp/i18n/fr.json b/webapp/i18n/fr.json index 8d4db079b..6f1fd5734 100644 --- a/webapp/i18n/fr.json +++ b/webapp/i18n/fr.json @@ -1063,6 +1063,8 @@ "password_send.link": "<p>Un lien de réinitialisation de mot de passe a été envoyé à <b>{email}</b></p>", "password_send.reset": "Réinitialiser mon mot de passe", "password_send.title": "Réinitialisation mot de passe", + "pending_post_actions.retry": "Réessayer", + "pending_post_actions.cancel": "Annuler", "permalink.error.access": "Permalink belongs to a channel you do not have access to", "post_attachment.collapse": "▲ réduire le texte", "post_attachment.more": "▼ lire la suite", @@ -1070,7 +1072,6 @@ "post_body.deleted": "(message supprimé)", "post_body.plusMore": " et {count} autres fichiers", "post_body.plusOne": " et 1 autre fichier", - "post_body.retry": "Réessayer", "post_delete.notPosted": "Le commentaire n'a pu être envoyé", "post_delete.okay": "Ok", "post_delete.someone": "Quelqu'un a supprimé le message sur lequel vous tentiez d'envoyer un commentaire.", @@ -1120,7 +1121,6 @@ "rhs_comment.del": "Supprimer", "rhs_comment.edit": "Éditer", "rhs_comment.permalink": "Lien permanent", - "rhs_comment.retry": "Réessayer", "rhs_header.details": "Détails du message", "rhs_root.del": "Supprimer", "rhs_root.direct": "Messages privés", diff --git a/webapp/i18n/ja.json b/webapp/i18n/ja.json index 3d56114f3..1dc1d8643 100644 --- a/webapp/i18n/ja.json +++ b/webapp/i18n/ja.json @@ -1063,6 +1063,8 @@ "password_send.link": "<p>パスワード初期化リンクが<b>{email}</b>に送信されました</p>", "password_send.reset": "自分のパスワードを初期化する", "password_send.title": "パスワードの初期化", + "pending_post_actions.retry": "再試行する", + "pending_post_actions.cancel": "キャンセル", "permalink.error.access": "アクセスできないチャンネルのパーマリンクです", "post_attachment.collapse": "▲テキストをたたむ", "post_attachment.more": "▼もっと読む", @@ -1070,7 +1072,6 @@ "post_body.deleted": "(メッセージは削除されています)", "post_body.plusMore": " {count}の他のファイルを追加する", "post_body.plusOne": " 1つの他のファイルを追加する", - "post_body.retry": "再試行する", "post_delete.notPosted": "コメントが投稿できませんでした", "post_delete.okay": "削除する", "post_delete.someone": "あなたがコメントしようとしたメッセージは削除されています。", @@ -1120,7 +1121,6 @@ "rhs_comment.del": "削除する", "rhs_comment.edit": "編集する", "rhs_comment.permalink": "パーマリンク", - "rhs_comment.retry": "再試行する", "rhs_header.details": "メッセージの詳細", "rhs_root.del": "削除する", "rhs_root.direct": "ダイレクトメッセージ", diff --git a/webapp/i18n/pt.json b/webapp/i18n/pt.json index f263b30c1..9b0027896 100644 --- a/webapp/i18n/pt.json +++ b/webapp/i18n/pt.json @@ -1063,6 +1063,8 @@ "password_send.link": "<p>Um link para resetar senha foi enviado para <b>{email}</b></p>", "password_send.reset": "Resetar minha senha", "password_send.title": "Resetar Senha", + "pending_post_actions.retry": "Tentar novamente", + "pending_post_actions.cancel": "Cancelar", "permalink.error.access": "Permalink pertence a um canal que você não tem acesso", "post_attachment.collapse": "▲ recolher texto", "post_attachment.more": "▼ leia mais", @@ -1070,7 +1072,6 @@ "post_body.deleted": "(mensagem deletada)", "post_body.plusMore": " mais {count} outros arquivos", "post_body.plusOne": " mais 1 outro arquivo", - "post_body.retry": "Tentar novamente", "post_delete.notPosted": "Comentário não pode ser postado", "post_delete.okay": "Ok", "post_delete.someone": "Alguém deletou a mensagem no qual você tentou postar um comentário.", @@ -1120,7 +1121,6 @@ "rhs_comment.del": "Deletar", "rhs_comment.edit": "Editar", "rhs_comment.permalink": "Permalink", - "rhs_comment.retry": "Tentar novamente", "rhs_header.details": "Detalhes da Mensagem", "rhs_root.del": "Deletar", "rhs_root.direct": "Mensagem Direta", diff --git a/webapp/sass/layout/_post.scss b/webapp/sass/layout/_post.scss index 07a78adfe..e3818ea94 100644 --- a/webapp/sass/layout/_post.scss +++ b/webapp/sass/layout/_post.scss @@ -814,6 +814,7 @@ body.ios { padding: .2em .5em; width: calc(100% - 75px); word-wrap: break-word; + position: relative; p { margin: 0 0 .4em; @@ -879,6 +880,20 @@ body.ios { margin-right: 8px; } } + + .pending-post-actions { + position: absolute; + right: 0; + top: 0; + padding: 5px 7px; + background: rgba(0, 0, 0, .7); + color: white; + font-size: .9em; + + a { + color: white; + } + } } .post__link { |