Merge pull request #1430 from hmhealey/plt737a

PLT-737 Converted DeletePostModal to React-Bootstrap
Этот коммит содержится в:
Christopher Speller
2015-11-18 09:07:57 -05:00
родитель 7b01528d17 a4267471a5
Коммит 9660adb007
11 изменённых файлов: 140 добавлений и 97 удалений

Просмотреть файл

@@ -194,7 +194,8 @@ export default class CreateComment extends React.Component {
title: 'Comment', title: 'Comment',
message: lastPost.message, message: lastPost.message,
postId: lastPost.id, postId: lastPost.id,
channelId: lastPost.channel_id channelId: lastPost.channel_id,
comments: PostStore.getCommentCount(lastPost)
}); });
} }
} }

Просмотреть файл

@@ -372,7 +372,8 @@ export default class CreatePost extends React.Component {
title: type, title: type,
message: lastPost.message, message: lastPost.message,
postId: lastPost.id, postId: lastPost.id,
channelId: lastPost.channel_id channelId: lastPost.channel_id,
comments: PostStore.getCommentCount(lastPost)
}); });
} }
} }

Просмотреть файл

@@ -3,7 +3,8 @@
var Client = require('../utils/client.jsx'); var Client = require('../utils/client.jsx');
var PostStore = require('../stores/post_store.jsx'); var PostStore = require('../stores/post_store.jsx');
var BrowserStore = require('../stores/browser_store.jsx'); var ModalStore = require('../stores/modal_store.jsx');
var Modal = ReactBootstrap.Modal;
var Utils = require('../utils/utils.jsx'); var Utils = require('../utils/utils.jsx');
var AsyncClient = require('../utils/async_client.jsx'); var AsyncClient = require('../utils/async_client.jsx');
var AppDispatcher = require('../dispatcher/app_dispatcher.jsx'); var AppDispatcher = require('../dispatcher/app_dispatcher.jsx');
@@ -15,18 +16,40 @@ export default class DeletePostModal extends React.Component {
super(props); super(props);
this.handleDelete = this.handleDelete.bind(this); this.handleDelete = this.handleDelete.bind(this);
this.handleToggle = this.handleToggle.bind(this);
this.handleHide = this.handleHide.bind(this);
this.onListenerChange = this.onListenerChange.bind(this); this.onListenerChange = this.onListenerChange.bind(this);
this.onShow = this.onShow.bind(this);
this.state = {title: '', postId: '', channelId: '', selectedList: PostStore.getSelectedPost(), comments: 0}; this.selectedList = null;
this.state = {
show: true,
post: null,
commentCount: 0,
error: ''
};
} }
componentDidMount() {
ModalStore.addModalListener(ActionTypes.TOGGLE_DELETE_POST_MODAL, this.handleToggle);
PostStore.addSelectedPostChangeListener(this.onListenerChange);
}
componentWillUnmount() {
PostStore.removeSelectedPostChangeListener(this.onListenerChange);
ModalStore.removeModalListener(ActionTypes.TOGGLE_DELETE_POST_MODAL, this.handleToggle);
}
handleDelete() { handleDelete() {
Client.deletePost(this.state.channelId, this.state.postId, Client.deletePost(
function deleteSuccess() { this.state.post.channel_id,
var selectedList = this.state.selectedList; this.state.post.id,
() => {
var selectedList = this.selectedList;
if (selectedList && selectedList.order && selectedList.order.length > 0) { if (selectedList && selectedList.order && selectedList.order.length > 0) {
var selectedPost = selectedList.posts[selectedList.order[0]]; var selectedPost = selectedList.posts[selectedList.order[0]];
if ((selectedPost.id === this.state.postId && this.state.title === 'Post') || selectedPost.root_id === this.state.postId) { if ((selectedPost.id === this.state.post.id && !this.state.root_id) || selectedPost.root_id === this.state.post.id) {
AppDispatcher.handleServerAction({ AppDispatcher.handleServerAction({
type: ActionTypes.RECIEVED_SEARCH, type: ActionTypes.RECIEVED_SEARCH,
results: null results: null
@@ -36,7 +59,7 @@ export default class DeletePostModal extends React.Component {
type: ActionTypes.RECIEVED_POST_SELECTED, type: ActionTypes.RECIEVED_POST_SELECTED,
results: null results: null
}); });
} else if (selectedPost.id === this.state.postId && this.state.title === 'Comment') { } else if (selectedPost.id === this.state.post.id && this.state.root_id) {
if (selectedPost.root_id && selectedPost.root_id.length > 0 && selectedList.posts[selectedPost.root_id]) { if (selectedPost.root_id && selectedPost.root_id.length > 0 && selectedList.posts[selectedPost.root_id]) {
selectedList.order = [selectedPost.root_id]; selectedList.order = [selectedPost.root_id];
delete selectedList.posts[selectedPost.id]; delete selectedList.posts[selectedPost.id];
@@ -53,98 +76,96 @@ export default class DeletePostModal extends React.Component {
} }
} }
} }
PostStore.removePost(this.state.postId, this.state.channelId);
AsyncClient.getPosts(this.state.channelId); PostStore.removePost(this.state.post.id, this.state.post.channel_id);
}.bind(this), AsyncClient.getPosts(this.state.post.channel_id);
function deleteFailed(err) { },
(err) => {
AsyncClient.dispatchError(err, 'deletePost'); AsyncClient.dispatchError(err, 'deletePost');
} }
); );
this.handleHide();
} }
onShow(e) {
var newState = {}; handleToggle(value, args) {
if (BrowserStore.getItem('edit_state_transfer')) { this.setState({
newState = BrowserStore.getItem('edit_state_transfer'); show: value,
BrowserStore.removeItem('edit_state_transfer'); post: args.post,
} else { commentCount: args.commentCount,
var button = e.relatedTarget; error: ''
newState = {title: $(button).attr('data-title'), channelId: $(button).attr('data-channelid'), postId: $(button).attr('data-postid'), comments: $(button).attr('data-comments')}; });
} }
this.setState(newState);
} handleHide() {
componentDidMount() { this.setState({show: false});
$(ReactDOM.findDOMNode(this.refs.modal)).on('show.bs.modal', this.onShow);
PostStore.addSelectedPostChangeListener(this.onListenerChange);
}
componentWillUnmount() {
PostStore.removeSelectedPostChangeListener(this.onListenerChange);
} }
onListenerChange() { onListenerChange() {
var newList = PostStore.getSelectedPost(); var newList = PostStore.getSelectedPost();
if (!Utils.areObjectsEqual(this.state.selectedList, newList)) { if (!Utils.areObjectsEqual(this.selectedList, newList)) {
this.setState({selectedList: newList}); this.selectedList = newList;
} }
} }
render() { render() {
if (!this.state.post) {
return null;
}
var error = null; var error = null;
if (this.state.error) { if (this.state.error) {
error = <div className='form-group has-error'><label className='control-label'>{this.state.error}</label></div>; error = <div className='form-group has-error'><label className='control-label'>{this.state.error}</label></div>;
} }
var commentWarning = ''; var commentWarning = '';
if (this.state.comments > 0) { if (this.state.commentCount > 0) {
commentWarning = 'This post has ' + this.state.comments + ' comment(s) on it.'; commentWarning = 'This post has ' + this.state.commentCount + ' comment(s) on it.';
} }
const postTerm = Utils.getPostTerm(this.state.post);
return ( return (
<div <Modal
className='modal fade' show={this.state.show}
id='delete_post' onHide={this.handleHide}
ref='modal'
role='dialog'
tabIndex='-1'
aria-hidden='true'
> >
<div className='modal-dialog modal-push-down'> <Modal.Header closeButton={true}>
<div className='modal-content'> {`Confirm ${postTerm} Delete`}
<div className='modal-header'> </Modal.Header>
<button <Modal.Body>
type='button' {`Are you sure you want to delete this ${postTerm.toLowerCase()}?`}
className='close'
data-dismiss='modal'
aria-label='Close'
>
<span aria-hidden='true'>&times;</span>
</button>
<h4 className='modal-title'>Confirm {this.state.title} Delete</h4>
</div>
<div className='modal-body'>
Are you sure you want to delete the {this.state.title.toLowerCase()}?
<br /> <br />
<br /> <br />
{commentWarning} {commentWarning}
</div>
{error} {error}
<div className='modal-footer'> </Modal.Body>
<Modal.Footer>
<button <button
type='button' type='button'
className='btn btn-default' className='btn btn-default'
data-dismiss='modal' onClick={this.handleHide}
> >
Cancel {'Cancel'}
</button> </button>
<button <button
type='button' type='button'
className='btn btn-danger' className='btn btn-danger'
data-dismiss='modal'
onClick={this.handleDelete} onClick={this.handleDelete}
> >
Delete {'Delete'}
</button> </button>
</div> </Modal.Footer>
</div> </Modal>
</div>
</div>
); );
} }
static show(post, commentCount) {
AppDispatcher.handleViewAction({
type: ActionTypes.TOGGLE_DELETE_POST_MODAL,
value: true,
post,
commentCount: commentCount || 0
});
}
} }

