mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-23 11:37:02 -04:00
Rework notifications (#1465)
* Rework notifications - dispatchUINotification returns a promise that contains the notification id - notifications use i18n instead of plain text Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de> * Reformat code Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
parent
808601eaba
commit
553e9f8ead
13 changed files with 154 additions and 105 deletions
|
@ -4,40 +4,56 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import i18n from 'i18next'
|
||||
import i18n, { TOptions } from 'i18next'
|
||||
import { store } from '../index'
|
||||
import {
|
||||
DismissUiNotificationAction,
|
||||
DispatchUiNotificationAction,
|
||||
UiNotificationActionType,
|
||||
UiNotificationButton
|
||||
} from './types'
|
||||
import { DismissUiNotificationAction, DispatchOptions, UiNotificationActionType } from './types'
|
||||
import { DateTime } from 'luxon'
|
||||
import { IconName } from '../../components/common/fork-awesome/types'
|
||||
|
||||
export const DEFAULT_DURATION_IN_SECONDS = 10
|
||||
|
||||
export const dispatchUiNotification = (
|
||||
title: string,
|
||||
content: string,
|
||||
durationInSecond = DEFAULT_DURATION_IN_SECONDS,
|
||||
icon?: IconName,
|
||||
buttons?: UiNotificationButton[]
|
||||
): void => {
|
||||
store.dispatch({
|
||||
type: UiNotificationActionType.DISPATCH_NOTIFICATION,
|
||||
notification: {
|
||||
title,
|
||||
content,
|
||||
date: DateTime.now(),
|
||||
dismissed: false,
|
||||
icon,
|
||||
durationInSecond,
|
||||
buttons: buttons
|
||||
}
|
||||
} as DispatchUiNotificationAction)
|
||||
/**
|
||||
* Dispatches a new UI Notification into the global application state.
|
||||
*
|
||||
* @param titleI18nKey I18n key used to show the localized title
|
||||
* @param contentI18nKey I18n key used to show the localized content
|
||||
* @param icon The icon in the upper left corner
|
||||
* @param durationInSecond Show duration of the notification. If omitted then a {@link DEFAULT_DURATION_IN_SECONDS default value} will be used.
|
||||
* @param buttons A array of actions that are shown in the notification
|
||||
* @param contentI18nOptions Options to configure the translation of the title. (e.g. variables)
|
||||
* @param titleI18nOptions Options to configure the translation of the content. (e.g. variables)
|
||||
* @return a promise that resolves as soon as the notification id available.
|
||||
*/
|
||||
export const dispatchUiNotification = async (
|
||||
titleI18nKey: string,
|
||||
contentI18nKey: string,
|
||||
{ icon, durationInSecond, buttons, contentI18nOptions, titleI18nOptions }: Partial<DispatchOptions>
|
||||
): Promise<number> => {
|
||||
return new Promise((resolve) => {
|
||||
store.dispatch({
|
||||
type: UiNotificationActionType.DISPATCH_NOTIFICATION,
|
||||
notificationIdCallback: (notificationId: number) => {
|
||||
resolve(notificationId)
|
||||
},
|
||||
notification: {
|
||||
titleI18nKey,
|
||||
contentI18nKey,
|
||||
date: DateTime.now(),
|
||||
dismissed: false,
|
||||
titleI18nOptions: titleI18nOptions ?? {},
|
||||
contentI18nOptions: contentI18nOptions ?? {},
|
||||
durationInSecond: durationInSecond ?? DEFAULT_DURATION_IN_SECONDS,
|
||||
buttons: buttons ?? [],
|
||||
icon: icon
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Dismisses a notification. It won't be removed from the global application state but hidden.
|
||||
*
|
||||
* @param notificationId The id of the notification to dismissed. Can be obtained from the returned promise of {@link dispatchUiNotification}
|
||||
*/
|
||||
export const dismissUiNotification = (notificationId: number): void => {
|
||||
store.dispatch({
|
||||
type: UiNotificationActionType.DISMISS_NOTIFICATION,
|
||||
|
@ -45,9 +61,18 @@ export const dismissUiNotification = (notificationId: number): void => {
|
|||
} as DismissUiNotificationAction)
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches an notification that is specialized for errors.
|
||||
*
|
||||
* @param messageI18nKey i18n key for the message
|
||||
* @param messageI18nOptions i18n options for the message
|
||||
*/
|
||||
export const showErrorNotification =
|
||||
(message: string) =>
|
||||
(messageI18nKey: string, messageI18nOptions?: TOptions | string) =>
|
||||
(error: Error): void => {
|
||||
console.error(message, error)
|
||||
dispatchUiNotification(i18n.t('common.errorOccurred'), message, DEFAULT_DURATION_IN_SECONDS, 'exclamation-triangle')
|
||||
console.error(i18n.t(messageI18nKey, messageI18nOptions), error)
|
||||
void dispatchUiNotification('common.errorOccurred', messageI18nKey, {
|
||||
contentI18nOptions: messageI18nOptions,
|
||||
icon: 'exclamation-triangle'
|
||||
})
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
import { Reducer } from 'redux'
|
||||
import { UiNotificationActions, UiNotificationActionType, UiNotificationState } from './types'
|
||||
import { UiNotification, UiNotificationActions, UiNotificationActionType, UiNotificationState } from './types'
|
||||
|
||||
export const UiNotificationReducer: Reducer<UiNotificationState, UiNotificationActions> = (
|
||||
state: UiNotificationState = [],
|
||||
|
@ -13,7 +13,7 @@ export const UiNotificationReducer: Reducer<UiNotificationState, UiNotificationA
|
|||
) => {
|
||||
switch (action.type) {
|
||||
case UiNotificationActionType.DISPATCH_NOTIFICATION:
|
||||
return state.concat(action.notification)
|
||||
return addNewNotification(state, action.notification, action.notificationIdCallback)
|
||||
case UiNotificationActionType.DISMISS_NOTIFICATION:
|
||||
return dismissNotification(state, action.notificationId)
|
||||
default:
|
||||
|
@ -21,6 +21,23 @@ export const UiNotificationReducer: Reducer<UiNotificationState, UiNotificationA
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link UiNotificationState notification state} by appending the given {@link UiNotification}.
|
||||
* @param state The current ui notification state
|
||||
* @param notification The new notification
|
||||
* @param notificationIdCallback This callback is executed with the id of the new notification
|
||||
* @return The new {@link UiNotificationState notification state}
|
||||
*/
|
||||
const addNewNotification = (
|
||||
state: UiNotificationState,
|
||||
notification: UiNotification,
|
||||
notificationIdCallback: (notificationId: number) => void
|
||||
): UiNotificationState => {
|
||||
const newState = [...state, notification]
|
||||
notificationIdCallback(newState.length - 1)
|
||||
return newState
|
||||
}
|
||||
|
||||
const dismissNotification = (
|
||||
notificationState: UiNotificationState,
|
||||
notificationIndex: number
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
import { Action } from 'redux'
|
||||
import { DateTime } from 'luxon'
|
||||
import { IconName } from '../../components/common/fork-awesome/types'
|
||||
import { TOptions } from 'i18next'
|
||||
|
||||
export enum UiNotificationActionType {
|
||||
DISPATCH_NOTIFICATION = 'notification/dispatch',
|
||||
|
@ -18,14 +19,19 @@ export interface UiNotificationButton {
|
|||
onClick: () => void
|
||||
}
|
||||
|
||||
export interface UiNotification {
|
||||
title: string
|
||||
date: DateTime
|
||||
content: string
|
||||
dismissed: boolean
|
||||
icon?: IconName
|
||||
export interface DispatchOptions {
|
||||
titleI18nOptions: TOptions | string
|
||||
contentI18nOptions: TOptions | string
|
||||
durationInSecond: number
|
||||
buttons?: UiNotificationButton[]
|
||||
icon?: IconName
|
||||
buttons: UiNotificationButton[]
|
||||
}
|
||||
|
||||
export interface UiNotification extends DispatchOptions {
|
||||
titleI18nKey: string
|
||||
contentI18nKey: string
|
||||
date: DateTime
|
||||
dismissed: boolean
|
||||
}
|
||||
|
||||
export type UiNotificationActions = DispatchUiNotificationAction | DismissUiNotificationAction
|
||||
|
@ -33,6 +39,7 @@ export type UiNotificationActions = DispatchUiNotificationAction | DismissUiNoti
|
|||
export interface DispatchUiNotificationAction extends Action<UiNotificationActionType> {
|
||||
type: UiNotificationActionType.DISPATCH_NOTIFICATION
|
||||
notification: UiNotification
|
||||
notificationIdCallback: (notificationId: number) => void
|
||||
}
|
||||
|
||||
export interface DismissUiNotificationAction extends Action<UiNotificationActionType> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue