PolyGerrit: Implement support for New Agreement screen

Bug: Issue 6866
Bug: Issue 6783
Change-Id: I3e69d317255f7318e225ff54cf192d9812fe0a70
This commit is contained in:
Paladox none
2017-07-27 16:36:58 +00:00
committed by Paladox
parent 1a6093b453
commit 2be2d2a3f2
11 changed files with 419 additions and 98 deletions

View File

@@ -21,7 +21,8 @@
CUSTOM_DASHBOARD: /^\/dashboard\/?$/,
PROJECT_DASHBOARD: /^\/p\/(.+)\/\+\/dashboard\/(.+)/,
AGREEMENTS: /^\/settings\/(agreements|new-agreement)/,
AGREEMENTS: /^\/settings\/agreements\/?/,
NEW_AGREEMENTS: /^\/settings\/new-agreement\/?/,
REGISTER: /^\/register(\/.*)?$/,
// Pattern for login and logout URLs intended to be passed-through. May
@@ -771,6 +772,9 @@
this._mapRoute(RoutePattern.AGREEMENTS, '_handleAgreementsRoute', true);
this._mapRoute(RoutePattern.NEW_AGREEMENTS, '_handleNewAgreementsRoute',
true);
this._mapRoute(RoutePattern.SETTINGS_LEGACY,
'_handleSettingsLegacyRoute', true);
@@ -1272,7 +1276,13 @@
}
},
// TODO fix this so it properly redirects
// to /settings#Agreements (Scrolls down)
_handleAgreementsRoute(data) {
this._redirect('/settings/#Agreements');
},
_handleNewAgreementsRoute(data) {
data.params.view = Gerrit.Nav.View.AGREEMENTS;
this._setParams(data.params);
},

View File

