diff options
Diffstat (limited to 'web/react')
-rw-r--r-- | web/react/components/channel_header.jsx | 15 | ||||
-rw-r--r-- | web/react/components/mention_list.jsx | 6 | ||||
-rw-r--r-- | web/react/components/new_channel.jsx | 7 | ||||
-rw-r--r-- | web/react/components/post_list.jsx | 15 | ||||
-rw-r--r-- | web/react/components/setting_picture.jsx | 30 | ||||
-rw-r--r-- | web/react/components/sidebar_header.jsx | 117 | ||||
-rw-r--r-- | web/react/components/user_profile.jsx | 3 | ||||
-rw-r--r-- | web/react/components/user_settings.jsx | 107 | ||||
-rw-r--r-- | web/react/utils/constants.jsx | 2 |
9 files changed, 179 insertions, 123 deletions
diff --git a/web/react/components/channel_header.jsx b/web/react/components/channel_header.jsx index b6182cfa5..90a776791 100644 --- a/web/react/components/channel_header.jsx +++ b/web/react/components/channel_header.jsx @@ -67,7 +67,7 @@ var PopoverListMembers = React.createClass({ return ( <div id='member_popover' data-toggle='popover' data-content={popoverHtml} data-original-title='Members' > - <div id='member_tooltip' data-toggle='tooltip' title='View Channel Members'> + <div id='member_tooltip' data-placement='left' data-toggle='tooltip' title='View Channel Members'> {count} <span className='glyphicon glyphicon-user' aria-hidden='true'></span> </div> </div> @@ -175,6 +175,11 @@ module.exports = React.createClass({ } } + var channelTerm = 'Channel'; + if (channel.type === 'P') { + channelTerm = 'Group'; + } + return ( <table className='channel-header alt'> <tr> @@ -196,18 +201,18 @@ module.exports = React.createClass({ <li role='presentation'><a role='menuitem' data-toggle='modal' data-target='#channel_members' href='#'>Manage Members</a></li> : null } - <li role='presentation'><a role='menuitem' href='#' data-toggle='modal' data-target='#edit_channel' data-desc={channel.description} data-title={channel.display_name} data-channelid={channel.id}>Set Channel Description...</a></li> + <li role='presentation'><a role='menuitem' href='#' data-toggle='modal' data-target='#edit_channel' data-desc={channel.description} data-title={channel.display_name} data-channelid={channel.id}>Set {channelTerm} Description...</a></li> <li role='presentation'><a role='menuitem' href='#' data-toggle='modal' data-target='#channel_notifications' data-title={channel.display_name} data-channelid={channel.id}>Notification Preferences</a></li> {isAdmin && !ChannelStore.isDefault(channel) ? - <li role='presentation'><a role='menuitem' href='#' data-toggle='modal' data-target='#rename_channel' data-display={channel.display_name} data-name={channel.name} data-channelid={channel.id}>Rename Channel...</a></li> + <li role='presentation'><a role='menuitem' href='#' data-toggle='modal' data-target='#rename_channel' data-display={channel.display_name} data-name={channel.name} data-channelid={channel.id}>Rename {channelTerm}...</a></li> : null } {isAdmin && !ChannelStore.isDefault(channel) ? - <li role='presentation'><a role='menuitem' href='#' data-toggle='modal' data-target='#delete_channel' data-title={channel.display_name} data-channelid={channel.id}>Delete Channel...</a></li> + <li role='presentation'><a role='menuitem' href='#' data-toggle='modal' data-target='#delete_channel' data-title={channel.display_name} data-channelid={channel.id}>Delete {channelTerm}...</a></li> : null } {!ChannelStore.isDefault(channel) ? - <li role='presentation'><a role='menuitem' href='#' onClick={this.handleLeave}>Leave Channel</a></li> + <li role='presentation'><a role='menuitem' href='#' onClick={this.handleLeave}>Leave {channelTerm}</a></li> : null } </ul> diff --git a/web/react/components/mention_list.jsx b/web/react/components/mention_list.jsx index a0f68df98..5f1bb6d0e 100644 --- a/web/react/components/mention_list.jsx +++ b/web/react/components/mention_list.jsx @@ -20,6 +20,12 @@ module.exports = React.createClass({ PostStore.addMentionDataChangeListener(this.onListenerChange); var self = this; + $('.post-right__scroll').scroll(function(){ + if($('.mentions--top').length){ + $('#reply_mention_tab .mentions--top').css({ bottom: $(window).height() - $('.post-right__scroll #reply_textbox').offset().top }); + } + }); + $('body').on('keydown.mentionlist', '#' + this.props.id, function(e) { if (!self.isEmpty() && self.state.mentionText !== '-1' && (e.which === 13 || e.which === 9)) { diff --git a/web/react/components/new_channel.jsx b/web/react/components/new_channel.jsx index 93884f6eb..ffcbfd32d 100644 --- a/web/react/components/new_channel.jsx +++ b/web/react/components/new_channel.jsx @@ -107,6 +107,11 @@ module.exports = React.createClass({ serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>; } + var channelTerm = 'Channel'; + if (this.state.channelType === 'P') { + channelTerm = 'Group'; + } + return ( <div className='modal fade' id='new_channel' ref='modal' tabIndex='-1' role='dialog' aria-hidden='true'> <div className='modal-dialog'> @@ -116,7 +121,7 @@ module.exports = React.createClass({ <span aria-hidden='true'>×</span> <span className='sr-only'>Cancel</span> </button> - <h4 className='modal-title'>New Channel</h4> + <h4 className='modal-title'>New {channelTerm}</h4> </div> <form role='form'> <div className='modal-body'> diff --git a/web/react/components/post_list.jsx b/web/react/components/post_list.jsx index 3f59d5843..bb1b1704c 100644 --- a/web/react/components/post_list.jsx +++ b/web/react/components/post_list.jsx @@ -37,15 +37,23 @@ module.exports = React.createClass({ componentDidMount: function() { var user = UserStore.getCurrentUser(); if (user.props && user.props.theme) { - utils.changeCss('a.theme', 'color:'+user.props.theme+'; fill:'+user.props.theme+'!important;'); utils.changeCss('div.theme', 'background-color:'+user.props.theme+';'); utils.changeCss('.btn.btn-primary', 'background: ' + user.props.theme+';'); - utils.changeCss('.btn.btn-primary:hover, .btn.btn-primary:active, .btn.btn-primary:focus', 'background: ' + utils.changeColor(user.props.theme, -10) +';'); utils.changeCss('.modal .modal-header', 'background: ' + user.props.theme+';'); utils.changeCss('.mention', 'background: ' + user.props.theme+';'); utils.changeCss('.mention-link', 'color: ' + user.props.theme+';'); utils.changeCss('@media(max-width: 768px){.search-bar__container', 'background: ' + user.props.theme+';}'); } + if (user.props.theme != '#000000' && user.props.theme != '#585858') { + utils.changeCss('.btn.btn-primary:hover, .btn.btn-primary:active, .btn.btn-primary:focus', 'background: ' + utils.changeColor(user.props.theme, -10) +';'); + utils.changeCss('a.theme', 'color:'+user.props.theme+'; fill:'+user.props.theme+'!important;'); + } else if (user.props.theme == '#000000') { + utils.changeCss('.btn.btn-primary:hover, .btn.btn-primary:active, .btn.btn-primary:focus', 'background: ' + utils.changeColor(user.props.theme, +50) +';'); + $('.team__header').addClass('theme--black'); + } else if (user.props.theme == '#585858') { + utils.changeCss('.btn.btn-primary:hover, .btn.btn-primary:active, .btn.btn-primary:focus', 'background: ' + utils.changeColor(user.props.theme, +10) +';'); + $('.team__header').addClass('theme--gray'); + } PostStore.addChangeListener(this._onChange); ChannelStore.addChangeListener(this._onChange); @@ -311,7 +319,6 @@ module.exports = React.createClass({ } else if (channel.type === 'D') { var teammate = utils.getDirectTeammate(channel.id) - if (teammate) { var teammate_name = teammate.nickname.length > 0 ? teammate.nickname : teammate.username; more_messages = ( @@ -399,7 +406,7 @@ module.exports = React.createClass({ var postCtls = []; if (posts) { - var previousPostDay = posts[order[order.length-1]] ? utils.getDateForUnixTicks(posts[order[order.length-1]].create_at): new Date(); + var previousPostDay = new Date(0); var currentPostDay; for (var i = order.length-1; i >= 0; i--) { diff --git a/web/react/components/setting_picture.jsx b/web/react/components/setting_picture.jsx index fa4c8bb62..e97b67706 100644 --- a/web/react/components/setting_picture.jsx +++ b/web/react/components/setting_picture.jsx @@ -20,8 +20,14 @@ module.exports = React.createClass({ } }, render: function() { - var client_error = this.props.client_error ? <div className='form-group has-error'><label className='control-label'>{ this.props.client_error }</label></div> : null; - var server_error = this.props.server_error ? <div className='form-group has-error'><label className='control-label'>{ this.props.server_error }</label></div> : null; + var clientError = null; + if (this.props.client_error) { + clientError = <div className='form-group has-error'><label className='control-label'>{this.props.client_error}</label></div>; + } + var serverError = null; + if (this.props.server_error) { + serverError = <div className='form-group has-error'><label className='control-label'>{this.props.server_error}</label></div>; + } var img = null; if (this.props.picture) { @@ -30,8 +36,20 @@ module.exports = React.createClass({ img = (<img ref='image' className='profile-img' src={this.props.src}/>); } - var self = this; + var confirmButton; + if (this.props.loadingPicture) { + confirmButton = <img className='spinner' src='/static/images/load.gif'/>; + } else { + var confirmButtonClass = 'btn btn-sm'; + if (this.props.submitActive) { + confirmButtonClass += ' btn-primary'; + } else { + confirmButtonClass += ' btn-inactive disabled'; + } + confirmButton = <a className={confirmButtonClass} onClick={this.props.submit}>Save</a>; + } + var self = this; return ( <ul className='section-max'> <li className='col-xs-12 section-title'>{this.props.title}</li> @@ -41,10 +59,10 @@ module.exports = React.createClass({ {img} </li> <li className='setting-list-item'> - {server_error} - {client_error} + {serverError} + {clientError} <span className='btn btn-sm btn-primary btn-file sel-btn'>Select<input ref='input' accept='.jpg,.png,.bmp' type='file' onChange={this.props.pictureChange}/></span> - <a className={this.props.submitActive ? 'btn btn-sm btn-primary' : 'btn btn-sm btn-inactive disabled'} onClick={this.props.submit}>Save</a> + {confirmButton} <a className='btn btn-sm theme' href='#' onClick={self.props.updateSection}>Cancel</a> </li> </ul> diff --git a/web/react/components/sidebar_header.jsx b/web/react/components/sidebar_header.jsx index e01ddcd05..ba8f9bacd 100644 --- a/web/react/components/sidebar_header.jsx +++ b/web/react/components/sidebar_header.jsx @@ -1,15 +1,15 @@ // Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. // See License.txt for license information. - var utils = require('../utils/utils.jsx'); var client = require('../utils/client.jsx'); var UserStore = require('../stores/user_store.jsx'); +var TeamStore = require('../stores/team_store.jsx'); var Constants = require('../utils/constants.jsx'); function getStateFromStores() { - return { teams: UserStore.getTeams() }; + return {teams: UserStore.getTeams(), currentTeam: TeamStore.getCurrent()}; } var NavbarDropdown = React.createClass({ @@ -19,20 +19,24 @@ var NavbarDropdown = React.createClass({ }, blockToggle: false, componentDidMount: function() { - UserStore.addTeamsChangeListener(this._onChange); + UserStore.addTeamsChangeListener(this.onListenerChange); + TeamStore.addChangeListener(this.onListenerChange); var self = this; - $(this.refs.dropdown.getDOMNode()).on('hide.bs.dropdown', function(e) { + $(this.refs.dropdown.getDOMNode()).on('hide.bs.dropdown', function() { self.blockToggle = true; - setTimeout(function(){self.blockToggle = false;}, 100); + setTimeout(function() { + self.blockToggle = false; + }, 100); }); }, componentWillUnmount: function() { - UserStore.removeTeamsChangeListener(this._onChange); + UserStore.removeTeamsChangeListener(this.onListenerChange); + TeamStore.removeChangeListener(this.onListenerChange); $(this.refs.dropdown.getDOMNode()).off('hide.bs.dropdown'); }, - _onChange: function() { + onListenerChange: function() { if (this.isMounted()) { var newState = getStateFromStores(); if (!utils.areStatesEqual(newState, this.state)) { @@ -44,62 +48,65 @@ var NavbarDropdown = React.createClass({ return getStateFromStores(); }, render: function() { - var team_link = ""; - var invite_link = ""; - var manage_link = ""; - var rename_link = ""; + var teamLink = ''; + var inviteLink = ''; + var manageLink = ''; + var renameLink = ''; var currentUser = UserStore.getCurrentUser(); var isAdmin = false; + var teamSettings = null; if (currentUser != null) { - isAdmin = currentUser.roles.indexOf("admin") > -1; + isAdmin = currentUser.roles.indexOf('admin') > -1; - invite_link = ( <li> <a href="#" data-toggle="modal" data-target="#invite_member">Invite New Member</a> </li>); + inviteLink = (<li> <a href='#' data-toggle='modal' data-target='#invite_member'>Invite New Member</a> </li>); - if (this.props.teamType == "O") { - team_link = ( + if (this.props.teamType === 'O') { + teamLink = ( <li> - <a href="#" data-toggle="modal" data-target="#get_link" data-title="Team Invite" data-value={location.origin+"/signup_user_complete/?id="+currentUser.team_id}>Get Team Invite Link</a> + <a href='#' data-toggle='modal' data-target='#get_link' data-title='Team Invite' data-value={location.origin + '/signup_user_complete/?id=' + currentUser.team_id}>Get Team Invite Link</a> </li> ); } } if (isAdmin) { - manage_link = ( <li> <a href="#" data-toggle="modal" data-target="#team_members">Manage Team</a> </li>); - rename_link = ( <li> <a href="#" data-toggle="modal" data-target="#rename_team_link">Rename</a> </li>); + manageLink = (<li> <a href='#' data-toggle='modal' data-target='#team_members'>Manage Team</a> </li>); + renameLink = (<li> <a href='#' data-toggle='modal' data-target='#rename_team_link'>Rename</a> </li>); + teamSettings = (<li> <a href='#' data-toggle='modal' data-target='#team_settings'>Team Settings</a> </li>); } var teams = []; - teams.push(<li className="divider" key="div"></li>); - if (this.state.teams.length > 1) { - for (var i = 0; i < this.state.teams.length; i++) { - var teamName = this.state.teams[i]; - - teams.push(<li key={ teamName }><a href={utils.getWindowLocationOrigin() + "/" + teamName }>Switch to { teamName }</a></li>); - } + teams.push(<li className='divider' key='div'></li>); + if (this.state.teams.length > 1 && this.state.currentTeam) { + var curTeamName = this.state.currentTeam.name; + this.state.teams.forEach(function(teamName) { + if (teamName !== curTeamName) { + teams.push(<li key={teamName}><a href={utils.getWindowLocationOrigin() + '/' + teamName}>Switch to {teamName}</a></li>); + } + }); } - teams.push(<li><a href={utils.getWindowLocationOrigin() + "/signup_team" }>Create a New Team</a></li>); + teams.push(<li><a href={utils.getWindowLocationOrigin() + '/signup_team'}>Create a New Team</a></li>); return ( - <ul className="nav navbar-nav navbar-right"> - <li ref="dropdown" className="dropdown"> - <a href="#" className="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"> - <span className="dropdown__icon" dangerouslySetInnerHTML={{__html: Constants.MENU_ICON }} /> + <ul className='nav navbar-nav navbar-right'> + <li ref='dropdown' className='dropdown'> + <a href='#' className='dropdown-toggle' data-toggle='dropdown' role='button' aria-expanded='false'> + <span className='dropdown__icon' dangerouslySetInnerHTML={{__html: Constants.MENU_ICON}} /> </a> - <ul className="dropdown-menu" role="menu"> - <li><a href="#" data-toggle="modal" data-target="#user_settings1">Account Settings</a></li> - { isAdmin ? <li><a href="#" data-toggle="modal" data-target="#team_settings">Team Settings</a></li> : null } - { invite_link } - { team_link } - { manage_link } - { rename_link } - <li><a href="#" onClick={this.handleLogoutClick}>Logout</a></li> - { teams } - <li className="divider"></li> - <li><a target="_blank" href={config.HelpLink}>Help</a></li> - <li><a target="_blank" href={config.ReportProblemLink}>Report a Problem</a></li> + <ul className='dropdown-menu' role='menu'> + <li><a href='#' data-toggle='modal' data-target='#user_settings1'>Account Settings</a></li> + {teamSettings} + {inviteLink} + {teamLink} + {manageLink} + {renameLink} + <li><a href='#' onClick={this.handleLogoutClick}>Logout</a></li> + {teams} + <li className='divider'></li> + <li><a target='_blank' href={config.HelpLink}>Help</a></li> + <li><a target='_blank' href={config.ReportProblemLink}>Report a Problem</a></li> </ul> </li> </ul> @@ -109,14 +116,13 @@ var NavbarDropdown = React.createClass({ module.exports = React.createClass({ displayName: 'SidebarHeader', - getDefaultProps: function() { return { teamDisplayName: config.SiteName }; }, - toggleDropdown: function(e) { + toggleDropdown: function() { if (this.refs.dropdown.blockToggle) { this.refs.dropdown.blockToggle = false; return; @@ -126,25 +132,26 @@ module.exports = React.createClass({ render: function() { var me = UserStore.getCurrentUser(); + var profilePicture = null; if (!me) { return null; } + if (me.last_picture_update) { + profilePicture = (<img className='user__picture' src={'/api/v1/users/' + me.id + '/image?time=' + me.update_at} />); + } + return ( - <div className="team__header theme"> - <a href="#" onClick={this.toggleDropdown}> - { me.last_picture_update ? - <img className="user__picture" src={"/api/v1/users/" + me.id + "/image?time=" + me.update_at} /> - : - null - } - <div className="header__info"> - <div className="user__name">{ '@' + me.username}</div> - <div className="team__name">{ this.props.teamDisplayName }</div> + <div className='team__header theme'> + <a href='#' onClick={this.toggleDropdown}> + {profilePicture} + <div className='header__info'> + <div className='user__name'>{'@' + me.username}</div> + <div className='team__name'>{this.props.teamDisplayName }</div> </div> </a> - <NavbarDropdown ref="dropdown" teamType={this.props.teamType} /> + <NavbarDropdown ref='dropdown' teamType={this.props.teamType} /> </div> ); } diff --git a/web/react/components/user_profile.jsx b/web/react/components/user_profile.jsx index 65f025919..5c4d26a23 100644 --- a/web/react/components/user_profile.jsx +++ b/web/react/components/user_profile.jsx @@ -28,6 +28,7 @@ module.exports = React.createClass({ componentDidMount: function() { UserStore.addChangeListener(this._onChange); $("#profile_" + this.uniqueId).popover({placement : 'right', container: 'body', trigger: 'hover', html: true, delay: { "show": 200, "hide": 100 }}); + $('body').tooltip( {selector: '[data-toggle=tooltip]', trigger: 'hover click'} ); }, componentWillUnmount: function() { UserStore.removeChangeListener(this._onChange); @@ -57,7 +58,7 @@ module.exports = React.createClass({ if (!config.ShowEmail) { data_content += "<div class='text-nowrap'>Email not shared</div>"; } else { - data_content += "<div><a href='mailto:" + this.state.profile.email + "' class='text-nowrap text-lowercase'>" + this.state.profile.email + "</a></div>"; + data_content += "<div data-toggle='tooltip' title= '" + this.state.profile.email + "'><a href='mailto:" + this.state.profile.email + "' class='text-nowrap text-lowercase user-popover__email'>" + this.state.profile.email + "</a></div>"; } return ( diff --git a/web/react/components/user_settings.jsx b/web/react/components/user_settings.jsx index c574d2365..e224f2a87 100644 --- a/web/react/components/user_settings.jsx +++ b/web/react/components/user_settings.jsx @@ -5,8 +5,6 @@ var UserStore = require('../stores/user_store.jsx'); var SettingItemMin = require('./setting_item_min.jsx'); var SettingItemMax = require('./setting_item_max.jsx'); var SettingPicture = require('./setting_picture.jsx'); -var AccessHistoryModal = require('./access_history_modal.jsx'); -var ActivityLogModal = require('./activity_log_modal.jsx'); var client = require('../utils/client.jsx'); var AsyncClient = require('../utils/async_client.jsx'); var utils = require('../utils/utils.jsx'); @@ -642,17 +640,17 @@ var GeneralTab = React.createClass({ var user = this.props.user; var username = this.state.username.trim(); - var username_error = utils.isValidUsername(username); - if (username_error === 'Cannot use a reserved word as a username.') { - this.setState({client_error: 'This username is reserved, please choose a new one.' }); + var usernameError = utils.isValidUsername(username); + if (usernameError === 'Cannot use a reserved word as a username.') { + this.setState({clientError: 'This username is reserved, please choose a new one.'}); return; - } else if (username_error) { - this.setState({client_error: "Username must begin with a letter, and contain between 3 to 15 lowercase characters made up of numbers, letters, and the symbols '.', '-' and '_'." }); + } else if (usernameError) { + this.setState({clientError: "Username must begin with a letter, and contain between 3 to 15 lowercase characters made up of numbers, letters, and the symbols '.', '-' and '_'."}); return; } if (user.username === username) { - this.setState({client_error: 'You must submit a new username'}); + this.setState({clientError: 'You must submit a new username'}); return; } @@ -667,7 +665,7 @@ var GeneralTab = React.createClass({ var nickname = this.state.nickname.trim(); if (user.nickname === nickname) { - this.setState({client_error: 'You must submit a new nickname'}) + this.setState({clientError: 'You must submit a new nickname'}); return; } @@ -679,11 +677,11 @@ var GeneralTab = React.createClass({ e.preventDefault(); var user = UserStore.getCurrentUser(); - var firstName = this.state.first_name.trim(); - var lastName = this.state.last_name.trim(); + var firstName = this.state.firstName.trim(); + var lastName = this.state.lastName.trim(); if (user.first_name === firstName && user.last_name === lastName) { - this.setState({client_error: 'You must submit a new first or last name'}) + this.setState({clientError: 'You must submit a new first or last name'}); return; } @@ -703,7 +701,7 @@ var GeneralTab = React.createClass({ } if (email === '' || !utils.isEmail(email)) { - this.setState({ email_error: 'Please enter a valid email address' }); + this.setState({emailError: 'Please enter a valid email address'}); return; } @@ -718,11 +716,11 @@ var GeneralTab = React.createClass({ AsyncClient.getMe(); }.bind(this), function(err) { - state = this.getInitialState(); + var state = this.getInitialState(); if (err.message) { - state.server_error = err.message; + state.serverError = err.message; } else { - state.server_error = err; + state.serverError = err; } this.setState(state); }.bind(this) @@ -742,12 +740,13 @@ var GeneralTab = React.createClass({ var picture = this.state.picture; if (picture.type !== 'image/jpeg' && picture.type !== 'image/png') { - this.setState({client_error: 'Only JPG or PNG images may be used for profile pictures'}); + this.setState({clientError: 'Only JPG or PNG images may be used for profile pictures'}); return; } var formData = new FormData(); formData.append('image', picture, picture.name); + this.setState({loadingPicture: true}); client.uploadProfileImage(formData, function() { @@ -756,8 +755,8 @@ var GeneralTab = React.createClass({ window.location.reload(); }.bind(this), function(err) { - state = this.getInitialState(); - state.server_error = err; + var state = this.getInitialState(); + state.serverError = err; this.setState(state); }.bind(this) ); @@ -766,10 +765,10 @@ var GeneralTab = React.createClass({ this.setState({username: e.target.value}); }, updateFirstName: function(e) { - this.setState({first_name: e.target.value}); + this.setState({firstName: e.target.value}); }, updateLastName: function(e) { - this.setState({last_name: e.target.value}); + this.setState({lastName: e.target.value}); }, updateNickname: function(e) { this.setState({nickname: e.target.value}); @@ -779,17 +778,16 @@ var GeneralTab = React.createClass({ }, updatePicture: function(e) { if (e.target.files && e.target.files[0]) { - this.setState({ picture: e.target.files[0] }); + this.setState({picture: e.target.files[0]}); this.submitActive = true; - this.setState({client_error: null}); - + this.setState({clientError: null}); } else { this.setState({picture: null}); } }, updateSection: function(section) { - this.setState({client_error:''}); + this.setState({clientError: ''}); this.submitActive = false; this.props.updateSection(section); }, @@ -798,7 +796,7 @@ var GeneralTab = React.createClass({ this.value = ''; }); - this.setState(assign({}, this.getInitialState(), {client_error: null, server_error: null, email_error: null})); + this.setState(assign({}, this.getInitialState(), {clientError: null, serverError: null, emailError: null})); this.props.updateSection(''); }, componentDidMount: function() { @@ -810,15 +808,24 @@ var GeneralTab = React.createClass({ getInitialState: function() { var user = this.props.user; - return { username: user.username, first_name: user.first_name, last_name: user.last_name, nickname: user.nickname, - email: user.email, picture: null }; + return {username: user.username, firstName: user.first_name, lastName: user.last_name, nickname: user.nickname, + email: user.email, picture: null, loadingPicture: false}; }, render: function() { var user = this.props.user; - 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 email_error = this.state.email_error ? this.state.email_error : null; + var clientError = null; + if (this.state.clientError) { + clientError = this.state.clientError; + } + var serverError = null; + if (this.state.serverError) { + serverError = this.state.serverError; + } + var emailError = null; + if (this.state.emailError) { + emailError = this.state.emailError; + } var nameSection; var self = this; @@ -829,7 +836,7 @@ var GeneralTab = React.createClass({ <div className='form-group'> <label className='col-sm-5 control-label'>First Name</label> <div className='col-sm-7'> - <input className='form-control' type='text' onChange={this.updateFirstName} value={this.state.first_name}/> + <input className='form-control' type='text' onChange={this.updateFirstName} value={this.state.firstName}/> </div> </div> ); @@ -838,7 +845,7 @@ var GeneralTab = React.createClass({ <div className='form-group'> <label className='col-sm-5 control-label'>Last Name</label> <div className='col-sm-7'> - <input className='form-control' type='text' onChange={this.updateLastName} value={this.state.last_name}/> + <input className='form-control' type='text' onChange={this.updateLastName} value={this.state.lastName}/> </div> </div> ); @@ -848,8 +855,8 @@ var GeneralTab = React.createClass({ title='Full Name' inputs={inputs} submit={this.submitName} - server_error={server_error} - client_error={client_error} + server_error={serverError} + client_error={clientError} updateSection={function(e) { self.updateSection(''); e.preventDefault(); @@ -857,20 +864,20 @@ var GeneralTab = React.createClass({ /> ); } else { - var full_name = ''; + var fullName = ''; if (user.first_name && user.last_name) { - full_name = user.first_name + ' ' + user.last_name; + fullName = user.first_name + ' ' + user.last_name; } else if (user.first_name) { - full_name = user.first_name; + fullName = user.first_name; } else if (user.last_name) { - full_name = user.last_name; + fullName = user.last_name; } nameSection = ( <SettingItemMin title='Full Name' - describe={full_name} + describe={fullName} updateSection={function() { self.updateSection('name'); }} @@ -880,7 +887,6 @@ var GeneralTab = React.createClass({ var nicknameSection; if (this.props.activeSection === 'nickname') { - inputs.push( <div className='form-group'> <label className='col-sm-5 control-label'>{utils.isMobile() ? '' : 'Nickname'}</label> @@ -895,8 +901,8 @@ var GeneralTab = React.createClass({ title='Nickname' inputs={inputs} submit={this.submitNickname} - server_error={server_error} - client_error={client_error} + server_error={serverError} + client_error={clientError} updateSection={function(e) { self.updateSection(''); e.preventDefault(); @@ -919,7 +925,7 @@ var GeneralTab = React.createClass({ if (this.props.activeSection === 'username') { inputs.push( <div className='form-group'> - <label className='col-sm-5 control-label'>{utils.isMobile() ? '': 'Username'}</label> + <label className='col-sm-5 control-label'>{utils.isMobile() ? '' : 'Username'}</label> <div className='col-sm-7'> <input className='form-control' type='text' onChange={this.updateUsername} value={this.state.username}/> </div> @@ -931,8 +937,8 @@ var GeneralTab = React.createClass({ title='Username' inputs={inputs} submit={this.submitUsername} - server_error={server_error} - client_error={client_error} + server_error={serverError} + client_error={clientError} updateSection={function(e) { self.updateSection(''); e.preventDefault(); @@ -966,8 +972,8 @@ var GeneralTab = React.createClass({ title='Email' inputs={inputs} submit={this.submitEmail} - server_error={server_error} - client_error={email_error} + server_error={serverError} + client_error={emailError} updateSection={function(e) { self.updateSection(''); e.preventDefault(); @@ -993,8 +999,8 @@ var GeneralTab = React.createClass({ title='Profile Picture' submit={this.submitPicture} src={'/api/v1/users/' + user.id + '/image?time=' + user.last_picture_update} - server_error={server_error} - client_error={client_error} + server_error={serverError} + client_error={clientError} updateSection={function(e) { self.updateSection(''); e.preventDefault(); @@ -1002,6 +1008,7 @@ var GeneralTab = React.createClass({ picture={this.state.picture} pictureChange={this.updatePicture} submitActive={this.submitActive} + loadingPicture={this.state.loadingPicture} /> ); } else { diff --git a/web/react/utils/constants.jsx b/web/react/utils/constants.jsx index 2b0976afd..bed0ec556 100644 --- a/web/react/utils/constants.jsx +++ b/web/react/utils/constants.jsx @@ -82,7 +82,7 @@ module.exports = { "channel", ], MONTHS: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], - MAX_DMS: 10, + MAX_DMS: 20, ONLINE_ICON_SVG: "<svg version='1.1' id='Layer_1' xmlns:dc='http://purl.org/dc/elements/1.1/' xmlns:cc='http://creativecommons.org/ns#' xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns:svg='http://www.w3.org/2000/svg' xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd' xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape' sodipodi:docname='TRASH_1_4.svg' inkscape:version='0.48.4 r9939' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' width='12px' height='12px' viewBox='0 0 12 12' enable-background='new 0 0 12 12' xml:space='preserve'><sodipodi:namedview inkscape:cy='139.7898' inkscape:cx='26.358185' inkscape:zoom='1.18' showguides='true' showgrid='false' id='namedview6' guidetolerance='10' gridtolerance='10' objecttolerance='10' borderopacity='1' bordercolor='#666666' pagecolor='#ffffff' inkscape:current-layer='Layer_1' inkscape:window-maximized='1' inkscape:window-y='-8' inkscape:window-x='-8' inkscape:window-height='705' inkscape:window-width='1366' inkscape:guide-bbox='true' inkscape:pageshadow='2' inkscape:pageopacity='0'><sodipodi:guide position='50.036793,85.991376' orientation='1,0' id='guide2986'></sodipodi:guide><sodipodi:guide position='58.426196,66.216355' orientation='0,1' id='guide3047'></sodipodi:guide></sodipodi:namedview><g><g><path class='online--icon' d='M6,5.487c1.371,0,2.482-1.116,2.482-2.493c0-1.378-1.111-2.495-2.482-2.495S3.518,1.616,3.518,2.994C3.518,4.371,4.629,5.487,6,5.487z M10.452,8.545c-0.101-0.829-0.36-1.968-0.726-2.541C9.475,5.606,8.5,5.5,8.5,5.5S8.43,7.521,6,7.521C3.507,7.521,3.5,5.5,3.5,5.5S2.527,5.606,2.273,6.004C1.908,6.577,1.648,7.716,1.547,8.545C1.521,8.688,1.49,9.082,1.498,9.142c0.161,1.295,2.238,2.322,4.375,2.358C5.916,11.501,5.958,11.501,6,11.501c0.043,0,0.084,0,0.127-0.001c2.076-0.026,4.214-1.063,4.375-2.358C10.509,9.082,10.471,8.696,10.452,8.545z'/></g></g></svg>", OFFLINE_ICON_SVG: "<svg version='1.1' id='Layer_1' xmlns:dc='http://purl.org/dc/elements/1.1/' xmlns:cc='http://creativecommons.org/ns#' xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns:svg='http://www.w3.org/2000/svg' xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd' xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape' sodipodi:docname='TRASH_1_4.svg' inkscape:version='0.48.4 r9939' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' width='12px' height='12px' viewBox='0 0 12 12' enable-background='new 0 0 12 12' xml:space='preserve'><sodipodi:namedview inkscape:cy='139.7898' inkscape:cx='26.358185' inkscape:zoom='1.18' showguides='true' showgrid='false' id='namedview6' guidetolerance='10' gridtolerance='10' objecttolerance='10' borderopacity='1' bordercolor='#666666' pagecolor='#ffffff' inkscape:current-layer='Layer_1' inkscape:window-maximized='1' inkscape:window-y='-8' inkscape:window-x='-8' inkscape:window-height='705' inkscape:window-width='1366' inkscape:guide-bbox='true' inkscape:pageshadow='2' inkscape:pageopacity='0'><sodipodi:guide position='50.036793,85.991376' orientation='1,0' id='guide2986'></sodipodi:guide><sodipodi:guide position='58.426196,66.216355' orientation='0,1' id='guide3047'></sodipodi:guide></sodipodi:namedview><g><g><path fill='#cccccc' d='M6.002,7.143C5.645,7.363,5.167,7.52,4.502,7.52c-2.493,0-2.5-2.02-2.5-2.02S1.029,5.607,0.775,6.004C0.41,6.577,0.15,7.716,0.049,8.545c-0.025,0.145-0.057,0.537-0.05,0.598c0.162,1.295,2.237,2.321,4.375,2.357c0.043,0.001,0.085,0.001,0.127,0.001c0.043,0,0.084,0,0.127-0.001c1.879-0.023,3.793-0.879,4.263-2h-2.89L6.002,7.143L6.002,7.143z M4.501,5.488c1.372,0,2.483-1.117,2.483-2.494c0-1.378-1.111-2.495-2.483-2.495c-1.371,0-2.481,1.117-2.481,2.495C2.02,4.371,3.13,5.488,4.501,5.488z M7.002,6.5v2h5v-2H7.002z'/></g></g></svg>", MENU_ICON: "<svg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px'width='4px' height='16px' viewBox='0 0 8 32' enable-background='new 0 0 8 32' xml:space='preserve'> <g> <circle cx='4' cy='4.062' r='4'/> <circle cx='4' cy='16' r='4'/> <circle cx='4' cy='28' r='4'/> </g> </svg>", |