feat: Inbox list display menu (#8847)

* feat: Inbox list display menu

* chore: Fix alignment
This commit is contained in:
Sivin Varghese
2024-02-04 10:23:16 +05:30
committed by GitHub
parent 0c35a77d4b
commit 45e630fc60
4 changed files with 210 additions and 14 deletions

View File

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

View File

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

View File

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

View File

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