@@ -134,6 +134,7 @@ limitations under the License.
'_handleGroupListOffsetRoute',
'_handleGroupMembersRoute',
'_handleGroupRoute',
'_handleNewAgreementsRoute',
'_handlePluginListFilterOffsetRoute',
'_handlePluginListFilterRoute',
'_handlePluginListOffsetRoute',
@@ -532,7 +533,14 @@ limitations under the License.
});
test('_handleAgreementsRoute', () => {
element._handleAgreementsRoute({params: {}});
const data = {params: {}};
element._handleAgreementsRoute(data);
assert.isTrue(redirectStub.calledOnce);
assert.equal(redirectStub.lastCall.args[0], '/settings/#Agreements');
});
test('_handleNewAgreementsRoute', () => {
element._handleNewAgreementsRoute({params: {}});
assert.isTrue(setParamsStub.calledOnce);
assert.equal(setParamsStub.lastCall.args[0].view,
Gerrit.Nav.View.AGREEMENTS);

View File

@@ -179,7 +179,7 @@ limitations under the License.
</gr-endpoint-decorator>
</template>
<template is="dom-if" if="[[_showCLAView]]" restamp="true">
<gr-cla-view path="[[_path]]"></gr-cla-view>
<gr-cla-view></gr-cla-view>
</template>
<div id="errorView" class="errorView">
<div class="errorEmoji">[[_lastError.emoji]]</div>

View File

@@ -53,8 +53,7 @@ limitations under the License.
</template>
</tbody>
</table>
<!-- TODO: Renable this when supported in polygerrit -->
<!-- <a href$="[[getUrl()]]">New Contributor Agreement</a> -->
<a href$="[[getUrl()]]">New Contributor Agreement</a>
</div>
<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
</template>

View File

@@ -1,5 +1,5 @@
<!--
Copyright (C) 2017 The Android Open Source Project
Copyright (C) 2018 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -14,12 +14,94 @@ See the License for the specific language governing permissions and
limitations under the License.
-->
<link rel="import" href="../../../behaviors/base-url-behavior/base-url-behavior.html">
<link rel="import" href="../../../bower_components/iron-input/iron-input.html">
<link rel="import" href="../../../bower_components/polymer/polymer.html">
<link rel="import" href="../../shared/gr-placeholder/gr-placeholder.html">
<link rel="import" href="../../../styles/gr-form-styles.html">
<link rel="import" href="../../../styles/shared-styles.html">
<link rel="import" href="../../shared/gr-button/gr-button.html">
<link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
<dom-module id="gr-cla-view">
<template>
<gr-placeholder title="Agreements" path="[[path]]"></gr-placeholder>
<style include="shared-styles">
h1 {
margin-bottom: .6em;
}
h3 {
margin-bottom: .5em;
}
.agreementsUrl {
border: 0.1em solid #b0bdcc;
margin-bottom: 1.25em;
margin-left: 1.25em;
margin-right: 1.25em;
padding: 0.3em;
}
#claNewAgreementsLabel {
font-family: var(--font-family-bold);
}
#claNewAgreement {
display: none;
}
#claNewAgreement.show {
display: block;
}
.contributorAgreementButton {
font-family: var(--font-family-bold);
}
.contributorAgreementAlreadySubmitted {
color: red;
margin: 0 2em;
padding: .5em;
}
.agreementsSubmitted,
.hideAgreementsTextBox {
display: none;
}
main {
margin: 2em auto;
max-width: 50em;
}
</style>
<style include="gr-form-styles"></style>
<main>
<h1>New Contributor Agreement</h1>
<h3>Select an agreement type:</h3>
<template is="dom-repeat" items="[[_serverConfig.auth.contributor_agreements]]">
<span class="contributorAgreementButton">
<input id$="claNewAgreementsInput[[item.name]]"
name="claNewAgreementsRadio"
type="radio"
data-name$="[[item.name]]"
data-url$="[[item.url]]"
on-tap="_handleShowAgreement"
disabled$="[[_disableAggreements(item, _groups)]]">
<label id="claNewAgreementsLabel">[[item.name]]</label>
</span>
<div class$="contributorAgreementAlreadySubmitted [[_hideAggreements(item, _groups)]]">
Agreement already submitted.
</div>
<div class="agreementsUrl">
[[item.description]]
</div>
</template>
<div id="claNewAgreement" class$="[[_computeShowAgreementsClass(_showAgreements)]]">
<h3 class="smallHeading">Review the agreement:</h3>
<div id="agreementsUrl" class="agreementsUrl">
<a href$="[[_agreementsUrl]]" target="blank" rel="noopener">
Please review the agreement.</a>
</div>
<div class$="agreementsTextBox [[_computeHideAgreementClass(_agreementName, _serverConfig.auth.contributor_agreements)]]">
<h3 class="smallHeading">Complete the agreement:</h3>
<input id="input-agreements" is="iron-input" bind-value="{{_agreementsText}}" placeholder="Enter 'I agree' here" />
<gr-button on-tap="_handleSaveAgreements" disabled="[[_disableAgreementsText(_agreementsText)]]">
Submit
</gr-button>
</div>
</div>
</main>
<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
</template>
<script src="gr-cla-view.js"></script>
</dom-module>
</dom-module>

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2017 The Android Open Source Project
// Copyright (C) 2018 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -18,7 +18,121 @@
is: 'gr-cla-view',
properties: {
path: String,
_groups: Object,
/** @type {?} */
_serverConfig: Object,
_agreementsText: String,
_agreementName: String,
_showAgreements: {
type: Boolean,
value: false,
},
_agreementsUrl: String,
},
behaviors: [
Gerrit.BaseUrlBehavior,
],
attached() {
this.loadData();
this.fire('title-change', {title: 'New Contributor Agreement'});
},
loadData() {
const promises = [];
promises.push(this.$.restAPI.getConfig(true).then(config => {
this._serverConfig = config;
}));
promises.push(this.$.restAPI.getAccountGroups().then(groups => {
this._groups = groups.sort((a, b) => {
return a.name.localeCompare(b.name);
});
}));
return Promise.all(promises);
},
_getAgreementsUrl(configUrl) {
let url;
if (!configUrl) { return ''; }
if (configUrl.startsWith('http:') || configUrl.startsWith('https:')) {
url = configUrl;
} else {
url = this.getBaseUrl() + '/' + configUrl;
}
return url;
},
_handleShowAgreement(e) {
this._agreementName = e.target.getAttribute('data-name');
this._agreementsUrl =
this._getAgreementsUrl(e.target.getAttribute('data-url'));
this._showAgreements = true;
},
_handleSaveAgreements(e) {
this._createToast('Agreement saving...');
const name = this._agreementName;
return this.$.restAPI.saveAccountAgreement({name}).then(res => {
let message = 'Agreement failed to be submitted, please try again';
if (res.status === 200) {
message = 'Agreement has been successfully submited.';
}
this._createToast(message);
this.loadData();
this._agreementsText = '';
this._showAgreements = false;
});
},
_createToast(message) {
this.dispatchEvent(new CustomEvent('show-alert',
{detail: {message}, bubbles: true}));
},
_computeShowAgreementsClass(agreements) {
return agreements ? 'show' : '';
},
_disableAggreements(item, groups) {
for (const value of groups) {
if (item && item.auto_verify_group &&
item.auto_verify_group.name === value.name) {
return true;
}
}
return false;
},
_hideAggreements(item, groups) {
return this._disableAggreements(item, groups) ?
'' : 'agreementsSubmitted';
},
_disableAgreementsText(text) {
return text.toLowerCase() === 'i agree' ? false : true;
},
// This checks for auto_verify_group,
// if specified it returns 'hideAgreementsTextBox' which
// then hides the text box and submit button.
_computeHideAgreementClass(name, config) {
for (const key in config) {
if (!config.hasOwnProperty(key)) { return; }
for (const prop in config[key]) {
if (!config[key].hasOwnProperty(prop)) { return; }
if (name === config[key].name &&
!config[key].auto_verify_group) {
return 'hideAgreementsTextBox';
}
}
}
},
});
})();

