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
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 i;
@ -349,14 +349,14 @@ IPA.nested_tabs = function(entity_name){
}
if (!IPA.tab_set) {
if (!IPA.nav.tabs) {
siblings.push(entity_name);
return siblings;
}
for (var top_i = 0; top_i < IPA.tab_set.length; top_i += 1){
var top_tab = IPA.tab_set[top_i];
for (sub_i = 0; sub_i < top_tab.children.length; sub_i += 1){
for (var top_i = 0; top_i < IPA.nav.tabs.length; top_i++) {
var top_tab = IPA.nav.tabs[top_i];
for (sub_i = 0; sub_i < top_tab.children.length; sub_i++) {
sub_tab = top_tab.children[sub_i];
nested_entities = sub_tab.children;
if (sub_tab.name === entity_name){
@ -379,6 +379,7 @@ IPA.nested_tabs = function(entity_name){
}
}
}
return siblings;
};
@ -454,7 +455,7 @@ IPA.entity_header = function(spec){
return false;
}
IPA.switch_and_show_page(entity.name, 'search');
IPA.show_page(entity.name, 'search');
$(that.facet_tabs).find('a').removeClass('selected');
return false;
@ -482,7 +483,7 @@ IPA.entity_header = function(spec){
return false;
}
var this_pkey = that.pkey_field.val();
IPA.switch_and_show_page(
IPA.show_page(
entity_name, other_facet_name,
this_pkey);
$(that.facet_tabs).find('a').removeClass('selected');

View File

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

View File

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

View File

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

View File

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