PolyGerrit and plugins

850 views
Skip to first unread message

Sven Selberg

unread,
Dec 6, 2017, 4:09:14 AM12/6/17
to Repo and Gerrit Discussion
Hi,

With Gerrit 3.0 approaching, without GWT UI, the need to rewrite plugins with UI elements to work with PolyGerrit is becoming quite pressing. We have some such plugins that are quite heavily used by our developers and not being able to provide these functionalities in PolyGerrit is more or less a blocker for us to upgrade to a Gerrit version without GWT UI.

I have been trying to find some documentation or plugin example on how to write e.g. a button - REST API endpoint plugin with PolyGerrit. And I have come up short. T
This was previously achieved by implementing UiAction and RestModicyView in the backend which then added the plugin to the list of UI Actions that where sent to the client that handled them dynamically in the uI. A very comfortable way for to get a button in the UI without having to take changes in the UI into consideration since the UI could decide for itself where to put it.
In master Viktar D has made some patches that makes a GWT style UiAction plugin work in PolyGerrit by adding a small javascript plugin hack (thanks Viktar). However the API he introduced is marked as deprecated which I suppose makes it a temporary solution. Furthermore this approach does not add a button to the change screen but rather adds it to the "more" menu which is unfortunate for functions that are used regularly (in the same class as "submit" and "rebase", consider them being in the "more" menu instead...).
This is a very common use-case and we have a couple of company specific plugins that follows this structure  (and I am certain we are not the only ones), so I'm wondering:
What is the recommended approach for rewriting such a plugin to work with PolyGerrit? And how would I make the button end up next to "submit" et.al. on the change screen instead of in the "more" menu?

Would it be feasible to rewrite the current handling of UiActions in PolyGerrit to a more general approach where the collection of UiActions will populate buttons in the UI dynamically?
(Let me first confess that I have only skimmed through the code section in PolyGerrit that handles UiActions so there are most likely some pitfalls and caveats I haven't identified) One approach could be that the UIActions themselves provide their own priority and placement, which would make the task of the client code only to place them in the correct order in the correct location. You could even combine this with prioritizing a hardcoded set of UiActions in the UI first and populate the rest with respect to the priority they provide themselves. You could also let the UiAction provide information about which REST endpoint to call onAction.

For plugins with more advanced UI interactions, is there, or will there be, a designated plugin-area in the UI (as is the case with GWT UI) or is the implementer of the plugin left to hook in to the UI where he/she see fit?

BR
Sven

David Shevitz

unread,
Dec 6, 2017, 11:11:01 AM12/6/17
to Sven Selberg, Repo and Gerrit Discussion
I know very little about how plugins work, but I would be happy to help craft any documentation that can help developers in this effort. Please feel free to keep me in the loop!

--
--
To unsubscribe, email repo-discuss+unsubscribe@googlegroups.com
More info at http://groups.google.com/group/repo-discuss?hl=en

---
You received this message because you are subscribed to the Google Groups "Repo and Gerrit Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to repo-discuss+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Dave Shevitz
Technical Writer

Viktar Donich

unread,
Dec 6, 2017, 2:10:42 PM12/6/17
to Repo and Gerrit Discussion
Hi Sven,

Thanks for taking time looking into this! Really appreciate provided feedback.

First things first, the best documentation that exists for PolyGerrit plugins is located here. It's far from being complete, unfortunately - work is in progress.

I see your point of convenience using UiAction for a trivial task of adding a button to the change menu. But clearly, this isn't and probably shouldn't be the only way for modifying UI, since there are number of downsides. For example this requires formalizing in the REST API all the UI aspects. Specifically, in the GWT UI all change actions were rendered in same way (lots of buttons), while in PolyGerrit there are primary and secondary, not to mention the `More` menu. Surely, this could be added as properties to the change actions, but this clearly would complicate things for PolyGerrit maintainers if making a UI change would trigger cascading changes to REST API (and that would require updating documentation, acceptance tests, let alone plugin considerations).

That's why one of the goals for PolyGerrit plugin API is to promote writing and using JS-based plugin API instead of Java-based one.

Practically speaking, UiActions hopefully can be easily migrated to plugin.changeActions() API. This would mean that UI manipulations would need to be moved into .js/.html files.

Let me know if that's anything that makes sense or if there's any scenario where this can cause problems, and I'll be happy to address all your concerns.

For plugins with more advanced UI interactions, is there, or will there be, a designated plugin-area in the UI (as is the case with GWT UI) or is the implementer of the plugin left to hook in to the UI where he/she see fit?

(this is a short recap of PG plugin dev guide)

Ideally, all UI modifications would be expressed as a high-level API, such as plugin.changeActions() mentioned above. This would make it easier to for plugin authors to use. Also this would simplify maintenance and migrations for future versions of PolyGerrit.

However, often times it's tricky to design one API that fits all, and for such cases low-level DOM API can be used. PolyGerrit plugin API provides DOM insertion/decoration points, accessible via `plugin.hook('hook-name-here')` API.
This concept is similar to self.panel() but is intended to be as close to DOM as possible, in order to be as general as possible.

Here's an example how high-level plugin API method `addReplyTextChangedCallback()` uses low-level API to capture reply dialog text change:


Adding such extension points are also trivial (example change), so the proposed procedure for adding new plugin APIs hopefully could look like this:
  • tracking bug is filed describing the requirements
  • extension point is added with params
  • plugin author experiments using plugin.hook() method and stabilizes requirements for high-level API
  • high-level API is implemented, covered with tests, documented, etc
  • and plugin author replaces plugin.hook() with the high level API
  • plugin author gets long-term support and PolyGerrit devs get well defined requirements to make maintenance/upgrades easier
I hope that addresses at least some of your concerns, sorry if I missed anything - let's keep talking, this is very good topic and it's very important for us.

WBR, VD.

Sven Selberg

unread,
Dec 7, 2017, 5:06:35 AM12/7/17
to Repo and Gerrit Discussion

Thanks for the extensive reply Viktar!

I agree, this is an important topic and I am very grateful for the work you and others have done so far to assist plugin development in PG.

Just to clarify inline comments below, they reflect two separate lines of argument:
- My opinion that the backend should define priority of Actions (primary, secondary and misc (or "more" if you wish)) , together with an argument for why it should be possible to specify such an action in the backend (through backend plugins) and get it rendered in the UI in a way the frontend see fit given the priority of the action.

- A separate discussion on how to help users to write frontend plugins using the PG plugin API.

BR
Sven

On Wednesday, December 6, 2017 at 8:10:42 PM UTC+1, Viktar Donich wrote:
Hi Sven,

Thanks for taking time looking into this! Really appreciate provided feedback.

First things first, the best documentation that exists for PolyGerrit plugins is located here. It's far from being complete, unfortunately - work is in progress.

Yeah, I found that but as you say, it's a work in progress. Perhaps I'm not the best canary here, but from those instructions I couldn't decipher a way to add a button in the change screen header without using the DOM API (but I felt a more stable solution would be preferable).
 

I see your point of convenience using UiAction for a trivial task of adding a button to the change menu. But clearly, this isn't and probably shouldn't be the only way for modifying UI,

Agreed, it shouldn't be the only way, but to be fair that was not what i suggested. Furthermore I concede that the "special case" aspect of UiActions doesn't speak to it's advantage. That being said, the special case of button/REST API point should be the most common one (that's why the UiAction was extracted as a special case in the GWT UI). My most personal reason for advocating a way to make it easy to implement an action (a button in the UI connected to a REST API point) is exactly that, it's the most common use case and it would be sweet if you could implement it without having to write some hundred lines of front-end boilerplate code.

