[PATCH] [Wok 0/3] Multiple fixes

Aline Manera (3): Bug fix: Make /tabs URI generic to be used by any plugin Bug fix: Respect user request while building the UI Fix bug #6: Proper load help page src/wok/root.py | 15 ++-- ui/js/src/wok.main.js | 177 +++++++++++++++++++++++----------------------- ui/pages/wok-ui.html.tmpl | 6 +- 3 files changed, 101 insertions(+), 97 deletions(-) -- 2.5.0

The /tabs URI is responsible to deliver the HTML content from a tab. It restores the last tab requested in the 'lastPage' cookie so the last user choice can be remembered when needed. Signed-off-by: Aline Manera <alinefm@linux.vnet.ibm.com> --- src/wok/root.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/wok/root.py b/src/wok/root.py index 1776915..dcc2991 100644 --- a/src/wok/root.py +++ b/src/wok/root.py @@ -27,7 +27,7 @@ from distutils.version import LooseVersion from wok import auth from wok import template from wok.i18n import messages -from wok.config import paths +from wok.config import paths as wok_paths from wok.control import sub_nodes from wok.control.base import Resource from wok.control.utils import parse_request @@ -103,13 +103,16 @@ class Root(Resource): # In order to load the Guests tab, we also use Cheetah in the tab # template to save the delay of the extra get to the guest page # For that, the tab template needs to know the correct path to ui files + paths = cherrypy.request.app.root.paths + script_name = cherrypy.request.app.script_name + last_page = script_name.lstrip("/") + "/tabs/" + page[:-5] + data = {} data['ui_dir'] = paths.ui_dir if page.endswith('.html'): - context = template.render('tabs/' + page, data) - cherrypy.response.cookie[ - "lastPage"] = "/#tabs/" + page[:-5] + context = template.render('/tabs/' + page, data) + cherrypy.response.cookie["lastPage"] = "/#" + last_page cherrypy.response.cookie['lastPage']['path'] = '/' return context raise cherrypy.HTTPError(404) @@ -121,9 +124,9 @@ class WokRoot(Root): self.default_page = 'wok-ui.html' for ident, node in sub_nodes.items(): setattr(self, ident, node(model)) - with open(os.path.join(paths.src_dir, 'API.json')) as f: + with open(os.path.join(wok_paths.src_dir, 'API.json')) as f: self.api_schema = json.load(f) - self.paths = paths + self.paths = wok_paths self.domain = 'wok' self.messages = messages -- 2.5.0

