Add setting to Show/Hide change table columns in settings
This change adds a widget to adjust change table columns in the user's settings. If no change table columns are adjusted, the server returns an empty array and the client determines the default columns, stored in the gr-change-table-behavior. Columns can get removed/re-ordered by the user but they are limited to those specified in gr-change-table-behavior. Column preferences persist across all gr-change-list items (dashboards, searches, etc). Feature: Issue 4753 Change-Id: I47d5b9f53a95c0c010b04c4495094f188d85e67e
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
<!--
|
||||
Copyright (C) 2016 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.
|
||||
-->
|
||||
<script>
|
||||
(function(window) {
|
||||
'use strict';
|
||||
|
||||
/** @polymerBehavior Gerrit.ChangeTableBehavior */
|
||||
var ChangeTableBehavior = {
|
||||
CHANGE_TABLE_COLUMNS: [
|
||||
'Subject',
|
||||
'Status',
|
||||
'Owner',
|
||||
'Project',
|
||||
'Branch',
|
||||
'Updated',
|
||||
'Size',
|
||||
],
|
||||
|
||||
/**
|
||||
* Returns the complement to the given column array
|
||||
* @param {Array} columns
|
||||
*/
|
||||
getComplementColumns: function(columns) {
|
||||
return this.CHANGE_TABLE_COLUMNS.filter(function(column) {
|
||||
return columns.indexOf(column) === -1;
|
||||
});
|
||||
},
|
||||
|
||||
isColumnHidden: function(columnToCheck, columnsToDisplay) {
|
||||
return columnsToDisplay.indexOf(columnToCheck) === -1;
|
||||
},
|
||||
};
|
||||
|
||||
window.Gerrit = window.Gerrit || {};
|
||||
window.Gerrit.ChangeTableBehavior = ChangeTableBehavior;
|
||||
})(window);
|
||||
</script>
|
||||
@@ -0,0 +1,106 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Copyright (C) 2016 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>keyboard-shortcut-behavior</title>
|
||||
|
||||
<script src="../../../bower_components/webcomponentsjs/webcomponents.min.js"></script>
|
||||
<script src="../../../bower_components/web-component-tester/browser.js"></script>
|
||||
|
||||
<link rel="import" href="../../../bower_components/iron-test-helpers/iron-test-helpers.html">
|
||||
<link rel="import" href="gr-change-table-behavior.html">
|
||||
|
||||
<test-fixture id="basic">
|
||||
<template>
|
||||
<test-element></test-element>
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<test-fixture id="within-overlay">
|
||||
<template>
|
||||
<gr-overlay>
|
||||
<test-element></test-element>
|
||||
</gr-overlay>
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<script>
|
||||
suite('gr-change-table-behavior tests', function() {
|
||||
var element;
|
||||
var overlay;
|
||||
|
||||
suiteSetup(function() {
|
||||
// Define a Polymer element that uses this behavior.
|
||||
Polymer({
|
||||
is: 'test-element',
|
||||
behaviors: [Gerrit.ChangeTableBehavior],
|
||||
});
|
||||
});
|
||||
|
||||
setup(function() {
|
||||
element = fixture('basic');
|
||||
overlay = fixture('within-overlay');
|
||||
});
|
||||
|
||||
test('getComplementColumns', function() {
|
||||
var columns = [
|
||||
'Subject',
|
||||
'Status',
|
||||
'Owner',
|
||||
'Project',
|
||||
'Branch',
|
||||
'Updated',
|
||||
'Size',
|
||||
];
|
||||
assert.deepEqual(element.getComplementColumns(columns), []);
|
||||
|
||||
columns = [
|
||||
'Subject',
|
||||
'Status',
|
||||
'Project',
|
||||
'Branch',
|
||||
'Size',
|
||||
];
|
||||
assert.deepEqual(element.getComplementColumns(columns),
|
||||
['Owner', 'Updated']);
|
||||
});
|
||||
|
||||
test('isColumnHidden', function() {
|
||||
var columnToCheck = 'Project';
|
||||
var columnsToDisplay = [
|
||||
'Subject',
|
||||
'Status',
|
||||
'Owner',
|
||||
'Project',
|
||||
'Branch',
|
||||
'Updated',
|
||||
'Size',
|
||||
];
|
||||
assert.isFalse(element.isColumnHidden(columnToCheck, columnsToDisplay));
|
||||
|
||||
var columnsToDisplay = [
|
||||
'Subject',
|
||||
'Status',
|
||||
'Owner',
|
||||
'Branch',
|
||||
'Updated',
|
||||
'Size',
|
||||
];
|
||||
assert.isTrue(element.isColumnHidden(columnToCheck, columnsToDisplay));
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -13,7 +13,7 @@ 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/gr-change-table-behavior/gr-change-table-behavior.html">
|
||||
<link rel="import" href="../../../behaviors/gr-url-encoding-behavior.html">
|
||||
<link rel="import" href="../../../behaviors/rest-client-behavior.html">
|
||||
<link rel="import" href="../../../bower_components/polymer/polymer.html">
|
||||
@@ -66,30 +66,51 @@ limitations under the License.
|
||||
}
|
||||
</style>
|
||||
<style include="gr-change-list-styles"></style>
|
||||
<span class="cell keyboard">
|
||||
<td class="cell keyboard">
|
||||
<span class="positionIndicator">▶</span>
|
||||
</span>
|
||||
<span class="cell star" hidden$="[[!showStar]]" hidden>
|
||||
</td>
|
||||
<td class="cell star" hidden$="[[!showStar]]" hidden>
|
||||
<gr-change-star change="{{change}}"></gr-change-star>
|
||||
</span>
|
||||
<a class="cell number" href$="[[changeURL]]" hidden$="[[!showNumber]]" hidden>
|
||||
[[change._number]]
|
||||
</a>
|
||||
<a class="cell subject" href$="[[changeURL]]">[[change.subject]]</a>
|
||||
<span class="cell status">[[changeStatusString(change)]]</span>
|
||||
<span class="cell owner">
|
||||
</td>
|
||||
<td class="cell number" hidden$="[[!showNumber]]" hidden>
|
||||
<a href$="[[changeURL]]"> [[change._number]]</a>
|
||||
</td>
|
||||
<td class="cell subject"
|
||||
hidden$="[[isColumnHidden('Subject', visibleChangeTableColumns)]]">
|
||||
<a href$="[[changeURL]]">[[change.subject]]</a>
|
||||
</td>
|
||||
<td class="cell status"
|
||||
hidden$="[[isColumnHidden('Status', visibleChangeTableColumns)]]">
|
||||
[[changeStatusString(change)]]
|
||||
</td>
|
||||
<td class="cell owner"
|
||||
hidden$="[[isColumnHidden('Owner', visibleChangeTableColumns)]]">
|
||||
<gr-account-link account="[[change.owner]]"></gr-account-link>
|
||||
</span>
|
||||
<a class="cell project" href$="[[_computeProjectURL(change.project)]]">[[change.project]]</a>
|
||||
<a class="cell branch" href$="[[_computeProjectBranchURL(change.project, change.branch)]]">[[change.branch]]</a>
|
||||
<gr-date-formatter class="cell updated" date-str="[[change.updated]]"></gr-date-formatter>
|
||||
<span class="cell size u-monospace">
|
||||
</td>
|
||||
<td class="cell project"
|
||||
hidden$="[[isColumnHidden('Project', visibleChangeTableColumns)]]">
|
||||
<a href$="[[_computeProjectURL(change.project)]]">[[change.project]]</a>
|
||||
</td>
|
||||
<td class="cell branch"
|
||||
hidden$="[[isColumnHidden('Branch', visibleChangeTableColumns)]]">
|
||||
<a href$="[[_computeProjectBranchURL(change.project, change.branch)]]">
|
||||
[[change.branch]]
|
||||
</a>
|
||||
</td>
|
||||
<td class="cell updated"
|
||||
hidden$="[[isColumnHidden('Updated', visibleChangeTableColumns)]]">
|
||||
<gr-date-formatter date-str="[[change.updated]]"></gr-date-formatter>
|
||||
</td>
|
||||
<td class="cell size u-monospace"
|
||||
hidden$="[[isColumnHidden('Size', visibleChangeTableColumns)]]">
|
||||
<span class="u-green"><span>+</span>[[change.insertions]]</span>,
|
||||
<span class="u-red"><span>-</span>[[change.deletions]]</span>
|
||||
</span>
|
||||
</td>
|
||||
<template is="dom-repeat" items="[[labelNames]]" as="labelName">
|
||||
<span title$="[[_computeLabelTitle(change, labelName)]]"
|
||||
class$="[[_computeLabelClass(change, labelName)]]">[[_computeLabelValue(change, labelName)]]</span>
|
||||
<td title$="[[_computeLabelTitle(change, labelName)]]"
|
||||
class$="[[_computeLabelClass(change, labelName)]]">
|
||||
[[_computeLabelValue(change, labelName)]]
|
||||
</td>
|
||||
</template>
|
||||
</template>
|
||||
<script src="gr-change-list-item.js"></script>
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
is: 'gr-change-list-item',
|
||||
|
||||
properties: {
|
||||
visibleChangeTableColumns: Array,
|
||||
selected: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
@@ -43,6 +44,7 @@
|
||||
},
|
||||
|
||||
behaviors: [
|
||||
Gerrit.ChangeTableBehavior,
|
||||
Gerrit.RESTClientBehavior,
|
||||
Gerrit.URLEncodingBehavior,
|
||||
],
|
||||
|
||||
@@ -22,6 +22,7 @@ limitations under the License.
|
||||
<script src="../../../bower_components/web-component-tester/browser.js"></script>
|
||||
<script src="../../../scripts/util.js"></script>
|
||||
|
||||
<link rel="import" href="../../../bower_components/iron-test-helpers/iron-test-helpers.html">
|
||||
<link rel="import" href="gr-change-list-item.html">
|
||||
|
||||
<test-fixture id="basic">
|
||||
@@ -45,7 +46,7 @@ limitations under the License.
|
||||
test('change status', function() {
|
||||
var getStatusForChange = function(change) {
|
||||
element.change = change;
|
||||
return element.$$('.cell.status').textContent;
|
||||
return element.$$('.cell.status').textContent.trim();
|
||||
};
|
||||
|
||||
assert.equal(getStatusForChange({mergeable: true}), '');
|
||||
@@ -137,5 +138,75 @@ limitations under the License.
|
||||
assert.equal(element.changeURL, '/c/43/');
|
||||
});
|
||||
|
||||
test('no hidden columns', function() {
|
||||
element.visibleChangeTableColumns = [
|
||||
'Subject',
|
||||
'Status',
|
||||
'Owner',
|
||||
'Project',
|
||||
'Branch',
|
||||
'Updated',
|
||||
'Size',
|
||||
];
|
||||
|
||||
flushAsynchronousOperations();
|
||||
|
||||
element.CHANGE_TABLE_COLUMNS.forEach(function(column) {
|
||||
var elementClass = '.' + column.toLowerCase();
|
||||
assert.isFalse(element.$$(elementClass).hidden);
|
||||
});
|
||||
});
|
||||
|
||||
test('no hidden columns', function() {
|
||||
element.visibleChangeTableColumns = [
|
||||
'Subject',
|
||||
'Status',
|
||||
'Owner',
|
||||
'Project',
|
||||
'Branch',
|
||||
'Updated',
|
||||
'Size',
|
||||
];
|
||||
|
||||
flushAsynchronousOperations();
|
||||
|
||||
element.CHANGE_TABLE_COLUMNS.forEach(function(column) {
|
||||
var elementClass = '.' + column.toLowerCase();
|
||||
assert.isFalse(element.$$(elementClass).hidden);
|
||||
});
|
||||
});
|
||||
|
||||
test('project column hidden', function() {
|
||||
element.visibleChangeTableColumns = [
|
||||
'Subject',
|
||||
'Status',
|
||||
'Owner',
|
||||
'Branch',
|
||||
'Updated',
|
||||
'Size',
|
||||
];
|
||||
|
||||
flushAsynchronousOperations();
|
||||
|
||||
element.CHANGE_TABLE_COLUMNS.forEach(function(column) {
|
||||
var elementClass = '.' + column.toLowerCase();
|
||||
if (column === 'Project') {
|
||||
assert.isTrue(element.$$(elementClass).hidden);
|
||||
} else {
|
||||
assert.isFalse(element.$$(elementClass).hidden);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('random column does not exist', function() {
|
||||
element.visibleChangeTableColumns = [
|
||||
'Bad',
|
||||
];
|
||||
|
||||
flushAsynchronousOperations();
|
||||
var elementClass = '.bad';
|
||||
assert.isNotOk(element.$$(elementClass));
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -15,6 +15,7 @@ limitations under the License.
|
||||
-->
|
||||
|
||||
<link rel="import" href="../../../bower_components/polymer/polymer.html">
|
||||
<link rel="import" href="../../../behaviors/gr-change-table-behavior/gr-change-table-behavior.html">
|
||||
<link rel="import" href="../../../behaviors/keyboard-shortcut-behavior/keyboard-shortcut-behavior.html">
|
||||
<link rel="import" href="../../../behaviors/rest-client-behavior.html">
|
||||
<link rel="import" href="../../../styles/gr-change-list-styles.html">
|
||||
@@ -28,42 +29,60 @@ limitations under the License.
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
#changeList {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
}
|
||||
.cell {
|
||||
flex-shrink: 0;
|
||||
padding: .3em .5em;
|
||||
}
|
||||
th {
|
||||
text-align: left;
|
||||
}
|
||||
</style>
|
||||
<style include="gr-change-list-styles"></style>
|
||||
<div class="headerRow">
|
||||
<span class="topHeader keyboard"></span> <!-- keyboard position indicator -->
|
||||
<span class="topHeader star" hidden$="[[!showStar]]" hidden></span>
|
||||
<span class="topHeader number" hidden$="[[!showNumber]]" hidden>#</span>
|
||||
<span class="topHeader subject">Subject</span>
|
||||
<span class="topHeader status">Status</span>
|
||||
<span class="topHeader owner">Owner</span>
|
||||
<span class="topHeader project">Project</span>
|
||||
<span class="topHeader branch">Branch</span>
|
||||
<span class="topHeader updated">Updated</span>
|
||||
<span class="topHeader size">Size</span>
|
||||
<template is="dom-repeat" items="[[labelNames]]" as="labelName">
|
||||
<span class="topHeader label" title$="[[labelName]]">
|
||||
[[_computeLabelShortcut(labelName)]]
|
||||
</span>
|
||||
<table id="changeList">
|
||||
<tr class="headerRow">
|
||||
<th class="topHeader keyboard"></th>
|
||||
<th class="topHeader star" hidden$="[[!showStar]]" hidden></th>
|
||||
<th class="topHeader number" hidden$="[[!showNumber]]" hidden>#</th>
|
||||
<template is="dom-repeat" items="[[changeTableColumns]]" as="item">
|
||||
<th class$="[[_lowerCase(item)]] topHeader"
|
||||
hidden$="[[isColumnHidden(item, visibleChangeTableColumns)]]">
|
||||
[[item]]
|
||||
</th>
|
||||
</template>
|
||||
<template is="dom-repeat" items="[[labelNames]]" as="labelName">
|
||||
<th class="topHeader label" title$="[[labelName]]">
|
||||
[[_computeLabelShortcut(labelName)]]
|
||||
</th>
|
||||
</template>
|
||||
</tr>
|
||||
<template is="dom-repeat" items="[[groups]]" as="changeGroup"
|
||||
index-as="groupIndex">
|
||||
<template is="dom-if" if="[[_groupTitle(groupIndex)]]">
|
||||
<tr class="groupHeader">
|
||||
<td class="cell">[[_groupTitle(groupIndex)]]</td>
|
||||
</tr>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!changeGroup.length]]">
|
||||
<tr class="noChanges"><td class="cell">No changes</td></tr>
|
||||
</template>
|
||||
<template is="dom-repeat" items="[[changeGroup]]" as="change">
|
||||
<tr>
|
||||
<gr-change-list-item
|
||||
selected$="[[_computeItemSelected(index, groupIndex, selectedIndex)]]"
|
||||
needs-review="[[_computeItemNeedsReview(account, change, showReviewedState)]]"
|
||||
change="[[change]]"
|
||||
visible-change-table-columns="[[visibleChangeTableColumns]]"
|
||||
show-number="[[showNumber]]"
|
||||
show-star="[[showStar]]"
|
||||
label-names="[[labelNames]]"></gr-change-list-item>
|
||||
</tr>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
<template is="dom-repeat" items="{{groups}}" as="changeGroup" index-as="groupIndex">
|
||||
<template is="dom-if" if="[[_groupTitle(groupIndex)]]">
|
||||
<div class="groupHeader">[[_groupTitle(groupIndex)]]</div>
|
||||
</template>
|
||||
<template is="dom-if" if="[[!changeGroup.length]]">
|
||||
<div class="noChanges">No changes</div>
|
||||
</template>
|
||||
<template is="dom-repeat" items="[[changeGroup]]" as="change">
|
||||
<gr-change-list-item
|
||||
selected$="[[_computeItemSelected(index, groupIndex, selectedIndex)]]"
|
||||
needs-review="[[_computeItemNeedsReview(account, change, showReviewedState)]]"
|
||||
change="[[change]]"
|
||||
show-number="[[showNumber]]"
|
||||
show-star="[[showStar]]"
|
||||
label-names="[[labelNames]]"></gr-change-list-item>
|
||||
</template>
|
||||
</template>
|
||||
</table>
|
||||
<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
|
||||
</template>
|
||||
<script src="gr-change-list.js"></script>
|
||||
|
||||
@@ -74,6 +74,7 @@
|
||||
},
|
||||
|
||||
behaviors: [
|
||||
Gerrit.ChangeTableBehavior,
|
||||
Gerrit.KeyboardShortcutBehavior,
|
||||
Gerrit.RESTClientBehavior,
|
||||
],
|
||||
@@ -88,15 +89,24 @@
|
||||
this._loadPreferences();
|
||||
},
|
||||
|
||||
_lowerCase: function(column) {
|
||||
return column.toLowerCase();
|
||||
},
|
||||
|
||||
_loadPreferences: function() {
|
||||
return this._getLoggedIn().then(function(loggedIn) {
|
||||
this.changeTableColumns = this.CHANGE_TABLE_COLUMNS;
|
||||
|
||||
if (!loggedIn) {
|
||||
this.showNumber = false;
|
||||
this.visibleChangeTableColumns = this.CHANGE_TABLE_COLUMNS;
|
||||
return;
|
||||
}
|
||||
return this._getPreferences().then(function(preferences) {
|
||||
this.showNumber = !!(preferences &&
|
||||
preferences.legacycid_in_change_table);
|
||||
this.visibleChangeTableColumns = preferences.change_table.length > 0 ?
|
||||
preferences.change_table : this.CHANGE_TABLE_COLUMNS;
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
@@ -70,9 +70,10 @@ limitations under the License.
|
||||
|
||||
suite('test show change number preference enabled', function() {
|
||||
setup(function(done) {
|
||||
return stubRestAPI(
|
||||
{legacycid_in_change_table: true, time_format: 'HHMM_12'}
|
||||
).then(function() {
|
||||
return stubRestAPI({legacycid_in_change_table: true,
|
||||
time_format: 'HHMM_12',
|
||||
change_table: [],
|
||||
}).then(function() {
|
||||
element = fixture('basic');
|
||||
element._loadPreferences().then(function() { done(); });
|
||||
});
|
||||
@@ -86,9 +87,8 @@ limitations under the License.
|
||||
suite('test show change number preference disabled', function() {
|
||||
setup(function(done) {
|
||||
// legacycid_in_change_table is not set when false.
|
||||
return stubRestAPI(
|
||||
{time_format: 'HHMM_12'}
|
||||
).then(function() {
|
||||
return stubRestAPI({time_format: 'HHMM_12', change_table: []}).then(
|
||||
function() {
|
||||
element = fixture('basic');
|
||||
element._loadPreferences().then(function() { done(); });
|
||||
});
|
||||
@@ -235,6 +235,120 @@ limitations under the License.
|
||||
'.noChanges');
|
||||
assert.equal(noChangesMsg.length, 2);
|
||||
});
|
||||
|
||||
suite('empty column preference', function() {
|
||||
var element;
|
||||
|
||||
setup(function(done) {
|
||||
return stubRestAPI({
|
||||
legacycid_in_change_table: true,
|
||||
time_format: 'HHMM_12',
|
||||
change_table: [],
|
||||
}
|
||||
).then(function() {
|
||||
element = fixture('basic');
|
||||
element._loadPreferences().then(function() { done(); });
|
||||
});
|
||||
});
|
||||
|
||||
test('show number enabled', function() {
|
||||
assert.isTrue(element.showNumber);
|
||||
});
|
||||
|
||||
test('all columns visible', function() {
|
||||
element.CHANGE_TABLE_COLUMNS.forEach(function(column) {
|
||||
var elementClass = '.' + element._lowerCase(column);
|
||||
assert.isFalse(element.$$(elementClass).hidden);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('full column preference', function() {
|
||||
var element;
|
||||
|
||||
setup(function(done) {
|
||||
return stubRestAPI({
|
||||
legacycid_in_change_table: true,
|
||||
time_format: 'HHMM_12',
|
||||
change_table: [
|
||||
'Subject',
|
||||
'Status',
|
||||
'Owner',
|
||||
'Project',
|
||||
'Branch',
|
||||
'Updated',
|
||||
'Size',
|
||||
],
|
||||
}).then(function() {
|
||||
element = fixture('basic');
|
||||
element._loadPreferences().then(function() { done(); });
|
||||
});
|
||||
});
|
||||
|
||||
test('all columns visible', function() {
|
||||
element.changeTableColumns.forEach(function(column) {
|
||||
var elementClass = '.' + element._lowerCase(column);
|
||||
assert.isFalse(element.$$(elementClass).hidden);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('partial column preference', function() {
|
||||
var element;
|
||||
|
||||
setup(function(done) {
|
||||
return stubRestAPI({
|
||||
legacycid_in_change_table: true,
|
||||
time_format: 'HHMM_12',
|
||||
change_table: [
|
||||
'Subject',
|
||||
'Status',
|
||||
'Owner',
|
||||
'Branch',
|
||||
'Updated',
|
||||
'Size',
|
||||
],
|
||||
}).then(function() {
|
||||
element = fixture('basic');
|
||||
element._loadPreferences().then(function() { done(); });
|
||||
});
|
||||
});
|
||||
|
||||
test('all columns except project visible', function() {
|
||||
element.changeTableColumns.forEach(function(column) {
|
||||
var elementClass = '.' + column.toLowerCase();
|
||||
if (column === 'Project') {
|
||||
assert.isTrue(element.$$(elementClass).hidden);
|
||||
} else {
|
||||
assert.isFalse(element.$$(elementClass).hidden);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('random column does not exist', function() {
|
||||
var element;
|
||||
|
||||
/* This would only exist if somebody manually updated the config
|
||||
file. */
|
||||
setup(function(done) {
|
||||
return stubRestAPI({
|
||||
legacycid_in_change_table: true,
|
||||
time_format: 'HHMM_12',
|
||||
change_table: [
|
||||
'Bad',
|
||||
],
|
||||
}).then(function() {
|
||||
element = fixture('basic');
|
||||
element._loadPreferences().then(function() { done(); });
|
||||
});
|
||||
});
|
||||
|
||||
test('bad column does not exist', function() {
|
||||
var elementClass = '.bad';
|
||||
assert.isNotOk(element.$$(elementClass));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
suite('gr-change-list groups', function() {
|
||||
@@ -294,6 +408,5 @@ limitations under the License.
|
||||
'Should navigate to /c/4/');
|
||||
showStub.restore();
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
<!--
|
||||
Copyright (C) 2016 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/gr-change-table-behavior/gr-change-table-behavior.html">
|
||||
<link rel="import" href="../../../bower_components/polymer/polymer.html">
|
||||
<link rel="import" href="../../../bower_components/iron-input/iron-input.html">
|
||||
<link rel="import" href="../../shared/gr-button/gr-button.html">
|
||||
<link rel="import" href="../../shared/gr-date-formatter/gr-date-formatter.html">
|
||||
<link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
|
||||
|
||||
<link rel="import" href="../../../styles/gr-settings-styles.html">
|
||||
|
||||
<dom-module id="gr-change-table-editor">
|
||||
<template>
|
||||
<style>
|
||||
th.nameHeader {
|
||||
width: 11em;
|
||||
}
|
||||
tbody tr:first-of-type td .move-up-button,
|
||||
tbody tr:last-of-type td .move-down-button {
|
||||
display: none;
|
||||
}
|
||||
.newTitleInput {
|
||||
width: 10em;
|
||||
}
|
||||
.newUrlInput {
|
||||
width: 23em;
|
||||
}
|
||||
.addOptions {
|
||||
margin-top: 1em;
|
||||
}
|
||||
</style>
|
||||
<style include="gr-settings-styles"></style>
|
||||
<div class="gr-settings-styles">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="nameHeader">Column</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<template is="dom-repeat" items="[[changeTableItems]]">
|
||||
<tr>
|
||||
<td>[[item]]</td>
|
||||
<td>
|
||||
<gr-button
|
||||
data-index="[[index]]"
|
||||
on-tap="_handleDeleteButton"
|
||||
class="remove-button">Delete</gr-button>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<template is="dom-if" if="[[changeTableNotDisplayed.length]]">
|
||||
<table class=addOptions>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="nameHeader">Hidden</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<template is="dom-repeat" items="[[changeTableNotDisplayed]]">
|
||||
<tr>
|
||||
<td>[[item]]</td>
|
||||
<td>
|
||||
<gr-button
|
||||
on-tap="_handleAddButton"
|
||||
class="add-button"
|
||||
data-index="[[index]]">
|
||||
Add
|
||||
</gr-button>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
<tbody>
|
||||
</table>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<script src="gr-change-table-editor.js"></script>
|
||||
</dom-module>
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright (C) 2016 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-change-table-editor',
|
||||
|
||||
properties: {
|
||||
changeTableItems: Array,
|
||||
changeTableNotDisplayed: Array,
|
||||
},
|
||||
|
||||
behaviors: [
|
||||
Gerrit.ChangeTableBehavior,
|
||||
],
|
||||
|
||||
_handleDeleteButton: function(e) {
|
||||
var index = e.target.dataIndex;
|
||||
this.splice('changeTableItems', index, 1);
|
||||
|
||||
// Use the change table behavior to make sure ordering of unused
|
||||
// columns ends up in the correct order. If the removed item is appended
|
||||
// to the end, when it is saved, the unused column order may shift around.
|
||||
this.set('changeTableNotDisplayed',
|
||||
this.getComplementColumns(this.changeTableItems));
|
||||
|
||||
},
|
||||
|
||||
_handleAddButton: function(e) {
|
||||
var index = e.target.dataIndex;
|
||||
var newColumn = this.changeTableNotDisplayed[index];
|
||||
this.splice('changeTableNotDisplayed', index, 1);
|
||||
|
||||
this.splice('changeTableItems', this.getComplementColumns(
|
||||
this.changeTableNotDisplayed).indexOf(newColumn), 0, newColumn);
|
||||
},
|
||||
});
|
||||
})();
|
||||
@@ -0,0 +1,193 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Copyright (C) 2016 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-settings-view</title>
|
||||
|
||||
<script src="../../../bower_components/webcomponentsjs/webcomponents.min.js"></script>
|
||||
<script src="../../../bower_components/web-component-tester/browser.js"></script>
|
||||
|
||||
<link rel="import" href="../../../bower_components/iron-test-helpers/iron-test-helpers.html">
|
||||
<link rel="import" href="gr-change-table-editor.html">
|
||||
|
||||
<test-fixture id="basic">
|
||||
<template>
|
||||
<gr-change-table-editor></gr-change-table-editor>
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<script>
|
||||
suite('gr-settings-view tests', function() {
|
||||
var element;
|
||||
var columns;
|
||||
|
||||
// Click the up/down button (according to direction) for the index'th row.
|
||||
// The index of the first row is 0, corresponding to the array.
|
||||
function move(element, index, direction) {
|
||||
var selector =
|
||||
'tr:nth-child(' + (index + 1) + ') .move-' + direction + '-button';
|
||||
var button = element.$$('tbody').querySelector(selector);
|
||||
MockInteractions.tap(button);
|
||||
flushAsynchronousOperations();
|
||||
}
|
||||
|
||||
setup(function() {
|
||||
element = fixture('basic');
|
||||
columns = [
|
||||
'Subject',
|
||||
'Status',
|
||||
'Owner',
|
||||
'Project',
|
||||
'Branch',
|
||||
'Updated',
|
||||
];
|
||||
|
||||
columnsNotDisplayed = ['Size'];
|
||||
|
||||
element.set('changeTableItems', columns);
|
||||
element.set('changeTableNotDisplayed', columnsNotDisplayed);
|
||||
flushAsynchronousOperations();
|
||||
});
|
||||
|
||||
test('renders', function() {
|
||||
var rows = element.$$('tbody').querySelectorAll('tr');
|
||||
var tds;
|
||||
|
||||
assert.equal(rows.length, columns.length);
|
||||
for (var i = 0; i < columns.length; i++) {
|
||||
tds = rows[i].querySelectorAll('td');
|
||||
assert.equal(tds[0].textContent, columns[i]);
|
||||
}
|
||||
});
|
||||
|
||||
test('add hidden item', function() {
|
||||
var originalNumberColumns = element.changeTableItems.length;
|
||||
var originalNumberHiddenColumns = element.changeTableNotDisplayed.length;
|
||||
|
||||
var addBtn = element.$$('.addOptions gr-button');
|
||||
var columnName = element.$$('.addOptions tr td').innerHTML;
|
||||
|
||||
assert.equal(element.$$('.addOptions').style.display, '');
|
||||
|
||||
MockInteractions.tap(addBtn);
|
||||
flushAsynchronousOperations();
|
||||
|
||||
assert.equal(element.changeTableItems.length, originalNumberColumns + 1);
|
||||
assert.equal(element.changeTableNotDisplayed.length,
|
||||
originalNumberHiddenColumns - 1);
|
||||
|
||||
assert.equal(
|
||||
element.changeTableItems[element.changeTableItems.length - 1],
|
||||
columnName);
|
||||
|
||||
assert.equal(element.$$('.addOptions').style.display, 'none');
|
||||
});
|
||||
|
||||
test('remove item', function() {
|
||||
var columns = element.changeTableItems.length;
|
||||
assert.deepEqual(element.changeTableItems, [
|
||||
'Subject',
|
||||
'Status',
|
||||
'Owner',
|
||||
'Project',
|
||||
'Branch',
|
||||
'Updated',
|
||||
]);
|
||||
|
||||
// Tap the delete button for the second item.
|
||||
MockInteractions.tap(
|
||||
element.$$('tbody').querySelector('tr:nth-child(2) .remove-button'));
|
||||
|
||||
assert.deepEqual(element.changeTableItems, [
|
||||
'Subject',
|
||||
'Owner',
|
||||
'Project',
|
||||
'Branch',
|
||||
'Updated',
|
||||
]);
|
||||
|
||||
assert.deepEqual(element.changeTableNotDisplayed, [
|
||||
'Status',
|
||||
'Size',
|
||||
]);
|
||||
|
||||
// Delete remaining items.
|
||||
for (var i = 0; i < columns - 1; i++) {
|
||||
MockInteractions.tap(
|
||||
element.$$('tbody').querySelector('tr:first-child .remove-button'));
|
||||
}
|
||||
assert.deepEqual(element.changeTableItems, []);
|
||||
assert.deepEqual(element.changeTableNotDisplayed, [
|
||||
'Subject',
|
||||
'Status',
|
||||
'Owner',
|
||||
'Project',
|
||||
'Branch',
|
||||
'Updated',
|
||||
'Size',
|
||||
]);
|
||||
});
|
||||
|
||||
test('add item', function() {
|
||||
|
||||
element.set('changeTableItems', [
|
||||
'Status',
|
||||
'Owner',
|
||||
'Project',
|
||||
'Branch',
|
||||
'Updated',
|
||||
]);
|
||||
|
||||
element.set('changeTableNotDisplayed', ['Subject', 'Size']);
|
||||
|
||||
var columns = element.changeTableItems.length;
|
||||
flushAsynchronousOperations();
|
||||
|
||||
// Tap the add button for the second item.
|
||||
MockInteractions.tap(
|
||||
element.$$('.addOptions').querySelector(
|
||||
'tr:nth-child(2) .add-button'));
|
||||
|
||||
flushAsynchronousOperations();
|
||||
assert.deepEqual(element.changeTableItems, [
|
||||
'Status',
|
||||
'Owner',
|
||||
'Project',
|
||||
'Branch',
|
||||
'Updated',
|
||||
'Size',
|
||||
]);
|
||||
assert.deepEqual(element.changeTableNotDisplayed, ['Subject']);
|
||||
|
||||
// Add remaining item.
|
||||
MockInteractions.tap(
|
||||
element.$$('.addOptions').querySelector('.add-button'));
|
||||
flushAsynchronousOperations();
|
||||
|
||||
assert.deepEqual(element.changeTableNotDisplayed, []);
|
||||
assert.deepEqual(element.changeTableItems, [
|
||||
'Subject',
|
||||
'Status',
|
||||
'Owner',
|
||||
'Project',
|
||||
'Branch',
|
||||
'Updated',
|
||||
'Size'
|
||||
]);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -20,6 +20,7 @@ limitations under the License.
|
||||
<link rel="import" href="../gr-email-editor/gr-email-editor.html">
|
||||
<link rel="import" href="../gr-group-list/gr-group-list.html">
|
||||
<link rel="import" href="../gr-http-password/gr-http-password.html">
|
||||
<link rel="import" href="../gr-change-table-editor/gr-change-table-editor.html">
|
||||
<link rel="import" href="../gr-menu-editor/gr-menu-editor.html">
|
||||
<link rel="import" href="../gr-ssh-editor/gr-ssh-editor.html">
|
||||
<link rel="import" href="../gr-watched-projects-editor/gr-watched-projects-editor.html">
|
||||
@@ -295,6 +296,19 @@ limitations under the License.
|
||||
on-tap="_handleSaveMenu"
|
||||
disabled="[[!_menuChanged]]">Save Changes</gr-button>
|
||||
</fieldset>
|
||||
<h2 class$="[[_computeHeaderClass(_changeTableChanged)]]">
|
||||
Change Table Columns
|
||||
</h2>
|
||||
<fieldset id="changeTableColumns">
|
||||
<gr-change-table-editor
|
||||
change-table-items="{{_localChangeTableColumns}}"
|
||||
change-table-not-displayed="{{_changeTableColumnsNotDisplayed}}">
|
||||
</gr-change-table-editor>
|
||||
<gr-button
|
||||
id="saveChangeTable"
|
||||
on-tap="_handleSaveChangeTable"
|
||||
disabled="[[!_changeTableChanged]]">Save Changes</gr-button>
|
||||
</fieldset>
|
||||
<h2
|
||||
id="Notifications"
|
||||
class$="[[_computeHeaderClass(_watchedProjectsChanged)]]">
|
||||
|
||||
@@ -39,10 +39,15 @@
|
||||
_accountInfoMutable: Boolean,
|
||||
_accountInfoChanged: Boolean,
|
||||
_diffPrefs: Object,
|
||||
_changeTableColumnsNotDisplayed: Array,
|
||||
_localPrefs: {
|
||||
type: Object,
|
||||
value: function() { return {}; },
|
||||
},
|
||||
_localChangeTableColumns: {
|
||||
type: Array,
|
||||
value: function() { return []; },
|
||||
},
|
||||
_localMenu: {
|
||||
type: Array,
|
||||
value: function() { return []; },
|
||||
@@ -51,6 +56,10 @@
|
||||
type: Boolean,
|
||||
value: true,
|
||||
},
|
||||
_changeTableChanged: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
_prefsChanged: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
@@ -89,10 +98,15 @@
|
||||
_loadingPromise: Object,
|
||||
},
|
||||
|
||||
behaviors: [
|
||||
Gerrit.ChangeTableBehavior,
|
||||
],
|
||||
|
||||
observers: [
|
||||
'_handlePrefsChanged(_localPrefs.*)',
|
||||
'_handleDiffPrefsChanged(_diffPrefs.*)',
|
||||
'_handleMenuChanged(_localMenu.splices)',
|
||||
'_handleChangeTableChanged(_localChangeTableColumns.splices)',
|
||||
],
|
||||
|
||||
attached: function() {
|
||||
@@ -110,6 +124,7 @@
|
||||
this.prefs = prefs;
|
||||
this._copyPrefs('_localPrefs', 'prefs');
|
||||
this._cloneMenu();
|
||||
this._cloneChangeTableColumns();
|
||||
}.bind(this)));
|
||||
|
||||
promises.push(this.$.restAPI.getDiffPreferences().then(function(prefs) {
|
||||
@@ -179,6 +194,30 @@
|
||||
this._localMenu = menu;
|
||||
},
|
||||
|
||||
_cloneChangeTableColumns: function() {
|
||||
var columns = this.prefs.change_table;
|
||||
|
||||
if (columns.length === 0) {
|
||||
columns = this.CHANGE_TABLE_COLUMNS;
|
||||
this._changeTableColumnsNotDisplayed = [];
|
||||
} else {
|
||||
this._changeTableColumnsNotDisplayed = this.getComplementColumns(
|
||||
this.prefs.change_table);
|
||||
}
|
||||
this._localChangeTableColumns = columns;
|
||||
},
|
||||
|
||||
_formatChangeTableColumns: function(changeTableArray) {
|
||||
return changeTableArray.map(function(item) {
|
||||
return {column: item};
|
||||
});
|
||||
},
|
||||
|
||||
_handleChangeTableChanged: function() {
|
||||
if (this._isLoading()) { return; }
|
||||
this._changeTableChanged = true;
|
||||
},
|
||||
|
||||
_handlePrefsChanged: function(prefs) {
|
||||
if (this._isLoading()) { return; }
|
||||
this._prefsChanged = true;
|
||||
@@ -224,6 +263,14 @@
|
||||
this.$.syntaxHighlighting.checked);
|
||||
},
|
||||
|
||||
_handleSaveChangeTable: function() {
|
||||
this.set('prefs.change_table', this._localChangeTableColumns);
|
||||
this._cloneChangeTableColumns();
|
||||
return this.$.restAPI.savePreferences(this.prefs).then(function() {
|
||||
this._changeTableChanged = false;
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
_handleSaveDiffPreferences: function() {
|
||||
return this.$.restAPI.saveDiffPreferences(this._diffPrefs)
|
||||
.then(function() {
|
||||
|
||||
@@ -88,6 +88,7 @@ limitations under the License.
|
||||
{url: '/first/url', name: 'first name', target: '_blank'},
|
||||
{url: '/second/url', name: 'second name', target: '_blank'},
|
||||
],
|
||||
change_table: [],
|
||||
};
|
||||
diffPreferences = {
|
||||
context: 10,
|
||||
|
||||
Reference in New Issue
Block a user