Skip to content
Snippets Groups Projects
Commit cf5cc6a9 authored by Filipa Lacerda's avatar Filipa Lacerda
Browse files

Follow vuex docs to divide store into: actions, getters and mutations

Use constants for mutation types as per vuex docs
parent fbdc02ad
No related branches found
No related tags found
No related merge requests found
Showing
with 446 additions and 408 deletions
Loading
Loading
@@ -209,12 +209,13 @@ export default {
aria-hidden="true"
class="fa fa-caret-down toggle-icon"></i>
</button>
<ul
class="note-type-dropdown dropdown-open-top dropdown-menu">
<ul class="note-type-dropdown dropdown-open-top dropdown-menu">
<li
:class="{ 'droplab-item-selected': noteType === 'comment' }"
@click.prevent="setNoteType('comment')">
<button class="btn btn-transparent">
<button
type="button"
class="btn btn-transparent">
<i
aria-hidden="true"
class="fa fa-check icon"></i>
Loading
Loading
@@ -230,10 +231,13 @@ export default {
<li
:class="{ 'droplab-item-selected': noteType === 'discussion' }"
@click.prevent="setNoteType('discussion')">
<button class="btn btn-transparent">
<button
type="button"
class="btn btn-transparent">
<i
aria-hidden="true"
class="fa fa-check icon"></i>
class="fa fa-check icon">
</i>
<div class="description">
<strong>Start discussion</strong>
<p>
Loading
Loading
@@ -244,21 +248,21 @@ export default {
</li>
</ul>
</div>
<a
<button
type="button"
@click="handleSave(true)"
v-if="canUpdateIssue"
:class="actionButtonClassNames"
class="btn btn-nr btn-comment btn-comment-and-close"
role="button">
class="btn btn-nr btn-comment btn-comment-and-close">
{{issueActionButtonTitle}}
</a>
<a
</button>
<button
type="button"
v-if="note.length"
@click="discard"
class="btn btn-cancel js-note-discard"
role="button">
class="btn btn-cancel js-note-discard">
Discard draft
</a>
</button>
</div>
</div>
</div>
Loading
Loading
Loading
Loading
@@ -71,7 +71,8 @@ export default {
cancelReplyForm(shouldConfirm) {
if (shouldConfirm && this.$refs.noteForm.isDirty) {
const msg = 'Are you sure you want to cancel creating this comment?';
const isConfirmed = confirm(msg); // eslint-disable-line
// eslint-disable-next-line no-alert
const isConfirmed = confirm(msg);
if (!isConfirmed) {
return;
}
Loading
Loading
@@ -112,7 +113,8 @@ export default {
:link-href="author.path"
:img-src="author.avatar_url"
:img-alt="author.name"
:img-size="40" />
:img-size="40"
/>
</div>
<div class="timeline-content">
<div class="discussion">
Loading
Loading
@@ -123,13 +125,15 @@ export default {
:note-id="discussion.id"
:include-toggle="true"
:toggle-handler="toggleDiscussion"
actionText="started a discussion" />
actionText="started a discussion"
/>
<issue-note-edited-text
v-if="note.last_updated_by"
:edited-at="note.last_updated_at"
:edited-by="note.last_updated_by"
actionText="Last updated"
className="discussion-headline-light js-discussion-headline" />
className="discussion-headline-light js-discussion-headline"
/>
</div>
</div>
<div
Loading
Loading
@@ -142,7 +146,8 @@ export default {
v-for="note in note.notes"
:is="componentName(note)"
:note="componentData(note)"
key="note.id" />
key="note.id"
/>
</ul>
<div class="flash-container"></div>
<div class="discussion-reply-holder">
Loading
Loading
Loading
Loading
@@ -2,6 +2,7 @@
import emojiSmiling from 'icons/_emoji_slightly_smiling_face.svg';
import emojiSmile from 'icons/_emoji_smile.svg';
import emojiSmiley from 'icons/_emoji_smiley.svg';
import loadingIcon from '../../vue_shared/components/loadingIcon.vue';
 
export default {
props: {
Loading
Loading
@@ -78,9 +79,7 @@ export default {
data-position="right"
href="#"
title="Add reaction">
<i
aria-hidden="true"
class="fa fa-spinner fa-spin"></i>
<loading-icon />
<span
v-html="emojiSmiling"
class="link-highlight award-control-icon-neutral"></span>
Loading
Loading
@@ -122,15 +121,14 @@ export default {
</a>
</li>
<li v-if="canEdit">
<a
<button
@click.prevent="deleteHandler"
class="btn btn-transparent js-note-delete js-note-delete"
href="#"
type="button">
<span class="text-danger">
Delete comment
</span>
</a>
</button>
</li>
</ul>
</div>
Loading
Loading
Loading
Loading
@@ -12,10 +12,7 @@ import issueSystemNote from './issue_system_note.vue';
import issueCommentForm from './issue_comment_form.vue';
import placeholderNote from './issue_placeholder_note.vue';
import placeholderSystemNote from './issue_placeholder_system_note.vue';
Vue.use(Vuex);
Vue.use(VueResource);
const store = new Vuex.Store(storeOptions);
import store from './store';
 
export default {
name: 'IssueNotes',
Loading
Loading
Loading
Loading
@@ -8,9 +8,13 @@ document.addEventListener('DOMContentLoaded', () => {
components: {
issueNotes,
},
template: `
<issue-notes ref="notes" />
`,
render(createElement) {
return createElement('issue-notes', {
attrs: {
ref: 'notes',
},
});
},
});
 
window.issueNotes = {
Loading
Loading
/* global Flash */
import * as types from './mutation_types';
import * as utils from './issue_notes_utils';
import service from '../services/issue_notes_service';
import loadAwardsHandler from '../../awards_handler';
import sidebarTimeTrackingEventHub from '../../sidebar/event_hub';
export const fetchNotes = ({ commit }, path) => service
.fetchNotes(path)
.then(res => res.json())
.then((res) => {
commit(types.SET_INITAL_NOTES, res);
});
export const deleteNote = ({ commit }, note) => service
.deleteNote(note.path)
.then(() => {
commit(types.DELETE_NOTE, note);
});
export const updateNote = ({ commit }, data) => {
const { endpoint, note } = data;
return service
.updateNote(endpoint, note)
.then(res => res.json())
.then((res) => {
commit(types.UPDATE_NOTE, res);
});
};
export const replyToDiscussion = ({ commit }, note) => {
const { endpoint, data } = note;
return service
.replyToDiscussion(endpoint, data)
.then(res => res.json())
.then((res) => {
commit(types.ADD_NEW_REPLY_TO_DISCUSSION, res);
return res;
});
};
export const createNewNote = ({ commit }, note) => {
const { endpoint, data } = note;
return service
.createNewNote(endpoint, data)
.then(res => res.json())
.then((res) => {
if (!res.errors) {
commit(types.ADD_NEW_NOTE, res);
}
return res;
});
};
export const saveNote = ({ commit, dispatch }, noteData) => {
const { note } = noteData.data.note;
let placeholderText = note;
const hasQuickActions = utils.hasQuickActions(placeholderText);
const replyId = noteData.data.in_reply_to_discussion_id;
const methodToDispatch = replyId ? 'replyToDiscussion' : 'createNewNote';
if (hasQuickActions) {
placeholderText = utils.stripQuickActions(placeholderText);
}
if (placeholderText.length) {
commit(types.SHOW_PLACEHOLDER_NOTE, {
noteBody: placeholderText,
replyId,
});
}
if (hasQuickActions) {
commit(types.SHOW_PLACEHOLDER_NOTE, {
isSystemNote: true,
noteBody: utils.getQuickActionText(note),
replyId,
});
}
return dispatch(methodToDispatch, noteData)
.then((res) => {
const { errors } = res;
const commandsChanges = res.commands_changes;
if (hasQuickActions && Object.keys(errors).length) {
dispatch('poll');
$('.js-gfm-input').trigger('clear-commands-cache.atwho');
Flash('Commands applied', 'notice', $(noteData.flashContainer));
}
if (commandsChanges) {
if (commandsChanges.emoji_award) {
const votesBlock = $('.js-awards-block').eq(0);
loadAwardsHandler()
.then((awardsHandler) => {
awardsHandler.addAwardToEmojiBar(votesBlock, commandsChanges.emoji_award);
awardsHandler.scrollToAwards();
})
.catch(() => {
Flash(
'Something went wrong while adding your award. Please try again.',
null,
$(noteData.flashContainer),
);
});
}
if (commandsChanges.spend_time != null || commandsChanges.time_estimate != null) {
sidebarTimeTrackingEventHub.$emit('timeTrackingUpdated', res);
}
}
if (errors && errors.commands_only) {
Flash(errors.commands_only, 'notice', $(noteData.flashContainer));
}
commit(types.REMOVE_PLACEHOLDER_NOTES);
return res;
})
.catch(() => {
Flash(
'Your comment could not be submitted! Please check your network connection and try again.',
'alert',
$(noteData.flashContainer),
);
commit(types.REMOVE_PLACEHOLDER_NOTES);
});
};
export const poll = ({ commit, state, getters }) => {
const { notesPath } = $('.js-notes-wrapper')[0].dataset;
return service
.poll(`${notesPath}?full_data=1`, state.lastFetchedAt)
.then(res => res.json())
.then((res) => {
if (res.notes.length) {
const { notesById } = getters;
res.notes.forEach((note) => {
if (notesById[note.id]) {
commit(types.UPDATE_NOTE, note);
} else if (note.type === 'DiscussionNote') {
const discussion = utils.findNoteObjectById(state.notes, note.discussion_id);
if (discussion) {
commit(types.ADD_NEW_REPLY_TO_DISCUSSION, note);
} else {
commit(types.ADD_NEW_NOTE, note);
}
} else {
commit(types.ADD_NEW_NOTE, note);
}
});
}
return res;
});
};
export const toggleAward = ({ commit, getters, dispatch }, data) => {
const { endpoint, awardName, noteId, skipMutalityCheck } = data;
const note = getters.notesById[noteId];
return service
.toggleAward(endpoint, { name: awardName })
.then(res => res.json())
.then(() => {
commit(types.TOGGLE_AWARD, { awardName, note });
if (!skipMutalityCheck && (awardName === 'thumbsup' || awardName === 'thumbsdown')) {
const counterAward = awardName === 'thumbsup' ? 'thumbsdown' : 'thumbsup';
const targetNote = getters.notesById[noteId];
let amIAwarded = false;
targetNote.award_emoji.forEach((a) => {
if (a.name === counterAward && a.user.id === window.gon.current_user_id) {
amIAwarded = true;
}
});
if (amIAwarded) {
Object.assign(data, { awardName: counterAward });
Object.assign(data, { skipMutalityCheck: true });
dispatch(types.TOGGLE_AWARD, data);
}
}
});
};
export const scrollToNoteIfNeeded = (context, el) => {
const isInViewport = gl.utils.isInViewport(el[0]);
if (!isInViewport) {
gl.utils.scrollToElement(el);
}
};
export const notes = state => state.notes;
export const targetNoteHash = state => state.targetNoteHash;
export const notesById = (state) => {
const notesByIdObject = {};
state.notes.forEach((note) => {
note.notes.forEach((n) => {
notesByIdObject[n.id] = n;
});
});
return notesByIdObject;
};
import Vue from 'vue';
import Vuex from 'vuex';
import * as actions from './actions';
import * as getters from './getters';
import mutations from './mutations';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
notes: [],
targetNoteHash: null,
lastFetchedAt: null,
},
actions,
getters,
mutations,
});
/* eslint-disable no-param-reassign */
/* global Flash */
import service from '../services/issue_notes_service';
import utils from './issue_notes_utils';
import loadAwardsHandler from '../../awards_handler';
import sidebarTimeTrackingEventHub from '../../sidebar/event_hub';
const state = {
notes: [],
targetNoteHash: null,
lastFetchedAt: null,
};
const getters = {
notes(storeState) {
return storeState.notes;
},
targetNoteHash(storeState) {
return storeState.targetNoteHash;
},
notesById(storeState) {
const notesById = {};
storeState.notes.forEach((note) => {
note.notes.forEach((n) => {
notesById[n.id] = n;
});
});
return notesById;
},
};
const mutations = {
setInitialNotes(storeState, notes) {
storeState.notes = notes;
},
setTargetNoteHash(storeState, hash) {
storeState.targetNoteHash = hash;
},
toggleDiscussion(storeState, { discussionId }) {
const discussion = utils.findNoteObjectById(storeState.notes, discussionId);
discussion.expanded = !discussion.expanded;
},
deleteNote(storeState, note) {
const noteObj = utils.findNoteObjectById(storeState.notes, note.discussion_id);
if (noteObj.individual_note) {
storeState.notes.splice(storeState.notes.indexOf(noteObj), 1);
} else {
const comment = utils.findNoteObjectById(noteObj.notes, note.id);
noteObj.notes.splice(noteObj.notes.indexOf(comment), 1);
if (!noteObj.notes.length) {
storeState.notes.splice(storeState.notes.indexOf(noteObj), 1);
}
}
},
addNewReplyToDiscussion(storeState, note) {
const noteObj = utils.findNoteObjectById(storeState.notes, note.discussion_id);
if (noteObj) {
noteObj.notes.push(note);
}
},
updateNote(storeState, note) {
const noteObj = utils.findNoteObjectById(storeState.notes, note.discussion_id);
if (noteObj.individual_note) {
noteObj.notes.splice(0, 1, note);
} else {
const comment = utils.findNoteObjectById(noteObj.notes, note.id);
noteObj.notes.splice(noteObj.notes.indexOf(comment), 1, note);
}
},
addNewNote(storeState, note) {
const { discussion_id, type } = note;
const noteData = {
expanded: true,
id: discussion_id,
individual_note: !(type === 'DiscussionNote'),
notes: [note],
reply_id: discussion_id,
};
storeState.notes.push(noteData);
},
toggleAward(storeState, data) {
const { awardName, note } = data;
const { id, name, username } = window.gl.currentUserData;
let index = -1;
note.award_emoji.forEach((a, i) => {
if (a.name === awardName && a.user.id === id) {
index = i;
}
});
if (index > -1) { // if I am awarded, remove my award
note.award_emoji.splice(index, 1);
} else {
note.award_emoji.push({
name: awardName,
user: { id, name, username },
});
}
},
setLastFetchedAt(storeState, fetchedAt) {
storeState.lastFetchedAt = fetchedAt;
},
showPlaceholderNote(storeState, data) {
let notesArr = storeState.notes;
if (data.replyId) {
notesArr = utils.findNoteObjectById(notesArr, data.replyId).notes;
}
notesArr.push({
individual_note: true,
isPlaceholderNote: true,
placeholderType: data.isSystemNote ? 'systemNote' : 'note',
notes: [
{
body: data.noteBody,
},
],
});
},
removePlaceholderNotes(storeState) {
const { notes } = storeState;
for (let i = notes.length - 1; i >= 0; i -= 1) {
const note = notes[i];
const children = note.notes;
if (children.length && !note.individual_note) { // remove placeholder from discussions
for (let j = children.length - 1; j >= 0; j -= 1) {
if (children[j].isPlaceholderNote) {
children.splice(j, 1);
}
}
} else if (note.isPlaceholderNote) { // remove placeholders from state root
notes.splice(i, 1);
}
}
},
};
const actions = {
fetchNotes(context, path) {
return service
.fetchNotes(path)
.then(res => res.json())
.then((res) => {
context.commit('setInitialNotes', res);
});
},
deleteNote(context, note) {
return service
.deleteNote(note.path)
.then(() => {
context.commit('deleteNote', note);
});
},
updateNote(context, data) {
const { endpoint, note } = data;
return service
.updateNote(endpoint, note)
.then(res => res.json())
.then((res) => {
context.commit('updateNote', res);
});
},
replyToDiscussion(context, noteData) {
const { endpoint, data } = noteData;
return service
.replyToDiscussion(endpoint, data)
.then(res => res.json())
.then((res) => {
context.commit('addNewReplyToDiscussion', res);
return res;
});
},
createNewNote(context, noteData) {
const { endpoint, data } = noteData;
return service
.createNewNote(endpoint, data)
.then(res => res.json())
.then((res) => {
if (!res.errors) {
context.commit('addNewNote', res);
}
return res;
});
},
saveNote(context, noteData) {
const { note } = noteData.data.note;
let placeholderText = note;
const hasQuickActions = utils.hasQuickActions(placeholderText);
const replyId = noteData.data.in_reply_to_discussion_id;
const methodToDispatch = replyId ? 'replyToDiscussion' : 'createNewNote';
if (hasQuickActions) {
placeholderText = utils.stripQuickActions(placeholderText);
}
if (placeholderText.length) {
context.commit('showPlaceholderNote', {
noteBody: placeholderText,
replyId,
});
}
if (hasQuickActions) {
context.commit('showPlaceholderNote', {
isSystemNote: true,
noteBody: utils.getQuickActionText(note),
replyId,
});
}
return context.dispatch(methodToDispatch, noteData)
.then((res) => {
const { errors } = res;
const commandsChanges = res.commands_changes;
if (hasQuickActions && Object.keys(errors).length) {
context.dispatch('poll');
$('.js-gfm-input').trigger('clear-commands-cache.atwho');
Flash('Commands applied', 'notice', $(noteData.flashContainer));
}
if (commandsChanges) {
if (commandsChanges.emoji_award) {
const votesBlock = $('.js-awards-block').eq(0);
loadAwardsHandler().then((awardsHandler) => {
awardsHandler.addAwardToEmojiBar(votesBlock, commandsChanges.emoji_award);
awardsHandler.scrollToAwards();
}).catch(() => {
const msg = 'Something went wrong while adding your award. Please try again.';
Flash(msg, $(noteData.flashContainer));
});
}
if (commandsChanges.spend_time != null || commandsChanges.time_estimate != null) {
sidebarTimeTrackingEventHub.$emit('timeTrackingUpdated', res);
}
}
if (errors && errors.commands_only) {
Flash(errors.commands_only, 'notice', $(noteData.flashContainer));
}
context.commit('removePlaceholderNotes');
return res;
})
.catch(() => {
const msg = 'Your comment could not be submitted! Please check your network connection and try again.';
Flash(msg, 'alert', $(noteData.flashContainer));
context.commit('removePlaceholderNotes');
});
},
poll(context) {
const { notesPath } = $('.js-notes-wrapper')[0].dataset;
return service
.poll(`${notesPath}?full_data=1`, context.state.lastFetchedAt)
.then(res => res.json())
.then((res) => {
if (res.notes.length) {
const { notesById } = context.getters;
res.notes.forEach((note) => {
if (notesById[note.id]) {
context.commit('updateNote', note);
} else if (note.type === 'DiscussionNote') {
const discussion = utils.findNoteObjectById(context.state.notes, note.discussion_id);
if (discussion) {
context.commit('addNewReplyToDiscussion', note);
} else {
context.commit('addNewNote', note);
}
} else {
context.commit('addNewNote', note);
}
});
}
return res;
});
},
toggleAward(context, data) {
const { endpoint, awardName, noteId, skipMutalityCheck } = data;
const note = context.getters.notesById[noteId];
return service
.toggleAward(endpoint, { name: awardName })
.then(res => res.json())
.then(() => {
context.commit('toggleAward', { awardName, note });
if (!skipMutalityCheck && (awardName === 'thumbsup' || awardName === 'thumbsdown')) {
const counterAward = awardName === 'thumbsup' ? 'thumbsdown' : 'thumbsup';
const targetNote = context.getters.notesById[noteId];
let amIAwarded = false;
targetNote.award_emoji.forEach((a) => {
if (a.name === counterAward && a.user.id === window.gon.current_user_id) {
amIAwarded = true;
}
});
if (amIAwarded) {
data.awardName = counterAward;
data.skipMutalityCheck = true;
context.dispatch('toggleAward', data);
}
}
});
},
scrollToNoteIfNeeded(context, el) {
const isInViewport = gl.utils.isInViewport(el[0]);
if (!isInViewport) {
gl.utils.scrollToElement(el);
}
},
};
export default {
state,
getters,
mutations,
actions,
};
import AjaxCache from '~/lib/utils/ajax_cache';
const REGEX_QUICK_ACTIONS = /^\/\w+.*$/gm;
export default {
findNoteObjectById(notes, id) {
return notes.filter(n => n.id === id)[0];
},
getQuickActionText(note) {
let text = 'Applying command';
const quickActions = AjaxCache.get(gl.GfmAutoComplete.dataSources.commands) || [];
const executedCommands = quickActions.filter((command) => {
const commandRegex = new RegExp(`/${command.name}`);
return commandRegex.test(note);
});
if (executedCommands && executedCommands.length) {
if (executedCommands.length > 1) {
text = 'Applying multiple commands';
} else {
const commandDescription = executedCommands[0].description.toLowerCase();
text = `Applying command to ${commandDescription}`;
}
}
return text;
},
hasQuickActions(note) {
return REGEX_QUICK_ACTIONS.test(note);
},
stripQuickActions(note) {
return note.replace(REGEX_QUICK_ACTIONS, '').trim();
},
};
export const ADD_NEW_NOTE = 'ADD_NEW_NOTE';
export const ADD_NEW_REPLY_TO_DISCUSSION = 'ADD_NEW_REPLY_TO_DISCUSSION';
export const DELETE_NOTE = 'DELETE_NOTE';
export const REMOVE_PLACEHOLDER_NOTES = 'REMOVE_PLACEHOLDER_NOTES';
export const SET_INITAL_NOTES = 'SET_INITIAL_NOTES';
export const SET_LAST_FETCHED_AT = 'SET_LAST_FETCHED_AT';
export const SET_TARGET_NOTE_HASH = 'SET_TARGET_NOTE_HASH';
export const SHOW_PLACEHOLDER_NOTE = 'SHOW_PLACEHOLDER_NOTE';
export const TOGGLE_AWARD = 'TOGGLE_AWARD';
export const TOGGLE_DISCUSSION = 'TOGGLE_DISCUSSION';
export const UPDATE_NOTE = 'UPDATE_NOTE';
import * as utils from './utils';
import * as types from './mutation_types';
export default {
[types.ADD_NEW_NOTE](state, note) {
const { discussion_id, type } = note;
const noteData = {
expanded: true,
id: discussion_id,
individual_note: !(type === 'DiscussionNote'),
notes: [note],
reply_id: discussion_id,
};
state.notes.push(noteData);
},
[types.ADD_NEW_REPLY_TO_DISCUSSION](state, note) {
const noteObj = utils.findNoteObjectById(state.notes, note.discussion_id);
if (noteObj) {
noteObj.notes.push(note);
}
},
[types.DELETE_NOTE](state, note) {
const noteObj = utils.findNoteObjectById(state.notes, note.discussion_id);
if (noteObj.individual_note) {
state.notes.splice(state.notes.indexOf(noteObj), 1);
} else {
const comment = utils.findNoteObjectById(noteObj.notes, note.id);
noteObj.notes.splice(noteObj.notes.indexOf(comment), 1);
if (!noteObj.notes.length) {
state.notes.splice(state.notes.indexOf(noteObj), 1);
}
}
},
[types.REMOVE_PLACEHOLDER_NOTES](state) {
const { notes } = state;
for (let i = notes.length - 1; i >= 0; i -= 1) {
const note = notes[i];
const children = note.notes;
if (children.length && !note.individual_note) { // remove placeholder from discussions
for (let j = children.length - 1; j >= 0; j -= 1) {
if (children[j].isPlaceholderNote) {
children.splice(j, 1);
}
}
} else if (note.isPlaceholderNote) { // remove placeholders from state root
notes.splice(i, 1);
}
}
},
[types.SET_INITAL_NOTES](state, notes) {
state.notes = notes;
},
[types.SET_LAST_FETCHED_AT](state, fetchedAt) {
state.lastFetchedAt = fetchedAt;
},
[types.SET_TARGET_NOTE_HASH](state, hash) {
state.targetNoteHash = hash;
},
[types.SHOW_PLACEHOLDER_NOTE](state, data) {
let notesArr = state.notes;
if (data.replyId) {
notesArr = utils.findNoteObjectById(notesArr, data.replyId).notes;
}
notesArr.push({
individual_note: true,
isPlaceholderNote: true,
placeholderType: data.isSystemNote ? 'systemNote' : 'note',
notes: [
{
body: data.noteBody,
},
],
});
},
[types.TOGGLE_AWARD](state, data) {
const { awardName, note } = data;
const { id, name, username } = window.gl.currentUserData;
let index = -1;
note.award_emoji.forEach((a, i) => {
if (a.name === awardName && a.user.id === id) {
index = i;
}
});
if (index > -1) { // if I am awarded, remove my award
note.award_emoji.splice(index, 1);
} else {
note.award_emoji.push({
name: awardName,
user: { id, name, username },
});
}
},
[types.TOGGLE_DISCUSSION](state, { discussionId }) {
const discussion = utils.findNoteObjectById(state.notes, discussionId);
discussion.expanded = !discussion.expanded;
},
[types.UPDATE_NOTE](state, note) {
const noteObj = utils.findNoteObjectById(state.notes, note.discussion_id);
if (noteObj.individual_note) {
noteObj.notes.splice(0, 1, note);
} else {
const comment = utils.findNoteObjectById(noteObj.notes, note.id);
noteObj.notes.splice(noteObj.notes.indexOf(comment), 1, note);
}
},
};
import AjaxCache from '~/lib/utils/ajax_cache';
const REGEX_QUICK_ACTIONS = /^\/\w+.*$/gm;
export const findNoteObjectById = (notes, id) => notes.filter(n => n.id === id)[0];
export const getQuickActionText = (note) => {
let text = 'Applying command';
const quickActions = AjaxCache.get(gl.GfmAutoComplete.dataSources.commands) || [];
const executedCommands = quickActions.filter((command) => {
const commandRegex = new RegExp(`/${command.name}`);
return commandRegex.test(note);
});
if (executedCommands && executedCommands.length) {
if (executedCommands.length > 1) {
text = 'Applying multiple commands';
} else {
const commandDescription = executedCommands[0].description.toLowerCase();
text = `Applying command to ${commandDescription}`;
}
}
return text;
};
export const hasQuickActions = note => REGEX_QUICK_ACTIONS.test(note);
export const stripQuickActions = note => note.replace(REGEX_QUICK_ACTIONS, '').trim();
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment