Refactored navigation.

The singular object IPA.nav has been converted into an IPA.navigation
class. The admin and self-service navigation tabs have been converted
into subclasses of IPA.navigation and will be instantiated according
to user authorization.
This commit is contained in:
Endi S. Dewata 2011-04-20 19:11:10 -05:00
parent e64c1995d4
commit 238da3dffd
5 changed files with 250 additions and 250 deletions

View File

@ -333,7 +333,7 @@ IPA.get_nested_tab_label = function(entity_name){
any nested tabs underneath it or any nested tabs underneath it or
its parent tab and the others nested at the same level*/ its parent tab and the others nested at the same level*/
IPA.nested_tabs = function(entity_name){ IPA.nested_tabs = function(entity_name) {
var siblings = []; var siblings = [];
var i; var i;
@ -349,14 +349,14 @@ IPA.nested_tabs = function(entity_name){
} }
if (!IPA.tab_set) { if (!IPA.nav.tabs) {
siblings.push(entity_name); siblings.push(entity_name);
return siblings; return siblings;
} }
for (var top_i = 0; top_i < IPA.tab_set.length; top_i += 1){ for (var top_i = 0; top_i < IPA.nav.tabs.length; top_i++) {
var top_tab = IPA.tab_set[top_i]; var top_tab = IPA.nav.tabs[top_i];
for (sub_i = 0; sub_i < top_tab.children.length; sub_i += 1){ for (sub_i = 0; sub_i < top_tab.children.length; sub_i++) {
sub_tab = top_tab.children[sub_i]; sub_tab = top_tab.children[sub_i];
nested_entities = sub_tab.children; nested_entities = sub_tab.children;
if (sub_tab.name === entity_name){ if (sub_tab.name === entity_name){
@ -379,6 +379,7 @@ IPA.nested_tabs = function(entity_name){
} }
} }
} }
return siblings; return siblings;
}; };
@ -454,7 +455,7 @@ IPA.entity_header = function(spec){
return false; return false;
} }
IPA.switch_and_show_page(entity.name, 'search'); IPA.show_page(entity.name, 'search');
$(that.facet_tabs).find('a').removeClass('selected'); $(that.facet_tabs).find('a').removeClass('selected');
return false; return false;
@ -482,7 +483,7 @@ IPA.entity_header = function(spec){
return false; return false;
} }
var this_pkey = that.pkey_field.val(); var this_pkey = that.pkey_field.val();
IPA.switch_and_show_page( IPA.show_page(
entity_name, other_facet_name, entity_name, other_facet_name,
this_pkey); this_pkey);
$(that.facet_tabs).find('a').removeClass('selected'); $(that.facet_tabs).find('a').removeClass('selected');

View File

@ -134,22 +134,22 @@ var IPA = ( function () {
return that.entities_by_name[name]; return that.entities_by_name[name];
}; };
function add_entity(entity) { that.add_entity = function(entity) {
that.entities.push(entity); that.entities.push(entity);
that.entities_by_name[entity.name] = entity; that.entities_by_name[entity.name] = entity;
} };
that.start_entities = function(){ that.start_entities = function() {
var factory; var factory;
var name ; var name;
for (name in that.entity_factories){ for (name in that.entity_factories) {
factory = that.entity_factories[name]; factory = that.entity_factories[name];
try{ try {
var entity = factory(); var entity = factory();
add_entity(entity); that.add_entity(entity);
entity.init(); entity.init();
}catch(e){ } catch (e) {
/*exceptions thrown by builder just mean that entities /*exceptions thrown by builder just mean that entities
are not to be registered. */ are not to be registered. */
} }
} }
@ -185,31 +185,19 @@ var IPA = ( function () {
return true; return true;
}; };
that.show_page = function (entity_name, facet_name) { that.show_page = function(entity_name, facet_name, pkey) {
if (!IPA.test_dirty()){ if (!IPA.test_dirty()) {
return false; return;
} }
var state = {}; var state = {};
if (pkey) {
state[entity_name + '-pkey'] = pkey;
}
state[entity_name + '-facet'] = facet_name; state[entity_name + '-facet'] = facet_name;
$.bbq.pushState(state); $.bbq.pushState(state);
return true;
};
that.switch_and_show_page = function (this_entity, facet_name, pkey) {
if (!IPA.test_dirty()){
return false;
}
if (!pkey){
that.show_page(this_entity, facet_name);
return false;
}
var state = {};
state[this_entity+'-pkey'] = pkey;
state[this_entity + '-facet'] = facet_name;
$.bbq.pushState(state);
return true;
}; };
that.display_activity_icon = function() { that.display_activity_icon = function() {

View File

@ -2,6 +2,7 @@
/* Authors: /* Authors:
* Pavel Zuna <pzuna@redhat.com> * Pavel Zuna <pzuna@redhat.com>
* Endi S. Dewata <edewata@redhat.com>
* *
* Copyright (C) 2010 Red Hat * Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information * see file 'COPYING' for use and warranty information
@ -20,39 +21,38 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
IPA.nav = { IPA.navigation = function(spec) {
tabs_lists : {},
nav_container : {},
push_state : function (params) { spec = spec || {};
if (!IPA.test_dirty()){
var that = {};
that.container = spec.container;
that.tab_class = spec.tab_class || 'tabs';
that.tabs = spec.tabs || [];
that.push_state = function(params) {
if (!IPA.test_dirty()) {
return false; return false;
} }
$.bbq.pushState(params); $.bbq.pushState(params);
return true; return true;
}, };
get_state : function (key) { that.get_state = function(key) {
return $.bbq.getState(key, true); return $.bbq.getState(key, true);
}, };
remove_state : function (key) { that.remove_state = function(key) {
$.bbq.removeState(key); $.bbq.removeState(key);
}, };
create : function (nls, container, tabclass) { that.create = function() {
if (!container){
container = $('#navigation');
}
if (!tabclass){
tabclass = 'tabs';
}
IPA.nav.tabs_lists = nls;
IPA.nav.nav_container = container;
IPA.nav.generate_tabs(nls, container, tabclass, 1); that._create(that.tabs, that.container, 1);
var tabs = $('.' + tabclass); var tabs = $('.' + that.tab_class);
tabs.tabs({ tabs.tabs({
select: function(event, ui) { select: function(event, ui) {
var panel = $(ui.panel); var panel = $(ui.panel);
@ -60,21 +60,22 @@ IPA.nav = {
var id = parent.attr('id'); var id = parent.attr('id');
var state = {}; var state = {};
state[id] = ui.index; state[id] = ui.index;
return IPA.nav.push_state(state); return that.push_state(state);
} }
}); });
}, };
generate_tabs : function (nls, container, tabclass, depth) { that._create = function(tabs, container, depth) {
container.addClass(tabclass);
container.addClass(that.tab_class);
container.addClass('tabs'+depth); container.addClass('tabs'+depth);
var ul = $('<ul/>'); var ul = $('<ul/>').appendTo(container);
container.append(ul);
for (var i = 0; i < nls.length; i += 1) { for (var i=0; i<tabs.length; i++) {
var tab = nls[i]; var tab = tabs[i];
if (tab.entity){
if (!tab.name) {
tab.name = tab.entity; tab.name = tab.entity;
} }
@ -82,8 +83,8 @@ IPA.nav = {
if (tab.entity) { if (tab.entity) {
var entity = IPA.get_entity(tab.entity); var entity = IPA.get_entity(tab.entity);
if (!entity){ if (!entity){
nls.splice(i,1); tabs.splice(i, 1);
i -= 1; i--;
continue; continue;
} }
label = entity.label; label = entity.label;
@ -93,60 +94,65 @@ IPA.nav = {
label = tab.label; label = tab.label;
} }
var li = IPA.nav.create_tab_li(tab.name, label); var li = that.create_tab_li(tab.name, label);
ul.append(li); ul.append(li);
var div = IPA.nav.create_tab_div(tab.name); var div = that.create_tab_div(tab.name);
container.append(div); container.append(div);
if (tab.entity) { if (tab.entity) {
div.addClass('entity-container'); div.addClass('entity-container');
} }
if (tab.children) { if (tab.children && tab.children.length) {
IPA.nav.generate_tabs(tab.children, div, tabclass, depth +1 ); that._create(tab.children, div, depth+1);
} }
} }
}, };
create_tab_li : function (id, name) { that.create_tab_li = function(id, name) {
return $('<li/>').append($('<a/>', { return $('<li/>').append($('<a/>', {
href: '#'+id, href: '#'+id,
title: id, title: id,
html: name html: name
})); }));
}, };
create_tab_div : function (id) { that.create_tab_div = function(id) {
return $('<div/>', { return $('<div/>', {
id: id id: id
}); });
}, };
update_tabs : function () { that.update = function() {
IPA.nav._update_tabs(IPA.nav.tabs_lists, IPA.nav.nav_container,1); that._update(that.tabs, that.container, 1);
}, };
that._update = function(tabs, container, depth) {
_update_tabs : function (nls, container,depth) {
var id = container.attr('id'); var id = container.attr('id');
var index = IPA.nav.get_state(id); var index = that.get_state(id);
if (!index || index >= nls.length) index = 0; if (!index || index >= tabs.length) index = 0;
container.tabs('select', index); container.tabs('select', index);
var tab = nls[index]; var tab = tabs[index];
var container2 = $('#' + tab.name); var container2 = $('#' + tab.name);
if (tab.children) { if (tab.children && tab.children.length) {
IPA.nav._update_tabs(tab.children, container2,depth+1); that._update(tab.children, container2, depth+1);
} else if (tab.entity) { } else if (tab.entity) {
tab.entity.setup(container2); tab.entity.setup(container2);
} }
} };
// methods that should be invoked by subclasses
that.navigation_update = that.update;
return that;
}; };
IPA.tab_state = function(entity_name,tab){ IPA.tab_state = function(entity_name,tab){
var state; var state;
var i; var i;
@ -154,7 +160,7 @@ IPA.tab_state = function(entity_name,tab){
var tab_name; var tab_name;
if (!tab){ if (!tab){
children = IPA.tab_set; children = IPA.nav.tabs;
tab_name = 'navigation'; tab_name = 'navigation';
}else if (tab.children){ }else if (tab.children){
children = tab.children; children = tab.children;

View File

@ -34,13 +34,7 @@ module('navigation', {
} }
}); });
test("Testing IPA.nav.create().", function() { test("Testing IPA.navigation.create().", function() {
var mock_tabs_lists = [
{ name:'identity', label:'IDENTITY', children: [
{name:'user', entity:'user'},
{name:'group', entity:'group'}
]}];
var entity; var entity;
@ -68,54 +62,66 @@ test("Testing IPA.nav.create().", function() {
IPA.start_entities(); IPA.start_entities();
IPA.metadata = {}; IPA.metadata = {};
var navigation = $('<div id="navigation"/>').appendTo(document.body); var container = $('<div id="navigation"/>').appendTo(document.body);
var user_mock_called = false; var user_mock_called = false;
var group_mock_called = false; var group_mock_called = false;
IPA.nav.create(mock_tabs_lists, navigation, 'tabs');
IPA.nav.update_tabs(); var navigation = IPA.navigation({
container: container,
tabs: [
{ name:'identity', label:'IDENTITY', children: [
{name:'user', entity:'user'},
{name:'group', entity:'group'}
]}
]
});
navigation.create();
navigation.update();
ok(user_mock_called, "mock user setup was called"); ok(user_mock_called, "mock user setup was called");
ok(!group_mock_called, "mock group setup was not called because the tab is inactive"); ok(!group_mock_called, "mock group setup was not called because the tab is inactive");
same( navigation[0].children.length, 2, "Two Child tabs"); same( container[0].children.length, 2, "Two Child tabs");
same( navigation[0].children[1].id, 'identity', "Identity Tab"); same( container[0].children[1].id, 'identity', "Identity Tab");
same( navigation[0].children[1].children[1].id, 'user', "User Tab"); same( container[0].children[1].children[1].id, 'user', "User Tab");
same( navigation[0].children[1].children[2].id, 'group', "User Tab"); same( container[0].children[1].children[2].id, 'group', "User Tab");
navigation.remove(); container.remove();
}); });
test("Testing IPA.nav.update_tabs() with valid index.", function() { test("Testing IPA.navigation.update() with valid index.", function() {
var orig_push_state = IPA.nav.push_state; var container = $('<div id="navigation"/>').appendTo(document.body);
var orig_get_state = IPA.nav.get_state;
var orig_remove_state = IPA.nav.remove_state;
var state = {}; var navigation = IPA.navigation({
container: container,
IPA.nav.push_state = function(params) { tabs: [
$.extend(state, params);
};
IPA.nav.get_state = function(key) {
return state[key];
};
IPA.nav.remove_state = function(key) {
delete state[key];
};
var mock_tabs_lists =
[
{ name:'identity', label:'IDENTITY', children: [ { name:'identity', label:'IDENTITY', children: [
{name:'one', label:'One', setup: function (){}}, {name:'one', label:'One', setup: function (){}},
{name:'two', label:'Two', setup: function (){}} {name:'two', label:'Two', setup: function (){}}
]}]; ]}
]
});
var navigation = $('<div id="navigation"/>').appendTo(document.body); var state = {};
IPA.nav.create(mock_tabs_lists, navigation, 'tabs'); navigation.push_state = function(params) {
$.extend(state, params);
};
IPA.nav.push_state({"identity":1}); navigation.get_state = function(key) {
IPA.nav.update_tabs(); return state[key];
};
navigation.remove_state = function(key) {
delete state[key];
};
navigation.create();
navigation.push_state({"identity":1});
navigation.update();
same( same(
navigation.tabs('option', 'selected'), 0, container.tabs('option', 'selected'), 0,
"Active tab at level 1" "Active tab at level 1"
); );
@ -124,49 +130,45 @@ test("Testing IPA.nav.update_tabs() with valid index.", function() {
"Active tab at level 2" "Active tab at level 2"
); );
IPA.nav.remove_state("identity"); navigation.remove_state("identity");
navigation.remove(); container.remove();
IPA.nav.push_state = orig_push_state;
IPA.nav.get_state = orig_get_state;
IPA.nav.remove_state = orig_remove_state;
}); });
test("Testing IPA.nav.update_tabs() with out-of-range index.", function() { test("Testing IPA.navigation.update() with out-of-range index.", function() {
var orig_push_state = IPA.nav.push_state; var container = $('<div id="navigation"/>').appendTo(document.body);
var orig_get_state = IPA.nav.get_state;
var orig_remove_state = IPA.nav.remove_state;
var state = {}; var navigation = IPA.navigation({
container: container,
IPA.nav.push_state = function(params) { tabs: [
$.extend(state, params);
};
IPA.nav.get_state = function(key) {
return state[key];
};
IPA.nav.remove_state = function(key) {
delete state[key];
};
var mock_tabs_lists =
[
{ name:'identity', label:'IDENTITY', children: [ { name:'identity', label:'IDENTITY', children: [
{name:'one', label:'One', setup: function (){}}, {name:'one', label:'One', setup: function (){}},
{name:'two', label:'Two', setup: function (){}} {name:'two', label:'Two', setup: function (){}}
]}]; ]}
]
});
var navigation = $('<div id="navigation"/>').appendTo(document.body); var state = {};
IPA.nav.create(mock_tabs_lists, navigation, 'tabs'); navigation.push_state = function(params) {
$.extend(state, params);
};
IPA.nav.push_state({"identity":2}); navigation.get_state = function(key) {
IPA.nav.update_tabs(); return state[key];
};
navigation.remove_state = function(key) {
delete state[key];
};
navigation.create();
navigation.push_state({"identity":2});
navigation.update();
same( same(
navigation.tabs('option', 'selected'), 0, container.tabs('option', 'selected'), 0,
"Active tab at level 1" "Active tab at level 1"
); );
@ -175,11 +177,7 @@ test("Testing IPA.nav.update_tabs() with out-of-range index.", function() {
"Active tab at level 2" "Active tab at level 2"
); );
IPA.nav.remove_state("identity"); navigation.remove_state("identity");
navigation.remove(); container.remove();
IPA.nav.push_state = orig_push_state;
IPA.nav.get_state = orig_get_state;
IPA.nav.remove_state = orig_remove_state;
}); });

View File

@ -3,6 +3,7 @@
/* Authors: /* Authors:
* Pavel Zuna <pzuna@redhat.com> * Pavel Zuna <pzuna@redhat.com>
* Endi S. Dewata <edewata@redhat.com>
* *
* Copyright (C) 2010 Red Hat * Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information * see file 'COPYING' for use and warranty information
@ -25,82 +26,111 @@
/* tabs definition for IPA webUI */ /* tabs definition for IPA webUI */
IPA.admin_navigation = function(spec) {
IPA.admin_tab_set = function () { spec = spec || {};
var tabset = [
{name:'identity', label: IPA.messages.tabs.identity, children:[ spec.tabs = [
{entity:'user'}, {name: 'identity', label: IPA.messages.tabs.identity, children: [
{entity:'group'}, {entity: 'user'},
{entity:'host'}, {entity: 'group'},
{entity:'hostgroup'}, {entity: 'host'},
{entity:'netgroup'}, {entity: 'hostgroup'},
{entity:'service'} {entity: 'netgroup'},
{entity: 'service'}
]}, ]},
{name:'policy', label: IPA.messages.tabs.policy, children:[ {name: 'policy', label: IPA.messages.tabs.policy, children: [
{entity:'dnszone'}, {entity: 'dnszone'},
{name:'hbac', label: IPA.messages.tabs.hbac , {name: 'hbac', label: IPA.messages.tabs.hbac, children: [
children:[ {entity: 'hbacrule'},
{entity:'hbacrule'}, {entity: 'hbacsvc'},
{entity:'hbacsvc'}, {entity: 'hbacsvcgroup'}
{entity:'hbacsvcgroup'}
]}, ]},
{name:'sudo', label: IPA.messages.tabs.sudo, {name: 'sudo', label: IPA.messages.tabs.sudo, children: [
children:[ {entity: 'sudorule'},
{entity:'sudorule'}, {entity: 'sudocmd'},
{entity:'sudocmd'}, {entity: 'sudocmdgroup'}
{entity:'sudocmdgroup'}
]}, ]},
// {entity:'automountlocation'}, // {entity: 'automountlocation'},
{entity:'pwpolicy'}, {entity: 'pwpolicy'},
{entity:'krbtpolicy'} {entity: 'krbtpolicy'}
]}, ]},
{name:'ipaserver', label: IPA.messages.tabs.ipaserver, children: [ {name: 'ipaserver', label: IPA.messages.tabs.ipaserver, children: [
{name:'rolebased', label: IPA.messages.tabs.role, {name: 'rolebased', label: IPA.messages.tabs.role, children: [
children:[ {entity: 'role'},
{entity:'role'}, {entity: 'privilege'},
{entity:'privilege'}, {entity: 'permission'}
{entity:'permission'}
]}, ]},
{entity:'selfservice'}, {entity: 'selfservice'},
{entity:'delegation'}, {entity: 'delegation'},
{entity:'entitle'}, {entity: 'entitle'},
{entity:'config'} {entity: 'config'}
]}]; ]}];
return tabset; var that = IPA.navigation(spec);
return that;
}; };
IPA.self_serv_tab_set = function(){ IPA.self_serv_navigation = function(spec) {
return [ { name:'identity',
children: spec = spec || {};
[
{entity:'user'}, spec.tabs = [
{entity:'group'} {name: 'identity', children: [
] {entity: 'user'},
} {entity: 'group'}
]; ]}];
var that = IPA.navigation(spec);
that.update = function() {
var pkey = $.bbq.getState('user-pkey');
var facet = $.bbq.getState('user-facet');
if (pkey && facet) {
that.navigation_update();
} else {
var state = {
'user-pkey': pkey || IPA.whoami_pkey,
'user-facet': facet || 'details'
};
$.bbq.pushState(state);
}
};
return that;
}; };
/* main (document onready event handler) */ /* main (document onready event handler) */
$(function() { $(function() {
/* main loop (hashchange event handler) */ /* main loop (hashchange event handler) */
function window_hashchange(evt){ function window_hashchange(evt){
IPA.nav.update_tabs(); IPA.nav.update();
} }
function should_show_all_ui(){ function create_navigation() {
var whoami = IPA.whoami; var whoami = IPA.whoami;
var factory;
if (whoami.hasOwnProperty('memberof_group') && if (whoami.hasOwnProperty('memberof_group') &&
whoami.memberof_group.indexOf('admins') !== -1) return true; whoami.memberof_group.indexOf('admins') !== -1) {
factory = IPA.admin_navigation;
return whoami.hasOwnProperty('memberof_rolegroup') && } else if (whoami.hasOwnProperty('memberof_rolegroup') &&
whoami.memberof_rolegroup.length > 0; whoami.memberof_rolegroup.length > 0) {
factory = IPA.admin_navigation;
} else {
factory = IPA.self_serv_navigation;
}
return factory({
container: $('#navigation')
});
} }
@ -108,49 +138,26 @@ $(function() {
$(window).bind('hashchange', window_hashchange); $(window).bind('hashchange', window_hashchange);
var whoami = IPA.whoami; var whoami = IPA.whoami;
IPA.whoami_pkey=whoami.uid[0]; IPA.whoami_pkey = whoami.uid[0];
$('#loggedinas').find('strong').text(whoami.cn[0]); $('#loggedinas strong').text(whoami.cn[0]);
$('#loggedinas a').fragment( $('#loggedinas a').fragment(
{'user-facet':'details', 'user-pkey':IPA.whoami_pkey},2); {'user-facet': 'details', 'user-pkey': IPA.whoami_pkey}, 2);
IPA.start_entities(); IPA.start_entities();
var navigation = $('#navigation'); IPA.nav = create_navigation();
IPA.nav.create();
if (should_show_all_ui()){ IPA.nav.update();
IPA.tab_set = IPA.admin_tab_set();
IPA.nav.create(IPA.tab_set, navigation, 'tabs');
IPA.nav.update_tabs();
} else {
IPA.tab_set = IPA.self_serv_tab_set();
IPA.nav.create(IPA.tab_set, navigation, 'tabs');
var pkey = $.bbq.getState('user-pkey');
var facet = $.bbq.getState('user-facet');
if (pkey && facet) {
IPA.nav.update_tabs();
} else {
var state = {
'user-pkey': pkey || IPA.whoami_pkey,
'user-facet': facet || 'details'
};
$.bbq.pushState(state);
}
}
$('#login_header').html(IPA.messages.login.header); $('#login_header').html(IPA.messages.login.header);
} }
function init_on_error(xhr, text_status, error_thrown) { function init_on_error(xhr, text_status, error_thrown) {
var navigation = $('#navigation').empty(); var container = $('#navigation').empty();
navigation.append('<p>Error: '+error_thrown.name+'</p>'); container.append('<p>Error: '+error_thrown.name+'</p>');
navigation.append('<p>'+error_thrown.title+'</p>'); container.append('<p>'+error_thrown.title+'</p>');
navigation.append('<p>'+error_thrown.message+'</p>'); container.append('<p>'+error_thrown.message+'</p>');
} }
IPA.init(null, null, init_on_win, init_on_error); IPA.init(null, null, init_on_win, init_on_error);