Skip to content

Commit

Permalink
fix: rendered versions on activity tab
Browse files Browse the repository at this point in the history
  • Loading branch information
shariquerik committed Aug 3, 2023
1 parent 762f487 commit d3a2d8f
Show file tree
Hide file tree
Showing 4 changed files with 292 additions and 95 deletions.
98 changes: 98 additions & 0 deletions crm/crm/doctype/crm_lead/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import json

import frappe
from frappe import _
from frappe.desk.form.load import get_docinfo


@frappe.whitelist()
def get_lead(name):
Lead = frappe.qb.DocType("CRM Lead")

query = (
frappe.qb.from_(Lead)
.select("*")
.where(Lead.name == name)
.limit(1)
)

lead = query.run(as_dict=True)
if not len(lead):
frappe.throw(_("Lead not found"), frappe.DoesNotExistError)
lead = lead.pop()

get_docinfo('', "CRM Lead", name)
docinfo = frappe.response["docinfo"]
activities = get_activities(lead, docinfo)

return { **lead, 'activities': activities }

def get_activities(doc, docinfo):
activities = [{
"activity_type": "creation",
"creation": doc.creation,
"owner": doc.owner,
"data": "created this lead",
}]

for version in docinfo.versions:
data = json.loads(version.data)
if change := data.get("changed")[0]:
activity_type = "changed"
data = {
"field": change[0],
"old_value": change[1],
"value": change[2],
}
if not change[1] and not change[2]:
continue
if not change[1] and change[2]:
activity_type = "added"
data = {
"field": change[0],
"value": change[2],
}
elif change[1] and not change[2]:
activity_type = "removed"
data = {
"field": change[0],
"value": change[1],
}

activity = {
"activity_type": activity_type,
"creation": version.creation,
"owner": version.owner,
"data": data,
}
activities.append(activity)

for comment in docinfo.comments:
activity = {
"activity_type": "comment",
"creation": comment.creation,
"owner": comment.owner,
"data": comment.content,
}
activities.append(activity)

for communication in docinfo.communications:
activity = {
"activity_type": "communication",
"creation": communication.creation,
"data": {
"subject": communication.subject,
"content": communication.content,
"sender_full_name": communication.sender_full_name,
"sender": communication.sender,
"recipients": communication.recipients,
"cc": communication.cc,
"bcc": communication.bcc,
"read_by_recipient": communication.read_by_recipient,
},
}
activities.append(activity)

activities.sort(key=lambda x: x["creation"], reverse=True)

return activities
118 changes: 115 additions & 3 deletions frontend/src/components/Activities.vue
Original file line number Diff line number Diff line change
@@ -1,15 +1,127 @@
<template>
<div class="p-6">
<div v-for="activity in activities">
<div>{{ activity.value }}</div>
<div class="p-5 flex items-center justify-between font-medium text-lg">
<div>{{ title }}</div>
</div>
<div>
<div v-for="(activity, i) in activities">
<div class="grid grid-cols-[30px_minmax(auto,_1fr)] gap-4 px-5">
<div
class="relative flex justify-center"
:class="{
'after:absolute after:border-l after:border-gray-300 after:top-0 after:left-[50%] after:h-full after:-z-10':
i != activities.length - 1,
}"
>
<div
class="flex items-center justify-center rounded-full outline outline-4 outline-white w-6 h-6 bg-gray-200 z-10"
>
<FeatherIcon
:name="timelineIcon(activity.activity_type)"
class="w-3.5 h-3.5 text-gray-600"
/>
</div>
</div>
<div class="flex flex-col gap-3 pb-6">
<div
class="flex items-start justify-stretch gap-2 text-base leading-6"
>
<Avatar
:image="getUser(activity.owner).user_image"
:label="getUser(activity.owner).full_name"
size="md"
/>

<div class="flex items-center gap-1">
<div>{{ getUser(activity.owner).full_name }}</div>
<div
v-if="activity.activity_type == 'creation'"
class="text-gray-600"
>
{{ activity.data }}
</div>
<div
v-else-if="activity.activity_type == 'added'"
class="inline-flex gap-1 text-gray-600"
>
<span>added</span>
<span class="text-gray-900 truncate max-w-xs">
{{ activity.data.field }}
</span>
<span>value as</span>
<span class="text-gray-900 truncate max-w-xs">
{{ activity.data.value }}
</span>
</div>
<div
v-else-if="activity.activity_type == 'removed'"
class="inline-flex gap-1 text-gray-600"
>
<span>removed</span>
<span class="text-gray-900 truncate max-w-xs">
{{ activity.data.field }}
</span>
<span>value</span>
<span class="text-gray-900 truncate max-w-xs">
{{ activity.data.value }}
</span>
</div>
<div
v-else-if="activity.activity_type == 'changed'"
class="inline-flex gap-1 text-gray-600"
>
<span>changed</span>
<span class="text-gray-900 truncate max-w-xs">
{{ activity.data.field }}
</span>
<span>value from</span>
<span class="text-gray-900 truncate max-w-xs">
{{ activity.data.old_value }}
</span>
<span>to</span>
<span class="text-gray-900 truncate max-w-xs">
{{ activity.data.value }}
</span>
</div>
</div>

<div class="ml-auto whitespace-nowrap">
<Tooltip
:text="dateFormat(activity.creation, dateTooltipFormat)"
class="text-sm text-gray-600 leading-6"
>
{{ timeAgo(activity.creation) }}
</Tooltip>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { Avatar, FeatherIcon, Tooltip, Button } from 'frappe-ui'
import { timeAgo, dateFormat, dateTooltipFormat } from '@/utils'
import { usersStore } from '@/stores/users'
const { getUser } = usersStore()
const props = defineProps({
title: {
type: String,
default: 'Activity',
},
activities: {
type: Array,
default: [],
},
})
function timelineIcon(activity_type) {
if (activity_type == 'creation') {
return 'plus'
} else if (activity_type == 'removed') {
return 'trash-2'
}
return 'edit'
}
</script>
Loading

0 comments on commit d3a2d8f

Please sign in to comment.