Commit 7a660f80 authored by Bryce Johnson's avatar Bryce Johnson

Check in arbitrary checkpoint.

parent 385257cc
//= require ../stores/approvals_store
//= require ../services/approvals_api //= require ../services/approvals_api
(() => { (() => {
const app = gl.MergeRequestWidget; const app = gl.MergeRequestWidget;
const api = gl.MergeRequestWidget.ApprovalsApi; const api = app.ApprovalsApi;
const componentRegistry = app.Components || (app.Components = {}); const componentRegistry = app.Components || (app.Components = {});
componentRegistry.approvalsBody = { componentRegistry.approvalsBody = {
name: 'ApprovalsBody', name: 'ApprovalsBody',
props: ['approverNames', 'approvalsLeft', 'canApprove'], props: ['approverNames', 'approvalsLeft', 'userCanApprove', 'userHasApproved'],
data() { data() {
return { return {
loading: true, loading: true,
...@@ -26,6 +28,9 @@ ...@@ -26,6 +28,9 @@
return newList; return newList;
}, ''); }, '');
}, },
showApproveButton() {
return this.userCanApprove && !this.userHasApproved;
},
}, },
methods: { methods: {
approveMergeRequest() { approveMergeRequest() {
...@@ -41,9 +46,8 @@ ...@@ -41,9 +46,8 @@
<div> <div>
<div> <div>
<h4> Requires {{ approvalsRequiredStringified }} (from {{ approverNamesStringified }})</h4> <h4> Requires {{ approvalsRequiredStringified }} (from {{ approverNamesStringified }})</h4>
<div class='append-bottom-10'> <div v-if='showApproveButton' class='append-bottom-10'>
<button <button
v-if='canApprove'
@click='approveMergeRequest' @click='approveMergeRequest'
class='btn btn-primary approve-btn'> class='btn btn-primary approve-btn'>
Approve Merge Request Approve Merge Request
......
...@@ -9,12 +9,20 @@ ...@@ -9,12 +9,20 @@
componentRegistry.approvalsFooter = { componentRegistry.approvalsFooter = {
name: 'ApprovalsFooter', name: 'ApprovalsFooter',
props: ['canUpdateMergeRequest', 'hasApprovedMergeRequest', 'approvedByUsers'], props: ['userCanApprove', 'userHasApproved', 'approvedByUsers', 'approvalsLeft'],
data() { data() {
return { return {
loading: true, loading: true,
}; };
}, },
computed: {
hasApprovers() {
return this.approvedByUsers && this.approvedByUsers.length;
},
showUnapproveButton() {
return this.userCanApprove && this.userHasApproved;
},
},
methods: { methods: {
removeApproval() { removeApproval() {
return api.unapproveMergeRequest(); return api.unapproveMergeRequest();
...@@ -26,7 +34,7 @@ ...@@ -26,7 +34,7 @@
}); });
}, },
template: ` template: `
<div> <div v-if='hasApprovers' class='mr-widget-footer approved-by-users'>
<div v-for='approver in approvedByUsers'> <div v-for='approver in approvedByUsers'>
<link-to-member-avatar <link-to-member-avatar
:avatar-url='approver.avatar.url' :avatar-url='approver.avatar.url'
...@@ -34,7 +42,7 @@ ...@@ -34,7 +42,7 @@
:username='approver.username'> :username='approver.username'>
</link-to-member-avatar> </link-to-member-avatar>
</div> </div>
<span> <span v-if='showUnapproveButton'>
<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>
</span> </span>
......
//= require ../stores/approvals_store //= require ../stores/approvals_store
// TODO: Determine whether component-specific store should be accessed here as a member // TODO: Determine whether component-specific store should be accessed here as a member
((MergeRequestWidget) => { ((MergeRequestWidget) => {
function mockApprovalRequest(payload) { function mockApprovalRequest(payload) {
const currentPayload = Object.assign({}, payload.data); const store = gl.MergeRequestWidget.Store;
const currentStore = gl.MergeRequestWidget.Store.data.approvals;
const parsedStore = JSON.parse(JSON.stringify(currentStore));
const mockResp = Object.assign(currentPayload, parsedStore);
return new Promise((resolve) => { return new Promise((resolve) => {
const approvalsStore = store.data.approvals;
setTimeout(() => { setTimeout(() => {
resolve(mockResp); resolve(approvalsStore);
}, 100); }, 100);
}); });
} }
class ApprovalsApi { class ApprovalsApi {
constructor() { constructor() {
this.store = null; this.store = gl.MergeRequestWidget.ApprovalsStore;
this.isFetching = false; this.isFetching = false;
this.hasBeenFetched = true; this.hasBeenFetched = true;
} }
...@@ -32,22 +32,20 @@ ...@@ -32,22 +32,20 @@
approveMergeRequest() { approveMergeRequest() {
const payload = { const payload = {
type: 'PUT', type: 'POST',
data: {
approve: true,
},
}; };
return this.genericApprovalRequest(payload); return this.genericApprovalRequest(payload).then(() => {
gl.MergeRequestWidget.ApprovalsStore.approve();
});
} }
unapproveMergeRequest() { unapproveMergeRequest() {
const payload = { const payload = {
type: 'PUT', type: 'DELETE',
data: {
approve: false,
},
}; };
return this.genericApprovalRequest(payload); return this.genericApprovalRequest(payload).then(() => {
gl.MergeRequestWidget.ApprovalsStore.unapprove();
});
} }
genericApprovalRequest(payload = {}) { genericApprovalRequest(payload = {}) {
......
(() => { (() => {
let singleton; let singleton;
const adminUser =
'{"id":1,"email":"admin@example.com","created_at":"2016-10-17T17:21:34.545Z","updated_at":"2016-12-01T12:40:12.884Z","name":"Administrator","admin":true,"projects_limit":100,"skype":"","linkedin":"","twitter":"","authentication_token":"9PQj4RxcKbyQwG5uAykL","theme_id":2,"bio":"","username":"root","can_create_group":true,"can_create_team":false,"state":"active","color_scheme_id":1,"password_expires_at":null,"created_by_id":null,"last_credential_check_at":null,"avatar":{"url":"/uploads/user/avatar/1/avatar.png"},"hide_no_ssh_key":true,"website_url":"","admin_email_unsubscribed_at":null,"notification_email":"admin@example.com","hide_no_password":false,"password_automatically_set":false,"location":"","encrypted_otp_secret":null,"encrypted_otp_secret_iv":null,"encrypted_otp_secret_salt":null,"otp_required_for_login":false,"otp_backup_codes":null,"public_email":"","dashboard":"projects","project_view":"readme","consumed_timestep":null,"layout":"fixed","hide_project_limit":false,"note":null,"otp_grace_period_started_at":null,"ldap_email":false,"external":false,"organization":"","incoming_email_token":"3rkrn7wdxmeyds49fdmlk7376","authorized_projects_populated":true}';
class ApprovalsStore { class ApprovalsStore {
constructor(rootEl) { constructor(rootEl) {
...@@ -13,18 +15,60 @@ ...@@ -13,18 +15,60 @@
init(rootEl) { init(rootEl) {
this.data = {}; this.data = {};
const dataset = rootEl.dataset; const dataset = rootEl.dataset;
const approverNames = JSON.parse(dataset.approverNames);
this.assignToData({ this.assignToData({
approvedByUsers: JSON.parse(dataset.approvedByUsers), approvedByUsers: JSON.parse(dataset.approvedByUsers),
approverNames: JSON.parse(dataset.approverNames), approvalsRequired: Number(dataset.approvalsRequired),
approverNames,
approvalsLeft: Number(dataset.approvalsLeft), approvalsLeft: Number(dataset.approvalsLeft),
moreApprovals: Number(dataset.moreApprovals), userHasApproved: Boolean(true),
userCanApprove: Boolean(true),
}); });
} }
assignToData(val) { assignToData(val) {
Object.assign(this.data, val); Object.assign(this.data, val);
} }
/** TODO: remove after backend integerated */
approve() {
const approvedByUsers = this.data.approvedByUsers;
const approverNames = this.data.approverNames;
const userCanApprove = this.data.userCanApprove;
const index = approverNames.indexOf("Administrator");
approverNames.splice(index, 1);
approvedByUsers.push(JSON.parse(adminUser));
this.assignToData({
approverNames,
approvedByUsers,
userHasApproved: true,
userCanApprove: true,
approvalsLeft: this.data.approvalsLeft -= 1
});
}
unapprove() {
debugger;
const approverNames = this.data.approverNames;
const approvedByUsers = this.data.approvedByUsers;
approverNames.push("Administrator");
approvedByUsers.pop(0);
this.assignToData({
approverNames,
approvedByUsers,
userHasApproved: false,
userCanApprove: true,
approvalsLeft: this.data.approvalsLeft += 1
});
}
} }
gl.MergeRequestWidget.ApprovalsStore = ApprovalsStore; gl.MergeRequestWidget.ApprovalsStore = ApprovalsStore;
})(); })();
// TODO: Document the weirdness of shared data because of the UI
//= require ./stores/widget_store //= require ./widget_store
//= require ./services/widget_service //= require ./approvals/services/approvals_api
//= require ./approvals/approvals_bundle //= require ./approvals/approvals_bundle
((MergeRequestWidget) => { ((MergeRequestWidget) => {
......
//= require ../approvals/stores/approvals_store //= require ./approvals/stores/approvals_store
((MergeRequestWidget) => { ((MergeRequestWidget) => {
let singleton; let singleton;
......
- approvers_names = @merge_request.approvers_left.map(&:name).to_json - approvers_names = @merge_request.approvers_left.map(&:name).to_json
- more_approvals = @merge_request.approvals_left - @merge_request.approvers_left.count - approvals_required = @merge_request.approvals_required
- approvals_left = @merge_request.approvals_left - approvals_left = @merge_request.approvals_left
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= page_specific_javascript_tag('merge_request_widget/widget_bundle.js') = page_specific_javascript_tag('merge_request_widget/widget_bundle.js')
#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'} #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-approvals-required' => approvals_required, '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.
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,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{':approver-names' => 'approvals.approverNames', ':approvals-left' => 'approvals.approvalsLeft', ':canApprove' => 'approvals.canApprove'} %approvals-body{':approver-names' => 'approvals.approverNames', ':approvals-left' => 'approvals.approvalsLeft', ':user-can-approve' => 'approvals.userCanApprove', ':user-has-approved' => 'approvals.userHasApproved'}
- 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)
...@@ -54,7 +54,6 @@ ...@@ -54,7 +54,6 @@
= mr_assign_issues_link = mr_assign_issues_link
- if @merge_request.approvals.any? - if @merge_request.approvals.any?
.mr-widget-footer.approved-by-users %approvals-footer{':approved-by-users' => 'approvals.approvedByUsers', ':approver-names' => 'approvals.approverNames', ':approvals-left' => 'approvals.approvalsLeft', ':user-can-approve' => 'approvals.userCanApprove', ':user-has-approved' => 'approvals.userHasApproved'}
%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