Big webUI patch.

Quick summary:
- use jQuery UI and jQuery BBQ libraries
- code restructuring

The patch has so many changes they can't be listed here. Many parts
of the code have been rewritten from scrach.

See freeipa-devel mailing list:
webUI code restructuring [wall of text, diagrams, ... you've been warned!]
2010-09-07
This commit is contained in:
Pavel Zuna
2010-09-16 10:28:07 -04:00
committed by Adam Young
parent 4f37775db7
commit 1bb412239d
22 changed files with 1267 additions and 2143 deletions

View File

@@ -23,6 +23,8 @@ app_DATA = \
pageparams.js \
search.js \
details.js \
entity.js \
webui.js \
user.js \
user-add.inc \
ipalogo.png \

View File

@@ -1,5 +1,5 @@
/* Authors:
* Adam Young <ayoung@redhat.com>
* Pavel Zuna <pzuna@redhat.com>
*
* Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information
@@ -16,107 +16,94 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* IPA Object Add - creating new instances of entities */
*/
/* REQUIRES: ipa.js */
var IPA_ADD_POPULATE = 1;
var IPA_ADD_UPDATE = 2;
//Process for managing the 'add' functionality
function EntityBuilder(obj,addProperties){
function add_dialog_create(obj_name, adl)
{
var add_dialog = $('<div></div>');
var builder = this;
this.obj = obj;
this.addProperties = addProperties;
this.getPKey = function(){
return $("#pkey").val();
}
this.getOptions = function(){
return {};
}
this.add_fail = function(desc){
alert(desc);
}
this.add = function(pkey, on_success){
var params = [pkey];
var options = this.getOptions();
ipa_cmd( 'add', params, options, on_success, this.add_fail, this.obj );
}
this.setup = function(){
showContent();
$("<h1/>" ,{ html : "Add new " + this.obj } ).appendTo("#content");
$("<div id='addForm'> </div>")
.appendTo("#content");
var label =$("<span>Add and </span>").appendTo("#addForm")
$("<input \>", {
id:'addEdit',
type:'button',
value:'Edit',
click: function(){
var params = ipa_parse_qs();
var pkey = builder.getPKey();
builder.add(pkey, function(response){
if (response.error){
if (response.error.message) {
alert(response.error.message);
} else {
alert("error adding entry");
}
return;
}
var hash= "tab="
+params["tab"]
+"&facet=details&pkey="
+pkey;
window.location.hash = hash;
});
function add(evt, called_from_add_and_edit) {
function add_win(data, text_status, xhr) {
if (called_from_add_and_edit) {
var state = {};
state[obj_name + '-facet'] = 'details';
var pkey_name = ipa_objs[obj_name].primary_key;
var selector = 'input[name=' + pkey_name + ']';
state[obj_name + '-pkey'] = add_dialog.find(selector).val();
$.bbq.pushState(state);
}
}).appendTo(label);
};
$("<input\>", {
id:'addAnother',
type:'button',
value:'Add Another',
click: function(){
var params = ipa_parse_qs();
var pkey = builder.getPKey();
builder.add(pkey, function(response){
if (response.error){
if (response.error.message) {
alert(response.error.message);
} else {
alert("error adding entry");
}
return;
}
builder.setup();
});
var pkey = [];
var options = {};
var pkey_name = ipa_objs[obj_name].primary_key;
var fields = adl[2];
for (var i = 0; i < fields.length; ++i) {
var f = fields[i];
var attr = f[0];
if (typeof f[2] == 'function') {
var value = f[2](add_dialog, IPA_ADD_UPDATE);
if (value != null) {
if (attr == pkey_name)
pkey = [value];
else
options[attr] = value;
}
}
}).appendTo(label);
}
$("<dl id='addProperties' />").appendTo("#addForm");
add_dialog.find('input').each(function () {
var jobj = $(this);
var attr = jobj.attr('name');
var value = jobj.val();
if (value) {
if (pkey.length == 0 && attr == pkey_name)
pkey = [jobj.val()];
else if (options[attr] == null)
options[attr] = jobj.val();
}
});
for (index = 0; index < this.addProperties.length; index++){
var prop = this.addProperties[index];
var title = $("<dt/>",{html:prop.title});
var definition = $("<dd></dd>");
$("<input/>",{
id:prop.id,
type:prop.type
}).appendTo(definition);
definition.appendTo(title);
title.appendTo("#addProperties");
ipa_cmd('add', pkey, options, add_win, null, obj_name);
add_dialog.dialog('close');
};
function add_and_edit(evt) {
add(evt, true);
add_dialog.dialog('close');
};
function cancel() {
add_dialog.dialog('close');
};
add_dialog.attr('id', adl[0]);
add_dialog.attr('title', adl[1]);
var fields = adl[2];
for (var i = 0; i < fields.length; ++i) {
var f = fields[i];
if (typeof f[2] == 'function') {
f[2](add_dialog, IPA_ADD_POPULATE);
} else {
add_dialog.append('<label>' + f[1] + '</label>');
add_dialog.append('<input type="text" name="' + f[0] + '" />');
}
}
add_dialog.dialog({
modal: true,
buttons: {
'Add': add,
'Add and edit': add_and_edit,
'Cancel': cancel
}
});
}

View File

@@ -16,22 +16,17 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* IPA Object Add - creating new instances of entities */
*/
/* REQUIRES: ipa.js */
function keyForFacet(tab, facet){
qs = ipa_parse_qs();
var key = qs['tab'] +'-'+ qs['facet'];
return key;
}
/* CURRENTLY ALSO REQUIRES search.js, because it reuses it's code to create
* the AssociationList elements; IT NEEDS IT'S OWN CODE! */
/**
*This associator is built for the case where each association requires a separate rpc
*/
function SerialAssociator(form, oneObjPkey, manyObjPkeys){
function SerialAssociator(form, oneObjPkey, manyObjPkeys)
{
this.form = form;
this.manyObjPkeys = manyObjPkeys;
this.oneObjPkey = oneObjPkey;
@@ -55,27 +50,28 @@ function SerialAssociator(form, oneObjPkey, manyObjPkeys){
},
form.manyObj );
}else{
location.hash="tab="+form.oneObj
+"&facet=details&pkey="+this.oneObjPkey;
var state = {};
state[form.oneObj + '-facet'] = 'associate';
state[form.oneObj + '-pkey'] = this.oneObjPkey;
$.bbq.pushState(state);
}
}
}
/**
*This associator is for the common case where all the asociations can be sent
in a single rpc
*/
function BulkAssociator(form, pkey, manyObjPkeys){
function BulkAssociator(form, pkey, manyObjPkeys)
{
this.form = form;
this.pkey = pkey;
this.manyObjPkeys = manyObjPkeys;
this.form = form;
this.pkey =pkey;
this.manyObjPkeys = manyObjPkeys;
this.associateNext = function(){
this.associateNext = function() {
var form = this.form;
var option = manyObjPkeys.shift();
while(manyObjPkeys.length > 0){
while(manyObjPkeys.length > 0) {
option += "," + manyObjPkeys.shift();
}
@@ -85,15 +81,16 @@ function BulkAssociator(form, pkey, manyObjPkeys){
options[form.manyObj] = option;
var args = [this.pkey];
var associator = this;
ipa_cmd( form.method,args, options ,
function(response){
var qs = ipa_parse_qs();
if (response.error){
alert("error adding memeber");
}else{
location.hash="tab=" +form.oneObj
+"&facet=details&pkey="+associator.pkey;
var state = {};
state[form.onObj + '-facet'] = 'associate';
state[form.oneObj + '-pkey'] = this.pkey;
$.bbq.pushState(state);
}
},
function(response){
@@ -107,45 +104,42 @@ function BulkAssociator(form, pkey, manyObjPkeys){
* Create a form for a one to many association.
*
*/
function AssociationForm(oneObj, manyObj,facet,facets, searchColumn, headerText , associatorConstructor, method){
function AssociationForm(oneObj, manyObj, pkey, jobj, associatorConstructor, method)
{
this.oneObj = oneObj;
this.manyObj = manyObj;
this.facet = facet;
this.facets = facets;
this.headerText = headerText;
this.searchColumn = searchColumn;
this.searchColumn = pkey;
this.parentTab = jobj
//An optional parameter to determine what ipa method to call to create
//the association
if (method){
if (method)
this.method = method;
}else{
else
this.method = 'add_member';
}
if (associatorConstructor){
if (associatorConstructor)
this.associatorConstructor = associatorConstructor;
}else{
else
this.associatorConstructor = SerialAssociator;
}
this.setup = function(pkey){
showAssociations();
qs = ipa_parse_qs();
$("#availableList").html("");
$("#enrollments").html("");
this.setup = function() {
association_form_create(this.parentTab);
this.parentTab.find('#availableList').html('');
this.parentTab.find('#enrollments').html('');
setupFacetNavigation(this.oneObj,qs['pkey'],qs['facet'],this.facets);
this.currentUserToEnroll = qs['pkey'];
this.manyObjPkeys = [];
var currentObjToEnroll = $.bbq.getState(this.oneObj + '-pkey', true) || '';
var form = this;
$('h1').text(this.headerText());
$("#enroll").click(function(){
$('h1').text('Enroll ' + this.oneObj + ' ' + currentObjToEnroll + ' in ' + this.manyObj + '.');
$('#enroll').click(function () {
form.associate();
});
$('#cancel').click(function () {
var state = {};
state[form.oneObj + '-facet'] = 'associate';
$.bbq.pushState(state);
});
$("#addToList").click(function(){
$('#availableList :selected').each(function(i, selected){
$("#enrollments").append(selected);
@@ -161,97 +155,91 @@ function AssociationForm(oneObj, manyObj,facet,facets, searchColumn, headerText
$("#find").click(function(){
form.search();
});
}
this.search = function(){
var queryFilter = $("#associateFilter").val();
};
this.search = function() {
var form = this;
ipa_cmd( 'find', [queryFilter], {},
function(searchResults){
form.populateSearch(searchResults);
},
function(){
alert("associationSearchFailure");
},
this.manyObj);
}
this.associate = function(){
var manyObjPkeys = [];
$('#enrollments').children().each(function(i, selected){
function search_on_win(data, text_status, xhr) {
var results = data.result;
$("#availableList").html("");
for (var i =0; i != results.count; i++){
var result = results.result[i];
$("<option></option>",{
value: result[form.searchColumn][0],
html: result[form.searchColumn][0]
}).appendTo( $("#availableList"));
}
};
function search_on_fail(xhr, text_status, errow_thrown) {
alert("associationSearchFailure");
};
var queryFilter = $('#associateFilter').val();
ipa_cmd('find', [queryFilter], {}, search_on_win, null, this.manyObj);
};
this.associate = function () {
var manyObjPkeys = [];
$('#enrollments').children().each(function (i, selected) {
manyObjPkeys.push(selected.value);
});
var pkey = qs['pkey'];
var pkey = $.bbq.getState(this.oneObj + '-pkey', true) || '';
var associator =
new this.associatorConstructor (this, pkey, manyObjPkeys);
new this.associatorConstructor(this, pkey, manyObjPkeys);
associator.associateNext();
}
this.populateSearch = function(searchResults){
var results = searchResults.result;
$("#availableList").html("");
for (var i =0; i != results.count; i++){
var result = results.result[i];
$("<option/>",{
value: result[this.searchColumn][0],
html: result[this.searchColumn][0]
}).appendTo( $("#availableList"));
}
}
};
}
/**
A modfied version of search. It shows the associations for an object.
*/
function AssociationList(obj,facet,assignFacet,associationColumns,facets) {
function AssociationList(obj, assignFacet, associationColumns, jobj)
{
this.obj = obj;
this.facet = facet;
this.assignFacet = assignFacet;
this.associationColumns = associationColumns;
this.facets = facets;
this.assignFacet = assignFacet;
this.parentTab = jobj;
this.populate = function(userData){
var associationList = userData.result.result[this.associationColumns[0].column];
for (var j = 0; j < associationList.length; j++){
var row = $("<tr/>").appendTo($('#searchResultsTable thead:last'));
this.populate = function(userData) {
var tbody = this.parentTab.find('.search-table tbody');
tbody.empty();
var associationList = userData.result.result[this.associationColumns[0].column];
for (var j = 0; j < associationList.length; j++){
var row = $("<tr/>").appendTo(tbody);
for (var k = 0; k < associationColumns.length ;k++){
var column = this.associationColumns[k].column;
var link =
"#tab="+this.associationColumns[k].title
+"&facet=details"
+"&pkey="+userData.result.result[column][j];
$("<td/>",{
html: $("<a />",{
href:link,
html:userData.result.result[column][j]
})
$("<td></td>",{
html: userData.result.result[column][j]
}).appendTo(row);
}
}
}
this.setup=function(){
qs = ipa_parse_qs();
showSearch();
buildFacetNavigation(facets);
$("#filter").css("display","none");
$("#searchButtons").html("");
$("<input/>",{
this.setup = function() {
association_list_create(this.obj, this.parentTab);
var form = this;
var pkey_hash = this.obj + '-pkey';
var pkey = $.bbq.getState(pkey_hash, true) || '';
this.parentTab.find(".search-filter").css("display", "none");
this.parentTab.find(".search-buttons").html("");
$("<input/>", {
type: 'button',
value: 'enroll',
click: function(){
location.hash="tab="+obj+"&facet="+assignFacet+"&pkey="+qs['pkey'];
click: function() {
var state = {};
state[form.obj + '-facet'] = form.assignFacet;
$.bbq.pushState(state);
}
}).appendTo("#searchButtons");
var header = $("<tr/>").appendTo($('#searchResultsTable thead:last'));
}).appendTo(this.parentTab.find(".search-buttons"));
var header = $("<tr></tr>").appendTo(this.parentTab.find('.search-table thead:last'));
for (var i =0 ; i != associationColumns.length ;i++){
$("<th/>",{
$("<th></th>",{
html: associationColumns[i].title
}).appendTo(header);
}
var form = this;
ipa_cmd( 'show', [qs['pkey']], {},
ipa_cmd( 'show', [pkey], {},
function(result){
form.populate(result);
},
@@ -261,3 +249,114 @@ function AssociationList(obj,facet,assignFacet,associationColumns,facets) {
this.obj);
}
}
/* FIXME: TEMPORARY FACET GENERATORS; WE NEED A BETTER WAY! */
function association_form_create(jobj)
{
var div = $('<div id="associations"></div>');
div.append($('<h1></h1>', {
text: 'Enroll in Groups'
}));
var form = $('<form></form>');
var form_div = $('<div></div>');
form_div.css('border-width', '1px');
var sub_div = $('<div></div>');
sub_div.append($('<input />', {
id: 'associateFilter',
type: 'text'
}));
sub_div.append($('<input />', {
id: 'find',
type: 'button',
value: 'Find'
}));
var but_span = $('<span></span>');
but_span.css('float', 'right');
but_span.append($('<input />', {
id: 'cancel',
type: 'button',
value: 'Cancel'
}));
but_span.append($('<input />', {
id: 'enroll',
type: 'button',
value: 'Enroll'
}));
sub_div.append(but_span);
form_div.append(sub_div);
form.append(form_div);
var form_div = $('<div id="results"></div>');
form_div.css('border', '2px solid rgb(0, 0, 0)');
form_div.css('position', 'relative');
form_div.css('height', '200px');
var sub_div = $('<div></div>');
sub_div.css('float', 'left');
sub_div.append($('<div></div>', {
text: 'Available'
}));
sub_div.append($('<select></select>', {
id: 'availableList',
width: '150px',
size: '10',
multiple: 'true'
}));
form_div.append(sub_div);
var sub_div = $('<div></div>');
sub_div.css('float', 'left');
var p = $('<p></p>');
p.append($('<input />', {
id: 'removeFromList',
type: 'button',
value: '<<'
}));
sub_div.append(p);
var p = $('<p></p>');
p.append($('<input />', {
id: 'addToList',
type: 'button',
value: '>>'
}));
sub_div.append(p);
form_div.append(sub_div);
var sub_div = $('<div></div>');
sub_div.css('float', 'left');
sub_div.append($('<div></div>', {
text: 'Prospective'
}));
sub_div.append($('<select></select>', {
id: 'enrollments',
width: '150px',
size: '10',
multiple: 'true'
}));
form_div.append(sub_div);
form.append(form_div);
form.append($('<hr />'));
form.append($('<div></div>', {
text: 'Message Area'
}));
form.append($('<hr />'));
var form_div = $('<div></div>');
var span = $('<span></span>');
span.css('float', 'left');
span.append($('<p></p>', {
text: '*Enter Group Names and Press Groups'
}));
span.append($('<p></p>', {
text: '*More stuff'
}));
span.append($('<p></p>', {
text: '*More stuff'
}));
form_div.append(span);
form.append(form_div);
div.append(form);
jobj.append(div);
}
function association_list_create(obj_name, jobj)
{
search_create(obj_name, [], jobj);
}

View File

@@ -1,6 +1,5 @@
/* Authors:
* Pavel Zuna <pzuna@redhat.com>
* Adam Young <ayoung@redhat.com>
*
* Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information
@@ -26,65 +25,122 @@
var IPA_DETAILS_POPULATE = 1;
var IPA_DETAILS_UPDATE = 2;
/* name of IPA object, that we're populating the lists for */
var _ipa_obj_name = '';
var ipa_details_cache = {};
/* initialize the IPA Object Details library */
function ipa_details_init(obj_name, url)
function ipa_details_create(obj_name, dls, container)
{
_ipa_obj_name = obj_name;
if (!container) {
alert('ERROR: ipa_details_create: Missing container argument!');
return;
}
container.attr('title', obj_name);
container.addClass('details-container');
container.append('<div class="details-buttons"></div>');
var jobj = container.children().last();
jobj.append('<a class="details-reset" href="jslink">Reset</a>');
jobj.append('<a class="details-update" href="jslink">Update</a>');
container.append('<hr />');
for (var i = 0; i < dls.length; ++i) {
var d = dls[i];
ipa_generate_dl(container.children().last(), d[0], d[1], d[2]);
}
container.append('<div class="details-back"></div>');
var jobj = container.children().last();
jobj.append('<a href="#details-viewtype">Back to Top</a>');
}
var _ipa_load_on_win_callback = null;
var _ipa_load_on_fail_callback = null;
var _ipa_h2_template = '<h2 onclick="_h2_on_click(this)">&#8722; I</h2>';
var _ipa_dl_template = '<dl id="I" class="entryattrs"></dl>';
var _ipa_dt_template = '<dt title="T">N:</dt>';
var ipa_details_cache = null;
function ipa_details_load(pkey, on_win, on_fail)
function ipa_generate_dl(jobj, id, name, dts)
{
if (!pkey)
if (!dts)
return;
_ipa_load_on_win_callback = on_win;
_ipa_load_on_fail_callback = on_fail;
var obj_name = jobj.parent().attr('title');
jobj.after(_ipa_h2_template.replace('I', name));
jobj = jobj.next();
jobj.after(_ipa_dl_template.replace('I', id));
jobj = jobj.next();
for (var i = 0; i < dts.length; ++i) {
var label = '';
if (dts[i][0].indexOf('call_') != 0) {
var param_info = ipa_get_param_info(obj_name, dts[i][0]);
if (param_info)
label = param_info['label'];
}
if ((!label) && (dts[i].length > 1))
label = dts[i][1];
jobj.append(
_ipa_dt_template.replace('T', dts[i][0]).replace('N', label)
);
}
jobj.after('<hr />');
}
function ipa_details_load(obj_name, pkey, on_win, on_fail, sampleData)
{
function load_on_win(data, text_status, xhr) {
if (on_win)
on_win(data, text_status, xhr);
if (data.error)
return;
var result = data.result.result;
ipa_details_cache[obj_name] = $.extend(true, {}, result);
ipa_details_display(obj_name, result);
};
function load_on_fail(xhr, text_status, error_thrown) {
if (on_fail)
on_fail(xhr, text_status, error_thrown);
};
if (!pkey)
return;
ipa_cmd(
'show', [pkey], {all: true}, _ipa_load_on_win, _ipa_load_on_fail,
_ipa_obj_name);
'show', [pkey], {all: true}, load_on_win, load_on_fail,
obj_name, sampleData
);
}
function _ipa_load_on_win(data, text_status, xhr)
function ipa_details_update(obj_name, pkey, on_win, on_fail)
{
if (_ipa_load_on_win_callback)
_ipa_load_on_win_callback(data, text_status, xhr);
function update_on_win(data, text_status, xhr) {
if (on_win)
on_win(data, text_status, xhr);
if (data.error)
return;
if (data['error'])
return;
var result = data.result.result;
ipa_details_cache[obj_name] = $.extend(true, {}, result);
ipa_details_display(obj_name, result);
};
var result = data.result.result;
function update_on_fail(xhr, text_status, error_thrown) {
if (on_fail)
on_fail(xhr, text_status, error_thrown);
};
ipa_details_cache = $.extend(true, {}, result);
ipa_details_display(result);
}
function _ipa_load_on_fail(xhr, text_status, error_thrown)
{
if (_ipa_load_on_fail_callback)
_ipa_load_on_fail_callback(xhr, text_status, error_thrown);
}
var _ipa_update_on_win_callback = null;
var _ipa_update_on_fail_callback = null;
function ipa_details_update(pkey, on_win, on_fail)
{
if (!pkey)
return;
var selector = '.details-container[title=' + obj_name + ']';
var modlist = {'all': true, 'setattr': [], 'addattr': []};
var attrs_wo_option = {};
$('.entryattrs input').each(function () {
$(selector + ' .entryattrs input').each(function () {
var jobj = $(this);
var dt = jobj.parent().prevAll('dt').slice(0, 1);
@@ -96,7 +152,7 @@ function ipa_details_update(pkey, on_win, on_fail)
return;
var value = jQuery.trim(jobj.val());
var param_info = ipa_get_param_info(attr);
var param_info = ipa_get_param_info(obj_name, attr);
if (param_info) {
modlist[attr] = value;
return;
@@ -107,7 +163,7 @@ function ipa_details_update(pkey, on_win, on_fail)
attrs_wo_option[attr].push(value);
});
$('.entryattrs dt').each(function () {
$(selector + ' .entryattrs dt').each(function () {
var jobj = $(this);
var attr = jobj.attr('title');
@@ -121,7 +177,7 @@ function ipa_details_update(pkey, on_win, on_fail)
return;
}
var param_info = ipa_get_param_info(attr);
var param_info = ipa_get_param_info(obj_name, attr);
if (param_info && param_info['primary_key'])
return;
@@ -138,76 +194,7 @@ function ipa_details_update(pkey, on_win, on_fail)
}
_ipa_update_on_win_callback = on_win;
_ipa_update_on_fail_callback = on_fail;
ipa_cmd(
'mod', [pkey], modlist, _ipa_update_on_win, _ipa_update_on_fail,
_ipa_obj_name
);
}
function _ipa_update_on_win(data, text_status, xhr)
{
if (_ipa_update_on_win_callback)
_ipa_update_on_win_callback(data, text_status, xhr);
if (data['error'])
return;
var result = data.result.result;
ipa_details_cache = $.extend(true, {}, result);
ipa_details_display(result);
}
function _ipa_update_on_fail(xhr, text_status, error_thrown)
{
if (_ipa_update_on_fail_callback)
_ipa_update_on_fail_callback(xhr, text_status, error_thrown);
}
function ipa_details_create(dls, container)
{
if (!container)
container = $('body');
for (var i = 0; i < dls.length; ++i) {
var d = dls[i];
ipa_generate_dl($('#detail-lists hr').last(), d[0], d[1], d[2]);
// ipa_generate_dl($("#detail-lists"), d[0], d[1], d[2]);
}
}
var _ipa_h2_template = '<h2 onclick="_h2_on_click(this)">&#8722; I</h2>';
var _ipa_dl_template = '<dl id="I" class="entryattrs"></dl>';
var _ipa_dt_template = '<dt title="T">N:</dt>';
function ipa_generate_dl(jobj, id, name, dts)
{
if (!dts)
return;
jobj.after(_ipa_h2_template.replace('I', name));
jobj = jobj.next();
jobj.after(_ipa_dl_template.replace('I', id));
jobj = jobj.next();
for (var i = 0; i < dts.length; ++i) {
var label = '';
if (dts[i][0].indexOf('call_') != 0) {
var param_info = ipa_get_param_info(dts[i][0]);
if (param_info)
label = param_info['label'];
}
if ((!label) && (dts[i].length > 1))
label = dts[i][1];
jobj.append(
_ipa_dt_template.replace('T', dts[i][0]).replace('N', label)
);
}
jobj.after('<hr />');
ipa_cmd('mod', [pkey], modlist, update_on_win, update_on_fail, obj_name);
}
/* HTML templates for ipa_details_display() */
@@ -230,13 +217,15 @@ var _ipa_span_doc_template = '<span class="attrhint">Hint: D</span>';
* arguments:
* entry_attrs - 'result' field as returned by ipa *-show commnads
* (basically an associative array with attr:value pairs) */
function ipa_details_display(entry_attrs)
function ipa_details_display(obj_name, entry_attrs)
{
var selector = '.details-container[title=' + obj_name + ']';
/* remove all <dd> tags i.e. all attribute values */
$('.entryattrs dd').remove();
$(selector + ' .entryattrs dd').remove();
/* go through all <dt> tags and pair them with newly created <dd>s */
$('.entryattrs dt').each(function () {
$(selector + ' .entryattrs dt').each(function () {
var jobj = $(this);
var attr = jobj.attr('title');
@@ -252,7 +241,7 @@ function ipa_details_display(entry_attrs)
var multivalue = false;
var hint_span = '';
var param_info = ipa_get_param_info(attr);
var param_info = ipa_get_param_info(obj_name, attr);
if (param_info) {
if (param_info['multivalue'] || param_info['class'] == 'List')
multivalue = true;
@@ -264,11 +253,13 @@ function ipa_details_display(entry_attrs)
var value = entry_attrs[attr];
if (value) {
ipa_insert_first_dd(
jobj, ipa_create_input(attr, value[0]) + hint_span
jobj, ipa_create_input(obj_name, attr, value[0]) + hint_span
);
for (var i = 1; i < value.length; ++i) {
jobj = jobj.next();
ipa_insert_other_dd(jobj, ipa_create_input(attr, value[i]));
ipa_insert_other_dd(
jobj, ipa_create_input(obj_name, attr, value[i])
);
}
if (multivalue) {
ipa_insert_other_dd(
@@ -282,7 +273,7 @@ function ipa_details_display(entry_attrs)
);
} else {
ipa_insert_first_dd(
jobj, ipa_create_input(attr, '') + hint_span
jobj, ipa_create_input(obj_name, attr, '') + hint_span
);
}
}
@@ -317,9 +308,9 @@ var _ipa_param_type_2_handler_map = {
* arguments:
* attr - LDAP attribute name
* value - the attributes value */
function ipa_create_input(attr, value)
function ipa_create_input(obj_name, attr, value)
{
var param_info = ipa_get_param_info(attr);
var param_info = ipa_get_param_info(obj_name, attr);
if (!param_info) {
/* no information about the param is available, default to text input */
return (_ipa_create_text_input(attr, value, null));
@@ -377,10 +368,10 @@ function _ipa_create_text_input(attr, value, param_info)
);
}
function ipa_details_reset()
function ipa_details_reset(obj_name)
{
if (ipa_details_cache)
ipa_details_display(ipa_details_cache);
if (ipa_details_cache[obj_name])
ipa_details_display(obj_name, ipa_details_cache[obj_name]);
}
@@ -391,8 +382,9 @@ function _ipa_add_on_click(obj)
var jobj = $(obj);
var attr = jobj.attr('title');
var par = jobj.parent();
var obj_name = jobj.closest('.details-container').attr('title');
par.prepend(ipa_create_input(attr, ''));
par.prepend(ipa_create_input(obj_name, attr, ''));
ipa_insert_other_dd(par, _ipa_a_add_template.replace('A', attr));
jobj.next('input').focus();
jobj.remove();
@@ -439,24 +431,3 @@ function _h2_on_click(obj)
}
}
function DetailsForm(obj, details_list, pkeyCol, facets ){
this.obj = obj;
this.details_list = details_list;
this.pkeyCol = pkeyCol;
this.facets = facets;
this.setup= function(key){
//re initialize global parse of parameters
qs = ipa_parse_qs();
showDetails();
$('h1').text("Managing " + this.obj +": " +qs['pkey'] );
setupFacetNavigation(this.obj,qs.pkey,qs.facet,this.facets);
ipa_details_init(this.obj);
ipa_details_create(this.details_list, $('#details'));
ipa_details_load(qs.pkey, on_win, null);
}
}

View File

@@ -0,0 +1,2 @@
ipa_use_sampledata = (window.location.protocol == 'file:');

163
install/static/entity.js Normal file
View File

@@ -0,0 +1,163 @@
/* Authors:
* Pavel Zuna <pzuna@redhat.com>
*
* Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 only
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* REQUIRES: ipa.js, details.js, search.js, add.js */
var ipa_entity_search_list = {};
var ipa_entity_add_list = {};
var ipa_entity_details_list = {};
function ipa_entity_set_search_definition(obj_name, data)
{
ipa_entity_search_list[obj_name] = data;
}
function ipa_entity_set_add_definition(obj_name, data)
{
ipa_entity_add_list[obj_name] = data;
}
function ipa_entity_set_details_definition(obj_name, data)
{
ipa_entity_details_list[obj_name] = data;
}
function ipa_entity_setup(jobj)
{
var obj_name = jobj.attr('id');
function reset_on_click() {
ipa_details_reset(obj_name);
return (false);
};
function update_on_click() {
var pkey_name = ipa_objs[obj_name].primary_key;
ipa_details_update(obj_name, ipa_details_cache[obj_name][pkey_name][0]);
return (false);
};
function new_on_click() {
add_dialog_create(obj_name, ipa_entity_add_list[obj_name]);
return (false);
};
function setup_search_facet() {
var filter = $.bbq.getState(obj_name + '-filter', true);
search_create(obj_name, ipa_entity_search_list[obj_name], jobj);
var input = jobj.find('input[value=find]');
input.after('<input type="submit" value="new" />');
input.next().click(new_on_click);
if (typeof filter != 'undefined')
search_load(obj_name, filter, null, null);
};
function setup_details_facet() {
var pkey = $.bbq.getState(obj_name + '-pkey', true);
ipa_entity_generate_views(obj_name, jobj);
ipa_details_create(obj_name, ipa_entity_details_list[obj_name], jobj);
jobj.find('.details-reset').click(reset_on_click);
jobj.find('.details-update').click(update_on_click);
if (pkey)
ipa_details_load(obj_name, pkey, null, null);
};
function setup_associate_facet() {
var enroll_obj_name = $.bbq.getState(obj_name + '-enroll', true) || '';
var attr = ipa_get_member_attribute(obj_name, enroll_obj_name);
var columns = [
{
title: ipa_objs[enroll_obj_name].label,
column: attr + '_' + enroll_obj_name
}
];
var frm = new AssociationList(obj_name, 'enroll', columns, jobj);
ipa_entity_generate_views(obj_name, jobj);
frm.setup();
};
function setup_enroll_facet() {
var enroll_obj_name = $.bbq.getState(obj_name + '-enroll', true) || '';
var pkey = ipa_objs[enroll_obj_name].primary_key;
var frm = new AssociationForm(obj_name, enroll_obj_name, pkey, jobj);
frm.setup();
};
jobj.empty();
var facet = $.bbq.getState(obj_name + '-facet', true) || 'search';
if (facet == 'search') {
setup_search_facet();
} else if (facet == 'details') {
setup_details_facet();
} else if (facet == 'associate') {
setup_associate_facet();
} else if (facet == 'enroll') {
setup_enroll_facet();
}
}
function ipa_entity_generate_views(obj_name, container)
{
function switch_view() {
var enroll_obj_name = $(this).attr('title');
var state = {};
if (enroll_obj_name != 'search' && enroll_obj_name != 'details') {
state[obj_name + '-facet'] = 'associate';
state[obj_name + '-enroll'] = enroll_obj_name;
} else {
state[obj_name + '-facet'] = enroll_obj_name;
state[obj_name + '-enroll'] = '';
}
$.bbq.pushState(state);
};
var ul = $('<ul></ul>', {'class': 'entity-views'});
ul.append($('<li></li>', {
text: 'Back to Search',
title: 'search',
click: switch_view
}));
ul.append($('<li></li>', {
text: 'Details',
title: 'details',
click: switch_view
}));
var attribute_members = ipa_objs[obj_name].attribute_members;
for (attr in attribute_members) {
var objs = attribute_members[attr];
for (var i = 0; i < objs.length; ++i) {
var m = objs[i];
var label = ipa_objs[m].label;
ul.append($('<li></li>', {
text: label,
title: m,
click: switch_view
}));
}
}
container.append(ul);
}

View File

@@ -1,139 +1,66 @@
function setupGroup(facet){
/* Authors:
* Pavel Zuna <pzuna@redhat.com>
*
* Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 only
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
if (groupForms[facet]){
groupForms[facet].setup();
}else if (facet == "details"){
setupGroupDetails();
}else if (facet == "add"){
setupAddGroup();
}else{
groupForms.search.setup();
/* REQUIRES: ipa.js, details.js, search.js, add.js, entity.js */
ipa_entity_set_search_definition('group', [
['cn', 'Name', null],
['gidnumber', 'GID', null],
['description', 'Description', null],
]);
ipa_entity_set_add_definition('group', [
'dialog-add-group', 'Add New Group', [
['cn', 'Name', null],
['description', 'Description', null],
['posix', 'Is this a POSIX group?', f_posix],
['gidnumber', 'GID', null]
]
]);
ipa_entity_set_details_definition('group', [
['identity', 'Group Details', [
['cn', 'Group Name'],
['description', 'Description'],
['gidnumber', 'Group ID']
]]
]);
function f_posix(dlg, mode)
{
function checkbox_on_click() {
var jobj = $(this);
if (jobj.attr('checked'))
jobj.attr('checked', false);
else
jobj.attr('checked', true);
};
if (mode == IPA_ADD_POPULATE) {
dlg.append('<label>Is this a POSIX group?</label>');
dlg.append('<input type="checkbox" name="posix" />');
dlg.children().last().click(checkbox_on_click);
} else {
if (dlg.find('input:checkbox[name=posix]').attr('checked'))
return (true);
return (false);
}
}
function addGroupFail(desc){
alert(desc);
}
function addGroup(on_success){
var options = {
posix: $('#isposix').is(':checked') ? 1 : 0 ,
description: $("#groupdescription").val()};
var gid = $("#groupidnumber").val();
if (gid.length > 0){
options.gidnumber = gid;
}
var params = [$("#groupname").val()];
ipa_cmd( 'add', params, options, on_success, addGroupFail, 'group' );
}
function addEditGroup(){
addGroup(function (response){
location.hash="tab=group&facet=details&pkey="+$("#groupname").val();
});
}
function addAnotherGroup(){
addGroup(setupAddGroup);
}
function setupAddGroup(){
showContent();
$("<h1>Add new Group</h1>").appendTo("#content");
$("<form id='addGroupForm'> </form>")
.appendTo("#content");
$("<label>Add and </label><input id='addEdit' type='button' value='Edit'/><input id='addAnother' type='button' value='Add Another'/>").appendTo("#addGroupForm");
$("<dl id='groupProperties' />").appendTo("#addGroupForm");
$("<dt>Name</dt><dd><input id='groupname' type='text'/></dd>")
.appendTo("#groupProperties");
$("<dt>Description</dt><dd><input id='groupdescription' type='text'/></dd>")
.appendTo("#groupProperties");
$("<dt>Is this a posix Group</dt><dd><input id='isposix' type='checkbox'/></dd>")
.appendTo("#groupProperties");
$("<dt>GID</dt><dd><input id='groupidnumber' type='text'/></dd>")
.appendTo("#groupProperties");
$("#addEdit").click(addEditGroup);
$("#addAnother").click(addAnotherGroup);
}
var group_details_list =
[['identity', 'Group Details', [
['cn', 'Group Name'],
['description', 'Description'],
['gidnumber', 'Group ID']]]];
var groupFacets=['details','users'];
function setupGroupDetails(group){
//re initialize global parse of parameters
qs = ipa_parse_qs();
showDetails();
setupFacetNavigation('group',qs['pkey'],qs['facet'],groupFacets);
ipa_details_init('group');
ipa_details_create(group_details_list, $('#details'));
ipa_details_load(qs['pkey'], on_win, null);
$('h1').text('Managing group: ' + group);
}
function renderGroupDetailColumn(current,cell){
$("<a/>",{
href:"#tab=group&facet=details&pkey="+current.cn,
html: ""+ current[this.column],
}).appendTo(cell);
}
var groupSearchColumns = [
{title:"Group Name", column:"cn",render: renderGroupDetailColumn},
{title:"GID", column:"gidnumber",render: renderSimpleColumn},
{title:"Description", column:"description",render: renderSimpleColumn}
];
var groupForms = new GroupForms();
function GroupForms(){
this.userListColumns = [ {title:"user",column:"member_user" }];
this.obj="group";
this.users = new AssociationList(
this.obj,
"users",
"assignusers",
this.userListColumns, groupFacets );
this.assignusers = new AssociationForm(
this.obj,
"user",
"assignusers",
groupFacets,
"uid",
function(){
return 'Add Users to group : ' + qs['pkey'] ;
},
BulkAssociator);
this.search = new SearchForm("group", "find", groupSearchColumns );
}

View File

@@ -1,253 +0,0 @@
var PluginData = {
"primary_key": "cn",
"default_attributes": [
"cn",
"description",
"gidnumber",
"member",
"memberof"
],
"object_name_plural": "groups",
"container_dn": "cn=groups,cn=accounts",
"object_class_config": "ipagroupobjectclasses",
"hidden_attributes": [
"objectclass",
"aci"
],
"uuid_attribute": "ipauniqueid",
"label": "User Groups",
"methods": [
"add",
"add_member",
"del",
"find",
"mod",
"remove_member",
"show"
],
"object_name": "group",
"takes_params": [
{
"exclude": null,
"minlength": null,
"include": null,
"cli_name": "name",
"primary_key": true,
"name": "cn",
"default": null,
"doc": "Group name",
"required": true,
"flags": [],
"label": "Group name",
"autofill": false,
"multivalue": false,
"pattern": null,
"type": "unicode",
"attribute": false,
"query": false,
"cli_short_name": null,
"length": null,
"class": "Str",
"maxlength": null
},
{
"exclude": null,
"minlength": null,
"include": null,
"cli_name": "desc",
"primary_key": false,
"name": "description",
"default": null,
"doc": "Group description",
"required": true,
"flags": [],
"label": "Description",
"autofill": false,
"multivalue": false,
"pattern": null,
"type": "unicode",
"attribute": false,
"query": false,
"cli_short_name": null,
"length": null,
"class": "Str",
"maxlength": null
},
{
"exclude": null,
"include": null,
"cli_name": "gid",
"primary_key": false,
"minvalue": null,
"doc": "GID (use this option to set it manually)",
"required": false,
"flags": [],
"label": "GID",
"default": null,
"autofill": false,
"multivalue": false,
"attribute": false,
"query": false,
"maxvalue": null,
"cli_short_name": null,
"type": "int",
"class": "Int",
"name": "gidnumber"
},
{
"exclude": null,
"minlength": null,
"include": null,
"cli_name": "member_group",
"primary_key": false,
"name": "member_group",
"default": null,
"doc": "Member groups",
"required": false,
"flags": [
"no_update",
"no_create",
"no_search"
],
"label": "Member groups",
"autofill": false,
"multivalue": false,
"pattern": null,
"type": "unicode",
"attribute": false,
"query": false,
"cli_short_name": null,
"length": null,
"class": "Str",
"maxlength": null
},
{
"exclude": null,
"minlength": null,
"include": null,
"cli_name": "member_user",
"primary_key": false,
"name": "member_user",
"default": null,
"doc": "Member users",
"required": false,
"flags": [
"no_update",
"no_create",
"no_search"
],
"label": "Member users",
"autofill": false,
"multivalue": false,
"pattern": null,
"type": "unicode",
"attribute": false,
"query": false,
"cli_short_name": null,
"length": null,
"class": "Str",
"maxlength": null
},
{
"exclude": null,
"minlength": null,
"include": null,
"cli_name": "member",
"primary_key": false,
"name": "member",
"default": null,
"doc": "Failed members",
"required": false,
"flags": [
"no_update",
"no_create",
"no_search"
],
"label": "Failed members",
"autofill": false,
"multivalue": false,
"pattern": null,
"type": "unicode",
"attribute": false,
"query": false,
"cli_short_name": null,
"length": null,
"class": "Str",
"maxlength": null
},
{
"exclude": null,
"minlength": null,
"include": null,
"cli_name": "user",
"primary_key": false,
"name": "user",
"default": null,
"doc": "Users",
"required": false,
"flags": [
"no_update",
"no_create",
"no_search"
],
"label": "Users",
"autofill": false,
"multivalue": false,
"pattern": null,
"type": "unicode",
"attribute": false,
"query": false,
"cli_short_name": null,
"length": null,
"class": "Str",
"maxlength": null
},
{
"exclude": null,
"minlength": null,
"include": null,
"cli_name": "group",
"primary_key": false,
"name": "group",
"default": null,
"doc": "Groups",
"required": false,
"flags": [
"no_update",
"no_create",
"no_search"
],
"label": "Groups",
"autofill": false,
"multivalue": false,
"pattern": null,
"type": "unicode",
"attribute": false,
"query": false,
"cli_short_name": null,
"length": null,
"class": "Str",
"maxlength": null
}
],
"attribute_members": {
"member": [
"user",
"group"
],
"memberof": [
"group",
"netgroup",
"rolegroup",
"taskgroup"
]
},
"parent_object": "",
"object_class": [
"ipausergroup"
],
"name": "group"
}
ipa_objs['group'] = PluginData;

View File

@@ -1,34 +1,43 @@
function setupHost(facet){
if (facet == "details"){
hostDetailsForm.setup();
}else if (facet == "add"){
hostBuilder.setup();
}else{
hostSearchForm.setup();
}
}
/* Authors:
* Pavel Zuna <pzuna@redhat.com>
*
* Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 only
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
var hostAddProperties = [{title: 'Domain Name', id: 'pkey', type: 'text'}];
var hostBuilder = new EntityBuilder("host",hostAddProperties);
/* REQUIRES: ipa.js, details.js, search.js, add.js, entity.js */
ipa_entity_set_search_definition('host', [
['fqdn', 'Name', null],
['description', 'Description', null],
['enrolled', 'Enrolled?', null],
['manages', 'Manages?', null]
]);
var host_details_list = [['host', 'Host Details', [
['fqdn', 'Fully Qualified Domain Name'],
['krbprincipalname', 'Kerberos Principal'],
['serverhostname', 'Server Host Name']
]]];
ipa_entity_set_add_definition('host', [
'dialog-add-host', 'Add New Host', [
['fqdn', 'Name', null]
]
]);
var hostFacets = ["details","hostgroup", "hostgroupmembership"];
ipa_entity_set_details_definition('host', [
['host', 'Host Details', [
['fqdn', 'Fully Qualified Domain Name', null],
['krbprincipalname', 'Kerberos Principal', null],
['serverhostname', 'Server Host Name', null]
]]
]);
var hostDetailsForm = new DetailsForm("host",host_details_list,"fqdn",
hostFacets ) ;
var hostSearchColumns = [
{title:"Host",column:"fqdn",render: function(current,cell){
renderPkeyColumn(hostDetailsForm,current,cell);
}},
{title:"Comment", column: "description", render: renderSimpleColumn},
{title:"Enrolled?", render: renderUnknownColumn},
{title:"Manages?", render: renderUnknownColumn}
];
var hostSearchForm = new SearchForm("host", "find", hostSearchColumns);

View File

@@ -1,82 +1,41 @@
/* Authors:
* Pavel Zuna <pzuna@redhat.com>
*
* Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 only
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
function setupHostgroup(facet){
hostgroupForms.setup(facet);
}
/* REQUIRES: ipa.js, details.js, search.js, add.js, entity.js */
var hostgroup_details_list =
[['identity', 'Hostgroup Details', [
['cn', 'Hostgroup Name'],
['description', 'Description']]]];
ipa_entity_set_search_definition('hostgroup', [
['cn', 'Name', null],
['description', 'Description', null]
]);
var hostgroupFacets = ["details","hosts","assignhosts"];
ipa_entity_set_add_definition('hostgroup', [
'dialog-add-hostgroup', 'Add New Hostgroup', [
['cn', 'Name', null],
['description', 'Description', null]
]
]);
ipa_entity_set_details_definition('hostgroup', [
['identity', 'Hostgroup Details', [
['cn', 'Name', null],
['description', 'Description', null]
]]
]);
var hostgroupForms = new HostgroupsForms();
function HostgroupsForms(){
this.setup = function(facet){
if (this[facet]){
this[facet].setup();
}else{
this.unspecified.setup();
}
}
/**
* used to initialize the search
*/
this.hostgroupSearchColumns = [
{
title:"Hostgroup",
column:"cn",
render: function(current,cell){
renderPkeyColumn2('hostgroup', 'cn', current,cell);
}
},
{title:"Description", column:"description",render: renderSimpleColumn}];
this.hostgroupAddProperties =
[{title: 'Hostgroup Name', id: 'pkey', type: 'text'},
{title: 'Description', id: 'description', type: 'text'}];
/**
Facets
*/
this.hostListColumns = [ {title:"host",column:"member_host" }];
this.obj="hostgroup";
this.hosts = new AssociationList(
this.obj,
"hosts",
"assignhosts",
this.hostListColumns, hostgroupFacets );
this.assignhosts = new AssociationForm(
this.obj,
"host",
"assignhosts",
hostgroupFacets,
"fqdn",
function(){
return 'Add Hosts to to hostgroup : ' + qs['pkey'] ;
},
BulkAssociator);
this.details = new DetailsForm("hostgroup",hostgroup_details_list,"cn",hostgroupFacets) ;
this.add = new EntityBuilder("hostgroup",this.hostgroupAddProperties);
this.add.getOptions = function() {
var options = {
name: $('#pkey').val(),
description: $('#description').val()
};
return options;
}
this.search = new SearchForm("hostgroup", "find", this.hostgroupSearchColumns);
this.unspecified = this.search;
}

View File

@@ -1,136 +1,46 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>IPA: Identity Policy Audit</title>
<link href="ipa.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="json2.js"></script>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="jquery.cookie.js"></script>
<script type="text/javascript" src="ipa.js"></script>
<script type="text/javascript" src="navigation.js"></script>
<script type="text/javascript" src="search.js"></script>
<script type="text/javascript" src="details.js"></script>
<script type="text/javascript" src="add.js"></script>
<script type="text/javascript" src="associate.js"></script>
<script type="text/javascript" src="entity.js"></script>
<script type="text/javascript" src="navigation.js"></script>
<script type="text/javascript" src="user.js"></script>
<script type="text/javascript" src="usermeta.js"></script>
<script type="text/javascript" src="group.js"></script>
<script type="text/javascript" src="groupmeta.js"></script>
<script type="text/javascript" src="host.js"></script>
<script type="text/javascript" src="hostgroup.js"></script>
<script type="text/javascript" src="netgroup.js"></script>
<script type="text/javascript" src="service.js"></script>
<script type="text/javascript">
<script type="text/javascript" src="develop.js"></script>
<script type="text/javascript" src="webui.js"></script>
$(document).ready(function(){
ipa_init( buildNavigation);
});
<link rel="stylesheet" type="text/css" href="ipa.css" />
</head>
</script>
</head>
<body>
<body>
<div class="header" >
<span class="logo">
<a href="#"><img src="ipalogo.png" /></a>
</span>
<span class="LoggedInAs" id="loggedinas">
Logged in as <strong>hardcoded@FREEIP.ORG</strong>
</span>
<span class="header-logo">
<img src="ipalogo.png" />
</span>
<span id="loggedinas" class="header-loggedinas">
<a>Logged in as <strong>hardcoded@FREEIP.ORG</strong></a>
</span>
</div>
<div id="navigation">
<div id="main-nav" />
<div id="sub-nav">Edit: </div>
</div>
<div id="navigation" class="tabs"></div>
</body>
<h1></h1>
<ul id="viewtype" style="display:none" >
<li id="viewcaption"></li>
</ul>
<div id="content" border="1" style="display:none" >
</div>
<div id="details" style="display:none" >
<div id="buttons">
<a href="jslink" onclick="return (reset_on_click(this));">
<img id="butreset" src="but-reset.png" alt="Reset" />
</a>
<a href="jslink" onclick="return (update_on_click(this));">
<img id="butupdate" src="but-update.png" alt="Update" />
</a>
</div>
<div id="detail-lists">
<hr />
</div>
<div id="backtotop">
<a href="#viewtype">Back to Top</a>
</div>
</div>
<div id="search" style="display:none">
<div class="searchControls" >
<span id="filter" class="filter" >
<input id="queryFilter" type="text"/>
<input id="query" type="submit" value="find" />
<input id="new" type="submit" value="new" />
</span>
<span class="filter" id="searchButtons" />
</div>
<table id="searchResultsTable" class="SearchResults" >
<thead></thead>
<tfoot></tfoot>
<tbody></tbody>
</table>
</div>
<div id="associations" style="display:none">
<ul id="viewtype">
<li id="viewcaption">View:</li>
</ul>
<form>
<div style="border-width:1px">
<div >
<input id="associateFilter" type="text"/>
<input id="find" type="button" value="Find"/>
<span style="float:right">
<input id="cancel" type="button" value="Cancel"/>
<input id="enroll" type="button" value="Enroll"/>
</span>
</div>
<div id="results" style="border: 2px solid rgb(0, 0, 0); position:relative; height:200px;" >
<div style="float:left;">
<div>Available</div>
<select id="availableList" width="150px" size="10" multiple="true" >
</select>
</div>
<div style="float:left;">
<p><input id="removeFromList" type="button" value="&lt;&lt;"/> </p>
<p><input id="addToList" type="button" value="&gt;&gt;"/></p>
</div>
<div style="float:left;">
<div>Prospective</div>
<select id="enrollments" width="150px" size="10" multiple="true" >
</select>
</div>
</div>
<hr/>
<div>Message Area</div>
<hr/>
<div>
<span style="float:left">
<p>*Enter Group Names and Press Groups</p>
<p>*More stuff</p>
<p>*More stuff</p>
</span>
</div>
</div>
</form>
</div>
</body>
</html>

View File

@@ -27,52 +27,47 @@ div.header {
background-color: #1f1f1f;
height: 70px;
}
div.header span.LoggedInAs {
color: #fff;
padding-right: 10px;
line-height: 35px;
float: right;
div.header a {
text-decoration: none;
}
div.header div.logo {
div.header a:link {
text-decoration: none;
}
div.header a:visited {
text-decoration: none;
}
div.header div.header-logo {
float: left;
padding: 10px 10px 0 10px;
}
div.header div.logo img {
div.header div.header-logo img {
border: 0;
}
div#view {
bottom: 0;
left: 0;
overflow: auto;
position: fixed;
right: 0;
top: 0;
}
div#header {
background: -moz-linear-gradient(top, #65646e, #1f1f1f);
background-color: #1f1f1f;
height: 70px;
}
div#header div#logo img {
border: 0;
}
div#header div#loggedinas {
div.header span.header-loggedinas {
color: #fff;
font-size: 12pt;
font-weight: bold;
float: right;
line-height: 35px;
padding-right: 10px;
text-align: right;
}
div#header div#loggedinas a {
color: #fff;
text-decoration: underline;
/* ---- Navigation ---- */
div.tabs {
overflow: auto;
}
/* ---- Search ---- */
table.search-table {
width: 100%;
}
table.search-table th {
text-align: left;
}
h1 {

View File

@@ -20,6 +20,11 @@
/* IPA JSON-RPC helper */
var IPA_DEFAULT_JSON_URL = '/ipa/json';
var IPA_SAMPLEDATA_URL = '/ipa/ui/sampledata';
var ipa_use_sampledata = false;
/* JSON-RPC ID counter */
var ipa_jsonrpc_id = 0;
@@ -27,29 +32,26 @@ var ipa_jsonrpc_id = 0;
var ipa_objs = {};
var _ipa_init_on_win_callback = null;
/* initialize the IPA JSON-RPC helper
* arguments:
* url - JSON-RPC URL to use (optional) */
/*Query String*/
var qs;
var useSampleData = (window.location.protocol == "file:");
function ipa_init(on_win)
function ipa_init(url, on_win, use_sampledata)
{
var url = '/ipa/json';
if (url)
ipa_json_url = url;
else
ipa_json_url = IPA_DEFAULT_JSON_URL;
if (use_sampledata)
ipa_use_sampledata = use_sampledata;
_ipa_init_on_win_callback = on_win;
var options = {
url: url,
type: 'POST',
contentType: 'application/json',
dataType: 'json',
processData: false,
type: 'POST',
contentType: 'application/json',
dataType: 'json',
processData: false,
};
$.ajaxSetup(options);
@@ -64,7 +66,7 @@ function _ipa_load_objs(data, textStatus, xhr)
{
ipa_objs = data.result.result;
if (_ipa_init_on_win_callback)
_ipa_init_on_win_callback(data, textStatus, xhr);
_ipa_init_on_win_callback(data, textStatus, xhr);
}
/* call an IPA command over JSON-RPC
@@ -75,35 +77,27 @@ function _ipa_load_objs(data, textStatus, xhr)
* win_callback - function to call if the JSON request succeeds
* fail_callback - function to call if the JSON request fails
* objname - name of an IPA object (optional) */
function ipa_cmd(name, args, options, win_callback, fail_callback, objname,sampleData)
function ipa_cmd(name, args, options, win_callback, fail_callback, objname)
{
id = ipa_jsonrpc_id++;
if (objname)
name = objname + '_' + name;
name = objname + '_' + name;
if (useSampleData){
var sampleData ="sampledata/"+name+".json";
var ajax_options = {
url: sampleData,
type: 'POST',
contentType: 'application/json',
dataType: 'json',
processData: false,
};
$.ajaxSetup(ajax_options);
}
var url = ipa_json_url;
if (ipa_use_sampledata && IPA_SAMPLEDATA_URL)
url = IPA_SAMPLEDATA_URL + '/' + name + '.json';
var data = {
method: name,
params: [args, options],
id: id,
method: name,
params: [args, options],
id: id,
};
var request = {
data: JSON.stringify(data),
success: win_callback,
error: fail_callback,
url: url,
data: JSON.stringify(data),
success: win_callback,
error: fail_callback,
};
$.ajax(request);
@@ -119,33 +113,47 @@ function ipa_parse_qs(qs)
var dict = {};
if (!qs)
qs = location.hash.substring(1);
qs = location.hash.substring(1);
qs = qs.replace(/\+/g, ' ');
var args = qs.split('&');
for (var i = 0; i < args.length; ++i) {
var parts = args[i].split('=', 2);
var key = decodeURIComponent(parts[0]);
if (parts.length == 2)
dict[key] = decodeURIComponent(parts[1]);
else
dict[key] = key;
var parts = args[i].split('=', 2);
var key = decodeURIComponent(parts[0]);
if (parts.length == 2)
dict[key] = decodeURIComponent(parts[1]);
else
dict[key] = key;
}
return (dict);
}
/* helper function used to retrieve information about an attribute */
function ipa_get_param_info(attr)
function ipa_get_param_info(obj_name, attr)
{
var takes_params = ipa_objs[_ipa_obj_name]['takes_params'];
var takes_params = ipa_objs[obj_name].takes_params;
if (!takes_params)
return (null);
return (null);
for (var i = 0; i < takes_params.length; ++i) {
if (takes_params[i]['name'] == attr)
return (takes_params[i]);
if (takes_params[i]['name'] == attr)
return (takes_params[i]);
}
return (null);
}
/* helper function used to retrieve attr name with members of type `member` */
function ipa_get_member_attribute(obj_name, member)
{
var attribute_members = ipa_objs[obj_name].attribute_members
for (var a in attribute_members) {
var objs = attribute_members[a];
for (var i = 0; i < objs.length; ++i) {
if (objs[i] == member)
return a;
}
}
}

View File

@@ -1,242 +1,80 @@
function setLoggedInText(principal){
$("#loggedinas").html( "Logged in as " + principal);
/* Authors:
* Pavel Zuna <pzuna@redhat.com>
*
* Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 only
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
function nav_create(nls, container, tabclass)
{
if (!container)
container = $('#navigation');
if (!tabclass)
tabclass = 'tabs';
nav_generate_tabs(nls, container, tabclass);
var tabs = $('.' + tabclass);
tabs.tabs({event: 'change'});
tabs.find('ul.ui-tabs-nav a').click(_nav_tab_on_click);
}
function whoamiSuccess(response){
function nav_generate_tabs(nls, container, tabclass)
{
container.addClass(tabclass);
container.prepend('<ul></ul>');
$.cookie("whoami", response.result.summary);
setLoggedInText(response.result.summary);
}
var ul = container.children().first();
for (var i = 0; i < nls.length; ++i) {
var n = nls[i];
function unimplemented(facet){
nav_insert_tab_li(ul, n[0], n[1]);
nav_insert_tab_div(container, n[0]);
showContent();
$('#content').append("<div>Not yet implemented.</div>");
}
var parentTabs;
function getParentTabs(){
if (!parentTabs){
parentTabs = {
user : "identity",
group : "identity",
host : "identity",
hostgroup: "identity",
netgroup : "identity",
service : "identity",
policy : "policy",
config : "config"
};
}
return parentTabs;
}
function buildNavigation(){
params= ipa_parse_qs();
var tab = params["tab"];
if (!tab){
tab=$.cookie("lastpage");
}
if ( !tab ) {
tab="user";
}
var facet = params["facet"];
var siteMap = [{name:"IDENTITY",
tab:"identity", //Default subtab
children : [
{name:"Users",tab:"user", setup: setupUser},
{name:"Groups",tab:"group",setup: setupGroup},
{name:"Hosts",tab:"host", setup: setupHost},
{name:"Hostgroups",
tab:"hostgroup",
setup: setupHostgroup},
{name:"Netgroups",tab:"netgroup", setup:setupNetgroup},
{name:"Services",tab:"service", setup:setupService}
]},
{name:"POLICY", tab:"policy", setup: unimplemented},
{name:"CONFIG", tab:"config", setup: unimplemented }];
//TODO autogen this from the site map
var separator = $("<span class='main-separator' />");
var currentMain = siteMap[0];
for (var i = 0 ; i < siteMap.length; i++){
current = siteMap[i];
if (i > 0){
$('#main-nav').append(separator.clone());
}
var tabClass = "main-nav-off";
if (tab == current.tab){
currentMain = current;
tabClass = "main-nav-on";
}
var span = $("<span/>", {
"class": tabClass,
id: "span-tab-"+current.tab,
});
$("<a/>",{
"id": "tab-"+current.tab,
href: "#tab="+current.tab,
text: current.name,
}).appendTo(span);
span.appendTo("#main-nav")
}
if (currentMain.children){
var selectedSub;
for (var i =0; i < currentMain.children.length; i++){
var currentSub = currentMain.children[i];
var tabClass = "sub-nav-off";
if (tab == currentSub.tab){
tabClass = "sub-nav-on";
selectedSub = currentSub;
}
var span = $("<span/>", {
"class": tabClass,
id: "span-subtab-"+currentSub.tab
});
$("<a/>",{
"id": "subtab-"+currentSub.tab,
href: "#tab="+currentSub.tab,
text: currentSub.name,
//click: setActiveSubtab,
}).appendTo(span);
span.appendTo("#sub-nav");
}
if (selectedSub && selectedSub.setup){
selectedSub.setup(facet);
}
}else if (currentMain && currentMain.setup){
currentMain.setup(facet);
}
var whoami = $.cookie("whoami");
if (whoami == null){
ipa_cmd( 'whoami', [], {}, whoamiSuccess, null,null);
}else{
setLoggedInText(whoami);
}
}
var setupFunctions;
function getSetupFunctions(){
if (!setupFunctions){
setupFunctions = {
user: setupUser,
group: setupGroup,
host: setupHost,
hostgroup:setupHostgroup,
netgroup:setupNetgroup,
service:setupService,
};
}
return setupFunctions;
}
$(window).bind( 'hashchange', function(e) {
var queryParams = ipa_parse_qs();
var tab=queryParams.tab;
if (!tab){
tab = 'user';
}
$(".sub-nav-on").removeClass('sub-nav-on').addClass("sub-nav-off")
var active = "#span-subtab-"+tab;
$(active).removeClass('sub-nav-off').addClass("sub-nav-on")
setActiveTab(getParentTabs()[tab]);
getSetupFunctions()[tab](queryParams.facet );
});
function setActiveTab(tabName){
$(".main-nav-on").removeClass('main-nav-on').addClass("main-nav-off")
var activeTab = "#span-tab-"+tabName;
$(activeTab).removeClass('main-nav-off').addClass("main-nav-on")
}
function buildFacetNavigation(facets){
setupFacetNavigation(qs['tab'], qs['pkey'],qs['facet'], facets);
}
function setupFacetNavigation(tab, pkey,facet,facets){
$('#viewtype').css("display","block");
$("#viewtype").html("");
for (var i =0; i < facets.length; i++){
var li = $('<li>').appendTo($("#viewtype"));
if (facets[i] == facet){
$('<img src="but-selected.png" alt="" />');
li.html(facets[i]);
}else{
$('<img src="but-unselected.png" alt="" />').appendTo(li);
$('<a/>',{
href: "#tab="+tab+"&facet="+facets[i]+"&pkey="+pkey,
html: facets[i]
}).appendTo(li);
var div = ul.parent().children().last();
if (typeof n[2] == 'function') {
n[2](div);
} else if (n[2].length) {
nav_generate_tabs(n[2], div, tabclass);
}
}
}
function clearOld(){
var _nav_li_tab_template = '<li><a href="#I">N</a></li>';
$('h1').html("");
$('#viewtype').css("display","none");
$('#search').css("display","none");
$('#details').css("display","none");
$('#content').css("display","none");
$('#associations').css("display","none");
$('#searchResultsTable thead').html("");
$('#searchResultsTable tfoot').html("");
$('#searchResultsTable tbody').find("tr").remove();
$("#searchButtons").html("");
$('#content').html("");
//remove old details
$('.entryattrs dd').remove();
$('#detail-lists').html("<hr/>");
function nav_insert_tab_li(jobj, id, name)
{
jobj.append(_nav_li_tab_template.replace('I', id).replace('N', name));
}
function showSearch(){
clearOld();
$('#search').css("display","block");
$("#filter").css("display","block");
var _nav_div_tab_template = '<div id="T"></div>';
function nav_insert_tab_div(jobj, id)
{
jobj.append(_nav_div_tab_template.replace('T', id));
}
function showContent(){
clearOld();
$('#viewtype').css("display","block");
$('#content').css("display","block");
function _nav_tab_on_click(obj)
{
var jobj = $(this);
var state = {};
var id = jobj.closest('.tabs').attr('id');
var index = jobj.parent().prevAll().length;
state[id] = index;
$.bbq.pushState(state);
}
function showDetails(){
clearOld();
$('#viewtype').css("display","block");
$('#details').css("display","block");
}
function showAssociations(){
clearOld();
$('#associations').css("display","block");
}

View File

@@ -1,107 +1,42 @@
function setupNetgroup(facet){
netgroupForms.setup(facet);
}
/* Authors:
* Pavel Zuna <pzuna@redhat.com>
*
* Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 only
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
var netgroupForms = new NetgroupForms();
/* REQUIRES: ipa.js, details.js, search.js, add.js, entity.js */
function NetgroupForms(){
this.obj='netgroup';
this.pkeycol = 'cn';
this.facets = ["details","users","assignusers","groups","assigngroups","hosts","assignhosts","hostgroups","assignhostgroups"];
ipa_entity_set_search_definition('netgroup', [
['cn', 'Name', null],
['description', 'Description', null]
]);
this.netgroupSearchColumns = [
{title:"Netgroup",column:"cn",render: function(current,cell){
renderPkeyColumn2('netgroup', 'cn', current,cell);
}},
{title:"Description", column:"description",render: renderSimpleColumn}];
ipa_entity_set_add_definition('netgroup', [
'dialog-add-netgroup', 'Add New Netgroup', [
['cn', 'Name', null],
['description', 'Description', null]
]
]);
ipa_entity_set_details_definition('netgroup', [
['identity', 'Netgroup Details', [
['cn', 'Name', null],
['description', 'Description', null],
['nisdomainname', 'NIS Domain', null]
]]
]);
this.details_list =
[['identity', 'Netgroup Details', [
['cn', 'Netgroup Name'],
['description', 'Description'],
['nisdomainname', 'NIS Domain']]]];
this.details = new DetailsForm(this.obj,this.details_list,this.pkeycol,
this.facets) ;
this.add_properties =
[{title: 'Netgroup Name', id: 'pkey', type: 'text'},
{title: 'Description', id: 'description', type: 'text'}];
this.add = new EntityBuilder("netgroup",this.add_properties);
this.add.getOptions = function() {
var options = {
name: $('#pkey').val(),
description: $('#description').val()
};
return options;
}
this.search = new SearchForm("netgroup", "find", this.netgroupSearchColumns);
this.userListColumns = [ {title:"user",column:"memberuser_user", }];
this.users = new AssociationList(
this.obj, "users", "assignusers", this.userListColumns, this.facets );
this.assignusers = new AssociationForm(
this.obj, "user", "assignuser", this.facets, "uid",
function(){
return 'Add Hosts to to netgroup : ' + qs['pkey'] ;
},
BulkAssociator);
this.groupListColumns = [ {title:"group",column:"memberuser_group", }];
this.groups = new AssociationList(
this.obj, "groups", "assigngroups", this.groupListColumns, this.facets );
this.assigngroups = new AssociationForm(
this.obj, "group", "assigngroup", this.facets, "cn",
function(){
return 'Add Hosts to to netgroup : ' + qs['pkey'] ;
},
BulkAssociator);
this.hostListColumns = [ {title:"host",column:"memberhost_host", }];
this.hosts = new AssociationList(
this.obj, "hosts", "assignhosts", this.hostListColumns, this.facets );
this.assignhosts = new AssociationForm(
this.obj, "host", "assignhosts", this.facets, "fqdn",
function(){
return 'Add Hosts to to netgroup : ' + qs['pkey'] ;
},
BulkAssociator);
this.hostgroupListColumns = [ {title:"hostgroup",column:"memberhost_hostgroup", }];
this.hostgroups = new AssociationList(
this.obj, "hostgroups", "assignhostgroups", this.hostgroupListColumns, this.facets );
this.assignhostgroups = new AssociationForm(
this.obj, "hostgroup", "assignhostgroups", this.facets, "cn",
function(){
return 'Add Hostgroups to to netgroup : ' + qs['pkey'] ;
},
BulkAssociator);
this.unspecified = this.search;
this.setup = function(facet){
if (this[facet]){
this[facet].setup();
}else{
this.unspecified.setup();
}
}
}

View File

@@ -1,15 +0,0 @@
function getPageParams(){
var qsParm = new Array();
var query = window.location.search.substring(1);
var parms = query.split("&");
for (var i=0; i<parms.length; i++) {
var pos = parms[i].indexOf('=');
if (pos > 0) {
var key = parms[i].substring(0,pos);
var val = parms[i].substring(pos+1);
qsParm[key] = val;
}
}
return qsParm;
}

View File

@@ -1,139 +1,171 @@
/* Authors:
* Pavel Zuna <pzuna@redhat.com>
* Adam Young <ayoung@redhat.com>
*
* Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 only
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
//Columns is an array of items in the form
// {title, column, render}
//title: the the value that goes at the head of the column
//filed: the column in the response used for populating the value
//render: the function used to generate cell.innerHtml
// it is in the form:
// render(current, cell)
// current is the row in response
// cell is the td in the table
/* REQUIRES: ipa.js */
function search_create(obj_name, scl, container)
{
function find_on_click() {
var filter = $(this).prev('input[type=text]').val();
var state = {};
state[obj_name + '-filter'] = filter;
$.bbq.pushState(state);
};
//These are helper functions, either assigned to the rneder method
//Or called from a thin wrapper render method
function renderSimpleColumn(current,cell){
cell.innerHTML = current[this.column];
if (!container) {
alert('ERROR: search_create: Second argument "container" missing!');
return;
}
container.attr('title', obj_name);
container.addClass('search-container');
container.append('<div class="search-controls"></div>');
var div = container.children().last();
div.append('<span class="search-filter"></span>');
var jobj = div.children().last();
jobj.append('<input type="text" />');
jobj.children().last().attr('name', 'search-' + obj_name + '-filter')
jobj.append('<input type="submit" value="find" />');;
jobj.children().last().click(find_on_click);
div.append('<span class="search-buttons"></span>');
container.append('<table class="search-table"></table>');
jobj = container.children().last();
jobj.append('<thead><tr></tr></thead>');
jobj.append('<tbody></tbody>');
jobj.append('<tfoot></tfoot>');
var tr = jobj.find('tr');
for (var i = 0; i < scl.length; ++i) {
var c = scl[i];
search_insert_th(tr, obj_name, c[0], c[1], c[2]);
}
}
var _search_th_template = '<th abbr="A" title="C">N</th>';
function renderUnknownColumn(current,cell){
cell.innerHTML = "Unknown";
function search_insert_th(jobj, obj_name, attr, name, render_call)
{
var th = _search_th_template.replace('A', attr);
var param_info = ipa_get_param_info(obj_name, attr);
if (param_info && param_info['label'])
th = th.replace('N', param_info['label']);
else
th = th.replace('N', name);
if (typeof render_call == 'function')
th = th.replace('C', render_call.name);
else
th = th.replace('C', '-');
jobj.append(th);
}
function search_load(obj_name, criteria, on_win, on_fail)
{
function load_on_win(data, text_status, xhr) {
if (data.error)
return;
search_display(obj_name, data);
if (on_win)
on_win(data, text_status, xhr);
};
function renderPkeyColumn2(obj,pkeyCol,current,cell){
$("<a/>",{
href:"#tab="+obj+"&facet=details&pkey="+current[pkeyCol],
html: "" + current[pkeyCol],
}).appendTo(cell);
function load_on_fail(xhr, text_status, error_thrown) {
if (on_fail)
on_fail(xhr, text_status, error_thrown);
};
ipa_cmd(
'find', [criteria], {all: true}, load_on_win, load_on_fail, obj_name
);
}
function renderPkeyColumn(form,current,cell){
renderPkeyColumn2(form.obj, form.pkeyCol,current, cell);
function search_generate_tr(thead, tbody, entry_attrs)
{
tbody.append('<tr></tr>');
var tr = tbody.children().last();
var ths = thead.find('th');
for (var i = 0; i < ths.length; ++i) {
var jobj = $(ths[i]);
var attr = jobj.attr('abbr');
var value = entry_attrs[attr];
var render_call = window[jobj.attr('title')];
if (typeof render_call == 'function')
render_call(tr, attr, value);
else
search_generate_td(tr, attr, value);
}
tbody.find('.search-a-pkey').click(function () {
var jobj = $(this);
var obj_name = tbody.closest('.search-container').attr('title');
var state = {};
state[obj_name + '-facet'] = 'details';
state[obj_name + '-pkey'] = $(this).text();
$.bbq.pushState(state);
return (false);
});
}
var _search_td_template = '<td title="A">V</td>';
var _search_a_pkey_template = '<a href="jslink" class="search-a-pkey">V</a>';
function search_generate_td(tr, attr, value)
{
var obj_name = tr.closest('.search-container').attr('title');
var param_info = ipa_get_param_info(obj_name, attr);
if (param_info && param_info['primary_key'])
value = _search_a_pkey_template.replace('V', value);
function renderDetailColumn(current,cell,pkey,obj){
$("<a/>",{
href:"#tab="+obj+"&facet=details&pkey="+pkey,
html: ""+ current[this.column],
}).appendTo(cell);
tr.append(_search_td_template.replace('A', attr).replace('V', value));
}
function search_display(obj_name, data)
{
var selector = '.search-container[title=' + obj_name + ']';
var thead = $(selector + ' thead');
var tbody = $(selector + ' tbody');
var tfoot = $(selector + ' tfoot');
tbody.find('tr').remove();
function SearchForm(obj, method, cols){
var result = data.result.result;
for (var i = 0; i < result.length; ++i)
search_generate_tr(thead, tbody, result[i]);
this.buildColumnHeaders = function (){
var columnHeaders = document.createElement("tr");
for (var i =0 ; i != this.columns.length ;i++){
var th = document.createElement("th");
th.innerHTML = this.columns[i].title;
columnHeaders.appendChild(th);
if (data.result.truncated) {
tfoot.text(
'More than ' + sizelimit + ' results returned. ' +
'First ' + sizelimit + ' results shown.'
);
} else {
tfoot.text(data.result.summary);
}
$('#searchResultsTable thead:last').append(columnHeaders);
}
this.renderResultRow = function(current){
var row = document.createElement("tr");
var cell;
var link;
for(var index = 0 ; index < this.columns.length; index++){
this.columns[index].render(current, row.insertCell(-1));
}
return row;
}
this.searchSuccess = function (json){
if (json.result.truncated){
$("#searchResultsTable tfoot").html("More than "+sizelimit+" results returned. First "+ sizelimit+" results shown." );
}else{
$("#searchResultsTable tfoot").html(json.result.summary);
}
$("#searchResultsTable tbody").find("tr").remove();
for (var index = 0; index != json.result.result.length; index++){
var current = json.result.result[index];
$('#searchResultsTable tbody:last').append(this.renderResultRow(current));
}
}
this.searchWithFilter = function(queryFilter){
var form = this;
$('#searchResultsTable tbody').html("");
$('#searchResultsTable tbody').html("");
$('#searchResultsTable tfoot').html("");
ipa_cmd(this.method,
[queryFilter],
{"all":"true"},
function(json){
form.searchSuccess(json);
},
function(json){
alert("Search Failed");
},
form.obj);
}
this.setup = function(){
showSearch();
$('#searchResultsTable thead').html("");
$('#searchResultsTable tbody').html("");
$('#searchResultsTable tfoot').html("");
$("#new").click(function(){
location.hash="tab="+obj+"&facet=add";
});
$("#query").click(executeSearch);
this.buildColumnHeaders();
var params = ipa_parse_qs();
qs = location.hash.substring(1);
//TODO fix this hack. since parse returns an object, I don't know how to see if that object has a"critia" property if criteria is null.
if (qs.indexOf("criteria") > 0)
{
this.searchWithFilter(params["criteria"]);
}
}
this.obj = obj;
this.method = method;
this.columns = cols;
this.setup();
}
executeSearch = function(){
var queryFilter = $("#queryFilter").val();
var qp = ipa_parse_qs();
var tab = qp.tab;
if (!tab){
tab = 'user';
}
window.location.hash="#tab="
+tab
+"&facet=search&criteria="
+queryFilter;
}

View File

@@ -1,243 +1,78 @@
var user_details_lists = [
/* Authors:
* Pavel Zuna <pzuna@redhat.com>
*
* Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 only
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* REQUIRES: ipa.js, details.js, search.js, add.js, entity.js */
ipa_entity_set_search_definition('user', [
['cn', 'Name', null],
['uid', 'Login', null],
['uidnumber', 'UID', null],
['mail', 'EMAIL', null],
['telephonenumber', 'Phone', null],
['title', 'Job Title', null],
['actions', 'Actions', null]
]);
ipa_entity_set_add_definition('user', [
'dialog-add-user', 'Add New User', [
['uid', 'Login', null],
['givenname', 'First Name', null],
['sn', 'Last Name', null]
]
]);
ipa_entity_set_details_definition('user', [
['identity', 'Identity Details', [
['title', 'Title'],
['givenname', 'First Name'],
['sn', 'Last Name'],
['cn', 'Full Name'],
['displayname', 'Dispaly Name'],
['initials', 'Initials']
]
],
['title', 'Title', null],
['givenname', 'First Name', null],
['sn', 'Last Name', null],
['cn', 'Full Name', null],
['displayname', 'Dispaly Name', null],
['initials', 'Initials', null]
]],
['account', 'Account Details', [
['call_a_status', 'Account Status'],
['uid', 'Login'],
['call_a_password', 'Password'],
['uidnumber', 'UID'],
['gidnumber', 'GID'],
['homedirectory', 'homedirectory']
]
],
['status', 'Account Status', a_status],
['uid', 'Login', null],
['userpassword', 'Password', a_password],
['uidnumber', 'UID', null],
['gidnumber', 'GID', null],
['homedirectory', 'homedirectory', null]
]],
['contact', 'Contact Details', [
['mail', 'E-mail Address'],
['call_a_numbers', 'Numbers']
]
],
['mail', 'E-mail Address', null],
['numbers', 'Numbers', a_numbers]
]],
['address', 'Mailing Address', [
['street', 'Address'],
['location', 'City'],
['call_a_st', 'State'],
['postalcode', 'ZIP']
]
],
['street', 'Address', null],
['location', 'City', null],
['state', 'State', a_st],
['postalcode', 'ZIP', null]
]],
['employee', 'Employee Information', [
['ou', 'Org. Unit'],
['call_a_manager', 'Manager']
]
],
['ou', 'Org. Unit', null],
['manager', 'Manager', a_manager]
]],
['misc', 'Misc. Information', [
['carlicense', 'Car License']
]
]
];
function setupUser(facet){
if (facet == "details"){
setupUserDetails();
}else if (facet == "add"){
userBuilder.setup();
}else if (facet == "group"){
setupUserGroupList();
}else if (facet == "groupmembership"){
userGroupMembershipForm.setup();
}else{
userSearchForm.setup();
}
}
function add_user_fail(reason){
alert("Add User Failed:"+JSON.stringify(reason));
}
function addUser(on_success){
var options = { givenname: $("#firstname").val(),
sn: $("#lastname").val(),
uid : $("#login").val()};
ipa_cmd( 'add', [], options, on_success, add_user_fail, 'user' );
}
function addAnotherUser(){
addUser(setupAddUser);
}
function addEditUser(){
addUser(function (response){
setupUserDetails($("#login").val());
});
}
var userAddProperties = [
{title: 'login', id: 'pkey', type: 'text'},
{title: 'First Name', id: 'firstname', type:'text'},
{title: 'Last Name', id: 'lastname', type:'text'}
];
var userBuilder =
new EntityBuilder(
"user",
userAddProperties);
userBuilder.getOptions = function() {
var options = {
givenname: $("#firstname").val(),
sn: $("#lastname").val()};
return options;
}
var userFacets = ["details","group", "groupmembership"];
function setupUserDetails(user){
qs = ipa_parse_qs();
showDetails();
setupFacetNavigation('user',qs.pkey,qs.facet,userFacets);
renderUserDetails();
}
function renderUserDetails()
{
ipa_details_init('user');
ipa_details_create(user_details_lists, $('#details'));
if (qs['principal']) {
ipa_cmd(
'find', [], {'krbprincipalname': qs['principal']},
on_win_find, null, 'user');
return;
}
if (!qs['pkey'])
return;
ipa_details_load(qs['pkey'], on_win, null);
$('h1').text('Managing user: ' + qs['pkey']);
}
function renderSimpleColumn(current,cell){
cell.innerHTML = current[this.column];
}
function renderUserLinks(current, cell){
link = document.createElement("a");
cell.appendChild(link);
$("<a/>",{
href:"#tab=user&facet=details&pkey="+current.uid,
html: "[D]",
}).appendTo(cell);
$("<a/>",{
href: "#tab=user&facet=group&pkey="+current.uid,
html: "[G]"
}).appendTo(cell);
$("<a/>",{
href:"#tab=user&facet=netgroup&pkey="+current.uid,
html: "[N]"
}).appendTo(cell);
$("<a/>",{
href:"#tab=user&facet=role&pkey="+current.uid,
html:"[R]"
}).appendTo(cell);
}
function renderUserDetailColumn(current,cell){
$("<a/>",{
href:"#tab=user&facet=details&pkey="+current.uid,
html: ""+ current[this.column],
click: function(){ setupUserDetails(current.uid)},
}).appendTo(cell);
}
var userSearchColumns = [
{title:"Name", column:"cn", render: renderSimpleColumn},
{title:"Login", column:"uid", render: renderUserDetailColumn},
{title:"UID", column:"uidnumber", render: renderSimpleColumn},
{title:"EMAIL", column:"mail", render: renderSimpleColumn},
{title:"Phone", column:"telephonenumber",render: renderSimpleColumn},
{title:"Job Title",column:"title", render: renderSimpleColumn},
{title:"Actions", column:"none", render: renderUserLinks}
];
var userSearchForm = new SearchForm("user", "find", userSearchColumns);
/*Usr group enrollement:
given a user, manage the groups in which they are enrolled */
function populateUserGroupFailure(){
alert("Can't find user");
}
var userGroupMembershipForm = new AssociationForm("user","group","groupmembership",userFacets, "cn", function(){
return 'Enroll user ' + qs['pkey'] + ' in groups';
}
);
/*Group Membership*/
var groupMembershipColumns = [
{title:"group", column:"memberof_group"},
];
function populateUserEnrollments(userData){
userEnrollmentList.populate(userData);
}
function setupUserGroupList(){
userEnrollmentList.setup();
}
var userEnrollmentList = new AssociationList('user', 'group','groupmembership',groupMembershipColumns,userFacets);
function on_win(data, textStatus, xhr)
{
if (data['error'])
alert(data['error']['message']);
}
function on_win_find(data, textStatus, xhr)
{
if (data['error']) {
alert(data['error']['message']);
return;
}
var result = data.result.result;
if (result.length == 1) {
var entry_attrs = result[0];
qs['pkey'] = entry_attrs['uid'][0];
ipa_details_load(qs['pkey'], on_win);
$('h1').text('Managing user: ' + qs['pkey']);
}
}
function reset_on_click()
{
ipa_details_reset();
return (false);
}
function update_on_click()
{
ipa_details_update(qs['pkey'], on_win);
return (false);
}
['carlicense', 'Car License', null]
]]
]);
/* Account status Toggle button */
@@ -365,3 +200,12 @@ function a_st(jobj, result, mode)
else
sel.val('');
}
function a_numbers(jobj, result, mode)
{
}
function a_manager(jobj, result, mode)
{
}

View File

@@ -1,415 +0,0 @@
//TODO: This data should be fetched from a separate web URL and
//generated off the metadata for the user object
//but it is basically static.
var PluginData = {
"primary_key": "uid",
"default_attributes": [
"uid",
"givenname",
"sn",
"homedirectory",
"loginshell",
"ou",
"telephonenumber",
"title",
"memberof"
],
"object_name_plural": "users",
"container_dn": "cn=users,cn=accounts",
"object_class_config": "ipauserobjectclasses",
"hidden_attributes": [
"objectclass",
"aci"
],
"uuid_attribute": "ipauniqueid",
"label": "Users",
"methods": [
"add",
"del",
"find",
"lock",
"mod",
"show",
"unlock"
],
"object_name": "user",
"takes_params": [
{
"exclude": null,
"minlength": null,
"include": null,
"cli_name": "login",
"primary_key": true,
"name": "uid",
"default": null,
"doc": "User login",
"required": true,
"flags": [],
"label": "User login",
"autofill": false,
"multivalue": false,
"pattern": null,
"type": "unicode",
"attribute": false,
"query": false,
"cli_short_name": null,
"length": null,
"class": "Str",
"maxlength": null
},
{
"exclude": null,
"minlength": null,
"include": null,
"cli_name": "first",
"primary_key": false,
"name": "givenname",
"default": null,
"doc": "First name",
"required": true,
"flags": [],
"label": "First name",
"autofill": false,
"multivalue": false,
"pattern": null,
"type": "unicode",
"attribute": false,
"query": false,
"cli_short_name": null,
"length": null,
"class": "Str",
"maxlength": null
},
{
"exclude": null,
"minlength": null,
"include": null,
"cli_name": "last",
"primary_key": false,
"name": "sn",
"default": null,
"doc": "Last name",
"required": true,
"flags": [],
"label": "Last name",
"autofill": false,
"multivalue": false,
"pattern": null,
"type": "unicode",
"attribute": false,
"query": false,
"cli_short_name": null,
"length": null,
"class": "Str",
"maxlength": null
},
{
"exclude": null,
"minlength": null,
"include": null,
"cli_name": "homedir",
"primary_key": false,
"name": "homedirectory",
"default": null,
"doc": "Home directory",
"required": false,
"flags": [],
"label": "Home directory",
"autofill": false,
"multivalue": false,
"pattern": null,
"type": "unicode",
"attribute": false,
"query": false,
"cli_short_name": null,
"length": null,
"class": "Str",
"maxlength": null
},
{
"exclude": null,
"minlength": null,
"include": null,
"cli_name": "gecos",
"primary_key": false,
"name": "gecos",
"default": null,
"doc": "GECOS field",
"required": false,
"flags": [],
"label": "GECOS field",
"autofill": true,
"multivalue": false,
"pattern": null,
"type": "unicode",
"attribute": false,
"query": false,
"cli_short_name": null,
"length": null,
"class": "Str",
"maxlength": null
},
{
"exclude": null,
"minlength": null,
"include": null,
"cli_name": "shell",
"primary_key": false,
"name": "loginshell",
"default": "/bin/sh",
"doc": "Login shell",
"required": false,
"flags": [],
"label": "Login shell",
"autofill": false,
"multivalue": false,
"pattern": null,
"type": "unicode",
"attribute": false,
"query": false,
"cli_short_name": null,
"length": null,
"class": "Str",
"maxlength": null
},
{
"exclude": null,
"minlength": null,
"include": null,
"cli_name": "principal",
"primary_key": false,
"name": "krbprincipalname",
"default": null,
"doc": "Kerberos principal",
"required": false,
"flags": [],
"label": "Kerberos principal",
"autofill": true,
"multivalue": false,
"pattern": null,
"type": "unicode",
"attribute": false,
"query": false,
"cli_short_name": null,
"length": null,
"class": "Str",
"maxlength": null
},
{
"exclude": null,
"minlength": null,
"include": null,
"cli_name": "email",
"primary_key": false,
"name": "mail",
"default": null,
"doc": "Email address",
"required": false,
"flags": [],
"label": "Email address",
"autofill": false,
"multivalue": false,
"pattern": null,
"type": "unicode",
"attribute": false,
"query": false,
"cli_short_name": null,
"length": null,
"class": "Str",
"maxlength": null
},
{
"exclude": [
"webui"
],
"minlength": null,
"include": null,
"cli_name": "password",
"primary_key": false,
"name": "userpassword",
"default": null,
"doc": "Set the user password",
"required": false,
"flags": [],
"label": "Password",
"autofill": false,
"multivalue": false,
"pattern": null,
"type": "unicode",
"attribute": false,
"query": false,
"cli_short_name": null,
"length": null,
"class": "Password",
"maxlength": null
},
{
"exclude": null,
"include": null,
"cli_name": "uid",
"primary_key": false,
"minvalue": null,
"doc": "User ID Number (system will assign one if not provided)",
"required": false,
"flags": [],
"label": "UID",
"default": 999,
"autofill": true,
"multivalue": false,
"attribute": false,
"query": false,
"maxvalue": null,
"cli_short_name": null,
"type": "int",
"class": "Int",
"name": "uidnumber"
},
{
"exclude": null,
"minlength": null,
"include": null,
"cli_name": "street",
"primary_key": false,
"name": "street",
"default": null,
"doc": "Street address",
"required": false,
"flags": [],
"label": "Street address",
"autofill": false,
"multivalue": false,
"pattern": null,
"type": "unicode",
"attribute": false,
"query": false,
"cli_short_name": null,
"length": null,
"class": "Str",
"maxlength": null
},
{
"exclude": null,
"minlength": null,
"include": null,
"cli_name": "memberof_group",
"primary_key": false,
"name": "memberof_group",
"default": null,
"doc": "Groups",
"required": false,
"flags": [
"no_update",
"no_create",
"no_search"
],
"label": "Groups",
"autofill": false,
"multivalue": false,
"pattern": null,
"type": "unicode",
"attribute": false,
"query": false,
"cli_short_name": null,
"length": null,
"class": "Str",
"maxlength": null
},
{
"exclude": null,
"minlength": null,
"include": null,
"cli_name": "memberof_netgroup",
"primary_key": false,
"name": "memberof_netgroup",
"default": null,
"doc": "Netgroups",
"required": false,
"flags": [
"no_update",
"no_create",
"no_search"
],
"label": "Netgroups",
"autofill": false,
"multivalue": false,
"pattern": null,
"type": "unicode",
"attribute": false,
"query": false,
"cli_short_name": null,
"length": null,
"class": "Str",
"maxlength": null
},
{
"exclude": null,
"minlength": null,
"include": null,
"cli_name": "memberof_rolegroup",
"primary_key": false,
"name": "memberof_rolegroup",
"default": null,
"doc": "Rolegroups",
"required": false,
"flags": [
"no_update",
"no_create",
"no_search"
],
"label": "Rolegroups",
"autofill": false,
"multivalue": false,
"pattern": null,
"type": "unicode",
"attribute": false,
"query": false,
"cli_short_name": null,
"length": null,
"class": "Str",
"maxlength": null
},
{
"exclude": null,
"minlength": null,
"include": null,
"cli_name": "memberof_taskgroup",
"primary_key": false,
"name": "memberof_taskgroup",
"default": null,
"doc": "Taskgroups",
"required": false,
"flags": [
"no_update",
"no_create",
"no_search"
],
"label": "Taskgroups",
"autofill": false,
"multivalue": false,
"pattern": null,
"type": "unicode",
"attribute": false,
"query": false,
"cli_short_name": null,
"length": null,
"class": "Str",
"maxlength": null
}
],
"attribute_members": {
"memberof": [
"group",
"netgroup",
"rolegroup",
"taskgroup"
]
},
"parent_object": "",
"object_class": [
"posixaccount"
],
"name": "user"
}
ipa_objs['user'] = PluginData;

124
install/static/webui.js Normal file
View File

@@ -0,0 +1,124 @@
/* Authors:
* Pavel Zuna <pzuna@redhat.com>
*
* Copyright (C) 2010 Red Hat
* see file 'COPYING' for use and warranty information
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 only
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* REQUIRES: everything, this file puts it all togheter */
/* tabs definition for IPA webUI */
var nav_tabs_lists = [
['identity', 'IDENTITY', [
['user', 'Users', ipa_entity_setup],
['group', 'Groups', ipa_entity_setup],
['host', 'Hosts', ipa_entity_setup],
['hostgroup', 'Hostgroups', ipa_entity_setup],
['netgroup', 'Netgroups', ipa_entity_setup],
]],
['policy', 'POLICY', unimplemented_tab],
['config', 'CONFIG', unimplemented_tab]
];
/* main (document onready event handler) */
$(function() {
function set_logged_in_as(principal) {
$.cookie('whoami', principal);
$('#loggedinas').find('strong').text(principal);
};
function whoami_on_win(data, text_status, xhr) {
if (!data.error)
set_logged_in_as(data.result.summary);
};
function init_on_win(data, text_status, xhr) {
nav_create(nav_tabs_lists, $('#navigation'), 'tabs');
$(window).bind('hashchange', window_hashchange);
window_hashchange(null);
var whoami = $.cookie('whoami');
if (whoami)
set_logged_in_as(whoami);
else
ipa_cmd('whoami', [], {}, whoami_on_win, null, null, 'sampledata/whoami.json');
};
ipa_init(null, init_on_win);
});
/* use this to track individual changes between two hashchange events */
var window_hash_cache = {};
/* main loop (hashchange event handler) */
function window_hashchange(evt)
{
$('.tabs').each(function () {
var jobj = $(this);
var index = $.bbq.getState(jobj.attr('id'), true) || 0;
jobj.find('ul.ui-tabs-nav a').eq(index).triggerHandler('change');
});
for (var i = 0; i < nav_tabs_lists.length; ++i) {
var t = nav_tabs_lists[i];
if (typeof t[2] != 'function' && t[2].length) {
for (var j = 0; j < t[2].length; ++j) {
var tt = t[2][j];
var obj_name = tt[0];
var entity_setup = tt[2];
var div = $('#' + t[0] + ' div[title=' + obj_name + ']');
var state = obj_name + '-facet';
var facet = $.bbq.getState(state, true) || 'search';
var last_facet = window_hash_cache[state] || 'search';
if (facet != last_facet) {
entity_setup(div);
continue;
}
if (facet == 'search') {
state = obj_name + '-filter';
var filter = $.bbq.getState(state, true);
var last_filter = window_hash_cache[state];
if (filter != last_filter)
entity_setup(div);
} else if (facet == 'details') {
state = obj_name + '-pkey';
var pkey = $.bbq.getState(state, true);
var last_pkey = window_hash_cache[state];
if (pkey != last_pkey)
entity_setup(div);
} else if (facet == 'associate' || facet == 'enroll') {
state = obj_name + '-enroll';
var enroll = $.bbq.getState(state, true);
var last_enroll = window_hash_cache[state];
if (enroll != last_enroll)
entity_setup(div);
}
}
}
}
window_hash_cache = $.bbq.getState();
}
/* builder function for unimplemented tab content */
function unimplemented_tab(jobj)
{
jobj.text('Not implemented yet!');
}

View File

@@ -390,6 +390,7 @@ fi
%{_usr}/share/ipa/migration/migration.css
%{_usr}/share/ipa/migration/migration.py*
%dir %{_usr}/share/ipa/static
%{_usr}/share/ipa/static/index.xhtml
%{_usr}/share/ipa/static/*.png
%{_usr}/share/ipa/static/*.css
%{_usr}/share/ipa/static/*.js

View File

@@ -314,6 +314,7 @@ class Param(ReadOnly):
('include', frozenset, None),
('exclude', frozenset, None),
('flags', frozenset, frozenset()),
('hint', (str, Gettext), None),
# The 'default' kwarg gets appended in Param.__init__():
# ('default', self.type, None),