import Vue from 'vue' import hljs from 'highlight.js' import * as api from '@/api' import {nameSpacer} from '@/util/helpers' export const subNotesNamespace = nameSpacer('submissionNotes/') export const subNotesMut = Object.freeze({ SET_SUBMISSION: 'SET_SUBMISSION', SET_ORIG_FEEDBACK: 'SET_ORIG_FEEDBACK', SET_SHOW_FEEDBACK: 'SET_SHOW_FEEDBACK', UPDATE_FEEDBACK_LINE: 'UPDATE_FEEDBACK_LINE', UPDATE_FEEDBACK_SCORE: 'UPDATE_FEEDBACK_SCORE', DELETE_FEEDBACK_LINE: 'DELETE_FEEDBACK_LINE', TOGGLE_EDITOR_ON_LINE: 'TOGGLE_EDITOR_ON_LINE', MARK_COMMENT_FOR_DELETION: 'MARK_COMMENT_FOR_DELETION', UN_MARK_COMMENT_FOR_DELETION: 'UN_MARK_COMMENT_FOR_DELETION', RESET_UPDATED_FEEDBACK: 'RESET_UPDATED_FEEDBACK', RESET_STATE: 'RESET_STATE' }) function initialState () { return { assignment: '', submission: { text: '', pk: '' }, ui: { showEditorOnLine: {}, selectedCommentOnLine: {}, showFeedback: true }, hasOrigFeedback: false, origFeedback: { score: null, isFinal: false, feedbackLines: {} }, updatedFeedback: { score: null, feedbackLines: {} }, commentsMarkedForDeletion: {} } } const submissionNotes = { namespaced: true, state: initialState(), getters: { submissionType: (state, getters, rootState) => { return rootState.submissionTypes[state.submission.type] }, // highlight the submission the reduce the string // submission.text into an object where the keys are the // line indexes starting at one and the values the corresponding submission line // this makes iterating over the submission much more pleasant submission: (state, getters) => { const language = getters.submissionType ? getters.submissionType.programmingLanguage : 'c' const highlighted = hljs.highlight(language, state.submission.text, true).value return highlighted.split('\n').reduce((acc, cur, index) => { acc[index + 1] = cur return acc }, {}) }, score: state => { return state.updatedFeedback.score !== null ? state.updatedFeedback.score : state.origFeedback.score }, workInProgress: state => { const openEditor = Object.values(state.ui.showEditorOnLine).reduce((acc, curr) => acc || curr, false) const feedbackWritten = Object.entries(state.updatedFeedback.feedbackLines).length > 0 return openEditor || feedbackWritten }, isFeedbackCreation: state => { return !state.origFeedback['feedbackStageForUser'] || state.origFeedback['feedbackStageForUser'] === 'feedback-creation' } }, mutations: { [subNotesMut.SET_SUBMISSION]: function (state, submission) { state.submission = submission }, [subNotesMut.SET_ORIG_FEEDBACK]: function (state, feedback) { if (feedback) { state.origFeedback = feedback state.hasOrigFeedback = true } }, [subNotesMut.SET_SHOW_FEEDBACK]: function (state, val) { state.ui.showFeedback = val }, [subNotesMut.UPDATE_FEEDBACK_LINE]: function (state, feedback) { Vue.set(state.updatedFeedback.feedbackLines, feedback.lineNo, feedback.comment) }, [subNotesMut.UPDATE_FEEDBACK_SCORE]: function (state, score) { state.updatedFeedback.score = score }, [subNotesMut.DELETE_FEEDBACK_LINE]: function (state, lineNo) { Vue.delete(state.updatedFeedback.feedbackLines, lineNo) }, [subNotesMut.TOGGLE_EDITOR_ON_LINE]: function (state, {lineNo, comment}) { Vue.set(state.ui.selectedCommentOnLine, lineNo, comment) Vue.set(state.ui.showEditorOnLine, lineNo, !state.ui.showEditorOnLine[lineNo]) }, [subNotesMut.MARK_COMMENT_FOR_DELETION]: function (state, comment) { Vue.set(state.commentsMarkedForDeletion, comment.pk, comment) }, [subNotesMut.UN_MARK_COMMENT_FOR_DELETION]: function (state, comment) { Vue.delete(state.commentsMarkedForDeletion, comment.pk) }, [subNotesMut.RESET_UPDATED_FEEDBACK]: function (state) { state.updatedFeedback = initialState().updatedFeedback }, [subNotesMut.RESET_STATE]: function (state) { Object.assign(state, initialState()) } }, actions: { deleteComments: async function ({state}) { return Promise.all( Object.values(state.commentsMarkedForDeletion).map(comment => { return api.deleteComment((comment as any)) }) ) }, submitFeedback: async function ({state, dispatch, getters}, {isFinal = false}) { let feedback = { isFinal: isFinal, ofSubmission: state.submission.pk } if (Object.keys(state.updatedFeedback.feedbackLines).length > 0) { feedback['feedbackLines'] = state.updatedFeedback.feedbackLines } if (state.origFeedback.score === null && state.updatedFeedback.score === null) { throw new Error('You need to give a score.') } else if (state.updatedFeedback.score !== null) { feedback['score'] = state.updatedFeedback.score } await dispatch('deleteComments') if (!state.hasOrigFeedback) { return api.submitFeedbackForAssignment({feedback}) } else { feedback['pk']= state.origFeedback.pk return api.submitUpdatedFeedback({feedback}) } } } } export default submissionNotes