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

Commit

Permalink
[MM-21405] Show warning first when Sync group members is turned on wi…
Browse files Browse the repository at this point in the history
…thout members and then show error if save without groups added (#5252)

* Don't show error as soon as you turn on sync without groups

* Update and address comments

* dont show save config

* fix linting

* fix error message

Co-authored-by: mattermod <[email protected]>
  • Loading branch information
hahmadia and mattermod committed Apr 8, 2020
1 parent debed84 commit c6ffb83
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,12 @@ export default class ChannelDetails extends React.Component<ChannelDetailsProps,
if (this.state.isSynced) {
try {
if (groups.length === 0) {
serverError = <NeedGroupsError/>;
serverError = (
<NeedGroupsError
warning={true}
isChannel={true}
/>
);
} else {
if (!channelID) {
return;
Expand Down Expand Up @@ -306,9 +311,6 @@ export default class ChannelDetails extends React.Component<ChannelDetailsProps,
isPublic,
isPrivacyChanging
});
if (this.state.groups.length === 0) {
return;
}
}
if (isPrivacyChanging && usersToRemove > 0) {
this.setState({showConvertAndRemoveConfirmModal: true});
Expand All @@ -331,68 +333,71 @@ export default class ChannelDetails extends React.Component<ChannelDetailsProps,
let saveNeeded = false;
const {groups: origGroups, channelID, actions, channel} = this.props;
if (this.state.groups.length === 0 && isSynced) {
serverError = <NeedGroupsError/>;
serverError = <NeedGroupsError isChannel={true}/>;
saveNeeded = true;
this.setState({serverError, saving: false, saveNeeded});
actions.setNavigationBlocked(saveNeeded);
return;
}

const promises = [];
if (isPrivacyChanging) {
const convert = actions.updateChannelPrivacy(channel.id, isPublic ? Constants.OPEN_CHANNEL : Constants.PRIVATE_CHANNEL);
promises.push(
convert.then((res) => {
if ('error' in res) {
return res;
}
return actions.patchChannel(channel.id, {
...channel,
group_constrained: isSynced
});
})
);
} else {
promises.push(
actions.patchChannel(channel.id, {
...channel,
group_constrained: isSynced
})
);
}

const patchChannelSyncable = groups.
filter((g) => {
return origGroups.some((group) => group.id === g.id && group.scheme_admin !== g.scheme_admin);
}).
map((g) => actions.patchGroupSyncable(g.id, channelID, Groups.SYNCABLE_TYPE_CHANNEL, {scheme_admin: g.scheme_admin}));
const unlink = origGroups.
filter((g) => {
return !groups.some((group) => group.id === g.id);
}).
map((g) => actions.unlinkGroupSyncable(g.id, channelID, Groups.SYNCABLE_TYPE_CHANNEL));
const link = groups.
filter((g) => {
return !origGroups.some((group) => group.id === g.id);
}).
map((g) => actions.linkGroupSyncable(g.id, channelID, Groups.SYNCABLE_TYPE_CHANNEL, {auto_add: true, scheme_admin: g.scheme_admin}));
const result = await Promise.all([...promises, ...patchChannelSyncable, ...unlink, ...link]);
const resultWithError = result.find((r) => 'error' in r);
if (resultWithError && 'error' in resultWithError) {
serverError = <FormError error={resultWithError.error.message}/>;
} else {
const promises = [];
const actionsToAwait: any[] = [actions.getGroups(channelID)];
if (isPrivacyChanging) {
const convert = actions.updateChannelPrivacy(channel.id, isPublic ? Constants.OPEN_CHANNEL : Constants.PRIVATE_CHANNEL);
promises.push(
convert.then((res) => {
if ('error' in res) {
return res;
// If the privacy is changing update the manage_members value for the channel moderation widget
actionsToAwait.push(
actions.getChannelModerations(channelID).then(() => {
const manageMembersIndex = channelPermissions!.findIndex((element) => element.name === Permissions.CHANNEL_MODERATED_PERMISSIONS.MANAGE_MEMBERS);
if (channelPermissions) {
const updatedManageMembers = this.props.channelPermissions!.find((element) => element.name === Permissions.CHANNEL_MODERATED_PERMISSIONS.MANAGE_MEMBERS);
channelPermissions[manageMembersIndex] = updatedManageMembers || channelPermissions[manageMembersIndex];
}
return actions.patchChannel(channel.id, {
...channel,
group_constrained: isSynced
});
})
);
} else {
promises.push(
actions.patchChannel(channel.id, {
...channel,
group_constrained: isSynced
this.setState({channelPermissions});
})
);
}

const patchChannelSyncable = groups.
filter((g) => {
return origGroups.some((group) => group.id === g.id && group.scheme_admin !== g.scheme_admin);
}).
map((g) => actions.patchGroupSyncable(g.id, channelID, Groups.SYNCABLE_TYPE_CHANNEL, {scheme_admin: g.scheme_admin}));
const unlink = origGroups.
filter((g) => {
return !groups.some((group) => group.id === g.id);
}).
map((g) => actions.unlinkGroupSyncable(g.id, channelID, Groups.SYNCABLE_TYPE_CHANNEL));
const link = groups.
filter((g) => {
return !origGroups.some((group) => group.id === g.id);
}).
map((g) => actions.linkGroupSyncable(g.id, channelID, Groups.SYNCABLE_TYPE_CHANNEL, {auto_add: true, scheme_admin: g.scheme_admin}));
const result = await Promise.all([...promises, ...patchChannelSyncable, ...unlink, ...link]);
const resultWithError = result.find((r) => 'error' in r);
if (resultWithError && 'error' in resultWithError) {
serverError = <FormError error={resultWithError.error.message}/>;
} else {
const actionsToAwait: any[] = [actions.getGroups(channelID)];
if (isPrivacyChanging) {
// If the privacy is changing update the manage_members value for the channel moderation widget
actionsToAwait.push(
actions.getChannelModerations(channelID).then(() => {
const manageMembersIndex = channelPermissions!.findIndex((element) => element.name === Permissions.CHANNEL_MODERATED_PERMISSIONS.MANAGE_MEMBERS);
if (channelPermissions) {
const updatedManageMembers = this.props.channelPermissions!.find((element) => element.name === Permissions.CHANNEL_MODERATED_PERMISSIONS.MANAGE_MEMBERS);
channelPermissions[manageMembersIndex] = updatedManageMembers || channelPermissions[manageMembersIndex];
}
this.setState({channelPermissions});
})
);
}
await Promise.all(actionsToAwait);
}
await Promise.all(actionsToAwait);
}

const patchChannelPermissionsArray: Array<ChannelModerationPatch> = channelPermissions!.map((p) => {
Expand All @@ -405,9 +410,9 @@ export default class ChannelDetails extends React.Component<ChannelDetailsProps,
};
});

const result = await actions.patchChannelModerations(channelID, patchChannelPermissionsArray);
if (result.error) {
serverError = <FormError error={result.error.message}/>;
const patchChannelModerationsResult = await actions.patchChannelModerations(channelID, patchChannelPermissionsArray);
if (patchChannelModerationsResult.error) {
serverError = <FormError error={patchChannelModerationsResult.error.message}/>;
}
this.restrictChannelMentions();

Expand All @@ -417,7 +422,6 @@ export default class ChannelDetails extends React.Component<ChannelDetailsProps,
}

this.setState({serverError, saving: false, saveNeeded, isPrivacyChanging: privacyChanging});

actions.setNavigationBlocked(saveNeeded);
};

Expand Down
35 changes: 25 additions & 10 deletions components/admin_console/team_channel_settings/errors.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,31 @@ import ToggleModalButton from 'components/toggle_modal_button.jsx';

import UsersToBeRemovedModal from './users_to_be_removed_modal';

export const NeedGroupsError = ({warning}) => (
<FormError
iconClassName={`fa-exclamation-${warning ? 'circle' : 'triangle'}`}
textClassName={`has-${warning ? 'warning' : 'error'}`}
error={(
export const NeedGroupsError = ({warning, isChannel = false}) => {
let error = (
<FormattedMessage
id='admin.team_channel_settings.need_groups'
defaultMessage='You must add at least one group to manage this team by sync group members.'
/>
);

if (isChannel) {
error = (
<FormattedMessage
id='admin.team_channel_settings.need_groups'
defaultMessage='You must add at least one group to manage this team by sync group members.'
/>)}
/>
);
id='admin.team_channel_settings.need_groups_channel'
defaultMessage='You must add at least one group to manage this channel by sync group members.'
/>
);
}

return (
<FormError
iconClassName={`fa-exclamation-${warning ? 'circle' : 'triangle'}`}
textClassName={`has-${warning ? 'warning' : 'error'}`}
error={error}
/>
);
};

export const NeedDomainsError = () => (
<FormError
Expand All @@ -36,6 +50,7 @@ export const NeedDomainsError = () => (

NeedGroupsError.propTypes = {
warning: PropTypes.bool,
isChannel: PropTypes.bool,
};

export class UsersWillBeRemovedError extends React.PureComponent {
Expand Down
1 change: 1 addition & 0 deletions i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1610,6 +1610,7 @@
"admin.team_channel_settings.list.paginatorCount": "{startCount, number} - {endCount, number} of {total, number}",
"admin.team_channel_settings.need_domains": "Please specify allowed email domains.",
"admin.team_channel_settings.need_groups": "You must add at least one group to manage this team by sync group members.",
"admin.team_channel_settings.need_groups_channel": "You must add at least one group to manage this channel by sync group members.",
"admin.team_channel_settings.removeConfirmModal.messageChannel": "{amount, number} {amount, plural, one {user} other {users}} will be removed. They are not in groups linked to this channel. Are you sure you wish to remove these users?",
"admin.team_channel_settings.removeConfirmModal.messageGroup": "{amount, number} {amount, plural, one {user} other {users}} will be removed. They are not in groups linked to this group. Are you sure you wish to remove these users?",
"admin.team_channel_settings.removeConfirmModal.remove": "Save and remove {amount, plural, one {user} other {users}}",
Expand Down

0 comments on commit c6ffb83

Please sign in to comment.