From 0ab2af171525bbefd947531dc90c6e3726082ffa Mon Sep 17 00:00:00 2001 From: mbauskar Date: Wed, 1 Mar 2017 11:23:13 +0530 Subject: [PATCH] [inbox] js clean ups, other minor fixes in imap --- .../doctype/communication/communication.json | 118 ++--- .../doctype/email_account/email_account.py | 52 ++- .../email_flag_queue/email_flag_queue.json | 61 +-- frappe/email/page/email_inbox/__init__.py | 117 ++--- frappe/email/page/email_inbox/email_inbox.js | 436 ++++++++++-------- .../page/email_inbox/email_inbox_sidebar.html | 19 + frappe/email/page/email_inbox/inbox_list.html | 57 ++- frappe/email/receive.py | 8 +- .../public/js/frappe/list/list_sidebar.html | 12 + 9 files changed, 457 insertions(+), 423 deletions(-) create mode 100644 frappe/email/page/email_inbox/email_inbox_sidebar.html diff --git a/frappe/core/doctype/communication/communication.json b/frappe/core/doctype/communication/communication.json index 7db2631954..96dac2845f 100644 --- a/frappe/core/doctype/communication/communication.json +++ b/frappe/core/doctype/communication/communication.json @@ -633,64 +633,6 @@ "set_only_once": 0, "unique": 0 }, - { - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "uid", - "fieldtype": "Int", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "UID", - "length": 0, - "no_copy": 1, - "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_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "fingerprint", - "fieldtype": "Data", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Fingerprint", - "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_on_submit": 0, "bold": 0, @@ -1315,6 +1257,64 @@ "bold": 0, "collapsible": 1, "columns": 0, + "fieldname": "uid", + "fieldtype": "Int", + "hidden": 1, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "UID", + "length": 0, + "no_copy": 1, + "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_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "fingerprint", + "fieldtype": "Data", + "hidden": 1, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Fingerprint", + "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_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, "fieldname": "feedback_section", "fieldtype": "Section Break", "hidden": 0, @@ -1486,5 +1486,5 @@ "sort_order": "DESC", "title_field": "subject", "track_changes": 1, - "track_seen": 1 + "track_seen": 0 } \ No newline at end of file diff --git a/frappe/email/doctype/email_account/email_account.py b/frappe/email/doctype/email_account/email_account.py index 53ae74fed5..3e9f6d8108 100755 --- a/frappe/email/doctype/email_account/email_account.py +++ b/frappe/email/doctype/email_account/email_account.py @@ -280,7 +280,7 @@ class EmailAccount(Document): #notify if user is linked to account if len(incoming_mails)>0 and not frappe.local.flags.in_test: - frappe.publish_realtime('new_email', {"account":self.email_account_name,"number":len(incoming_mails)}) + frappe.publish_realtime('new_email', {"account":self.email_account_name, "number":len(incoming_mails)}) if exceptions: raise Exception, frappe.as_json(exceptions) @@ -306,14 +306,15 @@ class EmailAccount(Document): frappe.db.commit() def insert_communication(self, msg, args={}): - if isinstance(msg,list): + if isinstance(msg, list): raw, uid, seen = msg else: raw = msg - seen = uid = None + uid = -1 + seen = 0 - if args.get("uid", None): uid = args.get("uid", None) - if args.get("seen", None): seen = args.get("seen", None) + if args.get("uid", -1): uid = args.get("uid", -1) + if args.get("seen", 0): seen = args.get("seen", 0) email = Email(raw) @@ -345,11 +346,11 @@ class EmailAccount(Document): "cc": email.mail.get("CC"), "email_account": self.name, "communication_medium": "Email", - "uid": uid, + "uid": int(uid or -1), "message_id": email.message_id, "communication_date": email.date, "has_attachment": 1 if email.attachments else 0, - "seen": seen, + "seen": seen or 0, "fingerprint": args.get("fingerprint", None) }) @@ -565,12 +566,13 @@ class EmailAccount(Document): if self.email_sync_option == "ALL": max_uid = get_max_email_uid(self.name) last_uid = max_uid + int(self.initial_sync_count or 100) if max_uid == 1 else "*" + print "UID {}:{}".format(max_uid, last_uid) return "UID {}:{}".format(max_uid, last_uid) else: return self.email_sync_option - def mark_emails_as_seen(self): - """ mark Email Flag Queue of self.email_account mails as seen""" + def mark_emails_as_read(self): + """ mark Email Flag Queue of self.email_account mails as read""" if not self.use_imap: return @@ -581,10 +583,33 @@ class EmailAccount(Document): uid_list = list(set([ flag.get("uid") for flag in flags ])) if flags and uid_list: email_server = self.get_incoming_server() - marked_as_seen = email_server.mark_as_seen(uid_list=uid_list) + email_server.update_flag(uid_list=uid_list) - docnames = ",".join([ "'%s'"%uid for uid in uid_list ]) - frappe.db.sql(""" update `tabCommunication` set seen=1 where name in ({docnames})""".format(docnames=docnames)) + docnames = ",".join([ "'%s'"%flag.get("name") for flag in flags ]) + frappe.db.sql(""" update `tabCommunication` set seen=1 + where name in ({docnames})""".format(docnames=docnames)) + + def mark_emails_as_unread(self): + """ mark Email Flag Queue of self.email_account mails as unread""" + + if not self.use_imap: + return + + flags = frappe.db.sql("""select name, communication, uid from `tabEmail Flag Queue` + where action = "Unread" and is_completed=0 """.format(email_account=self.name), as_dict=True) + + uid_list = list(set([ flag.get("uid") for flag in flags ])) + if flags and uid_list: + email_server = self.get_incoming_server() + email_server.update_flag(uid_list=uid_list, operation="Unread") + + docnames = ",".join([ "'%s'"%flag.get("communication") for flag in flags ]) + frappe.db.sql(""" update `tabCommunication` set seen=0 + where name in ({docnames})""".format(docnames=docnames)) + + docnames = ",".join([ "'%s'"%flag.get("name") for flag in flags ]) + frappe.db.sql(""" update `tabEmail Flag Queue` set is_completed=1 + where name in ({docnames})""".format(docnames=docnames)) @frappe.whitelist() def get_append_to(doctype=None, txt=None, searchfield=None, start=None, page_len=None, filters=None): @@ -661,7 +686,8 @@ def pull_from_email_account(email_account): email_account.receive() # mark Email Flag Queue mail as read - email_account.mark_emails_as_seen() + email_account.mark_emails_as_read() + email_account.mark_emails_as_unread() def get_max_email_uid(email_account): # get maximum uid of emails diff --git a/frappe/email/doctype/email_flag_queue/email_flag_queue.json b/frappe/email/doctype/email_flag_queue/email_flag_queue.json index 48921266ec..3e1d124978 100644 --- a/frappe/email/doctype/email_flag_queue/email_flag_queue.json +++ b/frappe/email/doctype/email_flag_queue/email_flag_queue.json @@ -1,5 +1,5 @@ { - "allow_copy": 0, + "allow_copy": 1, "allow_import": 0, "allow_rename": 0, "beta": 0, @@ -15,21 +15,23 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "email_account", - "fieldtype": "Data", + "fieldname": "is_completed", + "fieldtype": "Check", "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": "Email Account", + "label": "Is Completed", "length": 0, "no_copy": 0, "permlevel": 0, "precision": "", "print_hide": 0, "print_hide_if_no_value": 0, - "read_only": 0, + "read_only": 1, "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, @@ -43,10 +45,12 @@ "collapsible": 0, "columns": 0, "fieldname": "communication", - "fieldtype": "Data", + "fieldtype": "Link", "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": "Communication", @@ -70,45 +74,19 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "uid", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "UID", - "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_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "+FLAGS", "fieldname": "action", "fieldtype": "Select", "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": "Action", "length": 0, "no_copy": 0, - "options": "+FLAGS\n-FLAGS", + "options": "Read\nUnread", "permlevel": 0, "precision": "", "print_hide": 0, @@ -126,18 +104,18 @@ "bold": 0, "collapsible": 0, "columns": 0, - "default": "Seen", "fieldname": "flag", - "fieldtype": "Select", + "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, - "options": "Seen\nUnseen", "permlevel": 0, "precision": "", "print_hide": 0, @@ -155,13 +133,13 @@ "hide_toolbar": 0, "idx": 0, "image_view": 0, - "in_create": 0, + "in_create": 1, "in_dialog": 0, "is_submittable": 0, "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-02-13 07:58:35.414784", + "modified": "2017-03-01 05:24:47.756892", "modified_by": "Administrator", "module": "Email", "name": "Email Flag Queue", @@ -190,8 +168,9 @@ } ], "quick_entry": 0, - "read_only": 0, + "read_only": 1, "read_only_onload": 0, + "show_name_in_global_search": 0, "sort_field": "modified", "sort_order": "DESC", "track_changes": 0, diff --git a/frappe/email/page/email_inbox/__init__.py b/frappe/email/page/email_inbox/__init__.py index 4e141cbed1..cc3df29034 100644 --- a/frappe/email/page/email_inbox/__init__.py +++ b/frappe/email/page/email_inbox/__init__.py @@ -8,71 +8,41 @@ import json from frappe.model.document import Document from frappe.desk.form.load import get_attachments - -@frappe.whitelist() -def get_list(email_account,start,page_length): - inbox_list = [] - communications = frappe.db.sql("""select name, sender, sender_full_name, actualdate, recipients, communication_medium as comment_type, subject, status ,reference_doctype,reference_name,timeline_doctype,timeline_name,timeline_label,sent_or_received,uid,message_id, seen,nomatch,has_attachment - from tabCommunication - where email_account = %(email_account)s and deleted = 0 - ORDER BY actualdate DESC - LIMIT %(page_length)s OFFSET %(start)s""",{"email_account":email_account,"start":int(start),"page_length":int(page_length)},as_dict=1) - for c in communications: - comm = {} - - comm["name"] = c.get('name') - comm["reference_doctype"] = c.get('reference_doctype') - comm["reference_name"] = c.get('reference_name') - if c.get('recipients') != None: - comm["recipients"] = c.get('recipients').replace('"',"").strip("<>") - comm["sender"] = c.get('sender') - comm["sender_full_name"] = c.get('sender_full_name') - comm["actualdate"] = c.get('actualdate') - comm["subject"] = c.get('subject') - comm["status"] = c.get('status') - comm["content"] = c.get('content') - comm["timeline_doctype"] = c.get('timeline_doctype') - comm["timeline_name"] = c.get('timeline_name') - comm["timeline_label"] = c.get('timeline_label') - comm["sent_or_received"] = c.get('sent_or_received') - comm["uid"]= c.get('uid') - comm["message_id"]=c.get("message_id") - comm["seen"] = c.get('seen') - comm["nomatch"] =c.get('nomatch') - comm["has_attachment"]=c.get('has_attachment') - inbox_list.append(comm) - return inbox_list - @frappe.whitelist() def get_email_content(name): - docinfo = frappe.desk.form.load.get_attachments("Communication",name) - content = frappe.db.get_value("Communication", name,"content") + docinfo = frappe.desk.form.load.get_attachments("Communication", name) + content = frappe.db.get_value("Communication", name, "content") return docinfo, content @frappe.whitelist() -def create_flag_queue(names,action,flag,field): +def create_flag_queue(names, action, flag): names = json.loads(names) class Found(Exception): pass for item in names: - if item["uid"]: - state = frappe.db.get_value("Communication", item["name"], field) - if (action =='+FLAGS' and state ==0) or (action =='-FLAGS' and state ==1): #check states are correct + if item.get("uid"): + state = frappe.db.get_value("Communication", item.get("name"), "seen") + frappe.errprint(state) + + # check states are correct + if (action =='Read' and state == 0) or (action =='Unread' and state == 1): try: - queue = frappe.db.sql("""select name,action,flag from `tabEmail Flag Queue` - where comm_name = %(name)s""",{"name":item["name"]},as_dict=1) + queue = frappe.db.sql("""select name, action, flag from `tabEmail Flag Queue` + where communication = %(name)s""", {"name":item.get("name")}, as_dict=True) for q in queue: - if q.flag==flag:#is same email with same flag - if q.action!=action:#to prevent flag local and server states being out of sync + # 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 flag_queue = frappe.get_doc({ "doctype": "Email Flag Queue", - "comm_name": str(item["name"]), - "action":action, - "flag":flag + "communication": item.get("name"), + "action": action, + "flag": flag }) flag_queue.save(ignore_permissions=True); except Found: @@ -80,40 +50,35 @@ def create_flag_queue(names,action,flag,field): @frappe.whitelist() def setnomatch(name): - frappe.db.set_value("Communication", str(name), "nomatch", 1, update_modified=False) + frappe.db.set_value("Communication", name, "nomatch", 1, update_modified=False) @frappe.whitelist() -def update_local_flags(names,field,val): +def update_local_flags(names, field, val): names = json.loads(names) for d in names: - frappe.db.set_value("Communication", str(d["name"]), field, val,update_modified=False) - -@frappe.whitelist() -def get_length(email_account): - try: - return frappe.db.sql("""select count(name) - from tabCommunication - where deleted = 0 and email_account= %(email_account)s""",{"email_account":email_account}) - except: - return 0 + frappe.db.set_value("Communication", d.get("name"), field, val, update_modified=False) @frappe.whitelist() def get_accounts(user): - try: - return frappe.db.sql("""select email_account,email_id - from `tabUser Email` - where parent = %(user)s - order by idx""",{"user":user},as_dict=1) - except: - return + email_accounts = [] -# for the selection/deletion of multiple items -def set_multiple_status(names, status): - names = json.loads(names) - for name in names: - set_status(name, status) + accounts = frappe.get_all("User Email", filters={ "parent": user }, + fields=["email_account as account", "email_id as title"], + distinct=True, order_by="idx") -def set_status(name, status): - st = frappe.get_doc("Issue", name) - st.status = status - st.save() + if not accounts: + return None + + all_accounts = ",".join([ account.get("account") for account in accounts ]) + if len(accounts) > 1: + email_accounts.append({ + "account": all_accounts, + "title": "All Accounts" + }) + + email_accounts.extend(accounts) + + return { + "email_accounts": email_accounts, + "all_accounts": all_accounts + } diff --git a/frappe/email/page/email_inbox/email_inbox.js b/frappe/email/page/email_inbox/email_inbox.js index 1a167354e8..9338c74b42 100644 --- a/frappe/email/page/email_inbox/email_inbox.js +++ b/frappe/email/page/email_inbox/email_inbox.js @@ -1,3 +1,5 @@ +frappe.provide("frappe.email") + frappe.pages['email_inbox'].on_page_load = function(wrapper) { frappe.ui.make_app_page({ parent: wrapper, @@ -7,7 +9,7 @@ frappe.pages['email_inbox'].on_page_load = function(wrapper) { }); frappe.model.with_doctype('Communication', function() { - wrapper.Inbox = new frappe.Inbox({ + wrapper.inbox = new frappe.email.EmailInbox({ method: 'frappe.desk.reportview.get', wrapper: wrapper, page: wrapper.page, @@ -18,82 +20,79 @@ frappe.pages['email_inbox'].on_page_load = function(wrapper) { frappe.pages['email_inbox'].refresh = function(wrapper) { if (wrapper.inbox) { - wrapper.Inbox.refresh() + wrapper.inbox.refresh() } }; -frappe.Inbox = frappe.ui.Listing.extend({ +frappe.email.EmailInbox = frappe.ui.Listing.extend({ init: function(opts) { $.extend(this, opts); wrap = this; this.wrapper = opts.wrapper; - this.filters = {}; this.page_length = 20; this.start = 0; - this.cur_page = 1; this.no_result_message = 'No Emails to Display'; - this.render_sidemenu(); - if (this.account) { - var me = this; - // setup listing - me.make({ - doctype: 'Communication', - page: me.page, - method: 'frappe.desk.reportview.get', - get_args: me.get_args, - parent: me.page.main, - start: 0, - show_filters: true - }); - - this.render_headers(); - this.render_footer(); - this.run(); - this.render_buttons(); - this.init_select_all(); - var me = this; - frappe.realtime.on("new_email", function(data) { - for(var i =0; i (me.cur_page * me.page_length))?(me.cur_page * me.page_length):me.data_length) + ' of ' + me.data_length); - me.run(true,true); } + me.fresh = false }); - }); - $(me.wrapper).find('.list-paging-area').addClass('hide'); }, - update_footer:function(){ - var me = this; - //default filter used for filters - var filters = me.filter_list.get_filters(); - if (me.filter_list.default_filters){filters = filters.concat(me.filter_list.default_filters)} - return frappe.call({ - method: me.method || 'frappe.desk.query_builder.runquery', - type: "GET", - freeze: (me.freeze != undefined ? me.freeze : true), - args: { - doctype: me.doctype, - fields: ["count(*) as number"], - filters: filters, - save_list_settings: false - }, - callback: function (r) { - r.values = me.get_values_from_response(r.message); - me.data_length = r.values[0]["number"] - if (me.data_length != 0) { - me.footer.show(); - me.last_page = Math.ceil(me.data_length / me.page_length); - frappe.require('assets/frappe/js/lib/bootstrap-paginator.min.js',function(){ - me.footer.bootstrapPaginator({currentPage: 1, totalPages: me.last_page}) - }); - } else { - me.footer.hide(); + + render_list: function(data) { + var me = this + $(me.wrapper).find(".result-list").empty(); + + $.each(data, function(idx, email) { + $(frappe.render_template("inbox_list", {data: email})) + .data("data", email) + .appendTo($(me.wrapper).find(".result-list")) + }); + + //click action + $(me.wrapper).find(".result-list").find(".list-row").click(function(btn) { + if ($(btn.target).hasClass("noclick")) + return + + var row = $(btn.target).closest(".list-row").data("data"); + if($(btn.target).hasClass("relink-link")){ + me.relink(row); + return + } + + if(me.account != "Sent") { + if ($(btn.target).hasClass("company-link")) { + me.company_select(row, true); + return } - $('.footer-numbers').html('showing: ' + (me.cur_page - 1) * me.page_length + ' to ' + ( - (me.data_length > (me.cur_page * me.page_length)) ? (me.cur_page * me.page_length) : me.data_length) + ' of ' + me.data_length); - }, - no_spinner: this.no_loading + } + me.email_open(row); }); }, - company_select:function(row,nomatch) - { + + company_select: function(row, nomatch) { var me = this; - var fields = [{ + var fields = [ + { "fieldtype": "Heading", "label": __("Create new Contact to Match Email Address"), "fieldname": "Option1" - }, - { - "fieldtype": "Button", - "label": __("Create/Add new Contact"), - "fieldname":"newcontact", - "description": __('Create new Contact for a Customer, Supplier, User or Organisation to Match "') + row.sender + __('" Against') - } + }, + { + "fieldtype": "Button", + "label": __("Create/Add new Contact"), + "fieldname":"newcontact", + "description": __('Create new Contact for a Customer, Supplier, User or Organisation to Match "') + row.sender + __('" Against') + } + ]; - ]; if (!nomatch) { fields.push({ "fieldtype": "Heading", @@ -273,10 +290,12 @@ frappe.Inbox = frappe.ui.Listing.extend({ "fieldname":"nomatch" }) } + var d = new frappe.ui.Dialog ({ title: __("Match Emails to a Company"), fields: fields }); + d.get_input("newcontact").on("click", function (frm) { d.hide(); delete frappe.route_flags.update_contact; @@ -295,6 +314,7 @@ frappe.Inbox = frappe.ui.Listing.extend({ frappe.set_route("Form", "Contact", doc.name); }) }); + if (!nomatch) { d.get_input("nomatch").on("click", function (frm) { d.hide(); @@ -312,8 +332,8 @@ frappe.Inbox = frappe.ui.Listing.extend({ } d.show(); }, - email_open:function(row) - { + + email_open: function(row) { var me = this; me.actions_opened = false; if(me.open_email == row.name){ @@ -363,8 +383,15 @@ frappe.Inbox = frappe.ui.Listing.extend({ //adjust sizing $(".modal-dialog").addClass("modal-lg"); - $(emailitem.$wrapper).find(".modal-title").parent().removeClass("col-xs-7").addClass("col-xs-7 col-sm-8 col-md-9"); - $(emailitem.$wrapper).find(".text-right").parent().removeClass("col-xs-5").addClass("col-xs-5 col-sm-4 col-md-3"); + $(emailitem.$wrapper).find(".modal-title") + .parent() + .removeClass("col-xs-7") + .addClass("col-xs-7 col-sm-8 col-md-9"); + + $(emailitem.$wrapper).find(".text-right") + .parent() + .removeClass("col-xs-5") + .addClass("col-xs-5 col-sm-4 col-md-3"); //setup close emailitem.onhide = function() { @@ -373,9 +400,11 @@ frappe.Inbox = frappe.ui.Listing.extend({ emailitem.show(); }, + add_reply_btn_event: function (emailitem, c) { var me = this; -//reply + + //reply $(emailitem.$wrapper).find(".reply-link").on("click", function () { var sender = ""; for (var i=0;i") } - - // bold @mentions if (c.comment_type === "Comment") { c.comment_html = c.comment_html.replace(/(^|\W)(@\w+)/g, "$1$2"); @@ -514,6 +536,7 @@ frappe.Inbox = frappe.ui.Listing.extend({ return c }, + init_select_all: function () { var me = this; @@ -540,12 +563,13 @@ frappe.Inbox = frappe.ui.Listing.extend({ // after delete, hide delete button me.toggle_actions(); }, + render_buttons: function(){ var me = this; - me.page.add_action_item("Delete", function(){me.delete_email()}); - me.page.add_action_item("Mark as UnRead", function(){me.mark_unread()}); - me.page.add_action_item("Mark as Read", function(){me.mark_read()}); + me.page.add_action_item("Delete", function(){ me.delete_email() }); + me.page.add_action_item("Mark as Unread", function(){ me.mark_unread() }); + me.page.add_action_item("Mark as Read", function(){ me.mark_read() }); me.page.set_primary_action("New Email", function(){ var sender = ""; @@ -559,8 +583,9 @@ frappe.Inbox = frappe.ui.Listing.extend({ doc: {}, sender: sender }); - },"fa-plus","New Email"); + }, "fa-plus", "New Email"); }, + toggle_actions: function () { var me = this; if (me.page.main.find(".list-row-checkbox:checked").length) { @@ -573,61 +598,68 @@ frappe.Inbox = frappe.ui.Listing.extend({ $(me.page.btn_primary).show() } }, - delete_email:function(data){ + + delete_email: function(data){ var me = this; if (!data) { - var names = $.map(me.action_checked_items('.data("data")'),function(v){return {name:v.name, uid:v.uid}}); + var names = $.map(me.action_checked_items('.data("data")'), function(v){ + return {name:v.name, uid:v.uid} + }); me.action_checked_items('.remove()') } else { var names = [{name:data.name, uid:data.uid}] } }, - mark_unread:function(){ + + mark_unread: function(){ var me = this; - var names = $.map(me.action_checked_items('.data("data")'), function(v){return {name:v.name, uid:v.uid}}); - me.create_flag_queue(names,"-FLAGS","(\\SEEN)","seen"); + var names = $.map(me.action_checked_items('.data("data")'), function(v){ + return {name:v.name, uid:v.uid} + }); + me.create_flag_queue(names, "Unread", "SEEN"); me.action_checked_items('.css("font-weight", "BOLD")'); - me.update_local_flags(names,"seen","0") + me.update_local_flags(names, "seen", "0") }, - mark_read:function(data){ + + mark_read: function(data){ var me = this; if (!data) { var names = $.map(me.action_checked_items('.data("data")'), function(v){return {name:v.name, uid:v.uid}}); me.action_checked_items('.css("font-weight", "normal")') - } else{ - var names = [{name:data.name, uid:data.uid}]; - $(".row-named").filter("[data-name=" + data.name + "]").css("font-weight", "normal") + } else { + var names = [{name:data.name, uid:data.uid}]; + $(".row-named").filter("[data-name=" + data.name + "]").css("font-weight", "normal") } - me.create_flag_queue(names,"+FLAGS","(\\SEEN)","seen"); - me.update_local_flags(names,"seen","1") - + me.create_flag_queue(names, "Read", "SEEN"); + me.update_local_flags(names, "seen", "1"); }, - create_flag_queue:function(names,action,flag,field){ + + create_flag_queue: function(names, action, flag){ frappe.call({ method: 'frappe.email.page.email_inbox.create_flag_queue', args:{ - names:JSON.stringify(names), - action:action, - flag:flag, - field:field + names: JSON.stringify(names), + action: action, + flag: flag } }) }, + update_local_flags:function(names,field,val){ frappe.call({ method: 'frappe.email.page.email_inbox.update_local_flags', args:{ - names:JSON.stringify(names), - field:field, - val:val + names: JSON.stringify(names), + field: field, + val: val } }) $('.list-row-checkbox:checked').prop( "checked", false ); }, + action_checked_items: function(action) { return $.map(this.page.main.find('.list-row-checkbox:checked'), function(e) { return eval('$(e).closest(".row-named")'+action); }); }, -}); - +}); \ No newline at end of file diff --git a/frappe/email/page/email_inbox/email_inbox_sidebar.html b/frappe/email/page/email_inbox/email_inbox_sidebar.html new file mode 100644 index 0000000000..ffef821f8a --- /dev/null +++ b/frappe/email/page/email_inbox/email_inbox_sidebar.html @@ -0,0 +1,19 @@ + + + \ No newline at end of file diff --git a/frappe/email/page/email_inbox/inbox_list.html b/frappe/email/page/email_inbox/inbox_list.html index 8e94f85ae5..f39dbc6dbc 100644 --- a/frappe/email/page/email_inbox/inbox_list.html +++ b/frappe/email/page/email_inbox/inbox_list.html @@ -14,33 +14,32 @@ {%= data.subject %} - - - - - - - - + + + + + + + \ No newline at end of file diff --git a/frappe/email/receive.py b/frappe/email/receive.py index 33e348cde6..7b222c3e0c 100644 --- a/frappe/email/receive.py +++ b/frappe/email/receive.py @@ -224,7 +224,7 @@ class EmailServer: self.validate_message_limits(message_meta) if cint(self.settings.use_imap): - status, message = self.imap.uid('fetch', message_meta, '(RFC822 BODY.PEEK[HEADER] FLAGS)') + status, message = self.imap.uid('fetch', message_meta, '(BODY.PEEK[] BODY.PEEK[HEADER] FLAGS)') raw, header, ignore = message self.get_email_seen_status(message_meta, header[0]) @@ -342,7 +342,7 @@ class EmailServer: return error_msg - def mark_as_seen(self, uid_list=[]): + def update_flag(self, uid_list=[], operation="Read"): """ set all uids mails the flag as seen """ if not uid_list: @@ -351,10 +351,12 @@ class EmailServer: if not self.connect(): return + op = "+FLAGS" if operation == "Read" else "-FLAGS" + self.imap.select("Inbox") for uid in uid_list: try: - self.imap.uid('STORE', uid, '+FLAGS', '(\\SEEN)') + self.imap.uid('STORE', uid, op, '(\\SEEN)') except Exception as e: continue diff --git a/frappe/public/js/frappe/list/list_sidebar.html b/frappe/public/js/frappe/list/list_sidebar.html index b5b7ea6ed9..eb28a8ae1b 100644 --- a/frappe/public/js/frappe/list/list_sidebar.html +++ b/frappe/public/js/frappe/list/list_sidebar.html @@ -34,6 +34,18 @@ + {% if(doctype == "Communication") { %} + + {% } %}
  • {%= __("Assigned To Me") %}