IssueDiscussionsRefactor: Implement polling mechanism.
This commit is contained in:
parent
17d67a989b
commit
15f3362d34
5 changed files with 71 additions and 8 deletions
|
@ -133,13 +133,13 @@ export default {
|
||||||
ref="textarea"
|
ref="textarea"
|
||||||
slot="textarea"
|
slot="textarea"
|
||||||
placeholder="Write a comment or drag your files here..."
|
placeholder="Write a comment or drag your files here..."
|
||||||
@keydown.meta.enter="handleSave">
|
@keydown.meta.enter="handleSave()">
|
||||||
</textarea>
|
</textarea>
|
||||||
</markdown-field>
|
</markdown-field>
|
||||||
<div class="note-form-actions clearfix">
|
<div class="note-form-actions clearfix">
|
||||||
<div class="pull-left btn-group append-right-10 comment-type-dropdown js-comment-type-dropdown">
|
<div class="pull-left btn-group append-right-10 comment-type-dropdown js-comment-type-dropdown">
|
||||||
<input
|
<input
|
||||||
@click="handleSave"
|
@click="handleSave()"
|
||||||
:disabled="!note.length"
|
:disabled="!note.length"
|
||||||
:value="commentButtonTitle"
|
:value="commentButtonTitle"
|
||||||
class="btn btn-nr btn-create comment-btn js-comment-button js-comment-submit-button"
|
class="btn btn-nr btn-create comment-btn js-comment-button js-comment-submit-button"
|
||||||
|
|
|
@ -39,14 +39,27 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
const path = this.$el.parentNode.dataset.discussionsPath;
|
const { discussionsPath, notesPath, lastFetchedAt } = this.$el.parentNode.dataset;
|
||||||
this.$store.dispatch('fetchNotes', path)
|
this.$store.dispatch('fetchNotes', discussionsPath)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
new Flash('Something went wrong while fetching issue comments. Please try again.'); // eslint-disable-line
|
new Flash('Something went wrong while fetching issue comments. Please try again.'); // eslint-disable-line
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
endpoint: `${notesPath}?full_data=1`,
|
||||||
|
lastFetchedAt,
|
||||||
|
};
|
||||||
|
|
||||||
|
// FIXME: @fatihacet Implement real polling mechanism
|
||||||
|
setInterval(() => {
|
||||||
|
this.$store.dispatch('poll', options)
|
||||||
|
.then((res) => {
|
||||||
|
options.lastFetchedAt = res.last_fetched_at;
|
||||||
|
});
|
||||||
|
}, 6000);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -19,4 +19,13 @@ export default {
|
||||||
createNewNote(endpoint, data) {
|
createNewNote(endpoint, data) {
|
||||||
return Vue.http.post(endpoint, data, { emulateJSON: true });
|
return Vue.http.post(endpoint, data, { emulateJSON: true });
|
||||||
},
|
},
|
||||||
|
poll(endpoint, lastFetchedAt) {
|
||||||
|
const options = {
|
||||||
|
headers: {
|
||||||
|
'X-Last-Fetched-At': lastFetchedAt,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return Vue.http.get(endpoint, options);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,7 +15,7 @@ const getters = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const mutations = {
|
const mutations = {
|
||||||
setNotes(storeState, notes) {
|
setInitialNotes(storeState, notes) {
|
||||||
storeState.notes = notes;
|
storeState.notes = notes;
|
||||||
},
|
},
|
||||||
toggleDiscussion(storeState, { discussionId }) {
|
toggleDiscussion(storeState, { discussionId }) {
|
||||||
|
@ -40,7 +40,9 @@ const mutations = {
|
||||||
addNewReplyToDiscussion(storeState, note) {
|
addNewReplyToDiscussion(storeState, note) {
|
||||||
const noteObj = findNoteObjectById(storeState.notes, note.discussion_id);
|
const noteObj = findNoteObjectById(storeState.notes, note.discussion_id);
|
||||||
|
|
||||||
noteObj.notes.push(note);
|
if (noteObj) {
|
||||||
|
noteObj.notes.push(note);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
updateNote(storeState, note) {
|
updateNote(storeState, note) {
|
||||||
const noteObj = findNoteObjectById(storeState.notes, note.discussion_id);
|
const noteObj = findNoteObjectById(storeState.notes, note.discussion_id);
|
||||||
|
@ -72,7 +74,7 @@ const actions = {
|
||||||
.fetchNotes(path)
|
.fetchNotes(path)
|
||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
context.commit('setNotes', res);
|
context.commit('setInitialNotes', res);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
deleteNote(context, note) {
|
deleteNote(context, note) {
|
||||||
|
@ -114,6 +116,45 @@ const actions = {
|
||||||
return res;
|
return res;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
poll(context, data) {
|
||||||
|
const { endpoint, lastFetchedAt } = data;
|
||||||
|
|
||||||
|
return service
|
||||||
|
.poll(endpoint, lastFetchedAt)
|
||||||
|
.then(res => res.json())
|
||||||
|
.then((res) => {
|
||||||
|
if (res.notes.length) {
|
||||||
|
const notesById = {};
|
||||||
|
|
||||||
|
// Simple lookup object to check whether we have a discussion id already in our store
|
||||||
|
context.state.notes.forEach((note) => {
|
||||||
|
note.notes.forEach((n) => {
|
||||||
|
notesById[n.id] = true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
res.notes.forEach((note) => {
|
||||||
|
if (notesById[note.id]) {
|
||||||
|
context.commit('updateNote', note);
|
||||||
|
} else {
|
||||||
|
if (note.type === 'DiscussionNote') {
|
||||||
|
const discussion = 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;
|
||||||
|
});
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
= link_to 'Reopen issue', issue_path(@issue, issue: {state_event: :reopen}, format: 'json'), data: {original_text: "Reopen issue", alternative_text: "Comment & reopen issue"}, class: "btn btn-nr btn-reopen btn-comment js-note-target-reopen #{issue_button_visibility(@issue, false)}", title: 'Reopen issue'
|
= link_to 'Reopen issue', issue_path(@issue, issue: {state_event: :reopen}, format: 'json'), data: {original_text: "Reopen issue", alternative_text: "Comment & reopen issue"}, class: "btn btn-nr btn-reopen btn-comment js-note-target-reopen #{issue_button_visibility(@issue, false)}", title: 'Reopen issue'
|
||||||
= link_to 'Close issue', issue_path(@issue, issue: {state_event: :close}, format: 'json'), data: {original_text: "Close issue", alternative_text: "Comment & close issue"}, class: "btn btn-nr btn-close btn-comment js-note-target-close #{issue_button_visibility(@issue, true)}", title: 'Close issue'
|
= link_to 'Close issue', issue_path(@issue, issue: {state_event: :close}, format: 'json'), data: {original_text: "Close issue", alternative_text: "Comment & close issue"}, class: "btn btn-nr btn-close btn-comment js-note-target-close #{issue_button_visibility(@issue, true)}", title: 'Close issue'
|
||||||
|
|
||||||
%section{ data: { discussions_path: discussions_namespace_project_issue_path(@project.namespace, @project, @issue, format: :json), new_session_path: new_session_path(:user, redirect_to_referer: 'yes') } }
|
%section{ data: { discussions_path: discussions_namespace_project_issue_path(@project.namespace, @project, @issue, format: :json), new_session_path: new_session_path(:user, redirect_to_referer: 'yes'), notes_path: notes_url, last_fetched_at: Time.now.to_i } }
|
||||||
#js-notes
|
#js-notes
|
||||||
- content_for :page_specific_javascripts do
|
- content_for :page_specific_javascripts do
|
||||||
= webpack_bundle_tag 'common_vue'
|
= webpack_bundle_tag 'common_vue'
|
||||||
|
|
Loading…
Reference in a new issue