MM-47750: Adds PostAcknowledgements table and apis (#21689)
* 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 two columns, urgentmentioncount, and isurgent, in channelmembers, and threads tables respectively. Furthermore when asking for team/thread mention counts, we also return urgent mention counts for the user. * Fixes method in tests * empty commit * Fixes method call * Fixes single thread response is_urgent * Fixes errors * Fixes mysql migration and adds graphql schema * Fixes tests * Refactors IsUrgent and Adds PostsPriority table Changes: - removes is_urgent from the threads table - adds a new table to hold posts priorities - refactors priority out of the props and into the new table * Fixes * Adds translation strings * Fixes migrations and tests * Fixes tests * empty * Adds Priority to Copy * empty * Fixes priority not saved when boards is enabled 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. * Fixes tests * Adding store tests and fixes syntax error * Uses threads.ThreadTeamId * Fixes error * Adds UrgentMentionCount in graphql api test * Fetches post priority in batches * Addresses review comments * Restore only priority on create post * Fixes tests * Nits * Some refactoring * Fixes get thread options when post priority enabled * Adds missing translation * Use the constant instead of "urgent" string * Renames urgent constant * MM-47750: Adds PostAcknowledgements table and apis - Adds post acknowledgement api/app/store methods to be able to save and delete post acknowledgements by users. - Adds wesbsocket events for acknowledgement created/deleted - Returns post acknowledgements in the post's metadata * Empty * Fixes incorrect urgent count when marking a post as unread * Adds license * Fixes ACK api, and adds tests * Fixes vet * Fixes tests * Addresses review comments * Remove unnecessary lines * Adds config option and changes return of delete ack * Empty * Empty * Enable config by default * Fixes intl * Fixes test after setting config default true * Changes endpoints to PostForUser * Avoids replica lag * Fixes error in merge * Fixes RetryLayer tests due to merge * Empty * Empty * Empty Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
@@ -509,6 +509,7 @@ type AppIface interface {
|
||||
DeactivateGuests(c *request.Context) *model.AppError
|
||||
DeactivateMfa(userID string) *model.AppError
|
||||
DeauthorizeOAuthAppForUser(userID, appID string) *model.AppError
|
||||
DeleteAcknowledgementForPost(c *request.Context, postID, userID string) *model.AppError
|
||||
DeleteAllExpiredPluginKeys() *model.AppError
|
||||
DeleteAllKeysForPlugin(pluginID string) *model.AppError
|
||||
DeleteBrandImage() *model.AppError
|
||||
@@ -567,6 +568,8 @@ type AppIface interface {
|
||||
GenerateMfaSecret(userID string) (*model.MfaSecret, *model.AppError)
|
||||
GeneratePublicLink(siteURL string, info *model.FileInfo) string
|
||||
GenerateSupportPacket() []model.FileData
|
||||
GetAcknowledgementsForPost(postID string) ([]*model.PostAcknowledgement, *model.AppError)
|
||||
GetAcknowledgementsForPostList(postList *model.PostList) (map[string][]*model.PostAcknowledgement, *model.AppError)
|
||||
GetActivePluginManifests() ([]*model.Manifest, *model.AppError)
|
||||
GetAllChannels(c request.CTX, page, perPage int, opts model.ChannelSearchOpts) (model.ChannelListWithTeamData, *model.AppError)
|
||||
GetAllChannelsCount(c request.CTX, opts model.ChannelSearchOpts) (int64, *model.AppError)
|
||||
@@ -984,6 +987,7 @@ type AppIface interface {
|
||||
SanitizeProfile(user *model.User, asAdmin bool)
|
||||
SanitizeTeam(session model.Session, team *model.Team) *model.Team
|
||||
SanitizeTeams(session model.Session, teams []*model.Team) []*model.Team
|
||||
SaveAcknowledgementForPost(c *request.Context, postID, userID string) (*model.PostAcknowledgement, *model.AppError)
|
||||
SaveAdminNotification(userId string, notifyData *model.NotifyAdminToUpgradeRequest) *model.AppError
|
||||
SaveAdminNotifyData(data *model.NotifyAdminData) (*model.NotifyAdminData, *model.AppError)
|
||||
SaveBrandImage(imageData *multipart.FileHeader) *model.AppError
|
||||
|
||||
@@ -2838,6 +2838,28 @@ func (a *OpenTracingAppLayer) DefaultChannelNames(c request.CTX) []string {
|
||||
return resultVar0
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) DeleteAcknowledgementForPost(c *request.Context, postID string, userID string) *model.AppError {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.DeleteAcknowledgementForPost")
|
||||
|
||||
a.ctx = newCtx
|
||||
a.app.Srv().Store().SetContext(newCtx)
|
||||
defer func() {
|
||||
a.app.Srv().Store().SetContext(origCtx)
|
||||
a.ctx = origCtx
|
||||
}()
|
||||
|
||||
defer span.Finish()
|
||||
resultVar0 := a.app.DeleteAcknowledgementForPost(c, postID, userID)
|
||||
|
||||
if resultVar0 != nil {
|
||||
span.LogFields(spanlog.Error(resultVar0))
|
||||
ext.Error.Set(span, true)
|
||||
}
|
||||
|
||||
return resultVar0
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) DeleteAllExpiredPluginKeys() *model.AppError {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.DeleteAllExpiredPluginKeys")
|
||||
@@ -4411,6 +4433,50 @@ func (a *OpenTracingAppLayer) GenerateSupportPacket() []model.FileData {
|
||||
return resultVar0
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) GetAcknowledgementsForPost(postID string) ([]*model.PostAcknowledgement, *model.AppError) {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetAcknowledgementsForPost")
|
||||
|
||||
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.GetAcknowledgementsForPost(postID)
|
||||
|
||||
if resultVar1 != nil {
|
||||
span.LogFields(spanlog.Error(resultVar1))
|
||||
ext.Error.Set(span, true)
|
||||
}
|
||||
|
||||
return resultVar0, resultVar1
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) GetAcknowledgementsForPostList(postList *model.PostList) (map[string][]*model.PostAcknowledgement, *model.AppError) {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetAcknowledgementsForPostList")
|
||||
|
||||
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.GetAcknowledgementsForPostList(postList)
|
||||
|
||||
if resultVar1 != nil {
|
||||
span.LogFields(spanlog.Error(resultVar1))
|
||||
ext.Error.Set(span, true)
|
||||
}
|
||||
|
||||
return resultVar0, resultVar1
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) GetActivePluginManifests() ([]*model.Manifest, *model.AppError) {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetActivePluginManifests")
|
||||
@@ -14312,6 +14378,28 @@ func (a *OpenTracingAppLayer) SanitizeTeams(session model.Session, teams []*mode
|
||||
return resultVar0
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) SaveAcknowledgementForPost(c *request.Context, postID string, userID string) (*model.PostAcknowledgement, *model.AppError) {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SaveAcknowledgementForPost")
|
||||
|
||||
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.SaveAcknowledgementForPost(c, postID, userID)
|
||||
|
||||
if resultVar1 != nil {
|
||||
span.LogFields(spanlog.Error(resultVar1))
|
||||
ext.Error.Set(span, true)
|
||||
}
|
||||
|
||||
return resultVar0, resultVar1
|
||||
}
|
||||
|
||||
func (a *OpenTracingAppLayer) SaveAdminNotification(userId string, notifyData *model.NotifyAdminToUpgradeRequest) *model.AppError {
|
||||
origCtx := a.ctx
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SaveAdminNotification")
|
||||
|
||||
130
app/post_acknowledgements.go
Обычный файл
130
app/post_acknowledgements.go
Обычный файл
@@ -0,0 +1,130 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package app
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/app/request"
|
||||
"github.com/mattermost/mattermost-server/v6/model"
|
||||
"github.com/mattermost/mattermost-server/v6/shared/mlog"
|
||||
"github.com/mattermost/mattermost-server/v6/store"
|
||||
)
|
||||
|
||||
func (a *App) SaveAcknowledgementForPost(c *request.Context, postID, userID string) (*model.PostAcknowledgement, *model.AppError) {
|
||||
post, err := a.GetSinglePost(postID, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
channel, err := a.GetChannel(c, post.ChannelId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if channel.DeleteAt > 0 {
|
||||
return nil, model.NewAppError("SaveAcknowledgementForPost", "api.acknowledgement.save.archived_channel.app_error", nil, "", http.StatusForbidden)
|
||||
}
|
||||
|
||||
acknowledgedAt := model.GetMillis()
|
||||
acknowledgement, nErr := a.Srv().Store().PostAcknowledgement().Save(postID, userID, acknowledgedAt)
|
||||
|
||||
if nErr != nil {
|
||||
var appErr *model.AppError
|
||||
switch {
|
||||
case errors.As(nErr, &appErr):
|
||||
return nil, appErr
|
||||
default:
|
||||
return nil, model.NewAppError("SaveAcknowledgementForPost", "app.acknowledgement.save.save.app_error", nil, "", http.StatusInternalServerError).Wrap(nErr)
|
||||
}
|
||||
}
|
||||
|
||||
a.Srv().Go(func() {
|
||||
a.sendAcknowledgementEvent(model.WebsocketEventAcknowledgementAdded, acknowledgement, post)
|
||||
})
|
||||
|
||||
return acknowledgement, nil
|
||||
}
|
||||
|
||||
func (a *App) DeleteAcknowledgementForPost(c *request.Context, postID, userID string) *model.AppError {
|
||||
post, err := a.GetSinglePost(postID, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
channel, err := a.GetChannel(c, post.ChannelId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if channel.DeleteAt > 0 {
|
||||
return model.NewAppError("DeleteAcknowledgementForPost", "api.acknowledgement.delete.archived_channel.app_error", nil, "", http.StatusForbidden)
|
||||
}
|
||||
|
||||
oldAck, nErr := a.Srv().Store().PostAcknowledgement().Get(postID, userID)
|
||||
|
||||
if nErr != nil {
|
||||
var nfErr *store.ErrNotFound
|
||||
switch {
|
||||
case errors.As(nErr, &nfErr):
|
||||
return model.NewAppError("GetPostAcknowledgement", "app.acknowledgement.get.app_error", nil, "", http.StatusNotFound).Wrap(nErr)
|
||||
default:
|
||||
return model.NewAppError("GetPostAcknowledgement", "app.acknowledgement.get.app_error", nil, "", http.StatusInternalServerError).Wrap(nErr)
|
||||
}
|
||||
}
|
||||
|
||||
if model.GetMillis()-oldAck.AcknowledgedAt > 5*60*1000 {
|
||||
return model.NewAppError("DeleteAcknowledgementForPost", "api.acknowledgement.delete.deadline.app_error", nil, "", http.StatusForbidden)
|
||||
}
|
||||
|
||||
nErr = a.Srv().Store().PostAcknowledgement().Delete(oldAck)
|
||||
if nErr != nil {
|
||||
return model.NewAppError("DeleteAcknowledgementForPost", "app.acknowledgement.delete.app_error", nil, "", http.StatusInternalServerError).Wrap(nErr)
|
||||
}
|
||||
|
||||
a.Srv().Go(func() {
|
||||
a.sendAcknowledgementEvent(model.WebsocketEventAcknowledgementRemoved, oldAck, post)
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *App) GetAcknowledgementsForPost(postID string) ([]*model.PostAcknowledgement, *model.AppError) {
|
||||
acknowledgements, nErr := a.Srv().Store().PostAcknowledgement().GetForPost(postID)
|
||||
if nErr != nil {
|
||||
return nil, model.NewAppError("GetAcknowledgementsForPost", "app.acknowledgement.getforpost.get.app_error", nil, "", http.StatusInternalServerError).Wrap(nErr)
|
||||
}
|
||||
|
||||
return acknowledgements, nil
|
||||
}
|
||||
|
||||
func (a *App) GetAcknowledgementsForPostList(postList *model.PostList) (map[string][]*model.PostAcknowledgement, *model.AppError) {
|
||||
acknowledgements, err := a.Srv().Store().PostAcknowledgement().GetForPosts(postList.Order)
|
||||
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("GetPostAcknowledgementsForPostList", "app.acknowledgement.get.app_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
||||
}
|
||||
|
||||
acknowledgementsMap := make(map[string][]*model.PostAcknowledgement)
|
||||
|
||||
for _, ack := range acknowledgements {
|
||||
acknowledgementsMap[ack.PostId] = append(acknowledgementsMap[ack.PostId], ack)
|
||||
}
|
||||
|
||||
return acknowledgementsMap, nil
|
||||
}
|
||||
|
||||
func (a *App) sendAcknowledgementEvent(event string, acknowledgement *model.PostAcknowledgement, post *model.Post) {
|
||||
// send out that a acknowledgement has been added/removed
|
||||
message := model.NewWebSocketEvent(event, "", post.ChannelId, "", nil, "")
|
||||
|
||||
acknowledgementJSON, err := json.Marshal(acknowledgement)
|
||||
if err != nil {
|
||||
a.Log().Warn("Failed to encode acknowledgement to JSON", mlog.Err(err))
|
||||
}
|
||||
message.Add("acknowledgement", string(acknowledgementJSON))
|
||||
a.Publish(message)
|
||||
}
|
||||
149
app/post_acknowledgements_test.go
Обычный файл
149
app/post_acknowledgements_test.go
Обычный файл
@@ -0,0 +1,149 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
package app
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v6/model"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestPostAcknowledgementsApp(t *testing.T) {
|
||||
t.Run("SaveAcknowledgementForPost", func(t *testing.T) { testSaveAcknowledgementForPost(t) })
|
||||
t.Run("DeleteAcknowledgementForPost", func(t *testing.T) { testDeleteAcknowledgementForPost(t) })
|
||||
t.Run("GetAcknowledgementsForPostList", func(t *testing.T) { testGetAcknowledgementsForPostList(t) })
|
||||
}
|
||||
|
||||
func testSaveAcknowledgementForPost(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
t.Run("save acknowledgment for post should save acknowledgement", func(t *testing.T) {
|
||||
post, err := th.App.CreatePostAsUser(th.Context, &model.Post{
|
||||
UserId: th.BasicUser.Id,
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
Message: "message",
|
||||
}, "", true)
|
||||
|
||||
require.Nil(t, err)
|
||||
|
||||
acknowledgment, err := th.App.SaveAcknowledgementForPost(th.Context, post.Id, th.BasicUser.Id)
|
||||
require.Nil(t, err)
|
||||
|
||||
require.Greater(t, acknowledgment.AcknowledgedAt, int64(0))
|
||||
require.Equal(t, post.Id, acknowledgment.PostId)
|
||||
require.Equal(t, th.BasicUser.Id, acknowledgment.UserId)
|
||||
})
|
||||
}
|
||||
|
||||
func testDeleteAcknowledgementForPost(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
post, err := th.App.CreatePostAsUser(th.Context, &model.Post{
|
||||
UserId: th.BasicUser.Id,
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
CreateAt: model.GetMillis(),
|
||||
Message: "message",
|
||||
}, "", true)
|
||||
require.Nil(t, err)
|
||||
|
||||
t.Run("delete acknowledgment for post should delete acknowledgement", func(t *testing.T) {
|
||||
_, err = th.App.SaveAcknowledgementForPost(th.Context, post.Id, th.BasicUser.Id)
|
||||
require.Nil(t, err)
|
||||
|
||||
acknowledgments, err := th.App.GetAcknowledgementsForPost(post.Id)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, acknowledgments, 1)
|
||||
require.Greater(t, acknowledgments[0].AcknowledgedAt, int64(0))
|
||||
|
||||
err = th.App.DeleteAcknowledgementForPost(th.Context, post.Id, th.BasicUser.Id)
|
||||
require.Nil(t, err)
|
||||
|
||||
acknowledgments, err = th.App.GetAcknowledgementsForPost(post.Id)
|
||||
require.Nil(t, err)
|
||||
require.Empty(t, acknowledgments)
|
||||
})
|
||||
|
||||
t.Run("delete acknowledgment for post after 5 min after acknowledged should not delete", func(t *testing.T) {
|
||||
_, nErr := th.App.Srv().Store().PostAcknowledgement().Save(post.Id, th.BasicUser.Id, model.GetMillis()-int64(6*60*1000))
|
||||
require.NoError(t, nErr)
|
||||
|
||||
acknowledgments, err := th.App.GetAcknowledgementsForPost(post.Id)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, acknowledgments, 1)
|
||||
require.Greater(t, acknowledgments[0].AcknowledgedAt, int64(0))
|
||||
|
||||
err = th.App.DeleteAcknowledgementForPost(th.Context, post.Id, th.BasicUser.Id)
|
||||
require.NotNil(t, err)
|
||||
require.Equal(t, 403, err.StatusCode)
|
||||
|
||||
acknowledgments, err = th.App.GetAcknowledgementsForPost(post.Id)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, acknowledgments, 1)
|
||||
require.Greater(t, acknowledgments[0].AcknowledgedAt, int64(0))
|
||||
})
|
||||
}
|
||||
|
||||
func testGetAcknowledgementsForPostList(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
p1, err := th.App.CreatePostAsUser(th.Context, &model.Post{
|
||||
UserId: th.BasicUser.Id,
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
CreateAt: model.GetMillis(),
|
||||
Message: "message",
|
||||
}, "", true)
|
||||
require.Nil(t, err)
|
||||
|
||||
p2, err := th.App.CreatePostAsUser(th.Context, &model.Post{
|
||||
UserId: th.BasicUser.Id,
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
CreateAt: model.GetMillis(),
|
||||
Message: "message",
|
||||
}, "", true)
|
||||
require.Nil(t, err)
|
||||
|
||||
p3, err := th.App.CreatePostAsUser(th.Context, &model.Post{
|
||||
UserId: th.BasicUser.Id,
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
CreateAt: model.GetMillis(),
|
||||
Message: "message",
|
||||
}, "", true)
|
||||
require.Nil(t, err)
|
||||
|
||||
t.Run("get acknowledgments for post list should return a map", func(t *testing.T) {
|
||||
_, err = th.App.SaveAcknowledgementForPost(th.Context, p1.Id, th.BasicUser.Id)
|
||||
require.Nil(t, err)
|
||||
_, err = th.App.SaveAcknowledgementForPost(th.Context, p2.Id, th.BasicUser.Id)
|
||||
require.Nil(t, err)
|
||||
_, err = th.App.SaveAcknowledgementForPost(th.Context, p1.Id, th.BasicUser2.Id)
|
||||
require.Nil(t, err)
|
||||
|
||||
postList := model.NewPostList()
|
||||
postList.AddPost(p1)
|
||||
postList.AddOrder(p1.Id)
|
||||
postList.AddPost(p2)
|
||||
postList.AddOrder(p2.Id)
|
||||
postList.AddPost(p3)
|
||||
postList.AddOrder(p3.Id)
|
||||
|
||||
acks1, err := th.App.GetAcknowledgementsForPost(p1.Id)
|
||||
require.Nil(t, err)
|
||||
acks2, err := th.App.GetAcknowledgementsForPost(p2.Id)
|
||||
require.Nil(t, err)
|
||||
|
||||
acknowledgementsMap, err := th.App.GetAcknowledgementsForPostList(postList)
|
||||
require.Nil(t, err)
|
||||
|
||||
expected := map[string][]*model.PostAcknowledgement{
|
||||
p1.Id: acks1,
|
||||
p2.Id: acks2,
|
||||
}
|
||||
require.Equal(t, expected, acknowledgementsMap)
|
||||
require.Len(t, acknowledgementsMap[p1.Id], 2)
|
||||
require.Len(t, acknowledgementsMap[p2.Id], 1)
|
||||
require.Nil(t, acknowledgementsMap[p3.Id])
|
||||
})
|
||||
}
|
||||
@@ -63,10 +63,15 @@ func (a *App) PreparePostListForClient(c request.CTX, originalList *model.PostLi
|
||||
|
||||
if a.isPostPriorityEnabled() {
|
||||
priority, _ := a.GetPriorityForPostList(list)
|
||||
acknowledgements, _ := a.GetAcknowledgementsForPostList(list)
|
||||
|
||||
for _, id := range list.Order {
|
||||
if _, ok := priority[id]; ok {
|
||||
list.Posts[id].Metadata.Priority = priority[id]
|
||||
}
|
||||
if _, ok := acknowledgements[id]; ok {
|
||||
list.Posts[id].Metadata.Acknowledgements = acknowledgements[id]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,6 +144,13 @@ func (a *App) PreparePostForClient(c request.CTX, originalPost *model.Post, isNe
|
||||
} else {
|
||||
post.Metadata.Priority = priority
|
||||
}
|
||||
|
||||
// Post's acknowledgements if any
|
||||
if acknowledgements, err := a.GetAcknowledgementsForPost(post.Id); err != nil {
|
||||
mlog.Warn("Failed to get post acknowledgements for a post", mlog.String("post_id", post.Id), mlog.Err(err))
|
||||
} else {
|
||||
post.Metadata.Acknowledgements = acknowledgements
|
||||
}
|
||||
}
|
||||
|
||||
return post
|
||||
|
||||
Ссылка в новой задаче
Block a user