addressbook can now group contacts by organisations (sql only atm.) and change organisational fields for all organisation members

This commit is contained in:
Ralf Becker 2006-04-30 09:34:24 +00:00
parent 9d4a09f9ff
commit 6d6ec22c18
11 changed files with 810 additions and 263 deletions

View File

@ -63,6 +63,32 @@ class bocontacts extends socontacts
'n_fn',
);
/**
* @var array $org_fields fields belonging to the (virtual) organisation entry
*/
var $org_fields = array(
'org_name',
'org_unit',
'adr_one_street',
'adr_one_street2',
'adr_one_locality',
'adr_one_region',
'adr_one_postalcode',
'adr_one_countryname',
'label',
'tel_work',
'tel_fax',
'tel_assistent',
'assistent',
'email',
'url',
'tz',
);
/**
* @var double $org_common_factor minimum percentage of the contacts with identical values to construct the "common" (virtual) org-entry
*/
var $org_common_factor = 0.6;
var $contact_fields = array();
var $business_contact_fields = array();
var $home_contact_fields = array();
@ -441,6 +467,146 @@ class bocontacts extends socontacts
return ($this->grants[$owner] & $needed) &&
(!$contact['private'] || ($this->grants[$owner] & EGW_ACL_PRIVATE) || in_array($owner,$this->memberships));
}
/**
* Read (virtual) org-entry (values "common" for most contacts in the given org)
*
* @param string $org_id org_name:oooooo|||org_unit:uuuuuuuuu|||adr_one_locality:lllllll (org_unit and adr_one_locality are optional)
* @return array/boolean array with common org fields or false if org not found
*/
function read_org($org_id)
{
if (!$org_id) return false;
$org = array();
foreach(explode('|||',$org_id) as $part)
{
list($name,$value) = explode(':',$part);
$org[$name] = $value;
}
$contacts = parent::search('',$this->org_fields,'','','',false,'AND',false,$org);
if (!$contacts) return false;
// create a statistic about the commonness of each fields values
$fields = array();
foreach($contacts as $contact)
{
foreach($contact as $name => $value)
{
$fields[$name][$value]++;
}
}
foreach($fields as $name => $values)
{
if (!in_array($name,$this->org_fields)) continue;
arsort($values,SORT_NUMERIC);
list($value,$num) = each($values);
//echo "<p>$name: '$value' $num/".count($contacts)."=".($num / (double) count($contacts))." >= $this->org_common_factor = ".($num / (double) count($contacts) >= $this->org_common_factor ? 'true' : 'false')."</p>\n";
if ($value && $num / (double) count($contacts) >= $this->org_common_factor)
{
$org[$name] = $value;
}
}
echo $org_id; _debug_array($org);
return $org;
}
/**
* Return all org-members with same content in one or more of the given fields (only org_fields are counting)
*
* @param string $org_name
* @param array $fields field-name => value pairs
* @return array with contacts
*/
function org_similar($org_name,$fields)
{
$criteria = array();
foreach($this->org_fields as $name)
{
if (isset($fields[$name]))
{
$criteria[$name] = $fields[$name];
}
}
return parent::search($criteria,false,'n_family,n_given','','',false,'OR',false,array('org_name'=>$org_name));
}
/**
* Return the changed fields from two versions of a contact (not modified or modifier)
*
* @param array $from original/old version of the contact
* @param array $to changed/new version of the contact
* @param boolean $onld_org_fields=true check and return only org_fields, default true
* @return array with field-name => value from $from
*/
function changed_fields($from,$to,$only_org_fields=true)
{
$changed = array();
foreach($only_org_fields ? $this->org_fields : array_keys($this->contact_fields) as $name)
{
if (!isset($from[$name]) || in_array($name,array('modified','modifier'))) // never count these
{
continue;
}
if ((string) $from[$name] != (string) $to[$name])
{
$changed[$name] = $from[$name];
}
}
return $changed;
}
/**
* Change given fields in all members of the org with identical content in the field
*
* @param string $org_name
* @param array $from original/old version of the contact
* @param array $to changed/new version of the contact
* @param array $members=null org-members to change, default null --> function queries them itself
* @return array/boolean (changed-members,changed-fields,failed-members) or false if no org_fields changed or no (other) members matching that fields
*/
function change_org($org_name,$from,$to,$members=null)
{
if (!($changed = $this->changed_fields($from,$to,true))) return false;
if (is_null($members) || !is_array($members))
{
$members = $this->org_similar($org_name,$changed);
}
if (!$members) return false;
$changed_members = $changed_fields = $failed_members = 0;
foreach($members as $member)
{
$fields = 0;
foreach($changed as $name => $value)
{
if ((string)$value == (string)$member[$name])
{
$member[$name] = $to[$name];
//echo "<p>$member[n_family], $member[n_given]: $name='{$to[$name]}'</p>\n";
++$fields;
}
}
if ($fields)
{
if (!$this->check_perms(EGW_ACL_EDIT,$member) || !$this->save($member))
{
++$failed_members;
}
else
{
++$changed_members;
$changed_fields += $fields;
}
}
}
return array($changed_members,$changed_fields,$failed_members);
}
/**
* get title for a contact identified by $contact

View File

@ -56,7 +56,7 @@ class contacts_admin_prefs
// Disabled til they are working again
// 'Advanced search'=>$GLOBALS['egw']->link('/index.php','menuaction=addressbook.uicontacts.search'),
// 'import contacts' => $GLOBALS['egw']->link('/index.php','menuaction=addressbook.uiXport.import'),
// 'export contacts' => $GLOBALS['egw']->link('/index.php','menuaction=addressbook.uiXport.export')
// 'export contacts' => $GLOBALS['egw']->link('/index.php','menuaction=addressbook.uiXport.export'),
'CSV-Import' => $GLOBALS['egw']->link('/addressbook/csv_import.php')
);
display_sidebox($appname,lang('Addressbook menu'),$file);

View File

@ -93,6 +93,15 @@ class socontacts
*/
var $total;
/**
* @var object $somain sql (socontacts_sql) or ldap (so_ldap) backend class
*/
var $somain;
/**
* @var so_sql-object $soextra custom fields backend
*/
var $soextra;
function socontacts($contact_app='addressbook')
{
$this->user = $GLOBALS['egw_info']['user']['account_id'];
@ -147,10 +156,7 @@ class socontacts
$custom =& CreateObject('admin.customfields',$contact_app);
$this->customfields = $custom->get_customfields();
// if ($this->customfields && !is_array($this->customfields)) $this->customfields = unserialize($this->customfields);
// if (!$this->customfields) $this->customfields = array();
$this->content_types = $custom->get_content_types();
// if ($this->content_types && !is_array($this->content_types)) $this->content_types = unserialize($this->content_types);
if (!$this->content_types)
{
$this->content_types = $custom->content_types = array('n' => array(
@ -552,6 +558,65 @@ class socontacts
// ToDo: read custom-fields, if displayed in the index page
return $rows;
}
/**
* Query organisations by given parameters
*
* @var array $param
* @var string $param[org_view] 'org_name', 'org_name,adr_one_location', 'org_name,org_unit' how to group
* @var int $param[owner] addressbook to search
* @var string $param[search] search pattern for org_name
* @var string $param[searchletter] letter the org_name need to start with
* @var int $param[start]
* @var int $param[num_rows]
* @var string $param[sort] ASC or DESC
* @return array or arrays with keys org_name,count and evtl. adr_one_location or org_unit
*/
function organisations($param)
{
if (!method_exists($this->somain,'organisations')) return false;
if ($param['search'] && !is_array($param['search']))
{
$search = $param['search'];
$param['search'] = array();
foreach($this->columns_to_search as $col)
{
if ($col != 'contact_value') $param['search'][$col] = $search; // we dont search the customfields
}
}
if (is_array($param['search']) && count($param['search']))
{
$param['search'] = $this->data2db($param['search']);
}
$rows = $this->somain->organisations($param);
//echo "<p>socontacts::organisations(".print_r($param,true).")<br />".$this->somain->db->Query_ID->sql."</p>\n";
if (!$rows) return array();
list(,$by) = explode(',',$param['org_view']);
if (!$by) $by = 'adr_one_locality';
foreach($rows as $n => $row)
{
$rows[$n]['id'] = 'org_name:'.$row['org_name'];
foreach(array(
'org_unit' => lang('departments'),
'adr_one_locality' => lang('locations'),
) as $by => $by_label)
{
if ($row[$by.'_count'] > 1)
{
$rows[$n][$by] = $row[$by.'_count'].' '.$by_label;
}
else
{
$rows[$n]['id'] .= '|||'.$by.':'.$row[$by];
}
}
}
return $rows;
}
/**
* gets all contact fields from database

View File

@ -29,6 +29,135 @@ class socontacts_sql extends so_sql
var $accounts_join = ' JOIN egw_accounts ON person_id=egw_addressbook.contact_id';
var $extra_join = ' LEFT JOIN egw_addressbook_extra ON egw_addressbook.contact_id=egw_addressbook_extra.contact_id';
/**
* Query organisations by given parameters
*
* @var array $param
* @var string $param[org_view] 'org_name', 'org_name,adr_one_location', 'org_name,org_unit' how to group
* @var int $param[owner] addressbook to search
* @var string $param[search] search pattern for org_name
* @var string $param[searchletter] letter the org_name need to start with
* @var array $param[col_filter] filter
* @var string $param[search] or'ed search pattern
* @var int $param[start]
* @var int $param[num_rows]
* @var string $param[sort] ASC or DESC
* @return array or arrays with keys org_name,count and evtl. adr_one_location or org_unit
*/
function organisations($param)
{
$filter = is_array($param['col_filter']) ? $param['col_filter'] : array();
// add filter for read ACL in sql, if user is NOT the owner of the addressbook
if ($param['owner'] && $param['owner'] == $GLOBALS['egw_info']['user']['account_id'])
{
$filter['owner'] = $param['owner'];
}
else
{
// we have no private grants in addressbook at the moment, they have then to be added here too
if ($param['owner'])
{
if (!$this->grants[(int) $filter['owner']]) return false; // we have no access to that addressbook
$filter['owner'] = $param['owner'];
$filter['private'] = 0;
}
else // search all addressbooks, incl. accounts
{
$filter[] = "(contact_owner=".(int)$GLOBALS['egw_info']['user']['account_id'].
" OR contact_private=0 AND contact_owner IN (".
implode(',',array_keys($this->grants))."))";
}
}
if ($param['searchletter'])
{
$filter[] = 'org_name LIKE '.$this->db->quote($param['searchletter'].'%');
}
else
{
$filter[] = "org_name != ''";// AND org_name IS NOT NULL";
}
$sort = $param['sort'] == 'DESC' ? 'DESC' : 'ASC';
list(,$by) = explode(',',$param['org_view']);
if (!$by)
{
$extra = array(
'COUNT(org_name) AS org_count',
"COUNT(DISTINCT CASE WHEN org_unit IS NULL THEN '' ELSE org_unit END) AS org_unit_count",
"COUNT(DISTINCT CASE WHEN adr_one_locality IS NULL THEN '' ELSE adr_one_locality END) AS adr_one_locality_count",
);
$append = "GROUP BY org_name ORDER BY org_name $sort";
}
else // by adr_one_location or org_unit
{
// org total for more then one $by
$append = "GROUP BY org_name HAVING {$by}_count > 1 ORDER BY org_name $sort";
parent::search($param['search'],array('org_name'),$append,array(
"NULL AS $by",
'COUNT(org_name) AS org_count',
"COUNT(DISTINCT CASE WHEN org_unit IS NULL THEN '' ELSE org_unit END) AS org_unit_count",
"COUNT(DISTINCT CASE WHEN adr_one_locality IS NULL THEN '' ELSE adr_one_locality END) AS adr_one_locality_count",
),'%',false,'OR','UNION',$filter);
// org by location
$append = "GROUP BY org_name,$by ORDER BY org_name $sort,$by $sort";
parent::search($param['search'],array('org_name'),$append,array(
"CASE WHEN $by IS NULL THEN '' ELSE $by END AS $by",
'COUNT(org_name) AS org_count',
"COUNT(DISTINCT CASE WHEN org_unit IS NULL THEN '' ELSE org_unit END) AS org_unit_count",
"COUNT(DISTINCT CASE WHEN adr_one_locality IS NULL THEN '' ELSE adr_one_locality END) AS adr_one_locality_count",
),'%',false,'OR','UNION',$filter);
$append = "ORDER BY org_name $sort,CASE WHEN $by IS NULL THEN 1 ELSE 2 END,$by $sort";
}
$rows = parent::search($param['search'],array('org_name'),$append,$extra,'%',false,'OR',
array($param['start'],$param['num_rows']),$filter);
if (!$rows) return false;
// query the values for *_count == 1, to display them instead
$filter['org_name'] = $orgs = array();
foreach($rows as $n => $row)
{
if ($row['org_unit_count'] == 1 || $row['adr_one_locality_count'] == 1)
{
$filter['org_name'][$row['org_name']] = $row['org_name']; // use as key too to have every org only once
}
$org_key = $row['org_name'].($by ? '|||'.($row[$by] || $row[$by.'_count']==1 ? $row[$by] : '|||') : '');
$orgs[$org_key] = $row;
}
unset($rows);
if (count($filter['org_name']))
{
foreach((array) parent::search($criteria,array('org_name','org_unit','adr_one_locality'),'GROUP BY org_name,org_unit,adr_one_locality',
'','%',false,'AND',false,$filter) as $row)
{
$org_key = $row['org_name'].($by ? '|||'.$row[$by] : '');
if ($orgs[$org_key]['org_unit_count'] == 1)
{
$orgs[$org_key]['org_unit'] = $row['org_unit'];
}
if ($orgs[$org_key]['adr_one_locality_count'] == 1)
{
$orgs[$org_key]['adr_one_locality'] = $row['adr_one_locality'];
}
if ($by && isset($orgs[$org_key = $row['org_name'].'||||||']))
{
if ($orgs[$org_key]['org_unit_count'] == 1)
{
$orgs[$org_key]['org_unit'] = $row['org_unit'];
}
if ($orgs[$org_key]['adr_one_locality_count'] == 1)
{
$orgs[$org_key]['adr_one_locality'] = $row['adr_one_locality'];
}
}
}
}
return array_values($orgs);
}
/**
* searches db for rows matching searchcriteria
*

View File

@ -38,6 +38,7 @@ class uicontacts extends bocontacts
* var boolean $private_addressbook use a separate private addressbook (former private flag), for contacts not shareable via regular read acl
*/
var $private_addressbook = false;
var $org_views;
function uicontacts($contact_app='addressbook')
{
@ -57,6 +58,12 @@ class uicontacts extends bocontacts
}
$this->prefs =& $GLOBALS['egw_info']['user']['preferences']['addressbook'];
$this->private_addressbook = $this->contacts_repository == 'sql' && $this->prefs['private_addressbook'];
$this->org_views = array(
'org_name' => lang('Organisations'),
'org_name,adr_one_locality' => lang('Organisations by location'),
'org_name,org_unit' => lang('Organisations by departments'),
);
// our javascript
// to be moved in a seperate file if rewrite is over
@ -71,6 +78,7 @@ class uicontacts extends bocontacts
*/
function index($content=null,$msg=null)
{
//echo "<p>uicontacts::index(".print_r($content,true).",'$msg')</p>\n";
if (is_array($content))
{
$msg = $content['msg'];
@ -99,6 +107,14 @@ class uicontacts extends bocontacts
}
}
}
if ($content['nm']['rows']['view']) // show all contacts of an organisation
{
list($org_view) = each($content['nm']['rows']['view']);
}
else
{
$org_view = $content['nm']['org_view'];
}
}
$content = array(
'msg' => $msg ? $msg : $_GET['msg'],
@ -108,7 +124,8 @@ class uicontacts extends bocontacts
{
$content['nm'] = array(
'get_rows' => 'addressbook.uicontacts.get_rows', // I method/callback to request the data for the rows eg. 'notes.bo.get_rows'
'header_right' => 'addressbook.index.right', // I template to show right of the range-value, right-aligned (optional)
'header_left' => 'addressbook.index.left', // I template to show right of the range-value, right-aligned (optional)
// 'header_right' => 'addressbook.index.right', // I template to show right of the range-value, right-aligned (optional)
'bottom_too' => false, // I show the nextmatch-line (arrows, filters, search, ...) again after the rows
'never_hide' => True, // I never hide the nextmatch-line if less then maxmatch entrie
'start' => 0, // IO position in list
@ -138,12 +155,40 @@ class uicontacts extends bocontacts
$sel_options['action'] = array(
'delete' => lang('Delete'),
'csv' => lang('Export as CSV'),
'vcard' => lang('Export as VCard'),
// ToDo: 'vcard' => lang('Export as VCard'),
// ToDo: 'copy' => lang('Copy a contact and edit the copy'),
)+$this->get_addressbooks(EGW_ACL_ADD);
foreach($this->content_types as $tid => $data)
// dont show tid-selection if we have only one content_type
if (count($this->content_types) <= 1)
{
$sel_options['col_filter[tid]'][$tid] = $data['name'];
$preserv['tid'] = 'n';
}
else
{
$content['nm']['header_right'] = 'addressbook.index.right';
foreach($this->content_types as $tid => $data)
{
$sel_options['col_filter[tid]'][$tid] = $data['name'];
}
}
// get the availible org-views plus the label of the contacts view of one org
$sel_options['org_view'] = $this->org_views;
if (isset($org_view)) $content['nm']['org_view'] = $org_view;
if (!isset($sel_options['org_view'][(string) $content['nm']['org_view']]))
{
$org_name = array();
foreach(explode('|||',$content['nm']['org_view']) as $part)
{
list(,$name) = explode(':',$part,2);
if ($name) $org_name[] = $name;
}
$org_name = implode(': ',$org_name);
$sel_options['org_view'][(string) $content['nm']['org_view']] = $org_name;
}
$content['nm']['org_view_label'] = $sel_options['org_view'][(string) $content['nm']['org_view']];
$this->tmpl->read('addressbook.index');
return $this->tmpl->exec('addressbook.uicontacts.index',$content,$sel_options,$readonlys,$preserv);
}
@ -171,6 +216,23 @@ class uicontacts extends bocontacts
$query['num_rows'] = -1; // all
$this->get_rows($query,$checked,$readonlys,true); // true = only return the id's
}
// replace org_name:* id's with all id's of that org
$org_contacts = array();
foreach($checked as $n => $id)
{
if (substr($id,0,9) == 'org_name:')
{
unset($checked[$n]);
$query = $GLOBALS['egw']->session->appsession('index','addressbook');
$query['num_rows'] = -1; // all
$query['org_view'] = $id;
$this->get_rows($query,$extra,$readonlys,true); // true = only return the id's
if ($extra[0]) $org_contacts = array_merge($org_contacts,$extra);
}
}
if ($org_contacts) $checked = array_unique($checked ? array_merge($checked,$org_contacts) : $org_contacts);
//_debug_array($checked); return false;
switch($action)
{
case 'csv':
@ -281,11 +343,12 @@ class uicontacts extends bocontacts
$GLOBALS['egw']->session->appsession('index','addressbook',$query);
// save the state of the index in the user prefs
$state = serialize(array(
'filter' => $query['filter'],
'cat_id' => $query['cat_id'],
'order' => $query['order'],
'sort' => $query['sort'],
'filter' => $query['filter'],
'cat_id' => $query['cat_id'],
'order' => $query['order'],
'sort' => $query['sort'],
'col_filter' => array('tid' => $query['col_filter']['tid']),
'org_view' => $query['org_view'],
));
if ($state != $this->prefs['index_state'])
{
@ -312,36 +375,69 @@ class uicontacts extends bocontacts
$query['col_filter']['private'] = substr($query['filter'],-1) == 'p' ? 1 : 0;
}
}
// translate the select order to the realy used over all 3 columns
$sort = $query['sort'];
switch($query['order'])
if (isset($this->org_views[(string) $query['org_view']])) // we have an org view
{
case 'org_name':
$order = "org_name $sort,n_family $sort,n_given $sort";
break;
default:
$query['order'] = 'n_family';
case 'n_family':
$order = "n_family $sort,n_given $sort,org_name $sort";
break;
case 'n_given':
$order = "n_given $sort,n_family $sort,org_name $sort";
break;
case 'n_fileas':
$order = 'n_fileas '.$sort;
break;
$query['template'] = 'addressbook.index.org_rows';
if ($query['order'] != 'org_name')
{
$query['sort'] = 'ASC';
$query['order'] = 'org_name';
}
$rows = parent::organisations($query);
}
if ($query['searchletter']) // only show contacts which ordercriteria starts with the given letter
else // contacts view
{
$query['col_filter'][] = $query['order'].' LIKE '.$GLOBALS['egw']->db->quote($query['searchletter'].'%');
$query['template'] = 'addressbook.index.rows';
if ($query['org_view']) // view the contacts of one organisation only
{
foreach(explode('|||',$query['org_view']) as $part)
{
list($name,$value) = explode(':',$part,2);
$query['col_filter'][$name] = $value;
}
}
// translate the select order to the realy used over all 3 columns
$sort = $query['sort'];
switch($query['order'])
{
case 'org_name':
$order = "org_name $sort,n_family $sort,n_given $sort";
break;
default:
$query['order'] = 'n_family';
case 'n_family':
$order = "n_family $sort,n_given $sort,org_name $sort";
break;
case 'n_given':
$order = "n_given $sort,n_family $sort,org_name $sort";
break;
case 'n_fileas':
$order = 'n_fileas '.$sort;
break;
}
if ($query['searchletter']) // only show contacts which ordercriteria starts with the given letter
{
$query['col_filter'][] = $query['order'].' LIKE '.$GLOBALS['egw']->db->quote($query['searchletter'].'%');
}
else // dont show contacts with empty order criteria
{
$query['col_filter'][] = $query['order']."!=''";
}
$rows = parent::search($query['search'],$id_only ? array('id','org_name','n_family','n_given','n_fileas') : false,
$order,'','%',false,'OR',array((int)$query['start'],(int) $query['num_rows']),$query['col_filter']);
if (!$id_only && $this->prefs['custom_colum'] != 'never' && $rows) // do we need the custom fields
{
foreach((array) $rows as $n => $val)
{
if ($val) $ids[] = $val['id'];
}
if ($ids) $customfields = $this->read_customfields($ids);
}
}
else // dont show contacts with empty order criteria
{
$query['col_filter'][] = $query['order']."!=''";
}
$rows = (array) parent::search($query['search'],$id_only ? array('id','org_name','n_family','n_given','n_fileas') : false,
$order,'','%',false,'OR',array((int)$query['start'],(int) $query['num_rows']),$query['col_filter']);
//echo "<p style='margin-top: 100px;'>".$this->somain->db->Query_ID->sql."</p>\n";
if (!$rows) $rows = array();
if ($id_only)
{
@ -351,18 +447,8 @@ class uicontacts extends bocontacts
}
return $this->total; // no need to set other fields or $readonlys
}
if ($this->prefs['custom_colum'] != 'never' && $rows) // do we need the custom fields
{
foreach($rows as $n => $val)
{
$ids[] = $val['id'];
}
$customfields = $this->read_customfields($ids);
}
$order = $query['order'];
if (!$rows) $rows = array();
$readonlys = array();
$photos = $homeaddress = false;
foreach($rows as $n => $val)
@ -389,53 +475,63 @@ class uicontacts extends bocontacts
list($row['line1'],$row['line2']) = explode(': ',$row['n_fileas']);
break;
}
$this->type_icon($row['owner'],$row['private'],$row['tid'],$row['type'],$row['type_label']);
static $tel2show = array('tel_work','tel_cell','tel_home');
foreach($tel2show as $name)
if (isset($this->org_views[(string) $query['org_view']]))
{
$row['type'] = 'home';
$row['type_label'] = lang('Organisation');
$row[$name] .= ' '.($row['tel_prefer'] == $name ? '&#9829;' : ''); // .' ' to NOT remove the field
$readonlys["delete[$row[id]]"] = $query['filter'] && !($this->grants[(int)$query['filter']] & EGW_ACL_DELETE);
}
// allways show the prefered phone, if not already shown
if (!in_array($row['tel_prefer'],$tel2show) && $row[$row['tel_prefer']])
else
{
$row['tel_prefered'] = $row[$row['tel_prefer']].' &#9829;';
}
foreach(array('email','email_home') as $name)
{
if ($row[$name])
$this->type_icon($row['owner'],$row['private'],$row['tid'],$row['type'],$row['type_label']);
static $tel2show = array('tel_work','tel_cell','tel_home');
foreach($tel2show as $name)
{
$row[$name.'_link'] = $this->email2link($row[$name]);
if ($GLOBALS['egw_info']['user']['apps']['felamimail'])
$row[$name] .= ' '.($row['tel_prefer'] == $name ? '&#9829;' : ''); // .' ' to NOT remove the field
}
// allways show the prefered phone, if not already shown
if (!in_array($row['tel_prefer'],$tel2show) && $row[$row['tel_prefer']])
{
$row['tel_prefered'] = $row[$row['tel_prefer']].' &#9829;';
}
foreach(array('email','email_home') as $name)
{
if ($row[$name])
{
$row[$name.'_popup'] = '700x750';
$row[$name.'_link'] = $this->email2link($row[$name]);
if ($GLOBALS['egw_info']['user']['apps']['felamimail'])
{
$row[$name.'_popup'] = '700x750';
}
}
else
{
$row[$name] = ' '; // to NOT remove the field
}
}
else
$readonlys["delete[$row[id]]"] = !$this->check_perms(EGW_ACL_DELETE,$row);
$readonlys["edit[$row[id]]"] = !$this->check_perms(EGW_ACL_EDIT,$row);
if ($row['photo']) $photos = true;
if (isset($customfields[$row['id']]))
{
$row[$name] = ' '; // to NOT remove the field
foreach($this->customfields as $name => $data)
{
$row['customfields'][] = $customfields[$row['id']][$name];
}
}
}
$readonlys["delete[$row[id]]"] = !$this->check_perms(EGW_ACL_DELETE,$row);
$readonlys["edit[$row[id]]"] = !$this->check_perms(EGW_ACL_EDIT,$row);
if ($row['photo']) $photos = true;
if (isset($customfields[$row['id']]))
{
foreach($this->customfields as $name => $data)
if ($this->prefs['home_column'] != 'never' && !$homeaddress)
{
$row['customfields'][] = $customfields[$row['id']][$name];
foreach(array('adr_two_countryname','adr_two_locality','adr_two_postalcode','adr_two_street','adr_two_street2') as $name)
{
if ($row[$name]) $homeaddress = true;
}
}
}
if ($this->prefs['home_column'] != 'never' && !$homeaddress)
{
foreach(array('adr_two_countryname','adr_two_locality','adr_two_postalcode','adr_two_street','adr_two_street2') as $name)
{
if ($row[$name]) $homeaddress = true;
}
}
}
// disable photo column, if view contains no photo(s)
if (!$photos || $this->prefs['photo_column'] == 'never') $rows['no_photo'] = '1';
@ -448,16 +544,20 @@ class uicontacts extends bocontacts
$rows['customfields'] = array_values($this->customfields);
// full app-header with all search criteria for specially for the print
// full app-header with all search criteria specially for the print
$GLOBALS['egw_info']['flags']['app_header'] = lang('addressbook');
if ($query['filter'] !== '')
if ($query['filter'] !== '' && !isset($this->org_views[$query['org_view']]))
{
$GLOBALS['egw_info']['flags']['app_header'] .= ': '.($query['filter'] == '0' ? lang('accounts') :
$GLOBALS['egw_info']['flags']['app_header'] .= ' '.($query['filter'] == '0' ? lang('accounts') :
($GLOBALS['egw']->accounts->get_type($query['filter']) == 'g' ?
lang('Group %1',$GLOBALS['egw']->accounts->id2name($query['filter'])) :
$GLOBALS['egw']->common->grab_owner_name((int)$query['filter']).
(substr($query['filter'],-1) == 'p' ? ' ('.lang('private').')' : '')));
}
if ($query['org_view'])
{
$GLOBALS['egw_info']['flags']['app_header'] .= ': '.$query['org_view_label'];
}
if ($query['cat_id'])
{
$GLOBALS['egw_info']['flags']['app_header'] .= ': '.lang('Category').' '.$GLOBALS['egw']->categories->id2name($query['cat_id']);
@ -594,7 +694,33 @@ class uicontacts extends bocontacts
{
$links = $content['link_to']['to_id'];
}
$this->save($content);
if ($content['id'] && $content['org_name'] && $content['change_org'])
{
$old_org_entry = $this->read($content['id']);
}
if ($this->save($content))
{
$content['msg'] = lang('Contact saved');
if ($content['change_org'] && $old_org_entry && ($changed = $this->changed_fields($old_org_entry,$content,true)) &&
($members = $this->org_similar($old_org_entry['org_name'],$changed)))
{
//foreach($changed as $name => $old_value) echo "<p>$name: '$old_value' --> '{$content[$name]}'</p>\n";
list($changed_members,$changed_fields,$failed_members) = $this->change_org($old_org_entry['org_name'],$changed,$content,$members);
if ($changed_members)
{
$content['msg'] .= ', '.lang('%1 fields in %2 other organisation member(s) changed',$changed_fields,$changed_members);
}
if ($failed_members)
{
$content['msg'] .= ', '.lang('failed to change %1 organisation member(s) (insufficent rights) !!!',$failed_members);
}
}
}
else
{
$content['msg'] = lang('Error saving the contact !!!');
$button = 'apply'; // to not leave the dialog
}
// writing links for new entry, existing ones are handled by the widget itself
if ($links && $content['id'])
{
@ -603,22 +729,26 @@ class uicontacts extends bocontacts
if ($button == 'save')
{
echo "<html><body><script>var referer = opener.location;opener.location.href = referer+(referer.search?'&':'?')+'msg=".
addslashes(urlencode(lang('Contact saved')))."'; window.close();</script></body></html>\n";
addslashes(urlencode($content['msg']))."'; window.close();</script></body></html>\n";
$GLOBALS['egw']->common->egw_exit();
}
$content['link_to']['to_id'] = $content['id'];
$GLOBALS['egw_info']['flags']['java_script'] .= "<script LANGUAGE=\"JavaScript\">
var referer = opener.location;
opener.location.href = referer+(referer.search?'&':'?')+'msg=".addslashes(urlencode(lang('Contact saved')))."';</script>";
opener.location.href = referer+(referer.search?'&':'?')+'msg=".addslashes(urlencode($content['msg']))."';</script>";
break;
case 'delete':
if($this->delete($content));
if($this->delete($content))
{
echo "<html><body><script>var referer = opener.location; opener.location.href = referer+(referer.search?'&':'?')+'msg=".
addslashes(urlencode(lang('Contact deleted !!!')))."';window.close();</script></body></html>\n";
addslashes(urlencode(lang('Contact deleted')))."';window.close();</script></body></html>\n";
$GLOBALS['egw']->common->egw_exit();
}
else
{
$content['msg'] = lang('Error deleting the contact !!!');
}
break;
}
// type change
@ -635,15 +765,23 @@ class uicontacts extends bocontacts
}
else // not found
{
$state = $GLOBALS['egw']->session->appsession('index','addressbook');
// check if we create the new contact in an existing org
if ($_GET['org'])
{
$content = $this->read_org($_GET['org']);
}
elseif ($state['org_view'] && !isset($this->org_views[$state['org_view']]))
{
$content = $this->read_org($state['org_view']);
}
if (isset($_GET['owner']) && $_GET['owner'] !== '')
{
$content['owner'] = $_GET['owner'];
}
else
{
$state = $GLOBALS['egw']->session->appsession('index','addressbook');
$content['owner'] = $state['filter'];
unset($state);
}
$content['private'] = (int) ($content['owner'] && substr($content['owner'],-1) == 'p');
if (!($this->grants[$content['owner'] = (string) (int) $content['owner']] & EGW_ACL_ADD))
@ -658,6 +796,7 @@ class uicontacts extends bocontacts
}
$content['creator'] = $this->user;
$content['created'] = $this->now_su;
unset($state);
}
if($content && $_GET['makecp']) // copy the contact
@ -695,13 +834,24 @@ class uicontacts extends bocontacts
for($i = -23; $i<=23; $i++) $tz[$i] = ($i > 0 ? '+' : '').$i;
$sel_options['tz'] = $tz;
$content['tz'] = $content['tz'] ? $content['tz'] : 0;
foreach($this->content_types as $type => $data) $sel_options['tid'][$type] = $data['name'];
if (count($this->content_types) > 1)
{
foreach($this->content_types as $type => $data)
{
$sel_options['tid'][$type] = $data['name'];
}
$content['typegfx'] = $GLOBALS['egw']->html->image('addressbook',$this->content_types[$content['tid']]['options']['icon'],'',' width="16px" height="16px"');
}
else
{
$content['no_tid'] = true;
}
/* Conny: what's that?
foreach($GLOBALS['egw']->acl->get_all_location_rights($GLOBALS['egw']->acl->account_id,'addressbook',true) as $id => $right)
{
if($id < 0) $sel_options['published_groups'][$id] = $GLOBALS['egw']->accounts->id2name($id);
}
$content['typegfx'] = $GLOBALS['egw']->html->image('addressbook',$this->content_types[$content['tid']]['options']['icon'],'',' width="16px" height="16px"');
*/
$content['link_to'] = array(
'to_app' => 'addressbook',
'to_id' => $content['link_to']['to_id'],
@ -792,7 +942,7 @@ class uicontacts extends bocontacts
case 'delete':
$GLOBALS['egw']->redirect_link('/index.php',array(
'menuaction' => 'addressbook.uicontacts.index',
'msg' => $this->delete($content) ? lang('Something went wrong by deleting this contact') : lang('Contact deleted !!!'),
'msg' => $this->delete($content) ? lang('Error deleting the contact !!!') : lang('Contact deleted'),
));
}
}
@ -806,7 +956,7 @@ class uicontacts extends bocontacts
));
}
}
foreach((array)$content as $key => $val)
foreach(array_keys($this->contact_fields) as $key)
{
$readonlys[$key] = true;
if (in_array($key,array('tel_home','tel_work','tel_cell')))
@ -824,24 +974,38 @@ class uicontacts extends bocontacts
$readonlys['button[save]'] = $readonlys['button[apply]'] = $readonlys['change_photo'] = true;
$readonlys['button[delete]'] = !$this->check_perms(EGW_ACL_DELETE,$content);
$readonlys['button[edit]'] = !$this->check_perms(EGW_ACL_EDIT,$content);
// ToDo: fix vCard export
$readonlys['button[vcard]'] = true;
$sel_options['fileas_type'][$content['fileas_type']] = $this->fileas($content);
$sel_options['owner'] = $this->get_addressbooks();
for($i = -23; $i<=23; $i++) $tz[$i] = ($i > 0 ? '+' : '').$i;
$sel_options['tz'] = $tz;
$content['tz'] = $content['tz'] ? $content['tz'] : 0;
foreach($this->content_types as $type => $data) $sel_options['tid'][$type] = $data['name'];
if (count($this->content_types) > 1)
{
foreach($this->content_types as $type => $data)
{
$sel_options['tid'][$type] = $data['name'];
}
$content['typegfx'] = $GLOBALS['egw']->html->image('addressbook',$this->content_types[$content['tid']]['options']['icon'],'',' width="16px" height="16px"');
}
else
{
$content['no_tid'] = true;
}
/* Conny: what's that?
foreach(explode(',',$content['published_groups']) as $id)
{
$sel_options['published_groups'][$id] = $GLOBALS['egw']->accounts->id2name($id);
}
$content['typegfx'] = $GLOBALS['egw']->html->image('addressbook',$this->content_types[$content['tid']]['options']['icon'],'',' width="16px" height="16px"');
*/
$this->tmpl->read($this->content_types[$content['tid']]['options']['template']);
foreach(array('email','email_home','url') as $name)
foreach(array('email','email_home','url','url_home') as $name)
{
if ($content[$name] )
{
$url = $name == 'url' ? $content[$name] : $this->email2link($content[$name]);
$url = substr($name,0,3) == 'url' ? $content[$name] : $this->email2link($content[$name]);
if (!is_array($url))
{
$this->tmpl->set_cell_attribute($name,'size','b,,1');

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,6 @@
%1 contact(s) %2 addressbook de %1 Kontakt(e) %2
%1 contact(s) %2, %3 failed because of insufficent rights !!! addressbook de %1 Kontakt(e) %2, %3 nicht wegen fehlender Rechte !!!
%1 fields in %2 other organisation member(s) changed addressbook de %1 Felder in %2 Mitglied(ern) der Organisation geändert
%1 records imported addressbook de %1 Datensätze importiert
%1 records read (not yet imported, you may go %2back%3 and uncheck test import) addressbook de %1 Datensätze gelesen (noch nicht importiert, sie können %2zurück%3 gehen und Test-Import auschalten)
%1 starts with '%2' addressbook de %1 beginnt mit '%2'
@ -8,6 +9,7 @@
@-eval() is only availible to admins!!! addressbook de @-eval() ist nur verfügbar für Administratoren!!!
accounts addressbook de Benutzerkonten
actions addressbook de Befehle
add a contact to this organisation addressbook de Einen Kontakt zu dieser Organisation hinzufügen
add a new contact addressbook de Neuen Kontakt anlegen
add a single entry by passing the fields. addressbook de Hinzufügen eines einzelnen Eintrags durch Übergeben der Felder.
add custom field addressbook de Benutzerdefiniertes Feld hinzufügen
@ -23,8 +25,10 @@ addressbook the contact should be saved to addressbook de Adressbuch in das der
addressbook-fieldname addressbook de Adressbuch Feldname
addvcard addressbook de VCard hinzufügen
advanced search addressbook de Erweiterte Suche
all contacts addressbook de Alle Kontakte
alt. csv import addressbook de Alt. CSV Import
always addressbook de immer
apply changes to all members, whose fields have the same previous content addressbook de Wendet die Änderungen auf alle Mitglieder an, deren Felder gleichen vorherigen Inhalt haben
apply the action on the whole query, not only the shown contacts!!! addressbook de Wendet den Befehl auf die gesamte Abfrage an, NICHT nur auf die angezeigten Kontakte!!!
are you shure you want to delete this contact? addressbook de Diesen Kontakt löschen?
are you sure you want to delete this field? addressbook de Sind Sie sicher, dass Sie dieses Feld löschen wollen?
@ -46,6 +50,7 @@ business zip code addressbook de PLZ gesch
calendar uri addressbook de Kalender URI
car phone addressbook de Autotelefon
cell phone addressbook de Mobiltelefon
change all organisation members addressbook de Alle Mitglieder der Organisation ändern
charset for the csv export addressbook de Zeichensatz für den CSV Export
charset of file addressbook de Zeichensatz der Datei
check all addressbook de Alle auswählen
@ -57,10 +62,12 @@ company name addressbook de Firmenname
configuration common de Konfiguration
contact common de Kontakt
contact application admin de Kontakt Anwendung
contact deleted addressbook de Kontakt gelöscht
contact id addressbook de Kontakt ID
contact saved addressbook de Kontakt gespeichert
contact settings admin de Kontakt Einstellungen
copied by %1, from record #%2. addressbook de Kopiert von %1, vom Datensatz Nr. %2.
copy a contact and edit the copy addressbook de Kopiert einen Kontakt und bearbeitet dann die Kopie
country common de Land
create new links addressbook de Neue Verknüpfung erstellen
created addressbook de Angelegt von
@ -73,9 +80,11 @@ debug output in browser addressbook de Debugausgaben in Browser
default filter addressbook de Standardfilter
delete a single entry by passing the id. addressbook de Löscht einen einzelnen Eintrag durch Übergabe seiner ID.
delete this contact addressbook de Diesen Kontakt löschen
delete this organisation including all its contacts addressbook de Diese Organisation einschließlich ALLER Kontakte löschen
deleted addressbook de gelöscht
deletes the photo addressbook de Löscht das Foto
department common de Abteilung
departments addressbook de Abteilungen
displays a remider for birthdays happening today or tomorrow on the startpage (page you get when you enter egroupware or click on the homepage icon). addressbook de Zeigt auf der Startseite eine Geburtstags Erinnerung an, falls heute oder morgen jemand Geburtstag hat. Die Startseite ist die Seite die Sie sehen, wenn Sie eGroupWare betreten oder auf das Startseiten Icon (Haus) klicken.
do you want a private addressbook, which can not be viewed by users, you grant access to your personal addressbook? addressbook de Wollen Sie ein privates Adressbuch, dass nicht von Benutzern einsehbar ist, denen Sie Zugriff auf Ihr persönliches Adressbuch gegeben haben?
do your really want to delete this contact? addressbook de Wollen sie diesen Kontakt wirklich löschen?
@ -92,6 +101,8 @@ email & internet addressbook de Email & Internet
empty for all addressbook de leer für alle
enable an extra private addressbook addressbook de Privates Adressbuch einschalten
enter the path to the exported file here addressbook de Bitte geben Sie den Pfad für die exportierte Datei an
error deleting the contact !!! addressbook de Fehler beim Löschen des Kontakts !!!
error saving the contact !!! addressbook de Fehler beim Speichern des Kontakts !!!
existing links addressbook de Bestehende Verknüpfungen
export addressbook de Export
export as csv addressbook de Exportieren als CSV
@ -101,6 +112,7 @@ export file name addressbook de Dateiname zum Exportieren
export from addressbook addressbook de Export vom Adressbuch
exported addressbook de exportiert
extra addressbook de Extra
failed to change %1 organisation member(s) (insufficent rights) !!! addressbook de %1 Mitglied(er) der Organisation nicht geändert (fehlende Rechte) !!!
fax addressbook de Telefax
fax number common de Telefaxnummer
field %1 has been added ! addressbook de Feld %1 wurde hinzugefügt !
@ -149,6 +161,7 @@ links addressbook de Verkn
list all categories addressbook de Liste alle Kategorien
list all customfields addressbook de Liste alle benutzerdefinierten Felder
load vcard addressbook de VCard laden
locations addressbook de Standorte
mark records as private addressbook de Eintrag als Privat kennzeichnen
message phone addressbook de Anrufbeantworter
middle name addressbook de Zweiter Vorname
@ -164,6 +177,9 @@ number of records to read (%1) addressbook de Anzahl der einzulesenden Datens
only if there is content addressbook de nur wenn etwas angezeigt wird
options for type admin de Optionen für Typ
organisation addressbook de Organisation
organisations addressbook de Organisationen
organisations by departments addressbook de Organisationen nach Abteilungen
organisations by location addressbook de Organisationen nach Standorten
other number addressbook de andere Nr.
other phone addressbook de anderes Telefon
own sorting addressbook de eigene Sortierung
@ -189,6 +205,7 @@ role addressbook de Funktion
room addressbook de Raum
search for '%1' addressbook de Suche nach '%1'
select a portrait format jpeg photo. it will be resized to 60 pixel width. addressbook de Wählen Sie ein hochformatiges jpeg Foto. Es wird 60 Pixel breit skaliert.
select a view addressbook de Eine Ansicht auswählen
select addressbook type addressbook de Typ des Adressbuchs auswählen
select all addressbook de Alles auswählen
select an action or addressbook to move to addressbook de Befehl oder Adressbuch zum Verschieben auswählen
@ -200,10 +217,7 @@ select where you want to store / retrieve contacts admin de Ausw
show addressbook de Anzeigen
show a column for %1 addressbook de Zeige eine %1 Spalte
show birthday reminders on main screen addressbook de Geburtstagserinnerungen auf der Startseite anzeigen
something went wrong by deleting %1 addressbook de Beim Löschen von %1 trat ein Fehler auf
something went wrong by deleting this contact addressbook de Beim Löschen dieses Kontaktes trat ein Fehler auf
something went wrong by reading this contact addressbook de Bein Laden des Kontaktes trat ein Fehler auf
something went wrong by saving this contact. errorcode %1 addressbook de Beim Speichern dieses Kontaktes trat ein Fehler auf. Errocode %1
show the contacts of this organisation addressbook de Kontakte dieser Organisation anzeigen
startrecord addressbook de Startdatensatz
state common de Bundesland
street common de Straße

View File

@ -1,5 +1,6 @@
%1 contact(s) %2 addressbook en %1 contact(s) %2
%1 contact(s) %2, %3 failed because of insufficent rights !!! addressbook en %1 contact(s) %2, %3 failed because of insufficent rights !!!
%1 fields in %2 other organisation member(s) changed addressbook en %1 fields in %2 other organisation member(s) changed
%1 records imported addressbook en %1 records imported
%1 records read (not yet imported, you may go %2back%3 and uncheck test import) addressbook en %1 records read (not yet imported, you may go %2back%3 and uncheck Test Import)
%1 starts with '%2' addressbook en %1 starts with '%2'
@ -8,6 +9,7 @@
@-eval() is only availible to admins!!! addressbook en @-eval() is only availible to admins!!!
accounts addressbook en Accounts
actions addressbook en Actions
add a contact to this organisation addressbook en Add a contact to this organisation
add a new contact addressbook en Add a new contact
add a single entry by passing the fields. addressbook en Add a single entry by passing the fields.
add custom field addressbook en Add Custom Field
@ -23,8 +25,10 @@ addressbook the contact should be saved to addressbook en Addressbook the contac
addressbook-fieldname addressbook en Addressbook-Fieldname
addvcard addressbook en Add VCard
advanced search addressbook en Advanced search
all contacts addressbook en All contacts
alt. csv import addressbook en Alt. CSV Import
always addressbook en always
apply changes to all members, whose fields have the same previous content addressbook en Apply changes to all members, whose fields have the same previous content
apply the action on the whole query, not only the shown contacts!!! addressbook en Apply the action on the whole query, NOT only the shown contacts!!!
are you shure you want to delete this contact? addressbook en Are you shure you want to delete this contact?
are you sure you want to delete this field? addressbook en Are you sure you want to delete this field?
@ -46,6 +50,7 @@ business zip code addressbook en Business Postal Code
calendar uri addressbook en Calendar URI
car phone addressbook en Car Phone
cell phone addressbook en Mobile phone
change all organisation members addressbook en change all organisation members
charset for the csv export addressbook en Charset for the CSV export
charset of file addressbook en Charset of file
check all addressbook en Check all
@ -57,10 +62,12 @@ company name addressbook en company name
configuration common en Configuration
contact common en Contact
contact application admin en Contact application
contact deleted addressbook en Contact deleted
contact id addressbook en Contact ID
contact saved addressbook en Contact saved
contact settings admin en Contact Settings
copied by %1, from record #%2. addressbook en Copied by %1, from record #%2.
copy a contact and edit the copy addressbook en Copy a contact and edit the copy
country common en Country
create new links addressbook en Create new links
created addressbook en Created
@ -73,9 +80,11 @@ debug output in browser addressbook en Debug output in browser
default filter addressbook en Default Filter
delete a single entry by passing the id. addressbook en Delete a single entry by passing the id.
delete this contact addressbook en Delete this contact
delete this organisation including all its contacts addressbook en Delete this organisation including ALL its contacts
deleted addressbook en deleted
deletes the photo addressbook en Deletes the photo
department common en Department
departments addressbook en departments
displays a remider for birthdays happening today or tomorrow on the startpage (page you get when you enter egroupware or click on the homepage icon). addressbook en Displays a remider for birthdays happening today or tomorrow on the startpage (page you get when you enter eGroupWare or click on the homepage icon).
do you want a private addressbook, which can not be viewed by users, you grant access to your personal addressbook? addressbook en Do you want a private addressbook, which can not be viewed by users, you grant access to your personal addressbook?
do your really want to delete this contact? addressbook en Do your really want to delete this contact?
@ -92,6 +101,8 @@ email & internet addressbook en Email & Internet
empty for all addressbook en empty for all
enable an extra private addressbook addressbook en Enable an extra private addressbook
enter the path to the exported file here addressbook en Enter the path to the exported file here
error deleting the contact !!! addressbook en Error deleting the contact !!!
error saving the contact !!! addressbook en Error saving the contact !!!
existing links addressbook en Existing links
export addressbook en export
export as csv addressbook en Export as CSV
@ -101,6 +112,7 @@ export file name addressbook en Export file name
export from addressbook addressbook en Export from Addressbook
exported addressbook en exported
extra addressbook en Extra
failed to change %1 organisation member(s) (insufficent rights) !!! addressbook en failed to change %1 organisation member(s) (insufficent rights) !!!
fax addressbook en Fax
fax number common en Fax Number
field %1 has been added ! addressbook en Field %1 has been added !
@ -149,6 +161,7 @@ links addressbook en Links
list all categories addressbook en List all categories
list all customfields addressbook en List all customfields
load vcard addressbook en Load VCard
locations addressbook en locations
mark records as private addressbook en Mark records as private
message phone addressbook en Message Phone
middle name addressbook en Middle Name
@ -164,6 +177,9 @@ number of records to read (%1) addressbook en Number of records to read (%1)
only if there is content addressbook en only if there is content
options for type admin en Options for type
organisation addressbook en organisation
organisations addressbook en Organisations
organisations by departments addressbook en Organisations by departments
organisations by location addressbook en Organisations by location
other number addressbook en Other Number
other phone addressbook en Other Phone
own sorting addressbook en own sorting
@ -189,6 +205,7 @@ role addressbook en Role
room addressbook en Room
search for '%1' addressbook en Search for '%1'
select a portrait format jpeg photo. it will be resized to 60 pixel width. addressbook en Select a portrait format jpeg photo. It will be resized to 60 pixel width.
select a view addressbook en Select a view
select addressbook type addressbook en Select addressbook type
select all addressbook en Select all
select an action or addressbook to move to addressbook en Select an action or addressbook to move to
@ -200,10 +217,7 @@ select where you want to store / retrieve contacts admin en Select where you wan
show addressbook en Show
show a column for %1 addressbook en Show a column for %1
show birthday reminders on main screen addressbook en Show birthday reminders on main screen
something went wrong by deleting %1 addressbook en Something went wrong by deleting %1
something went wrong by deleting this contact addressbook en Something went wrong by deleting this contact
something went wrong by reading this contact addressbook en something went wrong by reading this contact
something went wrong by saving this contact. errorcode %1 addressbook en Something went wrong by saving this contact. Errorcode %1
show the contacts of this organisation addressbook en Show the contacts of this organisation
startrecord addressbook en Startrecord
state common en State
street common en Street

View File

@ -40,7 +40,7 @@
border-bottom: #9c9c9c 1px solid;
}
.phoneGroup fieldset{
margin-top: 17px;
margin-top: 14px;
font-size: 110%;
height: 117px;
border: solid black 2px;

View File

@ -1,93 +1,6 @@
<?xml version="1.0"?>
<!-- $Id$ -->
<overlay>
<template id="addressbook.editphones" template="" lang="" group="0" version="1.3.001">
<grid class="editphones">
<columns>
<column/>
<column/>
<column/>
</columns>
<rows>
<row>
<description span="all" class="windowheader" value="Edit Phonenumbers - " no_lang="1" align="center" id="fn"/>
<description/>
<description/>
</row>
<row class="th">
<description value="Description"/>
<description value="Number"/>
<description value="pref"/>
</row>
<row>
<description value="business" options=",,,tel_work2" class="bold"/>
<textbox size="30" id="tel_work2"/>
<radio options="tel_work" id="tel_prefer" statustext="select phone number as prefered way of contact"/>
</row>
<row>
<description value="mobile phone" options=",,,tel_cell2"/>
<textbox size="30" id="tel_cell2"/>
<radio options="tel_cell" id="tel_prefer" statustext="select phone number as prefered way of contact"/>
</row>
<row>
<description value="fax" options=",,,tel_fax"/>
<textbox size="30" id="tel_fax"/>
<radio options="tel_fax" id="tel_prefer" statustext="select phone number as prefered way of contact"/>
</row>
<row>
<description value="car phone" options=",,,tel_car"/>
<textbox size="30" id="tel_car"/>
<radio options="tel_car" id="tel_prefer" statustext="select phone number as prefered way of contact"/>
</row>
<row>
<description value="pager" options=",,,tel_pager"/>
<textbox size="30" id="tel_pager"/>
<radio options="tel_pager" id="tel_prefer" statustext="select phone number as prefered way of contact"/>
</row>
<row>
<hrule span="all"/>
</row>
<row>
<description value="Assistent" options=",,,assistent" class="bold"/>
<textbox size="35" id="assistent" span="2"/>
</row>
<row>
<description value="number" options=",,,tel_assistent"/>
<textbox size="30" id="tel_assistent"/>
<radio options="tel_assistent" id="tel_prefer" statustext="select phone number as prefered way of contact"/>
</row>
<row>
<hrule span="all"/>
</row>
<row>
<description value="Private" options=",,,tel_home2" class="bold"/>
<textbox size="30" id="tel_home2"/>
<radio options="tel_home" id="tel_prefer" statustext="select phone number as prefered way of contact"/>
</row>
<row>
<description value="mobile phone" options=",,,tel_cell_private"/>
<textbox size="30" id="tel_cell_private"/>
<radio options="tel_cell_private" id="tel_prefer" statustext="select phone number as prefered way of contact"/>
</row>
<row>
<description value="fax" options=",,,tel_fax_home"/>
<textbox size="30" id="tel_fax_home"/>
<radio options="tel_fax_home" id="tel_prefer" statustext="select phone number as prefered way of contact"/>
</row>
<row>
<hrule span="all"/>
</row>
<row>
<description value=" Other Phone" options=",,,tel_other"/>
<textbox size="30" id="tel_other"/>
<radio options="tel_other" id="tel_prefer" statustext="select phone number as prefered way of contact"/>
</row>
<row>
<button label="Ok" onclick="set_style_by_class('table','editphones','display','none'); if (window.hidephones) hidephones(this.form); return false;" span="all" align="center"/>
</row>
</rows>
</grid>
</template>
<template id="addressbook.edit.personal" template="" lang="" group="0" version="1.3.002">
<grid height="258">
<columns>
@ -132,8 +45,8 @@
</rows>
</grid>
</row>
<row height="30">
<image src="gohome"/>
<row height="28">
<image src="home"/>
<description value="company" options=",,,org_name"/>
<textbox size="45" maxlength="64" id="org_name" onchange="setFileasOptions(this);"/>
</row>
@ -152,7 +65,7 @@
</rows>
</grid>
</template>
<template id="addressbook.edit.organisation" template="" lang="" group="0" version="1.3.001">
<template id="addressbook.edit.organisation" template="" lang="" group="0" version="1.3.002">
<grid height="258">
<columns>
<column/>
@ -167,12 +80,6 @@
<textbox size="45" maxlength="64" id="title"/>
<description/>
</row>
<row>
<description/>
<description value="department" options=",,,org_unit"/>
<textbox id="org_unit" size="45" maxlength="64"/>
<description/>
</row>
<row>
<description/>
<description options=",,,role" value="Role"/>
@ -182,10 +89,10 @@
</hbox>
<description/>
</row>
<row>
<description/>
<description/>
<description/>
<row valign="bottom" height="30">
<image src="home"/>
<description value="department" options=",,,org_unit"/>
<textbox id="org_unit" size="45" maxlength="64"/>
<description/>
</row>
<row>
@ -224,16 +131,15 @@
<textbox size="45" maxlength="64" id="adr_one_countryname"/>
<description/>
</row>
<row>
<description/>
<description/>
<description/>
<row disabled="@view">
<image src="check"/>
<description/>
<checkbox label="change all organisation members" id="change_org" span="all" statustext="Apply changes to all members, whose fields have the same previous content"/>
</row>
</rows>
</grid>
</template>
<template id="addressbook.edit.home" template="" lang="" group="0" version="1.3.001">
<template id="addressbook.edit.home" template="" lang="" group="0" version="1.3.002">
<grid height="258">
<columns>
<column/>
@ -242,7 +148,7 @@
</columns>
<rows>
<row>
<image src="gohome"/>
<image src="accounts"/>
<description value="street" options=",,,adr_two_street"/>
<textbox size="45" maxlength="64" id="adr_two_street"/>
</row>
@ -272,7 +178,7 @@
<textbox size="45" maxlength="64" id="adr_two_countryname"/>
</row>
<row height="30">
<description/>
<image src="gear"/>
<description options=",,,bday" value="Birthday"/>
<hbox id="bday" orient=",0,0">
<date options="Y-m-d" id="bday"/>
@ -282,7 +188,7 @@
</hbox>
</row>
<row>
<image src="private"/>
<image src="private.png"/>
<description value="Public key" options=",,,pubkey"/>
<textbox multiline="true" rows="2" cols="40" id="pubkey"/>
</row>
@ -331,11 +237,98 @@
</rows>
</grid>
</template>
<template id="addressbook.edit" template="" lang="" group="0" version="1.3.002">
<grid width="800">
<template id="addressbook.editphones" template="" lang="" group="0" version="1.3.002">
<grid class="editphones">
<columns>
<column/>
<column/>
<column/>
</columns>
<rows>
<row>
<description span="all" class="windowheader" value="Edit Phonenumbers - " no_lang="1" align="center" id="fn"/>
<description/>
<description/>
</row>
<row class="th">
<description value="Description"/>
<description value="Number"/>
<description value="pref"/>
</row>
<row>
<description value="business" options=",,,tel_work2" class="bold"/>
<textbox size="30" id="tel_work2"/>
<radio options="tel_work,&amp;hearts;" id="tel_prefer" statustext="select phone number as prefered way of contact"/>
</row>
<row>
<description value="mobile phone" options=",,,tel_cell2"/>
<textbox size="30" id="tel_cell2"/>
<radio options="tel_cell,&amp;hearts;" id="tel_prefer" statustext="select phone number as prefered way of contact"/>
</row>
<row>
<description value="fax" options=",,,tel_fax"/>
<textbox size="30" id="tel_fax"/>
<radio options="tel_fax,&amp;hearts;" id="tel_prefer" statustext="select phone number as prefered way of contact"/>
</row>
<row>
<description value="car phone" options=",,,tel_car"/>
<textbox size="30" id="tel_car"/>
<radio options="tel_car,&amp;hearts;" id="tel_prefer" statustext="select phone number as prefered way of contact"/>
</row>
<row>
<description value="pager" options=",,,tel_pager"/>
<textbox size="30" id="tel_pager"/>
<radio options="tel_pager,&amp;hearts;" id="tel_prefer" statustext="select phone number as prefered way of contact"/>
</row>
<row>
<hrule span="all"/>
</row>
<row>
<description value="Assistent" options=",,,assistent" class="bold"/>
<textbox size="35" id="assistent" span="2"/>
</row>
<row>
<description value="number" options=",,,tel_assistent"/>
<textbox size="30" id="tel_assistent"/>
<radio options="tel_assistent,&amp;hearts;" id="tel_prefer" statustext="select phone number as prefered way of contact"/>
</row>
<row>
<hrule span="all"/>
</row>
<row>
<description value="Private" options=",,,tel_home2" class="bold"/>
<textbox size="30" id="tel_home2"/>
<radio options="tel_home,&amp;hearts;" id="tel_prefer" statustext="select phone number as prefered way of contact"/>
</row>
<row>
<description value="mobile phone" options=",,,tel_cell_private"/>
<textbox size="30" id="tel_cell_private"/>
<radio options="tel_cell_private,&amp;hearts;" id="tel_prefer" statustext="select phone number as prefered way of contact"/>
</row>
<row>
<description value="fax" options=",,,tel_fax_home"/>
<textbox size="30" id="tel_fax_home"/>
<radio options="tel_fax_home,&amp;hearts;" id="tel_prefer" statustext="select phone number as prefered way of contact"/>
</row>
<row>
<hrule span="all"/>
</row>
<row>
<description value=" Other Phone" options=",,,tel_other"/>
<textbox size="30" id="tel_other"/>
<radio options="tel_other,&amp;hearts;" id="tel_prefer" statustext="select phone number as prefered way of contact"/>
</row>
<row>
<button label="Ok" onclick="set_style_by_class('table','editphones','display','none'); if (window.hidephones) hidephones(this.form); return false;" span="all" align="center"/>
</row>
</rows>
</grid>
</template>
<template id="addressbook.edit" template="" lang="" group="0" version="1.3.003">
<grid>
<columns>
<column width="450"/>
<column/>
<column width="350"/>
</columns>
<rows>
<row disabled="!@msg">
@ -344,15 +337,22 @@
</row>
<row>
<menulist span=",fileas">
<menupopup data="" rows="1" cols="3" id="fileas_type" no_lang="1" statustext="used for links and for the own sorting of the list"/>
<menupopup data="" rows="1" cols="3" id="fileas_type" no_lang="1"/>
</menulist>
<hbox align="right">
<template id="addressbook.editphones"/>
<menulist span=",leftPad5">
<menupopup no_lang="1" id="tid" onchange="1" label="Type"/>
</menulist>
<html class="space" needed="1" label=" " no_lang="1" id="typegfx" readonly="true"/>
</hbox>
<grid>
<columns>
<column/>
<column/>
</columns>
<rows>
<row disabled="@no_tid">
<menulist span=",leftPad5">
<menupopup no_lang="1" id="tid" onchange="1" label="Type"/>
</menulist>
<html class="space" needed="1" label=" " no_lang="1" id="typegfx" readonly="true"/>
</row>
</rows>
</grid>
</row>
<row valign="top">
<tabbox>
@ -372,6 +372,7 @@
</tabpanels>
</tabbox>
<vbox>
<template id="addressbook.editphones"/>
<groupbox class="phoneGroup">
<caption label="Phone Numbers"/>
<grid>
@ -385,20 +386,20 @@
<row>
<image src="phone"/>
<description value="business" options=",,,tel_work"/>
<textbox id="tel_work" size="24" maxlength="40"/>
<radio options="tel_work" id="tel_prefer" statustext="select phone number as prefered way of contact"/>
<textbox id="tel_work" size="24" maxlength="40" class="telNumbers"/>
<radio options="tel_work,&amp;hearts;" id="tel_prefer" statustext="select phone number as prefered way of contact"/>
</row>
<row>
<description/>
<description value="mobile phone" options=",,,tel_cell"/>
<textbox id="tel_cell" size="24" maxlength="40"/>
<radio options="tel_cell" id="tel_prefer" statustext="select phone number as prefered way of contact"/>
<textbox id="tel_cell" size="24" maxlength="40" class="telNumbers"/>
<radio options="tel_cell,&amp;hearts;" id="tel_prefer" statustext="select phone number as prefered way of contact"/>
</row>
<row>
<description/>
<description value="Private" options=",,,tel_home"/>
<textbox id="tel_home" size="24" maxlength="40"/>
<radio options="tel_home" id="tel_prefer" statustext="select phone number as prefered way of contact"/>
<textbox id="tel_home" size="24" maxlength="40" class="telNumbers"/>
<radio options="tel_home,&amp;hearts;" id="tel_prefer" statustext="select phone number as prefered way of contact"/>
</row>
<row>
<description/>

View File

@ -1,6 +1,11 @@
<?xml version="1.0"?>
<!-- $Id$ -->
<overlay>
<template id="addressbook.index.left" template="" lang="" group="0" version="1.3.001">
<menulist span=",bold">
<menupopup data="" rows="1" cols="1" id="org_view" no_lang="1" statustext="Select a view" onchange="1" options="All contacts"/>
</menulist>
</template>
<template id="addressbook.index.right" template="" lang="" group="0" version="1.3.001">
<menulist>
<menupopup label="Type" id="col_filter[tid]" statustext="Select addressbook type" onchange="1"/>
@ -150,7 +155,7 @@
<description/>
</row>
<row disabled="1">
<description/>
<template id="addressbook.index.left"/>
<template align="right" id="addressbook.index.right"/>
</row>
<row>