Просмотреть файл

@@ -3,6 +3,7 @@
var Client = require('../utils/client.jsx'); var Client = require('../utils/client.jsx');
var AsyncClient = require('../utils/async_client.jsx'); var AsyncClient = require('../utils/async_client.jsx');
var DeletePostModal = require('./delete_post_modal.jsx');
var Textbox = require('./textbox.jsx'); var Textbox = require('./textbox.jsx');
var BrowserStore = require('../stores/browser_store.jsx'); var BrowserStore = require('../stores/browser_store.jsx');
var PostStore = require('../stores/post_store.jsx'); var PostStore = require('../stores/post_store.jsx');
@@ -34,7 +35,7 @@ export default class EditPostModal extends React.Component {
delete tempState.editText; delete tempState.editText;
BrowserStore.setItem('edit_state_transfer', tempState); BrowserStore.setItem('edit_state_transfer', tempState);
$('#edit_post').modal('hide'); $('#edit_post').modal('hide');
$('#delete_post').modal('show'); DeletePostModal.show(PostStore.getPost(this.state.channel_id, this.state.post_id), this.state.comments);
return; return;
} }

Просмотреть файл

@@ -1,6 +1,7 @@
// 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.
var DeletePostModal = require('./delete_post_modal.jsx');
var UserStore = require('../stores/user_store.jsx'); var UserStore = require('../stores/user_store.jsx');
var utils = require('../utils/utils.jsx'); var utils = require('../utils/utils.jsx');
var TimeSince = require('./time_since.jsx'); var TimeSince = require('./time_since.jsx');
@@ -50,7 +51,7 @@ export default class PostInfo extends React.Component {
data-channelid={post.channel_id} data-channelid={post.channel_id}
data-comments={dataComments} data-comments={dataComments}
> >
Edit {'Edit'}
</a> </a>
</li> </li>
); );
@@ -65,14 +66,9 @@ export default class PostInfo extends React.Component {
<a <a
href='#' href='#'
role='menuitem' role='menuitem'
data-toggle='modal' onClick={() => DeletePostModal.show(post, dataComments)}
data-target='#delete_post'
data-title={type}
data-postid={post.id}
data-channelid={post.channel_id}
data-comments={dataComments}
> >
Delete {'Delete'}
</a> </a>
</li> </li>
); );
@@ -89,7 +85,7 @@ export default class PostInfo extends React.Component {
href='#' href='#'
onClick={this.props.handleCommentClick} onClick={this.props.handleCommentClick}
> >
Reply {'Reply'}
</a> </a>
</li> </li>
); );

