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

Commit

Permalink
Merge pull request #1475 from matrix-org/luke/groups-room-directory-e…
Browse files Browse the repository at this point in the history
…sque

Modify GroupView UI
  • Loading branch information
dbkr authored Oct 16, 2017
2 parents 1d75d9e + 6f20445 commit e4a3309
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 19 deletions.
69 changes: 52 additions & 17 deletions src/components/structures/GroupView.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import classnames from 'classnames';

import GroupStoreCache from '../../stores/GroupStoreCache';
import GroupStore from '../../stores/GroupStore';
import { showGroupAddRoomDialog } from '../../GroupAddressPicker';
import GeminiScrollbar from 'react-gemini-scrollbar';

const RoomSummaryType = PropTypes.shape({
room_id: PropTypes.string.isRequired,
Expand Down Expand Up @@ -64,7 +66,7 @@ const CategoryRoomList = React.createClass({
editing: PropTypes.bool.isRequired,
},

onAddRoomsClicked: function(ev) {
onAddRoomsToSummaryClicked: function(ev) {
ev.preventDefault();
const AddressPickerDialog = sdk.getComponent("dialogs.AddressPickerDialog");
Modal.createTrackedDialog('Add Rooms to Group Summary', '', AddressPickerDialog, {
Expand Down Expand Up @@ -106,7 +108,9 @@ const CategoryRoomList = React.createClass({
render: function() {
const TintableSvg = sdk.getComponent("elements.TintableSvg");
const addButton = this.props.editing ?
(<AccessibleButton className="mx_GroupView_featuredThings_addButton" onClick={this.onAddRoomsClicked}>
(<AccessibleButton className="mx_GroupView_featuredThings_addButton"
onClick={this.onAddRoomsToSummaryClicked}
>
<TintableSvg src="img/icons-create-room.svg" width="64" height="64" />
<div className="mx_GroupView_featuredThings_addButton_label">
{ _t('Add a Room') }
Expand Down Expand Up @@ -450,6 +454,7 @@ export default React.createClass({
});
});
this._groupStore.on('error', (err) => {
console.error(err);
this.setState({
summary: null,
error: err,
Expand Down Expand Up @@ -601,6 +606,10 @@ export default React.createClass({
this._setPublicity(true);
},

_onAddRoomsClick: function() {
showGroupAddRoomDialog(this.props.groupId);
},

_setPublicity: function(publicity) {
this.setState({
publicityBusy: true,
Expand All @@ -612,6 +621,28 @@ export default React.createClass({
});
},

_getRoomsNode: function() {
const RoomDetailList = sdk.getComponent('rooms.RoomDetailList');
const AccessibleButton = sdk.getComponent('elements.AccessibleButton');
const TintableSvg = sdk.getComponent('elements.TintableSvg');
const addButton = this.state.editing ?
(<AccessibleButton onClick={this._onAddRoomsClick} >
<div className="mx_GroupView_rooms_header_addButton" >
<TintableSvg src="img/icons-room-add.svg" width="24" height="24" />
</div>
<div className="mx_GroupView_rooms_header_addButton_label">
{ _t('Add rooms to this group') }
</div>
</AccessibleButton>) : <div />;
return <div className="mx_GroupView_rooms">
<div className="mx_GroupView_rooms_header">
<h3>Rooms</h3>
{ addButton }
</div>
<RoomDetailList rooms={this._groupStore.getGroupRooms()} />
</div>;
},

_getFeaturedRoomsNode: function() {
const summary = this.state.summary;

Expand Down Expand Up @@ -799,7 +830,7 @@ export default React.createClass({
let avatarNode;
let nameNode;
let shortDescNode;
let roomBody;
let bodyNodes = [];
const rightButtons = [];
const headerClasses = {
mx_GroupView_header: true,
Expand Down Expand Up @@ -856,14 +887,15 @@ export default React.createClass({
width="18" height="18" alt={_t("Cancel")} />
</AccessibleButton>,
);
roomBody = <div>
<textarea className="mx_GroupView_editLongDesc" value={this.state.profileForm.long_description}
bodyNodes = [
<textarea className="mx_GroupView_editLongDesc"
value={this.state.profileForm.long_description}
onChange={this._onLongDescChange}
tabIndex="3"
/>
{ this._getFeaturedRoomsNode() }
{ this._getFeaturedUsersNode() }
</div>;
key="editLongDesc"
/>,
this._getRoomsNode(),
];
} else {
const groupAvatarUrl = summary.profile ? summary.profile.avatar_url : null;
avatarNode = <GroupAvatar
Expand All @@ -881,18 +913,19 @@ export default React.createClass({
} else {
nameNode = <span>{ this.props.groupId }</span>;
}
shortDescNode = <span>{ summary.profile.short_description }</span>;
if (summary.profile && summary.profile.short_description) {
shortDescNode = <span>{ summary.profile.short_description }</span>;
}

let description = null;
if (summary.profile && summary.profile.long_description) {
description = sanitizedHtmlNode(summary.profile.long_description);
}
roomBody = <div>
{ this._getMembershipSection() }
<div className="mx_GroupView_groupDesc">{ description }</div>
{ this._getFeaturedRoomsNode() }
{ this._getFeaturedUsersNode() }
</div>;
bodyNodes = [
this._getMembershipSection(),
<div key="groupDesc" className="mx_GroupView_groupDesc">{ description }</div>,
this._getRoomsNode(),
];
if (summary.user && summary.user.is_privileged) {
rightButtons.push(
<AccessibleButton className="mx_GroupHeader_button"
Expand Down Expand Up @@ -935,7 +968,9 @@ export default React.createClass({
{ rightButtons }
</div>
</div>
{ roomBody }
<GeminiScrollbar className="mx_GroupView_body">
{ bodyNodes }
</GeminiScrollbar>
</div>
);
} else if (this.state.error) {
Expand Down
1 change: 1 addition & 0 deletions src/components/structures/ScrollPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ module.exports = React.createClass({
onFillRequest: function(backwards) { return Promise.resolve(false); },
onUnfillRequest: function(backwards, scrollToken) {},
onScroll: function() {},
onResize: function() {},
};
},

Expand Down
128 changes: 128 additions & 0 deletions src/components/views/rooms/RoomDetailList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/*
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 sdk from '../../../index';
import dis from '../../../dispatcher';
import React from 'react';
import { _t } from '../../../languageHandler';
import linkifyString from 'linkifyjs/string';
import sanitizeHtml from 'sanitize-html';
import { ContentRepo } from 'matrix-js-sdk';
import MatrixClientPeg from '../../../MatrixClientPeg';
import PropTypes from 'prop-types';

function getDisplayAliasForRoom(room) {
return room.canonical_alias || (room.aliases ? room.aliases[0] : "");
}

const RoomDetailRow = React.createClass({
onClick: function(ev) {
ev.preventDefault();
dis.dispatch({
action: 'view_room',
room_id: this.props.room.room_id,
});
},

onTopicClick: function(ev) {
// When clicking a link in the topic, prevent the event being propagated
// to `onClick`.
ev.stopPropagation();
},

render: function() {
const BaseAvatar = sdk.getComponent('avatars.BaseAvatar');

const room = this.props.room;
const name = room.name || getDisplayAliasForRoom(room) || _t('Unnamed room');
const topic = linkifyString(sanitizeHtml(room.topic || ''));

const guestRead = room.world_readable ? (
<div className="mx_RoomDirectory_perm">{ _t('World readable') }</div>
) : <div />;
const guestJoin = room.guest_can_join ? (
<div className="mx_RoomDirectory_perm">{ _t('Guests can join') }</div>
) : <div />;

const perms = (guestRead || guestJoin) ? (<div className="mx_RoomDirectory_perms">
{ guestRead }
{ guestJoin }
</div>) : <div />;

return <tr key={room.room_id} onClick={this.onClick}>
<td className="mx_RoomDirectory_roomAvatar">
<BaseAvatar width={24} height={24} resizeMethod='crop'
name={name} idName={name}
url={ContentRepo.getHttpUriForMxc(
MatrixClientPeg.get().getHomeserverUrl(),
room.avatar_url, 24, 24, "crop")} />
</td>
<td className="mx_RoomDirectory_roomDescription">
<div className="mx_RoomDirectory_name">{ name }</div>&nbsp;
{ perms }
<div className="mx_RoomDirectory_topic"
onClick={this.onTopicClick}
dangerouslySetInnerHTML={{ __html: topic }} />
<div className="mx_RoomDirectory_alias">{ getDisplayAliasForRoom(room) }</div>
</td>
<td className="mx_RoomDirectory_roomMemberCount">
{ room.num_joined_members }
</td>
</tr>;
},
});

export default React.createClass({
displayName: 'RoomDetailList',

propTypes: {
rooms: PropTypes.arrayOf(PropTypes.shape({
name: PropTypes.string,
topic: PropTypes.string,
room_id: PropTypes.string,
num_joined_members: PropTypes.number,
canonical_alias: PropTypes.string,
aliases: PropTypes.arrayOf(PropTypes.string),

world_readable: PropTypes.bool,
guest_can_join: PropTypes.bool,
})),
},

getRows: function() {
if (!this.props.rooms) return [];
return this.props.rooms.map((room, index) => {
return <RoomDetailRow key={index} room={room} />;
});
},

render() {
const rows = this.getRows();
let rooms;
if (rows.length == 0) {
rooms = <i>{ _t('No rooms to show') }</i>;
} else {
rooms = <table ref="directory_table" className="mx_RoomDirectory_table">
<tbody>
{ this.getRows() }
</tbody>
</table>;
}
return <div className="mx_RoomDetailList">
{ rooms }
</div>;
},
});
5 changes: 3 additions & 2 deletions src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -924,7 +924,8 @@
"Related groups for this room:": "Related groups for this room:",
"This room has no related groups": "This room has no related groups",
"New group ID (e.g. +foo:%(localDomain)s)": "New group ID (e.g. +foo:%(localDomain)s)",
"%(serverName)s Matrix ID": "%(serverName)s Matrix ID",
"Add rooms to this group": "Add rooms to this group",
"Invites sent": "Invites sent",
"Your group invitations have been sent.": "Your group invitations have been sent.",
"%(serverName)s Matrix ID": "%(serverName)s Matrix ID"
"Your group invitations have been sent.": "Your group invitations have been sent."
}

0 comments on commit e4a3309

Please sign in to comment.