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>
Этот коммит содержится в:
Kyriakos Z
2022-11-24 02:41:23 +02:00
коммит произвёл GitHub
родитель c44d37629a
Коммит 27db854089
32 изменённых файлов: 1483 добавлений и 19 удалений

144
store/sqlstore/post_acknowledgements_store.go Обычный файл
Просмотреть файл

@@ -0,0 +1,144 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package sqlstore
import (
"database/sql"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/store"
sq "github.com/mattermost/squirrel"
"github.com/pkg/errors"
)
type SqlPostAcknowledgementStore struct {
*SqlStore
}
func newSqlPostAcknowledgementStore(sqlStore *SqlStore) store.PostAcknowledgementStore {
return &SqlPostAcknowledgementStore{sqlStore}
}
func (s *SqlPostAcknowledgementStore) Get(postID, userID string) (*model.PostAcknowledgement, error) {
query := s.getQueryBuilder().
Select("PostId", "UserId", "AcknowledgedAt").
From("PostAcknowledgements").
Where(sq.And{
sq.Eq{"PostId": postID},
sq.Eq{"UserId": userID},
sq.NotEq{"AcknowledgedAt": 0},
})
var acknowledgement model.PostAcknowledgement
err := s.GetReplicaX().GetBuilder(&acknowledgement, query)
if err != nil {
if err == sql.ErrNoRows {
return nil, store.NewErrNotFound("PostAcknowledgement", postID)
}
return nil, err
}
return &acknowledgement, nil
}
func (s *SqlPostAcknowledgementStore) Save(postID, userID string, acknowledgedAt int64) (*model.PostAcknowledgement, error) {
if acknowledgedAt == 0 {
acknowledgedAt = model.GetMillis()
}
acknowledgement := &model.PostAcknowledgement{
UserId: userID,
PostId: postID,
AcknowledgedAt: acknowledgedAt,
}
if err := acknowledgement.IsValid(); err != nil {
return nil, err
}
query := s.getQueryBuilder().
Insert("PostAcknowledgements").
Columns("PostId", "UserId", "AcknowledgedAt").
Values(acknowledgement.PostId, acknowledgement.UserId, acknowledgement.AcknowledgedAt)
if s.DriverName() == model.DatabaseDriverMysql {
query = query.SuffixExpr(sq.Expr("ON DUPLICATE KEY UPDATE AcknowledgedAt = ?", acknowledgement.AcknowledgedAt))
} else {
query = query.SuffixExpr(sq.Expr("ON CONFLICT (postid, userid) DO UPDATE SET AcknowledgedAt = ?", acknowledgement.AcknowledgedAt))
}
_, err := s.GetMasterX().ExecBuilder(query)
if err != nil {
return nil, err
}
return acknowledgement, nil
}
func (s *SqlPostAcknowledgementStore) Delete(ack *model.PostAcknowledgement) error {
query := s.getQueryBuilder().
Update("PostAcknowledgements").
Set("AcknowledgedAt", 0).
Where(sq.And{
sq.Eq{"PostId": ack.PostId},
sq.Eq{"UserId": ack.UserId},
})
_, err := s.GetMasterX().ExecBuilder(query)
if err != nil {
return err
}
return nil
}
func (s *SqlPostAcknowledgementStore) GetForPost(postID string) ([]*model.PostAcknowledgement, error) {
var acknowledgements []*model.PostAcknowledgement
query := s.getQueryBuilder().
Select("PostId", "UserId", "AcknowledgedAt").
From("PostAcknowledgements").
Where(sq.And{
sq.NotEq{"AcknowledgedAt": 0},
sq.Eq{"PostId": postID},
})
err := s.GetReplicaX().SelectBuilder(&acknowledgements, query)
if err != nil {
return nil, errors.Wrapf(err, "failed to get PostAcknowledgements for postID=%s", postID)
}
return acknowledgements, nil
}
func (s *SqlPostAcknowledgementStore) GetForPosts(postIds []string) ([]*model.PostAcknowledgement, error) {
var acknowledgements []*model.PostAcknowledgement
perPage := 200
for i := 0; i < len(postIds); i += perPage {
j := i + perPage
if len(postIds) < j {
j = len(postIds)
}
query := s.getQueryBuilder().
Select("PostId", "UserId", "AcknowledgedAt").
From("PostAcknowledgements").
Where(sq.And{
sq.Eq{"PostId": postIds[i:j]},
sq.NotEq{"AcknowledgedAt": 0},
})
var acknowledgementsBatch []*model.PostAcknowledgement
err := s.GetReplicaX().SelectBuilder(&acknowledgementsBatch, query)
if err != nil {
return nil, errors.Wrapf(err, "failed to get PostAcknowledgements for post list")
}
acknowledgements = append(acknowledgements, acknowledgementsBatch...)
}
return acknowledgements, nil
}

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

@@ -0,0 +1,14 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package sqlstore
import (
"testing"
"github.com/mattermost/mattermost-server/v6/store/storetest"
)
func TestPostAcknowledgementsStore(t *testing.T) {
StoreTestWithSqlStore(t, storetest.TestPostAcknowledgementsStore)
}

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

@@ -110,6 +110,7 @@ type SqlStoreStores struct {
sharedchannel store.SharedChannelStore
notifyAdmin store.NotifyAdminStore
postPriority store.PostPriorityStore
postAcknowledgement store.PostAcknowledgementStore
}
type SqlStore struct {
@@ -216,6 +217,7 @@ func New(settings model.SqlSettings, metrics einterfaces.MetricsInterface) *SqlS
store.stores.productNotices = newSqlProductNoticesStore(store)
store.stores.notifyAdmin = newSqlNotifyAdminStore(store)
store.stores.postPriority = newSqlPostPriorityStore(store)
store.stores.postAcknowledgement = newSqlPostAcknowledgementStore(store)
store.stores.preference.(*SqlPreferenceStore).deleteUnusedFeatures()
@@ -961,6 +963,10 @@ func (ss *SqlStore) PostPriority() store.PostPriorityStore {
return ss.stores.postPriority
}
func (ss *SqlStore) PostAcknowledgement() store.PostAcknowledgementStore {
return ss.stores.postAcknowledgement
}
func (ss *SqlStore) DropAllTables() {
if ss.DriverName() == model.DatabaseDriverPostgres {
ss.masterX.Exec(`DO