MM-46410: adds urgency on mention counts (#20999)
* MM-46410: adds urgency on mention counts We have introduced priority for posts in https://github.com/mattermost/mattermost-webapp/pull/10951. We do need to color the mention badges in the webapp with a prominent color when a mention is posted in an urgent message. A thread has urgent mentions if the root post is marked as urgent, and the replies contain mentions to the user viewing the thread. This PR adds a column, urgentmentioncount, in channelmembers. Furthermore when asking for team/thread mention counts, we also return urgent mention counts for the user. Adds a new table to hold posts priorities Refactors priority out of the props and into the new table We are nilifying Metadata when post.ForPlugin(), which didn't save Priority for a post when Boards was enabled. This commit copies metadata again to the post, so metadata are reinstated. Co-authored-by: Mattermod <mattermod@users.noreply.github.com> Co-authored-by: Vishal Choudhary <vish9812@gmail.com>
Этот коммит содержится в:
@@ -141,7 +141,7 @@ func createEphemeralPost(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
rp = model.AddPostActionCookies(rp, c.App.PostActionCookieSecret())
|
||||
rp = c.App.PreparePostForClientWithEmbedsAndImages(c.AppContext, rp, true, false)
|
||||
rp = c.App.PreparePostForClientWithEmbedsAndImages(c.AppContext, rp, true, false, true)
|
||||
rp, err := c.App.SanitizePostMetadataForUser(c.AppContext, rp, c.AppContext.Session().UserId)
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
@@ -420,7 +420,7 @@ func getPost(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
post = c.App.PreparePostForClientWithEmbedsAndImages(c.AppContext, post, false, false)
|
||||
post = c.App.PreparePostForClientWithEmbedsAndImages(c.AppContext, post, false, false, true)
|
||||
post, err = c.App.SanitizePostMetadataForUser(c.AppContext, post, c.AppContext.Session().UserId)
|
||||
if err != nil {
|
||||
c.Err = err
|
||||
@@ -479,7 +479,7 @@ func getPostsByIds(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
post = c.App.PreparePostForClient(c.AppContext, post, false, false)
|
||||
post = c.App.PreparePostForClient(c.AppContext, post, false, false, true)
|
||||
post.StripActionIntegrations()
|
||||
posts = append(posts, post)
|
||||
}
|
||||
|
||||
@@ -61,17 +61,18 @@ func TestGraphQLChannelMembers(t *testing.T) {
|
||||
SchemeManaged bool `json:"schemeManaged"`
|
||||
BuiltIn bool `json:"builtIn"`
|
||||
} `json:"roles"`
|
||||
LastViewedAt float64 `json:"lastViewedAt"`
|
||||
LastUpdateAt float64 `json:"lastUpdateAt"`
|
||||
MsgCount float64 `json:"msgCount"`
|
||||
MentionCount float64 `json:"mentionCount"`
|
||||
MentionCountRoot float64 `json:"mentionCountRoot"`
|
||||
MsgCountRoot float64 `json:"msgCountRoot"`
|
||||
NotifyProps model.StringMap `json:"notifyProps"`
|
||||
SchemeGuest bool `json:"schemeGuest"`
|
||||
SchemeUser bool `json:"schemeUser"`
|
||||
SchemeAdmin bool `json:"schemeAdmin"`
|
||||
Cursor string `json:"cursor"`
|
||||
LastViewedAt float64 `json:"lastViewedAt"`
|
||||
LastUpdateAt float64 `json:"lastUpdateAt"`
|
||||
MsgCount float64 `json:"msgCount"`
|
||||
MentionCount float64 `json:"mentionCount"`
|
||||
MentionCountRoot float64 `json:"mentionCountRoot"`
|
||||
UrgentMentionCount float64 `json:"urgentMentionCount"`
|
||||
MsgCountRoot float64 `json:"msgCountRoot"`
|
||||
NotifyProps model.StringMap `json:"notifyProps"`
|
||||
SchemeGuest bool `json:"schemeGuest"`
|
||||
SchemeUser bool `json:"schemeUser"`
|
||||
SchemeAdmin bool `json:"schemeAdmin"`
|
||||
Cursor string `json:"cursor"`
|
||||
} `json:"channelMembers"`
|
||||
}
|
||||
|
||||
@@ -101,6 +102,7 @@ func TestGraphQLChannelMembers(t *testing.T) {
|
||||
msgCount
|
||||
mentionCount
|
||||
mentionCountRoot
|
||||
urgentMentionCount
|
||||
msgCountRoot
|
||||
schemeGuest
|
||||
schemeUser
|
||||
@@ -181,6 +183,7 @@ func TestGraphQLChannelMembers(t *testing.T) {
|
||||
msgCount
|
||||
mentionCount
|
||||
mentionCountRoot
|
||||
urgentMentionCount
|
||||
}
|
||||
}
|
||||
`,
|
||||
|
||||
@@ -69,21 +69,22 @@ type Channel {
|
||||
}
|
||||
|
||||
type ChannelMember {
|
||||
channel : Channel
|
||||
user : User
|
||||
roles : [Role]!
|
||||
lastViewedAt : Float!
|
||||
msgCount : Float!
|
||||
mentionCount : Float!
|
||||
mentionCountRoot : Float!
|
||||
msgCountRoot : Float!
|
||||
notifyProps : StringMap!
|
||||
lastUpdateAt : Float!
|
||||
schemeGuest : Boolean!
|
||||
schemeUser : Boolean!
|
||||
schemeAdmin : Boolean!
|
||||
explicitRoles : String!
|
||||
cursor: String
|
||||
channel : Channel
|
||||
user : User
|
||||
roles : [Role]!
|
||||
lastViewedAt : Float!
|
||||
msgCount : Float!
|
||||
mentionCount : Float!
|
||||
urgentMentionCount: Float!
|
||||
mentionCountRoot : Float!
|
||||
msgCountRoot : Float!
|
||||
notifyProps : StringMap!
|
||||
lastUpdateAt : Float!
|
||||
schemeGuest : Boolean!
|
||||
schemeUser : Boolean!
|
||||
schemeAdmin : Boolean!
|
||||
explicitRoles : String!
|
||||
cursor : String
|
||||
}
|
||||
|
||||
# Deliberately omitting password, authData, mfaSecret.
|
||||
|
||||
@@ -5720,10 +5720,12 @@ func TestUpdatePassword(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetThreadsForUser(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
os.Setenv("MM_FEATUREFLAGS_POSTPRIORITY", "true")
|
||||
defer os.Unsetenv("MM_FEATUREFLAGS_POSTPRIORITY")
|
||||
os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
|
||||
defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||
*cfg.ServiceSettings.ThreadAutoFollow = true
|
||||
@@ -5820,7 +5822,49 @@ func TestGetThreadsForUser(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Len(t, uss.Threads, 1)
|
||||
require.Greater(t, uss.Threads[0].Post.DeleteAt, int64(0))
|
||||
})
|
||||
|
||||
t.Run("isUrgent, 1 thread", func(t *testing.T) {
|
||||
testCases := []struct {
|
||||
featureEnabled bool
|
||||
expected bool
|
||||
}{
|
||||
{featureEnabled: true, expected: true},
|
||||
{featureEnabled: false, expected: false},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
func() {
|
||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||
*cfg.ServiceSettings.PostPriority = tc.featureEnabled
|
||||
cfg.FeatureFlags.PostPriority = true
|
||||
})
|
||||
|
||||
client := th.Client
|
||||
|
||||
rpost, resp, err := client.CreatePost(&model.Post{
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
Message: "testMsg",
|
||||
Metadata: &model.PostMetadata{
|
||||
Priority: &model.PostPriority{
|
||||
Priority: model.NewString(model.PostPriorityUrgent),
|
||||
},
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
CheckCreatedStatus(t, resp)
|
||||
_, resp, err = client.CreatePost(&model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply", RootId: rpost.Id})
|
||||
require.NoError(t, err)
|
||||
CheckCreatedStatus(t, resp)
|
||||
|
||||
defer th.App.Srv().Store().Post().PermanentDeleteByUser(th.BasicUser.Id)
|
||||
|
||||
uss, _, err := th.Client.GetUserThreads(th.BasicUser.Id, th.BasicTeam.Id, model.GetUserThreadsOpts{})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, uss.Threads, 1)
|
||||
require.Equal(t, uss.Threads[0].IsUrgent, tc.expected)
|
||||
}()
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("paged, 30 threads", func(t *testing.T) {
|
||||
@@ -6515,13 +6559,19 @@ func TestThreadCounts(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSingleThreadGet(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
os.Setenv("MM_FEATUREFLAGS_POSTPRIORITY", "true")
|
||||
defer os.Unsetenv("MM_FEATUREFLAGS_POSTPRIORITY")
|
||||
os.Setenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS", "true")
|
||||
defer os.Unsetenv("MM_FEATUREFLAGS_COLLAPSEDTHREADS")
|
||||
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||
*cfg.ServiceSettings.ThreadAutoFollow = true
|
||||
*cfg.ServiceSettings.CollapsedThreads = model.CollapsedThreadsDefaultOn
|
||||
*cfg.ServiceSettings.PostPriority = true
|
||||
cfg.FeatureFlags.PostPriority = true
|
||||
})
|
||||
|
||||
client := th.Client
|
||||
@@ -6534,7 +6584,15 @@ func TestSingleThreadGet(t *testing.T) {
|
||||
postAndCheck(t, th.SystemAdminClient, &model.Post{ChannelId: th.BasicChannel.Id, Message: "testReply", RootId: rpost.Id})
|
||||
|
||||
// create another thread to check that we are not returning it by mistake
|
||||
rpost2, _ := postAndCheck(t, client, &model.Post{ChannelId: th.BasicChannel2.Id, Message: "testMsg2"})
|
||||
rpost2, _ := postAndCheck(t, client, &model.Post{
|
||||
ChannelId: th.BasicChannel2.Id,
|
||||
Message: "testMsg2",
|
||||
Metadata: &model.PostMetadata{
|
||||
Priority: &model.PostPriority{
|
||||
Priority: model.NewString(model.PostPriorityUrgent),
|
||||
},
|
||||
},
|
||||
})
|
||||
postAndCheck(t, th.SystemAdminClient, &model.Post{ChannelId: th.BasicChannel2.Id, Message: "testReply", RootId: rpost2.Id})
|
||||
|
||||
// regular user should have two threads with 3 replies total
|
||||
@@ -6546,9 +6604,22 @@ func TestSingleThreadGet(t *testing.T) {
|
||||
require.Equal(t, threads.Threads[0].PostId, tr.PostId)
|
||||
require.Empty(t, tr.Participants[0].Username)
|
||||
|
||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||
*cfg.ServiceSettings.PostPriority = false
|
||||
})
|
||||
|
||||
tr, _, err = th.Client.GetUserThread(th.BasicUser.Id, th.BasicTeam.Id, threads.Threads[0].PostId, true)
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, tr.Participants[0].Username)
|
||||
require.Equal(t, false, tr.IsUrgent)
|
||||
|
||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||
*cfg.ServiceSettings.PostPriority = true
|
||||
})
|
||||
|
||||
tr, _, err = th.Client.GetUserThread(th.BasicUser.Id, th.BasicTeam.Id, threads.Threads[0].PostId, true)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, tr.IsUrgent)
|
||||
}
|
||||
|
||||
func TestMaintainUnreadMentionsInThread(t *testing.T) {
|
||||
|
||||
Ссылка в новой задаче
Block a user