diff options
Diffstat (limited to 'web/react/components')
-rw-r--r-- | web/react/components/channel_header.jsx | 2 | ||||
-rw-r--r-- | web/react/components/channel_loader.jsx | 1 | ||||
-rw-r--r-- | web/react/components/confirm_modal.jsx | 31 | ||||
-rw-r--r-- | web/react/components/create_comment.jsx | 2 | ||||
-rw-r--r-- | web/react/components/create_post.jsx | 6 | ||||
-rw-r--r-- | web/react/components/invite_member_modal.jsx | 120 | ||||
-rw-r--r-- | web/react/components/navbar.jsx | 2 | ||||
-rw-r--r-- | web/react/components/post_body.jsx | 16 | ||||
-rw-r--r-- | web/react/components/settings_sidebar.jsx | 13 | ||||
-rw-r--r-- | web/react/components/sidebar_header.jsx | 3 | ||||
-rw-r--r-- | web/react/components/sidebar_right_menu.jsx | 2 | ||||
-rw-r--r-- | web/react/components/team_settings.jsx | 161 | ||||
-rw-r--r-- | web/react/components/team_settings_modal.jsx (renamed from web/react/components/settings_modal.jsx) | 14 | ||||
-rw-r--r-- | web/react/components/user_settings.jsx | 9 | ||||
-rw-r--r-- | web/react/components/user_settings_modal.jsx | 68 | ||||
-rw-r--r-- | web/react/components/view_image.jsx | 2 |
16 files changed, 380 insertions, 72 deletions
diff --git a/web/react/components/channel_header.jsx b/web/react/components/channel_header.jsx index 006c168ba..ade58a10a 100644 --- a/web/react/components/channel_header.jsx +++ b/web/react/components/channel_header.jsx @@ -201,7 +201,7 @@ module.exports = React.createClass({ </a> <ul className="dropdown-menu" role="menu" aria-labelledby="channel_header_dropdown"> <li role="presentation"><a role="menuitem" data-toggle="modal" data-target="#channel_info" data-channelid={this.state.channel.id} href="#">View Info</a></li> - <li role="presentation"><a role="menuitem" data-toggle="modal" data-target="#channel_invite" href="#">Invite Members</a></li> + <li role="presentation"><a role="menuitem" data-toggle="modal" data-target="#channel_invite" href="#">Add Members</a></li> { isAdmin ? <li role="presentation"><a role="menuitem" data-toggle="modal" data-target="#channel_members" href="#">Manage Members</a></li> : "" diff --git a/web/react/components/channel_loader.jsx b/web/react/components/channel_loader.jsx index 5252f275c..537a41d03 100644 --- a/web/react/components/channel_loader.jsx +++ b/web/react/components/channel_loader.jsx @@ -18,6 +18,7 @@ module.exports = React.createClass({ AsyncClient.getChannelExtraInfo(true); AsyncClient.findTeams(); AsyncClient.getStatuses(); + AsyncClient.getMyTeam(); /* End of async loads */ diff --git a/web/react/components/confirm_modal.jsx b/web/react/components/confirm_modal.jsx new file mode 100644 index 000000000..3be13cf9b --- /dev/null +++ b/web/react/components/confirm_modal.jsx @@ -0,0 +1,31 @@ +// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. +// See License.txt for license information. + +module.exports = React.createClass({ + handleConfirm: function() { + $('#'+this.props.parent_id).attr('data-confirm', 'true'); + $('#'+this.props.parent_id).modal('hide'); + $('#'+this.props.id).modal('hide'); + }, + render: function() { + return ( + <div className="modal fade" id={this.props.id} tabIndex="-1" role="dialog" aria-hidden="true"> + <div className="modal-dialog"> + <div className="modal-content"> + <div className="modal-header"> + <h4 className="modal-title">{this.props.title}</h4> + </div> + <div className="modal-body"> + {this.props.message} + </div> + <div className="modal-footer"> + <button type="button" className="btn btn-default" data-dismiss="modal">Cancel</button> + <button onClick={this.handleConfirm} type="button" className="btn btn-primary">{this.props.confirm_button}</button> + </div> + </div> + </div> + </div> + ); + } +}); + diff --git a/web/react/components/create_comment.jsx b/web/react/components/create_comment.jsx index 9bcbad079..cb7aa371c 100644 --- a/web/react/components/create_comment.jsx +++ b/web/react/components/create_comment.jsx @@ -145,7 +145,7 @@ module.exports = React.createClass({ onUserInput={this.handleUserInput} onKeyPress={this.commentMsgKeyPress} messageText={this.state.messageText} - createMessage="Create a comment..." + createMessage="Add a comment..." initialText="" id="reply_textbox" ref="textbox" /> diff --git a/web/react/components/create_post.jsx b/web/react/components/create_post.jsx index 191be9bf8..5a0b6f85f 100644 --- a/web/react/components/create_post.jsx +++ b/web/react/components/create_post.jsx @@ -31,9 +31,7 @@ module.exports = React.createClass({ post.message = this.state.messageText; - var repRegex = new RegExp("<br>", "g"); - if (post.message.replace(repRegex, " ").trim().length === 0 - && this.state.previews.length === 0) { + if (post.message.trim().length === 0 && this.state.previews.length === 0) { return; } @@ -250,7 +248,7 @@ module.exports = React.createClass({ onUserInput={this.handleUserInput} onKeyPress={this.postMsgKeyPress} messageText={this.state.messageText} - createMessage="Create a post..." + createMessage="Write a message..." channelId={this.state.channel_id} id="post_textbox" ref="textbox" /> diff --git a/web/react/components/invite_member_modal.jsx b/web/react/components/invite_member_modal.jsx index 1d2bbed84..5980664de 100644 --- a/web/react/components/invite_member_modal.jsx +++ b/web/react/components/invite_member_modal.jsx @@ -4,8 +4,37 @@ var utils = require('../utils/utils.jsx'); var Client =require('../utils/client.jsx'); var UserStore = require('../stores/user_store.jsx'); +var ConfirmModal = require('./confirm_modal.jsx'); module.exports = React.createClass({ + componentDidMount: function() { + var self = this; + $('#invite_member').on('hide.bs.modal', function(e) { + if ($('#invite_member').attr('data-confirm') === 'true') { + $('#invite_member').attr('data-confirm', 'false'); + return; + } + + var not_empty = false; + for (var i = 0; i < self.state.invite_ids.length; i++) { + var index = self.state.invite_ids[i]; + if (self.refs["email"+index].getDOMNode().value.trim() !== '') { + not_empty = true; + break; + } + } + + if (not_empty) { + $('#confirm_invite_modal').modal('show'); + e.preventDefault(); + } + + }); + + $('#invite_member').on('hidden.bs.modal', function() { + self.clearFields(); + }); + }, handleSubmit: function(e) { var invite_ids = this.state.invite_ids; var count = invite_ids.length; @@ -56,22 +85,8 @@ module.exports = React.createClass({ Client.inviteMembers(data, function() { + $(this.refs.modal.getDOMNode()).attr('data-confirm', 'true'); $(this.refs.modal.getDOMNode()).modal('hide'); - for (var i = 0; i < invite_ids.length; i++) { - var index = invite_ids[i]; - this.refs["email"+index].getDOMNode().value = ""; - if (config.AllowInviteNames) { - this.refs["first_name"+index].getDOMNode().value = ""; - this.refs["last_name"+index].getDOMNode().value = ""; - } - } - this.setState({ - invite_ids: [0], - id_count: 0, - email_errors: {}, - first_name_errors: {}, - last_name_errors: {} - }); }.bind(this), function(err) { this.setState({ server_error: err }); @@ -89,6 +104,26 @@ module.exports = React.createClass({ invite_ids.push(count); this.setState({ invite_ids: invite_ids, id_count: count }); }, + clearFields: function() { + var invite_ids = this.state.invite_ids; + + for (var i = 0; i < invite_ids.length; i++) { + var index = invite_ids[i]; + this.refs["email"+index].getDOMNode().value = ""; + if (config.AllowInviteNames) { + this.refs["first_name"+index].getDOMNode().value = ""; + this.refs["last_name"+index].getDOMNode().value = ""; + } + } + + this.setState({ + invite_ids: [0], + id_count: 0, + email_errors: {}, + first_name_errors: {}, + last_name_errors: {} + }); + }, removeInviteFields: function(index) { var invite_ids = this.state.invite_ids; var i = invite_ids.indexOf(index); @@ -147,29 +182,38 @@ module.exports = React.createClass({ var server_error = this.state.server_error ? <div className='form-group has-error'><label className='control-label'>{ this.state.server_error }</label></div> : null; return ( - <div className="modal fade" ref="modal" id="invite_member" tabIndex="-1" role="dialog" aria-hidden="true"> - <div className="modal-dialog"> - <div className="modal-content"> - <div className="modal-header"> - <button type="button" className="close" data-dismiss="modal" aria-label="Close" data-reactid=".5.0.0.0.0"><span aria-hidden="true" data-reactid=".5.0.0.0.0.0">×</span></button> - <h4 className="modal-title" id="myModalLabel">Invite New Member</h4> - </div> - <div ref="modalBody" className="modal-body"> - <form role="form"> - { invite_sections } - </form> - { server_error } - <button type="button" className="btn btn-default" onClick={this.addInviteFields}>Add another</button> - <br/> - <br/> - <label className='control-label'>People invited automatically join Town Square channel.</label> - </div> - <div className="modal-footer"> - <button type="button" className="btn btn-default" data-dismiss="modal">Close</button> - <button onClick={this.handleSubmit} type="button" className="btn btn-primary">Send Invitations</button> - </div> - </div> - </div> + <div> + <div className="modal fade" ref="modal" id="invite_member" tabIndex="-1" role="dialog" aria-hidden="true"> + <div className="modal-dialog"> + <div className="modal-content"> + <div className="modal-header"> + <button type="button" className="close" data-dismiss="modal" aria-label="Close" data-reactid=".5.0.0.0.0"><span aria-hidden="true" data-reactid=".5.0.0.0.0.0">×</span></button> + <h4 className="modal-title" id="myModalLabel">Invite New Member</h4> + </div> + <div ref="modalBody" className="modal-body"> + <form role="form"> + { invite_sections } + </form> + { server_error } + <button type="button" className="btn btn-default" onClick={this.addInviteFields}>Add another</button> + <br/> + <br/> + <label className='control-label'>People invited automatically join Town Square channel.</label> + </div> + <div className="modal-footer"> + <button type="button" className="btn btn-default" data-dismiss="modal">Close</button> + <button onClick={this.handleSubmit} type="button" className="btn btn-primary">Send Invitations</button> + </div> + </div> + </div> + </div> + <ConfirmModal + id="confirm_invite_modal" + parent_id="invite_member" + title="Discard Invitations?" + message="You have unsent invitations, are you sure you want to discard them?" + confirm_button="Yes, Discard" + /> </div> ); } else { diff --git a/web/react/components/navbar.jsx b/web/react/components/navbar.jsx index 3821c2772..35f7d9044 100644 --- a/web/react/components/navbar.jsx +++ b/web/react/components/navbar.jsx @@ -301,7 +301,7 @@ module.exports = React.createClass({ <span className="glyphicon glyphicon-chevron-down header-dropdown__icon"></span> </a> <ul className="dropdown-menu" role="menu" aria-labelledby="channel_header_dropdown"> - <li role="presentation"><a role="menuitem" data-toggle="modal" data-target="#channel_invite" href="#">Invite Members</a></li> + <li role="presentation"><a role="menuitem" data-toggle="modal" data-target="#channel_invite" href="#">Add Members</a></li> { isAdmin ? <li role="presentation"><a role="menuitem" data-toggle="modal" data-target="#channel_members" href="#">Manage Members</a></li> : "" diff --git a/web/react/components/post_body.jsx b/web/react/components/post_body.jsx index 55fc32c33..3079917ec 100644 --- a/web/react/components/post_body.jsx +++ b/web/react/components/post_body.jsx @@ -85,20 +85,22 @@ module.exports = React.createClass({ var postFiles = []; var images = []; if (filenames) { - for (var i = 0; i < filenames.length && i < Constants.MAX_DISPLAY_FILES; i++) { + for (var i = 0; i < filenames.length; i++) { var fileInfo = utils.splitFileLocation(filenames[i]); if (Object.keys(fileInfo).length === 0) continue; var type = utils.getFileType(fileInfo.ext); if (type === "image") { - postFiles.push( - <div className="post-image__column" key={filenames[i]}> - <a href="#" onClick={this.handleImageClick} data-img-id={images.length.toString()} data-toggle="modal" data-target={"#" + postImageModalId }><div ref={filenames[i]} className="post__load" style={{backgroundImage: 'url(/static/images/load.gif)'}}></div></a> - </div> - ); + if (i < Constants.MAX_DISPLAY_FILES) { + postFiles.push( + <div className="post-image__column" key={filenames[i]}> + <a href="#" onClick={this.handleImageClick} data-img-id={images.length.toString()} data-toggle="modal" data-target={"#" + postImageModalId }><div ref={filenames[i]} className="post__load" style={{backgroundImage: 'url(/static/images/load.gif)'}}></div></a> + </div> + ); + } images.push(filenames[i]); - } else { + } else if (i < Constants.MAX_DISPLAY_FILES) { postFiles.push( <div className="post-image__column custom-file" key={fileInfo.name}> <a href={fileInfo.path+"."+fileInfo.ext} download={fileInfo.name+"."+fileInfo.ext}> diff --git a/web/react/components/settings_sidebar.jsx b/web/react/components/settings_sidebar.jsx index a1546890f..ae8510cf2 100644 --- a/web/react/components/settings_sidebar.jsx +++ b/web/react/components/settings_sidebar.jsx @@ -1,6 +1,8 @@ // Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. // See License.txt for license information. +var utils = require('../utils/utils.jsx'); + module.exports = React.createClass({ updateTab: function(tab) { this.props.updateTab(tab); @@ -11,16 +13,11 @@ module.exports = React.createClass({ return ( <div className=""> <ul className="nav nav-pills nav-stacked"> - <li className={this.props.activeTab == 'general' ? 'active' : ''}><a href="#" onClick={function(){self.updateTab("general");}}><i className="glyphicon glyphicon-cog"></i>General</a></li> - <li className={this.props.activeTab == 'security' ? 'active' : ''}><a href="#" onClick={function(){self.updateTab("security");}}><i className="glyphicon glyphicon-lock"></i>Security</a></li> - <li className={this.props.activeTab == 'notifications' ? 'active' : ''}><a href="#" onClick={function(){self.updateTab("notifications");}}><i className="glyphicon glyphicon-exclamation-sign"></i>Notifications</a></li> - <li className={this.props.activeTab == 'appearance' ? 'active' : ''}><a href="#" onClick={function(){self.updateTab("appearance");}}><i className="glyphicon glyphicon-wrench"></i>Appearance</a></li> + {this.props.tabs.map(function(tab) { + return <li className={self.props.activeTab == tab.name ? 'active' : ''}><a href="#" onClick={function(){self.updateTab(tab.name);}}><i className={tab.icon}></i>{tab.ui_name}</a></li> + })} </ul> </div> ); - /* Temporarily removing sessions and activity logs - <li className={this.props.activeTab == 'sessions' ? 'active' : ''}><a href="#" onClick={function(){self.updateTab("sessions");}}><i className="glyphicon glyphicon-globe"></i>Sessions</a></li> - <li className={this.props.activeTab == 'activity_log' ? 'active' : ''}><a href="#" onClick={function(){self.updateTab("activity_log");}}><i className="glyphicon glyphicon-time"></i>Activity Log</a></li> - */ } }); diff --git a/web/react/components/sidebar_header.jsx b/web/react/components/sidebar_header.jsx index 5a872b7a0..0b59d2036 100644 --- a/web/react/components/sidebar_header.jsx +++ b/web/react/components/sidebar_header.jsx @@ -94,7 +94,8 @@ var NavbarDropdown = React.createClass({ <i className="dropdown__icon"></i> </a> <ul className="dropdown-menu" role="menu"> - <li><a href="#" data-toggle="modal" data-target="#settings_modal">Account Settings</a></li> + <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> : "" } { invite_link } { team_link } { manage_link } diff --git a/web/react/components/sidebar_right_menu.jsx b/web/react/components/sidebar_right_menu.jsx index d0c139d1a..c523ce554 100644 --- a/web/react/components/sidebar_right_menu.jsx +++ b/web/react/components/sidebar_right_menu.jsx @@ -59,7 +59,7 @@ module.exports = React.createClass({ <div className="nav-pills__container"> <ul className="nav nav-pills nav-stacked"> - <li><a href="#" data-toggle="modal" data-target="#settings_modal"><i className="glyphicon glyphicon-cog"></i>Account Settings</a></li> + <li><a href="#" data-toggle="modal" data-target="#user_settings1"><i className="glyphicon glyphicon-cog"></i>Account Settings</a></li> { invite_link } { team_link } { manage_link } diff --git a/web/react/components/team_settings.jsx b/web/react/components/team_settings.jsx new file mode 100644 index 000000000..0cec30f3e --- /dev/null +++ b/web/react/components/team_settings.jsx @@ -0,0 +1,161 @@ +// 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 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) + ); + }, + handleValetRadio: function(val) { + this.setState({ allow_valet: val }); + this.refs.wrapper.getDOMNode().focus(); + }, + 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 }); + }, + getInitialState: function() { + var team = this.props.team; + + var allow_valet = "false"; + if (team && team.allow_valet) { + allow_valet = "true"; + } + + 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 className="col-sm-12"> + <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/>Warning: Turning on the Valet feature and using it with any third party software increases the risk of a security breach.</div> + </div> + ); + + valetSection = ( + <SettingItemMax + title="Valet" + 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" + 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">×</span></button> + <h4 className="modal-title" ref="title"><i className="modal-back"></i>General 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> + ); + } +}); + +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 { + return <div/>; + } + } +}); diff --git a/web/react/components/settings_modal.jsx b/web/react/components/team_settings_modal.jsx index 57a869f93..08a952d2e 100644 --- a/web/react/components/settings_modal.jsx +++ b/web/react/components/team_settings_modal.jsx @@ -2,7 +2,7 @@ // See License.txt for license information. var SettingsSidebar = require('./settings_sidebar.jsx'); -var UserSettings = require('./user_settings.jsx'); +var TeamSettings = require('./team_settings.jsx'); module.exports = React.createClass({ componentDidMount: function() { @@ -22,27 +22,31 @@ module.exports = React.createClass({ this.setState({ active_section: section }); }, getInitialState: function() { - return { active_tab: "general", active_section: "" }; + return { active_tab: "feature", active_section: "" }; }, render: function() { + var tabs = []; + tabs.push({name: "feature", ui_name: "Features", icon: "glyphicon glyphicon-wrench"}); + return ( - <div className="modal fade" ref="modal" id="settings_modal" role="dialog" aria-hidden="true"> + <div className="modal fade" ref="modal" id="team_settings" role="dialog" 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">×</span></button> - <h4 className="modal-title" ref="title">Account Settings</h4> + <h4 className="modal-title" ref="title">Team Settings</h4> </div> <div className="modal-body"> <div className="settings-table"> <div className="settings-links"> <SettingsSidebar + tabs={tabs} activeTab={this.state.active_tab} updateTab={this.updateTab} /> </div> <div className="settings-content"> - <UserSettings + <TeamSettings activeTab={this.state.active_tab} activeSection={this.state.active_section} updateSection={this.updateSection} diff --git a/web/react/components/user_settings.jsx b/web/react/components/user_settings.jsx index a9c2433f2..7d542a8b7 100644 --- a/web/react/components/user_settings.jsx +++ b/web/react/components/user_settings.jsx @@ -658,9 +658,10 @@ var SecurityTab = React.createClass({ ); } else { var d = new Date(this.props.user.last_password_update); - var hour = d.getHours() < 10 ? "0" + d.getHours() : String(d.getHours()); + var hour = d.getHours() % 12 ? String(d.getHours() % 12) : "12"; var min = d.getMinutes() < 10 ? "0" + d.getMinutes() : String(d.getMinutes()); - var dateStr = "Last updated " + Constants.MONTHS[d.getMonth()] + " " + d.getDate() + ", " + d.getFullYear() + " at " + hour + ":" + min; + var timeOfDay = d.getHours() >= 12 ? " pm" : " am"; + var dateStr = "Last updated " + Constants.MONTHS[d.getMonth()] + " " + d.getDate() + ", " + d.getFullYear() + " at " + hour + ":" + min + timeOfDay; passwordSection = ( <SettingItemMin @@ -1056,7 +1057,7 @@ var AppearanceTab = React.createClass({ themeSection = ( <SettingItemMax - title="Theme" + title="Theme Color" inputs={inputs} submit={this.submitTheme} server_error={server_error} @@ -1066,7 +1067,7 @@ var AppearanceTab = React.createClass({ } else { themeSection = ( <SettingItemMin - title="Theme" + title="Theme Color" describe={this.state.theme} updateSection={function(){self.props.updateSection("theme");}} /> diff --git a/web/react/components/user_settings_modal.jsx b/web/react/components/user_settings_modal.jsx new file mode 100644 index 000000000..ff001611d --- /dev/null +++ b/web/react/components/user_settings_modal.jsx @@ -0,0 +1,68 @@ +// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. +// See License.txt for license information. + +var SettingsSidebar = require('./settings_sidebar.jsx'); +var UserSettings = require('./user_settings.jsx'); + +module.exports = React.createClass({ + componentDidMount: function() { + $('body').on('click', '.modal-back', function(){ + $(this).closest('.modal-dialog').removeClass('display--content'); + }); + $('body').on('click', '.modal-header .close', function(){ + setTimeout(function() { + $('.modal-dialog.display--content').removeClass('display--content'); + }, 500); + }); + }, + updateTab: function(tab) { + this.setState({ active_tab: tab }); + }, + updateSection: function(section) { + this.setState({ active_section: section }); + }, + getInitialState: function() { + return { active_tab: "general", active_section: "" }; + }, + render: function() { + var tabs = []; + tabs.push({name: "general", ui_name: "General", icon: "glyphicon glyphicon-cog"}); + tabs.push({name: "security", ui_name: "Security", icon: "glyphicon glyphicon-lock"}); + tabs.push({name: "notifications", ui_name: "Notifications", icon: "glyphicon glyphicon-exclamation-sign"}); + tabs.push({name: "appearance", ui_name: "Appearance", icon: "glyphicon glyphicon-wrench"}); + //tabs.push({name: "sessions", ui_name: "Sessions", icon: "glyphicon glyphicon-globe"}); + //tabs.push({name: "activity_log", ui_name: "Activity Log", icon: "glyphicon glyphicon-time"}); + + return ( + <div className="modal fade" ref="modal" id="user_settings1" role="dialog" 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">×</span></button> + <h4 className="modal-title" ref="title">Account Settings</h4> + </div> + <div className="modal-body"> + <div className="settings-table"> + <div className="settings-links"> + <SettingsSidebar + tabs={tabs} + activeTab={this.state.active_tab} + updateTab={this.updateTab} + /> + </div> + <div className="settings-content"> + <UserSettings + activeTab={this.state.active_tab} + activeSection={this.state.active_section} + updateSection={this.updateSection} + /> + </div> + </div> + </div> + </div> + </div> + </div> + ); + } +}); + diff --git a/web/react/components/view_image.jsx b/web/react/components/view_image.jsx index 4cb30e1d3..c573e9dbb 100644 --- a/web/react/components/view_image.jsx +++ b/web/react/components/view_image.jsx @@ -124,7 +124,7 @@ module.exports = React.createClass({ <div key={name+"_loading"}> <img ref="placeholder" className="loader-image" src="/static/images/load.gif" /> { percentage > 0 ? - <span className="loader-percent" >{"Downloading " + percentage + "%"}</span> + <span className="loader-percent" >{"Previewing " + percentage + "%"}</span> : ""} </div> ); |