* Addressbook: doublicate check while adding/editing contacts, based on email or match of 2 out of name, first name, organisation

This commit is contained in:
Ralf Becker 2012-09-06 12:42:10 +00:00
parent f3d12c72c1
commit 1f77853ff5
6 changed files with 128 additions and 69 deletions

View File

@ -1928,20 +1928,72 @@ class addressbook_ui extends addressbook_bo
}
}
function ajax_setFileasOptions($n_prefix,$n_given,$n_middle,$n_family,$n_suffix,$org_name)
/**
* Doublicate check: returns similar contacts: same email or 2 of name, firstname, org
*
* Also update/return fileas options, if necessary.
*
* @param array $values contact values from form
* @param string $name name of changed value, eg. "email"
* @param int $own_id=0 own contact id, to not check against it
* @return array with keys 'msg' => "EMail address exists, do you want to open contact?" (or null if not existing)
* 'data' => array of id => "full name (addressbook)" pairs
* 'fileas_options'
*/
public function ajax_check_values($values, $name, $own_id=0)
{
$names = array(
'n_prefix' => $n_prefix,
'n_given' => $n_given,
'n_middle' => $n_middle,
'n_family' => $n_family,
'n_suffix' => $n_suffix,
'org_name' => $org_name,
);
$response = new xajaxResponse();
$response->addScript("setOptions('".addslashes(implode("\b",$this->fileas_options($names)))."');");
if (preg_match('/^exec\[([^\]]+)\]$/', $name, $matches)) $name = $matches[1]; // remove exec[ ]
return $response->getXML();
$ret = array('doublicates' => array(), 'msg' => null);
// if email changed, check for doublicates
if (in_array($name, array('email', 'email_home')))
{
if (preg_match('/^'.url_widget::EMAIL_PREG.'$/i', $values[$name])) // only search for real email addresses, to not return to many contacts
{
$contacts = parent::search(array(
'email' => $values[$name],
'email_home' => $values[$name],
),$only_keys=false, $order_by='', $extra_cols='', $wildcard='', $empty=False, $op='OR');
}
}
else
{
// only set fileas-options if other then email changed
$ret['fileas_options'] = array_values($this->fileas_options($values));
// if name, firstname or org changed and at least 2 are specified, check for doublicates
if (in_array($name, array('n_given', 'n_family', 'org_name')) &&
!empty($values['n_given'])+!empty($values['n_family'])+!empty($values['org_name']) >= 2)
{
$filter = array();
foreach(array('email', 'n_given', 'n_family', 'org_name') as $n) // use email too, to exclude obvious false positives
{
if (!empty($values[$n])) $filter[$n] = $values[$n];
}
$contacts = parent::search($criteria='', $only_keys=false, $order_by='', $extra_cols='', $wildcard='',
$empty=False, $op='AND', $start=false, $filter);
}
}
if ($contacts)
{
foreach($contacts as $contact)
{
if ($own_id && $contact['id'] == $own_id) continue;
$ret['doublicates'][$contact['id']] = $this->fileas($contact).' ('.
(!$contact['owner'] ? lang('Accounts') : ($contact['owner'] == $this->user ?
($contact['private'] ? lang('Private') : lang('Personal')) : common::grab_owner_name($contact['owner']))).')';
}
if ($ret['doublicates'])
{
$ret['msg'] = lang('Similar contacts found:').
"\n\n".implode("\n", $ret['doublicates'])."\n\n".
lang('Open for editing?');
}
}
error_log(__METHOD__.'('.array2string($values).", '$name', $own_id) doublicates found ".array2string($ret['doublicates']));
egw_json_response::get()->data($ret);
}
function view($content=null)

View File

