diff --git a/frappe/core/doctype/communication/communication.js b/frappe/core/doctype/communication/communication.js index 1c51319790..cdbdf97852 100644 --- a/frappe/core/doctype/communication/communication.js +++ b/frappe/core/doctype/communication/communication.js @@ -37,13 +37,11 @@ frappe.ui.form.on("Communication", { if(frm.doc.status==="Open") { frm.add_custom_button(__("Close"), function() { - frm.set_value("status", "Closed"); - frm.save(); + frm.trigger('mark_as_closed_open'); }); } else if (frm.doc.status !== "Linked") { frm.add_custom_button(__("Reopen"), function() { - frm.set_value("status", "Open"); - frm.save(); + frm.trigger('mark_as_closed_open'); }); } @@ -61,30 +59,34 @@ frappe.ui.form.on("Communication", { frm.add_custom_button(__("Reply All"), function() { frm.trigger('reply_all'); - }, "Actions"); + }, __("Actions")); frm.add_custom_button(__("Forward"), function() { frm.trigger('forward_mail'); - }, "Actions"); + }, __("Actions")); - frm.add_custom_button(__("Mark as {0}", [frm.doc.seen? "Unread": "Read"]), function() { + frm.add_custom_button(frm.doc.seen ? __("Mark as Unread") : __("Mark as Read"), function() { frm.trigger('mark_as_read_unread'); - }, "Actions"); + }, __("Actions")); - frm.add_custom_button(__("Add Contact"), function() { - frm.trigger('add_to_contact'); - }, "Actions"); + frm.add_custom_button(__("Move"), function() { + frm.trigger('show_move_dialog'); + }, __("Actions")); if(frm.doc.email_status != "Spam") frm.add_custom_button(__("Mark as Spam"), function() { frm.trigger('mark_as_spam'); - }, "Actions"); + }, __("Actions")); if(frm.doc.email_status != "Trash") { frm.add_custom_button(__("Move To Trash"), function() { frm.trigger('move_to_trash'); - }, "Actions"); + }, __("Actions")); } + + frm.add_custom_button(__("Contact"), function() { + frm.trigger('add_to_contact'); + }, __('Create')); } if(frm.doc.communication_type=="Communication" @@ -93,7 +95,7 @@ frappe.ui.form.on("Communication", { frm.add_custom_button(__("Add Contact"), function() { frm.trigger('add_to_contact'); - }, "Actions"); + }, __("Actions")); } }, @@ -145,6 +147,43 @@ frappe.ui.form.on("Communication", { d.show(); }, + show_move_dialog: function(frm) { + var d = new frappe.ui.Dialog ({ + title: __("Move"), + fields: [{ + "fieldtype": "Link", + "options": "Email Account", + "label": __("Email Account"), + "fieldname": "email_account", + "reqd": 1, + "get_query": function() { + return { + "filters": { + "name": ["!=", frm.doc.email_account], + "enable_incoming": ["=", 1] + } + }; + } + }], + primary_action_label: __("Move"), + primary_action(values) { + d.hide(); + frappe.call({ + method: "frappe.email.inbox.move_email", + args: { + communication: frm.doc.name, + email_account: values.email_account + }, + freeze: true, + callback: function() { + window.history.back(); + } + }); + } + }); + d.show(); + }, + mark_as_read_unread: function(frm) { var action = frm.doc.seen? "Unread": "Read"; var flag = "(\\SEEN)"; @@ -156,7 +195,26 @@ frappe.ui.form.on("Communication", { 'action': action, 'flag': flag }, - freeze: true + freeze: true, + callback: function() { + frm.reload_doc(); + } + }); + }, + + mark_as_closed_open: function(frm) { + var status = frm.doc.status == "Open" ? "Closed" : "Open"; + + return frappe.call({ + method: "frappe.email.inbox.mark_as_closed_open", + args: { + communication: frm.doc.name, + status: status + }, + freeze: true, + callback: function() { + frm.reload_doc(); + } }); }, diff --git a/frappe/core/doctype/communication/communication.json b/frappe/core/doctype/communication/communication.json index ae6fb164ec..58adc6187c 100644 --- a/frappe/core/doctype/communication/communication.json +++ b/frappe/core/doctype/communication/communication.json @@ -197,6 +197,7 @@ "label": "More Information" }, { + "bold": 0, "default": "Now", "fieldname": "communication_date", "fieldtype": "Datetime", @@ -424,6 +425,15 @@ "share": 1, "write": 1 }, + { + "create": 1, + "delete": 1, + "email": 1, + "export":1, + "print":1, + "read": 1, + "role": "Inbox User" + }, { "delete": 1, "email": 1, diff --git a/frappe/core/doctype/communication/communication_list.js b/frappe/core/doctype/communication/communication_list.js index 67d4855c1f..454897b865 100644 --- a/frappe/core/doctype/communication/communication_list.js +++ b/frappe/core/doctype/communication/communication_list.js @@ -3,7 +3,7 @@ frappe.listview_settings['Communication'] = { "sent_or_received","recipients", "subject", "communication_medium", "communication_type", "sender", "seen", "reference_doctype", "reference_name", - "has_attachment" + "has_attachment", "communication_date" ], filters: [["status", "=", "Open"]], diff --git a/frappe/email/doctype/email_account/email_account.json b/frappe/email/doctype/email_account/email_account.json index 5c57a7f35d..6bde0291a0 100644 --- a/frappe/email/doctype/email_account/email_account.json +++ b/frappe/email/doctype/email_account/email_account.json @@ -65,6 +65,7 @@ "fieldname": "email_id", "fieldtype": "Data", "in_global_search": 1, + "in_list_view": 1, "label": "Email Address", "options": "Email", "reqd": 1 @@ -90,14 +91,12 @@ "default": "0", "fieldname": "awaiting_password", "fieldtype": "Check", - "in_list_view": 1, "label": "Awaiting password" }, { "default": "0", "fieldname": "ascii_encode_password", "fieldtype": "Check", - "in_list_view": 1, "label": "Use ASCII encoding for password" }, { @@ -116,6 +115,8 @@ "fieldname": "domain", "fieldtype": "Link", "label": "Domain", + "in_list_view": 1, + "in_standard_filter": 1, "options": "Email Domain" }, { @@ -424,6 +425,10 @@ "role": "System Manager", "set_user_permissions": 1, "write": 1 + }, + { + "read": 1, + "role": "Inbox User" } ], "sort_field": "modified", diff --git a/frappe/email/inbox.py b/frappe/email/inbox.py index 9d15b387e3..395a2d3e2d 100644 --- a/frappe/email/inbox.py +++ b/frappe/email/inbox.py @@ -96,14 +96,24 @@ def create_email_flag_queue(names, action): update_modified=False) mark_as_seen_unseen(name, action) +@frappe.whitelist() +def mark_as_closed_open(communication, status): + """Set status to open or close""" + frappe.db.set_value("Communication", communication, "status", status) + +@frappe.whitelist() +def move_email(communication, email_account): + """Move email to another email account.""" + frappe.db.set_value("Communication", communication, "email_account", email_account) + @frappe.whitelist() def mark_as_trash(communication): - """set email status to trash""" + """Set email status to trash.""" frappe.db.set_value("Communication", communication, "email_status", "Trash") @frappe.whitelist() def mark_as_spam(communication, sender): - """ set email status to spam """ + """Set email status to spam.""" email_rule = frappe.db.get_value("Email Rule", { "email_id": sender }) if not email_rule: frappe.get_doc({ @@ -118,4 +128,4 @@ def link_communication_to_document(doc, reference_doctype, reference_name, ignor doc.reference_doctype = reference_doctype doc.reference_name = reference_name doc.status = "Linked" - doc.save(ignore_permissions=True) \ No newline at end of file + doc.save(ignore_permissions=True) diff --git a/frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.json b/frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.json index bbdbf74a67..830afbae53 100755 --- a/frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.json +++ b/frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.json @@ -1,18 +1,28 @@ { + "actions": [], "creation": "2017-09-04 20:57:20.129205", "doctype": "DocType", "editable_grid": 1, "engine": "InnoDB", "field_order": [ "enabled", - "notify_email", - "send_email_for_successful_backup", - "frequency", + "api_access_section", "access_key_id", + "column_break_4", "secret_access_key", - "region", - "endpoint_url", + "notification_section", + "notify_email", + "column_break_8", + "send_email_for_successful_backup", + "s3_bucket_details_section", "bucket", + "endpoint_url", + "column_break_13", + "region", + "backup_details_section", + "frequency", + "backup_files", + "column_break_18", "backup_limit" ], "fields": [ @@ -27,6 +37,7 @@ "fieldtype": "Data", "in_list_view": 1, "label": "Send Notifications To", + "mandatory_depends_on": "enabled", "reqd": 1 }, { @@ -41,6 +52,7 @@ "fieldtype": "Select", "in_list_view": 1, "label": "Backup Frequency", + "mandatory_depends_on": "enabled", "options": "Daily\nWeekly\nMonthly\nNone", "reqd": 1 }, @@ -49,13 +61,15 @@ "fieldtype": "Data", "in_list_view": 1, "label": "Access Key ID", + "mandatory_depends_on": "enabled", "reqd": 1 }, { "fieldname": "secret_access_key", "fieldtype": "Password", "in_list_view": 1, - "label": "Secret Access Key", + "label": "Access Key Secret", + "mandatory_depends_on": "enabled", "reqd": 1 }, { @@ -74,19 +88,70 @@ { "fieldname": "bucket", "fieldtype": "Data", - "label": "Bucket", + "label": "Bucket Name", + "mandatory_depends_on": "enabled", "reqd": 1 }, { + "description": "Set to 0 for no limit on the number of backups taken", "fieldname": "backup_limit", "fieldtype": "Int", "label": "Backup Limit", + "mandatory_depends_on": "enabled", "reqd": 1 + }, + { + "depends_on": "enabled", + "fieldname": "api_access_section", + "fieldtype": "Section Break", + "label": "API Access" + }, + { + "fieldname": "column_break_4", + "fieldtype": "Column Break" + }, + { + "depends_on": "enabled", + "fieldname": "notification_section", + "fieldtype": "Section Break", + "label": "Notification" + }, + { + "fieldname": "column_break_8", + "fieldtype": "Column Break" + }, + { + "depends_on": "enabled", + "fieldname": "s3_bucket_details_section", + "fieldtype": "Section Break", + "label": "S3 Bucket Details" + }, + { + "fieldname": "column_break_13", + "fieldtype": "Column Break" + }, + { + "depends_on": "enabled", + "fieldname": "backup_details_section", + "fieldtype": "Section Break", + "label": "Backup Details" + }, + { + "default": "1", + "description": "Backup public and private files along with the database.", + "fieldname": "backup_files", + "fieldtype": "Check", + "label": "Backup Files" + }, + { + "fieldname": "column_break_18", + "fieldtype": "Column Break" } ], "hide_toolbar": 1, "issingle": 1, - "modified": "2019-08-22 16:26:04.774571", + "links": [], + "modified": "2020-04-13 20:57:24.432183", "modified_by": "Administrator", "module": "Integrations", "name": "S3 Backup Settings", diff --git a/frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.py b/frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.py index 7e69da922c..21232992f4 100755 --- a/frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.py +++ b/frappe/integrations/doctype/s3_backup_settings/s3_backup_settings.py @@ -102,6 +102,7 @@ def backup_to_s3(): doc = frappe.get_single("S3 Backup Settings") bucket = doc.bucket + backup_files = cint(doc.backup_files) conn = boto3.client( 's3', @@ -114,17 +115,22 @@ def backup_to_s3(): backup = new_backup(ignore_files=False, backup_path_db=None, backup_path_files=None, backup_path_private_files=None, force=True) db_filename = os.path.join(get_backups_path(), os.path.basename(backup.backup_path_db)) - files_filename = os.path.join(get_backups_path(), os.path.basename(backup.backup_path_files)) - private_files = os.path.join(get_backups_path(), os.path.basename(backup.backup_path_private_files)) + if backup_files: + files_filename = os.path.join(get_backups_path(), os.path.basename(backup.backup_path_files)) + private_files = os.path.join(get_backups_path(), os.path.basename(backup.backup_path_private_files)) else: - db_filename, files_filename, private_files = get_latest_backup_file(with_files=True) + if backup_files: + db_filename, files_filename, private_files = get_latest_backup_file(with_files=backup_files) + else: + db_filename = get_latest_backup_file() folder = os.path.basename(db_filename)[:15] + '/' # for adding datetime to folder name upload_file_to_s3(db_filename, folder, conn, bucket) - upload_file_to_s3(private_files, folder, conn, bucket) - upload_file_to_s3(files_filename, folder, conn, bucket) + if backup_files: + upload_file_to_s3(private_files, folder, conn, bucket) + upload_file_to_s3(files_filename, folder, conn, bucket) delete_old_backups(doc.backup_limit, bucket) diff --git a/frappe/public/js/frappe/list/list_sidebar.js b/frappe/public/js/frappe/list/list_sidebar.js index e3ba08a87c..0c7312d537 100644 --- a/frappe/public/js/frappe/list/list_sidebar.js +++ b/frappe/public/js/frappe/list/list_sidebar.js @@ -209,11 +209,13 @@ frappe.views.ListSidebar = class ListSidebar { accounts.forEach((account) => { let email_account = (account.email_id == "All Accounts") ? "All Accounts" : account.email_account; let route = ["List", "Communication", "Inbox", email_account].join('/'); + let display_name = ["All Accounts", "Sent Mail", "Spam", "Trash"].includes(account.email_id) ? __(account.email_id) : account.email_id; + if (!divider) { this.get_divider().appendTo($dropdown); divider = true; } - $(`
  • ${account.email_id}
  • `).appendTo($dropdown); + $(`
  • ${display_name}
  • `).appendTo($dropdown); if (account.email_id === "Sent Mail") divider = false; }); diff --git a/frappe/public/js/frappe/views/inbox/inbox_view.js b/frappe/public/js/frappe/views/inbox/inbox_view.js index 2b35d38683..f80b07751e 100644 --- a/frappe/public/js/frappe/views/inbox/inbox_view.js +++ b/frappe/public/js/frappe/views/inbox/inbox_view.js @@ -40,62 +40,53 @@ frappe.views.InboxView = class InboxView extends frappe.views.ListView { setup_defaults() { super.setup_defaults(); + + // initialize with saved order by + this.sort_by = this.view_user_settings.sort_by || 'communication_date'; + this.sort_order = this.view_user_settings.sort_order || 'desc'; + this.email_account = frappe.get_route()[3]; this.page_title = this.email_account; this.filters = this.get_inbox_filters(); } + setup_columns() { + // setup columns for list view + this.columns = []; + this.columns.push({ + type: 'Subject', + df: { + label: __('Subject'), + fieldname: 'subject' + } + }); + this.columns.push({ + type: 'Field', + df: { + label: this.is_sent_emails ? __("To") : __("From"), + fieldname: this.is_sent_emails ? 'recipients' : 'sender' + } + }); + } + get is_sent_emails() { const f = this.filter_area.get() .find(filter => filter[1] === 'sent_or_received'); return f && f[3] === 'Sent'; } + render_header() { + this.$result.find('.list-row-head').remove(); + this.$result.prepend(this.get_header_html()); + } + render() { - this.emails = this.data; - this.render_inbox_view(); - } - - render_inbox_view() { - let html = this.emails.map(this.render_email_row.bind(this)).join(""); - - this.$result.html(` - ${this.get_header_html()} - ${html} - `); - } - - get_header_html() { - return this.get_header_html_skeleton(` -
    - - ${__('Subject')} -
    - - `); - } - - render_email_row(email) { - if (!email.css_seen && email.seen) - email.css_seen = "seen"; - - const columns_html = ` -
    - - - - ${email.subject} - - -
    - - `; - - return this.get_list_row_html_skeleton(columns_html, this.get_meta_html(email)); + this.setup_columns(); + this.render_header(); + this.render_list(); + this.on_row_checked(); + this.render_count(); + this.render_tags(); } get_meta_html(email) { @@ -109,13 +100,18 @@ frappe.views.InboxView = class InboxView extends frappe.views.ListView { ` : ''; - const modified = comment_when(email.modified, true); + const communication_date = comment_when(email.communication_date, true); + const status = + email.status == "Closed" ? `` : + email.status == "Replied" ? `` : + ""; return ` -