Add dropdown for selecting diff view mode to file list
Setting persists for the duration of viewing a change. When a user
selects a new change, their default view mode is set.
Bug: Issue 4670
Change-Id: I4eade0e42c13bf2b3079ef38fb07239f98a243d8
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html
index a4b0a9b..5925725 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.html
@@ -298,7 +298,8 @@
drafts="[[_diffDrafts]]"
revisions="[[_change.revisions]]"
projectConfig="[[_projectConfig]]"
- selected-index="{{viewState.selectedFileIndex}}"></gr-file-list>
+ selected-index="{{viewState.selectedFileIndex}}"
+ diff-view-mode="{{viewState.diffMode}}"></gr-file-list>
</section>
<gr-messages-list id="messageList"
change-num="[[_changeNum]]"
diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.html b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.html
index 87e03dc..a297cb2 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.html
+++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.html
@@ -147,9 +147,18 @@
/
<gr-button link on-tap="_collapseAllDiffs">Hide diffs</gr-button>
/
+ <select
+ id="modeSelect"
+ is="gr-select"
+ bind-value="{{diffViewMode}}"
+ on-change="_handleDropdownChange">
+ <option value="SIDE_BY_SIDE">Side By Side</option>
+ <option value="UNIFIED_DIFF">Unified</option>
+ </select>
+ /
<label>
Diff against
- <select on-change="_handlePatchChange">
+ <select id="patchChange" on-change="_handlePatchChange">
<option value="PARENT">Base</option>
<template is="dom-repeat" items="[[_computePatchSets(revisions, patchRange.*)]]" as="patchNum">
<option
@@ -210,7 +219,7 @@
path="[[file.__path]]"
prefs="[[_diffPrefs]]"
project-config="[[projectConfig]]"
- view-mode="[[_userPrefs.diff_view]]"></gr-diff>
+ view-mode="[[_diffMode]]"></gr-diff>
</template>
<gr-button
class="fileListButton"
diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.js b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.js
index a562338..874cc89 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.js
+++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list.js
@@ -16,6 +16,11 @@
var COMMIT_MESSAGE_PATH = '/COMMIT_MSG';
+ var DiffViewMode = {
+ SIDE_BY_SIDE: 'SIDE_BY_SIDE',
+ UNIFIED: 'UNIFIED_DIFF',
+ };
+
Polymer({
is: 'gr-file-list',
@@ -36,7 +41,10 @@
value: function() { return document.body; },
},
change: Object,
-
+ diffViewMode: {
+ type: String,
+ notify: true,
+ },
_files: {
type: Array,
observer: '_filesChanged',
@@ -67,6 +75,10 @@
type: Array,
computed: '_computeFilesShown(_numFilesShown, _files.*)',
},
+ _diffMode: {
+ type: String,
+ computed: '_getDiffViewMode(diffViewMode, _userPrefs)',
+ },
},
behaviors: [
@@ -100,8 +112,17 @@
this._diffPrefs = prefs;
}.bind(this)));
+ // Initialize with user's diff mode preference. Default to
+ // SIDE_BY_SIDE in the meantime.
+ var setDiffViewMode = this.diffViewMode === null;
+ if (setDiffViewMode) {
+ this.set('diffViewMode', DiffViewMode.SIDE_BY_SIDE);
+ }
promises.push(this._getPreferences().then(function(prefs) {
this._userPrefs = prefs;
+ if (setDiffViewMode) {
+ this.set('diffViewMode', prefs.diff_view);
+ }
}.bind(this)));
},
@@ -474,5 +495,32 @@
_showAllFiles: function() {
this._numFilesShown = this._files.length;
},
+
+ /**
+ * _getDiffViewMode: Get the diff view (side-by-side or unified) based on
+ * the current state.
+ *
+ * The expected behavior is to use the mode specified in the user's
+ * preferences unless they have manually chosen the alternative view. If the
+ * user navigates up to the change view, it should clear this choice and
+ * revert to the preference the next time a diff is viewed.
+ *
+ * Use side-by-side if the user is not logged in.
+ *
+ * @return {String}
+ */
+ _getDiffViewMode: function() {
+ if (this.diffViewMode) {
+ return this.diffViewMode;
+ } else if (this._userPrefs && this._userPrefs.diff_view) {
+ return this.diffViewMode = this._userPrefs.diff_view;
+ }
+
+ return DiffViewMode.SIDE_BY_SIDE;
+ },
+
+ _handleDropdownChange: function(e) {
+ e.target.blur();
+ },
});
})();
diff --git a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.html b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.html
index 502597c..3402395 100644
--- a/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.html
+++ b/polygerrit-ui/app/elements/change/gr-file-list/gr-file-list_test.html
@@ -32,20 +32,36 @@
</template>
</test-fixture>
+<test-fixture id="blank">
+ <template>
+ <div></div>
+ </template>
+</test-fixture>
+
<script>
suite('gr-file-list tests', function() {
var element;
+ var sandbox;
setup(function() {
+ sandbox = sinon.sandbox.create();
stub('gr-rest-api-interface', {
getLoggedIn: function() { return Promise.resolve(true); },
getPreferences: function() { return Promise.resolve({}); },
+ fetchJSON: function() { return Promise.resolve({}); },
+ });
+ stub('gr-date-formatter', {
+ _loadTimeFormat: function() { return Promise.resolve(''); }
});
element = fixture('basic');
});
+ teardown(function() {
+ sandbox.restore();
+ });
+
test('get file list', function(done) {
- var getChangeFilesStub = sinon.stub(element.$.restAPI, 'getChangeFiles',
+ var getChangeFilesStub = sandbox.stub(element.$.restAPI, 'getChangeFiles',
function() {
return Promise.resolve({
'/COMMIT_MSG': {lines_inserted: 9},
@@ -97,12 +113,15 @@
});
test('toggle left diff via shortcut', function() {
- var toggleLeftDiffStub = sinon.stub();
- sinon.stub(element, 'diffs', {get: function() {
+ var toggleLeftDiffStub = sandbox.stub();
+ // Property getter cannot be stubbed w/ sandbox due to a bug in Sinon.
+ // https://github.com/sinonjs/sinon/issues/781
+ var diffsStub = sinon.stub(element, 'diffs', {get: function() {
return [{toggleLeftDiff: toggleLeftDiffStub}];
}});
MockInteractions.pressAndReleaseKeyOn(element, 65, 'shift'); // 'A'
assert.isTrue(toggleLeftDiffStub.calledOnce);
+ diffsStub.restore();
});
test('keyboard shortcuts', function() {
@@ -117,7 +136,7 @@
assert.equal(element.selectedIndex, 1);
MockInteractions.pressAndReleaseKeyOn(element, 74); // 'J'
- var showStub = sinon.stub(page, 'show');
+ var showStub = sandbox.stub(page, 'show');
assert.equal(element.selectedIndex, 2);
MockInteractions.pressAndReleaseKeyOn(element, 13); // 'ENTER'
assert(showStub.lastCall.calledWith('/c/42/2/myfile.txt'),
@@ -241,7 +260,7 @@
assert.isFalse(fileAdded.checked);
assert.isTrue(myFile.checked);
- var saveStub = sinon.stub(element, '_saveReviewedState',
+ var saveStub = sandbox.stub(element, '_saveReviewedState',
function() { return Promise.resolve(); });
MockInteractions.tap(commitMsg);
@@ -272,7 +291,7 @@
});
test('diff against dropdown', function(done) {
- var showStub = sinon.stub(page, 'show');
+ var showStub = sandbox.stub(page, 'show');
element.changeNum = '42';
element.patchRange = {
basePatchNum: 'PARENT',
@@ -284,7 +303,7 @@
rev3: {_number: 3},
};
flush(function() {
- var selectEl = element.$$('select');
+ var selectEl = element.$.patchChange;
assert.equal(selectEl.value, 'PARENT');
assert.isTrue(element.$$('option[value="3"]').hasAttribute('disabled'));
selectEl.addEventListener('change', function() {
@@ -313,7 +332,7 @@
var fileRows =
Polymer.dom(element.root).querySelectorAll('.row:not(.header)');
// Prevent diff from making API call.
- var diffStub = sinon.stub(element.diffs[0], 'reload');
+ var diffStub = sandbox.stub(element.diffs[0], 'reload');
var showHideCheck = fileRows[0].querySelector(
'input.show-hide[type="checkbox"]');
assert.isTrue(showHideCheck.checked);
@@ -339,5 +358,50 @@
element.$$('a').getAttribute('href'),
'/c/42/2/foo+bar/my%252Bfile.txt%2525');
});
+
+ test('diff mode correctly toggles the diffs', function() {
+ element._files = [
+ {__path: 'myfile.txt', __expanded: false},
+ ];
+ element.changeNum = '42';
+ element.patchRange = {
+ basePatchNum: 'PARENT',
+ patchNum: '2',
+ };
+ element.selectedIndex = 0;
+ flushAsynchronousOperations();
+ var select = element.$.modeSelect;
+ var diffDisplay = element.diffs[0];
+ element._userPrefs = {diff_view: 'SIDE_BY_SIDE'};
+ assert.equal(element._getDiffViewMode(), 'SIDE_BY_SIDE');
+ assert.equal(element.diffViewMode, 'SIDE_BY_SIDE');
+ assert.equal(diffDisplay.viewMode, 'SIDE_BY_SIDE');
+ element.set('diffViewMode', 'UNIFIED_DIFF');
+ assert.equal(element._getDiffViewMode(), 'UNIFIED_DIFF');
+ assert.equal(diffDisplay.viewMode, 'UNIFIED_DIFF');
+ });
+
+ test('diff mode selector initializes from preferences', function() {
+ var resolvePrefs;
+ var prefsPromise = new Promise(function(resolve) {
+ resolvePrefs = resolve;
+ });
+ sandbox.stub(element, '_getPreferences').returns(prefsPromise);
+
+ // Attach a new gr-file-list so we can intercept the preferences fetch.
+ var view = document.createElement('gr-file-list');
+ var select = view.$.modeSelect;
+ fixture('blank').appendChild(view);
+ flushAsynchronousOperations();
+
+ // At this point the diff mode doesn't yet have the user's preference.
+ assert.equal(select.value, 'SIDE_BY_SIDE');
+
+ // Receive the overriding preference.
+ resolvePrefs({diff_view: 'UNIFIED'});
+ flushAsynchronousOperations();
+ assert.equal(select.value, 'SIDE_BY_SIDE');
+ document.getElementById('blank').restore();
+ });
});
</script>
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js
index 6c73e08..03609c0 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js
@@ -104,7 +104,6 @@
this._setReviewed(true);
}
}.bind(this));
-
if (this.changeViewState.diffMode === null) {
// Initialize with user's diff mode preference. Default to
// SIDE_BY_SIDE in the meantime.
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.html b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.html
index 1eb3f95..566c6a1 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.html
@@ -457,7 +457,6 @@
// We will simulate a user change of the selected mode.
var newMode = 'UNIFIED_DIFF';
-
// Set the actual value of the select, and simulate the change event.
select.value = newMode;
element.fire('change', {}, {node: select});