since there are number of downsides. For example this requires formalizing in the REST API all the UI aspects. Specifically, in the GWT UI all change actions were rendered in same way (lots of buttons), while in PolyGerrit there are primary and secondary, not to mention the `More` menu.

I think for most users it would be enough if you could specify if the button would be in the Change screen header, the "more" menu or the "secondary" position (a term which I use recognizing that I don't know how a "secondary" action is defined if it's not in the "more" menu (which is a topic for another discussion)),
Just to be clear, I'm not advocating to put all actions as buttons in the change screen header. And the plethora of buttons was caused by the fact that there was only one place for ui-actions to go (so to speak).
 
Surely, this could be added as properties to the change actions, but this clearly would complicate things for PolyGerrit maintainers if making a UI change would trigger cascading changes to REST API (and that would require updating documentation, acceptance tests, let alone plugin considerations).

I can't say much about the life of a PolyGerrit maintainer since I'm not one myself (though I'm willing to contribute to the best of my abilities) but from my point of view it needn't complicate things if all the REST API says is "Here's a primary action named "Press me", when pressed call this REST endpoint otherwise do with it what you please", which, from my rummaging through the part of the PolyGerrit code that handles such things, is more or less what happens today. The main difference is that the "primary", "secondary", "more menu" state is hard coded in the UI which IMO is strange, the importance (or prioritization if you will) should be something that is determined in the backend and all the frontend should care about is how it want's to handle that prioritization "The primary actions goes here and they should be displayed as such, and the secondary actions goes here and they should be displayed as such". I could go as far as to let the frontend be aware of different, separate, actions so that it can prioritize within e.g. the "primary" group "Is there an action named "submit"? In that case it should be the leftmost "primary" action" and when all named actions are sorted just fill in the rest to the right of those. There needn't be much concern regarding what the end result would be (if there are 20 actions in the list implemented by various plugins), it is the responsibility of the individual Gerrit admins to assess how they want to handle the eventual UI mess that would be the result of adding "too many" "primary" actions through plugins. 

So if there is a UI change, in most cases it wouldn't have to care about the backend, unless there's a need to add e.g. a "tertiary" action but, as I have stated my opinion earlier, that state should be reflected in the backend and the UI should just handle that third state (or fourth if you count the "more" menu), not define it.
 

That's why one of the goals for PolyGerrit plugin API is to promote writing and using JS-based plugin API instead of Java-based one.

Practically speaking, UiActions hopefully can be easily migrated to plugin.changeActions() API. This would mean that UI manipulations would need to be moved into .js/.html files.

Let me know if that's anything that makes sense or if there's any scenario where this can cause problems, and I'll be happy to address all your concerns.

For plugins with more advanced UI interactions, is there, or will there be, a designated plugin-area in the UI (as is the case with GWT UI) or is the implementer of the plugin left to hook in to the UI where he/she see fit?

(this is a short recap of PG plugin dev guide)

Ideally, all UI modifications would be expressed as a high-level API, such as plugin.changeActions() mentioned above. This would make it easier to for plugin authors to use. Also this would simplify maintenance and migrations for future versions of PolyGerrit.

However, often times it's tricky to design one API that fits all, and for such cases low-level DOM API can be used. PolyGerrit plugin API provides DOM insertion/decoration points, accessible via `plugin.hook('hook-name-here')` API.
This concept is similar to self.panel() but is intended to be as close to DOM as possible, in order to be as general as possible.

I believe that a couple of areas where PG plugins can add elements and a couple of high level API points that covers the most common use-cases such as plugin.changeActions(), plugin.revisionActions(), goes a long way.
If you want to do accomplish something above and beyond you should be prepared to either use the DOM API or implement and argue for a plugin API point that supports that use case.
 

Here's an example how high-level plugin API method `addReplyTextChangedCallback()` uses low-level API to capture reply dialog text change:


Adding such extension points are also trivial (example change), so the proposed procedure for adding new plugin APIs hopefully could look like this:
  • tracking bug is filed describing the requirements
  • extension point is added with params
  • plugin author experiments using plugin.hook() method and stabilizes requirements for high-level API
  • high-level API is implemented, covered with tests, documented, etc
  • and plugin author replaces plugin.hook() with the high level API
I would like to add "add an example plugin using the API in plugins/example".
For Gerrit this is a vital part of the plugin API endpoint implementation and such an example plugin is extremely valuable for those who want to use the endpoint. So I suggest that PolyGerrit developers also adopt this habit. This is what I (I admit somewhat obscurely) requested in my previous post in the shape of "What is the recommended approach for rewriting such a plugin to work with PolyGerrit? And how would I make the button end up next to "submit" et.al. on the change screen instead of in the "more" menu?".
Compare the example I uploaded for the UiAction/PG hybrid plugin API you introduced:

Viktar Donich

unread,
Dec 12, 2017, 3:41:02 PM12/12/17
to Repo and Gerrit Discussion
(answers inline)


On Thursday, December 7, 2017 at 2:06:35 AM UTC-8, Sven Selberg wrote:
 
I see your point of convenience using UiAction for a trivial task of adding a button to the change menu. But clearly, this isn't and probably shouldn't be the only way for modifying UI,

Agreed, it shouldn't be the only way, but to be fair that was not what i suggested. Furthermore I concede that the "special case" aspect of UiActions doesn't speak to it's advantage. That being said, the special case of button/REST API point should be the most common one (that's why the UiAction was extracted as a special case in the GWT UI). My most personal reason for advocating a way to make it easy to implement an action (a button in the UI connected to a REST API point) is exactly that, it's the most common use case and it would be sweet if you could implement it without having to write some hundred lines of front-end boilerplate code.

