summaryrefslogtreecommitdiffstats
path: root/web/react/components
diff options
context:
space:
mode:
Diffstat (limited to 'web/react/components')
-rw-r--r--web/react/components/setting_item_max.jsx4
-rw-r--r--web/react/components/settings_sidebar.jsx2
-rw-r--r--web/react/components/team_feature_tab.jsx147
-rw-r--r--web/react/components/team_import_tab.jsx68
-rw-r--r--web/react/components/team_settings.jsx245
-rw-r--r--web/react/components/team_settings_modal.jsx43
6 files changed, 278 insertions, 231 deletions
diff --git a/web/react/components/setting_item_max.jsx b/web/react/components/setting_item_max.jsx
index 49eb58773..d3d386534 100644
--- a/web/react/components/setting_item_max.jsx
+++ b/web/react/components/setting_item_max.jsx
@@ -3,7 +3,7 @@
module.exports = React.createClass({
render: function() {
- var client_error = this.props.client_error ? <div className='form-group'><label className='col-sm-12 has-error'>{ this.props.client_error }</label></div> : null;
+ var clientError = this.props.clientError ? <div className='form-group'><label className='col-sm-12 has-error'>{ this.props.clientError }</label></div> : null;
var server_error = this.props.server_error ? <div className='form-group'><label className='col-sm-12 has-error'>{ this.props.server_error }</label></div> : null;
var inputs = this.props.inputs;
@@ -19,7 +19,7 @@ module.exports = React.createClass({
<li className="setting-list-item">
<hr />
{ server_error }
- { client_error }
+ { clientError }
{ this.props.submit ? <a className="btn btn-sm btn-primary" onClick={this.props.submit}>Submit</a> : "" }
<a className="btn btn-sm theme" href="#" onClick={this.props.updateSection}>Cancel</a>
</li>
diff --git a/web/react/components/settings_sidebar.jsx b/web/react/components/settings_sidebar.jsx
index b4d291622..d8091ec28 100644
--- a/web/react/components/settings_sidebar.jsx
+++ b/web/react/components/settings_sidebar.jsx
@@ -15,7 +15,7 @@ module.exports = React.createClass({
<div className="">
<ul className="nav nav-pills nav-stacked">
{this.props.tabs.map(function(tab) {
- return <li key={tab.name+'_li'} className={self.props.activeTab == tab.name ? 'active' : ''}><a key={tab.name + '_a'} href="#" onClick={function(){self.updateTab(tab.name);}}><i key={tab.name+'_i'} className={tab.icon}></i>{tab.ui_name}</a></li>
+ return <li key={tab.name+'_li'} className={self.props.activeTab == tab.name ? 'active' : ''}><a key={tab.name + '_a'} href="#" onClick={function(){self.updateTab(tab.name);}}><i key={tab.name+'_i'} className={tab.icon}></i>{tab.uiName}</a></li>
})}
</ul>
</div>
diff --git a/web/react/components/team_feature_tab.jsx b/web/react/components/team_feature_tab.jsx
new file mode 100644
index 000000000..ee0bfa874
--- /dev/null
+++ b/web/react/components/team_feature_tab.jsx
@@ -0,0 +1,147 @@
+// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+var SettingItemMin = require('./setting_item_min.jsx');
+var SettingItemMax = require('./setting_item_max.jsx');
+
+var client = require('../utils/client.jsx');
+var AsyncClient = require('../utils/async_client.jsx');
+
+module.exports = React.createClass({
+ displayName: 'Feature Tab',
+ propTypes: {
+ updateSection: React.PropTypes.func.isRequired,
+ team: React.PropTypes.object.isRequired,
+ activeSection: React.PropTypes.string.isRequired
+ },
+ submitValetFeature: function() {
+ var data = {};
+ data.allowValet = this.state.allowValet;
+
+ client.updateValetFeature(data,
+ function() {
+ this.props.updateSection('');
+ AsyncClient.getMyTeam();
+ }.bind(this),
+ function(err) {
+ var state = this.getInitialState();
+ state.serverError = err;
+ this.setState(state);
+ }.bind(this)
+ );
+ },
+ handleValetRadio: function(val) {
+ this.setState({allowValet: val});
+ this.refs.wrapper.getDOMNode().focus();
+ },
+ componentWillReceiveProps: function(newProps) {
+ var team = newProps.team;
+
+ var allowValet = 'false';
+ if (team && team.allowValet) {
+ allowValet = 'true';
+ }
+
+ this.setState({allowValet: allowValet});
+ },
+ getInitialState: function() {
+ var team = this.props.team;
+
+ var allowValet = 'false';
+ if (team && team.allowValet) {
+ allowValet = 'true';
+ }
+
+ return {allowValet: allowValet};
+ },
+ onUpdateSection: function() {
+ if (this.props.activeSection === 'valet') {
+ self.props.updateSection('valet');
+ } else {
+ self.props.updateSection('');
+ }
+ },
+ render: function() {
+ var clientError = null;
+ var serverError = null;
+ if (this.state.clientError) {
+ clientError = this.state.clientError;
+ }
+ if (this.state.serverError) {
+ serverError = this.state.serverError;
+ }
+
+ var valetSection;
+ var self = this;
+
+ if (this.props.activeSection === 'valet') {
+ var valetActive = ['', ''];
+ if (this.state.allowValet === 'false') {
+ valetActive[1] = 'active';
+ } else {
+ valetActive[0] = 'active';
+ }
+
+ var inputs = [];
+
+ function valetActivate() {
+ self.handleValetRadio('true');
+ }
+
+ function valetDeactivate() {
+ self.handleValetRadio('false');
+ }
+
+ inputs.push(
+ <div>
+ <div className='btn-group' data-toggle='buttons-radio'>
+ <button className={'btn btn-default ' + valetActive[0]} onClick={valetActivate}>On</button>
+ <button className={'btn btn-default ' + valetActive[1]} onClick={valetDeactivate}>Off</button>
+ </div>
+ <div><br/>Valet is a preview feature for enabling a non-user account limited to basic member permissions that can be manipulated by 3rd parties.<br/><br/>IMPORTANT: The preview version of Valet should not be used without a secure connection and a trusted 3rd party, since user credentials are used to connect. OAuth2 will be used in the final release.</div>
+ </div>
+ );
+
+ valetSection = (
+ <SettingItemMax
+ title='Valet (Preview - EXPERTS ONLY)'
+ inputs={inputs}
+ submit={this.submitValetFeature}
+ serverError={serverError}
+ clientError={clientError}
+ updateSection={this.onUpdateSection}
+ />
+ );
+ } else {
+ var describe = '';
+ if (this.state.allowValet === 'false') {
+ describe = 'Off';
+ } else {
+ describe = 'On';
+ }
+
+ valetSection = (
+ <SettingItemMin
+ title='Valet (Preview - EXPERTS ONLY)'
+ describe={describe}
+ updateSection={this.onUpdateSection}
+ />
+ );
+ }
+
+ return (
+ <div>
+ <div className='modal-header'>
+ <button type='button' className='close' data-dismiss='modal' aria-label='Close'><span aria-hidden='true'>&times;</span></button>
+ <h4 className='modal-title' ref='title'><i className='modal-back'></i>Feature Settings</h4>
+ </div>
+ <div ref='wrapper' className='user-settings'>
+ <h3 className='tab-header'>Feature Settings</h3>
+ <div className='divider-dark first'/>
+ {valetSection}
+ <div className='divider-dark'/>
+ </div>
+ </div>
+ );
+ }
+});
diff --git a/web/react/components/team_import_tab.jsx b/web/react/components/team_import_tab.jsx
new file mode 100644
index 000000000..131add999
--- /dev/null
+++ b/web/react/components/team_import_tab.jsx
@@ -0,0 +1,68 @@
+// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+var utils = require('../utils/utils.jsx');
+var SettingUpload = require('./setting_upload.jsx');
+
+module.exports = React.createClass({
+ displayName: 'Import Tab',
+ getInitialState: function() {
+ return {status: 'ready', link: ''};
+ },
+ onImportFailure: function() {
+ this.setState({status: 'fail', link: ''});
+ },
+ onImportSuccess: function(data) {
+ this.setState({status: 'done', link: 'data:application/octet-stream;charset=utf-8,' + encodeURIComponent(data)});
+ },
+ doImportSlack: function(file) {
+ this.setState({status: 'in-progress', link: ''});
+ utils.importSlack(file, this.onImportSuccess, this.onImportFailure);
+ },
+ render: function() {
+ var uploadSection = (
+ <SettingUpload
+ title='Import from Slack'
+ submit={this.doImportSlack}
+ fileTypesAccepted='.zip'/>
+ );
+
+ var messageSection;
+ switch (this.state.status) {
+ case 'ready':
+ messageSection = '';
+ break;
+ case 'in-progress':
+ messageSection = (
+ <p>Importing...</p>
+ );
+ break;
+ case 'done':
+ messageSection = (
+ <p>Import sucessfull: <a href={this.state.link} download='MattermostImportSummery.txt'>View Summery</a></p>
+ );
+ break;
+ case 'fail':
+ messageSection = (
+ <p>Import failure: <a href={this.state.link} download='MattermostImportSummery.txt'>View Summery</a></p>
+ );
+ break;
+ }
+
+ return (
+ <div>
+ <div className='modal-header'>
+ <button type='button' className='close' data-dismiss='modal' aria-label='Close'><span aria-hidden='true'>&times;</span></button>
+ <h4 className='modal-title' ref='title'><i className='modal-back'></i>Import</h4>
+ </div>
+ <div ref='wrapper' className='user-settings'>
+ <h3 className='tab-header'>Import</h3>
+ <div className='divider-dark first'/>
+ {uploadSection}
+ {messageSection}
+ <div className='divider-dark'/>
+ </div>
+ </div>
+ );
+ }
+});
diff --git a/web/react/components/team_settings.jsx b/web/react/components/team_settings.jsx
index 433ec9177..94d536651 100644
--- a/web/react/components/team_settings.jsx
+++ b/web/react/components/team_settings.jsx
@@ -1,231 +1,62 @@
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
// See License.txt for license information.
-var UserStore = require('../stores/user_store.jsx');
var TeamStore = require('../stores/team_store.jsx');
-var SettingItemMin = require('./setting_item_min.jsx');
-var SettingItemMax = require('./setting_item_max.jsx');
-var SettingPicture = require('./setting_picture.jsx');
-var SettingUpload = require('./setting_upload.jsx');
+var ImportTab = require('./team_import_tab.jsx');
+var FeatureTab = require('./team_feature_tab.jsx');
var utils = require('../utils/utils.jsx');
-var client = require('../utils/client.jsx');
-var AsyncClient = require('../utils/async_client.jsx');
-var Constants = require('../utils/constants.jsx');
-
-var FeatureTab = React.createClass({
- submitValetFeature: function() {
- data = {};
- data['allow_valet'] = this.state.allow_valet;
-
- client.updateValetFeature(data,
- function(data) {
- this.props.updateSection("");
- AsyncClient.getMyTeam();
- }.bind(this),
- function(err) {
- state = this.getInitialState();
- state.server_error = err;
- this.setState(state);
- }.bind(this)
- );
+module.exports = React.createClass({
+ displayName: 'Team Settings',
+ propTypes: {
+ activeTab: React.PropTypes.string.isRequired,
+ activeSection: React.PropTypes.string.isRequired,
+ updateSection: React.PropTypes.func.isRequired
},
- handleValetRadio: function(val) {
- this.setState({ allow_valet: val });
- this.refs.wrapper.getDOMNode().focus();
+ componentDidMount: function() {
+ TeamStore.addChangeListener(this.onChange);
},
- componentWillReceiveProps: function(newProps) {
- var team = newProps.team;
-
- var allow_valet = "false";
- if (team && team.allow_valet) {
- allow_valet = "true";
- }
-
- this.setState({ allow_valet: allow_valet });
+ componentWillUnmount: function() {
+ TeamStore.removeChangeListener(this.onChange);
},
- getInitialState: function() {
- var team = this.props.team;
-
- var allow_valet = "false";
- if (team && team.allow_valet) {
- allow_valet = "true";
+ onChange: function() {
+ var team = TeamStore.getCurrent();
+ if (!utils.areStatesEqual(this.state.team, team)) {
+ this.setState({team: team});
}
-
- return { allow_valet: allow_valet };
},
- render: function() {
- var team = this.props.team;
-
- var client_error = this.state.client_error ? this.state.client_error : null;
- var server_error = this.state.server_error ? this.state.server_error : null;
-
- var valetSection;
- var self = this;
-
- if (this.props.activeSection === 'valet') {
- var valetActive = ["",""];
- if (this.state.allow_valet === "false") {
- valetActive[1] = "active";
- } else {
- valetActive[0] = "active";
- }
-
- var inputs = [];
-
- inputs.push(
- <div>
- <div className="btn-group" data-toggle="buttons-radio">
- <button className={"btn btn-default "+valetActive[0]} onClick={function(){self.handleValetRadio("true")}}>On</button>
- <button className={"btn btn-default "+valetActive[1]} onClick={function(){self.handleValetRadio("false")}}>Off</button>
- </div>
- <div><br/>Valet is a preview feature for enabling a non-user account limited to basic member permissions that can be manipulated by 3rd parties.<br/><br/>IMPORTANT: The preview version of Valet should not be used without a secure connection and a trusted 3rd party, since user credentials are used to connect. OAuth2 will be used in the final release.</div>
- </div>
- );
-
- valetSection = (
- <SettingItemMax
- title="Valet (Preview - EXPERTS ONLY)"
- inputs={inputs}
- submit={this.submitValetFeature}
- server_error={server_error}
- client_error={client_error}
- updateSection={function(e){self.props.updateSection("");e.preventDefault();}}
- />
- );
- } else {
- var describe = "";
- if (this.state.allow_valet === "false") {
- describe = "Off";
- } else {
- describe = "On";
- }
-
- valetSection = (
- <SettingItemMin
- title="Valet (Preview - EXPERTS ONLY)"
- describe={describe}
- updateSection={function(){self.props.updateSection("valet");}}
- />
- );
- }
-
- return (
- <div>
- <div className="modal-header">
- <button type="button" className="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
- <h4 className="modal-title" ref="title"><i className="modal-back"></i>Feature Settings</h4>
- </div>
- <div ref="wrapper" className="user-settings">
- <h3 className="tab-header">Feature Settings</h3>
- <div className="divider-dark first"/>
- {valetSection}
- <div className="divider-dark"/>
- </div>
- </div>
- );
- }
-});
-
-var ImportTab = React.createClass({
getInitialState: function() {
- return {status: 'ready'};
- },
- onImportFailure: function() {
- this.setState({status: 'fail'});
- },
- onImportSuccess: function(data) {
- this.setState({status: 'done'});
- },
- doImportSlack: function(file) {
- this.setState({status: 'in-progress'});
- utils.importSlack(file, this.onImportSuccess, this.onImportFailure);
+ return {team: TeamStore.getCurrent()};
},
render: function() {
-
- uploadSection = (
- <SettingUpload
- title="Import from Slack"
- submit={this.doImportSlack}
- fileTypesAccepted='.zip'/>
- );
-
- var messageSection;
- switch (this.state.status) {
- case 'ready':
- messageSection = '';
+ var result;
+ switch (this.props.activeTab) {
+ case 'general':
+ result = (
+ <div>
+ </div>
+ );
break;
- case 'in-progress':
- messageSection = (
- <p>Importing...</p>
+ case 'feature':
+ result = (
+ <div>
+ <FeatureTab team={this.state.team} activeSection={this.props.activeSection} updateSection={this.props.updateSection} />
+ </div>
);
break;
- case 'done':
- messageSection = (
- <p>Import sucessfull: <a href={this.state.link} download='MattermostImportSummery.txt'>View Summery</a></p>
+ case 'import':
+ result = (
+ <div>
+ <ImportTab team={this.state.team} activeSection={this.props.activeSection} updateSection={this.props.updateSection} />
+ </div>
);
break;
- case 'fail':
- messageSection = (
- <p>Import failure: <a href={this.state.link} download='MattermostImportSummery.txt'>View Summery</a></p>
+ default:
+ result = (
+ <div/>
);
break;
}
-
- return (
- <div>
- <div className="modal-header">
- <button type="button" className="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
- <h4 className="modal-title" ref="title"><i className="modal-back"></i>Import</h4>
- </div>
- <div ref="wrapper" className="user-settings">
- <h3 className="tab-header">Import</h3>
- <div className="divider-dark first"/>
- {uploadSection}
- {messageSection}
- <div className="divider-dark"/>
- </div>
- </div>
- );
- }
-});
-
-module.exports = React.createClass({
- componentDidMount: function() {
- TeamStore.addChangeListener(this._onChange);
- },
- componentWillUnmount: function() {
- TeamStore.removeChangeListener(this._onChange);
- },
- _onChange: function () {
- var team = TeamStore.getCurrent();
- if (!utils.areStatesEqual(this.state.team, team)) {
- this.setState({ team: team });
- }
- },
- getInitialState: function() {
- return { team: TeamStore.getCurrent() };
- },
- render: function() {
- if (this.props.activeTab === 'general') {
- return (
- <div>
- </div>
- );
- } else if (this.props.activeTab === 'feature') {
- return (
- <div>
- <FeatureTab team={this.state.team} activeSection={this.props.activeSection} updateSection={this.props.updateSection} />
- </div>
- );
- } else if (this.props.activeTab === 'import') {
- return (
- <div>
- <ImportTab team={this.state.team} activeSection={this.props.activeSection} updateSection={this.props.updateSection} />
- </div>
- );
- } else {
- return <div/>;
- }
+ return result;
}
});
diff --git a/web/react/components/team_settings_modal.jsx b/web/react/components/team_settings_modal.jsx
index f935daf82..c9f479a22 100644
--- a/web/react/components/team_settings_modal.jsx
+++ b/web/react/components/team_settings_modal.jsx
@@ -5,51 +5,52 @@ var SettingsSidebar = require('./settings_sidebar.jsx');
var TeamSettings = require('./team_settings.jsx');
module.exports = React.createClass({
+ displayName: 'Team Settings Modal',
componentDidMount: function() {
- $('body').on('click', '.modal-back', function(){
+ $('body').on('click', '.modal-back', function onClick() {
$(this).closest('.modal-dialog').removeClass('display--content');
});
- $('body').on('click', '.modal-header .close', function(){
- setTimeout(function() {
+ $('body').on('click', '.modal-header .close', function onClick() {
+ setTimeout(function removeContent() {
$('.modal-dialog.display--content').removeClass('display--content');
}, 500);
});
},
updateTab: function(tab) {
- this.setState({ active_tab: tab });
+ this.setState({activeTab: tab});
},
updateSection: function(section) {
- this.setState({ active_section: section });
+ this.setState({activeSection: section});
},
getInitialState: function() {
- return { active_tab: "feature", active_section: "" };
+ return {activeTab: 'feature', activeSection: ''};
},
render: function() {
var tabs = [];
- tabs.push({name: "feature", ui_name: "Features", icon: "glyphicon glyphicon-wrench"});
- tabs.push({name: "import", ui_name: "Import", icon: "glyphicon glyphicon-upload"});
+ tabs.push({name: 'feature', uiName: 'Features', icon: 'glyphicon glyphicon-wrench'});
+ tabs.push({name: 'import', uiName: 'Import', icon: 'glyphicon glyphicon-upload'});
return (
- <div className="modal fade" ref="modal" id="team_settings" role="dialog" tabIndex="-1" aria-hidden="true">
- <div className="modal-dialog settings-modal">
- <div className="modal-content">
- <div className="modal-header">
- <button type="button" className="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
- <h4 className="modal-title" ref="title">Team Settings</h4>
+ <div className='modal fade' ref='modal' id='team_settings' role='dialog' tabIndex='-1' aria-hidden='true'>
+ <div className='modal-dialog settings-modal'>
+ <div className='modal-content'>
+ <div className='modal-header'>
+ <button type='button' className='close' data-dismiss='modal' aria-label='Close'><span aria-hidden='true'>&times;</span></button>
+ <h4 className='modal-title' ref='title'>Team Settings</h4>
</div>
- <div className="modal-body">
- <div className="settings-table">
- <div className="settings-links">
+ <div className='modal-body'>
+ <div className='settings-table'>
+ <div className='settings-links'>
<SettingsSidebar
tabs={tabs}
- activeTab={this.state.active_tab}
+ activeTab={this.state.activeTab}
updateTab={this.updateTab}
/>
</div>
- <div className="settings-content minimize-settings">
+ <div className='settings-content minimize-settings'>
<TeamSettings
- activeTab={this.state.active_tab}
- activeSection={this.state.active_section}
+ activeTab={this.state.activeTab}
+ activeSection={this.state.activeSection}
updateSection={this.updateSection}
/>
</div>