I want to share some thoughts I have been mulling over for a while, about how we could improve the way the core tool and extensions register operations. I want to make a case for improving the operation registry to support a few use cases.
When registering an operation, we currently only register the Java class for the operation in the backend. Unlike the importers, where we register in the same go the Java class that implements it and the HTML/JS files that implement the UI to configure the importing settings, operations only come with a backend-side component. If we could register their UI in the same go, I think it would enable a range of interesting use cases.
Which use cases do I have in mind?
-
The openrefine-command-palette, an extension by @abbe98 which lets users execute operations without going through the column menu, but by prompting them from the keyboard instead. It's a really nice UX, I encourage people to try it out. To achieve this, the extension needs to explicitly list each supported operation and associate it with:
- A human-readable name and description for the operation
- How to create the UI to configure it (for instance the
new ReconDialog(column)
code for the reconciliation operation) - Which bits of information need to be prompted from the user before showing them the configuration UI (typically, the name of the column to run the operation on)
You can see how it looks like in the
project-context.js
file. The problem is: @abbe98 needed to explicitly list all operations there together with the appropriate bits of UI, because that information is not currently available from the "official" operations registry. This has quite some downsides: if we implement a new operation, it will not directly be available in the command palette unless someone updates the extension. Also, if we change the UI for configuring an operation (like we have recently done for reconciliation), this can break the command palette in the same go.
- Other ways to provide alternative to our clunky column menu: for instance, by offering all available operations in a tool bar (independently of the columns), each represented by an icon accompanied with a name / description. The column to apply the operations on is prompted to the user when those buttons are clicked. If we wanted to implement something like that, we'd have to re-list all operations in a similar way.
- In the reproducibility project, one of the improvements we are considering is to make it possible to change the settings of a previous operation. Imagine a little "pencil" button in each entry of the history list that would let you reconfigure a previous step: for instance, change the settings used for reconciliation, tweak the GREL expression used to transform a column, or add a missing header to an URL fetching operation. Making such changes would trigger the recomputation (or discarding) of the later operations that would be impacted by the change. To implement something like this, we need a uniform way to generate the configuration UI from an operation.
So, how could we address those use cases? When registering an operation, we could also provide:
- a short name for the operation (as an i18n key, so that it's localizable?)
- a short description of the operation (similarly localizable)
- an icon for the operation, to be used in menu items or history list
- a javascript function which shows the UI for this operation. As parameters, this could have an existing operation configuration to pre-initialize the dialog with, a callback to call with the final configuration once the user has validated the dialog, and perhaps other things.
@zoecooper is looking into how hard it would be to come up with an icon set for our current operations, looking at existing icon sets or creating our own.
One problem we have is how to integrate into this picture the column(s) an operation is applied to. Given that currently, operations are generally triggered from the column menu, the dialogs that configure them typically don't prompt the user for that column name, since it is already implicit from the column menu used to trigger the operation. For instance, in the command palette, @abbe98 implemented his own pre-prompt for the column name inside the palette, to then be able to re-use the existing UI. A similar solution could be used in the "official" operations registry, but I have the feeling that this would be inheriting a design choice which is not necessarily pointing us to the right architecture in a context where operations are triggered from other contexts.
For instance, consider the "columnize by key/value columns" operation. The configuration dialog only lets the user pick three columns, as configuration for the operation. The column menu used to trigger the operation determines the pre-selection of the "key" column, but that's sort of arbitrary. This is typically an operation that does not belong to a column menu, really.
One could imagine that the dialogs for other operations could also let the user select which column the operation is run on, similarly to this dialog, and so that they could be exposed outside of any column menu.
What do you all think?