diff --git a/skins/base/views/atoms/create_room/RoomAlias.js b/skins/base/views/atoms/create_room/RoomAlias.js new file mode 100644 index 00000000..f60ec6b3 --- /dev/null +++ b/skins/base/views/atoms/create_room/RoomAlias.js @@ -0,0 +1,72 @@ +/* +Copyright 2015 OpenMarket 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. +*/ + +'use strict'; + +var React = require('react'); + +var RoomAliasController = require("../../../../../src/controllers/atoms/create_room/RoomAlias"); + +module.exports = React.createClass({ + displayName: 'RoomAlias', + mixins: [RoomAliasController], + + onValueChanged: function(ev) { + this.setState({room_alias: ev.target.value}) + }, + + onFocus: function(ev) { + var target = ev.target; + var curr_val = ev.target.value; + + if (curr_val == "") { + target.value = "#:example.com"; + setTimeout(function() { + target.setSelectionRange(1, 1); + }, 0); + } else { + setTimeout(function() { + target.setSelectionRange( + curr_val.startsWith("#") ? 1 : 0, + curr_val.endsWith(":example.com") ? (target.value.length - ":example.com".length) : target.value.length + ); + }, 0); + } + }, + + onBlur: function(ev) { + var curr_val = ev.target.value; + + if (curr_val == "#:example.com") { + ev.target.value = ""; + return; + } + + if (curr_val != "") { + var new_val = ev.target.value; + if (!curr_val.startsWith("#")) new_val = "#" + new_val; + if (!curr_val.endsWith(":example.com")) new_val = new_val + ":example.com"; + ev.target.value = new_val; + } + }, + + render: function() { + return ( + <input type="text" className="mx_RoomAlias" placeholder="Alias (optional)" + onChange={this.onValueChanged} onFocus={this.onFocus} onBlur={this.onBlur}/> + ); + } +}); diff --git a/skins/base/views/atoms/create_room/RoomNameTextbox.js b/skins/base/views/atoms/create_room/RoomNameTextbox.js index c358a14c..038d39a9 100644 --- a/skins/base/views/atoms/create_room/RoomNameTextbox.js +++ b/skins/base/views/atoms/create_room/RoomNameTextbox.js @@ -30,7 +30,7 @@ module.exports = React.createClass({ render: function() { return ( - <input type="text" className="mx_RoomNameTextbox" placeholder="ex. MyNewRoom" onChange={this.onValueChanged}/> + <input type="text" className="mx_RoomNameTextbox" placeholder="Name" onChange={this.onValueChanged}/> ); } }); diff --git a/skins/base/views/atoms/create_room/RoomTopic.js b/skins/base/views/atoms/create_room/RoomTopic.js new file mode 100644 index 00000000..134833f9 --- /dev/null +++ b/skins/base/views/atoms/create_room/RoomTopic.js @@ -0,0 +1,37 @@ +/* +Copyright 2015 OpenMarket 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. +*/ + +'use strict'; + +var React = require('react'); + +var RoomTopicController = require("../../../../../src/controllers/atoms/create_room/RoomTopic"); + +module.exports = React.createClass({ + displayName: 'RoomTopic', + mixins: [RoomTopicController], + + onValueChanged: function(ev) { + this.setState({room_topic: ev.target.value}) + }, + + render: function() { + return ( + <textarea className="mx_RoomTopic" placeholder="Description" onChange={this.onValueChanged}> + </textarea> + ); + } +}); diff --git a/skins/base/views/molecules/DirectoryMenu.js b/skins/base/views/molecules/DirectoryMenu.js index f3b9e592..60b5542d 100644 --- a/skins/base/views/molecules/DirectoryMenu.js +++ b/skins/base/views/molecules/DirectoryMenu.js @@ -33,11 +33,15 @@ module.exports = React.createClass({ dis.dispatch({action: 'view_user_settings'}); }, + onCreateRoomClick: function() { + dis.dispatch({action: 'view_create_room'}); + }, + render: function() { return ( <div className="mx_DirectoryMenu"> <div className="mx_DirectoryMenu_options"> - <div className="mx_RoomTile"> + <div className="mx_RoomTile" onClick={this.onCreateRoomClick}> <div className="mx_RoomTile_avatar"> <img src="img/create-big.png" width="42" height="42"/> </div> diff --git a/skins/base/views/organisms/CreateRoom.js b/skins/base/views/organisms/CreateRoom.js index 36f6e466..d7e84ccc 100644 --- a/skins/base/views/organisms/CreateRoom.js +++ b/skins/base/views/organisms/CreateRoom.js @@ -24,6 +24,8 @@ var ComponentBroker = require('../../../../src/ComponentBroker'); var CreateRoomButton = ComponentBroker.get("atoms/create_room/CreateRoomButton"); var RoomNameTextbox = ComponentBroker.get("atoms/create_room/RoomNameTextbox"); +var RoomTopic = ComponentBroker.get("atoms/create_room/RoomTopic"); +var RoomAlias = ComponentBroker.get("atoms/create_room/RoomAlias"); var Presets = ComponentBroker.get("atoms/create_room/Presets"); var UserSelector = ComponentBroker.get("molecules/UserSelector"); @@ -61,10 +63,12 @@ module.exports = React.createClass({ } return ( <div className="mx_CreateRoom"> - <label>Room Name <RoomNameTextbox ref="name_textbox" /></label> - <Presets ref="presets"/> - <UserSelector ref="user_selector"/> - <CreateRoomButton onCreateRoom={this.onCreateRoom} /> + <RoomNameTextbox ref="name_textbox" /> <br /> + <Presets ref="presets"/> <br /> + <RoomTopic /> <br /> + <RoomAlias /> <br /> + <UserSelector ref="user_selector"/> <br /> + <CreateRoomButton onCreateRoom={this.onCreateRoom} /> <br /> {error_box} </div> ); diff --git a/skins/base/views/pages/MatrixChat.js b/skins/base/views/pages/MatrixChat.js index 27d1a115..4ab0e649 100644 --- a/skins/base/views/pages/MatrixChat.js +++ b/skins/base/views/pages/MatrixChat.js @@ -25,28 +25,44 @@ var RightPanel = ComponentBroker.get('organisms/RightPanel'); var Login = ComponentBroker.get('templates/Login'); var UserSettings = ComponentBroker.get('organisms/UserSettings'); var Register = ComponentBroker.get('templates/Register'); +var CreateRoom = ComponentBroker.get('organisms/CreateRoom'); var MatrixChatController = require("../../../../src/controllers/pages/MatrixChat"); // should be atomised var Loader = require("react-loader"); +var dis = require("../../../../src/dispatcher"); + module.exports = React.createClass({ displayName: 'MatrixChat', mixins: [MatrixChatController], + onRoomCreated: function(room_id) { + dis.dispatch({ + action: "view_room", + room_id: room_id, + }); + }, + render: function() { if (this.state.logged_in && this.state.ready) { var page_element; var right_panel = ""; - if (this.state.page_type == this.PageTypes.RoomView) { - page_element = <RoomView roomId={this.state.currentRoom} key={this.state.currentRoom} /> - right_panel = <RightPanel roomId={this.state.currentRoom} /> - } else if (this.state.page_type == this.PageTypes.UserSettings) { - page_element = <UserSettings /> + switch (this.state.page_type) { + case this.PageTypes.RoomView: + page_element = <RoomView roomId={this.state.currentRoom} key={this.state.currentRoom} /> + right_panel = <RightPanel roomId={this.state.currentRoom} /> + break; + case this.PageTypes.UserSettings: + page_element = <UserSettings /> + break; + case this.PageTypes.CreateRoom: + page_element = <CreateRoom onRoomCreated={this.onRoomCreated}/> + break; } return ( diff --git a/src/ComponentBroker.js b/src/ComponentBroker.js index dfbcf2e2..58e8f2ee 100644 --- a/src/ComponentBroker.js +++ b/src/ComponentBroker.js @@ -63,6 +63,8 @@ require('../skins/base/views/atoms/EnableNotificationsButton'); require('../skins/base/views/atoms/MessageTimestamp'); require('../skins/base/views/atoms/create_room/CreateRoomButton'); require('../skins/base/views/atoms/create_room/RoomNameTextbox'); +require('../skins/base/views/atoms/create_room/RoomTopic'); +require('../skins/base/views/atoms/create_room/RoomAlias'); require('../skins/base/views/atoms/create_room/Presets'); require('../skins/base/views/atoms/EditableText'); require('../skins/base/views/molecules/MatrixToolbar'); diff --git a/src/controllers/atoms/create_room/RoomAlias.js b/src/controllers/atoms/create_room/RoomAlias.js new file mode 100644 index 00000000..804b0b29 --- /dev/null +++ b/src/controllers/atoms/create_room/RoomAlias.js @@ -0,0 +1,41 @@ +/* +Copyright 2015 OpenMarket 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. +*/ + +'use strict'; + +var React = require('react'); + +module.exports = { + propTypes: { + default_alias: React.PropTypes.string + }, + + getDefaultProps: function() { + return { + default_alias: '', + }; + }, + + getInitialState: function() { + return { + room_alias: this.props.default_alias, + } + }, + + getAlias: function() { + return this.state.room_alias; + }, +}; diff --git a/src/controllers/atoms/create_room/RoomTopic.js b/src/controllers/atoms/create_room/RoomTopic.js new file mode 100644 index 00000000..cbd21b9b --- /dev/null +++ b/src/controllers/atoms/create_room/RoomTopic.js @@ -0,0 +1,41 @@ +/* +Copyright 2015 OpenMarket 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. +*/ + +'use strict'; + +var React = require('react'); + +module.exports = { + propTypes: { + default_topic: React.PropTypes.string + }, + + getDefaultProps: function() { + return { + default_topic: '', + }; + }, + + getInitialState: function() { + return { + room_topic: this.props.default_topic, + } + }, + + getTopic: function() { + return this.state.room_topic; + }, +}; diff --git a/src/controllers/organisms/CreateRoom.js b/src/controllers/organisms/CreateRoom.js index c2112ce5..048f3679 100644 --- a/src/controllers/organisms/CreateRoom.js +++ b/src/controllers/organisms/CreateRoom.js @@ -77,11 +77,11 @@ module.exports = { var self = this; - deferred.then(function () { + deferred.then(function (resp) { self.setState({ phase: self.phases.CREATED, }); - self.props.onRoomCreated(); + self.props.onRoomCreated(resp.room_id); }, function(err) { self.setState({ phase: self.phases.ERROR, diff --git a/src/controllers/pages/MatrixChat.js b/src/controllers/pages/MatrixChat.js index 9367872b..26bc6cf6 100644 --- a/src/controllers/pages/MatrixChat.js +++ b/src/controllers/pages/MatrixChat.js @@ -32,6 +32,11 @@ module.exports = { PageTypes: { RoomView: "room_view", UserSettings: "user_settings", + CreateRoom: "create_room", + }, + + AuxPanel: { + RoomSettings: "room_settings", }, getInitialState: function() { @@ -39,6 +44,7 @@ module.exports = { logged_in: !!(MatrixClientPeg.get() && MatrixClientPeg.get().credentials), ready: false, page_type: this.PageTypes.RoomView, + aux_panel: null, }; }, @@ -143,6 +149,11 @@ module.exports = { page_type: this.PageTypes.UserSettings, }); break; + case 'view_create_room': + this.setState({ + page_type: this.PageTypes.CreateRoom, + }); + break; } },