Commit f9c58d93 authored by Phil Hughes's avatar Phil Hughes

Refactored diff notes Vue app

It now relies on its Vue bundle rather than the window. Fixes some reactivity issues that was happening in EE
parent 4975f416
/* eslint-disable comma-dangle, object-shorthand, func-names, no-else-return, quotes, no-lonely-if, max-len */
/* global Vue */
/* global CommentsStore */
const Vue = require('vue');
(() => {
const CommentAndResolveBtn = Vue.extend({
......@@ -9,13 +9,11 @@
},
data() {
return {
textareaIsEmpty: true
textareaIsEmpty: true,
discussion: {},
};
},
computed: {
discussion: function () {
return CommentsStore.state[this.discussionId];
},
showButton: function () {
if (this.discussion) {
return this.discussion.isResolvable();
......@@ -42,6 +40,9 @@
}
}
},
created() {
this.discussion = CommentsStore.state[this.discussionId];
},
mounted: function () {
const $textarea = $(`#new-discussion-note-form-${this.discussionId} .note-textarea`);
this.textareaIsEmpty = $textarea.val() === '';
......
/* eslint-disable comma-dangle, object-shorthand, func-names, no-else-return, guard-for-in, no-restricted-syntax, one-var, space-before-function-paren, no-lonely-if, no-continue, brace-style, max-len, quotes */
/* global Vue */
/* global DiscussionMixins */
/* global CommentsStore */
const Vue = require('vue');
(() => {
const JumpToDiscussion = Vue.extend({
......@@ -12,12 +12,10 @@
data: function () {
return {
discussions: CommentsStore.state,
discussion: {},
};
},
computed: {
discussion: function () {
return this.discussions[this.discussionId];
},
allResolved: function () {
return this.unresolvedDiscussionCount === 0;
},
......@@ -186,7 +184,10 @@
offset: -($('.navbar-gitlab').outerHeight() + $('.layout-nav').outerHeight())
});
}
}
},
created() {
this.discussion = this.discussions[this.discussionId];
},
});
Vue.component('jump-to-discussion', JumpToDiscussion);
......
/* eslint-disable comma-dangle, object-shorthand, func-names, quote-props, no-else-return, camelcase, no-new, max-len */
/* global Vue */
/* global CommentsStore */
/* global ResolveService */
/* global Flash */
const Vue = require('vue');
(() => {
const ResolveBtn = Vue.extend({
......@@ -10,14 +10,14 @@
noteId: Number,
discussionId: String,
resolved: Boolean,
projectPath: String,
canResolve: Boolean,
resolvedBy: String
},
data: function () {
return {
discussions: CommentsStore.state,
loading: false
loading: false,
note: {},
};
},
watch: {
......@@ -30,13 +30,6 @@
discussion: function () {
return this.discussions[this.discussionId];
},
note: function () {
if (this.discussion) {
return this.discussion.getNote(this.noteId);
} else {
return undefined;
}
},
buttonText: function () {
if (this.isResolved) {
return `Resolved by ${this.resolvedByName}`;
......@@ -73,10 +66,10 @@
if (this.isResolved) {
promise = ResolveService
.unresolve(this.projectPath, this.noteId);
.unresolve(this.noteId);
} else {
promise = ResolveService
.resolve(this.projectPath, this.noteId);
.resolve(this.noteId);
}
promise.then((response) => {
......@@ -106,6 +99,8 @@
},
created: function () {
CommentsStore.create(this.discussionId, this.noteId, this.canResolve, this.resolved, this.resolvedBy);
this.note = this.discussion.getNote(this.noteId);
}
});
......
/* eslint-disable comma-dangle, object-shorthand, func-names, no-param-reassign */
/* global Vue */
/* global DiscussionMixins */
/* global CommentsStore */
const Vue = require('vue');
((w) => {
w.ResolveCount = Vue.extend({
......
/* eslint-disable object-shorthand, func-names, space-before-function-paren, comma-dangle, no-else-return, quotes, max-len */
/* global Vue */
/* global CommentsStore */
/* global ResolveService */
const Vue = require('vue');
(() => {
const ResolveDiscussionBtn = Vue.extend({
props: {
discussionId: String,
mergeRequestId: Number,
projectPath: String,
canResolve: Boolean,
},
data: function() {
return {
discussions: CommentsStore.state
discussion: {},
};
},
computed: {
discussion: function () {
return this.discussions[this.discussionId];
},
showButton: function () {
if (this.discussion) {
return this.discussion.isResolvable();
......@@ -51,11 +48,13 @@
},
methods: {
resolve: function () {
ResolveService.toggleResolveForDiscussion(this.projectPath, this.mergeRequestId, this.discussionId);
ResolveService.toggleResolveForDiscussion(this.mergeRequestId, this.discussionId);
}
},
created: function () {
CommentsStore.createDiscussion(this.discussionId, this.canResolve);
this.discussion = CommentsStore.state[this.discussionId];
}
});
......
......@@ -3,6 +3,7 @@
/* global ResolveCount */
function requireAll(context) { return context.keys().map(context); }
const Vue = require('vue');
requireAll(require.context('./models', false, /^\.\/.*\.(js|es6)$/));
requireAll(require.context('./stores', false, /^\.\/.*\.(js|es6)$/));
requireAll(require.context('./services', false, /^\.\/.*\.(js|es6)$/));
......@@ -10,11 +11,14 @@ requireAll(require.context('./mixins', false, /^\.\/.*\.(js|es6)$/));
requireAll(require.context('./components', false, /^\.\/.*\.(js|es6)$/));
$(() => {
const projectPath = document.querySelector('.merge-request').dataset.projectPath;
const COMPONENT_SELECTOR = 'resolve-btn, resolve-discussion-btn, jump-to-discussion, comment-and-resolve-btn';
window.gl = window.gl || {};
window.gl.diffNoteApps = {};
window.ResolveService = new gl.DiffNotesResolveServiceClass(projectPath);
gl.diffNotesCompileComponents = () => {
const $components = $(COMPONENT_SELECTOR).filter(function () {
return $(this).closest('resolve-count').length !== 1;
......
/* eslint-disable class-methods-use-this, one-var, camelcase, no-new, comma-dangle, no-param-reassign, max-len */
/* global Vue */
/* global Flash */
/* global CommentsStore */
((w) => {
class ResolveServiceClass {
constructor() {
this.noteResource = Vue.resource('notes{/noteId}/resolve');
this.discussionResource = Vue.resource('merge_requests{/mergeRequestId}/discussions{/discussionId}/resolve');
}
const Vue = window.Vue = require('vue');
window.Vue.use(require('vue-resource'));
setCSRF() {
Vue.http.headers.common['X-CSRF-Token'] = $.rails.csrfToken();
}
(() => {
window.gl = window.gl || {};
prepareRequest(root) {
this.setCSRF();
Vue.http.options.root = root;
}
class ResolveServiceClass {
constructor(root) {
this.noteResource = Vue.resource(`${root}/notes{/noteId}/resolve`);
this.discussionResource = Vue.resource(`${root}/merge_requests{/mergeRequestId}/discussions{/discussionId}/resolve`);
resolve(projectPath, noteId) {
this.prepareRequest(projectPath);
Vue.http.interceptors.push((request, next) => {
if ($.rails) {
request.headers['X-CSRF-Token'] = $.rails.csrfToken();
}
next();
});
}
resolve(noteId) {
return this.noteResource.save({ noteId }, {});
}
unresolve(projectPath, noteId) {
this.prepareRequest(projectPath);
unresolve(noteId) {
return this.noteResource.delete({ noteId }, {});
}
toggleResolveForDiscussion(projectPath, mergeRequestId, discussionId) {
toggleResolveForDiscussion(mergeRequestId, discussionId) {
const discussion = CommentsStore.state[discussionId];
const isResolved = discussion.isResolved();
let promise;
if (isResolved) {
promise = this.unResolveAll(projectPath, mergeRequestId, discussionId);
promise = this.unResolveAll(mergeRequestId, discussionId);
} else {
promise = this.resolveAll(projectPath, mergeRequestId, discussionId);
promise = this.resolveAll(mergeRequestId, discussionId);
}
promise.then((response) => {
......@@ -62,11 +60,9 @@
});
}
resolveAll(projectPath, mergeRequestId, discussionId) {
resolveAll(mergeRequestId, discussionId) {
const discussion = CommentsStore.state[discussionId];
this.prepareRequest(projectPath);
discussion.loading = true;
return this.discussionResource.save({
......@@ -75,11 +71,9 @@
}, {});
}
unResolveAll(projectPath, mergeRequestId, discussionId) {
unResolveAll(mergeRequestId, discussionId) {
const discussion = CommentsStore.state[discussionId];
this.prepareRequest(projectPath);
discussion.loading = true;
return this.discussionResource.delete({
......@@ -89,5 +83,5 @@
}
}
w.ResolveService = new ResolveServiceClass();
})(window);
gl.DiffNotesResolveServiceClass = ResolveServiceClass;
})();
......@@ -455,7 +455,7 @@ require('vendor/task_list');
var mergeRequestId = $form.data('noteable-iid');
if (ResolveService != null) {
ResolveService.toggleResolveForDiscussion(projectPath, mergeRequestId, discussionId);
ResolveService.toggleResolveForDiscussion(mergeRequestId, discussionId);
}
}
......
- if discussion.for_merge_request?
%resolve-discussion-btn{ ":project-path" => "'#{project_path(discussion.project)}'",
":discussion-id" => "'#{discussion.id}'",
%resolve-discussion-btn{ ":discussion-id" => "'#{discussion.id}'",
":merge-request-id" => discussion.noteable.iid,
":can-resolve" => discussion.can_resolve?(current_user),
"inline-template" => true }
......
......@@ -3,10 +3,9 @@
- page_description @merge_request.description
- page_card_attributes @merge_request.card_attributes
- content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('lib_vue')
= page_specific_javascript_bundle_tag('diff_notes')
.merge-request{ 'data-url' => merge_request_path(@merge_request) }
.merge-request{ 'data-url' => merge_request_path(@merge_request), 'data-project-path' => project_path(@merge_request.project) }
= render "projects/merge_requests/show/mr_title"
.merge-request-details.issuable-details{ data: { id: @merge_request.project.id } }
......
......@@ -30,8 +30,7 @@
- if note.resolvable?
- can_resolve = can?(current_user, :resolve_note, note)
%resolve-btn{ "project-path" => "#{project_path(note.project)}",
"discussion-id" => "#{note.discussion_id}",
%resolve-btn{ "discussion-id" => "#{note.discussion_id}",
":note-id" => note.id,
":resolved" => note.resolved?,
":can-resolve" => can_resolve,
......
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