diff --git a/public/app/core/angular_wrappers.ts b/public/app/core/angular_wrappers.ts index 5b14ebe46fa..14a0dcdb234 100644 --- a/public/app/core/angular_wrappers.ts +++ b/public/app/core/angular_wrappers.ts @@ -5,12 +5,12 @@ import EmptyListCTA from './components/EmptyListCTA/EmptyListCTA'; import { SearchResult } from './components/search/SearchResult'; import { TagFilter } from './components/TagFilter/TagFilter'; import { SideMenu } from './components/sidemenu/SideMenu'; -import AlertList from './components/Alerts/AlertList'; +import AppNotificationList from './components/AppNotifications/AppNotificationList'; export function registerAngularDirectives() { react2AngularDirective('passwordStrength', PasswordStrength, ['password']); react2AngularDirective('sidemenu', SideMenu, []); - react2AngularDirective('pageAlertList', AlertList, []); + react2AngularDirective('pageAlertList', AppNotificationList, []); react2AngularDirective('pageHeader', PageHeader, ['model', 'noTabs']); react2AngularDirective('emptyListCta', EmptyListCTA, ['model']); react2AngularDirective('searchResult', SearchResult, []); diff --git a/public/app/core/components/Alerts/AlertList.tsx b/public/app/core/components/Alerts/AlertList.tsx deleted file mode 100644 index e384924d96f..00000000000 --- a/public/app/core/components/Alerts/AlertList.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import React, { PureComponent } from 'react'; -import { connect } from 'react-redux'; - -export interface Props { - alerts: any[]; -} - -export class AlertList extends PureComponent { - onClearAlert = alert => { - console.log('clear alert', alert); - }; - - render() { - const { alerts } = this.props; - - return ( -
- {alerts.map((alert, index) => { - return ( -
-
- -
-
-
{alert.title}
-
{alert.text}
-
- -
- ); - })} -
- ); - } -} - -function mapStateToProps(state) { - return { - alerts: state.alerts.alerts, - }; -} - -export default connect(mapStateToProps)(AlertList); diff --git a/public/app/core/components/Alerts/state/actions.ts b/public/app/core/components/Alerts/state/actions.ts deleted file mode 100644 index cc82f21a3e7..00000000000 --- a/public/app/core/components/Alerts/state/actions.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Alert } from 'app/types'; - -export enum ActionTypes { - AddAlert = 'ADD_ALERT', - ClearAlert = 'CLEAR_ALERT', -} - -interface AddAlertAction { - type: ActionTypes.AddAlert; - payload: Alert; -} - -interface ClearAlertAction { - type: ActionTypes.ClearAlert; - payload: Alert; -} - -export type Action = AddAlertAction | ClearAlertAction; - -export const clearAlert = (alert: Alert) => ({ - type: ActionTypes.ClearAlert, - payload: alert, -}); diff --git a/public/app/core/components/AppNotifications/AppNotificationList.tsx b/public/app/core/components/AppNotifications/AppNotificationList.tsx new file mode 100644 index 00000000000..a637d741541 --- /dev/null +++ b/public/app/core/components/AppNotifications/AppNotificationList.tsx @@ -0,0 +1,96 @@ +import React, { PureComponent } from 'react'; +import { connect } from 'react-redux'; +import appEvents from 'app/core/app_events'; +import { addAppNotification, clearAppNotification } from './state/actions'; + +export interface Props { + alerts: any[]; + addAppNotification: typeof addAppNotification; + clearAppNotification: typeof clearAppNotification; +} + +enum AppNotificationSeverity { + Success = 'success', + Warning = 'warning', + Error = 'error', + Info = 'info', +} + +export class AppNotificationList extends PureComponent { + componentDidMount() { + appEvents.on('alert-warning', options => this.addAppNotification(options[0], options[1], 'warning', 5000)); + appEvents.on('alert-success', options => this.addAppNotification(options[0], options[1], 'success', 3000)); + appEvents.on('alert-error', options => this.addAppNotification(options[0], options[1], 'error', 7000)); + } + + addAppNotification(title, text, severity, timeout) { + const newAlert = { + title: title || '', + text: text || '', + severity: severity || AppNotificationSeverity.Info, + icon: this.getIconForSeverity(severity), + remove: this.clearAutomatically(this, timeout), + }; + + this.props.addAppNotification(newAlert); + } + + getIconForSeverity(severity) { + switch (severity) { + case AppNotificationSeverity.Success: + return 'fa fa-check'; + case AppNotificationSeverity.Error: + return 'fa fa-exclamation-triangle'; + default: + return 'fa fa-exclamation'; + } + } + + clearAutomatically = (alert, timeout) => { + setTimeout(() => { + this.props.clearAppNotification(alert); + }, timeout); + }; + + onClearAppNotification = alert => { + this.props.clearAppNotification(alert); + }; + + render() { + const { alerts } = this.props; + + return ( +
+ {alerts.map((alert, index) => { + return ( +
+
+ +
+
+
{alert.title}
+
{alert.text}
+
+ +
+ ); + })} +
+ ); + } +} + +function mapStateToProps(state) { + return { + alerts: state.alerts.alerts, + }; +} + +const mapDispatchToProps = { + addAppNotification, + clearAppNotification, +}; + +export default connect(mapStateToProps, mapDispatchToProps)(AppNotificationList); diff --git a/public/app/core/components/AppNotifications/state/actions.ts b/public/app/core/components/AppNotifications/state/actions.ts new file mode 100644 index 00000000000..dfdb066e978 --- /dev/null +++ b/public/app/core/components/AppNotifications/state/actions.ts @@ -0,0 +1,28 @@ +import { AppNotification } from 'app/types'; + +export enum ActionTypes { + AddAppNotification = 'ADD_APP_NOTIFICATION', + ClearAppNotification = 'CLEAR_APP_NOTIFICATION', +} + +interface AddAppNotificationAction { + type: ActionTypes.AddAppNotification; + payload: AppNotification; +} + +interface ClearAppNotificationAction { + type: ActionTypes.ClearAppNotification; + payload: AppNotification; +} + +export type Action = AddAppNotificationAction | ClearAppNotificationAction; + +export const clearAppNotification = (alert: AppNotification) => ({ + type: ActionTypes.ClearAppNotification, + payload: alert, +}); + +export const addAppNotification = (alert: AppNotification) => ({ + type: ActionTypes.AddAppNotification, + payload: alert, +}); diff --git a/public/app/core/components/Alerts/state/reducers.test.ts b/public/app/core/components/AppNotifications/state/reducers.test.ts similarity index 94% rename from public/app/core/components/Alerts/state/reducers.test.ts rename to public/app/core/components/AppNotifications/state/reducers.test.ts index 16848e6b233..e81bbf27967 100644 --- a/public/app/core/components/Alerts/state/reducers.test.ts +++ b/public/app/core/components/AppNotifications/state/reducers.test.ts @@ -21,7 +21,7 @@ describe('clear alert', () => { }; const result = alertsReducer(initialState, { - type: ActionTypes.ClearAlert, + type: ActionTypes.ClearAppNotification, payload: initialState.alerts[1], }); diff --git a/public/app/core/components/Alerts/state/reducers.ts b/public/app/core/components/AppNotifications/state/reducers.ts similarity index 72% rename from public/app/core/components/Alerts/state/reducers.ts rename to public/app/core/components/AppNotifications/state/reducers.ts index efbfa96aa2c..7bb7b2f65bf 100644 --- a/public/app/core/components/Alerts/state/reducers.ts +++ b/public/app/core/components/AppNotifications/state/reducers.ts @@ -1,15 +1,15 @@ -import { Alert, AlertsState } from 'app/types'; +import { AppNotification, AlertsState } from 'app/types'; import { Action, ActionTypes } from './actions'; export const initialState: AlertsState = { - alerts: [] as Alert[], + alerts: [] as AppNotification[], }; export const alertsReducer = (state = initialState, action: Action): AlertsState => { switch (action.type) { - case ActionTypes.AddAlert: + case ActionTypes.AddAppNotification: return { ...state, alerts: state.alerts.concat([action.payload]) }; - case ActionTypes.ClearAlert: + case ActionTypes.ClearAppNotification: return { ...state, alerts: state.alerts.filter(alert => alert !== action.payload), diff --git a/public/app/types/alerts.ts b/public/app/types/alerts.ts index 2e744ddc9b7..96b764243ff 100644 --- a/public/app/types/alerts.ts +++ b/public/app/types/alerts.ts @@ -1,4 +1,4 @@ -export interface Alert { +export interface AppNotification { severity: string; icon: string; title: string; @@ -6,5 +6,5 @@ export interface Alert { } export interface AlertsState { - alerts: Alert[]; + alerts: AppNotification[]; } diff --git a/public/app/types/index.ts b/public/app/types/index.ts index af0dacf27ee..fbb3b3d7d65 100644 --- a/public/app/types/index.ts +++ b/public/app/types/index.ts @@ -9,7 +9,7 @@ import { ApiKey, ApiKeysState, NewApiKey } from './apiKeys'; import { Invitee, OrgUser, User, UsersState } from './user'; import { DataSource, DataSourcesState } from './datasources'; import { PluginDashboard, PluginMeta, Plugin, PluginsState } from './plugins'; -import { Alert, AlertsState } from './alerts'; +import { AppNotification, AlertsState } from './alerts'; export { Team, @@ -47,7 +47,7 @@ export { User, UsersState, PluginDashboard, - Alert, + AppNotification, AlertsState, };