fixing merge
Этот коммит содержится в:
@@ -13,9 +13,9 @@ import (
|
|||||||
"github.com/mattermost/platform/model"
|
"github.com/mattermost/platform/model"
|
||||||
"github.com/mattermost/platform/utils"
|
"github.com/mattermost/platform/utils"
|
||||||
"github.com/nfnt/resize"
|
"github.com/nfnt/resize"
|
||||||
|
_ "golang.org/x/image/bmp"
|
||||||
"image"
|
"image"
|
||||||
_ "image/gif"
|
_ "image/gif"
|
||||||
_ "golang.org/x/image/bmp"
|
|
||||||
"image/jpeg"
|
"image/jpeg"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -157,7 +157,7 @@ func fireAndForgetHandleImages(filenames []string, fileData [][]byte, teamId, ch
|
|||||||
go func() {
|
go func() {
|
||||||
var thumbnail image.Image
|
var thumbnail image.Image
|
||||||
if imgConfig.Width > int(utils.Cfg.ImageSettings.ThumbnailWidth) {
|
if imgConfig.Width > int(utils.Cfg.ImageSettings.ThumbnailWidth) {
|
||||||
thumbnail = resize.Resize(utils.Cfg.ImageSettings.ThumbnailWidth, utils.Cfg.ImageSettings.ThumbnailHeight, img, resize.NearestNeighbor)
|
thumbnail = resize.Resize(utils.Cfg.ImageSettings.ThumbnailWidth, utils.Cfg.ImageSettings.ThumbnailHeight, img, resize.Lanczos3)
|
||||||
} else {
|
} else {
|
||||||
thumbnail = img
|
thumbnail = img
|
||||||
}
|
}
|
||||||
@@ -182,7 +182,7 @@ func fireAndForgetHandleImages(filenames []string, fileData [][]byte, teamId, ch
|
|||||||
go func() {
|
go func() {
|
||||||
var preview image.Image
|
var preview image.Image
|
||||||
if imgConfig.Width > int(utils.Cfg.ImageSettings.PreviewWidth) {
|
if imgConfig.Width > int(utils.Cfg.ImageSettings.PreviewWidth) {
|
||||||
preview = resize.Resize(utils.Cfg.ImageSettings.PreviewWidth, utils.Cfg.ImageSettings.PreviewHeight, img, resize.NearestNeighbor)
|
preview = resize.Resize(utils.Cfg.ImageSettings.PreviewWidth, utils.Cfg.ImageSettings.PreviewHeight, img, resize.Lanczos3)
|
||||||
} else {
|
} else {
|
||||||
preview = img
|
preview = img
|
||||||
}
|
}
|
||||||
|
|||||||
14
api/post.go
14
api/post.go
@@ -14,6 +14,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
func InitPost(r *mux.Router) {
|
func InitPost(r *mux.Router) {
|
||||||
@@ -437,6 +438,19 @@ func fireAndForgetNotifications(post *model.Post, teamId, teamUrl string) {
|
|||||||
|
|
||||||
message := model.NewMessage(teamId, post.ChannelId, post.UserId, model.ACTION_POSTED)
|
message := model.NewMessage(teamId, post.ChannelId, post.UserId, model.ACTION_POSTED)
|
||||||
message.Add("post", post.ToJson())
|
message.Add("post", post.ToJson())
|
||||||
|
|
||||||
|
if len(post.Filenames) != 0 {
|
||||||
|
message.Add("otherFile", "true")
|
||||||
|
|
||||||
|
for _, filename := range post.Filenames {
|
||||||
|
ext := filepath.Ext(filename)
|
||||||
|
if model.IsFileExtImage(ext) {
|
||||||
|
message.Add("image", "true")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if len(mentionedUsers) != 0 {
|
if len(mentionedUsers) != 0 {
|
||||||
message.Add("mentions", model.ArrayToJson(mentionedUsers))
|
message.Add("mentions", model.ArrayToJson(mentionedUsers))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -729,6 +729,8 @@ func uploadProfileImage(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Srv.Store.User().UpdateUpdateAt(c.Session.UserId)
|
||||||
|
|
||||||
c.LogAudit("")
|
c.LogAudit("")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ DOCKER SETUP
|
|||||||
3. Add a line to your /etc/hosts that goes `<Docker IP> dockerhost`
|
3. Add a line to your /etc/hosts that goes `<Docker IP> dockerhost`
|
||||||
4. Run `boot2docker shellinit` and copy the export statements to your ~/.bash_profile
|
4. Run `boot2docker shellinit` and copy the export statements to your ~/.bash_profile
|
||||||
|
|
||||||
Any issues? Please let us know on our forums at: http://bit.ly/1MY1kul
|
Any issues? Please let us know on our forums at: http://forum.mattermost.org
|
||||||
|
|
||||||
GO SETUP
|
GO SETUP
|
||||||
|
|
||||||
@@ -39,4 +39,4 @@ MATTERMOST SETUP
|
|||||||
6. Then do `cd platform` and `make test`. Provided the test runs fine, you now have a complete build environment.
|
6. Then do `cd platform` and `make test`. Provided the test runs fine, you now have a complete build environment.
|
||||||
7. Use `make run` to run your code
|
7. Use `make run` to run your code
|
||||||
|
|
||||||
Any issues? Please let us know on our forums at: http://bit.ly/1MY1kul
|
Any issues? Please let us know on our forums at: http://forum.mattermost.org
|
||||||
|
|||||||
@@ -35,6 +35,11 @@ func NewSqlPostStore(sqlStore *SqlStore) PostStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s SqlPostStore) UpgradeSchemaIfNeeded() {
|
func (s SqlPostStore) UpgradeSchemaIfNeeded() {
|
||||||
|
|
||||||
|
// These execs are for upgrading currently created databases to full utf8mb4 compliance
|
||||||
|
// Will be removed as seen fit for upgrading
|
||||||
|
s.GetMaster().Exec("ALTER TABLE Posts charset=utf8mb4")
|
||||||
|
s.GetMaster().Exec("ALTER TABLE Posts MODIFY COLUMN Message varchar(4000) CHARACTER SET utf8mb4")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s SqlPostStore) CreateIndexesIfNotExists() {
|
func (s SqlPostStore) CreateIndexesIfNotExists() {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import (
|
|||||||
sqltrace "log"
|
sqltrace "log"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -81,7 +82,14 @@ func NewSqlStore() Store {
|
|||||||
|
|
||||||
func setupConnection(con_type string, driver string, dataSource string, maxIdle int, maxOpen int, trace bool) *gorp.DbMap {
|
func setupConnection(con_type string, driver string, dataSource string, maxIdle int, maxOpen int, trace bool) *gorp.DbMap {
|
||||||
|
|
||||||
db, err := dbsql.Open(driver, dataSource)
|
charset := ""
|
||||||
|
if strings.Index(dataSource, "?") > -1 {
|
||||||
|
charset = "&charset=utf8mb4,utf8"
|
||||||
|
} else {
|
||||||
|
charset = "?charset=utf8mb4,utf8"
|
||||||
|
}
|
||||||
|
|
||||||
|
db, err := dbsql.Open(driver, dataSource+charset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l4g.Critical("Failed to open sql connection to '%v' err:%v", dataSource, err)
|
l4g.Critical("Failed to open sql connection to '%v' err:%v", dataSource, err)
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
@@ -104,7 +112,7 @@ func setupConnection(con_type string, driver string, dataSource string, maxIdle
|
|||||||
if driver == "sqlite3" {
|
if driver == "sqlite3" {
|
||||||
dbmap = &gorp.DbMap{Db: db, TypeConverter: mattermConverter{}, Dialect: gorp.SqliteDialect{}}
|
dbmap = &gorp.DbMap{Db: db, TypeConverter: mattermConverter{}, Dialect: gorp.SqliteDialect{}}
|
||||||
} else if driver == "mysql" {
|
} else if driver == "mysql" {
|
||||||
dbmap = &gorp.DbMap{Db: db, TypeConverter: mattermConverter{}, Dialect: gorp.MySQLDialect{Engine: "InnoDB", Encoding: "UTF8"}}
|
dbmap = &gorp.DbMap{Db: db, TypeConverter: mattermConverter{}, Dialect: gorp.MySQLDialect{Engine: "InnoDB", Encoding: "UTF8MB4"}}
|
||||||
} else {
|
} else {
|
||||||
l4g.Critical("Failed to create dialect specific driver")
|
l4g.Critical("Failed to create dialect specific driver")
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
|
|||||||
@@ -150,6 +150,25 @@ func (us SqlUserStore) Update(user *model.User, allowActiveUpdate bool) StoreCha
|
|||||||
return storeChannel
|
return storeChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (us SqlUserStore) UpdateUpdateAt(userId string) StoreChannel {
|
||||||
|
storeChannel := make(StoreChannel)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
result := StoreResult{}
|
||||||
|
|
||||||
|
if _, err := us.GetMaster().Exec("UPDATE Users SET UpdateAt = ? WHERE Id = ?", model.GetMillis(), userId); err != nil {
|
||||||
|
result.Err = model.NewAppError("SqlUserStore.UpdateUpdateAt", "We couldn't update the update_at", "user_id="+userId)
|
||||||
|
} else {
|
||||||
|
result.Data = userId
|
||||||
|
}
|
||||||
|
|
||||||
|
storeChannel <- result
|
||||||
|
close(storeChannel)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return storeChannel
|
||||||
|
}
|
||||||
|
|
||||||
func (us SqlUserStore) UpdateLastPingAt(userId string, time int64) StoreChannel {
|
func (us SqlUserStore) UpdateLastPingAt(userId string, time int64) StoreChannel {
|
||||||
storeChannel := make(StoreChannel)
|
storeChannel := make(StoreChannel)
|
||||||
|
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ type PostStore interface {
|
|||||||
type UserStore interface {
|
type UserStore interface {
|
||||||
Save(user *model.User) StoreChannel
|
Save(user *model.User) StoreChannel
|
||||||
Update(user *model.User, allowRoleUpdate bool) StoreChannel
|
Update(user *model.User, allowRoleUpdate bool) StoreChannel
|
||||||
|
UpdateUpdateAt(userId string) StoreChannel
|
||||||
UpdateLastPingAt(userId string, time int64) StoreChannel
|
UpdateLastPingAt(userId string, time int64) StoreChannel
|
||||||
UpdateLastActivityAt(userId string, time int64) StoreChannel
|
UpdateLastActivityAt(userId string, time int64) StoreChannel
|
||||||
UpdateUserAndSessionActivity(userId string, sessionId string, time int64) StoreChannel
|
UpdateUserAndSessionActivity(userId string, sessionId string, time int64) StoreChannel
|
||||||
|
|||||||
@@ -56,13 +56,13 @@ module.exports = React.createClass({
|
|||||||
$(this.refs.modal.getDOMNode()).on('show.bs.modal', function(e) {
|
$(this.refs.modal.getDOMNode()).on('show.bs.modal', function(e) {
|
||||||
var newState = {};
|
var newState = {};
|
||||||
if(BrowserStore.getItem('edit_state_transfer')) {
|
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');
|
BrowserStore.removeItem('edit_state_transfer');
|
||||||
} else {
|
} else {
|
||||||
var button = e.relatedTarget;
|
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') };
|
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);
|
PostStore.addSelectedPostChangeListener(this._onChange);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
var Client = require('../utils/client.jsx');
|
var Client = require('../utils/client.jsx');
|
||||||
var AsyncClient = require('../utils/async_client.jsx');
|
var AsyncClient = require('../utils/async_client.jsx');
|
||||||
var Textbox = require('./textbox.jsx');
|
var Textbox = require('./textbox.jsx');
|
||||||
|
var BrowserStore = require('../stores/browser_store.jsx');
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
handleEdit: function(e) {
|
handleEdit: function(e) {
|
||||||
@@ -13,14 +14,14 @@ module.exports = React.createClass({
|
|||||||
if (updatedPost.message.length === 0) {
|
if (updatedPost.message.length === 0) {
|
||||||
var tempState = this.state;
|
var tempState = this.state;
|
||||||
delete tempState.editText;
|
delete tempState.editText;
|
||||||
BrowserStore.setItem('edit_state_transfer', JSON.stringify(tempState));
|
BrowserStore.setItem('edit_state_transfer', tempState);
|
||||||
$("#edit_post").modal('hide');
|
$("#edit_post").modal('hide');
|
||||||
$("#delete_post").modal('show');
|
$("#delete_post").modal('show');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
updatedPost.id = this.state.post_id
|
updatedPost.id = this.state.post_id;
|
||||||
updatedPost.channel_id = this.state.channel_id
|
updatedPost.channel_id = this.state.channel_id;
|
||||||
|
|
||||||
Client.updatePost(updatedPost,
|
Client.updatePost(updatedPost,
|
||||||
function(data) {
|
function(data) {
|
||||||
|
|||||||
24
web/react/components/loading_screen.jsx
Обычный файл
24
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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -23,6 +23,7 @@ module.exports = React.createClass({
|
|||||||
var member = this.props.member;
|
var member = this.props.member;
|
||||||
var isAdmin = this.props.isAdmin;
|
var isAdmin = this.props.isAdmin;
|
||||||
var isMemberAdmin = member.roles.indexOf("admin") > -1;
|
var isMemberAdmin = member.roles.indexOf("admin") > -1;
|
||||||
|
var timestamp = UserStore.getCurrentUser().update_at;
|
||||||
|
|
||||||
var invite;
|
var invite;
|
||||||
if (member.invited && this.props.handleInvite) {
|
if (member.invited && this.props.handleInvite) {
|
||||||
@@ -53,7 +54,7 @@ module.exports = React.createClass({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="row member-div">
|
<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-name">{member.username}</span>
|
||||||
<span className="member-email">{member.email}</span>
|
<span className="member-email">{member.email}</span>
|
||||||
{ invite }
|
{ invite }
|
||||||
|
|||||||
@@ -61,7 +61,8 @@ var MemberListTeamItem = React.createClass({
|
|||||||
render: function() {
|
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 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 user = this.props.user;
|
||||||
var currentRoles = "Member"
|
var currentRoles = "Member";
|
||||||
|
var timestamp = UserStore.getCurrentUser().update_at;
|
||||||
|
|
||||||
if (user.roles.length > 0) {
|
if (user.roles.length > 0) {
|
||||||
currentRoles = user.roles.charAt(0).toUpperCase() + user.roles.slice(1);
|
currentRoles = user.roles.charAt(0).toUpperCase() + user.roles.slice(1);
|
||||||
@@ -83,7 +84,7 @@ var MemberListTeamItem = React.createClass({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="row member-div">
|
<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-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-email">{user.full_name.trim() ? user.username : email}</span>
|
||||||
<div className="dropdown member-drop">
|
<div className="dropdown member-drop">
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
||||||
// See License.txt for license information.
|
// See License.txt for license information.
|
||||||
|
var UserStore = require("../stores/user_store.jsx");
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
handleClick: function() {
|
handleClick: function() {
|
||||||
@@ -7,8 +8,9 @@ module.exports = React.createClass({
|
|||||||
},
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
var icon;
|
var icon;
|
||||||
|
var timestamp = UserStore.getCurrentUser().update_at;
|
||||||
if (this.props.id != null) {
|
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 {
|
} else {
|
||||||
icon = <span><i className="mention-img fa fa-users fa-2x"></i></span>;
|
icon = <span><i className="mention-img fa fa-users fa-2x"></i></span>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,12 @@ var Mention = require('./mention.jsx');
|
|||||||
var Constants = require('../utils/constants.jsx');
|
var Constants = require('../utils/constants.jsx');
|
||||||
var ActionTypes = Constants.ActionTypes;
|
var ActionTypes = Constants.ActionTypes;
|
||||||
|
|
||||||
|
var MAX_HEIGHT_LIST = 292;
|
||||||
|
var MAX_ITEMS_IN_LIST = 25;
|
||||||
|
var ITEM_HEIGHT = 36;
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
|
displayName: "MentionList",
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
PostStore.addMentionDataChangeListener(this._onChange);
|
PostStore.addMentionDataChangeListener(this._onChange);
|
||||||
|
|
||||||
@@ -72,7 +77,7 @@ module.exports = React.createClass({
|
|||||||
},
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
var mentionText = this.state.mentionText;
|
var mentionText = this.state.mentionText;
|
||||||
if (mentionText === '-1') return (<div/>);
|
if (mentionText === '-1') return null;
|
||||||
|
|
||||||
var profiles = UserStore.getActiveOnlyProfiles();
|
var profiles = UserStore.getActiveOnlyProfiles();
|
||||||
var users = [];
|
var users = [];
|
||||||
@@ -100,8 +105,7 @@ module.exports = React.createClass({
|
|||||||
var mentions = {};
|
var mentions = {};
|
||||||
var index = 0;
|
var index = 0;
|
||||||
|
|
||||||
for (var i = 0; i < users.length; i++) {
|
for (var i = 0; i < users.length && index < MAX_ITEMS_IN_LIST; i++) {
|
||||||
if (Object.keys(mentions).length >= 25) break;
|
|
||||||
if (this.alreadyMentioned(users[i].username)) continue;
|
if (this.alreadyMentioned(users[i].username)) continue;
|
||||||
|
|
||||||
var firstName = "", lastName = "";
|
var firstName = "", lastName = "";
|
||||||
@@ -127,17 +131,20 @@ module.exports = React.createClass({
|
|||||||
}
|
}
|
||||||
var numMentions = Object.keys(mentions).length;
|
var numMentions = Object.keys(mentions).length;
|
||||||
|
|
||||||
if (numMentions < 1) return (<div/>);
|
if (numMentions < 1) return null;
|
||||||
|
|
||||||
var height = (numMentions*36) + 4;
|
var $mention_tab = $('#'+this.props.id);
|
||||||
var width = $('#'+this.props.id).parent().width();
|
var maxHeight = Math.min(MAX_HEIGHT_LIST, $mention_tab.offset().top - 10);
|
||||||
var bottom = $(window).height() - $('#'+this.props.id).offset().top;
|
var style = {
|
||||||
var left = $('#'+this.props.id).offset().left;
|
height: Math.min(maxHeight, (numMentions*ITEM_HEIGHT) + 4),
|
||||||
var max_height = $('#'+this.props.id).offset().top - 10;
|
width: $mention_tab.parent().width(),
|
||||||
|
bottom: $(window).height() - $mention_tab.offset().top,
|
||||||
|
left: $mention_tab.offset().left
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mentions--top" style={{height: height, width: width, bottom: bottom, left: left}}>
|
<div className="mentions--top" style={style}>
|
||||||
<div ref="mentionlist" className="mentions-box" style={{height: height, width: width}}>
|
<div ref="mentionlist" className="mentions-box">
|
||||||
{ mentions }
|
{ mentions }
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ var client = require('../utils/client.jsx');
|
|||||||
var asyncClient = require('../utils/async_client.jsx');
|
var asyncClient = require('../utils/async_client.jsx');
|
||||||
var UserStore = require('../stores/user_store.jsx');
|
var UserStore = require('../stores/user_store.jsx');
|
||||||
var ChannelStore = require('../stores/channel_store.jsx');
|
var ChannelStore = require('../stores/channel_store.jsx');
|
||||||
|
var LoadingScreen = require('./loading_screen.jsx');
|
||||||
|
|
||||||
function getStateFromStores() {
|
function getStateFromStores() {
|
||||||
return {
|
return {
|
||||||
@@ -16,6 +17,8 @@ function getStateFromStores() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
|
displayName: "MoreChannelsModal",
|
||||||
|
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
ChannelStore.addMoreChangeListener(this._onChange);
|
ChannelStore.addMoreChangeListener(this._onChange);
|
||||||
$(this.refs.modal.getDOMNode()).on('shown.bs.modal', function (e) {
|
$(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-name">{channel.display_name}</p>
|
||||||
<p className="more-channel-description">{channel.description}</p>
|
<p className="more-channel-description">{channel.description}</p>
|
||||||
</td>
|
</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>
|
</tr>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
@@ -100,15 +103,7 @@ module.exports = React.createClass({
|
|||||||
<p className="primary-message">No more channels to join</p>
|
<p className="primary-message">No more channels to join</p>
|
||||||
<p className="secondary-message">Click 'Create New Channel' to make a new one</p>
|
<p className="secondary-message">Click 'Create New Channel' to make a new one</p>
|
||||||
</div>)
|
</div>)
|
||||||
: <div ref="loadingscreen" className="loading-screen loading-screen--channel">
|
: <LoadingScreen /> }
|
||||||
<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>
|
|
||||||
}
|
|
||||||
{ server_error }
|
{ server_error }
|
||||||
</div>
|
</div>
|
||||||
<div className="modal-footer">
|
<div className="modal-footer">
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ var UserStore = require('../stores/user_store.jsx');
|
|||||||
var ActionTypes = Constants.ActionTypes;
|
var ActionTypes = Constants.ActionTypes;
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
|
displayName: "Post",
|
||||||
componentDidMount: function() {
|
componentDidMount: function() {
|
||||||
$('.modal').on('show.bs.modal', function () {
|
$('.modal').on('show.bs.modal', function () {
|
||||||
$('.modal-body').css('overflow-y', 'auto');
|
$('.modal-body').css('overflow-y', 'auto');
|
||||||
@@ -19,7 +20,7 @@ module.exports = React.createClass({
|
|||||||
handleCommentClick: function(e) {
|
handleCommentClick: function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
data = {};
|
var data = {};
|
||||||
data.order = [this.props.post.id];
|
data.order = [this.props.post.id];
|
||||||
data.posts = this.props.posts;
|
data.posts = this.props.posts;
|
||||||
|
|
||||||
@@ -48,7 +49,6 @@ module.exports = React.createClass({
|
|||||||
|
|
||||||
var commentCount = 0;
|
var commentCount = 0;
|
||||||
var commentRootId = parentPost ? post.root_id : post.id;
|
var commentRootId = parentPost ? post.root_id : post.id;
|
||||||
var rootUser = "";
|
|
||||||
for (var postId in posts) {
|
for (var postId in posts) {
|
||||||
if (posts[postId].root_id == commentRootId) {
|
if (posts[postId].root_id == commentRootId) {
|
||||||
commentCount += 1;
|
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;
|
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){
|
var rootUser = this.props.sameRoot ? "same--root" : "other--root";
|
||||||
rootUser = "same--root";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
rootUser = "other--root";
|
|
||||||
}
|
|
||||||
|
|
||||||
var postType = "";
|
var postType = "";
|
||||||
if (type != "Post"){
|
if (type != "Post"){
|
||||||
@@ -74,14 +69,16 @@ module.exports = React.createClass({
|
|||||||
currentUserCss = "current--user";
|
currentUserCss = "current--user";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var timestamp = UserStore.getCurrentUser().update_at;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div id={post.id} className={"post " + this.props.sameUser + " " + rootUser + " " + postType + " " + currentUserCss}>
|
<div id={post.id} className={"post " + this.props.sameUser + " " + rootUser + " " + postType + " " + currentUserCss}>
|
||||||
{ !this.props.hideProfilePic ?
|
{ !this.props.hideProfilePic ?
|
||||||
<div className="post-profile-img__container">
|
<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>
|
</div>
|
||||||
: "" }
|
: null }
|
||||||
<div className="post__content">
|
<div className="post__content">
|
||||||
<PostHeader post={post} sameRoot={this.props.sameRoot} commentCount={commentCount} handleCommentClick={this.handleCommentClick} isLastComment={this.props.isLastComment} />
|
<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} />
|
<PostBody post={post} sameRoot={this.props.sameRoot} parentPost={parentPost} posts={posts} handleCommentClick={this.handleCommentClick} />
|
||||||
|
|||||||
@@ -71,11 +71,22 @@ module.exports = React.createClass({
|
|||||||
name = <a className="theme" onClick={function(){ utils.searchForTerm(profile.username); }}>{profile.username}</a>;
|
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 = (
|
comment = (
|
||||||
<p className="post-link">
|
<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>
|
</p>
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -120,7 +131,7 @@ module.exports = React.createClass({
|
|||||||
return (
|
return (
|
||||||
<div className="post-body">
|
<div className="post-body">
|
||||||
{ comment }
|
{ 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 ?
|
{ filenames && filenames.length > 0 ?
|
||||||
<div className="post-image__columns">
|
<div className="post-image__columns">
|
||||||
{ postFiles }
|
{ postFiles }
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ var UserProfile = require( './user_profile.jsx' );
|
|||||||
var AsyncClient = require('../utils/async_client.jsx');
|
var AsyncClient = require('../utils/async_client.jsx');
|
||||||
var CreatePost = require('./create_post.jsx');
|
var CreatePost = require('./create_post.jsx');
|
||||||
var Post = require('./post.jsx');
|
var Post = require('./post.jsx');
|
||||||
|
var LoadingScreen = require('./loading_screen.jsx');
|
||||||
var SocketStore = require('../stores/socket_store.jsx');
|
var SocketStore = require('../stores/socket_store.jsx');
|
||||||
var utils = require('../utils/utils.jsx');
|
var utils = require('../utils/utils.jsx');
|
||||||
var Client = require('../utils/client.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({
|
module.exports = React.createClass({
|
||||||
|
displayName: "PostList",
|
||||||
scrollPosition: 0,
|
scrollPosition: 0,
|
||||||
preventScrollTrigger: false,
|
preventScrollTrigger: false,
|
||||||
gotMorePosts: 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('a.theme', 'color:'+user.props.theme+'; fill:'+user.props.theme+'!important;');
|
||||||
utils.changeCss('div.theme', 'background-color:'+user.props.theme+';');
|
utils.changeCss('div.theme', 'background-color:'+user.props.theme+';');
|
||||||
utils.changeCss('.btn.btn-primary', 'background: ' + 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('.modal .modal-header', 'background: ' + user.props.theme+';');
|
||||||
utils.changeCss('.mention', 'background: ' + user.props.theme+';');
|
utils.changeCss('.mention', 'background: ' + user.props.theme+';');
|
||||||
utils.changeCss('.mention-link', 'color: ' + user.props.theme+';');
|
utils.changeCss('.mention-link', 'color: ' + user.props.theme+';');
|
||||||
@@ -161,24 +133,20 @@ module.exports = React.createClass({
|
|||||||
$('body').off('click.userpopover');
|
$('body').off('click.userpopover');
|
||||||
},
|
},
|
||||||
resize: function() {
|
resize: function() {
|
||||||
|
var post_holder = $(".post-list-holder-by-time")[0];
|
||||||
|
this.preventScrollTrigger = true;
|
||||||
if (this.gotMorePosts) {
|
if (this.gotMorePosts) {
|
||||||
this.gotMorePosts = false;
|
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).scrollTop($(post_holder).scrollTop() + (post_holder.scrollHeight-this.oldScrollHeight) );
|
||||||
$(post_holder).perfectScrollbar('update');
|
|
||||||
} else {
|
} else {
|
||||||
var post_holder = $(".post-list-holder-by-time")[0];
|
|
||||||
this.preventScrollTrigger = true;
|
|
||||||
if ($("#new_message")[0] && !this.scrolledToNew) {
|
if ($("#new_message")[0] && !this.scrolledToNew) {
|
||||||
$(post_holder).scrollTop($(post_holder).scrollTop() + $("#new_message").offset().top - 63);
|
$(post_holder).scrollTop($(post_holder).scrollTop() + $("#new_message").offset().top - 63);
|
||||||
$(post_holder).perfectScrollbar('update');
|
|
||||||
this.scrolledToNew = true;
|
this.scrolledToNew = true;
|
||||||
} else {
|
} else {
|
||||||
$(post_holder).scrollTop(post_holder.scrollHeight);
|
$(post_holder).scrollTop(post_holder.scrollHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
$(post_holder).perfectScrollbar('update');
|
$(post_holder).perfectScrollbar('update');
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
_onChange: function() {
|
_onChange: function() {
|
||||||
var newState = getStateFromStores();
|
var newState = getStateFromStores();
|
||||||
@@ -342,12 +310,15 @@ module.exports = React.createClass({
|
|||||||
more_messages = (
|
more_messages = (
|
||||||
<div className="channel-intro">
|
<div className="channel-intro">
|
||||||
<div className="post-profile-img__container channel-intro-img">
|
<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>
|
||||||
<div className="channel-intro-profile">
|
<div className="channel-intro-profile">
|
||||||
<strong><UserProfile userId={teammate.id} /></strong>
|
<strong><UserProfile userId={teammate.id} /></strong>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
);
|
);
|
||||||
} else {
|
} 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." }
|
{ channel.type === 'P' ? " Only invited members can see this private group." : " Any member can join and read this channel." }
|
||||||
<br/>
|
<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" 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>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -420,37 +391,35 @@ module.exports = React.createClass({
|
|||||||
|
|
||||||
var postCtls = [];
|
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 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--) {
|
for (var i = order.length-1; i >= 0; i--) {
|
||||||
var post = posts[order[i]];
|
var post = posts[order[i]];
|
||||||
var parentPost;
|
var parentPost = post.parent_id ? posts[post.parent_id] : null;
|
||||||
|
|
||||||
if (post.parent_id) {
|
var sameUser = '';
|
||||||
parentPost = posts[post.parent_id];
|
var sameRoot = false;
|
||||||
} else {
|
var hideProfilePic = false;
|
||||||
parentPost = null;
|
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" : "";
|
if (prevPost) {
|
||||||
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;
|
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
|
// 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 === '';
|
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
|
// 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
|
// 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);
|
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} />;
|
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);
|
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(
|
postCtls.push(
|
||||||
<div className="date-separator">
|
<div className="date-separator">
|
||||||
<hr className="separator__hr" />
|
<hr className="separator__hr" />
|
||||||
@@ -469,20 +438,10 @@ module.exports = React.createClass({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
postCtls.push(postCtl);
|
postCtls.push(postCtl);
|
||||||
previousPostDay = utils.getDateForUnixTicks(post.create_at);
|
previousPostDay = currentPostDay;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
postCtls.push(<LoadingScreen position="absolute" />);
|
||||||
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>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -497,5 +456,3 @@ module.exports = React.createClass({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ RootPost = React.createClass({
|
|||||||
var message = utils.textToJsx(this.props.post.message);
|
var message = utils.textToJsx(this.props.post.message);
|
||||||
var filenames = this.props.post.filenames;
|
var filenames = this.props.post.filenames;
|
||||||
var isOwner = UserStore.getCurrentId() == this.props.post.user_id;
|
var isOwner = UserStore.getCurrentId() == this.props.post.user_id;
|
||||||
|
var timestamp = UserStore.getProfile(this.props.post.user_id).update_at;
|
||||||
|
|
||||||
var type = "Post";
|
var type = "Post";
|
||||||
if (this.props.post.root_id.length > 0) {
|
if (this.props.post.root_id.length > 0) {
|
||||||
@@ -118,7 +119,7 @@ RootPost = React.createClass({
|
|||||||
return (
|
return (
|
||||||
<div className={"post post--root " + currentUserCss}>
|
<div className={"post post--root " + currentUserCss}>
|
||||||
<div className="post-profile-img__container">
|
<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>
|
||||||
<div className="post__content">
|
<div className="post__content">
|
||||||
<ul className="post-header">
|
<ul className="post-header">
|
||||||
@@ -227,11 +228,12 @@ CommentPost = React.createClass({
|
|||||||
}
|
}
|
||||||
|
|
||||||
var message = utils.textToJsx(this.props.post.message);
|
var message = utils.textToJsx(this.props.post.message);
|
||||||
|
var timestamp = UserStore.getCurrentUser().update_at;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={commentClass + " " + currentUserCss}>
|
<div className={commentClass + " " + currentUserCss}>
|
||||||
<div className="post-profile-img__container">
|
<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>
|
||||||
<div className="post__content">
|
<div className="post__content">
|
||||||
<ul className="post-header">
|
<ul className="post-header">
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ SearchItem = React.createClass({
|
|||||||
var message = utils.textToJsx(this.props.post.message, {searchTerm: this.props.term, noMentionHighlight: !this.props.isMentionSearch});
|
var message = utils.textToJsx(this.props.post.message, {searchTerm: this.props.term, noMentionHighlight: !this.props.isMentionSearch});
|
||||||
var channelName = "";
|
var channelName = "";
|
||||||
var channel = ChannelStore.get(this.props.post.channel_id)
|
var channel = ChannelStore.get(this.props.post.channel_id)
|
||||||
|
var timestamp = UserStore.getCurrentUser().update_at;
|
||||||
|
|
||||||
if (channel) {
|
if (channel) {
|
||||||
if (channel.type === 'D') {
|
if (channel.type === 'D') {
|
||||||
@@ -89,7 +90,7 @@ SearchItem = React.createClass({
|
|||||||
<div className="search-item-container post" onClick={this.handleClick}>
|
<div className="search-item-container post" onClick={this.handleClick}>
|
||||||
<div className="search-channel__name">{ channelName }</div>
|
<div className="search-channel__name">{ channelName }</div>
|
||||||
<div className="post-profile-img__container">
|
<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>
|
||||||
<div className="post__content">
|
<div className="post__content">
|
||||||
<ul className="post-header">
|
<ul className="post-header">
|
||||||
|
|||||||
@@ -249,11 +249,27 @@ var SidebarLoggedIn = React.createClass({
|
|||||||
|
|
||||||
var repRegex = new RegExp("<br>", "g");
|
var repRegex = new RegExp("<br>", "g");
|
||||||
var post = JSON.parse(msg.props.post);
|
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) {
|
if (msg.length > 50) {
|
||||||
msg = msg.substring(0,49) + "...";
|
msg = msg.substring(0,49) + "...";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
utils.notifyMe(title, username + " wrote: " + msg, channel);
|
||||||
|
}
|
||||||
if (!user.notify_props || user.notify_props.desktop_sound === "true") {
|
if (!user.notify_props || user.notify_props.desktop_sound === "true") {
|
||||||
utils.ding();
|
utils.ding();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,10 +121,15 @@ module.exports = React.createClass({
|
|||||||
},
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
var teamName = this.props.teamName ? this.props.teamName : config.SiteName;
|
var teamName = this.props.teamName ? this.props.teamName : config.SiteName;
|
||||||
|
var me = UserStore.getCurrentUser()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="team__header theme">
|
<div className="team__header theme">
|
||||||
|
<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>
|
<a className="team__name" href="/channels/town-square">{ teamName }</a>
|
||||||
|
</div>
|
||||||
<NavbarDropdown teamType={this.props.teamType} />
|
<NavbarDropdown teamType={this.props.teamType} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -596,19 +596,14 @@ PasswordPage = React.createClass({
|
|||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
updateParent: function(state, skipSet) {
|
updateParent: function(state, skipSet) {
|
||||||
BrowserStore.setGlobalItem(this.props.hash, JSON.stringify(state));
|
BrowserStore.setGlobalItem(this.props.hash, state);
|
||||||
|
|
||||||
if (!skipSet) {
|
if (!skipSet) {
|
||||||
this.setState(state);
|
this.setState(state);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
var props = null;
|
var props = BrowserStore.getGlobalItem(this.props.hash);
|
||||||
try {
|
|
||||||
props = JSON.parse(BrowserStore.getGlobalItem(this.props.hash));
|
|
||||||
}
|
|
||||||
catch(parse_error) {
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!props) {
|
if (!props) {
|
||||||
props = {};
|
props = {};
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ module.exports = React.createClass({
|
|||||||
return;
|
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.") {
|
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: ""});
|
this.setState({name_error: "This username is reserved, please choose a new one.", email_error: "", password_error: "", server_error: ""});
|
||||||
return;
|
return;
|
||||||
@@ -72,12 +72,7 @@ module.exports = React.createClass({
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
var props = null;
|
var props = BrowserStore.getGlobalItem(this.props.hash);
|
||||||
try {
|
|
||||||
props = JSON.parse(BrowserStore.getGlobalItem(this.props.hash));
|
|
||||||
}
|
|
||||||
catch(parse_error) {
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!props) {
|
if (!props) {
|
||||||
props = {};
|
props = {};
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ module.exports = React.createClass({
|
|||||||
var name = this.props.overwriteName ? this.props.overwriteName : this.state.profile.username;
|
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) {
|
if (!config.ShowEmail) {
|
||||||
data_content += "<div class='text-nowrap'>Email not shared</div>";
|
data_content += "<div class='text-nowrap'>Email not shared</div>";
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -626,7 +626,7 @@ var SecurityTab = React.createClass({
|
|||||||
|
|
||||||
client.updatePassword(data,
|
client.updatePassword(data,
|
||||||
function(data) {
|
function(data) {
|
||||||
this.updateSection("");
|
this.props.updateSection("");
|
||||||
AsyncClient.getMe();
|
AsyncClient.getMe();
|
||||||
this.setState({ current_password: '', new_password: '', confirm_password: '' });
|
this.setState({ current_password: '', new_password: '', confirm_password: '' });
|
||||||
}.bind(this),
|
}.bind(this),
|
||||||
|
|||||||
@@ -1,85 +1,104 @@
|
|||||||
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
|
||||||
// See License.txt for license information.
|
// See License.txt for license information.
|
||||||
var UserStore = require('../stores/user_store.jsx');
|
|
||||||
|
var UserStore;
|
||||||
|
function getPrefix() {
|
||||||
|
if (!UserStore) UserStore = require('./user_store.jsx');
|
||||||
|
return UserStore.getCurrentId() + '_';
|
||||||
|
}
|
||||||
|
|
||||||
// Also change model/utils.go ETAG_ROOT_VERSION
|
// Also change model/utils.go ETAG_ROOT_VERSION
|
||||||
var BROWSER_STORE_VERSION = '.1';
|
var BROWSER_STORE_VERSION = '.3';
|
||||||
|
|
||||||
var _initialized = false;
|
module.exports = {
|
||||||
|
_initialized: false,
|
||||||
|
|
||||||
function _initialize() {
|
_initialize: function() {
|
||||||
var currentVersion = localStorage.getItem("local_storage_version");
|
var currentVersion = localStorage.getItem("local_storage_version");
|
||||||
if (currentVersion !== BROWSER_STORE_VERSION) {
|
if (currentVersion !== BROWSER_STORE_VERSION) {
|
||||||
localStorage.clear();
|
this.clear();
|
||||||
sessionStorage.clear();
|
|
||||||
localStorage.setItem("local_storage_version", BROWSER_STORE_VERSION);
|
localStorage.setItem("local_storage_version", BROWSER_STORE_VERSION);
|
||||||
}
|
}
|
||||||
_initialized = true;
|
this._initialized = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
getItem: function(name, defaultValue) {
|
||||||
|
return this.getGlobalItem(getPrefix() + name, defaultValue);
|
||||||
|
},
|
||||||
|
|
||||||
|
setItem: function(name, value) {
|
||||||
|
this.setGlobalItem(getPrefix() + name, value);
|
||||||
|
},
|
||||||
|
|
||||||
|
removeItem: function(name) {
|
||||||
|
if (!this._initialized) this._initialize();
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
var result = null;
|
||||||
|
try {
|
||||||
|
result = JSON.parse(localStorage.getItem(name));
|
||||||
|
} catch (err) {}
|
||||||
|
|
||||||
|
if (result === null && typeof defaultValue !== 'undefined') {
|
||||||
|
result = defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.setItem = function(name, value) {
|
return result;
|
||||||
if (!_initialized) _initialize();
|
},
|
||||||
var user_id = UserStore.getCurrentId();
|
|
||||||
localStorage.setItem(user_id + "_" + name, value);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.getItem = function(name) {
|
removeGlobalItem: function(name) {
|
||||||
if (!_initialized) _initialize();
|
if (!this._initialized) this._initialize();
|
||||||
var user_id = UserStore.getCurrentId();
|
|
||||||
return localStorage.getItem(user_id + "_" + name);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.removeItem = function(name) {
|
|
||||||
if (!_initialized) _initialize();
|
|
||||||
var user_id = UserStore.getCurrentId();
|
|
||||||
localStorage.removeItem(user_id + "_" + name);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.setGlobalItem = function(name, value) {
|
|
||||||
if (!_initialized) _initialize();
|
|
||||||
localStorage.setItem(name, value);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.getGlobalItem = function(name) {
|
|
||||||
if (!_initialized) _initialize();
|
|
||||||
return localStorage.getItem(name);
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports.removeGlobalItem = function(name) {
|
|
||||||
if (!_initialized) _initialize();
|
|
||||||
localStorage.removeItem(name);
|
localStorage.removeItem(name);
|
||||||
};
|
},
|
||||||
|
|
||||||
module.exports.clear = function() {
|
clear: function() {
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
sessionStorage.clear();
|
sessionStorage.clear();
|
||||||
};
|
},
|
||||||
|
|
||||||
// Preforms the given action on each item that has the given prefix
|
/**
|
||||||
// Signiture for action is action(key, value)
|
* Preforms the given action on each item that has the given prefix
|
||||||
module.exports.actionOnItemsWithPrefix = function (prefix, action) {
|
* Signiture for action is action(key, value)
|
||||||
var user_id = UserStore.getCurrentId();
|
*/
|
||||||
var id_len = user_id.length;
|
actionOnItemsWithPrefix: function (prefix, action) {
|
||||||
var prefix_len = prefix.length;
|
if (!this._initialized) this._initialize();
|
||||||
|
|
||||||
|
var globalPrefix = getPrefix();
|
||||||
|
var globalPrefixiLen = globalPrefix.length;
|
||||||
for (var key in localStorage) {
|
for (var key in localStorage) {
|
||||||
if (key.substring(id_len, id_len + prefix_len) === prefix) {
|
if (key.lastIndexOf(globalPrefix + prefix, 0) === 0) {
|
||||||
var userkey = key.substring(id_len);
|
var userkey = key.substring(globalPrefixiLen);
|
||||||
action(userkey, BrowserStore.getItem(key));
|
action(userkey, this.getGlobalItem(key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
},
|
||||||
|
|
||||||
module.exports.isLocalStorageSupported = function() {
|
isLocalStorageSupported: function() {
|
||||||
try {
|
try {
|
||||||
sessionStorage.setItem("testSession", '1');
|
sessionStorage.setItem("testSession", '1');
|
||||||
sessionStorage.removeItem("testSession");
|
sessionStorage.removeItem("testSession");
|
||||||
|
|
||||||
localStorage.setItem("testLocal", '1');
|
localStorage.setItem("testLocal", '1');
|
||||||
|
if (localStorage.getItem("testLocal") != '1') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
localStorage.removeItem("testLocal", '1');
|
localStorage.removeItem("testLocal", '1');
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
} catch (e) {
|
||||||
catch (e) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ var MORE_CHANGE_EVENT = 'change';
|
|||||||
var EXTRA_INFO_EVENT = 'extra_info';
|
var EXTRA_INFO_EVENT = 'extra_info';
|
||||||
|
|
||||||
var ChannelStore = assign({}, EventEmitter.prototype, {
|
var ChannelStore = assign({}, EventEmitter.prototype, {
|
||||||
|
_current_id: null,
|
||||||
emitChange: function() {
|
emitChange: function() {
|
||||||
this.emit(CHANGE_EVENT);
|
this.emit(CHANGE_EVENT);
|
||||||
},
|
},
|
||||||
@@ -88,10 +89,7 @@ var ChannelStore = assign({}, EventEmitter.prototype, {
|
|||||||
return this._getMoreChannels();
|
return this._getMoreChannels();
|
||||||
},
|
},
|
||||||
setCurrentId: function(id) {
|
setCurrentId: function(id) {
|
||||||
if (id == null)
|
this._current_id = id;
|
||||||
BrowserStore.removeItem("current_channel_id");
|
|
||||||
else
|
|
||||||
BrowserStore.setItem("current_channel_id", id);
|
|
||||||
},
|
},
|
||||||
setLastVisitedName: function(name) {
|
setLastVisitedName: function(name) {
|
||||||
if (name == null)
|
if (name == null)
|
||||||
@@ -117,10 +115,10 @@ var ChannelStore = assign({}, EventEmitter.prototype, {
|
|||||||
this._storeChannelMembers(cm);
|
this._storeChannelMembers(cm);
|
||||||
},
|
},
|
||||||
getCurrentId: function() {
|
getCurrentId: function() {
|
||||||
return BrowserStore.getItem("current_channel_id");
|
return this._current_id;
|
||||||
},
|
},
|
||||||
getCurrent: function() {
|
getCurrent: function() {
|
||||||
var currentId = ChannelStore.getCurrentId();
|
var currentId = this.getCurrentId();
|
||||||
|
|
||||||
if (currentId != null)
|
if (currentId != null)
|
||||||
return this.get(currentId);
|
return this.get(currentId);
|
||||||
@@ -165,49 +163,22 @@ var ChannelStore = assign({}, EventEmitter.prototype, {
|
|||||||
return extra;
|
return extra;
|
||||||
},
|
},
|
||||||
_storeChannels: function(channels) {
|
_storeChannels: function(channels) {
|
||||||
BrowserStore.setItem("channels", JSON.stringify(channels));
|
BrowserStore.setItem("channels", channels);
|
||||||
},
|
},
|
||||||
_getChannels: function() {
|
_getChannels: function() {
|
||||||
var channels = [];
|
return BrowserStore.getItem("channels", []);
|
||||||
try {
|
|
||||||
channels = JSON.parse(BrowserStore.getItem("channels"));
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
}
|
|
||||||
|
|
||||||
if (channels == null) {
|
|
||||||
channels = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
return channels;
|
|
||||||
},
|
},
|
||||||
_storeChannelMembers: function(channelMembers) {
|
_storeChannelMembers: function(channelMembers) {
|
||||||
BrowserStore.setItem("channel_members", JSON.stringify(channelMembers));
|
BrowserStore.setItem("channel_members", channelMembers);
|
||||||
},
|
},
|
||||||
_getChannelMembers: function() {
|
_getChannelMembers: function() {
|
||||||
var members = {};
|
return BrowserStore.getItem("channel_members", {});
|
||||||
try {
|
|
||||||
members = JSON.parse(BrowserStore.getItem("channel_members"));
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
}
|
|
||||||
|
|
||||||
if (members == null) {
|
|
||||||
members = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return members;
|
|
||||||
},
|
},
|
||||||
_storeMoreChannels: function(channels) {
|
_storeMoreChannels: function(channels) {
|
||||||
BrowserStore.setItem("more_channels", JSON.stringify(channels));
|
BrowserStore.setItem("more_channels", channels);
|
||||||
},
|
},
|
||||||
_getMoreChannels: function() {
|
_getMoreChannels: function() {
|
||||||
var channels = null;
|
var channels = BrowserStore.getItem("more_channels");
|
||||||
try {
|
|
||||||
channels = JSON.parse(BrowserStore.getItem("more_channels"));
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
}
|
|
||||||
|
|
||||||
if (channels == null) {
|
if (channels == null) {
|
||||||
channels = {};
|
channels = {};
|
||||||
@@ -217,21 +188,10 @@ var ChannelStore = assign({}, EventEmitter.prototype, {
|
|||||||
return channels;
|
return channels;
|
||||||
},
|
},
|
||||||
_storeExtraInfos: function(extraInfos) {
|
_storeExtraInfos: function(extraInfos) {
|
||||||
BrowserStore.setItem("extra_infos", JSON.stringify(extraInfos));
|
BrowserStore.setItem("extra_infos", extraInfos);
|
||||||
},
|
},
|
||||||
_getExtraInfos: function() {
|
_getExtraInfos: function() {
|
||||||
var members = {};
|
return BrowserStore.getItem("extra_infos", {});
|
||||||
try {
|
|
||||||
members = JSON.parse(BrowserStore.getItem("extra_infos"));
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
}
|
|
||||||
|
|
||||||
if (members == null) {
|
|
||||||
members = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return members;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -29,18 +29,11 @@ var ErrorStore = assign({}, EventEmitter.prototype, {
|
|||||||
BrowserStore.removeItem("last_error");
|
BrowserStore.removeItem("last_error");
|
||||||
},
|
},
|
||||||
getLastError: function() {
|
getLastError: function() {
|
||||||
var error = null;
|
return BrowserStore.getItem('last_error');
|
||||||
try {
|
|
||||||
error = JSON.parse(BrowserStore.getItem("last_error"));
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
}
|
|
||||||
|
|
||||||
return error;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_storeLastError: function(error) {
|
_storeLastError: function(error) {
|
||||||
BrowserStore.setItem("last_error", JSON.stringify(error));
|
BrowserStore.setItem("last_error", error);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -106,55 +106,27 @@ var PostStore = assign({}, EventEmitter.prototype, {
|
|||||||
this.emitChange();
|
this.emitChange();
|
||||||
},
|
},
|
||||||
_storePosts: function(channelId, posts) {
|
_storePosts: function(channelId, posts) {
|
||||||
BrowserStore.setItem("posts_" + channelId, JSON.stringify(posts));
|
BrowserStore.setItem("posts_" + channelId, posts);
|
||||||
},
|
},
|
||||||
getPosts: function(channelId) {
|
getPosts: function(channelId) {
|
||||||
var posts = null;
|
return BrowserStore.getItem("posts_" + channelId);
|
||||||
try {
|
|
||||||
posts = JSON.parse(BrowserStore.getItem("posts_" + channelId));
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
}
|
|
||||||
|
|
||||||
return posts;
|
|
||||||
},
|
},
|
||||||
storeSearchResults: function(results, is_mention_search) {
|
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
|
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() {
|
getSearchResults: function() {
|
||||||
var results = null;
|
return BrowserStore.getItem("search_results");
|
||||||
try {
|
|
||||||
results = JSON.parse(BrowserStore.getItem("search_results"));
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
}
|
|
||||||
|
|
||||||
return results;
|
|
||||||
},
|
},
|
||||||
getIsMentionSearch: function() {
|
getIsMentionSearch: function() {
|
||||||
var result = false;
|
return BrowserStore.getItem("is_mention_search");
|
||||||
try {
|
|
||||||
result = JSON.parse(BrowserStore.getItem("is_mention_search"));
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
},
|
},
|
||||||
storeSelectedPost: function(post_list) {
|
storeSelectedPost: function(post_list) {
|
||||||
BrowserStore.setItem("select_post", JSON.stringify(post_list));
|
BrowserStore.setItem("select_post", post_list);
|
||||||
},
|
},
|
||||||
getSelectedPost: function() {
|
getSelectedPost: function() {
|
||||||
var post_list = null;
|
return BrowserStore.getItem("select_post");
|
||||||
try {
|
|
||||||
post_list = JSON.parse(BrowserStore.getItem("select_post"));
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
}
|
|
||||||
|
|
||||||
return post_list;
|
|
||||||
},
|
},
|
||||||
storeSearchTerm: function(term) {
|
storeSearchTerm: function(term) {
|
||||||
BrowserStore.setItem("search_term", term);
|
BrowserStore.setItem("search_term", term);
|
||||||
@@ -165,25 +137,24 @@ var PostStore = assign({}, EventEmitter.prototype, {
|
|||||||
storeCurrentDraft: function(draft) {
|
storeCurrentDraft: function(draft) {
|
||||||
var channel_id = ChannelStore.getCurrentId();
|
var channel_id = ChannelStore.getCurrentId();
|
||||||
var user_id = UserStore.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() {
|
getCurrentDraft: function() {
|
||||||
var channel_id = ChannelStore.getCurrentId();
|
var channel_id = ChannelStore.getCurrentId();
|
||||||
var user_id = UserStore.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) {
|
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) {
|
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() {
|
clearDraftUploads: function() {
|
||||||
BrowserStore.actionOnItemsWithPrefix("draft_", function (key, value) {
|
BrowserStore.actionOnItemsWithPrefix("draft_", function (key, value) {
|
||||||
var d = JSON.parse(value);
|
if (value) {
|
||||||
if (d) {
|
value.uploadsInProgress = 0;
|
||||||
d['uploadsInProgress'] = 0;
|
BrowserStore.setItem(key, value);
|
||||||
BrowserStore.setItem(key, JSON.stringify(d));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,6 @@ var client = require('../utils/client.jsx');
|
|||||||
var Constants = require('../utils/constants.jsx');
|
var Constants = require('../utils/constants.jsx');
|
||||||
var ActionTypes = Constants.ActionTypes;
|
var ActionTypes = Constants.ActionTypes;
|
||||||
|
|
||||||
var BrowserStore = require('../stores/browser_store.jsx');
|
|
||||||
|
|
||||||
var CHANGE_EVENT = 'change';
|
var CHANGE_EVENT = 'change';
|
||||||
|
|
||||||
var conn;
|
var conn;
|
||||||
|
|||||||
@@ -63,22 +63,10 @@ var TeamStore = assign({}, EventEmitter.prototype, {
|
|||||||
this._storeTeams(teams);
|
this._storeTeams(teams);
|
||||||
},
|
},
|
||||||
_storeTeams: function(teams) {
|
_storeTeams: function(teams) {
|
||||||
BrowserStore.setItem("user_teams", JSON.stringify(teams));
|
BrowserStore.setItem("user_teams", teams);
|
||||||
},
|
},
|
||||||
_getTeams: function() {
|
_getTeams: function() {
|
||||||
var teams = {};
|
return BrowserStore.getItem("user_teams", {});
|
||||||
|
|
||||||
try {
|
|
||||||
teams = JSON.parse(BrowserStore.getItem("user_teams"));
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
}
|
|
||||||
|
|
||||||
if (teams == null) {
|
|
||||||
teams = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return teams;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ var client = require('../utils/client.jsx');
|
|||||||
|
|
||||||
var Constants = require('../utils/constants.jsx');
|
var Constants = require('../utils/constants.jsx');
|
||||||
var ActionTypes = Constants.ActionTypes;
|
var ActionTypes = Constants.ActionTypes;
|
||||||
var BrowserStore = require('../stores/browser_store.jsx');
|
var BrowserStore = require('./browser_store.jsx');
|
||||||
|
|
||||||
var CHANGE_EVENT = 'change';
|
var CHANGE_EVENT = 'change';
|
||||||
var CHANGE_EVENT_SESSIONS = 'change_sessions';
|
var CHANGE_EVENT_SESSIONS = 'change_sessions';
|
||||||
@@ -18,6 +18,8 @@ var CHANGE_EVENT_STATUSES = 'change_statuses';
|
|||||||
|
|
||||||
var UserStore = assign({}, EventEmitter.prototype, {
|
var UserStore = assign({}, EventEmitter.prototype, {
|
||||||
|
|
||||||
|
_current_id: null,
|
||||||
|
|
||||||
emitChange: function(userId) {
|
emitChange: function(userId) {
|
||||||
this.emit(CHANGE_EVENT, userId);
|
this.emit(CHANGE_EVENT, userId);
|
||||||
},
|
},
|
||||||
@@ -64,13 +66,10 @@ var UserStore = assign({}, EventEmitter.prototype, {
|
|||||||
this.removeListener(CHANGE_EVENT_STATUSES, callback);
|
this.removeListener(CHANGE_EVENT_STATUSES, callback);
|
||||||
},
|
},
|
||||||
setCurrentId: function(id) {
|
setCurrentId: function(id) {
|
||||||
if (id == null)
|
this._current_id = id;
|
||||||
BrowserStore.removeGlobalItem("current_user_id");
|
|
||||||
else
|
|
||||||
BrowserStore.setGlobalItem("current_user_id", id);
|
|
||||||
},
|
},
|
||||||
getCurrentId: function(skipFetch) {
|
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
|
// this is a speical case to force fetch the
|
||||||
// current user if it's missing
|
// current user if it's missing
|
||||||
@@ -97,21 +96,13 @@ var UserStore = assign({}, EventEmitter.prototype, {
|
|||||||
this.setCurrentId(user.id);
|
this.setCurrentId(user.id);
|
||||||
},
|
},
|
||||||
getLastDomain: function() {
|
getLastDomain: function() {
|
||||||
var last_domain = BrowserStore.getItem("last_domain");
|
return BrowserStore.getItem("last_domain", '');
|
||||||
if (last_domain == null) {
|
|
||||||
last_domain = "";
|
|
||||||
}
|
|
||||||
return last_domain;
|
|
||||||
},
|
},
|
||||||
setLastDomain: function(domain) {
|
setLastDomain: function(domain) {
|
||||||
BrowserStore.setItem("last_domain", domain);
|
BrowserStore.setItem("last_domain", domain);
|
||||||
},
|
},
|
||||||
getLastEmail: function() {
|
getLastEmail: function() {
|
||||||
var last_email = BrowserStore.getItem("last_email");
|
return BrowserStore.getItem("last_email", '');
|
||||||
if (last_email == null) {
|
|
||||||
last_email = "";
|
|
||||||
}
|
|
||||||
return last_email;
|
|
||||||
},
|
},
|
||||||
setLastEmail: function(email) {
|
setLastEmail: function(email) {
|
||||||
BrowserStore.setItem("last_email", email);
|
BrowserStore.setItem("last_email", email);
|
||||||
@@ -153,91 +144,36 @@ var UserStore = assign({}, EventEmitter.prototype, {
|
|||||||
this._storeProfiles(ps);
|
this._storeProfiles(ps);
|
||||||
},
|
},
|
||||||
_storeProfiles: function(profiles) {
|
_storeProfiles: function(profiles) {
|
||||||
BrowserStore.setGlobalItem("profiles", JSON.stringify(profiles));
|
BrowserStore.setGlobalItem("profiles", profiles);
|
||||||
var profileUsernameMap = {};
|
var profileUsernameMap = {};
|
||||||
for (var id in profiles) {
|
for (var id in profiles) {
|
||||||
profileUsernameMap[profiles[id].username] = profiles[id];
|
profileUsernameMap[profiles[id].username] = profiles[id];
|
||||||
}
|
}
|
||||||
BrowserStore.setGlobalItem("profileUsernameMap", JSON.stringify(profileUsernameMap));
|
BrowserStore.setGlobalItem("profileUsernameMap", profileUsernameMap);
|
||||||
},
|
},
|
||||||
_getProfiles: function() {
|
_getProfiles: function() {
|
||||||
var profiles = {};
|
return BrowserStore.getGlobalItem("profiles", {});
|
||||||
try {
|
|
||||||
profiles = JSON.parse(BrowserStore.getGlobalItem("profiles"));
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
}
|
|
||||||
|
|
||||||
if (profiles == null) {
|
|
||||||
profiles = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return profiles;
|
|
||||||
},
|
},
|
||||||
_getProfilesUsernameMap: function() {
|
_getProfilesUsernameMap: function() {
|
||||||
var profileUsernameMap = {};
|
return BrowserStore.getGlobalItem("profileUsernameMap", {});
|
||||||
try {
|
|
||||||
profileUsernameMap = JSON.parse(BrowserStore.getGlobalItem("profileUsernameMap"));
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
}
|
|
||||||
|
|
||||||
if (profileUsernameMap == null) {
|
|
||||||
profileUsernameMap = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return profileUsernameMap;
|
|
||||||
},
|
},
|
||||||
setSessions: function(sessions) {
|
setSessions: function(sessions) {
|
||||||
BrowserStore.setItem("sessions", JSON.stringify(sessions));
|
BrowserStore.setItem("sessions", sessions);
|
||||||
},
|
},
|
||||||
getSessions: function() {
|
getSessions: function() {
|
||||||
var sessions = [];
|
return BrowserStore.getItem("sessions", []);
|
||||||
try {
|
|
||||||
sessions = JSON.parse(BrowserStore.getItem("sessions"));
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
}
|
|
||||||
if (sessions == null) {
|
|
||||||
sessions = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
return sessions;
|
|
||||||
},
|
},
|
||||||
setAudits: function(audits) {
|
setAudits: function(audits) {
|
||||||
BrowserStore.setItem("audits", JSON.stringify(audits));
|
BrowserStore.setItem("audits", audits);
|
||||||
},
|
},
|
||||||
getAudits: function() {
|
getAudits: function() {
|
||||||
var audits = [];
|
return BrowserStore.getItem("audits", []);
|
||||||
try {
|
|
||||||
audits = JSON.parse(BrowserStore.getItem("audits"));
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
}
|
|
||||||
|
|
||||||
if (audits == null) {
|
|
||||||
audits = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
return audits;
|
|
||||||
},
|
},
|
||||||
setTeams: function(teams) {
|
setTeams: function(teams) {
|
||||||
BrowserStore.setItem("teams", JSON.stringify(teams));
|
BrowserStore.setItem("teams", teams);
|
||||||
},
|
},
|
||||||
getTeams: function() {
|
getTeams: function() {
|
||||||
var teams = [];
|
return BrowserStore.getItem("teams", []);
|
||||||
try {
|
|
||||||
teams = JSON.parse(BrowserStore.getItem("teams"));
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
}
|
|
||||||
|
|
||||||
if (teams == null) {
|
|
||||||
teams = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
return teams;
|
|
||||||
},
|
},
|
||||||
getCurrentMentionKeys: function() {
|
getCurrentMentionKeys: function() {
|
||||||
var user = this.getCurrentUser();
|
var user = this.getCurrentUser();
|
||||||
@@ -258,11 +194,7 @@ var UserStore = assign({}, EventEmitter.prototype, {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
getLastVersion: function() {
|
getLastVersion: function() {
|
||||||
var last_version = BrowserStore.getItem("last_version");
|
return BrowserStore.getItem("last_version", '');
|
||||||
if (last_version == null) {
|
|
||||||
last_version = "";
|
|
||||||
}
|
|
||||||
return last_version;
|
|
||||||
},
|
},
|
||||||
setLastVersion: function(version) {
|
setLastVersion: function(version) {
|
||||||
BrowserStore.setItem("last_version", version);
|
BrowserStore.setItem("last_version", version);
|
||||||
@@ -272,7 +204,7 @@ var UserStore = assign({}, EventEmitter.prototype, {
|
|||||||
this.emitStatusesChange();
|
this.emitStatusesChange();
|
||||||
},
|
},
|
||||||
_setStatuses: function(statuses) {
|
_setStatuses: function(statuses) {
|
||||||
BrowserStore.setItem("statuses", JSON.stringify(statuses));
|
BrowserStore.setItem("statuses", statuses);
|
||||||
},
|
},
|
||||||
setStatus: function(user_id, status) {
|
setStatus: function(user_id, status) {
|
||||||
var statuses = this.getStatuses();
|
var statuses = this.getStatuses();
|
||||||
@@ -281,18 +213,7 @@ var UserStore = assign({}, EventEmitter.prototype, {
|
|||||||
this.emitStatusesChange();
|
this.emitStatusesChange();
|
||||||
},
|
},
|
||||||
getStatuses: function() {
|
getStatuses: function() {
|
||||||
var statuses = {};
|
return BrowserStore.getItem("statuses", {});
|
||||||
try {
|
|
||||||
statuses = JSON.parse(BrowserStore.getItem("statuses"));
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
}
|
|
||||||
|
|
||||||
if (statuses == null) {
|
|
||||||
statuses = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return statuses;
|
|
||||||
},
|
},
|
||||||
getStatus: function(id) {
|
getStatus: function(id) {
|
||||||
return this.getStatuses()[id];
|
return this.getStatuses()[id];
|
||||||
@@ -341,4 +262,3 @@ UserStore.setMaxListeners(0);
|
|||||||
global.window.UserStore = UserStore;
|
global.window.UserStore = UserStore;
|
||||||
module.exports = UserStore;
|
module.exports = UserStore;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -782,3 +782,34 @@ module.exports.getHomeLink = function() {
|
|||||||
parts[0] = "www";
|
parts[0] = "www";
|
||||||
return window.location.protocol + "//" + parts.join(".");
|
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);
|
||||||
|
|
||||||
|
};
|
||||||
|
|||||||
@@ -137,7 +137,7 @@
|
|||||||
border: 1px solid #E2E2E2;
|
border: 1px solid #E2E2E2;
|
||||||
background-color: #FFF;
|
background-color: #FFF;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: left center;
|
background-position: top left;
|
||||||
}
|
}
|
||||||
a {
|
a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|||||||
@@ -75,14 +75,16 @@
|
|||||||
// Team Header in Sidebar
|
// Team Header in Sidebar
|
||||||
.sidebar--left, .sidebar--menu {
|
.sidebar--left, .sidebar--menu {
|
||||||
.team__header {
|
.team__header {
|
||||||
padding: 0 15px 0 15px;
|
padding: 10px;
|
||||||
@include legacy-pie-clearfix;
|
@include legacy-pie-clearfix;
|
||||||
a {
|
a {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
.navbar-right {
|
.navbar-right {
|
||||||
font-size: 0.85em;
|
font-size: 0.85em;
|
||||||
margin: 16px -5px 0;
|
position: absolute;
|
||||||
|
top: 20px;
|
||||||
|
right: 22px;
|
||||||
.dropdown-toggle {
|
.dropdown-toggle {
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
}
|
}
|
||||||
@@ -100,17 +102,32 @@
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.team__name {
|
.user__picture {
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
float: left;
|
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-weight: 600;
|
||||||
font-size: 1.2em;
|
font-size: 16px;
|
||||||
max-width: 80%;
|
max-width: 80%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
.user__name {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #eee;
|
||||||
|
}
|
||||||
> .nav {
|
> .nav {
|
||||||
> li {
|
> li {
|
||||||
> a {
|
> a {
|
||||||
|
|||||||
@@ -2,13 +2,8 @@
|
|||||||
display: table;
|
display: table;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: absolute;
|
padding: 60px;
|
||||||
@include box-sizing(border-box);
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
&.loading-screen--channel {
|
|
||||||
position: relative;
|
|
||||||
padding: 4em 0 3.5em;
|
|
||||||
}
|
|
||||||
.loading__content {
|
.loading__content {
|
||||||
display: table-cell;
|
display: table-cell;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
@@ -19,11 +14,7 @@
|
|||||||
margin: 0 0.2em 0;
|
margin: 0 0.2em 0;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.loading-screen {
|
|
||||||
.loading__content {
|
|
||||||
.round {
|
.round {
|
||||||
background-color: #444;
|
background-color: #444;
|
||||||
width: 4px;
|
width: 4px;
|
||||||
@@ -32,43 +23,18 @@
|
|||||||
margin: 0 2px;
|
margin: 0 2px;
|
||||||
opacity: 0.1;
|
opacity: 0.1;
|
||||||
@include border-radius(10px);
|
@include border-radius(10px);
|
||||||
-moz-animation: move 0.75s infinite linear;
|
@include animation(move 0.75s infinite linear);
|
||||||
-webkit-animation: move 0.75s infinite linear;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#round_1 {
|
@for $i from 1 through 3 {
|
||||||
-moz-animation-delay: .2s;
|
.round-#{$i} {
|
||||||
-webkit-animation-delay: .2s;
|
@include animation-delay(.2s*$i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#round_2 {
|
@include keyframes(move) {
|
||||||
-moz-animation-delay: .4s;
|
from { opacity: 1; }
|
||||||
-webkit-animation-delay: .4s;
|
to { opacity: 0.1; }
|
||||||
}
|
|
||||||
|
|
||||||
#round_3 {
|
|
||||||
-moz-animation-delay: .6s;
|
|
||||||
-webkit-animation-delay: .6s;
|
|
||||||
}
|
|
||||||
|
|
||||||
@-moz-keyframes move {
|
|
||||||
0% {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
opacity: 0.1;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@-webkit-keyframes move {
|
|
||||||
0% {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
opacity: 0.1;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,8 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 1060;
|
z-index: 1060;
|
||||||
.mentions-box {
|
.mentions-box {
|
||||||
max-height: 303px;
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border: $border-gray;
|
border: $border-gray;
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ body.ios {
|
|||||||
table-layout: fixed;
|
table-layout: fixed;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
|
height: 100%;
|
||||||
.post-list__content {
|
.post-list__content {
|
||||||
display: table-cell;
|
display: table-cell;
|
||||||
vertical-align: bottom;
|
vertical-align: bottom;
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user