diff options
Diffstat (limited to 'web')
-rw-r--r-- | web/react/components/channel_header.jsx | 2 | ||||
-rw-r--r-- | web/react/components/member_list_team.jsx | 4 | ||||
-rw-r--r-- | web/react/components/mention_list.jsx | 18 | ||||
-rw-r--r-- | web/react/components/post_info.jsx | 3 | ||||
-rw-r--r-- | web/react/components/post_list.jsx | 2 | ||||
-rw-r--r-- | web/react/components/search_bar.jsx | 2 | ||||
-rw-r--r-- | web/react/components/sidebar.jsx | 4 | ||||
-rw-r--r-- | web/react/components/user_settings.jsx | 107 | ||||
-rw-r--r-- | web/react/stores/user_store.jsx | 18 | ||||
-rw-r--r-- | web/react/utils/utils.jsx | 26 | ||||
-rw-r--r-- | web/sass-files/sass/partials/_headers.scss | 7 | ||||
-rw-r--r-- | web/sass-files/sass/partials/_modal.scss | 2 | ||||
-rw-r--r-- | web/sass-files/sass/partials/_responsive.scss | 9 | ||||
-rw-r--r-- | web/sass-files/sass/partials/_search.scss | 13 | ||||
-rw-r--r-- | web/templates/head.html | 2 | ||||
-rw-r--r-- | web/web.go | 6 |
16 files changed, 146 insertions, 79 deletions
diff --git a/web/react/components/channel_header.jsx b/web/react/components/channel_header.jsx index 2e430489f..30435dc08 100644 --- a/web/react/components/channel_header.jsx +++ b/web/react/components/channel_header.jsx @@ -153,7 +153,7 @@ module.exports = React.createClass({ if (isDirect) { if (this.state.users.length > 1) { var contact = this.state.users[((this.state.users[0].id === currentId) ? 1 : 0)]; - channelTitle = <UserProfile userId={contact.id} overwriteName={contact.full_name || contact.username} />; + channelTitle = <UserProfile userId={contact.id} overwriteName={contact.nickname || contact.username} />; } } diff --git a/web/react/components/member_list_team.jsx b/web/react/components/member_list_team.jsx index 89b5e49d5..6f1d83193 100644 --- a/web/react/components/member_list_team.jsx +++ b/web/react/components/member_list_team.jsx @@ -85,8 +85,8 @@ var MemberListTeamItem = React.createClass({ return ( <div className="row member-div"> <img className="post-profile-img pull-left" src={"/api/v1/users/" + user.id + "/image?time=" + timestamp} height="36" width="36" /> - <span className="member-name">{user.full_name.trim() ? user.full_name : user.username}</span> - <span className="member-email">{user.full_name.trim() ? user.username : email}</span> + <span className="member-name">{utils.getDisplayName(user)}</span> + <span className="member-email">{email}</span> <div className="dropdown member-drop"> <a href="#" className="dropdown-toggle theme" type="button" id="channel_header_dropdown" data-toggle="dropdown" aria-expanded="true"> <span>{currentRoles} </span> diff --git a/web/react/components/mention_list.jsx b/web/react/components/mention_list.jsx index c5ff82346..524f1b337 100644 --- a/web/react/components/mention_list.jsx +++ b/web/react/components/mention_list.jsx @@ -165,14 +165,14 @@ module.exports = React.createClass({ var all = {}; all.username = "all"; - all.full_name = ""; + all.nickname = ""; all.secondary_text = "Notifies everyone in the team"; all.id = "allmention"; users.push(all); var channel = {}; channel.username = "channel"; - channel.full_name = ""; + channel.nickname = ""; channel.secondary_text = "Notifies everyone in the channel"; channel.id = "channelmention"; users.push(channel); @@ -188,21 +188,13 @@ module.exports = React.createClass({ for (var i = 0; i < users.length && index < MAX_ITEMS_IN_LIST; i++) { if (this.alreadyMentioned(users[i].username)) continue; - var firstName = "", lastName = ""; - if (users[i].full_name.length > 0) { - var splitName = users[i].full_name.split(' '); - firstName = splitName[0].toLowerCase(); - lastName = splitName.length > 1 ? splitName[splitName.length-1].toLowerCase() : ""; - users[i].secondary_text = users[i].full_name; - } - - if (firstName.lastIndexOf(mentionText,0) === 0 - || lastName.lastIndexOf(mentionText,0) === 0 || users[i].username.lastIndexOf(mentionText,0) === 0) { + if (users[i].first_name.lastIndexOf(mentionText,0) === 0 + || users[i].last_name.lastIndexOf(mentionText,0) === 0 || users[i].username.lastIndexOf(mentionText,0) === 0) { mentions[index] = ( <Mention ref={'mention' + index} username={users[i].username} - secondary_text={users[i].secondary_text} + secondary_text={users[i].first_name + " " + users[i].last_name} id={users[i].id} listId={index} isFocused={this.state.selectedMention === index ? "mentions-focus" : ""} diff --git a/web/react/components/post_info.jsx b/web/react/components/post_info.jsx index 17746655d..d6422fe3a 100644 --- a/web/react/components/post_info.jsx +++ b/web/react/components/post_info.jsx @@ -11,6 +11,7 @@ module.exports = React.createClass({ render: function() { var post = this.props.post; var isOwner = UserStore.getCurrentId() == post.user_id; + var isAdmin = UserStore.getCurrentUser().roles.indexOf("admin") > -1 var type = "Post" if (post.root_id.length > 0) { @@ -34,7 +35,7 @@ module.exports = React.createClass({ <ul className="dropdown-menu" role="menu"> { isOwner ? <li role="presentation"><a href="#" role="menuitem" data-toggle="modal" data-target="#edit_post" data-title={type} data-message={post.message} data-postid={post.id} data-channelid={post.channel_id} data-comments={type === "Post" ? this.props.commentCount : 0}>Edit</a></li> : "" } - { isOwner ? <li role="presentation"><a href="#" role="menuitem" data-toggle="modal" data-target="#delete_post" data-title={type} data-postid={post.id} data-channelid={post.channel_id} data-comments={type === "Post" ? this.props.commentCount : 0}>Delete</a></li> + { isOwner || isAdmin ? <li role="presentation"><a href="#" role="menuitem" data-toggle="modal" data-target="#delete_post" data-title={type} data-postid={post.id} data-channelid={post.channel_id} data-comments={type === "Post" ? this.props.commentCount : 0}>Delete</a></li> : "" } { this.props.allowReply === "true" ? <li role="presentation"><a className="reply-link theme" href="#" onClick={this.props.handleCommentClick}>Reply</a></li> : "" } diff --git a/web/react/components/post_list.jsx b/web/react/components/post_list.jsx index 573799a19..5439ca43d 100644 --- a/web/react/components/post_list.jsx +++ b/web/react/components/post_list.jsx @@ -305,7 +305,7 @@ module.exports = React.createClass({ var teammate = utils.getDirectTeammate(channel.id) if (teammate) { - var teammate_name = teammate.full_name.length > 0 ? teammate.full_name : teammate.username; + var teammate_name = teammate.nickname.length > 0 ? teammate.nickname : teammate.username; more_messages = ( <div className="channel-intro"> <div className="post-profile-img__container channel-intro-img"> diff --git a/web/react/components/search_bar.jsx b/web/react/components/search_bar.jsx index ab7e99d60..f21f0cd58 100644 --- a/web/react/components/search_bar.jsx +++ b/web/react/components/search_bar.jsx @@ -92,7 +92,7 @@ module.exports = React.createClass({ render: function() { return ( <div> - <div className="sidebar__collapse" onClick={this.handleClose}></div> + <div className="sidebar__collapse" onClick={this.handleClose}>Cancel</div> <span className="glyphicon glyphicon-search sidebar__search-icon"></span> <form role="form" className="search__form relative-div" onSubmit={this.handleSubmit}> <input diff --git a/web/react/components/sidebar.jsx b/web/react/components/sidebar.jsx index cae9425d3..65727c597 100644 --- a/web/react/components/sidebar.jsx +++ b/web/react/components/sidebar.jsx @@ -131,7 +131,7 @@ function getStateFromStores() { var channel = ChannelStore.getByName(channelName); if (channel != null) { - channel.display_name = teammate.full_name.trim() != "" ? teammate.full_name : teammate.username; + channel.display_name = utils.getDisplayName(teammate); channel.teammate_username = teammate.username; channel.status = UserStore.getStatus(teammate.id); @@ -150,7 +150,7 @@ function getStateFromStores() { var tempChannel = {}; tempChannel.fake = true; tempChannel.name = channelName; - tempChannel.display_name = teammate.full_name.trim() != "" ? teammate.full_name : teammate.username; + tempChannel.display_name = utils.getDisplayName(teammate); tempChannel.status = UserStore.getStatus(teammate.id); tempChannel.last_post_at = 0; readDirectChannels.push(tempChannel); diff --git a/web/react/components/user_settings.jsx b/web/react/components/user_settings.jsx index 38e4b1aea..59c97c309 100644 --- a/web/react/components/user_settings.jsx +++ b/web/react/components/user_settings.jsx @@ -156,6 +156,8 @@ var NotificationsTab = React.createClass({ var self = this; + var user = this.props.user; + var desktopSection; if (this.props.activeSection === 'desktop') { var notifyActive = [false, false, false]; @@ -314,20 +316,14 @@ var NotificationsTab = React.createClass({ var keysSection; if (this.props.activeSection === 'keys') { - var user = this.props.user; - var first_name = ""; - if (user.full_name.length > 0) { - first_name = user.full_name.split(' ')[0]; - } - var inputs = []; - if (first_name != "") { + if (user.first_name) { inputs.push( <div> <div className="checkbox"> <label> - <input type="checkbox" checked={this.state.first_name_key} onChange={function(e){self.updateFirstNameKey(e.target.checked);}}>{'Your case sensitive first name "' + first_name + '"'}</input> + <input type="checkbox" checked={this.state.first_name_key} onChange={function(e){self.updateFirstNameKey(e.target.checked);}}>{'Your case sensitive first name "' + user.first_name + '"'}</input> </label> </div> </div> @@ -396,14 +392,9 @@ var NotificationsTab = React.createClass({ ); } else { var keys = []; - if (this.state.first_name_key) { - var first_name = ""; - var user = this.props.user; - if (user.full_name.length > 0) first_name = user.full_name.split(' ')[0]; - if (first_name != "") keys.push(first_name); - } - if (this.state.username_key) keys.push(this.props.user.username); - if (this.state.mention_key) keys.push('@'+this.props.user.username); + if (this.state.first_name_key) keys.push(user.first_name); + if (this.state.username_key) keys.push(user.username); + if (this.state.mention_key) keys.push('@'+user.username); if (this.state.all_key) keys.push('@all'); if (this.state.channel_key) keys.push('@channel'); if (this.state.custom_keys.length > 0) keys = keys.concat(this.state.custom_keys.split(',')); @@ -752,6 +743,21 @@ var GeneralTab = React.createClass({ this.submitUser(user); }, + submitNickname: function(e) { + e.preventDefault(); + + var user = UserStore.getCurrentUser(); + var nickname = this.state.nickname.trim(); + + if (user.nickname === nickname) { + this.setState({client_error: "You must submit a new nickname"}) + return; + } + + user.nickname = nickname; + + this.submitUser(user); + }, submitName: function(e) { e.preventDefault(); @@ -759,14 +765,13 @@ var GeneralTab = React.createClass({ var firstName = this.state.first_name.trim(); var lastName = this.state.last_name.trim(); - var fullName = firstName + ' ' + lastName; - - if (user.full_name === fullName) { - this.setState({client_error: "You must submit a new name"}) + if (user.first_name === firstName && user.last_name === lastName) { + this.setState({client_error: "You must submit a new first or last name"}) return; } - user.full_name = fullName; + user.first_name = firstName; + user.last_name = lastName; this.submitUser(user); }, @@ -839,6 +844,9 @@ var GeneralTab = React.createClass({ updateLastName: function(e) { this.setState({ last_name: e.target.value}); }, + updateNickname: function(e) { + this.setState({nickname: e.target.value}); + }, updateEmail: function(e) { this.setState({ email: e.target.value}); }, @@ -861,11 +869,7 @@ var GeneralTab = React.createClass({ getInitialState: function() { var user = this.props.user; - var splitStr = user.full_name.split(' '); - var firstName = splitStr.shift(); - var lastName = splitStr.join(' '); - - return { username: user.username, first_name: firstName, last_name: lastName, + return { username: user.username, first_name: user.first_name, last_name: user.last_name, nickname: user.nickname, email: user.email, picture: null }; }, render: function() { @@ -901,7 +905,7 @@ var GeneralTab = React.createClass({ nameSection = ( <SettingItemMax - title="Name" + title="Full Name" inputs={inputs} submit={this.submitName} server_error={server_error} @@ -910,15 +914,58 @@ var GeneralTab = React.createClass({ /> ); } else { + var full_name = ""; + + if (user.first_name && user.last_name) { + full_name = user.first_name + " " + user.last_name; + } else if (user.first_name) { + full_name = user.first_name; + } else if (user.last_name) { + full_name = user.last_name; + } + nameSection = ( <SettingItemMin - title="Name" - describe={UserStore.getCurrentUser().full_name} + title="Full Name" + describe={full_name} updateSection={function(){self.updateSection("name");}} /> ); } + var nicknameSection; + if (this.props.activeSection === 'nickname') { + var inputs = []; + + inputs.push( + <div className="form-group"> + <label className="col-sm-5 control-label">{utils.isMobile() ? "": "Nickname"}</label> + <div className="col-sm-7"> + <input className="form-control" type="text" onChange={this.updateNickname} value={this.state.nickname}/> + </div> + </div> + ); + + nicknameSection = ( + <SettingItemMax + title="Nickname" + inputs={inputs} + submit={this.submitNickname} + server_error={server_error} + client_error={client_error} + updateSection={function(e){self.updateSection("");e.preventDefault();}} + /> + ); + } else { + nicknameSection = ( + <SettingItemMin + title="Nickname" + describe={UserStore.getCurrentUser().nickname} + updateSection={function(){self.updateSection("nickname");}} + /> + ); + } + var usernameSection; if (this.props.activeSection === 'username') { var inputs = []; @@ -1026,6 +1073,8 @@ var GeneralTab = React.createClass({ <div className="divider-light"/> {usernameSection} <div className="divider-light"/> + {nicknameSection} + <div className="divider-light"/> {emailSection} <div className="divider-light"/> {pictureSection} diff --git a/web/react/stores/user_store.jsx b/web/react/stores/user_store.jsx index dd207ca80..b0ea719d4 100644 --- a/web/react/stores/user_store.jsx +++ b/web/react/stores/user_store.jsx @@ -177,21 +177,15 @@ var UserStore = assign({}, EventEmitter.prototype, { }, getCurrentMentionKeys: function() { var user = this.getCurrentUser(); - if (user && user.notify_props && user.notify_props.mention_keys) { - var keys = user.notify_props.mention_keys.split(','); - if (user.full_name.length > 0 && user.notify_props.first_name === "true") { - var first = user.full_name.split(' ')[0]; - if (first.length > 0) keys.push(first); - } + var keys = []; - if (user.notify_props.all === "true") keys.push('@all'); - if (user.notify_props.channel === "true") keys.push('@channel'); + if (user.notify_props && user.notify_props.mention_keys) keys = keys.concat(user.notify_props.mention_keys.split(',')); + if (user.first_name && user.notify_props.first_name === "true") keys.push(user.first_name); + if (user.notify_props.all === "true") keys.push('@all'); + if (user.notify_props.channel === "true") keys.push('@channel'); - return keys; - } else { - return []; - } + return keys; }, getLastVersion: function() { return BrowserStore.getItem("last_version", ''); diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx index 7186251e7..416ea5ae4 100644 --- a/web/react/utils/utils.jsx +++ b/web/react/utils/utils.jsx @@ -796,7 +796,6 @@ module.exports.getHomeLink = function() { return window.location.protocol + "//" + parts.join("."); } - module.exports.changeColor =function(col, amt) { var usePound = false; @@ -824,5 +823,30 @@ module.exports.changeColor =function(col, amt) { else if (g < 0) g = 0; return (usePound?"#":"") + String("000000" + (g | (b << 8) | (r << 16)).toString(16)).slice(-6); +}; + +module.exports.getFullName = function(user) { + if (user.first_name && user.last_name) { + return user.first_name + " " + user.last_name; + } else if (user.first_name) { + return user.first_name; + } else if (user.last_name) { + return user.last_name; + } else { + return ""; + } +}; + +module.exports.getDisplayName = function(user) { + if (user.nickname && user.nickname.trim().length > 0) { + return user.nickname; + } else { + var fullName = module.exports.getFullName(user); + if (fullName) { + return fullName; + } else { + return user.username; + } + } }; diff --git a/web/sass-files/sass/partials/_headers.scss b/web/sass-files/sass/partials/_headers.scss index d876d8b37..c2740891a 100644 --- a/web/sass-files/sass/partials/_headers.scss +++ b/web/sass-files/sass/partials/_headers.scss @@ -157,6 +157,7 @@ font-size: 14px; line-height: 50px; #member_popover { + margin-right: 5px; width: 45px; color: #999; cursor: pointer; @@ -232,12 +233,16 @@ vertical-align: top; display: inline-block; width: 15px; - margin: 9px 3px 3px 0; + margin: 9px 4px 3px 0; &:hover { svg { fill: #888; } } + a { + height: 100%; + display: block; + } svg { vertical-align: top; margin-top: 8px; diff --git a/web/sass-files/sass/partials/_modal.scss b/web/sass-files/sass/partials/_modal.scss index 1b0338884..f359037c5 100644 --- a/web/sass-files/sass/partials/_modal.scss +++ b/web/sass-files/sass/partials/_modal.scss @@ -155,7 +155,7 @@ position: relative; max-width: 90%; min-height: 50px; - min-width: 280px; + min-width: 320px; @include border-radius(3px); display: table; margin: 0 auto; diff --git a/web/sass-files/sass/partials/_responsive.scss b/web/sass-files/sass/partials/_responsive.scss index 1f9643175..a33d69378 100644 --- a/web/sass-files/sass/partials/_responsive.scss +++ b/web/sass-files/sass/partials/_responsive.scss @@ -432,13 +432,16 @@ color: #fff; .search__form { border: none; - padding: 0 10px 0 30px; + padding: 0 60px 0 25px; .form-control { + line-height: 31px; background: none; color: #fff; - border-bottom: 1px solid rgba(#fff, 0.7); border-radius: 0; - padding: 0 10px 0 23px; + padding: 0 10px 0; + @include input-placeholder { + color: rgba(#fff, 0.6); + } } ::-webkit-input-placeholder { color: #fff; diff --git a/web/sass-files/sass/partials/_search.scss b/web/sass-files/sass/partials/_search.scss index 8d51d00c0..d4a4da243 100644 --- a/web/sass-files/sass/partials/_search.scss +++ b/web/sass-files/sass/partials/_search.scss @@ -2,21 +2,20 @@ padding: 8px 8px 8px 0; } .sidebar__collapse { - width: 20px; - height: 30px; + width: auto; + height: auto; position: absolute; - top: 10px; - left: 6px; + top: 17px; + right: 15px; cursor: pointer; - background: url("../images/arrow-left.png") center no-repeat; - @include background-size(10px 15px); z-index: 5; display: none; } .sidebar__search-icon { position: absolute; - left: 40px; + left: 15px; top: 18px; + font-size: 16px; @include opacity(0.8); display: none; } diff --git a/web/templates/head.html b/web/templates/head.html index 5b423d487..0cbda28c5 100644 --- a/web/templates/head.html +++ b/web/templates/head.html @@ -59,7 +59,7 @@ var user = window.UserStore.getCurrentUser(true); if (user) { analytics.identify(user.id, { - name: user.full_name, + name: user.nickname, email: user.email, createdAt: user.create_at, username: user.username, diff --git a/web/web.go b/web/web.go index e771157d8..b11e6e6b1 100644 --- a/web/web.go +++ b/web/web.go @@ -303,8 +303,8 @@ func getChannel(c *api.Context, w http.ResponseWriter, r *http.Request) { //api.Handle404(w, r) //Bad channel urls just redirect to the town-square for now - - http.Redirect(w,r,"/channels/town-square", http.StatusFound) + + http.Redirect(w, r, "/channels/town-square", http.StatusFound) return } } @@ -351,7 +351,7 @@ func verifyEmail(c *api.Context, w http.ResponseWriter, r *http.Request) { return } else { user := result.Data.(*model.User) - api.FireAndForgetVerifyEmail(user.Id, strings.Split(user.FullName, " ")[0], user.Email, domain, c.TeamUrl) + api.FireAndForgetVerifyEmail(user.Id, user.FirstName, user.Email, domain, c.TeamUrl) http.Redirect(w, r, "/", http.StatusFound) return } |