[Engine-devel] UI Plugins: PoC patch revision 6 now available

Itamar Heim iheim at redhat.com
Tue Oct 23 06:49:02 UTC 2012


On 10/22/2012 05:25 PM, Morrissey, Christopher wrote:
> Hi Vojtech,
>
> Thanks again for the delivery of the patch. For revision 7, do you have
> a list of content? I had previously indicated I could work on adding the
> plugin API to launch a dialog, but hadn’t been able to get started on it
> until now. I wanted to see if you by chance were already working on it
> or if you were planning to deliver that yourself in the next revision?
>
> A couple of other items we are looking for are the ability to add tasks
> for execution and get access to the session ID or some kind of
> authentication token so that we can make calls from our server into the
> REST API. I’m not very familiar yet with the REST API so I’m not sure
> what authentication methods are available and which would be best.

Oved - I remember we discussed UI plugins should be able to use same 
logic as jasper reports for getting a session identifier for using the 
REST API.
do you remember the details on this one?

Thanks,
    Itamar

>
> -Chris
>
> *From:*engine-devel-bounces at ovirt.org
> [mailto:engine-devel-bounces at ovirt.org] *On Behalf Of *Vojtech Szocs
> *Sent:* Thursday, October 18, 2012 10:49 AM
> *To:* engine-devel
> *Subject:* [Engine-devel] UI Plugins: PoC patch revision 6 now available
>
> Hi guys,
>
> the latest revision of UI Plugins proof-of-concept patch is now
> available for you to experiment with. You can download the patch from
> oVirt Gerrit at http://gerrit.ovirt.org/#/c/8120/2 (patch set 2).
>
> Please read on to learn what's new in this revision. If you have any
> comments, questions or ideas, please let me know!
>
> ------------------------------------------------------------------------
>
>
> *0. UI plugin path information resolved using local Engine configuration**
> *
> Server-side UI plugin infrastructure now uses local (machine-specific)
> Engine configuration instead of global (/vdc_options/ database table)
> Engine configuration:
>
>   * Previously, path information was resolved through
>     org.ovirt.engine.core.common.config.Config class - Engine
>     configuration values were retrieved from /vdc_options/ database table.
>   * Currently, path information is resolved through
>     org.ovirt.engine.core.utils.LocalConfig class - Engine configuration
>     values are retrieved from local file system.
>
> In case you're not working with oVirt Engine through RPM package system,
> e.g. you have a local development environment set up and you build and
> deploy oVirt Engine through Maven, please follow these steps:
>
> a. Copy default Engine configuration into /usr/share/*ovirt-engine*/conf
>
> # mkdir -p /usr/share/ovirt-engine/conf
> # cp <OVIRT_HOME>/backend/manager/conf/engine.conf.defaults
> /usr/share/ovirt-engine/conf/engine.conf.defaults
>
>
> b. If necessary, copy UI plugin data files from
> /usr/share/engine/ui-plugins to /usr/share/*ovirt-engine*/ui-plugins
>
> c. If necessary, copy UI plugin config files from /etc/engine/ui-plugins
> to /etc/*ovirt-engine*/ui-plugins
>
> d, In case you want to override the default Engine configuration, put
> your custom property file into /etc/sysconfig/ovirt-engine
>
> The reason behind this change is that path information for UI plugin
> data and configuration is typically machine-specific, and should be
> customizable per machine through Engine local configuration.
>
> ------------------------------------------------------------------------
>
>
> *1. New plugin API function: addMainTabActionButton
> *
> The "addMainTabActionButton" API adds custom context-sensitive button to
> the given main tab's data grid, along with corresponding data grid
> context menu item.
>
> addMainTabActionButton(entityTypeName, label, actionButtonInterface)
>
> /entityTypeName/ indicates which main tab's data grid the button should
> be added to, according to the entity type associated with the main
> tab./entityTypeName/ values are strings reflecting
> org.ovirt.engine.ui.webadmin.plugin.entityEntityType enum members.
> Following /entityTypeName/ values are currently supported (values are
> case-sensitive): "DataCenter", "Cluster", "Host", "Storage", "Disk",
> "VirtualMachine", "Template".
>
> Note: "Pool" value is currently not supported, because of
> org.ovirt.engine.core.common.businessentities.vm_pools entity not
> implementing the BusinessEntity interface, not sure why though. Maybe we
> should switch from BusinessEntity to IVdcQueryable interface and always
> cast getQueryableId method result value to Guid?
>
> /label/ is the title displayed on the button/.
> /
> /actionButtonInterface/ represents an object that "implements the button
> interface" by declaring its functions: /onClick/, /isEnabled/,
> /isAccessible/. All functions of /actionButtonInterface/ receive
> currently selected item(s) as function arguments.
>
> Let's take a closer look at the concept behind /actionButtonInterface/.
> In traditional class-based object-oriented languages, such as Java,
> interface is an abstract type that contains method declarations without
> an implementation. A class that implements the given interface must
> implement all methods declared by that interface (unless it's an
> abstract class, but this isn't relevant in our case).
>
> In contrast with traditional class-based object-oriented languages,
> JavaScript supports OOP through prototype-based programming model
> (https://developer.mozilla.org/en-US/docs/JavaScript/Introduction_to_Object-Oriented_JavaScript).
> At the same time, JavaScript language is dynamically-typed and therefore
> doesn't support traditional concept of interface in OOP, it uses "duck
> typing" technique instead (http://en.wikipedia.org/wiki/Duck_typing).
>
> The simplest way to provide an object that "implements the given
> interface" in JavaScript is to use "duck typing" technique: providing an
> object that contains well-known functions. In UI plugin infrastructure,
> I call this concept "interface object", represented by
> org.ovirt.engine.ui.webadmin.plugin.jsni.JsInterfaceObject class. Unlike
> the traditional concept of interface abstract type in object-oriented
> languages, an "interface object" _does not necessarily have to declare
> all functions of the given interface_ in order to "implement" such
> interface. In fact, an empty object can be used as a valid "interface
> object". Missing functions will be simply treated as empty (no-op)
> functions. Furthermore, an "interface object" can "implement" multiple
> interfaces by declaring functions of those interfaces (interface
> composition).
>
> Getting back to "addMainTabActionButton" API, here's a sample code that
> adds new button to "Host" main tab data grid, as part of UiInit event
> handler function:
>
> UiInit: *function*() {
>      api.addMainTabActionButton('Host', 'Single-Host Action',
>
>          // Action button interface object
>          // All functions receive currently selected item(s) as function
> arguments
>          {
>
>              // Called when the user clicks the button
> onClick: *function*() {
>                  // Calling 'arguments[0]' is safe, because onClick()
> can be called
>                  // only when exactly one item is currently selected in
> the data grid
>                  window.alert('Selected host entity ID = ' +
> arguments[0].entityId);
>              },
>
>              // Returning 'true' means the button is enabled (clickable)
>              // Returning 'false' means the button is disabled
> (non-clickable)
>              // Default value = 'true'
> isEnabled: *function*() {
>                  // Enable button only when exactly one item is selected
> *return*arguments.length == 1;
>              },
>
>              // Returning 'true' means the button is visible
>              // Returning 'false' means the button is hidden
>              // Default value = 'true'
> isAccessible: *function*() {
>                  // Always show the button in the corresponding data grid
> *return**true*;
>              }
>
>          }
>
>      );
> }
>
> As mentioned above, all functions of an interface object are optional.
> For functions expecting return value, default value is defined by UI
> plugin infrastructure. For example:
>
>   * onClick - no default value (no return value expected)
>   * isEnabled / isAccessible - default value "true" (boolean return
>     value expected)
>
> Note: UI plugin infrastructure checks the actual return value type, and
> uses default value in case the function returned something of wrong
> (unexpected) type.
>
>
> In the example above, "currently selected item(s)" maps to JSON-like
> representations of business entities currently selected in the
> corresponding data grid. For now, the entity representation is quite
> simple and same for all entity types:
>
> { entityId: "[BusinessEntityGuidAsString]" }
>
> In future, we will create specific JSON-like representations for
> specific business entities, in compliance with Engine REST API entity
> structure.
>
> For a more extensive example of using "addMainTabActionButton" API,
> please see the attached "addMainTabActionButton.html.example" file.
>
> ------------------------------------------------------------------------
>
>
> *2. Improved plugin API function: addMainTab
> *
> The "addMainTab" API was improved to address following issues:
>
>   * "addMainTab" can now be called at any moment during UI plugin
>     runtime, given that the plugin is allowed invoke plugin API
>     functions (plugin is either INITIALIZING or IN_USE).
>     Previously, "addMainTab" worked reliably only when called from
>     within UiInit event handler function.
>     Currently, it's possible to call "addMainTab" at any moment, e.g.
>     from within some other event handler function (after UiInit has
>     completed).
>
>   * "addMainTab" now retains "active" tab (highlighted tab GUI).
>     "addMainTab" works by adding new tab component (GWTP presenter
>     proxy) and refreshing main tab panel GUI by removing all related
>     tabs and re-adding them again.
>     This logic is handled by
>     org.ovirt.engine.ui.common.presenter.DynamicTabContainerPresenter
>     class, which makes sure that "active" tab is retained even after
>     main tab panel was refreshed.
>
> Furthermore, custom main tab implementation now displays the content of
> the given URL through HTML iframe element.
>
> ------------------------------------------------------------------------
>
>
> *3. Improved native JavaScript function handling* (GWT JSNI)
>
> This patch introduces
> org.ovirt.engine.ui.webadmin.plugin.jsni.JsFunction and
> org.ovirt.engine.ui.webadmin.plugin.jsni.JsFunctionResultHelper classes
> providing Java abstraction for invoking native JavaScript functions.
> These classes follow the general contract of "interface object" as
> mentioned above.
>
> JsFunctionResultHelper is particularly useful when dealing with
> functions which are expected to return value of a certain type. Too bad
> standard GWT JSNI classes don't provide such abstraction for working
> with native functions out-of-the-box...
>
> ------------------------------------------------------------------------
>
>
> *4. ActionPanel and ActionTable type hierarchy refactoring* (related to
> "addMainTabActionButton" API)*
> *
> Previously, AbstractActionPanel and AbstractActionTable classes didn't
> implement any reasonable interface that would allow other components
> (client-side UI plugin infrastructure) to depend on their functionality
> in a loosely-coupled manner. This would make code that implements
> "addMainTabActionButton" API "ugly": main tab view interface would have
> to reference AbstractActionTable class directly. In MVP design pattern,
> view interface should avoid referencing specific GWT Widget classes
> directly.
>
> This patch introduces new interfaces for ActionPanel and ActionTable
> components while eliminating code redundancy (duplicate or unnecessary
> code).
>
> ------------------------------------------------------------------------
>
>
> *5. ActionPanel type hierarchy refactoring* (related to "addMainTab" API)
>
> Since org.ovirt.engine.ui.common.presenter.DynamicTabContainerPresenter
> defines new DynamicTabPanel interface that extends standard GWTP
> TabPanel interface, some refactoring had to be done in related
> ActionPanel classes.
>
> This patch makes sure that both
> org.ovirt.engine.ui.common.widget.tab.AbstractTabPanel (widget) and
> org.ovirt.engine.ui.common.view.AbstractTabPanelView (view) support
> DynamicTabPanel interface.
>
> Note that for now, only main tab panel
> (org.ovirt.engine.ui.webadmin.section.main.presenter.MainTabPanelPresenter)
> supports dynamic tabs within its view.
>
> ------------------------------------------------------------------------
>
>
> *Where is addSubTab API function?*
>
> Implementing "addSubTab" API requires some more changes, and I didn't
> want to delay this PoC patch just because of it...
>
> Here's a sample code that illustrates proposed "addSubTab" API usage:
>
> UiInit: *function*() {
>      api.addSubTab('Host', // entityTypeName
>          'Custom Host Sub Tab', // label
>          'custom-host-sub-tab', // historyToken
>          'http://www.ovirt.org/', // contentUrl
>
> // Sub tab interface object
>          // All functions receive currently selected item(s)
>          // within the main tab data grid as function arguments
>          {
>
>              // Returning 'true' means the sub tab is visible
>              // Returning 'false' means the sub tab is hidden
>              // Default value = 'true'
> isAccessible: *function*() {
> *return*arguments.length == 1 && arguments[0].entityId ==
> '<MyHostEntityId>';
>              }
>
>          }
>
>      );
> }
>
> As part of "addSubTab" API implementation, I'll refactor custom main tab
> components, in order to use one "tab type" for both main and sub tabs.
>
> Currently, we have one (and only one) "tab type" - a tab that shows
> content of the given URL through HTML iframe element.
>
> We could also create new "tab types", e.g. form-based tab that shows
> key/value pairs (IMHO this could be quite useful for custom sub tabs).
>
> ------------------------------------------------------------------------
>
>
> Let me know what you think!
>
> Cheers,
> Vojtech
>
>
>
> _______________________________________________
> Engine-devel mailing list
> Engine-devel at ovirt.org
> http://lists.ovirt.org/mailman/listinfo/engine-devel
>





More information about the Engine-devel mailing list