MM-33708 - Add MentionCountRoot column to ChannelMembers (#17099)
* added new column for root-only mentions Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
3c21eef110
Коммит
480796a1df
@@ -320,6 +320,9 @@ jobs:
|
|||||||
mattermost/mattermost-build-server:20201119_golang-1.15.5 \
|
mattermost/mattermost-build-server:20201119_golang-1.15.5 \
|
||||||
bash -c "ulimit -n 8096; make ARGS='version' run-cli && make MM_SQLSETTINGS_DATASOURCE='postgres://mmuser:mostest@postgres:5432/latest?sslmode=disable&connect_timeout=10' ARGS='version' run-cli"
|
bash -c "ulimit -n 8096; make ARGS='version' run-cli && make MM_SQLSETTINGS_DATASOURCE='postgres://mmuser:mostest@postgres:5432/latest?sslmode=disable&connect_timeout=10' ARGS='version' run-cli"
|
||||||
|
|
||||||
|
echo "Ignoring known mismatch: ChannelMembers.MentionCountRoot"
|
||||||
|
docker-compose --no-ansi exec -T postgres sh -c 'exec echo "ALTER TABLE ChannelMembers DROP COLUMN MentionCountRoot;" | exec psql -U mmuser -d migrated'
|
||||||
|
docker-compose --no-ansi exec -T postgres sh -c 'exec echo "ALTER TABLE ChannelMembers DROP COLUMN MentionCountRoot;" | exec psql -U mmuser -d latest'
|
||||||
echo "Ignoring known mismatch: ChannelMembers.MsgCountRoot and Channels.TotalMsgCountRoot"
|
echo "Ignoring known mismatch: ChannelMembers.MsgCountRoot and Channels.TotalMsgCountRoot"
|
||||||
docker-compose --no-ansi exec -T postgres sh -c 'exec echo "ALTER TABLE ChannelMembers DROP COLUMN MsgCountRoot;" | exec psql -U mmuser -d migrated'
|
docker-compose --no-ansi exec -T postgres sh -c 'exec echo "ALTER TABLE ChannelMembers DROP COLUMN MsgCountRoot;" | exec psql -U mmuser -d migrated'
|
||||||
docker-compose --no-ansi exec -T postgres sh -c 'exec echo "ALTER TABLE ChannelMembers DROP COLUMN MsgCountRoot;" | exec psql -U mmuser -d latest'
|
docker-compose --no-ansi exec -T postgres sh -c 'exec echo "ALTER TABLE ChannelMembers DROP COLUMN MsgCountRoot;" | exec psql -U mmuser -d latest'
|
||||||
@@ -359,7 +362,9 @@ jobs:
|
|||||||
echo "Ignoring known MySQL mismatch: ChannelMembers.SchemeGuest"
|
echo "Ignoring known MySQL mismatch: ChannelMembers.SchemeGuest"
|
||||||
docker-compose --no-ansi exec -T mysql mysql -D migrated -uroot -pmostest -e "ALTER TABLE ChannelMembers DROP COLUMN SchemeGuest;"
|
docker-compose --no-ansi exec -T mysql mysql -D migrated -uroot -pmostest -e "ALTER TABLE ChannelMembers DROP COLUMN SchemeGuest;"
|
||||||
docker-compose --no-ansi exec -T mysql mysql -D latest -uroot -pmostest -e "ALTER TABLE ChannelMembers DROP COLUMN SchemeGuest;"
|
docker-compose --no-ansi exec -T mysql mysql -D latest -uroot -pmostest -e "ALTER TABLE ChannelMembers DROP COLUMN SchemeGuest;"
|
||||||
echo "Ignoring known MySQL mismatch: ChannelMembers.MentionCountRoot"
|
echo "Ignoring known MySQL mismatch: ChannelMembers.MentionCountRoot and MsgCountRoot"
|
||||||
|
docker-compose --no-ansi exec -T mysql mysql -D migrated -uroot -pmostest -e "ALTER TABLE ChannelMembers DROP COLUMN MentionCountRoot;"
|
||||||
|
docker-compose --no-ansi exec -T mysql mysql -D latest -uroot -pmostest -e "ALTER TABLE ChannelMembers DROP COLUMN MentionCountRoot;"
|
||||||
docker-compose --no-ansi exec -T mysql mysql -D migrated -uroot -pmostest -e "ALTER TABLE ChannelMembers DROP COLUMN MsgCountRoot;"
|
docker-compose --no-ansi exec -T mysql mysql -D migrated -uroot -pmostest -e "ALTER TABLE ChannelMembers DROP COLUMN MsgCountRoot;"
|
||||||
docker-compose --no-ansi exec -T mysql mysql -D latest -uroot -pmostest -e "ALTER TABLE ChannelMembers DROP COLUMN MsgCountRoot;"
|
docker-compose --no-ansi exec -T mysql mysql -D latest -uroot -pmostest -e "ALTER TABLE ChannelMembers DROP COLUMN MsgCountRoot;"
|
||||||
echo "Ignoring known MySQL mismatch: Channels.TotalMsgCountRoot"
|
echo "Ignoring known MySQL mismatch: Channels.TotalMsgCountRoot"
|
||||||
|
|||||||
@@ -2152,6 +2152,7 @@ func TestViewChannel(t *testing.T) {
|
|||||||
CheckNoError(t, resp)
|
CheckNoError(t, resp)
|
||||||
require.Equal(t, channel.TotalMsgCount, member.MsgCount, "should match message counts")
|
require.Equal(t, channel.TotalMsgCount, member.MsgCount, "should match message counts")
|
||||||
require.Equal(t, int64(0), member.MentionCount, "should have no mentions")
|
require.Equal(t, int64(0), member.MentionCount, "should have no mentions")
|
||||||
|
require.Equal(t, int64(0), member.MentionCountRoot, "should have no mentions")
|
||||||
|
|
||||||
_, resp = Client.ViewChannel("junk", view)
|
_, resp = Client.ViewChannel("junk", view)
|
||||||
CheckBadRequestStatus(t, resp)
|
CheckBadRequestStatus(t, resp)
|
||||||
@@ -4064,3 +4065,43 @@ func TestMoveChannel(t *testing.T) {
|
|||||||
require.Equal(t, team2.Id, newChannel.TeamId)
|
require.Equal(t, team2.Id, newChannel.TeamId)
|
||||||
}, "Should be able to (force) move private channel by a member that is not member of target team")
|
}, "Should be able to (force) move private channel by a member that is not member of target team")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRootMentionsCount(t *testing.T) {
|
||||||
|
th := Setup(t).InitBasic()
|
||||||
|
defer th.TearDown()
|
||||||
|
Client := th.Client
|
||||||
|
user := th.BasicUser
|
||||||
|
channel := th.BasicChannel
|
||||||
|
|
||||||
|
// initially, MentionCountRoot is 0 in the database
|
||||||
|
channelMember, err := th.App.Srv().Store.Channel().GetMember(context.Background(), channel.Id, user.Id)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, int64(0), channelMember.MentionCountRoot)
|
||||||
|
require.Equal(t, int64(0), channelMember.MentionCount)
|
||||||
|
|
||||||
|
// mention the user in a root post
|
||||||
|
post1, resp := th.SystemAdminClient.CreatePost(&model.Post{ChannelId: channel.Id, Message: "hey @" + user.Username})
|
||||||
|
CheckNoError(t, resp)
|
||||||
|
// mention the user in a reply post
|
||||||
|
post2 := &model.Post{ChannelId: channel.Id, Message: "reply at @" + user.Username, RootId: post1.Id}
|
||||||
|
_, resp = th.SystemAdminClient.CreatePost(post2)
|
||||||
|
CheckNoError(t, resp)
|
||||||
|
|
||||||
|
// this should perform lazy migration and populate the field
|
||||||
|
channelUnread, resp := Client.GetChannelUnread(channel.Id, user.Id)
|
||||||
|
CheckNoError(t, resp)
|
||||||
|
// reply post is not counted, so we should have one root mention
|
||||||
|
require.EqualValues(t, int64(1), channelUnread.MentionCountRoot)
|
||||||
|
// regular count stays the same
|
||||||
|
require.Equal(t, int64(2), channelUnread.MentionCount)
|
||||||
|
// validate that DB is updated
|
||||||
|
channelMember, err = th.App.Srv().Store.Channel().GetMember(context.Background(), channel.Id, user.Id)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.EqualValues(t, int64(1), channelMember.MentionCountRoot)
|
||||||
|
|
||||||
|
// validate that Team level counts are calculated
|
||||||
|
counts, appErr := th.App.GetTeamUnread(channel.TeamId, user.Id)
|
||||||
|
require.Nil(t, appErr)
|
||||||
|
require.Equal(t, int64(1), counts.MentionCountRoot)
|
||||||
|
require.Equal(t, int64(2), counts.MentionCount)
|
||||||
|
}
|
||||||
|
|||||||
21
api4/user.go
21
api4/user.go
@@ -94,7 +94,6 @@ func (api *API) InitUser() {
|
|||||||
|
|
||||||
api.BaseRoutes.UserThreads.Handle("", api.ApiSessionRequired(getThreadsForUser)).Methods("GET")
|
api.BaseRoutes.UserThreads.Handle("", api.ApiSessionRequired(getThreadsForUser)).Methods("GET")
|
||||||
api.BaseRoutes.UserThreads.Handle("/read", api.ApiSessionRequired(updateReadStateAllThreadsByUser)).Methods("PUT")
|
api.BaseRoutes.UserThreads.Handle("/read", api.ApiSessionRequired(updateReadStateAllThreadsByUser)).Methods("PUT")
|
||||||
api.BaseRoutes.UserThreads.Handle("/mention_counts", api.ApiSessionRequired(getMentionCountsForAllThreadsByUser)).Methods("GET")
|
|
||||||
|
|
||||||
api.BaseRoutes.UserThread.Handle("", api.ApiSessionRequired(getThreadForUser)).Methods("GET")
|
api.BaseRoutes.UserThread.Handle("", api.ApiSessionRequired(getThreadForUser)).Methods("GET")
|
||||||
api.BaseRoutes.UserThread.Handle("/following", api.ApiSessionRequired(followThreadByUser)).Methods("PUT")
|
api.BaseRoutes.UserThread.Handle("/following", api.ApiSessionRequired(followThreadByUser)).Methods("PUT")
|
||||||
@@ -2871,26 +2870,6 @@ func getThreadForUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
w.Write([]byte(threads.ToJson()))
|
w.Write([]byte(threads.ToJson()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func getMentionCountsForAllThreadsByUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
|
||||||
c.RequireUserId().RequireTeamId()
|
|
||||||
if c.Err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !c.App.SessionHasPermissionToUser(*c.App.Session(), c.Params.UserId) {
|
|
||||||
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
counts, err := c.App.GetThreadMentionsForUserPerChannel(c.Params.UserId, c.Params.TeamId)
|
|
||||||
if err != nil {
|
|
||||||
c.Err = err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
resp, _ := json.Marshal(counts)
|
|
||||||
|
|
||||||
w.Write(resp)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getThreadsForUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
func getThreadsForUser(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||||
c.RequireUserId().RequireTeamId()
|
c.RequireUserId().RequireTeamId()
|
||||||
if c.Err != nil {
|
if c.Err != nil {
|
||||||
|
|||||||
@@ -5840,11 +5840,6 @@ func TestMaintainUnreadMentionsInThread(t *testing.T) {
|
|||||||
*cfg.ServiceSettings.ThreadAutoFollow = true
|
*cfg.ServiceSettings.ThreadAutoFollow = true
|
||||||
*cfg.ServiceSettings.CollapsedThreads = model.COLLAPSED_THREADS_DEFAULT_ON
|
*cfg.ServiceSettings.CollapsedThreads = model.COLLAPSED_THREADS_DEFAULT_ON
|
||||||
})
|
})
|
||||||
checkMentionCounts := func(client *model.Client4, userId string, expected map[string]int64) {
|
|
||||||
actual, resp2 := client.GetThreadMentionsForUserPerChannel(userId, th.BasicTeam.Id)
|
|
||||||
CheckNoError(t, resp2)
|
|
||||||
require.EqualValues(t, expected, actual)
|
|
||||||
}
|
|
||||||
checkThreadList := func(client *model.Client4, userId string, expectedMentions, expectedThreads int) (*model.Threads, *model.Response) {
|
checkThreadList := func(client *model.Client4, userId string, expectedMentions, expectedThreads int) (*model.Threads, *model.Response) {
|
||||||
uss, resp := client.GetUserThreads(userId, th.BasicTeam.Id, model.GetUserThreadsOpts{
|
uss, resp := client.GetUserThreads(userId, th.BasicTeam.Id, model.GetUserThreadsOpts{
|
||||||
Deleted: false,
|
Deleted: false,
|
||||||
@@ -5870,7 +5865,6 @@ func TestMaintainUnreadMentionsInThread(t *testing.T) {
|
|||||||
// create reply and mention the original poster and another user
|
// create reply and mention the original poster and another user
|
||||||
postAndCheck(t, th.SystemAdminClient, &model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply @" + th.BasicUser.Username + " and @" + th.BasicUser2.Username, RootId: rpost.Id})
|
postAndCheck(t, th.SystemAdminClient, &model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply @" + th.BasicUser.Username + " and @" + th.BasicUser2.Username, RootId: rpost.Id})
|
||||||
|
|
||||||
checkMentionCounts(Client, th.BasicUser.Id, map[string]int64{th.BasicChannel.Id: 1})
|
|
||||||
// basic user 1 was mentioned 1 time
|
// basic user 1 was mentioned 1 time
|
||||||
checkThreadList(th.Client, th.BasicUser.Id, 1, 1)
|
checkThreadList(th.Client, th.BasicUser.Id, 1, 1)
|
||||||
// basic user 2 was mentioned 1 time
|
// basic user 2 was mentioned 1 time
|
||||||
@@ -5899,7 +5893,6 @@ func TestMaintainUnreadMentionsInThread(t *testing.T) {
|
|||||||
postAndCheck(t, th.SystemAdminClient, &model.Post{ChannelId: dm.Id, Message: "msg2", RootId: dm_root_post.Id})
|
postAndCheck(t, th.SystemAdminClient, &model.Post{ChannelId: dm.Id, Message: "msg2", RootId: dm_root_post.Id})
|
||||||
// expect increment by two mentions
|
// expect increment by two mentions
|
||||||
checkThreadList(th.Client, th.BasicUser.Id, 3, 2)
|
checkThreadList(th.Client, th.BasicUser.Id, 3, 2)
|
||||||
checkMentionCounts(Client, th.BasicUser.Id, map[string]int64{th.BasicChannel.Id: 1, dm.Id: 2})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReadThreads(t *testing.T) {
|
func TestReadThreads(t *testing.T) {
|
||||||
|
|||||||
@@ -704,7 +704,6 @@ type AppIface interface {
|
|||||||
GetTermsOfService(id string) (*model.TermsOfService, *model.AppError)
|
GetTermsOfService(id string) (*model.TermsOfService, *model.AppError)
|
||||||
GetThreadForUser(userID, teamID, threadId string, extended bool) (*model.ThreadResponse, *model.AppError)
|
GetThreadForUser(userID, teamID, threadId string, extended bool) (*model.ThreadResponse, *model.AppError)
|
||||||
GetThreadMembershipsForUser(userID, teamID string) ([]*model.ThreadMembership, error)
|
GetThreadMembershipsForUser(userID, teamID string) ([]*model.ThreadMembership, error)
|
||||||
GetThreadMentionsForUserPerChannel(userId, teamId string) (map[string]int64, *model.AppError)
|
|
||||||
GetThreadsForUser(userID, teamID string, options model.GetUserThreadsOpts) (*model.Threads, *model.AppError)
|
GetThreadsForUser(userID, teamID string, options model.GetUserThreadsOpts) (*model.Threads, *model.AppError)
|
||||||
GetUploadSession(uploadId string) (*model.UploadSession, *model.AppError)
|
GetUploadSession(uploadId string) (*model.UploadSession, *model.AppError)
|
||||||
GetUploadSessionsForUser(userID string) ([]*model.UploadSession, *model.AppError)
|
GetUploadSessionsForUser(userID string) ([]*model.UploadSession, *model.AppError)
|
||||||
|
|||||||
@@ -1873,7 +1873,6 @@ func (a *App) GetChannelUnread(channelID, userID string) (*model.ChannelUnread,
|
|||||||
channelUnread.MsgCount = 0
|
channelUnread.MsgCount = 0
|
||||||
channelUnread.MsgCountRoot = 0
|
channelUnread.MsgCountRoot = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
return channelUnread, nil
|
return channelUnread, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2340,7 +2339,7 @@ func (a *App) MarkChannelAsUnreadFromPost(postID string, userID string) (*model.
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
unreadMentions, err := a.countMentionsFromPost(user, post)
|
unreadMentions, unreadMentionsRoot, err := a.countMentionsFromPost(user, post)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -2382,7 +2381,7 @@ func (a *App) MarkChannelAsUnreadFromPost(postID string, userID string) (*model.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
channelUnread, nErr := a.Srv().Store.Channel().UpdateLastViewedAtPost(post, userID, unreadMentions, *a.Config().ServiceSettings.ThreadAutoFollow)
|
channelUnread, nErr := a.Srv().Store.Channel().UpdateLastViewedAtPost(post, userID, unreadMentions, unreadMentionsRoot, *a.Config().ServiceSettings.ThreadAutoFollow)
|
||||||
if nErr != nil {
|
if nErr != nil {
|
||||||
return channelUnread, model.NewAppError("MarkChannelAsUnreadFromPost", "app.channel.update_last_viewed_at_post.app_error", nil, nErr.Error(), http.StatusInternalServerError)
|
return channelUnread, model.NewAppError("MarkChannelAsUnreadFromPost", "app.channel.update_last_viewed_at_post.app_error", nil, nErr.Error(), http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
@@ -2390,6 +2389,7 @@ func (a *App) MarkChannelAsUnreadFromPost(postID string, userID string) (*model.
|
|||||||
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_POST_UNREAD, channelUnread.TeamId, channelUnread.ChannelId, channelUnread.UserId, nil)
|
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_POST_UNREAD, channelUnread.TeamId, channelUnread.ChannelId, channelUnread.UserId, nil)
|
||||||
message.Add("msg_count", channelUnread.MsgCount)
|
message.Add("msg_count", channelUnread.MsgCount)
|
||||||
message.Add("mention_count", channelUnread.MentionCount)
|
message.Add("mention_count", channelUnread.MentionCount)
|
||||||
|
message.Add("mention_count_root", channelUnread.MentionCountRoot)
|
||||||
message.Add("last_viewed_at", channelUnread.LastViewedAt)
|
message.Add("last_viewed_at", channelUnread.LastViewedAt)
|
||||||
message.Add("post_id", postID)
|
message.Add("post_id", postID)
|
||||||
a.Publish(message)
|
a.Publish(message)
|
||||||
|
|||||||
@@ -1343,15 +1343,24 @@ func TestMarkChannelAsUnreadFromPost(t *testing.T) {
|
|||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
th.CreatePost(c2)
|
th.CreatePost(c2)
|
||||||
|
|
||||||
|
th.App.CreatePost(&model.Post{
|
||||||
|
UserId: u2.Id,
|
||||||
|
ChannelId: c2.Id,
|
||||||
|
RootId: p4.Id,
|
||||||
|
Message: "@" + u1.Username,
|
||||||
|
}, c2, false, true)
|
||||||
|
|
||||||
response, err := th.App.MarkChannelAsUnreadFromPost(p4.Id, u1.Id)
|
response, err := th.App.MarkChannelAsUnreadFromPost(p4.Id, u1.Id)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, int64(1), response.MsgCount)
|
assert.Equal(t, int64(1), response.MsgCount)
|
||||||
assert.Equal(t, int64(1), response.MentionCount)
|
assert.Equal(t, int64(2), response.MentionCount)
|
||||||
|
assert.Equal(t, int64(1), response.MentionCountRoot)
|
||||||
|
|
||||||
unread, err := th.App.GetChannelUnread(c2.Id, u1.Id)
|
unread, err := th.App.GetChannelUnread(c2.Id, u1.Id)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
assert.Equal(t, int64(1), unread.MsgCount)
|
assert.Equal(t, int64(2), unread.MsgCount)
|
||||||
assert.Equal(t, int64(1), unread.MentionCount)
|
assert.Equal(t, int64(2), unread.MentionCount)
|
||||||
|
assert.Equal(t, int64(1), unread.MentionCountRoot)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Unread on a DM channel", func(t *testing.T) {
|
t.Run("Unread on a DM channel", func(t *testing.T) {
|
||||||
@@ -1361,15 +1370,20 @@ func TestMarkChannelAsUnreadFromPost(t *testing.T) {
|
|||||||
th.CreatePost(dc)
|
th.CreatePost(dc)
|
||||||
th.CreatePost(dc)
|
th.CreatePost(dc)
|
||||||
|
|
||||||
|
_, err := th.App.CreatePost(&model.Post{ChannelId: dc.Id, UserId: th.BasicUser.Id, Message: "testReply", RootId: dm1.Id}, dc, false, false)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
response, err := th.App.MarkChannelAsUnreadFromPost(dm1.Id, u2.Id)
|
response, err := th.App.MarkChannelAsUnreadFromPost(dm1.Id, u2.Id)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, int64(0), response.MsgCount)
|
assert.Equal(t, int64(0), response.MsgCount)
|
||||||
assert.Equal(t, int64(3), response.MentionCount)
|
assert.Equal(t, int64(4), response.MentionCount)
|
||||||
|
assert.Equal(t, int64(3), response.MentionCountRoot)
|
||||||
|
|
||||||
unread, err := th.App.GetChannelUnread(dc.Id, u2.Id)
|
unread, err := th.App.GetChannelUnread(dc.Id, u2.Id)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
assert.Equal(t, int64(3), unread.MsgCount)
|
assert.Equal(t, int64(4), unread.MsgCount)
|
||||||
assert.Equal(t, int64(3), unread.MentionCount)
|
assert.Equal(t, int64(4), unread.MentionCount)
|
||||||
|
assert.Equal(t, int64(3), unread.MentionCountRoot)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Can't unread an imaginary post", func(t *testing.T) {
|
t.Run("Can't unread an imaginary post", func(t *testing.T) {
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ func (a *App) SendNotifications(post *model.Post, team *model.Team, channel *mod
|
|||||||
umc := make(chan *model.AppError, 1)
|
umc := make(chan *model.AppError, 1)
|
||||||
go func(userID string) {
|
go func(userID string) {
|
||||||
defer close(umc)
|
defer close(umc)
|
||||||
nErr := a.Srv().Store.Channel().IncrementMentionCount(post.ChannelId, userID, *a.Config().ServiceSettings.ThreadAutoFollow)
|
nErr := a.Srv().Store.Channel().IncrementMentionCount(post.ChannelId, userID, *a.Config().ServiceSettings.ThreadAutoFollow, post.RootId == "")
|
||||||
if nErr != nil {
|
if nErr != nil {
|
||||||
umc <- model.NewAppError("SendNotifications", "app.channel.increment_mention_count.app_error", nil, nErr.Error(), http.StatusInternalServerError)
|
umc <- model.NewAppError("SendNotifications", "app.channel.increment_mention_count.app_error", nil, nErr.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -8650,28 +8650,6 @@ func (a *OpenTracingAppLayer) GetThreadMembershipsForUser(userID string, teamID
|
|||||||
return resultVar0, resultVar1
|
return resultVar0, resultVar1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *OpenTracingAppLayer) GetThreadMentionsForUserPerChannel(userId string, teamId string) (map[string]int64, *model.AppError) {
|
|
||||||
origCtx := a.ctx
|
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetThreadMentionsForUserPerChannel")
|
|
||||||
|
|
||||||
a.ctx = newCtx
|
|
||||||
a.app.Srv().Store.SetContext(newCtx)
|
|
||||||
defer func() {
|
|
||||||
a.app.Srv().Store.SetContext(origCtx)
|
|
||||||
a.ctx = origCtx
|
|
||||||
}()
|
|
||||||
|
|
||||||
defer span.Finish()
|
|
||||||
resultVar0, resultVar1 := a.app.GetThreadMentionsForUserPerChannel(userId, teamId)
|
|
||||||
|
|
||||||
if resultVar1 != nil {
|
|
||||||
span.LogFields(spanlog.Error(resultVar1))
|
|
||||||
ext.Error.Set(span, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
return resultVar0, resultVar1
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *OpenTracingAppLayer) GetThreadsForUser(userID string, teamID string, options model.GetUserThreadsOpts) (*model.Threads, *model.AppError) {
|
func (a *OpenTracingAppLayer) GetThreadsForUser(userID string, teamID string, options model.GetUserThreadsOpts) (*model.Threads, *model.AppError) {
|
||||||
origCtx := a.ctx
|
origCtx := a.ctx
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetThreadsForUser")
|
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetThreadsForUser")
|
||||||
|
|||||||
26
app/post.go
26
app/post.go
@@ -1403,25 +1403,25 @@ func (a *App) countThreadMentions(user *model.User, post *model.Post, teamID str
|
|||||||
|
|
||||||
// countMentionsFromPost returns the number of posts in the post's channel that mention the user after and including the
|
// countMentionsFromPost returns the number of posts in the post's channel that mention the user after and including the
|
||||||
// given post.
|
// given post.
|
||||||
func (a *App) countMentionsFromPost(user *model.User, post *model.Post) (int, *model.AppError) {
|
func (a *App) countMentionsFromPost(user *model.User, post *model.Post) (int, int, *model.AppError) {
|
||||||
channel, err := a.GetChannel(post.ChannelId)
|
channel, err := a.GetChannel(post.ChannelId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if channel.Type == model.CHANNEL_DIRECT {
|
if channel.Type == model.CHANNEL_DIRECT {
|
||||||
// In a DM channel, every post made by the other user is a mention
|
// In a DM channel, every post made by the other user is a mention
|
||||||
count, _, nErr := a.Srv().Store.Channel().CountPostsAfter(post.ChannelId, post.CreateAt-1, channel.GetOtherUserIdForDM(user.Id))
|
count, countRoot, nErr := a.Srv().Store.Channel().CountPostsAfter(post.ChannelId, post.CreateAt-1, channel.GetOtherUserIdForDM(user.Id))
|
||||||
if nErr != nil {
|
if nErr != nil {
|
||||||
return 0, model.NewAppError("countMentionsFromPost", "app.channel.count_posts_since.app_error", nil, nErr.Error(), http.StatusInternalServerError)
|
return 0, 0, model.NewAppError("countMentionsFromPost", "app.channel.count_posts_since.app_error", nil, nErr.Error(), http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
return count, nil
|
return count, countRoot, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
channelMember, err := a.GetChannelMember(context.Background(), channel.Id, user.Id)
|
channelMember, err := a.GetChannelMember(context.Background(), channel.Id, user.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
keywords := addMentionKeywordsForUser(
|
keywords := addMentionKeywordsForUser(
|
||||||
@@ -1439,13 +1439,16 @@ func (a *App) countMentionsFromPost(user *model.User, post *model.Post) (int, *m
|
|||||||
|
|
||||||
thread, err := a.GetPostThread(post.Id, false, false, false, user.Id)
|
thread, err := a.GetPostThread(post.Id, false, false, false, user.Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
count := 0
|
count := 0
|
||||||
|
countRoot := 0
|
||||||
if isPostMention(user, post, keywords, thread.Posts, mentionedByThread, checkForCommentMentions) {
|
if isPostMention(user, post, keywords, thread.Posts, mentionedByThread, checkForCommentMentions) {
|
||||||
count += 1
|
count += 1
|
||||||
|
if post.RootId == "" {
|
||||||
|
countRoot += 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
page := 0
|
page := 0
|
||||||
@@ -1458,12 +1461,15 @@ func (a *App) countMentionsFromPost(user *model.User, post *model.Post) (int, *m
|
|||||||
PerPage: perPage,
|
PerPage: perPage,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, postID := range postList.Order {
|
for _, postID := range postList.Order {
|
||||||
if isPostMention(user, postList.Posts[postID], keywords, postList.Posts, mentionedByThread, checkForCommentMentions) {
|
if isPostMention(user, postList.Posts[postID], keywords, postList.Posts, mentionedByThread, checkForCommentMentions) {
|
||||||
count += 1
|
count += 1
|
||||||
|
if postList.Posts[postID].RootId == "" {
|
||||||
|
countRoot += 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1474,7 +1480,7 @@ func (a *App) countMentionsFromPost(user *model.User, post *model.Post) (int, *m
|
|||||||
page += 1
|
page += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
return count, nil
|
return count, countRoot, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func isCommentMention(user *model.User, post *model.Post, otherPosts map[string]*model.Post, mentionedByThread map[string]bool) bool {
|
func isCommentMention(user *model.User, post *model.Post, otherPosts map[string]*model.Post, mentionedByThread map[string]bool) bool {
|
||||||
|
|||||||
@@ -1231,7 +1231,7 @@ func TestCountMentionsFromPost(t *testing.T) {
|
|||||||
}, channel, false, true)
|
}, channel, false, true)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
count, err := th.App.countMentionsFromPost(user2, post1)
|
count, _, err := th.App.countMentionsFromPost(user2, post1)
|
||||||
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 0, count)
|
assert.Equal(t, 0, count)
|
||||||
@@ -1270,7 +1270,7 @@ func TestCountMentionsFromPost(t *testing.T) {
|
|||||||
|
|
||||||
// post1 and post3 should mention the user
|
// post1 and post3 should mention the user
|
||||||
|
|
||||||
count, err := th.App.countMentionsFromPost(user2, post1)
|
count, _, err := th.App.countMentionsFromPost(user2, post1)
|
||||||
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 2, count)
|
assert.Equal(t, 2, count)
|
||||||
@@ -1309,7 +1309,7 @@ func TestCountMentionsFromPost(t *testing.T) {
|
|||||||
|
|
||||||
// post2 and post3 should mention the user
|
// post2 and post3 should mention the user
|
||||||
|
|
||||||
count, err := th.App.countMentionsFromPost(user2, post1)
|
count, _, err := th.App.countMentionsFromPost(user2, post1)
|
||||||
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 2, count)
|
assert.Equal(t, 2, count)
|
||||||
@@ -1346,7 +1346,7 @@ func TestCountMentionsFromPost(t *testing.T) {
|
|||||||
}, channel, false, true)
|
}, channel, false, true)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
count, err := th.App.countMentionsFromPost(user2, post1)
|
count, _, err := th.App.countMentionsFromPost(user2, post1)
|
||||||
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 0, count)
|
assert.Equal(t, 0, count)
|
||||||
@@ -1388,7 +1388,7 @@ func TestCountMentionsFromPost(t *testing.T) {
|
|||||||
}, channel, false, true)
|
}, channel, false, true)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
count, err := th.App.countMentionsFromPost(user2, post1)
|
count, _, err := th.App.countMentionsFromPost(user2, post1)
|
||||||
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 0, count)
|
assert.Equal(t, 0, count)
|
||||||
@@ -1442,7 +1442,7 @@ func TestCountMentionsFromPost(t *testing.T) {
|
|||||||
|
|
||||||
// post2 should mention the user
|
// post2 should mention the user
|
||||||
|
|
||||||
count, err := th.App.countMentionsFromPost(user2, post1)
|
count, _, err := th.App.countMentionsFromPost(user2, post1)
|
||||||
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 1, count)
|
assert.Equal(t, 1, count)
|
||||||
@@ -1496,7 +1496,7 @@ func TestCountMentionsFromPost(t *testing.T) {
|
|||||||
|
|
||||||
// post2 and post5 should mention the user
|
// post2 and post5 should mention the user
|
||||||
|
|
||||||
count, err := th.App.countMentionsFromPost(user2, post1)
|
count, _, err := th.App.countMentionsFromPost(user2, post1)
|
||||||
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 2, count)
|
assert.Equal(t, 2, count)
|
||||||
@@ -1545,7 +1545,7 @@ func TestCountMentionsFromPost(t *testing.T) {
|
|||||||
|
|
||||||
// should be mentioned by post2 and post3
|
// should be mentioned by post2 and post3
|
||||||
|
|
||||||
count, err := th.App.countMentionsFromPost(user2, post1)
|
count, _, err := th.App.countMentionsFromPost(user2, post1)
|
||||||
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 2, count)
|
assert.Equal(t, 2, count)
|
||||||
@@ -1575,12 +1575,12 @@ func TestCountMentionsFromPost(t *testing.T) {
|
|||||||
}, channel, false, true)
|
}, channel, false, true)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
count, err := th.App.countMentionsFromPost(user2, post1)
|
count, _, err := th.App.countMentionsFromPost(user2, post1)
|
||||||
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 2, count)
|
assert.Equal(t, 2, count)
|
||||||
|
|
||||||
count, err = th.App.countMentionsFromPost(user1, post1)
|
count, _, err = th.App.countMentionsFromPost(user1, post1)
|
||||||
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 0, count)
|
assert.Equal(t, 0, count)
|
||||||
@@ -1617,7 +1617,7 @@ func TestCountMentionsFromPost(t *testing.T) {
|
|||||||
|
|
||||||
// post1 and post3 should mention the user, but we only count post3
|
// post1 and post3 should mention the user, but we only count post3
|
||||||
|
|
||||||
count, err := th.App.countMentionsFromPost(user2, post2)
|
count, _, err := th.App.countMentionsFromPost(user2, post2)
|
||||||
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 1, count)
|
assert.Equal(t, 1, count)
|
||||||
@@ -1648,7 +1648,7 @@ func TestCountMentionsFromPost(t *testing.T) {
|
|||||||
|
|
||||||
// post2 should mention the user
|
// post2 should mention the user
|
||||||
|
|
||||||
count, err := th.App.countMentionsFromPost(user2, post1)
|
count, _, err := th.App.countMentionsFromPost(user2, post1)
|
||||||
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 1, count)
|
assert.Equal(t, 1, count)
|
||||||
@@ -1695,7 +1695,7 @@ func TestCountMentionsFromPost(t *testing.T) {
|
|||||||
|
|
||||||
// post4 should mention the user
|
// post4 should mention the user
|
||||||
|
|
||||||
count, err := th.App.countMentionsFromPost(user2, post3)
|
count, _, err := th.App.countMentionsFromPost(user2, post3)
|
||||||
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 1, count)
|
assert.Equal(t, 1, count)
|
||||||
@@ -1735,7 +1735,7 @@ func TestCountMentionsFromPost(t *testing.T) {
|
|||||||
|
|
||||||
// post3 should mention the user
|
// post3 should mention the user
|
||||||
|
|
||||||
count, err := th.App.countMentionsFromPost(user2, post1)
|
count, _, err := th.App.countMentionsFromPost(user2, post1)
|
||||||
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 1, count)
|
assert.Equal(t, 1, count)
|
||||||
@@ -1771,7 +1771,7 @@ func TestCountMentionsFromPost(t *testing.T) {
|
|||||||
|
|
||||||
// Every post should mention the user
|
// Every post should mention the user
|
||||||
|
|
||||||
count, err := th.App.countMentionsFromPost(user2, post1)
|
count, _, err := th.App.countMentionsFromPost(user2, post1)
|
||||||
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, numPosts, count)
|
assert.Equal(t, numPosts, count)
|
||||||
|
|||||||
21
app/team.go
21
app/team.go
@@ -1139,14 +1139,15 @@ func (a *App) GetTeamUnread(teamID, userID string) (*model.TeamUnread, *model.Ap
|
|||||||
}
|
}
|
||||||
|
|
||||||
var teamUnread = &model.TeamUnread{
|
var teamUnread = &model.TeamUnread{
|
||||||
MsgCount: 0,
|
MsgCount: 0,
|
||||||
MsgCountRoot: 0,
|
MentionCount: 0,
|
||||||
MentionCount: 0,
|
MentionCountRoot: 0,
|
||||||
TeamId: teamID,
|
MsgCountRoot: 0,
|
||||||
|
TeamId: teamID,
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, cu := range channelUnreads {
|
for _, cu := range channelUnreads {
|
||||||
teamUnread.MentionCount += cu.MentionCount
|
teamUnread.MentionCount += cu.MentionCount
|
||||||
|
teamUnread.MentionCountRoot += cu.MentionCountRoot
|
||||||
|
|
||||||
if cu.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] != model.CHANNEL_MARK_UNREAD_MENTION {
|
if cu.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] != model.CHANNEL_MARK_UNREAD_MENTION {
|
||||||
teamUnread.MsgCount += cu.MsgCount
|
teamUnread.MsgCount += cu.MsgCount
|
||||||
@@ -1677,6 +1678,7 @@ func (a *App) GetTeamsUnreadForUser(excludeTeamId string, userID string) ([]*mod
|
|||||||
|
|
||||||
unreads := func(cu *model.ChannelUnread, tu *model.TeamUnread) *model.TeamUnread {
|
unreads := func(cu *model.ChannelUnread, tu *model.TeamUnread) *model.TeamUnread {
|
||||||
tu.MentionCount += cu.MentionCount
|
tu.MentionCount += cu.MentionCount
|
||||||
|
tu.MentionCountRoot += cu.MentionCountRoot
|
||||||
|
|
||||||
if cu.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] != model.CHANNEL_MARK_UNREAD_MENTION {
|
if cu.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] != model.CHANNEL_MARK_UNREAD_MENTION {
|
||||||
tu.MsgCount += cu.MsgCount
|
tu.MsgCount += cu.MsgCount
|
||||||
@@ -1692,10 +1694,11 @@ func (a *App) GetTeamsUnreadForUser(excludeTeamId string, userID string) ([]*mod
|
|||||||
membersMap[id] = unreads(data[i], mu)
|
membersMap[id] = unreads(data[i], mu)
|
||||||
} else {
|
} else {
|
||||||
membersMap[id] = unreads(data[i], &model.TeamUnread{
|
membersMap[id] = unreads(data[i], &model.TeamUnread{
|
||||||
MsgCount: 0,
|
MsgCount: 0,
|
||||||
MsgCountRoot: 0,
|
MentionCount: 0,
|
||||||
MentionCount: 0,
|
MentionCountRoot: 0,
|
||||||
TeamId: id,
|
MsgCountRoot: 0,
|
||||||
|
TeamId: id,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2401,14 +2401,6 @@ func (a *App) GetThreadsForUser(userID, teamID string, options model.GetUserThre
|
|||||||
return threads, nil
|
return threads, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) GetThreadMentionsForUserPerChannel(userId, teamId string) (map[string]int64, *model.AppError) {
|
|
||||||
res, err := a.Srv().Store.Thread().GetThreadMentionsForUserPerChannel(userId, teamId)
|
|
||||||
if err != nil {
|
|
||||||
return nil, model.NewAppError("GetThreadMentionsForUserPerChannel", "app.user.get_threads_for_user.app_error", nil, err.Error(), http.StatusInternalServerError)
|
|
||||||
}
|
|
||||||
return res, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) GetThreadForUser(userID, teamID, threadId string, extended bool) (*model.ThreadResponse, *model.AppError) {
|
func (a *App) GetThreadForUser(userID, teamID, threadId string, extended bool) (*model.ThreadResponse, *model.AppError) {
|
||||||
thread, err := a.Srv().Store.Thread().GetThreadForUser(userID, teamID, threadId, extended)
|
thread, err := a.Srv().Store.Thread().GetThreadForUser(userID, teamID, threadId, extended)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -24,39 +24,42 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ChannelUnread struct {
|
type ChannelUnread struct {
|
||||||
TeamId string `json:"team_id"`
|
TeamId string `json:"team_id"`
|
||||||
ChannelId string `json:"channel_id"`
|
ChannelId string `json:"channel_id"`
|
||||||
MsgCount int64 `json:"msg_count"`
|
MsgCount int64 `json:"msg_count"`
|
||||||
MsgCountRoot int64 `json:"msg_count_root"`
|
MentionCount int64 `json:"mention_count"`
|
||||||
MentionCount int64 `json:"mention_count"`
|
MentionCountRoot int64 `json:"mention_count_root"`
|
||||||
NotifyProps StringMap `json:"-"`
|
MsgCountRoot int64 `json:"msg_count_root"`
|
||||||
|
NotifyProps StringMap `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChannelUnreadAt struct {
|
type ChannelUnreadAt struct {
|
||||||
TeamId string `json:"team_id"`
|
TeamId string `json:"team_id"`
|
||||||
UserId string `json:"user_id"`
|
UserId string `json:"user_id"`
|
||||||
ChannelId string `json:"channel_id"`
|
ChannelId string `json:"channel_id"`
|
||||||
MsgCount int64 `json:"msg_count"`
|
MsgCount int64 `json:"msg_count"`
|
||||||
MsgCountRoot int64 `json:"msg_count_root"`
|
MentionCount int64 `json:"mention_count"`
|
||||||
MentionCount int64 `json:"mention_count"`
|
MentionCountRoot int64 `json:"mention_count_root"`
|
||||||
LastViewedAt int64 `json:"last_viewed_at"`
|
MsgCountRoot int64 `json:"msg_count_root"`
|
||||||
NotifyProps StringMap `json:"-"`
|
LastViewedAt int64 `json:"last_viewed_at"`
|
||||||
|
NotifyProps StringMap `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChannelMember struct {
|
type ChannelMember struct {
|
||||||
ChannelId string `json:"channel_id"`
|
ChannelId string `json:"channel_id"`
|
||||||
UserId string `json:"user_id"`
|
UserId string `json:"user_id"`
|
||||||
Roles string `json:"roles"`
|
Roles string `json:"roles"`
|
||||||
LastViewedAt int64 `json:"last_viewed_at"`
|
LastViewedAt int64 `json:"last_viewed_at"`
|
||||||
MsgCount int64 `json:"msg_count"`
|
MsgCount int64 `json:"msg_count"`
|
||||||
MentionCount int64 `json:"mention_count"`
|
MentionCount int64 `json:"mention_count"`
|
||||||
NotifyProps StringMap `json:"notify_props"`
|
MentionCountRoot int64 `json:"mention_count_root"`
|
||||||
LastUpdateAt int64 `json:"last_update_at"`
|
MsgCountRoot int64 `json:"msg_count_root"`
|
||||||
SchemeGuest bool `json:"scheme_guest"`
|
NotifyProps StringMap `json:"notify_props"`
|
||||||
SchemeUser bool `json:"scheme_user"`
|
LastUpdateAt int64 `json:"last_update_at"`
|
||||||
SchemeAdmin bool `json:"scheme_admin"`
|
SchemeGuest bool `json:"scheme_guest"`
|
||||||
ExplicitRoles string `json:"explicit_roles"`
|
SchemeUser bool `json:"scheme_user"`
|
||||||
MsgCountRoot int64 `json:"msg_count_root"`
|
SchemeAdmin bool `json:"scheme_admin"`
|
||||||
|
ExplicitRoles string `json:"explicit_roles"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChannelMembers []ChannelMember
|
type ChannelMembers []ChannelMember
|
||||||
|
|||||||
@@ -5885,20 +5885,6 @@ func (c *Client4) DownloadExport(name string, wr io.Writer, offset int64) (int64
|
|||||||
return n, BuildResponse(r)
|
return n, BuildResponse(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client4) GetThreadMentionsForUserPerChannel(userId, teamId string) (map[string]int64, *Response) {
|
|
||||||
url := c.GetUserThreadsRoute(userId, teamId)
|
|
||||||
r, appErr := c.DoApiGet(url+"/mention_counts", "")
|
|
||||||
if appErr != nil {
|
|
||||||
return nil, BuildErrorResponse(r, appErr)
|
|
||||||
}
|
|
||||||
defer closeBody(r)
|
|
||||||
|
|
||||||
var counts map[string]int64
|
|
||||||
json.NewDecoder(r.Body).Decode(&counts)
|
|
||||||
|
|
||||||
return counts, BuildResponse(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client4) GetUserThreads(userId, teamId string, options GetUserThreadsOpts) (*Threads, *Response) {
|
func (c *Client4) GetUserThreads(userId, teamId string, options GetUserThreadsOpts) (*Threads, *Response) {
|
||||||
v := url.Values{}
|
v := url.Values{}
|
||||||
if options.Since != 0 {
|
if options.Since != 0 {
|
||||||
|
|||||||
@@ -31,10 +31,11 @@ type TeamMember struct {
|
|||||||
|
|
||||||
//msgp:ignore TeamUnread
|
//msgp:ignore TeamUnread
|
||||||
type TeamUnread struct {
|
type TeamUnread struct {
|
||||||
TeamId string `json:"team_id"`
|
TeamId string `json:"team_id"`
|
||||||
MsgCount int64 `json:"msg_count"`
|
MsgCount int64 `json:"msg_count"`
|
||||||
MsgCountRoot int64 `json:"msg_count_root"`
|
MentionCount int64 `json:"mention_count"`
|
||||||
MentionCount int64 `json:"mention_count"`
|
MentionCountRoot int64 `json:"mention_count_root"`
|
||||||
|
MsgCountRoot int64 `json:"msg_count_root"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//msgp:ignore TeamMemberForExport
|
//msgp:ignore TeamMemberForExport
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ make ARGS="config set SqlSettings.DataSource 'mmuser:mostest@tcp(localhost:3306)
|
|||||||
echo "Setting up fresh db"
|
echo "Setting up fresh db"
|
||||||
make ARGS="version --config $TMPDIR/config.json" run-cli
|
make ARGS="version --config $TMPDIR/config.json" run-cli
|
||||||
|
|
||||||
for i in "ChannelMembers SchemeGuest" "ChannelMembers MsgCountRoot" "Channels TotalMsgCountRoot"; do
|
for i in "ChannelMembers SchemeGuest" "ChannelMembers MsgCountRoot" "ChannelMembers MentionCountRoot" "Channels TotalMsgCountRoot"; do
|
||||||
a=( $i );
|
a=( $i );
|
||||||
echo "Ignoring known MySQL mismatch: ${a[0]}.${a[1]}"
|
echo "Ignoring known MySQL mismatch: ${a[0]}.${a[1]}"
|
||||||
docker exec mattermost-mysql mysql -D migrated -uroot -pmostest -e "ALTER TABLE ${a[0]} DROP COLUMN ${a[1]};"
|
docker exec mattermost-mysql mysql -D migrated -uroot -pmostest -e "ALTER TABLE ${a[0]} DROP COLUMN ${a[1]};"
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ make ARGS="config set SqlSettings.DataSource 'postgres://mmuser:mostest@localhos
|
|||||||
echo "Setting up fresh db"
|
echo "Setting up fresh db"
|
||||||
make ARGS="version --config $TMPDIR/config.json" run-cli
|
make ARGS="version --config $TMPDIR/config.json" run-cli
|
||||||
|
|
||||||
for i in "ChannelMembers MsgCountRoot" "Channels TotalMsgCountRoot"; do
|
for i in "ChannelMembers MentionCountRoot" "ChannelMembers MsgCountRoot" "Channels TotalMsgCountRoot"; do
|
||||||
a=( $i );
|
a=( $i );
|
||||||
echo "Ignoring known Postgres mismatch: ${a[0]}.${a[1]}"
|
echo "Ignoring known Postgres mismatch: ${a[0]}.${a[1]}"
|
||||||
docker exec mattermost-postgres psql -U mmuser -d migrated -c "ALTER TABLE ${a[0]} DROP COLUMN ${a[1]};"
|
docker exec mattermost-postgres psql -U mmuser -d migrated -c "ALTER TABLE ${a[0]} DROP COLUMN ${a[1]};"
|
||||||
|
|||||||
@@ -1556,7 +1556,7 @@ func (s *OpenTracingLayerChannelStore) GroupSyncedChannelCount() (int64, error)
|
|||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *OpenTracingLayerChannelStore) IncrementMentionCount(channelID string, userId string, updateThreads bool) error {
|
func (s *OpenTracingLayerChannelStore) IncrementMentionCount(channelID string, userId string, updateThreads bool, isRoot bool) error {
|
||||||
origCtx := s.Root.Store.Context()
|
origCtx := s.Root.Store.Context()
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.IncrementMentionCount")
|
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.IncrementMentionCount")
|
||||||
s.Root.Store.SetContext(newCtx)
|
s.Root.Store.SetContext(newCtx)
|
||||||
@@ -1565,7 +1565,7 @@ func (s *OpenTracingLayerChannelStore) IncrementMentionCount(channelID string, u
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
err := s.ChannelStore.IncrementMentionCount(channelID, userId, updateThreads)
|
err := s.ChannelStore.IncrementMentionCount(channelID, userId, updateThreads, isRoot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
span.LogFields(spanlog.Error(err))
|
span.LogFields(spanlog.Error(err))
|
||||||
ext.Error.Set(span, true)
|
ext.Error.Set(span, true)
|
||||||
@@ -2110,7 +2110,7 @@ func (s *OpenTracingLayerChannelStore) UpdateLastViewedAt(channelIds []string, u
|
|||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *OpenTracingLayerChannelStore) UpdateLastViewedAtPost(unreadPost *model.Post, userID string, mentionCount int, updateThreads bool) (*model.ChannelUnreadAt, error) {
|
func (s *OpenTracingLayerChannelStore) UpdateLastViewedAtPost(unreadPost *model.Post, userID string, mentionCount int, mentionCountRoot int, updateThreads bool) (*model.ChannelUnreadAt, error) {
|
||||||
origCtx := s.Root.Store.Context()
|
origCtx := s.Root.Store.Context()
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.UpdateLastViewedAtPost")
|
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ChannelStore.UpdateLastViewedAtPost")
|
||||||
s.Root.Store.SetContext(newCtx)
|
s.Root.Store.SetContext(newCtx)
|
||||||
@@ -2119,7 +2119,7 @@ func (s *OpenTracingLayerChannelStore) UpdateLastViewedAtPost(unreadPost *model.
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
result, err := s.ChannelStore.UpdateLastViewedAtPost(unreadPost, userID, mentionCount, updateThreads)
|
result, err := s.ChannelStore.UpdateLastViewedAtPost(unreadPost, userID, mentionCount, mentionCountRoot, updateThreads)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
span.LogFields(spanlog.Error(err))
|
span.LogFields(spanlog.Error(err))
|
||||||
ext.Error.Set(span, true)
|
ext.Error.Set(span, true)
|
||||||
@@ -7864,24 +7864,6 @@ func (s *OpenTracingLayerThreadStore) GetThreadForUser(userId string, teamId str
|
|||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *OpenTracingLayerThreadStore) GetThreadMentionsForUserPerChannel(userId string, teamId string) (map[string]int64, error) {
|
|
||||||
origCtx := s.Root.Store.Context()
|
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ThreadStore.GetThreadMentionsForUserPerChannel")
|
|
||||||
s.Root.Store.SetContext(newCtx)
|
|
||||||
defer func() {
|
|
||||||
s.Root.Store.SetContext(origCtx)
|
|
||||||
}()
|
|
||||||
|
|
||||||
defer span.Finish()
|
|
||||||
result, err := s.ThreadStore.GetThreadMentionsForUserPerChannel(userId, teamId)
|
|
||||||
if err != nil {
|
|
||||||
span.LogFields(spanlog.Error(err))
|
|
||||||
ext.Error.Set(span, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *OpenTracingLayerThreadStore) GetThreadsForUser(userId string, teamId string, opts model.GetUserThreadsOpts) (*model.Threads, error) {
|
func (s *OpenTracingLayerThreadStore) GetThreadsForUser(userId string, teamId string, opts model.GetUserThreadsOpts) (*model.Threads, error) {
|
||||||
origCtx := s.Root.Store.Context()
|
origCtx := s.Root.Store.Context()
|
||||||
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ThreadStore.GetThreadsForUser")
|
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "ThreadStore.GetThreadsForUser")
|
||||||
|
|||||||
@@ -1690,11 +1690,11 @@ func (s *RetryLayerChannelStore) GroupSyncedChannelCount() (int64, error) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RetryLayerChannelStore) IncrementMentionCount(channelID string, userId string, updateThreads bool) error {
|
func (s *RetryLayerChannelStore) IncrementMentionCount(channelID string, userId string, updateThreads bool, isRoot bool) error {
|
||||||
|
|
||||||
tries := 0
|
tries := 0
|
||||||
for {
|
for {
|
||||||
err := s.ChannelStore.IncrementMentionCount(channelID, userId, updateThreads)
|
err := s.ChannelStore.IncrementMentionCount(channelID, userId, updateThreads, isRoot)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -2238,11 +2238,11 @@ func (s *RetryLayerChannelStore) UpdateLastViewedAt(channelIds []string, userId
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RetryLayerChannelStore) UpdateLastViewedAtPost(unreadPost *model.Post, userID string, mentionCount int, updateThreads bool) (*model.ChannelUnreadAt, error) {
|
func (s *RetryLayerChannelStore) UpdateLastViewedAtPost(unreadPost *model.Post, userID string, mentionCount int, mentionCountRoot int, updateThreads bool) (*model.ChannelUnreadAt, error) {
|
||||||
|
|
||||||
tries := 0
|
tries := 0
|
||||||
for {
|
for {
|
||||||
result, err := s.ChannelStore.UpdateLastViewedAtPost(unreadPost, userID, mentionCount, updateThreads)
|
result, err := s.ChannelStore.UpdateLastViewedAtPost(unreadPost, userID, mentionCount, mentionCountRoot, updateThreads)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
@@ -8538,26 +8538,6 @@ func (s *RetryLayerThreadStore) GetThreadForUser(userId string, teamId string, t
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RetryLayerThreadStore) GetThreadMentionsForUserPerChannel(userId string, teamId string) (map[string]int64, error) {
|
|
||||||
|
|
||||||
tries := 0
|
|
||||||
for {
|
|
||||||
result, err := s.ThreadStore.GetThreadMentionsForUserPerChannel(userId, teamId)
|
|
||||||
if err == nil {
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
if !isRepeatableError(err) {
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
tries++
|
|
||||||
if tries >= 3 {
|
|
||||||
err = errors.Wrap(err, "giving up after 3 consecutive repeatable transaction failures")
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *RetryLayerThreadStore) GetThreadsForUser(userId string, teamId string, opts model.GetUserThreadsOpts) (*model.Threads, error) {
|
func (s *RetryLayerThreadStore) GetThreadsForUser(userId string, teamId string, opts model.GetUserThreadsOpts) (*model.Threads, error) {
|
||||||
|
|
||||||
tries := 0
|
tries := 0
|
||||||
|
|||||||
@@ -39,34 +39,36 @@ type SqlChannelStore struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type channelMember struct {
|
type channelMember struct {
|
||||||
ChannelId string
|
ChannelId string
|
||||||
UserId string
|
UserId string
|
||||||
Roles string
|
Roles string
|
||||||
LastViewedAt int64
|
LastViewedAt int64
|
||||||
MsgCount int64
|
MsgCount int64
|
||||||
MentionCount int64
|
MentionCount int64
|
||||||
NotifyProps model.StringMap
|
NotifyProps model.StringMap
|
||||||
LastUpdateAt int64
|
LastUpdateAt int64
|
||||||
SchemeUser sql.NullBool
|
SchemeUser sql.NullBool
|
||||||
SchemeAdmin sql.NullBool
|
SchemeAdmin sql.NullBool
|
||||||
SchemeGuest sql.NullBool
|
SchemeGuest sql.NullBool
|
||||||
MsgCountRoot int64
|
MentionCountRoot int64
|
||||||
|
MsgCountRoot int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewChannelMemberFromModel(cm *model.ChannelMember) *channelMember {
|
func NewChannelMemberFromModel(cm *model.ChannelMember) *channelMember {
|
||||||
return &channelMember{
|
return &channelMember{
|
||||||
ChannelId: cm.ChannelId,
|
ChannelId: cm.ChannelId,
|
||||||
UserId: cm.UserId,
|
UserId: cm.UserId,
|
||||||
Roles: cm.ExplicitRoles,
|
Roles: cm.ExplicitRoles,
|
||||||
LastViewedAt: cm.LastViewedAt,
|
LastViewedAt: cm.LastViewedAt,
|
||||||
MsgCount: cm.MsgCount,
|
MsgCount: cm.MsgCount,
|
||||||
MsgCountRoot: cm.MsgCountRoot,
|
MentionCount: cm.MentionCount,
|
||||||
MentionCount: cm.MentionCount,
|
MentionCountRoot: cm.MentionCountRoot,
|
||||||
NotifyProps: cm.NotifyProps,
|
MsgCountRoot: cm.MsgCountRoot,
|
||||||
LastUpdateAt: cm.LastUpdateAt,
|
NotifyProps: cm.NotifyProps,
|
||||||
SchemeGuest: sql.NullBool{Valid: true, Bool: cm.SchemeGuest},
|
LastUpdateAt: cm.LastUpdateAt,
|
||||||
SchemeUser: sql.NullBool{Valid: true, Bool: cm.SchemeUser},
|
SchemeGuest: sql.NullBool{Valid: true, Bool: cm.SchemeGuest},
|
||||||
SchemeAdmin: sql.NullBool{Valid: true, Bool: cm.SchemeAdmin},
|
SchemeUser: sql.NullBool{Valid: true, Bool: cm.SchemeUser},
|
||||||
|
SchemeAdmin: sql.NullBool{Valid: true, Bool: cm.SchemeAdmin},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,6 +79,7 @@ type channelMemberWithSchemeRoles struct {
|
|||||||
LastViewedAt int64
|
LastViewedAt int64
|
||||||
MsgCount int64
|
MsgCount int64
|
||||||
MentionCount int64
|
MentionCount int64
|
||||||
|
MentionCountRoot int64
|
||||||
NotifyProps model.StringMap
|
NotifyProps model.StringMap
|
||||||
LastUpdateAt int64
|
LastUpdateAt int64
|
||||||
SchemeGuest sql.NullBool
|
SchemeGuest sql.NullBool
|
||||||
@@ -92,7 +95,7 @@ type channelMemberWithSchemeRoles struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func channelMemberSliceColumns() []string {
|
func channelMemberSliceColumns() []string {
|
||||||
return []string{"ChannelId", "UserId", "Roles", "LastViewedAt", "MsgCount", "MsgCountRoot", "MentionCount", "NotifyProps", "LastUpdateAt", "SchemeUser", "SchemeAdmin", "SchemeGuest"}
|
return []string{"ChannelId", "UserId", "Roles", "LastViewedAt", "MsgCount", "MsgCountRoot", "MentionCount", "MentionCountRoot", "NotifyProps", "LastUpdateAt", "SchemeUser", "SchemeAdmin", "SchemeGuest"}
|
||||||
}
|
}
|
||||||
|
|
||||||
func channelMemberToSlice(member *model.ChannelMember) []interface{} {
|
func channelMemberToSlice(member *model.ChannelMember) []interface{} {
|
||||||
@@ -104,6 +107,7 @@ func channelMemberToSlice(member *model.ChannelMember) []interface{} {
|
|||||||
resultSlice = append(resultSlice, member.MsgCount)
|
resultSlice = append(resultSlice, member.MsgCount)
|
||||||
resultSlice = append(resultSlice, member.MsgCountRoot)
|
resultSlice = append(resultSlice, member.MsgCountRoot)
|
||||||
resultSlice = append(resultSlice, member.MentionCount)
|
resultSlice = append(resultSlice, member.MentionCount)
|
||||||
|
resultSlice = append(resultSlice, member.MentionCountRoot)
|
||||||
resultSlice = append(resultSlice, model.MapToJson(member.NotifyProps))
|
resultSlice = append(resultSlice, model.MapToJson(member.NotifyProps))
|
||||||
resultSlice = append(resultSlice, member.LastUpdateAt)
|
resultSlice = append(resultSlice, member.LastUpdateAt)
|
||||||
resultSlice = append(resultSlice, member.SchemeUser)
|
resultSlice = append(resultSlice, member.SchemeUser)
|
||||||
@@ -229,19 +233,20 @@ func (db channelMemberWithSchemeRoles) ToModel() *model.ChannelMember {
|
|||||||
strings.Fields(db.Roles),
|
strings.Fields(db.Roles),
|
||||||
)
|
)
|
||||||
return &model.ChannelMember{
|
return &model.ChannelMember{
|
||||||
ChannelId: db.ChannelId,
|
ChannelId: db.ChannelId,
|
||||||
UserId: db.UserId,
|
UserId: db.UserId,
|
||||||
Roles: strings.Join(rolesResult.roles, " "),
|
Roles: strings.Join(rolesResult.roles, " "),
|
||||||
LastViewedAt: db.LastViewedAt,
|
LastViewedAt: db.LastViewedAt,
|
||||||
MsgCount: db.MsgCount,
|
MsgCount: db.MsgCount,
|
||||||
MsgCountRoot: db.MsgCountRoot,
|
MsgCountRoot: db.MsgCountRoot,
|
||||||
MentionCount: db.MentionCount,
|
MentionCount: db.MentionCount,
|
||||||
NotifyProps: db.NotifyProps,
|
MentionCountRoot: db.MentionCountRoot,
|
||||||
LastUpdateAt: db.LastUpdateAt,
|
NotifyProps: db.NotifyProps,
|
||||||
SchemeAdmin: rolesResult.schemeAdmin,
|
LastUpdateAt: db.LastUpdateAt,
|
||||||
SchemeUser: rolesResult.schemeUser,
|
SchemeAdmin: rolesResult.schemeAdmin,
|
||||||
SchemeGuest: rolesResult.schemeGuest,
|
SchemeUser: rolesResult.schemeUser,
|
||||||
ExplicitRoles: strings.Join(rolesResult.explicitRoles, " "),
|
SchemeGuest: rolesResult.schemeGuest,
|
||||||
|
ExplicitRoles: strings.Join(rolesResult.explicitRoles, " "),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -717,10 +722,7 @@ func (s SqlChannelStore) GetChannelUnread(channelId, userId string) (*model.Chan
|
|||||||
var unreadChannel model.ChannelUnread
|
var unreadChannel model.ChannelUnread
|
||||||
err := s.GetReplica().SelectOne(&unreadChannel,
|
err := s.GetReplica().SelectOne(&unreadChannel,
|
||||||
`SELECT
|
`SELECT
|
||||||
Channels.TeamId TeamId, Channels.Id ChannelId,
|
Channels.TeamId TeamId, Channels.Id ChannelId, (Channels.TotalMsgCount - ChannelMembers.MsgCount) MsgCount, (Channels.TotalMsgCountRoot - ChannelMembers.MsgCountRoot) MsgCountRoot, ChannelMembers.MentionCount MentionCount, ChannelMembers.MentionCountRoot MentionCountRoot, ChannelMembers.NotifyProps NotifyProps
|
||||||
(Channels.TotalMsgCount - ChannelMembers.MsgCount) MsgCount,
|
|
||||||
(Channels.TotalMsgCountRoot - ChannelMembers.MsgCountRoot) MsgCountRoot,
|
|
||||||
ChannelMembers.MentionCount MentionCount, ChannelMembers.NotifyProps NotifyProps
|
|
||||||
FROM
|
FROM
|
||||||
Channels, ChannelMembers
|
Channels, ChannelMembers
|
||||||
WHERE
|
WHERE
|
||||||
@@ -2086,6 +2088,7 @@ func (s SqlChannelStore) UpdateLastViewedAt(channelIds []string, userId string,
|
|||||||
ChannelMembers cm
|
ChannelMembers cm
|
||||||
SET
|
SET
|
||||||
MentionCount = 0,
|
MentionCount = 0,
|
||||||
|
MentionCountRoot = 0,
|
||||||
MsgCount = greatest(cm.MsgCount, c.TotalMsgCount),
|
MsgCount = greatest(cm.MsgCount, c.TotalMsgCount),
|
||||||
MsgCountRoot = greatest(cm.MsgCountRoot, c.TotalMsgCountRoot),
|
MsgCountRoot = greatest(cm.MsgCountRoot, c.TotalMsgCountRoot),
|
||||||
LastViewedAt = greatest(cm.LastViewedAt, c.LastPostAt),
|
LastViewedAt = greatest(cm.LastViewedAt, c.LastPostAt),
|
||||||
@@ -2140,6 +2143,7 @@ func (s SqlChannelStore) UpdateLastViewedAt(channelIds []string, userId string,
|
|||||||
ChannelMembers
|
ChannelMembers
|
||||||
SET
|
SET
|
||||||
MentionCount = 0,
|
MentionCount = 0,
|
||||||
|
MentionCountRoot = 0,
|
||||||
MsgCount = CASE ChannelId ` + msgCountQuery + ` END,
|
MsgCount = CASE ChannelId ` + msgCountQuery + ` END,
|
||||||
MsgCountRoot = CASE ChannelId ` + msgCountQueryRoot + ` END,
|
MsgCountRoot = CASE ChannelId ` + msgCountQueryRoot + ` END,
|
||||||
LastViewedAt = CASE ChannelId ` + lastViewedQuery + ` END,
|
LastViewedAt = CASE ChannelId ` + lastViewedQuery + ` END,
|
||||||
@@ -2196,7 +2200,7 @@ func (s SqlChannelStore) CountPostsAfter(channelId string, timestamp int64, user
|
|||||||
// UpdateLastViewedAtPost updates a ChannelMember as if the user last read the channel at the time of the given post.
|
// UpdateLastViewedAtPost updates a ChannelMember as if the user last read the channel at the time of the given post.
|
||||||
// If the provided mentionCount is -1, the given post and all posts after it are considered to be mentions. Returns
|
// If the provided mentionCount is -1, the given post and all posts after it are considered to be mentions. Returns
|
||||||
// an updated model.ChannelUnreadAt that can be returned to the client.
|
// an updated model.ChannelUnreadAt that can be returned to the client.
|
||||||
func (s SqlChannelStore) UpdateLastViewedAtPost(unreadPost *model.Post, userID string, mentionCount int, updateThreads bool) (*model.ChannelUnreadAt, error) {
|
func (s SqlChannelStore) UpdateLastViewedAtPost(unreadPost *model.Post, userID string, mentionCount, mentionCountRoot int, updateThreads bool) (*model.ChannelUnreadAt, error) {
|
||||||
var threadsToUpdate []string
|
var threadsToUpdate []string
|
||||||
unreadDate := unreadPost.CreateAt - 1
|
unreadDate := unreadPost.CreateAt - 1
|
||||||
if updateThreads {
|
if updateThreads {
|
||||||
@@ -2214,6 +2218,7 @@ func (s SqlChannelStore) UpdateLastViewedAtPost(unreadPost *model.Post, userID s
|
|||||||
|
|
||||||
params := map[string]interface{}{
|
params := map[string]interface{}{
|
||||||
"mentions": mentionCount,
|
"mentions": mentionCount,
|
||||||
|
"mentionsRoot": mentionCountRoot,
|
||||||
"unreadCount": unread,
|
"unreadCount": unread,
|
||||||
"unreadCountRoot": unreadRoot,
|
"unreadCountRoot": unreadRoot,
|
||||||
"lastViewedAt": unreadDate,
|
"lastViewedAt": unreadDate,
|
||||||
@@ -2229,6 +2234,7 @@ func (s SqlChannelStore) UpdateLastViewedAtPost(unreadPost *model.Post, userID s
|
|||||||
ChannelMembers
|
ChannelMembers
|
||||||
SET
|
SET
|
||||||
MentionCount = :mentions,
|
MentionCount = :mentions,
|
||||||
|
MentionCountRoot = :mentionsRoot,
|
||||||
MsgCount = (SELECT TotalMsgCount FROM Channels WHERE ID = :channelId) - :unreadCount,
|
MsgCount = (SELECT TotalMsgCount FROM Channels WHERE ID = :channelId) - :unreadCount,
|
||||||
MsgCountRoot = (SELECT TotalMsgCountRoot FROM Channels WHERE ID = :channelId) - :unreadCountRoot,
|
MsgCountRoot = (SELECT TotalMsgCountRoot FROM Channels WHERE ID = :channelId) - :unreadCountRoot,
|
||||||
LastViewedAt = :lastViewedAt,
|
LastViewedAt = :lastViewedAt,
|
||||||
@@ -2250,6 +2256,7 @@ func (s SqlChannelStore) UpdateLastViewedAtPost(unreadPost *model.Post, userID s
|
|||||||
cm.MsgCount MsgCount,
|
cm.MsgCount MsgCount,
|
||||||
cm.MsgCountRoot MsgCountRoot,
|
cm.MsgCountRoot MsgCountRoot,
|
||||||
cm.MentionCount MentionCount,
|
cm.MentionCount MentionCount,
|
||||||
|
cm.MentionCountRoot MentionCountRoot,
|
||||||
cm.LastViewedAt LastViewedAt,
|
cm.LastViewedAt LastViewedAt,
|
||||||
cm.NotifyProps NotifyProps
|
cm.NotifyProps NotifyProps
|
||||||
FROM
|
FROM
|
||||||
@@ -2271,7 +2278,7 @@ func (s SqlChannelStore) UpdateLastViewedAtPost(unreadPost *model.Post, userID s
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s SqlChannelStore) IncrementMentionCount(channelId string, userId string, updateThreads bool) error {
|
func (s SqlChannelStore) IncrementMentionCount(channelId string, userId string, updateThreads, isRoot bool) error {
|
||||||
now := model.GetMillis()
|
now := model.GetMillis()
|
||||||
var threadsToUpdate []string
|
var threadsToUpdate []string
|
||||||
if updateThreads {
|
if updateThreads {
|
||||||
@@ -2281,17 +2288,21 @@ func (s SqlChannelStore) IncrementMentionCount(channelId string, userId string,
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
rootInc := 0
|
||||||
|
if isRoot {
|
||||||
|
rootInc = 1
|
||||||
|
}
|
||||||
_, err := s.GetMaster().Exec(
|
_, err := s.GetMaster().Exec(
|
||||||
`UPDATE
|
`UPDATE
|
||||||
ChannelMembers
|
ChannelMembers
|
||||||
SET
|
SET
|
||||||
MentionCount = MentionCount + 1,
|
MentionCount = MentionCount + 1,
|
||||||
|
MentionCountRoot = MentionCountRoot + :RootInc,
|
||||||
LastUpdateAt = :LastUpdateAt
|
LastUpdateAt = :LastUpdateAt
|
||||||
WHERE
|
WHERE
|
||||||
UserId = :UserId
|
UserId = :UserId
|
||||||
AND ChannelId = :ChannelId`,
|
AND ChannelId = :ChannelId`,
|
||||||
map[string]interface{}{"ChannelId": channelId, "UserId": userId, "LastUpdateAt": now})
|
map[string]interface{}{"ChannelId": channelId, "UserId": userId, "LastUpdateAt": now, "RootInc": rootInc})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "failed to Update ChannelMembers with channelId=%s and userId=%s", channelId, userId)
|
return errors.Wrapf(err, "failed to Update ChannelMembers with channelId=%s and userId=%s", channelId, userId)
|
||||||
}
|
}
|
||||||
@@ -3186,6 +3197,7 @@ func (s SqlChannelStore) GetChannelMembersForExport(userId string, teamId string
|
|||||||
ChannelMembers.LastViewedAt,
|
ChannelMembers.LastViewedAt,
|
||||||
ChannelMembers.MsgCount,
|
ChannelMembers.MsgCount,
|
||||||
ChannelMembers.MentionCount,
|
ChannelMembers.MentionCount,
|
||||||
|
ChannelMembers.MentionCountRoot,
|
||||||
ChannelMembers.NotifyProps,
|
ChannelMembers.NotifyProps,
|
||||||
ChannelMembers.LastUpdateAt,
|
ChannelMembers.LastUpdateAt,
|
||||||
ChannelMembers.SchemeUser,
|
ChannelMembers.SchemeUser,
|
||||||
@@ -3236,7 +3248,7 @@ func (s SqlChannelStore) GetAllDirectChannelsForExportAfter(limit int, afterId s
|
|||||||
channelIds = append(channelIds, channel.Id)
|
channelIds = append(channelIds, channel.Id)
|
||||||
}
|
}
|
||||||
query = s.getQueryBuilder().
|
query = s.getQueryBuilder().
|
||||||
Select("u.Username as Username, ChannelId, UserId, cm.Roles as Roles, LastViewedAt, MsgCount, MentionCount, cm.NotifyProps as NotifyProps, LastUpdateAt, SchemeUser, SchemeAdmin, (SchemeGuest IS NOT NULL AND SchemeGuest) as SchemeGuest").
|
Select("u.Username as Username, ChannelId, UserId, cm.Roles as Roles, LastViewedAt, MsgCount, MentionCount, MentionCountRoot, cm.NotifyProps as NotifyProps, LastUpdateAt, SchemeUser, SchemeAdmin, (SchemeGuest IS NOT NULL AND SchemeGuest) as SchemeGuest").
|
||||||
From("ChannelMembers cm").
|
From("ChannelMembers cm").
|
||||||
Join("Users u ON ( u.Id = cm.UserId )").
|
Join("Users u ON ( u.Id = cm.UserId )").
|
||||||
Where(sq.And{
|
Where(sq.And{
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ func testNewChannelMemberFromModel(t *testing.T) {
|
|||||||
assert.Equal(t, m.LastViewedAt, db.LastViewedAt)
|
assert.Equal(t, m.LastViewedAt, db.LastViewedAt)
|
||||||
assert.Equal(t, m.MsgCount, db.MsgCount)
|
assert.Equal(t, m.MsgCount, db.MsgCount)
|
||||||
assert.Equal(t, m.MentionCount, db.MentionCount)
|
assert.Equal(t, m.MentionCount, db.MentionCount)
|
||||||
|
assert.Equal(t, int64(0), m.MentionCountRoot)
|
||||||
assert.Equal(t, m.NotifyProps, db.NotifyProps)
|
assert.Equal(t, m.NotifyProps, db.NotifyProps)
|
||||||
assert.Equal(t, m.LastUpdateAt, db.LastUpdateAt)
|
assert.Equal(t, m.LastUpdateAt, db.LastUpdateAt)
|
||||||
assert.Equal(t, true, db.SchemeGuest.Valid)
|
assert.Equal(t, true, db.SchemeGuest.Valid)
|
||||||
@@ -111,6 +112,7 @@ func testChannelMemberWithSchemeRolesToModel(t *testing.T) {
|
|||||||
assert.Equal(t, db.LastViewedAt, m.LastViewedAt)
|
assert.Equal(t, db.LastViewedAt, m.LastViewedAt)
|
||||||
assert.Equal(t, db.MsgCount, m.MsgCount)
|
assert.Equal(t, db.MsgCount, m.MsgCount)
|
||||||
assert.Equal(t, db.MentionCount, m.MentionCount)
|
assert.Equal(t, db.MentionCount, m.MentionCount)
|
||||||
|
assert.Equal(t, db.MentionCountRoot, m.MentionCountRoot)
|
||||||
assert.Equal(t, db.NotifyProps, m.NotifyProps)
|
assert.Equal(t, db.NotifyProps, m.NotifyProps)
|
||||||
assert.Equal(t, db.LastUpdateAt, m.LastUpdateAt)
|
assert.Equal(t, db.LastUpdateAt, m.LastUpdateAt)
|
||||||
assert.Equal(t, db.SchemeGuest.Bool, m.SchemeGuest)
|
assert.Equal(t, db.SchemeGuest.Bool, m.SchemeGuest)
|
||||||
|
|||||||
@@ -919,6 +919,7 @@ func (s *SqlGroupStore) ChannelMembersToRemove(channelID *string) ([]*model.Chan
|
|||||||
"ChannelMembers.MsgCount",
|
"ChannelMembers.MsgCount",
|
||||||
"ChannelMembers.MsgCountRoot",
|
"ChannelMembers.MsgCountRoot",
|
||||||
"ChannelMembers.MentionCount",
|
"ChannelMembers.MentionCount",
|
||||||
|
"ChannelMembers.MentionCountRoot",
|
||||||
"ChannelMembers.NotifyProps",
|
"ChannelMembers.NotifyProps",
|
||||||
"ChannelMembers.LastUpdateAt",
|
"ChannelMembers.LastUpdateAt",
|
||||||
"ChannelMembers.LastUpdateAt",
|
"ChannelMembers.LastUpdateAt",
|
||||||
|
|||||||
@@ -2030,7 +2030,7 @@ func (s *SqlPostStore) GetDirectPostParentsForExportAfter(limit int, afterId str
|
|||||||
channelIds = append(channelIds, post.ChannelId)
|
channelIds = append(channelIds, post.ChannelId)
|
||||||
}
|
}
|
||||||
query = s.getQueryBuilder().
|
query = s.getQueryBuilder().
|
||||||
Select("u.Username as Username, ChannelId, UserId, cm.Roles as Roles, LastViewedAt, MsgCount, MentionCount, cm.NotifyProps as NotifyProps, LastUpdateAt, SchemeUser, SchemeAdmin, (SchemeGuest IS NOT NULL AND SchemeGuest) as SchemeGuest").
|
Select("u.Username as Username, ChannelId, UserId, cm.Roles as Roles, LastViewedAt, MsgCount, MentionCount, MentionCountRoot, cm.NotifyProps as NotifyProps, LastUpdateAt, SchemeUser, SchemeAdmin, (SchemeGuest IS NOT NULL AND SchemeGuest) as SchemeGuest").
|
||||||
From("ChannelMembers cm").
|
From("ChannelMembers cm").
|
||||||
Join("Users u ON ( u.Id = cm.UserId )").
|
Join("Users u ON ( u.Id = cm.UserId )").
|
||||||
Where(sq.Eq{
|
Where(sq.Eq{
|
||||||
|
|||||||
@@ -1177,7 +1177,7 @@ func (s SqlTeamStore) GetTeamsForUserWithPagination(userId string, page, perPage
|
|||||||
// for all the channels in all the teams except the excluded ones.
|
// for all the channels in all the teams except the excluded ones.
|
||||||
func (s SqlTeamStore) GetChannelUnreadsForAllTeams(excludeTeamId, userId string) ([]*model.ChannelUnread, error) {
|
func (s SqlTeamStore) GetChannelUnreadsForAllTeams(excludeTeamId, userId string) ([]*model.ChannelUnread, error) {
|
||||||
query, args, err := s.getQueryBuilder().
|
query, args, err := s.getQueryBuilder().
|
||||||
Select("Channels.TeamId TeamId", "Channels.Id ChannelId", "(Channels.TotalMsgCount - ChannelMembers.MsgCount) MsgCount", "(Channels.TotalMsgCountRoot - ChannelMembers.MsgCountRoot) MsgCountRoot", "ChannelMembers.MentionCount MentionCount", "ChannelMembers.NotifyProps NotifyProps").
|
Select("Channels.TeamId TeamId", "Channels.Id ChannelId", "(Channels.TotalMsgCount - ChannelMembers.MsgCount) MsgCount", "(Channels.TotalMsgCountRoot - ChannelMembers.MsgCountRoot) MsgCountRoot", "ChannelMembers.MentionCount MentionCount", "ChannelMembers.MentionCountRoot MentionCountRoot", "ChannelMembers.NotifyProps NotifyProps").
|
||||||
From("Channels").
|
From("Channels").
|
||||||
Join("ChannelMembers ON Id = ChannelId").
|
Join("ChannelMembers ON Id = ChannelId").
|
||||||
Where(sq.Eq{"UserId": userId, "DeleteAt": 0}).
|
Where(sq.Eq{"UserId": userId, "DeleteAt": 0}).
|
||||||
@@ -1199,7 +1199,7 @@ func (s SqlTeamStore) GetChannelUnreadsForAllTeams(excludeTeamId, userId string)
|
|||||||
// GetChannelUnreadsForTeam returns unreads msg count, mention counts and notifyProps for all the channels in a single team.
|
// GetChannelUnreadsForTeam returns unreads msg count, mention counts and notifyProps for all the channels in a single team.
|
||||||
func (s SqlTeamStore) GetChannelUnreadsForTeam(teamId, userId string) ([]*model.ChannelUnread, error) {
|
func (s SqlTeamStore) GetChannelUnreadsForTeam(teamId, userId string) ([]*model.ChannelUnread, error) {
|
||||||
query, args, err := s.getQueryBuilder().
|
query, args, err := s.getQueryBuilder().
|
||||||
Select("Channels.TeamId TeamId", "Channels.Id ChannelId", "(Channels.TotalMsgCount - ChannelMembers.MsgCount) MsgCount", "(Channels.TotalMsgCountRoot - ChannelMembers.MsgCountRoot) MsgCountRoot", "ChannelMembers.MentionCount MentionCount", "ChannelMembers.NotifyProps NotifyProps").
|
Select("Channels.TeamId TeamId", "Channels.Id ChannelId", "(Channels.TotalMsgCount - ChannelMembers.MsgCount) MsgCount", "(Channels.TotalMsgCountRoot - ChannelMembers.MsgCountRoot) MsgCountRoot", "ChannelMembers.MentionCount MentionCount", "ChannelMembers.MentionCountRoot MentionCountRoot", "ChannelMembers.NotifyProps NotifyProps").
|
||||||
From("Channels").
|
From("Channels").
|
||||||
Join("ChannelMembers ON Id = ChannelId").
|
Join("ChannelMembers ON Id = ChannelId").
|
||||||
Where(sq.Eq{"UserId": userId, "TeamId": teamId, "DeleteAt": 0}).ToSql()
|
Where(sq.Eq{"UserId": userId, "TeamId": teamId, "DeleteAt": 0}).ToSql()
|
||||||
|
|||||||
@@ -109,35 +109,6 @@ func (s *SqlThreadStore) Get(id string) (*model.Thread, error) {
|
|||||||
return &thread, nil
|
return &thread, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SqlThreadStore) GetThreadMentionsForUserPerChannel(userId, teamId string) (map[string]int64, error) {
|
|
||||||
type Count struct {
|
|
||||||
UnreadMentions int64
|
|
||||||
ChannelId string
|
|
||||||
}
|
|
||||||
var counts []Count
|
|
||||||
|
|
||||||
sql, args, _ := s.getQueryBuilder().
|
|
||||||
Select("SUM(UnreadMentions) as UnreadMentions", "ChannelId").
|
|
||||||
From("ThreadMemberships").
|
|
||||||
LeftJoin("Threads ON Threads.PostId = ThreadMemberships.PostId").
|
|
||||||
LeftJoin("Channels ON Threads.ChannelId = Channels.Id").
|
|
||||||
Where(sq.And{
|
|
||||||
sq.Or{sq.Eq{"Channels.TeamId": teamId}, sq.Eq{"Channels.TeamId": ""}},
|
|
||||||
sq.Eq{"ThreadMemberships.UserId": userId},
|
|
||||||
sq.Eq{"ThreadMemberships.Following": true},
|
|
||||||
}).
|
|
||||||
GroupBy("Threads.ChannelId").ToSql()
|
|
||||||
|
|
||||||
if _, err := s.GetMaster().Select(&counts, sql, args...); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
result := map[string]int64{}
|
|
||||||
for _, count := range counts {
|
|
||||||
result[count.ChannelId] = count.UnreadMentions
|
|
||||||
}
|
|
||||||
return result, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SqlThreadStore) GetThreadsForUser(userId, teamId string, opts model.GetUserThreadsOpts) (*model.Threads, error) {
|
func (s *SqlThreadStore) GetThreadsForUser(userId, teamId string, opts model.GetUserThreadsOpts) (*model.Threads, error) {
|
||||||
type JoinedThread struct {
|
type JoinedThread struct {
|
||||||
PostId string
|
PostId string
|
||||||
|
|||||||
@@ -1011,6 +1011,38 @@ func upgradeDatabaseToVersion535(sqlStore *SqlStore) {
|
|||||||
|
|
||||||
sqlStore.CreateColumnIfNotExists("SidebarCategories", "Collapsed", "tinyint(1)", "boolean", "0")
|
sqlStore.CreateColumnIfNotExists("SidebarCategories", "Collapsed", "tinyint(1)", "boolean", "0")
|
||||||
|
|
||||||
|
// note: setting default 0 on pre-5.0 tables causes test-db-migration script to fail, so this column will be added to ignore list
|
||||||
|
sqlStore.CreateColumnIfNotExists("ChannelMembers", "MentionCountRoot", "bigint", "bigint", "0")
|
||||||
|
sqlStore.AlterColumnDefaultIfExists("ChannelMembers", "MentionCountRoot", model.NewString("0"), model.NewString("0"))
|
||||||
|
|
||||||
|
mentionCountRootCTE := `
|
||||||
|
SELECT ChannelId, COALESCE(SUM(UnreadMentions), 0) AS UnreadMentions, UserId
|
||||||
|
FROM ThreadMemberships
|
||||||
|
LEFT JOIN Threads ON ThreadMemberships.PostId = Threads.PostId
|
||||||
|
GROUP BY Threads.ChannelId, ThreadMemberships.UserId
|
||||||
|
`
|
||||||
|
updateMentionCountRootQuery := `
|
||||||
|
UPDATE ChannelMembers INNER JOIN (` + mentionCountRootCTE + `) AS q ON
|
||||||
|
q.ChannelId = ChannelMembers.ChannelId AND
|
||||||
|
q.UserId=ChannelMembers.UserId AND
|
||||||
|
ChannelMembers.MentionCount > 0
|
||||||
|
SET MentionCountRoot = ChannelMembers.MentionCount - q.UnreadMentions
|
||||||
|
`
|
||||||
|
if sqlStore.DriverName() == model.DATABASE_DRIVER_POSTGRES {
|
||||||
|
updateMentionCountRootQuery = `
|
||||||
|
WITH q AS (` + mentionCountRootCTE + `)
|
||||||
|
UPDATE channelmembers
|
||||||
|
SET MentionCountRoot = ChannelMembers.MentionCount - q.UnreadMentions
|
||||||
|
FROM q
|
||||||
|
WHERE
|
||||||
|
q.ChannelId = ChannelMembers.ChannelId AND
|
||||||
|
q.UserId = ChannelMembers.UserId AND
|
||||||
|
ChannelMembers.MentionCount > 0
|
||||||
|
`
|
||||||
|
}
|
||||||
|
if _, err := sqlStore.GetMaster().Exec(updateMentionCountRootQuery); err != nil {
|
||||||
|
mlog.Error("Error updating ChannelId in Threads table", mlog.Err(err))
|
||||||
|
}
|
||||||
sqlStore.CreateColumnIfNotExists("Channels", "TotalMsgCountRoot", "bigint", "bigint", "0")
|
sqlStore.CreateColumnIfNotExists("Channels", "TotalMsgCountRoot", "bigint", "bigint", "0")
|
||||||
sqlStore.CreateColumnIfNotExistsNoDefault("Channels", "LastRootPostAt", "bigint", "bigint")
|
sqlStore.CreateColumnIfNotExistsNoDefault("Channels", "LastRootPostAt", "bigint", "bigint")
|
||||||
defer sqlStore.RemoveColumnIfExists("Channels", "LastRootPostAt")
|
defer sqlStore.RemoveColumnIfExists("Channels", "LastRootPostAt")
|
||||||
|
|||||||
@@ -1634,6 +1634,7 @@ func (us SqlUserStore) GetUsersBatchForIndexing(startTime, endTime int64, limit
|
|||||||
cm.LastViewedAt,
|
cm.LastViewedAt,
|
||||||
cm.MsgCount,
|
cm.MsgCount,
|
||||||
cm.MentionCount,
|
cm.MentionCount,
|
||||||
|
cm.MentionCountRoot,
|
||||||
cm.NotifyProps,
|
cm.NotifyProps,
|
||||||
cm.LastUpdateAt,
|
cm.LastUpdateAt,
|
||||||
cm.SchemeUser,
|
cm.SchemeUser,
|
||||||
|
|||||||
@@ -193,9 +193,9 @@ type ChannelStore interface {
|
|||||||
PermanentDeleteMembersByUser(userId string) error
|
PermanentDeleteMembersByUser(userId string) error
|
||||||
PermanentDeleteMembersByChannel(channelID string) error
|
PermanentDeleteMembersByChannel(channelID string) error
|
||||||
UpdateLastViewedAt(channelIds []string, userId string, updateThreads bool) (map[string]int64, error)
|
UpdateLastViewedAt(channelIds []string, userId string, updateThreads bool) (map[string]int64, error)
|
||||||
UpdateLastViewedAtPost(unreadPost *model.Post, userID string, mentionCount int, updateThreads bool) (*model.ChannelUnreadAt, error)
|
UpdateLastViewedAtPost(unreadPost *model.Post, userID string, mentionCount, mentionCountRoot int, updateThreads bool) (*model.ChannelUnreadAt, error)
|
||||||
CountPostsAfter(channelID string, timestamp int64, userId string) (int, int, error)
|
CountPostsAfter(channelID string, timestamp int64, userId string) (int, int, error)
|
||||||
IncrementMentionCount(channelID string, userId string, updateThreads bool) error
|
IncrementMentionCount(channelID string, userId string, updateThreads, isRoot bool) error
|
||||||
AnalyticsTypeCount(teamID string, channelType string) (int64, error)
|
AnalyticsTypeCount(teamID string, channelType string) (int64, error)
|
||||||
GetMembersForUser(teamID string, userId string) (*model.ChannelMembers, error)
|
GetMembersForUser(teamID string, userId string) (*model.ChannelMembers, error)
|
||||||
GetMembersForUserWithPagination(teamID, userId string, page, perPage int) (*model.ChannelMembers, error)
|
GetMembersForUserWithPagination(teamID, userId string, page, perPage int) (*model.ChannelMembers, error)
|
||||||
@@ -257,7 +257,6 @@ type ThreadStore interface {
|
|||||||
GetThreadForUser(userId, teamId, threadId string, extended bool) (*model.ThreadResponse, error)
|
GetThreadForUser(userId, teamId, threadId string, extended bool) (*model.ThreadResponse, error)
|
||||||
Delete(postId string) error
|
Delete(postId string) error
|
||||||
GetPosts(threadId string, since int64) ([]*model.Post, error)
|
GetPosts(threadId string, since int64) ([]*model.Post, error)
|
||||||
GetThreadMentionsForUserPerChannel(userId, teamId string) (map[string]int64, error)
|
|
||||||
|
|
||||||
MarkAllAsRead(userId, teamID string) error
|
MarkAllAsRead(userId, teamID string) error
|
||||||
MarkAsRead(userId, threadID string, timestamp int64) error
|
MarkAsRead(userId, threadID string, timestamp int64) error
|
||||||
|
|||||||
@@ -340,7 +340,7 @@ func testGetChannelUnread(t *testing.T, ss store.Store) {
|
|||||||
_, nErr = ss.Channel().Save(c2, -1)
|
_, nErr = ss.Channel().Save(c2, -1)
|
||||||
require.NoError(t, nErr)
|
require.NoError(t, nErr)
|
||||||
|
|
||||||
cm2 := &model.ChannelMember{ChannelId: c2.Id, UserId: m2.UserId, NotifyProps: notifyPropsModel, MsgCount: 90, MsgCountRoot: 90, MentionCount: 5}
|
cm2 := &model.ChannelMember{ChannelId: c2.Id, UserId: m2.UserId, NotifyProps: notifyPropsModel, MsgCount: 90, MsgCountRoot: 90, MentionCount: 5, MentionCountRoot: 1}
|
||||||
_, err = ss.Channel().SaveMember(cm2)
|
_, err = ss.Channel().SaveMember(cm2)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
@@ -361,6 +361,7 @@ func testGetChannelUnread(t *testing.T, ss store.Store) {
|
|||||||
require.Equal(t, c2.Id, ch2.ChannelId, "Wrong channel id")
|
require.Equal(t, c2.Id, ch2.ChannelId, "Wrong channel id")
|
||||||
require.Equal(t, teamId2, ch2.TeamId, "Wrong team id")
|
require.Equal(t, teamId2, ch2.TeamId, "Wrong team id")
|
||||||
require.EqualValues(t, 5, ch2.MentionCount, "wrong MentionCount for channel 2")
|
require.EqualValues(t, 5, ch2.MentionCount, "wrong MentionCount for channel 2")
|
||||||
|
require.EqualValues(t, 1, ch2.MentionCountRoot, "wrong MentionCountRoot for channel 2")
|
||||||
require.EqualValues(t, 10, ch2.MsgCount, "wrong MsgCount for channel 2")
|
require.EqualValues(t, 10, ch2.MsgCount, "wrong MsgCount for channel 2")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4200,16 +4201,16 @@ func testChannelStoreIncrementMentionCount(t *testing.T, ss store.Store) {
|
|||||||
_, err := ss.Channel().SaveMember(&m1)
|
_, err := ss.Channel().SaveMember(&m1)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = ss.Channel().IncrementMentionCount(m1.ChannelId, m1.UserId, false)
|
err = ss.Channel().IncrementMentionCount(m1.ChannelId, m1.UserId, false, false)
|
||||||
require.NoError(t, err, "failed to update")
|
require.NoError(t, err, "failed to update")
|
||||||
|
|
||||||
err = ss.Channel().IncrementMentionCount(m1.ChannelId, "missing id", false)
|
err = ss.Channel().IncrementMentionCount(m1.ChannelId, "missing id", false, false)
|
||||||
require.NoError(t, err, "failed to update")
|
require.NoError(t, err, "failed to update")
|
||||||
|
|
||||||
err = ss.Channel().IncrementMentionCount("missing id", m1.UserId, false)
|
err = ss.Channel().IncrementMentionCount("missing id", m1.UserId, false, false)
|
||||||
require.NoError(t, err, "failed to update")
|
require.NoError(t, err, "failed to update")
|
||||||
|
|
||||||
err = ss.Channel().IncrementMentionCount("missing id", "missing id", false)
|
err = ss.Channel().IncrementMentionCount("missing id", "missing id", false, false)
|
||||||
require.NoError(t, err, "failed to update")
|
require.NoError(t, err, "failed to update")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1294,13 +1294,13 @@ func (_m *ChannelStore) GroupSyncedChannelCount() (int64, error) {
|
|||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
// IncrementMentionCount provides a mock function with given fields: channelID, userId, updateThreads
|
// IncrementMentionCount provides a mock function with given fields: channelID, userId, updateThreads, isRoot
|
||||||
func (_m *ChannelStore) IncrementMentionCount(channelID string, userId string, updateThreads bool) error {
|
func (_m *ChannelStore) IncrementMentionCount(channelID string, userId string, updateThreads bool, isRoot bool) error {
|
||||||
ret := _m.Called(channelID, userId, updateThreads)
|
ret := _m.Called(channelID, userId, updateThreads, isRoot)
|
||||||
|
|
||||||
var r0 error
|
var r0 error
|
||||||
if rf, ok := ret.Get(0).(func(string, string, bool) error); ok {
|
if rf, ok := ret.Get(0).(func(string, string, bool, bool) error); ok {
|
||||||
r0 = rf(channelID, userId, updateThreads)
|
r0 = rf(channelID, userId, updateThreads, isRoot)
|
||||||
} else {
|
} else {
|
||||||
r0 = ret.Error(0)
|
r0 = ret.Error(0)
|
||||||
}
|
}
|
||||||
@@ -1817,13 +1817,13 @@ func (_m *ChannelStore) UpdateLastViewedAt(channelIds []string, userId string, u
|
|||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateLastViewedAtPost provides a mock function with given fields: unreadPost, userID, mentionCount, updateThreads
|
// UpdateLastViewedAtPost provides a mock function with given fields: unreadPost, userID, mentionCount, mentionCountRoot, updateThreads
|
||||||
func (_m *ChannelStore) UpdateLastViewedAtPost(unreadPost *model.Post, userID string, mentionCount int, updateThreads bool) (*model.ChannelUnreadAt, error) {
|
func (_m *ChannelStore) UpdateLastViewedAtPost(unreadPost *model.Post, userID string, mentionCount int, mentionCountRoot int, updateThreads bool) (*model.ChannelUnreadAt, error) {
|
||||||
ret := _m.Called(unreadPost, userID, mentionCount, updateThreads)
|
ret := _m.Called(unreadPost, userID, mentionCount, mentionCountRoot, updateThreads)
|
||||||
|
|
||||||
var r0 *model.ChannelUnreadAt
|
var r0 *model.ChannelUnreadAt
|
||||||
if rf, ok := ret.Get(0).(func(*model.Post, string, int, bool) *model.ChannelUnreadAt); ok {
|
if rf, ok := ret.Get(0).(func(*model.Post, string, int, int, bool) *model.ChannelUnreadAt); ok {
|
||||||
r0 = rf(unreadPost, userID, mentionCount, updateThreads)
|
r0 = rf(unreadPost, userID, mentionCount, mentionCountRoot, updateThreads)
|
||||||
} else {
|
} else {
|
||||||
if ret.Get(0) != nil {
|
if ret.Get(0) != nil {
|
||||||
r0 = ret.Get(0).(*model.ChannelUnreadAt)
|
r0 = ret.Get(0).(*model.ChannelUnreadAt)
|
||||||
@@ -1831,8 +1831,8 @@ func (_m *ChannelStore) UpdateLastViewedAtPost(unreadPost *model.Post, userID st
|
|||||||
}
|
}
|
||||||
|
|
||||||
var r1 error
|
var r1 error
|
||||||
if rf, ok := ret.Get(1).(func(*model.Post, string, int, bool) error); ok {
|
if rf, ok := ret.Get(1).(func(*model.Post, string, int, int, bool) error); ok {
|
||||||
r1 = rf(unreadPost, userID, mentionCount, updateThreads)
|
r1 = rf(unreadPost, userID, mentionCount, mentionCountRoot, updateThreads)
|
||||||
} else {
|
} else {
|
||||||
r1 = ret.Error(1)
|
r1 = ret.Error(1)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -180,29 +180,6 @@ func (_m *ThreadStore) GetThreadForUser(userId string, teamId string, threadId s
|
|||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetThreadMentionsForUserPerChannel provides a mock function with given fields: userId, teamId
|
|
||||||
func (_m *ThreadStore) GetThreadMentionsForUserPerChannel(userId string, teamId string) (map[string]int64, error) {
|
|
||||||
ret := _m.Called(userId, teamId)
|
|
||||||
|
|
||||||
var r0 map[string]int64
|
|
||||||
if rf, ok := ret.Get(0).(func(string, string) map[string]int64); ok {
|
|
||||||
r0 = rf(userId, teamId)
|
|
||||||
} else {
|
|
||||||
if ret.Get(0) != nil {
|
|
||||||
r0 = ret.Get(0).(map[string]int64)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var r1 error
|
|
||||||
if rf, ok := ret.Get(1).(func(string, string) error); ok {
|
|
||||||
r1 = rf(userId, teamId)
|
|
||||||
} else {
|
|
||||||
r1 = ret.Error(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return r0, r1
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetThreadsForUser provides a mock function with given fields: userId, teamId, opts
|
// GetThreadsForUser provides a mock function with given fields: userId, teamId, opts
|
||||||
func (_m *ThreadStore) GetThreadsForUser(userId string, teamId string, opts model.GetUserThreadsOpts) (*model.Threads, error) {
|
func (_m *ThreadStore) GetThreadsForUser(userId string, teamId string, opts model.GetUserThreadsOpts) (*model.Threads, error) {
|
||||||
ret := _m.Called(userId, teamId, opts)
|
ret := _m.Called(userId, teamId, opts)
|
||||||
|
|||||||
@@ -243,7 +243,7 @@ func testThreadStorePopulation(t *testing.T, ss store.Store) {
|
|||||||
_, err := ss.Thread().UpdateMembership(m)
|
_, err := ss.Thread().UpdateMembership(m)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
_, err = ss.Channel().UpdateLastViewedAtPost(newPosts[0], newPosts[0].UserId, 0, true)
|
_, err = ss.Channel().UpdateLastViewedAtPost(newPosts[0], newPosts[0].UserId, 0, 0, true)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Eventually(t, func() bool {
|
assert.Eventually(t, func() bool {
|
||||||
@@ -263,7 +263,7 @@ func testThreadStorePopulation(t *testing.T, ss store.Store) {
|
|||||||
_, err := ss.Thread().UpdateMembership(m)
|
_, err := ss.Thread().UpdateMembership(m)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
err = ss.Channel().IncrementMentionCount(newPosts[0].ChannelId, newPosts[0].UserId, true)
|
err = ss.Channel().IncrementMentionCount(newPosts[0].ChannelId, newPosts[0].UserId, true, false)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Eventually(t, func() bool {
|
assert.Eventually(t, func() bool {
|
||||||
@@ -317,7 +317,7 @@ func testThreadStorePopulation(t *testing.T, ss store.Store) {
|
|||||||
_, err := ss.Thread().UpdateMembership(m)
|
_, err := ss.Thread().UpdateMembership(m)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
_, err = ss.Channel().UpdateLastViewedAtPost(newPosts[0], newPosts[0].UserId, 0, true)
|
_, err = ss.Channel().UpdateLastViewedAtPost(newPosts[0], newPosts[0].UserId, 0, 0, true)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Eventually(t, func() bool {
|
assert.Eventually(t, func() bool {
|
||||||
|
|||||||
@@ -2246,7 +2246,7 @@ func testUserUnreadCount(t *testing.T, ss store.Store) {
|
|||||||
// Post one message with mention to open channel
|
// Post one message with mention to open channel
|
||||||
_, nErr = ss.Post().Save(&p1)
|
_, nErr = ss.Post().Save(&p1)
|
||||||
require.NoError(t, nErr)
|
require.NoError(t, nErr)
|
||||||
nErr = ss.Channel().IncrementMentionCount(c1.Id, u2.Id, false)
|
nErr = ss.Channel().IncrementMentionCount(c1.Id, u2.Id, false, false)
|
||||||
require.NoError(t, nErr)
|
require.NoError(t, nErr)
|
||||||
|
|
||||||
// Post 2 messages without mention to direct channel
|
// Post 2 messages without mention to direct channel
|
||||||
@@ -2257,7 +2257,7 @@ func testUserUnreadCount(t *testing.T, ss store.Store) {
|
|||||||
|
|
||||||
_, nErr = ss.Post().Save(&p2)
|
_, nErr = ss.Post().Save(&p2)
|
||||||
require.NoError(t, nErr)
|
require.NoError(t, nErr)
|
||||||
nErr = ss.Channel().IncrementMentionCount(c2.Id, u2.Id, false)
|
nErr = ss.Channel().IncrementMentionCount(c2.Id, u2.Id, false, false)
|
||||||
require.NoError(t, nErr)
|
require.NoError(t, nErr)
|
||||||
|
|
||||||
p3 := model.Post{}
|
p3 := model.Post{}
|
||||||
@@ -2267,7 +2267,7 @@ func testUserUnreadCount(t *testing.T, ss store.Store) {
|
|||||||
_, nErr = ss.Post().Save(&p3)
|
_, nErr = ss.Post().Save(&p3)
|
||||||
require.NoError(t, nErr)
|
require.NoError(t, nErr)
|
||||||
|
|
||||||
nErr = ss.Channel().IncrementMentionCount(c2.Id, u2.Id, false)
|
nErr = ss.Channel().IncrementMentionCount(c2.Id, u2.Id, false, false)
|
||||||
require.NoError(t, nErr)
|
require.NoError(t, nErr)
|
||||||
|
|
||||||
badge, unreadCountErr := ss.User().GetUnreadCount(u2.Id)
|
badge, unreadCountErr := ss.User().GetUnreadCount(u2.Id)
|
||||||
|
|||||||
@@ -1431,10 +1431,10 @@ func (s *TimerLayerChannelStore) GroupSyncedChannelCount() (int64, error) {
|
|||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TimerLayerChannelStore) IncrementMentionCount(channelID string, userId string, updateThreads bool) error {
|
func (s *TimerLayerChannelStore) IncrementMentionCount(channelID string, userId string, updateThreads bool, isRoot bool) error {
|
||||||
start := timemodule.Now()
|
start := timemodule.Now()
|
||||||
|
|
||||||
err := s.ChannelStore.IncrementMentionCount(channelID, userId, updateThreads)
|
err := s.ChannelStore.IncrementMentionCount(channelID, userId, updateThreads, isRoot)
|
||||||
|
|
||||||
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
||||||
if s.Root.Metrics != nil {
|
if s.Root.Metrics != nil {
|
||||||
@@ -1952,10 +1952,10 @@ func (s *TimerLayerChannelStore) UpdateLastViewedAt(channelIds []string, userId
|
|||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TimerLayerChannelStore) UpdateLastViewedAtPost(unreadPost *model.Post, userID string, mentionCount int, updateThreads bool) (*model.ChannelUnreadAt, error) {
|
func (s *TimerLayerChannelStore) UpdateLastViewedAtPost(unreadPost *model.Post, userID string, mentionCount int, mentionCountRoot int, updateThreads bool) (*model.ChannelUnreadAt, error) {
|
||||||
start := timemodule.Now()
|
start := timemodule.Now()
|
||||||
|
|
||||||
result, err := s.ChannelStore.UpdateLastViewedAtPost(unreadPost, userID, mentionCount, updateThreads)
|
result, err := s.ChannelStore.UpdateLastViewedAtPost(unreadPost, userID, mentionCount, mentionCountRoot, updateThreads)
|
||||||
|
|
||||||
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
||||||
if s.Root.Metrics != nil {
|
if s.Root.Metrics != nil {
|
||||||
@@ -7096,22 +7096,6 @@ func (s *TimerLayerThreadStore) GetThreadForUser(userId string, teamId string, t
|
|||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TimerLayerThreadStore) GetThreadMentionsForUserPerChannel(userId string, teamId string) (map[string]int64, error) {
|
|
||||||
start := timemodule.Now()
|
|
||||||
|
|
||||||
result, err := s.ThreadStore.GetThreadMentionsForUserPerChannel(userId, teamId)
|
|
||||||
|
|
||||||
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
|
||||||
if s.Root.Metrics != nil {
|
|
||||||
success := "false"
|
|
||||||
if err == nil {
|
|
||||||
success = "true"
|
|
||||||
}
|
|
||||||
s.Root.Metrics.ObserveStoreMethodDuration("ThreadStore.GetThreadMentionsForUserPerChannel", success, elapsed)
|
|
||||||
}
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *TimerLayerThreadStore) GetThreadsForUser(userId string, teamId string, opts model.GetUserThreadsOpts) (*model.Threads, error) {
|
func (s *TimerLayerThreadStore) GetThreadsForUser(userId string, teamId string, opts model.GetUserThreadsOpts) (*model.Threads, error) {
|
||||||
start := timemodule.Now()
|
start := timemodule.Now()
|
||||||
|
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user