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

  1. package posts
  2. import (
  3. "errors"
  4. "git.aiterp.net/rpdata/api/models"
  5. "github.com/globalsign/mgo/bson"
  6. )
  7. // Move the post
  8. func Move(post models.Post, toPosition int) ([]models.Post, error) {
  9. if toPosition < 1 {
  10. return nil, errors.New("Invalid position")
  11. }
  12. mutex.Lock()
  13. defer mutex.Unlock()
  14. // To avoid problems, only allow target indices that are allowed. If it's 1, then there is bound to
  15. // be a post at the position.
  16. if toPosition > 1 {
  17. existing := models.Post{}
  18. err := collection.Find(bson.M{"logId": post.LogID, "position": toPosition}).One(&existing)
  19. if err != nil || existing.Position != toPosition {
  20. return nil, errors.New("No post found at the position")
  21. }
  22. }
  23. query := bson.M{"logId": post.LogID}
  24. operation := bson.M{"$inc": bson.M{"position": 1}}
  25. if toPosition < post.Position {
  26. query["$and"] = []bson.M{
  27. bson.M{"position": bson.M{"$gte": toPosition}},
  28. bson.M{"position": bson.M{"$lt": post.Position}},
  29. }
  30. } else {
  31. query["$and"] = []bson.M{
  32. bson.M{"position": bson.M{"$gt": post.Position}},
  33. bson.M{"position": bson.M{"$lte": toPosition}},
  34. }
  35. operation["$inc"] = bson.M{"position": -1}
  36. }
  37. _, err := collection.UpdateAll(query, operation)
  38. if err != nil {
  39. return nil, errors.New("Moving others failed: " + err.Error())
  40. }
  41. err = collection.UpdateId(post.ID, bson.M{"$set": bson.M{"position": toPosition}})
  42. if err != nil {
  43. return nil, errors.New("Moving failed: " + err.Error() + " (If you see this on the page, please let me know ASAP)")
  44. }
  45. from, to := post.Position, toPosition
  46. if to < from {
  47. from, to = to, from
  48. }
  49. posts := make([]models.Post, 0, (to-from)+1)
  50. err = collection.Find(bson.M{"logId": post.LogID, "position": bson.M{"$gte": from, "$lte": to}}).Sort("position").All(&posts)
  51. if err != nil {
  52. return nil, errors.New("The move completed successfully, but finding the moved posts failed: " + err.Error())
  53. }
  54. return posts, nil
  55. }