thread.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. import AjaxErrorHandler from '../../assets/js/errorHandler'
  2. const state = {
  3. thread: '',
  4. threadId: undefined,
  5. posts: [],
  6. locked: false,
  7. reply: {
  8. username: '',
  9. id: null
  10. },
  11. editor: {
  12. show: false,
  13. loading: false,
  14. value: ''
  15. },
  16. mentions: [],
  17. loadingPosts: false,
  18. nextURL: '',
  19. previousURL: '',
  20. nextPostsCount: 10,
  21. previousPostsCount: 0,
  22. totalPostsCount: 0
  23. }
  24. const getters = {
  25. sortedPosts (state) {
  26. return state.posts.sort((a, b) => {
  27. return new Date(a.createdAt) - new Date(b.createdAt)
  28. })
  29. }
  30. }
  31. const actions = {
  32. addPostAsync ({ state, commit, rootState }, vue) {
  33. let content = state.editor.value
  34. state.mentions.forEach(mention => {
  35. let regexp = new RegExp('(^|\\s)@' + mention + '($|\\s)')
  36. content = content.replace(regexp, `$1[@${mention}](/user/${mention})$2`)
  37. })
  38. var post = {
  39. content,
  40. mentions: state.mentions,
  41. threadId: +vue.$route.params.id
  42. };
  43. if(state.reply.id) {
  44. post.replyingToId = state.reply.id;
  45. }
  46. commit('setThreadEditorLoading', true)
  47. vue.axios
  48. .post('/api/v1/post', post)
  49. .then(res => {
  50. commit('setThreadEditorLoading', false)
  51. commit('addPost', res.data);
  52. commit('addReplyBubble', res.data)
  53. commit('setThreadEditorValue', '');
  54. commit('setThreadEditorState', false);
  55. commit('setTotalPostsCount', state.totalPostsCount+1)
  56. commit({
  57. type: 'setReply',
  58. username: '',
  59. id: ''
  60. });
  61. })
  62. .catch(e => {
  63. commit('setThreadEditorLoading', false)
  64. AjaxErrorHandler(vue.$store)(e)
  65. })
  66. },
  67. loadInitialPostsAsync ({ state, commit, dispatch, rootState }, vue) {
  68. let postNumber = vue.$route.params.post_number
  69. let apiURL = '/api/v1/thread/' + vue.$route.params.id
  70. if(postNumber !== undefined) {
  71. apiURL += '?postNumber=' + postNumber
  72. }
  73. vue.axios
  74. .get(apiURL)
  75. .then(res => {
  76. commit('setThread', res.data)
  77. dispatch('setTitle', res.data.name)
  78. commit('setNextURL', res.data.meta.nextURL)
  79. commit('setLocked', res.data.locked)
  80. commit('setPreviousURL', res.data.meta.previousURL)
  81. commit('setNextURL', res.data.meta.nextURL)
  82. commit('setPreviousURL', res.data.meta.previousURL)
  83. commit('setPostCounts', res.data.meta)
  84. commit('setTotalPostsCount', res.data.postsCount)
  85. commit('setPosts', res.data.Posts)
  86. if(postNumber !== undefined) {
  87. vue.$router.push({ name: 'thread-post', params: { post_number: postNumber } })
  88. vue.highlightPost(+postNumber)
  89. }
  90. }).catch(AjaxErrorHandler(vue.$store))
  91. },
  92. loadPostsAsync ({ state, commit, rootState }, { vue, previous }) {
  93. let URL
  94. if(previous) {
  95. commit('setLoadingPostsState', 'previous')
  96. URL = state.previousURL
  97. } else {
  98. commit('setLoadingPostsState', 'next')
  99. URL = state.nextURL
  100. }
  101. if(URL === null) {
  102. commit('setLoadingPostsState', false)
  103. } else {
  104. vue.axios
  105. .get(URL)
  106. .then(res => {
  107. let currentPostsIds = state.posts.map(p => p.id)
  108. let filteredPosts =
  109. res.data.Posts.filter(p => !currentPostsIds.includes(p.id))
  110. commit('setLoadingPostsState', false)
  111. if(previous) {
  112. let last = filteredPosts.slice(-1)[0]
  113. commit('prependPosts', filteredPosts)
  114. commit('setPreviousURL', res.data.meta.previousURL)
  115. if(last) {
  116. vue.scrollTo(last.postNumber)
  117. }
  118. } else {
  119. commit('addPost', filteredPosts)
  120. commit('setNextURL', res.data.meta.nextURL)
  121. }
  122. commit('setPostCounts', res.data.meta)
  123. })
  124. .catch((e) => {
  125. console.log(e)
  126. AjaxErrorHandler(vue.$store)
  127. })
  128. }
  129. },
  130. loadNewPostsSinceLoad ({ state, commit }, post) {
  131. if(state.nextPostsCount < 10) {
  132. let nextURL = state.nextURL
  133. let baseURL = '/api/v1/thread/' + state.threadId + '?limit=10&from='
  134. commit('incrementNextPostsCount')
  135. if(nextURL === null) {
  136. commit('setNextURL', baseURL + (post.postNumber-1))
  137. }
  138. }
  139. },
  140. setThreadLockedState ({ state, commit }, vue) {
  141. vue.axios
  142. .put('/api/v1/thread/' + state.threadId, { locked: !state.locked })
  143. .then(res => {
  144. commit('setLocked', !state.locked)
  145. })
  146. .catch((e) => {
  147. console.log(e)
  148. AjaxErrorHandler(vue.$store)
  149. })
  150. }
  151. }
  152. const mutations = {
  153. setReply (state, payload) {
  154. state.reply.username = payload.username;
  155. state.reply.id = payload.id;
  156. },
  157. addPost (state, post) {
  158. if(Array.isArray(post)) {
  159. state.posts.push(...post)
  160. } else {
  161. state.posts.push(post)
  162. }
  163. },
  164. prependPosts (state, posts) {
  165. state.posts.unshift(...posts)
  166. },
  167. addReplyBubble (state, post) {
  168. let repliedToPost = {}, index
  169. if(post.replyId) {
  170. state.posts.forEach((p, i) => {
  171. if(p.id === post.replyId) {
  172. index = i
  173. repliedToPost = p
  174. }
  175. })
  176. repliedToPost.Replies.push(post)
  177. state.posts.splice(index, 1, repliedToPost)
  178. }
  179. },
  180. setThreadEditorValue (state, value) {
  181. state.editor.value = value
  182. },
  183. setThreadEditorLoading (state, value) {
  184. state.editor.loading = value
  185. },
  186. setThreadEditorState (state, value) {
  187. state.editor.show = value
  188. },
  189. setLoadingPostsState (state, value) {
  190. state.loadingPosts = value
  191. },
  192. setPosts (state, value) {
  193. state.posts = value
  194. },
  195. setThread (state, obj) {
  196. state.thread = obj.name
  197. state.threadId = obj.id
  198. },
  199. setNextURL (state, URL) {
  200. state.nextURL = URL
  201. },
  202. setPreviousURL (state, URL) {
  203. state.previousURL = URL
  204. },
  205. setPostCounts (state, meta) {
  206. state.previousPostsCount = meta.previousPostsCount
  207. state.nextPostsCount = meta.nextPostsCount
  208. },
  209. setTotalPostsCount (state, count) {
  210. state.totalPostsCount = count
  211. },
  212. incrementNextPostsCount (state) {
  213. state.nextPostsCount++
  214. },
  215. setMentions (state, mentions) {
  216. state.mentions = mentions
  217. },
  218. setLocked (state, value) {
  219. state.locked = value
  220. }
  221. }
  222. export default {
  223. state,
  224. getters,
  225. actions,
  226. mutations
  227. }