diff --git a/crm/api/activities.py b/crm/api/activities.py index 449b579a4..3ccb173c4 100644 --- a/crm/api/activities.py +++ b/crm/api/activities.py @@ -2,6 +2,7 @@ import frappe from frappe import _ +from frappe.utils.caching import redis_cache from frappe.desk.form.load import get_docinfo @frappe.whitelist() @@ -98,6 +99,7 @@ def get_deal_activities(name): "recipients": communication.recipients, "cc": communication.cc, "bcc": communication.bcc, + "attachments": get_attachments(communication.name), "read_by_recipient": communication.read_by_recipient, }, "is_lead": False, @@ -185,6 +187,7 @@ def get_lead_activities(name): "recipients": communication.recipients, "cc": communication.cc, "bcc": communication.bcc, + "attachments": get_attachments(communication.name), "read_by_recipient": communication.read_by_recipient, }, "is_lead": True, @@ -196,6 +199,14 @@ def get_lead_activities(name): return activities +@redis_cache() +def get_attachments(name): + return frappe.db.get_all( + "File", + filters={"attached_to_doctype": "Communication", "attached_to_name": name}, + fields=["name", "file_name", "file_url", "file_size", "is_private"], + ) + def handle_multiple_versions(versions): activities = [] grouped_versions = [] diff --git a/crm/fcrm/doctype/crm_call_log/crm_call_log.py b/crm/fcrm/doctype/crm_call_log/crm_call_log.py index 4369e0a20..8f2865bfd 100644 --- a/crm/fcrm/doctype/crm_call_log/crm_call_log.py +++ b/crm/fcrm/doctype/crm_call_log/crm_call_log.py @@ -96,6 +96,7 @@ def get_call_log(name): if doc.note: note = frappe.db.get_values("CRM Note", doc.note, ["title", "content"])[0] _doc.note_doc = { + "name": doc.note, "title": note[0], "content": note[1] } diff --git a/frontend/package.json b/frontend/package.json index 61faae065..ce000952e 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -14,6 +14,7 @@ "@vueuse/integrations": "^10.3.0", "feather-icons": "^4.28.0", "frappe-ui": "^0.1.17", + "mime": "^4.0.1", "pinia": "^2.0.33", "socket.io-client": "^4.7.2", "sortablejs": "^1.15.0", diff --git a/frontend/src/components/Activities.vue b/frontend/src/components/Activities.vue index 8bfc19b4d..1fd23977e 100644 --- a/frontend/src/components/Activities.vue +++ b/frontend/src/components/Activities.vue @@ -26,8 +26,11 @@ New Task -
-
+
+
-
+
-
+
-
@@ -266,7 +265,7 @@
-
+
-
+
-
+ +
+ +
new Date(b.creation) - new Date(a.creation) + (a, b) => new Date(a.creation) - new Date(b.creation) ) } @@ -771,15 +785,21 @@ const activities = computed(() => { activities = all_activities() } else if (props.title == 'Emails') { if (!versions.data) return [] - activities = versions.data.filter( - (activity) => activity.activity_type === 'communication' - ) + activities = versions.data + .filter((activity) => activity.activity_type === 'communication') + .sort((a, b) => new Date(a.creation) - new Date(b.creation)) } else if (props.title == 'Calls') { - return calls.data + return calls.data.sort( + (a, b) => new Date(a.creation) - new Date(b.creation) + ) } else if (props.title == 'Tasks') { - return tasks.data + return tasks.data.sort( + (a, b) => new Date(a.creation) - new Date(b.creation) + ) } else if (props.title == 'Notes') { - return notes.data + return notes.data.sort( + (a, b) => new Date(a.creation) - new Date(b.creation) + ) } activities.forEach((activity) => { activity.icon = timelineIcon(activity.activity_type, activity.is_lead) @@ -876,6 +896,7 @@ function timelineIcon(activity_type, is_lead) { // Notes const showNoteModal = ref(false) const note = ref({}) +const emailBox = ref(null) function showNote(n) { note.value = n || { @@ -928,6 +949,21 @@ function updateTaskStatus(status, task) { }) } +// Email +function reply(message) { + emailBox.value.show = true + let editor = emailBox.value.editor.editor + editor + .chain() + .clearContent() + .insertContent(message) + .focus('all') + .setBlockquote() + .insertContentAt(0, { type: 'paragraph' }) + .focus('start') + .run() +} + watch([reload, reload_email], ([reload_value, reload_email_value]) => { if (reload_value || reload_email_value) { versions.reload() @@ -935,6 +971,21 @@ watch([reload, reload_email], ([reload_value, reload_email_value]) => { reload_email.value = false } }) + +function scroll(el) { + setTimeout(() => { + if (!el) { + let e = document.getElementsByClassName('activity') + el = e[e.length - 1] + } + if (!useElementVisibility(el).value) { + el.scrollIntoView({ behavior: 'smooth' }) + el.focus() + } + }, 500) +} + +nextTick(() => scroll())