Add item count to notification drawer (#23414)

Co-authored-by: Pascal Jufer <pascal-jufer@bluewin.ch>
This commit is contained in:
Dominic Marcelino
2024-08-20 12:51:32 +02:00
committed by GitHub
parent d7267ca6be
commit 772b2901f1
3 changed files with 92 additions and 29 deletions

View File

@@ -0,0 +1,5 @@
---
'@directus/app': minor
---
Added item count to the notification drawer

View File

@@ -1,4 +1,4 @@
import { useI18n } from 'vue-i18n';
import { ComposerNumberFormatting, ComposerTranslation, useI18n } from 'vue-i18n';
export type FormatItemsCountPaginatedOptions = {
currentItems: number;
@@ -6,6 +6,7 @@ export type FormatItemsCountPaginatedOptions = {
perPage: number;
isFiltered?: boolean;
totalItems?: number;
i18n?: { t: ComposerTranslation; n: ComposerNumberFormatting };
};
export function formatItemsCountPaginated({
@@ -14,8 +15,9 @@ export function formatItemsCountPaginated({
perPage,
isFiltered,
totalItems,
i18n,
}: FormatItemsCountPaginatedOptions) {
const { t, n } = useI18n();
const { t, n } = i18n ? i18n : useI18n();
const values = {
start: n((currentPage - 1) * perPage + 1),
@@ -39,14 +41,16 @@ export type FormatItemsCountRelativeOptions = {
totalItems: number;
currentItems: number;
isFiltered?: boolean;
i18n?: { t: ComposerTranslation; n: ComposerNumberFormatting };
};
export function formatItemsCountRelative({
totalItems,
currentItems,
isFiltered = false,
i18n,
}: FormatItemsCountRelativeOptions) {
const { t, n } = useI18n();
const { t, n } = i18n ? i18n : useI18n();
const values = {
count: n(currentItems),

View File

@@ -4,11 +4,13 @@ import useDatetime from '@/components/use-datetime.vue';
import { useCollectionsStore } from '@/stores/collections';
import { useNotificationsStore } from '@/stores/notifications';
import { useUserStore } from '@/stores/user';
import { formatItemsCountPaginated } from '@/utils/format-items-count';
import { getCollectionRoute, getItemRoute } from '@/utils/get-route';
import SearchInput from '@/views/private/components/search-input.vue';
import { useItems } from '@directus/composables';
import { useAppStore } from '@directus/stores';
import { Filter, Notification } from '@directus/types';
import { mergeFilters } from '@directus/utils';
import { storeToRefs } from 'pinia';
import { computed, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n';
@@ -18,7 +20,7 @@ type LocalNotification = Notification & {
to?: string;
};
const { t } = useI18n();
const { t, n } = useI18n();
const appStore = useAppStore();
const userStore = useUserStore();
const collectionsStore = useCollectionsStore();
@@ -69,30 +71,36 @@ function toggleNotification(id: string) {
}
}
const filter = computed(() => ({
_and: [
{
recipient: {
_eq: userStore.currentUser!.id,
},
},
{
status: {
_eq: tab.value[0],
},
},
userFilter.value,
],
}));
const filterSystem = computed(
() =>
({
_and: [
{
recipient: {
_eq: userStore.currentUser!.id,
},
},
{
status: {
_eq: tab.value[0],
},
},
],
}) as Filter,
);
const { items, loading, getItems, totalPages, getItemCount } = useItems(ref('directus_notifications'), {
filter,
fields: ref(['id', 'subject', 'message', 'collection', 'item', 'timestamp']),
sort: ref(['-timestamp']),
search,
limit,
page,
});
const { items, loading, totalPages, totalCount, itemCount, getItems, getItemCount, getTotalCount } = useItems(
collection,
{
filter: computed(() => mergeFilters(filter.value, filterSystem.value)),
filterSystem,
fields: ref(['id', 'subject', 'message', 'collection', 'item', 'timestamp']),
sort: ref(['-timestamp']),
search,
limit,
page,
},
);
const notifications = computed<LocalNotification[]>(() => {
return items.value.map((item) => {
@@ -117,9 +125,24 @@ const notifications = computed<LocalNotification[]>(() => {
});
});
const showingCount = computed(() => {
// Don't show count if there are no items
if (!totalCount.value || !itemCount.value) return;
return formatItemsCountPaginated({
currentItems: itemCount.value,
currentPage: page.value,
perPage: limit.value,
isFiltered: !!filter.value,
totalItems: totalCount.value,
i18n: { t, n },
});
});
async function refresh() {
await getItemCount();
await getItems();
await getTotalCount();
await getItemCount();
}
async function archiveAll() {
@@ -168,8 +191,16 @@ function onLinkClick(to: string) {
:sidebar-label="t('folders')"
@cancel="notificationsDrawerOpen = false"
>
<template #actions:prepend>
<transition name="fade">
<span v-if="showingCount" class="item-count">
{{ showingCount }}
</span>
</transition>
</template>
<template #actions>
<search-input v-model="search" v-model:filter="userFilter" collection="directus_notifications" />
<search-input v-model="search" v-model:filter="filter" collection="directus_notifications" />
<v-button
v-tooltip.bottom="tab[0] === 'inbox' ? t('archive') : t('unarchive')"
icon
@@ -268,6 +299,19 @@ function onLinkClick(to: string) {
</template>
<style lang="scss" scoped>
.item-count {
position: relative;
display: none;
margin: 0 8px;
color: var(--theme--foreground-subdued);
white-space: nowrap;
align-self: center;
@media (min-width: 600px) {
display: inline;
}
}
.content {
padding: 0px var(--content-padding) var(--content-padding-bottom) var(--content-padding);
}
@@ -325,4 +369,14 @@ function onLinkClick(to: string) {
}
}
}
.fade-enter-active,
.fade-leave-active {
transition: opacity var(--medium) var(--transition);
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
</style>