Refactor: Improve display of notifications to indicate severity. This allow user to disable toasts and just rely on color coding

This commit is contained in:
arabcoders 2025-11-20 16:49:50 +03:00
parent c74c6ed60e
commit 4d22e345e5
3 changed files with 54 additions and 4 deletions

View file

@ -45,11 +45,12 @@
<div class="navbar-item has-dropdown is-hoverable"> <div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link"> <a class="navbar-link">
<span class="icon"><i class="fas fa-bell" /></span> <span class="icon"><i class="fas fa-bell" /></span>
<span class="tag ml-2"> <span class="tag ml-2" :class="store.severityColor">
<span class="is-underlined">{{ store.unreadCount }}</span> <span :class="{ 'is-bold': store.unreadCount }">{{ store.unreadCount }}</span>
<span>&nbsp;/&nbsp;</span> <span>&nbsp;/&nbsp;</span>
<span class="is-underlined">{{ store.notifications.length }}</span> <span class="is-underlined">{{ store.notifications.length }}</span>
</span> </span>
<span class="icon ml-2" v-if="store.severityIcon"><i :class="store.severityIcon" /></span>
</a> </a>
<div class="navbar-dropdown is-right" style="width: 400px;"> <div class="navbar-dropdown is-right" style="width: 400px;">
<template v-if="store.notifications.length > 0"> <template v-if="store.notifications.length > 0">

View file

@ -204,7 +204,7 @@ const pauseDownload = () => {
dialog_confirm.value.visible = true dialog_confirm.value.visible = true
dialog_confirm.value.html_message = ` dialog_confirm.value.html_message = `
<span class="icon-text"> <span class="icon-text">
<span class="icon"><i class="fa-solid fa-exclamation-triangle"/></span> <span class="icon"><i class="fa-solid fa-exclamation-triangle"></i></span>
<span class="is-bold">Pause All non-active downloads?</span> <span class="is-bold">Pause All non-active downloads?</span>
</span> </span>
<br> <br>

View file

@ -2,10 +2,46 @@ import { defineStore } from 'pinia'
import { useStorage } from '@vueuse/core' import { useStorage } from '@vueuse/core'
import type { notification, notificationType } from '~/composables/useNotification' import type { notification, notificationType } from '~/composables/useNotification'
const _map: Record<notificationType, { level: number; color: string; icon: string }> = {
'error': { level: 3, color: 'is-danger', icon: 'fas fa-circle-exclamation' },
'warning': { level: 2, color: 'is-warning', icon: 'fas fa-triangle-exclamation' },
'success': { level: 1, color: 'is-primary', icon: 'fas fa-circle-check' },
'info': { level: 0, color: 'is-info', icon: 'fas fa-circle-info' }
}
export const useNotificationStore = defineStore('notifications', () => { export const useNotificationStore = defineStore('notifications', () => {
const notifications = useStorage<notification[]>('notifications', []) const notifications = useStorage<notification[]>('notifications', [])
const unreadCount = computed<number>(() => notifications.value.filter(n => !n.seen).length) const unreadCount = computed<number>(() => notifications.value.filter(n => !n.seen).length)
const severityLevel = computed<notificationType | null>(() => {
const unread = notifications.value.filter(n => !n.seen)
if (0 === unread.length) {
return null
}
return unread.reduce((h, n) => _map[n.level].level > _map[h.level].level ? n : h).level
})
const severityColor = computed<string>(() => {
const level = severityLevel.value
return level ? _map[level].color : ''
})
const severityIcon = computed<string>(() => {
const level = severityLevel.value
return level ? _map[level].icon : ''
})
const sortedNotifications = computed<notification[]>(() => {
return [...notifications.value].sort((a, b) => {
const severityDiff = _map[b.level].level - _map[a.level].level
if (0 !== severityDiff) {
return severityDiff
}
return (new Date(b.created).getTime()) - (new Date(a.created).getTime())
})
})
const add = (level: notificationType, message: string, seen: boolean = false): string => { const add = (level: notificationType, message: string, seen: boolean = false): string => {
const id = Array.from( const id = Array.from(
window.crypto.getRandomValues(new Uint8Array(14 / 2)), window.crypto.getRandomValues(new Uint8Array(14 / 2)),
@ -43,5 +79,18 @@ export const useNotificationStore = defineStore('notifications', () => {
const remove = (id: string) => notifications.value = notifications.value.filter(n => n.id !== id) const remove = (id: string) => notifications.value = notifications.value.filter(n => n.id !== id)
return { notifications, unreadCount, add, get, markAllRead, clear, markRead, remove } return {
notifications,
unreadCount,
severityLevel,
severityColor,
severityIcon,
sortedNotifications,
add,
get,
markAllRead,
clear,
markRead,
remove
}
}) })