Commit 6362c0c6 authored by Filipa Lacerda's avatar Filipa Lacerda

Merge branch 'fix-broken-master-specs' into 'master'

Fix broken master specs

See merge request !1190
parents 40e3494d d1f8e381
...@@ -26,7 +26,7 @@ class PipelinesStore { ...@@ -26,7 +26,7 @@ class PipelinesStore {
*/ */
startTimeAgoLoops() { startTimeAgoLoops() {
const startTimeLoops = () => { const startTimeLoops = () => {
this.timeLoopInterval = setInterval(function timeloopInterval() { this.timeLoopInterval = setInterval(() => {
this.$children[0].$children.reduce((acc, component) => { this.$children[0].$children.reduce((acc, component) => {
const timeAgoComponent = component.$children.filter(el => el.$options._componentTag === 'time-ago')[0]; const timeAgoComponent = component.$children.filter(el => el.$options._componentTag === 'time-ago')[0];
acc.push(timeAgoComponent); acc.push(timeAgoComponent);
......
/* eslint-disable comma-dangle, object-shorthand, func-names, no-else-return, quotes, no-lonely-if, max-len */ /* eslint-disable comma-dangle, object-shorthand, func-names, no-else-return, quotes, no-lonely-if, max-len */
/* global Vue */ /* global Vue */
/* global CommentsStore */ /* global CommentsStore */
const Vue = require('vue');
(() => { (() => {
const CommentAndResolveBtn = Vue.extend({ const CommentAndResolveBtn = Vue.extend({
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
/* global Vue */ /* global Vue */
/* global DiscussionMixins */ /* global DiscussionMixins */
/* global CommentsStore */ /* global CommentsStore */
const Vue = require('vue');
(() => { (() => {
const JumpToDiscussion = Vue.extend({ const JumpToDiscussion = Vue.extend({
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
/* global CommentsStore */ /* global CommentsStore */
/* global ResolveService */ /* global ResolveService */
/* global Flash */ /* global Flash */
const Vue = require('vue');
(() => { (() => {
const ResolveBtn = Vue.extend({ const ResolveBtn = Vue.extend({
...@@ -16,6 +17,7 @@ ...@@ -16,6 +17,7 @@
}, },
data: function () { data: function () {
return { return {
note: {},
discussions: CommentsStore.state, discussions: CommentsStore.state,
loading: false loading: false
}; };
...@@ -30,13 +32,6 @@ ...@@ -30,13 +32,6 @@
discussion: function () { discussion: function () {
return this.discussions[this.discussionId]; return this.discussions[this.discussionId];
}, },
note: function () {
if (this.discussion) {
return this.discussion.getNote(this.noteId);
} else {
return undefined;
}
},
buttonText: function () { buttonText: function () {
if (this.isResolved) { if (this.isResolved) {
return `Resolved by ${this.resolvedByName}`; return `Resolved by ${this.resolvedByName}`;
...@@ -106,6 +101,8 @@ ...@@ -106,6 +101,8 @@
}, },
created: function () { created: function () {
CommentsStore.create(this.discussionId, this.noteId, this.canResolve, this.resolved, this.resolvedBy); CommentsStore.create(this.discussionId, this.noteId, this.canResolve, this.resolved, this.resolvedBy);
this.note = this.discussion.getNote(this.noteId);
} }
}); });
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
/* global Vue */ /* global Vue */
/* global DiscussionMixins */ /* global DiscussionMixins */
/* global CommentsStore */ /* global CommentsStore */
const Vue = require('vue');
((w) => { ((w) => {
w.ResolveCount = Vue.extend({ w.ResolveCount = Vue.extend({
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
/* global Vue */ /* global Vue */
/* global CommentsStore */ /* global CommentsStore */
/* global ResolveService */ /* global ResolveService */
const Vue = require('vue');
(() => { (() => {
const ResolveDiscussionBtn = Vue.extend({ const ResolveDiscussionBtn = Vue.extend({
...@@ -13,13 +14,11 @@ ...@@ -13,13 +14,11 @@
}, },
data: function() { data: function() {
return { return {
discussions: CommentsStore.state discussions: CommentsStore.state,
discussion: {},
}; };
}, },
computed: { computed: {
discussion: function () {
return this.discussions[this.discussionId];
},
showButton: function () { showButton: function () {
if (this.discussion) { if (this.discussion) {
return this.discussion.isResolvable(); return this.discussion.isResolvable();
...@@ -56,6 +55,8 @@ ...@@ -56,6 +55,8 @@
}, },
created: function () { created: function () {
CommentsStore.createDiscussion(this.discussionId, this.canResolve); CommentsStore.createDiscussion(this.discussionId, this.canResolve);
this.discussion = this.discussions[this.discussionId];
} }
}); });
......
/* eslint-disable func-names, comma-dangle, new-cap, no-new, import/newline-after-import, no-multi-spaces, max-len */ /* eslint-disable func-names, comma-dangle, new-cap, no-new, import/newline-after-import, no-multi-spaces, max-len */
/* global Vue */ /* global Vue */
/* global ResolveCount */ /* global ResolveCount */
/* global ResolveServiceClass */
function requireAll(context) { return context.keys().map(context); } function requireAll(context) { return context.keys().map(context); }
const Vue = require('vue');
requireAll(require.context('./models', false, /^\.\/.*\.(js|es6)$/)); requireAll(require.context('./models', false, /^\.\/.*\.(js|es6)$/));
requireAll(require.context('./stores', false, /^\.\/.*\.(js|es6)$/)); requireAll(require.context('./stores', false, /^\.\/.*\.(js|es6)$/));
requireAll(require.context('./services', false, /^\.\/.*\.(js|es6)$/)); requireAll(require.context('./services', false, /^\.\/.*\.(js|es6)$/));
...@@ -10,11 +12,14 @@ requireAll(require.context('./mixins', false, /^\.\/.*\.(js|es6)$/)); ...@@ -10,11 +12,14 @@ requireAll(require.context('./mixins', false, /^\.\/.*\.(js|es6)$/));
requireAll(require.context('./components', 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'; const COMPONENT_SELECTOR = 'resolve-btn, resolve-discussion-btn, jump-to-discussion, comment-and-resolve-btn';
window.gl = window.gl || {}; window.gl = window.gl || {};
window.gl.diffNoteApps = {}; window.gl.diffNoteApps = {};
window.ResolveService = new ResolveServiceClass(projectPath);
gl.diffNotesCompileComponents = () => { gl.diffNotesCompileComponents = () => {
const $components = $(COMPONENT_SELECTOR).filter(function () { const $components = $(COMPONENT_SELECTOR).filter(function () {
return $(this).closest('resolve-count').length !== 1; return $(this).closest('resolve-count').length !== 1;
...@@ -44,6 +49,6 @@ $(() => { ...@@ -44,6 +49,6 @@ $(() => {
el: '#resolve-count-app', el: '#resolve-count-app',
components: { components: {
'resolve-count': ResolveCount 'resolve-count': ResolveCount
} },
}); });
}); });
...@@ -3,20 +3,21 @@ ...@@ -3,20 +3,21 @@
/* global Flash */ /* global Flash */
/* global CommentsStore */ /* global CommentsStore */
((w) => { window.Vue.use(require('vue-resource'));
class ResolveServiceClass {
constructor() { (() => {
this.noteResource = Vue.resource('notes{/noteId}/resolve'); window.ResolveServiceClass = class ResolveServiceClass {
this.discussionResource = Vue.resource('merge_requests{/mergeRequestId}/discussions{/discussionId}/resolve'); constructor(rootPath) {
this.noteResource = Vue.resource(`${rootPath}/notes{/noteId}/resolve`);
this.discussionResource = Vue.resource(`${rootPath}/merge_requests{/mergeRequestId}/discussions{/discussionId}/resolve`);
} }
setCSRF() { setCSRF() {
Vue.http.headers.common['X-CSRF-Token'] = $.rails.csrfToken(); Vue.http.headers.common['X-CSRF-Token'] = $.rails.csrfToken();
} }
prepareRequest(root) { prepareRequest() {
this.setCSRF(); this.setCSRF();
Vue.http.options.root = root;
} }
resolve(projectPath, noteId) { resolve(projectPath, noteId) {
...@@ -87,7 +88,5 @@ ...@@ -87,7 +88,5 @@
discussionId discussionId
}, {}); }, {});
} }
} };
})();
w.ResolveService = new ResolveServiceClass();
})(window);
/* global Vue */
/* global Flash */ /* global Flash */
window.Vue = require('vue');
window.Vue.use(require('vue-resource'));
const Vue = window.Vue;
require('./approvals_store'); require('./approvals_store');
(() => { class ApprovalsApi {
class ApprovalsApi { constructor(endpoint) {
constructor(endpoint) { gl.ApprovalsApi = this;
gl.ApprovalsApi = this; this.init(endpoint);
this.init(endpoint); }
}
init(mergeRequestEndpoint) { init(mergeRequestEndpoint) {
this.baseEndpoint = `${mergeRequestEndpoint}/approvals`; this.baseEndpoint = `${mergeRequestEndpoint}/approvals`;
Vue.http.headers.common['X-CSRF-Token'] = $.rails.csrfToken(); Vue.http.headers.common['X-CSRF-Token'] = $.rails.csrfToken();
} }
fetchApprovals() { fetchApprovals() {
const flashErrorMessage = 'An error occured while retrieving approval data for this merge request.'; const flashErrorMessage = 'An error occured while retrieving approval data for this merge request.';
return Vue.http.get(this.baseEndpoint).catch(() => new Flash(flashErrorMessage)); return Vue.http.get(this.baseEndpoint).catch(() => new Flash(flashErrorMessage));
} }
approveMergeRequest() { approveMergeRequest() {
const flashErrorMessage = 'An error occured while submitting your approval.'; const flashErrorMessage = 'An error occured while submitting your approval.';
return Vue.http.post(this.baseEndpoint).catch(() => new Flash(flashErrorMessage)); return Vue.http.post(this.baseEndpoint).catch(() => new Flash(flashErrorMessage));
} }
unapproveMergeRequest() { unapproveMergeRequest() {
const flashErrorMessage = 'An error occured while removing your approval.'; const flashErrorMessage = 'An error occured while removing your approval.';
return Vue.http.delete(this.baseEndpoint).catch(() => new Flash(flashErrorMessage)); return Vue.http.delete(this.baseEndpoint).catch(() => new Flash(flashErrorMessage));
}
} }
}
gl.ApprovalsApi = ApprovalsApi; window.gl = window.gl || {};
})(); window.gl.ApprovalsApi = ApprovalsApi;
function requireAll(context) { return context.keys().map(context); }
require('./approvals_store'); require('./approvals_store');
require('./approvals_api'); require('./approvals_api');
require('./components/approvals_body');
requireAll(require.context('./components', true, /^\.\/.*\.(js|es6)$/)); require('./components/approvals_footer');
/* global Vue */
require('./approvals_api'); require('./approvals_api');
(() => { let singleton;
let singleton;
class MergeRequestApprovalsStore { class MergeRequestApprovalsStore {
constructor(rootStore) { constructor(rootStore) {
if (!singleton) { if (!singleton) {
singleton = this; singleton = this;
this.init(rootStore); this.init(rootStore);
}
return singleton;
} }
return singleton;
}
init(rootStore) { init(rootStore) {
this.rootStore = rootStore; this.rootStore = rootStore;
this.api = new gl.ApprovalsApi(rootStore.rootEl.dataset.endpoint); this.api = new gl.ApprovalsApi(rootStore.rootEl.dataset.endpoint);
this.state = { this.state = {
fetching: false, fetching: false,
}; };
} }
initStoreOnce() { initStoreOnce() {
const state = this.state; const state = this.state;
if (!state.fetching) { if (!state.fetching) {
state.fetching = true; state.fetching = true;
return this.fetch() return this.fetch()
.then(() => { .then(() => {
state.fetching = false; state.fetching = false;
this.assignToRootStore('showApprovals', true); this.assignToRootStore('showApprovals', true);
}); });
} }
return Promise.resolve(); return Promise.resolve();
} }
fetch() { fetch() {
return this.api.fetchApprovals() return this.api.fetchApprovals()
.then(res => this.assignToRootStore('approvals', res.json())) .then(res => this.assignToRootStore('approvals', res.json()))
.then(data => this.setMergeRequestAcceptanceStatus(data.approvals_left)); .then(data => this.setMergeRequestAcceptanceStatus(data.approvals_left));
} }
approve() { approve() {
return this.api.approveMergeRequest() return this.api.approveMergeRequest()
.then(res => this.assignToRootStore('approvals', res.json())) .then(res => this.assignToRootStore('approvals', res.json()))
.then(data => this.setMergeRequestAcceptanceStatus(data.approvals_left)); .then(data => this.setMergeRequestAcceptanceStatus(data.approvals_left));
} }
unapprove() { unapprove() {
return this.api.unapproveMergeRequest() return this.api.unapproveMergeRequest()
.then(res => this.assignToRootStore('approvals', res.json())) .then(res => this.assignToRootStore('approvals', res.json()))
.then(data => this.setMergeRequestAcceptanceStatus(data.approvals_left)); .then(data => this.setMergeRequestAcceptanceStatus(data.approvals_left));
} }
setMergeRequestAcceptanceStatus(approvalsLeft) { setMergeRequestAcceptanceStatus(approvalsLeft) {
return this.rootStore.assignToData('disableAcceptance', !!approvalsLeft); return this.rootStore.assignToData('disableAcceptance', !!approvalsLeft);
} }
assignToRootStore(key, data) { assignToRootStore(key, data) {
return this.rootStore.assignToData(key, data); return this.rootStore.assignToData(key, data);
}
} }
gl.MergeRequestApprovalsStore = MergeRequestApprovalsStore; }
})(window.gl || (window.gl = {}));
window.gl = window.gl || {};
window.gl.MergeRequestApprovalsStore = MergeRequestApprovalsStore;
/* global Vue */ /* global Vue */
const Vue = require('vue');
require('../approvals_store'); require('../approvals_store');
require('../approvals_api'); require('../approvals_api');
(() => { Vue.component('approvals-body', {
Vue.component('approvals-body', { name: 'approvals-body',
name: 'approvals-body', props: {
props: { approvedBy: {
approvedBy: { type: Array,
type: Array, required: false,
required: false,
},
approvalsLeft: {
type: Number,
required: false,
},
userCanApprove: {
type: Boolean,
required: false,
},
userHasApproved: {
type: Boolean,
required: false,
},
suggestedApprovers: {
type: Array,
required: false,
},
}, },
data() { approvalsLeft: {
return { type: Number,
approving: false, required: false,
};
}, },
computed: { userCanApprove: {
approvalsRequiredStringified() { type: Boolean,
const baseString = `${this.approvalsLeft} more approval`; required: false,
return this.approvalsLeft === 1 ? baseString : `${baseString}s`; },
}, userHasApproved: {
approverNamesStringified() { type: Boolean,
const approvers = this.suggestedApprovers; required: false,
},
suggestedApprovers: {
type: Array,
required: false,
},
},
data() {
return {
approving: false,
};
},
computed: {
approvalsRequiredStringified() {
const baseString = `${this.approvalsLeft} more approval`;
return this.approvalsLeft === 1 ? baseString : `${baseString}s`;
},
approverNamesStringified() {
const approvers = this.suggestedApprovers;
if (!approvers) { if (!approvers) {
return ''; return '';
} }
return approvers.length === 1 ? approvers[0].name : return approvers.length === 1 ? approvers[0].name :
approvers.reduce((memo, curr, index) => { approvers.reduce((memo, curr, index) => {
const nextMemo = `${memo}${curr.name}`; const nextMemo = `${memo}${curr.name}`;
if (index === approvers.length - 2) { // second to last index if (index === approvers.length - 2) { // second to last index
return `${nextMemo} or `; return `${nextMemo} or `;
} else if (index === approvers.length - 1) { // last index } else if (index === approvers.length - 1) { // last index
return nextMemo; return nextMemo;
} }
return `${nextMemo}, `; return `${nextMemo}, `;
}, ''); }, '');
}, },
showApproveButton() { showApproveButton() {
return this.userCanApprove && !this.userHasApproved; return this.userCanApprove && !this.userHasApproved;
},
showSuggestedApprovers() {
return this.suggestedApprovers && this.suggestedApprovers.length;
},
}, },
methods: { showSuggestedApprovers() {
approveMergeRequest() { return this.suggestedApprovers && this.suggestedApprovers.length;
this.approving = true;
return gl.ApprovalsStore.approve().then(() => {
this.approving = false;
});
},
}, },
beforeCreate() { },
gl.ApprovalsStore.initStoreOnce(); methods: {
approveMergeRequest() {
this.approving = true;
return gl.ApprovalsStore.approve().then(() => {
this.approving = false;
});
}, },
template: ` },
<div class='approvals-body mr-widget-footer mr-approvals-footer'> beforeCreate() {
<h4> Requires {{ approvalsRequiredStringified }} gl.ApprovalsStore.initStoreOnce();
<span v-if='showSuggestedApprovers'> (from {{ approverNamesStringified }}) </span> },
</h4> template: `
<div v-if='showApproveButton' class='append-bottom-10'> <div class='approvals-body mr-widget-footer mr-approvals-footer'>
<button <h4> Requires {{ approvalsRequiredStringified }}
:disabled='approving' <span v-if='showSuggestedApprovers'> (from {{ approverNamesStringified }}) </span>
@click='approveMergeRequest' </h4>
class='btn btn-primary approve-btn'> <div v-if='showApproveButton' class='append-bottom-10'>
Approve Merge Request <button
</button> :disabled='approving'
</div> @click='approveMergeRequest'
class='btn btn-primary approve-btn'>
Approve Merge Request
</button>
</div> </div>
`, </div>
}); `,
})(); });
/* global Vue */ /* global Vue */
const Vue = require('vue');
require('../approvals_store'); require('../approvals_store');
require('../../../vue_common_component/link_to_member_avatar'); require('../../../vue_common_component/link_to_member_avatar');
(() => { Vue.component('approvals-footer', {
Vue.component('approvals-footer', { name: 'approvals-footer',
name: 'approvals-footer', props: {
props: { approvedBy: {
approvedBy: { type: Array,
type: Array, required: false,
required: false,
},
approvalsLeft: {
type: Number,
required: false,
},
userCanApprove: {
type: Boolean,
required: false,
},
userHasApproved: {
type: Boolean,
required: false,
},
suggestedApprovers: {
type: Array,
required: false,
},
pendingAvatarSvg: {
type: String,
required: true,
},
checkmarkSvg: {
type: String,
required: true,
},
}, },
data() { approvalsLeft: {
return { type: Number,
unapproving: false, required: false,
};
}, },
computed: { userCanApprove: {
showUnapproveButton() { type: Boolean,
return this.userHasApproved && !this.userCanApprove; required: false,
},
}, },
methods: { userHasApproved: {
unapproveMergeRequest() { type: Boolean,
this.unapproving = true; required: false,
gl.ApprovalsStore.unapprove().then(() => {
this.unapproving = false;
});
},
}, },
beforeCreate() { suggestedApprovers: {
gl.ApprovalsStore.initStoreOnce(); type: Array,
required: false,
}, },
template: ` pendingAvatarSvg: {
<div class='mr-widget-footer approved-by-users approvals-footer clearfix mr-approvals-footer'> type: String,
<span class='approvers-prefix'> Approved by </span> required: true,
<span v-for='approver in approvedBy'> },
<link-to-member-avatar checkmarkSvg: {
extra-link-class='approver-avatar' type: String,
:avatar-url='approver.user.avatar_url' required: true,
:display-name='approver.user.name' },
:profile-url='approver.user.web_url' },
:avatar-html='checkmarkSvg' data() {
:show-tooltip='true'> return {
</link-to-member-avatar> unapproving: false,
</span> };
<span v-for='n in approvalsLeft'> },
<link-to-member-avatar computed: {
:clickable='false' showUnapproveButton() {
:avatar-html='pendingAvatarSvg' return this.userHasApproved && !this.userCanApprove;
:show-tooltip='false' },
extra-link-class='hide-asset'> },
</link-to-member-avatar> methods: {
</span> unapproveMergeRequest() {
<span class='unapprove-btn-wrap' v-if='showUnapproveButton'> this.unapproving = true;
<button gl.ApprovalsStore.unapprove().then(() => {
:disabled='unapproving' this.unapproving = false;
@click='unapproveMergeRequest' });
class='btn btn-link unapprove-btn'> },
<i class='fa fa-close'></i> },
Remove your approval</span> beforeCreate() {
</button> gl.ApprovalsStore.initStoreOnce();
</span> },
</div> template: `
`, <div class='mr-widget-footer approved-by-users approvals-footer clearfix mr-approvals-footer'>
}); <span class='approvers-prefix'> Approved by </span>
})(); <span v-for='approver in approvedBy'>
<link-to-member-avatar
extra-link-class='approver-avatar'
:avatar-url='approver.user.avatar_url'
:display-name='approver.user.name'
:profile-url='approver.user.web_url'
:avatar-html='checkmarkSvg'
:show-tooltip='true'>
</link-to-member-avatar>
</span>
<span v-for='n in approvalsLeft'>
<link-to-member-avatar
:clickable='false'
:avatar-html='pendingAvatarSvg'
:show-tooltip='false'
extra-link-class='hide-asset'>
</link-to-member-avatar>
</span>
<span class='unapprove-btn-wrap' v-if='showUnapproveButton'>
<button
:disabled='unapproving'
@click='unapproveMergeRequest'
class='btn btn-link unapprove-btn'>
<i class='fa fa-close'></i>
Remove your approval</span>
</button>
</span>
</div>
`,
});
/* global Vue */ /* global merge_request_widget */
const Vue = require('vue');
require('./widget_store'); require('./widget_store');
require('./approvals/approvals_bundle'); require('./approvals/approvals_bundle');
(() => { window.gl = window.gl || {};
$(() => {
const rootEl = document.getElementById('merge-request-widget-app'); $(() => {
const widgetSharedStore = new gl.MergeRequestWidgetStore(rootEl); const rootEl = document.getElementById('merge-request-widget-app');
const widgetSharedStore = new gl.MergeRequestWidgetStore(rootEl);
gl.MergeRequestWidgetApp = new Vue({ gl.MergeRequestWidgetApp = new Vue({
el: rootEl, el: rootEl,
data: widgetSharedStore.data, data: widgetSharedStore.data,
}); mounted() {
// re-init the MiniPipelineGraph because of Vue is messing with the element
merge_request_widget.initMiniPipelineGraph();
},
}); });
})(window.gl || (window.gl = {})); });
require('./approvals/approvals_store'); require('./approvals/approvals_store');
(() => { let singleton;
let singleton;
class MergeRequestWidgetStore {
class MergeRequestWidgetStore { constructor(rootEl) {
constructor(rootEl) { if (!singleton) {
if (!singleton) { singleton = gl.MergeRequestWidget.Store = this;
singleton = gl.MergeRequestWidget.Store = this; this.init(rootEl);
this.init(rootEl);
}
return singleton;
} }
return singleton;
}
init(rootEl) { init(rootEl) {
this.rootEl = rootEl; this.rootEl = rootEl;
this.data = {}; this.data = {};
// init other widget stores here // init other widget stores here
this.initWidgetState(); this.initWidgetState();
this.initApprovals(); this.initApprovals();
} }
initWidgetState() { initWidgetState() {
this.assignToData('showApprovals', false); this.assignToData('showApprovals', false);
this.assignToData('disableAcceptance', this.rootEl.dataset.approvalPending === 'true'); this.assignToData('disableAcceptance', this.rootEl.dataset.approvalPending === 'true');
} }
initApprovals() { initApprovals() {
gl.ApprovalsStore = new gl.MergeRequestApprovalsStore(this); gl.ApprovalsStore = new gl.MergeRequestApprovalsStore(this);
this.assignToData('approvals', {}); this.assignToData('approvals', {});
} }
assignToData(key, val) { assignToData(key, val) {
this.data[key] = val; this.data[key] = val;
return val; return val;
}
} }
gl.MergeRequestWidgetStore = MergeRequestWidgetStore; }
})(window.gl || (window.gl = {}));
window.gl = window.gl || {};
window.gl.MergeRequestWidgetStore = MergeRequestWidgetStore;
...@@ -14,5 +14,16 @@ ...@@ -14,5 +14,16 @@
window.addEventListener('focus', startIntervals); window.addEventListener('focus', startIntervals);
window.addEventListener('blur', removeIntervals); window.addEventListener('blur', removeIntervals);
document.addEventListener('beforeunload', removeAll); document.addEventListener('beforeunload', removeAll);
// add removeAll methods to stack
const stack = gl.VueRealtimeListener.reset;
gl.VueRealtimeListener.reset = () => {
gl.VueRealtimeListener.reset = stack;
removeAll();
stack();
};
}; };
// remove all event listeners and intervals
gl.VueRealtimeListener.reset = () => undefined; // noop
})(window.gl || (window.gl = {})); })(window.gl || (window.gl = {}));
...@@ -3,10 +3,9 @@ ...@@ -3,10 +3,9 @@
- page_description @merge_request.description - page_description @merge_request.description
- page_card_attributes @merge_request.card_attributes - page_card_attributes @merge_request.card_attributes
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('lib_vue')
= page_specific_javascript_bundle_tag('diff_notes') = 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" = render "projects/merge_requests/show/mr_title"
.merge-request-details.issuable-details{ data: { id: @merge_request.project.id } } .merge-request-details.issuable-details{ data: { id: @merge_request.project.id } }
......
...@@ -7,6 +7,9 @@ describe('Store', () => { ...@@ -7,6 +7,9 @@ describe('Store', () => {
store = new gl.commits.pipelines.PipelinesStore(); store = new gl.commits.pipelines.PipelinesStore();
}); });
// unregister intervals and event handlers
afterEach(() => gl.VueRealtimeListener.reset());
it('should start with a blank state', () => { it('should start with a blank state', () => {
expect(store.state.pipelines.length).toBe(0); expect(store.state.pipelines.length).toBe(0);
}); });
......
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