Commit c299f62a authored by Bryce Johnson's avatar Bryce Johnson

Wire up approvals front end and backend, mostly.

parent 3be2fb3f
...@@ -2,13 +2,8 @@ ...@@ -2,13 +2,8 @@
//= require ../services/approvals_api //= require ../services/approvals_api
(() => { (() => {
const app = gl.MergeRequestWidget; Vue.component('approvals-body', {
const api = app.ApprovalsApi; name: 'approvals-body',
const componentRegistry = app.Components || (app.Components = {});
componentRegistry.approvalsBody = {
name: 'ApprovalsBody',
props: ['approverNames', 'approvalsLeft', 'userCanApprove', 'userHasApproved'], props: ['approverNames', 'approvalsLeft', 'userCanApprove', 'userHasApproved'],
data() { data() {
return { return {
...@@ -34,11 +29,11 @@ ...@@ -34,11 +29,11 @@
}, },
methods: { methods: {
approveMergeRequest() { approveMergeRequest() {
return api.approveMergeRequest(); return gl.ApprovalsStore.approve();
}, },
}, },
beforeCreate() { beforeCreate() {
api.fetchApprovals().then(() => { gl.ApprovalsStore.fetch().then(() => {
this.loading = false; this.loading = false;
}); });
}, },
...@@ -57,5 +52,5 @@ ...@@ -57,5 +52,5 @@
<loading-icon v-if='loading'></loading-icon> <loading-icon v-if='loading'></loading-icon>
</div> </div>
`, `,
}; });
})(); })();
//= require ../services/approvals_api //= require ../stores/approvals_store
//= require vue_common_component/link_to_member_avatar //= require vue_common_component/link_to_member_avatar
//= require vue_common_component/loading_icon //= require vue_common_component/loading_icon
(() => { (() => {
const app = gl.MergeRequestWidget;
const api = gl.MergeRequestWidget.ApprovalsApi;
const componentRegistry = app.Components || (app.Components = {});
componentRegistry.approvalsFooter = { Vue.component('approvals-footer', {
name: 'ApprovalsFooter', name: 'approvals-footer',
props: ['userCanApprove', 'userHasApproved', 'approvedByUsers', 'approvalsLeft', 'pendingAvatarSvg', 'checkmarkSvg'], props: ['userCanApprove', 'userHasApproved', 'approvedByUsers', 'approvalsLeft', 'pendingAvatarSvg', 'checkmarkSvg'],
data() { data() {
return { return {
...@@ -22,15 +19,14 @@ ...@@ -22,15 +19,14 @@
showUnapproveButton() { showUnapproveButton() {
return this.userCanApprove && this.userHasApproved; return this.userCanApprove && this.userHasApproved;
}, },
}, },
methods: { methods: {
removeApproval() { removeApproval() {
return api.unapproveMergeRequest(); return gl.ApprovalsStore.unapprove();
}, },
}, },
beforeCreate() { beforeCreate() {
api.fetchApprovals().then(() => { return gl.ApprovalsStore.fetch().then(() => {
this.loading = false; this.loading = false;
}); });
}, },
...@@ -62,5 +58,5 @@ ...@@ -62,5 +58,5 @@
<loading-icon v-if='loading'></loading-icon> <loading-icon v-if='loading'></loading-icon>
</div> </div>
`, `,
}; });
})(); })();
...@@ -3,32 +3,35 @@ ...@@ -3,32 +3,35 @@
(() => { (() => {
class ApprovalsApi { class ApprovalsApi {
constructor() { constructor(endpoint) {
this.resource = gl.ApprovalsResource = new gl.SubbableResource('my/endpoint'); gl.ApprovalsApi = this;
this.store = gl.MergeRequestWidget.ApprovalsStore; this.init(endpoint);
}
init(mergeRequestEndpoint) {
const approvalsEndpoint = `${mergeRequestEndpoint}/approvals`;
this.resource = gl.ApprovalsResource = new gl.SubbableResource(approvalsEndpoint);
} }
fetchApprovals() { fetchApprovals() {
return this.resource.get(); return this.resource.get().fail((err) => {
console.error(`Error fetching approvals. ${err}`);
});
} }
approveMergeRequest() { approveMergeRequest() {
return this.resource.post().then(() => { return this.resource.post().fail((err) => {
gl.MergeRequestWidget.ApprovalsStore.approve(); console.error(`Error approving merge request. ${err}`);
}); });
} }
unapproveMergeRequest() { unapproveMergeRequest() {
return this.resource.delete().then(() => { return this.resource.delete().fail((err) => {
gl.MergeRequestWidget.ApprovalsStore.unapprove(); console.error(`Error unapproving merge request. ${err}`);
}); });
} }
updateStore(newState = {}) {
this.store = gl.MergeRequestWidget.Store.data.approvals;
return Object.assign(this.store, newState);
} }
} gl.ApprovalsApi = ApprovalsApi;
gl.MergeRequestWidget.ApprovalsApi = new ApprovalsApi();
})(); })();
//= require ../services/approvals_api
(() => { (() => {
let singleton; let singleton;
class ApprovalsStore { class ApprovalsStore {
constructor(rootEl) { constructor(rootStore) {
if (!singleton) { if (!singleton) {
singleton = gl.MergeRequestWidget.ApprovalsStore = this; singleton = gl.ApprovalsStore = this;
this.init(rootEl); this.init(rootStore);
} }
return singleton; return singleton;
} }
init(rootEl) { init(rootStore) {
this.rootStore = rootStore;
this.api = new gl.ApprovalsApi(rootStore.dataset.endpoint);
}
assignToRootStore(data) {
return this.rootStore.assignToData('approvals', data);
} }
assignToData(val) { fetch() {
return this.api.fetchApprovals({ type: 'GET' })
.then((data) => this.rootStore.assignToData(data));
} }
/** TODO: remove after backend integerated */
approve() { approve() {
return this.api.approveMergeRequest({ type: 'POST' })
.then((data) => this.rootStore.assignToData(data));
} }
unapprove() { unapprove() {
return this.api.unapproveMergeRequest({ type: 'DELETE' })
.then((data) => this.rootStore.assignToData(data));
} }
} }
gl.MergeRequestWidget.ApprovalsStore = ApprovalsStore;
gl.ApprovalsStore = ApprovalsStore;
})(); })();
//= require ./widget_store //= require ./widget_store
//= require ./approvals/services/approvals_api
//= require ./approvals/approvals_bundle //= require ./approvals/approvals_bundle
((MergeRequestWidget) => { (() => {
$(() => { $(() => {
const rootEl = document.getElementById('merge-request-widget-app'); const rootEl = document.getElementById('merge-request-widget-app');
const store = new MergeRequestWidget.Store(rootEl); const widgetSharedStore = new gl.MergeRequestWidgetStore(rootEl); // TODO: encapsulate better
const components = MergeRequestWidget.Components;
MergeRequestWidget.App = new Vue({ gl.MergeRequestWidgetApp = new Vue({
el: rootEl, el: rootEl,
data: store.data, data: widgetSharedStore.data,
components: {
'approvals-body': components.approvalsBody,
'approvals-footer': components.approvalsFooter,
},
}); });
}); });
})(gl.MergeRequestWidget || (gl.MergeRequestWidget = {})); })(window.gl || (window.gl = {}));
//= require ./approvals/stores/approvals_store //= require ./approvals/stores/approvals_store
((MergeRequestWidget) => { (() => {
let singleton; let singleton;
class MergeRequestWidgetStore { class MergeRequestWidgetStore {
constructor(rootEl) { constructor(rootEl) {
if (!singleton) { if (!singleton) {
singleton = MergeRequestWidget.Store = this; singleton = gl.MergeRequestWidget.Store = this;
this.init(rootEl); this.init(rootEl);
} }
return singleton; return singleton;
// TODO: add the following to the root el dataset: approvedByUsers,
// approverNames, approvalsNeeded, canUpdateMergeRequest, endpoint
} }
init(rootEl) { init(rootEl) {
this.rootEl = rootEl; this.rootEl = rootEl;
this.dataset = rootEl.dataset; this.dataset = rootEl.dataset;
this.data = {}; this.data = {};
this.initResource();
this.initPermissions();
this.initApprovals();
}
/* General Resources */ // init other widget stores here
this.initApprovals();
initResource() {
this.assignToData('resource', {
endpoint: 'my/endpoint',
});
}
initPermissions() {
this.assignToData('permissions', {
canUpdateMergeRequest: Boolean(this.dataset.canUpdateMergeRequest),
});
} }
/* Component-specific */
initApprovals() { initApprovals() {
const approvalsStore = new gl.MergeRequestWidget.ApprovalsStore(this.rootEl); const approvalsStore = new gl.ApprovalsStore(this);
this.assignToData('approvals', approvalsStore.data); this.assignToData('approvals', approvalsStore.data);
} }
...@@ -48,6 +31,5 @@ ...@@ -48,6 +31,5 @@
Object.assign(this.data[key], val); Object.assign(this.data[key], val);
} }
} }
gl.MergeRequestWidgetStore = MergeRequestWidgetStore;
MergeRequestWidget.Store = MergeRequestWidgetStore; })(window.gl || (window.gl = {}));
})(gl.MergeRequestWidget || (MergeRequestWidget = {}));
#merge-request-widget-app.mr-state-widget{'data-endpoint'=> '/myendpoint/tho'} - content_for :page_specific_javascripts do
= page_specific_javascript_tag('merge_request_widget/widget_bundle.js')
#merge-request-widget-app.mr-state-widget{ 'data-approvals' => @merge_request.approvals.to_json, 'data-endpoint'=> merge_request_path(@merge_request)}
= render 'projects/merge_requests/widget/heading' = render 'projects/merge_requests/widget/heading'
.mr-widget-body .mr-widget-body
-# After conflicts are resolved, the user is redirected back to the MR page. -# After conflicts are resolved, the user is redirected back to the MR page.
...@@ -50,6 +53,4 @@ ...@@ -50,6 +53,4 @@
- if @merge_request.approvals.any? - if @merge_request.approvals.any?
%approvals-footer{'pending-avatar-svg' => custom_icon('icon_dotted_circle'), 'checkmark-svg' => custom_icon('icon_checkmark') } %approvals-footer{'pending-avatar-svg' => custom_icon('icon_dotted_circle'), 'checkmark-svg' => custom_icon('icon_checkmark') }
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('merge_request_widget/widget_bundle.js')
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