@ -99,25 +99,39 @@ function getElement(form,pattern)
}
}
function setName(input)
function check_value(input, own_id)
{
var prefix = document.getElementById("exec[n_prefix]").value;
var given = document.getElementById("exec[n_given]").value;
var middle = document.getElementById("exec[n_middle]").value;
var family = document.getElementById("exec[n_family]").value;
var suffix = document.getElementById("exec[n_suffix]").value;
var org = document.getElementById("exec[org_name]").value;
var name = document.getElementById("exec[n_fn]");
name.value = "";
if (prefix) name.value += prefix+" ";
if (given) name.value += given+" ";
if (middle) name.value += middle+" ";
if (family) name.value += family+" ";
if (suffix) name.value += suffix;
xajax_doXMLHTTP("addressbook.addressbook_ui.ajax_setFileasOptions",prefix,given,middle,family,suffix,org);
var values = egw_json_getFormValues(input.form).exec; // todo use eT2 method, if running under et2
if (input.name.match(/n_/))
{
var name = document.getElementById("exec[n_fn]");
name.value = "";
if (values.n_prefix) name.value += values.n_prefix+" ";
if (values.n_given) name.value += values.n_given+" ";
if (values.n_middle) name.value += values.n_middle+" ";
if (values.n_family) name.value += values.n_family+" ";
if (values.n_suffix) name.value += values.n_suffix;
}
var req = new egw_json_request('addressbook.addressbook_ui.ajax_check_values', [values, input.name, own_id]);
req.sendRequest(true, function(data) {
if (data.msg && confirm(data.msg))
{
for(var id in data.doublicates)
{
//egw.open(id, 'addressbook');
opener.egw_openWindowCentered2(egw_webserverUrl+'/index.php?menuaction=addressbook.addressbook_ui.edit&contact_id='+id, '_blank', 870, 480, 'yes', 'addressbook');
}
}
if (typeof data.fileas_options == 'object')
{
var selbox = document.getElementById("exec[fileas_type]");
for (var i=0; i < data.fileas_options.length; i++)
{
selbox.options[i].text = data.fileas_options[i];
}
}
});
}
function add_whole_list(list)
@ -133,17 +147,6 @@ function add_whole_list(list)
xajax_doXMLHTTP("addressbook.addressbook_ui.ajax_add_whole_list",list,email_type);
}
function setOptions(options_str)
{
var options = options_str.split("\\b");
var selbox = document.getElementById("exec[fileas_type]");
var i;
for (i=0; i < options.length; i++)
{
selbox.options[i].text = options[i];
}
}
function show_custom_country(selectbox)
{
if(!selectbox) return;

View File

@ -314,6 +314,7 @@ no vcard addressbook de Keine VCard
number addressbook de Nummer
number of records to read (%1) addressbook de Anzahl der einzulesenden Datensätze (%1)
open email addresses in external mail program addressbook de Öffne E-Mail Adressen in externem Mail Programm
open for editing? addressbook de Zum Bearbeiten öffnen?
options for type admin de Optionen für Typ
organisation addressbook de Organisation
organisations addressbook de Organisationen
@ -381,6 +382,7 @@ show addressbook de Anzeigen
show birthday reminders on main screen addressbook de Geburtstagserinnerungen auf der Startseite anzeigen
show infolog entries for this organisation addressbook de InfoLog Einträge dieser Organisation anzeigen
show the contacts of this organisation addressbook de Kontakte dieser Organisation anzeigen
similar contacts found: addressbook de Ähnliche Kontakte gefunden:
size of popup (wxh, eg.400x300, if a popup should be used) admin de Größe des Popup (WxH, zB. 400x300, falls ein Popup verwendet werden soll)
stadt addressbook de Stadt
start admin de Starten

View File

@ -314,6 +314,7 @@ no vcard addressbook en No vCard
number addressbook en Number
number of records to read (%1) addressbook en Number of records to read (%1)
open email addresses in external mail program addressbook en Open EMail addresses in external mail program
open for editing? addressbook en Open for editing?
options for type admin en Options for type
organisation addressbook en Organisation
organisations addressbook en Organisations
@ -381,6 +382,7 @@ show addressbook en Show
show birthday reminders on main screen addressbook en Birthday reminders
show infolog entries for this organisation addressbook en Show InfoLog entries for this organisation
show the contacts of this organisation addressbook en Show contacts of this organisation
similar contacts found: addressbook en Similar contacts found:
size of popup (wxh, eg.400x300, if a popup should be used) admin en Size of popup. Width x Height e.g. 400x300
stadt addressbook en City
start admin en Start

File diff suppressed because one or more lines are too long

View File

@ -14,7 +14,7 @@
<file statustext="Select a portrait format jpeg photo. It will be resized to 60 pixel width." id="upload_photo" class="photo"/>
</row>
<row>
<button align="center" label="Ok" onclick="set_style_by_class('table','uploadphoto','display','none'); return false;"/>
<button align="center" label="Ok" onclick="jQuery('table.uploadphoto').css('display','none'); return false;"/>
</row>
</rows>
</grid>
@ -28,33 +28,33 @@
<rows>
<row>
<description value="prefix" for="n_prefix"/>
<textbox id="n_prefix" onchange="setName(this);" size="35" maxlength="64"/>
<textbox id="n_prefix" onchange="check_value(this,'$cont[id]');" size="35" maxlength="64"/>
</row>
<row>
<description value="first name" for="n_given"/>
<textbox id="n_given" onchange="setName(this);" size="35" maxlength="64"/>
<textbox id="n_given" onchange="check_value(this,'$cont[id]');" size="35" maxlength="64"/>
</row>
<row>
<description value="middle name" for="n_middle"/>
<textbox id="n_middle" onchange="setName(this);" size="35" maxlength="64"/>
<textbox id="n_middle" onchange="check_value(this,'$cont[id]');" size="35" maxlength="64"/>
</row>
<row>
<description value="last name" for="n_family"/>
<textbox id="n_family" onchange="setName(this);" size="35" maxlength="64"/>
<textbox id="n_family" onchange="check_value(this,'$cont[id]');" size="35" maxlength="64"/>
</row>
<row>
<description value="suffix" for="n_suffix"/>
<textbox id="n_suffix" onchange="setName(this);" size="35" maxlength="64"/>
<textbox id="n_suffix" onchange="check_value(this,'$cont[id]');" size="35" maxlength="64"/>
</row>
<row>
<description/>
<button label="Ok" id="button[ok]" onclick="set_style_by_class('table','editname','display','none'); if(document.getElementById(form::name('title'))){document.getElementById(form::name('title')).focus();} return false;"/>
<button label="Ok" id="button[ok]" onclick="jQuery('table.editname').css('display','none'); if(document.getElementById(form::name('title'))){document.getElementById(form::name('title')).focus();} return false;"/>
</row>
</rows>
</grid>
</template>
<template id="addressbook.edit.general" template="" lang="" group="0" version="1.9.003">
<grid height="286">
<grid width="100%" height="286">
<columns>
<column/>
<column/>
@ -64,7 +64,7 @@
<row valign="top">
<image src="accounts"/>
<vbox>
<image src="photo" onclick="set_style_by_class('table','uploadphoto','display','inline'); return false;" class="photo"/>
<image src="photo" onclick="jQuery('table.uploadphoto').css('display','inline'); return false;" class="photo"/>
<template id="addressbook.edit.upload"/>
</vbox>
<grid>
@ -77,7 +77,7 @@
<rows>
<row>
<description value="Name"/>
<textbox cols="3" id="n_fn" no_lang="1" onclick="set_style_by_class('table','editname','display','inline'); var focElem = document.getElementById(form::name('n_prefix')); if (!(typeof(focElem) == 'undefined') &amp;&amp; typeof(focElem.focus)=='function') document.getElementById(form::name('n_prefix')).focus();" readonly="true" rows="1" size="-36" span="2" class="cursorHand"/>
<textbox cols="3" id="n_fn" no_lang="1" onclick="jQuery('table.editname').css('display','inline'); var focElem = document.getElementById(form::name('n_prefix')); if (!(typeof(focElem) == 'undefined') &amp;&amp; typeof(focElem.focus)=='function') document.getElementById(form::name('n_prefix')).focus();" readonly="true" rows="1" size="-36" span="2" class="cursorHand"/>
</row>
<row>
<description/>
@ -102,12 +102,12 @@
<row>
<image src="home"/>
<description value="Organisation"/>
<textbox id="org_name" onchange="setName(this);" size="45" maxlength="128"/>
<textbox id="org_name" onchange="check_value(this,'$cont[id]');" size="45" maxlength="128"/>
</row>
<row>
<description/>
<description value="department" for="org_unit"/>
<textbox id="org_unit" size="45" maxlength="64"/>
<textbox id="org_unit" onchange="check_value(this,'$cont[id]');" size="45" maxlength="64"/>
</row>
<row>
<image src="gohome"/>
@ -382,7 +382,7 @@
<description value="Custom fields"/>
</row>
<row height="100%">
<customfields options="$cont[tid],1"/>
<customfields id="private" options="$cont[tid],1"/>
</row>
</rows>
</grid>
@ -481,12 +481,12 @@
<radio statustext="select phone number as prefered way of contact" id="tel_prefer" options="tel_other,&amp;hearts;"/>
</row>
<row>
<button align="center" label="Ok" id="button[ok]" onclick="set_style_by_class('table','editphones','display','none'); if (window.hidephones) hidephones(this.form); return false;" span="all"/>
<button align="center" label="Ok" id="button[ok]" onclick="jQuery('table.editphones').css('display','none'); if (window.hidephones) hidephones(this.form); return false;" span="all"/>
</row>
</rows>
</grid>
</template>
<template id="addressbook.edit" template="" lang="" group="0" version="1.9.002">
<template id="addressbook.edit" template="" lang="" group="0" version="1.9.004">
<grid>
<columns>
<column width="450"/>
@ -580,7 +580,7 @@
<row>
<description/>
<description/>
<button accesskey="m" label="More ..." id="button[more]" onclick="set_style_by_class('table','editphones','display','inline'); if (window.showphones) showphones(this.form); return false;"/>
<button accesskey="m" label="More ..." id="button[more]" onclick="jQuery('table.editphones').css('display','inline'); if (window.showphones) showphones(this.form); return false;"/>
<description/>
</row>
</rows>
@ -608,12 +608,12 @@
<row>
<image src="email.png"/>
<description value="email" for="email"/>
<url-email id="email" options="28,128"/>
<url-email id="email" onchange="check_value(this,'$cont[id]');" options="28,128"/>
</row>
<row>
<description/>
<description value="Private" for="email_home"/>
<url-email id="email_home" options="28,128"/>
<url-email id="email_home" onchange="check_value(this,'$cont[id]');" options="28,128"/>
</row>
</rows>
</grid>