thread.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. let slug = require('slug')
  2. module.exports = (sequelize, DataTypes) => {
  3. let Thread = sequelize.define('Thread', {
  4. name: {
  5. type: DataTypes.TEXT,
  6. set (val) {
  7. this.setDataValue('name', val)
  8. if(val) this.setDataValue('slug', slug(val).toLowerCase())
  9. },
  10. allowNull: false,
  11. validate: {
  12. notEmpty: {
  13. msg: 'The title cannot be empty'
  14. },
  15. len: {
  16. args: [0, 256],
  17. msg: 'The title can only be up to 256 characters'
  18. },
  19. isString (val) {
  20. if(typeof val !== 'string') {
  21. throw new sequelize.ValidationError('The title must be a string')
  22. }
  23. }
  24. }
  25. },
  26. slug: DataTypes.TEXT,
  27. postsCount: {
  28. type: DataTypes.INTEGER,
  29. defaultValue: 0
  30. },
  31. locked: {
  32. type: DataTypes.BOOLEAN,
  33. defaultValue: false
  34. }
  35. }, {
  36. instanceMethods: {
  37. getMeta (limit) {
  38. let meta = {}
  39. let posts = this.Posts
  40. let firstPost = posts[0]
  41. let lastPost = posts.slice(-1)[0]
  42. //next url
  43. if(!lastPost || lastPost.postNumber+1 === this.postsCount) {
  44. meta.nextURL = null
  45. } else {
  46. meta.nextURL =
  47. `/api/v1/thread/${this.id}?limit=${limit}&from=${lastPost.postNumber + 1}`
  48. }
  49. //previous url
  50. if(!firstPost || firstPost.postNumber === 0) {
  51. meta.previousURL = null
  52. } else if(firstPost.postNumber - limit < 0) {
  53. meta.previousURL =
  54. `/api/v1/thread/${this.id}?limit=${firstPost.postNumber}&from=0`
  55. } else {
  56. meta.previousURL =
  57. `/api/v1/thread/${this.id}?limit=${limit}&from=${firstPost.postNumber - limit}`
  58. }
  59. //remaining posts
  60. if(lastPost === undefined) {
  61. meta.nextPostsCount = 0
  62. meta.previousPostsCount = 0
  63. meta.postsRemaining = 0
  64. } else {
  65. let postsRemaining =
  66. this.postsCount - lastPost.postNumber - 1
  67. meta.postsRemaining = postsRemaining
  68. if(postsRemaining < limit) {
  69. meta.nextPostsCount = postsRemaining
  70. } else {
  71. meta.nextPostsCount = limit
  72. }
  73. if(firstPost.postNumber === 0) {
  74. meta.previousPostsCount = 0
  75. } else if(firstPost.postNumber - limit < 0) {
  76. meta.previousPostsCount = firstPost.postNumber
  77. } else {
  78. meta.previousPostsCount = limit
  79. }
  80. }
  81. return meta
  82. }
  83. },
  84. classMethods: {
  85. associate (models) {
  86. Thread.belongsTo(models.User)
  87. Thread.belongsTo(models.Category)
  88. Thread.belongsTo(models.PollQuestion)
  89. Thread.hasMany(models.Post)
  90. },
  91. includeOptions (from, limit) {
  92. let models = sequelize.models
  93. return [
  94. { model: models.User, attributes: ['username', 'createdAt', 'color', 'updatedAt', 'id'] },
  95. models.Category,
  96. {
  97. model: models.Post,
  98. where: { postNumber: { $gte: from } },
  99. order: [['id', 'ASC']],
  100. limit,
  101. include: [
  102. { model: models.Thread, attributes: ['slug'] },
  103. { model: models.User, as: 'Likes', attributes: ['username', 'createdAt', 'id', 'color'] },
  104. { model: models.User, attributes: ['username', 'createdAt', 'id', 'color'] },
  105. {
  106. model: models.Post, as: 'Replies', include:
  107. [{ model: models.User, attributes: ['username', 'id', 'color'] }]
  108. }
  109. ]
  110. }
  111. ]
  112. }
  113. }
  114. })
  115. return Thread
  116. }