Merge branch 'develop' of https://github.com/frappe/frappe into contextual-translation

This commit is contained in:
Suraj Shetty 2020-05-03 16:01:52 +05:30
commit a2facbd9d3
9 changed files with 235 additions and 82 deletions

View file

@ -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();
}
});
},

View file

@ -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,

View file

@ -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"]],

View file

@ -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",

View file

@ -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)
doc.save(ignore_permissions=True)

View file

@ -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",

View file

@ -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)

View file

@ -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;
}
$(`<li><a href="#${route}">${account.email_id}</a></li>`).appendTo($dropdown);
$(`<li><a href="#${route}">${display_name}</a></li>`).appendTo($dropdown);
if (account.email_id === "Sent Mail")
divider = false;
});

View file

@ -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(`
<div class="list-row-col list-subject level">
<input class="level-item list-check-all hidden-xs" type="checkbox" title="Select All">
<span class="level-item">${__('Subject')}</span>
</div>
<div class="list-row-col hidden-xs">
<span>${this.is_sent_emails ? __("To") : __("From")}</span>
</div>
`);
}
render_email_row(email) {
if (!email.css_seen && email.seen)
email.css_seen = "seen";
const columns_html = `
<div class="list-row-col list-subject level ellipsis">
<input class="level-item list-row-checkbox hidden-xs" type="checkbox" data-name="${email.name}">
<span class="level-item">
<a class="${ email.seen ? '' : 'bold'} ellipsis" href="${this.get_form_link(email)}">
${email.subject}
</a>
</span>
</div>
<div class="list-row-col hidden-xs">
<span>${this.is_sent_emails ? email.recipients : email.sender }</span>
</div>
`;
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 {
<i class="fa fa-link fa-large"></i>
</a>` : '';
const modified = comment_when(email.modified, true);
const communication_date = comment_when(email.communication_date, true);
const status =
email.status == "Closed" ? `<span class="fa fa-check fa-large" title="${__(email.status)}"></span>` :
email.status == "Replied" ? `<span class="fa fa-mail-reply fa-large" title="${__(email.status)}"></span>` :
"";
return `
<div class="level-item hidden-xs list-row-activity">
<div class="level-item list-row-activity">
${link}
${attachment}
${modified}
${status}
${communication_date}
</div>
`;
}
@ -146,6 +142,7 @@ frappe.views.InboxView = class InboxView extends frappe.views.ListView {
filters = default_filters.concat([
["Communication", "sent_or_received", "=", "Received", true],
["Communication", "status", "=", "Open", true],
["Communication", "email_account", op, email_account, true],
["Communication", "email_status", "not in", "Spam,Trash", true],
]);