GraphQL API and utilities for the rpdata project
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

69 lines
1.9 KiB

package posts
import (
"errors"
"git.aiterp.net/rpdata/api/models"
"github.com/globalsign/mgo/bson"
)
// Move the post
func Move(post models.Post, toPosition int) ([]models.Post, error) {
if toPosition < 1 {
return nil, errors.New("Invalid position")
}
mutex.Lock()
defer mutex.Unlock()
// To avoid problems, only allow target indices that are allowed. If it's 1, then there is bound to
// be a post at the position.
if toPosition > 1 {
existing := models.Post{}
err := collection.Find(bson.M{"logId": post.LogID, "position": toPosition}).One(&existing)
if err != nil || existing.Position != toPosition {
return nil, errors.New("No post found at the position")
}
}
query := bson.M{"logId": post.LogID}
operation := bson.M{"$inc": bson.M{"position": 1}}
if toPosition < post.Position {
query["$and"] = []bson.M{
bson.M{"position": bson.M{"$gte": toPosition}},
bson.M{"position": bson.M{"$lt": post.Position}},
}
} else {
query["$and"] = []bson.M{
bson.M{"position": bson.M{"$gt": post.Position}},
bson.M{"position": bson.M{"$lte": toPosition}},
}
operation["$inc"] = bson.M{"position": -1}
}
_, err := collection.UpdateAll(query, operation)
if err != nil {
return nil, errors.New("Moving others failed: " + err.Error())
}
err = collection.UpdateId(post.ID, bson.M{"$set": bson.M{"position": toPosition}})
if err != nil {
return nil, errors.New("Moving failed: " + err.Error() + " (If you see this on the page, please let me know ASAP)")
}
from, to := post.Position, toPosition
if to < from {
from, to = to, from
}
posts := make([]models.Post, 0, (to-from)+1)
err = collection.Find(bson.M{"logId": post.LogID, "position": bson.M{"$gte": from, "$lte": to}}).Sort("position").All(&posts)
if err != nil {
return nil, errors.New("The move completed successfully, but finding the moved posts failed: " + err.Error())
}
return posts, nil
}