mirror of
https://github.com/lingble/chatwoot.git
synced 2025-10-30 10:42:38 +00:00
feat: Inbox card context menu component (#8815)
* feat: Inbox item context menu component * chore: Minor fix * chore: Minor height fix * fix: Conflict * minor fix * chore: Fix conflicts * chore: Minor fix --------- Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
This commit is contained in:
@@ -12,6 +12,12 @@
|
||||
"CONVERSATION_ASSIGNMENT": "A conversation has been assigned to you",
|
||||
"ASSIGNED_CONVERSATION_NEW_MESSAGE": "New message in an assigned conversation",
|
||||
"PARTICIPATING_CONVERSATION_NEW_MESSAGE": "New message in a conversation you are participating in"
|
||||
},
|
||||
"MENU_ITEM": {
|
||||
"MARK_AS_READ": "Mark as read",
|
||||
"MARK_AS_UNREAD": "Mark as unread",
|
||||
"SNOOZE": "Snooze",
|
||||
"DELETE": "Delete"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
<div
|
||||
role="button"
|
||||
class="flex flex-col pl-5 pr-3 gap-2.5 py-3 w-full bg-white dark:bg-slate-900 border-b border-slate-50 dark:border-slate-800/50 hover:bg-slate-25 dark:hover:bg-slate-800 cursor-pointer"
|
||||
@contextmenu="openContextMenu($event)"
|
||||
@click="openConversation(notificationItem)"
|
||||
>
|
||||
<div class="flex relative items-center justify-between w-full">
|
||||
@@ -41,17 +42,24 @@
|
||||
{{ lastActivityAt }}
|
||||
</span>
|
||||
</div>
|
||||
<inbox-context-menu
|
||||
v-if="isContextMenuOpen"
|
||||
:context-menu-position="contextMenuPosition"
|
||||
@close="closeContextMenu"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import PriorityIcon from './PriorityIcon.vue';
|
||||
import StatusIcon from './StatusIcon.vue';
|
||||
import InboxNameAndId from './InboxNameAndId.vue';
|
||||
import InboxContextMenu from './InboxContextMenu.vue';
|
||||
import Thumbnail from 'dashboard/components/widgets/Thumbnail.vue';
|
||||
import timeMixin from 'dashboard/mixins/time';
|
||||
export default {
|
||||
components: {
|
||||
PriorityIcon,
|
||||
InboxContextMenu,
|
||||
StatusIcon,
|
||||
InboxNameAndId,
|
||||
Thumbnail,
|
||||
@@ -63,6 +71,12 @@ export default {
|
||||
default: () => {},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isContextMenuOpen: false,
|
||||
contextMenuPosition: { x: null, y: null },
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
primaryActor() {
|
||||
return this.notificationItem?.primary_actor;
|
||||
@@ -93,10 +107,26 @@ export default {
|
||||
return this.shortTimestamp(dynamicTime, true);
|
||||
},
|
||||
},
|
||||
unmounted() {
|
||||
this.closeContextMenu();
|
||||
},
|
||||
methods: {
|
||||
openConversation(notification) {
|
||||
this.$emit('open-conversation', notification);
|
||||
},
|
||||
closeContextMenu() {
|
||||
this.isContextMenuOpen = false;
|
||||
this.contextMenuPosition = { x: null, y: null };
|
||||
},
|
||||
openContextMenu(e) {
|
||||
this.closeContextMenu();
|
||||
e.preventDefault();
|
||||
this.contextMenuPosition = {
|
||||
x: e.pageX || e.clientX,
|
||||
y: e.pageY || e.clientY,
|
||||
};
|
||||
this.isContextMenuOpen = true;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<woot-context-menu
|
||||
:x="contextMenuPosition.x"
|
||||
:y="contextMenuPosition.y"
|
||||
@close="handleClose"
|
||||
>
|
||||
<div
|
||||
class="bg-white dark:bg-slate-900 w-40 py-1 border shadow-md border-slate-100 dark:border-slate-500 rounded-xl"
|
||||
>
|
||||
<menu-item
|
||||
v-for="item in menuItems"
|
||||
:key="item.key"
|
||||
:label="item.label"
|
||||
@click="onMenuItemClick(item.key)"
|
||||
/>
|
||||
</div>
|
||||
</woot-context-menu>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MenuItem from './MenuItem.vue';
|
||||
export default {
|
||||
components: {
|
||||
MenuItem,
|
||||
},
|
||||
props: {
|
||||
contextMenuPosition: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
menuItems: [
|
||||
{
|
||||
key: 'mark_as_read',
|
||||
label: this.$t('INBOX.MENU_ITEM.MARK_AS_READ'),
|
||||
},
|
||||
{
|
||||
key: 'mark_as_unread',
|
||||
label: this.$t('INBOX.MENU_ITEM.MARK_AS_UNREAD'),
|
||||
},
|
||||
{
|
||||
key: 'snooze',
|
||||
label: this.$t('INBOX.MENU_ITEM.SNOOZE'),
|
||||
},
|
||||
{
|
||||
key: 'delete',
|
||||
label: this.$t('INBOX.MENU_ITEM.DELETE'),
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
handleClose() {
|
||||
this.$emit('close');
|
||||
},
|
||||
onMenuItemClick(key) {
|
||||
this.$emit('click', key);
|
||||
this.handleClose();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,25 @@
|
||||
<script setup>
|
||||
import { defineProps, defineEmits } from 'vue';
|
||||
|
||||
defineProps({
|
||||
label: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
|
||||
const emits = defineEmits(['click']);
|
||||
|
||||
const onMenuItemClick = () => {
|
||||
emits('click');
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<div
|
||||
role="button"
|
||||
class="py-1 px-2 w-full h-8 font-medium text-xs text-slate-800 dark:text-slate-100 flex items-center whitespace-nowrap text-ellipsis overflow-hidden hover:text-woot-600 dark:hover:text-woot-500 cursor-pointer rounded-md"
|
||||
@click.stop="onMenuItemClick"
|
||||
>
|
||||
{{ label }}
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user