From 5f7ab2d9a2f9ebdda35a5c687f9d4d037ec0a4ab Mon Sep 17 00:00:00 2001 From: Jonas Schwabe Date: Sun, 25 Dec 2016 16:44:44 +0100 Subject: [PATCH] Add an add team button to the TabBar --- src/browser/components/MainPage.jsx | 30 +++++++ src/browser/components/NewTeamModal.jsx | 115 ++++++++++++++++++++++++ src/browser/components/TabBar.jsx | 17 +++- src/browser/config/AppConfig.js | 12 +++ src/browser/css/index.css | 13 +++ src/browser/index.jsx | 11 +-- 6 files changed, 187 insertions(+), 11 deletions(-) create mode 100644 src/browser/components/NewTeamModal.jsx create mode 100644 src/browser/config/AppConfig.js diff --git a/src/browser/components/MainPage.jsx b/src/browser/components/MainPage.jsx index cd58cad9..83689b91 100644 --- a/src/browser/components/MainPage.jsx +++ b/src/browser/components/MainPage.jsx @@ -10,6 +10,8 @@ const MattermostView = require('./MattermostView.jsx'); const TabBar = require('./TabBar.jsx'); const HoveringURL = require('./HoveringURL.jsx'); +const NewTeamModal = require('./NewTeamModal.jsx'); + // Todo: Need to consider better way to apply styles const styles = { hoveringURL: { @@ -237,6 +239,11 @@ const MainPage = React.createClass({ this.setState({targetURL}); } }, + addTeam() { + this.setState({ + showNewTeamModal: true + }); + }, render() { var self = this; @@ -253,6 +260,7 @@ const MainPage = React.createClass({ mentionAtActiveCounts={this.state.mentionAtActiveCounts} activeKey={this.state.key} onSelect={this.handleSelect} + onAddTeam={this.addTeam} /> ); @@ -296,6 +304,25 @@ const MainPage = React.createClass({ authServerURL = `${tmpURL.protocol}//${tmpURL.host}`; authInfo = this.state.loginQueue[0].authInfo; } + var modal; + if (this.state.showNewTeamModal) { + modal = ( + { + this.setState({ + showNewTeamModal: false + }); + }} + onSave={(newTeam) => { + this.setState({ + showNewTeamModal: false + }); + this.props.teams.push(newTeam); + this.render(); + }} + /> + ); + } return (
} +
+ { modal } +
); } diff --git a/src/browser/components/NewTeamModal.jsx b/src/browser/components/NewTeamModal.jsx new file mode 100644 index 00000000..1dd9427b --- /dev/null +++ b/src/browser/components/NewTeamModal.jsx @@ -0,0 +1,115 @@ +const React = require('react'); +const {Modal, Button, FormGroup, FormControl, ControlLabel, HelpBlock} = require('react-bootstrap'); +const validUrl = require('valid-url'); + +class NewTeamModal extends React.Component { + + constructor() { + super(); + this.state = { + teamName: '', + teamUrl: '' + }; + } + + shouldComponentUpdate() { + return true; + } + + getTeamNameValidationState() { + return this.state.teamName.length > 0 ? '' : 'error'; + } + + handleTeamNameChange(e) { + this.setState({ + teamName: e.target.value + }); + } + + getTeamUrlValidationState() { + if (this.state.teamUrl.length === 0) { + return 'error'; + } + if (!validUrl.isUri(this.state.teamUrl)) { + return 'error'; + } + return ''; + } + + handleTeamUrlChange(e) { + this.setState({ + teamUrl: e.target.value + }); + } + + validateForm() { + return this.getTeamNameValidationState() === '' && + this.getTeamUrlValidationState() === ''; + } + + render() { + return ( + + + {'Add a new Team'} + + + + {'Please specify a team name and a valid Mattermost URL'} +
+ + {'Team Display Name'} + + + {'Team Name must not be empty'} + + + {'Team URL'} + + + {'Must be a valid URL'} + +
+
+ + + + + + +
+ ); + } +} + +NewTeamModal.propTypes = { + onClose: React.PropTypes.func, + onSave: React.PropTypes.func +}; + +module.exports = NewTeamModal; diff --git a/src/browser/components/TabBar.jsx b/src/browser/components/TabBar.jsx index 4282bd2e..afaf596a 100644 --- a/src/browser/components/TabBar.jsx +++ b/src/browser/components/TabBar.jsx @@ -1,5 +1,5 @@ const React = require('react'); -const {Nav, NavItem} = require('react-bootstrap'); +const {Nav, NavItem, Button} = require('react-bootstrap'); class TabBar extends React.Component { render() { @@ -75,16 +75,29 @@ class TabBar extends React.Component { onSelect={this.props.onSelect} > { tabs } + { this.renderAddTeamButton() } ); } + + renderAddTeamButton() { + return ( + + ); + } } TabBar.propTypes = { activeKey: React.PropTypes.number, id: React.PropTypes.string, onSelect: React.PropTypes.func, - teams: React.PropTypes.array + teams: React.PropTypes.array, + onAddTeam: React.PropTypes.func }; module.exports = TabBar; diff --git a/src/browser/config/AppConfig.js b/src/browser/config/AppConfig.js new file mode 100644 index 00000000..06496970 --- /dev/null +++ b/src/browser/config/AppConfig.js @@ -0,0 +1,12 @@ +const settings = require('../../common/settings'); +const {remote} = require('electron'); + +var config; +try { + const configFile = remote.app.getPath('userData') + '/config.json'; + config = settings.readFileSync(configFile); +} catch (e) { + config = {}; +} + +module.exports = config; diff --git a/src/browser/css/index.css b/src/browser/css/index.css index b0c13b5b..30e6d530 100644 --- a/src/browser/css/index.css +++ b/src/browser/css/index.css @@ -16,3 +16,16 @@ opacity: 0.01; transition: opacity 500ms ease-in-out; } + +.btn-tabButton { + margin-top: 3px; + color: #333; + background-color: #fff; + border-color: #ccc; +} + +.btn-tabButton:hover { + color: #333; + background-color: #e6e6e6; + border-color: #adadad; +} diff --git a/src/browser/index.jsx b/src/browser/index.jsx index aa236382..1c051744 100644 --- a/src/browser/index.jsx +++ b/src/browser/index.jsx @@ -9,19 +9,12 @@ const ReactDOM = require('react-dom'); const {remote, ipcRenderer} = require('electron'); const MainPage = require('./components/MainPage.jsx'); -const settings = require('../common/settings'); +const AppConfig = require('./config/AppConfig.js'); const badge = require('./js/badge'); remote.getCurrentWindow().removeAllListeners('focus'); -var config; -try { - const configFile = remote.app.getPath('userData') + '/config.json'; - config = settings.readFileSync(configFile); -} catch (e) { - window.location = 'settings.html'; -} -if (config.teams.length === 0) { +if (AppConfig.teams.length === 0) { window.location = 'settings.html'; }