feat: Inbox list display menu (#8847)
* feat: Inbox list display menu * chore: Fix alignment
This commit is contained in:
@@ -27,6 +27,21 @@
|
||||
"MARK_ALL_READ": "Mark all as read",
|
||||
"DELETE_ALL": "Delete all",
|
||||
"DELETE_ALL_READ": "Delete all read"
|
||||
},
|
||||
"DISPLAY_MENU": {
|
||||
"SORT": "Sort",
|
||||
"DISPLAY": "Display :",
|
||||
"SORT_OPTIONS": {
|
||||
"NEWEST": "Newest",
|
||||
"OLDEST": "Oldest",
|
||||
"PRIORITY": "Priority"
|
||||
},
|
||||
"DISPLAY_OPTIONS": {
|
||||
"SNOOZED": "Snoozed",
|
||||
"READ": "Read",
|
||||
"LABELS": "Labels",
|
||||
"CONVERSATION_ID": "Conversation ID"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,6 +166,7 @@ export default {
|
||||
const targetNotification = this.notifications[activeIndex + indexOffset];
|
||||
if (targetNotification) {
|
||||
const {
|
||||
id,
|
||||
primary_actor_id: primaryActorId,
|
||||
primary_actor_type: primaryActorType,
|
||||
primary_actor: { id: conversationId, meta: { unreadCount } = {} },
|
||||
@@ -177,6 +178,7 @@ export default {
|
||||
});
|
||||
|
||||
this.$store.dispatch('notifications/read', {
|
||||
id,
|
||||
primaryActorId,
|
||||
primaryActorType,
|
||||
unreadCount,
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
<template>
|
||||
<div
|
||||
class="flex flex-col bg-white z-50 dark:bg-slate-900 w-[170px] border shadow-md border-slate-100 dark:border-slate-700/50 rounded-xl divide-y divide-slate-100 dark:divide-slate-700/50"
|
||||
>
|
||||
<div class="flex items-center justify-between h-11 p-3 rounded-t-lg">
|
||||
<div class="flex gap-1.5">
|
||||
<fluent-icon
|
||||
icon="arrow-sort"
|
||||
type="outline"
|
||||
size="16"
|
||||
class="text-slate-700 dark:text-slate-100"
|
||||
/>
|
||||
<span class="font-medium text-xs text-slate-800 dark:text-slate-100">
|
||||
{{ $t('INBOX.DISPLAY_MENU.SORT') }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="relative">
|
||||
<div
|
||||
role="button"
|
||||
class="border h-5 flex gap-1 rounded-md items-center pr-1.5 pl-1 py-0.5 w-[70px] justify-between border-slate-100 dark:border-slate-700/50"
|
||||
@click="openSortMenu"
|
||||
>
|
||||
<span class="text-xs font-medium text-slate-600 dark:text-slate-300">
|
||||
{{ activeSortOption }}
|
||||
</span>
|
||||
<fluent-icon
|
||||
icon="chevron-down"
|
||||
size="12"
|
||||
class="text-slate-600 dark:text-slate-200"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-if="showSortMenu"
|
||||
class="absolute flex flex-col gap-0.5 bg-white z-60 dark:bg-slate-800 rounded-md p-0.5 top-0 w-[70px] border border-slate-100 dark:border-slate-700/50"
|
||||
>
|
||||
<div
|
||||
v-for="option in sortOptions"
|
||||
:key="option.key"
|
||||
role="button"
|
||||
class="flex rounded-[4px] h-5 w-full items-center justify-between p-0.5 gap-1"
|
||||
:class="
|
||||
activeSort === option.key ? 'bg-woot-50 dark:bg-woot-700/50' : ''
|
||||
"
|
||||
@click.stop="onSortOptionClick(option.key)"
|
||||
>
|
||||
<span
|
||||
class="text-xs font-medium hover:text-woot-600 dark:hover:text-woot-600"
|
||||
:class="
|
||||
activeSort === option.key
|
||||
? 'text-woot-600 dark:text-woot-600'
|
||||
: 'text-slate-600 dark:text-slate-300'
|
||||
"
|
||||
>
|
||||
{{ option.name }}
|
||||
</span>
|
||||
<fluent-icon
|
||||
v-if="activeSort === option.key"
|
||||
icon="checkmark"
|
||||
size="14"
|
||||
class="text-woot-600 dark:text-woot-600"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<span
|
||||
class="font-medium text-xs py-4 px-3 text-slate-400 dark:text-slate-400"
|
||||
>
|
||||
{{ $t('INBOX.DISPLAY_MENU.DISPLAY') }}
|
||||
</span>
|
||||
<div
|
||||
class="flex flex-col divide-y divide-slate-100 dark:divide-slate-700/50"
|
||||
>
|
||||
<div
|
||||
v-for="option in displayOptions"
|
||||
:key="option.id"
|
||||
class="flex items-center px-3 py-2 gap-1.5 h-9"
|
||||
>
|
||||
<input
|
||||
:id="option.value"
|
||||
type="checkbox"
|
||||
:name="option.value"
|
||||
:checked="option.selected"
|
||||
class="m-0 border-[1.5px] shadow border-slate-200 dark:border-slate-600 appearance-none rounded-[4px] w-4 h-4 dark:bg-slate-800 focus:ring-1 focus:ring-slate-100 dark:focus:ring-slate-700 checked:bg-woot-600 dark:checked:bg-woot-600 after:content-[''] after:text-white checked:after:content-['✓'] after:flex after:items-center after:justify-center checked:border-t checked:border-woot-700 dark:checked:border-woot-300 checked:border-b-0 checked:border-r-0 checked:border-l-0 after:text-center after:text-xs after:font-bold after:relative after:-top-[1.5px]"
|
||||
@change="updateDisplayOption(option)"
|
||||
/>
|
||||
<label
|
||||
:for="option.value"
|
||||
class="text-xs font-medium text-slate-800 !ml-0 !mr-0 dark:text-slate-100"
|
||||
>
|
||||
{{ option.name }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
showSortMenu: false,
|
||||
displayOptions: [
|
||||
{
|
||||
id: 1,
|
||||
name: this.$t('INBOX.DISPLAY_MENU.DISPLAY_OPTIONS.SNOOZED'),
|
||||
value: 'snoozed',
|
||||
selected: false,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: this.$t('INBOX.DISPLAY_MENU.DISPLAY_OPTIONS.READ'),
|
||||
value: 'read',
|
||||
selected: true,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: this.$t('INBOX.DISPLAY_MENU.DISPLAY_OPTIONS.LABELS'),
|
||||
value: 'labels',
|
||||
selected: false,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: this.$t('INBOX.DISPLAY_MENU.DISPLAY_OPTIONS.CONVERSATION_ID'),
|
||||
value: 'conversationId',
|
||||
selected: false,
|
||||
},
|
||||
],
|
||||
sortOptions: [
|
||||
{
|
||||
name: this.$t('INBOX.DISPLAY_MENU.SORT_OPTIONS.NEWEST'),
|
||||
key: 'newest',
|
||||
},
|
||||
{
|
||||
name: this.$t('INBOX.DISPLAY_MENU.SORT_OPTIONS.OLDEST'),
|
||||
key: 'oldest',
|
||||
},
|
||||
{
|
||||
name: this.$t('INBOX.DISPLAY_MENU.SORT_OPTIONS.PRIORITY'),
|
||||
key: 'priority',
|
||||
},
|
||||
],
|
||||
activeSort: 'newest',
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
activeSortOption() {
|
||||
return this.sortOptions.find(option => option.key === this.activeSort)
|
||||
.name;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
updateDisplayOption(option) {
|
||||
option.selected = !option.selected;
|
||||
// TODO: Update the display options
|
||||
},
|
||||
openSortMenu() {
|
||||
this.showSortMenu = !this.showSortMenu;
|
||||
},
|
||||
onSortOptionClick(key) {
|
||||
this.activeSort = key;
|
||||
this.showSortMenu = false;
|
||||
// TODO: Update the sort options
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -6,20 +6,27 @@
|
||||
<h1 class="font-medium text-slate-900 dark:text-slate-25 text-xl">
|
||||
{{ $t('INBOX.LIST.TITLE') }}
|
||||
</h1>
|
||||
<div
|
||||
role="button"
|
||||
class="flex gap-1 items-center py-1 px-2 border border-slate-100 dark:border-slate-700/50 rounded-md"
|
||||
@click="openInboxDisplayMenu"
|
||||
>
|
||||
<span
|
||||
class="text-slate-600 relative -top-px dark:text-slate-200 text-xs text-center font-medium"
|
||||
<div class="relative">
|
||||
<div
|
||||
role="button"
|
||||
class="flex gap-1 items-center py-1 px-2 border border-slate-100 dark:border-slate-700/50 rounded-md"
|
||||
@click="openInboxDisplayMenu"
|
||||
>
|
||||
{{ $t('INBOX.LIST.DISPLAY_DROPDOWN') }}
|
||||
</span>
|
||||
<fluent-icon
|
||||
icon="chevron-down"
|
||||
size="12"
|
||||
class="text-slate-600 dark:text-slate-200"
|
||||
<span
|
||||
class="text-slate-600 dark:text-slate-200 text-xs text-center font-medium"
|
||||
>
|
||||
{{ $t('INBOX.LIST.DISPLAY_DROPDOWN') }}
|
||||
</span>
|
||||
<fluent-icon
|
||||
icon="chevron-down"
|
||||
size="12"
|
||||
class="text-slate-600 dark:text-slate-200"
|
||||
/>
|
||||
</div>
|
||||
<inbox-display-menu
|
||||
v-if="showInboxDisplayMenu"
|
||||
v-on-clickaway="openInboxDisplayMenu"
|
||||
class="absolute top-8"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -50,19 +57,22 @@
|
||||
<script>
|
||||
import { mixin as clickaway } from 'vue-clickaway';
|
||||
import InboxOptionMenu from './InboxOptionMenu.vue';
|
||||
import InboxDisplayMenu from './InboxDisplayMenu.vue';
|
||||
export default {
|
||||
components: {
|
||||
InboxOptionMenu,
|
||||
InboxDisplayMenu,
|
||||
},
|
||||
mixins: [clickaway],
|
||||
data() {
|
||||
return {
|
||||
showInboxDisplayMenu: false,
|
||||
showInboxOptionMenu: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
openInboxDisplayMenu() {
|
||||
this.$emit('open-display-menu');
|
||||
this.showInboxDisplayMenu = !this.showInboxDisplayMenu;
|
||||
},
|
||||
openInboxOptionsMenu() {
|
||||
this.showInboxOptionMenu = !this.showInboxOptionMenu;
|
||||
|
||||
Reference in New Issue
Block a user