2021-06-25 22:49:24 +02:00
import { E as EgwApp , e as egw , a as et2 _nextmatch , b as etemplate2 , c as et2 _dialog , n as nm _action , f as fetchAll } from '../../chunks/etemplate2-c2e8c88a.js' ;
import '../../chunks/egw_dragdrop_dhtmlx_tree-03e0edbb.js' ;
import '../../chunks/egw-745f42d8.js' ;
import '../../vendor/bower-asset/jquery/dist/jquery.min.js' ;
import '../../vendor/bower-asset/jquery-ui/jquery-ui.js' ;
import '../../chunks/egw_json-05acc323.js' ;
import '../../chunks/egw_core-fa745c26.js' ;
import '../../vendor/tinymce/tinymce/tinymce.min.js' ;
/ * *
* EGroupware - Addressbook - Javascript UI
*
* @ link : https : //www.egroupware.org
* @ package addressbook
* @ author Hadi Nategh < hn - AT - stylite . de >
* @ author Ralf Becker < rb - AT - egroupware . org >
* @ copyright ( c ) 2008 - 21 by Ralf Becker < RalfBecker - AT - outdoor - training . de >
* @ license http : //opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* /
/ * *
* UI for Addressbook CRM view
*
* /
class CRMView extends EgwApp {
// List ID
list _id = "" ; // Reference to the list
nm = null ; // Which addressbook contact id(s) we are showing entries for
contact _ids = [ ] ; // Private js for the list
app _obj = null ; // Hold on to the original push handler
// Push data key(s) to check for our contact ID in the entry's ACL data
push _contact _ids = [ "contact_id" ] ;
/ * *
* Constructor
*
* CRM is part of addressbook
* /
constructor ( ) {
// call parent
super ( 'addressbook' ) ;
}
/ * *
* Destructor
* /
destroy ( _app ) {
this . nm = null ;
if ( this . app _obj != null ) {
this . app _obj . destroy ( _app ) ;
} // call parent
super . destroy ( _app ) ;
}
/ * *
* A template from an app is ready , looks like it might be a CRM view .
* Check it , get CRM ready , and bind accordingly
*
* @ param et2
* @ param appname
* /
static view _ready ( et2 , app _obj ) {
// Check to see if the template is for a CRM view
if ( et2 . app == app _obj . appname ) {
return CRMView . reconnect ( app _obj ) ;
} // Make sure object is there, etemplate2 will pick it up and call our et2_ready
let crm = undefined ; // @ts-ignore
if ( typeof et2 . app _obj . crm == "undefined" && app . classes . crm ) {
// @ts-ignore
crm = et2 . app _obj . crm = new app . classes . crm ( ) ;
}
if ( typeof crm == "undefined" ) {
egw . debug ( "error" , "CRMView object is missing" ) ;
return false ;
} // We can set this now
crm . set _view _obj ( app _obj ) ;
}
/ * *
* This function is called when the etemplate2 object is loaded
* and ready . The associated app [ is supposed to have ] already called its own et2 _ready ( ) ,
* so any changes done here will override the app .
*
* @ param { etemplate2 } et2 newly ready object
* @ param { string } name Template name
* /
et2 _ready ( et2 , name ) {
// call parent
super . et2 _ready ( et2 , name ) ;
}
/ * *
* Our CRM has become disconnected from its list , probably because something submitted .
* Find it , and get things working again .
*
* @ param app _obj
* /
static reconnect ( app _obj ) {
// Check
let contact _ids = app _obj . et2 . getArrayMgr ( "content" ) . getEntry ( "action_id" ) || "" ;
if ( ! contact _ids ) return ;
for ( let existing _app of EgwApp . _instances ) {
if ( existing _app instanceof CRMView && existing _app . list _id == app _obj . et2 . getInstanceManager ( ) . uniqueId ) {
// List was reloaded. Rebind.
existing _app . app _obj . destroy ( existing _app . app _obj . appname ) ;
if ( ! existing _app . nm ? . getParent ( ) ) {
try {
// This will probably not die cleanly, we had a reference when it was destroyed
existing _app . nm . destroy ( ) ;
} catch ( e ) { }
}
return existing _app . set _view _obj ( app _obj ) ;
}
}
}
/ * *
* Set the associated private app JS
* We try and pull the needed info here
* /
set _view _obj ( app _obj ) {
this . app _obj = app _obj ; // Make sure object is there, etemplate2 will pick it up and call our et2_ready
app _obj . et2 . getInstanceManager ( ) . app _obj . crm = this ; // Make _sure_ we get notified if the list is removed (actions, refresh) - this is not always a full
// destruction
jQuery ( app _obj . et2 . getDOMNode ( ) ) . on ( 'clear' , function ( ) {
this . nm = null ;
} . bind ( this ) ) ; // For easy reference later
this . list _id = app _obj . et2 . getInstanceManager ( ) . uniqueId ;
this . nm = app _obj . et2 . getDOMWidgetById ( 'nm' ) ;
let contact _ids = app _obj . et2 . getArrayMgr ( "content" ) . getEntry ( "action_id" ) || "" ;
if ( typeof contact _ids == "string" ) {
contact _ids = contact _ids . split ( "," ) ;
}
this . set _contact _ids ( contact _ids ) ; // Override the push handler
this . _override _push ( app _obj ) ;
}
/ * *
* Set or change which contact IDs we are showing entries for
* /
set _contact _ids ( ids ) {
this . contact _ids = ids ;
let filter = {
action _id : this . contact _ids
} ;
if ( this . nm !== null ) {
this . nm . applyFilters ( filter ) ;
}
}
/ * *
* Handle a push notification about entry changes from the websocket
*
* @ param pushData
* @ param { string } pushData . app application name
* @ param { ( string | number ) } pushData . id id of entry to refresh or null
* @ param { string } pushData . type either 'update' , 'edit' , 'delete' , 'add' or null
* - update : request just modified data from given rows . Sorting is not considered ,
* so if the sort field is changed , the row will not be moved .
* - edit : rows changed , but sorting may be affected . Requires full reload .
* - delete : just delete the given rows clientside ( no server interaction neccessary )
* - add : ask server for data , add in intelligently
* @ param { object | null } pushData . acl Extra data for determining relevance . eg : owner or responsible to decide if update is necessary
* @ param { number } pushData . account _id User that caused the notification
* /
push ( pushData ) {
if ( pushData . app !== this . app _obj . appname || ! this . nm ) return ; // If we know about it and it's an update, just update.
// This must be before all ACL checks, as contact might have changed and entry needs to be removed
// (server responds then with null / no entry causing the entry to disappear)
if ( pushData . type !== "add" && this . egw . dataHasUID ( this . uid ( pushData ) ) ) {
// Check to see if it's in OUR nextmatch
let uid = this . uid ( pushData ) ;
let known = Object . values ( this . nm . controller . _indexMap ) . filter ( function ( row ) {
return row . uid == uid ;
} ) ;
let type = pushData . type ;
if ( known && known . length > 0 ) {
if ( ! this . id _check ( pushData . acl ) ) {
// Was ours, not anymore, and we know this now - no server needed. Just remove from nm.
type = et2 _nextmatch . DELETE ;
}
return this . nm . refresh ( pushData . id , type ) ;
}
}
if ( this . id _check ( pushData . acl ) ) {
return this . _app _obj _push ( pushData ) ;
}
}
/ * *
* Check to see if the given entry is "ours"
*
* @ param entry
* /
id _check ( entry ) {
// Check if it's for one of our contacts
for ( let field of this . push _contact _ids ) {
if ( entry && entry [ field ] ) {
let val = typeof entry [ field ] == "string" ? [ entry [ field ] ] : entry [ field ] ;
if ( val . filter ( v => this . contact _ids . indexOf ( v ) >= 0 ) . length > 0 ) {
return true ;
}
}
}
return false ;
}
/ * *
* Override the list 's push handler to do nothing, we' ll call it if we want it .
*
* @ param app _obj
* @ private
* /
_override _push ( app _obj ) {
this . _app _obj _push = app _obj . push . bind ( app _obj ) ;
app _obj . push = function ( pushData ) {
return false ;
} ;
}
}
app . classes . crm = CRMView ;
2011-04-26 18:22:10 +02:00
/ * *
2013-09-20 12:50:48 +02:00
* EGroupware - Addressbook - Javascript UI
2011-04-26 18:22:10 +02:00
*
2020-02-09 13:07:42 +01:00
* @ link : https : //www.egroupware.org
2013-09-20 12:50:48 +02:00
* @ package addressbook
2021-06-09 11:11:34 +02:00
* @ author Hadi Nategh < hn - AT - egroupware . org >
* @ author Ralf Becker < rb - AT - egroupware . org >
* @ copyright ( c ) 2008 - 21 by Ralf Becker < RalfBecker - AT - outdoor - training . de >
2013-09-20 12:50:48 +02:00
* @ license http : //opensource.org/licenses/gpl-license.php GPL - GNU General Public License
2011-04-26 18:22:10 +02:00
* /
2021-06-25 22:49:24 +02:00
/ * *
* Object to call app . addressbook . openCRMview with
2020-02-09 13:07:42 +01:00
* /
2021-06-25 22:49:24 +02:00
2011-04-26 18:22:10 +02:00
/ * *
2013-09-20 12:50:48 +02:00
* UI for Addressbook
*
* @ augments AppJS
2011-04-26 18:22:10 +02:00
* /
2021-06-09 11:11:34 +02:00
class AddressbookApp extends EgwApp {
2021-06-25 22:49:24 +02:00
// These fields help with push
push _grant _fields = [ "owner" , "shared_with" ] ;
push _filter _fields = [ "tid" , "owner" , "cat_id" ] ;
/ * *
* Constructor
*
* @ memberOf app . addressbook
* /
constructor ( ) {
// call parent
super ( 'addressbook' ) ;
}
/ * *
* Destructor
* /
destroy ( _app ) {
// call parent
super . destroy ( _app ) ;
}
/ * *
* This function is called when the etemplate2 object is loaded
* and ready . If you must store a reference to the et2 object ,
* make sure to clean it up in destroy ( ) .
*
* @ param { etemplate2 } et2 newly ready object
* @ param { string } name
* /
et2 _ready ( et2 , name ) {
// r49769 let's CRM view run under currentapp == "addressbook", which causes
// app.addressbook.et2_ready called before app.infolog.et2_ready and therefore
// app.addressbook.et2 would point to infolog template, if we not stop here
if ( name . match ( /^infolog|tracker\./ ) ) return ; // call parent
super . et2 _ready ( et2 , name ) ;
switch ( name ) {
case 'addressbook.edit' :
var content = this . et2 . getArrayMgr ( 'content' ) . data ;
if ( typeof content . showsearchbuttons == 'undefined' || ! content . showsearchbuttons ) {
this . show _custom _country ( jQuery ( 'select[id*="adr_one_countrycode"]' ) . get ( 0 ) ) ;
this . show _custom _country ( jQuery ( 'select[id*="adr_two_countrycode"]' ) . get ( 0 ) ) ; // Instanciate infolog JS too - wrong app, so it won't be done automatically
if ( typeof window . app . infolog != 'object' && typeof window . app . classes [ 'infolog' ] == 'function' ) {
window . app . infolog = new window . app . classes . infolog ( ) ;
}
} // Call check value if the AB got opened with presets
if ( window . location . href . match ( /&presets\[email\]/g ) && content . presets _fields ) {
for ( var i = 0 ; i < content . presets _fields . length ; i ++ ) {
this . check _value ( this . et2 . getWidgetById ( content . presets _fields ) , 0 ) ;
}
}
break ;
2020-02-09 13:07:42 +01:00
}
2021-06-25 22:49:24 +02:00
jQuery ( 'select[id*="adr_one_countrycode"]' ) . each ( function ( ) {
if ( app . addressbook ) app . addressbook . show _custom _country ( this ) ;
} ) ;
jQuery ( 'select[id*="adr_two_countrycode"]' ) . each ( function ( ) {
if ( app . addressbook ) app . addressbook . show _custom _country ( this ) ;
} ) ;
}
/ * *
* Observer method receives update notifications from all applications
*
* App is responsible for only reacting to "messages" it is interested in !
*
* Addressbook checks for CRM view to update the displayed data if you edit
* that contact
*
* @ param { string } _msg message ( already translated ) to show , eg . 'Entry deleted'
* @ param { string } _app application name
* @ param { ( string | number ) } _id id of entry to refresh or null
* @ param { string } _type either 'update' , 'edit' , 'delete' , 'add' or null
* - update : request just modified data from given rows . Sorting is not considered ,
* so if the sort field is changed , the row will not be moved .
* - edit : rows changed , but sorting may be affected . Requires full reload .
* - delete : just delete the given rows clientside ( no server interaction neccessary )
* - add : requires full reload for proper sorting
* @ param { string } _msg _type 'error' , 'warning' or 'success' ( default )
* @ param { object | null } _links app => array of ids of linked entries
* or null , if not triggered on server - side , which adds that info
* @ return { false | * } false to stop regular refresh , thought all observers are run
* /
observer ( _msg , _app , _id , _type , _msg _type , _links ) {
// Edit to the current entry
var state = this . getState ( ) ;
if ( _app === 'addressbook' && state && state . type && state . type === 'view' && state . id === _id ) {
var content = egw . dataGetUIDdata ( 'addressbook::' + _id ) ;
if ( content . data ) {
var view = etemplate2 . getById ( 'addressbook-view' ) ;
if ( view ) {
view . widgetContainer . _children [ 0 ] . set _value ( {
content : content . data
} ) ;
}
}
return false ;
} else if ( _app === 'calendar' ) {
// Event changed, update any [known] contacts participating
var content = egw . dataGetUIDdata ( _app + '::' + _id ) ;
if ( content && content . data && content . data . participant _types && content . data . participant _types . c ) {
for ( var contact in content . data . participant _types . c ) {
// Refresh handles checking to see if the contact is known,
// and updating it directly
egw . dataRefreshUID ( 'addressbook::' + contact ) ;
}
return true ;
} else if ( ! content ) {
// No data on the event, we'll have to reload if calendar column is visible
// to get the updated information
var nm = etemplate2 . getById ( 'addressbook-index' ) . widgetContainer . getWidgetById ( 'nm' ) ;
var pref = nm ? nm . _getPreferences ( ) : false ;
if ( pref && pref . visible . indexOf ( 'calendar_calendar' ) > - 1 ) {
nm . refresh ( null , 'update' ) ;
}
}
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
return true ;
}
/ * *
* Handle a push notification about entry changes from the websocket
*
* Get ' s called for data of all apps , but should only handle data of apps it displays ,
* which is by default only it ' s own , but can be for multiple apps eg . for calendar .
*
* @ param pushData
* @ param { string } pushData . app application name
* @ param { ( string | number ) } pushData . id id of entry to refresh or null
* @ param { string } pushData . type either 'update' , 'edit' , 'delete' , 'add' or null
* - update : request just modified data from given rows . Sorting is not considered ,
* so if the sort field is changed , the row will not be moved .
* - edit : rows changed , but sorting may be affected . Requires full reload .
* - delete : just delete the given rows clientside ( no server interaction neccessary )
* - add : requires full reload for proper sorting
* @ param { object | null } pushData . acl Extra data for determining relevance . eg : owner or responsible to decide if update is necessary
* @ param { number } pushData . account _id User that caused the notification
* /
push ( pushData ) {
// show missed calls on their CRM view
let et2 _id = this . et2 ? . getInstanceManager ( ) . uniqueId ;
if ( pushData . app === 'stylite' && pushData . acl . missed && et2 _id && et2 _id . substr ( 0 , 17 ) === 'addressbook-view-' && pushData . acl . account _id == this . egw . user ( 'account_id' ) && pushData . acl . contact _id == this . et2 . getArrayMgr ( "content" ) ? . getEntry ( "id" ) ) {
egw _getFramework ( ) ? . notifyAppTab ( et2 _id . substr ( 17 ) ) ;
} // don't care about other apps data
if ( pushData . app !== this . appname ) return ; // Update the contact list
if ( this . et2 && this . et2 . getInstanceManager ( ) . name == "addressbook.index" ) {
return super . push ( pushData ) ;
} // Update CRM view (sidebox part), if open
let contact _id = this . et2 ? . getArrayMgr ( "content" ) ? . getEntry ( "id" ) || 0 ;
if ( this . et2 && contact _id && contact _id == pushData . id ) {
this . et2 . getInstanceManager ( ) . submit ( ) ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
}
/ * *
* Change handler for contact / org selectbox
*
* @ param node
* @ param { et2 _extension _nextmatch } nm
* @ param { et2 _selectbox } widget
* /
change _grouped _view ( node , nm , widget ) {
let template = "addressbook.index.rows" ;
let value = { } ;
if ( nm . activeFilters . sitemgr _display ) {
template = nm . activeFilters . sitemgr _display + '.rows' ;
} else if ( widget . getValue ( ) . indexOf ( "org_name" ) == 0 ) {
template = "addressbook.index.org_rows" ;
} else if ( widget . getValue ( ) . indexOf ( 'duplicate' ) === 0 ) {
template = 'addressbook.index.duplicate_rows' ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
if ( nm . activeFilters . col _filter . parent _id ) {
template = widget . getValue ( ) . indexOf ( 'duplicate' ) === 0 ? 'addressbook.index.duplicate_rows' : 'addressbook.index.org_rows' ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
let promise = nm . set _template ( template ) ;
value [ widget . id ] = widget . getValue ( ) ;
if ( promise ) {
jQuery . when . apply ( null , promise ) . done ( function ( ) {
nm . applyFilters ( value ) ;
} ) ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
return ! promise ;
}
/ * *
* Open CRM view from addressbook index itself
*
* @ param _action
* @ param _senders
* /
view ( _action , _senders ) {
let extras = {
contact _id : _senders [ 0 ] . id . split ( '::' ) . pop ( ) ,
index : _senders [ 0 ] . _index
} ;
let data = egw . dataGetUIDdata ( _senders [ 0 ] . id ) [ 'data' ] ; // CRM list
if ( _action . id != 'view' ) {
extras . crm _list = _action . id . replace ( 'view-' , '' ) ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
if ( ! extras . crm _list ) extras . crm _list = egw . preference ( 'crm_list' , 'addressbook' ) ;
extras . title = _action . id . match ( /\-organisation/ ) && data . org _name != "" ? data . org _name : data . n _fn + " (" + egw . lang ( extras . crm _list ) + ")" ;
extras . icon = data . photo ;
return this . openCRMview ( extras ) ;
}
/ * *
* Open a CRM view for a contact : callback for link - registry / egw . open / other apps
*
* @ param { CrmParams } _params object with attribute "contact_id" and optional "title" , "crm_list" , "icon"
* @ param { object } _senders use egw . dataGetUIDdata to get contact _id
* /
openCRMview ( _params , _senders ) {
let contact _id = typeof _params === 'object' ? _params . contact _id : _params ;
if ( typeof _senders === 'object' ) {
let data = egw . dataGetUIDdata ( _senders [ 0 ] . id ) ;
contact _id = data . data . contact _id ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
if ( typeof contact _id !== 'undefined' ) {
let crm _list = _params . crm _list || egw . preference ( 'crm_list' , 'addressbook' ) ;
if ( ! crm _list || crm _list === '~edit~' ) crm _list = 'infolog' ;
let url = this . egw . link ( '/index.php' , {
menuaction : 'addressbook.addressbook_ui.view' ,
ajax : 'true' ,
contact _id : contact _id ,
crm _list : crm _list
} ) ; // no framework, just open the url
if ( typeof this . egw . window . framework === 'undefined' ) {
return this . egw . open _link ( url ) ;
}
let open = function ( _title ) {
let title = _title || this . egw . link _title ( 'addressbook' , contact _id , open ) ;
if ( title ) {
this . egw . window . framework . tabLinkHandler ( url , {
displayName : title ,
icon : _params . icon || this . egw . link ( '/api/avatar.php' , {
contact _id : contact _id ,
etag : new Date ( ) . valueOf ( ) / 86400 | 0 // cache for a day, better then no invalidation
} ) ,
refreshCallback : function ( ) {
etemplate2 . getById ( "addressbook-view-" + this . appName ) ? . app _obj . addressbook . view _set _list ( ) ;
} ,
id : contact _id + '-' + crm _list
} ) ;
2020-02-09 13:07:42 +01:00
}
2021-06-25 22:49:24 +02:00
} . bind ( this ) ;
open ( _params . title ) ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
}
/ * *
* Set link filter for the already open & rendered list
*
* @ param { Object } filter Object with key / value pairs of filters to set
* /
view _set _list ( filter ) {
// Find the infolog list
var list = etemplate2 . getById ( jQuery ( this . et2 . getInstanceManager ( ) . DOMContainer ) . nextAll ( '.et2_container' ) . attr ( 'id' ) ) ;
var nm = list ? list . widgetContainer . getWidgetById ( 'nm' ) : null ;
if ( nm ) {
nm . applyFilters ( filter ) ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
}
/ * *
* Run an action from CRM view toolbar
*
* @ param { object } _action
* /
view _actions ( _action , _widget ) {
var app _id = _widget . dom _id . split ( '_' ) ;
var et2 = etemplate2 . getById ( app _id [ 0 ] ) ;
var id = et2 . widgetContainer . getArrayMgr ( 'content' ) . data . id ;
switch ( _widget . id ) {
case 'button[edit]' :
this . egw . open ( id , 'addressbook' , 'edit' ) ;
break ;
case 'button[copy]' :
this . egw . open ( id , 'addressbook' , 'edit' , {
makecp : 1
} ) ;
break ;
case 'button[delete]' :
et2 _dialog . confirm ( _widget , egw . lang ( 'Delete this contact?' ) , egw . lang ( 'Delete' ) ) ;
break ;
case 'button[close]' :
framework . activeApp . tab . closeButton . click ( ) ;
break ;
default :
// submit all other buttons back to server
et2 . widgetContainer . _inst . submit ( ) ;
break ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
}
/ * *
* Open the calender to view the selected contacts
* @ param { egwAction } _action
* @ param { egwActionObject [ ] } _senders
* /
view _calendar ( _action , _senders ) {
var extras = {
filter : 'all' ,
cat _id : '' ,
owner : [ ]
} ;
var orgs = [ ] ;
for ( var i = 0 ; i < _senders . length ; i ++ ) {
// Remove UID prefix for just contact_id
var ids = _senders [ i ] . id . split ( '::' ) ;
ids . shift ( ) ;
ids = ids . join ( '::' ) ; // Orgs need to get all the contact IDs first
if ( ids . substr ( 0 , 9 ) == 'org_name:' ) {
orgs . push ( ids ) ;
} else {
// Check to see if this is a user account, we prefer to use
// account ID in calendar
var data = this . egw . dataGetUIDdata ( _senders [ i ] . id ) ;
if ( data && data . data && data . data . account _id ) {
extras . owner . push ( data . data . account _id ) ;
} else {
extras . owner . push ( 'c' + ids ) ;
}
}
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
if ( orgs . length > 0 ) {
// Get organisation contacts, then show infolog list
this . egw . json ( 'addressbook.addressbook_ui.ajax_organisation_contacts' , [ orgs ] , function ( contacts ) {
for ( var i = 0 ; i < contacts . length ; i ++ ) {
extras . owner . push ( 'c' + contacts [ i ] ) ;
}
extras . owner = extras . owner . join ( ',' ) ;
this . egw . open ( '' , 'calendar' , 'list' , extras , 'calendar' ) ;
} , this , true , this ) . sendRequest ( ) ;
} else {
extras . owner = extras . owner . join ( ',' ) ;
egw . open ( '' , 'calendar' , 'list' , extras , 'calendar' ) ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
}
/ * *
* Add appointment or show calendar for selected contacts , call default nm _action after some checks
*
* @ param _action
* @ param _senders
* /
add _cal ( _action , _senders ) {
if ( ! _senders [ 0 ] . id . match ( /^(?:addressbook::)?[0-9]+$/ ) ) {
// send org-view requests to server
_action . data . nm _action = "submit" ;
nm _action ( _action , _senders ) ;
} else {
var ids = egw . user ( 'account_id' ) + ',' ;
for ( var i = 0 ; i < _senders . length ; i ++ ) {
// Remove UID prefix for just contact_id
var id = _senders [ i ] . id . split ( '::' ) ;
ids += "c" + id [ 1 ] + ( i < _senders . length - 1 ? "," : "" ) ;
}
var extra = { } ;
extra [ _action . data && _action . data . url && _action . data . url . indexOf ( 'owner' ) > 0 ? 'owner' : 'participants' ] = ids ;
if ( _action . id === 'schedule_call' ) extra [ 'videoconference' ] = 1 ; // Use framework to add calendar entry
egw . open ( '' , 'calendar' , 'add' , extra ) ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
}
/ * *
* View infolog entries linked to selected contact
* @ param { egwAction } _action Select action
* @ param { egwActionObject [ ] } _senders Selected contact ( s )
* /
view _infolog ( _action , _senders ) {
var extras = {
action : 'addressbook' ,
action _id : [ ] ,
action _title : _senders . length > 1 ? this . egw . lang ( 'selected contacts' ) : ''
} ;
var orgs = [ ] ;
for ( var i = 0 ; i < _senders . length ; i ++ ) {
// Remove UID prefix for just contact_id
var ids = _senders [ i ] . id . split ( '::' ) ;
ids . shift ( ) ;
ids = ids . join ( '::' ) ; // Orgs need to get all the contact IDs first
if ( ids . substr ( 0 , 9 ) == 'org_name:' ) {
orgs . push ( ids ) ;
} else {
extras . action _id . push ( ids ) ;
}
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
if ( orgs . length > 0 ) {
// Get organisation contacts, then show infolog list
this . egw . json ( 'addressbook.addressbook_ui.ajax_organisation_contacts' , [ orgs ] , function ( contacts ) {
extras . action _id = extras . action _id . concat ( contacts ) ;
this . egw . open ( '' , 'infolog' , 'list' , extras , 'infolog' ) ;
} , this , true , this ) . sendRequest ( ) ;
} else {
egw . open ( '' , 'infolog' , 'list' , extras , 'infolog' ) ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
}
/ * *
* Add task for selected contacts , call default nm _action after some checks
*
* @ param _action
* @ param _senders
* /
add _task ( _action , _senders ) {
if ( ! _senders [ 0 ] . id . match ( /^(addressbook::)?[0-9]+$/ ) ) {
// send org-view requests to server
_action . data . nm _action = "submit" ;
} else {
// call nm_action's popup
_action . data . nm _action = "popup" ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
nm _action ( _action , _senders ) ;
}
/ * *
* Actions via ajax
*
* @ param { egwAction } _action
* @ param { egwActionObject [ ] } _selected
* /
action ( _action , _selected ) {
let all = _action . parent . data . nextmatch ? . getSelection ( ) . all ;
let no _notifications = _action . parent . getActionById ( "no_notifications" ) ? . checked || false ;
let ids = [ ] ; // Loop so we get just the app's ID
for ( var i = 0 ; i < _selected . length ; i ++ ) {
var id = _selected [ i ] . id ;
ids . push ( id . split ( "::" ) . pop ( ) ) ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
switch ( _action . id ) {
case 'delete' :
egw . json ( "addressbook.addressbook_ui.ajax_action" , [ _action . id , ids , all , no _notifications ] ) . sendRequest ( true ) ;
break ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
}
/ * *
* [ More ... ] in phones clicked : copy allways shown phone numbers to phone popup
*
* @ param { jQuery . event } _event
* @ param { et2 _widget } _widget
* /
showphones ( _event , _widget ) {
this . _copyvalues ( {
tel _home : 'tel_home2' ,
tel _work : 'tel_work2' ,
tel _cell : 'tel_cell2' ,
tel _fax : 'tel_fax2'
} ) ;
jQuery ( 'table.editphones' ) . css ( 'display' , 'inline' ) ;
_event . stopPropagation ( ) ;
return false ;
}
/ * *
* [ OK ] in phone popup clicked : copy phone numbers back to always shown ones
*
* @ param { jQuery . event } _event
* @ param { et2 _widget } _widget
* /
hidephones ( _event , _widget ) {
this . _copyvalues ( {
tel _home2 : 'tel_home' ,
tel _work2 : 'tel_work' ,
tel _cell2 : 'tel_cell' ,
tel _fax2 : 'tel_fax'
} ) ;
jQuery ( 'table.editphones' ) . css ( 'display' , 'none' ) ;
_event . stopPropagation ( ) ;
return false ;
}
/ * *
* Copy content of multiple fields
*
* @ param { object } what object with src : dst pairs
* /
_copyvalues ( what ) {
for ( var name in what ) {
var src = this . et2 . getWidgetById ( name ) ;
var dst = this . et2 . getWidgetById ( what [ name ] ) ;
if ( src && dst ) dst . set _value ( src . get _value ? src . get _value ( ) : src . value ) ;
} // change tel_prefer according to what
var tel _prefer = this . et2 . getWidgetById ( 'tel_prefer' ) ;
if ( tel _prefer ) {
var val = tel _prefer . get _value ? tel _prefer . get _value ( ) : tel _prefer . value ;
if ( typeof what [ val ] != 'undefined' ) tel _prefer . set _value ( what [ val ] ) ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
}
/ * *
* Callback function to create confirm dialog for duplicates contacts
*
* @ param { object } _data includes duplicates contacts information
*
* /
_confirmdialog _callback ( _data ) {
var confirmdialog = function ( _title , _value , _buttons , _egw _or _appname ) {
return et2 _createWidget ( "dialog" , {
callback ( _buttons , _value ) {
if ( _buttons == et2 _dialog . OK _BUTTON ) {
var id = '' ;
var content = this . template . widgetContainer . getArrayMgr ( 'content' ) . data ;
for ( var row in _value . grid ) {
if ( _value . grid [ row ] . confirm == "true" && typeof content . grid != 'undefined' ) {
id = this . options . value . content . grid [ row ] . confirm ;
egw . open ( id , 'addressbook' ) ;
}
2020-02-09 13:07:42 +01:00
}
2021-06-25 22:49:24 +02:00
}
} ,
title : _title || egw . lang ( 'Input required' ) ,
buttons : _buttons || et2 _dialog . BUTTONS _OK _CANCEL ,
value : {
content : {
grid : _value
}
} ,
template : egw . webserverUrl + '/addressbook/templates/default/dupconfirmdialog.xet'
} , et2 _dialog . _create _parent ( _egw _or _appname ) ) ;
} ;
if ( _data . msg && _data . doublicates ) {
var content = [ ] ;
for ( var id in _data . doublicates ) {
content . push ( {
"confirm" : id ,
"name" : _data . doublicates [ id ]
} ) ;
}
confirmdialog ( this . egw . lang ( 'Duplicate warning' ) , content , et2 _dialog . BUTTONS _OK _CANCEL ) ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
if ( typeof _data . fileas _options == 'object' && this . et2 ) {
var selbox = this . et2 . getWidgetById ( 'fileas_type' ) ;
if ( selbox ) {
selbox . set _select _options ( _data . fileas _sel _options ) ;
}
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
}
/ * *
* Callback if certain fields get changed
*
* @ param { widget } widget widget
* @ param { string } own _id Current AB id
* /
check _value ( widget , own _id ) {
// if we edit an account, call account_change to let it do it's stuff too
if ( this . et2 . getWidgetById ( 'account_lid' ) ) {
this . account _change ( null , widget ) ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
var values = this . et2 . _inst . getValues ( this . et2 ) ;
if ( widget . id . match ( /n_/ ) ) {
var value = '' ;
if ( values . n _prefix ) value += values . n _prefix + " " ;
if ( values . n _given ) value += values . n _given + " " ;
if ( values . n _middle ) value += values . n _middle + " " ;
if ( values . n _family ) value += values . n _family + " " ;
if ( values . n _suffix ) value += values . n _suffix ;
var name = this . et2 . getWidgetById ( "n_fn" ) ;
if ( typeof name != 'undefined' ) name . set _value ( value ) ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
egw . json ( 'addressbook.addressbook_ui.ajax_check_values' , [ values , widget . id , own _id ] , this . _confirmdialog _callback , this , true , this ) . sendRequest ( ) ;
}
show _custom _country ( selectbox ) {
if ( ! selectbox ) return ;
var custom _field _name = selectbox . id . replace ( "countrycode" , "countryname" ) ;
var custom _field = document . getElementById ( custom _field _name ) ;
if ( custom _field && selectbox . value == "-custom-" ) {
custom _field . style . display = "inline" ;
} else if ( custom _field ) {
if ( ( selectbox . value == "" || selectbox . value == null ) && custom _field . value != "" ) {
selectbox . value = "-custom-" ; // Chosen needs this to update
jQuery ( selectbox ) . trigger ( "liszt:updated" ) ;
custom _field . style . display = "inline" ;
} else {
custom _field . style . display = "none" ;
}
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
var region = this . et2 . getWidgetById ( selectbox . name . replace ( 'countrycode' , 'region' ) ) ;
if ( region ) {
region . set _country _code ( selectbox . value ) ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
}
/ * *
* Add a new mailing list . If any contacts are selected , they will be added .
*
* @ param { egwAction } owner
* @ param { egwActionObject [ ] } selected
* /
add _new _list ( owner , selected ) {
if ( ! owner || typeof owner == 'object' ) {
var filter = this . et2 . getWidgetById ( 'filter' ) ;
owner = filter . getValue ( ) || egw . preference ( 'add_default' , 'addressbook' ) ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
var contacts = [ ] ;
if ( selected && selected [ 0 ] && selected [ 0 ] . getAllSelected ( ) ) {
// Action says all contacts selected, better ask the server for _all_ the IDs
var fetching = fetchAll ( selected , this . et2 . getWidgetById ( 'nm' ) , jQuery . proxy ( function ( contacts ) {
this . _add _new _list _prompt ( owner , contacts ) ;
} , this ) ) ;
if ( fetching ) return ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
if ( selected && selected . length ) {
for ( var i = 0 ; i < selected . length ; i ++ ) {
// Remove UID prefix for just contact_id
var ids = selected [ i ] . id . split ( '::' ) ;
ids . shift ( ) ;
ids = ids . join ( '::' ) ;
contacts . push ( ids ) ;
}
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
this . _add _new _list _prompt ( owner , contacts ) ;
}
/ * *
* Ask the user for a name , then create a new list with the provided contacts
* in it .
*
* @ param { int } owner
* @ param { String [ ] } contacts
* /
_add _new _list _prompt ( owner , contacts ) {
var lists = this . et2 . getWidgetById ( 'filter2' ) ;
let owner _options = this . et2 . getArrayMgr ( 'sel_options' ) . getEntry ( 'filter' ) || { } ;
let callback = function ( button , values ) {
if ( button == et2 _dialog . OK _BUTTON ) {
egw . json ( 'addressbook.addressbook_ui.ajax_set_list' , [ 0 , values . name , values . owner , contacts ] , function ( result ) {
if ( typeof result == 'object' ) return ; // This response not for us
// Update list
if ( result ) {
lists . options . select _options . unshift ( {
value : result ,
label : values . name
} ) ;
lists . set _select _options ( lists . options . select _options ) ; // Set to new list so they can see it easily
lists . set _value ( result ) ; // Call change event manually after setting the value
// Not sure why our selectbox does not trigger change event
jQuery ( lists . node ) . change ( ) ;
} // Add to actions
var addressbook _actions = egw _getActionManager ( 'addressbook' , false ) ;
var dist _lists = null ;
if ( addressbook _actions && ( dist _lists = addressbook _actions . getActionById ( 'to_list' ) ) ) {
var id = 'to_list_' + result ;
var action = dist _lists . addAction ( 'popup' , id , values . name ) ;
action . setDefaultExecute ( action . parent . onExecute . fnct ) ;
action . updateAction ( {
group : 1
} ) ;
}
} ) . sendRequest ( true ) ;
}
} ;
let dialog = et2 _createWidget ( "dialog" , {
callback : callback ,
title : this . egw . lang ( 'Add a new list' ) ,
buttons : et2 _dialog . BUTTONS _OK _CANCEL ,
value : {
content : {
owner : owner
} ,
sel _options : {
owner : owner _options
}
} ,
template : egw . webserverUrl + '/addressbook/templates/default/add_list_dialog.xet' ,
class : "et2_prompt" ,
minWidth : 400
} , this . et2 ) ;
}
/ * *
* Rename the current distribution list selected in the nextmatch filter2
*
* Differences from add _new _list are in the dialog , parameters sent , and how the
* response is dealt with
*
* @ param { egwAction } action Action selected in context menu ( rename )
* @ param { egwActionObject [ ] } selected The selected row ( s ) . Not used for this .
* /
rename _list ( action , selected ) {
var lists = this . et2 . getWidgetById ( 'filter2' ) ;
var list = lists . getValue ( ) || 0 ;
var value = null ;
for ( var i = 0 ; i < lists . options . select _options . length ; i ++ ) {
if ( lists . options . select _options [ i ] . value == list ) {
value = lists . options . select _options [ i ] ;
}
}
et2 _dialog . show _prompt ( function ( button , name ) {
if ( button == et2 _dialog . OK _BUTTON ) {
egw . json ( 'addressbook.addressbook_ui.ajax_set_list' , [ list , name ] , function ( result ) {
if ( typeof result == 'object' ) return ; // This response not for us
// Update list
if ( result ) {
value . label = name ;
lists . set _select _options ( lists . options . select _options ) ;
}
} ) . sendRequest ( true ) ;
}
} , this . egw . lang ( 'Name for the distribution list' ) , this . egw . lang ( 'Rename list' ) , value . label ) ;
}
/ * *
* OnChange for distribution list selectbox
* /
filter2 _onchange ( ) {
var filter = this . et2 . getWidgetById ( 'filter' ) ;
var filter2 = this . et2 . getWidgetById ( 'filter2' ) ;
var widget = this . et2 . getWidgetById ( 'nm' ) ;
var filter2 _val = filter2 . get _value ( ) ;
if ( filter2 _val == 'add' ) {
this . add _new _list ( typeof widget == 'undefined' ? this . et2 . getWidgetById ( 'filter' ) . value : widget . header . filter . get _value ( ) ) ;
filter2 . set _value ( '' ) ;
} // automatic switch to accounts addressbook or all addressbooks depending on distribution list is a group
else if ( filter2 _val && filter2 _val < 0 !== ( filter . get _value ( ) === '0' ) ) {
// Change filter & filter2 at the same time
widget . applyFilters ( {
filter : filter2 _val < 0 ? '0' : '' ,
filter2 : filter2 _val
} ) ; // Don't get rows here, let applyFilters() do it
2020-02-09 13:07:42 +01:00
return false ;
2021-06-25 22:49:24 +02:00
}
return true ;
}
/ * *
* Method to enable actions by comparing a field with given value
* /
nm _compare _field ( ) {
var field = this . et2 . getWidgetById ( 'filter2' ) ;
if ( field ) var val = field . get _value ( ) ;
if ( val ) {
return nm _compare _field ;
} else {
return false ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
}
/ * *
* Apply advanced search filters to index nextmatch
*
* @ param { object } filters
* /
adv _search ( filters ) {
var index = window . opener . etemplate2 . getById ( 'addressbook-index' ) ;
if ( ! index ) {
alert ( 'Could not find index' ) ;
egw ( window ) . close ( ) ;
return false ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
var nm = index . widgetContainer . getWidgetById ( 'nm' ) ;
if ( ! index ) {
window . opener . egw . message ( 'Could not find list' , 'error' ) ;
egw ( window ) . close ( ) ;
return false ;
} // Reset filters first
nm . activeFilters = { } ;
nm . applyFilters ( filters ) ;
return false ;
}
/ * *
* Mail vCard
*
* @ param { object } _action
* @ param { array } _elems
* /
adb _mail _vcard ( _action , _elems ) {
var link = {
'preset[type]' : [ ] ,
'preset[file]' : [ ]
} ;
var content = {
data : {
files : {
file : [ ] ,
type : [ ]
}
}
} ;
var nm = this . et2 . getWidgetById ( 'nm' ) ;
if ( fetchAll ( _elems , nm , jQuery . proxy ( function ( ids ) {
this . adb _mail _vcard ( _action , ids . map ( function ( num ) {
return {
id : 'addressbook::' + num
} ;
} ) ) ;
} , this ) ) ) {
return ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
for ( var i = 0 ; i < _elems . length ; i ++ ) {
var idToUse = _elems [ i ] . id ;
var idToUseArray = idToUse . split ( '::' ) ;
idToUse = idToUseArray [ 1 ] ;
link [ 'preset[type]' ] . push ( "text/vcard; charset=" + ( egw . preference ( 'vcard_charset' , 'addressbook' ) || 'utf-8' ) ) ;
link [ 'preset[file]' ] . push ( "vfs://default/apps/addressbook/" + idToUse + "/.entry" ) ;
content . data . files . file . push ( "vfs://default/apps/addressbook/" + idToUse + "/.entry" ) ;
content . data . files . type . push ( "text/vcard; charset=" + ( egw . preference ( 'vcard_charset' , 'addressbook' ) || 'utf-8' ) ) ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
egw . openWithinWindow ( "mail" , "setCompose" , content , link , /mail.mail_compose.compose/ ) ;
for ( var index in content ) {
if ( content [ index ] . file . length > 0 ) {
egw . message ( egw . lang ( '%1 contact(s) added as %2' , content [ index ] . file . length , egw . lang ( index ) ) ) ;
return ;
}
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
}
/ * *
* Action function to set business or private mail checkboxes to user preferences
*
* @ param { egwAction } action Action user selected .
* /
mailCheckbox ( action ) {
var preferences = {
business : action . getManager ( ) . getActionById ( 'email_business' ) . checked ? true : false ,
private : action . getManager ( ) . getActionById ( 'email_home' ) . checked ? true : false
} ;
this . egw . set _preference ( 'addressbook' , 'preferredMail' , preferences ) ;
}
/ * *
* Action function to add the email address ( business or home ) of the selected
* contacts to a compose email popup window .
*
* Uses the egw API to handle the opening of the popup .
*
* @ param { egwAction } action Action user selected . Should have ID of either
* 'email_business' or 'email_home' , from server side definition of actions .
* @ param { egwActionObject [ ] } selected Selected rows
* /
addEmail ( action , selected ) {
// Check for all selected.
var nm = this . et2 . getWidgetById ( 'nm' ) ;
if ( fetchAll ( selected , nm , jQuery . proxy ( function ( ids ) {
// fetchAll() returns just the ID, no prefix, so map it to match normal selected
this . addEmail ( action , ids . map ( function ( num ) {
return {
id : 'addressbook::' + num
} ;
} ) ) ;
} , this ) ) ) {
// Need more IDs, will use the above callback when they're ready.
return ;
} // Go through selected & pull email addresses from data
var emails = [ ] ;
for ( var i = 0 ; i < selected . length ; i ++ ) {
// Pull data from global cache
var data = egw . dataGetUIDdata ( selected [ i ] . id ) || {
data : { }
} ;
var email _business = data . data [ action . getManager ( ) . getActionById ( 'email_business' ) . checked ? 'email' : '' ] ;
var email = data . data [ action . getManager ( ) . getActionById ( 'email_home' ) . checked ? 'email_home' : '' ] ; // prefix email with full name
var personal = data . data . n _fn || '' ;
if ( personal . match ( /[^a-z0-9. -]/i ) ) personal = '"' + personal . replace ( /"/ , '\\"' ) + '"' ; //remove comma in personal as it will confilict with mail content comma seperator in the process
personal = personal . replace ( /,/g , '' ) ;
if ( email _business ) {
emails . push ( ( personal ? personal + ' <' : '' ) + email _business + ( personal ? '>' : '' ) ) ;
}
if ( email ) {
emails . push ( ( personal ? personal + ' <' : '' ) + email + ( personal ? '>' : '' ) ) ;
}
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
switch ( action . id ) {
case "add_to_to" :
egw . open _link ( 'mailto:' + emails . join ( ',' ) . replace ( /&/g , '__AMPERSAND__' ) ) ;
break ;
case "add_to_cc" :
egw . open _link ( 'mailto:' + '?cc=' + emails . join ( ',' ) . replace ( /&/g , '__AMPERSAND__' ) ) ; //egw.mailto('mailto:');
break ;
case "add_to_bcc" :
egw . open _link ( 'mailto:' + '?bcc=' + emails . join ( ',' ) . replace ( /&/g , '__AMPERSAND__' ) ) ;
break ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
return false ;
}
/ * *
* Merge the selected contacts into the target document .
*
* Normally we let the framework handle this , but in addressbook we want to
* interfere and customize things a little to ask about saving to infolog .
*
* @ param { egwAction } action - The document they clicked
* @ param { egwActionObject [ ] } selected - Rows selected
* /
merge _mail ( action , selected , target ) {
// Special processing for email documents - ask about infolog
if ( action && action . data && selected . length > 1 ) {
var callback = function ( button , value ) {
if ( button == et2 _dialog . OK _BUTTON ) {
var _action = jQuery . extend ( true , { } , action ) ;
if ( value . infolog ) {
_action . data . menuaction += '&to_app=infolog&info_type=' + value . info _type ;
}
nm _action ( _action , selected , target ) ;
}
} ;
et2 _createWidget ( "dialog" , {
callback : callback ,
title : action . caption ,
buttons : et2 _dialog . BUTTONS _OK _CANCEL ,
type : et2 _dialog . QUESTION _MESSAGE ,
template : egw . webserverUrl + '/addressbook/templates/default/mail_merge_dialog.xet' ,
value : {
content : {
info _type : 'email'
} ,
sel _options : this . et2 . getArrayMgr ( 'sel_options' ) . data
}
} ) ;
} else {
// Normal processing for only one contact selected
return nm _action ( action , selected , target ) ;
}
}
/ * *
* Retrieve the current state of the application for future restoration
*
* Overridden from parent to handle viewing a contact . In this case state
* will be { contact _id : # }
*
* @ return { object } Application specific map representing the current state
* /
getState ( ) {
// Most likely we're in the list view
var state = super . getState ( ) ;
if ( jQuery . isEmptyObject ( state ) ) {
// Not in a list view. Try to find contact ID
var etemplates = etemplate2 . getByApplication ( 'addressbook' ) ;
for ( var i = 0 ; i < etemplates . length ; i ++ ) {
var content = etemplates [ i ] . widgetContainer . getArrayMgr ( "content" ) ;
if ( content && content . getEntry ( 'id' ) ) {
state = {
app : 'addressbook' ,
id : content . getEntry ( 'id' ) ,
type : 'view'
} ;
break ;
}
}
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
return state ;
}
/ * *
* Set the application ' s state to the given state .
*
* Overridden from parent to stop the contact view ' s infolog nextmatch from
* being changed .
*
* @ param { { name : string , state : object } | string } state Object ( or JSON string ) for a state .
* Only state is required , and its contents are application specific .
*
* @ return { boolean } false - Returns false to stop event propagation
* /
setState ( state , template ) {
var current _state = this . getState ( ) ; // State should be an object, not a string, but we'll parse
if ( typeof state == "string" ) {
if ( state . indexOf ( '{' ) != - 1 || state == 'null' ) {
state = JSON . parse ( state ) ;
}
} // Redirect from view to list - parent would do this, but infolog nextmatch stops it
if ( current _state . app && current _state . id && ( typeof state . state == 'undefined' || typeof state . state . app == 'undefined' ) ) {
// Redirect to list
// 'blank' is the special name for no filters, send that instead of the nice translated name
var safe _name = jQuery . isEmptyObject ( state ) || jQuery . isEmptyObject ( state . state || state . filter ) ? 'blank' : state . name . replace ( /[^A-Za-z0-9-_]/g , '_' ) ;
egw . open ( '' , this . appname , 'list' , {
'favorite' : safe _name
} , this . appname ) ;
return false ;
} else if ( jQuery . isEmptyObject ( state ) ) {
// Regular handling first to clear everything but advanced search
super . setState ( state ) ; // Clear advanced search, which is in session and etemplate
egw . json ( 'addressbook.addressbook_ui.ajax_clear_advanced_search' , [ ] , function ( ) {
framework . setWebsiteTitle ( 'addressbook' , '' ) ;
var index = etemplate2 . getById ( 'addressbook-index' ) ;
if ( index && index . widgetContainer ) {
var nm = index . widgetContainer . getWidgetById ( 'nm' ) ;
if ( nm ) {
nm . applyFilters ( {
advanced _search : false
2020-02-09 13:07:42 +01:00
} ) ;
2021-06-25 22:49:24 +02:00
}
}
} , this ) . sendRequest ( true ) ;
return false ;
} else if ( state . state . grouped _view ) {
// Deal with grouped views that are not valid (not in list of options)
// by faking viewing that organisation
var index = etemplate2 . getById ( 'addressbook-index' ) ;
if ( index && index . widgetContainer ) {
var grouped = index . widgetContainer . getWidgetById ( 'grouped_view' ) ;
var options ;
if ( grouped && grouped . options && grouped . options . select _options ) {
options = grouped . options . select _options ;
} // Check to see if it's not there
if ( options && ( options . find && ! options . find ( function ( e ) {
console . log ( e ) ;
return e . value === state . state . grouped _view ;
} ) || typeof options . find === 'undefined' && ! options [ state . state . grouped _view ] ) ) {
window . setTimeout ( function ( ) {
app . addressbook . setState ( state ) ;
} , 500 ) ;
var nm = index . widgetContainer . getWidgetById ( 'nm' ) ;
var action = nm . controller . _actionManager . getActionById ( 'view_org' ) ;
var senders = [ {
_context : {
_widget : nm
}
} ] ;
return nm _action ( action , senders , { } , {
ids : [ state . state . grouped _view ]
} ) ;
}
}
} // Make sure advanced search is false if not set, this clears any
// currently set advanced search
if ( typeof state . state . advanced _search === 'undefined' ) {
state . state . advanced _search = false ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
return super . setState ( state ) ;
}
/ * *
* Field changed , call server validation
*
* @ param { jQuery . Event } _ev
* @ param { et2 _button } _widget
* /
account _change ( _ev , _widget ) {
switch ( _widget . id ) {
case 'account_passwd' :
case 'account_lid' :
case 'n_family' :
case 'n_given' :
case 'account_passwd_2' :
var values = this . et2 . _inst . getValues ( this . et2 ) ;
var data = {
account _id : this . et2 . getArrayMgr ( 'content' ) . data . account _id ,
account _lid : values . account _lid ,
account _firstname : values . n _given ,
account _lastname : values . n _family ,
account _email : values . email ,
account _passwd : values . account _passwd ,
account _passwd _2 : values . account _passwd _2
} ;
this . egw . message ( '' ) ;
this . egw . json ( 'admin_account::ajax_check' , [ data , _widget . id ] , function ( _msg ) {
if ( _msg && typeof _msg == 'string' ) {
egw ( window ) . message ( _msg , 'error' ) ; // context get's lost :(
_widget . getDOMNode ( ) . focus ( ) ;
}
} , this ) . sendRequest ( ) ;
break ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
}
/ * *
* Get title in order to set it as document title
* @ returns { string }
* /
getWindowTitle ( ) {
var widget = this . et2 . getWidgetById ( 'n_fn' ) ;
if ( widget ) return widget . options . value ;
}
/ * *
* Enable / Disable geolocation action items in contextmenu base on address availabilty
*
* @ param { egwAction } _action
* @ param { egwActionObject [ ] } _selected selected rows
* @ returns { boolean } return false if no address found
* /
geoLocation _enabled ( _action , _selected ) {
// multiple selection is not supported
if ( _selected . length > 1 ) return false ;
var url = this . getGeolocationConfig ( ) ; // exit if no url or invalide url given
if ( ! url || typeof url === 'undefined' || typeof url !== 'string' ) {
egw . debug ( 'warn' , 'no url or invalid url given as geoLocationUrl' ) ;
return false ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
var content = egw . dataGetUIDdata ( _selected [ 0 ] . id ) ; // Selected, but data not found
if ( ! content || typeof content . data === 'undefined' ) return false ;
var type = _action . id === 'business' ? 'one' : 'two' ;
var addrs = [ content . data [ 'adr_' + type + '_street' ] , content . data [ 'adr_' + type + '_locality' ] , content . data [ 'adr_' + type + '_postalcode' ] ] ;
var fields = '' ; // Replcae placeholders with acctual values
for ( var i = 0 ; i < addrs . length ; i ++ ) {
fields += addrs [ i ] ? addrs [ i ] : '' ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
return url !== '' && fields !== '' ? true : false ;
}
/ * *
* Generate a geo location URL based on geolocation _url in
* site configuration
*
* @ param { object } _dest _data
* @ param { string } _dest _type type of destination address ( 'one' | 'two' )
* @ param { object } _src _data address data to be used as source contact data | coordination object
* @ param { string } _src _type type of source address ( 'browser' | 'one' | 'two' )
* @ returns { Boolean | string } return url and return false if no address
* /
geoLocationUrl ( _dest _data , _dest _type , _src _data , _src _type ) {
var dest _type = _dest _type || 'one' ;
var url = this . getGeolocationConfig ( ) ; // exit if no url or invalide url given
if ( ! url || typeof url === 'undefined' || typeof url !== 'string' ) {
egw . debug ( 'warn' , 'no url or invalid url given as geoLocationUrl' ) ;
return false ;
} // array of placeholders with their representing values
var addrs = [ [ // source address
{
id : 'r0' ,
val : _src _type === 'browser' ? _src _data . latitude : _src _data [ 'adr_' + _src _type + '_street' ]
} , {
id : 't0' ,
val : _src _type === 'browser' ? _src _data . longitude : _src _data [ 'adr_' + _src _type + '_locality' ]
} , {
id : 'c0' ,
val : _src _type === 'browser' ? '' : _src _data [ 'adr_' + _src _type + '_countrycode' ]
} , {
id : 'z0' ,
val : _src _type === 'browser' ? '' : _src _data [ 'adr_' + _src _type + '_postalcode' ]
} ] , [ // destination address
{
id : 'r1' ,
val : _dest _data [ 'adr_' + dest _type + '_street' ]
} , {
id : 't1' ,
val : _dest _data [ 'adr_' + dest _type + '_locality' ]
} , {
id : 'c1' ,
val : _dest _data [ 'adr_' + dest _type + '_countrycode' ]
} , {
id : 'z1' ,
val : _dest _data [ 'adr_' + dest _type + '_postalcode' ]
} ] ] ;
var src _param = url . match ( /{{%rs=.*%rs}}/ig ) ;
if ( src _param [ 0 ] ) {
src _param = src _param [ 0 ] . replace ( /{{%rs=/ , '' ) ;
src _param = src _param . replace ( /%rs}}/ , '' ) ;
url = url . replace ( /{{%rs=.*%rs}}/ , src _param ) ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
var d _param = url . match ( /{{%d=.*%d}}/ig ) ;
if ( d _param [ 0 ] ) {
d _param = d _param [ 0 ] . replace ( /{{%d=/ , '' ) ;
d _param = d _param . replace ( /%d}}/ , '' ) ;
url = url . replace ( /{{%d=.*%d}}/ , d _param ) ;
} // Replcae placeholders with acctual values
for ( var j = 0 ; j < addrs . length ; j ++ ) {
for ( var i = 0 ; i < addrs [ j ] . length ; i ++ ) {
url = url . replace ( '%' + addrs [ j ] [ i ] [ 'id' ] , addrs [ j ] [ i ] [ 'val' ] ? addrs [ j ] [ i ] [ 'val' ] : "" ) ;
}
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
return url !== '' ? url : false ;
}
/ * *
* Open a popup base on selected address in provided map
*
* @ param { object } _action
* @ param { object } _selected
* /
geoLocationExec ( _action , _selected ) {
var content = egw . dataGetUIDdata ( _selected [ 0 ] . id ) ;
var geolocation _src = egw . preference ( 'geolocation_src' , 'addressbook' ) ;
var self = this ;
if ( geolocation _src === 'browser' && navigator . geolocation ) {
navigator . geolocation . getCurrentPosition ( function ( position ) {
if ( position && position . coords ) {
var url = self . geoLocationUrl ( content . data , _action . id === 'business' ? 'one' : 'two' , position . coords , 'browser' ) ;
window . open ( url , '_blank' ) ;
}
} ) ;
} else {
egw . json ( 'addressbook.addressbook_ui.ajax_get_contact' , [ egw . user ( 'account_id' ) ] , function ( _data ) {
var url = self . geoLocationUrl ( content . data , _action . id === 'business' ? 'one' : 'two' , _data , geolocation _src === 'browser' ? 'one' : geolocation _src ) ;
window . open ( url , '_blank' ) ;
} ) . sendRequest ( ) ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
}
/ * *
* Get geolocation _url stored in config | default url
*
* @ returns { String }
* /
getGeolocationConfig ( ) {
// This default url should be identical to the first value of geolocation_url array
// defined in addressbook_hooks::config
var default _url = 'https://maps.here.com/directions/drive{{%rs=/%rs}}%r0,%t0,%z0,%c0{{%d=/%d}}%r1,%t1,%z1+%c1' ;
var geo _url = egw . config ( 'geolocation_url' ) ;
if ( geo _url ) geo _url = geo _url [ 0 ] ;
return geo _url || default _url ;
}
/ * *
* Check to see if the selection contains at most one account
*
* @ param { egwAction } action
* @ param { egwActionObject [ ] } selected Selected rows
* /
can _merge ( action , selected ) {
return selected . filter ( function ( row ) {
var data = egw . dataGetUIDdata ( row . id ) ;
return data && data . data . account _id ;
} ) . length <= 1 ;
}
/ * *
* Check if the share action is enabled for this entry
* This only works for single contacts
*
* @ param { egwAction } _action
* @ param { egwActionObject [ ] } _entries
* @ param { egwActionObject } _target
* @ returns { boolean } if action is enabled
* /
is _share _enabled ( _action , _entries , _target ) {
var enabled = true ;
for ( var i = 0 ; i < _entries . length ; i ++ ) {
let id = _entries [ i ] . id . split ( '::' ) ;
if ( isNaN ( id [ 1 ] ) ) {
return false ;
}
}
return enabled ;
}
/ * *
* Check if selected user ( s ) is online then enable action
* @ param _action
* @ param _selected
* /
videoconference _isUserOnline ( _action , _selected ) {
let list = app . status ? app . status . getEntireList ( ) : { } ;
for ( let sel in _selected ) {
if ( sel == '0' && _selected [ sel ] [ 'id' ] == 'nm' ) continue ;
let row = egw . dataGetUIDdata ( _selected [ sel ] [ 'id' ] ) ;
let enabled = false ;
for ( let entry in list ) {
if ( row . data && row . data . account _id && row . data . account _id == list [ entry ] [ 'account_id' ] ) {
enabled = list [ entry ] [ 'data' ] [ 'status' ] [ 'active' ] ;
}
}
if ( ! enabled ) return false ;
}
return true ;
}
videoconference _isThereAnyCall ( _action , _selected ) {
return this . videoconference _isUserOnline ( _action , _selected ) && egw . getSessionItem ( 'status' , 'videoconference-session' ) ;
}
/ * *
* Call action
* @ param _action
* @ param _selected
* /
videoconference _actionCall ( _action , _selected ) {
let data = [ ] ;
for ( let sel in _selected ) {
let row = egw . dataGetUIDdata ( _selected [ sel ] [ 'id' ] ) ;
data . push ( {
id : row . data . account _id ,
name : row . data . n _fn ,
avatar : "account:" + row . data . account _id ,
audioonly : _action . id == 'audiocall' ? true : false
} ) ;
}
if ( _action . id == 'invite' ) {
app . status . inviteToCall ( data , egw . getSessionItem ( 'status' , 'videoconference-session' ) ) ;
} else {
app . status . makeCall ( data ) ;
}
}
/ * *
* Check if new shared _with value is allowed / user has rights to share into that AB
*
* Remove the entry again , if user is not allowed
* /
shared _changed ( ) {
let shared = this . et2 . getInputWidgetById ( 'shared_values' ) ;
let value = shared ? . get _value ( ) ;
if ( value ) {
this . egw . json ( 'addressbook.addressbook_ui.ajax_check_shared' , [ {
contact : this . et2 . getInstanceManager ( ) . getValues ( this . et2 ) ,
// for sharing policy
shared _values : value ,
shared _writable : this . et2 . getInputWidgetById ( 'shared_writable' ) . get _value ( )
} ] , _data => {
if ( Array . isArray ( _data ) && _data . length ) {
// remove not allowed entries
shared . set _value ( value . filter ( val => _data . indexOf ( val ) === - 1 ) ) ;
}
} ) . sendRequest ( ) ;
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
}
2021-06-09 11:11:34 +02:00
}
2021-06-25 22:49:24 +02:00
2020-02-09 13:07:42 +01:00
app . classes . addressbook = AddressbookApp ;
2021-06-25 22:49:24 +02:00
//# sourceMappingURL=app.js.map