Commit bf88af0e authored by Fatih Acet's avatar Fatih Acet

IssueNotesRefactor: Implement quick actions with system note placeholders.

parent d9928d1a
<script>
/* global Flash */
import AjaxCache from '~/lib/utils/ajax_cache';
import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import MarkdownField from '../../vue_shared/components/markdown/field.vue';
import IssueNoteSignedOutWidget from './issue_note_signed_out_widget.vue';
import eventHub from '../event_hub';
const REGEX_QUICK_ACTIONS = /^\/\w+.*$/gm;
export default {
props: {},
data() {
const { create_note_path, state } = window.gl.issueData;
const { currentUserData } = window.gl;
......@@ -67,14 +68,14 @@ export default {
}
this.$store.dispatch('createNewNote', data)
.then((res) => {
if (res.errors) {
this.handleError();
} else {
this.discard();
}
})
.then(this.handleNewNoteCreated)
.catch(this.handleError);
if (this.hasQuickActions()) {
this.$store.commit('showPlaceholderSystemNote', {
noteBody: this.getQuickActionText(),
});
}
}
if (withIssueAction) {
......@@ -93,6 +94,26 @@ export default {
$(`.js-btn-issue-action.${btnClass}:visible`).trigger('click');
}
},
handleNewNoteCreated(res) {
const { commands_changes, errors, valid } = res;
if (!valid && errors) {
const { commands_only } = errors;
if (commands_only) {
new Flash(commands_only, 'notice', $(this.$el)); // eslint-disable-line
$(this.$refs.textarea).trigger('clear-commands-cache.atwho');
this.$store.dispatch('poll');
this.discard();
} else {
this.handleError();
}
} else {
this.discard();
}
this.$store.commit('removePlaceholderSystemNote');
},
discard() {
// `blur` is needed to clear slash commands autocomplete cache if event fired.
// `focus` is needed to remain cursor in the textarea.
......@@ -117,6 +138,30 @@ export default {
}
}
},
getQuickActionText() {
let text = 'Applying command';
const quickActions = AjaxCache.get(gl.GfmAutoComplete.dataSources.commands);
const { note } = this;
const executedCommands = quickActions.filter((command, index) => {
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() {
return REGEX_QUICK_ACTIONS.test(this.note);
},
},
mounted() {
const issuableDataEl = document.getElementById('js-issuable-app-initial-data');
......@@ -141,6 +186,7 @@ export default {
class="notes notes-form timeline new-note">
<li class="timeline-entry">
<div class="timeline-entry-inner">
<div class="flash-container timeline-content"></div>
<div class="timeline-icon hidden-xs hidden-sm">
<user-avatar-link
v-if="author"
......
......@@ -9,6 +9,7 @@ import IssueNote from './issue_note.vue';
import IssueDiscussion from './issue_discussion.vue';
import IssueSystemNote from './issue_system_note.vue';
import IssueCommentForm from './issue_comment_form.vue';
import PlaceholderSystemNote from './issue_placeholder_system_note.vue';
Vue.use(Vuex);
const store = new Vuex.Store(storeOptions);
......@@ -26,6 +27,7 @@ export default {
IssueDiscussion,
IssueSystemNote,
IssueCommentForm,
PlaceholderSystemNote,
},
computed: {
...Vuex.mapGetters([
......@@ -35,7 +37,12 @@ export default {
},
methods: {
component(note) {
if (note.individual_note) {
if (note.placeholderNote) {
if (note.placeholderType === 'systemNote') {
return PlaceholderSystemNote;
}
}
else if (note.individual_note) {
return note.notes[0].system ? IssueSystemNote : IssueNote;
}
......
<script>
export default {
props: {
note: {
type: Object,
required: true,
}
},
};
</script>
<template>
<li class="note system-note timeline-entry being-posted fade-in-half">
<div class="timeline-entry-inner">
<div class="timeline-content">
<i>{{note.body}}</i>
</div>
</div>
</li>
</template>
......@@ -108,6 +108,32 @@ const mutations = {
setLastFetchedAt(storeState, fetchedAt) {
storeState.lastFetchedAt = fetchedAt;
},
showPlaceholderSystemNote(storeState, data) {
storeState.notes.push({
placeholderNote: true,
individual_note: true,
placeholderType: 'systemNote',
notes: [
{
id: 'placeholderSystemNote',
body: data.noteBody,
},
],
});
},
removePlaceholderSystemNote(storeState) {
let index = -1;
storeState.notes.forEach((n, i) => {
if (n.placeholderNote && n.placeholderType === 'systemNote') {
index = i;
}
});
if (index > -1) {
storeState.notes.splice(index, 1);
}
},
};
const actions = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment