The IPA.get_entity() has been modified to accept either entity name or entity object. If it receives an entity object it will return the object itself. Otherwise, it will resolve the name in the entity registry. The other_entity variables have been modified to store a reference to the entity object instead of its name. The test cases have been modified to use real entity objects instead of just the names. Ticket #2042
728 lines
18 KiB
JavaScript
728 lines
18 KiB
JavaScript
/*jsl:import ipa.js */
|
|
/* Authors:
|
|
* Endi Sukma Dewata <edewata@redhat.com>
|
|
* Adam Young <ayoung@redhat.com>
|
|
* Pavel Zuna <pzuna@redhat.com>
|
|
* Petr Vobornik <pvoborni@redhat.com>
|
|
*
|
|
* Copyright (C) 2011 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, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* 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, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/* REQUIRES: ipa.js, widget.js */
|
|
|
|
IPA.field = function(spec) {
|
|
spec = spec || {};
|
|
|
|
var that = {};
|
|
|
|
that.entity = IPA.get_entity(spec.entity);
|
|
that.container = null;
|
|
that.name = spec.name;
|
|
that.label = spec.label;
|
|
that.tooltip = spec.tooltip;
|
|
|
|
that.widget = null;
|
|
that.widget_name = spec.widget;
|
|
|
|
// override the required flag in metadata
|
|
that.required = spec.required;
|
|
|
|
// read_only is set when widget is created
|
|
that.read_only = spec.read_only;
|
|
|
|
// writable is set during load
|
|
that.writable = true;
|
|
|
|
that.enabled = spec.enabled === undefined ? true : spec.enabled;
|
|
|
|
that.undo = spec.undo === undefined ? true : spec.undo;
|
|
that.join = spec.join;
|
|
|
|
that.metadata = spec.metadata;
|
|
|
|
that.priority = spec.priority;
|
|
|
|
that.values = [];
|
|
that.dirty = false;
|
|
that.valid = true;
|
|
|
|
that.dirty_changed = IPA.observer();
|
|
|
|
var init = function() {
|
|
if (!that.metadata && that.entity) {
|
|
that.metadata = IPA.get_entity_param(that.entity.name, that.name);
|
|
}
|
|
if (that.metadata) {
|
|
if (that.label === undefined) {
|
|
that.label = that.metadata.label;
|
|
}
|
|
if (that.tooltip === undefined) {
|
|
that.tooltip = that.metadata.doc;
|
|
}
|
|
}
|
|
};
|
|
|
|
that.is_required = function() {
|
|
if (that.read_only) return false;
|
|
if (!that.writable) return false;
|
|
|
|
if (that.required !== undefined) return that.required;
|
|
return that.metadata && that.metadata.required;
|
|
};
|
|
|
|
that.set_required = function(required) {
|
|
that.required = required;
|
|
|
|
that.update_required();
|
|
};
|
|
|
|
that.update_required = function() {
|
|
if(that.widget && that.widget.set_required) {
|
|
that.widget.set_required(that.is_required());
|
|
}
|
|
};
|
|
|
|
that.validate_required = function() {
|
|
var values = that.save();
|
|
if (!values || !values.length || values[0] === '') {
|
|
if (that.is_required()) {
|
|
that.valid = false;
|
|
that.show_error(IPA.messages.widget.validation.required);
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
|
|
/*returns true and clears the error message if the field value passes
|
|
* the validation pattern. If the field value does not pass validation,
|
|
* displays the error message and returns false. */
|
|
that.validate = function() {
|
|
that.hide_error();
|
|
that.valid = true;
|
|
|
|
var values = that.save();
|
|
if (!values) {
|
|
return that.valid;
|
|
}
|
|
if (values.length === 0) {
|
|
return that.valid;
|
|
}
|
|
var value = values[0];
|
|
if (!value) {
|
|
return that.valid;
|
|
}
|
|
|
|
if (!that.metadata) {
|
|
return that.valid;
|
|
}
|
|
|
|
var message;
|
|
|
|
if (that.metadata.type == 'int') {
|
|
if (!value.match(/^-?\d+$/)) {
|
|
that.valid = false;
|
|
that.show_error(IPA.messages.widget.validation.integer);
|
|
return that.valid;
|
|
}
|
|
|
|
if (that.metadata.minvalue !== undefined && value < that.metadata.minvalue) {
|
|
that.valid = false;
|
|
message = IPA.messages.widget.validation.min_value;
|
|
message = message.replace('${value}', that.metadata.minvalue);
|
|
that.show_error(message);
|
|
return that.valid;
|
|
}
|
|
|
|
if (that.metadata.maxvalue !== undefined && value > that.metadata.maxvalue) {
|
|
that.valid = false;
|
|
message = IPA.messages.widget.validation.max_value;
|
|
message = message.replace('${value}', that.metadata.maxvalue);
|
|
that.show_error(message);
|
|
return that.valid;
|
|
}
|
|
}
|
|
|
|
if (that.metadata.pattern) {
|
|
var regex = new RegExp(that.metadata.pattern);
|
|
if (!value.match(regex)) {
|
|
that.valid = false;
|
|
that.show_error(that.metadata.pattern_errmsg);
|
|
return that.valid;
|
|
}
|
|
}
|
|
|
|
return that.valid;
|
|
};
|
|
|
|
/**
|
|
* This function stores the entire record and the values
|
|
* of the field, then invoke reset() to update the UI.
|
|
*/
|
|
that.load = function(record) {
|
|
that.record = record;
|
|
|
|
var value = record[that.name];
|
|
if (value instanceof Array) {
|
|
that.values = value;
|
|
} else {
|
|
that.values = value !== undefined ? [value] : [];
|
|
}
|
|
|
|
if (!that.values.length) {
|
|
that.values = [''];
|
|
}
|
|
|
|
that.load_writable(record);
|
|
|
|
that.reset();
|
|
};
|
|
|
|
that.load_writable = function(record) {
|
|
|
|
that.writable = true;
|
|
|
|
if (that.metadata) {
|
|
if (that.metadata.primary_key) {
|
|
that.writable = false;
|
|
}
|
|
|
|
if (that.metadata.flags && 'no_update' in that.metadata.flags) {
|
|
that.writable = false;
|
|
}
|
|
}
|
|
|
|
if (record.attributelevelrights) {
|
|
var rights = record.attributelevelrights[that.name];
|
|
if (!rights || rights.indexOf('w') < 0) {
|
|
that.writable = false;
|
|
}
|
|
}
|
|
};
|
|
|
|
that.reset = function() {
|
|
that.set_widget_flags();
|
|
that.update_required();
|
|
that.update();
|
|
that.validate();
|
|
that.set_dirty(false);
|
|
};
|
|
|
|
that.update = function() {
|
|
if(that.widget && that.widget.update) that.widget.update(that.values);
|
|
};
|
|
|
|
that.get_update_info = function() {
|
|
|
|
var update_info = IPA.update_info_builder.new_update_info();
|
|
if(that.is_dirty()) {
|
|
update_info.fields.push(IPA.update_info_builder.new_field_info(
|
|
that,
|
|
that.save()));
|
|
}
|
|
return update_info;
|
|
};
|
|
|
|
/**
|
|
* This function saves the values entered in the UI.
|
|
* It returns the values in an array, or null if
|
|
* the field should not be saved.
|
|
*/
|
|
that.save = function(record) {
|
|
|
|
var values = that.values;
|
|
|
|
if(!that.enabled) return [''];
|
|
|
|
if(that.widget) {
|
|
values = that.widget.save();
|
|
}
|
|
|
|
if(record) {
|
|
record[that.name] = values;
|
|
}
|
|
|
|
return values;
|
|
};
|
|
|
|
/**
|
|
* This function compares the original values and the
|
|
* values entered in the UI. If the values have changed
|
|
* it will return true.
|
|
*/
|
|
that.test_dirty = function() {
|
|
|
|
if (that.read_only) return false;
|
|
|
|
var values = that.save();
|
|
|
|
//check for empty value: null, [''], '', []
|
|
var orig_empty = that.is_empty(that.values);
|
|
var new_empty= that.is_empty(values);
|
|
if (orig_empty && new_empty) return false;
|
|
if (orig_empty != new_empty) return true;
|
|
|
|
//strict equality - checks object's ref equality, numbers, strings
|
|
if (values === that.values) return false;
|
|
|
|
//compare values in array
|
|
if (values.length !== that.values.length) return true;
|
|
|
|
values.sort();
|
|
that.values.sort();
|
|
|
|
for (var i=0; i<values.length; i++) {
|
|
if (values[i] != that.values[i]) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
};
|
|
|
|
that.is_empty = function(value) {
|
|
|
|
var empty = false;
|
|
|
|
if (!value) empty = true;
|
|
|
|
if (value instanceof Array) {
|
|
empty = empty || value.length === 0 ||
|
|
(value.length === 1) && (value[0] === '');
|
|
}
|
|
|
|
if (value === '') empty = true;
|
|
|
|
return empty;
|
|
};
|
|
|
|
/**
|
|
* This function compares the original values and the
|
|
* values entered in the UI. If the values have changed
|
|
* it will return true.
|
|
*/
|
|
that.is_dirty = function() {
|
|
return that.dirty;
|
|
};
|
|
|
|
that.set_dirty = function(dirty) {
|
|
var old = that.dirty;
|
|
that.dirty = dirty;
|
|
if (that.undo) {
|
|
that.show_undo(dirty);
|
|
}
|
|
|
|
if (old !== dirty) {
|
|
that.dirty_changed.notify([], that);
|
|
}
|
|
};
|
|
|
|
|
|
that.show_error = function(message) {
|
|
if (that.widget && that.widget.show_error) that.widget.show_error(message);
|
|
};
|
|
|
|
that.hide_error = function() {
|
|
if (that.widget && that.widget.hide_error) that.widget.hide_error();
|
|
};
|
|
|
|
that.show_undo = function(value) {
|
|
if (that.widget && that.widget.show_undo) {
|
|
if(value) { that.widget.show_undo(); }
|
|
else { that.widget.hide_undo(); }
|
|
}
|
|
};
|
|
|
|
that.set_enabled = function(value) {
|
|
that.enabled = value;
|
|
if (that.widget && that.widget.set_enabled) {
|
|
that.widget.set_enabled(value);
|
|
}
|
|
};
|
|
|
|
that.refresh = function() {
|
|
};
|
|
|
|
that.set_widget_flags = function() {
|
|
|
|
if (that.widget) {
|
|
if(that.label) that.widget.label = that.label;
|
|
if(that.title) that.widget.title = that.title;
|
|
that.widget.undo = that.undo;
|
|
that.widget.writable = that.writable;
|
|
that.widget.read_only = that.read_only;
|
|
}
|
|
};
|
|
|
|
that.widgets_created = function() {
|
|
|
|
that.widget = that.container.widgets.get_widget(that.widget_name);
|
|
|
|
if(that.widget) {
|
|
that.set_widget_flags();
|
|
|
|
that.widget.value_changed.attach(that.widget_value_changed);
|
|
that.widget.undo_clicked.attach(that.widget_undo_clicked);
|
|
}
|
|
};
|
|
|
|
that.widget_value_changed = function() {
|
|
that.set_dirty(that.test_dirty());
|
|
that.validate();
|
|
};
|
|
|
|
that.widget_undo_clicked = function() {
|
|
that.reset();
|
|
};
|
|
|
|
init();
|
|
|
|
// methods that should be invoked by subclasses
|
|
that.field_load = that.load;
|
|
that.field_reset = that.reset;
|
|
that.field_save = that.save;
|
|
that.field_set_dirty = that.set_dirty;
|
|
that.field_show_error = that.show_error;
|
|
that.field_test_dirty = that.test_dirty;
|
|
that.field_widgets_created = that.widgets_created;
|
|
|
|
return that;
|
|
};
|
|
|
|
IPA.checkbox_field = function(spec) {
|
|
|
|
spec = spec || {};
|
|
|
|
var that = IPA.field(spec);
|
|
|
|
that.checked = spec.checked || false;
|
|
|
|
that.widgets_created = function() {
|
|
|
|
that.field_widgets_created();
|
|
that.widget.checked = that.checked;
|
|
};
|
|
|
|
// a checkbox will always have a value, so it's never required
|
|
that.is_required = function() {
|
|
return false;
|
|
};
|
|
|
|
that.checkbox_load = that.load;
|
|
|
|
return that;
|
|
};
|
|
|
|
IPA.checkboxes_field = function(spec) {
|
|
|
|
spec = spec || {};
|
|
|
|
var that = IPA.field(spec);
|
|
|
|
that.checkbox_load = that.load;
|
|
/*
|
|
// a checkbox will always have a value, so it's never required
|
|
that.is_required = function() {
|
|
return false;
|
|
};
|
|
*/
|
|
return that;
|
|
};
|
|
|
|
IPA.radio_field = function(spec) {
|
|
|
|
spec = spec || {};
|
|
|
|
var that = IPA.field(spec);
|
|
|
|
// a radio will always have a value, so it's never required
|
|
that.is_required = function() {
|
|
return false;
|
|
};
|
|
|
|
that.widgets_created = function() {
|
|
|
|
that.field_widgets_created();
|
|
};
|
|
|
|
return that;
|
|
};
|
|
|
|
IPA.multivalued_field = function(spec) {
|
|
|
|
spec = spec || {};
|
|
|
|
var that = IPA.field(spec);
|
|
|
|
that.widgets_created = function() {
|
|
|
|
that.field_widgets_created();
|
|
};
|
|
|
|
that.load = function(record) {
|
|
|
|
that.field_load(record);
|
|
};
|
|
|
|
that.test_dirty = function() {
|
|
var dirty = that.field_test_dirty();
|
|
dirty = dirty || that.widget.test_dirty(); //also checks order
|
|
return dirty;
|
|
};
|
|
|
|
that.widget_value_changed = function() {
|
|
that.set_dirty(that.test_dirty());
|
|
//that.validate(); disabling validation for now
|
|
};
|
|
|
|
return that;
|
|
};
|
|
|
|
IPA.select_field = function(spec) {
|
|
|
|
spec = spec || {};
|
|
|
|
var that = IPA.field(spec);
|
|
|
|
that.widgets_created = function() {
|
|
|
|
that.field_widgets_created();
|
|
};
|
|
|
|
return that;
|
|
};
|
|
|
|
|
|
IPA.combobox_field = function(spec) {
|
|
|
|
spec = spec || {};
|
|
|
|
var that = IPA.field(spec);
|
|
|
|
that.widgets_created = function() {
|
|
|
|
that.field_widgets_created();
|
|
that.widget.input_field_changed.attach(that.on_input_field_changed);
|
|
};
|
|
|
|
that.on_input_field_changed = function() {
|
|
that.validate();
|
|
};
|
|
|
|
return that;
|
|
};
|
|
|
|
IPA.link_field = function(spec) {
|
|
|
|
spec = spec || {};
|
|
|
|
var that = IPA.field(spec);
|
|
|
|
that.other_entity = IPA.get_entity(spec.other_entity);
|
|
|
|
function other_pkeys () {
|
|
return that.entity.get_primary_key();
|
|
}
|
|
that.other_pkeys = spec.other_pkeys || other_pkeys;
|
|
|
|
that.on_link_clicked = function() {
|
|
|
|
IPA.nav.show_entity_page(
|
|
that.other_entity,
|
|
'default',
|
|
that.other_pkeys());
|
|
};
|
|
|
|
that.load = function(record) {
|
|
|
|
that.field_load(record);
|
|
that.check_entity_link();
|
|
};
|
|
|
|
that.check_entity_link = function() {
|
|
|
|
IPA.command({
|
|
entity: that.other_entity.name,
|
|
method: 'show',
|
|
args: that.other_pkeys(),
|
|
options: {},
|
|
retry: false,
|
|
on_success: function (result) {
|
|
that.widget.is_link = result.result !== undefined;
|
|
that.widget.update(that.values);
|
|
}
|
|
}).execute();
|
|
};
|
|
|
|
that.widgets_created = function() {
|
|
that.field_widgets_created();
|
|
that.widget.link_clicked.attach(that.on_link_clicked);
|
|
};
|
|
|
|
|
|
return that;
|
|
};
|
|
|
|
IPA.enable_field = function(spec) {
|
|
|
|
spec = spec || {};
|
|
|
|
var that = IPA.radio_field(spec);
|
|
|
|
that.enable_method = spec.enable_method || 'enable';
|
|
that.disable_method = spec.enable_method || 'disable';
|
|
that.enable_option = spec.enable_option || 'TRUE';
|
|
|
|
that.get_update_info = function() {
|
|
|
|
var info = IPA.update_info_builder.new_update_info();
|
|
if(that.test_dirty()) {
|
|
var values = that.save();
|
|
var method = that.disable_method;
|
|
|
|
if(values[0] === that.enable_option) {
|
|
method = that.enable_method;
|
|
}
|
|
|
|
var command = IPA.command({
|
|
entity: that.entity.name,
|
|
method: method,
|
|
args: that.entity.get_primary_key(),
|
|
options: {all: true, rights: true}
|
|
});
|
|
|
|
|
|
info.append_command(command, that.priority);
|
|
}
|
|
|
|
return info;
|
|
};
|
|
|
|
return that;
|
|
};
|
|
|
|
IPA.field_container = function(spec) {
|
|
|
|
spec = spec || {};
|
|
|
|
var that = {};
|
|
|
|
that.container = spec.container; //usually facet or dialog
|
|
|
|
that.fields = $.ordered_map();
|
|
|
|
that.get_field = function(name) {
|
|
return that.fields.get(name);
|
|
};
|
|
|
|
that.get_fields = function(name) {
|
|
return that.fields.values;
|
|
};
|
|
|
|
that.add_field = function(field) {
|
|
field.container = that.container;
|
|
that.fields.put(field.name, field);
|
|
};
|
|
|
|
that.widgets_created = function() {
|
|
var fields = that.fields.values;
|
|
|
|
for (var i=0; i<fields.length; i++) {
|
|
fields[i].widgets_created();
|
|
}
|
|
};
|
|
|
|
that.container_add_field = that.add_field;
|
|
|
|
return that;
|
|
};
|
|
|
|
IPA.field_builder = function(spec) {
|
|
|
|
spec = spec || {};
|
|
|
|
var that = {};
|
|
|
|
that.default_factory = spec.default_factory || IPA.field;
|
|
that.container = spec.container;
|
|
that.field_options = spec.field_options || {};
|
|
|
|
that.get_field_factory = function(spec) {
|
|
|
|
var factory;
|
|
if (spec.factory) {
|
|
factory = spec.factory;
|
|
} else if(spec.type) {
|
|
factory = IPA.field_factories[spec.type];
|
|
}
|
|
|
|
if (!factory) {
|
|
factory = that.default_factory;
|
|
}
|
|
|
|
return factory;
|
|
};
|
|
|
|
that.build_field = function(spec, container) {
|
|
|
|
container = container || that.container;
|
|
|
|
if(!(spec instanceof Object)) {
|
|
spec = { name: spec };
|
|
}
|
|
|
|
if(that.field_options) {
|
|
$.extend(spec, that.field_options);
|
|
}
|
|
|
|
var factory = that.get_field_factory(spec);
|
|
|
|
var field = factory(spec);
|
|
|
|
if(container) {
|
|
container.add_field(field);
|
|
}
|
|
|
|
return field;
|
|
};
|
|
|
|
that.build_fields = function(specs, container) {
|
|
|
|
container = container || that.container;
|
|
|
|
for(var i=0; i<specs.length; i++) {
|
|
that.build_field(specs[i], container);
|
|
}
|
|
};
|
|
|
|
return that;
|
|
};
|
|
|
|
IPA.field_factories['field'] = IPA.field;
|
|
IPA.field_factories['text'] = IPA.field;
|
|
IPA.field_factories['password'] = IPA.field;
|
|
IPA.field_factories['checkbox'] = IPA.checkbox_field;
|
|
IPA.field_factories['checkboxes'] = IPA.checkboxes_field;
|
|
IPA.field_factories['radio'] = IPA.radio_field;
|
|
IPA.field_factories['multivalued'] = IPA.multivalued_field;
|
|
IPA.field_factories['select'] = IPA.select_field;
|
|
IPA.field_factories['textarea'] = IPA.field;
|
|
IPA.field_factories['entity_select'] = IPA.combobox_field;
|
|
IPA.field_factories['combobox'] = IPA.combobox_field;
|
|
IPA.field_factories['link'] = IPA.link_field;
|
|
IPA.field_factories['enable'] = IPA.enable_field;
|