time sort in tree with replies #35
This commit is contained in:
+24
-6
@@ -3,6 +3,7 @@ package rest
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/umputun/remark/app/store"
|
||||
)
|
||||
@@ -16,6 +17,12 @@ type Tree struct {
|
||||
type Node struct {
|
||||
Comment store.Comment `json:"comment"`
|
||||
Replies []*Node `json:"replies,omitempty"`
|
||||
ts time.Time
|
||||
}
|
||||
|
||||
// timeStamp wraps time.Time to simplify pointer ops
|
||||
type timeStamp struct {
|
||||
time.Time
|
||||
}
|
||||
|
||||
// MakeTree gets unsorted list of comments and produces Tree
|
||||
@@ -27,10 +34,12 @@ func MakeTree(comments []store.Comment, sortType string) *Tree {
|
||||
for _, rootComment := range topComments {
|
||||
node := Node{Comment: rootComment}
|
||||
|
||||
commentsTree := res.proc(comments, &node, rootComment.ID)
|
||||
ts := timeStamp{}
|
||||
commentsTree, t := res.proc(comments, &node, &ts, rootComment.ID)
|
||||
if rootComment.Deleted && len(commentsTree.Replies) == 0 { // skip deleted with no subcomments
|
||||
continue
|
||||
}
|
||||
commentsTree.ts = t
|
||||
res.Nodes = append(res.Nodes, commentsTree)
|
||||
}
|
||||
|
||||
@@ -39,18 +48,26 @@ func MakeTree(comments []store.Comment, sortType string) *Tree {
|
||||
}
|
||||
|
||||
// proc makes tree for one top-level comment recursively
|
||||
func (t *Tree) proc(comments []store.Comment, node *Node, parentID string) *Node {
|
||||
func (t *Tree) proc(comments []store.Comment, node *Node, ts *timeStamp, parentID string) (*Node, time.Time) {
|
||||
|
||||
if ts.IsZero() {
|
||||
ts.Time = node.Comment.Timestamp
|
||||
}
|
||||
|
||||
repComments := t.filter(comments, parentID)
|
||||
for _, rc := range repComments {
|
||||
if rc.Timestamp.After(ts.Time) {
|
||||
ts.Time = rc.Timestamp
|
||||
}
|
||||
rnode := &Node{Comment: rc, Replies: []*Node{}}
|
||||
node.Replies = append(node.Replies, rnode)
|
||||
t.proc(comments, rnode, rc.ID)
|
||||
t.proc(comments, rnode, ts, rc.ID)
|
||||
}
|
||||
// replies always sorted by time
|
||||
sort.Slice(node.Replies, func(i, j int) bool {
|
||||
return node.Replies[i].Comment.Timestamp.Before(node.Replies[j].Comment.Timestamp)
|
||||
})
|
||||
return node
|
||||
return node, ts.Time
|
||||
}
|
||||
|
||||
// filter returns comments for parentID
|
||||
@@ -65,15 +82,16 @@ func (t *Tree) filter(comments []store.Comment, parentID string) (f []store.Comm
|
||||
}
|
||||
|
||||
// sort list of nodes, i.e. top-level comments
|
||||
// time sort uses ts from latest reply
|
||||
func (t *Tree) sortNodes(sortType string) {
|
||||
|
||||
sort.Slice(t.Nodes, func(i, j int) bool {
|
||||
switch sortType {
|
||||
case "+time", "-time", "time":
|
||||
if strings.HasPrefix(sortType, "-") {
|
||||
return t.Nodes[i].Comment.Timestamp.After(t.Nodes[j].Comment.Timestamp)
|
||||
return t.Nodes[i].ts.After(t.Nodes[j].ts)
|
||||
}
|
||||
return t.Nodes[i].Comment.Timestamp.Before(t.Nodes[j].Comment.Timestamp)
|
||||
return t.Nodes[i].ts.Before(t.Nodes[j].ts)
|
||||
|
||||
case "+score", "-score", "score":
|
||||
if strings.HasPrefix(sortType, "-") {
|
||||
|
||||
@@ -50,8 +50,8 @@ func TestTreeSortNodes(t *testing.T) {
|
||||
{ID: "2", Timestamp: time.Date(2017, 12, 25, 19, 47, 2, 0, time.UTC), Score: 3},
|
||||
{ID: "11", ParentID: "1", Timestamp: time.Date(2017, 12, 25, 19, 46, 11, 0, time.UTC)},
|
||||
{ID: "13", ParentID: "1", Timestamp: time.Date(2017, 12, 25, 19, 46, 13, 0, time.UTC)},
|
||||
{ID: "12", ParentID: "1", Timestamp: time.Date(2017, 12, 25, 19, 46, 12, 0, time.UTC)},
|
||||
{ID: "131", ParentID: "13", Timestamp: time.Date(2017, 12, 25, 19, 46, 31, 0, time.UTC)},
|
||||
{ID: "12", ParentID: "1", Timestamp: time.Date(2017, 12, 25, 19, 46, 14, 0, time.UTC)},
|
||||
{ID: "131", ParentID: "13", Timestamp: time.Date(2017, 12, 25, 19, 50, 31, 0, time.UTC)},
|
||||
{ID: "132", ParentID: "13", Timestamp: time.Date(2017, 12, 25, 19, 46, 32, 0, time.UTC)},
|
||||
{ID: "21", ParentID: "2", Timestamp: time.Date(2017, 12, 25, 19, 47, 21, 0, time.UTC)},
|
||||
{ID: "22", ParentID: "2", Timestamp: time.Date(2017, 12, 25, 19, 47, 22, 0, time.UTC)},
|
||||
@@ -61,14 +61,13 @@ func TestTreeSortNodes(t *testing.T) {
|
||||
{ID: "5", Deleted: true},
|
||||
}
|
||||
|
||||
res := MakeTree(comments, "time")
|
||||
assert.Equal(t, "1", res.Nodes[0].Comment.ID)
|
||||
|
||||
res = MakeTree(comments, "time")
|
||||
assert.Equal(t, "1", res.Nodes[0].Comment.ID)
|
||||
res := MakeTree(comments, "+time")
|
||||
assert.Equal(t, "2", res.Nodes[0].Comment.ID)
|
||||
t.Log(res.Nodes[0].Comment.ID, res.Nodes[0].ts)
|
||||
|
||||
res = MakeTree(comments, "-time")
|
||||
assert.Equal(t, "6", res.Nodes[0].Comment.ID)
|
||||
t.Log(res.Nodes[0].Comment.ID, res.Nodes[0].ts)
|
||||
assert.Equal(t, "1", res.Nodes[0].Comment.ID)
|
||||
|
||||
res = MakeTree(comments, "score")
|
||||
assert.Equal(t, "4", res.Nodes[0].Comment.ID)
|
||||
|
||||
Reference in New Issue
Block a user