summaryrefslogtreecommitdiffstats
path: root/web
diff options
context:
space:
mode:
author=Corey Hulen <corey@hulen.com>2015-07-15 10:22:05 -0800
committer=Corey Hulen <corey@hulen.com>2015-07-15 10:22:05 -0800
commite017babc5ddd66e65469326bf723d5359875c2d1 (patch)
tree0da7ee5d9f4039eeb20f70940483c40943c9aa23 /web
parent252d0f3924dd19aa4dd1900c6c00c41c84755d1e (diff)
parent38f9e140e98123eb256968fb31f7fbb2aef978e0 (diff)
downloadchat-e017babc5ddd66e65469326bf723d5359875c2d1.tar.gz
chat-e017babc5ddd66e65469326bf723d5359875c2d1.tar.bz2
chat-e017babc5ddd66e65469326bf723d5359875c2d1.zip
fixing merge
Diffstat (limited to 'web')
-rw-r--r--web/react/components/delete_post_modal.jsx4
-rw-r--r--web/react/components/edit_post_modal.jsx7
-rw-r--r--web/react/components/loading_screen.jsx24
-rw-r--r--web/react/components/member_list_item.jsx3
-rw-r--r--web/react/components/member_list_team.jsx5
-rw-r--r--web/react/components/mention.jsx4
-rw-r--r--web/react/components/mention_list.jsx29
-rw-r--r--web/react/components/more_channels.jsx15
-rw-r--r--web/react/components/post.jsx17
-rw-r--r--web/react/components/post_body.jsx17
-rw-r--r--web/react/components/post_list.jsx105
-rw-r--r--web/react/components/post_right.jsx6
-rw-r--r--web/react/components/search_results.jsx3
-rw-r--r--web/react/components/sidebar.jsx20
-rw-r--r--web/react/components/sidebar_header.jsx9
-rw-r--r--web/react/components/signup_team_complete.jsx11
-rw-r--r--web/react/components/signup_user_complete.jsx11
-rw-r--r--web/react/components/user_profile.jsx2
-rw-r--r--web/react/components/user_settings.jsx2
-rw-r--r--web/react/stores/browser_store.jsx153
-rw-r--r--web/react/stores/channel_store.jsx64
-rw-r--r--web/react/stores/error_store.jsx11
-rw-r--r--web/react/stores/post_store.jsx59
-rw-r--r--web/react/stores/socket_store.jsx2
-rw-r--r--web/react/stores/team_store.jsx16
-rw-r--r--web/react/stores/user_store.jsx120
-rw-r--r--web/react/utils/utils.jsx39
-rw-r--r--web/sass-files/sass/partials/_files.scss2
-rw-r--r--web/sass-files/sass/partials/_headers.scss27
-rw-r--r--web/sass-files/sass/partials/_loading.scss50
-rw-r--r--web/sass-files/sass/partials/_mentions.scss9
-rw-r--r--web/sass-files/sass/partials/_post.scss1
32 files changed, 361 insertions, 486 deletions
diff --git a/web/react/components/delete_post_modal.jsx b/web/react/components/delete_post_modal.jsx
index fefac12d7..11970bc2b 100644
--- a/web/react/components/delete_post_modal.jsx
+++ b/web/react/components/delete_post_modal.jsx
@@ -56,13 +56,13 @@ module.exports = React.createClass({
$(this.refs.modal.getDOMNode()).on('show.bs.modal', function(e) {
var newState = {};
if(BrowserStore.getItem('edit_state_transfer')) {
- newState = JSON.parse(BrowserStore.getItem('edit_state_transfer'));
+ newState = BrowserStore.getItem('edit_state_transfer');
BrowserStore.removeItem('edit_state_transfer');
} else {
var button = e.relatedTarget;
newState = { title: $(button).attr('data-title'), channel_id: $(button).attr('data-channelid'), post_id: $(button).attr('data-postid'), comments: $(button).attr('data-comments') };
}
- self.setState(newState)
+ self.setState(newState);
});
PostStore.addSelectedPostChangeListener(this._onChange);
},
diff --git a/web/react/components/edit_post_modal.jsx b/web/react/components/edit_post_modal.jsx
index d741e189b..21b75bb6e 100644
--- a/web/react/components/edit_post_modal.jsx
+++ b/web/react/components/edit_post_modal.jsx
@@ -4,6 +4,7 @@
var Client = require('../utils/client.jsx');
var AsyncClient = require('../utils/async_client.jsx');
var Textbox = require('./textbox.jsx');
+var BrowserStore = require('../stores/browser_store.jsx');
module.exports = React.createClass({
handleEdit: function(e) {
@@ -13,14 +14,14 @@ module.exports = React.createClass({
if (updatedPost.message.length === 0) {
var tempState = this.state;
delete tempState.editText;
- BrowserStore.setItem('edit_state_transfer', JSON.stringify(tempState));
+ BrowserStore.setItem('edit_state_transfer', tempState);
$("#edit_post").modal('hide');
$("#delete_post").modal('show');
return;
}
- updatedPost.id = this.state.post_id
- updatedPost.channel_id = this.state.channel_id
+ updatedPost.id = this.state.post_id;
+ updatedPost.channel_id = this.state.channel_id;
Client.updatePost(updatedPost,
function(data) {
diff --git a/web/react/components/loading_screen.jsx b/web/react/components/loading_screen.jsx
new file mode 100644
index 000000000..5905e519b
--- /dev/null
+++ b/web/react/components/loading_screen.jsx
@@ -0,0 +1,24 @@
+// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+module.exports = React.createClass({
+ displayName: "LoadingScreen",
+ propTypes: {
+ position: React.PropTypes.oneOf(['absolute', 'fixed', 'relative', 'static', 'inherit'])
+ },
+ getDefaultProps: function() {
+ return { position: 'relative' };
+ },
+ render: function() {
+ return (
+ <div className="loading-screen" style={{position: this.props.position}}>
+ <div className="loading__content">
+ <h3>Loading</h3>
+ <div className="round round-1"></div>
+ <div className="round round-2"></div>
+ <div className="round round-3"></div>
+ </div>
+ </div>
+ );
+ }
+});
diff --git a/web/react/components/member_list_item.jsx b/web/react/components/member_list_item.jsx
index 357fd49a8..cf8c71d7e 100644
--- a/web/react/components/member_list_item.jsx
+++ b/web/react/components/member_list_item.jsx
@@ -23,6 +23,7 @@ module.exports = React.createClass({
var member = this.props.member;
var isAdmin = this.props.isAdmin;
var isMemberAdmin = member.roles.indexOf("admin") > -1;
+ var timestamp = UserStore.getCurrentUser().update_at;
var invite;
if (member.invited && this.props.handleInvite) {
@@ -53,7 +54,7 @@ module.exports = React.createClass({
return (
<div className="row member-div">
- <img className="post-profile-img pull-left" src={"/api/v1/users/" + member.id + "/image"} height="36" width="36" />
+ <img className="post-profile-img pull-left" src={"/api/v1/users/" + member.id + "/image?time=" + timestamp} height="36" width="36" />
<span className="member-name">{member.username}</span>
<span className="member-email">{member.email}</span>
{ invite }
diff --git a/web/react/components/member_list_team.jsx b/web/react/components/member_list_team.jsx
index cfb473e5e..aa53c5db6 100644
--- a/web/react/components/member_list_team.jsx
+++ b/web/react/components/member_list_team.jsx
@@ -61,7 +61,8 @@ var MemberListTeamItem = React.createClass({
render: function() {
var server_error = this.state.server_error ? <div style={{ clear: "both" }} className="has-error"><label className='has-error control-label'>{this.state.server_error}</label></div> : null;
var user = this.props.user;
- var currentRoles = "Member"
+ var currentRoles = "Member";
+ var timestamp = UserStore.getCurrentUser().update_at;
if (user.roles.length > 0) {
currentRoles = user.roles.charAt(0).toUpperCase() + user.roles.slice(1);
@@ -83,7 +84,7 @@ var MemberListTeamItem = React.createClass({
return (
<div className="row member-div">
- <img className="post-profile-img pull-left" src={"/api/v1/users/" + user.id + "/image"} height="36" width="36" />
+ <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>
<div className="dropdown member-drop">
diff --git a/web/react/components/mention.jsx b/web/react/components/mention.jsx
index 3c33ddf49..520b81cbb 100644
--- a/web/react/components/mention.jsx
+++ b/web/react/components/mention.jsx
@@ -1,5 +1,6 @@
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
// See License.txt for license information.
+var UserStore = require("../stores/user_store.jsx");
module.exports = React.createClass({
handleClick: function() {
@@ -7,8 +8,9 @@ module.exports = React.createClass({
},
render: function() {
var icon;
+ var timestamp = UserStore.getCurrentUser().update_at;
if (this.props.id != null) {
- icon = <span><img className="mention-img" src={"/api/v1/users/" + this.props.id + "/image"}/></span>;
+ icon = <span><img className="mention-img" src={"/api/v1/users/" + this.props.id + "/image?time=" + timestamp}/></span>;
} else {
icon = <span><i className="mention-img fa fa-users fa-2x"></i></span>;
}
diff --git a/web/react/components/mention_list.jsx b/web/react/components/mention_list.jsx
index ba2c53612..103ff29bb 100644
--- a/web/react/components/mention_list.jsx
+++ b/web/react/components/mention_list.jsx
@@ -9,7 +9,12 @@ var Mention = require('./mention.jsx');
var Constants = require('../utils/constants.jsx');
var ActionTypes = Constants.ActionTypes;
+var MAX_HEIGHT_LIST = 292;
+var MAX_ITEMS_IN_LIST = 25;
+var ITEM_HEIGHT = 36;
+
module.exports = React.createClass({
+ displayName: "MentionList",
componentDidMount: function() {
PostStore.addMentionDataChangeListener(this._onChange);
@@ -72,7 +77,7 @@ module.exports = React.createClass({
},
render: function() {
var mentionText = this.state.mentionText;
- if (mentionText === '-1') return (<div/>);
+ if (mentionText === '-1') return null;
var profiles = UserStore.getActiveOnlyProfiles();
var users = [];
@@ -100,8 +105,7 @@ module.exports = React.createClass({
var mentions = {};
var index = 0;
- for (var i = 0; i < users.length; i++) {
- if (Object.keys(mentions).length >= 25) break;
+ for (var i = 0; i < users.length && index < MAX_ITEMS_IN_LIST; i++) {
if (this.alreadyMentioned(users[i].username)) continue;
var firstName = "", lastName = "";
@@ -127,17 +131,20 @@ module.exports = React.createClass({
}
var numMentions = Object.keys(mentions).length;
- if (numMentions < 1) return (<div/>);
+ if (numMentions < 1) return null;
- var height = (numMentions*36) + 4;
- var width = $('#'+this.props.id).parent().width();
- var bottom = $(window).height() - $('#'+this.props.id).offset().top;
- var left = $('#'+this.props.id).offset().left;
- var max_height = $('#'+this.props.id).offset().top - 10;
+ var $mention_tab = $('#'+this.props.id);
+ var maxHeight = Math.min(MAX_HEIGHT_LIST, $mention_tab.offset().top - 10);
+ var style = {
+ height: Math.min(maxHeight, (numMentions*ITEM_HEIGHT) + 4),
+ width: $mention_tab.parent().width(),
+ bottom: $(window).height() - $mention_tab.offset().top,
+ left: $mention_tab.offset().left
+ };
return (
- <div className="mentions--top" style={{height: height, width: width, bottom: bottom, left: left}}>
- <div ref="mentionlist" className="mentions-box" style={{height: height, width: width}}>
+ <div className="mentions--top" style={style}>
+ <div ref="mentionlist" className="mentions-box">
{ mentions }
</div>
</div>
diff --git a/web/react/components/more_channels.jsx b/web/react/components/more_channels.jsx
index c3ddc76f3..007476f9b 100644
--- a/web/react/components/more_channels.jsx
+++ b/web/react/components/more_channels.jsx
@@ -7,6 +7,7 @@ var client = require('../utils/client.jsx');
var asyncClient = require('../utils/async_client.jsx');
var UserStore = require('../stores/user_store.jsx');
var ChannelStore = require('../stores/channel_store.jsx');
+var LoadingScreen = require('./loading_screen.jsx');
function getStateFromStores() {
return {
@@ -16,6 +17,8 @@ function getStateFromStores() {
}
module.exports = React.createClass({
+ displayName: "MoreChannelsModal",
+
componentDidMount: function() {
ChannelStore.addMoreChangeListener(this._onChange);
$(this.refs.modal.getDOMNode()).on('shown.bs.modal', function (e) {
@@ -90,7 +93,7 @@ module.exports = React.createClass({
<p className="more-channel-name">{channel.display_name}</p>
<p className="more-channel-description">{channel.description}</p>
</td>
- <td className="td--action"><button onClick={outter.handleJoin.bind(outter, channel.id)} className="pull-right btn btn-primary">Join</button></td>
+ <td className="td--action"><button onClick={outter.handleJoin.bind(outter, channel.id)} className="btn btn-primary">Join</button></td>
</tr>
)
})}
@@ -100,15 +103,7 @@ module.exports = React.createClass({
<p className="primary-message">No more channels to join</p>
<p className="secondary-message">Click 'Create New Channel' to make a new one</p>
</div>)
- : <div ref="loadingscreen" className="loading-screen loading-screen--channel">
- <div className="loading__content">
- <h3>Loading</h3>
- <div id="round_1" className="round"></div>
- <div id="round_2" className="round"></div>
- <div id="round_3" className="round"></div>
- </div>
- </div>
- }
+ : <LoadingScreen /> }
{ server_error }
</div>
<div className="modal-footer">
diff --git a/web/react/components/post.jsx b/web/react/components/post.jsx
index 04b5ba082..5457e1cd3 100644
--- a/web/react/components/post.jsx
+++ b/web/react/components/post.jsx
@@ -10,6 +10,7 @@ var UserStore = require('../stores/user_store.jsx');
var ActionTypes = Constants.ActionTypes;
module.exports = React.createClass({
+ displayName: "Post",
componentDidMount: function() {
$('.modal').on('show.bs.modal', function () {
$('.modal-body').css('overflow-y', 'auto');
@@ -19,7 +20,7 @@ module.exports = React.createClass({
handleCommentClick: function(e) {
e.preventDefault();
- data = {};
+ var data = {};
data.order = [this.props.post.id];
data.posts = this.props.posts;
@@ -48,7 +49,6 @@ module.exports = React.createClass({
var commentCount = 0;
var commentRootId = parentPost ? post.root_id : post.id;
- var rootUser = "";
for (var postId in posts) {
if (posts[postId].root_id == commentRootId) {
commentCount += 1;
@@ -57,12 +57,7 @@ module.exports = React.createClass({
var error = this.state.error ? <div className='form-group has-error'><label className='control-label'>{ this.state.error }</label></div> : null;
- if (this.props.sameRoot){
- rootUser = "same--root";
- }
- else {
- rootUser = "other--root";
- }
+ var rootUser = this.props.sameRoot ? "same--root" : "other--root";
var postType = "";
if (type != "Post"){
@@ -74,14 +69,16 @@ module.exports = React.createClass({
currentUserCss = "current--user";
}
+ var timestamp = UserStore.getCurrentUser().update_at;
+
return (
<div>
<div id={post.id} className={"post " + this.props.sameUser + " " + rootUser + " " + postType + " " + currentUserCss}>
{ !this.props.hideProfilePic ?
<div className="post-profile-img__container">
- <img className="post-profile-img" src={"/api/v1/users/" + post.user_id + "/image"} height="36" width="36" />
+ <img className="post-profile-img" src={"/api/v1/users/" + post.user_id + "/image?time=" + timestamp} height="36" width="36" />
</div>
- : "" }
+ : null }
<div className="post__content">
<PostHeader post={post} sameRoot={this.props.sameRoot} commentCount={commentCount} handleCommentClick={this.handleCommentClick} isLastComment={this.props.isLastComment} />
<PostBody post={post} sameRoot={this.props.sameRoot} parentPost={parentPost} posts={posts} handleCommentClick={this.handleCommentClick} />
diff --git a/web/react/components/post_body.jsx b/web/react/components/post_body.jsx
index 7d5ef4d33..d9678df30 100644
--- a/web/react/components/post_body.jsx
+++ b/web/react/components/post_body.jsx
@@ -71,11 +71,22 @@ module.exports = React.createClass({
name = <a className="theme" onClick={function(){ utils.searchForTerm(profile.username); }}>{profile.username}</a>;
}
- var message = parentPost.message;
+ var message = ""
+ if(parentPost.message) {
+ message = utils.replaceHtmlEntities(parentPost.message)
+ } else if (parentPost.filenames.length) {
+ message = parentPost.filenames[0].split('/').pop();
+
+ if (parentPost.filenames.length === 2) {
+ message += " plus 1 other file";
+ } else if (parentPost.filenames.length > 2) {
+ message += " plus " + (parentPost.filenames.length - 1) + " other files";
+ }
+ }
comment = (
<p className="post-link">
- <span>Commented on {name}{apostrophe} message: <a className="theme" onClick={this.props.handleCommentClick}>{utils.replaceHtmlEntities(message)}</a></span>
+ <span>Commented on {name}{apostrophe} message: <a className="theme" onClick={this.props.handleCommentClick}>{message}</a></span>
</p>
);
@@ -120,7 +131,7 @@ module.exports = React.createClass({
return (
<div className="post-body">
{ comment }
- <p key={post.Id+"_message"} className={postClass}><span>{inner}</span></p>
+ <p key={post.id+"_message"} className={postClass}><span>{inner}</span></p>
{ filenames && filenames.length > 0 ?
<div className="post-image__columns">
{ postFiles }
diff --git a/web/react/components/post_list.jsx b/web/react/components/post_list.jsx
index d6dc9ce30..9349d0240 100644
--- a/web/react/components/post_list.jsx
+++ b/web/react/components/post_list.jsx
@@ -8,6 +8,7 @@ var UserProfile = require( './user_profile.jsx' );
var AsyncClient = require('../utils/async_client.jsx');
var CreatePost = require('./create_post.jsx');
var Post = require('./post.jsx');
+var LoadingScreen = require('./loading_screen.jsx');
var SocketStore = require('../stores/socket_store.jsx');
var utils = require('../utils/utils.jsx');
var Client = require('../utils/client.jsx');
@@ -26,37 +27,8 @@ function getStateFromStores() {
};
}
-function changeColor(col, amt) {
-
- var usePound = false;
-
- if (col[0] == "#") {
- col = col.slice(1);
- usePound = true;
- }
-
- var num = parseInt(col,16);
-
- var r = (num >> 16) + amt;
-
- if (r > 255) r = 255;
- else if (r < 0) r = 0;
-
- var b = ((num >> 8) & 0x00FF) + amt;
-
- if (b > 255) b = 255;
- else if (b < 0) b = 0;
-
- var g = (num & 0x0000FF) + amt;
-
- if (g > 255) g = 255;
- else if (g < 0) g = 0;
-
- return (usePound?"#":"") + String("000000" + (g | (b << 8) | (r << 16)).toString(16)).slice(-6);
-
-}
-
module.exports = React.createClass({
+ displayName: "PostList",
scrollPosition: 0,
preventScrollTrigger: false,
gotMorePosts: false,
@@ -69,7 +41,7 @@ module.exports = React.createClass({
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: ' + changeColor(user.props.theme, -10) +';');
+ 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+';');
@@ -161,24 +133,20 @@ module.exports = React.createClass({
$('body').off('click.userpopover');
},
resize: function() {
+ var post_holder = $(".post-list-holder-by-time")[0];
+ this.preventScrollTrigger = true;
if (this.gotMorePosts) {
this.gotMorePosts = false;
- var post_holder = $(".post-list-holder-by-time")[0];
- this.preventScrollTrigger = true;
$(post_holder).scrollTop($(post_holder).scrollTop() + (post_holder.scrollHeight-this.oldScrollHeight) );
- $(post_holder).perfectScrollbar('update');
} else {
- var post_holder = $(".post-list-holder-by-time")[0];
- this.preventScrollTrigger = true;
if ($("#new_message")[0] && !this.scrolledToNew) {
$(post_holder).scrollTop($(post_holder).scrollTop() + $("#new_message").offset().top - 63);
- $(post_holder).perfectScrollbar('update');
this.scrolledToNew = true;
} else {
$(post_holder).scrollTop(post_holder.scrollHeight);
- $(post_holder).perfectScrollbar('update');
}
}
+ $(post_holder).perfectScrollbar('update');
},
_onChange: function() {
var newState = getStateFromStores();
@@ -342,12 +310,15 @@ module.exports = React.createClass({
more_messages = (
<div className="channel-intro">
<div className="post-profile-img__container channel-intro-img">
- <img className="post-profile-img" src={"/api/v1/users/" + teammate.id + "/image"} height="50" width="50" />
+ <img className="post-profile-img" src={"/api/v1/users/" + teammate.id + "/image?time=" + teammate.update_at} height="50" width="50" />
</div>
<div className="channel-intro-profile">
<strong><UserProfile userId={teammate.id} /></strong>
</div>
- <p className="channel-intro-text">{"This is the start of your private message history with " + teammate_name + "." }<br/>{"Private messages and files shared here are not shown to people outside this area."}</p>
+ <p className="channel-intro-text">
+ {"This is the start of your private message history with " + teammate_name + "." }<br/>
+ {"Private messages and files shared here are not shown to people outside this area."}
+ </p>
</div>
);
} else {
@@ -410,7 +381,7 @@ module.exports = React.createClass({
{ channel.type === 'P' ? " Only invited members can see this private group." : " Any member can join and read this channel." }
<br/>
<a className="intro-links" href="#" style={userStyle} data-toggle="modal" data-target="#edit_channel" data-desc={channel.description} data-title={channel.display_name} data-channelid={channel.id}><i className="fa fa-pencil"></i>Set a description</a>
- <a className="intro-links" style={userStyle} data-toggle="modal" data-target="#channel_invite"><i className="fa fa-user-plus"></i>Invite others to this {ui_type}</a>
+ <a className="intro-links" href="#" style={userStyle} data-toggle="modal" data-target="#channel_invite"><i className="fa fa-user-plus"></i>Invite others to this {ui_type}</a>
</p>
</div>
);
@@ -420,37 +391,35 @@ module.exports = React.createClass({
var postCtls = [];
- if (posts != undefined) {
+ if (posts) {
var previousPostDay = posts[order[order.length-1]] ? utils.getDateForUnixTicks(posts[order[order.length-1]].create_at): new Date();
- var currentPostDay = new Date();
+ var currentPostDay;
for (var i = order.length-1; i >= 0; i--) {
var post = posts[order[i]];
- var parentPost;
+ var parentPost = post.parent_id ? posts[post.parent_id] : null;
- if (post.parent_id) {
- parentPost = posts[post.parent_id];
- } else {
- parentPost = null;
- }
+ var sameUser = '';
+ var sameRoot = false;
+ var hideProfilePic = false;
+ var prevPost = (i < order.length - 1) ? posts[order[i + 1]] : null;
- var sameUser = i < order.length-1 && posts[order[i+1]].user_id === post.user_id && post.create_at - posts[order[i+1]].create_at <= 1000*60*5 ? "same--user" : "";
- var sameRoot = i < order.length-1 && post.root_id != "" && (posts[order[i+1]].id === post.root_id || posts[order[i+1]].root_id === post.root_id) ? true : false;
+ if (prevPost) {
+ sameUser = (prevPost.user_id === post.user_id) && (post.create_at - prevPost.create_at <= 1000*60*5) ? "same--user" : "";
+ sameRoot = utils.isComment(post) && (prevPost.id === post.root_id || prevPost.root_id === post.root_id);
- // we only hide the profile pic if the previous post is not a comment, the current post is not a comment, and the previous post was made by the same user as the current post
- var hideProfilePic = i < order.length-1 && posts[order[i+1]].user_id === post.user_id && posts[order[i+1]].root_id === '' && post.root_id === '';
+ // we only hide the profile pic if the previous post is not a comment, the current post is not a comment, and the previous post was made by the same user as the current post
+ hideProfilePic = (prevPost.user_id === post.user_id) && !utils.isComment(prevPost) && !utils.isComment(post);
+ }
// check if it's the last comment in a consecutive string of comments on the same post
- var isLastComment = false;
- if (utils.isComment(post)) {
- // it is the last comment if it is last post in the channel or the next post has a different root post
- isLastComment = (i === 0 || posts[order[i-1]].root_id != post.root_id);
- }
+ // it is the last comment if it is last post in the channel or the next post has a different root post
+ var isLastComment = utils.isComment(post) && (i === 0 || posts[order[i-1]].root_id != post.root_id);
var postCtl = <Post sameUser={sameUser} sameRoot={sameRoot} post={post} parentPost={parentPost} key={post.id} posts={posts} hideProfilePic={hideProfilePic} isLastComment={isLastComment} />;
currentPostDay = utils.getDateForUnixTicks(post.create_at);
- if(currentPostDay.getDate() !== previousPostDay.getDate() || currentPostDay.getMonth() !== previousPostDay.getMonth() || currentPostDay.getFullYear() !== previousPostDay.getFullYear()) {
+ if (currentPostDay.toDateString() != previousPostDay.toDateString()) {
postCtls.push(
<div className="date-separator">
<hr className="separator__hr" />
@@ -469,20 +438,10 @@ module.exports = React.createClass({
);
}
postCtls.push(postCtl);
- previousPostDay = utils.getDateForUnixTicks(post.create_at);
+ previousPostDay = currentPostDay;
}
- }
- else {
- postCtls.push(
- <div ref="loadingscreen" className="loading-screen">
- <div className="loading__content">
- <h3>Loading</h3>
- <div id="round_1" className="round"></div>
- <div id="round_2" className="round"></div>
- <div id="round_3" className="round"></div>
- </div>
- </div>
- );
+ } else {
+ postCtls.push(<LoadingScreen position="absolute" />);
}
return (
@@ -497,5 +456,3 @@ module.exports = React.createClass({
);
}
});
-
-
diff --git a/web/react/components/post_right.jsx b/web/react/components/post_right.jsx
index 115ee87d4..408fbf83a 100644
--- a/web/react/components/post_right.jsx
+++ b/web/react/components/post_right.jsx
@@ -67,6 +67,7 @@ RootPost = React.createClass({
var message = utils.textToJsx(this.props.post.message);
var filenames = this.props.post.filenames;
var isOwner = UserStore.getCurrentId() == this.props.post.user_id;
+ var timestamp = UserStore.getProfile(this.props.post.user_id).update_at;
var type = "Post";
if (this.props.post.root_id.length > 0) {
@@ -118,7 +119,7 @@ RootPost = React.createClass({
return (
<div className={"post post--root " + currentUserCss}>
<div className="post-profile-img__container">
- <img className="post-profile-img" src={"/api/v1/users/" + this.props.post.user_id + "/image"} height="36" width="36" />
+ <img className="post-profile-img" src={"/api/v1/users/" + this.props.post.user_id + "/image?time=" + timestamp} height="36" width="36" />
</div>
<div className="post__content">
<ul className="post-header">
@@ -227,11 +228,12 @@ CommentPost = React.createClass({
}
var message = utils.textToJsx(this.props.post.message);
+ var timestamp = UserStore.getCurrentUser().update_at;
return (
<div className={commentClass + " " + currentUserCss}>
<div className="post-profile-img__container">
- <img className="post-profile-img" src={"/api/v1/users/" + this.props.post.user_id + "/image"} height="36" width="36" />
+ <img className="post-profile-img" src={"/api/v1/users/" + this.props.post.user_id + "/image?time=" + timestamp} height="36" width="36" />
</div>
<div className="post__content">
<ul className="post-header">
diff --git a/web/react/components/search_results.jsx b/web/react/components/search_results.jsx
index 003a38b7e..156cf0120 100644
--- a/web/react/components/search_results.jsx
+++ b/web/react/components/search_results.jsx
@@ -76,6 +76,7 @@ SearchItem = React.createClass({
var message = utils.textToJsx(this.props.post.message, {searchTerm: this.props.term, noMentionHighlight: !this.props.isMentionSearch});
var channelName = "";
var channel = ChannelStore.get(this.props.post.channel_id)
+ var timestamp = UserStore.getCurrentUser().update_at;
if (channel) {
if (channel.type === 'D') {
@@ -89,7 +90,7 @@ SearchItem = React.createClass({
<div className="search-item-container post" onClick={this.handleClick}>
<div className="search-channel__name">{ channelName }</div>
<div className="post-profile-img__container">
- <img className="post-profile-img" src={"/api/v1/users/" + this.props.post.user_id + "/image"} height="36" width="36" />
+ <img className="post-profile-img" src={"/api/v1/users/" + this.props.post.user_id + "/image?time=" + timestamp} height="36" width="36" />
</div>
<div className="post__content">
<ul className="post-header">
diff --git a/web/react/components/sidebar.jsx b/web/react/components/sidebar.jsx
index 2095978e8..cae9425d3 100644
--- a/web/react/components/sidebar.jsx
+++ b/web/react/components/sidebar.jsx
@@ -249,11 +249,27 @@ var SidebarLoggedIn = React.createClass({
var repRegex = new RegExp("<br>", "g");
var post = JSON.parse(msg.props.post);
- var msg = post.message.replace(repRegex, "\n").split("\n")[0].replace("<mention>", "").replace("</mention>", "");
+ var msgProps = msg.props;
+ var msg = post.message.replace(repRegex, "\n").replace(/\n+/g, " ").replace("<mention>", "").replace("</mention>", "");
+
if (msg.length > 50) {
msg = msg.substring(0,49) + "...";
}
- utils.notifyMe(title, username + " wrote: " + msg, channel);
+
+ if (msg.length === 0) {
+ if (msgProps.image) {
+ utils.notifyMe(title, username + " uploaded an image", channel);
+ }
+ else if (msgProps.otherFile) {
+ utils.notifyMe(title, username + " uploaded a file", channel);
+ }
+ else {
+ utils.notifyMe(title, username + " did something new", channel);
+ }
+ }
+ else {
+ utils.notifyMe(title, username + " wrote: " + msg, channel);
+ }
if (!user.notify_props || user.notify_props.desktop_sound === "true") {
utils.ding();
}
diff --git a/web/react/components/sidebar_header.jsx b/web/react/components/sidebar_header.jsx
index 0b59d2036..54858a04d 100644
--- a/web/react/components/sidebar_header.jsx
+++ b/web/react/components/sidebar_header.jsx
@@ -77,7 +77,7 @@ var NavbarDropdown = React.createClass({
for (var i = 0; i < this.state.teams.length; i++) {
var domain = this.state.teams[i];
- if (domain == utils.getSubDomain())
+ if (domain == utils.getSubDomain())
continue;
if (teams.length == 0)
@@ -121,10 +121,15 @@ module.exports = React.createClass({
},
render: function() {
var teamName = this.props.teamName ? this.props.teamName : config.SiteName;
+ var me = UserStore.getCurrentUser()
return (
<div className="team__header theme">
- <a className="team__name" href="/channels/town-square">{ teamName }</a>
+ <img className="user__picture" src={"/api/v1/users/" + me.id + "/image?time=" + me.update_at} />
+ <div className="header__info">
+ <div className="user__name">@{me.username}</div>
+ <a className="team__name" href="/channels/town-square">{ teamName }</a>
+ </div>
<NavbarDropdown teamType={this.props.teamType} />
</div>
);
diff --git a/web/react/components/signup_team_complete.jsx b/web/react/components/signup_team_complete.jsx
index 500ee231e..9e2a13955 100644
--- a/web/react/components/signup_team_complete.jsx
+++ b/web/react/components/signup_team_complete.jsx
@@ -596,19 +596,14 @@ PasswordPage = React.createClass({
module.exports = React.createClass({
updateParent: function(state, skipSet) {
- BrowserStore.setGlobalItem(this.props.hash, JSON.stringify(state));
+ BrowserStore.setGlobalItem(this.props.hash, state);
if (!skipSet) {
this.setState(state);
}
},
getInitialState: function() {
- var props = null;
- try {
- props = JSON.parse(BrowserStore.getGlobalItem(this.props.hash));
- }
- catch(parse_error) {
- }
+ var props = BrowserStore.getGlobalItem(this.props.hash);
if (!props) {
props = {};
@@ -628,7 +623,7 @@ module.exports = React.createClass({
props.data = this.props.data;
}
- return props ;
+ return props;
},
render: function() {
if (this.state.wizard == "welcome") {
diff --git a/web/react/components/signup_user_complete.jsx b/web/react/components/signup_user_complete.jsx
index ef1eb1c62..d1053c778 100644
--- a/web/react/components/signup_user_complete.jsx
+++ b/web/react/components/signup_user_complete.jsx
@@ -17,7 +17,7 @@ module.exports = React.createClass({
return;
}
- var username_error = utils.isValidUsername(this.state.user.username)
+ var username_error = utils.isValidUsername(this.state.user.username);
if (username_error === "Cannot use a reserved word as a username.") {
this.setState({name_error: "This username is reserved, please choose a new one.", email_error: "", password_error: "", server_error: ""});
return;
@@ -72,12 +72,7 @@ module.exports = React.createClass({
);
},
getInitialState: function() {
- var props = null;
- try {
- props = JSON.parse(BrowserStore.getGlobalItem(this.props.hash));
- }
- catch(parse_error) {
- }
+ var props = BrowserStore.getGlobalItem(this.props.hash);
if (!props) {
props = {};
@@ -90,7 +85,7 @@ module.exports = React.createClass({
props.original_email = this.props.email;
}
- return props ;
+ return props;
},
render: function() {
diff --git a/web/react/components/user_profile.jsx b/web/react/components/user_profile.jsx
index 648960471..89d0a80ff 100644
--- a/web/react/components/user_profile.jsx
+++ b/web/react/components/user_profile.jsx
@@ -53,7 +53,7 @@ module.exports = React.createClass({
var name = this.props.overwriteName ? this.props.overwriteName : this.state.profile.username;
- var data_content = "<img style='margin: 10px' src='/api/v1/users/" + this.state.profile.id + "/image' height='128' width='128' />";
+ var data_content = "<img style='margin: 10px' src='/api/v1/users/" + this.state.profile.id + "/image?time=" + this.state.profile.update_at + "' height='128' width='128' />";
if (!config.ShowEmail) {
data_content += "<div class='text-nowrap'>Email not shared</div>";
} else {
diff --git a/web/react/components/user_settings.jsx b/web/react/components/user_settings.jsx
index b4c3747af..06d8d0208 100644
--- a/web/react/components/user_settings.jsx
+++ b/web/react/components/user_settings.jsx
@@ -626,7 +626,7 @@ var SecurityTab = React.createClass({
client.updatePassword(data,
function(data) {
- this.updateSection("");
+ this.props.updateSection("");
AsyncClient.getMe();
this.setState({ current_password: '', new_password: '', confirm_password: '' });
}.bind(this),
diff --git a/web/react/stores/browser_store.jsx b/web/react/stores/browser_store.jsx
index 82cf9a942..4d6eb0b8d 100644
--- a/web/react/stores/browser_store.jsx
+++ b/web/react/stores/browser_store.jsx
@@ -1,85 +1,104 @@
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
// See License.txt for license information.
-var UserStore = require('../stores/user_store.jsx');
-// Also change model/utils.go ETAG_ROOT_VERSION
-var BROWSER_STORE_VERSION = '.1';
-
-var _initialized = false;
-
-function _initialize() {
- var currentVersion = localStorage.getItem("local_storage_version");
- if (currentVersion !== BROWSER_STORE_VERSION) {
- localStorage.clear();
- sessionStorage.clear();
- localStorage.setItem("local_storage_version", BROWSER_STORE_VERSION);
- }
- _initialized = true;
+var UserStore;
+function getPrefix() {
+ if (!UserStore) UserStore = require('./user_store.jsx');
+ return UserStore.getCurrentId() + '_';
}
-module.exports.setItem = function(name, value) {
- if (!_initialized) _initialize();
- var user_id = UserStore.getCurrentId();
- localStorage.setItem(user_id + "_" + name, value);
-};
+// Also change model/utils.go ETAG_ROOT_VERSION
+var BROWSER_STORE_VERSION = '.3';
-module.exports.getItem = function(name) {
- if (!_initialized) _initialize();
- var user_id = UserStore.getCurrentId();
- return localStorage.getItem(user_id + "_" + name);
-};
+module.exports = {
+ _initialized: false,
-module.exports.removeItem = function(name) {
- if (!_initialized) _initialize();
- var user_id = UserStore.getCurrentId();
- localStorage.removeItem(user_id + "_" + name);
-};
+ _initialize: function() {
+ var currentVersion = localStorage.getItem("local_storage_version");
+ if (currentVersion !== BROWSER_STORE_VERSION) {
+ this.clear();
+ localStorage.setItem("local_storage_version", BROWSER_STORE_VERSION);
+ }
+ this._initialized = true;
+ },
-module.exports.setGlobalItem = function(name, value) {
- if (!_initialized) _initialize();
- localStorage.setItem(name, value);
-};
+ getItem: function(name, defaultValue) {
+ return this.getGlobalItem(getPrefix() + name, defaultValue);
+ },
-module.exports.getGlobalItem = function(name) {
- if (!_initialized) _initialize();
- return localStorage.getItem(name);
-};
+ setItem: function(name, value) {
+ this.setGlobalItem(getPrefix() + name, value);
+ },
-module.exports.removeGlobalItem = function(name) {
- if (!_initialized) _initialize();
- localStorage.removeItem(name);
-};
+ removeItem: function(name) {
+ if (!this._initialized) this._initialize();
-module.exports.clear = function() {
- localStorage.clear();
- sessionStorage.clear();
-};
+ localStorage.removeItem(getPrefix() + name);
+ },
+
+ setGlobalItem: function(name, value) {
+ if (!this._initialized) this._initialize();
+
+ localStorage.setItem(name, JSON.stringify(value));
+ },
+
+ getGlobalItem: function(name, defaultValue) {
+ if (!this._initialized) this._initialize();
-// Preforms the given action on each item that has the given prefix
-// Signiture for action is action(key, value)
-module.exports.actionOnItemsWithPrefix = function (prefix, action) {
- var user_id = UserStore.getCurrentId();
- var id_len = user_id.length;
- var prefix_len = prefix.length;
- for (var key in localStorage) {
- if (key.substring(id_len, id_len + prefix_len) === prefix) {
- var userkey = key.substring(id_len);
- action(userkey, BrowserStore.getItem(key));
+ var result = null;
+ try {
+ result = JSON.parse(localStorage.getItem(name));
+ } catch (err) {}
+
+ if (result === null && typeof defaultValue !== 'undefined') {
+ result = defaultValue;
}
- }
-};
-module.exports.isLocalStorageSupported = function() {
- try {
- sessionStorage.setItem("testSession", '1');
- sessionStorage.removeItem("testSession");
+ return result;
+ },
- localStorage.setItem("testLocal", '1');
- localStorage.removeItem("testLocal", '1');
+ removeGlobalItem: function(name) {
+ if (!this._initialized) this._initialize();
- return true;
- }
- catch (e) {
- return false;
+ localStorage.removeItem(name);
+ },
+
+ clear: function() {
+ localStorage.clear();
+ sessionStorage.clear();
+ },
+
+ /**
+ * Preforms the given action on each item that has the given prefix
+ * Signiture for action is action(key, value)
+ */
+ actionOnItemsWithPrefix: function (prefix, action) {
+ if (!this._initialized) this._initialize();
+
+ var globalPrefix = getPrefix();
+ var globalPrefixiLen = globalPrefix.length;
+ for (var key in localStorage) {
+ if (key.lastIndexOf(globalPrefix + prefix, 0) === 0) {
+ var userkey = key.substring(globalPrefixiLen);
+ action(userkey, this.getGlobalItem(key));
+ }
+ }
+ },
+
+ isLocalStorageSupported: function() {
+ try {
+ sessionStorage.setItem("testSession", '1');
+ sessionStorage.removeItem("testSession");
+
+ localStorage.setItem("testLocal", '1');
+ if (localStorage.getItem("testLocal") != '1') {
+ return false;
+ }
+ localStorage.removeItem("testLocal", '1');
+
+ return true;
+ } catch (e) {
+ return false;
+ }
}
};
diff --git a/web/react/stores/channel_store.jsx b/web/react/stores/channel_store.jsx
index 4429a5312..4a27e5f17 100644
--- a/web/react/stores/channel_store.jsx
+++ b/web/react/stores/channel_store.jsx
@@ -16,6 +16,7 @@ var MORE_CHANGE_EVENT = 'change';
var EXTRA_INFO_EVENT = 'extra_info';
var ChannelStore = assign({}, EventEmitter.prototype, {
+ _current_id: null,
emitChange: function() {
this.emit(CHANGE_EVENT);
},
@@ -88,10 +89,7 @@ var ChannelStore = assign({}, EventEmitter.prototype, {
return this._getMoreChannels();
},
setCurrentId: function(id) {
- if (id == null)
- BrowserStore.removeItem("current_channel_id");
- else
- BrowserStore.setItem("current_channel_id", id);
+ this._current_id = id;
},
setLastVisitedName: function(name) {
if (name == null)
@@ -117,10 +115,10 @@ var ChannelStore = assign({}, EventEmitter.prototype, {
this._storeChannelMembers(cm);
},
getCurrentId: function() {
- return BrowserStore.getItem("current_channel_id");
+ return this._current_id;
},
getCurrent: function() {
- var currentId = ChannelStore.getCurrentId();
+ var currentId = this.getCurrentId();
if (currentId != null)
return this.get(currentId);
@@ -165,49 +163,22 @@ var ChannelStore = assign({}, EventEmitter.prototype, {
return extra;
},
_storeChannels: function(channels) {
- BrowserStore.setItem("channels", JSON.stringify(channels));
+ BrowserStore.setItem("channels", channels);
},
_getChannels: function() {
- var channels = [];
- try {
- channels = JSON.parse(BrowserStore.getItem("channels"));
- }
- catch (err) {
- }
-
- if (channels == null) {
- channels = [];
- }
-
- return channels;
+ return BrowserStore.getItem("channels", []);
},
_storeChannelMembers: function(channelMembers) {
- BrowserStore.setItem("channel_members", JSON.stringify(channelMembers));
+ BrowserStore.setItem("channel_members", channelMembers);
},
_getChannelMembers: function() {
- var members = {};
- try {
- members = JSON.parse(BrowserStore.getItem("channel_members"));
- }
- catch (err) {
- }
-
- if (members == null) {
- members = {};
- }
-
- return members;
+ return BrowserStore.getItem("channel_members", {});
},
_storeMoreChannels: function(channels) {
- BrowserStore.setItem("more_channels", JSON.stringify(channels));
+ BrowserStore.setItem("more_channels", channels);
},
_getMoreChannels: function() {
- var channels = null;
- try {
- channels = JSON.parse(BrowserStore.getItem("more_channels"));
- }
- catch (err) {
- }
+ var channels = BrowserStore.getItem("more_channels");
if (channels == null) {
channels = {};
@@ -217,21 +188,10 @@ var ChannelStore = assign({}, EventEmitter.prototype, {
return channels;
},
_storeExtraInfos: function(extraInfos) {
- BrowserStore.setItem("extra_infos", JSON.stringify(extraInfos));
+ BrowserStore.setItem("extra_infos", extraInfos);
},
_getExtraInfos: function() {
- var members = {};
- try {
- members = JSON.parse(BrowserStore.getItem("extra_infos"));
- }
- catch (err) {
- }
-
- if (members == null) {
- members = {};
- }
-
- return members;
+ return BrowserStore.getItem("extra_infos", {});
}
});
diff --git a/web/react/stores/error_store.jsx b/web/react/stores/error_store.jsx
index 3aed6aef2..203b692ec 100644
--- a/web/react/stores/error_store.jsx
+++ b/web/react/stores/error_store.jsx
@@ -29,18 +29,11 @@ var ErrorStore = assign({}, EventEmitter.prototype, {
BrowserStore.removeItem("last_error");
},
getLastError: function() {
- var error = null;
- try {
- error = JSON.parse(BrowserStore.getItem("last_error"));
- }
- catch (err) {
- }
-
- return error;
+ return BrowserStore.getItem('last_error');
},
_storeLastError: function(error) {
- BrowserStore.setItem("last_error", JSON.stringify(error));
+ BrowserStore.setItem("last_error", error);
},
});
diff --git a/web/react/stores/post_store.jsx b/web/react/stores/post_store.jsx
index 8bf3fdcb2..e773bb688 100644
--- a/web/react/stores/post_store.jsx
+++ b/web/react/stores/post_store.jsx
@@ -106,55 +106,27 @@ var PostStore = assign({}, EventEmitter.prototype, {
this.emitChange();
},
_storePosts: function(channelId, posts) {
- BrowserStore.setItem("posts_" + channelId, JSON.stringify(posts));
+ BrowserStore.setItem("posts_" + channelId, posts);
},
getPosts: function(channelId) {
- var posts = null;
- try {
- posts = JSON.parse(BrowserStore.getItem("posts_" + channelId));
- }
- catch (err) {
- }
-
- return posts;
+ return BrowserStore.getItem("posts_" + channelId);
},
storeSearchResults: function(results, is_mention_search) {
- BrowserStore.setItem("search_results", JSON.stringify(results));
+ BrowserStore.setItem("search_results", results);
is_mention_search = is_mention_search ? true : false; // force to bool
- BrowserStore.setItem("is_mention_search", JSON.stringify(is_mention_search));
+ BrowserStore.setItem("is_mention_search", is_mention_search);
},
getSearchResults: function() {
- var results = null;
- try {
- results = JSON.parse(BrowserStore.getItem("search_results"));
- }
- catch (err) {
- }
-
- return results;
+ return BrowserStore.getItem("search_results");
},
getIsMentionSearch: function() {
- var result = false;
- try {
- result = JSON.parse(BrowserStore.getItem("is_mention_search"));
- }
- catch (err) {
- }
-
- return result;
+ return BrowserStore.getItem("is_mention_search");
},
storeSelectedPost: function(post_list) {
- BrowserStore.setItem("select_post", JSON.stringify(post_list));
+ BrowserStore.setItem("select_post", post_list);
},
getSelectedPost: function() {
- var post_list = null;
- try {
- post_list = JSON.parse(BrowserStore.getItem("select_post"));
- }
- catch (err) {
- }
-
- return post_list;
+ return BrowserStore.getItem("select_post");
},
storeSearchTerm: function(term) {
BrowserStore.setItem("search_term", term);
@@ -165,25 +137,24 @@ var PostStore = assign({}, EventEmitter.prototype, {
storeCurrentDraft: function(draft) {
var channel_id = ChannelStore.getCurrentId();
var user_id = UserStore.getCurrentId();
- BrowserStore.setItem("draft_" + channel_id + "_" + user_id, JSON.stringify(draft));
+ BrowserStore.setItem("draft_" + channel_id + "_" + user_id, draft);
},
getCurrentDraft: function() {
var channel_id = ChannelStore.getCurrentId();
var user_id = UserStore.getCurrentId();
- return JSON.parse(BrowserStore.getItem("draft_" + channel_id + "_" + user_id));
+ return BrowserStore.getItem("draft_" + channel_id + "_" + user_id);
},
storeDraft: function(channel_id, user_id, draft) {
- BrowserStore.setItem("draft_" + channel_id + "_" + user_id, JSON.stringify(draft));
+ BrowserStore.setItem("draft_" + channel_id + "_" + user_id, draft);
},
getDraft: function(channel_id, user_id) {
- return JSON.parse(BrowserStore.getItem("draft_" + channel_id + "_" + user_id));
+ return BrowserStore.getItem("draft_" + channel_id + "_" + user_id);
},
clearDraftUploads: function() {
BrowserStore.actionOnItemsWithPrefix("draft_", function (key, value) {
- var d = JSON.parse(value);
- if (d) {
- d['uploadsInProgress'] = 0;
- BrowserStore.setItem(key, JSON.stringify(d));
+ if (value) {
+ value.uploadsInProgress = 0;
+ BrowserStore.setItem(key, value);
}
});
}
diff --git a/web/react/stores/socket_store.jsx b/web/react/stores/socket_store.jsx
index 39800ead5..8ebb854c9 100644
--- a/web/react/stores/socket_store.jsx
+++ b/web/react/stores/socket_store.jsx
@@ -10,8 +10,6 @@ var client = require('../utils/client.jsx');
var Constants = require('../utils/constants.jsx');
var ActionTypes = Constants.ActionTypes;
-var BrowserStore = require('../stores/browser_store.jsx');
-
var CHANGE_EVENT = 'change';
var conn;
diff --git a/web/react/stores/team_store.jsx b/web/react/stores/team_store.jsx
index c494cb5b5..b7199a4a8 100644
--- a/web/react/stores/team_store.jsx
+++ b/web/react/stores/team_store.jsx
@@ -63,22 +63,10 @@ var TeamStore = assign({}, EventEmitter.prototype, {
this._storeTeams(teams);
},
_storeTeams: function(teams) {
- BrowserStore.setItem("user_teams", JSON.stringify(teams));
+ BrowserStore.setItem("user_teams", teams);
},
_getTeams: function() {
- var teams = {};
-
- try {
- teams = JSON.parse(BrowserStore.getItem("user_teams"));
- }
- catch (err) {
- }
-
- if (teams == null) {
- teams = {};
- }
-
- return teams;
+ return BrowserStore.getItem("user_teams", {});
}
});
diff --git a/web/react/stores/user_store.jsx b/web/react/stores/user_store.jsx
index e832b34c7..93ddfec70 100644
--- a/web/react/stores/user_store.jsx
+++ b/web/react/stores/user_store.jsx
@@ -8,7 +8,7 @@ var client = require('../utils/client.jsx');
var Constants = require('../utils/constants.jsx');
var ActionTypes = Constants.ActionTypes;
-var BrowserStore = require('../stores/browser_store.jsx');
+var BrowserStore = require('./browser_store.jsx');
var CHANGE_EVENT = 'change';
var CHANGE_EVENT_SESSIONS = 'change_sessions';
@@ -18,6 +18,8 @@ var CHANGE_EVENT_STATUSES = 'change_statuses';
var UserStore = assign({}, EventEmitter.prototype, {
+ _current_id: null,
+
emitChange: function(userId) {
this.emit(CHANGE_EVENT, userId);
},
@@ -64,13 +66,10 @@ var UserStore = assign({}, EventEmitter.prototype, {
this.removeListener(CHANGE_EVENT_STATUSES, callback);
},
setCurrentId: function(id) {
- if (id == null)
- BrowserStore.removeGlobalItem("current_user_id");
- else
- BrowserStore.setGlobalItem("current_user_id", id);
+ this._current_id = id;
},
getCurrentId: function(skipFetch) {
- var current_id = BrowserStore.getGlobalItem("current_user_id");
+ var current_id = this._current_id;
// this is a speical case to force fetch the
// current user if it's missing
@@ -97,21 +96,13 @@ var UserStore = assign({}, EventEmitter.prototype, {
this.setCurrentId(user.id);
},
getLastDomain: function() {
- var last_domain = BrowserStore.getItem("last_domain");
- if (last_domain == null) {
- last_domain = "";
- }
- return last_domain;
+ return BrowserStore.getItem("last_domain", '');
},
setLastDomain: function(domain) {
BrowserStore.setItem("last_domain", domain);
},
getLastEmail: function() {
- var last_email = BrowserStore.getItem("last_email");
- if (last_email == null) {
- last_email = "";
- }
- return last_email;
+ return BrowserStore.getItem("last_email", '');
},
setLastEmail: function(email) {
BrowserStore.setItem("last_email", email);
@@ -153,91 +144,36 @@ var UserStore = assign({}, EventEmitter.prototype, {
this._storeProfiles(ps);
},
_storeProfiles: function(profiles) {
- BrowserStore.setGlobalItem("profiles", JSON.stringify(profiles));
+ BrowserStore.setGlobalItem("profiles", profiles);
var profileUsernameMap = {};
for (var id in profiles) {
profileUsernameMap[profiles[id].username] = profiles[id];
}
- BrowserStore.setGlobalItem("profileUsernameMap", JSON.stringify(profileUsernameMap));
+ BrowserStore.setGlobalItem("profileUsernameMap", profileUsernameMap);
},
_getProfiles: function() {
- var profiles = {};
- try {
- profiles = JSON.parse(BrowserStore.getGlobalItem("profiles"));
- }
- catch (err) {
- }
-
- if (profiles == null) {
- profiles = {};
- }
-
- return profiles;
+ return BrowserStore.getGlobalItem("profiles", {});
},
_getProfilesUsernameMap: function() {
- var profileUsernameMap = {};
- try {
- profileUsernameMap = JSON.parse(BrowserStore.getGlobalItem("profileUsernameMap"));
- }
- catch (err) {
- }
-
- if (profileUsernameMap == null) {
- profileUsernameMap = {};
- }
-
- return profileUsernameMap;
+ return BrowserStore.getGlobalItem("profileUsernameMap", {});
},
setSessions: function(sessions) {
- BrowserStore.setItem("sessions", JSON.stringify(sessions));
+ BrowserStore.setItem("sessions", sessions);
},
getSessions: function() {
- var sessions = [];
- try {
- sessions = JSON.parse(BrowserStore.getItem("sessions"));
- }
- catch (err) {
- }
- if (sessions == null) {
- sessions = [];
- }
-
- return sessions;
+ return BrowserStore.getItem("sessions", []);
},
setAudits: function(audits) {
- BrowserStore.setItem("audits", JSON.stringify(audits));
+ BrowserStore.setItem("audits", audits);
},
getAudits: function() {
- var audits = [];
- try {
- audits = JSON.parse(BrowserStore.getItem("audits"));
- }
- catch (err) {
- }
-
- if (audits == null) {
- audits = [];
- }
-
- return audits;
+ return BrowserStore.getItem("audits", []);
},
setTeams: function(teams) {
- BrowserStore.setItem("teams", JSON.stringify(teams));
+ BrowserStore.setItem("teams", teams);
},
getTeams: function() {
- var teams = [];
- try {
- teams = JSON.parse(BrowserStore.getItem("teams"));
-
- }
- catch (err) {
- }
-
- if (teams == null) {
- teams = [];
- }
-
- return teams;
+ return BrowserStore.getItem("teams", []);
},
getCurrentMentionKeys: function() {
var user = this.getCurrentUser();
@@ -258,11 +194,7 @@ var UserStore = assign({}, EventEmitter.prototype, {
}
},
getLastVersion: function() {
- var last_version = BrowserStore.getItem("last_version");
- if (last_version == null) {
- last_version = "";
- }
- return last_version;
+ return BrowserStore.getItem("last_version", '');
},
setLastVersion: function(version) {
BrowserStore.setItem("last_version", version);
@@ -272,7 +204,7 @@ var UserStore = assign({}, EventEmitter.prototype, {
this.emitStatusesChange();
},
_setStatuses: function(statuses) {
- BrowserStore.setItem("statuses", JSON.stringify(statuses));
+ BrowserStore.setItem("statuses", statuses);
},
setStatus: function(user_id, status) {
var statuses = this.getStatuses();
@@ -281,18 +213,7 @@ var UserStore = assign({}, EventEmitter.prototype, {
this.emitStatusesChange();
},
getStatuses: function() {
- var statuses = {};
- try {
- statuses = JSON.parse(BrowserStore.getItem("statuses"));
- }
- catch (err) {
- }
-
- if (statuses == null) {
- statuses = {};
- }
-
- return statuses;
+ return BrowserStore.getItem("statuses", {});
},
getStatus: function(id) {
return this.getStatuses()[id];
@@ -341,4 +262,3 @@ UserStore.setMaxListeners(0);
global.window.UserStore = UserStore;
module.exports = UserStore;
-
diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx
index 5ded0e76f..19c074606 100644
--- a/web/react/utils/utils.jsx
+++ b/web/react/utils/utils.jsx
@@ -225,7 +225,7 @@ module.exports.extractLinks = function(text) {
}
return { "links": links, "text": text };
-}
+}
module.exports.escapeRegExp = function(string) {
return string.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
@@ -671,13 +671,13 @@ module.exports.isValidUsername = function (name) {
error = "First character must be a letter.";
}
- else
+ else
{
var lowerName = name.toLowerCase().trim();
- for (var i = 0; i < Constants.RESERVED_USERNAMES.length; i++)
+ for (var i = 0; i < Constants.RESERVED_USERNAMES.length; i++)
{
- if (lowerName === Constants.RESERVED_USERNAMES[i])
+ if (lowerName === Constants.RESERVED_USERNAMES[i])
{
error = "Cannot use a reserved word as a username.";
break;
@@ -782,3 +782,34 @@ module.exports.getHomeLink = function() {
parts[0] = "www";
return window.location.protocol + "//" + parts.join(".");
}
+
+
+module.exports.changeColor =function(col, amt) {
+
+ var usePound = false;
+
+ if (col[0] == "#") {
+ col = col.slice(1);
+ usePound = true;
+ }
+
+ var num = parseInt(col,16);
+
+ var r = (num >> 16) + amt;
+
+ if (r > 255) r = 255;
+ else if (r < 0) r = 0;
+
+ var b = ((num >> 8) & 0x00FF) + amt;
+
+ if (b > 255) b = 255;
+ else if (b < 0) b = 0;
+
+ var g = (num & 0x0000FF) + amt;
+
+ if (g > 255) g = 255;
+ else if (g < 0) g = 0;
+
+ return (usePound?"#":"") + String("000000" + (g | (b << 8) | (r << 16)).toString(16)).slice(-6);
+
+};
diff --git a/web/sass-files/sass/partials/_files.scss b/web/sass-files/sass/partials/_files.scss
index 79142176e..c584c240d 100644
--- a/web/sass-files/sass/partials/_files.scss
+++ b/web/sass-files/sass/partials/_files.scss
@@ -137,7 +137,7 @@
border: 1px solid #E2E2E2;
background-color: #FFF;
background-repeat: no-repeat;
- background-position: left center;
+ background-position: top left;
}
a {
text-decoration: none;
diff --git a/web/sass-files/sass/partials/_headers.scss b/web/sass-files/sass/partials/_headers.scss
index 1ec1109a5..338f5ceb4 100644
--- a/web/sass-files/sass/partials/_headers.scss
+++ b/web/sass-files/sass/partials/_headers.scss
@@ -75,14 +75,16 @@
// Team Header in Sidebar
.sidebar--left, .sidebar--menu {
.team__header {
- padding: 0 15px 0 15px;
+ padding: 10px;
@include legacy-pie-clearfix;
a {
color: #fff;
}
.navbar-right {
font-size: 0.85em;
- margin: 16px -5px 0;
+ position: absolute;
+ top: 20px;
+ right: 22px;
.dropdown-toggle {
padding: 0 10px;
}
@@ -100,17 +102,32 @@
display: inline-block;
}
}
- .team__name {
+ .user__picture {
+ width: 36px;
+ height: 36px;
float: left;
- line-height: 50px;
+ @include border-radius(36px);
+ }
+ .header__info {
+ padding-left: 42px;
+ color: #fff;
+ }
+ .team__name, .user__name {
+ display: block;
+ line-height: 18px;
font-weight: 600;
- font-size: 1.2em;
+ font-size: 16px;
max-width: 80%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
text-decoration: none;
}
+ .user__name {
+ font-size: 14px;
+ font-weight: 400;
+ color: #eee;
+ }
> .nav {
> li {
> a {
diff --git a/web/sass-files/sass/partials/_loading.scss b/web/sass-files/sass/partials/_loading.scss
index bc819e8f5..d71055722 100644
--- a/web/sass-files/sass/partials/_loading.scss
+++ b/web/sass-files/sass/partials/_loading.scss
@@ -2,13 +2,8 @@
display: table;
width: 100%;
height: 100%;
- position: absolute;
- @include box-sizing(border-box);
+ padding: 60px;
text-align: center;
- &.loading-screen--channel {
- position: relative;
- padding: 4em 0 3.5em;
- }
.loading__content {
display: table-cell;
vertical-align: middle;
@@ -19,11 +14,7 @@
margin: 0 0.2em 0;
display: inline-block;
}
- }
-}
-.loading-screen {
- .loading__content {
.round {
background-color: #444;
width: 4px;
@@ -32,43 +23,18 @@
margin: 0 2px;
opacity: 0.1;
@include border-radius(10px);
- -moz-animation: move 0.75s infinite linear;
- -webkit-animation: move 0.75s infinite linear;
- }
-
- #round_1 {
- -moz-animation-delay: .2s;
- -webkit-animation-delay: .2s;
+ @include animation(move 0.75s infinite linear);
}
- #round_2 {
- -moz-animation-delay: .4s;
- -webkit-animation-delay: .4s;
- }
-
- #round_3 {
- -moz-animation-delay: .6s;
- -webkit-animation-delay: .6s;
- }
-
- @-moz-keyframes move {
- 0% {
- opacity: 1;
+ @for $i from 1 through 3 {
+ .round-#{$i} {
+ @include animation-delay(.2s*$i);
}
-
- 100% {
- opacity: 0.1;
- };
}
- @-webkit-keyframes move {
- 0% {
- opacity: 1;
- }
-
- 100% {
- opacity: 0.1;
- };
+ @include keyframes(move) {
+ from { opacity: 1; }
+ to { opacity: 0.1; }
}
}
}
diff --git a/web/sass-files/sass/partials/_mentions.scss b/web/sass-files/sass/partials/_mentions.scss
index da46866c8..7e8c1869a 100644
--- a/web/sass-files/sass/partials/_mentions.scss
+++ b/web/sass-files/sass/partials/_mentions.scss
@@ -11,13 +11,14 @@
position: absolute;
z-index: 1060;
.mentions-box {
- max-height: 303px;
- position:absolute;
- background-color:#fff;
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ background-color: #fff;
border: $border-gray;
overflow-x: hidden;
overflow-y: scroll;
- bottom:0;
+ bottom: 0;
}
}
diff --git a/web/sass-files/sass/partials/_post.scss b/web/sass-files/sass/partials/_post.scss
index d0c536363..40ed40b49 100644
--- a/web/sass-files/sass/partials/_post.scss
+++ b/web/sass-files/sass/partials/_post.scss
@@ -119,6 +119,7 @@ body.ios {
table-layout: fixed;
width: 100%;
min-height: 100%;
+ height: 100%;
.post-list__content {
display: table-cell;
vertical-align: bottom;