diff --git a/lib/client/kolab_client_task_settings.php b/lib/client/kolab_client_task_settings.php index 961b457..af544be 100644 --- a/lib/client/kolab_client_task_settings.php +++ b/lib/client/kolab_client_task_settings.php @@ -1,978 +1,978 @@ | +--------------------------------------------------------------------------+ | Author: Aleksander Machniak | +--------------------------------------------------------------------------+ */ class kolab_client_task_settings extends kolab_client_task { protected $ajax_only = true; protected $menu = array( 'type_list' => 'type.list', 'type.add' => 'type.add', ); protected $form_element_types = array( 'text', 'text-separated', 'text-quota', 'text-autocomplete', 'select', 'multiselect', 'list', 'list-autocomplete', 'checkbox', 'password', 'ldap_url', 'aci', 'imap_acl', ); protected $special_attributes = array('ou'); /** * Default action. */ public function action_default() { $caps_actions = $this->get_capability('actions'); // Display user info by default if (self::can_edit_self($caps_actions)) { $this->action_info(); } // otherwise display object types list else if (self::can_edit_types($caps_actions)) { $this->action_type_list(); unset($this->menu['type_list']); // ... and type add form if (!empty($caps_actions['type.add'])) { $this->action_type_add(); } else { $this->output->command('set_watermark', 'taskcontent'); } } // fallback else { $this->output->command('set_watermark', 'content'); } $this->output->set_object('task_navigation', $this->menu()); } /** * Checks if it's possible to edit data of current user */ private static function can_edit_self($caps_actions) { // Disable user form for directory manager (see #1025) if (preg_match('/^cn=([a-z ]+)/i', $_SESSION['user']['id'])) { return false; } if (empty($caps_actions['user.info'])) { return false; } // If we can do user.info, we can at least display // the form, effective rights will be checked later // there's a very small chance that user cannot view his data return true; } /** * Checks if it's possible to edit object types */ private static function can_edit_types($caps_actions) { // I think type management interface shouldn't be displayed at all // if user has no write rights to 'type' service if (!empty($caps_actions['type.edit']) || !empty($caps_actions['type.add']) || !empty($caps_actions['type.delete'])) { return true; } return false; } /** * Check if any of task actions is accessible for current user * * @return bool */ public static function is_enabled($caps_actions) { // User form if (self::can_edit_self($caps_actions)) { return true; } if (self::can_edit_types($caps_actions)) { return true; } return false; } /** * Returns task menu output (overrides parent's menu method). * * @return string HTML output */ protected function menu() { $caps = $this->capabilities(); $menu = array(); foreach ($this->menu as $idx => $label) { if (strpos($idx, '.') && !array_key_exists($idx, (array)$caps['actions'])) { continue; } $idx = str_replace('.', '_', $idx); $action = 'settings.' . $idx; $class = $idx; $menu[$idx] = sprintf('
  • ' .'%s
  • ', $class, $idx, $action, $this->translate($label)); } return ''; } /** * User info action. */ public function action_info() { $_POST['id'] = $_SESSION['user']['id']; $user_task = new kolab_client_task_user($this->output); $user_task->action_info(); - $this->output->set_object('content', $this->output->get_object('taskcontent')); + $this->output->set_object('content', '
    ' . $this->output->get_object('taskcontent') . '
    '); } /** * Object types list action. */ public function action_type_list() { $page_size = 20; $page = (int) self::get_input('page', 'POST'); if (!$page || $page < 1) { $page = 1; } // request parameters $post = array( 'attributes' => array('name', 'key'), // 'sort_order' => 'ASC', 'sort_by' => array('name', 'key'), 'page_size' => $page_size, 'page' => $page, ); // search parameters if (!empty($_POST['search'])) { $search = self::get_input('search', 'POST', true); $field = self::get_input('field', 'POST'); $method = self::get_input('method', 'POST'); $search_request = array( $field => array( 'value' => $search, 'type' => $method, ), ); } else if (!empty($_POST['search_request'])) { $search_request = self::get_input('search_request', 'POST'); $search_request = @unserialize(base64_decode($search_request)); } if (!empty($search_request)) { $post['search'] = $search_request; $post['search_operator'] = 'OR'; } else { $this->output->set_object('content', 'type', true); } // object type $type = self::get_input('type', 'POST'); if (empty($type) || !in_array($type, $this->object_types)) { $type = 'user'; } // get object types list $result = $this->object_types($type); // Implement searching here, not in the API, we don't expect too many records if (!empty($search_request)) { foreach ($result as $idx => $record) { $found = false; foreach ($search_request as $key => $value) { if (!empty($record[$key])) { $s = mb_strtoupper($value['value']); $v = mb_strtoupper($record[$key]); switch ($value['type']) { case 'both': $res = $v === $s || strpos($v, $s) !== false; break; case 'exact': $res = $v === $s; break; case 'prefix': $res = strpos($v, $s) === 0; break; } if ($res) { $found = true; break; } } } if (!$found) { unset($result[$idx]); } } } // assign ID foreach (array_keys($result) as $idx) { $result[$idx]['id'] = $idx; } $result = array_values($result); $count = count($result); // calculate records if ($count) { $start = 1 + max(0, $page - 1) * $page_size; $end = min($start + $page_size - 1, $count); // sort and slice the result array if ($count > $page_size) { $result = array_slice($result, $start - 1, $page_size); } } $rows = $head = $foot = array(); $cols = array('name'); $i = 0; // table header $head[0]['cells'][] = array('class' => 'name', 'body' => $this->translate('type.list')); // table footer (navigation) if ($count) { $pages = ceil($count / $page_size); $prev = max(0, $page - 1); $next = $page < $pages ? $page + 1 : 0; $count_str = kolab_html::span(array( 'content' => $this->translate('list.records', $start, $end, $count)), true); $prev = kolab_html::a(array( 'class' => 'prev font-icon' . ($prev ? '' : ' disabled'), 'href' => '#', 'onclick' => $prev ? "kadm.command('settings.type_list', {page: $prev})" : "return false", )); $next = kolab_html::a(array( 'class' => 'next font-icon' . ($next ? '' : ' disabled'), 'href' => '#', 'onclick' => $next ? "kadm.command('settings.type_list', {page: $next})" : "return false", )); $foot_body = kolab_html::span(array('content' => $prev . $count_str . $next)); } $foot[0]['cells'][] = array('class' => 'listnav', 'body' => $foot_body); // table body if (!empty($result)) { foreach ($result as $idx => $item) { if (!is_array($item) || empty($item['name'])) { continue; } $i++; $cells = array(); $cells[] = array('class' => 'name', 'body' => kolab_html::escape($item['name']), 'onclick' => "kadm.command('settings.type_info', '$type:" . $item['id'] . "')"); $rows[] = array('id' => $i, 'class' => 'selectable', 'cells' => $cells); } } else { $rows[] = array('cells' => array( 0 => array('class' => 'empty-body', 'body' => $this->translate('type.norecords') ))); } $table = kolab_html::table(array( 'id' => 'settingstypelist', 'class' => 'list table table-sm', 'head' => $head, 'body' => $rows, 'foot' => $foot, )); if ($this->action == 'type_list') { $this->output->command('set_watermark', 'taskcontent'); } $this->output->set_env('search_request', $search_request ? base64_encode(serialize($search_request)) : null); $this->output->set_env('list_page', $page); $this->output->set_env('list_count', $count); $this->output->set_env('list_size', count($result)); $this->output->set_object('typelist', $table); } /** * Object type information (form) action. */ public function action_type_info() { $id = $this->get_input('id', 'POST'); $result = $this->read_type_data($id); $output = $this->type_form($result['attribs'], $result['data']); $this->output->set_object('taskcontent', $output); } /** * Object type adding (form) action. */ public function action_type_add() { if ($clone_id = $this->get_input('clone_id', 'POST')) { $result = $this->read_type_data($clone_id); $data = $result['data']; unset($data['id'], $data['is_default'], $data['key'], $data['name']); } if (empty($data)) { $data = $this->get_input('data', 'POST'); if (empty($data['type'])) { $data['type'] = self::get_input('type', 'POST'); if (empty($data['type']) || !in_array($data['type'], $this->object_types)) { $data['type'] = 'user'; } } } $output = $this->type_form(null, $data, true); $this->output->set_object('taskcontent', $output); } private function read_type_data($id, $clone = false) { $data = array(); $attribs = array(); list($type, $idx) = explode(':', $id); if ($idx && $type && ($result = $this->object_types($type))) { if (!empty($result[$idx])) { $data = $result[$idx]; } } // prepare data for form if (!empty($data)) { $data['id'] = $idx; $data['type'] = $type; $data['objectclass'] = $data['attributes']['fields']['objectclass']; unset($data['attributes']['fields']['objectclass']); // enable Clone button if (!$clone) { $caps_actions = $this->get_capability('actions'); if (!empty($caps_actions['type.add'])) { $attribs = array('clone-button' => 'settings.type_clone'); } } } return array( 'data' => $data, 'attribs' => $attribs, ); } /** * Group edit/add form. */ private function type_form($attribs, $data = array()) { if (!is_array($attribs)) { $attribs = array(); } if (empty($attribs['id'])) { $attribs['id'] = 'type-form'; } // Form sections $sections = array( 'props' => 'type.properties', 'attribs' => 'type.attributes', ); // field-to-section map and fields order $fields_map = array( 'id' => 'props', 'type' => 'props', 'key' => 'props', 'name' => 'props', 'description' => 'props', 'objectclass' => 'props', 'used_for' => 'props', 'is_default' => 'props', 'attributes' => 'attribs', ); // Prepare fields $fields = $this->type_form_prepare($data); $add_mode = empty($data['id']); $title = $add_mode ? $this->translate('type.add') : $data['name']; $data['id'] = $data['id'] ? $data['type'].':'.$data['id'] : null; // Create form object and populate with fields $form = $this->form_create('type', $attribs, $sections, $fields, $fields_map, $data, $add_mode); $form->set_title(kolab_html::escape($title)); return $form->output(); } /** * HTML Form elements preparation. * * @param array $data Object data * * @return array Fields list */ protected function type_form_prepare(&$data) { // select top class by default for new type if (empty($data['objectclass'])) { $data['objectclass'] = array('top'); } // Get the rights on the entry and attribute level $data['effective_rights'] = $this->effective_rights('type', $data['id']); $attribute_rights = (array) $data['effective_rights']['attribute']; $entry_rights = (array) $data['effective_rights']['entry']; $add_mode = empty($data['id']); $fields = array( 'key' => array( 'type' => kolab_form::INPUT_TEXT, 'required' => true, 'value' => $data['key'], ), 'name' => array( 'type' => kolab_form::INPUT_TEXT, 'required' => true, 'value' => $data['name'], ), 'description' => array( 'type' => kolab_form::INPUT_TEXTAREA, 'value' => $data['description'], ), 'objectclass' => array( 'type' => kolab_form::INPUT_SELECT, 'name' => 'objectclass', // needed for form_element_select_data() below 'multiple' => true, 'required' => true, 'value' => $data['objectclass'], 'onchange' => "kadm.type_attr_class_change(this)", ), 'used_for' => array( 'value' => 'hosted', 'type' => kolab_form::INPUT_CHECKBOX, 'checked' => !empty($data['used_for']) && $data['used_for'] == 'hosted', ), 'is_default' => array( 'value' => '1', 'type' => kolab_form::INPUT_CHECKBOX, 'checked' => !empty($data['is_default']), ), 'attributes' => array( 'type' => kolab_form::INPUT_CONTENT, 'content' => $this->type_form_attributes($data), ), ); if ($data['type'] != 'user') { unset($form_fields['used_for']); } // 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); foreach ($fields as $idx => $field) { if (!array_key_exists($idx, $attribute_rights)) { // If the entry level rights contain 'add' and 'delete', well, you're an admin if (in_array('add', $entry_rights) && in_array('delete', $entry_rights)) { if ($admin_auto_fields_rw) { $fields[$idx]['readonly'] = false; } } else { $fields[$idx]['readonly'] = true; } } else { if (in_array('add', $entry_rights) && in_array('delete', $entry_rights)) { if ($admin_auto_fields_rw) { $fields[$idx]['readonly'] = false; } } // Explicit attribute level rights, check for 'write' elseif (!in_array('write', $attribute_rights[$idx])) { $fields[$idx]['readonly'] = true; } } } // (Re-|Pre-)populate auto_form_fields if (!$add_mode) { // Add debug information if ($this->devel_mode) { ksort($data); $debug = kolab_html::escape(print_r($data, true)); $debug = preg_replace('/(^Array\n\(|\n*\)$|\t)/', '', $debug); $debug = str_replace("\n ", "\n", $debug); $debug = '
    ' . $debug . '
    '; $fields['debug'] = array( 'label' => 'debug', 'section' => 'props', 'value' => $debug, ); } } // Get object classes $sd = $this->form_element_select_data($fields['objectclass'], null, true); $fields['objectclass'] = array_merge($fields['objectclass'], $sd); // Add entry identifier if (!$add_mode) { $fields['id'] = array( 'section' => 'props', 'type' => kolab_form::INPUT_HIDDEN, 'value' => $data['id'], ); } $fields['type'] = array( 'section' => 'props', 'type' => kolab_form::INPUT_HIDDEN, 'value' => $data['type'] ?: 'user', ); 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 table table-sm', ); $cells = array( 'name' => array( 'body' => $this->translate('attribute.name'), ), 'type' => array( 'body' => $this->translate('attribute.type'), ), 'readonly' => array( 'body' => $this->translate('attribute.readonly'), ), 'optional' => array( 'body' => $this->translate('attribute.optional'), ), 'validate' => array( 'body' => $this->translate('attribute.validate'), ), ); if (!empty($data['effective_rights']['entry'])) { $cells['actions'] = array(); } foreach ($cells as $idx => $cell) { $cells[$idx]['class'] = $idx; } // get attributes list from $data if (!empty($data) && count($data) > 1) { $attributes = array_merge( array_keys((array) $data['attributes']['auto_form_fields']), array_keys((array) $data['attributes']['form_fields']), array_keys((array) $data['attributes']['fields']) ); $attributes = array_filter($attributes); $attributes = array_unique($attributes); } // get all available attributes $available = $this->type_attributes($data['objectclass']); // table header $table['head'] = array(array('cells' => $cells)); $rights = (array)$data['effective_rights']['attribute']['attributes']; $yes = $this->translate('yes'); $no = ''; // defined attributes foreach ($attributes as $attr) { $row = $cells; $type = $data['attributes']['form_fields'][$attr]['type'] ?: 'text'; $optional = $data['attributes']['form_fields'][$attr]['optional']; $autocomplete = $data['attributes']['form_fields'][$attr]['autocomplete']; $validate = $data['attributes']['form_fields'][$attr]['validate']; $valtype = 'normal'; $value = ''; if ($type == 'list' && $autocomplete) { $type = 'list-autocomplete'; } else if ($type == 'text' && $autocomplete) { $type = 'text-autocomplete'; } if ($data['attributes']['fields'][$attr]) { $valtype = 'static'; $_data = $data['attributes']['fields'][$attr]; $_data = is_array($_data) ? implode(',', $_data) : $_data; $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'); if (!empty($_data)) { $value . ': ' . kolab_html::escape($_data); } if (!array_key_exists($attr, (array) $data['attributes']['form_fields'])) { $valtype = 'auto-readonly'; } if (empty($type) && !empty($data['attributes']['auto_form_fields'][$attr]['type'])) { $type = $data['attributes']['auto_form_fields'][$attr]['type']; } } $n_validate = $validate === false ? 'none' : $validate ? $validate : 'default'; // set cell content $row['name']['body'] = !empty($available[$attr]) ? $available[$attr] : $attr; $row['type']['body'] = $type; $row['readonly']['body'] = $valtype == 'auto-readonly' ? $yes : $no; $row['optional']['body'] = $optional ? $yes : $no; $row['validate']['body'] = $this->translate('attribute.validate.' . $n_validate); if (!empty($row['actions'])) { $row['actions']['body'] = ''; if (in_array('delete', $rights)) { $row['actions']['body'] .= kolab_html::a(array( 'href' => '#delete', 'onclick' => "kadm.type_attr_delete('$attr')", 'class' => 'button font-icon delete', 'title' => $this->translate('delete'))); } if (in_array('write', $rights)) { $row['actions']['body'] .= kolab_html::a(array( 'href' => '#edit', 'onclick' => "kadm.type_attr_edit('$attr')", 'class' => 'button font-icon edit', 'title' => $this->translate('edit'))); } } $rows[] = array( 'id' => 'attr_table_row_' . $attr, 'title' => $value, 'cells' => $row, ); // data array for the UI $attr_table[$attr] = array( 'type' => !empty($type) ? $type : 'text', 'valtype' => $valtype, 'optional' => $optional, 'validate' => $n_validate, 'maxcount' => $data['attributes']['form_fields'][$attr]['maxcount'], 'data' => $_data, 'values' => $data['attributes']['form_fields'][$attr]['values'], 'default' => $data['attributes']['form_fields'][$attr]['default'], ); } // 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', 'attribute.required.error', 'attribute.validate.default', 'attribute.validate.basic', 'attribute.validate.none', 'attribute.validate.extended' ); // Add attribute link if (in_array('write', $rights)) { $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 $form = array( 'name' => array( 'type' => kolab_form::INPUT_SELECT, 'options' => $attributes, 'onchange' => 'kadm.type_attr_name_change(this)', ), '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' => '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)', ), 'default' => array( 'type' => kolab_form::INPUT_TEXT, ), 'validate' => array( 'type' => kolab_form::INPUT_SELECT, 'options' => array( 'default' => $this->translate('attribute.validate.default'), 'extended' => $this->translate('attribute.validate.extended'), 'basic' => $this->translate('attribute.validate.basic'), 'none' => $this->translate('attribute.validate.none'), ), ), 'optional' => array( 'type' => kolab_form::INPUT_CHECKBOX, 'value' => 1, ), ); $result = new kolab_form(); foreach ($form as $idx => $element) { $element['name'] = 'attr_' . $idx; if ($idx === 'value') { $add = array( 'name' => 'attr_data', 'type' => kolab_form::INPUT_TEXT, ); $element = kolab_html::div(array( 'class' => 'input-group', 'content' => kolab_form::get_element($element) . kolab_form::get_element($add) )); $element = array('value' => $element); } $element['label'] = $this->translate('attribute.' . $idx); $result->add_element($element); } $result->add_button(array( 'value' => $this->translate('button.save'), 'onclick' => "kadm.type_attr_save()", )); $result->add_button(array( 'value' => $this->translate('button.cancel'), 'onclick' => "kadm.type_attr_cancel()", )); return $result->output(); } /** * 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(); $required = array(); // convert to hash array if (!empty($response['list'])) { // remove objectClass $attributes = array_diff($response['list'], array('objectClass')); // add special attributes - always supported $attributes = array_unique(array_merge($attributes, $this->special_attributes)); sort($attributes); if (count($attributes)) { $attributes = array_combine(array_map('strtolower', $attributes), $attributes); } } if (!empty($response['required'])) { // remove objectClass $required = array_diff($response['required'], array('objectClass')); } $this->output->set_env('attributes', $attributes); $this->output->set_env('attributes_required', $required); $this->output->set_env('special_attributes', $this->special_attributes); return $attributes; } /** * Users search form. * * @return string HTML output of the form */ public function type_search_form() { $form = new kolab_form(array('id' => 'search-form')); $form->add_section('criteria', kolab_html::escape($this->translate('search.criteria'))); $form->add_element(array( 'section' => 'criteria', 'label' => $this->translate('search.field'), 'name' => 'field', 'type' => kolab_form::INPUT_SELECT, 'options' => array( 'name' => kolab_html::escape($this->translate('search.name')), 'key' => kolab_html::escape($this->translate('search.key')), 'description' => kolab_html::escape($this->translate('search.description')), ), )); $form->add_element(array( 'section' => 'criteria', 'label' => $this->translate('search.method'), 'name' => 'method', 'type' => kolab_form::INPUT_SELECT, 'options' => array( 'both' => kolab_html::escape($this->translate('search.contains')), 'exact' => kolab_html::escape($this->translate('search.is')), 'prefix' => kolab_html::escape($this->translate('search.prefix')), ), )); return $form->output(); } /** * Users search form. * * @return string HTML output of the form */ public function type_filter() { $options = array(); foreach ($this->object_types as $type) { $options[$type] = $this->translate('type.' . $type); } $filter = array( 'type' => kolab_form::INPUT_SELECT, 'name' => 'type', 'id' => 'type_list_filter', 'options' => $options, 'value' => !empty($_POST['type']) ? $_POST['type'] : 'user', 'onchange' => "kadm.command('settings.type_list')", ); return kolab_form::get_element($filter); } } diff --git a/lib/locale/en_US.php b/lib/locale/en_US.php index d67c413..2fb1a3c 100644 --- a/lib/locale/en_US.php +++ b/lib/locale/en_US.php @@ -1,448 +1,448 @@ Kolab Server.'; $LANG['about.kolab'] = 'Kolab'; $LANG['about.kolabsys'] = 'Kolab Systems'; $LANG['about.support'] = 'Professional support is available from Kolab Systems.'; $LANG['about.technology'] = 'Technology'; $LANG['about.warranty'] = 'It comes with absolutely no warranties and is typically run entirely self supported. You can find help & information on the community web site & wiki.'; $LANG['aci.new'] = 'New...'; $LANG['aci.edit'] = 'Edit...'; $LANG['aci.remove'] = 'Remove'; $LANG['aci.users'] = 'Users'; $LANG['aci.rights'] = 'Rights'; $LANG['aci.targets'] = 'Targets'; $LANG['aci.aciname'] = 'ACI name:'; $LANG['aci.hosts'] = 'Hosts'; $LANG['aci.times'] = 'Times'; $LANG['aci.name'] = 'Name'; $LANG['aci.userid'] = 'User ID'; $LANG['aci.email'] = 'E-mail'; $LANG['aci.read'] = 'Read'; $LANG['aci.compare'] = 'Compare'; $LANG['aci.search'] = 'Search'; $LANG['aci.write'] = 'Write'; $LANG['aci.selfwrite'] = 'Self-write'; $LANG['aci.delete'] = 'Delete'; $LANG['aci.add'] = 'Add'; $LANG['aci.proxy'] = 'Proxy'; $LANG['aci.all'] = 'All rights'; $LANG['aci.allow'] = 'Allow'; $LANG['aci.deny'] = 'Deny'; $LANG['aci.typeusers'] = 'Users'; $LANG['aci.typegroups'] = 'Groups'; $LANG['aci.typeroles'] = 'Roles'; $LANG['aci.typeadmins'] = 'Administrators'; $LANG['aci.typespecials'] = 'Special Rights'; $LANG['aci.ldap-self'] = 'Self'; $LANG['aci.ldap-anyone'] = 'All users'; $LANG['aci.ldap-all'] = 'All authenticated users'; $LANG['aci.ldap-parent'] = 'Parent'; $LANG['aci.usersearch'] = 'Search for:'; $LANG['aci.usersearchresult'] = 'Search results:'; $LANG['aci.userselected'] = 'Selected users/groups/roles:'; $LANG['aci.useradd'] = 'Add'; $LANG['aci.userremove'] = 'Remove'; $LANG['aci.error.noname'] = 'ACI rule name is required!'; $LANG['aci.error.exists'] = 'ACI rule with specified name already exists!'; $LANG['aci.error.nousers'] = 'At least one user entry is required!'; $LANG['aci.rights.target'] = 'Target entry:'; $LANG['aci.rights.filter'] = 'Filter:'; $LANG['aci.rights.attrs'] = 'Attributes:'; $LANG['aci.checkall'] = 'Check all'; $LANG['aci.checknone'] = 'Check none'; $LANG['aci.thisentry'] = 'This entry'; $LANG['aci.selected'] = 'all selected'; $LANG['aci.other'] = 'all except selected'; $LANG['acl.all'] = 'All'; $LANG['acl.custom'] = 'Custom...'; $LANG['acl.full'] = 'Full (without access control)'; $LANG['acl.read-only'] = 'Read-Only'; $LANG['acl.read-write'] = 'Read/Write'; $LANG['acl.semi-full'] = 'Write new items'; $LANG['acl.l'] = 'l - Lookup'; $LANG['acl.r'] = 'r - Read messages'; $LANG['acl.s'] = 's - Keep Seen state'; $LANG['acl.w'] = 'w - Write flags'; $LANG['acl.i'] = 'i - Insert (Copy into)'; $LANG['acl.p'] = 'p - Post'; $LANG['acl.c'] = 'c - Create subfolders'; $LANG['acl.k'] = 'k - Create subfolders'; $LANG['acl.d'] = 'd - Delete messages'; $LANG['acl.t'] = 't - Delete messages'; $LANG['acl.e'] = 'e - Expunge'; $LANG['acl.x'] = 'x - Delete folder'; $LANG['acl.a'] = 'a - Administer'; $LANG['acl.n'] = 'n - Annotate messages'; $LANG['acl.identifier'] = 'Identifier'; $LANG['acl.rights'] = 'Access Rights'; $LANG['acl.expire'] = 'Expires On'; $LANG['acl.user'] = 'User...'; $LANG['acl.anyone'] = 'All users (anyone)'; $LANG['acl.anonymous'] = 'Guests (anonymous)'; $LANG['acl.error.invaliddate'] = 'Invalid date format!'; $LANG['acl.error.norights'] = 'No access rights specified!'; $LANG['acl.error.subjectexists'] = 'Access rights for specified identifier already exist!'; $LANG['acl.error.nouser'] = 'User identifier not specified!'; $LANG['add'] = 'Add'; $LANG['api.notypeid'] = 'No object type ID specified!'; $LANG['api.invalidtypeid'] = 'Invalid object type ID!'; $LANG['attribute.add'] = 'Add attribute'; $LANG['attribute.default'] = 'Default value'; $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['attribute.required.error'] = 'Required attributes missing in attributes list ($1)!'; $LANG['attribute.validate'] = ' Validation'; $LANG['attribute.validate.default'] = 'default'; $LANG['attribute.validate.none'] = 'none'; $LANG['attribute.validate.basic'] = 'basic'; $LANG['attribute.validate.extended'] = 'extended'; $LANG['button.cancel'] = 'Cancel'; $LANG['button.clone'] = 'Clone'; $LANG['button.delete'] = 'Delete'; $LANG['button.ok'] = 'OK'; $LANG['button.save'] = 'Save'; $LANG['button.submit'] = 'Submit'; $LANG['creatorsname'] = 'Created by'; $LANG['days'] = 'days'; $LANG['debug'] = 'Debug info'; $LANG['delete'] = 'Delete'; $LANG['deleting'] = 'Deleting data...'; $LANG['domain.add'] = 'Add Domain'; $LANG['domain.add.success'] = 'Domain created successfully.'; $LANG['domain.associateddomain'] = 'Domain name(s)'; $LANG['domain.delete.confirm'] = 'Are you sure, you want to delete this domain?'; $LANG['domain.delete.force'] = "There are users assigned to this domain.\nAre you sure, you want to delete this domain and all assigned objects?"; $LANG['domain.delete.success'] = 'Domain deleted successfully.'; $LANG['domain.edit'] = 'Edit domain'; $LANG['domain.edit.success'] = 'Domain updated successfully.'; $LANG['domain.inetdomainbasedn'] = 'Custom Root DN'; $LANG['domain.inetdomainstatus'] = 'Status'; $LANG['domain.list'] = 'Domains List'; $LANG['domain.norecords'] = 'No domain records found!'; $LANG['domain.o'] = 'Organization'; $LANG['domain.other'] = 'Other'; $LANG['domain.system'] = 'System'; $LANG['domain.type_id'] = 'Standard Domain'; $LANG['edit'] = 'Edit'; $LANG['error'] = 'Error'; $LANG['error.401'] = 'Unauthorized.'; $LANG['error.403'] = 'Access forbidden.'; $LANG['error.404'] = 'Object not found.'; $LANG['error.408'] = 'Request timeout.'; $LANG['error.450'] = 'Domain is not empty.'; $LANG['error.500'] = 'Internal server error.'; $LANG['error.503'] = 'Service unavailable. Try again later.'; $LANG['form.required.empty'] = 'Some of the required fields are empty!'; $LANG['form.maxcount.exceeded'] = 'Maximum count of items exceeded!'; $LANG['group.add'] = 'Add Group'; $LANG['group.add.success'] = 'Group created successfully.'; $LANG['group.cn'] = 'Common name'; $LANG['group.delete.confirm'] = 'Are you sure, you want to delete this group?'; $LANG['group.delete.success'] = 'Group deleted successfully.'; $LANG['group.edit.success'] = 'Group updated successfully.'; $LANG['group.gidnumber'] = 'Primary group number'; $LANG['group.kolaballowsmtprecipient'] = 'Recipient(s) Access List'; $LANG['group.kolaballowsmtpsender'] = 'Sender Access List'; $LANG['group.list'] = 'Groups List'; $LANG['group.mail'] = 'Primary Email Address'; $LANG['group.member'] = 'Member(s)'; $LANG['group.memberurl'] = 'Members URL'; $LANG['group.norecords'] = 'No group records found!'; $LANG['group.other'] = 'Other'; $LANG['group.ou'] = 'Organizational Unit'; $LANG['group.system'] = 'System'; $LANG['group.type_id'] = 'Group type'; $LANG['group.uniquemember'] = 'Members'; $LANG['info'] = 'Information'; $LANG['internalerror'] = 'Internal system error!'; $LANG['ldap.one'] = 'one: all entries one level under the base DN'; $LANG['ldap.sub'] = 'sub: whole subtree starting with the base DN'; $LANG['ldap.base'] = 'base: base DN only'; $LANG['ldap.basedn'] = 'Base DN'; $LANG['ldap.host'] = 'LDAP Server'; $LANG['ldap.conditions'] = 'Conditions'; $LANG['ldap.scope'] = 'Scope'; $LANG['ldap.filter_any'] = 'is non-empty'; $LANG['ldap.filter_both'] = 'contains'; $LANG['ldap.filter_prefix'] = 'starts with'; $LANG['ldap.filter_suffix'] = 'ends with'; $LANG['ldap.filter_exact'] = 'is equal to'; $LANG['list.records'] = '$1 to $2 of $3'; $LANG['loading'] = 'Loading...'; $LANG['logout'] = 'Logout'; $LANG['login.username'] = 'Username'; $LANG['login.password'] = 'Password'; $LANG['login.login'] = 'Login'; $LANG['loginerror'] = 'Incorrect username or password!'; $LANG['MB'] = 'MB'; $LANG['menu.about'] = 'About'; $LANG['menu.domains'] = 'Domains'; $LANG['menu.groups'] = 'Groups'; $LANG['menu.ous'] = 'Units'; $LANG['menu.resources'] = 'Resources'; $LANG['menu.roles'] = 'Roles'; $LANG['menu.settings'] = 'Settings'; $LANG['menu.sharedfolders'] = 'Shared Folders'; $LANG['menu.users'] = 'Users'; $LANG['modifiersname'] = 'Modified by'; $LANG['password.generate'] = 'Generate password'; $LANG['reqtime'] = 'Request time: $1 sec.'; $LANG['ou.aci'] = 'Access Rights'; $LANG['ou.add'] = 'Add Unit'; $LANG['ou.add.success'] = 'Unit created successfully.'; $LANG['ou.ou'] = 'Unit Name'; $LANG['ou.delete.confirm'] = 'Are you sure, you want to delete this organizational unit?'; $LANG['ou.delete.success'] = 'Unit deleted successfully.'; $LANG['ou.description'] = 'Unit Description'; $LANG['ou.edit.success'] = 'Unit updated successfully.'; -$LANG['ou.list'] = 'Organizational Unit List'; +$LANG['ou.list'] = 'Organizational Units List'; $LANG['ou.norecords'] = 'No organizational unit records found!'; $LANG['ou.system'] = 'Details'; $LANG['ou.type_id'] = 'Unit Type'; $LANG['ou.base_dn'] = 'Parent Unit'; $LANG['resource.acl'] = 'Access Rights'; $LANG['resource.add'] = 'Add Resource'; $LANG['resource.add.success'] = 'Resource created successfully.'; $LANG['resource.cn'] = 'Name'; $LANG['resource.delete'] = 'Delete Resource'; $LANG['resource.delete.confirm'] = 'Are you sure, you want to delete this resource?'; $LANG['resource.delete.success'] = 'Resource deleted successfully.'; $LANG['resource.edit'] = 'Edit Resource'; $LANG['resource.edit.success'] = 'Resource updated successfully.'; $LANG['resource.kolabtargetfolder'] = 'Target Folder'; $LANG['resource.kolabinvitationpolicy'] = 'Invitation Policy'; $LANG['resource.kolabdescattribute'] = 'Attributes'; -$LANG['resource.list'] = 'Resource (Collection) List'; +$LANG['resource.list'] = 'Resources (Collections) List'; $LANG['resource.mail'] = 'Mail Address'; $LANG['resource.member'] = 'Collection Members'; $LANG['resource.norecords'] = 'No resource records found!'; $LANG['resource.other'] = 'Other'; $LANG['resource.ou'] = 'Organizational Unit'; $LANG['resource.system'] = 'System'; $LANG['resource.type_id'] = 'Resource Type'; $LANG['resource.uniquemember'] = 'Collection Members'; $LANG['resource.description'] = 'Description'; $LANG['resource.owner'] = 'Owner'; $LANG['role.add'] = 'Add Role'; $LANG['role.add.success'] = 'Role created successfully.'; $LANG['role.cn'] = 'Role Name'; $LANG['role.delete.confirm'] = 'Are you sure, you want to delete this role?'; $LANG['role.delete.success'] = 'Role deleted successfully.'; $LANG['role.description'] = 'Role Description'; $LANG['role.edit.success'] = 'Role updated successfully.'; -$LANG['role.list'] = 'Role List'; +$LANG['role.list'] = 'Roles List'; $LANG['role.norecords'] = 'No role records found!'; $LANG['role.system'] = 'Details'; $LANG['role.type_id'] = 'Role Type'; $LANG['saving'] = 'Saving data...'; $LANG['search'] = 'Search...'; $LANG['search.reset'] = 'Reset'; $LANG['search.criteria'] = 'Search criteria'; $LANG['search.field'] = 'Field:'; $LANG['search.method'] = 'Method:'; $LANG['search.contains'] = 'contains'; $LANG['search.is'] = 'is'; $LANG['search.key'] = 'key'; $LANG['search.prefix'] = 'begins with'; $LANG['search.name'] = 'name'; $LANG['search.email'] = 'email'; $LANG['search.description'] = 'description'; $LANG['search.uid'] = 'UID'; $LANG['search.loading'] = 'Searching...'; $LANG['search.acchars'] = 'At least $min characters required for autocompletion'; $LANG['servererror'] = 'Server Error!'; $LANG['session.expired'] = 'Session has expired. Login again, please'; $LANG['sharedfolder.acl'] = 'IMAP Access Rights'; $LANG['sharedfolder.add'] = 'Add Shared Folder'; $LANG['sharedfolder.add.success'] = 'Shared folder created successfully.'; $LANG['sharedfolder.alias'] = 'Secondary Email Address(es)'; $LANG['sharedfolder.cn'] = 'Folder Name'; $LANG['sharedfolder.delete.confirm'] = 'Are you sure, you want to delete this shared folder?'; $LANG['sharedfolder.delete.success'] = 'Shared folder deleted successfully.'; $LANG['sharedfolder.edit'] = 'Edit Shared Folder'; $LANG['sharedfolder.edit.success'] = 'Shared folder updated successfully.'; $LANG['sharedfolder.kolaballowsmtprecipient'] = 'Recipient(s) Access List'; $LANG['sharedfolder.kolaballowsmtpsender'] = 'Sender Access List'; $LANG['sharedfolder.kolabdelegate'] = 'Delegate(s)'; $LANG['sharedfolder.kolabtargetfolder'] = 'Target IMAP Folder'; $LANG['sharedfolder.list'] = 'Shared Folders List'; $LANG['sharedfolder.norecords'] = 'No shared folder records found!'; $LANG['sharedfolder.mail'] = 'Email Address'; $LANG['sharedfolder.other'] = 'Other'; $LANG['sharedfolder.system'] = 'System'; $LANG['sharedfolder.type_id'] = 'Shared Folder Type'; $LANG['signup.headline'] = 'Sign Up for Hosted Kolab'; $LANG['signup.intro1'] = 'Having an account on a Kolab server is way better than just simple Email. It also provides you with full groupware functionality including synchronization for shared addressbooks, calendars, tasks, journal and more.'; $LANG['signup.intro2'] = 'You can sign up here now for an account.'; $LANG['signup.formtitle'] = 'Sign Up'; $LANG['signup.username'] = 'Username'; $LANG['signup.domain'] = 'Domain'; $LANG['signup.mailalternateaddress'] = 'Current Email Address'; $LANG['signup.futuremail'] = 'Future Email Address'; $LANG['signup.company'] = 'Company'; $LANG['signup.captcha'] = 'CAPTCHA'; $LANG['signup.userexists'] = 'User already exists!'; $LANG['signup.usercreated'] = '

    Your account has been successfully added!

    Congratulations, you now have your own Kolab account.'; $LANG['signup.wronguid'] = 'Invalid Username!'; $LANG['signup.wrongmailalternateaddress'] = 'Please provide a valid Email Address!'; $LANG['signup.footer'] = 'This is a service offered by Kolab Systems.'; $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.confirm'] = 'Are you sure, you want to delete this object type?'; $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.is_default'] = 'Default'; $LANG['type.list'] = 'Object Types List'; $LANG['type.key'] = 'Key'; $LANG['type.name'] = 'Name'; $LANG['type.norecords'] = 'No object type records found!'; $LANG['type.objectclass'] = 'Object class'; $LANG['type.object_type'] = 'Object type'; $LANG['type.ou'] = 'Organizational Unit'; $LANG['type.properties'] = 'Properties'; $LANG['type.resource'] = 'Resource'; $LANG['type.role'] = 'Role'; $LANG['type.sharedfolder'] = 'Shared Folder'; $LANG['type.used_for'] = 'Hosted'; $LANG['type.user'] = 'User'; $LANG['user.add'] = 'Add User'; $LANG['user.add.success'] = 'User created successfully.'; $LANG['user.alias'] = 'Secondary Email Address(es)'; $LANG['user.astaccountallowedcodec'] = 'Allowed codec(s)'; $LANG['user.astaccountcallerid'] = 'Caller ID'; $LANG['user.astaccountcontext'] = 'Account Context'; $LANG['user.astaccountdefaultuser'] = 'Asterisk Account Default User'; $LANG['user.astaccountdeny'] = 'Account deny'; $LANG['user.astaccounthost'] = 'Asterisk Host'; $LANG['user.astaccountmailbox'] = 'Mailbox'; $LANG['user.astaccountnat'] = 'Account uses NAT'; $LANG['user.astaccountname'] = 'Asterisk Account Name'; $LANG['user.astaccountqualify'] = 'Account Qualify'; $LANG['user.astaccountrealmedpassword'] = 'Realmed Account Password'; $LANG['user.astaccountregistrationexten'] = 'Extension'; $LANG['user.astaccountregistrationcontext'] = 'Registration Context'; $LANG['user.astaccountsecret'] = 'Plaintext Password'; $LANG['user.astaccounttype'] = 'Account Type'; $LANG['user.astcontext'] = 'Asterisk Context'; $LANG['user.asterisk'] = 'Asterisk SIP'; $LANG['user.astextension'] = 'Asterisk Extension'; $LANG['user.astvoicemailpassword'] = 'Voicemail PIN Code'; $LANG['user.c'] = 'Country'; $LANG['user.city'] = 'City'; $LANG['user.cn'] = 'Common name'; $LANG['user.config'] = 'Configuration'; $LANG['user.contact'] = 'Contact'; $LANG['user.contact_info'] = 'Contact Information'; $LANG['user.country'] = 'Country'; $LANG['user.country.desc'] = '2 letter code from ISO 3166-1'; $LANG['user.delete.confirm'] = 'Are you sure, you want to delete this user?'; $LANG['user.delete.success'] = 'User deleted successfully.'; $LANG['user.displayname'] = 'Display name'; $LANG['user.edit.success'] = 'User updated successfully.'; $LANG['user.fax'] = 'Fax number'; $LANG['user.fbinterval'] = 'Free-Busy interval'; $LANG['user.fbinterval.desc'] = 'Leave blank for default (60 days)'; $LANG['user.gidnumber'] = 'Primary group number'; $LANG['user.givenname'] = 'Given name'; $LANG['user.homedirectory'] = 'Home directory'; $LANG['user.homephone'] = 'Home Phone Number'; $LANG['user.initials'] = 'Initials'; $LANG['user.invitation-policy'] = 'Invitation policy'; $LANG['user.kolaballowsmtprecipient'] = 'Recipient(s) Access List'; $LANG['user.kolaballowsmtpsender'] = 'Sender Access List'; $LANG['user.kolabdelegate'] = 'Delegates'; $LANG['user.kolabhomeserver'] = 'Email Server'; $LANG['user.kolabinvitationpolicy'] = 'Invitation Handling Policy'; $LANG['user.l'] = 'City, Region'; $LANG['user.list'] = 'Users List'; $LANG['user.loginshell'] = 'Shell'; $LANG['user.mail'] = 'Primary Email Address'; $LANG['user.mailalternateaddress'] = 'External Email Address(es)'; $LANG['user.mailforwardingaddress'] = 'Forward Mail To'; $LANG['user.mailhost'] = 'Email Server'; $LANG['user.mailquota'] = 'Quota'; $LANG['user.mailquota.desc'] = 'Leave blank for unlimited'; $LANG['user.mobile'] = 'Mobile Phone Number'; $LANG['user.name'] = 'Name'; $LANG['user.norecords'] = 'No user records found!'; $LANG['user.nsrole'] = 'Role(s)'; $LANG['user.nsroledn'] = 'Role(s)'; $LANG['user.other'] = 'Other'; $LANG['user.o'] = 'Organization'; $LANG['user.org'] = 'Organization'; $LANG['user.orgunit'] = 'Organizational Unit'; $LANG['user.ou'] = 'Organizational Unit'; $LANG['user.pager'] = 'Pager Number'; $LANG['user.password.notallowed'] = 'Password contains characters (eg. Umlaut) that are not permitted'; $LANG['user.password.mismatch'] = 'Passwords do not match!'; $LANG['user.password.moreupper'] = 'Password needs to contain at least $1 uppercase character(s)'; $LANG['user.password.morelower'] = 'Password needs to contain at least $1 lowercase character(s)'; $LANG['user.password.moredigits'] = 'Password needs to contain at least $1 digit(s)'; $LANG['user.password.morespecial'] = 'Password needs to contain at least $1 special character(s): $2'; $LANG['user.password.tooshort'] = 'Password is too short, it must have at least $1 characters'; $LANG['user.personal'] = 'Personal'; $LANG['user.phone'] = 'Phone number'; $LANG['user.postalcode'] = 'Postal Code'; $LANG['user.postbox'] = 'Postal box'; $LANG['user.postcode'] = 'Postal code'; $LANG['user.preferredlanguage'] = 'Native tongue'; $LANG['user.room'] = 'Room number'; $LANG['user.sn'] = 'Surname'; $LANG['user.street'] = 'Street'; $LANG['user.system'] = 'System'; $LANG['user.telephonenumber'] = 'Phone Number'; $LANG['user.title'] = 'Job Title'; $LANG['user.type_id'] = 'Account type'; $LANG['user.uid'] = 'Unique identity (UID)'; $LANG['user.userpassword'] = 'Password'; $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/skins/default/style.css b/public_html/skins/default/style.css index 0cb9af5..5013dfb 100644 --- a/public_html/skins/default/style.css +++ b/public_html/skins/default/style.css @@ -1,926 +1,927 @@ @font-face { font-family: 'Icons'; font-style: normal; font-weight: 900; src: url("fonts/fa-solid-900.woff2") format('woff2'), url("fonts/fa-solid-900.woff") format('woff'); } @font-face { font-family: 'Icons'; font-style: normal; font-weight: 400; src: url("fonts/fa-regular-400.woff2") format('woff2'), url("fonts/fa-regular-400.woff") format('woff'); } @font-face { font-family: 'Roboto'; font-style: normal; font-weight: 400; src: local('Roboto'), local('Roboto-Regular'), url('fonts/roboto-v18-greek-ext_cyrillic-ext_cyrillic_greek_latin-ext_latin-regular.woff2') format('woff2'), // Chrome 26+, Opera 23+, Firefox 39+ url('fonts/roboto-v18-greek-ext_cyrillic-ext_cyrillic_greek_latin-ext_latin-regular.woff') format('woff'); // Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ } @font-face { font-family: 'Roboto'; font-style: italic; font-weight: 400; src: local('Roboto Italic'), local('Roboto-Italic'), url('fonts/roboto-v18-greek-ext_cyrillic-ext_cyrillic_greek_latin-ext_latin-italic.woff2') format('woff2'), // Chrome 26+, Opera 23+, Firefox 39+ url('fonts/roboto-v18-greek-ext_cyrillic-ext_cyrillic_greek_latin-ext_latin-italic.woff') format('woff'); // Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ } @font-face { font-family: 'Roboto'; font-style: normal; font-weight: 700; src: local('Roboto Bold'), local('Roboto-Bold'), url('fonts/roboto-v18-greek-ext_cyrillic-ext_cyrillic_greek_latin-ext_latin-700.woff2') format('woff2'), // Chrome 26+, Opera 23+, Firefox 39+ url('fonts/roboto-v18-greek-ext_cyrillic-ext_cyrillic_greek_latin-ext_latin-700.woff') format('woff'); // Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ } @font-face { font-family: 'Roboto'; font-style: italic; font-weight: 700; src: local('Roboto Bold Italic'), local('Roboto-BoldItalic'), url('fonts/roboto-v18-greek-ext_cyrillic-ext_cyrillic_greek_latin-ext_latin-700italic.woff2') format('woff2'), // Chrome 26+, Opera 23+, Firefox 39+ url('fonts/roboto-v18-greek-ext_cyrillic-ext_cyrillic_greek_latin-ext_latin-700italic.woff') format('woff'); // Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ } html { font-size: 9pt; } body { margin: 0; color: #4f4f4f; background: #f1eeea; line-height: 1.5; } body, button, input, optgroup, select, textarea, .popover { font-family: Roboto, sans-serif; } a { text-decoration: none; } table.list { border: 1px solid #d0d0d0; border-spacing: 0; width: 100%; } table.list thead tr { background: #f1eeea; } table.list thead tr th { border-width: 1px; border-top: 0; } table.list tfoot tr { background: #f1eeea; } table.list tbody tr.selectable td { cursor: default; } table.list tbody tr.selectable:hover { background-color: #fef9e6; } table.list tbody tr td.empty-body { height: 150px; color: #f3a628; text-align: center; + vertical-align: middle; } table.list tbody tr.deleted td { color: #999; } fieldset { margin-top: 10px; } legend { color: #909090; font-size: 1rem; } form .required input, form .required select, form .required textarea { background-color: #f0f9ff !important; } form input.error, form select.error, form textarea.error { background-color: #f5e3e3 !important; } table.list.tree td span.expando { cursor: pointer; padding: 0 2px; } table.list.tree td span.expando:before { content: "\f146"; font-size: 1rem; font-weight: normal; } table.list.tree tr.expanded td span.expando:before { content: "\f0fe"; font-size: 1rem; font-weight: normal; } table.list.tree td span.expando, table.list.tree td span.spacer, table.list.tree td span.level { display: inline-block; } table.list.tree td span.spacer { width: 16px; } .table, .form-group { margin-bottom: .5rem; } .input-group-text, .form-control:disabled, .form-control[readonly] { background-color: #f5f3f0; } .modal-dialog { max-width: 640px; margin: 10rem auto; } .col-sm-9 > input[type=checkbox] { margin-top: .4em; } input[type=radio] { vertical-align: middle; } /**** Font-icons ****/ .font-icon:before { font-size: 1.25em; display: inline-block; width: 1em; height: 1em; line-height: 1; font-family: 'Icons'; font-style: normal; font-weight: 900; text-decoration: inherit; text-align: center; speak: none; font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-font-smoothing: antialiased; } .font-icon.add:before { content: "\f067"; } .font-icon.reset:before, .font-icon.delete:before { content: "\f1f8"; } .font-icon.edit:before { content: "\f303"; } .font-icon.settings:before { content: "\f7d9"; } .font-icon.search:before { content: "\f002"; } .font-icon.logout:before { content: "\f011"; } .font-icon.login:before { content: "\f007"; } .font-icon.domain:before { content: "\f0ac"; } .font-icon.password:before { content: "\f023"; } .font-icon.prev:before { content: "\f104"; } .font-icon.next:before { content: "\f105"; } .input-group-text.font-icon { padding: 0 5px; text-decoration: none; } .font-icon-text:before { margin-right: .5em; font-size: 1em; } /**** Common UI elements ****/ #topmenu { text-align: right; height: 20px; padding: 0 5px; white-space: nowrap; background-color: #3a444e; } #topmenu > span { color: #aaa; font-size: 11px; padding-top: 2px; line-height: 20px; } #navigation { padding: 0 5px; text-align: right; height: 36px; z-index: 2; white-space: nowrap; background-color: #3a444e; } #task_navigation { margin: 0 5px; text-align: right; min-height: 2em; z-index: 2; white-space: nowrap; } #message { position: absolute; top: 80px; left: 0; right: 0; height: 56px; z-index: 20; } #message div { opacity: .97; display: table; } #message.notice div { color: #3465a4; background: #c0e0ff; } #message.error div { color: #a40000; background: #edcccc; } #message div:before { font-size: 32px; margin: 12px 1.5rem; } #message.notice div:before { content: "\f05a"; } #message.error div:before { content: "\f071"; } #message div span { vertical-align: middle; display: table-cell; width: 99%; } #logo { position: absolute; top: 0px; left: 5px; cursor: pointer; } #content { min-height: 400px; padding: 10px; background-color: #fff; border: 1px solid #d0d0d0; border-width: 1px 0 1px 0; } #footer { margin: 5px; color: #666; font-size: 7pt; margin-bottom: 10px; clear: both; } #loading { position: absolute; display: none; top: 60px; left: 15px; width: 150px; height: 16px; font-size: 11px; line-height: 1.5; z-index: 1; white-space: nowrap; } #topmenu .logout { margin-right: 10px; color: white; } #topmenu .login { margin-right: 10px; } #topmenu .domain { margin-right: 10px; } #topmenu .domain:before { margin-right: 0; } #navigation ul { list-style-type: none; margin: 0; padding: 0; } #navigation ul li { display: inline-block; font-weight: bold; padding: 0; } #navigation ul li a { display: inline-block; line-height: 36px; padding: 0 10px; text-decoration: none; color: #999; } #navigation ul li:hover { background: #505e6b; } #navigation ul li:hover a, #navigation ul li.active a { color: #e1e2e3; } #task_navigation ul { list-style-type: none; margin: 0; } #task_navigation ul li { display: inline; font-weight: bold; } #task_navigation ul li a { line-height: 2; padding: 0 10px; text-decoration: none; color: #f3a628; text-shadow: 1px 1px #fff; } #navigation ul li a:active, #task_navigation ul li a:active { outline: none; } #taskcontent { min-height: 380px; padding: 0 10px; display: flex; flex-direction: column; } #toc { float: left; width: 260px; min-height: 380px; } #search { padding: 7px; border: 1px solid #d0d0d0; border-bottom: 0; background-color: #f1eeea; } #searchinput:focus { outline: none; } .searchdetails { display: none; } .searchfilter { margin-top: 5px; } #search fieldset { margin: 0; margin-top: 5px; } #search + div > table.list { border-top: 0; } div.vsplitter { float: left; width: 10px; min-height: 400px; } /**** Common classes ****/ .nowrap { white-space: nowrap; } .watermark { flex: 1; display: flex; justify-content: center; } .watermark img { opacity: .3; width: 75%; } .link { cursor: pointer; } .formtitle { font-size: 18px; font-weight: bold; margin-bottom: 1rem; } .formbuttons { text-align: center; white-space: nowrap; } .formbuttons input { margin: 5px; } .listnav { font-size: 10px; } .listnav a { display: inline-block; text-decoration: none; padding: 0 .25rem; line-height: 1; font-size: 10pt; color: inherit; } .listnav a.disabled { opacity: .3; cursor: default; } .listnav > span { display: flex; align-items: center; } pre.debug { height: 200px; overflow: auto; } .popup { display: none; position: absolute; border: none; border-radius: 3px; box-shadow: 0 2px 6px 0 #333; } a.button { text-decoration: none; color: #495057; padding: 0 .25rem; line-height: 2.1; } /********* Form smart inputs *********/ .listelement:not(:first-child) > input, .listelement:not(:first-child) > span { margin-top: -1px; } .listelement.input-group > input { border-radius: 0 !important; } .listelement.input-group > span :first-child { border-radius: 0 !important; } .listelement.input-group:first-child > input { border-top-right-radius: .25rem !important; } .listelement.input-group:first-child > span :first-child { border-top-left-radius: .25rem !important; } .listelement:last-child input { border-bottom-right-radius: .25rem !important; } .listelement:last-child > span :first-child { border-bottom-left-radius: .25rem !important; } .listarea.disabled, .listarea.readonly, .listarea.disabled span.listelement input, .listarea.readonly span.listelement input { background-color: #f5f3f0; } .listcontent { display: block; max-height: 94px; overflow-x: hidden; overflow-y: auto; background-color: #f1eeea; cursor: default; border-radius: 0 0 .25rem .25rem; } .listcontent .listelement { padding: 0 5px; line-height: 2; color: #4f4f4f; font-size: 9pt; } .listcontent .listelement:hover, .listcontent .listelement.selected { background-color: #fef9e6; } span.form_error { color: #FF0000; font-weight: bold; font-size: 90%; padding-left: 5px; } .ldap_url ul { list-style-type: none; padding: 0; margin: 0; } .ldap_url ul li:not(:last-child) { margin-bottom: .25rem; } form .required .ldap_url { padding: .25rem; border-radius: .25rem; } .ldap_host .input-group-text { height: calc(1.5em + .75rem + 2px); border-radius: 0; border-right: 0; border-left: 0; } .ldap_host input:first-child { flex: 10; } .ldap_filter select { max-width: 120px; } .acltable { border-spacing: 0; } .acltable select { width: 99%; padding: 0; } .acltable .buttons { width: 1%; vertical-align: top; text-align: center; } .acltable .buttons input { width: 80px; margin-bottom: 5px; } .acltable td.list { padding-right: 5px; } /***** autocomplete list *****/ #autocompletepane { background-color: white; border: 1px solid #d0d0d0; min-width: 351px; } #autocompletepane ul { margin: 0; padding: 2px; } #autocompletepane ul li { display: block; padding-left: 6px; padding-right: 6px; white-space: nowrap; cursor: pointer; line-height: 2; } #autocompletepane ul li.selected { background-color: #fef9e6; } /**** ACI widget ********/ #aci-rights label { display: block; } #aci-rights label input { vertical-align: middle; } #aci-rights label span { padding-left: 5px; } #aci-targets-targetbtn { height: calc(1.5em + .75rem + 2px); } #aci-targets-attr + label { padding-right: 1rem; } /**** IMAP ACL widget ********/ #acl-form label { display: block; } #acl-type { margin-bottom: .5rem; } #acl-type + div label input { vertical-align: middle; } #acl-type + div label span { padding-left: 5px; } /**** Login form elements ****/ #login_form { margin: auto; margin-top: 75px; padding: 20px; width: 330px; background-color: #f1eeea; border: 1px solid #d0d0d0; border-radius: .25rem; text-align: center; } #login_form label { padding: 0 1rem; } #login_submit { margin-top: 5px; } /**** Main screen elements ****/ #main { display: flex; flex-wrap: wrap; } #main div { margin: 10px; width: 150px; height: 150px; text-align: center; cursor: pointer; background-color: #f1eeea; border: 1px solid #d0d0d0; border-radius: 3px; } #main div:hover { background-color: #fef9e6; } #main div span.image:before { font-size: 96px; color: #f3a628; margin: 15px 0 10px; width: 100%; } #main div.user span.image:before { content: "\f007"; } #main div.group span.image:before { content: "\f0c0"; } #main div.resource span.image:before { content: "\f013"; } #main div.sharedfolder span.image:before { content: "\f07c"; } #main div.settings span.image:before { content: "\f7d9"; } #main div.domain span.image:before { content: "\f0ac"; } #main div.role span.image:before { content: "\f21b"; } #main div.ou span.image:before { content: "\f0e8"; } #main div.about span.image:before { content: "\f05a"; } #main div span.label { font-weight: bold; } #reqtime { white-space: nowrap; vertical-align: top; } #domain-selector span.link { color: white; text-decoration: none; } /**** About pages ****/ td.yes { background-color: #d4edda; color: #155724; text-align: center; font-style: italic; } td.no { background-color: #f8d7da; color: #721c24; text-align: center; } /**** Settings ****/ #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 td { padding: 1rem; background-color: #f8f8f8; } /**** Signup page ****/ body.signup #logo { position: relative; cursor: default; } body.signup #taskcontent { align-items: center; } body.signup .formtitle { margin: 1rem 0 0 0; } body.signup form { padding-top: 10px; margin-bottom: 3rem; min-width: 320px; max-width: 600px; width: 75%; } body.signup #footer { text-align: center; } body.signup #message { top: 55px; } \ No newline at end of file