View File

@@ -0,0 +1,183 @@
<!DOCTYPE html>
<!--
Copyright (C) 2018 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<title>gr-cla-view</title>
<script src="../../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
<script src="../../../bower_components/web-component-tester/browser.js"></script>
<link rel="import" href="../../../test/common-test-setup.html"/>
<link rel="import" href="gr-cla-view.html">
<script>void(0);</script>
<test-fixture id="basic">
<template>
<gr-cla-view></gr-cla-view>
</template>
</test-fixture>
<script>
suite('gr-cla-view tests', () => {
let element;
let agreements;
const auth = {
name: 'Individual',
description: 'test-description',
url: 'static/cla_individual.html',
auto_verify_group: {
url: '#/admin/groups/uuid-bc53f2738ef8ad0b3a4f53846ff59b05822caecb',
options: {
visible_to_all: true,
},
group_id: 20,
owner: 'CLA Accepted - Individual',
owner_id: 'bc53f2738ef8ad0b3a4f53846ff59b05822caecb',
created_on: '2017-07-31 15:11:04.000000000',
id: 'bc53f2738ef8ad0b3a4f53846ff59b05822caecb',
name: 'CLA Accepted - Individual',
},
};
const auth2 = {
name: 'Individual2',
description: 'test-description2',
url: 'static/cla_individual2.html',
auto_verify_group: {
url: '#/admin/groups/uuid-e9aaddc47f305be7661ad4db9b66f9b707bd19a0',
options: {},
group_id: 21,
owner: 'CLA Accepted - Individual2',
owner_id: 'e9aaddc47f305be7661ad4db9b66f9b707bd19a0',
created_on: '2017-07-31 15:25:42.000000000',
id: 'e9aaddc47f305be7661ad4db9b66f9b707bd19a0',
name: 'CLA Accepted - Individual2',
},
};
const config = {
auth: {
use_contributor_agreements: true,
contributor_agreements: [
{
name: 'Individual',
description: 'test-description',
url: 'static/cla_individual.html',
},
],
},
};
const config2 = {
auth: {
use_contributor_agreements: true,
contributor_agreements: [
{
name: 'Individual2',
description: 'test-description2',
url: 'static/cla_individual2.html',
},
],
},
};
const groups = [
{
url: 'some url',
options: {},
description: 'Group 1 description',
group_id: 1,
owner: 'Administrators',
owner_id: '123',
id: 'abc',
name: 'Individual',
},
{
options: {visible_to_all: true},
id: '456',
group_id: 2,
name: 'Individual 2',
},
{
options: {visible_to_all: true},
id: '457',
group_id: 3,
name: 'CLA Accepted - Individual',
},
];
setup(done => {
agreements = [{
url: 'test-agreements.html',
description: 'Agreements 1 description',
name: 'Agreements 1',
}];
stub('gr-rest-api-interface', {
getAccountGroups() { return Promise.resolve(agreements); },
});
element = fixture('basic');
element.loadData().then(() => { flush(done); });
});
test('_disableAggreements equals true', () => {
assert.isTrue(element._disableAggreements(auth, groups));
});
test('_disableAggreements equals false', () => {
assert.isFalse(element._disableAggreements(auth2, groups));
});
test('_hideAggreements equals string', () => {
assert.equal(element._hideAggreements(auth, groups), '');
});
test('_hideAggreements equals agreementsSubmitted', () => {
assert.equal(element._hideAggreements(auth2, groups),
'agreementsSubmitted');
});
test('_disableAgreementsText equals true', () => {
assert.isFalse(element._disableAgreementsText('I AGREE'));
});
test('_disableAgreementsText equals true', () => {
assert.isTrue(element._disableAgreementsText('I DO NOT AGREE'));
});
test('_computeHideAgreementClass returns true', () => {
assert.equal(
element._computeHideAgreementClass(
auth.name, config.auth.contributor_agreements),
'hideAgreementsTextBox');
});
test('_computeHideAgreementClass returns undefined', () => {
assert.isUndefined(
element._computeHideAgreementClass(
auth.name, config2.auth.contributor_agreements));
});
test('_getAgreementsUrl has http', () => {
assert.equal(element._getAgreementsUrl(
'http://test.org/test.html'), 'http://test.org/test.html');
});
test('_getAgreementsUrl does not have http://', () => {
assert.equal(element._getAgreementsUrl(
'test_cla.html'), '/test_cla.html');
});
});
</script>

