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
// has this user approved this MR
// What is the info about users who can approve this MR but have not yet?
// How many approvals are needed?
// How many approvals are had?
gl.MergeRequestWidget.approvalsBody = {
const app = gl.MergeRequestWidget;
const api = gl.MergeRequestWidget.ApprovalsApi;
const componentRegistry = app.Components || (app.Components = {});
componentRegistry.approvalsBody = {
name: 'ApprovalsBody',
props: ['approverNames', 'approvalsLeft', 'canApprove'],
data() {
return {
loading: true,
};
},
computed: {
approvalsRequiredStringified() {
return this.approvalsLeft === 1 ? "one more approval" :
return this.approvalsLeft === 1 ? 'one more approval' :
`${this.approvalsLeft} more approvals`;
},
approverNamesStringified() {
const lastIdx = this.approverNames.length - 1;
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: {
approveMergeRequest() {
approvalsService.approveMergeRequest();
return api.approveMergeRequest();
},
},
beforeCreate() {
approvalsService.fetchApprovals();
api.fetchApprovals().then(() => {
this.loading = false;
});
},
template: `
<div>
<h4> Requires {{ approvalsRequiredStringified }} (from {{ approverNamesStringified }})</h4>
<div class="append-bottom-10">
<button v-if='canApprove' @click='approveMergeRequest' class="btn btn-primary approve-btn">Approve Merge Request</button>
<div>
<h4> Requires {{ approvalsRequiredStringified }} (from {{ approverNamesStringified }})</h4>
<div class='append-bottom-10'>
<button
v-if='canApprove'
@click='approveMergeRequest'
class='btn btn-primary approve-btn'>
Approve Merge Request
</button>
</div>
</div>
<loading-icon v-if='loading'></loading-icon>
</div>
`,
};
})();
//= require ../services/approvals_api
//= require vue_common_component/link_to_member_avatar
//= require vue_common_component/loading_icon
(() => {
// does the user have permission to edit this thing
// has the user already approved this or not
// what are the users who have approved this already, with all their info
gl.MergeRequestWidget.approvalsFooter = {
const app = gl.MergeRequestWidget;
const api = gl.MergeRequestWidget.ApprovalsApi;
const componentRegistry = app.Components || (app.Components = {});
componentRegistry.approvalsFooter = {
name: 'ApprovalsFooter',
props: ['canUpdateMergeRequest', 'hasApprovedMergeRequest', 'approvedByUsers'],
data() {
return {
loading: true,
};
},
methods: {
removeApproval() {
approvalsService.unapproveMergeRequest();
}
return api.unapproveMergeRequest();
},
},
beforeCreate() {
approvalsService.fetchApprovals();
api.fetchApprovals().then(() => {
this.loading = false;
});
},
template: `
<div>
......@@ -26,9 +37,9 @@
<span>
<i class='fa fa-close'></i>
<button @click='removeApproval'>Remove your approval</button>
{{ approvedByUsers[0].name }}
</span>
<loading-icon v-if='loading'></loading-icon>
</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
(()=>{
})()
\ No newline at end of file
(() => {
let singleton;
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 {
constructor(el) {
this.dataset = el.dataset;
constructor(rootEl) {
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 = {};
// TODO: Break each into their own store
this.initResource();
this.initPermissions();
this.initApprovals();
}
/* General Resources */
initResource() {
Object.assign(this.data, {
resource: {
endpoint: this.dataset.endpoint
}
this.assignToData('resource', {
endpoint: 'my/endpoint',
});
}
initPermissions() {
Object.assign(this.data, {
permissions: {
canApprove: Boolean(this.dataset.canApprove)
}
this.assignToData('permissions', {
canUpdateMergeRequest: Boolean(this.dataset.canUpdateMergeRequest),
});
}
/* Component-specific */
initApprovals() {
const dataset = this.dataset;
Object.assign(this.data, {
approvals: {
approvedByUsers: JSON.parse(dataset.approvedByUsers),
approverNames: JSON.parse(dataset.approverNames),
approvalsLeft: Number(dataset.approvalsLeft),
moreApprovals: Number(dataset.approvalsLeft),
}
});
const approvalsStore = new gl.MergeRequestWidget.ApprovalsStore(this.rootEl);
this.assignToData('approvals', approvalsStore.data);
}
assignToData(key, val) {
this.data[key] = {};
Object.assign(this.data[key], val);
}
}
gl.MergeRequestWidgetStore = MergeRequestWidgetStore;
})()
\ No newline at end of file
MergeRequestWidget.Store = MergeRequestWidgetStore;
})(gl.MergeRequestWidget || (MergeRequestWidget = {}));
//= require ./stores/widget_store
//= require ./services/widget_service
//= require ./approvals/approvals_bundle
/**
*
* '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' }
*
*/
$(() => {
// Move initialization to somewhere else -- all can be conducted before DOM ready
new gl.MergeRequestWidgetStore();
new gl.MergeRequestWidgetService();
const app = gl.MergeRequestWidget;
new Vue({
el: '#merge-request-widget-app',
data: Store.data,
components: {
'approvals-body': app.approvalsBody,
'approvals-footer': app.approvalsFooter
}
((MergeRequestWidget) => {
$(() => {
const rootEl = document.getElementById('merge-request-widget-app');
const store = new MergeRequestWidget.Store(rootEl);
const components = MergeRequestWidget.Components;
MergeRequestWidget.App = new Vue({
el: rootEl,
data: store.data,
components: {
'approvals-body': components.approvalsBody,
'approvals-footer': components.approvalsFooter,
},
});
});
});
/**
*
* 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
})(gl.MergeRequestWidget || (gl.MergeRequestWidget = {}));
#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'
.mr-widget-body
-# After conflicts are resolved, the user is redirected back to the MR page.
......@@ -24,8 +28,7 @@
- elsif @merge_request.work_in_progress?
= render 'projects/merge_requests/widget/open/wip'
- 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?) }
= icon('spinner spin', class: 'loading-icon')
%approvals-body{':approver-names' => 'approvals.approverNames', ':approvals-left' => 'approvals.approvalsLeft', ':canApprove' => 'approvals.canApprove'}
- elsif @merge_request.merge_when_build_succeeds?
= render 'projects/merge_requests/widget/open/merge_when_build_succeeds'
- elsif !@merge_request.can_be_merged_by?(current_user)
......@@ -50,6 +53,6 @@
- if @merge_request.approvals.any?
.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? }
= icon('spinner spin', class: 'loading-icon'')
%approvals-footer{':approver-names' => 'approvals.approverNames', ':approvals-left' => 'approvals.approvalsLeft', ':canApprove' => 'approvals.canApprove', ':approved-by-users' => 'approvals.approvedByUsers'}
= 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