Implement simple GroupRoomInfo
which replaces the "X" on the GroupRoomTile with "Remove from community" under Admin Tools.
This commit is contained in:
parent
0dcd52d88f
commit
64a369216a
3 changed files with 178 additions and 71 deletions
170
src/components/views/groups/GroupRoomInfo.js
Normal file
170
src/components/views/groups/GroupRoomInfo.js
Normal file
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
Copyright 2017 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { MatrixClient } from 'matrix-js-sdk';
|
||||
import dis from '../../../dispatcher';
|
||||
import Modal from '../../../Modal';
|
||||
import sdk from '../../../index';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import { GroupRoomType } from '../../../groups';
|
||||
import GroupStoreCache from '../../../stores/GroupStoreCache';
|
||||
import GeminiScrollbar from 'react-gemini-scrollbar';
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'GroupRoomInfo',
|
||||
|
||||
contextTypes: {
|
||||
matrixClient: PropTypes.instanceOf(MatrixClient),
|
||||
},
|
||||
|
||||
propTypes: {
|
||||
groupId: PropTypes.string,
|
||||
groupRoom: GroupRoomType,
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
removingRoom: false,
|
||||
isUserPrivilegedInGroup: null,
|
||||
};
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
this._initGroupStore(this.props.groupId);
|
||||
},
|
||||
|
||||
componentWillReceiveProps(newProps) {
|
||||
if (newProps.groupId !== this.props.groupId) {
|
||||
this._unregisterGroupStore();
|
||||
this._initGroupStore(newProps.groupId);
|
||||
}
|
||||
},
|
||||
|
||||
_initGroupStore(groupId) {
|
||||
this._groupStore = GroupStoreCache.getGroupStore(
|
||||
this.context.matrixClient, this.props.groupId,
|
||||
);
|
||||
this._groupStore.registerListener(this.onGroupStoreUpdated);
|
||||
},
|
||||
|
||||
_unregisterGroupStore() {
|
||||
if (this._groupStore) {
|
||||
this._groupStore.unregisterListener(this.onGroupStoreUpdated);
|
||||
}
|
||||
},
|
||||
|
||||
onGroupStoreUpdated: function() {
|
||||
this.setState({
|
||||
isUserPrivilegedInGroup: this._groupStore.isUserPrivileged(),
|
||||
});
|
||||
},
|
||||
|
||||
_onRemove: function(e) {
|
||||
const groupId = this.props.groupId;
|
||||
const roomName = this.props.groupRoom.displayname;
|
||||
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 community will also remove it from the community page."),
|
||||
button: _t("Remove"),
|
||||
onFinished: (proceed) => {
|
||||
if (!proceed) return;
|
||||
this.setState({removingRoom: true});
|
||||
const groupId = this.props.groupId;
|
||||
const roomId = this.props.groupRoom.roomId;
|
||||
this._groupStore.removeRoomFromGroup(roomId).then(() => {
|
||||
dis.dispatch({
|
||||
action: "view_group_room_list",
|
||||
});
|
||||
}).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 community"),
|
||||
description: _t(
|
||||
"Failed to remove '%(roomName)s' from %(groupId)s", {groupId, roomName},
|
||||
),
|
||||
});
|
||||
}).finally(() => {
|
||||
this.setState({removingRoom: false});
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
_onCancel: function(e) {
|
||||
dis.dispatch({
|
||||
action: "view_group_room_list",
|
||||
});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
const BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
|
||||
const EmojiText = sdk.getComponent('elements.EmojiText');
|
||||
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
|
||||
if (this.state.removingRoom) {
|
||||
const Spinner = sdk.getComponent("elements.Spinner");
|
||||
return <Spinner />;
|
||||
}
|
||||
|
||||
let adminTools;
|
||||
if (this.state.isUserPrivilegedInGroup) {
|
||||
adminTools =
|
||||
<div className="mx_MemberInfo_adminTools">
|
||||
<h3>{ _t("Admin Tools") }</h3>
|
||||
<div className="mx_MemberInfo_buttons">
|
||||
<AccessibleButton className="mx_MemberInfo_field" onClick={this._onRemove}>
|
||||
{ _t('Remove from community') }
|
||||
</AccessibleButton>
|
||||
</div>
|
||||
</div>;
|
||||
}
|
||||
|
||||
const avatarUrl = this.context.matrixClient.mxcUrlToHttp(
|
||||
this.props.groupRoom.avatarUrl,
|
||||
36, 36, 'crop',
|
||||
);
|
||||
|
||||
const groupRoomName = this.props.groupRoom.displayname;
|
||||
const avatar = <BaseAvatar name={groupRoomName} width={36} height={36} url={avatarUrl} />;
|
||||
return (
|
||||
<div className="mx_MemberInfo">
|
||||
<GeminiScrollbar autoshow={true}>
|
||||
<AccessibleButton className="mx_MemberInfo_cancel"onClick={this._onCancel}>
|
||||
<img src="img/cancel.svg" width="18" height="18" className="mx_filterFlipColor" />
|
||||
</AccessibleButton>
|
||||
<div className="mx_MemberInfo_avatar">
|
||||
{ avatar }
|
||||
</div>
|
||||
|
||||
<EmojiText element="h2">{ groupRoomName }</EmojiText>
|
||||
|
||||
<div className="mx_MemberInfo_profile">
|
||||
<div className="mx_MemberInfo_profileField">
|
||||
{ this.props.groupRoom.canonical_alias }
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{ adminTools }
|
||||
</GeminiScrollbar>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
|
@ -16,13 +16,10 @@ limitations under the License.
|
|||
|
||||
import React from 'react';
|
||||
import {MatrixClient} from 'matrix-js-sdk';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import PropTypes from 'prop-types';
|
||||
import sdk from '../../../index';
|
||||
import dis from '../../../dispatcher';
|
||||
import { GroupRoomType } from '../../../groups';
|
||||
import GroupStoreCache from '../../../stores/GroupStoreCache';
|
||||
import Modal from '../../../Modal';
|
||||
|
||||
const GroupRoomTile = React.createClass({
|
||||
displayName: 'GroupRoomTile',
|
||||
|
@ -32,68 +29,11 @@ const GroupRoomTile = React.createClass({
|
|||
groupRoom: GroupRoomType.isRequired,
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
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");
|
||||
},
|
||||
|
||||
removeRoomFromGroup: function() {
|
||||
const groupId = this.props.groupId;
|
||||
const groupStore = GroupStoreCache.getGroupStore(this.context.matrixClient, groupId);
|
||||
const roomName = this.state.name;
|
||||
const roomId = this.props.groupRoom.roomId;
|
||||
groupStore.removeRoomFromGroup(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 community"),
|
||||
description: _t("Failed to remove '%(roomName)s' from %(groupId)s", {groupId, roomName}),
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
onClick: function(e) {
|
||||
let roomId;
|
||||
let roomAlias;
|
||||
if (this.props.groupRoom.canonicalAlias) {
|
||||
roomAlias = this.props.groupRoom.canonicalAlias;
|
||||
} else {
|
||||
roomId = this.props.groupRoom.roomId;
|
||||
}
|
||||
dis.dispatch({
|
||||
action: 'view_room',
|
||||
room_id: roomId,
|
||||
room_alias: roomAlias,
|
||||
});
|
||||
},
|
||||
|
||||
onDeleteClick: function(e) {
|
||||
const groupId = this.props.groupId;
|
||||
const roomName = this.state.name;
|
||||
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 community will also remove it from the community page."),
|
||||
button: _t("Remove"),
|
||||
onFinished: (success) => {
|
||||
if (success) {
|
||||
this.removeRoomFromGroup();
|
||||
}
|
||||
},
|
||||
action: 'view_group_room',
|
||||
groupId: this.props.groupId,
|
||||
groupRoom: this.props.groupRoom,
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -106,7 +46,7 @@ const GroupRoomTile = React.createClass({
|
|||
);
|
||||
|
||||
const av = (
|
||||
<BaseAvatar name={this.state.name}
|
||||
<BaseAvatar name={this.props.groupRoom.displayname}
|
||||
width={36} height={36}
|
||||
url={avatarUrl}
|
||||
/>
|
||||
|
@ -118,14 +58,8 @@ const GroupRoomTile = React.createClass({
|
|||
{ av }
|
||||
</div>
|
||||
<div className="mx_GroupRoomTile_name">
|
||||
{ this.state.name }
|
||||
{ this.props.groupRoom.displayname }
|
||||
</div>
|
||||
<AccessibleButton className="mx_GroupRoomTile_delete"
|
||||
onClick={this.onDeleteClick}
|
||||
tooltip={_t("Remove this room from the community")}
|
||||
>
|
||||
<img src="img/cancel.svg" width="15" height="15" className="mx_filterFlipColor" />
|
||||
</AccessibleButton>
|
||||
</AccessibleButton>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -15,6 +15,7 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import { _t } from './languageHandler.js';
|
||||
|
||||
export const GroupMemberType = PropTypes.shape({
|
||||
userId: PropTypes.string.isRequired,
|
||||
|
@ -23,6 +24,7 @@ export const GroupMemberType = PropTypes.shape({
|
|||
});
|
||||
|
||||
export const GroupRoomType = PropTypes.shape({
|
||||
displayname: PropTypes.string,
|
||||
name: PropTypes.string,
|
||||
roomId: PropTypes.string.isRequired,
|
||||
canonicalAlias: PropTypes.string,
|
||||
|
@ -39,6 +41,7 @@ export function groupMemberFromApiObject(apiObject) {
|
|||
|
||||
export function groupRoomFromApiObject(apiObject) {
|
||||
return {
|
||||
displayname: apiObject.name || apiObject.canonical_alias || _t("Unnamed Room"),
|
||||
name: apiObject.name,
|
||||
roomId: apiObject.room_id,
|
||||
canonicalAlias: apiObject.canonical_alias,
|
||||
|
|
Loading…
Reference in a new issue