Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
8516e113
Commit
8516e113
authored
Feb 08, 2017
by
Mike Greiling
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix MR widget approvals bundle
parent
40e3494d
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
282 additions
and
287 deletions
+282
-287
app/assets/javascripts/merge_request_widget/approvals/approvals_api.js.es6
...ripts/merge_request_widget/approvals/approvals_api.js.es6
+27
-25
app/assets/javascripts/merge_request_widget/approvals/approvals_bundle.js.es6
...ts/merge_request_widget/approvals/approvals_bundle.js.es6
+2
-4
app/assets/javascripts/merge_request_widget/approvals/approvals_store.js.es6
...pts/merge_request_widget/approvals/approvals_store.js.es6
+51
-53
app/assets/javascripts/merge_request_widget/approvals/components/approvals_body.js.es6
...request_widget/approvals/components/approvals_body.js.es6
+79
-80
app/assets/javascripts/merge_request_widget/approvals/components/approvals_footer.js.es6
...quest_widget/approvals/components/approvals_footer.js.es6
+82
-83
app/assets/javascripts/merge_request_widget/widget_bundle.js.es6
...ets/javascripts/merge_request_widget/widget_bundle.js.es6
+10
-11
app/assets/javascripts/merge_request_widget/widget_store.js.es6
...sets/javascripts/merge_request_widget/widget_store.js.es6
+31
-31
No files found.
app/assets/javascripts/merge_request_widget/approvals/approvals_api.js.es6
View file @
8516e113
/* 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
;
app/assets/javascripts/merge_request_widget/approvals/approvals_bundle.js.es6
View file @
8516e113
function requireAll(context) { return context.keys().map(context); }
require('./approvals_store');
require('./approvals_store');
require('./approvals_api');
require('./approvals_api');
require('./components/approvals_body');
require
All(require.context('./components', true, /^\.\/.*\.(js|es6)$/)
);
require
('./components/approvals_footer'
);
app/assets/javascripts/merge_request_widget/approvals/approvals_store.js.es6
View file @
8516e113
/* 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;
app/assets/javascripts/merge_request_widget/approvals/components/approvals_body.js.es6
View file @
8516e113
/* 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>
});
`,
})
()
;
});
app/assets/javascripts/merge_request_widget/approvals/components/approvals_footer.js.es6
View file @
8516e113
/* 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>
`,
});
app/assets/javascripts/merge_request_widget/widget_bundle.js.es6
View file @
8516e113
/* global Vue */
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,
});
});
});
})
(window.gl || (window.gl = {}))
;
});
app/assets/javascripts/merge_request_widget/widget_store.js.es6
View file @
8516e113
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;
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment