3ca4a11ca3
* feat: basic notification listener sturcuture * feat: clean up generated gql * chore: edited structure * feat: added basic repo * feat: ported comment email to job queue * feat: ported stream access request accepted * feat: added notification insertion * fix: minor typings * feat: delayed notifications * updated types * feat: fixed gql * notifications are listed * index on notifications * feat: while loop skiping for update locked * delayed notification for access request * take into account user prefrences * on comment view, notification is marked as read * feat: added gql notifications * feat: avoid raising errors * fix: error added scopes * fix: mr comments * fix: cursor and service method * feat: added stronger types to notifications and versioning logic * minor: rows updated
80 lines
3.4 KiB
TypeScript
80 lines
3.4 KiB
TypeScript
import type { NotificationPreferences } from '@/modules/notifications/helpers/types'
|
|
import { NotificationChannel } from '@/modules/notifications/helpers/types'
|
|
import { InvalidArgumentError } from '@/modules/shared/errors'
|
|
import type {
|
|
GetSavedUserNotificationPreferences,
|
|
GetUserNotificationPreferences,
|
|
GetUserPreferenceForNotificationType,
|
|
SaveUserNotificationPreferences
|
|
} from '@/modules/notifications/domain/operations'
|
|
import { NotificationType } from '@speckle/shared/notifications'
|
|
|
|
export const getUserNotificationPreferencesFactory =
|
|
(deps: {
|
|
getSavedUserNotificationPreferences: GetSavedUserNotificationPreferences
|
|
}): GetUserNotificationPreferences =>
|
|
async (userId: string): Promise<NotificationPreferences> => {
|
|
const savedPreferences = await deps.getSavedUserNotificationPreferences(userId)
|
|
return addDefaultPreferenceValues(savedPreferences)
|
|
}
|
|
|
|
function addDefaultPreferenceValues(
|
|
preferences: NotificationPreferences
|
|
): NotificationPreferences {
|
|
const savedPreferences = { ...preferences }
|
|
|
|
Object.values(NotificationType).forEach((nt) => {
|
|
const notificationTypeSettings = savedPreferences[nt] ?? {}
|
|
|
|
Object.values(NotificationChannel).forEach((nc) => {
|
|
notificationTypeSettings[nc] = notificationTypeSettings[nc] ?? true
|
|
})
|
|
savedPreferences[nt] = notificationTypeSettings
|
|
})
|
|
return savedPreferences
|
|
}
|
|
|
|
export const getUserPreferenceForNotificationTypeFactory =
|
|
(deps: {
|
|
getSavedUserNotificationPreferences: GetSavedUserNotificationPreferences
|
|
}): GetUserPreferenceForNotificationType =>
|
|
async (userId, notificationType, notificationChannel) => {
|
|
const preferences = await deps.getSavedUserNotificationPreferences(userId)
|
|
if (!preferences) return true
|
|
|
|
const notificationTypeSettings = preferences[notificationType]
|
|
return notificationTypeSettings?.[notificationChannel] ?? false
|
|
}
|
|
|
|
export const updateNotificationPreferencesFactory =
|
|
(deps: { saveUserNotificationPreferences: SaveUserNotificationPreferences }) =>
|
|
async (userId: string, rawPreferences: Record<string, unknown>): Promise<void> => {
|
|
const parsedPreferences: NotificationPreferences = {}
|
|
// lets do some nested attribute copying, to sanitize the input
|
|
for (const key in rawPreferences) {
|
|
if (!Object.values(NotificationType).includes(key as NotificationType))
|
|
throw new InvalidArgumentError(
|
|
`Notification preferences input contains an unknown setting: ${key}`
|
|
)
|
|
const nt = key as NotificationType
|
|
const notificationTypePreferences: Partial<Record<NotificationChannel, boolean>> =
|
|
{}
|
|
const notificationTypeSettings = rawPreferences[nt] as Record<string, unknown>
|
|
for (const ncKey in notificationTypeSettings) {
|
|
if (!Object.values(NotificationChannel).includes(ncKey as NotificationChannel))
|
|
throw new InvalidArgumentError(
|
|
`Notification preferences input contains an unknown setting: ${ncKey}`
|
|
)
|
|
const nc = ncKey as NotificationChannel
|
|
const preferenceValue = notificationTypeSettings[nc]
|
|
if (typeof preferenceValue !== 'boolean')
|
|
throw new InvalidArgumentError(
|
|
`Notification preferences input contains and invalid value: ${preferenceValue}`
|
|
)
|
|
notificationTypePreferences[nc] = preferenceValue
|
|
}
|
|
parsedPreferences[nt] = notificationTypePreferences
|
|
}
|
|
return await deps.saveUserNotificationPreferences(userId, parsedPreferences)
|
|
}
|