feat: move notification helper to store and add translation support
This commit is contained in:
parent
def270bd08
commit
7075ab83cb
|
@ -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">
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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() {
|
||||
|
|
Reference in New Issue