summaryrefslogtreecommitdiffstats
path: root/web
diff options
context:
space:
mode:
Diffstat (limited to 'web')
-rw-r--r--web/react/components/channel_header.jsx2
-rw-r--r--web/react/components/member_list_team.jsx4
-rw-r--r--web/react/components/mention_list.jsx18
-rw-r--r--web/react/components/post_info.jsx3
-rw-r--r--web/react/components/post_list.jsx2
-rw-r--r--web/react/components/search_bar.jsx2
-rw-r--r--web/react/components/sidebar.jsx4
-rw-r--r--web/react/components/user_settings.jsx107
-rw-r--r--web/react/stores/user_store.jsx18
-rw-r--r--web/react/utils/utils.jsx26
-rw-r--r--web/sass-files/sass/partials/_headers.scss7
-rw-r--r--web/sass-files/sass/partials/_modal.scss2
-rw-r--r--web/sass-files/sass/partials/_responsive.scss9
-rw-r--r--web/sass-files/sass/partials/_search.scss13
-rw-r--r--web/templates/head.html7
-rw-r--r--web/web.go6
16 files changed, 149 insertions, 81 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..7e939812d 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 && users[i].first_name.lastIndexOf(mentionText,0) === 0)
+ || (users[i].last_name && 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..d14340998 100644
--- a/web/templates/head.html
+++ b/web/templates/head.html
@@ -42,6 +42,9 @@
}
config.SiteName = '{{ .SiteName }}';
</script>
+
+ <script src="/static/js/bundle.js"></script>
+
<script>
if (config.LogglyWriteKey != null && config.LogglyWriteKey !== "") {
var _LTracker = _LTracker || [];
@@ -59,7 +62,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,
@@ -101,7 +104,5 @@
}
</script>
<!-- Snowplow stops plowing -->
-
- <script src="/static/js/bundle.js"></script>
</head>
{{end}}
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
}