diff --git a/addressbook/inc/class.addressbook_ui.inc.php b/addressbook/inc/class.addressbook_ui.inc.php index de637b057c..0d31e5949c 100644 --- a/addressbook/inc/class.addressbook_ui.inc.php +++ b/addressbook/inc/class.addressbook_ui.inc.php @@ -3250,8 +3250,6 @@ class addressbook_ui extends addressbook_bo // need to load list's app.js now, as exec calls header before other app can include it // Framework::includeJS('/'.$crm_list.'/js/app.js'); - // Load CRM code - Framework::includeJS('.','CRM','addressbook'); $content['view_sidebox'] = addressbook_hooks::getViewDOMID($content['id'], $crm_list); $this->tmpl->exec('addressbook.addressbook_ui.view',$content,$sel_options,$readonlys,array( 'id' => $content['id'], diff --git a/addressbook/js/app.ts b/addressbook/js/app.ts index 80e758971c..1c07c4eb9c 100644 --- a/addressbook/js/app.ts +++ b/addressbook/js/app.ts @@ -1110,6 +1110,62 @@ class AddressbookApp extends EgwApp return false; } + /** + * Get email addresses from selected contacts + * + * @param selected + * @param {string[]} email_fields + * @param {string} name_field + * @returns {Promise} + */ + async _getEmails(selected, email_fields = ["email"], name_field = 'n_fn') : Promise + { + if(email_fields.length == 0) + { + return []; + } + + // Check for all selected, don't resolve until all done + let nm = this.et2.getWidgetById('nm'); + let all = new Promise(function(resolve) + { + let fetching = fetchAll(selected, nm, ids => {resolve(ids.map(function(num) {return {id: 'addressbook::' + num};}))}); + if(!fetching) + { + resolve(selected); + } + }); + let awaited = await all; + + // Go through selected & pull email addresses from data + let emails = []; + for(let i = 0; i < awaited.length; i++) + { + // Pull data from global cache + const data = egw.dataGetUIDdata(awaited[i].id) || {data: {}}; + let emailAddresses = email_fields.map(field => + { + return data.data[field]; + }) + + // prefix email with full name + let personal = data.data[name_field] || ''; + 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, ''); + + emailAddresses.forEach(mail => + { + emails.push((personal ? personal + ' <' : '') + mail + (personal ? '>' : '')); + }); + } + return emails; + } + /** * Merge the selected contacts into the target document. * diff --git a/addressbook/templates/kdots/view.xet b/addressbook/templates/kdots/view.xet new file mode 100644 index 0000000000..169c4a613a --- /dev/null +++ b/addressbook/templates/kdots/view.xet @@ -0,0 +1,63 @@ + + + + + \ No newline at end of file diff --git a/admin/js/app.ts b/admin/js/app.ts index 484c9ea54f..a949957bc6 100644 --- a/admin/js/app.ts +++ b/admin/js/app.ts @@ -423,7 +423,14 @@ class AdminApp extends EgwApp if(!_data || _data.type != undefined) return; // Insert the content, etemplate will load into it - jQuery(this.ajax_target.getDOMNode()).append(typeof _data === 'string' ? _data : _data[0]); + if(typeof _data === "string" || typeof _data[0] !== "undefined") + { + jQuery(this.ajax_target.getDOMNode()).append(typeof _data === 'string' ? _data : _data[0]); + } + else if(typeof _data.DOMNodeID == "string") + { + this.ajax_target.setAttribute("id", _data.DOMNodeID); + } } /** diff --git a/admin/templates/default/index.xet b/admin/templates/default/index.xet index bcebf05698..45eef7a5a8 100644 --- a/admin/templates/default/index.xet +++ b/admin/templates/default/index.xet @@ -83,7 +83,7 @@