I think hundred lines of front-end code is an overestimation. Maybe a better documentation would make this a non-issue? 

Here's a complete minimal sample for adding a change action in the client code:

<dom-module id="my-plugin">

 <script>

   Gerrit.install(plugin => {

       plugin.on('showchange', () => {

           const changeActions = plugin.changeActions();

           const key = changeActions.add('change', 'kaboom');

           changeActions.addTapListener(key, () => {

               plugin.restApi().get('/config/server/version').then(console.log);

           });

       });

   });

 </script>

</dom-module>


changeActions() the oldest API existing in PolyGerrit, and clearly it can be improved. And it wasn't documented since most of its users are front-end developers who essentially implemented it or reviewed the implementation.

Since adding a UI action is a fairly common thing, this clearly could be wrapped into a high-level API so the final script code would simply be the following:

const opts = {overflow: false, primary: true};

plugin.changeActions().addUIAction('kaboom', () => {

   plugin.restApi().get('/config/server/version').then(console.log);

}, opts);


This isn't hard to do, so it essentially boils down to the philosophy of the API.

On the other hand, it doesn't seem that adding overflow and primary properties to extensions.webui.UiAction is complex, too.
If that's the only thing that's needed, I see no harm in that.

My main concern is for this to become a slippery slope - if there's a way for modifying UI from server side through REST API responses - and that's how UiAction works under the hood - there might be motivation to add more support for files in com.google.gerrit.extensions.webui package later. Which I don't believe is the best long-term strategy, and that's why I'm trying to resolve this question on philosophical level first.
  
Surely, this could be added as properties to the change actions, but this clearly would complicate things for PolyGerrit maintainers if making a UI change would trigger cascading changes to REST API (and that would require updating documentation, acceptance tests, let alone plugin considerations).

