3 commits - lib/client lib/kolab_client_task.php lib/locale public_html/js public_html/skins
Aleksander Machniak
machniak at kolabsys.com
Wed Oct 3 13:28:32 CEST 2012
lib/client/kolab_client_task_settings.php | 269 +++++++++++++++++++++++----
lib/kolab_client_task.php | 24 +-
lib/locale/en_US.php | 24 ++
public_html/js/kolab_admin.js | 250 ++++++++++++++++++++++++-
public_html/skins/default/images/buttons.png |binary
public_html/skins/default/style.css | 59 +++++
6 files changed, 564 insertions(+), 62 deletions(-)
New commits:
commit a98368884d0294fe5145adab25475f29f977e4c9
Author: Aleksander Machniak <alec at alec.pl>
Date: Wed Oct 3 13:27:36 2012 +0200
Object types management - editable
diff --git a/lib/client/kolab_client_task_settings.php b/lib/client/kolab_client_task_settings.php
index 09d7697..1e87de5 100644
--- a/lib/client/kolab_client_task_settings.php
+++ b/lib/client/kolab_client_task_settings.php
@@ -32,9 +32,10 @@ class kolab_client_task_settings extends kolab_client_task
);
protected $form_element_types = array(
- 'text', 'select', 'multiselect', 'list', 'checkbox', 'password'
+ 'text', 'select', 'multiselect', 'list', 'list-autocomplete', 'checkbox', 'password'
);
+
/**
* Default action.
*/
@@ -382,9 +383,11 @@ class kolab_client_task_settings extends kolab_client_task
$title = $add_mode ? $this->translate('type.add') : $data['name'];
// unset $data for correct form_create() run, we've got already data specified
+ $effective_rights = $data['effective_rights'];
+ $id = $data['id'] ? $data['type'].':'.$data['id'] : null;
$data = array();
- // enable delete button
- $data['effective_rights']['entry'] = array('delete');
+ $data['effective_rights'] = $effective_rights;
+ $data['id'] = $id;
// Create form object and populate with fields
$form = $this->form_create('type', $attribs, $sections, $fields, $fields_map, $data, $add_mode);
@@ -431,6 +434,7 @@ class kolab_client_task_settings extends kolab_client_task
'multiple' => true,
'required' => true,
'value' => $data['objectclass'],
+ 'onchange' => "kadm.type_attr_class_change(this)",
),
'used_for' => array(
'value' => 'hosted',
@@ -447,7 +451,7 @@ class kolab_client_task_settings extends kolab_client_task
unset($form_fields['used_for']);
}
-/*
+
// Get the rights on the entry and attribute level
$data['effective_rights'] = $this->effective_rights($name, $data['id']);
$attribute_rights = $data['effective_rights']['attribute'];
@@ -455,7 +459,7 @@ class kolab_client_task_settings extends kolab_client_task
// See if "administrators" (those who can delete and add back on the entry
// level) may override the automatically generated contents of auto_form_fields.
- $admin_auto_fields_rw = $this->config_get('admin_auto_fields_rw', false, Conf::BOOL);
+ //$admin_auto_fields_rw = $this->config_get('admin_auto_fields_rw', false, Conf::BOOL);
foreach ($fields as $idx => $field) {
if (!array_key_exists($idx, $attribute_rights)) {
@@ -481,7 +485,7 @@ class kolab_client_task_settings extends kolab_client_task
}
}
}
-*/
+
// (Re-|Pre-)populate auto_form_fields
if (!$add_mode) {
// Add debug information
@@ -500,7 +504,7 @@ class kolab_client_task_settings extends kolab_client_task
}
// Get object classes
- $sd = $this->form_element_select_data($fields['objectclass']);
+ $sd = $this->form_element_select_data($fields['objectclass'], null, true);
$fields['objectclass'] = array_merge($fields['objectclass'], $sd);
// Add entry identifier
@@ -521,39 +525,42 @@ class kolab_client_task_settings extends kolab_client_task
return $fields;
}
+ /**
+ * Type attributes table
+ */
private function type_form_attributes($data)
{
$attributes = array();
$rows = array();
+ $attr_table = array();
$table = array(
+ 'id' => 'type_attr_table',
'class' => 'list',
);
$cells = array(
'name' => array(
- 'class' => 'name',
'body' => $this->translate('attribute.name'),
),
'type' => array(
- 'class' => 'type',
'body' => $this->translate('attribute.type'),
),
+ 'readonly' => array(
+ 'body' => $this->translate('attribute.readonly'),
+ ),
'optional' => array(
- 'class' => 'optional',
'body' => $this->translate('attribute.optional'),
),
- 'auto' => array(
- 'class' => 'auto',
- 'body' => $this->translate('attribute.auto'),
+ 'value' => array(
+ 'body' => $this->translate('attribute.value'),
),
- 'static' => array(
- 'class' => 'default',
- 'body' => $this->translate('attribute.static'),
+ 'actions' => array(
),
-// 'actions' => array(
-// 'class' => 'actions',
-// ),
);
+ foreach ($cells as $idx => $cell) {
+ $cells[$idx]['class'] = $idx;
+ }
+
// get attributes list from $data
if (!empty($data) && count($data) > 1) {
$attributes = array_merge(
@@ -565,43 +572,229 @@ class kolab_client_task_settings extends kolab_client_task
$attributes = array_unique($attributes);
}
+ // get all available attributes
+ $available = $this->type_attributes($data['objectclass']);
+
// table header
$table['head'] = array(array('cells' => $cells));
-/*
- // attribute row elements
- $cells['type']['element'] = array(
- 'type' => kolab_form::INPUT_SELECT,
- 'options' => $this->form_element_types,
- );
- $cells['optional']['element'] = array(
- 'type' => kolab_form::INPUT_CHECKBOX,
- 'value' => 1,
- );
-*/
+
$yes = $this->translate('yes');
+ $no = '';
// defined attributes
foreach ($attributes as $attr) {
- $row = $cells;
+ $row = $cells;
+ $type = $data['attributes']['form_fields'][$attr]['type'];
+ $optional = $data['attributes']['form_fields'][$attr]['optional'];
+ $autocomplete = $data['attributes']['form_fields'][$attr]['autocomplete'];
+ $valtype = 'normal';
+ $value = '';
+
+ if ($type == 'list' && $autocomplete) {
+ $type = 'list-autocomplete';
+ }
+
+ if ($data['attributes']['fields'][$attr]) {
+ $valtype = 'static';
+ $_data = $data['attributes']['fields'][$attr];
+ $value = $this->translate('attribute.value.static') . ': ' . kolab_html::escape($_data);
+ }
+ else if (isset($data['attributes']['auto_form_fields'][$attr])) {
+ $valtype = 'auto';
+ if (is_array($data['attributes']['auto_form_fields'][$attr]['data'])) {
+ $_data = implode(',', $data['attributes']['auto_form_fields'][$attr]['data']);
+ }
+ else {
+ $_data = '';
+ }
+ $value = $this->translate('attribute.value.auto') . ': ' . kolab_html::escape($_data);
- $type = $data['attributes']['form_fields'][$attr]['type'];
- $optional = $data['attributes']['form_fields'][$attr]['optional'];
+ if (empty($data['attributes']['form_fields'][$attr])) {
+ $valtype = 'auto-readonly';
+ }
+ }
// set cell content
- $row['name']['body'] = $attr;
- $row['static']['body'] = kolab_html::escape($data['attributes']['fields'][$attr]);
- $row['auto']['body'] = isset($data['attributes']['fields'][$attr]) ? $yes : '';
+ $row['name']['body'] = !empty($available[$attr]) ? $available[$attr] : $attr;
$row['type']['body'] = !empty($type) ? $type : 'text';
- $row['optional']['body'] = $optional ? $yes : '';
+ $row['value']['body'] = $value;
+ $row['readonly']['body'] = $valtype == 'auto-readonly' ? $yes : $no;
+ $row['optional']['body'] = $optional ? $yes : $no;
+ $row['actions']['body'] =
+ kolab_html::a(array('href' => '#delete', 'onclick' => "kadm.type_attr_delete('$attr')",
+ 'class' => 'button delete', 'title' => $this->translate('delete')))
+ . kolab_html::a(array('href' => '#edit', 'onclick' => "kadm.type_attr_edit('$attr')",
+ 'class' => 'button edit', 'title' => $this->translate('edit')));
+
+ $rows[] = array(
+ 'id' => 'attr_table_row_' . $attr,
+ 'cells' => $row,
+ );
- $rows[] = array('cells' => $row);
+ // data array for the UI
+ $attr_table[$attr] = array(
+ 'type' => !empty($type) ? $type : 'text',
+ 'valtype' => $valtype,
+ 'optional' => $optional,
+ 'maxcount' => $data['attributes']['form_fields'][$attr]['maxcount'],
+ 'data' => $_data,
+ 'values' => $data['attributes']['form_fields'][$attr]['values'],
+ );
}
+ // edit form
+ $rows[] = array(
+ 'cells' => array(
+ array(
+ 'body' => $this->type_form_attributes_form($available),
+ 'colspan' => count($cells),
+ ),
+ ),
+ 'id' => 'type_attr_form',
+ );
+
$table['body'] = $rows;
+ // sort attr_table by attribute name
+ ksort($attr_table);
+
+ // set environment variables
+ $this->output->set_env('attr_table', $attr_table);
+ $this->output->set_env('yes_label', $yes);
+ $this->output->set_env('no_label', $no);
+ $this->output->add_translation('attribute.value.auto', 'attribute.value.static',
+ 'attribute.key.invalid');
+
+ // Add attribute link
+ $link = kolab_html::a(array(
+ 'href' => '#add_attr', 'class' => 'add_attr',
+ 'onclick' => "kadm.type_attr_add()",
+ 'content' => $this->translate('attribute.add')), true);
+
+ return kolab_html::table($table) . $link;
+ }
+
+ /**
+ * Attributes edit form
+ */
+ private function type_form_attributes_form($attributes)
+ {
+ // build form
+ $rows = array();
+ $form = array(
+ 'name' => array(
+ 'type' => kolab_form::INPUT_SELECT,
+ 'options' => $attributes,
+ ),
+ 'type' => array(
+ 'type' => kolab_form::INPUT_SELECT,
+ 'options' => array_combine($this->form_element_types, $this->form_element_types),
+ 'onchange' => 'kadm.type_attr_type_change(this)',
+ ),
+ 'options' => array(
+ 'type' => kolab_form::INPUT_TEXTAREA,
+ 'data-type' => kolab_form::TYPE_LIST,
+ ),
+ 'maxcount' => array(
+ 'type' => kolab_form::INPUT_TEXT,
+ 'size' => 5,
+ ),
+ 'value' => array(
+ 'type' => kolab_form::INPUT_SELECT,
+ 'options' => array(
+ 'normal' => $this->translate('attribute.value.normal'),
+ 'auto' => $this->translate('attribute.value.auto'),
+ 'auto-readonly' => $this->translate('attribute.value.auto-readonly'),
+ 'static' => $this->translate('attribute.value.static'),
+ ),
+ 'onchange' => 'kadm.type_attr_value_change(this)',
+ ),
+ 'optional' => array(
+ 'type' => kolab_form::INPUT_CHECKBOX,
+ 'value' => 1,
+ ),
+ );
+
+ foreach ($form as $idx => $element) {
+ $element['name'] = 'attr_' . $idx;
+ $body = kolab_form::get_element($element);
+
+ if ($idx == 'value') {
+ $body .= kolab_form::get_element(array(
+ 'name' => 'attr_data',
+ 'type' => kolab_form::INPUT_TEXT,
+ ));
+ }
+
+ $rows[] = array(
+ 'id' => 'attr_form_row_' . $idx,
+ 'cells' => array(
+ array(
+ 'class' => 'label',
+ 'body' => $this->translate('attribute.' . $idx),
+ ),
+ array(
+ 'class' => 'value',
+ 'body' => $body,
+ ),
+ ),
+ );
+ }
+
+ $rows[] = array(
+ 'cells' => array(
+ array(
+ 'colspan' => 2,
+ 'class' => 'formbuttons',
+ 'body' => kolab_html::input(array(
+ 'type' => 'button',
+ 'value' => $this->translate('button.save'),
+ 'onclick' => "kadm.type_attr_save()",
+ ))
+ . kolab_html::input(array(
+ 'type' => 'button',
+ 'value' => $this->translate('button.cancel'),
+ 'onclick' => "kadm.type_attr_cancel()",
+ )),
+ ),
+ ),
+ );
+
+ $table = array(
+ 'class' => 'form',
+ 'body' => $rows,
+ );
+
return kolab_html::table($table);
}
/**
+ * Returns list of LDAP attributes for specified opject classes.
+ */
+ public function type_attributes($object_class = null)
+ {
+ $post_data = array(
+ 'attributes' => array('attribute'),
+ 'classes' => $object_class,
+ );
+
+ // get all available attributes
+ $response = $this->api->post('form_value.select_options', null, $post_data);
+ $response = $response->get('attribute');
+ $attributes = array();
+
+ // convert to hash array
+ if (!empty($response['list'])) {
+ $attributes = array_combine(array_map('strtolower', $response['list']), $response['list']);
+ }
+
+ $this->output->set_env('attributes', $attributes);
+ // @TODO: check if all required attributes are used
+// $this->output->set_env('attributes_required', $attributes['required']);
+
+ return $attributes;
+ }
+
+ /**
* Users search form.
*
* @return string HTML output of the form
diff --git a/lib/kolab_client_task.php b/lib/kolab_client_task.php
index 13a90f1..fec0404 100644
--- a/lib/kolab_client_task.php
+++ b/lib/kolab_client_task.php
@@ -279,10 +279,10 @@ class kolab_client_task
// Run security checks
$this->input_checks();
- $action = $this->get_input('action', 'GET');
+ $this->action = $this->get_input('action', 'GET');
- if ($action) {
- $method = 'action_' . $action;
+ if ($this->action) {
+ $method = 'action_' . $this->action;
if (method_exists($this, $method)) {
$this->$method();
}
@@ -817,10 +817,11 @@ class kolab_client_task
*
* @param array $field Field attributes
* @param array $data Attribute values
+ * @param bool $lc Convert option values to lower-case
*
* @return array Options/Default definition
*/
- protected function form_element_select_data($field, $data = array())
+ protected function form_element_select_data($field, $data = array(), $lc = false)
{
$options = array();
$default = null;
@@ -836,7 +837,12 @@ class kolab_client_task
}
if (!empty($field['values'])) {
- $options = array_combine($field['values'], $field['values']);
+ if ($lc) {
+ $options = array_combine(array_map('strtolower', $field['values']), $field['values']);
+ }
+ else {
+ $options = array_combine($field['values'], $field['values']);
+ }
// Exceptions
if ($field['name'] == 'ou') {
@@ -1237,7 +1243,7 @@ class kolab_client_task
if ($writeable) {
$form->add_button(array(
- 'value' => kolab_html::escape($this->translate('submit.button')),
+ 'value' => kolab_html::escape($this->translate('button.submit')),
'onclick' => "kadm.{$name}_save()",
));
}
@@ -1245,7 +1251,7 @@ class kolab_client_task
if (!empty($data['id']) && in_array('delete', $data['effective_rights']['entry'])) {
$id = $data['id'];
$form->add_button(array(
- 'value' => kolab_html::escape($this->translate('delete.button')),
+ 'value' => kolab_html::escape($this->translate('button.delete')),
'onclick' => "kadm.{$name}_delete('{$id}')",
));
}
diff --git a/lib/locale/en_US.php b/lib/locale/en_US.php
index 9f5561e..23d81d4 100644
--- a/lib/locale/en_US.php
+++ b/lib/locale/en_US.php
@@ -7,16 +7,29 @@ $LANG['about.support'] = 'Professional support is available from <a href="http:/
$LANG['about.technology'] = 'Technology';
$LANG['about.warranty'] = 'It comes with absolutely <b>no warranties</b> and is typically run entirely self supported. You can find help & information on the community <a href="http://kolab.org">web site</a> & <a href="http://wiki.kolab.org">wiki</a>.';
-$LANG['attribute.auto'] = 'Auto-generated';
+$LANG['attribute.add'] = 'Add attribute';
$LANG['attribute.static'] = 'Static value';
$LANG['attribute.name'] = 'Attribute';
$LANG['attribute.optional'] = 'Optional';
+$LANG['attribute.maxcount'] = 'Max. count';
+$LANG['attribute.readonly'] = 'Read-only';
$LANG['attribute.type'] = 'Field type';
+$LANG['attribute.value'] = 'Value';
+$LANG['attribute.value.auto'] = 'Generated';
+$LANG['attribute.value.auto-readonly'] = 'Generated (read-only)';
+$LANG['attribute.value.normal'] = 'Normal';
+$LANG['attribute.value.static'] = 'Static';
+$LANG['attribute.options'] = 'Options';
+$LANG['attribute.key.invalid'] = 'Type key contains forbidden characters!';
+
+$LANG['button.cancel'] = 'Cancel';
+$LANG['button.delete'] = 'Delete';
+$LANG['button.save'] = 'Save';
+$LANG['button.submit'] = 'Submit';
$LANG['creatorsname'] = 'Created by';
$LANG['days'] = 'days';
$LANG['debug'] = 'Debug info';
-$LANG['delete.button'] = 'Delete';
$LANG['deleting'] = 'Deleting data...';
$LANG['domain.add'] = 'Add Domain';
@@ -140,12 +153,13 @@ $LANG['signup.wronguid'] = 'Invalid Username!';
$LANG['signup.wrongmailalternateaddress'] = 'Please provide a valid Email Address!';
$LANG['signup.footer'] = 'This is a service offered by <a href="http://kolabsys.com">Kolab Systems</a>.';
-$LANG['submit.button'] = 'Submit';
-
$LANG['type.add'] = 'Add Object Type';
+$LANG['type.add.success'] = 'Object type created successfully.';
$LANG['type.attributes'] = 'Attributes';
$LANG['type.description'] = 'Description';
+$LANG['type.delete.success'] = 'Object type deleted successfully.';
$LANG['type.domain'] = 'Domain';
+$LANG['type.edit.success'] = 'Object type updated successfully.';
$LANG['type.group'] = 'Group';
$LANG['type.list'] = 'Object Types List';
$LANG['type.key'] = 'Key';
@@ -240,3 +254,5 @@ $LANG['user.userpassword2'] = 'Confirm password';
$LANG['user.uidnumber'] = 'User ID number';
$LANG['welcome'] = 'Welcome to the Kolab Groupware Server Maintenance';
+
+$LANG['yes'] = 'yes';
diff --git a/public_html/js/kolab_admin.js b/public_html/js/kolab_admin.js
index c58a592..e4bf81e 100644
--- a/public_html/js/kolab_admin.js
+++ b/public_html/js/kolab_admin.js
@@ -1648,9 +1648,6 @@ function kolab_admin()
this.type_delete = function(id)
{
- // @TODO:
- return alert('Not implemented');
-
this.set_busy(true, 'deleting');
this.api_post('type.delete', this.type_id_parse(id), 'type_delete_response');
};
@@ -1667,16 +1664,14 @@ function kolab_admin()
page -= 1;
this.display_message('type.delete.success');
- this.command('type.list', {page: page});
+ this.command('settings.type_list', {page: page});
this.set_watermark('taskcontent');
};
this.type_save = function(reload, section)
{
- // @TODO:
- return alert('Not implemented');
-
- var data = this.serialize_form('#'+this.env.form_id),
+ var i, attr, request = {},
+ data = this.serialize_form('#'+this.env.form_id),
action = data.id ? 'edit' : 'add';
if (reload) {
@@ -1692,8 +1687,57 @@ function kolab_admin()
return;
}
+ if (data.key.match(/[^a-z_-]/)) {
+ this.display_message('attribute.key.invalid', 'error');
+ return;
+ }
+
+ request.id = data.id;
+ request.key = data.key;
+ request.name = data.name;
+ request.type = data.type;
+ request.description = data.description;
+ request.used_for = data.used_for;
+ request.attributes = {fields: {}, form_fields: {}, auto_form_fields: {}};
+ request.attributes.fields.objectclass = data.objectclass;
+
+ // Build attributes array compatible with the API format
+ // @TODO: use attr_table format
+ for (i in this.env.attr_table) {
+ attr = this.env.attr_table[i];
+ data = {};
+
+ if (attr.valtype == 'static') {
+ request.attributes.fields[i] = attr.data;
+ continue;
+ }
+
+ if (attr.type == 'list-autocomplete') {
+ data.type = 'list';
+ data.autocomplete = true;
+ }
+ else if (attr.type != 'text')
+ data.type = attr.type;
+
+ if ((attr.type == 'select' || attr.type == 'multiselect') && attr.values)
+ data.values = attr.values;
+
+ if (attr.optional)
+ data.optional = true;
+ if (attr.maxcount)
+ data.maxcount = attr.maxcount;
+
+ if (attr.valtype == 'normal' || attr.valtype == 'auto')
+ request.attributes.form_fields[i] = data;
+ if (attr.valtype == 'auto' || attr.valtype == 'auto-readonly') {
+ if (attr.data)
+ data.data = attr.data.split(/,/);
+ request.attributes.auto_form_fields[i] = data;
+ }
+ }
+
this.set_busy(true, 'saving');
- this.api_post('type.' + action, data, 'type_' + action + '_response');
+ this.api_post('type.' + action, request, 'type_' + action + '_response');
};
this.type_add_response = function(response)
@@ -1716,12 +1760,199 @@ function kolab_admin()
this.set_watermark('taskcontent');
};
+ /*********************************************************/
+ /********* Various helper methods *********/
+ /*********************************************************/
+
+ // Parses object type identifier
this.type_id_parse = function(id)
{
var id = String(id).split(':');
return {type: id[0], id: id[1]};
};
+ // Removes attribute row
+ this.type_attr_delete = function(attr)
+ {
+ $('#attr_table_row_' + attr).remove();
+ $('select[name="attr_name"] > option[value="'+attr+'"]').show();
+
+ delete this.env.attr_table[attr];
+ this.type_attr_cancel();
+ };
+
+ // Displays attribute edition form
+ this.type_attr_edit = function(attr)
+ {
+ var form = $('#type_attr_form');
+
+ form.detach();
+ $('#attr_table_row_'+attr).after(form);
+ this.type_attr_form_init(attr);
+ form.slideDown(400);
+ };
+
+ // Displays attribute addition form
+ this.type_attr_add = function()
+ {
+ var form = $('#type_attr_form');
+
+ form.detach();
+ $('#type_attr_table > tbody').append(form);
+ this.type_attr_form_init();
+ form.slideDown(400);
+ };
+
+ // Saves attribute form, create/update attribute row
+ this.type_attr_save = function()
+ {
+ var attr, row, value = '', data = {},
+ form_data = this.serialize_form('#'+this.env.form_id),
+ name_select = $('select[name="attr_name"]');
+
+ // read attribute form data
+ data.type = form_data.attr_type;
+ data.valtype = form_data.attr_value;
+ data.optional = form_data.attr_optional;
+ data.data = data.valtype != 'normal' ? form_data.attr_data : null;
+ data.maxcount = data.type == 'list' || data.type == 'list-autocomplete' ? form_data.attr_maxcount : 0;
+ data.values = data.type == 'select' || data.type == 'multiselect' ? form_data.attr_options : [];
+
+ if (name_select.is(':visible')) {
+ // new attribute
+ attr = name_select.val();
+ row = $('<tr><td class="name"></td><td class="type"></td><td class="readonly"></td>'
+ +'<td class="optional"></td><td class="value"></td><td class="actions">'
+ +'<a class="button delete" title="delete" onclick="kadm.type_attr_delete(\''+attr+'\')" href="#delete"></a>'
+ +'<a class="button edit" title="edit" onclick="kadm.type_attr_edit(\''+attr+'\')" href="#edit"></a></td></tr>')
+ .attr('id', 'attr_table_row_' + attr).appendTo('#type_attr_table > tbody');
+ }
+ else {
+ // edited attribute
+ attr = $('span', name_select.parent()).text().toLowerCase();
+ row = $('#attr_table_row_' + attr);
+ }
+
+ if (data.valtype != 'normal') {
+ value = this.t('attribute.value.' + (data.valtype == 'static' ? 'static' : 'auto')) + ': ' + data.data;
+ }
+
+ // Update table row
+ $('td.name', row).text(this.env.attributes[attr]);
+ $('td.type', row).text(data.type);
+ $('td.readonly', row).text(data.valtype == 'auto-readonly' ? this.env.yes_label : this.env.no_label);
+ $('td.optional', row).text(data.optional ? this.env.yes_label : this.env.no_label);
+ $('td.value', row).text(value);
+
+ // Update env data
+ this.env.attr_table[attr] = data;
+
+ this.type_attr_cancel();
+ };
+
+ // Hide attribute form
+ this.type_attr_cancel = function()
+ {
+ $('#type_attr_form').hide();
+ };
+
+ this.type_attr_form_init = function(attr)
+ {
+ var name_select = $('select[name="attr_name"]'),
+ data = attr ? this.env.attr_table[attr] : {},
+ type = data.type ? data.type : 'text';
+
+ $('select[name="attr_type"]').val(type);
+ $('select[name="attr_value"]').val(attr ? data.valtype : 'normal');
+ $('input[name="attr_optional"]').attr('checked', attr ? data.optional : false);
+ $('input[name="attr_data"]').val(attr ? data.data : '');
+ $('input[name="attr_maxcount"]').val(data.maxcount ? data.maxcount : '');
+ $('textarea[name="attr_options"]').val(data.values ? data.values.join("\n") : '');
+ this.form_element_update({name: 'attr_options'});
+
+ $('span', name_select.parent()).remove();
+ this.type_attr_type_change('select[name="attr_type"]');
+ this.type_attr_value_change('select[name="attr_value"]');
+
+ if (attr) {
+ name_select.hide().val(attr);
+ $('<span></span>').text(this.env.attributes[attr] ? this.env.attributes[attr] : attr).appendTo(name_select.parent());
+ return;
+ }
+
+ this.type_attr_select_init();
+ name_select.show();
+ };
+
+ // Initialize attribute name selector
+ this.type_attr_select_init = function()
+ {
+ var select = $('select[name="attr_name"]'),
+ options = $('option', select);
+
+ options.each(function() {
+ if (kadm.env.attr_table[this.value])
+ $(this).attr('disabled', true);
+ });
+ options.not(':disabled').first().attr('selected', true);
+ };
+
+ // Update attribute form on value type change
+ this.type_attr_value_change = function(elem)
+ {
+ var type = $(elem).val();
+ $('input[name="attr_data"]')[type != 'normal' ? 'show' : 'hide']();
+ $('#attr_form_row_optional')[type != 'static' ? 'show' : 'hide']();
+ $('#attr_form_row_readonly')[type != 'static' ? 'show' : 'hide']();
+ };
+
+ // Update attribute form on type change
+ this.type_attr_type_change = function(elem)
+ {
+ var type = $(elem).val();
+ $('#attr_form_row_maxcount')[type == 'list' || type == 'list-autocomplete' ? 'show' : 'hide']();
+ $('#attr_form_row_options')[type == 'select' || type == 'multiselect' ? 'show' : 'hide']();
+ };
+
+ // Update attributes list on object classes change
+ this.type_attr_class_change = function(field)
+ {
+ var data = {attributes: 'attribute', classes: this.type_object_classes(field)};
+ this.api_post('form_value.select_options', data, 'type_attr_class_change_response');
+ this.type_attr_cancel();
+ };
+
+ // Update attributes list on object classes change - API response handler
+ this.type_attr_class_change_response = function(response)
+ {
+ if (!this.api_response(response))
+ return;
+
+ var i, lc, list = response.result.attribute.list,
+ required = response.result.attribute.required,
+ select = $('select[name="attr_name"]');
+
+ this.env.attributes = {};
+ select.empty();
+
+ for (i in list) {
+ lc = list[i].toLowerCase()
+ this.env.attributes[list[i].toLowerCase()] = list[i];
+ $('<option>').text(list[i]).val(lc).appendTo(select);
+ }
+ };
+
+ // Return selected objectclasses array
+ this.type_object_classes = function(field)
+ {
+ var classes = [];
+ $('option:selected', $(field)).each(function() {
+ classes.push(this.value);
+ });
+ return classes;
+ };
+
+ // Password generation - request
this.generate_password = function(fieldname)
{
this.env.password_field = fieldname;
@@ -1730,6 +1961,7 @@ function kolab_admin()
this.api_post('form_value.generate', {attributes: [fieldname]}, 'generate_password_response');
};
+ // Password generation - response handler
this.generate_password_response = function(response)
{
if (!this.api_response(response))
diff --git a/public_html/skins/default/style.css b/public_html/skins/default/style.css
index 201e7f6..cf597ee 100644
--- a/public_html/skins/default/style.css
+++ b/public_html/skins/default/style.css
@@ -117,11 +117,13 @@ table.form td {
}
table.form tr.required input,
+table.form tr.required select,
table.form tr.required textarea {
background-color: #f0f9ff;
}
table.form tr input.error,
+table.form tr select.error,
table.form tr textarea.error {
background-color: #f5e3e3;
}
@@ -472,6 +474,7 @@ input.inactive {
.formbuttons {
text-align: center;
+ white-space: nowrap;
}
.formbuttons input {
@@ -548,6 +551,21 @@ pre.debug {
-o-box-shadow: 0 2px 6px 0 #333;
}
+a.button {
+ display: inline-block;
+ width: 18px;
+ height: 18px;
+ background: url(images/buttons.png) 0 0 no-repeat;
+}
+
+a.button.edit {
+ background-position: -81px 0;
+}
+
+a.button.delete {
+ background-position: -1px 0;
+}
+
/********* Form smart inputs *********/
span.listarea {
@@ -944,3 +962,40 @@ td.no {
font-weight: bold;
text-align: center;
}
+
+/**** Settings ****/
+
+table.form table.list td {
+ padding: 2px 4px;
+}
+
+#type_attr_table td.actions {
+ width: 40px;
+ padding: 0;
+ white-space: nowrap;
+}
+
+#type_attr_table thead td {
+ white-space: nowrap;
+}
+
+#type_attr_table tfoot span {
+ cursor: pointer;
+}
+
+#type_attr_table td.readonly {
+ color: #514949;
+}
+
+#type_attr_form {
+ display: none;
+}
+
+#type_attr_form table.form td {
+ border: none;
+}
+
+a.add_attr {
+ padding-left: 2px;
+ padding-top: 2px;
+}
commit 9f5c62f030f174ebb95d0a3544c33610c6820bf4
Author: Aleksander Machniak <alec at alec.pl>
Date: Fri Sep 28 08:14:53 2012 +0200
Add edit button for future use
diff --git a/public_html/skins/default/images/buttons.png b/public_html/skins/default/images/buttons.png
index 586851e..d206367 100644
Binary files a/public_html/skins/default/images/buttons.png and b/public_html/skins/default/images/buttons.png differ
diff --git a/public_html/skins/default/style.css b/public_html/skins/default/style.css
index db3e596..201e7f6 100644
--- a/public_html/skins/default/style.css
+++ b/public_html/skins/default/style.css
@@ -629,11 +629,11 @@ span.listelement span.actions span.reset {
}
span.listelement span.actions span.add {
- background-position: -43px -2px;
+ background-position: -41px -2px;
}
span.listelement span.actions span.search {
- background-position: -65px -1px;
+ background-position: -61px -1px;
cursor: default;
}
commit 9209287971a6683cd28547669cd60994e9feeb1d
Author: Aleksander Machniak <alec at alec.pl>
Date: Thu Sep 27 15:03:57 2012 +0200
Fix PHP warning when capability response is empty/malformed
diff --git a/lib/kolab_client_task.php b/lib/kolab_client_task.php
index 4326b9a..13a90f1 100644
--- a/lib/kolab_client_task.php
+++ b/lib/kolab_client_task.php
@@ -504,11 +504,11 @@ class kolab_client_task
$menu = array();
$task = $this->get_task();
- $caps = $this->capabilities();
+ $caps = (array) $this->get_capability('actions');
foreach ($this->menu as $idx => $label) {
if (in_array($task, array('domain', 'group', 'resource', 'role', 'user'))) {
- if (!array_key_exists($task . "." . $idx, $caps['actions'])) {
+ if (!array_key_exists($task . "." . $idx, $caps)) {
continue;
}
}
More information about the commits
mailing list