* Begin UI for threads and moderation overhaul * Hide close button on non-report threads * Fix review age coloring * Add project count * Remove action buttons from queue page and add queued date to project page * Hook up to actual data * Remove unused icon * Get up to 1000 projects in queue * prettier * more prettier * Changed all the things * lint * rebuild * Add omorphia * Workaround formatjs bug in ThreadSummary.vue * Fix notifications page on prod * Fix a few notifications and threads bugs * lockfile * Fix duplicate button styles * more fixes and polishing * More fixes * Remove legacy pages * More bugfixes * Add some error catching for reports and notifications * More error handling * fix lint * Add inbox links * Remove loading component and rename member header * Rely on threads always existing * Handle if project update notifs are not grouped * oops * Fix chips on notifications page * Import ModalModeration * finish threads * New authentication (#1234) * Initial new auth work * more auth pages * Finish most * more * fix on landing page * Finish everything but PATs + Sessions * fix threads merge bugs * fix cf pages ssr * fix most issues * Finish authentication * Fix merge --------- Co-authored-by: triphora <emma@modrinth.com> Co-authored-by: Jai A <jaiagr+gpg@pm.me> Co-authored-by: Geometrically <18202329+Geometrically@users.noreply.github.com>
137 lines
3.5 KiB
Vue
137 lines
3.5 KiB
Vue
<template>
|
|
<div>
|
|
<section class="universal-card">
|
|
<Breadcrumbs
|
|
v-if="history"
|
|
current-title="History"
|
|
:link-stack="[{ href: `/dashboard/notifications`, label: 'Notifications' }]"
|
|
/>
|
|
<div class="header__row">
|
|
<div class="header__title">
|
|
<h2 v-if="history">Notification history</h2>
|
|
<h2 v-else>Notifications</h2>
|
|
</div>
|
|
<template v-if="!history">
|
|
<Button v-if="allNotifs && allNotifs.some((notif) => notif.read)" @click="updateRoute()">
|
|
<HistoryIcon /> View history
|
|
</Button>
|
|
<Button v-if="notifications.length > 0" color="danger" @click="readAll()">
|
|
<CheckCheckIcon /> Mark all as read
|
|
</Button>
|
|
</template>
|
|
</div>
|
|
<template v-if="notifications.length > 0">
|
|
<Chips
|
|
v-if="notifTypes.length > 1"
|
|
v-model="selectedType"
|
|
:items="notifTypes"
|
|
:format-label="
|
|
(x) => (x === 'all' ? 'All' : $formatProjectType(x).replace('_', ' ') + 's')
|
|
"
|
|
:capitalize="false"
|
|
/>
|
|
<NotificationItem
|
|
v-for="notification in notifications"
|
|
:key="notification.id"
|
|
v-model:notifications="allNotifs"
|
|
class="universal-card recessed"
|
|
:notification="notification"
|
|
:auth="auth"
|
|
raised
|
|
/>
|
|
</template>
|
|
<p v-else>You don't have any unread notifications.</p>
|
|
</section>
|
|
</div>
|
|
</template>
|
|
<script setup>
|
|
import { Button, HistoryIcon } from 'omorphia'
|
|
import { fetchNotifications, groupNotifications, markAsRead } from '~/helpers/notifications.js'
|
|
import NotificationItem from '~/components/ui/NotificationItem.vue'
|
|
import Chips from '~/components/ui/Chips.vue'
|
|
import CheckCheckIcon from '~/assets/images/utils/check-check.svg'
|
|
import Breadcrumbs from '~/components/ui/Breadcrumbs.vue'
|
|
|
|
useHead({
|
|
title: 'Notifications - Modrinth',
|
|
})
|
|
|
|
const auth = await useAuth()
|
|
|
|
const route = useRoute()
|
|
const router = useRouter()
|
|
|
|
const history = computed(() => {
|
|
return route.name === 'dashboard-notifications-history'
|
|
})
|
|
|
|
const allNotifs = ref(null)
|
|
|
|
const notifTypes = computed(() => {
|
|
if (allNotifs.value === null) {
|
|
return []
|
|
}
|
|
const types = [
|
|
...new Set(
|
|
allNotifs.value
|
|
.filter((notification) => {
|
|
return history.value || !notification.read
|
|
})
|
|
.map((notif) => notif.type)
|
|
),
|
|
]
|
|
return types.length > 1 ? ['all', ...types] : types
|
|
})
|
|
|
|
const notifications = computed(() => {
|
|
if (allNotifs.value === null) {
|
|
return []
|
|
}
|
|
const groupedNotifs = groupNotifications(allNotifs.value, history.value)
|
|
return groupedNotifs.filter(
|
|
(notif) => selectedType.value === 'all' || notif.type === selectedType.value
|
|
)
|
|
})
|
|
|
|
const selectedType = ref('all')
|
|
|
|
await fetchNotifications().then((result) => {
|
|
allNotifs.value = result
|
|
})
|
|
|
|
function updateRoute() {
|
|
if (history.value) {
|
|
router.push('/dashboard/notifications')
|
|
} else {
|
|
router.push('/dashboard/notifications/history')
|
|
}
|
|
}
|
|
|
|
async function readAll() {
|
|
const ids = notifications.value.flatMap((notification) => [
|
|
notification.id,
|
|
...(notification.grouped_notifs ? notification.grouped_notifs.map((notif) => notif.id) : []),
|
|
])
|
|
|
|
const updateNotifs = await markAsRead(ids)
|
|
allNotifs.value = updateNotifs(allNotifs.value)
|
|
}
|
|
</script>
|
|
<style lang="scss" scoped>
|
|
.read-toggle-input {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--spacing-card-md);
|
|
|
|
.label__title {
|
|
margin: 0;
|
|
}
|
|
}
|
|
|
|
.header__title {
|
|
h2 {
|
|
margin: 0 auto 0 0;
|
|
}
|
|
}
|
|
</style>
|