I can't say much about the life of a PolyGerrit maintainer since I'm not one myself (though I'm willing to contribute to the best of my abilities) but from my point of view it needn't complicate things if all the REST API says is "Here's a primary action named "Press me", when pressed call this REST endpoint otherwise do with it what you please", which, from my rummaging through the part of the PolyGerrit code that handles such things, is more or less what happens today.

Yes, but even in GWT UI there is a special handling of that data. Backed provides REST API response with change and revision actions, including ones added by plugins, and some of those actions end up as buttons:


For example, looks like there's no way to omit Abandon, for what it's worth.

The main difference is that the "primary", "secondary", "more menu" state is hard coded in the UI which IMO is strange, the importance (or prioritization if you will) should be something that is determined in the backend and all the frontend should care about is how it want's to handle that prioritization "The primary actions goes here and they should be displayed as such, and the secondary actions goes here and they should be displayed as such". I could go as far as to let the frontend be aware of different, separate, actions so that it can prioritize within e.g. the "primary" group "Is there an action named "submit"? In that case it should be the leftmost "primary" action" and when all named actions are sorted just fill in the rest to the right of those. There needn't be much concern regarding what the end result would be (if there are 20 actions in the list implemented by various plugins), it is the responsibility of the individual Gerrit admins to assess how they want to handle the eventual UI mess that would be the result of adding "too many" "primary" actions through plugins. 

So you're saying that it's the Gerrit admins who carry the burden of UI to be presentable to user in the end. I think that's fair, but even in this case it would be easier for admins to file feature requests against PolyGerrit rather than chasing plugin developers.

Overall, I agree with what you're saying. That's essentially something that PolyGerrit generally tries to achieve as well, based on data from various sources. The decisions that were made in this field are best of our knowledge and we're constantly improving them based on user feedback, various UX studies, design iterations, etc. Some of that is hardcoded, for example reply button size and position. Some of that is available for configuration, some isn't, for various reasons.
 
So if there is a UI change, in most cases it wouldn't have to care about the backend, unless there's a need to add e.g. a "tertiary" action but, as I have stated my opinion earlier, that state should be reflected in the backend and the UI should just handle that third state (or fourth if you count the "more" menu), not define it. 

I see your point, but I afraid I can't fully agree with it on a general basis. And as I said above - if that only relates to UiAction and overflow menu - I think this isn't a problem to do.

However, I can easily imagine situation when plugin provides an action that should not be added to More menu, but PolyGerrit does that anyway because number of buttons is too large, or they has too much text in them. 
Another scenario might be that the screen size is too narrow, for example it's a mobile device. In any case, this decision has nothing to do with backend - I don't think it would be beneficial for UiAction to have branching logic based on client's platform, aspect ratio, etc.

Just as a mental exercise, please try to imagine REST API for Gerrit's non-existent Android application. I'm certain, such API would have even less authority over application appearance.
 
I believe that a couple of areas where PG plugins can add elements and a couple of high level API points that covers the most common
use-cases such as plugin.changeActions(), plugin.revisionActions(), goes a long way.
 
If you want to do accomplish something above and beyond you should be prepared to either use the DOM API or implement and argue for a plugin API point that supports that use case. 
 
Yes! I think we agree here. If you have any specific high-level API ideas, please file an issue using this template:


If the API is reasonable - like changeActions() - I don't think anyone will argue about it.
  • tracking bug is filed describing the requirements
  • extension point is added with params
  • plugin author experiments using plugin.hook() method and stabilizes requirements for high-level API
  • high-level API is implemented, covered with tests, documented, etc
  • and plugin author replaces plugin.hook() with the high level API
I would like to add "add an example plugin using the API in plugins/example".

Great point! We're not yet at the point when stackoverflow.com is of any help, so providing examples is clearly a big plus.

Sven Selberg

unread,
Dec 22, 2017, 6:59:50 AM12/22/17
to Repo and Gerrit Discussion
Thank you again Viktar and sorry for the late reply

I think hundred lines of front-end code is an overestimation. Maybe a better documentation would make this a non-issue? 
 
Here's a complete minimal sample for adding a change action in the client code:

<dom-module id="my-plugin">

 <script>

   Gerrit.install(plugin => {

       plugin.on('showchange', () => {

           const changeActions = plugin.changeActions();

           const key = changeActions.add('change', 'kaboom');

           changeActions.addTapListener(key, () => {

               plugin.restApi().get('/config/server/version').then(console.log);

           });

       });

   });

 </script>

</dom-module>


That is a great example of how to add a generic button in the Change Screen Header with less than 100 lines of code.
But it is not an example of how to convert a UiAction type plugin to a PolyGerrit compliant (for lack of a better word) one without using plugin.deprecated.install.
A default example of how to do that would be extremely helpful, and since surely it was considered how such a thing would be accomplished it would be enormously appreciated if someone versed in PolyGerrit could add such an example to plugins/examples with calling plugin REST API points and reloading the Change Screen without additional REST API calls if the reply from the REST API is a brand new ChangeInfo etc.
 

changeActions() the oldest API existing in PolyGerrit, and clearly it can be improved. And it wasn't documented since most of its users are front-end developers who essentially implemented it or reviewed the implementation.

Since adding a UI action is a fairly common thing, this clearly could be wrapped into a high-level API so the final script code would simply be the following:

const opts = {overflow: false, primary: true};

plugin.changeActions().addUIAction('kaboom', () => {

   plugin.restApi().get('/config/server/version').then(console.log);

}, opts);


This isn't hard to do, so it essentially boils down to the philosophy of the API.

On the other hand, it doesn't seem that adding overflow and primary properties to extensions.webui.UiAction is complex, too.
If that's the only thing that's needed, I see no harm in that.

My main concern is for this to become a slippery slope - if there's a way for modifying UI from server side through REST API responses - and that's how UiAction works under the hood - there might be motivation to add more support for files in com.google.gerrit.extensions.webui package later. Which I don't believe is the best long-term strategy, and that's why I'm trying to resolve this question on philosophical level first.

I share your concerns regarding the slippery slope. Special cases tend to add up, and it would probably be better to have one approach to rule them all.

  
Surely, this could be added as properties to the change actions, but this clearly would complicate things for PolyGerrit maintainers if making a UI change would trigger cascading changes to REST API (and that would require updating documentation, acceptance tests, let alone plugin considerations).

I can't say much about the life of a PolyGerrit maintainer since I'm not one myself (though I'm willing to contribute to the best of my abilities) but from my point of view it needn't complicate things if all the REST API says is "Here's a primary action named "Press me", when pressed call this REST endpoint otherwise do with it what you please", which, from my rummaging through the part of the PolyGerrit code that handles such things, is more or less what happens today.

Yes, but even in GWT UI there is a special handling of that data. Backed provides REST API response with change and revision actions, including ones added by plugins, and some of those actions end up as buttons:


For example, looks like there's no way to omit Abandon, for what it's worth.

The main difference is that the "primary", "secondary", "more menu" state is hard coded in the UI which IMO is strange, the importance (or prioritization if you will) should be something that is determined in the backend and all the frontend should care about is how it want's to handle that prioritization "The primary actions goes here and they should be displayed as such, and the secondary actions goes here and they should be displayed as such". I could go as far as to let the frontend be aware of different, separate, actions so that it can prioritize within e.g. the "primary" group "Is there an action named "submit"? In that case it should be the leftmost "primary" action" and when all named actions are sorted just fill in the rest to the right of those. There needn't be much concern regarding what the end result would be (if there are 20 actions in the list implemented by various plugins), it is the responsibility of the individual Gerrit admins to assess how they want to handle the eventual UI mess that would be the result of adding "too many" "primary" actions through plugins. 

So you're saying that it's the Gerrit admins who carry the burden of UI to be presentable to user in the end. I think that's fair, but even in this case it would be easier for admins to file feature requests against PolyGerrit rather than chasing plugin developers.

Overall, I agree with what you're saying. That's essentially something that PolyGerrit generally tries to achieve as well, based on data from various sources. The decisions that were made in this field are best of our knowledge and we're constantly improving them based on user feedback, various UX studies, design iterations, etc. Some of that is hardcoded, for example reply button size and position. Some of that is available for configuration, some isn't, for various reasons.
 
So if there is a UI change, in most cases it wouldn't have to care about the backend, unless there's a need to add e.g. a "tertiary" action but, as I have stated my opinion earlier, that state should be reflected in the backend and the UI should just handle that third state (or fourth if you count the "more" menu), not define it. 

I see your point, but I afraid I can't fully agree with it on a general basis. And as I said above - if that only relates to UiAction and overflow menu - I think this isn't a problem to do.

However, I can easily imagine situation when plugin provides an action that should not be added to More menu, but PolyGerrit does that anyway because number of buttons is too large, or they has too much text in them. 
Another scenario might be that the screen size is too narrow, for example it's a mobile device. In any case, this decision has nothing to do with backend - I don't think it would be beneficial for UiAction to have branching logic based on client's platform, aspect ratio, etc.

Yes, but what I'm saying is that you could give the Action a priority in the back-end. Let's say a brand new production critical action is implemented as a UiAction in a plugin and it "needs" not to be hidden in the "more" menu. All the same it's a best effort, if someone is using a screen where there's no room for the button then reality wins. If this is unacceptable then you have a special case where you have to step out of the UiAction comfort zone and solve it elsewhere.
 

Just as a mental exercise, please try to imagine REST API for Gerrit's non-existent Android application. I'm certain, such API would have even less authority over application appearance.

As I tried to relay above, I do not argue that the back-end should have _any_ application appearance authority at all apart from description, it should just give the UI a chance to order the Actions on the priority that the back-end gives them. The android application is as free as the web-app to do with it what it pleases, preferably making some best effort attempt to display that prioritization to the best of its abilities.
 
I believe that a couple of areas where PG plugins can add elements and a couple of high level API points that covers the most common
use-cases such as plugin.changeActions(), plugin.revisionActions(), goes a long way.
 
If you want to do accomplish something above and beyond you should be prepared to either use the DOM API or implement and argue for a plugin API point that supports that use case. 
 
Yes! I think we agree here. If you have any specific high-level API ideas, please file an issue using this template:


If the API is reasonable - like changeActions() - I don't think anyone will argue about it.
  • tracking bug is filed describing the requirements
  • extension point is added with params
  • plugin author experiments using plugin.hook() method and stabilizes requirements for high-level API
  • high-level API is implemented, covered with tests, documented, etc
  • and plugin author replaces plugin.hook() with the high level API
I would like to add "add an example plugin using the API in plugins/example".

Great point! We're not yet at the point when stackoverflow.com is of any help, so providing examples is clearly a big plus.
 
Examples in the Gerrit documentation or plugins/example are extremely valuable to get started quickly and we shouldn't rely on developers supplying them on stackoverflow. IMO stackoverflow could be a valuable resource when you want to solve any problems you encounter once you try to expand your "Hello World" example, since then you are in a more general realm.

Viktar Donich

unread,
Jan 5, 2018, 2:49:46 PM1/5/18
to Repo and Gerrit Discussion


On Friday, December 22, 2017 at 3:59:50 AM UTC-8, Sven Selberg wrote:

A default example of how to do that would be extremely helpful, and since surely it was considered how such a thing would be accomplished it would be enormously appreciated if someone versed in PolyGerrit could add such an example to plugins/examples with calling plugin REST API points and reloading the Change Screen without additional REST API calls if the reply from the REST API is a brand new ChangeInfo etc.

Fair point, filed this as a Monorail issue https://bugs.chromium.org/p/gerrit/issues/detail?id=8093

 
 

changeActions() the oldest API existing in PolyGerrit, and clearly it can be improved. And it wasn't documented since most of its users are front-end developers who essentially implemented it or reviewed the implementation.

Since adding a UI action is a fairly common thing, this clearly could be wrapped into a high-level API so the final script code would simply be the following:

const opts = {overflow: false, primary: true};

plugin.changeActions().addUIAction('kaboom', () => {

   plugin.restApi().get('/config/server/version').then(console.log);

}, opts);


This isn't hard to do, so it essentially boils down to the philosophy of the API.

On the other hand, it doesn't seem that adding overflow and primary properties to extensions.webui.UiAction is complex, too.
If that's the only thing that's needed, I see no harm in that.

My main concern is for this to become a slippery slope - if there's a way for modifying UI from server side through REST API responses - and that's how UiAction works under the hood - there might be motivation to add more support for files in com.google.gerrit.extensions.webui package later. Which I don't believe is the best long-term strategy, and that's why I'm trying to resolve this question on philosophical level first.

I share your concerns regarding the slippery slope. Special cases tend to add up, and it would probably be better to have one approach to rule them all.

  
Surely, this could be added as properties to the change actions, but this clearly would complicate things for PolyGerrit maintainers if making a UI change would trigger cascading changes to REST API (and that would require updating documentation, acceptance tests, let alone plugin considerations).

I can't say much about the life of a PolyGerrit maintainer since I'm not one myself (though I'm willing to contribute to the best of my abilities) but from my point of view it needn't complicate things if all the REST API says is "Here's a primary action named "Press me", when pressed call this REST endpoint otherwise do with it what you please", which, from my rummaging through the part of the PolyGerrit code that handles such things, is more or less what happens today.

Yes, but even in GWT UI there is a special handling of that data. Backed provides REST API response with change and revision actions, including ones added by plugins, and some of those actions end up as buttons:


For example, looks like there's no way to omit Abandon, for what it's worth.

The main difference is that the "primary", "secondary", "more menu" state is hard coded in the UI which IMO is strange, the importance (or prioritization if you will) should be something that is determined in the backend and all the frontend should care about is how it want's to handle that prioritization "The primary actions goes here and they should be displayed as such, and the secondary actions goes here and they should be displayed as such". I could go as far as to let the frontend be aware of different, separate, actions so that it can prioritize within e.g. the "primary" group "Is there an action named "submit"? In that case it should be the leftmost "primary" action" and when all named actions are sorted just fill in the rest to the right of those. There needn't be much concern regarding what the end result would be (if there are 20 actions in the list implemented by various plugins), it is the responsibility of the individual Gerrit admins to assess how they want to handle the eventual UI mess that would be the result of adding "too many" "primary" actions through plugins. 

So you're saying that it's the Gerrit admins who carry the burden of UI to be presentable to user in the end. I think that's fair, but even in this case it would be easier for admins to file feature requests against PolyGerrit rather than chasing plugin developers.

Overall, I agree with what you're saying. That's essentially something that PolyGerrit generally tries to achieve as well, based on data from various sources. The decisions that were made in this field are best of our knowledge and we're constantly improving them based on user feedback, various UX studies, design iterations, etc. Some of that is hardcoded, for example reply button size and position. Some of that is available for configuration, some isn't, for various reasons.
 
So if there is a UI change, in most cases it wouldn't have to care about the backend, unless there's a need to add e.g. a "tertiary" action but, as I have stated my opinion earlier, that state should be reflected in the backend and the UI should just handle that third state (or fourth if you count the "more" menu), not define it. 

I see your point, but I afraid I can't fully agree with it on a general basis. And as I said above - if that only relates to UiAction and overflow menu - I think this isn't a problem to do.

However, I can easily imagine situation when plugin provides an action that should not be added to More menu, but PolyGerrit does that anyway because number of buttons is too large, or they has too much text in them. 
Another scenario might be that the screen size is too narrow, for example it's a mobile device. In any case, this decision has nothing to do with backend - I don't think it would be beneficial for UiAction to have branching logic based on client's platform, aspect ratio, etc.

Yes, but what I'm saying is that you could give the Action a priority in the back-end. Let's say a brand new production critical action is implemented as a UiAction in a plugin and it "needs" not to be hidden in the "more" menu. All the same it's a best effort, if someone is using a screen where there's no room for the button then reality wins. If this is unacceptable then you have a special case where you have to step out of the UiAction comfort zone and solve it elsewhere.

That's a fair point, but again, the decision will be made by the UI, which under certain circumstances may heavily discount plugin-provided actions.
On the other hand, if the action is managed by UI, it will have more options to ensure the required feature is provided, one way or another - it will have access to the screen resolution, for example, and may use different mechanisms for achieving the goal. For example, it may add different customizations for different browsers (mobile). Adding such functionality to UiAction is probably not reasonable.

In any case, I feel this is a philosophical issue on server-side data-driven approach versus client code that uses client API, and it's definitely ok to have different points of view.

I hope augmenting UiAction to have PolyGerrit-specific properties (e.g. more menu location) would solve this in the short-term.

Just as a mental exercise, please try to imagine REST API for Gerrit's non-existent Android application. I'm certain, such API would have even less authority over application appearance.

As I tried to relay above, I do not argue that the back-end should have _any_ application appearance authority at all apart from description, it should just give the UI a chance to order the Actions on the priority that the back-end gives them.

Right, but the android application may decide to have Submit and Reply as buttons and hide everything else in more menu. If the Android application provides plugin interface similar to PolyGerrit's, UI script part of the plugin could take extra steps to ensure the action is visible in this case, while this if much more difficult for backend and involves changes to much more layers.

And again, if there's anything PolyGerrit team could do to improve, please don't hesitate filing issues.

Thanks a lot for the constructive discussion,
WBR, VD.

Orgad Shaneh

unread,
Apr 23, 2018, 10:42:03 AM4/23/18
to Repo and Gerrit Discussion
Hi,

Can you please provide an example for a button that does more than just console.log? I have some buttons in GWT that show a popup that accepts user input, then use this input for interacting with other systems. I don't need the Java backend, my buttons only use Javascript. But I have no idea how to make them work in PG.

lucamilanesio

unread,
May 10, 2018, 6:39:02 PM5/10/18
to Repo and Gerrit Discussion
I checked the PolyGerrit documentation for plugins, but it is still very much WIP :-(
Any example on how to add a top-menu item? The old extension point works only with GWT UX, and the extra menus do not show up in PolyGerrit.

Thanks for the feedback.

Luca.

thomasmu...@yahoo.com

unread,
May 10, 2018, 7:35:12 PM5/10/18
to Repo and Gerrit Discussion
Adding top-menu is not supported yet (i doin't think)

luca.mi...@gmail.com

unread,
May 11, 2018, 2:43:16 AM5/11/18
to thomasmu...@yahoo.com, repo-d...@googlegroups.com
This is a show-stopper for abandoning the GWT UX: how can plugins add menus?

In theory the PolyGerrit plugins should be able to change the page DOM and add items, isn’t it?

Luca

Sent from my iPhone
--
--
To unsubscribe, email repo-discuss...@googlegroups.com

More info at http://groups.google.com/group/repo-discuss?hl=en

---
You received this message because you are subscribed to the Google Groups "Repo and Gerrit Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to repo-discuss...@googlegroups.com.

thomasmu...@yahoo.com

unread,
May 11, 2018, 12:02:46 PM5/11/18
to Repo and Gerrit Discussion
Chad @ wmf was wondering if we could do this as we are using the top extension thing to link to wmf in house docs and other stuff.

Luca Milanesio

unread,
May 11, 2018, 12:04:42 PM5/11/18
to Paladox, Viktar Donich, Luca Milanesio, Repo and Gerrit Discussion
@Viktar?

Luca.

thomasmu...@yahoo.com

unread,
May 11, 2018, 12:10:48 PM5/11/18
to Repo and Gerrit Discussion
This would probaly need a new api since it's all split up :).

And not to mention isen't polygerrit header being redesgned?
@Viktar?

Luca.

Logan Hanks

unread,
May 11, 2018, 12:17:42 PM5/11/18
to thomasmu...@yahoo.com, Repo and Gerrit Discussion
Viktar is out of the office today, you may have to wait until next week for a response from him. We have an issue for this in Monorail[1], so we can escalate as needed.

Luca Milanesio

unread,
May 11, 2018, 12:30:29 PM5/11/18
to Logan Hanks, Luca Milanesio, thomasmu...@yahoo.com, Repo and Gerrit Discussion
Hi Logan,
thanks for the feedback.

I've added my comment and star to the issue.
I believe it is more urgent than a P2, having in mind that GWT is going to be phased out very soon :-O

Luca.

Viktar Donich

unread,
May 15, 2018, 4:40:13 PM5/15/18
to Luca Milanesio, Paladox, Repo and Gerrit Discussion
Hi all,

Answers inline, not in any particular order.

Can you please provide an example for a button that does more than just console.log?

Orgad, could you please clarify what's the button in question?
The reason I'm asking is that adding a change action button (Reply, Submit, etc) will be different from adding a random button anywhere else.

Here are few key documentation pieces:

For example, to add a basic html button to the change metadata, one could to do following:

plugin.html

Gerrit.install(plugin => {
  plugin.hook('change-metadata-item').onAttached(el => {
    const b = el.appendChild(document.createElement('input'));
    b.type = 'button';
    b.value = 'Foo bar';
    b.onclick = () => alert('foo');
  });
});

And obviously instead of input any other element could be used.

Also, if you find missing part of documentation, or another place you might need to make customizable, please file an issue using this link: 


WBR, VD.

@Viktar?

Luca.


More info at http://groups.google.com/group/repo-discuss?hl=en

--- 
You received this message because you are subscribed to the Google Groups "Repo and Gerrit Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to repo-discuss+unsubscribe@googlegroups.com.

Igor

unread,
Jun 7, 2018, 11:08:17 AM6/7/18
to Repo and Gerrit Discussion
Hi,

I tried this example plugin, but it worked for me only when attached to 'header-title' endpoint. Checked on v2.15.2, do I have to build and install master?
 
Gerrit.install(plugin => {
  plugin.hook('change-metadata-item').onAttached(el => {
    const b = el.appendChild(document.createElement('input'));
    b.type = 'button';
    b.value = 'Foo bar';
    b.onclick = () => alert('foo');
  });
});


Thanks,
Igor. 

Martin Wallgren

unread,
Jun 8, 2018, 2:56:30 AM6/8/18
to Repo and Gerrit Discussion
I stumbled upon the same issue with that example. I noticed that there are changes to master that does not exist in 2.15 see this.

I tried to address this here but there was not much response.

/Martin
.

Orgad Shaneh

unread,
Jan 18, 2019, 2:14:14 AM1/18/19
to Repo and Gerrit Discussion
Hi,

I'd really appreciate if anyone can post an example of adding a change action with a popup on PG.

The old cookbook plugin uad super-useful examples for both change action and revision action:

I would love to have similar examples for PG.

Is it possible to use external web components in a plugin? I'd like to use paper-multi-select for instance. How do I do this?

Sven Selberg

unread,
Jan 18, 2019, 4:08:06 AM1/18/19
to Repo and Gerrit Discussion
On Friday, January 18, 2019 at 8:14:14 AM UTC+1, Orgad Shaneh wrote:
Hi,

I'd really appreciate if anyone can post an example of adding a change action with a popup on PG.

I agree, it would be extremely valuable to have some examples of the different PG extension points in "plugins/examples".
The only example I've seen so far is that some plugin(s) have implemented the menu-item(!?) extension points but none in "plugins/examples".

David Ostrovsky

unread,
Jan 18, 2019, 4:45:38 AM1/18/19
to Repo and Gerrit Discussion

Am Freitag, 18. Januar 2019 10:08:06 UTC+1 schrieb Sven Selberg:
On Friday, January 18, 2019 at 8:14:14 AM UTC+1, Orgad Shaneh wrote:
Hi,

I'd really appreciate if anyone can post an example of adding a change action with a popup on PG.

I agree, it would be extremely valuable to have some examples of the different PG extension points in "plugins/examples".
The only example I've seen so far is that some plugin(s) have implemented the menu-item(!?) extension points but none in "plugins/examples".

Sven Selberg

unread,
Jan 18, 2019, 9:52:33 AM1/18/19
to Repo and Gerrit Discussion
Thanks David,

It used to be practice that when you implemented|updated a plugin extension-point you also made a minimal working example in the cookbook-plugin (replaced by plugins/examples).
Those minimal examples were very useful, time-saving and appreciated by those who wanted to use them in plugins.
They were also useful as a POC or to get an idea of the usefulness of said extension-points.

I, and others, would greatly appreciate, and benefit from, some PolyGerrit examples.
I have requested such examples before and have even tried to contribute a PG example but it got no response and the change was finally abandoned (and out-of-date probably given the speed that PolyGerrit have been developed in).

If someone more well-versed in PolyGerrit than me would take the time to give minimal examples of the PG extension-points, how to use the REST API from PG, etc. I think it would be very appreciated.
Perhaps this could be a Hackathon-topic?

That being said, I woefully notice that the extension-point-examples practice seems to have been lost:
https://gerrit-review.googlesource.com/q/project:plugins/examples - Last merged change in April 2017, almost two years ago.

Another hackathon-topic could be:
Should we keep plugins/examples even though it doesn't seem to be updated?
Stale examples can be more frustrating than useful so if we don't maintain it it might be better to deprecate the repo.

/Sven
Reply all
Reply to author
Forward
0 new messages