[ci skip] Fix shortcuts for preview
This commit is contained in:
parent
9b87e680ca
commit
f5a21c596b
8 changed files with 175 additions and 177 deletions
|
@ -89,10 +89,10 @@
|
|||
if (res.errors.commands_only) {
|
||||
this.discard();
|
||||
} else {
|
||||
this.handleError();
|
||||
return Flash('Something went wrong while adding your comment. Please try again.');
|
||||
}
|
||||
} else {
|
||||
return Flash('Something went wrong while adding your comment. Please try again.');
|
||||
this.discard();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
|
@ -132,7 +132,7 @@
|
|||
editCurrentUserLastNote() {
|
||||
if (this.note === '') {
|
||||
const lastNote = this.getCurrentUserLastNote(window.gon.current_user_id);
|
||||
console.log(lastNote)
|
||||
|
||||
if (lastNote) {
|
||||
eventHub.$emit('enterEditMode', {
|
||||
noteId: lastNote.id,
|
||||
|
@ -172,102 +172,104 @@
|
|||
/>
|
||||
</div>
|
||||
<div class="js-main-target-form timeline-content timeline-content-form common-note-form">
|
||||
<markdown-field
|
||||
:markdown-preview-url="markdownPreviewUrl"
|
||||
:markdown-docs="markdownDocsUrl"
|
||||
:quick-actions-docs="quickActionsDocsUrl"
|
||||
:add-spacing-classes="false">
|
||||
<textarea
|
||||
id="note-body"
|
||||
name="note[note]"
|
||||
class="note-textarea js-gfm-input js-autosize markdown-area js-note-text"
|
||||
data-supports-slash-commands="true"
|
||||
data-supports-quick-actions="true"
|
||||
aria-label="Description"
|
||||
v-model="note"
|
||||
ref="textarea"
|
||||
slot="textarea"
|
||||
placeholder="Write a comment or drag your files here..."
|
||||
@keydown.up="editCurrentUserLastNote()"
|
||||
@keydown.meta.enter="handleSave()">
|
||||
</textarea>
|
||||
</markdown-field>
|
||||
<div class="note-form-actions">
|
||||
<div class="pull-left btn-group append-right-10 comment-type-dropdown js-comment-type-dropdown droplab-dropdown">
|
||||
<button
|
||||
@click="handleSave"
|
||||
:disabled="!note.length"
|
||||
class="btn btn-nr btn-create comment-btn js-comment-button js-comment-submit-button"
|
||||
type="button">
|
||||
{{commentButtonTitle}}
|
||||
</button>
|
||||
<button
|
||||
:disabled="!note.length"
|
||||
name="button"
|
||||
type="button"
|
||||
class="btn btn-nr comment-btn note-type-toggle js-note-new-discussion dropdown-toggle"
|
||||
data-toggle="dropdown"
|
||||
aria-label="Open comment type dropdown">
|
||||
<i
|
||||
aria-hidden="true"
|
||||
class="fa fa-caret-down toggle-icon">
|
||||
</i>
|
||||
</button>
|
||||
<form>
|
||||
<markdown-field
|
||||
:markdown-preview-url="markdownPreviewUrl"
|
||||
:markdown-docs="markdownDocsUrl"
|
||||
:quick-actions-docs="quickActionsDocsUrl"
|
||||
:add-spacing-classes="false">
|
||||
<textarea
|
||||
id="note-body"
|
||||
name="note[note]"
|
||||
class="note-textarea js-gfm-input js-autosize markdown-area js-note-text"
|
||||
data-supports-slash-commands="true"
|
||||
data-supports-quick-actions="true"
|
||||
aria-label="Description"
|
||||
v-model="note"
|
||||
ref="textarea"
|
||||
slot="textarea"
|
||||
placeholder="Write a comment or drag your files here..."
|
||||
@keydown.up="editCurrentUserLastNote()"
|
||||
@keydown.meta.enter="handleSave()">
|
||||
</textarea>
|
||||
</markdown-field>
|
||||
<div class="note-form-actions">
|
||||
<div class="pull-left btn-group append-right-10 comment-type-dropdown js-comment-type-dropdown droplab-dropdown">
|
||||
<button
|
||||
@click="handleSave()"
|
||||
:disabled="!note.length"
|
||||
class="btn btn-nr btn-create comment-btn js-comment-button js-comment-submit-button"
|
||||
type="button">
|
||||
{{commentButtonTitle}}
|
||||
</button>
|
||||
<button
|
||||
:disabled="!note.length"
|
||||
name="button"
|
||||
type="button"
|
||||
class="btn btn-nr comment-btn note-type-toggle js-note-new-discussion dropdown-toggle"
|
||||
data-toggle="dropdown"
|
||||
aria-label="Open comment type dropdown">
|
||||
<i
|
||||
aria-hidden="true"
|
||||
class="fa fa-caret-down toggle-icon">
|
||||
</i>
|
||||
</button>
|
||||
|
||||
<ul class="note-type-dropdown dropdown-open-top dropdown-menu">
|
||||
<li :class="{ 'droplab-item-selected': noteType === 'comment' }">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-transparent"
|
||||
@click.prevent="setNoteType('comment')">
|
||||
<i
|
||||
aria-hidden="true"
|
||||
class="fa fa-check icon">
|
||||
</i>
|
||||
<div class="description">
|
||||
<strong>Comment</strong>
|
||||
<p>
|
||||
Add a general comment to this issue.
|
||||
</p>
|
||||
</div>
|
||||
</button>
|
||||
</li>
|
||||
<li class="divider droplab-item-ignore"></li>
|
||||
<li :class="{ 'droplab-item-selected': noteType === 'discussion' }">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-transparent"
|
||||
@click.prevent="setNoteType('discussion')">
|
||||
<i
|
||||
aria-hidden="true"
|
||||
class="fa fa-check icon">
|
||||
<ul class="note-type-dropdown dropdown-open-top dropdown-menu">
|
||||
<li :class="{ 'droplab-item-selected': noteType === 'comment' }">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-transparent"
|
||||
@click.prevent="setNoteType('comment')">
|
||||
<i
|
||||
aria-hidden="true"
|
||||
class="fa fa-check icon">
|
||||
</i>
|
||||
<div class="description">
|
||||
<strong>Start discussion</strong>
|
||||
<p>
|
||||
Discuss a specific suggestion or question.
|
||||
</p>
|
||||
</div>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="description">
|
||||
<strong>Comment</strong>
|
||||
<p>
|
||||
Add a general comment to this issue.
|
||||
</p>
|
||||
</div>
|
||||
</button>
|
||||
</li>
|
||||
<li class="divider droplab-item-ignore"></li>
|
||||
<li :class="{ 'droplab-item-selected': noteType === 'discussion' }">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-transparent"
|
||||
@click.prevent="setNoteType('discussion')">
|
||||
<i
|
||||
aria-hidden="true"
|
||||
class="fa fa-check icon">
|
||||
</i>
|
||||
<div class="description">
|
||||
<strong>Start discussion</strong>
|
||||
<p>
|
||||
Discuss a specific suggestion or question.
|
||||
</p>
|
||||
</div>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
@click="handleSave(true)"
|
||||
v-if="canUpdateIssue"
|
||||
:class="actionButtonClassNames"
|
||||
class="btn btn-nr btn-comment btn-comment-and-close">
|
||||
{{issueActionButtonTitle}}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
v-if="note.length"
|
||||
@click="discard"
|
||||
class="btn btn-cancel js-note-discard">
|
||||
Discard draft
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
@click="handleSave(true)"
|
||||
v-if="canUpdateIssue"
|
||||
:class="actionButtonClassNames"
|
||||
class="btn btn-nr btn-comment btn-comment-and-close">
|
||||
{{issueActionButtonTitle}}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
v-if="note.length"
|
||||
@click="discard"
|
||||
class="btn btn-cancel js-note-discard">
|
||||
Discard draft
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
|
|
@ -94,7 +94,6 @@
|
|||
to ensure information is not lost.
|
||||
</div>
|
||||
<form
|
||||
@submit="handleUpdate"
|
||||
class="edit-note common-note-form">
|
||||
<markdown-field
|
||||
:markdown-preview-url="markdownPreviewUrl"
|
||||
|
@ -103,7 +102,7 @@
|
|||
<textarea
|
||||
id="note-body"
|
||||
name="note[note]"
|
||||
class="note-textarea js-gfm-input js-autosize markdown-area js-note-text"
|
||||
class="note-textarea js-gfm-input js-autosize markdown-area"
|
||||
data-supports-slash-commands="true"
|
||||
data-supports-quick-actions="true"
|
||||
aria-label="Description"
|
||||
|
@ -118,7 +117,8 @@
|
|||
</markdown-field>
|
||||
<div class="note-form-actions clearfix">
|
||||
<button
|
||||
type="submit"
|
||||
type="button"
|
||||
@click="handleUpdate"
|
||||
class="btn btn-nr btn-save">
|
||||
{{saveButtonTitle}}
|
||||
</button>
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
computed: {
|
||||
...mapGetters([
|
||||
'notes',
|
||||
'notesById',
|
||||
'getNotesDataByProp',
|
||||
]),
|
||||
},
|
||||
|
@ -55,7 +56,7 @@
|
|||
...mapActions({
|
||||
actionFetchNotes: 'fetchNotes',
|
||||
poll: 'poll',
|
||||
toggleAward: 'toggleAward',
|
||||
actionToggleAward: 'toggleAward',
|
||||
scrollToNoteIfNeeded: 'scrollToNoteIfNeeded',
|
||||
setNotesData: 'setNotesData',
|
||||
setIssueData: 'setIssueData',
|
||||
|
@ -113,11 +114,11 @@
|
|||
const { awardName, noteId } = data;
|
||||
const endpoint = this.notesById[noteId].toggle_award_path;
|
||||
|
||||
this.toggleAward({ endpoint, awardName, noteId })
|
||||
.catch(() => Flash('Something went wrong on our end.'));
|
||||
this.actionToggleAward({ endpoint, awardName, noteId })
|
||||
.catch((error) => Flash('Something went wrong on our end.'));
|
||||
});
|
||||
|
||||
//TODO: FILIPA: REMOVE JQUERY
|
||||
// JQuery is needed here because it is a custom event being dispatched with jQuery.
|
||||
$(document).on('issuable:change', (e, isClosed) => {
|
||||
eventHub.$emit('issueStateChanged', isClosed);
|
||||
});
|
||||
|
|
|
@ -1,45 +1,48 @@
|
|||
import Vue from 'vue';
|
||||
import issueNotesApp from './components/issue_notes_app.vue';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => new Vue({
|
||||
el: '#js-vue-notes',
|
||||
components: {
|
||||
issueNotesApp,
|
||||
},
|
||||
data() {
|
||||
const notesDataset = document.getElementById('js-vue-notes').dataset;
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const vm = new Vue({
|
||||
el: '#js-vue-notes',
|
||||
components: {
|
||||
issueNotesApp,
|
||||
},
|
||||
data() {
|
||||
const notesDataset = document.getElementById('js-vue-notes').dataset;
|
||||
|
||||
return {
|
||||
issueData: JSON.parse(notesDataset.issueData),
|
||||
currentUserData: JSON.parse(notesDataset.currentUserData),
|
||||
notesData: {
|
||||
lastFetchedAt: notesDataset.lastFetchedAt,
|
||||
discussionsPath: notesDataset.discussionsPath,
|
||||
newSessionPath: notesDataset.newSessionPath,
|
||||
registerPath: notesDataset.registerPath,
|
||||
notesPath: notesDataset.notesPath,
|
||||
markdownDocs: notesDataset.markdownDocs,
|
||||
quickActionsDocs: notesDataset.quickActionsDocs,
|
||||
},
|
||||
};
|
||||
},
|
||||
render(createElement) {
|
||||
return createElement('issue-notes-app', {
|
||||
attrs: {
|
||||
ref: 'notes',
|
||||
},
|
||||
props: {
|
||||
issueData: this.issueData,
|
||||
notesData: this.notesData,
|
||||
userData: this.currentUserData,
|
||||
},
|
||||
});
|
||||
},
|
||||
}));
|
||||
return {
|
||||
issueData: JSON.parse(notesDataset.issueData),
|
||||
currentUserData: JSON.parse(notesDataset.currentUserData),
|
||||
notesData: {
|
||||
lastFetchedAt: notesDataset.lastFetchedAt,
|
||||
discussionsPath: notesDataset.discussionsPath,
|
||||
newSessionPath: notesDataset.newSessionPath,
|
||||
registerPath: notesDataset.registerPath,
|
||||
notesPath: notesDataset.notesPath,
|
||||
markdownDocs: notesDataset.markdownDocs,
|
||||
quickActionsDocs: notesDataset.quickActionsDocs,
|
||||
},
|
||||
};
|
||||
},
|
||||
render(createElement) {
|
||||
return createElement('issue-notes-app', {
|
||||
attrs: {
|
||||
ref: 'notes',
|
||||
},
|
||||
props: {
|
||||
issueData: this.issueData,
|
||||
notesData: this.notesData,
|
||||
userData: this.currentUserData,
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// This is used in note_polling_spec
|
||||
window.issueNotes = {
|
||||
refresh() {
|
||||
vm.$refs.notes.$store.dispatch('poll');
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
// // TODO: FILIPA: FIX THIS
|
||||
// window.issueNotes = {
|
||||
// refresh() {
|
||||
// vm.$refs.notes.$store.dispatch('poll');
|
||||
// },
|
||||
// };
|
||||
|
|
|
@ -131,32 +131,31 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
|
|||
});
|
||||
};
|
||||
|
||||
export const poll = ({ commit, state, getters }) => {
|
||||
return service.poll(state.notesData.notesPath, state.lastFetchedAt)
|
||||
.then(res => res.json())
|
||||
.then((res) => {
|
||||
if (res.notes.length) {
|
||||
const { notesById } = getters;
|
||||
export const poll = ({ commit, state, getters }) => service
|
||||
.poll(state.notesData.notesPath, 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 === constants.DISCUSSION_NOTE) {
|
||||
const discussion = utils.findNoteObjectById(state.notes, note.discussion_id);
|
||||
res.notes.forEach((note) => {
|
||||
if (notesById[note.id]) {
|
||||
commit(types.UPDATE_NOTE, note);
|
||||
} else if (note.type === constants.DISCUSSION_NOTE) {
|
||||
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);
|
||||
}
|
||||
if (discussion) {
|
||||
commit(types.ADD_NEW_REPLY_TO_DISCUSSION, note);
|
||||
} else {
|
||||
commit(types.ADD_NEW_NOTE, note);
|
||||
}
|
||||
});
|
||||
}
|
||||
return res;
|
||||
});
|
||||
};
|
||||
} else {
|
||||
commit(types.ADD_NEW_NOTE, note);
|
||||
}
|
||||
});
|
||||
}
|
||||
return res;
|
||||
});
|
||||
|
||||
export const toggleAward = ({ commit, getters, dispatch }, data) => {
|
||||
const { endpoint, awardName, noteId, skipMutalityCheck } = data;
|
||||
|
|
|
@ -10,17 +10,10 @@ export const getIssueDataByProp = state => prop => state.issueData[prop];
|
|||
export const getUserData = state => state.userData;
|
||||
export const getUserDataByProp = state => prop => state.notesData[prop];
|
||||
|
||||
export const notesById = (state) => {
|
||||
const notesByIdObject = {};
|
||||
// TODO: FILIPA: TRANSFORM INTO A REDUCE
|
||||
state.notes.forEach((note) => {
|
||||
note.notes.forEach((n) => {
|
||||
notesByIdObject[n.id] = n;
|
||||
});
|
||||
});
|
||||
|
||||
return notesByIdObject;
|
||||
};
|
||||
export const notesById = state => state.notes.reduce((acc, note) => {
|
||||
note.notes.every(n => Object.assign(acc, { [n.id]: n }));
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
const reverseNotes = array => array.slice(0).reverse();
|
||||
const isLastNote = (note, userId) => !note.system && note.author.id === userId;
|
||||
|
@ -31,6 +24,7 @@ export const getCurrentUserLastNote = state => userId => reverseNotes(state.note
|
|||
return acc;
|
||||
}, []).filter(el => el !== undefined)[0];
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
export const getDiscussionLastNote = state => (discussion, userId) => reverseNotes(discussion.notes)
|
||||
.find(el => isLastNote(el, userId));
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@ export default new Vuex.Store({
|
|||
notesData: {},
|
||||
userData: {},
|
||||
issueData: {},
|
||||
paths: {},
|
||||
},
|
||||
actions,
|
||||
getters,
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
new_session_path: new_session_path(:user, redirect_to_referer: 'yes'),
|
||||
markdown_docs: help_page_path('user/markdown'),
|
||||
quick_actions_docs: help_page_path('user/project/quick_actions'),
|
||||
notes_path: '#{notes_url}?full_data=1',
|
||||
notes_path: "#{notes_url}?full_data=1",
|
||||
last_fetched_at: Time.now.to_i,
|
||||
issue_data: serialize_issuable(@issue),
|
||||
current_user_data: UserSerializer.new.represent(current_user).to_json }}
|
||||
|
|
Loading…
Reference in a new issue