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",
|
"MARK_ALL_READ": "Mark all as read",
|
||||||
"DELETE_ALL": "Delete all",
|
"DELETE_ALL": "Delete all",
|
||||||
"DELETE_ALL_READ": "Delete all read"
|
"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];
|
const targetNotification = this.notifications[activeIndex + indexOffset];
|
||||||
if (targetNotification) {
|
if (targetNotification) {
|
||||||
const {
|
const {
|
||||||
|
id,
|
||||||
primary_actor_id: primaryActorId,
|
primary_actor_id: primaryActorId,
|
||||||
primary_actor_type: primaryActorType,
|
primary_actor_type: primaryActorType,
|
||||||
primary_actor: { id: conversationId, meta: { unreadCount } = {} },
|
primary_actor: { id: conversationId, meta: { unreadCount } = {} },
|
||||||
@@ -177,6 +178,7 @@ export default {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.$store.dispatch('notifications/read', {
|
this.$store.dispatch('notifications/read', {
|
||||||
|
id,
|
||||||
primaryActorId,
|
primaryActorId,
|
||||||
primaryActorType,
|
primaryActorType,
|
||||||
unreadCount,
|
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,13 +6,14 @@
|
|||||||
<h1 class="font-medium text-slate-900 dark:text-slate-25 text-xl">
|
<h1 class="font-medium text-slate-900 dark:text-slate-25 text-xl">
|
||||||
{{ $t('INBOX.LIST.TITLE') }}
|
{{ $t('INBOX.LIST.TITLE') }}
|
||||||
</h1>
|
</h1>
|
||||||
|
<div class="relative">
|
||||||
<div
|
<div
|
||||||
role="button"
|
role="button"
|
||||||
class="flex gap-1 items-center py-1 px-2 border border-slate-100 dark:border-slate-700/50 rounded-md"
|
class="flex gap-1 items-center py-1 px-2 border border-slate-100 dark:border-slate-700/50 rounded-md"
|
||||||
@click="openInboxDisplayMenu"
|
@click="openInboxDisplayMenu"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="text-slate-600 relative -top-px dark:text-slate-200 text-xs text-center font-medium"
|
class="text-slate-600 dark:text-slate-200 text-xs text-center font-medium"
|
||||||
>
|
>
|
||||||
{{ $t('INBOX.LIST.DISPLAY_DROPDOWN') }}
|
{{ $t('INBOX.LIST.DISPLAY_DROPDOWN') }}
|
||||||
</span>
|
</span>
|
||||||
@@ -22,6 +23,12 @@
|
|||||||
class="text-slate-600 dark:text-slate-200"
|
class="text-slate-600 dark:text-slate-200"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<inbox-display-menu
|
||||||
|
v-if="showInboxDisplayMenu"
|
||||||
|
v-on-clickaway="openInboxDisplayMenu"
|
||||||
|
class="absolute top-8"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex relative gap-1 items-center">
|
<div class="flex relative gap-1 items-center">
|
||||||
<!-- <woot-button
|
<!-- <woot-button
|
||||||
@@ -50,19 +57,22 @@
|
|||||||
<script>
|
<script>
|
||||||
import { mixin as clickaway } from 'vue-clickaway';
|
import { mixin as clickaway } from 'vue-clickaway';
|
||||||
import InboxOptionMenu from './InboxOptionMenu.vue';
|
import InboxOptionMenu from './InboxOptionMenu.vue';
|
||||||
|
import InboxDisplayMenu from './InboxDisplayMenu.vue';
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
InboxOptionMenu,
|
InboxOptionMenu,
|
||||||
|
InboxDisplayMenu,
|
||||||
},
|
},
|
||||||
mixins: [clickaway],
|
mixins: [clickaway],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
showInboxDisplayMenu: false,
|
||||||
showInboxOptionMenu: false,
|
showInboxOptionMenu: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
openInboxDisplayMenu() {
|
openInboxDisplayMenu() {
|
||||||
this.$emit('open-display-menu');
|
this.showInboxDisplayMenu = !this.showInboxDisplayMenu;
|
||||||
},
|
},
|
||||||
openInboxOptionsMenu() {
|
openInboxOptionsMenu() {
|
||||||
this.showInboxOptionMenu = !this.showInboxOptionMenu;
|
this.showInboxOptionMenu = !this.showInboxOptionMenu;
|
||||||
|
|||||||
Reference in New Issue
Block a user