feat: move notification helper to store and add translation support

This commit is contained in:
Dominik Pschenitschni 2022-11-14 14:57:41 +01:00
parent def270bd08
commit 7075ab83cb
Signed by: dpschen
GPG Key ID: B257AC0149F43A77
4 changed files with 114 additions and 75 deletions

View File

@ -2,19 +2,19 @@
<div class="single-notification">
<div class="read-indicator" :class="{'read': notification.readAt !== null}" />
<user
class="user"
v-if="notification.notification.doer"
class="user"
:user="notification.notification.doer"
:show-username="false"
:avatar-size="16"
/>
<div class="detail">
<div>
<span class="has-text-weight-bold mr-1" v-if="notification.notification.doer">
<span v-if="notification.notification.doer" class="has-text-weight-bold mr-1">
{{ getDisplayName(notification.notification.doer) }}
</span>
<BaseButton :to="to" @click="emit('markNotificationAsRead')">
{{ notificationText }}
<BaseButton :to="getNotificationRoute(notification)" @click="emit('markNotificationAsRead')">
{{ getNotificationTitle(notification, userInfo) }}
</BaseButton>
</div>
<span class="created" v-tooltip="formatDateLong(notification.created)">
@ -27,17 +27,18 @@
<script setup lang="ts">
import {computed} from 'vue'
import {useAuthStore} from '@/stores/auth'
import type {INotification} from '@/modelTypes/INotification'
import {NOTIFICATION_NAMES, type INotification} from '@/modelTypes/INotification'
import BaseButton from '@/components/base/BaseButton.vue'
import User from '@/components/misc/user.vue'
import {useAuthStore} from '@/stores/auth'
import {formatDateLong, formatDateSince} from '@/helpers/time/formatDate'
import {getDisplayName} from '@/models/user'
import {getTextIdentifier} from '@/models/task'
import {getNotificationRoute, getNotificationTitle} from '@/services/notification'
const props = defineProps<{
defineProps<{
notification: INotification
}>()
@ -47,67 +48,6 @@ const emit = defineEmits<{
const authStore = useAuthStore()
const userInfo = computed(() => authStore.info)
const to = computed(() => {
const to = {
name: '',
params: {},
}
switch (props.notification.name) {
case NOTIFICATION_NAMES.TASK_COMMENT:
case NOTIFICATION_NAMES.TASK_ASSIGNED:
to.name = 'task.detail'
to.params.id = props.notification.notification.task.id
break
case NOTIFICATION_NAMES.TASK_DELETED:
// Nothing
break
case NOTIFICATION_NAMES.LIST_CREATED:
to.name = 'task.index'
to.params.listId = props.notification.notification.list.id
break
case NOTIFICATION_NAMES.TEAM_MEMBER_ADDED:
to.name = 'teams.edit'
to.params.id = props.notification.notification.team.id
break
default:
}
return to
})
const notificationText = computed(() => {
const notification = props.notification.notification
let who = ''
switch (props.notification.name) {
case NOTIFICATION_NAMES.TASK_COMMENT:
return `commented on ${getTextIdentifier(notification.task)}`
case NOTIFICATION_NAMES.TASK_ASSIGNED:
if (userInfo.value !== null && userInfo.value.id === notification.assignee.id) {
who = 'you'
} else {
who = `${getDisplayName(notification.assignee)}`
}
return `assigned ${who} to ${getTextIdentifier(notification.task)}`
case NOTIFICATION_NAMES.TASK_DELETED:
return `deleted ${getTextIdentifier(notification.task)}`
case NOTIFICATION_NAMES.LIST_CREATED:
return `created ${notification.list.title}`
case NOTIFICATION_NAMES.TEAM_MEMBER_ADDED:
if (userInfo.value !== null && userInfo.value.id === notification.member.id) {
who = 'you'
} else {
who = `${getDisplayName(notification.member)}`
}
return `added ${who} to the ${notification.team.name} team`
}
return ''
})
</script>
<style scoped lang="scss">

View File

@ -45,6 +45,8 @@ import type {INotification} from '@/modelTypes/INotification'
import NavbarTriggerButton from '@/components/home/NavbarTriggerButton.vue'
import NotificationItem from '@/components/notifications/NotificationItem.vue'
import {findIndexById} from '@/helpers/utils'
const NOTIFICATIONS_PULL_INTERVAL = 10000
const allNotifications = ref<INotification[]>([])
@ -90,11 +92,18 @@ async function loadNotifications() {
allNotifications.value = await notificationService.getAll()
}
async function markNotificationAsRead(index: number, notification: INotification) {
allNotifications.value[index] = await notificationService.update({
async function markNotificationAsRead(notification: INotification) {
const index = findIndexById(allNotifications.value, notification.id)
if (index === -1) {
return
}
allNotifications.value[index] = {
...notification,
read: true,
})
}
await notificationService.update(allNotifications.value[index])
}
</script>
@ -134,7 +143,6 @@ async function markNotificationAsRead(index: number, notification: INotification
.head {
font-family: $vikunja-font;
font-size: 1rem;
padding: .5rem;
}
.notification-item:last-child {

View File

@ -945,7 +945,26 @@
"notification": {
"title": "Notifications",
"none": "You don't have any notifications. Have a nice day!",
"explainer": "Notifications will appear here when actions on namespaces, lists or tasks you subscribed to happen."
"explainer": "Notifications will appear here when actions on namespaces, lists or tasks you subscribed to happen.",
"items": {
"taskComment": {
"message": "commented on {taskIdentifier}"
},
"taskAssigned": {
"message": "assigned {user} to {taskIdentifier}",
"userYou": "you"
},
"taskDeleted": {
"message": "deleted {taskIdentifier}"
},
"listCreated": {
"message": "created {listTitle}"
},
"teamMemberAdded": {
"message": "added ${user} to the {teamName} team",
"userYou": "you"
}
}
},
"quickActions": {
"commands": "Commands",

View File

@ -1,6 +1,78 @@
import AbstractService from '@/services/abstractService'
import NotificationModel from '@/models/notification'
import type {INotification} from '@/modelTypes/INotification'
import {NOTIFICATION_NAMES, type INotification} from '@/modelTypes/INotification'
import type {IUser} from '@/modelTypes/IUser'
import {getTextIdentifier} from '@/models/task'
import {getDisplayName} from '@/models/user'
import {i18n} from '@/i18n'
export function getNotificationTitle(notificationItem: INotification, user: IUser | null) {
const notification = notificationItem.notification
let who: string
switch (notificationItem.name) {
case NOTIFICATION_NAMES.TASK_COMMENT:
return i18n.global.t('notification.items.taskComment.message', { taskIdentifier: getTextIdentifier(notification.task)})
case NOTIFICATION_NAMES.TASK_ASSIGNED:
who = (user !== null && user.id === notification.assignee.id)
? i18n.global.t('notification.items.taskAssigned.userYou')
: `${getDisplayName(notification.assignee)}`
return i18n.global.t('notification.items.taskAssigned.message', {
user: who,
taskIdentifier: getTextIdentifier(notification.task),
})
case NOTIFICATION_NAMES.TASK_DELETED:
// TODO: add user to title
return i18n.global.t('notification.items.taskDeleted.message', {
taskIdentifier: getTextIdentifier(notification.task),
})
case NOTIFICATION_NAMES.LIST_CREATED:
return i18n.global.t('notification.items.listCreated.message', {
listTitle: notification.list.title,
})
case NOTIFICATION_NAMES.TEAM_MEMBER_ADDED:
who = (user !== null && user.id === notification.member.id)
? i18n.global.t('notification.items.teamMemberAdded.userYou')
: `${getDisplayName(notification.member)}`
return i18n.global.t('notification.items.teamMemberAdded.message', {
user: who,
teamName: notification.team.name,
})
}
}
export function getNotificationRoute(notificationItem: INotification) {
const to = {
name: '',
params: {},
}
switch (notificationItem.name) {
case NOTIFICATION_NAMES.TASK_COMMENT:
case NOTIFICATION_NAMES.TASK_ASSIGNED:
to.name = 'task.detail'
to.params.id = notificationItem.notification.task.id
break
case NOTIFICATION_NAMES.TASK_DELETED:
// Nothing
break
case NOTIFICATION_NAMES.LIST_CREATED:
to.name = 'task.index'
to.params.listId = notificationItem.notification.list.id
break
case NOTIFICATION_NAMES.TEAM_MEMBER_ADDED:
to.name = 'teams.edit'
to.params.id = notificationItem.notification.team.id
break
default:
return undefined
}
return to
}
export default class NotificationService extends AbstractService<INotification> {
constructor() {