chore(front): Notifications

This commit is contained in:
ArneBo 2025-03-21 10:29:09 +01:00
parent 89d9aedd9e
commit e31c6c0e74
2 changed files with 172 additions and 170 deletions

View File

@ -13,7 +13,8 @@ import Button from '~/components/ui/Button.vue'
import Popover from '~/components/ui/Popover.vue' import Popover from '~/components/ui/Popover.vue'
import PopoverItem from '~/components/ui/popover/PopoverItem.vue' import PopoverItem from '~/components/ui/popover/PopoverItem.vue'
import PopoverSubmenu from '~/components/ui/popover/PopoverSubmenu.vue' import PopoverSubmenu from '~/components/ui/popover/PopoverSubmenu.vue'
import Link from '~/components/ui/Link.vue' import Spacer from '~/components/ui/Spacer.vue'
import Pill from '~/components/ui/Pill.vue'
const route = useRoute() const route = useRoute()
const store = useStore() const store = useStore()
@ -75,13 +76,6 @@ const labels = computed(() => ({
/> />
</Button> </Button>
<template #items> <template #items>
<PopoverItem v-if="store.state.ui.notifications.inbox /* TODO: Check: + additionalNotifications */ > 0">
<Link :to="{name: 'notifications'}">
<i class="bi bi-inbox-fill" />
{{ store.state.ui.notifications.inbox /* TODO: Check: + additionalNotifications */ }}
{{ labels.notifications }}
</Link>
</PopoverItem>
<PopoverItem <PopoverItem
v-if="store.state.auth.authenticated" v-if="store.state.auth.authenticated"
:to="{name: 'profile.overview', params: { username: store.state.auth.username },}" :to="{name: 'profile.overview', params: { username: store.state.auth.username },}"
@ -89,6 +83,26 @@ const labels = computed(() => ({
<i class="bi bi-person-fill" /> <i class="bi bi-person-fill" />
{{ labels.profile }} {{ labels.profile }}
</PopoverItem> </PopoverItem>
<PopoverItem
v-if="store.state.auth.authenticated"
:to="{name: 'notifications'}"
>
<i class="bi bi-inbox-fill" />
{{ labels.notifications }}
<Spacer grow />
<div
v-if="store.state.ui.notifications.inbox > 0"
:title="labels.notifications"
style="
background: var(--fw-gray-400);
color: var(--fw-gray-800);
padding: 2px 7px;
border-radius: 10px;
"
>
{{ store.state.ui.notifications.inbox }}
</div>
</PopoverItem>
<PopoverItem <PopoverItem
v-if="store.state.auth.authenticated" v-if="store.state.auth.authenticated"
:to="{ path: '/settings' }" :to="{ path: '/settings' }"

View File

@ -14,6 +14,15 @@ import useWebSocketHandler from '~/composables/useWebSocketHandler'
import useErrorHandler from '~/composables/useErrorHandler' import useErrorHandler from '~/composables/useErrorHandler'
import useMarkdown from '~/composables/useMarkdown' import useMarkdown from '~/composables/useMarkdown'
import Layout from '~/components/ui/Layout.vue'
import Loader from '~/components/ui/Loader.vue'
import Spacer from '~/components/ui/Spacer.vue'
import Header from '~/components/ui/Header.vue'
import Toggle from '~/components/ui/Toggle.vue'
import Button from '~/components/ui/Button.vue'
import Alert from '~/components/ui/Alert.vue'
import Table from '~/components/ui/Table.vue'
const store = useStore() const store = useStore()
const supportMessage = useMarkdown(() => store.state.instance.settings.instance.support_message.value) const supportMessage = useMarkdown(() => store.state.instance.settings.instance.support_message.value)
const { t } = useI18n() const { t } = useI18n()
@ -90,180 +99,159 @@ const markAllAsRead = async () => {
</script> </script>
<template> <template>
<main <Layout
main
stack
v-title="labels.title" v-title="labels.title"
class="main page-notifications" class="main page-notifications"
> >
<section class="ui vertical aligned stripe segment"> <div
<div class="ui container"> v-if="additionalNotifications"
>
<Header :h1="t('views.Notifications.header.messages')" />
<Layout flex>
<div <div
v-if="additionalNotifications" v-if="showInstanceSupportMessage"
class="ui container"
> >
<h1 class="ui header"> <Alert blue>
{{ t('views.Notifications.header.messages') }} <h4 class="header">
</h1> {{ t('views.Notifications.header.instanceSupport') }}
<div class="ui two column stackable grid"> </h4>
<div <sanitized-html :html="supportMessage" />
v-if="showInstanceSupportMessage" </Alert>
class="column" <div class="ui bottom attached segment">
<form
class="ui inline form"
@submit.prevent="setDisplayDate('instance_support_message_display_date', instanceSupportMessageDelay)"
> >
<div class="ui attached info message"> <div class="inline field">
<h4 class="header"> <label for="instance-reminder-delay">
{{ t('views.Notifications.header.instanceSupport') }} {{ t('views.Notifications.label.reminder') }}
</h4> </label>
<sanitized-html :html="supportMessage" /> <select
</div> id="instance-reminder-delay"
<div class="ui bottom attached segment"> v-model="instanceSupportMessageDelay"
<form
class="ui inline form"
@submit.prevent="setDisplayDate('instance_support_message_display_date', instanceSupportMessageDelay)"
> >
<div class="inline field"> <option :value="30">
<label for="instance-reminder-delay"> {{ t('views.Notifications.option.delay.30') }}
{{ t('views.Notifications.label.reminder') }} </option>
</label> <option :value="60">
<select {{ t('views.Notifications.option.delay.60') }}
id="instance-reminder-delay" </option>
v-model="instanceSupportMessageDelay" <option :value="90">
> {{ t('views.Notifications.option.delay.90') }}
<option :value="30"> </option>
{{ t('views.Notifications.option.delay.30') }} <!-- NOTE: Postpone notification 100 years, so that the user never sees it -->
</option> <option :value="36500">
<option :value="60"> {{ t('views.Notifications.option.delay.never') }}
{{ t('views.Notifications.option.delay.60') }} </option>
</option> </select>
<option :value="90"> <Button
{{ t('views.Notifications.option.delay.90') }} type="submit"
</option> secondary
<!-- NOTE: Postpone notification 100 years, so that the user never sees it -->
<option :value="36500">
{{ t('views.Notifications.option.delay.never') }}
</option>
</select>
<button
type="submit"
class="ui right floated basic button"
>
{{ t('views.Notifications.button.submit') }}
</button>
</div>
</form>
</div>
</div>
<div
v-if="showFunkwhaleSupportMessage"
class="column"
>
<div class="ui info attached message">
<h4 class="header">
{{ t('views.Notifications.header.funkwhaleSupport') }}
</h4>
<p>
{{ t('views.Notifications.message.funkwhaleSupport') }}
</p>
<a
href="https://funkwhale.audio/donate"
target="_blank"
rel="noopener"
class="ui primary inverted button"
> >
{{ t('views.Notifications.link.donate') }} {{ t('views.Notifications.button.submit') }}
</a> </Button>
<a
href="https://contribute.funkwhale.audio"
target="_blank"
rel="noopener"
class="ui secondary inverted button"
>
{{ t('views.Notifications.link.help') }}
</a>
</div> </div>
<div class="ui bottom attached segment"> </form>
<form
class="ui inline form"
@submit.prevent="setDisplayDate('funkwhale_support_message_display_date', funkwhaleSupportMessageDelay)"
>
<div class="inline field">
<label for="funkwhale-reminder-delay">
{{ t('views.Notifications.label.reminder') }}
</label>
<select
id="funkwhale-reminder-delay"
v-model="funkwhaleSupportMessageDelay"
>
<option :value="30">
{{ t('views.Notifications.option.delay.30') }}
</option>
<option :value="60">
{{ t('views.Notifications.option.delay.60') }}
</option>
<option :value="90">
{{ t('views.Notifications.option.delay.90') }}
</option>
<!-- NOTE: Postpone notification 100 years, so that the user never sees it -->
<option :value="36500">
{{ t('views.Notifications.option.delay.never') }}
</option>
</select>
<button
type="submit"
class="ui right floated basic button"
>
{{ t('views.Notifications.button.submit') }}
</button>
</div>
</form>
</div>
</div>
</div> </div>
</div> </div>
<h1 class="ui header"> <Alert
{{ t('views.Notifications.header.notifications') }} v-if="showFunkwhaleSupportMessage"
</h1> blue
<div class="ui toggle checkbox"> >
<input <h4 class="header">
id="show-read-notifications" {{ t('views.Notifications.header.funkwhaleSupport') }}
v-model="filters.is_read" </h4>
type="checkbox" <p>
{{ t('views.Notifications.message.funkwhaleSupport') }}
</p>
<a
href="https://funkwhale.audio/donate"
target="_blank"
rel="noopener"
class="ui primary inverted button"
> >
<label for="show-read-notifications">{{ t('views.Notifications.label.showRead') }}</label> {{ t('views.Notifications.link.donate') }}
</div> </a>
<button <a
v-if="filters.is_read === false && notifications.count > 0" href="https://contribute.funkwhale.audio"
class="ui basic labeled icon right floated button" target="_blank"
@click.prevent="markAllAsRead" rel="noopener"
> class="ui secondary inverted button"
<i class="ui check icon" /> >
{{ t('views.Notifications.button.read') }} {{ t('views.Notifications.link.help') }}
</button> </a>
<div class="ui hidden divider" /> <template #actions>
<form
class="ui inline form"
@submit.prevent="setDisplayDate('funkwhale_support_message_display_date', funkwhaleSupportMessageDelay)"
>
<Layout flex>
<label for="funkwhale-reminder-delay" style="align-self: center;">
{{ t('views.Notifications.label.reminder') }}
</label>
<select
id="funkwhale-reminder-delay"
class="ui dropdown"
style="margin-top: 0px;"
v-model="funkwhaleSupportMessageDelay"
>
<option :value="30">
{{ t('views.Notifications.option.delay.30') }}
</option>
<option :value="60">
{{ t('views.Notifications.option.delay.60') }}
</option>
<option :value="90">
{{ t('views.Notifications.option.delay.90') }}
</option>
<!-- NOTE: Postpone notification 100 years, so that the user never sees it -->
<option :value="36500">
{{ t('views.Notifications.option.delay.never') }}
</option>
</select>
<Button
type="submit"
primary
>
{{ t('views.Notifications.button.submit') }}
</Button>
</Layout>
</form>
</template>
</Alert>
</Layout>
</div>
<Header :h1="t('views.Notifications.header.notifications')" />
<Toggle
id="show-read-notifications"
v-model="filters.is_read"
:label="t('views.Notifications.label.showRead')"
/>
<Button
v-if="filters.is_read === false && notifications.count > 0"
secondary
@click.prevent="markAllAsRead"
icon="bi-check-all"
>
{{ t('views.Notifications.button.read') }}
</Button>
<div <Loader v-if="isLoading" />
v-if="isLoading"
:class="['ui', {'active': isLoading}, 'inverted', 'dimmer']"
>
<div class="ui text loader">
{{ t('views.Notifications.loading.notifications') }}
</div>
</div>
<table <Table
v-else-if="notifications.count > 0" v-else-if="notifications.count > 0"
class="ui table" :gridTemplateColumns="['auto', 'auto', 'auto', 'auto']"
> >
<tbody> <notification-row
<notification-row v-for="item in notifications.results"
v-for="item in notifications.results" :key="item.id"
:key="item.id" :initial-item="item"
:initial-item="item" />
/> </Table>
</tbody> <p v-else-if="additionalNotifications === 0">
</table> {{ t('views.Notifications.empty.notifications') }}
<p v-else-if="additionalNotifications === 0"> </p>
{{ t('views.Notifications.empty.notifications') }} </Layout>
</p>
</div>
</section>
</main>
</template> </template>