Every time the UI was built (for a first access or after a browser refresh), the user was always redirected to the first tab. Fix it, by respecting the user request when building the UI and only redirect to the default page when no specific tab was requested. This patch also fixes issue #3 Signed-off-by: Aline Manera <alinefm@linux.vnet.ibm.com> --- ui/js/src/wok.main.js | 166 ++++++++++++++++++++++++---------------------- ui/pages/wok-ui.html.tmpl | 6 +- 2 files changed, 89 insertions(+), 83 deletions(-) diff --git a/ui/js/src/wok.main.js b/ui/js/src/wok.main.js index 28db413..95e8ed6 100644 --- a/ui/js/src/wok.main.js +++ b/ui/js/src/wok.main.js @@ -27,6 +27,7 @@ wok.main = function() { var genTabs = function(tabs) { var tabsHtml = []; $(tabs).each(function(i, tab) { + var functionality = tab['functionality']; var title = tab['title']; var path = tab['path']; var mode = tab['mode']; @@ -34,10 +35,11 @@ wok.main = function() { var helpPath = wok.checkHelpFile(path); var disableHelp = (helpPath.length == 0 ? "disableHelp" : helpPath); tabsHtml.push( - '<li>', - '<a class="item ', disableHelp,' ','" href="', path, '">', + '<li class="', functionality.toLowerCase() + 'Tab', '">', + '<a class="item ', disableHelp, '" href="', path, '">', title, '</a>', + '<input id="funcTab" name="funcTab" class="sr-only" value="' + functionality.toLowerCase() + '" type="hidden"/>', '<input id="helpPathId" name="helpPath" class="sr-only" value="' + helpPath + '" type="hidden"/>', '</li>' ); @@ -45,20 +47,19 @@ wok.main = function() { }); return tabsHtml.join(''); }; - var genFunctTabs = function(tabs){ + + var genFuncTabs = function(tabs){ var functionalTabHtml = []; - var functionalTabs = Object.keys(tabs); - var css =""; - $(functionalTabs).each(function(i, tab) { + $(tabs).each(function(i, tab) { functionalTabHtml.push( - '<li>', - '<a class="item',' ',tab.toLowerCase(),'Tab','" href="#">', - tab, - '</a>', - '</li>' + '<li>', + '<a class="item',' ',tab.toLowerCase(),'Tab','" href="#">', + tab, + '</a>', + '</li>' ); }); - return functionalTabHtml.join(''); + return functionalTabHtml.join(''); }; var parseTabs = function(xmlData) { @@ -69,7 +70,6 @@ wok.main = function() { var $tab = $(this); var titleKey = $tab.find('title').text(); var title = i18n[titleKey] ? i18n[titleKey] : titleKey; - var css = $tab.find('class').text(); var path = $tab.find('path').text(); var roles = wok.cookie.get('roles'); if (roles) { @@ -77,29 +77,21 @@ wok.main = function() { var mode = $tab.find('[role="' + role + '"]').attr('mode'); wok.tabMode[titleKey.toLowerCase()] = mode; tabs.push({ + functionality: functionality, title: title, path: path, - css: css, mode: mode }); } else { document.location.href = 'login.html'; } }); - var tabsDetails = JSON.parse(wok.cookie.get('tabs')); - - var isExisting = tabsDetails[functionality] && (tabsDetails[functionality].length)>0; - - if(isExisting){ - tabs.push.apply(tabs,tabsDetails[functionality]); - } - functionalTabs[functionality] = tabs; - return functionalTabs; + return tabs; }; var retrieveTabs = function(url) { - var tabs; + var tabs = []; $.ajax({ url : url, async : false, @@ -114,8 +106,8 @@ wok.main = function() { var pluginI18nUrl = 'plugins/{plugin}/i18n.json'; var DEFAULT_HASH; var buildTabs = function(callback) { - var tabs = {}; - wok.cookie.set('tabs',JSON.stringify(tabs)); + var tabs = []; + var functionalTabs = []; wok.listPlugins(function(plugins) { $(plugins).each(function(i, p) { var url = wok.substitute(pluginConfigUrl, { @@ -125,38 +117,30 @@ wok.main = function() { plugin: p }); wok.getI18n(function(i18nObj){ $.extend(i18n, i18nObj)}, - function(i18nObj){ //i18n is not define by plugin - }, i18nUrl, true); - tabs = $.extend({},tabs, retrieveTabs(url)); - wok.cookie.set('tabs',JSON.stringify(tabs)); - }); - - var orderedtabs ={}; - Object.keys(tabs).sort().forEach(function(key){ - orderedtabs[key]=tabs[key]; + function(i18nObj){ //i18n is not define by plugin + }, i18nUrl, true); + var pluginTabs = retrieveTabs(url); + var func = pluginTabs[0].functionality + if (functionalTabs.indexOf(func) == -1) { + functionalTabs.push(pluginTabs[0].functionality) + } + tabs.push.apply(tabs, pluginTabs); }); - //defaulting the first tab in second level - var defaultFunctionalTab = Object.keys(orderedtabs)[0]; - - var defaultTab = tabs[defaultFunctionalTab][0]; - - var defaultTabPath = defaultTab && defaultTab['path'] - //redirect to empty page when no plugin installed if(tabs.length===0){ - DEFAULT_HASH = 'wok-empty'; - }else{ + DEFAULT_HASH = 'wok-empty'; + } else { + var defaultTab = tabs[0] + var defaultTabPath = defaultTab && defaultTab['path'] + // Remove file extension from 'defaultTabPath' DEFAULT_HASH = defaultTabPath && defaultTabPath.substring(0, defaultTabPath.lastIndexOf('.')) } - $('#nav-menu ul.navbar-nav li.hostname').after(genFunctTabs(orderedtabs)); - $('#nav-menu ul.navbar-nav li a.item').first().parent().addClass('active').focus(); - $('#tabPanel').addClass(defaultFunctionalTab.toLowerCase()+'Tab'); - $(genTabs(tabs[defaultFunctionalTab])).appendTo('#tabPanel ul'); - $('#tabPanel ul li a.item').first().addClass(defaultFunctionalTab.toLowerCase()+'Selected').focus(); + $('#functionalTabPanel ul').append(genFuncTabs(functionalTabs)); + $('#tabPanel ul').append(genTabs(tabs)); wok.getHostname(); callback && callback(); @@ -186,21 +170,35 @@ wok.main = function() { * point to the tab. If nothing found, inform user the URL is invalid * and clear location.hash to jump to home page. */ - var tab = $('#tabPanel ul.navbar-nav li a[href="' + url + '"]'); - if (tab.length === 0 && url!='wok-empty.html'){ - location.hash = ''; + var tab = $('#tabPanel a[href="' + url + '"]'); + if (tab.length === 0 && url != 'wok-empty.html') { + location.hash = '#'; return; } //Remove the tab arrow indicator for no plugin - if(url=='wok-empty.html') { - $('#main').html('No plugins installed currently.You can download the available plugins <a href="https://github.com/kimchi-project/kimchi">Kimchi</a> and <a href="https://github.com/kimchi-project/ginger">Ginger</a> from Github').addClass('noPluginMessage'); + if (url == 'wok-empty.html') { + $('#main').html('No plugins installed currently.You can download the available plugins <a href="https://github.com/kimchi-project/kimchi">Kimchi</a> and <a href="https://github.com/kimchi-project/ginger">Ginger</a> from Github').addClass('noPluginMessage'); } else { - var tab = $('#tabPanel ul.navbar-nav li a[href="' + url + '"]'); - var plugin = $('#nav-menu ul li.active a').text(); - // Update the visual style of tabs; focus the selected one. + var plugin = $(tab).parent().find("input[name='funcTab']").val(); + + $('#tabPanel').removeClass(function(i, css) { + return (css.match(/\S+Tab/g) || []).join(' '); + }); + $('#tabPanel').addClass(plugin + 'Tab'); $('#tabPanel ul li').removeClass('active'); + $.each($('#tabPanel li'), function(i, t) { + if ($(t).hasClass(plugin + 'Tab')) { + $(t).css('display', 'block'); + } else { + $(t).css('display', 'none'); + } + }); + $(tab).parent().addClass('active'); - $(tab).addClass(plugin.toLowerCase()+'Selected').focus(); + $(tab).addClass(plugin + 'Selected').focus(); + + $('#functionalTabPanel ul li').removeClass('active'); + $('#functionalTabPanel ul .' + plugin + 'Tab').parent().addClass('active').focus(); // Disable Help button according to selected tab if ($(tab).hasClass("disableHelp")) { @@ -225,7 +223,7 @@ wok.main = function() { url && $('#main').load(url, function(responseText, textStatus, jqXHR) { if (jqXHR['status'] === 401 || jqXHR['status'] === 303) { var isSessionTimeout = jqXHR['responseText'].indexOf("sessionTimeout")!=-1; - document.location.href= isSessionTimeout ? 'login.html?error=sessionTimeout' : 'login.html'; + document.location.href = isSessionTimeout ? 'login.html?error=sessionTimeout' : 'login.html'; return; } }); @@ -241,6 +239,7 @@ wok.main = function() { var updatePage = function() { // Parse hash string. var hashString = (location.hash && location.hash.substr(1)); + /* * If hash string is empty, then apply the default one; * or else, publish an "redirect" event to load the page. @@ -298,25 +297,31 @@ wok.main = function() { * Register click listener of second level tabs. Replace the default reloading page * behavior of <a> with Ajax loading. */ - $('#nav-menu ul li').on('click', 'a.item', function(event) { - var functionalTab = $(this).text(); - var previousSelection = $('#nav-menu ul li.active a').text(); - $('#tabPanel').removeClass(previousSelection.toLowerCase()+'Tab'); - - $('#nav-menu ul li').removeClass('active'); - $(this).parent().addClass('active').focus(); - - $('#tabPanel').addClass(functionalTab.toLowerCase()+'Tab'); - var tabs = JSON.parse(wok.cookie.get('tabs')); - $('#tabPanel ul').empty(); - $(genTabs(tabs[functionalTab])).appendTo('#tabPanel ul'); - var firstTab = $('#tabPanel ul.navbar-nav li').first(); - $(firstTab).addClass('active'); - $('a.item',firstTab).addClass(functionalTab.toLowerCase()+'Selected'); - var href= $('a.item',firstTab).attr('href'); - location.hash = href.substring(0,href.lastIndexOf('.')); - event.preventDefault(); - }); + $('#functionalTabPanel ul li').on('click', 'a.item', function(event) { + var plugin = $(this).text().toLowerCase(); + var previousPlugin = $('#functionalTabPanel ul li.active a').text().toLowerCase(); + + $('#tabPanel').switchClass(previousPlugin + 'Tab', plugin + 'Tab'); + $('#tabPanel ul li').removeClass('active'); + $.each($('#tabPanel li'), function(i, t) { + if ($(t).hasClass(plugin + 'Tab')) { + $(t).css('display', 'block'); + } else { + $(t).css('display', 'none'); + } + }); + + $('#functionalTabPanel ul li').removeClass('active'); + $(this).parent().addClass('active').focus(); + + var firstTab = $('#tabPanel ul.navbar-nav li.' + plugin + 'Tab').first(); + $(firstTab).addClass('active'); + $('a.item', firstTab).addClass(plugin + 'Selected'); + + var href = $('a.item', firstTab).attr('href'); + location.hash = href.substring(0,href.lastIndexOf('.')); + event.preventDefault(); + }); // Perform logging out via Ajax request. $('#btn-logout').on('click', function() { @@ -420,10 +425,11 @@ wok.main = function() { function(i18nStrings){ //success i18n = i18nStrings; buildTabs(initUI); - }, + }, function(data){ //error wok.message.error(data.responseJSON.reason); - }); + } + ); }; diff --git a/ui/pages/wok-ui.html.tmpl b/ui/pages/wok-ui.html.tmpl index cd98239..6d77060 100644 --- a/ui/pages/wok-ui.html.tmpl +++ b/ui/pages/wok-ui.html.tmpl @@ -133,12 +133,12 @@ <span class="icon-bar"><!-- Hamburguer button here --></span> </button> </div> - <div class="collapse navbar-collapse" id="nav-menu"> - <ul id="functionalTabPanel" class="nav navbar-nav"> + <div id="functionalTabPanel" class="collapse navbar-collapse"> + <ul class="nav navbar-nav"> <li class="hostname"><span class="host-location"></span></li> </ul> </div> - <div class="collapse navbar-collapse" id="tabPanel"> + <div id="tabPanel" class="collapse navbar-collapse"> <ul class="nav navbar-nav"> </ul> </div> -- 2.5.0

