Add tabs to files area

This allows plugin authors to dynamically add tabs in the same location as the
files list. When there are no dynamically added tabs, the tab header is not
present.

Change-Id: I89170dc84a76e11b430db04acabdaf98b6de4743
This commit is contained in:
Thomas Shafer
2019-02-28 16:50:15 -08:00
parent 0861f7a878
commit 5ec0d74eca
5 changed files with 120 additions and 5 deletions

View File

@@ -149,11 +149,44 @@ The following endpoints are available to plugins.
=== change-list-header
The `change-list-header` extension point adds a header to the change list view.
=== change-list-item-cell
The `change-list-item-cell` extension point adds a cell to the change list item.
In addition to default parameters, the following are available:
* `change`
+
current change of the row, an instance of
link:rest-api-changes.html#change-info[ChangeInfo]
=== change-view-tab-header
The `change-view-tab-header` extension point adds a primary tab to the change
view. This must be used in conjunction with `change-view-tab-content`.
In addition to default parameters, the following are available:
* `change`
+
current change displayed, an instance of
link:rest-api-changes.html#change-info[ChangeInfo]
* `revision`
+
current revision displayed, an instance of
link:rest-api-changes.html#revision-info[RevisionInfo]
=== change-view-tab-content
The `change-view-tab-content` extension point adds primary tab content to
the change view. This must be used in conjunction with `change-view-tab-header`.
In addition to default parameters, the following are available:
* `change`
+
current change displayed, an instance of
link:rest-api-changes.html#change-info[ChangeInfo]
* `revision`
+
current revision displayed, an instance of
link:rest-api-changes.html#revision-info[RevisionInfo]

View File

@@ -519,8 +519,27 @@ limitations under the License.
</div>
</div>
</section>
<section class="patchInfo">
<gr-file-list-header
<template is="dom-if" if="[[_showPrimaryTabs]]">
<paper-tabs id="primaryTabs" on-selected-changed="_handleFileTabChange">
<paper-tab>Files</paper-tab>
<template is="dom-repeat" items="[[_dynamicTabHeaderEndpoints]]"
as="tabHeader">
<paper-tab>
<gr-endpoint-decorator name$="[[tabHeader]]">
<gr-endpoint-param name="change" value="[[_change]]">
</gr-endpoint-param>
<gr-endpoint-param name="revision" value="[[_selectedRevision]]">
</gr-endpoint-param>
</gr-endpoint-decorator>
</paper-tab>
</template>
</paper-tabs>
</template>
<div hidden$="[[!_showFileTabContent]]">
<gr-file-list-header
id="fileListHeader"
account="[[_account]]"
all-patch-sets="[[_allPatchSets]]"
@@ -539,6 +558,7 @@ limitations under the License.
base-patch-num="{{_patchRange.basePatchNum}}"
files-expanded="[[_filesExpanded]]"
diff-prefs-disabled="[[_diffPrefsDisabled]]"
show-title="[[!_showPrimaryTabs]]"
on-open-diff-prefs="_handleOpenDiffPrefs"
on-open-download-dialog="_handleOpenDownloadDialog"
on-open-upload-help-dialog="_handleOpenUploadHelpDialog"
@@ -566,7 +586,18 @@ limitations under the License.
on-files-shown-changed="_setShownFiles"
on-file-action-tap="_handleFileActionTap"
on-reload-drafts="_reloadDraftsWithCallback"></gr-file-list>
</div>
<template is="dom-if" if="[[!_showFileTabContent]]">
<gr-endpoint-decorator name$="[[_selectedFilesTabPluginEndpoint]]">
<gr-endpoint-param name="change" value="[[_change]]">
</gr-endpoint-param>
<gr-endpoint-param name="revision" value="[[_selectedRevision]]">
</gr-endpoint-param>
</gr-endpoint-decorator>
</template>
</section>
<gr-endpoint-decorator name="change-view-integration">
<gr-endpoint-param name="change" value="[[_change]]">
</gr-endpoint-param>
@@ -575,7 +606,7 @@ limitations under the License.
</gr-endpoint-decorator>
<paper-tabs
id="commentTabs"
on-selected-changed="_handleTabChange">
on-selected-changed="_handleCommentTabChange">
<paper-tab class="changeLog">Change Log</paper-tab>
<paper-tab
class="commentThreads">

View File

@@ -253,6 +253,25 @@
type: Boolean,
value: true,
},
_showFileTabContent: {
type: Boolean,
value: true,
},
/** @type {Array<string>} */
_dynamicTabHeaderEndpoints: {
type: Array,
},
_showPrimaryTabs: {
type: Boolean,
computed: '_computeShowPrimaryTabs(_dynamicTabHeaderEndpoints)',
},
/** @type {Array<string>} */
_dynamicTabContentEndpoints: {
type: Array,
},
_selectedFilesTabPluginEndpoint: {
type: String,
},
},
behaviors: [
@@ -310,6 +329,17 @@
this._setDiffViewMode();
});
Gerrit.awaitPluginsLoaded().then(() => {
this._dynamicTabHeaderEndpoints =
Gerrit._endpoints.getDynamicEndpoints('change-view-tab-header');
this._dynamicTabContentEndpoints =
Gerrit._endpoints.getDynamicEndpoints('change-view-tab-content');
if (this._dynamicTabContentEndpoints.length
!== this._dynamicTabHeaderEndpoints.length) {
console.warn('Different number of tab headers and tab content.');
}
});
this.addEventListener('comment-save', this._handleCommentSave.bind(this));
this.addEventListener('comment-refresh', this._reloadDrafts.bind(this));
this.addEventListener('comment-discard',
@@ -368,10 +398,18 @@
}
},
_handleTabChange() {
_handleCommentTabChange() {
this._showMessagesView = this.$.commentTabs.selected === 0;
},
_handleFileTabChange() {
const selectedIndex = this.$$('#primaryTabs').selected;
this._showFileTabContent = selectedIndex === 0;
// Initial tab is the static files list.
this._selectedFilesTabPluginEndpoint =
this._dynamicTabContentEndpoints[selectedIndex - 1];
},
_handleEditCommitMessage(e) {
this._editingCommitMessage = true;
this.$.commitMessageEditor.focusTextarea();
@@ -699,6 +737,8 @@
// Selected has to be set after the paper-tabs are visible because
// the selected underline depends on calculations made by the browser.
this.$.commentTabs.selected = 0;
const primaryTabs = this.$$('#primaryTabs');
if (primaryTabs) primaryTabs.selected = 0;
this.async(() => {
if (this.viewState.scrollTop) {
@@ -821,6 +861,10 @@
this.fire('title-change', {title});
},
_computeShowPrimaryTabs(dynamicTabContentEndpoints) {
return dynamicTabContentEndpoints.length > 0;
},
_computeChangeUrl(change) {
return Gerrit.Nav.getUrlForChange(change);
},

View File

@@ -154,7 +154,10 @@ limitations under the License.
</style>
<div class$="patchInfo-header [[_computeEditModeClass(editMode)]] [[_computePatchInfoClass(patchNum, allPatchSets)]]">
<div class="patchInfo-left">
<h3 class="label">Files</h3>
<template is="dom-if"
if="[[showTitle]]">
<h3 class="label">Files</h3>
</template>
<div class="patchInfoContent">
<gr-patch-range-select
id="rangeSelect"

View File

@@ -81,6 +81,10 @@
type: String,
value: '',
},
showTitle: {
type: Boolean,
value: true,
},
_descriptionReadOnly: {
type: Boolean,
computed: '_computeDescriptionReadOnly(loggedIn, change, account)',