2018-03-17 18:26:18 +05:30
|
|
|
import * as utils from './utils';
|
|
|
|
import * as types from './mutation_types';
|
|
|
|
import * as constants from '../constants';
|
2018-03-27 19:54:05 +05:30
|
|
|
import { isInMRPage } from '../../lib/utils/common_utils';
|
2018-03-17 18:26:18 +05:30
|
|
|
|
|
|
|
export default {
|
2018-12-05 23:21:45 +05:30
|
|
|
[types.ADD_NEW_NOTE](state, data) {
|
|
|
|
const note = data.discussion ? data.discussion.notes[0] : data;
|
2018-03-17 18:26:18 +05:30
|
|
|
const { discussion_id, type } = note;
|
2018-11-08 19:23:39 +05:30
|
|
|
const [exists] = state.discussions.filter(n => n.id === note.discussion_id);
|
|
|
|
const isDiscussion = type === constants.DISCUSSION_NOTE || type === constants.DIFF_NOTE;
|
2018-03-17 18:26:18 +05:30
|
|
|
|
|
|
|
if (!exists) {
|
|
|
|
const noteData = {
|
|
|
|
expanded: true,
|
|
|
|
id: discussion_id,
|
2018-03-27 19:54:05 +05:30
|
|
|
individual_note: !isDiscussion,
|
2018-03-17 18:26:18 +05:30
|
|
|
notes: [note],
|
|
|
|
reply_id: discussion_id,
|
|
|
|
};
|
|
|
|
|
2018-03-27 19:54:05 +05:30
|
|
|
if (isDiscussion && isInMRPage()) {
|
|
|
|
noteData.resolvable = note.resolvable;
|
|
|
|
noteData.resolved = false;
|
2019-02-15 15:39:39 +05:30
|
|
|
noteData.active = true;
|
2018-03-27 19:54:05 +05:30
|
|
|
noteData.resolve_path = note.resolve_path;
|
|
|
|
noteData.resolve_with_issue_path = note.resolve_with_issue_path;
|
2019-02-15 15:39:39 +05:30
|
|
|
noteData.diff_discussion = false;
|
2018-03-27 19:54:05 +05:30
|
|
|
}
|
|
|
|
|
2018-11-08 19:23:39 +05:30
|
|
|
state.discussions.push(noteData);
|
2018-03-17 18:26:18 +05:30
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
[types.ADD_NEW_REPLY_TO_DISCUSSION](state, note) {
|
2018-11-08 19:23:39 +05:30
|
|
|
const noteObj = utils.findNoteObjectById(state.discussions, note.discussion_id);
|
2018-03-17 18:26:18 +05:30
|
|
|
|
|
|
|
if (noteObj) {
|
|
|
|
noteObj.notes.push(note);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
[types.DELETE_NOTE](state, note) {
|
2018-11-08 19:23:39 +05:30
|
|
|
const noteObj = utils.findNoteObjectById(state.discussions, note.discussion_id);
|
2018-03-17 18:26:18 +05:30
|
|
|
|
|
|
|
if (noteObj.individual_note) {
|
2018-11-08 19:23:39 +05:30
|
|
|
state.discussions.splice(state.discussions.indexOf(noteObj), 1);
|
2018-03-17 18:26:18 +05:30
|
|
|
} else {
|
|
|
|
const comment = utils.findNoteObjectById(noteObj.notes, note.id);
|
|
|
|
noteObj.notes.splice(noteObj.notes.indexOf(comment), 1);
|
|
|
|
|
|
|
|
if (!noteObj.notes.length) {
|
2018-11-08 19:23:39 +05:30
|
|
|
state.discussions.splice(state.discussions.indexOf(noteObj), 1);
|
2018-03-17 18:26:18 +05:30
|
|
|
}
|
|
|
|
}
|
2018-11-08 19:23:39 +05:30
|
|
|
},
|
|
|
|
|
|
|
|
[types.EXPAND_DISCUSSION](state, { discussionId }) {
|
|
|
|
const discussion = utils.findNoteObjectById(state.discussions, discussionId);
|
2018-11-20 20:47:30 +05:30
|
|
|
Object.assign(discussion, { expanded: true });
|
2018-11-08 19:23:39 +05:30
|
|
|
},
|
2018-03-27 19:54:05 +05:30
|
|
|
|
2018-11-08 19:23:39 +05:30
|
|
|
[types.COLLAPSE_DISCUSSION](state, { discussionId }) {
|
|
|
|
const discussion = utils.findNoteObjectById(state.discussions, discussionId);
|
2018-11-20 20:47:30 +05:30
|
|
|
Object.assign(discussion, { expanded: false });
|
2018-03-17 18:26:18 +05:30
|
|
|
},
|
|
|
|
|
|
|
|
[types.REMOVE_PLACEHOLDER_NOTES](state) {
|
2018-11-08 19:23:39 +05:30
|
|
|
const { discussions } = state;
|
2018-03-17 18:26:18 +05:30
|
|
|
|
2018-11-08 19:23:39 +05:30
|
|
|
for (let i = discussions.length - 1; i >= 0; i -= 1) {
|
|
|
|
const note = discussions[i];
|
2018-03-17 18:26:18 +05:30
|
|
|
const children = note.notes;
|
|
|
|
|
2018-05-09 12:01:36 +05:30
|
|
|
if (children.length && !note.individual_note) {
|
|
|
|
// remove placeholder from discussions
|
2018-03-17 18:26:18 +05:30
|
|
|
for (let j = children.length - 1; j >= 0; j -= 1) {
|
|
|
|
if (children[j].isPlaceholderNote) {
|
|
|
|
children.splice(j, 1);
|
|
|
|
}
|
|
|
|
}
|
2018-05-09 12:01:36 +05:30
|
|
|
} else if (note.isPlaceholderNote) {
|
|
|
|
// remove placeholders from state root
|
2018-11-08 19:23:39 +05:30
|
|
|
discussions.splice(i, 1);
|
2018-03-17 18:26:18 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
[types.SET_NOTES_DATA](state, data) {
|
|
|
|
Object.assign(state, { notesData: data });
|
|
|
|
},
|
|
|
|
|
|
|
|
[types.SET_NOTEABLE_DATA](state, data) {
|
|
|
|
Object.assign(state, { noteableData: data });
|
|
|
|
},
|
|
|
|
|
|
|
|
[types.SET_USER_DATA](state, data) {
|
|
|
|
Object.assign(state, { userData: data });
|
|
|
|
},
|
2018-11-20 20:47:30 +05:30
|
|
|
|
2018-11-08 19:23:39 +05:30
|
|
|
[types.SET_INITIAL_DISCUSSIONS](state, discussionsData) {
|
2019-02-15 15:39:39 +05:30
|
|
|
const discussions = discussionsData.reduce((acc, d) => {
|
|
|
|
const discussion = { ...d };
|
|
|
|
const diffData = {};
|
2018-03-17 18:26:18 +05:30
|
|
|
|
2018-11-20 20:47:30 +05:30
|
|
|
if (discussion.diff_file) {
|
2019-02-15 15:39:39 +05:30
|
|
|
diffData.file_hash = discussion.diff_file.file_hash;
|
2019-03-02 22:35:43 +05:30
|
|
|
|
|
|
|
diffData.truncated_diff_lines = utils.prepareDiffLines(
|
|
|
|
discussion.truncated_diff_lines || [],
|
|
|
|
);
|
2018-11-20 20:47:30 +05:30
|
|
|
}
|
|
|
|
|
2018-03-17 18:26:18 +05:30
|
|
|
// To support legacy notes, should be very rare case.
|
2018-11-08 19:23:39 +05:30
|
|
|
if (discussion.individual_note && discussion.notes.length > 1) {
|
|
|
|
discussion.notes.forEach(n => {
|
2019-02-15 15:39:39 +05:30
|
|
|
acc.push({
|
2018-11-08 19:23:39 +05:30
|
|
|
...discussion,
|
2019-02-15 15:39:39 +05:30
|
|
|
...diffData,
|
2018-03-27 19:54:05 +05:30
|
|
|
notes: [n], // override notes array to only have one item to mimick individual_note
|
|
|
|
});
|
2018-03-17 18:26:18 +05:30
|
|
|
});
|
|
|
|
} else {
|
2018-11-08 19:23:39 +05:30
|
|
|
const oldNote = utils.findNoteObjectById(state.discussions, discussion.id);
|
2018-03-27 19:54:05 +05:30
|
|
|
|
2019-02-15 15:39:39 +05:30
|
|
|
acc.push({
|
2018-11-08 19:23:39 +05:30
|
|
|
...discussion,
|
2019-02-15 15:39:39 +05:30
|
|
|
...diffData,
|
2018-11-08 19:23:39 +05:30
|
|
|
expanded: oldNote ? oldNote.expanded : discussion.expanded,
|
2018-03-27 19:54:05 +05:30
|
|
|
});
|
2018-03-17 18:26:18 +05:30
|
|
|
}
|
2019-02-15 15:39:39 +05:30
|
|
|
|
|
|
|
return acc;
|
|
|
|
}, []);
|
2018-03-17 18:26:18 +05:30
|
|
|
|
2018-11-08 19:23:39 +05:30
|
|
|
Object.assign(state, { discussions });
|
2018-03-17 18:26:18 +05:30
|
|
|
},
|
|
|
|
[types.SET_LAST_FETCHED_AT](state, fetchedAt) {
|
|
|
|
Object.assign(state, { lastFetchedAt: fetchedAt });
|
|
|
|
},
|
|
|
|
|
|
|
|
[types.SET_TARGET_NOTE_HASH](state, hash) {
|
|
|
|
Object.assign(state, { targetNoteHash: hash });
|
|
|
|
},
|
|
|
|
|
|
|
|
[types.SHOW_PLACEHOLDER_NOTE](state, data) {
|
2018-11-08 19:23:39 +05:30
|
|
|
let notesArr = state.discussions;
|
|
|
|
|
|
|
|
const existingDiscussion = utils.findNoteObjectById(notesArr, data.replyId);
|
|
|
|
if (existingDiscussion) {
|
|
|
|
notesArr = existingDiscussion.notes;
|
2018-03-17 18:26:18 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
notesArr.push({
|
|
|
|
individual_note: true,
|
|
|
|
isPlaceholderNote: true,
|
2018-11-08 19:23:39 +05:30
|
|
|
placeholderType: data.isSystemNote ? constants.SYSTEM_NOTE : constants.NOTE,
|
2018-03-17 18:26:18 +05:30
|
|
|
notes: [
|
|
|
|
{
|
|
|
|
body: data.noteBody,
|
|
|
|
},
|
|
|
|
],
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
[types.TOGGLE_AWARD](state, data) {
|
|
|
|
const { awardName, note } = data;
|
|
|
|
const { id, name, username } = state.userData;
|
|
|
|
|
2018-05-09 12:01:36 +05:30
|
|
|
const hasEmojiAwardedByCurrentUser = note.award_emoji.filter(
|
|
|
|
emoji => emoji.name === data.awardName && emoji.user.id === id,
|
|
|
|
);
|
2018-03-17 18:26:18 +05:30
|
|
|
|
|
|
|
if (hasEmojiAwardedByCurrentUser.length) {
|
|
|
|
// If current user has awarded this emoji, remove it.
|
2018-11-08 19:23:39 +05:30
|
|
|
note.award_emoji.splice(note.award_emoji.indexOf(hasEmojiAwardedByCurrentUser[0]), 1);
|
2018-03-17 18:26:18 +05:30
|
|
|
} else {
|
|
|
|
note.award_emoji.push({
|
|
|
|
name: awardName,
|
|
|
|
user: { id, name, username },
|
|
|
|
});
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2019-02-15 15:39:39 +05:30
|
|
|
[types.TOGGLE_DISCUSSION](state, { discussionId, forceExpanded = null }) {
|
2018-11-08 19:23:39 +05:30
|
|
|
const discussion = utils.findNoteObjectById(state.discussions, discussionId);
|
2019-02-15 15:39:39 +05:30
|
|
|
Object.assign(discussion, {
|
|
|
|
expanded: forceExpanded === null ? !discussion.expanded : forceExpanded,
|
|
|
|
});
|
2018-03-17 18:26:18 +05:30
|
|
|
},
|
|
|
|
|
|
|
|
[types.UPDATE_NOTE](state, note) {
|
2018-11-08 19:23:39 +05:30
|
|
|
const noteObj = utils.findNoteObjectById(state.discussions, note.discussion_id);
|
2018-03-17 18:26:18 +05:30
|
|
|
|
|
|
|
if (noteObj.individual_note) {
|
2019-05-18 00:54:41 +05:30
|
|
|
if (note.type === constants.DISCUSSION_NOTE) {
|
|
|
|
noteObj.individual_note = false;
|
|
|
|
}
|
|
|
|
|
2018-03-17 18:26:18 +05:30
|
|
|
noteObj.notes.splice(0, 1, note);
|
|
|
|
} else {
|
|
|
|
const comment = utils.findNoteObjectById(noteObj.notes, note.id);
|
|
|
|
noteObj.notes.splice(noteObj.notes.indexOf(comment), 1, note);
|
|
|
|
}
|
2018-03-27 19:54:05 +05:30
|
|
|
},
|
|
|
|
|
2019-02-15 15:39:39 +05:30
|
|
|
[types.APPLY_SUGGESTION](state, { noteId, discussionId, suggestionId }) {
|
|
|
|
const noteObj = utils.findNoteObjectById(state.discussions, discussionId);
|
|
|
|
const comment = utils.findNoteObjectById(noteObj.notes, noteId);
|
|
|
|
|
|
|
|
comment.suggestions = comment.suggestions.map(suggestion => ({
|
|
|
|
...suggestion,
|
|
|
|
applied: suggestion.applied || suggestion.id === suggestionId,
|
|
|
|
appliable: false,
|
|
|
|
}));
|
|
|
|
},
|
|
|
|
|
2018-03-27 19:54:05 +05:30
|
|
|
[types.UPDATE_DISCUSSION](state, noteData) {
|
|
|
|
const note = noteData;
|
2018-11-20 20:47:30 +05:30
|
|
|
const selectedDiscussion = state.discussions.find(disc => disc.id === note.id);
|
2018-03-27 19:54:05 +05:30
|
|
|
note.expanded = true; // override expand flag to prevent collapse
|
2018-11-20 20:47:30 +05:30
|
|
|
if (note.diff_file) {
|
2019-02-15 15:39:39 +05:30
|
|
|
Object.assign(note, {
|
|
|
|
file_hash: note.diff_file.file_hash,
|
|
|
|
});
|
2018-11-20 20:47:30 +05:30
|
|
|
}
|
|
|
|
Object.assign(selectedDiscussion, { ...note });
|
2018-03-27 19:54:05 +05:30
|
|
|
},
|
|
|
|
|
|
|
|
[types.CLOSE_ISSUE](state) {
|
|
|
|
Object.assign(state.noteableData, { state: constants.CLOSED });
|
|
|
|
},
|
|
|
|
|
|
|
|
[types.REOPEN_ISSUE](state) {
|
|
|
|
Object.assign(state.noteableData, { state: constants.REOPENED });
|
|
|
|
},
|
|
|
|
|
|
|
|
[types.TOGGLE_STATE_BUTTON_LOADING](state, value) {
|
|
|
|
Object.assign(state, { isToggleStateButtonLoading: value });
|
2018-03-17 18:26:18 +05:30
|
|
|
},
|
2018-11-08 19:23:39 +05:30
|
|
|
|
|
|
|
[types.SET_NOTES_FETCHED_STATE](state, value) {
|
|
|
|
Object.assign(state, { isNotesFetched: value });
|
|
|
|
},
|
|
|
|
|
2018-12-13 13:39:08 +05:30
|
|
|
[types.SET_NOTES_LOADING_STATE](state, value) {
|
|
|
|
state.isLoading = value;
|
|
|
|
},
|
|
|
|
|
2018-11-08 19:23:39 +05:30
|
|
|
[types.SET_DISCUSSION_DIFF_LINES](state, { discussionId, diffLines }) {
|
|
|
|
const discussion = utils.findNoteObjectById(state.discussions, discussionId);
|
|
|
|
|
2019-03-02 22:35:43 +05:30
|
|
|
discussion.truncated_diff_lines = utils.prepareDiffLines(diffLines);
|
2018-11-08 19:23:39 +05:30
|
|
|
},
|
2018-12-13 13:39:08 +05:30
|
|
|
|
|
|
|
[types.DISABLE_COMMENTS](state, value) {
|
|
|
|
state.commentsDisabled = value;
|
|
|
|
},
|
2019-02-15 15:39:39 +05:30
|
|
|
[types.UPDATE_RESOLVABLE_DISCUSSIONS_COUNTS](state) {
|
|
|
|
state.resolvableDiscussionsCount = state.discussions.filter(
|
|
|
|
discussion => !discussion.individual_note && discussion.resolvable,
|
|
|
|
).length;
|
|
|
|
state.unresolvedDiscussionsCount = state.discussions.filter(
|
|
|
|
discussion =>
|
|
|
|
!discussion.individual_note &&
|
|
|
|
discussion.resolvable &&
|
|
|
|
discussion.notes.some(note => note.resolvable && !note.resolved),
|
|
|
|
).length;
|
|
|
|
state.hasUnresolvedDiscussions = state.unresolvedDiscussionsCount > 1;
|
|
|
|
},
|
2019-03-02 22:35:43 +05:30
|
|
|
|
|
|
|
[types.CONVERT_TO_DISCUSSION](state, discussionId) {
|
2019-05-18 00:54:41 +05:30
|
|
|
const convertedDisscussionIds = [...state.convertedDisscussionIds, discussionId];
|
|
|
|
Object.assign(state, { convertedDisscussionIds });
|
|
|
|
},
|
|
|
|
|
|
|
|
[types.REMOVE_CONVERTED_DISCUSSION](state, discussionId) {
|
|
|
|
const convertedDisscussionIds = [...state.convertedDisscussionIds];
|
|
|
|
|
|
|
|
convertedDisscussionIds.splice(convertedDisscussionIds.indexOf(discussionId), 1);
|
|
|
|
Object.assign(state, { convertedDisscussionIds });
|
2019-03-02 22:35:43 +05:30
|
|
|
},
|
2018-03-17 18:26:18 +05:30
|
|
|
};
|