From fbee99e870dfea8fe2d17bba42c16d5560177439 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20V=C3=A9lez?= Date: Tue, 5 Nov 2024 14:24:50 +0100 Subject: [PATCH] MM-60124-emit and read create scheduled post WS event (#28844) * MM-60124-emit and read create scheduled post WS event * fix unit test; reorder get team id logic; use userid for ws events * MM-60145 - ws events on update scheduled posts (#28871) * MM-60145 - ws events on update scheduled posts * MM-60147 - ws events on delete scheduled posts (#28872) * MM-60147 - ws events on delete scheduled posts * remove unnecessary channelID * remove unnecesary memoization --- server/channels/api4/scheduled_post.go | 8 ++- server/channels/app/app_iface.go | 4 +- .../app/opentracing/opentracing_layer.go | 8 +-- server/channels/app/scheduled_post.go | 27 ++++++++-- server/channels/app/scheduled_post_test.go | 52 +++++++++--------- server/public/model/websocket_message.go | 3 ++ .../src/actions/websocket_actions.jsx | 53 +++++++++++++++++++ .../src/selectors/entities/teams.ts | 9 ++++ webapp/channels/src/utils/constants.tsx | 3 ++ 9 files changed, 130 insertions(+), 37 deletions(-) diff --git a/server/channels/api4/scheduled_post.go b/server/channels/api4/scheduled_post.go index 254ec1968e..5712766e10 100644 --- a/server/channels/api4/scheduled_post.go +++ b/server/channels/api4/scheduled_post.go @@ -61,6 +61,8 @@ func createSchedulePost(c *Context, w http.ResponseWriter, r *http.Request) { return } + connectionID := r.Header.Get(model.ConnectionId) + var scheduledPost model.ScheduledPost if err := json.NewDecoder(r.Body).Decode(&scheduledPost); err != nil { c.SetInvalidParamWithErr("schedule_post", err) @@ -78,7 +80,7 @@ func createSchedulePost(c *Context, w http.ResponseWriter, r *http.Request) { return } - createdScheduledPost, appErr := c.App.SaveScheduledPost(c.AppContext, &scheduledPost) + createdScheduledPost, appErr := c.App.SaveScheduledPost(c.AppContext, &scheduledPost, connectionID) if appErr != nil { c.Err = appErr return @@ -145,6 +147,8 @@ func updateScheduledPost(c *Context, w http.ResponseWriter, r *http.Request) { return } + connectionID := r.Header.Get(model.ConnectionId) + scheduledPostId := mux.Vars(r)["scheduled_post_id"] if scheduledPostId == "" { c.SetInvalidURLParam("scheduled_post_id") @@ -172,7 +176,7 @@ func updateScheduledPost(c *Context, w http.ResponseWriter, r *http.Request) { } userId := c.AppContext.Session().UserId - updatedScheduledPost, appErr := c.App.UpdateScheduledPost(c.AppContext, userId, &scheduledPost) + updatedScheduledPost, appErr := c.App.UpdateScheduledPost(c.AppContext, userId, &scheduledPost, connectionID) if appErr != nil { c.Err = appErr return diff --git a/server/channels/app/app_iface.go b/server/channels/app/app_iface.go index 91148ca0da..6cf92b035d 100644 --- a/server/channels/app/app_iface.go +++ b/server/channels/app/app_iface.go @@ -1070,7 +1070,7 @@ type AppIface interface { SaveComplianceReport(rctx request.CTX, job *model.Compliance) (*model.Compliance, *model.AppError) SaveReactionForPost(c request.CTX, reaction *model.Reaction) (*model.Reaction, *model.AppError) SaveReportChunk(format string, prefix string, count int, reportData []model.ReportableObject) *model.AppError - SaveScheduledPost(rctx request.CTX, scheduledPost *model.ScheduledPost) (*model.ScheduledPost, *model.AppError) + SaveScheduledPost(rctx request.CTX, scheduledPost *model.ScheduledPost, connectionId string) (*model.ScheduledPost, *model.AppError) SaveSharedChannelRemote(remote *model.SharedChannelRemote) (*model.SharedChannelRemote, error) SaveUserTermsOfService(userID, termsOfServiceId string, accepted bool) *model.AppError SchemesIterator(scope string, batchSize int) func() []*model.Scheme @@ -1207,7 +1207,7 @@ type AppIface interface { UpdateRemoteCluster(rc *model.RemoteCluster) (*model.RemoteCluster, *model.AppError) UpdateRemoteClusterTopics(remoteClusterId string, topics string) (*model.RemoteCluster, *model.AppError) UpdateRole(role *model.Role) (*model.Role, *model.AppError) - UpdateScheduledPost(rctx request.CTX, userId string, scheduledPost *model.ScheduledPost) (*model.ScheduledPost, *model.AppError) + UpdateScheduledPost(rctx request.CTX, userId string, scheduledPost *model.ScheduledPost, connectionId string) (*model.ScheduledPost, *model.AppError) UpdateScheme(scheme *model.Scheme) (*model.Scheme, *model.AppError) UpdateSharedChannel(sc *model.SharedChannel) (*model.SharedChannel, error) UpdateSharedChannelRemoteCursor(id string, cursor model.GetPostsSinceForSyncCursor) error diff --git a/server/channels/app/opentracing/opentracing_layer.go b/server/channels/app/opentracing/opentracing_layer.go index b4e0a7aded..ee3e66c70b 100644 --- a/server/channels/app/opentracing/opentracing_layer.go +++ b/server/channels/app/opentracing/opentracing_layer.go @@ -15570,7 +15570,7 @@ func (a *OpenTracingAppLayer) SaveReportChunk(format string, prefix string, coun return resultVar0 } -func (a *OpenTracingAppLayer) SaveScheduledPost(rctx request.CTX, scheduledPost *model.ScheduledPost) (*model.ScheduledPost, *model.AppError) { +func (a *OpenTracingAppLayer) SaveScheduledPost(rctx request.CTX, scheduledPost *model.ScheduledPost, connectionId string) (*model.ScheduledPost, *model.AppError) { origCtx := a.ctx span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SaveScheduledPost") @@ -15582,7 +15582,7 @@ func (a *OpenTracingAppLayer) SaveScheduledPost(rctx request.CTX, scheduledPost }() defer span.Finish() - resultVar0, resultVar1 := a.app.SaveScheduledPost(rctx, scheduledPost) + resultVar0, resultVar1 := a.app.SaveScheduledPost(rctx, scheduledPost, connectionId) if resultVar1 != nil { span.LogFields(spanlog.Error(resultVar1)) @@ -18771,7 +18771,7 @@ func (a *OpenTracingAppLayer) UpdateRole(role *model.Role) (*model.Role, *model. return resultVar0, resultVar1 } -func (a *OpenTracingAppLayer) UpdateScheduledPost(rctx request.CTX, userId string, scheduledPost *model.ScheduledPost) (*model.ScheduledPost, *model.AppError) { +func (a *OpenTracingAppLayer) UpdateScheduledPost(rctx request.CTX, userId string, scheduledPost *model.ScheduledPost, connectionId string) (*model.ScheduledPost, *model.AppError) { origCtx := a.ctx span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.UpdateScheduledPost") @@ -18783,7 +18783,7 @@ func (a *OpenTracingAppLayer) UpdateScheduledPost(rctx request.CTX, userId strin }() defer span.Finish() - resultVar0, resultVar1 := a.app.UpdateScheduledPost(rctx, userId, scheduledPost) + resultVar0, resultVar1 := a.app.UpdateScheduledPost(rctx, userId, scheduledPost, connectionId) if resultVar1 != nil { span.LogFields(spanlog.Error(resultVar1)) diff --git a/server/channels/app/scheduled_post.go b/server/channels/app/scheduled_post.go index 0a8efa471c..d7844710b9 100644 --- a/server/channels/app/scheduled_post.go +++ b/server/channels/app/scheduled_post.go @@ -4,13 +4,15 @@ package app import ( + "encoding/json" "net/http" "github.com/mattermost/mattermost/server/public/model" + "github.com/mattermost/mattermost/server/public/shared/mlog" "github.com/mattermost/mattermost/server/public/shared/request" ) -func (a *App) SaveScheduledPost(rctx request.CTX, scheduledPost *model.ScheduledPost) (*model.ScheduledPost, *model.AppError) { +func (a *App) SaveScheduledPost(rctx request.CTX, scheduledPost *model.ScheduledPost, connectionId string) (*model.ScheduledPost, *model.AppError) { maxMessageLength := a.Srv().Store().ScheduledPost().GetMaxMessageSize() scheduledPost.PreSave() if validationErr := scheduledPost.IsValid(maxMessageLength); validationErr != nil { @@ -32,7 +34,7 @@ func (a *App) SaveScheduledPost(rctx request.CTX, scheduledPost *model.Scheduled return nil, model.NewAppError("App.ScheduledPost", "app.save_scheduled_post.save.app_error", map[string]any{"user_id": scheduledPost.UserId, "channel_id": scheduledPost.ChannelId}, "", http.StatusBadRequest) } - // TODO: add WebSocket event broadcast here + publishScheduledPostEvent(a, rctx, model.WebsocketScheduledPostCreated, savedScheduledPost, connectionId) return savedScheduledPost, nil } @@ -54,7 +56,7 @@ func (a *App) GetUserTeamScheduledPosts(rctx request.CTX, userId, teamId string) return scheduledPosts, nil } -func (a *App) UpdateScheduledPost(rctx request.CTX, userId string, scheduledPost *model.ScheduledPost) (*model.ScheduledPost, *model.AppError) { +func (a *App) UpdateScheduledPost(rctx request.CTX, userId string, scheduledPost *model.ScheduledPost, connectionId string) (*model.ScheduledPost, *model.AppError) { maxMessageLength := a.Srv().Store().ScheduledPost().GetMaxMessageSize() scheduledPost.PreUpdate() if validationErr := scheduledPost.IsValid(maxMessageLength); validationErr != nil { @@ -83,7 +85,7 @@ func (a *App) UpdateScheduledPost(rctx request.CTX, userId string, scheduledPost return nil, model.NewAppError("app.UpdateScheduledPost", "app.update_scheduled_post.update.error", map[string]any{"user_id": userId, "scheduled_post_id": scheduledPost.Id}, "", http.StatusInternalServerError) } - // TODO: add WebSocket event broadcast here. This will be done in a later PR + publishScheduledPostEvent(a, rctx, model.WebsocketScheduledPostUpdated, scheduledPost, connectionId) return scheduledPost, nil } @@ -106,7 +108,22 @@ func (a *App) DeleteScheduledPost(rctx request.CTX, userId, scheduledPostId, con return nil, model.NewAppError("app.DeleteScheduledPost", "app.delete_scheduled_post.delete_error", map[string]any{"user_id": userId, "scheduled_post_id": scheduledPostId}, "", http.StatusInternalServerError) } - // TODO: add WebSocket event broadcast here. This will be done in a later PR + publishScheduledPostEvent(a, rctx, model.WebsocketScheduledPostDeleted, scheduledPost, connectionId) return scheduledPost, nil } + +func publishScheduledPostEvent(a *App, rctx request.CTX, eventType model.WebsocketEventType, scheduledPost *model.ScheduledPost, connectionId string) { + if scheduledPost == nil { + rctx.Logger().Warn("publishScheduledPostEvent called with nil scheduledPost") + return + } + message := model.NewWebSocketEvent(eventType, "", "", scheduledPost.UserId, nil, connectionId) + scheduledPostJSON, jsonErr := json.Marshal(scheduledPost) + if jsonErr != nil { + rctx.Logger().Warn("publishScheduledPostEvent - Failed to Marshal", mlog.Err(jsonErr)) + return + } + message.Add("scheduledPost", string(scheduledPostJSON)) + a.Publish(message) +} diff --git a/server/channels/app/scheduled_post_test.go b/server/channels/app/scheduled_post_test.go index 4356628f43..4268218e5b 100644 --- a/server/channels/app/scheduled_post_test.go +++ b/server/channels/app/scheduled_post_test.go @@ -14,6 +14,7 @@ import ( func TestSaveScheduledPost(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() + user1ConnID := model.NewId() t.Run("base case", func(t *testing.T) { userId := model.NewId() @@ -48,7 +49,7 @@ func TestSaveScheduledPost(t *testing.T) { }, ScheduledAt: model.GetMillis() + 100000, // 100 seconds in the future } - createdScheduledPost, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost) + createdScheduledPost, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost, user1ConnID) require.Nil(t, appErr) require.NotNil(t, createdScheduledPost) }) @@ -57,7 +58,7 @@ func TestSaveScheduledPost(t *testing.T) { scheduledPost := &model.ScheduledPost{ // a completely empty scheduled post } - createdScheduledPost, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost) + createdScheduledPost, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost, user1ConnID) require.NotNil(t, appErr) require.Nil(t, createdScheduledPost) }) @@ -74,7 +75,7 @@ func TestSaveScheduledPost(t *testing.T) { }, ScheduledAt: model.GetMillis() - 100000, // 100 seconds in the past } - createdScheduledPost, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost) + createdScheduledPost, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost, user1ConnID) require.NotNil(t, appErr) require.Nil(t, createdScheduledPost) }) @@ -93,7 +94,7 @@ func TestSaveScheduledPost(t *testing.T) { }, ScheduledAt: model.GetMillis() + 100000, // 100 seconds in the future } - createdScheduledPost, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost) + createdScheduledPost, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost, user1ConnID) require.NotNil(t, appErr) require.Nil(t, createdScheduledPost) }) @@ -134,7 +135,7 @@ func TestSaveScheduledPost(t *testing.T) { }, ScheduledAt: model.GetMillis() + 100000, // 100 seconds in the future } - createdScheduledPost, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost) + createdScheduledPost, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost, user1ConnID) require.NotNil(t, appErr) require.Nil(t, createdScheduledPost) }) @@ -172,13 +173,13 @@ func TestSaveScheduledPost(t *testing.T) { }, ScheduledAt: model.GetMillis() + 100000, // 100 seconds in the future } - createdScheduledPost, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost) + createdScheduledPost, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost, user1ConnID) require.Nil(t, appErr) require.NotNil(t, createdScheduledPost) scheduledPost.Message = "this is a second scheduled post" scheduledPost.Id = model.NewId() - createdScheduledPost, appErr = th.App.SaveScheduledPost(th.Context, scheduledPost) + createdScheduledPost, appErr = th.App.SaveScheduledPost(th.Context, scheduledPost, user1ConnID) require.Nil(t, appErr) require.NotNil(t, createdScheduledPost) }) @@ -215,7 +216,7 @@ func TestSaveScheduledPost(t *testing.T) { }, ScheduledAt: model.GetMillis() + 100000, // 100 seconds in the future } - createdScheduledPost, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost) + createdScheduledPost, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost, user1ConnID) require.NotNil(t, appErr) require.Nil(t, createdScheduledPost) }) @@ -224,6 +225,7 @@ func TestSaveScheduledPost(t *testing.T) { func TestGetUserTeamScheduledPosts(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() + user1ConnID := model.NewId() t.Run("should get created scheduled posts", func(t *testing.T) { t.Skip("https://mattermost.atlassian.net/browse/MM-61523") @@ -236,7 +238,7 @@ func TestGetUserTeamScheduledPosts(t *testing.T) { }, ScheduledAt: model.GetMillis() + 100000, // 100 seconds in the future } - createdScheduledPost1, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost1) + createdScheduledPost1, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost1, user1ConnID) require.Nil(t, appErr) require.NotNil(t, createdScheduledPost1) @@ -249,7 +251,7 @@ func TestGetUserTeamScheduledPosts(t *testing.T) { }, ScheduledAt: model.GetMillis() + 100000, // 100 seconds in the future } - createdScheduledPost2, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost2) + createdScheduledPost2, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost2, user1ConnID) require.Nil(t, appErr) require.NotNil(t, createdScheduledPost2) @@ -282,7 +284,7 @@ func TestGetUserTeamScheduledPosts(t *testing.T) { }, ScheduledAt: model.GetMillis() + 100000, // 100 seconds in the future } - createdScheduledPost1, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost1) + createdScheduledPost1, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost1, user1ConnID) require.Nil(t, appErr) require.NotNil(t, createdScheduledPost1) @@ -295,7 +297,7 @@ func TestGetUserTeamScheduledPosts(t *testing.T) { }, ScheduledAt: model.GetMillis() + 100000, // 100 seconds in the future } - createdScheduledPost2, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost2) + createdScheduledPost2, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost2, user1ConnID) require.Nil(t, appErr) require.NotNil(t, createdScheduledPost2) @@ -335,7 +337,7 @@ func TestGetUserTeamScheduledPosts(t *testing.T) { }, ScheduledAt: model.GetMillis() + 100000, // 100 seconds in the future } - createdScheduledPost1, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost1) + createdScheduledPost1, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost1, user1ConnID) require.Nil(t, appErr) require.NotNil(t, createdScheduledPost1) @@ -348,7 +350,7 @@ func TestGetUserTeamScheduledPosts(t *testing.T) { }, ScheduledAt: model.GetMillis() + 100000, // 100 seconds in the future } - createdScheduledPost2, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost2) + createdScheduledPost2, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost2, user1ConnID) require.Nil(t, appErr) require.NotNil(t, createdScheduledPost2) @@ -383,7 +385,7 @@ func TestGetUserTeamScheduledPosts(t *testing.T) { }, ScheduledAt: model.GetMillis() + 100000, // 100 seconds in the future } - createdScheduledPost1, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost1) + createdScheduledPost1, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost1, user1ConnID) require.Nil(t, appErr) require.NotNil(t, createdScheduledPost1) @@ -396,7 +398,7 @@ func TestGetUserTeamScheduledPosts(t *testing.T) { }, ScheduledAt: model.GetMillis() + 100000, // 100 seconds in the future } - createdScheduledPost2, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost2) + createdScheduledPost2, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost2, user1ConnID) require.Nil(t, appErr) require.NotNil(t, createdScheduledPost2) @@ -417,6 +419,7 @@ func TestGetUserTeamScheduledPosts(t *testing.T) { func TestUpdateScheduledPost(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() + user1ConnID := model.NewId() t.Run("base case", func(t *testing.T) { // first we'll create a scheduled post @@ -452,7 +455,7 @@ func TestUpdateScheduledPost(t *testing.T) { }, ScheduledAt: model.GetMillis() + 100000, // 100 seconds in the future } - createdScheduledPost, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost) + createdScheduledPost, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost, user1ConnID) require.Nil(t, appErr) require.NotNil(t, createdScheduledPost) @@ -461,7 +464,7 @@ func TestUpdateScheduledPost(t *testing.T) { createdScheduledPost.ScheduledAt = newScheduledAtTime createdScheduledPost.Message = "Updated Message!!!" - updatedScheduledPost, appErr := th.App.UpdateScheduledPost(th.Context, userId, createdScheduledPost) + updatedScheduledPost, appErr := th.App.UpdateScheduledPost(th.Context, userId, createdScheduledPost, user1ConnID) require.Nil(t, appErr) require.NotNil(t, updatedScheduledPost) @@ -503,7 +506,7 @@ func TestUpdateScheduledPost(t *testing.T) { }, ScheduledAt: model.GetMillis() + 100000, // 100 seconds in the future } - createdScheduledPost, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost) + createdScheduledPost, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost, user1ConnID) require.Nil(t, appErr) require.NotNil(t, createdScheduledPost) @@ -512,7 +515,7 @@ func TestUpdateScheduledPost(t *testing.T) { createdScheduledPost.ScheduledAt = newScheduledAtTime createdScheduledPost.Message = "Updated Message!!!" - updatedScheduledPost, appErr := th.App.UpdateScheduledPost(th.Context, th.BasicUser2.Id, createdScheduledPost) + updatedScheduledPost, appErr := th.App.UpdateScheduledPost(th.Context, th.BasicUser2.Id, createdScheduledPost, user1ConnID) require.NotNil(t, appErr) require.Equal(t, http.StatusForbidden, appErr.StatusCode) require.Nil(t, updatedScheduledPost) @@ -552,7 +555,7 @@ func TestUpdateScheduledPost(t *testing.T) { }, ScheduledAt: model.GetMillis() + 100000, // 100 seconds in the future } - createdScheduledPost, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost) + createdScheduledPost, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost, user1ConnID) require.Nil(t, appErr) require.NotNil(t, createdScheduledPost) @@ -567,7 +570,7 @@ func TestUpdateScheduledPost(t *testing.T) { createdScheduledPost.FileIds = []string{model.NewId(), model.NewId()} createdScheduledPost.ErrorCode = model.ScheduledPostErrorUnknownError - updatedScheduledPost, appErr := th.App.UpdateScheduledPost(th.Context, userId, createdScheduledPost) + updatedScheduledPost, appErr := th.App.UpdateScheduledPost(th.Context, userId, createdScheduledPost, user1ConnID) require.Nil(t, appErr) require.NotNil(t, createdScheduledPost) @@ -583,6 +586,7 @@ func TestUpdateScheduledPost(t *testing.T) { func TestDeleteScheduledPost(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() + user1ConnID := model.NewId() t.Run("base case", func(t *testing.T) { // first we'll create a scheduled post @@ -595,7 +599,7 @@ func TestDeleteScheduledPost(t *testing.T) { }, ScheduledAt: model.GetMillis() + 100000, // 100 seconds in the future } - createdScheduledPost, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost) + createdScheduledPost, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost, user1ConnID) require.Nil(t, appErr) require.NotNil(t, createdScheduledPost) @@ -631,7 +635,7 @@ func TestDeleteScheduledPost(t *testing.T) { }, ScheduledAt: model.GetMillis() + 100000, // 100 seconds in the future } - createdScheduledPost, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost) + createdScheduledPost, appErr := th.App.SaveScheduledPost(th.Context, scheduledPost, user1ConnID) require.Nil(t, appErr) require.NotNil(t, createdScheduledPost) diff --git a/server/public/model/websocket_message.go b/server/public/model/websocket_message.go index a3b94720e3..bf0fb0ebe6 100644 --- a/server/public/model/websocket_message.go +++ b/server/public/model/websocket_message.go @@ -91,6 +91,9 @@ const ( WebsocketEventChannelBookmarkSorted WebsocketEventType = "channel_bookmark_sorted" WebsocketPresenceIndicator WebsocketEventType = "presence" WebsocketPostedNotifyAck WebsocketEventType = "posted_notify_ack" + WebsocketScheduledPostCreated WebsocketEventType = "scheduled_post_created" + WebsocketScheduledPostUpdated WebsocketEventType = "scheduled_post_updated" + WebsocketScheduledPostDeleted WebsocketEventType = "scheduled_post_deleted" ) type WebSocketMessage interface { diff --git a/webapp/channels/src/actions/websocket_actions.jsx b/webapp/channels/src/actions/websocket_actions.jsx index 3ef7532ea7..9e5caa492a 100644 --- a/webapp/channels/src/actions/websocket_actions.jsx +++ b/webapp/channels/src/actions/websocket_actions.jsx @@ -21,6 +21,7 @@ import { CloudTypes, HostedCustomerTypes, ChannelBookmarkTypes, + ScheduledPostTypes, } from 'mattermost-redux/action_types'; import {getStandardAnalytics} from 'mattermost-redux/actions/admin'; import {fetchAppBindings, fetchRHSAppsBindings} from 'mattermost-redux/actions/apps'; @@ -83,6 +84,7 @@ import {getPost, getMostRecentPostIdInChannel, getTeamIdFromPost} from 'mattermo import {isCollapsedThreadsEnabled} from 'mattermost-redux/selectors/entities/preferences'; import {haveISystemPermission, haveITeamPermission} from 'mattermost-redux/selectors/entities/roles'; import { + getTeamIdByChannelId, getMyTeams, getCurrentRelativeTeamUrl, getCurrentTeamId, @@ -609,6 +611,15 @@ export function handleEvent(msg) { case SocketEvents.DRAFT_DELETED: dispatch(handleDeleteDraftEvent(msg)); break; + case SocketEvents.SCHEDULED_POST_CREATED: + dispatch(handleCreateScheduledPostEvent(msg)); + break; + case SocketEvents.SCHEDULED_POST_UPDATED: + dispatch(handleUpdateScheduledPostEvent(msg)); + break; + case SocketEvents.SCHEDULED_POST_DELETED: + dispatch(handleDeleteScheduledPostEvent(msg)); + break; case SocketEvents.PERSISTENT_NOTIFICATION_TRIGGERED: dispatch(handlePersistentNotification(msg)); break; @@ -1748,6 +1759,48 @@ function handleUpsertDraftEvent(msg) { }; } +function handleCreateScheduledPostEvent(msg) { + return async (doDispatch) => { + const scheduledPost = JSON.parse(msg.data.scheduledPost); + const state = getState(); + const teamId = getTeamIdByChannelId(state, scheduledPost.channel_id); + + doDispatch({ + type: ScheduledPostTypes.SINGLE_SCHEDULED_POST_RECEIVED, + data: { + scheduledPost, + teamId, + }, + }); + }; +} + +function handleUpdateScheduledPostEvent(msg) { + return async (doDispatch) => { + const scheduledPost = JSON.parse(msg.data.scheduledPost); + + doDispatch({ + type: ScheduledPostTypes.SCHEDULED_POST_UPDATED, + data: { + scheduledPost, + }, + }); + }; +} + +function handleDeleteScheduledPostEvent(msg) { + return async (doDispatch) => { + const scheduledPost = JSON.parse(msg.data.scheduledPost); + + doDispatch({ + type: ScheduledPostTypes.SCHEDULED_POST_DELETED, + data: { + scheduledPost, + }, + }); + }; +} + function handleDeleteDraftEvent(msg) { return async (doDispatch) => { const draft = JSON.parse(msg.data.draft); diff --git a/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/teams.ts b/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/teams.ts index 8ea86ae803..ba6288e4e3 100644 --- a/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/teams.ts +++ b/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/teams.ts @@ -372,3 +372,12 @@ export function makeGetBadgeCountForTeamId(): (state: GlobalState, id: string) = export function searchTeamsInPolicy(teams: Team[], term: string): Team[] { return filterTeamsStartingWithTerm(teams, term); } + +export function getTeamIdByChannelId(state: GlobalState, channelId: string): string | undefined { + const channels = state.entities.channels.channels; + if (!channels) { + return undefined; + } + const channel = channels[channelId]; + return channel ? channel.team_id : undefined; +} diff --git a/webapp/channels/src/utils/constants.tsx b/webapp/channels/src/utils/constants.tsx index eb0f22e573..d4b5be7c79 100644 --- a/webapp/channels/src/utils/constants.tsx +++ b/webapp/channels/src/utils/constants.tsx @@ -660,6 +660,9 @@ export const SocketEvents = { DRAFT_CREATED: 'draft_created', DRAFT_UPDATED: 'draft_updated', DRAFT_DELETED: 'draft_deleted', + SCHEDULED_POST_CREATED: 'scheduled_post_created', + SCHEDULED_POST_UPDATED: 'scheduled_post_updated', + SCHEDULED_POST_DELETED: 'scheduled_post_deleted', PERSISTENT_NOTIFICATION_TRIGGERED: 'persistent_notification_triggered', HOSTED_CUSTOMER_SIGNUP_PROGRESS_UPDATED: 'hosted_customer_signup_progress_updated', };