diff --git a/web/src/components/Notifications/CriticalNotifications.standalone.vue b/web/src/components/Notifications/CriticalNotifications.standalone.vue index a40cf2818..d9595a267 100644 --- a/web/src/components/Notifications/CriticalNotifications.standalone.vue +++ b/web/src/components/Notifications/CriticalNotifications.standalone.vue @@ -11,6 +11,7 @@ import type { WarningAndAlertNotificationsQueryVariables, } from '~/composables/gql/graphql'; +import { NOTIFICATION_ICONS, NOTIFICATION_TOAST_COLORS } from '~/components/Notifications/constants'; import { archiveNotification, NOTIFICATION_FRAGMENT, @@ -95,19 +96,19 @@ const importanceMeta: Record< [NotificationImportance.ALERT]: { label: 'Alert', badge: 'bg-red-100 text-red-700 border border-red-300', - icon: 'i-lucide-octagon', + icon: NOTIFICATION_ICONS[NotificationImportance.ALERT], accent: 'text-red-600', }, [NotificationImportance.WARNING]: { label: 'Warning', badge: 'bg-amber-100 text-amber-700 border border-amber-300', - icon: 'i-lucide-alert-triangle', + icon: NOTIFICATION_ICONS[NotificationImportance.WARNING], accent: 'text-amber-600', }, [NotificationImportance.INFO]: { label: 'Info', badge: 'bg-blue-100 text-blue-700 border border-blue-300', - icon: 'i-lucide-alert-triangle', + icon: NOTIFICATION_ICONS[NotificationImportance.INFO], accent: 'text-blue-600', }, }; @@ -160,15 +161,7 @@ onNotificationAdded(({ data }) => { if (notification.timestamp) { // Trigger the global toast in tandem with the subscription update. - const funcMapping: Record< - NotificationImportance, - 'error' | 'warning' | 'info' | 'primary' | 'secondary' | 'success' | 'neutral' - > = { - [NotificationImportance.ALERT]: 'error', - [NotificationImportance.WARNING]: 'warning', - [NotificationImportance.INFO]: 'success', - }; - const color = funcMapping[notification.importance]; + const color = NOTIFICATION_TOAST_COLORS[notification.importance]; const createOpener = () => ({ label: 'Open', onClick: () => { @@ -194,7 +187,11 @@ onNotificationAdded(({ data }) => {
-
diff --git a/web/src/components/Notifications/Indicator.vue b/web/src/components/Notifications/Indicator.vue index c72b94e1e..1bcf4986b 100644 --- a/web/src/components/Notifications/Indicator.vue +++ b/web/src/components/Notifications/Indicator.vue @@ -5,6 +5,7 @@ import { cn } from '@unraid/ui'; import type { OverviewQuery } from '~/composables/gql/graphql'; +import { NOTIFICATION_COLORS, NOTIFICATION_ICONS } from '~/components/Notifications/constants'; import { NotificationImportance as Importance } from '~/composables/gql/graphql'; const props = defineProps<{ overview?: OverviewQuery['notifications']['overview']; seen?: boolean }>(); @@ -26,19 +27,18 @@ const indicatorLevel = computed(() => { }); const icon = computed<{ name: string; color: string } | null>(() => { - switch (indicatorLevel.value) { - case Importance.WARNING: - return { - name: 'i-heroicons-exclamation-triangle-20-solid', - color: 'text-yellow-500 translate-y-0.5', - }; - case Importance.ALERT: - return { - name: 'i-heroicons-shield-exclamation-20-solid', - color: 'text-unraid-red', - }; + const level = indicatorLevel.value; + + if (level !== Importance.WARNING && level !== Importance.ALERT) { + return null; } - return null; + + return { + name: NOTIFICATION_ICONS[level], + color: cn(NOTIFICATION_COLORS[level], { + 'translate-y-0.5': level === Importance.WARNING, + }), + }; }); diff --git a/web/src/components/Notifications/Item.vue b/web/src/components/Notifications/Item.vue index 5dd4d0a7f..e0d4e87f5 100644 --- a/web/src/components/Notifications/Item.vue +++ b/web/src/components/Notifications/Item.vue @@ -9,6 +9,7 @@ import { navigate } from '~/helpers/external-navigation'; import type { NotificationFragmentFragment } from '~/composables/gql/graphql'; +import { NOTIFICATION_COLORS, NOTIFICATION_ICONS } from '~/components/Notifications/constants'; import { archiveNotification as archiveMutation, deleteNotification as deleteMutation, @@ -29,24 +30,14 @@ const descriptionMarkup = computedAsync(async () => { }, ''); const icon = computed<{ name: string; color: string } | null>(() => { - switch (props.importance) { - case 'INFO': - return { - name: 'i-heroicons-check-badge-20-solid', - color: 'text-unraid-green', - }; - case 'WARNING': - return { - name: 'i-heroicons-exclamation-triangle-20-solid', - color: 'text-yellow-accent', - }; - case 'ALERT': - return { - name: 'i-heroicons-shield-exclamation-20-solid', - color: 'text-unraid-red', - }; + if (!props.importance || !NOTIFICATION_ICONS[props.importance]) { + return null; } - return null; + + return { + name: NOTIFICATION_ICONS[props.importance], + color: NOTIFICATION_COLORS[props.importance], + }; }); const archive = reactive( diff --git a/web/src/components/Notifications/List.vue b/web/src/components/Notifications/List.vue index a448faa2b..a4689534b 100644 --- a/web/src/components/Notifications/List.vue +++ b/web/src/components/Notifications/List.vue @@ -6,7 +6,9 @@ import { useQuery } from '@vue/apollo-composable'; import { vInfiniteScroll } from '@vueuse/components'; import { useDebounceFn } from '@vueuse/core'; -import { dbgApolloError, extractGraphQLErrorMessage } from '~/helpers/functions'; +import { extractGraphQLErrorMessage } from '~/helpers/functions'; + +// import { dbgApolloError } from '~/helpers/functions'; import type { ApolloError } from '@apollo/client/errors'; import type { diff --git a/web/src/components/Notifications/Sidebar.vue b/web/src/components/Notifications/Sidebar.vue index 7912d0955..d45837ffb 100644 --- a/web/src/components/Notifications/Sidebar.vue +++ b/web/src/components/Notifications/Sidebar.vue @@ -6,6 +6,7 @@ import { useMutation, useQuery, useSubscription } from '@vue/apollo-composable'; import { navigate } from '~/helpers/external-navigation'; import ConfirmDialog from '~/components/ConfirmDialog.vue'; +import { NOTIFICATION_TOAST_COLORS } from '~/components/Notifications/constants'; import { archiveAllNotifications, deleteArchivedNotifications, @@ -95,15 +96,7 @@ onNotificationAdded(({ data }) => { latestNotificationTimestamp.value = notif.timestamp; } - const funcMapping: Record< - Importance, - 'error' | 'warning' | 'info' | 'primary' | 'secondary' | 'success' | 'neutral' - > = { - [Importance.ALERT]: 'error', - [Importance.WARNING]: 'warning', - [Importance.INFO]: 'success', - }; - const color = funcMapping[notif.importance]; + const color = NOTIFICATION_TOAST_COLORS[notif.importance]; const createOpener = () => ({ label: t('notifications.sidebar.toastOpen'), onClick: () => navigate(notif.link as string), diff --git a/web/src/components/Notifications/constants.ts b/web/src/components/Notifications/constants.ts new file mode 100644 index 000000000..a7b6fabf6 --- /dev/null +++ b/web/src/components/Notifications/constants.ts @@ -0,0 +1,23 @@ +import { NotificationImportance } from '~/composables/gql/graphql'; + +export const NOTIFICATION_ICONS: Record = { + [NotificationImportance.INFO]: 'i-heroicons-check-badge-20-solid', + [NotificationImportance.WARNING]: 'i-heroicons-exclamation-triangle-20-solid', + [NotificationImportance.ALERT]: 'i-heroicons-shield-exclamation-20-solid', +}; + +export const NOTIFICATION_COLORS: Record = { + [NotificationImportance.INFO]: 'text-unraid-green', + [NotificationImportance.WARNING]: 'text-yellow-accent', + [NotificationImportance.ALERT]: 'text-unraid-red', +}; + +// Toast color mapping (used in Sidebar and CriticalNotifications) +export const NOTIFICATION_TOAST_COLORS: Record< + NotificationImportance, + 'error' | 'warning' | 'info' | 'success' +> = { + [NotificationImportance.ALERT]: 'error', + [NotificationImportance.WARNING]: 'warning', + [NotificationImportance.INFO]: 'success', +};