@@ -14,7 +14,7 @@ import os, sys, importlib, inspect, json | |||||
from .exceptions import * | from .exceptions import * | ||||
from .utils.jinja import get_jenv, get_template, render_template, get_email_from_template | from .utils.jinja import get_jenv, get_template, render_template, get_email_from_template | ||||
__version__ = '8.10.8' | |||||
__version__ = '8.10.9' | |||||
__title__ = "Frappe Framework" | __title__ = "Frappe Framework" | ||||
local = Local() | local = Local() | ||||
@@ -26,17 +26,16 @@ class Communication(Document): | |||||
if self.communication_type == "Communication" and self.communication_medium == "Email" \ | if self.communication_type == "Communication" and self.communication_medium == "Email" \ | ||||
and self.sent_or_received == "Received" and self.uid and self.uid != -1: | and self.sent_or_received == "Received" and self.uid and self.uid != -1: | ||||
flag = frappe.db.get_value("Email Flag Queue", { | |||||
email_flag_queue = frappe.db.get_value("Email Flag Queue", { | |||||
"communication": self.name, | "communication": self.name, | ||||
"is_completed": 0}) | "is_completed": 0}) | ||||
if flag: | |||||
if email_flag_queue: | |||||
return | return | ||||
frappe.get_doc({ | frappe.get_doc({ | ||||
"doctype": "Email Flag Queue", | "doctype": "Email Flag Queue", | ||||
"action": "Read", | "action": "Read", | ||||
"communication": self.name, | "communication": self.name, | ||||
"flag": "(\\SEEN)", | |||||
"uid": self.uid, | "uid": self.uid, | ||||
"email_account": self.email_account | "email_account": self.email_account | ||||
}).insert(ignore_permissions=True) | }).insert(ignore_permissions=True) | ||||
@@ -9,13 +9,13 @@ frappe.listview_settings['Communication'] = { | |||||
filters: [["status", "=", "Open"]], | filters: [["status", "=", "Open"]], | ||||
onload: function(list_view) { | onload: function(list_view) { | ||||
var method = "frappe.email.inbox.create_email_flag_queue" | |||||
let method = "frappe.email.inbox.create_email_flag_queue" | |||||
list_view.page.add_menu_item(__("Mark as Read"), function() { | list_view.page.add_menu_item(__("Mark as Read"), function() { | ||||
list_view.call_for_selected_items(method, { action: "Read" }) | |||||
list_view.call_for_selected_items(method, { action: "Read" }); | |||||
}); | }); | ||||
list_view.page.add_menu_item(__("Mark as Unread"), function() { | list_view.page.add_menu_item(__("Mark as Unread"), function() { | ||||
list_view.call_for_selected_items(method, { action: "Unread" }) | |||||
list_view.call_for_selected_items(method, { action: "Unread" }); | |||||
}); | }); | ||||
}, | }, | ||||
@@ -289,6 +289,9 @@ def set_incoming_outgoing_accounts(doc): | |||||
{"default_outgoing": 1, "enable_outgoing": 1}, | {"default_outgoing": 1, "enable_outgoing": 1}, | ||||
["email_id", "always_use_account_email_id_as_sender", "name", "send_unsubscribe_message"], as_dict=True) or frappe._dict() | ["email_id", "always_use_account_email_id_as_sender", "name", "send_unsubscribe_message"], as_dict=True) or frappe._dict() | ||||
if doc.sent_or_received == "Sent": | |||||
doc.db_set("email_account", doc.outgoing_email_account.name) | |||||
def get_recipients(doc, fetched_from_email_account=False): | def get_recipients(doc, fetched_from_email_account=False): | ||||
"""Build a list of email addresses for To""" | """Build a list of email addresses for To""" | ||||
# [EDGE CASE] doc.recipients can be None when an email is sent as BCC | # [EDGE CASE] doc.recipients can be None when an email is sent as BCC | ||||
@@ -12,6 +12,7 @@ | |||||
"editable_grid": 0, | "editable_grid": 0, | ||||
"fields": [ | "fields": [ | ||||
{ | { | ||||
"allow_bulk_edit": 0, | |||||
"allow_on_submit": 0, | "allow_on_submit": 0, | ||||
"bold": 0, | "bold": 0, | ||||
"collapsible": 0, | "collapsible": 0, | ||||
@@ -41,6 +42,7 @@ | |||||
"unique": 0 | "unique": 0 | ||||
}, | }, | ||||
{ | { | ||||
"allow_bulk_edit": 0, | |||||
"allow_on_submit": 0, | "allow_on_submit": 0, | ||||
"bold": 0, | "bold": 0, | ||||
"collapsible": 0, | "collapsible": 0, | ||||
@@ -71,6 +73,7 @@ | |||||
"unique": 0 | "unique": 0 | ||||
}, | }, | ||||
{ | { | ||||
"allow_bulk_edit": 0, | |||||
"allow_on_submit": 0, | "allow_on_submit": 0, | ||||
"bold": 0, | "bold": 0, | ||||
"collapsible": 0, | "collapsible": 0, | ||||
@@ -101,35 +104,7 @@ | |||||
"unique": 0 | "unique": 0 | ||||
}, | }, | ||||
{ | { | ||||
"allow_on_submit": 0, | |||||
"bold": 0, | |||||
"collapsible": 0, | |||||
"columns": 0, | |||||
"fieldname": "flag", | |||||
"fieldtype": "Data", | |||||
"hidden": 0, | |||||
"ignore_user_permissions": 0, | |||||
"ignore_xss_filter": 0, | |||||
"in_filter": 0, | |||||
"in_global_search": 0, | |||||
"in_list_view": 0, | |||||
"in_standard_filter": 0, | |||||
"label": "Flag", | |||||
"length": 0, | |||||
"no_copy": 0, | |||||
"permlevel": 0, | |||||
"precision": "", | |||||
"print_hide": 0, | |||||
"print_hide_if_no_value": 0, | |||||
"read_only": 0, | |||||
"remember_last_selected_value": 0, | |||||
"report_hide": 0, | |||||
"reqd": 0, | |||||
"search_index": 0, | |||||
"set_only_once": 0, | |||||
"unique": 0 | |||||
}, | |||||
{ | |||||
"allow_bulk_edit": 0, | |||||
"allow_on_submit": 0, | "allow_on_submit": 0, | ||||
"bold": 0, | "bold": 0, | ||||
"collapsible": 0, | "collapsible": 0, | ||||
@@ -159,6 +134,7 @@ | |||||
"unique": 0 | "unique": 0 | ||||
}, | }, | ||||
{ | { | ||||
"allow_bulk_edit": 0, | |||||
"allow_on_submit": 0, | "allow_on_submit": 0, | ||||
"bold": 0, | "bold": 0, | ||||
"collapsible": 0, | "collapsible": 0, | ||||
@@ -198,7 +174,7 @@ | |||||
"issingle": 0, | "issingle": 0, | ||||
"istable": 0, | "istable": 0, | ||||
"max_attachments": 0, | "max_attachments": 0, | ||||
"modified": "2017-03-15 13:09:28.002266", | |||||
"modified": "2017-09-20 15:27:12.142079", | |||||
"modified_by": "Administrator", | "modified_by": "Administrator", | ||||
"module": "Email", | "module": "Email", | ||||
"name": "Email Flag Queue", | "name": "Email Flag Queue", | ||||
@@ -46,48 +46,54 @@ def get_email_accounts(user=None): | |||||
} | } | ||||
@frappe.whitelist() | @frappe.whitelist() | ||||
def create_email_flag_queue(names, action, flag="(\\Seen)"): | |||||
def create_email_flag_queue(names, action): | |||||
""" create email flag queue to mark email either as read or unread """ | """ create email flag queue to mark email either as read or unread """ | ||||
class Found(Exception): | |||||
pass | |||||
if not all([names, action, flag]): | |||||
def mark_as_seen_unseen(name, action): | |||||
doc = frappe.get_doc("Communication", name) | |||||
if action == "Read": | |||||
doc.add_seen() | |||||
else: | |||||
_seen = json.loads(doc._seen or '[]') | |||||
_seen = [user for user in _seen if frappe.session.user != user] | |||||
doc.db_set('_seen', json.dumps(_seen), update_modified=False) | |||||
if not all([names, action]): | |||||
return | return | ||||
for name in json.loads(names or []): | for name in json.loads(names or []): | ||||
uid, seen_status, email_account = frappe.db.get_value("Communication", name, | uid, seen_status, email_account = frappe.db.get_value("Communication", name, | ||||
["ifnull(uid, -1)", "ifnull(seen, 0)", "email_account"]) | ["ifnull(uid, -1)", "ifnull(seen, 0)", "email_account"]) | ||||
# can not mark email SEEN or UNSEEN without uid | |||||
if not uid or uid == -1: | if not uid or uid == -1: | ||||
continue | continue | ||||
seen = 1 if action == "Read" else 0 | seen = 1 if action == "Read" else 0 | ||||
# check if states are correct | # check if states are correct | ||||
if (action =='Read' and seen_status == 0) or (action =='Unread' and seen_status == 1): | if (action =='Read' and seen_status == 0) or (action =='Unread' and seen_status == 1): | ||||
try: | |||||
queue = frappe.db.sql("""select name, action, flag from `tabEmail Flag Queue` | |||||
where communication = %(name)s""", {"name":name}, as_dict=True) | |||||
for q in queue: | |||||
# is same email with same flag | |||||
if q.flag == flag: | |||||
# to prevent flag local and server states being out of sync | |||||
if q.action != action: | |||||
frappe.delete_doc("Email Flag Queue", q.name) | |||||
raise Found | |||||
create_new = True | |||||
email_flag_queue = frappe.db.sql("""select name, action from `tabEmail Flag Queue` | |||||
where communication = %(name)s and is_completed=0""", {"name":name}, as_dict=True) | |||||
for queue in email_flag_queue: | |||||
if queue.action != action: | |||||
frappe.delete_doc("Email Flag Queue", queue.name, ignore_permissions=True) | |||||
elif queue.action == action: | |||||
# Read or Unread request for email is already available | |||||
create_new = False | |||||
if create_new: | |||||
flag_queue = frappe.get_doc({ | flag_queue = frappe.get_doc({ | ||||
"uid": uid, | "uid": uid, | ||||
"flag": flag, | |||||
"action": action, | "action": action, | ||||
"communication": name, | "communication": name, | ||||
"doctype": "Email Flag Queue", | "doctype": "Email Flag Queue", | ||||
"email_account": email_account | "email_account": email_account | ||||
}) | }) | ||||
flag_queue.save(ignore_permissions=True); | |||||
flag_queue.save(ignore_permissions=True) | |||||
frappe.db.set_value("Communication", name, "seen", seen, | frappe.db.set_value("Communication", name, "seen", seen, | ||||
update_modified=False) | update_modified=False) | ||||
except Found: | |||||
pass | |||||
mark_as_seen_unseen(name, action) | |||||
@frappe.whitelist() | @frappe.whitelist() | ||||
def mark_as_trash(communication): | def mark_as_trash(communication): | ||||
@@ -524,7 +524,7 @@ frappe.ui.BaseList = Class.extend({ | |||||
if (me.list_header) { | if (me.list_header) { | ||||
me.list_header.find(".list-select-all").prop("checked", false); | me.list_header.find(".list-select-all").prop("checked", false); | ||||
} | } | ||||
me.refresh(); | |||||
me.refresh(true); | |||||
} | } | ||||
} | } | ||||
}); | }); | ||||
@@ -32,13 +32,13 @@ frappe.ui.FieldGroup = frappe.ui.form.Layout.extend({ | |||||
this.catch_enter_as_submit(); | this.catch_enter_as_submit(); | ||||
} | } | ||||
$(this.body).find('input').on('change', function() { | |||||
me.refresh_dependency(); | |||||
}) | |||||
$(this.body).find('input, select').on('change', function() { | |||||
frappe.run_serially([ | |||||
() => frappe.timeout(0.1), | |||||
() => me.refresh_dependency() | |||||
]); | |||||
}); | |||||
$(this.body).find('select').on("change", function() { | |||||
me.refresh_dependency(); | |||||
}) | |||||
} | } | ||||
}, | }, | ||||
add_fields: function(fields) { | add_fields: function(fields) { | ||||
@@ -361,7 +361,7 @@ frappe.ready(function() { | |||||
} | } | ||||
}); | }); | ||||
} | } | ||||
}) | |||||
}); | |||||
// setup datepicker in all inputs within the given element | // setup datepicker in all inputs within the given element | ||||
var setup_date_picker = function(ele) { | var setup_date_picker = function(ele) { | ||||