Просмотреть файл

@@ -8,6 +8,7 @@ var UserStore = require('../stores/user_store.jsx');
var AppDispatcher = require('../dispatcher/app_dispatcher.jsx'); var AppDispatcher = require('../dispatcher/app_dispatcher.jsx');
var Utils = require('../utils/utils.jsx'); var Utils = require('../utils/utils.jsx');
var Constants = require('../utils/constants.jsx'); var Constants = require('../utils/constants.jsx');
var DeletePostModal = require('./delete_post_modal.jsx');
var FileAttachmentList = require('./file_attachment_list.jsx'); var FileAttachmentList = require('./file_attachment_list.jsx');
var Client = require('../utils/client.jsx'); var Client = require('../utils/client.jsx');
var AsyncClient = require('../utils/async_client.jsx'); var AsyncClient = require('../utils/async_client.jsx');
@@ -114,12 +115,7 @@ export default class RhsComment extends React.Component {
<a <a
href='#' href='#'
role='menuitem' role='menuitem'
data-toggle='modal' onClick={() => DeletePostModal.show(post, 0)}
data-target='#delete_post'
data-title='Comment'
data-postid={post.id}
data-channelid={post.channel_id}
data-comments={0}
> >
{'Delete'} {'Delete'}
</a> </a>

Просмотреть файл

@@ -6,6 +6,7 @@ var UserProfile = require('./user_profile.jsx');
var UserStore = require('../stores/user_store.jsx'); var UserStore = require('../stores/user_store.jsx');
var TextFormatting = require('../utils/text_formatting.jsx'); var TextFormatting = require('../utils/text_formatting.jsx');
var utils = require('../utils/utils.jsx'); var utils = require('../utils/utils.jsx');
var DeletePostModal = require('./delete_post_modal.jsx');
var FileAttachmentList = require('./file_attachment_list.jsx'); var FileAttachmentList = require('./file_attachment_list.jsx');
var twemoji = require('twemoji'); var twemoji = require('twemoji');
var Constants = require('../utils/constants.jsx'); var Constants = require('../utils/constants.jsx');
@@ -86,21 +87,16 @@ export default class RhsRootPost extends React.Component {
data-postid={post.id} data-postid={post.id}
data-channelid={post.channel_id} data-channelid={post.channel_id}
> >
Edit {'Edit'}
</a> </a>
</li> </li>
<li role='presentation'> <li role='presentation'>
<a <a
href='#' href='#'
role='menuitem' role='menuitem'
data-toggle='modal' onClick={() => DeletePostModal.show(post, this.props.commentCount)}
data-target='#delete_post'
data-title={type}
data-postid={post.id}
data-channelid={post.channel_id}
data-comments={this.props.commentCount}
> >
Delete {'Delete'}
</a> </a>
</li> </li>
</ul> </ul>

Просмотреть файл

@@ -27,12 +27,14 @@ class ModalStoreClass extends EventEmitter {
} }
handleEventPayload(payload) { handleEventPayload(payload) {
const action = payload.action; // toggle event handlers should accept a boolean show/hide value and can accept a map of arguments
const {type, value, ...args} = payload.action;
switch (action.type) { switch (type) {
case ActionTypes.TOGGLE_IMPORT_THEME_MODAL: case ActionTypes.TOGGLE_IMPORT_THEME_MODAL:
case ActionTypes.TOGGLE_INVITE_MEMBER_MODAL: case ActionTypes.TOGGLE_INVITE_MEMBER_MODAL:
this.emit(action.type, action.value); case ActionTypes.TOGGLE_DELETE_POST_MODAL:
this.emit(type, value, args);
break; break;
} }
} }

Просмотреть файл

@@ -40,6 +40,7 @@ class PostStoreClass extends EventEmitter {
this.storePosts = this.storePosts.bind(this); this.storePosts = this.storePosts.bind(this);
this.pStorePosts = this.pStorePosts.bind(this); this.pStorePosts = this.pStorePosts.bind(this);
this.getPosts = this.getPosts.bind(this); this.getPosts = this.getPosts.bind(this);
this.getPost = this.getPost.bind(this);
this.storePost = this.storePost.bind(this); this.storePost = this.storePost.bind(this);
this.pStorePost = this.pStorePost.bind(this); this.pStorePost = this.pStorePost.bind(this);
this.removePost = this.removePost.bind(this); this.removePost = this.removePost.bind(this);
@@ -68,6 +69,7 @@ class PostStoreClass extends EventEmitter {
this.storeLatestUpdate = this.storeLatestUpdate.bind(this); this.storeLatestUpdate = this.storeLatestUpdate.bind(this);
this.getLatestUpdate = this.getLatestUpdate.bind(this); this.getLatestUpdate = this.getLatestUpdate.bind(this);
this.getCurrentUsersLatestPost = this.getCurrentUsersLatestPost.bind(this); this.getCurrentUsersLatestPost = this.getCurrentUsersLatestPost.bind(this);
this.getCommentCount = this.getCommentCount.bind(this);
} }
emitChange() { emitChange() {
this.emit(CHANGE_EVENT); this.emit(CHANGE_EVENT);
@@ -193,6 +195,9 @@ class PostStoreClass extends EventEmitter {
getPosts(channelId) { getPosts(channelId) {
return BrowserStore.getItem('posts_' + channelId); return BrowserStore.getItem('posts_' + channelId);
} }
getPost(channelId, postId) {
return this.getPosts(channelId).posts[postId];
}
getCurrentUsersLatestPost(channelId, rootId) { getCurrentUsersLatestPost(channelId, rootId) {
const userId = UserStore.getCurrentId(); const userId = UserStore.getCurrentId();
var postList = makePostListNonNull(this.getPosts(channelId)); var postList = makePostListNonNull(this.getPosts(channelId));
@@ -402,6 +407,20 @@ class PostStoreClass extends EventEmitter {
getLatestUpdate(channelId) { getLatestUpdate(channelId) {
return BrowserStore.getItem('latest_post_' + channelId, 0); return BrowserStore.getItem('latest_post_' + channelId, 0);
} }
getCommentCount(post) {
const posts = this.getPosts(post.channel_id).posts;
let commentCount = 0;
for (let id in posts) {
if (posts.hasOwnProperty(id)) {
if (posts[id].root_id === post.id) {
commentCount += 1;
}
}
}
return commentCount;
}
} }
var PostStore = new PostStoreClass(); var PostStore = new PostStoreClass();

Просмотреть файл

@@ -40,7 +40,8 @@ module.exports = {
RECIEVED_ALL_TEAMS: null, RECIEVED_ALL_TEAMS: null,
TOGGLE_IMPORT_THEME_MODAL: null, TOGGLE_IMPORT_THEME_MODAL: null,
TOGGLE_INVITE_MEMBER_MODAL: null TOGGLE_INVITE_MEMBER_MODAL: null,
TOGGLE_DELETE_POST_MODAL: null
}), }),
PayloadSources: keyMirror({ PayloadSources: keyMirror({

Просмотреть файл

@@ -1232,3 +1232,12 @@ export function getChannelTerm(channelType) {
return channelTerm; return channelTerm;
} }
export function getPostTerm(post) {
let postTerm = 'Post';
if (post.root_id) {
postTerm = 'Comment';
}
return postTerm;
}