cubash-archive/frontend/src/store/modules/thread.js

332 lines
7.9 KiB
JavaScript

import AjaxErrorHandler from '../../assets/js/errorHandler'
const state = {
thread: '',
category: null,
threadId: undefined,
PollQuestionId: null,
posts: [],
postNotification: null,
locked: false,
reply: {
username: '',
id: null
},
editor: {
show: false,
loading: false,
value: ''
},
mentions: [],
loadingPosts: false,
nextURL: '',
previousURL: '',
nextPostsCount: 10,
previousPostsCount: 0,
totalPostsCount: 0,
selectedPosts: [],
removePostsButtonLoading: false,
showRemovePostsButton: false
}
const getters = {
sortedPosts (state) {
return state.posts.sort((a, b) => {
return new Date(a.createdAt) - new Date(b.createdAt)
})
}
}
const actions = {
deleteThread ({ state }, vue) {
vue.axios
.delete(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'forums/thread/' + state.threadId)
.then(() => {
vue.$router.push('/')
})
.catch(AjaxErrorHandler(vue.$store))
},
removePostsAsync ({ state, commit }, vue) {
commit('setRemovePostsButtonLoading', true)
let promises = state.selectedPosts.map(id => vue.axios.delete(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'forums/post/' + id))
Promise.all(promises)
.then(() => {
commit('setRemovePostsButtonLoading', false)
commit('setShowRemovePostsButton', false)
state.posts = state.posts.map(post => {
if(state.selectedPosts.includes(post.id)) {
post.content = '<p>[This post has been removed by an administrator]</p>'
}
return post
})
state.selectedPosts = []
})
.catch(e => {
commit('setRemovePostsButtonLoading', false)
commit('setShowRemovePostsButton', false)
AjaxErrorHandler(vue.$store)(e)
})
},
addPostAsync ({ state, commit }, vue) {
let content = state.editor.value
state.mentions.forEach(mention => {
let regexp = new RegExp('(^|\\s)@' + mention + '($|\\s)')
content = content.replace(regexp, `$1[@${mention}](https://kaverti.com/u/${mention})$2`)
})
var post = {
content,
mentions: state.mentions,
threadId: +vue.$route.params.id
};
if(state.reply.id) {
post.replyingToId = state.reply.id;
}
commit('setThreadEditorLoading', true)
vue.axios
.post(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'forums/post', post)
.then(res => {
commit('setThreadEditorLoading', false)
commit('addPost', res.data);
commit('addReplyBubble', res.data)
commit('setThreadEditorValue', '');
commit('setThreadEditorState', false);
commit('setTotalPostsCount', state.totalPostsCount+1)
commit({
type: 'setReply',
username: '',
id: ''
});
})
.catch(e => {
commit('setThreadEditorLoading', false)
AjaxErrorHandler(vue.$store)(e)
})
},
loadInitialPostsAsync ({ commit, dispatch }, vue) {
commit('setPosts', [])
commit('setThread', { name: 'Loading...' })
dispatch('setTitle', 'Loading...')
let postNumber = vue.$route.params.post_number
let apiURL = process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'forums/thread/' + vue.$route.params.id
if(postNumber !== undefined) {
apiURL += '?postNumber=' + postNumber
}
vue.axios
.get(apiURL)
.then(res => {
commit('setThread', res.data)
dispatch('setTitle', res.data.title)
commit('setNextURL', res.data.meta.nextURL)
commit('setLocked', res.data.locked)
commit('setPreviousURL', res.data.meta.previousURL)
commit('setNextURL', res.data.meta.nextURL)
commit('setPreviousURL', res.data.meta.previousURL)
commit('setPostCounts', res.data.meta)
commit('setTotalPostsCount', res.data.postsCount)
commit('setPosts', res.data.Posts)
vue.$router.replace({ name: 'thread-post', params: {
post_number: postNumber || 0,
slug: res.data.slug
}});
if(postNumber !== undefined) {
vue.highlightPost(+postNumber)
}
}).catch(e => {
if(e.response.status === 400) {
commit('set404Page', true)
} else {
AjaxErrorHandler(vue.$store)(e)
}
})
},
loadPostsAsync ({ state, commit }, { vue, previous }) {
let URL
if(previous) {
commit('setLoadingPostsState', 'previous')
URL = state.previousURL
} else {
commit('setLoadingPostsState', 'next')
URL = state.nextURL
}
if(URL === null) {
commit('setLoadingPostsState', false)
} else {
vue.axios
.get(URL)
.then(res => {
let currentPostsIds = state.posts.map(p => p.id)
let filteredPosts =
res.data.Posts.filter(p => !currentPostsIds.includes(p.id))
commit('setLoadingPostsState', false)
if(previous) {
let last = filteredPosts.slice(-1)[0]
commit('prependPosts', filteredPosts)
commit('setPreviousURL', res.data.meta.previousURL)
if(last) {
vue.scrollTo(last.postNumber)
}
} else {
commit('addPost', filteredPosts)
commit('setNextURL', res.data.meta.nextURL)
}
commit('setPostCounts', res.data.meta)
})
.catch((e) => {
console.log(e)
AjaxErrorHandler(vue.$store)
})
}
},
loadNewPostsSinceLoad ({ state, commit }, post) {
if(state.nextPostsCount < 10) {
let nextURL = state.nextURL
let baseURL = process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'forums/thread/' + state.threadId + '?limit=10&from='
commit('incrementNextPostsCount')
if(nextURL === null) {
commit('setNextURL', baseURL + (post.postNumber-1))
}
}
},
setThreadLockedState ({ state, commit }, vue) {
vue.axios
.put(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'forums/thread/' + state.threadId, { locked: !state.locked })
.then(() => {
commit('setLocked', !state.locked)
})
.catch((e) => {
console.log(e)
AjaxErrorHandler(vue.$store)
})
}
}
const mutations = {
setReply (state, payload) {
state.reply.username = payload.username;
state.reply.id = payload.id;
if(payload.quote) {
state.editor.value = payload.quote;
}
},
'thread/setPostNotification': (state, post) => {
state.postNotification = post
},
addPost (state, post) {
if(Array.isArray(post)) {
state.posts.push(...post)
} else {
state.posts.push(post)
}
},
prependPosts (state, posts) {
state.posts.unshift(...posts)
},
addReplyBubble (state, post) {
let repliedToPost = {}, index
if(post.replyId) {
state.posts.forEach((p, i) => {
if(p.id === post.replyId) {
index = i
repliedToPost = p
}
})
repliedToPost.Replies.push(post)
state.posts.splice(index, 1, repliedToPost)
}
},
setThreadEditorValue (state, value) {
state.editor.value = value
},
setThreadEditorLoading (state, value) {
state.editor.loading = value
},
setThreadEditorState (state, value) {
state.editor.show = value
},
setLoadingPostsState (state, value) {
state.loadingPosts = value
},
setPosts (state, value) {
state.posts = value
},
setThread (state, obj) {
state.thread = obj.name
state.content = obj.content
state.title = obj.title
state.threadId = obj.id
state.PollQuestionId = obj.PollQuestionId
state.category = obj.Category
},
setNextURL (state, URL) {
state.nextURL = URL
},
setPreviousURL (state, URL) {
state.previousURL = URL
},
setPostCounts (state, meta) {
state.previousPostsCount = meta.previousPostsCount
state.nextPostsCount = meta.nextPostsCount
},
setTotalPostsCount (state, count) {
state.totalPostsCount = count
},
incrementNextPostsCount (state) {
state.nextPostsCount++
},
setMentions (state, mentions) {
state.mentions = mentions
},
setLocked (state, value) {
state.locked = value
},
setSelectedPosts (state, id ) {
let index = state.selectedPosts.indexOf(id)
if(index > -1) {
state.selectedPosts.splice(index, 1)
} else {
state.selectedPosts.push(id)
}
},
setRemovePostsButtonLoading (state, value) {
state.removePostsButtonLoading = value
},
setShowRemovePostsButton (state, value) {
state.showRemovePostsButton = value
}
}
export default {
state,
getters,
actions,
mutations
}