Skip to content
This repository has been archived by the owner on Mar 13, 2024. It is now read-only.

Migrate delete_post_modal.jsx to be pure and use Redux #989

Merged
merged 7 commits into from Mar 23, 2018
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 0 additions & 10 deletions actions/global_actions.jsx
Expand Up @@ -188,16 +188,6 @@ export function toggleShortcutsModal() {
});
}

export function showDeletePostModal(post, commentCount = 0, isRHS) {
AppDispatcher.handleViewAction({
type: ActionTypes.TOGGLE_DELETE_POST_MODAL,
value: true,
isRHS,
post,
commentCount,
});
}

export function showChannelHeaderUpdateModal(channel) {
AppDispatcher.handleViewAction({
type: ActionTypes.TOGGLE_CHANNEL_HEADER_UPDATE_MODAL,
Expand Down
2 changes: 0 additions & 2 deletions components/channel_layout/channel_controller.jsx
Expand Up @@ -7,7 +7,6 @@ import {Route} from 'react-router-dom';

import Pluggable from 'plugins/pluggable';
import AnnouncementBar from 'components/announcement_bar';
import DeletePostModal from 'components/delete_post_modal.jsx';
import EditPostModal from 'components/edit_post_modal';
import GetPostLinkModal from 'components/get_post_link_modal';
import GetTeamInviteLinkModal from 'components/get_team_invite_link_modal';
Expand Down Expand Up @@ -64,7 +63,6 @@ export default class ChannelController extends React.Component {
<ImportThemeModal/>
<TeamSettingsModal/>
<EditPostModal/>
<DeletePostModal/>
<RemovedFromChannelModal/>
<ResetStatusModal/>
<LeavePrivateChannelModal/>
Expand Down
@@ -1,106 +1,83 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.

import PropTypes from 'prop-types';
import React from 'react';
import {Modal} from 'react-bootstrap';
import {FormattedMessage} from 'react-intl';

import {deletePost} from 'actions/post_actions.jsx';
import ModalStore from 'stores/modal_store.jsx';
import Constants from 'utils/constants.jsx';
import * as UserAgent from 'utils/user_agent.jsx';

var ActionTypes = Constants.ActionTypes;
export default class DeletePostModal extends React.PureComponent {
static propTypes = {

export default class DeletePostModal extends React.Component {
constructor(props) {
super(props);
post: PropTypes.object.isRequired,
commentCount: PropTypes.number.isRequired,

this.state = {
show: false,
post: null,
commentCount: 0,
error: '',
};
}
/**
* Does the post come from RHS mode
*/
isRHS: PropTypes.bool.isRequired,

componentDidMount() {
ModalStore.addModalListener(ActionTypes.TOGGLE_DELETE_POST_MODAL, this.handleToggle);
}
/**
* Function called when modal is dismissed
*/
onHide: PropTypes.func.isRequired,

componentWillUnmount() {
ModalStore.removeModalListener(ActionTypes.TOGGLE_DELETE_POST_MODAL, this.handleToggle);
}
actions: PropTypes.shape({

componentDidUpdate(prevProps, prevState) {
if (this.state.show && !prevState.show) {
setTimeout(() => {
if (this.deletePostBtn) {
this.deletePostBtn.focus();
}
}, 200);
}
/**
* Function called for deleting post
*/
deletePost: PropTypes.func.isRequired,
}),
}

handleDelete = () => {
deletePost(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @GitHubJasper!
Forgot to mention earlier:

handleDelete = async () => {
    const {
        actions,
        channelName,
        focusedPostId,
        post,
        teamURL,
    } = this.props;

    const {data} = await actions.deletePost(post);

    if (post.id === focusedPostId && channelName) {
        browserHistory.push(teamURL + '/channels/' + channelName);
    }

    if (data) {
        this.onHide();
    }
}

Then at delete_post_modal/index.js, need to generate those new props, like so:

import {getChannel} from 'mattermost-redux/selectors/entities/channels';
import {getCurrentTeamUrl} from 'mattermost-redux/selectors/entities/teams';

function mapStateToProps(state, ownProps) {
    const channel = getChannel(state, ownProps.post.channel_id);
    let channelName = '';
    if (channel) {
        channelName = channel.name;
    }

    const {focusedPostId} = state.views.channel;

    return {
        channelName,
        focusedPostId,
        teamURL: getCurrentTeamUrl(state),
    };
}

(I have not tested above code but more or less it should be like that. Feel free to test functionality :) )

this.state.post.channel_id,
this.state.post,
() => {
this.handleHide();
},
(err) => {
this.setState({error: err.message});
}
);
constructor(props) {
super(props);
this.handleDelete = this.handleDelete.bind(this);
this.onHide = this.onHide.bind(this);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No action required but just a heads up if you use arrow syntax you don't need these binds (since it will autobind). e.g

handleDelete = () => {
// stuff
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, that is good to know. Thanks!

this.state = {
show: true,
};
}

handleToggle = (value, args) => {
this.setState({
show: value,
post: args.post,
isRHS: args.isRHS,
commentCount: args.commentCount,
error: '',
});
handleDelete() {
this.props.actions.deletePost(this.props.post);
this.onHide();
}

handleHide = () => {
onHide() {
this.setState({show: false});

if (!UserAgent.isMobile()) {
if (this.state.isRHS) {
document.getElementById('reply_textbox').focus();
var element;
if (this.props.isRHS) {
element = document.getElementById('reply_textbox');
} else {
document.getElementById('post_textbox').focus();
element = document.getElementById('post_textbox');
}
if (element) {
element.focus();
}
}
}

render() {
if (!this.state.post) {
return null;
}

var error = null;
if (this.state.error) {
error = <div className='form-group has-error'><label className='control-label'>{this.state.error}</label></div>;
}

var commentWarning = '';
if (this.state.commentCount > 0) {
if (this.props.commentCount > 0) {
commentWarning = (
<FormattedMessage
id='delete_post.warning'
defaultMessage='This post has {count, number} {count, plural, one {comment} other {comments}} on it.'
values={{
count: this.state.commentCount,
count: this.props.commentCount,
}}
/>
);
}

const postTerm = this.state.post.root_id ? (
const postTerm = this.props.post.root_id ? (
<FormattedMessage
id='delete_post.comment'
defaultMessage='Comment'
Expand All @@ -115,7 +92,8 @@ export default class DeletePostModal extends React.Component {
return (
<Modal
show={this.state.show}
onHide={this.handleHide}
onHide={this.onHide}
onExited={this.props.onHide}
enforceFocus={false}
>
<Modal.Header closeButton={true}>
Expand All @@ -140,7 +118,6 @@ export default class DeletePostModal extends React.Component {
<br/>
<br/>
{commentWarning}
{error}
</Modal.Body>
<Modal.Footer>
<button
Expand Down
18 changes: 18 additions & 0 deletions components/delete_post_modal/index.js
@@ -0,0 +1,18 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.

import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {deletePost} from 'mattermost-redux/actions/posts';

import DeletePostModal from './delete_post_modal.jsx';

function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators({
deletePost,
}, dispatch),
};
}

export default connect(null, mapDispatchToProps)(DeletePostModal);
20 changes: 14 additions & 6 deletions components/dot_menu/dot_menu.jsx
Expand Up @@ -27,30 +27,35 @@ export default class DotMenu extends Component {

actions: PropTypes.shape({

/*
/**
* Function flag the post
*/
flagPost: PropTypes.func.isRequired,

/*
/**
* Function to unflag the post
*/
unflagPost: PropTypes.func.isRequired,

/*
* Function to set the edting post
/**
* Function to set the editing post
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch!

*/
setEditingPost: PropTypes.func.isRequired,

/*
/**
* Function to pin the post
*/
pinPost: PropTypes.func.isRequired,

/*
/**
* Function to unpin the post
*/
unpinPost: PropTypes.func.isRequired,

/**
* Function to open a modal
*/
openModal: PropTypes.func.isRequired,
}).isRequired,
}

Expand Down Expand Up @@ -185,6 +190,9 @@ export default class DotMenu extends Component {
idCount={this.props.idCount}
post={this.props.post}
commentCount={type === 'Post' ? this.props.commentCount : 0}
actions={{
openModal: this.props.actions.openModal,
}}
/>
);
}
Expand Down
27 changes: 22 additions & 5 deletions components/dot_menu/dot_menu_item.jsx
Expand Up @@ -5,8 +5,9 @@ import PropTypes from 'prop-types';
import React from 'react';
import {FormattedMessage} from 'react-intl';

import {showDeletePostModal, showGetPostLinkModal} from 'actions/global_actions.jsx';
import Constants from 'utils/constants.jsx';
import {showGetPostLinkModal} from 'actions/global_actions.jsx';
import DeletePostModal from 'components/delete_post_modal';
import {Constants, ModalIdentifiers} from 'utils/constants.jsx';
import * as Utils from 'utils/utils.jsx';

export default function DotMenuItem(props) {
Expand All @@ -27,7 +28,18 @@ export default function DotMenuItem(props) {

function handleDeletePost(e) {
e.preventDefault();
showDeletePostModal(props.post, props.commentCount, props.isRHS);

const deletePostModalData = {
ModalId: ModalIdentifiers.DELETE_POST,
dialogType: DeletePostModal,
dialogProps: {
post: props.post,
commentCount: props.commentCount,
isRHS: props.isRHS,
},
};

props.actions.openModal(deletePostModalData);
}

const attrib = {};
Expand Down Expand Up @@ -101,15 +113,20 @@ DotMenuItem.propTypes = {

actions: PropTypes.shape({

/*
/**
* Function to pin the post
*/
pinPost: PropTypes.func,

/*
/**
* Function to unpin the post
*/
unpinPost: PropTypes.func,

/**
* Function to open a modal
*/
openModal: PropTypes.func,
}),
};

Expand Down
2 changes: 2 additions & 0 deletions components/dot_menu/index.js
Expand Up @@ -5,6 +5,7 @@ import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {flagPost, unflagPost} from 'mattermost-redux/actions/posts';

import {openModal} from 'actions/views/modals';
import {pinPost, unpinPost, setEditingPost} from 'actions/post_actions.jsx';

import DotMenu from './dot_menu.jsx';
Expand All @@ -21,6 +22,7 @@ function mapDispatchToProps(dispatch) {
setEditingPost,
pinPost,
unpinPost,
openModal,
}, dispatch),
};
}
Expand Down
17 changes: 14 additions & 3 deletions components/edit_post_modal/edit_post_modal.jsx
Expand Up @@ -7,11 +7,11 @@ import {FormattedMessage} from 'react-intl';
import PropTypes from 'prop-types';
import * as Selectors from 'mattermost-redux/selectors/entities/posts';

import * as GlobalActions from 'actions/global_actions.jsx';
import store from 'stores/redux_store.jsx';
import Constants from 'utils/constants.jsx';
import {Constants, ModalIdentifiers} from 'utils/constants.jsx';
import * as UserAgent from 'utils/user_agent.jsx';
import * as Utils from 'utils/utils.jsx';
import DeletePostModal from 'components/delete_post_modal';
import EmojiPickerOverlay from 'components/emoji_picker/emoji_picker_overlay.jsx';
import EmojiIcon from 'components/svg/emoji_icon';
import Textbox from 'components/textbox.jsx';
Expand Down Expand Up @@ -165,7 +165,18 @@ export default class EditPostModal extends React.PureComponent {
const hasAttachment = editingPost.post.file_ids && editingPost.post.file_ids.length > 0;
if (updatedPost.message.trim().length === 0 && !hasAttachment) {
this.handleHide(false);
GlobalActions.showDeletePostModal(Selectors.getPost(getState(), editingPost.postId), editingPost.commentsCount, editingPost.isRHS);

const deletePostModalData = {
ModalId: ModalIdentifiers.DELETE_POST,
dialogType: DeletePostModal,
dialogProps: {
post: Selectors.getPost(getState(), editingPost.postId),
commentCount: editingPost.commentsCount,
isRHS: editingPost.isRHS,
},
};

this.props.actions.openModal(deletePostModalData);
return;
}

Expand Down
2 changes: 2 additions & 0 deletions components/edit_post_modal/index.js
Expand Up @@ -8,6 +8,7 @@ import {Preferences} from 'mattermost-redux/constants';
import {getConfig} from 'mattermost-redux/selectors/entities/general';
import {getBool} from 'mattermost-redux/selectors/entities/preferences';

import {openModal} from 'actions/views/modals';
import {hideEditPostModal} from 'actions/post_actions';
import {editPost} from 'actions/views/edit_post_modal';
import {getEditingPost} from 'selectors/posts';
Expand All @@ -28,6 +29,7 @@ function mapDispatchToProps(dispatch) {
addMessageIntoHistory,
editPost,
hideEditPostModal,
openModal,
}, dispatch),
};
}
Expand Down