[ci skip] Fix shortcuts for preview

This commit is contained in:
Filipa Lacerda 2017-07-28 19:59:31 +01:00
parent 9b87e680ca
commit f5a21c596b
8 changed files with 175 additions and 177 deletions

View file

@ -89,10 +89,10 @@
if (res.errors.commands_only) { if (res.errors.commands_only) {
this.discard(); this.discard();
} else { } else {
this.handleError(); return Flash('Something went wrong while adding your comment. Please try again.');
} }
} else { } else {
return Flash('Something went wrong while adding your comment. Please try again.'); this.discard();
} }
}) })
.catch(() => { .catch(() => {
@ -132,7 +132,7 @@
editCurrentUserLastNote() { editCurrentUserLastNote() {
if (this.note === '') { if (this.note === '') {
const lastNote = this.getCurrentUserLastNote(window.gon.current_user_id); const lastNote = this.getCurrentUserLastNote(window.gon.current_user_id);
console.log(lastNote)
if (lastNote) { if (lastNote) {
eventHub.$emit('enterEditMode', { eventHub.$emit('enterEditMode', {
noteId: lastNote.id, noteId: lastNote.id,
@ -172,102 +172,104 @@
/> />
</div> </div>
<div class="js-main-target-form timeline-content timeline-content-form common-note-form"> <div class="js-main-target-form timeline-content timeline-content-form common-note-form">
<markdown-field <form>
:markdown-preview-url="markdownPreviewUrl" <markdown-field
:markdown-docs="markdownDocsUrl" :markdown-preview-url="markdownPreviewUrl"
:quick-actions-docs="quickActionsDocsUrl" :markdown-docs="markdownDocsUrl"
:add-spacing-classes="false"> :quick-actions-docs="quickActionsDocsUrl"
<textarea :add-spacing-classes="false">
id="note-body" <textarea
name="note[note]" id="note-body"
class="note-textarea js-gfm-input js-autosize markdown-area js-note-text" name="note[note]"
data-supports-slash-commands="true" class="note-textarea js-gfm-input js-autosize markdown-area js-note-text"
data-supports-quick-actions="true" data-supports-slash-commands="true"
aria-label="Description" data-supports-quick-actions="true"
v-model="note" aria-label="Description"
ref="textarea" v-model="note"
slot="textarea" ref="textarea"
placeholder="Write a comment or drag your files here..." slot="textarea"
@keydown.up="editCurrentUserLastNote()" placeholder="Write a comment or drag your files here..."
@keydown.meta.enter="handleSave()"> @keydown.up="editCurrentUserLastNote()"
</textarea> @keydown.meta.enter="handleSave()">
</markdown-field> </textarea>
<div class="note-form-actions"> </markdown-field>
<div class="pull-left btn-group append-right-10 comment-type-dropdown js-comment-type-dropdown droplab-dropdown"> <div class="note-form-actions">
<button <div class="pull-left btn-group append-right-10 comment-type-dropdown js-comment-type-dropdown droplab-dropdown">
@click="handleSave" <button
:disabled="!note.length" @click="handleSave()"
class="btn btn-nr btn-create comment-btn js-comment-button js-comment-submit-button" :disabled="!note.length"
type="button"> class="btn btn-nr btn-create comment-btn js-comment-button js-comment-submit-button"
{{commentButtonTitle}} type="button">
</button> {{commentButtonTitle}}
<button </button>
:disabled="!note.length" <button
name="button" :disabled="!note.length"
type="button" name="button"
class="btn btn-nr comment-btn note-type-toggle js-note-new-discussion dropdown-toggle" type="button"
data-toggle="dropdown" class="btn btn-nr comment-btn note-type-toggle js-note-new-discussion dropdown-toggle"
aria-label="Open comment type dropdown"> data-toggle="dropdown"
<i aria-label="Open comment type dropdown">
aria-hidden="true" <i
class="fa fa-caret-down toggle-icon"> aria-hidden="true"
</i> class="fa fa-caret-down toggle-icon">
</button> </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' }"> <li :class="{ 'droplab-item-selected': noteType === 'comment' }">
<button <button
type="button" type="button"
class="btn btn-transparent" class="btn btn-transparent"
@click.prevent="setNoteType('comment')"> @click.prevent="setNoteType('comment')">
<i <i
aria-hidden="true" aria-hidden="true"
class="fa fa-check icon"> 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">
</i> </i>
<div class="description"> <div class="description">
<strong>Start discussion</strong> <strong>Comment</strong>
<p> <p>
Discuss a specific suggestion or question. Add a general comment to this issue.
</p> </p>
</div> </div>
</button> </button>
</li> </li>
</ul> <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> </div>
<button </form>
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>
</div> </div>
</div> </div>
</li> </li>

View file

@ -94,7 +94,6 @@
to ensure information is not lost. to ensure information is not lost.
</div> </div>
<form <form
@submit="handleUpdate"
class="edit-note common-note-form"> class="edit-note common-note-form">
<markdown-field <markdown-field
:markdown-preview-url="markdownPreviewUrl" :markdown-preview-url="markdownPreviewUrl"
@ -103,7 +102,7 @@
<textarea <textarea
id="note-body" id="note-body"
name="note[note]" 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-slash-commands="true"
data-supports-quick-actions="true" data-supports-quick-actions="true"
aria-label="Description" aria-label="Description"
@ -118,7 +117,8 @@
</markdown-field> </markdown-field>
<div class="note-form-actions clearfix"> <div class="note-form-actions clearfix">
<button <button
type="submit" type="button"
@click="handleUpdate"
class="btn btn-nr btn-save"> class="btn btn-nr btn-save">
{{saveButtonTitle}} {{saveButtonTitle}}
</button> </button>

View file

@ -48,6 +48,7 @@
computed: { computed: {
...mapGetters([ ...mapGetters([
'notes', 'notes',
'notesById',
'getNotesDataByProp', 'getNotesDataByProp',
]), ]),
}, },
@ -55,7 +56,7 @@
...mapActions({ ...mapActions({
actionFetchNotes: 'fetchNotes', actionFetchNotes: 'fetchNotes',
poll: 'poll', poll: 'poll',
toggleAward: 'toggleAward', actionToggleAward: 'toggleAward',
scrollToNoteIfNeeded: 'scrollToNoteIfNeeded', scrollToNoteIfNeeded: 'scrollToNoteIfNeeded',
setNotesData: 'setNotesData', setNotesData: 'setNotesData',
setIssueData: 'setIssueData', setIssueData: 'setIssueData',
@ -113,11 +114,11 @@
const { awardName, noteId } = data; const { awardName, noteId } = data;
const endpoint = this.notesById[noteId].toggle_award_path; const endpoint = this.notesById[noteId].toggle_award_path;
this.toggleAward({ endpoint, awardName, noteId }) this.actionToggleAward({ endpoint, awardName, noteId })
.catch(() => Flash('Something went wrong on our end.')); .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) => { $(document).on('issuable:change', (e, isClosed) => {
eventHub.$emit('issueStateChanged', isClosed); eventHub.$emit('issueStateChanged', isClosed);
}); });

View file

@ -1,45 +1,48 @@
import Vue from 'vue'; import Vue from 'vue';
import issueNotesApp from './components/issue_notes_app.vue'; import issueNotesApp from './components/issue_notes_app.vue';
document.addEventListener('DOMContentLoaded', () => new Vue({ document.addEventListener('DOMContentLoaded', () => {
el: '#js-vue-notes', const vm = new Vue({
components: { el: '#js-vue-notes',
issueNotesApp, components: {
}, issueNotesApp,
data() { },
const notesDataset = document.getElementById('js-vue-notes').dataset; data() {
const notesDataset = document.getElementById('js-vue-notes').dataset;
return { return {
issueData: JSON.parse(notesDataset.issueData), issueData: JSON.parse(notesDataset.issueData),
currentUserData: JSON.parse(notesDataset.currentUserData), currentUserData: JSON.parse(notesDataset.currentUserData),
notesData: { notesData: {
lastFetchedAt: notesDataset.lastFetchedAt, lastFetchedAt: notesDataset.lastFetchedAt,
discussionsPath: notesDataset.discussionsPath, discussionsPath: notesDataset.discussionsPath,
newSessionPath: notesDataset.newSessionPath, newSessionPath: notesDataset.newSessionPath,
registerPath: notesDataset.registerPath, registerPath: notesDataset.registerPath,
notesPath: notesDataset.notesPath, notesPath: notesDataset.notesPath,
markdownDocs: notesDataset.markdownDocs, markdownDocs: notesDataset.markdownDocs,
quickActionsDocs: notesDataset.quickActionsDocs, quickActionsDocs: notesDataset.quickActionsDocs,
}, },
}; };
}, },
render(createElement) { render(createElement) {
return createElement('issue-notes-app', { return createElement('issue-notes-app', {
attrs: { attrs: {
ref: 'notes', ref: 'notes',
}, },
props: { props: {
issueData: this.issueData, issueData: this.issueData,
notesData: this.notesData, notesData: this.notesData,
userData: this.currentUserData, 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');
// },
// };

View file

@ -131,32 +131,31 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
}); });
}; };
export const poll = ({ commit, state, getters }) => { export const poll = ({ commit, state, getters }) => service
return service.poll(state.notesData.notesPath, state.lastFetchedAt) .poll(state.notesData.notesPath, state.lastFetchedAt)
.then(res => res.json()) .then(res => res.json())
.then((res) => { .then((res) => {
if (res.notes.length) { if (res.notes.length) {
const { notesById } = getters; const { notesById } = getters;
res.notes.forEach((note) => { res.notes.forEach((note) => {
if (notesById[note.id]) { if (notesById[note.id]) {
commit(types.UPDATE_NOTE, note); commit(types.UPDATE_NOTE, note);
} else if (note.type === constants.DISCUSSION_NOTE) { } else if (note.type === constants.DISCUSSION_NOTE) {
const discussion = utils.findNoteObjectById(state.notes, note.discussion_id); const discussion = utils.findNoteObjectById(state.notes, note.discussion_id);
if (discussion) { if (discussion) {
commit(types.ADD_NEW_REPLY_TO_DISCUSSION, note); commit(types.ADD_NEW_REPLY_TO_DISCUSSION, note);
} else {
commit(types.ADD_NEW_NOTE, note);
}
} else { } else {
commit(types.ADD_NEW_NOTE, note); commit(types.ADD_NEW_NOTE, note);
} }
}); } else {
} commit(types.ADD_NEW_NOTE, note);
return res; }
}); });
}; }
return res;
});
export const toggleAward = ({ commit, getters, dispatch }, data) => { export const toggleAward = ({ commit, getters, dispatch }, data) => {
const { endpoint, awardName, noteId, skipMutalityCheck } = data; const { endpoint, awardName, noteId, skipMutalityCheck } = data;

View file

@ -10,17 +10,10 @@ export const getIssueDataByProp = state => prop => state.issueData[prop];
export const getUserData = state => state.userData; export const getUserData = state => state.userData;
export const getUserDataByProp = state => prop => state.notesData[prop]; export const getUserDataByProp = state => prop => state.notesData[prop];
export const notesById = (state) => { export const notesById = state => state.notes.reduce((acc, note) => {
const notesByIdObject = {}; note.notes.every(n => Object.assign(acc, { [n.id]: n }));
// TODO: FILIPA: TRANSFORM INTO A REDUCE return acc;
state.notes.forEach((note) => { }, {});
note.notes.forEach((n) => {
notesByIdObject[n.id] = n;
});
});
return notesByIdObject;
};
const reverseNotes = array => array.slice(0).reverse(); const reverseNotes = array => array.slice(0).reverse();
const isLastNote = (note, userId) => !note.system && note.author.id === userId; const isLastNote = (note, userId) => !note.system && note.author.id === userId;
@ -31,6 +24,7 @@ export const getCurrentUserLastNote = state => userId => reverseNotes(state.note
return acc; return acc;
}, []).filter(el => el !== undefined)[0]; }, []).filter(el => el !== undefined)[0];
// eslint-disable-next-line no-unused-vars
export const getDiscussionLastNote = state => (discussion, userId) => reverseNotes(discussion.notes) export const getDiscussionLastNote = state => (discussion, userId) => reverseNotes(discussion.notes)
.find(el => isLastNote(el, userId)); .find(el => isLastNote(el, userId));

View file

@ -16,7 +16,6 @@ export default new Vuex.Store({
notesData: {}, notesData: {},
userData: {}, userData: {},
issueData: {}, issueData: {},
paths: {},
}, },
actions, actions,
getters, getters,

View file

@ -9,7 +9,7 @@
new_session_path: new_session_path(:user, redirect_to_referer: 'yes'), new_session_path: new_session_path(:user, redirect_to_referer: 'yes'),
markdown_docs: help_page_path('user/markdown'), markdown_docs: help_page_path('user/markdown'),
quick_actions_docs: help_page_path('user/project/quick_actions'), 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, last_fetched_at: Time.now.to_i,
issue_data: serialize_issuable(@issue), issue_data: serialize_issuable(@issue),
current_user_data: UserSerializer.new.represent(current_user).to_json }} current_user_data: UserSerializer.new.represent(current_user).to_json }}