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:
Sivin Varghese
2024-02-01 14:56:15 +05:30
committed by GitHub
parent b7a7e5a0d3
commit 9464d4d647
4 changed files with 125 additions and 0 deletions

View File

@@ -12,6 +12,12 @@
"CONVERSATION_ASSIGNMENT": "A conversation has been assigned to you", "CONVERSATION_ASSIGNMENT": "A conversation has been assigned to you",
"ASSIGNED_CONVERSATION_NEW_MESSAGE": "New message in an assigned conversation", "ASSIGNED_CONVERSATION_NEW_MESSAGE": "New message in an assigned conversation",
"PARTICIPATING_CONVERSATION_NEW_MESSAGE": "New message in a conversation you are participating in" "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"
} }
} }
} }

View File

@@ -2,6 +2,7 @@
<div <div
role="button" 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" 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)" @click="openConversation(notificationItem)"
> >
<div class="flex relative items-center justify-between w-full"> <div class="flex relative items-center justify-between w-full">
@@ -41,17 +42,24 @@
{{ lastActivityAt }} {{ lastActivityAt }}
</span> </span>
</div> </div>
<inbox-context-menu
v-if="isContextMenuOpen"
:context-menu-position="contextMenuPosition"
@close="closeContextMenu"
/>
</div> </div>
</template> </template>
<script> <script>
import PriorityIcon from './PriorityIcon.vue'; import PriorityIcon from './PriorityIcon.vue';
import StatusIcon from './StatusIcon.vue'; import StatusIcon from './StatusIcon.vue';
import InboxNameAndId from './InboxNameAndId.vue'; import InboxNameAndId from './InboxNameAndId.vue';
import InboxContextMenu from './InboxContextMenu.vue';
import Thumbnail from 'dashboard/components/widgets/Thumbnail.vue'; import Thumbnail from 'dashboard/components/widgets/Thumbnail.vue';
import timeMixin from 'dashboard/mixins/time'; import timeMixin from 'dashboard/mixins/time';
export default { export default {
components: { components: {
PriorityIcon, PriorityIcon,
InboxContextMenu,
StatusIcon, StatusIcon,
InboxNameAndId, InboxNameAndId,
Thumbnail, Thumbnail,
@@ -63,6 +71,12 @@ export default {
default: () => {}, default: () => {},
}, },
}, },
data() {
return {
isContextMenuOpen: false,
contextMenuPosition: { x: null, y: null },
};
},
computed: { computed: {
primaryActor() { primaryActor() {
return this.notificationItem?.primary_actor; return this.notificationItem?.primary_actor;
@@ -93,10 +107,26 @@ export default {
return this.shortTimestamp(dynamicTime, true); return this.shortTimestamp(dynamicTime, true);
}, },
}, },
unmounted() {
this.closeContextMenu();
},
methods: { methods: {
openConversation(notification) { openConversation(notification) {
this.$emit('open-conversation', 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> </script>

View File

@@ -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>

View File

@@ -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>