Add ability for plugins to add columns to the change list
Adds registerDynamicPluginEndpoint to Gerrit. Dynamic plugin endpoints are registered to the dynamic prefix. The two supported dynamic endpoints are 'change-list-header' and 'change-list-item-cell'. Change-Id: I0e45f1767e39da004933c48b633fc977724bf863
This commit is contained in:
@@ -177,6 +177,14 @@ See list of supported link:pg-plugin-endpoints.html[endpoints].
|
||||
|
||||
Note: TODO
|
||||
|
||||
=== registerDynamicCustomComponent
|
||||
`plugin.registerDynamicCustomComponent(dynamicEndpointName, opt_moduleName,
|
||||
opt_options)`
|
||||
|
||||
See list of supported link:pg-plugin-endpoints.html[endpoints].
|
||||
|
||||
Note: TODO
|
||||
|
||||
=== registerStyleModule
|
||||
`plugin.registerStyleModule(endpointName, moduleName)`
|
||||
|
||||
|
||||
@@ -141,3 +141,19 @@ link:rest-api-changes.html#change-info[ChangeInfo]
|
||||
+
|
||||
The submit action, including the title and label, an instance of
|
||||
link:rest-api-changes.html#action-info[ActionInfo]
|
||||
|
||||
== Dynamic Plugin endpoints
|
||||
|
||||
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.
|
||||
|
||||
* `change`
|
||||
+
|
||||
current change of the row, an instance of
|
||||
link:rest-api-changes.html#change-info[ChangeInfo]
|
||||
|
||||
@@ -222,6 +222,15 @@ limitations under the License.
|
||||
[[_computeLabelValue(change, labelName)]]
|
||||
</td>
|
||||
</template>
|
||||
<template is="dom-repeat" items="[[_dynamicCellEndpoints]]"
|
||||
as="pluginEndpointName">
|
||||
<td class="cell endpoint">
|
||||
<gr-endpoint-decorator name$="[[pluginEndpointName]]">
|
||||
<gr-endpoint-param name="change" value="[[change]]">
|
||||
</gr-endpoint-param>
|
||||
</gr-endpoint-decorator>
|
||||
</td>
|
||||
</template>
|
||||
</template>
|
||||
<script src="gr-change-list-item.js"></script>
|
||||
</dom-module>
|
||||
|
||||
@@ -57,6 +57,9 @@
|
||||
type: String,
|
||||
computed: '_computeChangeSize(change)',
|
||||
},
|
||||
_dynamicCellEndpoints: {
|
||||
type: Array,
|
||||
},
|
||||
},
|
||||
|
||||
behaviors: [
|
||||
@@ -67,6 +70,13 @@
|
||||
Gerrit.URLEncodingBehavior,
|
||||
],
|
||||
|
||||
attached() {
|
||||
Gerrit.awaitPluginsLoaded().then(() => {
|
||||
this._dynamicCellEndpoints = Gerrit._endpoints.getDynamicEndpoints(
|
||||
'change-list-item-cell');
|
||||
});
|
||||
},
|
||||
|
||||
_computeItemNeedsReview(reviewed) {
|
||||
return !reviewed;
|
||||
},
|
||||
|
||||
@@ -52,6 +52,13 @@ limitations under the License.
|
||||
[[_computeLabelShortcut(labelName)]]
|
||||
</th>
|
||||
</template>
|
||||
<template is="dom-repeat" items="[[_dynamicHeaderEndpoints]]"
|
||||
as="pluginHeader">
|
||||
<th class="endpoint">
|
||||
<gr-endpoint-decorator name$="[[pluginHeader]]">
|
||||
</gr-endpoint-decorator>
|
||||
</th>
|
||||
</template>
|
||||
</tr>
|
||||
<template is="dom-repeat" items="[[sections]]" as="changeSection"
|
||||
index-as="sectionIndex">
|
||||
|
||||
@@ -76,6 +76,9 @@
|
||||
type: Array,
|
||||
computed: '_computeLabelNames(sections)',
|
||||
},
|
||||
_dynamicHeaderEndpoints: {
|
||||
type: Array,
|
||||
},
|
||||
selectedIndex: {
|
||||
type: Number,
|
||||
notify: true,
|
||||
@@ -128,6 +131,13 @@
|
||||
};
|
||||
},
|
||||
|
||||
attached() {
|
||||
Gerrit.awaitPluginsLoaded().then(() => {
|
||||
this._dynamicHeaderEndpoints = Gerrit._endpoints.getDynamicEndpoints(
|
||||
'change-list-header');
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Iron-a11y-keys-behavior catches keyboard events globally. Some keyboard
|
||||
* events must be scoped to a component level (e.g. `enter`) in order to not
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
function GrPluginEndpoints() {
|
||||
this._endpoints = {};
|
||||
this._callbacks = {};
|
||||
this._dynamicPlugins = {};
|
||||
}
|
||||
|
||||
GrPluginEndpoints.prototype.onNewEndpoint = function(endpoint, callback) {
|
||||
@@ -51,8 +52,21 @@
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Register a plugin to an endpoint.
|
||||
*
|
||||
* Dynamic plugins are registered to a specific prefix, such as
|
||||
* 'change-list-header'. These plugins are then fetched by prefix to determine
|
||||
* which endpoints to dynamically add to the page.
|
||||
*/
|
||||
GrPluginEndpoints.prototype.registerModule = function(plugin, endpoint, type,
|
||||
moduleName, domHook) {
|
||||
moduleName, domHook, dynamicEndpoint) {
|
||||
if (dynamicEndpoint) {
|
||||
if (!this._dynamicPlugins[dynamicEndpoint]) {
|
||||
this._dynamicPlugins[dynamicEndpoint] = new Set();
|
||||
}
|
||||
this._dynamicPlugins[dynamicEndpoint].add(endpoint);
|
||||
}
|
||||
if (!this._endpoints[endpoint]) {
|
||||
this._endpoints[endpoint] = [];
|
||||
}
|
||||
@@ -63,6 +77,12 @@
|
||||
}
|
||||
};
|
||||
|
||||
GrPluginEndpoints.prototype.getDynamicEndpoints = function(dynamicEndpoint) {
|
||||
const plugins = this._dynamicPlugins[dynamicEndpoint];
|
||||
if (!plugins) return [];
|
||||
return Array.from(plugins);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get detailed information about modules registered with an extension
|
||||
* endpoint.
|
||||
|
||||
@@ -189,14 +189,36 @@
|
||||
this, endpointName, EndpointType.STYLE, moduleName);
|
||||
};
|
||||
|
||||
/**
|
||||
* Registers an endpoint for the plugin.
|
||||
*/
|
||||
Plugin.prototype.registerCustomComponent = function(
|
||||
endpointName, opt_moduleName, opt_options) {
|
||||
return this._registerCustomComponent(endpointName, opt_moduleName,
|
||||
opt_options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Registers a dynamic endpoint for the plugin.
|
||||
*
|
||||
* Dynamic plugins are registered by specific prefix, such as
|
||||
* 'change-list-header'.
|
||||
*/
|
||||
Plugin.prototype.registerDynamicCustomComponent = function(
|
||||
endpointName, opt_moduleName, opt_options) {
|
||||
const fullEndpointName = `${endpointName}-${this.getPluginName()}`;
|
||||
return this._registerCustomComponent(fullEndpointName, opt_moduleName,
|
||||
opt_options, endpointName);
|
||||
};
|
||||
|
||||
Plugin.prototype._registerCustomComponent = function(
|
||||
endpointName, opt_moduleName, opt_options, dynamicEndpoint) {
|
||||
const type = opt_options && opt_options.replace ?
|
||||
EndpointType.REPLACE : EndpointType.DECORATE;
|
||||
const hook = this._domHooks.getDomHook(endpointName, opt_moduleName);
|
||||
const moduleName = opt_moduleName || hook.getModuleName();
|
||||
Gerrit._endpoints.registerModule(
|
||||
this, endpointName, type, moduleName, hook);
|
||||
this, endpointName, type, moduleName, hook, dynamicEndpoint);
|
||||
return hook.getPublicAPI();
|
||||
};
|
||||
|
||||
|
||||
@@ -55,8 +55,8 @@ limitations under the License.
|
||||
.cell {
|
||||
vertical-align: middle;
|
||||
}
|
||||
th:not(.label),
|
||||
.cell:not(.label) {
|
||||
th:not(.label):not(.endpoint),
|
||||
.cell:not(.label):not(.endpoint) {
|
||||
padding-right: 8px;
|
||||
}
|
||||
th.label {
|
||||
@@ -128,8 +128,10 @@ limitations under the License.
|
||||
.star {
|
||||
width: 30px;
|
||||
}
|
||||
.label {
|
||||
.label, .endpoint {
|
||||
border-left: 1px solid var(--border-color);
|
||||
}
|
||||
.label {
|
||||
text-align: center;
|
||||
width: 3rem;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user