summaryrefslogtreecommitdiffstats
path: root/api
diff options
context:
space:
mode:
authorGabin Aureche <gabin.aureche@live.fr>2017-03-13 13:25:08 +0100
committerGeorge Goldberg <george@gberg.me>2017-03-13 12:25:08 +0000
commitfe38d6d5bb36e18ddefbe490cc21f48f4f4c8d81 (patch)
treeb96d457cde64b7397f91028106e93a7f92a179bd /api
parent482a0fb5fc248b1ec61db35299dc3e6d963ad5ab (diff)
downloadchat-fe38d6d5bb36e18ddefbe490cc21f48f4f4c8d81.tar.gz
chat-fe38d6d5bb36e18ddefbe490cc21f48f4f4c8d81.tar.bz2
chat-fe38d6d5bb36e18ddefbe490cc21f48f4f4c8d81.zip
Add pinned posts (#4217)
Diffstat (limited to 'api')
-rw-r--r--api/admin_test.go4
-rw-r--r--api/apitestlib.go19
-rw-r--r--api/channel.go16
-rw-r--r--api/channel_test.go33
-rw-r--r--api/post.go55
-rw-r--r--api/post_test.go46
6 files changed, 165 insertions, 8 deletions
diff --git a/api/admin_test.go b/api/admin_test.go
index 801ad8f21..dc569620e 100644
--- a/api/admin_test.go
+++ b/api/admin_test.go
@@ -225,7 +225,7 @@ func TestGetTeamAnalyticsStandard(t *testing.T) {
t.Fatal()
}
- if rows[0].Value != 3 {
+ if rows[0].Value != 4 {
t.Log(rows.ToJson())
t.Fatal()
}
@@ -245,7 +245,7 @@ func TestGetTeamAnalyticsStandard(t *testing.T) {
t.Fatal()
}
- if rows[2].Value != 5 {
+ if rows[2].Value != 6 {
t.Log(rows.ToJson())
t.Fatal()
}
diff --git a/api/apitestlib.go b/api/apitestlib.go
index 475469a36..df5ac5d26 100644
--- a/api/apitestlib.go
+++ b/api/apitestlib.go
@@ -21,6 +21,7 @@ type TestHelper struct {
BasicUser2 *model.User
BasicChannel *model.Channel
BasicPost *model.Post
+ PinnedPost *model.Post
SystemAdminClient *model.Client
SystemAdminTeam *model.Team
@@ -91,6 +92,9 @@ func (me *TestHelper) InitBasic() *TestHelper {
me.BasicChannel = me.CreateChannel(me.BasicClient, me.BasicTeam)
me.BasicPost = me.CreatePost(me.BasicClient, me.BasicChannel)
+ pinnedPostChannel := me.CreateChannel(me.BasicClient, me.BasicTeam)
+ me.PinnedPost = me.CreatePinnedPost(me.BasicClient, pinnedPostChannel)
+
return me
}
@@ -265,6 +269,21 @@ func (me *TestHelper) CreatePost(client *model.Client, channel *model.Channel) *
return r
}
+func (me *TestHelper) CreatePinnedPost(client *model.Client, channel *model.Channel) *model.Post {
+ id := model.NewId()
+
+ post := &model.Post{
+ ChannelId: channel.Id,
+ Message: "message_" + id,
+ IsPinned: true,
+ }
+
+ utils.DisableDebugLogForTest()
+ r := client.Must(client.CreatePost(post)).Data.(*model.Post)
+ utils.EnableDebugLogForTest()
+ return r
+}
+
func (me *TestHelper) LoginBasic() {
utils.DisableDebugLogForTest()
me.BasicClient.Must(me.BasicClient.Login(me.BasicUser.Email, me.BasicUser.Password))
diff --git a/api/channel.go b/api/channel.go
index 9c11f073e..0db3499e0 100644
--- a/api/channel.go
+++ b/api/channel.go
@@ -39,6 +39,7 @@ func InitChannel() {
BaseRoutes.NeedChannel.Handle("/stats", ApiUserRequired(getChannelStats)).Methods("GET")
BaseRoutes.NeedChannel.Handle("/members/{user_id:[A-Za-z0-9]+}", ApiUserRequired(getChannelMember)).Methods("GET")
BaseRoutes.NeedChannel.Handle("/members/ids", ApiUserRequired(getChannelMembersByIds)).Methods("POST")
+ BaseRoutes.NeedChannel.Handle("/pinned", ApiUserRequired(getPinnedPosts)).Methods("GET")
BaseRoutes.NeedChannel.Handle("/join", ApiUserRequired(join)).Methods("POST")
BaseRoutes.NeedChannel.Handle("/leave", ApiUserRequired(leave)).Methods("POST")
BaseRoutes.NeedChannel.Handle("/delete", ApiUserRequired(deleteChannel)).Methods("POST")
@@ -598,6 +599,21 @@ func getMyChannelMembers(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
+func getPinnedPosts(c *Context, w http.ResponseWriter, r *http.Request) {
+ params := mux.Vars(r)
+ channelId := params["channel_id"]
+ posts := &model.PostList{}
+
+ if result := <-app.Srv.Store.Channel().GetPinnedPosts(channelId); result.Err != nil {
+ c.Err = result.Err
+ return
+ } else {
+ posts = result.Data.(*model.PostList)
+ }
+
+ w.Write([]byte(posts.ToJson()))
+}
+
func addMember(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
id := params["channel_id"]
diff --git a/api/channel_test.go b/api/channel_test.go
index 93c79d416..08136bc35 100644
--- a/api/channel_test.go
+++ b/api/channel_test.go
@@ -926,8 +926,8 @@ func TestGetMoreChannelsPage(t *testing.T) {
} else {
channels := r.Data.(*model.ChannelList)
- // 1 for BasicChannel, 2 for open channels created above
- if len(*channels) != 3 {
+ // 1 for BasicChannel, 1 for PinnedPostChannel, 2 for open channels created above
+ if len(*channels) != 4 {
t.Fatal("wrong length")
}
@@ -990,11 +990,11 @@ func TestGetChannelCounts(t *testing.T) {
} else {
counts := result.Data.(*model.ChannelCounts)
- if len(counts.Counts) != 5 {
+ if len(counts.Counts) != 6 {
t.Fatal("wrong number of channel counts")
}
- if len(counts.UpdateTimes) != 5 {
+ if len(counts.UpdateTimes) != 6 {
t.Fatal("wrong number of channel update times")
}
@@ -1024,8 +1024,8 @@ func TestGetMyChannelMembers(t *testing.T) {
} else {
members := result.Data.(*model.ChannelMembers)
- // town-square, off-topic, basic test channel, channel1, channel2
- if len(*members) != 5 {
+ // town-square, off-topic, basic test channel, pinned post channel, channel1, channel2
+ if len(*members) != 6 {
t.Fatal("wrong number of members", len(*members))
}
}
@@ -2117,3 +2117,24 @@ func TestUpdateChannelRoles(t *testing.T) {
t.Fatal("Channel member should not be able to promote itself to channel admin:", meta)
}
}
+
+func TestGetPinnedPosts(t *testing.T) {
+ th := Setup().InitBasic()
+ Client := th.BasicClient
+
+ post1 := th.BasicPost
+ r1 := Client.Must(Client.GetPinnedPosts(post1.ChannelId)).Data.(*model.PostList)
+ if len(r1.Order) != 0 {
+ t.Fatal("should not have gotten a pinned post")
+ }
+
+ post2 := th.PinnedPost
+ r2 := Client.Must(Client.GetPinnedPosts(post2.ChannelId)).Data.(*model.PostList)
+ if len(r2.Order) == 0 {
+ t.Fatal("should have gotten a pinned post")
+ }
+
+ if _, ok := r2.Posts[post2.Id]; !ok {
+ t.Fatal("missing pinned post")
+ }
+}
diff --git a/api/post.go b/api/post.go
index 4e7801e2b..d6de65e40 100644
--- a/api/post.go
+++ b/api/post.go
@@ -38,6 +38,8 @@ func InitPost() {
BaseRoutes.NeedPost.Handle("/before/{offset:[0-9]+}/{num_posts:[0-9]+}", ApiUserRequired(getPostsBefore)).Methods("GET")
BaseRoutes.NeedPost.Handle("/after/{offset:[0-9]+}/{num_posts:[0-9]+}", ApiUserRequired(getPostsAfter)).Methods("GET")
BaseRoutes.NeedPost.Handle("/get_file_infos", ApiUserRequired(getFileInfosForPost)).Methods("GET")
+ BaseRoutes.NeedPost.Handle("/pin", ApiUserRequired(pinPost)).Methods("POST")
+ BaseRoutes.NeedPost.Handle("/unpin", ApiUserRequired(unpinPost)).Methods("POST")
}
func createPost(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -91,6 +93,59 @@ func updatePost(c *Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte(rpost.ToJson()))
}
+func saveIsPinnedPost(c *Context, w http.ResponseWriter, r *http.Request, isPinned bool) {
+ params := mux.Vars(r)
+
+ channelId := params["channel_id"]
+ if len(channelId) != 26 {
+ c.SetInvalidParam("savedIsPinnedPost", "channelId")
+ return
+ }
+
+ postId := params["post_id"]
+ if len(postId) != 26 {
+ c.SetInvalidParam("savedIsPinnedPost", "postId")
+ return
+ }
+
+ pchan := app.Srv.Store.Post().Get(postId)
+
+ var oldPost *model.Post
+ if result := <-pchan; result.Err != nil {
+ c.Err = result.Err
+ return
+ } else {
+ oldPost = result.Data.(*model.PostList).Posts[postId]
+ newPost := &model.Post{}
+ *newPost = *oldPost
+ newPost.IsPinned = isPinned
+
+ if result := <-app.Srv.Store.Post().Update(newPost, oldPost); result.Err != nil {
+ c.Err = result.Err
+ return
+ } else {
+ rpost := result.Data.(*model.Post)
+
+ message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_POST_EDITED, "", rpost.ChannelId, "", nil)
+ message.Add("post", rpost.ToJson())
+
+ go app.Publish(message)
+
+ app.InvalidateCacheForChannelPosts(rpost.ChannelId)
+
+ w.Write([]byte(rpost.ToJson()))
+ }
+ }
+}
+
+func pinPost(c *Context, w http.ResponseWriter, r *http.Request) {
+ saveIsPinnedPost(c, w, r, true)
+}
+
+func unpinPost(c *Context, w http.ResponseWriter, r *http.Request) {
+ saveIsPinnedPost(c, w, r, false)
+}
+
func getFlaggedPosts(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
diff --git a/api/post_test.go b/api/post_test.go
index bab27cc65..5546e7165 100644
--- a/api/post_test.go
+++ b/api/post_test.go
@@ -1378,3 +1378,49 @@ func TestGetOpenGraphMetadata(t *testing.T) {
t.Fatal("should have failed with 501 - disabled link previews")
}
}
+
+func TestPinPost(t *testing.T) {
+ th := Setup().InitBasic()
+ Client := th.BasicClient
+
+ post := th.BasicPost
+ if rupost1, err := Client.PinPost(post.ChannelId, post.Id); err != nil {
+ t.Fatal(err)
+ } else {
+ if rupost1.Data.(*model.Post).IsPinned != true {
+ t.Fatal("failed to pin post")
+ }
+ }
+
+ pinnedPost := th.PinnedPost
+ if rupost2, err := Client.PinPost(pinnedPost.ChannelId, pinnedPost.Id); err != nil {
+ t.Fatal(err)
+ } else {
+ if rupost2.Data.(*model.Post).IsPinned != true {
+ t.Fatal("pinning a post should be idempotent")
+ }
+ }
+}
+
+func TestUnpinPost(t *testing.T) {
+ th := Setup().InitBasic()
+ Client := th.BasicClient
+
+ pinnedPost := th.PinnedPost
+ if rupost1, err := Client.UnpinPost(pinnedPost.ChannelId, pinnedPost.Id); err != nil {
+ t.Fatal(err)
+ } else {
+ if rupost1.Data.(*model.Post).IsPinned != false {
+ t.Fatal("failed to unpin post")
+ }
+ }
+
+ post := th.BasicPost
+ if rupost2, err := Client.UnpinPost(post.ChannelId, post.Id); err != nil {
+ t.Fatal(err)
+ } else {
+ if rupost2.Data.(*model.Post).IsPinned != false {
+ t.Fatal("unpinning a post should be idempotent")
+ }
+ }
+}