From 6085b1eed9a2d988bc97da313e53410b26c17cd7 Mon Sep 17 00:00:00 2001 From: phot0n Date: Mon, 4 Apr 2022 18:30:33 +0530 Subject: [PATCH 1/6] feat(minor): use specific email signature via from field * fix: increase debounce timeout so that events dont clash * fix: signature getting appended multiple time upon dialog open/close (cherry picked from commit b9af0ac37e47cc54bc77aa97794927ba2bb51aeb) --- .../js/frappe/form/footer/form_timeline.js | 4 +- frappe/public/js/frappe/ui/field_group.js | 10 +++++ .../public/js/frappe/views/communication.js | 43 ++++++++++++++----- 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/frappe/public/js/frappe/form/footer/form_timeline.js b/frappe/public/js/frappe/form/footer/form_timeline.js index fcd4326eb80f..083e1a4beedd 100644 --- a/frappe/public/js/frappe/form/footer/form_timeline.js +++ b/frappe/public/js/frappe/form/footer/form_timeline.js @@ -422,13 +422,13 @@ class FormTimeline extends BaseTimeline { } if (this.frm.doctype === "Communication") { - args.txt = ""; + args.message = ""; args.last_email = this.frm.doc; args.recipients = this.frm.doc.sender; args.subject = __("Re: {0}", [this.frm.doc.subject]); } else { const comment_value = frappe.markdown(this.frm.comment_box.get_value()); - args.txt = strip_html(comment_value) ? comment_value : ''; + args.message = strip_html(comment_value) ? comment_value : ''; } new frappe.views.CommunicationComposer(args); diff --git a/frappe/public/js/frappe/ui/field_group.js b/frappe/public/js/frappe/ui/field_group.js index df56fe7b8448..db03bf0a6a04 100644 --- a/frappe/public/js/frappe/ui/field_group.js +++ b/frappe/public/js/frappe/ui/field_group.js @@ -129,8 +129,18 @@ frappe.ui.FieldGroup = frappe.ui.form.Layout.extend({ resolve(); } }); +<<<<<<< HEAD }, set_input: function(key, val) { +======= + } + + has_field(fieldname) { + return !!this.fields_dict[fieldname]; + } + + set_input(key, val) { +>>>>>>> b9af0ac37e (feat(minor): use specific email signature via from field) return this.set_value(key, val); }, set_values: function(dict) { diff --git a/frappe/public/js/frappe/views/communication.js b/frappe/public/js/frappe/views/communication.js index b33cd1a3f181..25ee79c86d57 100755 --- a/frappe/public/js/frappe/views/communication.js +++ b/frappe/public/js/frappe/views/communication.js @@ -95,7 +95,7 @@ frappe.views.CommunicationComposer = class { fieldname: "content", onchange: frappe.utils.debounce( this.save_as_draft.bind(this), - 300 + 500 ) }, { fieldtype: "Section Break" }, @@ -151,7 +151,14 @@ frappe.views.CommunicationComposer = class { fieldname: "sender", options: email_accounts.map(function(e) { return e.email_id; - }) + }), + change: async () => { + let sender_email = this.dialog.get_value("sender"); + this.reply_set = !!sender_email; + this.content_set = sender_email && this.sender && this.sender != sender_email; + await this.set_content(sender_email); + this.sender = sender_email; + } }); } @@ -237,7 +244,9 @@ frappe.views.CommunicationComposer = class { // some email clients (outlook) may not send the message id to identify // the thread. So as a backup we use the name of the document as identifier const identifier = `#${this.frm.doc.name}`; - if (!this.subject.includes(identifier)) { + + // converting to str for int names + if (!cstr(this.subject).includes(identifier)) { this.subject = `${this.subject} (${identifier})`; } } @@ -349,7 +358,7 @@ frappe.views.CommunicationComposer = class { } async set_values_from_last_edited_communication() { - if (this.txt || this.message) return; + if (this.message) return; const last_edited = this.get_last_edited_communication(); if (!last_edited.content) return; @@ -708,10 +717,10 @@ frappe.views.CommunicationComposer = class { } } - async set_content() { + async set_content(sender_email) { if (this.content_set) return; - let message = this.txt || this.message || ""; + let message = this.message || ""; if (!message && this.frm) { const { doctype, docname } = this.frm; message = await localforage.getItem(doctype + docname) || ""; @@ -721,7 +730,7 @@ frappe.views.CommunicationComposer = class { this.content_set = true; } - message += await this.get_signature(); + message += await this.get_signature(sender_email || null); const SALUTATION_END_COMMENT = ""; if (this.real_name && !message.includes(SALUTATION_END_COMMENT)) { @@ -732,20 +741,30 @@ frappe.views.CommunicationComposer = class { `; } - if (this.is_a_reply) { + if (this.is_a_reply && !this.reply_set) { message += this.get_earlier_reply(); } await this.dialog.set_value("content", message); } - async get_signature() { + async get_signature(sender_email) { let signature = frappe.boot.user.email_signature; if (!signature) { + let filters = {}; + if (sender_email) { + filters['email_id'] = sender_email; + } else { + if (this.dialog.has_field("sender")) return ""; + + filters['default_outgoing'] = 1; + } + filters['add_signature'] = 1; + const response = await frappe.db.get_value( 'Email Account', - {'default_outgoing': 1, 'add_signature': 1}, + filters, 'signature' ); @@ -762,6 +781,8 @@ frappe.views.CommunicationComposer = class { } get_earlier_reply() { + this.reply_set = false; + const last_email = ( this.last_email || this.frm && this.frm.timeline.get_last_email(true) @@ -785,6 +806,8 @@ frappe.views.CommunicationComposer = class { last_email.communication_date || last_email.creation ); + this.reply_set = true; + return `

${separator_element || ''} From 3b6a50b2ab1a7bca4c0d8b9b571c0d32c61908f6 Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Thu, 7 Apr 2022 12:57:11 +0530 Subject: [PATCH 2/6] fix: added add signature button if multiple sender emails available (cherry picked from commit 0a1595e94e5bd1af7c44bcf4fbd45f3d14438100) --- .../public/js/frappe/views/communication.js | 57 ++++++++++++------- 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/frappe/public/js/frappe/views/communication.js b/frappe/public/js/frappe/views/communication.js index 25ee79c86d57..c74cb3183ce0 100755 --- a/frappe/public/js/frappe/views/communication.js +++ b/frappe/public/js/frappe/views/communication.js @@ -98,6 +98,17 @@ frappe.views.CommunicationComposer = class { 500 ) }, + { + fieldtype: "Button", + label: __("Add Signature"), + fieldname: 'add_signature', + hidden: 1, + click: async () => { + let sender_email = this.dialog.get_value('sender') || ""; + this.content_set = false; + await this.set_content(sender_email); + } + }, { fieldtype: "Section Break" }, { label: __("Send me a copy"), @@ -144,21 +155,16 @@ frappe.views.CommunicationComposer = class { }); if (email_accounts.length) { + this.user_email_accounts = email_accounts.map(function(e) { + return e.email_id; + }); + fields.unshift({ label: __("From"), fieldtype: "Select", reqd: 1, fieldname: "sender", - options: email_accounts.map(function(e) { - return e.email_id; - }), - change: async () => { - let sender_email = this.dialog.get_value("sender"); - this.reply_set = !!sender_email; - this.content_set = sender_email && this.sender && this.sender != sender_email; - await this.set_content(sender_email); - this.sender = sender_email; - } + options: this.user_email_accounts }); } @@ -182,9 +188,15 @@ frappe.views.CommunicationComposer = class { this.setup_email(); this.setup_email_template(); this.setup_last_edited_communication(); + this.setup_add_signature_button(); this.set_values(); } + setup_add_signature_button() { + let is_sender = this.dialog.has_field('sender'); + this.dialog.set_df_property('add_signature', 'hidden', !is_sender); + } + setup_multiselect_queries() { ['recipients', 'cc', 'bcc'].forEach(field => { this.dialog.fields_dict[field].get_data = () => { @@ -752,23 +764,28 @@ frappe.views.CommunicationComposer = class { let signature = frappe.boot.user.email_signature; if (!signature) { - let filters = {}; + let filters = { + 'add_signature': 1 + }; + if (sender_email) { filters['email_id'] = sender_email; } else { - if (this.dialog.has_field("sender")) return ""; - filters['default_outgoing'] = 1; } - filters['add_signature'] = 1; - const response = await frappe.db.get_value( - 'Email Account', - filters, - 'signature' - ); + const email = await frappe.db.get_list("Email Account", { + filters: filters, + fields: ['signature', 'email_id'], + limit: 1 + }); - signature = response.message.signature; + signature = email && email[0].signature; + + if (this.user_email_accounts && + this.user_email_accounts.includes(email[0].email_id)) { + this.dialog.set_value('sender', email[0].email_id); + } } if (!signature) return ""; From 0e0eb008368271b460580f269491df494be11899 Mon Sep 17 00:00:00 2001 From: Shariq Ansari Date: Mon, 11 Apr 2022 13:07:52 +0530 Subject: [PATCH 3/6] style: Added gap between from and to field (cherry picked from commit 1e63475b2ae6bfced2a473f7554f8963b2b43681) --- frappe/public/scss/common/modal.scss | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/frappe/public/scss/common/modal.scss b/frappe/public/scss/common/modal.scss index 44510b4b4328..b6208e6e2f6b 100644 --- a/frappe/public/scss/common/modal.scss +++ b/frappe/public/scss/common/modal.scss @@ -210,16 +210,22 @@ body.modal-open[style^="padding-right"] { form { display: flex; align-items: center; - .frappe-control:first-child { - flex: 1; - margin-bottom: 0px; - } - .frappe-control:last-child { - margin-left: 10px; - margin-bottom: -24px; - button { - // same as form-control input - height: calc(1.5em + .75rem + 2px); + + .frappe-control { + &[data-fieldname="sender"] { + flex: 1; + margin-bottom: 0px; + } + &[data-fieldname="recipients"] { + margin-left: 10px; + } + &[data-fieldname="option_toggle_button"] { + margin-left: 10px; + margin-bottom: -24px; + button { + // same as form-control input + height: calc(1.5em + .75rem + 2px); + } } } } From f3277067c92da3b6f58adee2bd032fce70e874ab Mon Sep 17 00:00:00 2001 From: Shariq Ansari <30859809+shariquerik@users.noreply.github.com> Date: Mon, 11 Apr 2022 13:53:40 +0530 Subject: [PATCH 4/6] fix: resolved conflicts --- frappe/public/js/frappe/ui/field_group.js | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/frappe/public/js/frappe/ui/field_group.js b/frappe/public/js/frappe/ui/field_group.js index db03bf0a6a04..5aa590d281be 100644 --- a/frappe/public/js/frappe/ui/field_group.js +++ b/frappe/public/js/frappe/ui/field_group.js @@ -129,18 +129,11 @@ frappe.ui.FieldGroup = frappe.ui.form.Layout.extend({ resolve(); } }); -<<<<<<< HEAD }, - set_input: function(key, val) { -======= - } - - has_field(fieldname) { + has_field: function(fieldname) { return !!this.fields_dict[fieldname]; - } - - set_input(key, val) { ->>>>>>> b9af0ac37e (feat(minor): use specific email signature via from field) + }, + set_input: function(key, val) { return this.set_value(key, val); }, set_values: function(dict) { From 7feafd9eecc51f10d43cd2539119e543492c1b87 Mon Sep 17 00:00:00 2001 From: Shariq Ansari <30859809+shariquerik@users.noreply.github.com> Date: Mon, 11 Apr 2022 14:05:58 +0530 Subject: [PATCH 5/6] fix: reverting arrow function to normal function --- frappe/public/js/frappe/views/communication.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/public/js/frappe/views/communication.js b/frappe/public/js/frappe/views/communication.js index c74cb3183ce0..38fbcc95a752 100755 --- a/frappe/public/js/frappe/views/communication.js +++ b/frappe/public/js/frappe/views/communication.js @@ -103,7 +103,7 @@ frappe.views.CommunicationComposer = class { label: __("Add Signature"), fieldname: 'add_signature', hidden: 1, - click: async () => { + click: async function() { let sender_email = this.dialog.get_value('sender') || ""; this.content_set = false; await this.set_content(sender_email); From e31395ef327e9d2f8f087f49a3351ee6a3c16fbe Mon Sep 17 00:00:00 2001 From: fproldan Date: Fri, 10 Jan 2025 13:20:00 +0000 Subject: [PATCH 6/6] fix --- .../public/js/frappe/views/communication.js | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/frappe/public/js/frappe/views/communication.js b/frappe/public/js/frappe/views/communication.js index 38fbcc95a752..b6dd4cac263a 100755 --- a/frappe/public/js/frappe/views/communication.js +++ b/frappe/public/js/frappe/views/communication.js @@ -34,7 +34,7 @@ frappe.views.CommunicationComposer = class { minimizable: true }); - this.dialog.sections[0].wrapper.addClass('to_section'); + $(this.dialog.$wrapper.find(".form-section").get(0)).addClass('to_section'); this.prepare(); this.dialog.show(); @@ -95,7 +95,7 @@ frappe.views.CommunicationComposer = class { fieldname: "content", onchange: frappe.utils.debounce( this.save_as_draft.bind(this), - 500 + 300 ) }, { @@ -103,11 +103,11 @@ frappe.views.CommunicationComposer = class { label: __("Add Signature"), fieldname: 'add_signature', hidden: 1, - click: async function() { + click: async function () { let sender_email = this.dialog.get_value('sender') || ""; this.content_set = false; await this.set_content(sender_email); - } + }.bind(this) }, { fieldtype: "Section Break" }, { @@ -166,6 +166,10 @@ frappe.views.CommunicationComposer = class { fieldname: "sender", options: this.user_email_accounts }); + //Preselect email senders if there is only one + if (this.user_email_accounts.length==1) { + this['sender'] = this.user_email_accounts + } } return fields; @@ -193,8 +197,8 @@ frappe.views.CommunicationComposer = class { } setup_add_signature_button() { - let is_sender = this.dialog.has_field('sender'); - this.dialog.set_df_property('add_signature', 'hidden', !is_sender); + let has_sender = this.dialog.has_field('sender'); + this.dialog.set_df_property('add_signature', 'hidden', !has_sender); } setup_multiselect_queries() { @@ -282,7 +286,6 @@ frappe.views.CommunicationComposer = class { const subject_field = me.dialog.fields_dict.subject; let content = content_field.get_value() || ""; - content = content.split('')[1] || content; content_field.set_value(`${reply.message}
${content}`); subject_field.set_value(reply.subject); @@ -744,15 +747,6 @@ frappe.views.CommunicationComposer = class { message += await this.get_signature(sender_email || null); - const SALUTATION_END_COMMENT = ""; - if (this.real_name && !message.includes(SALUTATION_END_COMMENT)) { - message = ` -

${__('Dear {0},', [this.real_name], 'Salutation in new email')},

- ${SALUTATION_END_COMMENT}
- ${message} - `; - } - if (this.is_a_reply && !this.reply_set) { message += this.get_earlier_reply(); } @@ -774,17 +768,23 @@ frappe.views.CommunicationComposer = class { filters['default_outgoing'] = 1; } - const email = await frappe.db.get_list("Email Account", { + const email_accounts = await frappe.db.get_list("Email Account", { filters: filters, fields: ['signature', 'email_id'], limit: 1 }); - signature = email && email[0].signature; + let filtered_email = null; + if (email_accounts.length) { + signature = email_accounts[0].signature; + filtered_email = email_accounts[0].email_id; + } - if (this.user_email_accounts && - this.user_email_accounts.includes(email[0].email_id)) { - this.dialog.set_value('sender', email[0].email_id); + if (!sender_email && filtered_email) { + if (this.user_email_accounts && + this.user_email_accounts.includes(filtered_email)) { + this.dialog.set_value('sender', filtered_email); + } } } @@ -794,7 +794,7 @@ frappe.views.CommunicationComposer = class { signature = signature.replace(/\n/g, "
"); } - return "
" + signature; + return "
" + signature; } get_earlier_reply() { @@ -839,12 +839,12 @@ frappe.views.CommunicationComposer = class { html2text(html) { // convert HTML to text and try and preserve whitespace - const d = document.createElement( 'div' ); - d.innerHTML = html.replace(/<\/div>/g, '
') // replace end of blocks - .replace(/<\/p>/g, '

') // replace end of paragraphs - .replace(/
/g, '\n'); + html = html + .replace(/<\/div>/g, "
") // replace end of blocks + .replace(/<\/p>/g, "

") // replace end of paragraphs + .replace(/
/g, "\n"); - // replace multiple empty lines with just one - return d.textContent.replace(/\n{3,}/g, '\n\n'); + const text = frappe.utils.html2text(html); + return text.replace(/\n{3,}/g, "\n\n"); } -}; +}; \ No newline at end of file