Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Merge develop to main #389

Merged
merged 10 commits into from
Oct 1, 2024
4 changes: 3 additions & 1 deletion crm/api/comment.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,18 @@ def notify_mentions(doc):
if not content:
return
mentions = extract_mentions(content)
reference_doc = frappe.get_doc(doc.reference_doctype, doc.reference_name)
for mention in mentions:
owner = frappe.get_cached_value("User", doc.owner, "full_name")
doctype = doc.reference_doctype
if doctype.startswith("CRM "):
doctype = doctype[4:].lower()
name = reference_doc.lead_name or name if doctype == "lead" else reference_doc.organization or reference_doc.lead_name or name
notification_text = f"""
<div class="mb-2 leading-5 text-gray-600">
<span class="font-medium text-gray-900">{ owner }</span>
<span>{ _('mentioned you in {0}').format(doctype) }</span>
<span class="font-medium text-gray-900">{ doc.reference_name }</span>
<span class="font-medium text-gray-900">{ name }</span>
</div>
"""
notify_user({
Expand Down
1 change: 1 addition & 0 deletions crm/api/doc.py
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,7 @@ def get_field_obj(field):
obj["placeholder"] = field.get("placeholder") or "Select " + field.label + "..."
obj["doctype"] = field.options
elif field.fieldtype == "Select" and field.options:
obj["placeholder"] = field.get("placeholder") or "Select " + field.label + "..."
obj["options"] = [{"label": option, "value": option} for option in field.options.split("\n")]

if field.read_only:
Expand Down
16 changes: 15 additions & 1 deletion crm/api/notifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def get_notifications():
"type": notification.type,
"to_user": notification.to_user,
"read": notification.read,
"comment": notification.comment,
"hash": get_hash(notification),
"notification_text": notification.notification_text,
"notification_type_doctype": notification.notification_type_doctype,
"notification_type_doc": notification.notification_type_doc,
Expand Down Expand Up @@ -58,3 +58,17 @@ def mark_as_read(user=None, doc=None):
d = frappe.get_doc("CRM Notification", n.name)
d.read = True
d.save()

def get_hash(notification):
_hash = ""
if notification.type == "Mention" and notification.notification_type_doc:
_hash = "#" + notification.notification_type_doc

if notification.type == "WhatsApp":
_hash = "#whatsapp"

if notification.type == "Assignment" and notification.notification_type_doctype == "CRM Task":
_hash = "#tasks"
if "has been removed by" in notification.message:
_hash = ""
return _hash
6 changes: 3 additions & 3 deletions crm/api/todo.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ def get_notification_text(owner, doc, reference_doc, is_cancelled=False):
if doctype.startswith("CRM "):
doctype = doctype[4:].lower()

if doctype in ["CRM Lead", "CRM Deal"]:
name = reference_doc.lead_name or name if doctype == "CRM Lead" else reference_doc.organization or reference_doc.lead_name or name
if doctype in ["lead", "deal"]:
name = reference_doc.lead_name or name if doctype == "lead" else reference_doc.organization or reference_doc.lead_name or name

if is_cancelled:
return f"""
Expand All @@ -76,7 +76,7 @@ def get_notification_text(owner, doc, reference_doc, is_cancelled=False):
</div>
"""

if doc.reference_type == "CRM Task":
if doctype == "task":
if is_cancelled:
return f"""
<div class="mb-2 leading-5 text-gray-600">
Expand Down
2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"@vueuse/core": "^10.3.0",
"@vueuse/integrations": "^10.3.0",
"feather-icons": "^4.28.0",
"frappe-ui": "^0.1.66",
"frappe-ui": "^0.1.70",
"gemoji": "^8.1.0",
"lodash": "^4.17.21",
"mime": "^4.0.1",
Expand Down
60 changes: 31 additions & 29 deletions frontend/src/components/Activities/Activities.vue
Original file line number Diff line number Diff line change
Expand Up @@ -457,10 +457,6 @@ const { getUser } = usersStore()
const { getContact, getLeadContact } = contactsStore()

const props = defineProps({
title: {
type: String,
default: 'Activity',
},
doctype: {
type: String,
default: 'CRM Lead',
Expand All @@ -471,13 +467,17 @@ const props = defineProps({
},
})

const route = useRoute()

const doc = defineModel()
const reload = defineModel('reload')
const tabIndex = defineModel('tabIndex')

const reload_email = ref(false)
const modalRef = ref(null)

const title = computed(() => props.tabs?.[tabIndex.value]?.name || 'Activity')

const all_activities = createResource({
url: 'crm.api.activities.get_activities',
params: { name: doc.value.data.name },
Expand Down Expand Up @@ -549,6 +549,14 @@ onMounted(() => {
whatsappMessages.reload()
}
})

nextTick(() => {
const hash = route.hash.slice(1) || null
let tabNames = props.tabs?.map((tab) => tab.name)
if (!tabNames?.includes(hash)) {
scroll(hash)
}
})
})

function sendTemplate(template) {
Expand Down Expand Up @@ -577,25 +585,25 @@ function get_activities() {

const activities = computed(() => {
let activities = []
if (props.title == 'Activity') {
if (title.value == 'Activity') {
activities = get_activities()
} else if (props.title == 'Emails') {
} else if (title.value == 'Emails') {
if (!all_activities.data?.versions) return []
activities = all_activities.data.versions.filter(
(activity) => activity.activity_type === 'communication',
)
} else if (props.title == 'Comments') {
} else if (title.value == 'Comments') {
if (!all_activities.data?.versions) return []
activities = all_activities.data.versions.filter(
(activity) => activity.activity_type === 'comment',
)
} else if (props.title == 'Calls') {
} else if (title.value == 'Calls') {
if (!all_activities.data?.calls) return []
return sortByCreation(all_activities.data.calls)
} else if (props.title == 'Tasks') {
} else if (title.value == 'Tasks') {
if (!all_activities.data?.tasks) return []
return sortByCreation(all_activities.data.tasks)
} else if (props.title == 'Notes') {
} else if (title.value == 'Notes') {
if (!all_activities.data?.notes) return []
return sortByCreation(all_activities.data.notes)
}
Expand Down Expand Up @@ -649,35 +657,35 @@ function update_activities_details(activity) {

const emptyText = computed(() => {
let text = 'No Activities'
if (props.title == 'Emails') {
if (title.value == 'Emails') {
text = 'No Email Communications'
} else if (props.title == 'Comments') {
} else if (title.value == 'Comments') {
text = 'No Comments'
} else if (props.title == 'Calls') {
} else if (title.value == 'Calls') {
text = 'No Call Logs'
} else if (props.title == 'Notes') {
} else if (title.value == 'Notes') {
text = 'No Notes'
} else if (props.title == 'Tasks') {
} else if (title.value == 'Tasks') {
text = 'No Tasks'
} else if (props.title == 'WhatsApp') {
} else if (title.value == 'WhatsApp') {
text = 'No WhatsApp Messages'
}
return text
})

const emptyTextIcon = computed(() => {
let icon = ActivityIcon
if (props.title == 'Emails') {
if (title.value == 'Emails') {
icon = Email2Icon
} else if (props.title == 'Comments') {
} else if (title.value == 'Comments') {
icon = CommentIcon
} else if (props.title == 'Calls') {
} else if (title.value == 'Calls') {
icon = PhoneIcon
} else if (props.title == 'Notes') {
} else if (title.value == 'Notes') {
icon = NoteIcon
} else if (props.title == 'Tasks') {
} else if (title.value == 'Tasks') {
icon = TaskIcon
} else if (props.title == 'WhatsApp') {
} else if (title.value == 'WhatsApp') {
icon = WhatsAppIcon
}
return h(icon, { class: 'text-gray-500' })
Expand Down Expand Up @@ -720,6 +728,7 @@ watch([reload, reload_email], ([reload_value, reload_email_value]) => {
})

function scroll(hash) {
if (['tasks', 'notes'].includes(route.hash?.slice(1))) return
setTimeout(() => {
let el
if (!hash) {
Expand All @@ -736,11 +745,4 @@ function scroll(hash) {
}

defineExpose({ emailBox })

const route = useRoute()

nextTick(() => {
const hash = route.hash.slice(1) || null
scroll(hash)
})
</script>
16 changes: 16 additions & 0 deletions frontend/src/components/Activities/AllModals.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,23 @@
:task="task"
:doctype="doctype"
:doc="doc.data?.name"
@after="redirect('tasks')"
/>
<NoteModal
v-model="showNoteModal"
v-model:reloadNotes="activities"
:note="note"
:doctype="doctype"
:doc="doc.data?.name"
@after="redirect('notes')"
/>
</template>
<script setup>
import TaskModal from '@/components/Modals/TaskModal.vue'
import NoteModal from '@/components/Modals/NoteModal.vue'
import { call } from 'frappe-ui'
import { ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'

const props = defineProps({
doctype: String,
Expand Down Expand Up @@ -74,6 +77,19 @@ function showNote(n) {
showNoteModal.value = true
}

// common
const route = useRoute()
const router = useRouter()

function redirect(tabName) {
if (route.name == 'Lead' || route.name == 'Deal') {
let hash = '#' + tabName
if (route.hash != hash) {
router.push({ ...route, hash })
}
}
}

defineExpose({
showTask,
deleteTask,
Expand Down
12 changes: 6 additions & 6 deletions frontend/src/components/Activities/WhatsAppBox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
@update:modelValue="
() => {
content += emoji
$refs.textarea.$el.focus()
$refs.textareaRef.el.focus()
capture('whatsapp_emoji_added')
}
"
Expand All @@ -50,15 +50,15 @@
</IconPicker>
</div>
<Textarea
ref="textarea"
ref="textareaRef"
type="textarea"
class="min-h-8 w-full"
:rows="rows"
v-model="content"
:placeholder="placeholder"
@focus="rows = 6"
@blur="rows = 1"
@keydown.enter="(e) => sendTextMessage(e)"
@keydown.enter.stop="(e) => sendTextMessage(e)"
/>
</div>
</template>
Expand All @@ -78,15 +78,15 @@ const doc = defineModel()
const whatsapp = defineModel('whatsapp')
const reply = defineModel('reply')
const rows = ref(1)
const textarea = ref(null)
const textareaRef = ref(null)
const emoji = ref('')

const content = ref('')
const placeholder = ref(__('Type your message here...'))
const fileType = ref('')

function show() {
nextTick(() => textarea.value.$el.focus())
nextTick(() => textareaRef.value.el.focus())
}

function uploadFile(file) {
Expand All @@ -99,7 +99,7 @@ function uploadFile(file) {
function sendTextMessage(event) {
if (event.shiftKey) return
sendWhatsAppMessage()
textarea.value.$el.blur()
textareaRef.value.el?.blur()
content.value = ''
capture('whatsapp_send_message')
}
Expand Down
Loading
Loading