Merge pull request #365 from mattermost/mm-1700

MM-1700 don't pull all channel data all the time
Этот коммит содержится в:
Christopher Speller
2015-08-14 08:35:19 -04:00
родитель b1d37e9c38 2485b87b28
Коммит a8930cbabe
18 изменённых файлов: 865 добавлений и 363 удалений

Просмотреть файл

@@ -18,11 +18,13 @@ func InitChannel(r *mux.Router) {
sr := r.PathPrefix("/channels").Subrouter() sr := r.PathPrefix("/channels").Subrouter()
sr.Handle("/", ApiUserRequiredActivity(getChannels, false)).Methods("GET") sr.Handle("/", ApiUserRequiredActivity(getChannels, false)).Methods("GET")
sr.Handle("/more", ApiUserRequired(getMoreChannels)).Methods("GET") sr.Handle("/more", ApiUserRequired(getMoreChannels)).Methods("GET")
sr.Handle("/counts", ApiUserRequiredActivity(getChannelCounts, false)).Methods("GET")
sr.Handle("/create", ApiUserRequired(createChannel)).Methods("POST") sr.Handle("/create", ApiUserRequired(createChannel)).Methods("POST")
sr.Handle("/create_direct", ApiUserRequired(createDirectChannel)).Methods("POST") sr.Handle("/create_direct", ApiUserRequired(createDirectChannel)).Methods("POST")
sr.Handle("/update", ApiUserRequired(updateChannel)).Methods("POST") sr.Handle("/update", ApiUserRequired(updateChannel)).Methods("POST")
sr.Handle("/update_desc", ApiUserRequired(updateChannelDesc)).Methods("POST") sr.Handle("/update_desc", ApiUserRequired(updateChannelDesc)).Methods("POST")
sr.Handle("/update_notify_level", ApiUserRequired(updateNotifyLevel)).Methods("POST") sr.Handle("/update_notify_level", ApiUserRequired(updateNotifyLevel)).Methods("POST")
sr.Handle("/{id:[A-Za-z0-9]+}/", ApiUserRequiredActivity(getChannel, false)).Methods("GET")
sr.Handle("/{id:[A-Za-z0-9]+}/extra_info", ApiUserRequired(getChannelExtraInfo)).Methods("GET") sr.Handle("/{id:[A-Za-z0-9]+}/extra_info", ApiUserRequired(getChannelExtraInfo)).Methods("GET")
sr.Handle("/{id:[A-Za-z0-9]+}/join", ApiUserRequired(joinChannel)).Methods("POST") sr.Handle("/{id:[A-Za-z0-9]+}/join", ApiUserRequired(joinChannel)).Methods("POST")
sr.Handle("/{id:[A-Za-z0-9]+}/leave", ApiUserRequired(leaveChannel)).Methods("POST") sr.Handle("/{id:[A-Za-z0-9]+}/leave", ApiUserRequired(leaveChannel)).Methods("POST")
@@ -275,7 +277,7 @@ func updateChannelDesc(c *Context, w http.ResponseWriter, r *http.Request) {
func getChannels(c *Context, w http.ResponseWriter, r *http.Request) { func getChannels(c *Context, w http.ResponseWriter, r *http.Request) {
// user is already in the newtork // user is already in the team
if result := <-Srv.Store.Channel().GetChannels(c.Session.TeamId, c.Session.UserId); result.Err != nil { if result := <-Srv.Store.Channel().GetChannels(c.Session.TeamId, c.Session.UserId); result.Err != nil {
if result.Err.Message == "No channels were found" { if result.Err.Message == "No channels were found" {
@@ -300,7 +302,7 @@ func getChannels(c *Context, w http.ResponseWriter, r *http.Request) {
func getMoreChannels(c *Context, w http.ResponseWriter, r *http.Request) { func getMoreChannels(c *Context, w http.ResponseWriter, r *http.Request) {
// user is already in the newtork // user is already in the team
if result := <-Srv.Store.Channel().GetMoreChannels(c.Session.TeamId, c.Session.UserId); result.Err != nil { if result := <-Srv.Store.Channel().GetMoreChannels(c.Session.TeamId, c.Session.UserId); result.Err != nil {
c.Err = result.Err c.Err = result.Err
@@ -314,6 +316,22 @@ func getMoreChannels(c *Context, w http.ResponseWriter, r *http.Request) {
} }
} }
func getChannelCounts(c *Context, w http.ResponseWriter, r *http.Request) {
// user is already in the team
if result := <-Srv.Store.Channel().GetChannelCounts(c.Session.TeamId, c.Session.UserId); result.Err != nil {
c.Err = model.NewAppError("getChannelCounts", "Unable to get channel counts from the database", result.Err.Message)
return
} else if HandleEtag(result.Data.(*model.ChannelCounts).Etag(), w, r) {
return
} else {
data := result.Data.(*model.ChannelCounts)
w.Header().Set(model.HEADER_ETAG_SERVER, data.Etag())
w.Write([]byte(data.ToJson()))
}
}
func joinChannel(c *Context, w http.ResponseWriter, r *http.Request) { func joinChannel(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r) params := mux.Vars(r)
@@ -548,6 +566,37 @@ func updateLastViewedAt(c *Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte(model.MapToJson(result))) w.Write([]byte(model.MapToJson(result)))
} }
func getChannel(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
id := params["id"]
//pchan := Srv.Store.Channel().CheckPermissionsTo(c.Session.TeamId, id, c.Session.UserId)
cchan := Srv.Store.Channel().Get(id)
cmchan := Srv.Store.Channel().GetMember(id, c.Session.UserId)
if cresult := <-cchan; cresult.Err != nil {
c.Err = cresult.Err
return
} else if cmresult := <-cmchan; cmresult.Err != nil {
c.Err = cmresult.Err
return
} else {
data := &model.ChannelData{}
data.Channel = cresult.Data.(*model.Channel)
member := cmresult.Data.(model.ChannelMember)
data.Member = &member
if HandleEtag(data.Etag(), w, r) {
return
} else {
w.Header().Set(model.HEADER_ETAG_SERVER, data.Etag())
w.Header().Set("Expires", "-1")
w.Write([]byte(data.ToJson()))
}
}
}
func getChannelExtraInfo(c *Context, w http.ResponseWriter, r *http.Request) { func getChannelExtraInfo(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r) params := mux.Vars(r)

Просмотреть файл

@@ -320,6 +320,27 @@ func TestGetChannel(t *testing.T) {
if _, err := Client.UpdateLastViewedAt(channel2.Id); err != nil { if _, err := Client.UpdateLastViewedAt(channel2.Id); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if resp, err := Client.GetChannel(channel1.Id, ""); err != nil {
t.Fatal(err)
} else {
data := resp.Data.(*model.ChannelData)
if data.Channel.DisplayName != channel1.DisplayName {
t.Fatal("name didn't match")
}
// test etag caching
if cache_result, err := Client.GetChannel(channel1.Id, resp.Etag); err != nil {
t.Fatal(err)
} else if cache_result.Data.(*model.ChannelData) != nil {
t.Log(cache_result.Data)
t.Fatal("cache should be empty")
}
}
if _, err := Client.GetChannel("junk", ""); err == nil {
t.Fatal("should have failed - bad channel id")
}
} }
func TestGetMoreChannel(t *testing.T) { func TestGetMoreChannel(t *testing.T) {
@@ -366,6 +387,47 @@ func TestGetMoreChannel(t *testing.T) {
} }
} }
func TestGetChannelCounts(t *testing.T) {
Setup()
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
team = Client.Must(Client.CreateTeam(team)).Data.(*model.Team)
user := &model.User{TeamId: team.Id, Email: model.NewId() + "corey@test.com", Nickname: "Corey Hulen", Password: "pwd"}
user = Client.Must(Client.CreateUser(user, "")).Data.(*model.User)
store.Must(Srv.Store.User().VerifyEmail(user.Id))
Client.LoginByEmail(team.Name, user.Email, "pwd")
channel1 := &model.Channel{DisplayName: "A Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
channel2 := &model.Channel{DisplayName: "B Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team.Id}
channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel)
if result, err := Client.GetChannelCounts(""); err != nil {
t.Fatal(err)
} else {
counts := result.Data.(*model.ChannelCounts)
if len(counts.Counts) != 4 {
t.Fatal("wrong number of channel counts")
}
if len(counts.UpdateTimes) != 4 {
t.Fatal("wrong number of channel update times")
}
if cache_result, err := Client.GetChannelCounts(result.Etag); err != nil {
t.Fatal(err)
} else if cache_result.Data.(*model.ChannelCounts) != nil {
t.Log(cache_result.Data)
t.Fatal("result data should be empty")
}
}
}
func TestJoinChannel(t *testing.T) { func TestJoinChannel(t *testing.T) {
Setup() Setup()

63
model/channel_count.go Обычный файл
Просмотреть файл

@@ -0,0 +1,63 @@
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
// See License.txt for license information.
package model
import (
"crypto/md5"
"encoding/json"
"fmt"
"io"
"sort"
"strconv"
)
type ChannelCounts struct {
Counts map[string]int64 `json:"counts"`
UpdateTimes map[string]int64 `json:"update_times"`
}
func (o *ChannelCounts) Etag() string {
ids := []string{}
for id, _ := range o.Counts {
ids = append(ids, id)
}
sort.Strings(ids)
str := ""
for _, id := range ids {
str += id + strconv.FormatInt(o.Counts[id], 10)
}
md5Counts := fmt.Sprintf("%x", md5.Sum([]byte(str)))
var update int64 = 0
for _, u := range o.UpdateTimes {
if u > update {
update = u
}
}
return Etag(md5Counts, update)
}
func (o *ChannelCounts) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
}
func ChannelCountsFromJson(data io.Reader) *ChannelCounts {
decoder := json.NewDecoder(data)
var o ChannelCounts
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
}

43
model/channel_data.go Обычный файл
Просмотреть файл

@@ -0,0 +1,43 @@
// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved.
// See License.txt for license information.
package model
import (
"encoding/json"
"io"
)
type ChannelData struct {
Channel *Channel `json:"channel"`
Member *ChannelMember `json:"member"`
}
func (o *ChannelData) Etag() string {
var mt int64 = 0
if o.Member != nil {
mt = o.Member.LastUpdateAt
}
return Etag(o.Channel.Id, o.Channel.UpdateAt, o.Channel.LastPostAt, mt)
}
func (o *ChannelData) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
}
func ChannelDataFromJson(data io.Reader) *ChannelData {
decoder := json.NewDecoder(data)
var o ChannelData
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
}

Просмотреть файл

@@ -390,6 +390,15 @@ func (c *Client) GetChannels(etag string) (*Result, *AppError) {
} }
} }
func (c *Client) GetChannel(id, etag string) (*Result, *AppError) {
if r, err := c.DoGet("/channels/"+id+"/", "", etag); err != nil {
return nil, err
} else {
return &Result{r.Header.Get(HEADER_REQUEST_ID),
r.Header.Get(HEADER_ETAG_SERVER), ChannelDataFromJson(r.Body)}, nil
}
}
func (c *Client) GetMoreChannels(etag string) (*Result, *AppError) { func (c *Client) GetMoreChannels(etag string) (*Result, *AppError) {
if r, err := c.DoGet("/channels/more", "", etag); err != nil { if r, err := c.DoGet("/channels/more", "", etag); err != nil {
return nil, err return nil, err
@@ -399,6 +408,15 @@ func (c *Client) GetMoreChannels(etag string) (*Result, *AppError) {
} }
} }
func (c *Client) GetChannelCounts(etag string) (*Result, *AppError) {
if r, err := c.DoGet("/channels/counts", "", etag); err != nil {
return nil, err
} else {
return &Result{r.Header.Get(HEADER_REQUEST_ID),
r.Header.Get(HEADER_ETAG_SERVER), ChannelCountsFromJson(r.Body)}, nil
}
}
func (c *Client) JoinChannel(id string) (*Result, *AppError) { func (c *Client) JoinChannel(id string) (*Result, *AppError) {
if r, err := c.DoPost("/channels/"+id+"/join", ""); err != nil { if r, err := c.DoPost("/channels/"+id+"/join", ""); err != nil {
return nil, err return nil, err

Просмотреть файл

@@ -281,6 +281,41 @@ func (s SqlChannelStore) GetMoreChannels(teamId string, userId string) StoreChan
return storeChannel return storeChannel
} }
type channelIdWithCountAndUpdateAt struct {
Id string
TotalMsgCount int64
UpdateAt int64
}
func (s SqlChannelStore) GetChannelCounts(teamId string, userId string) StoreChannel {
storeChannel := make(StoreChannel)
go func() {
result := StoreResult{}
var data []channelIdWithCountAndUpdateAt
_, err := s.GetReplica().Select(&data, "SELECT Id, TotalMsgCount, UpdateAt FROM Channels WHERE Id IN (SELECT ChannelId FROM ChannelMembers WHERE UserId = :UserId) AND TeamId = :TeamId AND DeleteAt = 0 ORDER BY DisplayName", map[string]interface{}{"TeamId": teamId, "UserId": userId})
if err != nil {
result.Err = model.NewAppError("SqlChannelStore.GetChannelCounts", "We couldn't get the channel counts", "teamId="+teamId+", userId="+userId+", err="+err.Error())
} else {
counts := &model.ChannelCounts{Counts: make(map[string]int64), UpdateTimes: make(map[string]int64)}
for i := range data {
v := data[i]
counts.Counts[v.Id] = v.TotalMsgCount
counts.UpdateTimes[v.Id] = v.UpdateAt
}
result.Data = counts
}
storeChannel <- result
close(storeChannel)
}()
return storeChannel
}
func (s SqlChannelStore) GetByName(teamId string, name string) StoreChannel { func (s SqlChannelStore) GetByName(teamId string, name string) StoreChannel {
storeChannel := make(StoreChannel) storeChannel := make(StoreChannel)

Просмотреть файл

@@ -462,6 +462,53 @@ func TestChannelStoreGetMoreChannels(t *testing.T) {
} }
} }
func TestChannelStoreGetChannelCounts(t *testing.T) {
Setup()
o2 := model.Channel{}
o2.TeamId = model.NewId()
o2.DisplayName = "Channel2"
o2.Name = "a" + model.NewId() + "b"
o2.Type = model.CHANNEL_OPEN
Must(store.Channel().Save(&o2))
o1 := model.Channel{}
o1.TeamId = model.NewId()
o1.DisplayName = "Channel1"
o1.Name = "a" + model.NewId() + "b"
o1.Type = model.CHANNEL_OPEN
Must(store.Channel().Save(&o1))
m1 := model.ChannelMember{}
m1.ChannelId = o1.Id
m1.UserId = model.NewId()
m1.NotifyLevel = model.CHANNEL_NOTIFY_ALL
Must(store.Channel().SaveMember(&m1))
m2 := model.ChannelMember{}
m2.ChannelId = o1.Id
m2.UserId = model.NewId()
m2.NotifyLevel = model.CHANNEL_NOTIFY_ALL
Must(store.Channel().SaveMember(&m2))
m3 := model.ChannelMember{}
m3.ChannelId = o2.Id
m3.UserId = model.NewId()
m3.NotifyLevel = model.CHANNEL_NOTIFY_ALL
Must(store.Channel().SaveMember(&m3))
cresult := <-store.Channel().GetChannelCounts(o1.TeamId, m1.UserId)
counts := cresult.Data.(*model.ChannelCounts)
if len(counts.Counts) != 1 {
t.Fatal("wrong number of counts")
}
if len(counts.UpdateTimes) != 1 {
t.Fatal("wrong number of update times")
}
}
func TestChannelStoreUpdateLastViewedAt(t *testing.T) { func TestChannelStoreUpdateLastViewedAt(t *testing.T) {
Setup() Setup()

Просмотреть файл

@@ -50,6 +50,7 @@ type ChannelStore interface {
GetByName(team_id string, domain string) StoreChannel GetByName(team_id string, domain string) StoreChannel
GetChannels(teamId string, userId string) StoreChannel GetChannels(teamId string, userId string) StoreChannel
GetMoreChannels(teamId string, userId string) StoreChannel GetMoreChannels(teamId string, userId string) StoreChannel
GetChannelCounts(teamId string, userId string) StoreChannel
SaveMember(member *model.ChannelMember) StoreChannel SaveMember(member *model.ChannelMember) StoreChannel
GetMembers(channelId string) StoreChannel GetMembers(channelId string) StoreChannel

Просмотреть файл

@@ -14,7 +14,7 @@ module.exports = React.createClass({
Client.updateChannelDesc(data, Client.updateChannelDesc(data,
function(data) { function(data) {
this.setState({ server_error: "" }); this.setState({ server_error: "" });
AsyncClient.getChannels(true); AsyncClient.getChannel(this.state.channel_id);
$(this.refs.modal.getDOMNode()).modal('hide'); $(this.refs.modal.getDOMNode()).modal('hide');
}.bind(this), }.bind(this),
function(err) { function(err) {

Просмотреть файл

@@ -1,34 +1,32 @@
// 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 utils = require('../utils/utils.jsx'); var utils = require('../utils/utils.jsx');
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 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'); var LoadingScreen = require('./loading_screen.jsx');
function getStateFromStores() { function getStateFromStores() {
return { return {
channels: ChannelStore.getMoreAll(), channels: ChannelStore.getMoreAll(),
server_error: null serverError: null
}; };
} }
module.exports = React.createClass({ module.exports = React.createClass({
displayName: "MoreChannelsModal", 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 shown() {
asyncClient.getMoreChannels(true); asyncClient.getMoreChannels(true);
}); });
var self = this; var self = this;
$(this.refs.modal.getDOMNode()).on('show.bs.modal', function(e) { $(this.refs.modal.getDOMNode()).on('show.bs.modal', function show(e) {
var button = e.relatedTarget; var button = e.relatedTarget;
self.setState({ channel_type: $(button).attr('data-channeltype') }); self.setState({channelType: $(button).attr('data-channeltype')});
}); });
}, },
componentWillUnmount: function() { componentWillUnmount: function() {
@@ -42,18 +40,17 @@ module.exports = React.createClass({
}, },
getInitialState: function() { getInitialState: function() {
var initState = getStateFromStores(); var initState = getStateFromStores();
initState.channel_type = ""; initState.channelType = '';
return initState; return initState;
}, },
handleJoin: function(e) { handleJoin: function(id) {
var self = this; client.joinChannel(id,
client.joinChannel(e, function() {
function(data) { $(this.refs.modal.getDOMNode()).modal('hide');
$(self.refs.modal.getDOMNode()).modal('hide'); asyncClient.getChannel(id);
asyncClient.getChannels(true);
}.bind(this), }.bind(this),
function(err) { function(err) {
this.state.server_error = err.message; this.state.serverError = err.message;
this.setState(this.state); this.setState(this.state);
}.bind(this) }.bind(this)
); );
@@ -62,52 +59,66 @@ module.exports = React.createClass({
$(this.refs.modal.getDOMNode()).modal('hide'); $(this.refs.modal.getDOMNode()).modal('hide');
}, },
render: function() { render: function() {
var server_error = this.state.server_error ? <div className='form-group has-error'><label className='control-label'>{ this.state.server_error }</label></div> : null; var serverError;
if (this.state.serverError) {
serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>;
}
var outter = this; var outter = this;
var moreChannels; var moreChannels;
if (this.state.channels != null) if (this.state.channels != null) {
moreChannels = this.state.channels; var channels = this.state.channels;
if (!channels.loading) {
if (channels.length) {
moreChannels = (
<table className='more-channel-table table'>
<tbody>
{channels.map(function cMap(channel) {
return (
<tr key={channel.id}>
<td>
<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='btn btn-primary'>Join</button></td>
</tr>
);
})}
</tbody>
</table>
);
} else {
moreChannels = (
<div className='no-channel-message'>
<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>
);
}
} else {
moreChannels = <LoadingScreen />;
}
}
return ( return (
<div className="modal fade" id="more_channels" ref="modal" tabIndex="-1" role="dialog" aria-hidden="true"> <div className='modal fade' id='more_channels' ref='modal' tabIndex='-1' role='dialog' aria-hidden='true'>
<div className="modal-dialog"> <div className='modal-dialog'>
<div className="modal-content"> <div className='modal-content'>
<div className="modal-header"> <div className='modal-header'>
<button type="button" className="close" data-dismiss="modal"> <button type='button' className='close' data-dismiss='modal'>
<span aria-hidden="true">&times;</span> <span aria-hidden='true'>&times;</span>
<span className="sr-only">Close</span> <span className='sr-only'>Close</span>
</button> </button>
<h4 className="modal-title">More Channels</h4> <h4 className='modal-title'>More Channels</h4>
<button data-toggle="modal" data-target="#new_channel" data-channeltype={this.state.channel_type} type="button" className="btn btn-primary channel-create-btn" onClick={this.handleNewChannel}>Create New Channel</button> <button data-toggle='modal' data-target='#new_channel' data-channeltype={this.state.channelType} type='button' className='btn btn-primary channel-create-btn' onClick={this.handleNewChannel}>Create New Channel</button>
</div> </div>
<div className="modal-body"> <div className='modal-body'>
{!moreChannels.loading ? {moreChannels}
(moreChannels.length ? {serverError}
<table className="more-channel-table table">
<tbody>
{moreChannels.map(function(channel) {
return (
<tr key={channel.id}>
<td>
<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="btn btn-primary">Join</button></td>
</tr>
)
})}
</tbody>
</table>
: <div className="no-channel-message">
<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>)
: <LoadingScreen /> }
{ server_error }
</div> </div>
<div className="modal-footer"> <div className='modal-footer'>
<button type="button" className="btn btn-default" data-dismiss="modal">Close</button> <button type='button' className='btn btn-default' data-dismiss='modal'>Close</button>
</div> </div>
</div> </div>
</div> </div>

Просмотреть файл

@@ -55,16 +55,16 @@ module.exports = React.createClass({
channel.description = this.refs.channel_desc.getDOMNode().value.trim(); channel.description = this.refs.channel_desc.getDOMNode().value.trim();
channel.type = this.state.channelType; channel.type = this.state.channelType;
var self = this;
client.createChannel(channel, client.createChannel(channel,
function() { function(data) {
$(this.refs.modal.getDOMNode()).modal('hide');
asyncClient.getChannel(data.id);
utils.switchChannel(data);
this.refs.display_name.getDOMNode().value = ''; this.refs.display_name.getDOMNode().value = '';
this.refs.channel_name.getDOMNode().value = ''; this.refs.channel_name.getDOMNode().value = '';
this.refs.channel_desc.getDOMNode().value = ''; this.refs.channel_desc.getDOMNode().value = '';
$(self.refs.modal.getDOMNode()).modal('hide');
window.location = TeamStore.getCurrentTeamUrl() + '/channels/' + channel.name;
asyncClient.getChannels(true);
}.bind(this), }.bind(this),
function(err) { function(err) {
state.serverError = err.message; state.serverError = err.message;

Просмотреть файл

@@ -63,12 +63,14 @@ module.exports = React.createClass({
Client.updateChannel(channel, Client.updateChannel(channel,
function(data, text, req) { function(data, text, req) {
$(this.refs.modal.getDOMNode()).modal('hide');
AsyncClient.getChannel(channel.id);
utils.updateTabTitle(channel.display_name);
utils.updateAddressBar(channel.name);
this.refs.display_name.getDOMNode().value = ""; this.refs.display_name.getDOMNode().value = "";
this.refs.channel_name.getDOMNode().value = ""; this.refs.channel_name.getDOMNode().value = "";
$('#' + this.props.modalId).modal('hide');
window.location.href = TeamStore.getCurrentTeamUrl() + '/channels/' + this.state.channel_name;
AsyncClient.getChannels(true);
}.bind(this), }.bind(this),
function(err) { function(err) {
state.server_error = err.message; state.server_error = err.message;

Просмотреть файл

@@ -102,7 +102,7 @@ function getStateFromStores() {
} }
readDirectChannels = readDirectChannels.slice(index); readDirectChannels = readDirectChannels.slice(index);
showDirectChannels.sort(function(a, b) { showDirectChannels.sort(function directSort(a, b) {
if (a.display_name < b.display_name) { if (a.display_name < b.display_name) {
return -1; return -1;
} }
@@ -114,7 +114,7 @@ function getStateFromStores() {
} }
return { return {
active_id: currentId, activeId: currentId,
channels: ChannelStore.getAll(), channels: ChannelStore.getAll(),
members: members, members: members,
showDirectChannels: showDirectChannels, showDirectChannels: showDirectChannels,
@@ -157,9 +157,11 @@ module.exports = React.createClass({
onSocketChange: function(msg) { onSocketChange: function(msg) {
if (msg.action === 'posted') { if (msg.action === 'posted') {
if (ChannelStore.getCurrentId() === msg.channel_id) { if (ChannelStore.getCurrentId() === msg.channel_id) {
AsyncClient.getChannels(true, window.isActive); if (window.isActive) {
AsyncClient.updateLastViewedAt();
}
} else { } else {
AsyncClient.getChannels(true); AsyncClient.getChannels();
} }
if (UserStore.getCurrentId() !== msg.user_id) { if (UserStore.getCurrentId() !== msg.user_id) {
@@ -214,12 +216,12 @@ module.exports = React.createClass({
} }
} }
} else if (msg.action === 'viewed') { } else if (msg.action === 'viewed') {
if (ChannelStore.getCurrentId() != msg.channel_id) { if (ChannelStore.getCurrentId() !== msg.channel_id && UserStore.getCurrentId() === msg.user_id) {
AsyncClient.getChannels(true); AsyncClient.getChannel(msg.channel_id);
} }
} else if (msg.action === 'user_added') { } else if (msg.action === 'user_added') {
if (UserStore.getCurrentId() === msg.user_id) { if (UserStore.getCurrentId() === msg.user_id) {
AsyncClient.getChannels(true); AsyncClient.getChannel(msg.channel_id);
} }
} else if (msg.action === 'user_removed') { } else if (msg.action === 'user_removed') {
if (msg.user_id === UserStore.getCurrentId()) { if (msg.user_id === UserStore.getCurrentId()) {
@@ -282,7 +284,7 @@ module.exports = React.createClass({
}, },
render: function() { render: function() {
var members = this.state.members; var members = this.state.members;
var activeId = this.state.active_id; var activeId = this.state.activeId;
var badgesActive = false; var badgesActive = false;
// keep track of the first and last unread channels so we can use them to set the unread indicators // keep track of the first and last unread channels so we can use them to set the unread indicators
@@ -294,7 +296,7 @@ module.exports = React.createClass({
var channelMember = members[channel.id]; var channelMember = members[channel.id];
var linkClass = ''; var linkClass = '';
if (channel.id === self.state.active_id) { if (channel.id === activeId) {
linkClass = 'active'; linkClass = 'active';
} }

Просмотреть файл

@@ -10,212 +10,264 @@ var ActionTypes = Constants.ActionTypes;
var BrowserStore = require('../stores/browser_store.jsx'); var BrowserStore = require('../stores/browser_store.jsx');
var CHANGE_EVENT = 'change'; var CHANGE_EVENT = 'change';
var MORE_CHANGE_EVENT = 'change'; 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, currentId: null,
emitChange: function() { emitChange: function() {
this.emit(CHANGE_EVENT); this.emit(CHANGE_EVENT);
}, },
addChangeListener: function(callback) { addChangeListener: function(callback) {
this.on(CHANGE_EVENT, callback); this.on(CHANGE_EVENT, callback);
}, },
removeChangeListener: function(callback) { removeChangeListener: function(callback) {
this.removeListener(CHANGE_EVENT, callback); this.removeListener(CHANGE_EVENT, callback);
}, },
emitMoreChange: function() { emitMoreChange: function() {
this.emit(MORE_CHANGE_EVENT); this.emit(MORE_CHANGE_EVENT);
}, },
addMoreChangeListener: function(callback) { addMoreChangeListener: function(callback) {
this.on(MORE_CHANGE_EVENT, callback); this.on(MORE_CHANGE_EVENT, callback);
}, },
removeMoreChangeListener: function(callback) { removeMoreChangeListener: function(callback) {
this.removeListener(MORE_CHANGE_EVENT, callback); this.removeListener(MORE_CHANGE_EVENT, callback);
}, },
emitExtraInfoChange: function() { emitExtraInfoChange: function() {
this.emit(EXTRA_INFO_EVENT); this.emit(EXTRA_INFO_EVENT);
}, },
addExtraInfoChangeListener: function(callback) { addExtraInfoChangeListener: function(callback) {
this.on(EXTRA_INFO_EVENT, callback); this.on(EXTRA_INFO_EVENT, callback);
}, },
removeExtraInfoChangeListener: function(callback) { removeExtraInfoChangeListener: function(callback) {
this.removeListener(EXTRA_INFO_EVENT, callback); this.removeListener(EXTRA_INFO_EVENT, callback);
}, },
findFirstBy: function(field, value) { findFirstBy: function(field, value) {
var channels = this._getChannels(); var channels = this.pGetChannels();
for (var i = 0; i < channels.length; i++) { for (var i = 0; i < channels.length; i++) {
if (channels[i][field] == value) { if (channels[i][field] === value) {
return channels[i]; return channels[i];
} }
}
return null;
},
get: function(id) {
return this.findFirstBy('id', id);
},
getMember: function(id) {
return this.getAllMembers()[id];
},
getByName: function(name) {
return this.findFirstBy('name', name);
},
getAll: function() {
return this.pGetChannels();
},
getAllMembers: function() {
return this.pGetChannelMembers();
},
getMoreAll: function() {
return this.pGetMoreChannels();
},
setCurrentId: function(id) {
this.currentId = id;
},
setLastVisitedName: function(name) {
if (name == null) {
BrowserStore.removeItem('last_visited_name');
} else {
BrowserStore.setItem('last_visited_name', name);
}
},
getLastVisitedName: function() {
return BrowserStore.getItem('last_visited_name');
},
resetCounts: function(id) {
var cm = this.pGetChannelMembers();
for (var cmid in cm) {
if (cm[cmid].channel_id === id) {
var c = this.get(id);
if (c) {
cm[cmid].msg_count = this.get(id).total_msg_count;
cm[cmid].mention_count = 0;
}
break;
}
}
this.pStoreChannelMembers(cm);
},
getCurrentId: function() {
return this.currentId;
},
getCurrent: function() {
var currentId = this.getCurrentId();
if (currentId) {
return this.get(currentId);
} else {
return null;
}
},
getCurrentMember: function() {
var currentId = ChannelStore.getCurrentId();
if (currentId) {
return this.getAllMembers()[currentId];
} else {
return null;
}
},
setChannelMember: function(member) {
var members = this.pGetChannelMembers();
members[member.channel_id] = member;
this.pStoreChannelMembers(members);
this.emitChange();
},
getCurrentExtraInfo: function() {
var currentId = ChannelStore.getCurrentId();
var extra = null;
if (currentId) {
extra = this.pGetExtraInfos()[currentId];
}
if (extra == null) {
extra = {members: []};
}
return extra;
},
getExtraInfo: function(channelId) {
var extra = null;
if (channelId) {
extra = this.pGetExtraInfos()[channelId];
}
if (extra == null) {
extra = {members: []};
}
return extra;
},
pStoreChannel: function(channel) {
var channels = this.pGetChannels();
var found;
for (var i = 0; i < channels.length; i++) {
if (channels[i].id === channel.id) {
channels[i] = channel;
found = true;
break;
}
}
if (!found) {
channels.push(channel);
}
channels.sort(function chanSort(a, b) {
if (a.display_name.toLowerCase() < b.display_name.toLowerCase()) {
return -1;
}
if (a.display_name.toLowerCase() > b.display_name.toLowerCase()) {
return 1;
}
return 0;
});
this.pStoreChannels(channels);
},
pStoreChannels: function(channels) {
BrowserStore.setItem('channels', channels);
},
pGetChannels: function() {
return BrowserStore.getItem('channels', []);
},
pStoreChannelMember: function(channelMember) {
var members = this.pGetChannelMembers();
members[channelMember.channel_id] = channelMember;
this.pStoreChannelMembers(members);
},
pStoreChannelMembers: function(channelMembers) {
BrowserStore.setItem('channel_members', channelMembers);
},
pGetChannelMembers: function() {
return BrowserStore.getItem('channel_members', {});
},
pStoreMoreChannels: function(channels) {
BrowserStore.setItem('more_channels', channels);
},
pGetMoreChannels: function() {
var channels = BrowserStore.getItem('more_channels');
if (channels == null) {
channels = {};
channels.loading = true;
}
return channels;
},
pStoreExtraInfos: function(extraInfos) {
BrowserStore.setItem('extra_infos', extraInfos);
},
pGetExtraInfos: function() {
return BrowserStore.getItem('extra_infos', {});
},
isDefault: function(channel) {
return channel.name === Constants.DEFAULT_CHANNEL;
} }
return null;
},
get: function(id) {
return this.findFirstBy('id', id);
},
getMember: function(id) {
return this.getAllMembers()[id];
},
getByName: function(name) {
return this.findFirstBy('name', name);
},
getAll: function() {
return this._getChannels();
},
getAllMembers: function() {
return this._getChannelMembers();
},
getMoreAll: function() {
return this._getMoreChannels();
},
setCurrentId: function(id) {
this._current_id = id;
},
setLastVisitedName: function(name) {
if (name == null)
BrowserStore.removeItem("last_visited_name");
else
BrowserStore.setItem("last_visited_name", name);
},
getLastVisitedName: function() {
return BrowserStore.getItem("last_visited_name");
},
resetCounts: function(id) {
var cm = this._getChannelMembers();
for (var cmid in cm) {
if (cm[cmid].channel_id == id) {
var c = this.get(id);
if (c) {
cm[cmid].msg_count = this.get(id).total_msg_count;
cm[cmid].mention_count = 0;
}
break;
}
}
this._storeChannelMembers(cm);
},
getCurrentId: function() {
return this._current_id;
},
getCurrent: function() {
var currentId = this.getCurrentId();
if (currentId)
return this.get(currentId);
else
return null;
},
getCurrentMember: function() {
var currentId = ChannelStore.getCurrentId();
if (currentId)
return this.getAllMembers()[currentId];
else
return null;
},
setChannelMember: function(member) {
var members = this._getChannelMembers();
members[member.channel_id] = member;
this._storeChannelMembers(members);
this.emitChange();
},
getCurrentExtraInfo: function() {
var currentId = ChannelStore.getCurrentId();
var extra = null;
if (currentId)
extra = this._getExtraInfos()[currentId];
if (extra == null)
extra = {members: []};
return extra;
},
getExtraInfo: function(channel_id) {
var extra = null;
if (channel_id)
extra = this._getExtraInfos()[channel_id];
if (extra == null)
extra = {members: []};
return extra;
},
_storeChannels: function(channels) {
BrowserStore.setItem("channels", channels);
},
_getChannels: function() {
return BrowserStore.getItem("channels", []);
},
_storeChannelMembers: function(channelMembers) {
BrowserStore.setItem("channel_members", channelMembers);
},
_getChannelMembers: function() {
return BrowserStore.getItem("channel_members", {});
},
_storeMoreChannels: function(channels) {
BrowserStore.setItem("more_channels", channels);
},
_getMoreChannels: function() {
var channels = BrowserStore.getItem("more_channels");
if (channels == null) {
channels = {};
channels.loading = true;
}
return channels;
},
_storeExtraInfos: function(extraInfos) {
BrowserStore.setItem("extra_infos", extraInfos);
},
_getExtraInfos: function() {
return BrowserStore.getItem("extra_infos", {});
},
isDefault: function(channel) {
return channel.name == Constants.DEFAULT_CHANNEL;
}
}); });
ChannelStore.dispatchToken = AppDispatcher.register(function(payload) { ChannelStore.dispatchToken = AppDispatcher.register(function(payload) {
var action = payload.action; var action = payload.action;
var currentId;
switch(action.type) { switch(action.type) {
case ActionTypes.CLICK_CHANNEL: case ActionTypes.CLICK_CHANNEL:
ChannelStore.setCurrentId(action.id); ChannelStore.setCurrentId(action.id);
ChannelStore.setLastVisitedName(action.name); ChannelStore.setLastVisitedName(action.name);
ChannelStore.resetCounts(action.id); ChannelStore.resetCounts(action.id);
ChannelStore.emitChange(); ChannelStore.emitChange();
break; break;
case ActionTypes.RECIEVED_CHANNELS: case ActionTypes.RECIEVED_CHANNELS:
ChannelStore._storeChannels(action.channels); ChannelStore.pStoreChannels(action.channels);
ChannelStore._storeChannelMembers(action.members); ChannelStore.pStoreChannelMembers(action.members);
var currentId = ChannelStore.getCurrentId(); currentId = ChannelStore.getCurrentId();
if (currentId) ChannelStore.resetCounts(currentId); if (currentId) {
ChannelStore.emitChange(); ChannelStore.resetCounts(currentId);
break; }
ChannelStore.emitChange();
break;
case ActionTypes.RECIEVED_MORE_CHANNELS: case ActionTypes.RECIEVED_CHANNEL:
ChannelStore._storeMoreChannels(action.channels); ChannelStore.pStoreChannel(action.channel);
ChannelStore.emitMoreChange(); ChannelStore.pStoreChannelMember(action.member);
break; currentId = ChannelStore.getCurrentId();
if (currentId) {
ChannelStore.resetCounts(currentId);
}
ChannelStore.emitChange();
break;
case ActionTypes.RECIEVED_CHANNEL_EXTRA_INFO: case ActionTypes.RECIEVED_MORE_CHANNELS:
var extra_infos = ChannelStore._getExtraInfos(); ChannelStore.pStoreMoreChannels(action.channels);
extra_infos[action.extra_info.id] = action.extra_info; ChannelStore.emitMoreChange();
ChannelStore._storeExtraInfos(extra_infos); break;
ChannelStore.emitExtraInfoChange();
break;
default: case ActionTypes.RECIEVED_CHANNEL_EXTRA_INFO:
} var extraInfos = ChannelStore.pGetExtraInfos();
extraInfos[action.extra_info.id] = action.extra_info;
ChannelStore.pStoreExtraInfos(extraInfos);
ChannelStore.emitExtraInfoChange();
break;
default:
}
}); });
module.exports = ChannelStore; module.exports = ChannelStore;

Просмотреть файл

@@ -14,100 +14,171 @@ var ActionTypes = Constants.ActionTypes;
// Used to track in progress async calls // Used to track in progress async calls
var callTracker = {}; var callTracker = {};
var dispatchError = function(err, method) { function dispatchError(err, method) {
AppDispatcher.handleServerAction({ AppDispatcher.handleServerAction({
type: ActionTypes.RECIEVED_ERROR, type: ActionTypes.RECIEVED_ERROR,
err: err, err: err,
method: method method: method
}); });
}; }
module.exports.dispatchError = dispatchError;
var isCallInProgress = function(callName) { function isCallInProgress(callName) {
if (!(callName in callTracker)) return false; if (!(callName in callTracker)) {
return false;
}
if (callTracker[callName] === 0) return false; if (callTracker[callName] === 0) {
return false;
}
if (utils.getTimestamp() - callTracker[callName] > 5000) { if (utils.getTimestamp() - callTracker[callName] > 5000) {
console.log("AsyncClient call " + callName + " expired after more than 5 seconds"); console.log('AsyncClient call ' + callName + ' expired after more than 5 seconds');
return false; return false;
} }
return true; return true;
}; }
module.exports.dispatchError = dispatchError; function getChannels(force, updateLastViewed, checkVersion) {
var channels = ChannelStore.getAll();
module.exports.getChannels = function(force, updateLastViewed, checkVersion) { if (channels.length === 0 || force) {
if (isCallInProgress("getChannels")) return; if (isCallInProgress('getChannels')) {
return;
}
callTracker.getChannels = utils.getTimestamp();
if (ChannelStore.getAll().length == 0 || force) {
callTracker["getChannels"] = utils.getTimestamp();
client.getChannels( client.getChannels(
function(data, textStatus, xhr) { function(data, textStatus, xhr) {
callTracker["getChannels"] = 0; callTracker.getChannels = 0;
if (updateLastViewed && ChannelStore.getCurrentId() != null) {
module.exports.updateLastViewedAt();
}
if (checkVersion) { if (checkVersion) {
var serverVersion = xhr.getResponseHeader("X-Version-ID"); var serverVersion = xhr.getResponseHeader('X-Version-ID');
if (!UserStore.getLastVersion()) { if (!UserStore.getLastVersion()) {
UserStore.setLastVersion(serverVersion); UserStore.setLastVersion(serverVersion);
} }
if (serverVersion != UserStore.getLastVersion()) { if (serverVersion !== UserStore.getLastVersion()) {
UserStore.setLastVersion(serverVersion); UserStore.setLastVersion(serverVersion);
window.location.href = window.location.href; window.location.href = window.location.href;
console.log("Detected version update refreshing the page"); console.log('Detected version update refreshing the page');
} }
} }
if (xhr.status === 304 || !data) return; if (xhr.status === 304 || !data) {
return;
}
AppDispatcher.handleServerAction({ AppDispatcher.handleServerAction({
type: ActionTypes.RECIEVED_CHANNELS, type: ActionTypes.RECIEVED_CHANNELS,
channels: data.channels, channels: data.channels,
members: data.members members: data.members
}); });
}, },
function(err) { function(err) {
callTracker["getChannels"] = 0; callTracker.getChannels = 0;
dispatchError(err, "getChannels"); dispatchError(err, 'getChannels');
}
);
} else {
if (isCallInProgress('getChannelCounts')) {
return;
}
callTracker.getChannelCounts = utils.getTimestamp();
client.getChannelCounts(
function(data, textStatus, xhr) {
callTracker.getChannelCounts = 0;
if (xhr.status === 304 || !data) {
return;
}
var countMap = data.counts;
var updateAtMap = data.update_times;
for (var id in countMap) {
var c = ChannelStore.get(id);
var count = countMap[id];
var updateAt = updateAtMap[id];
if (!c || c.total_msg_count !== count || updateAt > c.update_at) {
getChannel(id);
}
}
},
function(err) {
callTracker.getChannelCounts = 0;
dispatchError(err, 'getChannelCounts');
} }
); );
} }
if (updateLastViewed && ChannelStore.getCurrentId() != null) {
module.exports.updateLastViewedAt();
}
} }
module.exports.getChannels = getChannels;
function getChannel(id) {
if (isCallInProgress('getChannel' + id)) {
return;
}
callTracker['getChannel' + id] = utils.getTimestamp();
client.getChannel(id,
function(data, textStatus, xhr) {
callTracker['getChannel' + id] = 0;
if (xhr.status === 304 || !data) {
return;
}
AppDispatcher.handleServerAction({
type: ActionTypes.RECIEVED_CHANNEL,
channel: data.channel,
member: data.member
});
},
function(err) {
callTracker['getChannel' + id] = 0;
dispatchError(err, 'getChannel');
}
);
}
module.exports.getChannel = getChannel;
module.exports.updateLastViewedAt = function() { module.exports.updateLastViewedAt = function() {
if (isCallInProgress("updateLastViewed")) return; if (isCallInProgress('updateLastViewed')) return;
if (ChannelStore.getCurrentId() == null) return; if (ChannelStore.getCurrentId() == null) return;
callTracker["updateLastViewed"] = utils.getTimestamp(); callTracker['updateLastViewed'] = utils.getTimestamp();
client.updateLastViewedAt( client.updateLastViewedAt(
ChannelStore.getCurrentId(), ChannelStore.getCurrentId(),
function(data) { function(data) {
callTracker["updateLastViewed"] = 0; callTracker['updateLastViewed'] = 0;
}, },
function(err) { function(err) {
callTracker["updateLastViewed"] = 0; callTracker['updateLastViewed'] = 0;
dispatchError(err, "updateLastViewedAt"); dispatchError(err, 'updateLastViewedAt');
} }
); );
} }
module.exports.getMoreChannels = function(force) { module.exports.getMoreChannels = function(force) {
if (isCallInProgress("getMoreChannels")) return; if (isCallInProgress('getMoreChannels')) return;
if (ChannelStore.getMoreAll().loading || force) { if (ChannelStore.getMoreAll().loading || force) {
callTracker["getMoreChannels"] = utils.getTimestamp(); callTracker['getMoreChannels'] = utils.getTimestamp();
client.getMoreChannels( client.getMoreChannels(
function(data, textStatus, xhr) { function(data, textStatus, xhr) {
callTracker["getMoreChannels"] = 0; callTracker['getMoreChannels'] = 0;
if (xhr.status === 304 || !data) return; if (xhr.status === 304 || !data) return;
@@ -118,8 +189,8 @@ module.exports.getMoreChannels = function(force) {
}); });
}, },
function(err) { function(err) {
callTracker["getMoreChannels"] = 0; callTracker['getMoreChannels'] = 0;
dispatchError(err, "getMoreChannels"); dispatchError(err, 'getMoreChannels');
} }
); );
} }
@@ -129,15 +200,15 @@ module.exports.getChannelExtraInfo = function(force) {
var channelId = ChannelStore.getCurrentId(); var channelId = ChannelStore.getCurrentId();
if (channelId != null) { if (channelId != null) {
if (isCallInProgress("getChannelExtraInfo_"+channelId)) return; if (isCallInProgress('getChannelExtraInfo_'+channelId)) return;
var minMembers = ChannelStore.getCurrent() && ChannelStore.getCurrent().type === 'D' ? 1 : 0; var minMembers = ChannelStore.getCurrent() && ChannelStore.getCurrent().type === 'D' ? 1 : 0;
if (ChannelStore.getCurrentExtraInfo().members.length <= minMembers || force) { if (ChannelStore.getCurrentExtraInfo().members.length <= minMembers || force) {
callTracker["getChannelExtraInfo_"+channelId] = utils.getTimestamp(); callTracker['getChannelExtraInfo_'+channelId] = utils.getTimestamp();
client.getChannelExtraInfo( client.getChannelExtraInfo(
channelId, channelId,
function(data, textStatus, xhr) { function(data, textStatus, xhr) {
callTracker["getChannelExtraInfo_"+channelId] = 0; callTracker['getChannelExtraInfo_'+channelId] = 0;
if (xhr.status === 304 || !data) return; if (xhr.status === 304 || !data) return;
@@ -147,8 +218,8 @@ module.exports.getChannelExtraInfo = function(force) {
}); });
}, },
function(err) { function(err) {
callTracker["getChannelExtraInfo_"+channelId] = 0; callTracker['getChannelExtraInfo_'+channelId] = 0;
dispatchError(err, "getChannelExtraInfo"); dispatchError(err, 'getChannelExtraInfo');
} }
); );
} }
@@ -156,12 +227,12 @@ module.exports.getChannelExtraInfo = function(force) {
} }
module.exports.getProfiles = function() { module.exports.getProfiles = function() {
if (isCallInProgress("getProfiles")) return; if (isCallInProgress('getProfiles')) return;
callTracker["getProfiles"] = utils.getTimestamp(); callTracker['getProfiles'] = utils.getTimestamp();
client.getProfiles( client.getProfiles(
function(data, textStatus, xhr) { function(data, textStatus, xhr) {
callTracker["getProfiles"] = 0; callTracker['getProfiles'] = 0;
if (xhr.status === 304 || !data) return; if (xhr.status === 304 || !data) return;
@@ -171,20 +242,20 @@ module.exports.getProfiles = function() {
}); });
}, },
function(err) { function(err) {
callTracker["getProfiles"] = 0; callTracker['getProfiles'] = 0;
dispatchError(err, "getProfiles"); dispatchError(err, 'getProfiles');
} }
); );
} }
module.exports.getSessions = function() { module.exports.getSessions = function() {
if (isCallInProgress("getSessions")) return; if (isCallInProgress('getSessions')) return;
callTracker["getSessions"] = utils.getTimestamp(); callTracker['getSessions'] = utils.getTimestamp();
client.getSessions( client.getSessions(
UserStore.getCurrentId(), UserStore.getCurrentId(),
function(data, textStatus, xhr) { function(data, textStatus, xhr) {
callTracker["getSessions"] = 0; callTracker['getSessions'] = 0;
if (xhr.status === 304 || !data) return; if (xhr.status === 304 || !data) return;
@@ -194,20 +265,20 @@ module.exports.getSessions = function() {
}); });
}, },
function(err) { function(err) {
callTracker["getSessions"] = 0; callTracker['getSessions'] = 0;
dispatchError(err, "getSessions"); dispatchError(err, 'getSessions');
} }
); );
} }
module.exports.getAudits = function() { module.exports.getAudits = function() {
if (isCallInProgress("getAudits")) return; if (isCallInProgress('getAudits')) return;
callTracker["getAudits"] = utils.getTimestamp(); callTracker['getAudits'] = utils.getTimestamp();
client.getAudits( client.getAudits(
UserStore.getCurrentId(), UserStore.getCurrentId(),
function(data, textStatus, xhr) { function(data, textStatus, xhr) {
callTracker["getAudits"] = 0; callTracker['getAudits'] = 0;
if (xhr.status === 304 || !data) return; if (xhr.status === 304 || !data) return;
@@ -217,22 +288,22 @@ module.exports.getAudits = function() {
}); });
}, },
function(err) { function(err) {
callTracker["getAudits"] = 0; callTracker['getAudits'] = 0;
dispatchError(err, "getAudits"); dispatchError(err, 'getAudits');
} }
); );
} }
module.exports.findTeams = function(email) { module.exports.findTeams = function(email) {
if (isCallInProgress("findTeams_"+email)) return; if (isCallInProgress('findTeams_'+email)) return;
var user = UserStore.getCurrentUser(); var user = UserStore.getCurrentUser();
if (user) { if (user) {
callTracker["findTeams_"+email] = utils.getTimestamp(); callTracker['findTeams_'+email] = utils.getTimestamp();
client.findTeams( client.findTeams(
user.email, user.email,
function(data, textStatus, xhr) { function(data, textStatus, xhr) {
callTracker["findTeams_"+email] = 0; callTracker['findTeams_'+email] = 0;
if (xhr.status === 304 || !data) return; if (xhr.status === 304 || !data) return;
@@ -242,21 +313,21 @@ module.exports.findTeams = function(email) {
}); });
}, },
function(err) { function(err) {
callTracker["findTeams_"+email] = 0; callTracker['findTeams_'+email] = 0;
dispatchError(err, "findTeams"); dispatchError(err, 'findTeams');
} }
); );
} }
} }
module.exports.search = function(terms) { module.exports.search = function(terms) {
if (isCallInProgress("search_"+String(terms))) return; if (isCallInProgress('search_'+String(terms))) return;
callTracker["search_"+String(terms)] = utils.getTimestamp(); callTracker['search_'+String(terms)] = utils.getTimestamp();
client.search( client.search(
terms, terms,
function(data, textStatus, xhr) { function(data, textStatus, xhr) {
callTracker["search_"+String(terms)] = 0; callTracker['search_'+String(terms)] = 0;
if (xhr.status === 304 || !data) return; if (xhr.status === 304 || !data) return;
@@ -266,8 +337,8 @@ module.exports.search = function(terms) {
}); });
}, },
function(err) { function(err) {
callTracker["search_"+String(terms)] = 0; callTracker['search_'+String(terms)] = 0;
dispatchError(err, "search"); dispatchError(err, 'search');
} }
); );
} }
@@ -276,7 +347,7 @@ module.exports.getPosts = function(force, id, maxPosts) {
if (PostStore.getCurrentPosts() == null || force) { if (PostStore.getCurrentPosts() == null || force) {
var channelId = id ? id : ChannelStore.getCurrentId(); var channelId = id ? id : ChannelStore.getCurrentId();
if (isCallInProgress("getPosts_"+channelId)) return; if (isCallInProgress('getPosts_'+channelId)) return;
var post_list = PostStore.getCurrentPosts(); var post_list = PostStore.getCurrentPosts();
@@ -291,7 +362,7 @@ module.exports.getPosts = function(force, id, maxPosts) {
} }
if (channelId != null) { if (channelId != null) {
callTracker["getPosts_"+channelId] = utils.getTimestamp(); callTracker['getPosts_'+channelId] = utils.getTimestamp();
client.getPosts( client.getPosts(
channelId, channelId,
0, 0,
@@ -308,23 +379,25 @@ module.exports.getPosts = function(force, id, maxPosts) {
module.exports.getProfiles(); module.exports.getProfiles();
}, },
function(err) { function(err) {
dispatchError(err, "getPosts"); dispatchError(err, 'getPosts');
}, },
function() { function() {
callTracker["getPosts_"+channelId] = 0; callTracker['getPosts_'+channelId] = 0;
} }
); );
} }
} }
} }
module.exports.getMe = function() { function getMe() {
if (isCallInProgress("getMe")) return; if (isCallInProgress('getMe')) {
return;
}
callTracker["getMe"] = utils.getTimestamp(); callTracker.getMe = utils.getTimestamp();
client.getMe( client.getMe(
function(data, textStatus, xhr) { function(data, textStatus, xhr) {
callTracker["getMe"] = 0; callTracker.getMe = 0;
if (xhr.status === 304 || !data) return; if (xhr.status === 304 || !data) return;
@@ -334,19 +407,20 @@ module.exports.getMe = function() {
}); });
}, },
function(err) { function(err) {
callTracker["getMe"] = 0; callTracker.getMe = 0;
dispatchError(err, "getMe"); dispatchError(err, 'getMe');
} }
); );
} }
module.exports.getMe = getMe;
module.exports.getStatuses = function() { module.exports.getStatuses = function() {
if (isCallInProgress("getStatuses")) return; if (isCallInProgress('getStatuses')) return;
callTracker["getStatuses"] = utils.getTimestamp(); callTracker['getStatuses'] = utils.getTimestamp();
client.getStatuses( client.getStatuses(
function(data, textStatus, xhr) { function(data, textStatus, xhr) {
callTracker["getStatuses"] = 0; callTracker['getStatuses'] = 0;
if (xhr.status === 304 || !data) return; if (xhr.status === 304 || !data) return;
@@ -356,19 +430,19 @@ module.exports.getStatuses = function() {
}); });
}, },
function(err) { function(err) {
callTracker["getStatuses"] = 0; callTracker['getStatuses'] = 0;
dispatchError(err, "getStatuses"); dispatchError(err, 'getStatuses');
} }
); );
} }
module.exports.getMyTeam = function() { module.exports.getMyTeam = function() {
if (isCallInProgress("getMyTeam")) return; if (isCallInProgress('getMyTeam')) return;
callTracker["getMyTeam"] = utils.getTimestamp(); callTracker['getMyTeam'] = utils.getTimestamp();
client.getMyTeam( client.getMyTeam(
function(data, textStatus, xhr) { function(data, textStatus, xhr) {
callTracker["getMyTeam"] = 0; callTracker['getMyTeam'] = 0;
if (xhr.status === 304 || !data) return; if (xhr.status === 304 || !data) return;
@@ -378,8 +452,8 @@ module.exports.getMyTeam = function() {
}); });
}, },
function(err) { function(err) {
callTracker["getMyTeam"] = 0; callTracker['getMyTeam'] = 0;
dispatchError(err, "getMyTeam"); dispatchError(err, 'getMyTeam');
} }
); );
} }

Просмотреть файл

@@ -540,18 +540,34 @@ module.exports.updateLastViewedAt = function(channelId, success, error) {
}); });
}; };
module.exports.getChannels = function(success, error) { function getChannels(success, error) {
$.ajax({ $.ajax({
url: "/api/v1/channels/", url: '/api/v1/channels/',
dataType: 'json', dataType: 'json',
type: 'GET', type: 'GET',
success: success, success: success,
ifModified: true, ifModified: true,
error: function(xhr, status, err) { error: function(xhr, status, err) {
e = handleError("getChannels", xhr, status, err); var e = handleError('getChannels', xhr, status, err);
error(e); error(e);
} }
}); });
}
module.exports.getChannels = getChannels;
module.exports.getChannel = function(id, success, error) {
$.ajax({
url: "/api/v1/channels/" + id + "/",
dataType: 'json',
type: 'GET',
success: success,
error: function(xhr, status, err) {
e = handleError("getChannel", xhr, status, err);
error(e);
}
});
module.exports.track('api', 'api_channel_get');
}; };
module.exports.getMoreChannels = function(success, error) { module.exports.getMoreChannels = function(success, error) {
@@ -568,6 +584,21 @@ module.exports.getMoreChannels = function(success, error) {
}); });
}; };
function getChannelCounts(success, error) {
$.ajax({
url: '/api/v1/channels/counts',
dataType: 'json',
type: 'GET',
success: success,
ifModified: true,
error: function(xhr, status, err) {
var e = handleError('getChannelCounts', xhr, status, err);
error(e);
}
});
}
module.exports.getChannelCounts = getChannelCounts;
module.exports.getChannelExtraInfo = function(id, success, error) { module.exports.getChannelExtraInfo = function(id, success, error) {
$.ajax({ $.ajax({
url: "/api/v1/channels/" + id + "/extra_info", url: "/api/v1/channels/" + id + "/extra_info",

Просмотреть файл

@@ -10,6 +10,7 @@ module.exports = {
CLICK_CHANNEL: null, CLICK_CHANNEL: null,
CREATE_CHANNEL: null, CREATE_CHANNEL: null,
RECIEVED_CHANNELS: null, RECIEVED_CHANNELS: null,
RECIEVED_CHANNEL: null,
RECIEVED_MORE_CHANNELS: null, RECIEVED_MORE_CHANNELS: null,
RECIEVED_CHANNEL_EXTRA_INFO: null, RECIEVED_CHANNEL_EXTRA_INFO: null,

Просмотреть файл

@@ -732,20 +732,19 @@ module.exports.isValidUsername = function (name) {
return error; return error;
} }
module.exports.switchChannel = function(channel, teammate_name) { function switchChannel(channel, teammateName) {
AppDispatcher.handleViewAction({ AppDispatcher.handleViewAction({
type: ActionTypes.CLICK_CHANNEL, type: ActionTypes.CLICK_CHANNEL,
name: channel.name, name: channel.name,
id: channel.id id: channel.id
}); });
var teamURL = window.location.href.split('/channels')[0]; updateAddressBar(channel.name);
history.replaceState('data', '', teamURL + '/channels/' + channel.name);
if (channel.type === 'D' && teammate_name) { if (channel.type === 'D' && teammateName) {
document.title = teammate_name + " " + document.title.substring(document.title.lastIndexOf("-")); updateTabTitle(teammateName);
} else { } else {
document.title = channel.display_name + " " + document.title.substring(document.title.lastIndexOf("-")); updateTabTitle(channel.display_name);
} }
AsyncClient.getChannels(true, true, true); AsyncClient.getChannels(true, true, true);
@@ -759,6 +758,18 @@ module.exports.switchChannel = function(channel, teammate_name) {
return false; return false;
} }
module.exports.switchChannel = switchChannel;
function updateTabTitle(name) {
document.title = name + ' ' + document.title.substring(document.title.lastIndexOf('-'));
}
module.exports.updateTabTitle = updateTabTitle;
function updateAddressBar(channelName) {
var teamURL = window.location.href.split('/channels')[0];
history.replaceState('data', '', teamURL + '/channels/' + channelName);
}
module.exports.updateAddressBar = updateAddressBar;
module.exports.isMobile = function() { module.exports.isMobile = function() {
return screen.width <= 768; return screen.width <= 768;