Signed-off-by: Aline Manera <alinefm@linux.vnet.ibm.com> --- ui/js/src/wok.main.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/ui/js/src/wok.main.js b/ui/js/src/wok.main.js index 95e8ed6..e672259 100644 --- a/ui/js/src/wok.main.js +++ b/ui/js/src/wok.main.js @@ -435,12 +435,7 @@ wok.main = function() { wok.checkHelpFile = function(path) { var lang = wok.lang.get(); - var url = "" - // Find help page path according to tab name - if (/^tabs/.test(path)) - url = path.replace("tabs", "help/" + lang); - else if (/^plugins/.test(path)) - url = path.slice(0, path.lastIndexOf('/')) + "/help/" + lang + path.slice(path.lastIndexOf('/')); + var url = path.replace("tabs", "help/" + lang); // Checking if help page exist. $.ajax({ url: url, @@ -458,8 +453,8 @@ wok.getHostname = function(e) { } wok.openHelp = function(e) { - var tab = $('#nav-menu a.current'); - var url = $(tab).parent().find("input[name='helpPath']").val(); + var tab = $('#tabPanel ul li.active'); + var url = $(tab).find("input[name='helpPath']").val(); window.open(url, "Wok Help"); e.preventDefault(); }; -- 2.5.0

Reviewed by: Jose Ricardo Ziviani <joserz@linux.vnet.ibm.com> On 10-12-2015 14:46, Aline Manera wrote:
Aline Manera (3): Bug fix: Make /tabs URI generic to be used by any plugin Bug fix: Respect user request while building the UI Fix bug #6: Proper load help page
src/wok/root.py | 15 ++-- ui/js/src/wok.main.js | 177 +++++++++++++++++++++++----------------------- ui/pages/wok-ui.html.tmpl | 6 +- 3 files changed, 101 insertions(+), 97 deletions(-)
-- Jose Ricardo Ziviani ----------------------------- Software Engineer Linux Technology Center - IBM

Aline, Also please apply these patches to next as well so that I will send patch for proper help pages for gingerbase. In general if possible we could apply the master patches to next as well so that next always have the latest from master plus additional changes. In this way I guess it will be easy to merge next back to master. Regards Chandra On 11/12/15 2:41 AM, Aline Manera wrote:
Applied. Thanks.
Regards,
Aline Manera
_______________________________________________ Kimchi-devel mailing list Kimchi-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/kimchi-devel

On 12/15/2015 05:55 AM, Chandra Shekhar Reddy Potula wrote:
Aline,
Also please apply these patches to next as well so that I will send patch for proper help pages for gingerbase.
If we're talking about this issue https://github.com/kimchi-project/gingerbase/issues/14 this is an issue I would like fixed for the 2.0 release, master branch of gingerbase. Please make it happen asap. Daniel
In general if possible we could apply the master patches to next as well so that next always have the latest from master plus additional changes. In this way I guess it will be easy to merge next back to master.
Regards Chandra On 11/12/15 2:41 AM, Aline Manera wrote:
Applied. Thanks.
Regards,
Aline Manera
_______________________________________________ Kimchi-devel mailing list Kimchi-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/kimchi-devel
_______________________________________________ Kimchi-devel mailing list Kimchi-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/kimchi-devel

On 15/12/15 6:11 PM, Daniel Henrique Barboza wrote:
On 12/15/2015 05:55 AM, Chandra Shekhar Reddy Potula wrote:
Aline,
Also please apply these patches to next as well so that I will send patch for proper help pages for gingerbase.
If we're talking about this issue https://github.com/kimchi-project/gingerbase/issues/14 this is an issue I would like fixed for the 2.0 release, master branch of gingerbase.
Please make it happen asap.
Daniel
Daniel, I am planning to send a patch latest by tomorrow.
In general if possible we could apply the master patches to next as well so that next always have the latest from master plus additional changes. In this way I guess it will be easy to merge next back to master.
Regards Chandra On 11/12/15 2:41 AM, Aline Manera wrote:
Applied. Thanks.
Regards,
Aline Manera
_______________________________________________ Kimchi-devel mailing list Kimchi-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/kimchi-devel
_______________________________________________ Kimchi-devel mailing list Kimchi-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/kimchi-devel
_______________________________________________ Kimchi-devel mailing list Kimchi-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/kimchi-devel

On 15/12/2015 05:55, Chandra Shekhar Reddy Potula wrote:
Aline,
Also please apply these patches to next as well so that I will send patch for proper help pages for gingerbase.
In general if possible we could apply the master patches to next as well so that next always have the latest from master plus additional changes. In this way I guess it will be easy to merge next back to master.
Those patches are in next branch since Dex 11th https://github.com/kimchi-project/kimchi/commits/next Regards, Aline Manera
Regards Chandra On 11/12/15 2:41 AM, Aline Manera wrote:
Applied. Thanks.
Regards,
Aline Manera
_______________________________________________ Kimchi-devel mailing list Kimchi-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/kimchi-devel
_______________________________________________ Kimchi-devel mailing list Kimchi-devel@ovirt.org http://lists.ovirt.org/mailman/listinfo/kimchi-devel
participants (4)
-
Aline Manera
-
Chandra Shekhar Reddy Potula
-
Daniel Henrique Barboza
-
Jose Ricardo Ziviani