Show blame in diff
With this change a blame column is added to the left side of diff
tables. The column is empty and hidden until blame is loaded. A button
is added to the change view to trigger a load of the blame for that
diff, as well as a unload it if already loaded. In this stage, the blame
information is non-interactive and only displays the SHA, date and
commit author.
Feature: Issue 6075
Change-Id: Ifcb951265d0e6339094e6b7c9574ec9c69e60b51
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.html b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.html
index f67abcc..008852e 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.html
@@ -159,6 +159,12 @@
.editLoaded .hideOnEdit {
display: none;
}
+ .blameLoader {
+ display: none;
+ }
+ .blameLoader.show {
+ display: inline;
+ }
@media screen and (max-width: 50em) {
header {
padding: .5em var(--default-horizontal-margin);
@@ -312,6 +318,13 @@
on-tap="_handlePrefsTap">Preferences</gr-button>
</span>
</span>
+ <span class$="blameLoader [[_computeBlameLoaderClass(_isImageDiff, _isBlameSupported)]]">
+ <span class="separator">/</span>
+ <gr-button
+ link
+ disabled="[[_isBlameLoading]]"
+ on-tap="_toggleBlame">[[_computeBlameToggleLabel(_isBlameLoaded, _isBlameLoading)]]</gr-button>
+ </span>
</div>
</div>
<div class="fileNav mobile">
@@ -340,6 +353,7 @@
project-config="[[_projectConfig]]"
project-name="[[_change.project]]"
view-mode="[[_diffMode]]"
+ is-blame-loaded="{{_isBlameLoaded}}"
on-line-selected="_onLineSelected">
</gr-diff>
<gr-diff-preferences
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 3bb373f..fbd845a 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
@@ -18,6 +18,8 @@
const MERGE_LIST_PATH = '/MERGE_LIST';
const ERR_REVIEW_STATUS = 'Couldn’t change file review status.';
+ const MSG_LOADING_BLAME = 'Loading blame...';
+ const MSG_LOADED_BLAME = 'Blame loaded';
const PARENT = 'PARENT';
@@ -125,6 +127,16 @@
type: Boolean,
computed: '_computeEditLoaded(_patchRange.*)',
},
+
+ _isBlameSupported: {
+ type: Boolean,
+ value: false,
+ },
+ _isBlameLoaded: Boolean,
+ _isBlameLoading: {
+ type: Boolean,
+ value: false,
+ },
},
behaviors: [
@@ -160,6 +172,10 @@
this._loggedIn = loggedIn;
});
+ this.$.restAPI.getConfig().then(config => {
+ this._isBlameSupported = config.change.allow_blame;
+ });
+
this.$.cursor.push('diffs', this.$.diff);
},
@@ -805,5 +821,36 @@
_computeContainerClass(editLoaded) {
return editLoaded ? 'editLoaded' : '';
},
+
+ _computeBlameToggleLabel(loaded, loading) {
+ if (loaded) { return 'Hide blame'; }
+ return 'Show blame';
+ },
+
+ /**
+ * Load and display blame information if it has not already been loaded.
+ * Otherwise hide it.
+ */
+ _toggleBlame() {
+ if (this._isBlameLoaded) {
+ this.$.diff.clearBlame();
+ return;
+ }
+
+ this._isBlameLoading = true;
+ this.fire('show-alert', {message: MSG_LOADING_BLAME});
+ this.$.diff.loadBlame()
+ .then(() => {
+ this._isBlameLoading = false;
+ this.fire('show-alert', {message: MSG_LOADED_BLAME});
+ })
+ .catch(() => {
+ this._isBlameLoading = false;
+ });
+ },
+
+ _computeBlameLoaderClass(isImageDiff, supported) {
+ return !isImageDiff && supported ? 'show' : '';
+ },
});
})();