Commit 28b5bb94 authored by Bryce Johnson's avatar Bryce Johnson

Wire up stores and services base.

parent 1905650a
//= require ../services/approvals_api
(() => { (() => {
// can the user edit this MR const app = gl.MergeRequestWidget;
// has this user approved this MR const api = gl.MergeRequestWidget.ApprovalsApi;
// What is the info about users who can approve this MR but have not yet? const componentRegistry = app.Components || (app.Components = {});
// How many approvals are needed?
// How many approvals are had? componentRegistry.approvalsBody = {
gl.MergeRequestWidget.approvalsBody = { name: 'ApprovalsBody',
props: ['approverNames', 'approvalsLeft', 'canApprove'], props: ['approverNames', 'approvalsLeft', 'canApprove'],
data() {
return {
loading: true,
};
},
computed: { computed: {
approvalsRequiredStringified() { approvalsRequiredStringified() {
return this.approvalsLeft === 1 ? "one more approval" : return this.approvalsLeft === 1 ? 'one more approval' :
`${this.approvalsLeft} more approvals`; `${this.approvalsLeft} more approvals`;
}, },
approverNamesStringified() { approverNamesStringified() {
const lastIdx = this.approverNames.length - 1; const lastIdx = this.approverNames.length - 1;
return this.approverNames.reduce((memo, curr, index) => { return this.approverNames.reduce((memo, curr, index) => {
return index !== lastIdx ? `${memo} ${curr}, ` : `${memo} or ${curr}`; const newList = index !== lastIdx ? `${memo} ${curr}, ` :
`${memo} or ${curr}`;
return newList;
}, ''); }, '');
} },
}, },
methods: { methods: {
approveMergeRequest() { approveMergeRequest() {
approvalsService.approveMergeRequest(); return api.approveMergeRequest();
}, },
}, },
beforeCreate() { beforeCreate() {
approvalsService.fetchApprovals(); api.fetchApprovals().then(() => {
this.loading = false;
});
}, },
template: ` template: `
<div> <div>
<h4> Requires {{ approvalsRequiredStringified }} (from {{ approverNamesStringified }})</h4> <div>
<div class="append-bottom-10"> <h4> Requires {{ approvalsRequiredStringified }} (from {{ approverNamesStringified }})</h4>
<button v-if='canApprove' @click='approveMergeRequest' class="btn btn-primary approve-btn">Approve Merge Request</button> <div class='append-bottom-10'>
<button
v-if='canApprove'
@click='approveMergeRequest'
class='btn btn-primary approve-btn'>
Approve Merge Request
</button>
</div>
</div> </div>
<loading-icon v-if='loading'></loading-icon>
</div> </div>
`, `,
}; };
})(); })();
//= require ../services/approvals_api
//= require vue_common_component/link_to_member_avatar //= require vue_common_component/link_to_member_avatar
//= require vue_common_component/loading_icon
(() => { (() => {
// does the user have permission to edit this thing const app = gl.MergeRequestWidget;
// has the user already approved this or not const api = gl.MergeRequestWidget.ApprovalsApi;
// what are the users who have approved this already, with all their info const componentRegistry = app.Components || (app.Components = {});
gl.MergeRequestWidget.approvalsFooter = {
componentRegistry.approvalsFooter = {
name: 'ApprovalsFooter',
props: ['canUpdateMergeRequest', 'hasApprovedMergeRequest', 'approvedByUsers'], props: ['canUpdateMergeRequest', 'hasApprovedMergeRequest', 'approvedByUsers'],
data() {
return {
loading: true,
};
},
methods: { methods: {
removeApproval() { removeApproval() {
approvalsService.unapproveMergeRequest(); return api.unapproveMergeRequest();
} },
}, },
beforeCreate() { beforeCreate() {
approvalsService.fetchApprovals(); api.fetchApprovals().then(() => {
this.loading = false;
});
}, },
template: ` template: `
<div> <div>
...@@ -26,9 +37,9 @@ ...@@ -26,9 +37,9 @@
<span> <span>
<i class='fa fa-close'></i> <i class='fa fa-close'></i>
<button @click='removeApproval'>Remove your approval</button> <button @click='removeApproval'>Remove your approval</button>
{{ approvedByUsers[0].name }}
</span> </span>
<loading-icon v-if='loading'></loading-icon>
</div> </div>
` `,
}; };
})(); })();
//= require ../stores/approvals_store
// TODO: Determine whether component-specific store should be accessed here as a member
((MergeRequestWidget) => {
function mockApprovalRequest(payload) {
const currentPayload = Object.assign({}, payload.data);
const currentStore = gl.MergeRequestWidget.Store.data.approvals;
const parsedStore = JSON.parse(JSON.stringify(currentStore));
const mockResp = Object.assign(currentPayload, parsedStore);
return new Promise((resolve) => {
setTimeout(() => {
resolve(mockResp);
}, 100);
});
}
class ApprovalsApi {
constructor() {
this.store = null;
this.isFetching = false;
this.hasBeenFetched = true;
}
fetchApprovals() {
const payload = {
type: 'GET',
};
return this.genericApprovalRequest(payload);
}
approveMergeRequest() {
const payload = {
type: 'PUT',
data: {
approve: true,
},
};
return this.genericApprovalRequest(payload);
}
unapproveMergeRequest() {
const payload = {
type: 'PUT',
data: {
approve: false,
},
};
return this.genericApprovalRequest(payload);
}
genericApprovalRequest(payload = {}) {
return mockApprovalRequest(payload)
.then(resp => this.updateStore(resp))
.catch((err) => {
throw err;
});
}
updateStore(newState = {}) {
this.store = gl.MergeRequestWidget.Store.data.approvals; // Always update shared store
return Object.assign(this.store, newState);
}
}
gl.MergeRequestWidget.ApprovalsApi = new ApprovalsApi();
})(gl.MergeRequestWidget || (gl.MergeRequestWidget = {}));
//= require ../stores/approvals_store
(() => {
class ApprovalsService {
constructor() {
this.isFetching = false;
this.hasBeenFetched = true;
}
fetchApprovals() {
return makeRequest().then((data) => {
this.isFetching = false;
this.hasBeenFetched = true;
return data;
});
}
approveMergeRequest(payload) {
return payload;
}
unapproveMergeRequest(payload) {
return payload;
}
}
gl.mergeRequestWidget.ApprovalsService = ApprovalsService;
})();
\ No newline at end of file
(()=>{ (() => {
let singleton;
})()
\ No newline at end of file class ApprovalsStore {
constructor(rootEl) {
if (!singleton) {
singleton = gl.MergeRequestWidget.ApprovalsStore = this;
this.init(rootEl);
}
return singleton;
}
init(rootEl) {
this.data = {};
const dataset = rootEl.dataset;
this.assignToData({
approvedByUsers: JSON.parse(dataset.approvedByUsers),
approverNames: JSON.parse(dataset.approverNames),
approvalsLeft: Number(dataset.approvalsLeft),
moreApprovals: Number(dataset.moreApprovals),
});
}
assignToData(val) {
Object.assign(this.data, val);
}
}
gl.MergeRequestWidget.ApprovalsStore = ApprovalsStore;
})();
(() => { //= require ../approvals/stores/approvals_store
((MergeRequestWidget) => {
let singleton;
class MergeRequestWidgetStore { class MergeRequestWidgetStore {
constructor(el) { constructor(rootEl) {
this.dataset = el.dataset; if (!singleton) {
singleton = MergeRequestWidget.Store = this;
this.init(rootEl);
}
return singleton;
// TODO: add the following to the root el dataset: approvedByUsers,
// approverNames, approvalsNeeded, canUpdateMergeRequest, endpoint
}
init(rootEl) {
this.rootEl = rootEl;
this.dataset = rootEl.dataset;
this.data = {}; this.data = {};
// TODO: Break each into their own store
this.initResource(); this.initResource();
this.initPermissions(); this.initPermissions();
this.initApprovals(); this.initApprovals();
} }
/* General Resources */
initResource() { initResource() {
Object.assign(this.data, { this.assignToData('resource', {
resource: { endpoint: 'my/endpoint',
endpoint: this.dataset.endpoint
}
}); });
} }
initPermissions() { initPermissions() {
Object.assign(this.data, { this.assignToData('permissions', {
permissions: { canUpdateMergeRequest: Boolean(this.dataset.canUpdateMergeRequest),
canApprove: Boolean(this.dataset.canApprove)
}
}); });
} }
/* Component-specific */
initApprovals() { initApprovals() {
const dataset = this.dataset; const approvalsStore = new gl.MergeRequestWidget.ApprovalsStore(this.rootEl);
Object.assign(this.data, { this.assignToData('approvals', approvalsStore.data);
approvals: { }
approvedByUsers: JSON.parse(dataset.approvedByUsers),
approverNames: JSON.parse(dataset.approverNames), assignToData(key, val) {
approvalsLeft: Number(dataset.approvalsLeft), this.data[key] = {};
moreApprovals: Number(dataset.approvalsLeft), Object.assign(this.data[key], val);
}
});
} }
} }
gl.MergeRequestWidgetStore = MergeRequestWidgetStore;
})() MergeRequestWidget.Store = MergeRequestWidgetStore;
\ No newline at end of file })(gl.MergeRequestWidget || (MergeRequestWidget = {}));
//= require ./stores/widget_store //= require ./stores/widget_store
//= require ./services/widget_service //= require ./services/widget_service
//= require ./approvals/approvals_bundle //= require ./approvals/approvals_bundle
/**
* ((MergeRequestWidget) => {
* 'data-approved-by-users' => @merge_request.approved_by_users.to_json, 'data-approver-names' => @merge_request.approvers.to_json,'data-approvals-left' => @merge_request.approvals_left, 'data-more-approvals' => (@merge_request.approvals_left - @merge_request.approvers_left.count), 'data-can-approve' => @merge_request.user_is_approver(current_user), 'data-endpoint'=> '/myendpoint/tho' } $(() => {
* const rootEl = document.getElementById('merge-request-widget-app');
*/ const store = new MergeRequestWidget.Store(rootEl);
$(() => { const components = MergeRequestWidget.Components;
// Move initialization to somewhere else -- all can be conducted before DOM ready
new gl.MergeRequestWidgetStore(); MergeRequestWidget.App = new Vue({
new gl.MergeRequestWidgetService(); el: rootEl,
data: store.data,
const app = gl.MergeRequestWidget; components: {
'approvals-body': components.approvalsBody,
new Vue({ 'approvals-footer': components.approvalsFooter,
el: '#merge-request-widget-app', },
data: Store.data, });
components: {
'approvals-body': app.approvalsBody,
'approvals-footer': app.approvalsFooter
}
}); });
}); })(gl.MergeRequestWidget || (gl.MergeRequestWidget = {}));
/**
*
* gl.MergeRequestWidgetApp
* Store
* ApiService
*
*
* TODO: Add documentation for registering new widget components
*
*/
// Need list of approved by, list of those who can approve, and the number required
\ No newline at end of file
#merge-request-widget-app.mr-state-widget - approvers_names = @merge_request.approvers_left.map(&:name).to_json
- more_approvals = @merge_request.approvals_left - @merge_request.approvers_left.count
- approvals_left = @merge_request.approvals_left
#merge-request-widget-app.mr-state-widget{'data-approved-by-users' => @merge_request.approved_by_users.to_json, 'data-approver-names' => approvers_names,'data-approvals-left' => approvals_left, 'data-more-approvals' => more_approvals, 'data-endpoint'=> '/myendpoint/tho'}
= 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.
...@@ -24,8 +28,7 @@ ...@@ -24,8 +28,7 @@
- elsif @merge_request.work_in_progress? - elsif @merge_request.work_in_progress?
= render 'projects/merge_requests/widget/open/wip' = render 'projects/merge_requests/widget/open/wip'
- elsif @merge_request.requires_approve? && !@merge_request.approved? - elsif @merge_request.requires_approve? && !@merge_request.approved?
%approvals-body{ '@give-approval' => 'approveMergeRequest', '@fetch-approvals' => 'fetchApprovals', :approver-names' => 'approvals.approverNames', ':approvals-left' => 'approvals.approvalsLeft', ':more-approvals' => 'approvals.moreApprovals', ':can-approve' => 'permissions.canApprove', ':needs-approval' => (@merge_request.requires_approve? && !@merge_request.approved?) } %approvals-body{':approver-names' => 'approvals.approverNames', ':approvals-left' => 'approvals.approvalsLeft', ':canApprove' => 'approvals.canApprove'}
= icon('spinner spin', class: 'loading-icon')
- elsif @merge_request.merge_when_build_succeeds? - elsif @merge_request.merge_when_build_succeeds?
= render 'projects/merge_requests/widget/open/merge_when_build_succeeds' = render 'projects/merge_requests/widget/open/merge_when_build_succeeds'
- elsif !@merge_request.can_be_merged_by?(current_user) - elsif !@merge_request.can_be_merged_by?(current_user)
...@@ -50,6 +53,6 @@ ...@@ -50,6 +53,6 @@
- if @merge_request.approvals.any? - if @merge_request.approvals.any?
.mr-widget-footer.approved-by-users .mr-widget-footer.approved-by-users
%approvals-footer{ '@remove-approval' => 'unapproveMergeRequest', '@fetch-approvals' => 'fetchApprovals', ':approved-by-users' => 'approvals.approvedByUsers', ':approver-names' => 'approvals.approverNames', ':approvals-left' => 'approvals.approvalsLeft', ':more-approvals' => 'approvals.moreApprovals', ':can-approve' => 'permissions.canApprove', 'has-approvals' => @merge_request.approvals.any? } %approvals-footer{':approver-names' => 'approvals.approverNames', ':approvals-left' => 'approvals.approvalsLeft', ':canApprove' => 'approvals.canApprove', ':approved-by-users' => 'approvals.approvedByUsers'}
= icon('spinner spin', class: 'loading-icon'') = icon('spinner spin', class: 'loading-icon')
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