From 955ca6cd2b19dfab7cc30b2303ba05f9885876b3 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Fri, 29 Sep 2017 17:59:24 +0100 Subject: [PATCH 1/4] Implement button to remove a room from a group NB: This doesn't provide any feedback to the user. We should use a GroupSummaryStore-style component to refresh the view after a successful hit to the API. This could affect the summary view as well, because when rooms are removed from a group, they are also removed from the summary (if necessary). --- src/components/views/groups/GroupRoomTile.js | 10 ++++++++++ src/groups.js | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/components/views/groups/GroupRoomTile.js b/src/components/views/groups/GroupRoomTile.js index 452f862d16..1081890f40 100644 --- a/src/components/views/groups/GroupRoomTile.js +++ b/src/components/views/groups/GroupRoomTile.js @@ -49,6 +49,13 @@ const GroupRoomTile = React.createClass({ }); }, + onDeleteClick: function(e) { + e.preventDefault(); + e.stopPropagation(); + this.context.matrixClient + .removeRoomFromGroup(this.props.groupId, this.props.groupRoom.roomId); + }, + render: function() { const BaseAvatar = sdk.getComponent('avatars.BaseAvatar'); const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); @@ -76,6 +83,9 @@ const GroupRoomTile = React.createClass({
{ name }
+ + + ); }, diff --git a/src/groups.js b/src/groups.js index 2ff95f7d65..69871c45e9 100644 --- a/src/groups.js +++ b/src/groups.js @@ -24,8 +24,7 @@ export const GroupMemberType = PropTypes.shape({ export const GroupRoomType = PropTypes.shape({ name: PropTypes.string, - // TODO: API doesn't return this yet - // roomId: PropTypes.string.isRequired, + roomId: PropTypes.string.isRequired, canonicalAlias: PropTypes.string, avatarUrl: PropTypes.string, }); @@ -41,6 +40,7 @@ export function groupMemberFromApiObject(apiObject) { export function groupRoomFromApiObject(apiObject) { return { name: apiObject.name, + roomId: apiObject.room_id, canonicalAlias: apiObject.canonical_alias, avatarUrl: apiObject.avatar_url, }; From 3e34a460a411935ed994c469b8e87e6fa8b2f6d4 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 3 Oct 2017 10:06:18 +0100 Subject: [PATCH 2/4] Add error dialog for when removing room fails --- src/components/views/groups/GroupRoomTile.js | 34 +++++++++++++++----- src/i18n/strings/en_EN.json | 4 ++- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/components/views/groups/GroupRoomTile.js b/src/components/views/groups/GroupRoomTile.js index 1081890f40..eeba9d6d8a 100644 --- a/src/components/views/groups/GroupRoomTile.js +++ b/src/components/views/groups/GroupRoomTile.js @@ -21,6 +21,7 @@ import PropTypes from 'prop-types'; import sdk from '../../../index'; import dis from '../../../dispatcher'; import { GroupRoomType } from '../../../groups'; +import Modal from '../../../Modal'; const GroupRoomTile = React.createClass({ displayName: 'GroupRoomTile', @@ -31,7 +32,19 @@ const GroupRoomTile = React.createClass({ }, getInitialState: function() { - return {}; + return { + name: this.calculateRoomName(this.props.groupRoom), + }; + }, + + componentWillReceiveProps: function(newProps) { + this.setState({ + name: this.calculateRoomName(newProps.groupRoom), + }); + }, + + calculateRoomName: function(groupRoom) { + return groupRoom.name || groupRoom.canonicalAlias || _t("Unnamed Room"); }, onClick: function(e) { @@ -52,24 +65,29 @@ const GroupRoomTile = React.createClass({ onDeleteClick: function(e) { e.preventDefault(); e.stopPropagation(); + const groupId = this.props.groupId; + const roomName = this.state.name; this.context.matrixClient - .removeRoomFromGroup(this.props.groupId, this.props.groupRoom.roomId); + .removeRoomFromGroup(groupId, this.props.groupRoom.roomId) + .catch((err) => { + const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); + Modal.createTrackedDialog('Failed to remove room from group', '', ErrorDialog, { + title: _t("Failed to remove room from group"), + description: _t("Failed to remove '%(roomName)s' from %(groupId)s", {groupId, roomName}), + }); + }); }, render: function() { const BaseAvatar = sdk.getComponent('avatars.BaseAvatar'); const AccessibleButton = sdk.getComponent('elements.AccessibleButton'); - - const name = this.props.groupRoom.name || - this.props.groupRoom.canonicalAlias || - _t("Unnamed Room"); const avatarUrl = this.context.matrixClient.mxcUrlToHttp( this.props.groupRoom.avatarUrl, 36, 36, 'crop', ); const av = ( - @@ -81,7 +99,7 @@ const GroupRoomTile = React.createClass({ { av }
- { name } + { this.state.name }
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 87fd6d4364..10e135fc6e 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -895,5 +895,7 @@ "Matrix Room ID": "Matrix Room ID", "email address": "email address", "Try using one of the following valid address types: %(validTypesList)s.": "Try using one of the following valid address types: %(validTypesList)s.", - "You have entered an invalid address.": "You have entered an invalid address." + "You have entered an invalid address.": "You have entered an invalid address.", + "Failed to remove room from group": "Failed to remove room from group", + "Failed to remove '%(roomName)s' from %(groupId)s": "Failed to remove '%(roomName)s' from %(groupId)s" } From 0116c4b48681a9ba90348010d7691befcdbcf386 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 3 Oct 2017 10:14:08 +0100 Subject: [PATCH 3/4] Log the error when failing to removie room from group --- src/components/views/groups/GroupRoomTile.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/views/groups/GroupRoomTile.js b/src/components/views/groups/GroupRoomTile.js index eeba9d6d8a..ea8b5b9993 100644 --- a/src/components/views/groups/GroupRoomTile.js +++ b/src/components/views/groups/GroupRoomTile.js @@ -67,9 +67,11 @@ const GroupRoomTile = React.createClass({ e.stopPropagation(); const groupId = this.props.groupId; const roomName = this.state.name; + const roomId = this.props.groupRoom.roomId; this.context.matrixClient - .removeRoomFromGroup(groupId, this.props.groupRoom.roomId) + .removeRoomFromGroup(groupId, roomId) .catch((err) => { + console.error(`Error whilst removing ${roomId} from ${groupId}`, err); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); Modal.createTrackedDialog('Failed to remove room from group', '', ErrorDialog, { title: _t("Failed to remove room from group"), From 6b834bc72e5bd073e572928e3aa8c0ed3e533123 Mon Sep 17 00:00:00 2001 From: Luke Barnard Date: Tue, 3 Oct 2017 11:16:22 +0100 Subject: [PATCH 4/4] Add confirmation dialog for removing room from group --- src/components/views/groups/GroupRoomTile.js | 42 ++++++++++++++------ src/i18n/strings/en_EN.json | 4 +- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/components/views/groups/GroupRoomTile.js b/src/components/views/groups/GroupRoomTile.js index ea8b5b9993..b6bdb9735b 100644 --- a/src/components/views/groups/GroupRoomTile.js +++ b/src/components/views/groups/GroupRoomTile.js @@ -47,6 +47,22 @@ const GroupRoomTile = React.createClass({ return groupRoom.name || groupRoom.canonicalAlias || _t("Unnamed Room"); }, + removeRoomFromGroup: function() { + const groupId = this.props.groupId; + const roomName = this.state.name; + const roomId = this.props.groupRoom.roomId; + this.context.matrixClient + .removeRoomFromGroup(groupId, roomId) + .catch((err) => { + console.error(`Error whilst removing ${roomId} from ${groupId}`, err); + const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); + Modal.createTrackedDialog('Failed to remove room from group', '', ErrorDialog, { + title: _t("Failed to remove room from group"), + description: _t("Failed to remove '%(roomName)s' from %(groupId)s", {groupId, roomName}), + }); + }); + }, + onClick: function(e) { let roomId; let roomAlias; @@ -63,21 +79,21 @@ const GroupRoomTile = React.createClass({ }, onDeleteClick: function(e) { - e.preventDefault(); - e.stopPropagation(); const groupId = this.props.groupId; const roomName = this.state.name; - const roomId = this.props.groupRoom.roomId; - this.context.matrixClient - .removeRoomFromGroup(groupId, roomId) - .catch((err) => { - console.error(`Error whilst removing ${roomId} from ${groupId}`, err); - const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); - Modal.createTrackedDialog('Failed to remove room from group', '', ErrorDialog, { - title: _t("Failed to remove room from group"), - description: _t("Failed to remove '%(roomName)s' from %(groupId)s", {groupId, roomName}), - }); - }); + e.preventDefault(); + e.stopPropagation(); + const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog"); + Modal.createTrackedDialog('Confirm removal of group from room', '', QuestionDialog, { + title: _t("Are you sure you want to remove '%(roomName)s' from %(groupId)s?", {roomName, groupId}), + description: _t("Removing a room from the group will also remove it from the group page."), + button: _t("Remove"), + onFinished: (success) => { + if (success) { + this.removeRoomFromGroup(); + } + }, + }); }, render: function() { diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 10e135fc6e..bc377d8359 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -897,5 +897,7 @@ "Try using one of the following valid address types: %(validTypesList)s.": "Try using one of the following valid address types: %(validTypesList)s.", "You have entered an invalid address.": "You have entered an invalid address.", "Failed to remove room from group": "Failed to remove room from group", - "Failed to remove '%(roomName)s' from %(groupId)s": "Failed to remove '%(roomName)s' from %(groupId)s" + "Failed to remove '%(roomName)s' from %(groupId)s": "Failed to remove '%(roomName)s' from %(groupId)s", + "Are you sure you want to remove '%(roomName)s' from %(groupId)s?": "Are you sure you want to remove '%(roomName)s' from %(groupId)s?", + "Removing a room from the group will also remove it from the group page.": "Removing a room from the group will also remove it from the group page." }