diff --git a/src/components/views/room_settings/RelatedGroupSettings.js b/src/components/views/room_settings/RelatedGroupSettings.js new file mode 100644 index 0000000000..60bdbf1481 --- /dev/null +++ b/src/components/views/room_settings/RelatedGroupSettings.js @@ -0,0 +1,125 @@ +/* +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 React from 'react'; +import {MatrixEvent, MatrixClient} from 'matrix-js-sdk'; +import sdk from '../../../index'; +import { _t } from '../../../languageHandler'; +import Modal from '../../../Modal'; + +const GROUP_ID_REGEX = /\+\S+\:\S+/; + +module.exports = React.createClass({ + displayName: 'RelatedGroupSettings', + + propTypes: { + roomId: React.PropTypes.string.isRequired, + canSetRelatedRooms: React.PropTypes.bool.isRequired, + relatedGroupsEvent: React.PropTypes.instanceOf(MatrixEvent), + }, + + contextTypes: { + matrixClient: React.PropTypes.instanceOf(MatrixClient), + }, + + getDefaultProps: function() { + return { + canSetRelatedRooms: false, + }; + }, + + getInitialState: function() { + return { + newGroupsList: this.props.relatedGroupsEvent ? + (this.props.relatedGroupsEvent.getContent().groups || []) : [], + newGroupId: null, + }; + }, + + saveSettings: function() { + return this.context.matrixClient.sendStateEvent( + this.props.roomId, + 'm.room.related_groups', + { + groups: this.state.newGroupsList, + }, + '', + ); + }, + + validateGroupId: function(groupId) { + if (!GROUP_ID_REGEX.test(groupId)) { + const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); + Modal.createTrackedDialog('Invalid related group ID', '', ErrorDialog, { + title: _t('Invalid group ID'), + description: _t('\'%(groupId)s\' is not a valid group ID', { groupId }), + }); + return false; + } + return true; + }, + + onNewGroupChanged: function(newGroupId) { + this.setState({ newGroupId }); + }, + + onGroupAdded: function(groupId) { + if (groupId.length === 0 || !this.validateGroupId(groupId)) { + return; + } + this.setState({ + newGroupsList: this.state.newGroupsList.concat([groupId]), + newGroupId: '', + }); + }, + + onGroupEdited: function(groupId, index) { + if (groupId.length === 0 || !this.validateGroupId(groupId)) { + return; + } + this.setState({ + newGroupsList: Object.assign(this.state.newGroupsList, {[index]: groupId}), + }); + }, + + onGroupDeleted: function(index) { + const newGroupsList = this.state.newGroupsList.slice(); + newGroupsList.splice(index, 1), + this.setState({ newGroupsList }); + }, + + render: function() { + const localDomain = this.context.matrixClient.getDomain(); + const EditableItemList = sdk.getComponent('elements.EditableItemList'); + return (
+

{ _t('Related Groups') }

+ +
); + }, +}); diff --git a/src/components/views/rooms/RoomSettings.js b/src/components/views/rooms/RoomSettings.js index 0fea50d2fa..d1d32d8c71 100644 --- a/src/components/views/rooms/RoomSettings.js +++ b/src/components/views/rooms/RoomSettings.js @@ -287,6 +287,9 @@ module.exports = React.createClass({ promises.push(ps); } + // related groups + promises.push(this.saveRelatedGroups()); + // encryption p = this.saveEnableEncryption(); if (!p.isFulfilled()) { @@ -304,6 +307,11 @@ module.exports = React.createClass({ return this.refs.alias_settings.saveSettings(); }, + saveRelatedGroups: function() { + if (!this.refs.related_groups) { return Promise.resolve(); } + return this.refs.related_groups.saveSettings(); + }, + saveColor: function() { if (!this.refs.color_settings) { return Promise.resolve(); } return this.refs.color_settings.saveSettings(); @@ -590,6 +598,7 @@ module.exports = React.createClass({ var AliasSettings = sdk.getComponent("room_settings.AliasSettings"); var ColorSettings = sdk.getComponent("room_settings.ColorSettings"); var UrlPreviewSettings = sdk.getComponent("room_settings.UrlPreviewSettings"); + var RelatedGroupSettings = sdk.getComponent("room_settings.RelatedGroupSettings"); var EditableText = sdk.getComponent('elements.EditableText'); var PowerSelector = sdk.getComponent('elements.PowerSelector'); var Loader = sdk.getComponent("elements.Spinner"); @@ -846,6 +855,11 @@ module.exports = React.createClass({ canonicalAliasEvent={this.props.room.currentState.getStateEvents('m.room.canonical_alias', '')} aliasEvents={this.props.room.currentState.getStateEvents('m.room.aliases')} /> + +

{ _t('Permissions') }

diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 6a8c848f14..6acaba9fae 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -902,5 +902,9 @@ "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", "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." + "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.", + "Related Groups": "Related Groups", + "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)" }