View File

@@ -1,55 +0,0 @@
<!--
Copyright (C) 2017 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<link rel="import" href="../../../behaviors/base-url-behavior/base-url-behavior.html">
<link rel="import" href="../../../bower_components/polymer/polymer.html">
<link rel="import" href="../../../styles/shared-styles.html">
<dom-module id="gr-placeholder">
<template>
<style include="shared-styles">
main {
margin: 2em auto;
max-width: 46em;
}
h1 {
margin-bottom: .1em;
}
@media only screen and (max-width: 67em) {
main {
margin: 2em 0 2em 15em;
}
}
@media only screen and (max-width: 53em) {
.loading {
padding: 0 var(--default-horizontal-margin);
}
main {
margin: 2em 1em;
}
}
</style>
<main>
<h1>[[title]]</h1>
<section>
This page is not yet implemented in PolyGerrit. View it in the
<a id="gwtLink" href$="[[computeGwtUrl(path)]]" rel="external">
Old UI</a>
</section>
</main>
</template>
<script src="gr-placeholder.js"></script>
</dom-module>

View File

@@ -1,29 +0,0 @@
// Copyright (C) 2017 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
(function() {
'use strict';
Polymer({
is: 'gr-placeholder',
properties: {
path: String,
title: String,
},
behaviors: [
Gerrit.BaseUrlBehavior,
],
});
})();

View File

@@ -230,8 +230,12 @@
return JSON.parse(source.substring(JSON_PREFIX.length));
},
getConfig() {
return this._fetchSharedCacheURL('/config/server/info');
getConfig(noCache) {
if (!noCache) {
return this._fetchSharedCacheURL('/config/server/info');
}
return this.fetchJSON('/config/server/info');
},
getRepo(repo) {
@@ -675,13 +679,17 @@
},
getAccountGroups() {
return this._fetchSharedCacheURL('/accounts/self/groups');
return this.fetchJSON('/accounts/self/groups');
},
getAccountAgreements() {
return this._fetchSharedCacheURL('/accounts/self/agreements');
},
saveAccountAgreement(name) {
return this.send('PUT', '/accounts/self/agreements', name);
},
/**
* @param {string=} opt_params
*/

View File

@@ -119,6 +119,7 @@ limitations under the License.
'plugins/gr-settings-api/gr-settings-api_test.html',
'settings/gr-account-info/gr-account-info_test.html',
'settings/gr-change-table-editor/gr-change-table-editor_test.html',
'settings/gr-cla-view/gr-cla-view_test.html',
'settings/gr-edit-preferences/gr-edit-preferences_test.html',
'settings/gr-email-editor/gr-email-editor_test.html',
'settings/gr-group-list/gr-group-list_test.html',