mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
cleaned up the flow
This commit is contained in:
@@ -22,7 +22,7 @@ export const clearAppNotification = (appNotificationId: number) => ({
|
||||
payload: appNotificationId,
|
||||
});
|
||||
|
||||
export const addAppNotification = (alert: AppNotification) => ({
|
||||
export const notifyApp = (appNotification: AppNotification) => ({
|
||||
type: ActionTypes.AddAppNotification,
|
||||
payload: alert,
|
||||
payload: appNotification,
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { updateLocation } from './location';
|
||||
import { updateNavIndex, UpdateNavIndexAction } from './navModel';
|
||||
import { notifyApp, clearAppNotification } from './appNotification';
|
||||
|
||||
export { updateLocation, updateNavIndex, UpdateNavIndexAction };
|
||||
export { updateLocation, updateNavIndex, UpdateNavIndexAction, notifyApp, clearAppNotification };
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import React, { Component } from 'react';
|
||||
import { AppNotification } from 'app/types';
|
||||
|
||||
interface Props {
|
||||
appNotification: AppNotification;
|
||||
onClearNotification: (id) => void;
|
||||
}
|
||||
|
||||
export default class AppNotificationItem extends Component<Props> {
|
||||
shouldComponentUpdate(nextProps) {
|
||||
return this.props.appNotification.id !== nextProps.appNotification.id;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { appNotification, onClearNotification } = this.props;
|
||||
setTimeout(() => {
|
||||
onClearNotification(appNotification.id);
|
||||
}, appNotification.timeout);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { appNotification, onClearNotification } = this.props;
|
||||
return (
|
||||
<div className={`alert-${appNotification.severity} alert`}>
|
||||
<div className="alert-icon">
|
||||
<i className={appNotification.icon} />
|
||||
</div>
|
||||
<div className="alert-body">
|
||||
<div className="alert-title">{appNotification.title}</div>
|
||||
<div className="alert-text">{appNotification.text}</div>
|
||||
</div>
|
||||
<button type="button" className="alert-close" onClick={() => onClearNotification(appNotification.id)}>
|
||||
<i className="fa fa fa-remove" />
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,53 +1,30 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import appEvents from 'app/core/app_events';
|
||||
import { addAppNotification, clearAppNotification } from '../../actions/appNotification';
|
||||
import AppNotificationItem from './AppNotificationItem';
|
||||
import { notifyApp, clearAppNotification } from 'app/core/actions';
|
||||
import { connectWithStore } from 'app/core/utils/connectWithReduxStore';
|
||||
import { AppNotification, AppNotificationSeverity, StoreState } from 'app/types';
|
||||
import { AppNotification, StoreState } from 'app/types';
|
||||
import {
|
||||
createErrorNotification,
|
||||
createSuccessNotification,
|
||||
createWarningNotification,
|
||||
} from '../../copy/appNotification';
|
||||
|
||||
export interface Props {
|
||||
appNotifications: AppNotification[];
|
||||
addAppNotification: typeof addAppNotification;
|
||||
notifyApp: typeof notifyApp;
|
||||
clearAppNotification: typeof clearAppNotification;
|
||||
}
|
||||
|
||||
export class AppNotificationList extends PureComponent<Props> {
|
||||
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));
|
||||
const { notifyApp } = this.props;
|
||||
|
||||
appEvents.on('alert-warning', options => notifyApp(createWarningNotification(options[0], options[1])));
|
||||
appEvents.on('alert-success', options => notifyApp(createSuccessNotification(options[0], options[1])));
|
||||
appEvents.on('alert-error', options => notifyApp(createErrorNotification(options[0], options[1])));
|
||||
}
|
||||
|
||||
addAppNotification(title, text, severity, timeout) {
|
||||
const id = Date.now();
|
||||
const newAlert = {
|
||||
id: id,
|
||||
title: title || '',
|
||||
text: text || '',
|
||||
severity: severity || AppNotificationSeverity.Info,
|
||||
icon: this.getIconForSeverity(severity),
|
||||
remove: this.clearAutomatically(id, 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 = (id, timeout) => {
|
||||
setTimeout(() => {
|
||||
this.props.clearAppNotification(id);
|
||||
}, timeout);
|
||||
};
|
||||
|
||||
onClearAppNotification = id => {
|
||||
this.props.clearAppNotification(id);
|
||||
};
|
||||
@@ -59,22 +36,11 @@ export class AppNotificationList extends PureComponent<Props> {
|
||||
<div>
|
||||
{appNotifications.map((appNotification, index) => {
|
||||
return (
|
||||
<div key={index} className={`alert-${appNotification.severity} alert`}>
|
||||
<div className="alert-icon">
|
||||
<i className={appNotification.icon} />
|
||||
</div>
|
||||
<div className="alert-body">
|
||||
<div className="alert-title">{appNotification.title}</div>
|
||||
<div className="alert-text">{appNotification.text}</div>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
className="alert-close"
|
||||
onClick={() => this.onClearAppNotification(appNotification.id)}
|
||||
>
|
||||
<i className="fa fa fa-remove" />
|
||||
</button>
|
||||
</div>
|
||||
<AppNotificationItem
|
||||
key={`${appNotification.id}-${index}`}
|
||||
appNotification={appNotification}
|
||||
onClearNotification={id => this.onClearAppNotification(id)}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
@@ -87,7 +53,7 @@ const mapStateToProps = (state: StoreState) => ({
|
||||
});
|
||||
|
||||
const mapDispatchToProps = {
|
||||
addAppNotification,
|
||||
notifyApp,
|
||||
clearAppNotification,
|
||||
};
|
||||
|
||||
|
||||
46
public/app/core/copy/appNotification.ts
Normal file
46
public/app/core/copy/appNotification.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { AppNotification, AppNotificationSeverity, AppNotificationTimeout } from 'app/types';
|
||||
|
||||
const defaultSuccessNotification: AppNotification = {
|
||||
title: '',
|
||||
text: '',
|
||||
severity: AppNotificationSeverity.Success,
|
||||
icon: 'fa fa-check',
|
||||
timeout: AppNotificationTimeout.Success,
|
||||
};
|
||||
|
||||
const defaultWarningNotification: AppNotification = {
|
||||
title: '',
|
||||
text: '',
|
||||
severity: AppNotificationSeverity.Warning,
|
||||
icon: 'fa fa-exclamation',
|
||||
timeout: AppNotificationTimeout.Warning,
|
||||
};
|
||||
|
||||
const defaultErrorNotification: AppNotification = {
|
||||
title: '',
|
||||
text: '',
|
||||
severity: AppNotificationSeverity.Error,
|
||||
icon: 'fa fa-exclamation-triangle',
|
||||
timeout: AppNotificationTimeout.Error,
|
||||
};
|
||||
|
||||
export const createSuccessNotification = (title: string, text?: string): AppNotification => ({
|
||||
...defaultSuccessNotification,
|
||||
title: title,
|
||||
text: text,
|
||||
id: Date.now(),
|
||||
});
|
||||
|
||||
export const createErrorNotification = (title: string, text?: string): AppNotification => ({
|
||||
...defaultErrorNotification,
|
||||
title: title,
|
||||
text: text,
|
||||
id: Date.now(),
|
||||
});
|
||||
|
||||
export const createWarningNotification = (title: string, text?: string): AppNotification => ({
|
||||
...defaultWarningNotification,
|
||||
title: title,
|
||||
text: text,
|
||||
id: Date.now(),
|
||||
});
|
||||
@@ -1,6 +1,6 @@
|
||||
import { appNotificationsReducer } from './appNotification';
|
||||
import { ActionTypes } from '../actions/appNotification';
|
||||
import { AppNotificationSeverity } from 'app/types/index';
|
||||
import { AppNotificationSeverity, AppNotificationTimeout } from 'app/types/';
|
||||
|
||||
describe('clear alert', () => {
|
||||
it('should filter alert', () => {
|
||||
@@ -15,6 +15,7 @@ describe('clear alert', () => {
|
||||
icon: 'success',
|
||||
title: 'test',
|
||||
text: 'test alert',
|
||||
timeout: AppNotificationTimeout.Success,
|
||||
},
|
||||
{
|
||||
id: id2,
|
||||
@@ -22,6 +23,7 @@ describe('clear alert', () => {
|
||||
icon: 'warning',
|
||||
title: 'test2',
|
||||
text: 'test alert fail 2',
|
||||
timeout: AppNotificationTimeout.Warning,
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -39,6 +41,7 @@ describe('clear alert', () => {
|
||||
icon: 'success',
|
||||
title: 'test',
|
||||
text: 'test alert',
|
||||
timeout: AppNotificationTimeout.Success,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AppNotification, AppNotificationsState } from 'app/types/index';
|
||||
import { AppNotification, AppNotificationsState } from 'app/types/';
|
||||
import { Action, ActionTypes } from '../actions/appNotification';
|
||||
|
||||
export const initialState: AppNotificationsState = {
|
||||
@@ -17,7 +17,3 @@ export const appNotificationsReducer = (state = initialState, action: Action): A
|
||||
}
|
||||
return state;
|
||||
};
|
||||
|
||||
export default {
|
||||
appNotifications: appNotificationsReducer,
|
||||
};
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { navIndexReducer as navIndex } from './navModel';
|
||||
import { locationReducer as location } from './location';
|
||||
import { appNotificationsReducer as appNotifications } from './appNotification';
|
||||
|
||||
export default {
|
||||
navIndex,
|
||||
location,
|
||||
appNotifications,
|
||||
};
|
||||
|
||||
@@ -10,7 +10,6 @@ import dashboardReducers from 'app/features/dashboard/state/reducers';
|
||||
import pluginReducers from 'app/features/plugins/state/reducers';
|
||||
import dataSourcesReducers from 'app/features/datasources/state/reducers';
|
||||
import usersReducers from 'app/features/users/state/reducers';
|
||||
import appNotificationReducers from 'app/core/reducers/appNotification';
|
||||
|
||||
const rootReducers = {
|
||||
...sharedReducers,
|
||||
@@ -22,7 +21,6 @@ const rootReducers = {
|
||||
...pluginReducers,
|
||||
...dataSourcesReducers,
|
||||
...usersReducers,
|
||||
...appNotificationReducers,
|
||||
};
|
||||
|
||||
export let store;
|
||||
|
||||
@@ -4,6 +4,7 @@ export interface AppNotification {
|
||||
icon: string;
|
||||
title: string;
|
||||
text: string;
|
||||
timeout: AppNotificationTimeout;
|
||||
}
|
||||
|
||||
export enum AppNotificationSeverity {
|
||||
@@ -13,6 +14,12 @@ export enum AppNotificationSeverity {
|
||||
Info = 'info',
|
||||
}
|
||||
|
||||
export enum AppNotificationTimeout {
|
||||
Warning = 5000,
|
||||
Success = 3000,
|
||||
Error = 7000,
|
||||
}
|
||||
|
||||
export interface AppNotificationsState {
|
||||
appNotifications: AppNotification[];
|
||||
}
|
||||
|
||||
@@ -9,7 +9,12 @@ 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 { AppNotification, AppNotificationSeverity, AppNotificationsState } from './appNotifications';
|
||||
import {
|
||||
AppNotification,
|
||||
AppNotificationSeverity,
|
||||
AppNotificationsState,
|
||||
AppNotificationTimeout,
|
||||
} from './appNotifications';
|
||||
|
||||
export {
|
||||
Team,
|
||||
@@ -50,6 +55,7 @@ export {
|
||||
AppNotification,
|
||||
AppNotificationsState,
|
||||
AppNotificationSeverity,
|
||||
AppNotificationTimeout,
|
||||
};
|
||||
|
||||
export interface StoreState {
|
||||
|
||||
Reference in New Issue
Block a user