From bf82facd5afd6e2c71845f5732654069554c3a16 Mon Sep 17 00:00:00 2001 From: Reed Garmsen Date: Fri, 21 Aug 2015 16:36:53 -0700 Subject: Moved the ability to rename a team into the team settings modal; fixed issues with valet settings --- web/react/components/rename_team_modal.jsx | 95 -------------- web/react/components/sidebar_header.jsx | 3 - web/react/components/team_feature_tab.jsx | 65 ++++++---- web/react/components/team_general_tab.jsx | 180 +++++++++++++++++++++++++++ web/react/components/team_settings.jsx | 10 +- web/react/components/team_settings_modal.jsx | 9 +- 6 files changed, 235 insertions(+), 127 deletions(-) delete mode 100644 web/react/components/rename_team_modal.jsx create mode 100644 web/react/components/team_general_tab.jsx (limited to 'web/react/components') diff --git a/web/react/components/rename_team_modal.jsx b/web/react/components/rename_team_modal.jsx deleted file mode 100644 index bebdd6662..000000000 --- a/web/react/components/rename_team_modal.jsx +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. -// See License.txt for license information. - -var Client = require('../utils/client.jsx'); -var utils = require('../utils/utils.jsx'); - -module.exports = React.createClass({ - handleSubmit: function(e) { - e.preventDefault(); - - var state = { server_error: "" }; - var valid = true; - - var name = this.state.name.trim(); - if (!name) { - state.name_error = "This field is required"; - valid = false; - } else { - state.name_error = ""; - } - - this.setState(state); - - if (!valid) - return; - - if (this.props.teamDisplayName === name) - return; - - var data = {}; - data["new_name"] = name; - - Client.updateTeamDisplayName(data, - function(data) { - $('#rename_team_link').modal('hide'); - window.location.reload(); - }.bind(this), - function(err) { - state.server_error = err.message; - this.setState(state); - }.bind(this) - ); - }, - onNameChange: function() { - this.setState({ name: this.refs.name.getDOMNode().value }) - }, - handleClose: function() { - this.setState({ name: this.props.teamDisplayName, name_error: "", server_error: ""}); - }, - componentDidMount: function() { - $(this.refs.modal.getDOMNode()).on('hidden.bs.modal', this.handleClose); - }, - componentWillUnmount: function() { - $(this.refs.modal.getDOMNode()).off('hidden.bs.modal', this.handleClose); - }, - getInitialState: function() { - return { name: this.props.teamDisplayName }; - }, - render: function() { - - var name_error = this.state.name_error ? : null; - var server_error = this.state.server_error ?
: null; - - return ( - - ); - } -}); - diff --git a/web/react/components/sidebar_header.jsx b/web/react/components/sidebar_header.jsx index 761c06e74..d5d16816f 100644 --- a/web/react/components/sidebar_header.jsx +++ b/web/react/components/sidebar_header.jsx @@ -51,7 +51,6 @@ var NavbarDropdown = React.createClass({ var teamLink = ''; var inviteLink = ''; var manageLink = ''; - var renameLink = ''; var currentUser = UserStore.getCurrentUser(); var isAdmin = false; var teamSettings = null; @@ -72,7 +71,6 @@ var NavbarDropdown = React.createClass({ if (isAdmin) { manageLink = (
  • Manage Team
  • ); - renameLink = (
  • Rename
  • ); teamSettings = (
  • Team Settings
  • ); } @@ -101,7 +99,6 @@ var NavbarDropdown = React.createClass({ {inviteLink} {teamLink} {manageLink} - {renameLink}
  • Logout
  • {teams}
  • diff --git a/web/react/components/team_feature_tab.jsx b/web/react/components/team_feature_tab.jsx index 4f28d84c6..4f8f0b2cf 100644 --- a/web/react/components/team_feature_tab.jsx +++ b/web/react/components/team_feature_tab.jsx @@ -16,7 +16,7 @@ module.exports = React.createClass({ }, submitValetFeature: function() { var data = {}; - data.allowValet = this.state.allowValet; + data.allow_valet = this.state.allowValet; client.updateValetFeature(data, function() { @@ -38,7 +38,7 @@ module.exports = React.createClass({ var team = newProps.team; var allowValet = 'false'; - if (team && team.allowValet) { + if (team && team.allow_valet) { allowValet = 'true'; } @@ -48,17 +48,18 @@ module.exports = React.createClass({ var team = this.props.team; var allowValet = 'false'; - if (team && team.allowValet) { + if (team && team.allow_valet) { allowValet = 'true'; } return {allowValet: allowValet}; }, - onUpdateSection: function() { + onUpdateSection: function(e) { + e.preventDefault(); if (this.props.activeSection === 'valet') { - self.props.updateSection('valet'); + this.props.updateSection(''); } else { - self.props.updateSection(''); + this.props.updateSection('valet'); } }, render: function() { @@ -75,31 +76,43 @@ module.exports = React.createClass({ var self = this; if (this.props.activeSection === 'valet') { - var valetActive = ['', '']; + var valetActive = [false, false]; if (this.state.allowValet === 'false') { - valetActive[1] = 'active'; + valetActive[1] = true; } else { - valetActive[0] = 'active'; + valetActive[0] = true; } - var inputs = []; - - function valetActivate() { - self.handleValetRadio('true'); - } - - function valetDeactivate() { - self.handleValetRadio('false'); - } + let inputs = []; inputs.push( -
    -
    - - +
    +
    + +
    -

    Valet is a preview feature for enabling a non-user account limited to basic member permissions that can be manipulated by 3rd parties.

    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.
    -
    +
    + +
    +
    +

    Valet is a preview feature for enabling a non-user account limited to basic member permissions that can be manipulated by 3rd parties.

    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.
    +
    ); valetSection = ( @@ -107,8 +120,8 @@ module.exports = React.createClass({ title='Valet (Preview - EXPERTS ONLY)' inputs={inputs} submit={this.submitValetFeature} - serverError={serverError} - clientError={clientError} + server_error={serverError} + client_error={clientError} updateSection={this.onUpdateSection} /> ); diff --git a/web/react/components/team_general_tab.jsx b/web/react/components/team_general_tab.jsx new file mode 100644 index 000000000..fd2a22731 --- /dev/null +++ b/web/react/components/team_general_tab.jsx @@ -0,0 +1,180 @@ +// 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 utils = require('../utils/utils.jsx'); + +export default class GeneralTab extends React.Component { + constructor(props) { + super(props); + + this.handleNameSubmit = this.handleNameSubmit.bind(this); + this.handleClose = this.handleClose.bind(this); + this.onUpdateSection = this.onUpdateSection.bind(this); + this.updateName = this.updateName.bind(this); + + this.state = {name: this.props.teamDisplayName, serverError: '', clientError: ''}; + } + handleNameSubmit(e) { + e.preventDefault(); + + var state = {serverError: '', clientError: ''}; + var valid = true; + + var name = this.state.name.trim(); + if (!name) { + state.clientError = 'This field is required'; + valid = false; + } else if (name === this.props.teamDisplayName) { + state.clientError = 'Please choose a new name for your ' + strings.Team; + valid = false; + } else { + state.clientError = ''; + } + + this.setState(state); + + if (!valid) { + return; + } + + var data = {}; + data.new_name = name; + + client.updateTeamDisplayName(data, + function nameChangeSuccess() { + this.props.updateSection(''); + $('#team_settings').modal('hide'); + window.location.reload(); + }.bind(this), + function nameChangeFail(err) { + state.serverError = err.message; + this.setState(state); + }.bind(this) + ); + } + componentWillReceiveProps(newProps) { + if (newProps.team && newProps.teamDisplayName) { + this.setState({name: newProps.teamDisplayName}); + } + } + handleClose() { + this.setState({clientError: '', serverError: ''}); + this.props.updateSection(''); + } + componentDidMount() { + $('#team_settings').on('hidden.bs.modal', this.handleClose); + } + componentWillUnmount() { + $('#team_settings').off('hidden.bs.modal', this.handleClose); + } + onUpdateSection(e) { + e.preventDefault(); + if (this.props.activeSection === 'name') { + this.props.updateSection(''); + } else { + this.props.updateSection('name'); + } + } + updateName(e) { + e.preventDefault(); + this.setState({name: e.target.value}); + } + render() { + var clientError = null; + var serverError = null; + if (this.state.clientError) { + clientError = this.state.clientError; + } + if (this.state.serverError) { + serverError = this.state.serverError; + } + + var nameSection; + + if (this.props.activeSection === 'name') { + let inputs = []; + + let teamNameLabel = utils.toTitleCase(strings.Team) + ' Name'; + if (utils.isMobile()) { + teamNameLabel = ''; + } + + inputs.push( +
    + +
    + +
    +
    + ); + + nameSection = ( + + ); + } else { + let describe = this.state.name; + + nameSection = ( + + ); + } + + return ( +
    +
    + +

    + + General Settings +

    +
    +
    +

    General Settings

    +
    + {nameSection} +
    +
    +
    + ); + } +} + +GeneralTab.propTypes = { + updateSection: React.PropTypes.func.isRequired, + team: React.PropTypes.object.isRequired, + activeSection: React.PropTypes.string.isRequired, + teamDisplayName: React.PropTypes.string.isRequired +}; diff --git a/web/react/components/team_settings.jsx b/web/react/components/team_settings.jsx index 94d536651..1a79eef1d 100644 --- a/web/react/components/team_settings.jsx +++ b/web/react/components/team_settings.jsx @@ -4,6 +4,7 @@ var TeamStore = require('../stores/team_store.jsx'); var ImportTab = require('./team_import_tab.jsx'); var FeatureTab = require('./team_feature_tab.jsx'); +var GeneralTab = require('./team_general_tab.jsx'); var utils = require('../utils/utils.jsx'); module.exports = React.createClass({ @@ -11,7 +12,8 @@ module.exports = React.createClass({ propTypes: { activeTab: React.PropTypes.string.isRequired, activeSection: React.PropTypes.string.isRequired, - updateSection: React.PropTypes.func.isRequired + updateSection: React.PropTypes.func.isRequired, + teamDisplayName: React.PropTypes.string.isRequired }, componentDidMount: function() { TeamStore.addChangeListener(this.onChange); @@ -34,6 +36,12 @@ module.exports = React.createClass({ case 'general': result = (
    +
    ); break; diff --git a/web/react/components/team_settings_modal.jsx b/web/react/components/team_settings_modal.jsx index ef2564de0..7e65e8cab 100644 --- a/web/react/components/team_settings_modal.jsx +++ b/web/react/components/team_settings_modal.jsx @@ -6,6 +6,9 @@ var TeamSettings = require('./team_settings.jsx'); module.exports = React.createClass({ displayName: 'Team Settings Modal', + propTypes: { + teamDisplayName: React.PropTypes.string.isRequired + }, componentDidMount: function() { $('body').on('click', '.modal-back', function onClick() { $(this).closest('.modal-dialog').removeClass('display--content'); @@ -17,16 +20,17 @@ module.exports = React.createClass({ }); }, updateTab: function(tab) { - this.setState({activeTab: tab}); + this.setState({activeTab: tab, activeSection: ''}); }, updateSection: function(section) { this.setState({activeSection: section}); }, getInitialState: function() { - return {activeTab: 'feature', activeSection: ''}; + return {activeTab: 'general', activeSection: ''}; }, render: function() { var tabs = []; + tabs.push({name: 'general', uiName: 'General', icon: 'glyphicon glyphicon-cog'}); tabs.push({name: 'import', uiName: 'Import', icon: 'glyphicon glyphicon-upload'}); tabs.push({name: 'feature', uiName: 'Advanced', icon: 'glyphicon glyphicon-wrench'}); @@ -52,6 +56,7 @@ module.exports = React.createClass({ activeTab={this.state.activeTab} activeSection={this.state.activeSection} updateSection={this.updateSection} + teamDisplayName={this.props.teamDisplayName} />
    -- cgit v1.2.3-1-g7c22