diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index 0df3c031ff..ecd59f42bb 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -9,7 +9,7 @@ from datetime import datetime, timedelta from poplib import error_proto import frappe -from frappe import _, are_emails_muted +from frappe import _, are_emails_muted, safe_encode from frappe.desk.form import assign_to from frappe.email.receive import EmailServer, InboundMail, SentEmailInInboxError from frappe.email.smtp import SMTPServer @@ -601,7 +601,6 @@ class EmailAccount(Document): def append_email_to_sent_folder(self, message): - email_server = None try: email_server = self.get_incoming_server(in_receive=True) @@ -615,7 +614,8 @@ class EmailAccount(Document): if email_server.imap: try: - email_server.imap.append("Sent", "\\Seen", imaplib.Time2Internaldate(time.time()), message.encode()) + message = safe_encode(message) + email_server.imap.append("Sent", "\\Seen", imaplib.Time2Internaldate(time.time()), message) except Exception: frappe.log_error() diff --git a/frappe/public/js/frappe/form/controls/text_editor.js b/frappe/public/js/frappe/form/controls/text_editor.js index 059b0f76f8..99e87c5f21 100644 --- a/frappe/public/js/frappe/form/controls/text_editor.js +++ b/frappe/public/js/frappe/form/controls/text_editor.js @@ -1,7 +1,10 @@ import Quill from 'quill'; import ImageResize from 'quill-image-resize'; +import MagicUrl from 'quill-magic-url'; + Quill.register('modules/imageResize', ImageResize); +Quill.register('modules/magicUrl', MagicUrl); const CodeBlockContainer = Quill.import('formats/code-block-container'); CodeBlockContainer.tagName = 'PRE'; Quill.register(CodeBlockContainer, true); @@ -148,7 +151,8 @@ frappe.ui.form.ControlTextEditor = class ControlTextEditor extends frappe.ui.for modules: { toolbar: this.get_toolbar_options(), table: true, - imageResize: {} + imageResize: {}, + magicUrl: true }, theme: 'snow' }; diff --git a/frappe/public/js/frappe/form/grid.js b/frappe/public/js/frappe/form/grid.js index a77791d0a2..ebc3fa19f5 100644 --- a/frappe/public/js/frappe/form/grid.js +++ b/frappe/public/js/frappe/form/grid.js @@ -210,9 +210,9 @@ export default class Grid { delete_all_rows() { frappe.confirm(__("Are you sure you want to delete all rows?"), () => { - this.frm.doc[this.df.fieldname] = []; - $(this.parent).find('.rows').empty(); - this.grid_rows = []; + this.grid_rows.forEach(row => { + row.remove(); + }); this.frm.script_manager.trigger(this.df.fieldname + "_delete", this.doctype); this.wrapper.find('.grid-heading-row .grid-row-check:checked:first').prop('checked', 0); @@ -236,6 +236,10 @@ export default class Grid { } refresh_remove_rows_button() { + if (this.df.cannot_delete_rows) { + return; + } + this.remove_rows_button.toggleClass('hidden', this.wrapper.find('.grid-body .grid-row-check:checked:first').length ? false : true); this.remove_all_rows_button.toggleClass('hidden', diff --git a/frappe/public/js/frappe/form/grid_row.js b/frappe/public/js/frappe/form/grid_row.js index 33db00dede..8c51314066 100644 --- a/frappe/public/js/frappe/form/grid_row.js +++ b/frappe/public/js/frappe/form/grid_row.js @@ -569,6 +569,9 @@ export default class GridRow { .find('.grid-insert-row-below, .grid-insert-row, .grid-duplicate-row, .grid-append-row') .toggle(!cannot_add_rows); + this.wrapper.find('.grid-delete-row') + .toggle(!(this.grid.df && this.grid.df.cannot_delete_rows)); + frappe.dom.freeze("", "dark"); if (cur_frm) cur_frm.cur_grid = this; this.wrapper.addClass("grid-row-open"); diff --git a/frappe/public/js/frappe/ui/page.js b/frappe/public/js/frappe/ui/page.js index c5ef0d0184..22fdf476b8 100644 --- a/frappe/public/js/frappe/ui/page.js +++ b/frappe/public/js/frappe/ui/page.js @@ -377,11 +377,12 @@ frappe.ui.Page = class Page { }); } - add_actions_menu_item(label, click, standard) { + add_actions_menu_item(label, click, standard, shortcut) { return this.add_dropdown_item({ label, click, standard, + shortcut, parent: this.actions, show_parent: false }); diff --git a/package.json b/package.json index 9fff5422ee..8b22a6e92c 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "quagga": "^0.12.1", "quill": "2.0.0-dev.4", "quill-image-resize": "^3.0.9", + "quill-magic-url": "^3.0.0", "qz-tray": "^2.0.8", "redis": "^3.1.1", "showdown": "^1.9.1", diff --git a/yarn.lock b/yarn.lock index 36811dce47..50a7bb165d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4405,6 +4405,11 @@ normalize-url@^4.1.0, normalize-url@^4.5.0: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== +normalize-url@^4.5.0: + version "4.5.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" + integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== + npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" @@ -5451,6 +5456,14 @@ quill-image-resize@^3.0.9: quill "^1.2.2" raw-loader "^0.5.1" +quill-magic-url@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/quill-magic-url/-/quill-magic-url-3.0.2.tgz#84654c749650e006250cbaf905295cb87796f3a7" + integrity sha512-kLPDwjNExGJZyCLGxbaiTFD/OYHagNLRvsdKRV+2d946I8cxaXaB7IT9wbrB49jC8z1X5cwI+pzZzHZeV0orFw== + dependencies: + normalize-url "^4.5.0" + quill-delta "^3.6.2" + quill@2.0.0-dev.4: version "2.0.0-dev.4" resolved "https://registry.yarnpkg.com/quill/-/quill-2.0.0-dev.4.tgz#130e38efe7a16b3766d767d750c8aacc038945e7"