Channel info delete (#222)

* Initial setup to delete channels

* Combine leave and delete

* Working delete when removing the current channel id delete

* Initial working delete with handling web sockets

* Move go back out of component

* Refactor alert function and handle after leave navigation

* Remove promise then

* Allow channel membership to default to empty object

* Ensure that channel is present to avoid method on undefined

* Remove view channel delete action

* Remove unused type
This commit is contained in:
Chris Duarte 2017-02-09 09:12:44 -08:00 committed by enahum
parent 8c0f5c70d7
commit 263fd50887
8 changed files with 74 additions and 43 deletions

View file

@ -195,10 +195,9 @@ export function unmarkFavorite(channelId) {
export function leaveChannel(channel, reset = false) {
return async (dispatch, getState) => {
const {currentId: teamId} = getState().entities.teams;
serviceLeaveChannel(teamId, channel.id)(dispatch, getState).then(() => {
if (channel.isCurrent || reset) {
selectInitialChannel(teamId)(dispatch, getState);
}
});
await serviceLeaveChannel(teamId, channel.id)(dispatch, getState);
if (channel.isCurrent || reset) {
await selectInitialChannel(teamId)(dispatch, getState);
}
};
}

View file

@ -283,7 +283,7 @@ class ChannelList extends React.Component {
const member = this.props.channelMembers[channel.id];
let mentions = 0;
let unreadCount = 0;
if (member) {
if (member && channel) {
mentions = member.mention_count;
unreadCount = channel.total_msg_count - member.msg_count;

View file

@ -47,11 +47,12 @@ class ChannelInfo extends PureComponent {
actions: PropTypes.shape({
getChannelStats: PropTypes.func.isRequired,
goToChannelMembers: PropTypes.func.isRequired,
goBack: PropTypes.func.isRequired,
goToChannelAddMembers: PropTypes.func.isRequired,
markFavorite: PropTypes.func.isRequired,
unmarkFavorite: PropTypes.func.isRequired,
goBack: PropTypes.func.isRequired,
leaveChannel: PropTypes.func.isRequired
leaveChannel: PropTypes.func.isRequired,
deleteChannel: PropTypes.func.isRequired
})
};
@ -72,16 +73,6 @@ class ChannelInfo extends PureComponent {
if (isFavorite !== this.state.isFavorite) {
this.setState({isFavorite});
}
this.navigateAfterLeave(nextProps.leaveChannelRequest);
}
navigateAfterLeave(leaveChannelRequest) {
if (
leaveChannelRequest !== this.props.leaveChannelRequest &&
leaveChannelRequest.status === 'success'
) {
this.props.actions.goBack();
}
}
handleFavorite = () => {
@ -92,34 +83,54 @@ class ChannelInfo extends PureComponent {
toggleFavorite(currentChannel.id);
};
handleLeave() {
handleDeleteOrLeave(eventType) {
const {formatMessage} = this.props.intl;
const channel = this.props.currentChannel;
const term = channel.type === Constants.OPEN_CHANNEL ?
formatMessage({id: 'mobile.channel_info.publicChannel', defaultMessage: 'Public Channel'}) :
formatMessage({id: 'mobile.channel_info.privateChannel', defaultMessage: 'Private Channel'});
let title;
let message;
let onPressAction;
if (eventType === 'leave') {
title = {id: 'mobile.channel_info.alertTitleLeaveChannel', defaultMessage: 'Leave {term}'};
message = {
id: 'mobile.channel_info.alertMessageLeaveChannel',
defaultMessage: 'Are you sure you want to leave the {term} {name}?'
};
onPressAction = () => {
this.props.actions.leaveChannel(channel, true).then(this.props.actions.goBack);
};
} else if (eventType === 'delete') {
title = {id: 'mobile.channel_info.alertTitleDeleteChannel', defaultMessage: 'Delete {term}'};
message = {
id: 'mobile.channel_info.alertMessageDeleteChannel',
defaultMessage: 'Are you sure you want to delete the {term} {name}?'
};
onPressAction = () => {
this.props.actions.deleteChannel(channel.team_id, channel.id).then(this.props.actions.goBack);
};
}
Alert.alert(
formatMessage({id: 'mobile.channel_info.alertTitleLeaveChannel', defaultMessage: 'Leave {term}'}, {term}),
formatMessage({
id: 'mobile.channel_info.alertMessageLeaveChannel',
defaultMessage: 'Are you sure you want to leave the {term} with {name}?'
}, {
term: term.toLowerCase(),
name: channel.display_name
}),
formatMessage(title, {term}),
formatMessage(
message,
{
term: term.toLowerCase(),
name: channel.display_name
}
),
[{
text: formatMessage({id: 'mobile.channel_info.alertNo', defaultMessage: 'No'})
}, {
text: formatMessage({id: 'mobile.channel_info.alertYes', defaultMessage: 'Yes'}),
onPress: () => {
this.props.actions.leaveChannel(channel, true);
}
}]
onPress: onPressAction
}],
);
}
renderLeaveChannelRow() {
renderLeaveOrDeleteChannelRow() {
const channel = this.props.currentChannel;
const isDefaultChannel = channel.name === Constants.DEFAULT_CHANNEL;
const isDirectMessage = channel.type === Constants.DM_CHANNEL;
@ -190,20 +201,21 @@ class ChannelInfo extends PureComponent {
</View>
}
<ChannelInfoRow
action={() => this.handleLeave()}
action={() => this.handleDeleteOrLeave('leave')}
defaultMessage='Leave Channel'
icon='sign-out'
textId='navbar.leave'
shouldRender={this.renderLeaveChannelRow()}
shouldRender={this.renderLeaveOrDeleteChannelRow()}
/>
<View style={style.footer}>
<ChannelInfoRow
action={() => true}
action={() => this.handleDeleteOrLeave('delete')}
defaultMessage='Delete Channel'
icon='trash'
iconColor='#DA4A4A'
textId='mobile.routes.channelInfo.delete_channel'
textColor='#DA4A4A'
shouldRender={this.renderLeaveOrDeleteChannelRow()}
/>
</View>
</ScrollView>

View file

@ -6,7 +6,7 @@ import {bindActionCreators} from 'redux';
import navigationSceneConnect from '../navigationSceneConnect';
import {goToChannelMembers, goToChannelAddMembers, goBack} from 'app/actions/navigation';
import {getChannelStats} from 'service/actions/channels';
import {getChannelStats, deleteChannel} from 'service/actions/channels';
import {markFavorite, unmarkFavorite, leaveChannel} from 'app/actions/views/channel';
import {getCurrentChannel, getCurrentChannelStats, getChannelsByCategory} from 'service/selectors/entities/channels';
import {getTheme} from 'service/selectors/entities/preferences';
@ -23,7 +23,6 @@ function mapStateToProps(state, ownProps) {
const isFavorite = favoriteChannels.indexOf(currentChannel.id) > -1;
const leaveChannelRequest = state.requests.channels.leaveChannel;
const currentUserRoles = getCurrentUserRoles(state);
const isAdmin = currentUserRoles.includes('_admin');
return {
@ -47,6 +46,7 @@ function mapDispatchToProps(dispatch) {
markFavorite,
unmarkFavorite,
leaveChannel,
deleteChannel,
goBack
}, dispatch)
};

View file

@ -1486,6 +1486,8 @@
"mobile.channel_info.privateChannel": "Private Channel",
"mobile.channel_info.alertTitleLeaveChannel": "Leave {term}",
"mobile.channel_info.alertMessageLeaveChannel": "Are you sure you want to leave the {term} with {name}?",
"mobile.channel_info.alertTitleDeleteChannel": "Delete {term}",
"mobile.channel_info.alertMessageDeleteChannel": "Are you sure you want to delete the {term} with {name}?",
"mobile.channel_info.alertNo": "No",
"mobile.channel_info.alertYes": "Yes",
"mobile.channel_list.alertTitleLeaveChannel": "Leave {term}",

View file

@ -381,6 +381,18 @@ export function deleteChannel(teamId, channelId) {
return;
}
const entities = getState().entities;
const {channels, currentId} = entities.channels;
if (channelId === currentId) {
const channel = Object.keys(channels).filter((key) => channels[key].name === Constants.DEFAULT_CHANNEL);
let defaultChannelId = '';
if (channel.length) {
defaultChannelId = channel[0];
}
dispatch({type: ChannelTypes.SELECT_CHANNEL, data: defaultChannelId}, getState);
}
dispatch(batchActions([
{
type: ChannelTypes.RECEIVED_CHANNEL_DELETED,
@ -407,23 +419,30 @@ export function viewChannel(teamId, channelId, prevChannelId = '') {
}
const {channels} = getState().entities.channels;
let totalMsgCount = 0;
if (channels[channelId]) {
totalMsgCount = channels[channelId].total_msg_count;
}
const actions = [{
type: ChannelTypes.RECEIVED_LAST_VIEWED,
data: {
channel_id: channelId,
last_viewed_at: new Date().getTime(),
total_msg_count: channels[channelId].total_msg_count
total_msg_count: totalMsgCount
}
}];
if (prevChannelId) {
let prevTotalMsgCount = 0;
if (channels[channelId]) {
prevTotalMsgCount = channels[channelId].total_msg_count;
}
actions.push({
type: ChannelTypes.RECEIVED_LAST_VIEWED,
data: {
channel_id: prevChannelId,
last_viewed_at: new Date().getTime(),
total_msg_count: channels[prevChannelId].total_msg_count
total_msg_count: prevTotalMsgCount
}
});
}

View file

@ -313,8 +313,6 @@ function handleChannelDeletedEvent(msg, dispatch, getState) {
const teams = entities.teams;
if (msg.broadcast.team_id === teams.currentId) {
dispatch({type: ChannelTypes.RECEIVED_CHANNEL_DELETED, data: msg.data.channel_id}, getState);
if (msg.data.channel_id === currentId) {
let channelId = '';
const channel = Object.keys(channels).filter((key) => channels[key].name === Constants.DEFAULT_CHANNEL);
@ -325,6 +323,7 @@ function handleChannelDeletedEvent(msg, dispatch, getState) {
dispatch({type: ChannelTypes.SELECT_CHANNEL, data: channelId}, getState);
}
dispatch({type: ChannelTypes.RECEIVED_CHANNEL_DELETED, data: msg.data.channel_id}, getState);
fetchMyChannelsAndMembers(teams.currentId)(dispatch, getState);
}

View file

@ -39,7 +39,7 @@ export const getCurrentChannelMembership = createSelector(
getCurrentChannelId,
getChannelMemberships,
(currentChannelId, channelMemberships) => {
return channelMemberships[currentChannelId];
return channelMemberships[currentChannelId] || {};
}
);