Merge "Introduce gr-edit-file-controls"
This commit is contained in:
@@ -23,6 +23,7 @@ limitations under the License.
|
||||
<link rel="import" href="../../diff/gr-comment-api/gr-comment-api.html">
|
||||
<link rel="import" href="../../diff/gr-diff/gr-diff.html">
|
||||
<link rel="import" href="../../diff/gr-diff-cursor/gr-diff-cursor.html">
|
||||
<link rel="import" href="../../edit/gr-edit-file-controls/gr-edit-file-controls.html">
|
||||
<link rel="import" href="../../shared/gr-button/gr-button.html">
|
||||
<link rel="import" href="../../shared/gr-cursor-manager/gr-cursor-manager.html">
|
||||
<link rel="import" href="../../shared/gr-linked-text/gr-linked-text.html">
|
||||
@@ -50,6 +51,12 @@ limitations under the License.
|
||||
:host(.editLoaded) .hideOnEdit {
|
||||
display: none;
|
||||
}
|
||||
.showOnEdit {
|
||||
display: none;
|
||||
}
|
||||
:host(.editLoaded) .showOnEdit {
|
||||
display: initial;
|
||||
}
|
||||
.reviewed,
|
||||
.status {
|
||||
align-items: center;
|
||||
@@ -184,6 +191,10 @@ limitations under the License.
|
||||
display: initial;
|
||||
opacity: 100;
|
||||
}
|
||||
.editFileControls {
|
||||
margin-left: 1em;
|
||||
width: 4em;
|
||||
}
|
||||
@media screen and (max-width: 50em) {
|
||||
.desktop {
|
||||
display: none;
|
||||
@@ -299,6 +310,12 @@ limitations under the License.
|
||||
<span class="markReviewed" title="Mark as reviewed (shortcut: r)">[[_computeReviewedText(file.isReviewed)]]</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="editFileControls showOnEdit">
|
||||
<gr-edit-file-controls
|
||||
class$="[[_computeClass('', file.__path)]]"
|
||||
file-path="[[file.__path]]"
|
||||
on-edit-tap="_handleEditTap"></gr-edit-file-controls>
|
||||
</div>
|
||||
</div>
|
||||
<template is="dom-if"
|
||||
if="[[_isFileExpanded(file.__path, _expandedFilePaths.*)]]">
|
||||
@@ -338,6 +355,7 @@ limitations under the License.
|
||||
</div>
|
||||
<!-- Empty div here exists to keep spacing in sync with file rows. -->
|
||||
<div class="reviewed hideOnEdit" hidden$="[[!_loggedIn]]" hidden></div>
|
||||
<div class="editFileControls showOnEdit"></div>
|
||||
</div>
|
||||
<div
|
||||
class$="row totalChanges [[_computeExpandInlineClass(_userPrefs)]]"
|
||||
|
||||
@@ -926,5 +926,10 @@
|
||||
_computeReviewedText(isReviewed) {
|
||||
return isReviewed ? 'MARK UNREVIEWED' : 'MARK REVIEWED';
|
||||
},
|
||||
|
||||
_handleEditTap(e) {
|
||||
const url = Gerrit.Nav.getEditUrlForDiff(this.change, e.detail.path);
|
||||
Gerrit.Nav.navigateToRelativeUrl(url);
|
||||
},
|
||||
});
|
||||
})();
|
||||
|
||||
@@ -1238,6 +1238,20 @@ limitations under the License.
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('editing actions', () => {
|
||||
element.editLoaded = true;
|
||||
element.change = {_number: '42', project: 'test'};
|
||||
const navStub = sandbox.stub(Gerrit.Nav, 'navigateToRelativeUrl');
|
||||
const editControls =
|
||||
Polymer.dom(element.root).querySelectorAll('.row:not(.header)')
|
||||
.map(row => row.querySelector('gr-edit-file-controls'));
|
||||
|
||||
// Commit message should not have edit controls.
|
||||
assert.isTrue(editControls[0].classList.contains('invisible'));
|
||||
MockInteractions.tap(editControls[1].$.edit);
|
||||
assert.isTrue(navStub.called);
|
||||
});
|
||||
});
|
||||
a11ySuite('basic');
|
||||
</script>
|
||||
|
||||
@@ -57,6 +57,7 @@ limitations under the License.
|
||||
console.warn('Use of uninitialized routing');
|
||||
};
|
||||
|
||||
const EDIT_PATCHNUM = 'edit';
|
||||
const PARENT_PATCHNUM = 'PARENT';
|
||||
|
||||
window.Gerrit.Nav = {
|
||||
@@ -277,6 +278,7 @@ limitations under the License.
|
||||
changeNum,
|
||||
project,
|
||||
path,
|
||||
patchNum: EDIT_PATCHNUM,
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
@@ -191,8 +191,9 @@
|
||||
_generateUrl(params) {
|
||||
const base = this.getBaseUrl();
|
||||
let url = '';
|
||||
const Views = Gerrit.Nav.View;
|
||||
|
||||
if (params.view === Gerrit.Nav.View.SEARCH) {
|
||||
if (params.view === Views.SEARCH) {
|
||||
const operators = [];
|
||||
if (params.owner) {
|
||||
operators.push('owner:' + this.encodeURL(params.owner, false));
|
||||
@@ -223,7 +224,7 @@
|
||||
}
|
||||
}
|
||||
url = '/q/' + operators.join('+');
|
||||
} else if (params.view === Gerrit.Nav.View.CHANGE) {
|
||||
} else if (params.view === Views.CHANGE) {
|
||||
let range = this._getPatchRangeExpression(params);
|
||||
if (range.length) { range = '/' + range; }
|
||||
if (params.project) {
|
||||
@@ -231,7 +232,7 @@
|
||||
} else {
|
||||
url = `/c/${params.changeNum}${range}`;
|
||||
}
|
||||
} else if (params.view === Gerrit.Nav.View.DASHBOARD) {
|
||||
} else if (params.view === Views.DASHBOARD) {
|
||||
if (params.sections) {
|
||||
// Custom dashboard.
|
||||
const queryParams = params.sections.map(section => {
|
||||
@@ -247,11 +248,14 @@
|
||||
// User dashboard.
|
||||
url = `/dashboard/${params.user || 'self'}`;
|
||||
}
|
||||
} else if (params.view === Gerrit.Nav.View.DIFF) {
|
||||
} else if (params.view === Views.DIFF || params.view === Views.EDIT) {
|
||||
let range = this._getPatchRangeExpression(params);
|
||||
if (range.length) { range = '/' + range; }
|
||||
|
||||
let suffix = `${range}/${this.encodeURL(params.path, true)}`;
|
||||
|
||||
if (params.view === Views.EDIT) { suffix += ',edit'; }
|
||||
|
||||
if (params.lineNum) {
|
||||
suffix += '#';
|
||||
if (params.leftSide) { suffix += 'b'; }
|
||||
@@ -263,9 +267,6 @@
|
||||
} else {
|
||||
url = `/c/${params.changeNum}${suffix}`;
|
||||
}
|
||||
if (params.edit) {
|
||||
url += ',edit';
|
||||
}
|
||||
} else {
|
||||
throw new Error('Can\'t generate');
|
||||
}
|
||||
|
||||
@@ -280,6 +280,17 @@ limitations under the License.
|
||||
'/c/test/+/42/2/file.cpp#b123');
|
||||
});
|
||||
|
||||
test('edit', () => {
|
||||
const params = {
|
||||
view: Gerrit.Nav.View.EDIT,
|
||||
changeNum: '42',
|
||||
project: 'test',
|
||||
path: 'x+y/path.cpp',
|
||||
};
|
||||
assert.equal(element._generateUrl(params),
|
||||
'/c/test/+/42/x%252By/path.cpp,edit');
|
||||
});
|
||||
|
||||
test('_getPatchRangeExpression', () => {
|
||||
const params = {};
|
||||
let actual = element._getPatchRangeExpression(params);
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
<!--
|
||||
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="../../../bower_components/polymer/polymer.html">
|
||||
|
||||
<link rel="import" href="../../shared/gr-button/gr-button.html">
|
||||
<link rel="import" href="../../shared/gr-dropdown/gr-dropdown.html">
|
||||
|
||||
<link rel="import" href="../../../styles/shared-styles.html">
|
||||
|
||||
<dom-module id="gr-edit-file-controls">
|
||||
<template>
|
||||
<style include="shared-styles">
|
||||
:host {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
#edit {
|
||||
margin-right: .5em;
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
<gr-button
|
||||
id="edit"
|
||||
link
|
||||
on-tap="_handleEditTap">Edit</gr-button>
|
||||
<!-- TODO(kaspern): implement more menu. -->
|
||||
<gr-dropdown
|
||||
id="more"
|
||||
hidden
|
||||
link>More</gr-dropdown>
|
||||
</template>
|
||||
<script src="gr-edit-file-controls.js"></script>
|
||||
</dom-module>
|
||||
@@ -0,0 +1,34 @@
|
||||
// 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-edit-file-controls',
|
||||
|
||||
/**
|
||||
* Fired when the edit button is pressed.
|
||||
*
|
||||
* @event edit-tap
|
||||
*/
|
||||
|
||||
properties: {
|
||||
filePath: String,
|
||||
},
|
||||
|
||||
_handleEditTap() {
|
||||
this.fire('edit-tap', {path: this.filePath});
|
||||
},
|
||||
});
|
||||
})();
|
||||
@@ -0,0 +1,56 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
|
||||
<title>gr-edit-file-controls</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-edit-file-controls.html">
|
||||
|
||||
<script>void(0);</script>
|
||||
|
||||
<test-fixture id="basic">
|
||||
<template>
|
||||
<gr-edit-file-controls></gr-edit-file-controls>
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<script>
|
||||
suite('gr-edit-file-controls tests', () => {
|
||||
let element;
|
||||
let sandbox;
|
||||
|
||||
setup(() => {
|
||||
sandbox = sinon.sandbox.create();
|
||||
element = fixture('basic');
|
||||
});
|
||||
|
||||
teardown(() => { sandbox.restore(); });
|
||||
|
||||
test('edit tap emits event', () => {
|
||||
const handler = sandbox.stub();
|
||||
element.addEventListener('edit-tap', handler);
|
||||
element.filePath = 'foo';
|
||||
|
||||
MockInteractions.tap(element.$.edit);
|
||||
assert.isTrue(handler.called);
|
||||
assert.equal(handler.lastCall.args[0].detail.path, 'foo');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -36,7 +36,7 @@ limitations under the License.
|
||||
gr-fixed-panel {
|
||||
background-color: #fff;
|
||||
border-bottom: 1px #eee solid;
|
||||
z-index: 1;
|
||||
z-index: 10;
|
||||
}
|
||||
header,
|
||||
.subHeader {
|
||||
@@ -94,7 +94,7 @@ limitations under the License.
|
||||
</header>
|
||||
</gr-fixed-panel>
|
||||
<div class="textareaWrapper">
|
||||
<textarea id="file">{{_newContent}}</textarea>
|
||||
<textarea value="{{_newContent::input}}" id="file"></textarea>
|
||||
</div>
|
||||
<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
|
||||
</template>
|
||||
|
||||
@@ -111,11 +111,11 @@
|
||||
if (res.status === 404) {
|
||||
// No edits have been made yet.
|
||||
return this.$.restAPI.getFileInChangeEdit(changeNum, path, true)
|
||||
.then(res => res.text().then(text => atob(text)));
|
||||
.then(res => res.text);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
return res.text().then(text => atob(text));
|
||||
return res.text;
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
@@ -1265,7 +1265,14 @@
|
||||
const e = '/edit/' + encodeURIComponent(path);
|
||||
let payload = null;
|
||||
if (opt_base) { payload = {base: true}; }
|
||||
return this.getChangeURLAndSend(changeNum, 'GET', null, e, payload);
|
||||
return this.getChangeURLAndSend(changeNum, 'GET', null, e, payload)
|
||||
.then(res => {
|
||||
if (!res.ok) { return res; }
|
||||
return res.text().then(text => {
|
||||
res.text = atob(text);
|
||||
return res;
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
rebaseChangeEdit(changeNum) {
|
||||
|
||||
@@ -103,6 +103,7 @@ limitations under the License.
|
||||
'diff/gr-selection-action-box/gr-selection-action-box_test.html',
|
||||
'diff/gr-syntax-layer/gr-syntax-layer_test.html',
|
||||
'diff/gr-syntax-lib-loader/gr-syntax-lib-loader_test.html',
|
||||
'edit/gr-edit-file-controls/gr-edit-file-controls_test.html',
|
||||
'edit/gr-editor-view/gr-editor-view_test.html',
|
||||
'plugins/gr-attribute-helper/gr-attribute-helper_test.html',
|
||||
'plugins/gr-endpoint-decorator/gr-endpoint-decorator_test.html',
|
||||
|
||||
Reference in New Issue
Block a user