<html><head><style type='text/css'>p { margin: 0; }</style></head><body><div style='font-family: times new roman,new york,times,serif; font-size: 12pt; color: #000000'>Hi guys,<br><br>the latest revisi<span id="DWT4651" class="ZmSearchResult"><span id="DWT4655" class="ZmSearchResult">on</span></span> of <span id="DWT4657" class="ZmSearchResult"><span id="DWT4661" class="ZmSearchResult">UI</span></span> <span id="DWT4659" class="ZmSearchResult"><span id="DWT4663" class="ZmSearchResult">Plugins</span></span> proof-of-c<span id="DWT4653" class="ZmSearchResult"><span id="DWT4665" class="ZmSearchResult">on</span></span>cept patch is now available for you to experiment with. I've split revision 7 changes apart from revision 6 to make it easier to review new features that were added into revision 7.<br><br>You can download and apply UI Plugins patches from oVirt Gerrit code review system:<br><ol><li>revision 6 - http://gerrit.ovirt.org/#/c/8120/</li><li>revision 7 - http://gerrit.ovirt.org/#/c/9250/<br></li></ol>Please read <span id="DWT4669" class="ZmSearchResult"><span id="DWT4673" class="ZmSearchResult">on</span></span> to learn what's new in this revisi<span id="DWT4671" class="ZmSearchResult"><span id="DWT4675" class="ZmSearchResult">on</span></span>. If you have any comments, questi<span id="DWT4677" class="ZmSearchResult"><span id="DWT4679" class="ZmSearchResult">on</span></span>s or ideas, please let me know!<br><br><hr style="width: 100%; height: 2px;"><br><strong>Engine REST API integration</strong><br style="font-weight: bold;"><br><em>UiInit</em> is not the only event handler function anymore! :)<br><br>UI plugin infrastructure now integrates with Engine REST API by acquiring new REST API session [1] upon successful user authentication.<br><br>REST API session ID is provided to plugins via <span style="font-style: italic;">RestApiSessionAcquired</span> event handler function. For example:<br><br><span style="font-family: courier new,courier,monaco,monospace,sans-serif;">api.register({</span><br style="font-family: courier new,courier,monaco,monospace,sans-serif;"><span style="font-family: courier new,courier,monaco,monospace,sans-serif;">&nbsp; RestApiSessionAcquired: function(sessionId) {</span><br style="font-family: courier new,courier,monaco,monospace,sans-serif;"><span style="font-family: courier new,courier,monaco,monospace,sans-serif;">&nbsp;&nbsp;&nbsp; // Do something with newly acquired session ID</span><br style="font-family: courier new,courier,monaco,monospace,sans-serif;"><span style="font-family: courier new,courier,monaco,monospace,sans-serif;">&nbsp; }</span><br style="font-family: courier new,courier,monaco,monospace,sans-serif;"><span style="font-family: courier new,courier,monaco,monospace,sans-serif;">});</span><br><br>Note that <span style="font-style: italic;">UiInit</span> function is still the first function to be invoked on the given plugin. Plugins can therefore expect <span style="font-style: italic;">RestApiSessionAcquired</span> function to be called shortly after <span style="font-style: italic;">UiInit</span> function.<br><br>For now, UI plugin infrastructure guarantees that acquired Engine REST API session will be valid while the user stays authenticated in WebAdmin. This is done by keeping REST API session alive via periodic heartbeats (HTTP requests) in the background. This also means that it's safe to store and use REST API session ID until <span style="font-style: italic;">RestApiSessionAcquired</span> function is called again with new value. In future, we might consider dropping this kind of guarantee to avoid the keep-alive heartbeat, and use some kind of "is session valid" query to determine if the REST API session is still valid.<br><br>After the user signs out of WebAdmin, Engine REST API session will be closed, as per [1]. After signing in again, the process of acquiring new REST API session and calling <span style="font-style: italic;">RestApiSessionAcquired</span> function repeats with new session ID value.<br><br>Engine REST API integration also works seamlessly with auto login - if the user is already logged in on the backend, running WebAdmin in new window (tab) will take him directly to the main (authenticated) section of the application. In this case, UI plugin infrastructure remembers the currently valid REST API session ID using HTML5 local storage (or cookie if the browser doesn't support it).<br><br><hr style="width: 100%; height: 2px;"><br><span style="font-weight: bold;">New API function: showDialog</span><br style="font-weight: bold;"><br>It's now possible to open custom dialogs using <span style="font-style: italic;">showDialog</span> function. For example:<br><br><span style="font-family: courier new,courier,monaco,monospace,sans-serif;">api.register({</span><br style="font-family: courier new,courier,monaco,monospace,sans-serif;"><span style="font-family: courier new,courier,monaco,monospace,sans-serif;">&nbsp; UiInit: function() {</span><br style="font-family: courier new,courier,monaco,monospace,sans-serif;"><span style="font-family: courier new,courier,monaco,monospace,sans-serif;">&nbsp;&nbsp;&nbsp; api.addMainTabActionButton('Host', 'Show Test Dialog', {</span><br style="font-family: courier new,courier,monaco,monospace,sans-serif;"><span style="font-family: courier new,courier,monaco,monospace,sans-serif;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; onClick: function() {</span><br style="font-family: courier new,courier,monaco,monospace,sans-serif;"><span style="font-family: courier new,courier,monaco,monospace,sans-serif;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; api.showDialog('Test Dialog', 'http://www.ovirt.org/', 600, 400);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span><br style="font-family: courier new,courier,monaco,monospace,sans-serif;"><span style="font-family: courier new,courier,monaco,monospace,sans-serif;">&nbsp;&nbsp;&nbsp; });</span><br style="font-family: courier new,courier,monaco,monospace,sans-serif;"><span style="font-family: courier new,courier,monaco,monospace,sans-serif;">&nbsp; }</span><br style="font-family: courier new,courier,monaco,monospace,sans-serif;"><span style="font-family: courier new,courier,monaco,monospace,sans-serif;">});</span><br style="font-family: courier new,courier,monaco,monospace,sans-serif;"><br>The signature of <span style="font-style: italic;">showDialog</span> function is following:<br><br><div style="margin-left: 40px;"><span style="font-style: italic;">showDialog(title, contentUrl, width, height)</span><br></div><br>For now, dialogs are shown using <span style="font-style: italic;">window.open</span> API (non-modal browser popups). This will be changed in future, providing close integration with GWTP / WebAdmin dialog infrastructure.<br><br><hr style="width: 100%; height: 2px;"><br><span style="font-weight: bold;">New API function: setMainTabContentUrl</span><br style="font-weight: bold;"><br>It's now possible to update content URL of the given custom main tab using <span style="font-style: italic;">setMainTabContentUrl</span> function. For example:<br><br><span style="font-family: courier new,courier,monaco,monospace,sans-serif;">api.register({</span><br style="font-family: courier new,courier,monaco,monospace,sans-serif;"><span style="font-family: courier new,courier,monaco,monospace,sans-serif;">&nbsp; UiInit: function() {</span><br style="font-family: courier new,courier,monaco,monospace,sans-serif;"><span style="font-family: courier new,courier,monaco,monospace,sans-serif;">&nbsp;&nbsp;&nbsp; // Use 'about:blank' URL to display empty content</span><br style="font-family: courier new,courier,monaco,monospace,sans-serif;"><span style="font-family: courier new,courier,monaco,monospace,sans-serif;">&nbsp;&nbsp;&nbsp; api.addMainTab('Custom Tab', 'custom-tab', 'about:blank');</span><br style="font-family: courier new,courier,monaco,monospace,sans-serif;"><span style="font-family: courier new,courier,monaco,monospace,sans-serif;">&nbsp; },</span><br style="font-family: courier new,courier,monaco,monospace,sans-serif;"><span style="font-family: courier new,courier,monaco,monospace,sans-serif;">&nbsp; RestApiSessionAcquired: function(sessionId) {</span><br style="font-family: courier new,courier,monaco,monospace,sans-serif;"><span style="font-family: courier new,courier,monaco,monospace,sans-serif;">&nbsp;&nbsp;&nbsp; var url = 'http://www.ovirt.org/?s=' + encodeURIComponent(sessionId);</span><br style="font-family: courier new,courier,monaco,monospace,sans-serif;"><span style="font-family: courier new,courier,monaco,monospace,sans-serif;">&nbsp;&nbsp;&nbsp; api.setMainTabContentUrl('custom-tab', url);</span><br style="font-family: courier new,courier,monaco,monospace,sans-serif;"><span style="font-family: courier new,courier,monaco,monospace,sans-serif;">&nbsp; }</span><br style="font-family: courier new,courier,monaco,monospace,sans-serif;"><span style="font-family: courier new,courier,monaco,monospace,sans-serif;">});</span><br style="font-family: courier new,courier,monaco,monospace,sans-serif;"><br>In the above example, we first add an empty custom main tab. We do this in <span style="font-style: italic;">UiInit</span> event handler function because we know that it's the best place for one-time UI initialization :) As soon as we receive REST API session ID, we update the URL of the custom main tab. This is just an example how REST API session ID can be sent over to your server as part of main tab content URL.<br><br>The signature of <span style="font-style: italic;">setMainTabContentUrl</span> function is following:<br><br><div style="margin-left: 40px;"><span style="font-style: italic;">setMainTabContentUrl(historyToken, contentUrl)</span><br></div><br>Note that <span style="font-style: italic;">historyToken</span> essentially identifies the custom main tab.<br><br><hr style="width: 100%; height: 2px;"><br>That's it for now, let me know what you think!<br><br>Regards,<br>Vojtech<br><br><span style="font-weight: bold;"></span><br>[1] http://wiki.ovirt.org/wiki/Features/RESTSessionManagement<br><br></div></body></html>