feat(notification): display app errors, close #319 (#333)

* refactor(log): Refactor logging service

Removed the InjectionToken and changed LogService as default logger.
Finally ElectronLogService implements LogService directly.

* refactor: Optimize imports

* fix(app-update): Add missing rxjs imports

* style: Remove extra line

* refactor(store): Move app.actions.ts to shared module

* feat(notification): Add notification panel

Add angular-notifier to the app and created the ShowNotificationAction
to manage notifications

* style(notification): Fix tslint suggestion

* fix(notification): Add missing rxjs imports
This commit is contained in:
Róbert Kiss
2017-07-05 13:41:31 +02:00
committed by László Monda
parent 6bc2bc8331
commit c9a1e9853c
21 changed files with 181 additions and 41 deletions

View File

@@ -1,3 +1,5 @@
@import '~angular-notifier/styles.scss';
main-app {
display: block;
overflow: hidden;

View File

@@ -0,0 +1,44 @@
import { NotifierOptions } from 'angular-notifier';
export const angularNotifierConfig: NotifierOptions = {
position: {
horizontal: {
/**
* Defines the horizontal position on the screen
* @type {'left' | 'middle' | 'right'}
*/
position: 'right',
/**
* Defines the horizontal distance to the screen edge (in px)
* @type {number}
*/
distance: 12
},
vertical: {
/**
* Defines the vertical position on the screen
* @type {'top' | 'bottom'}
*/
position: 'top',
/**
* Defines the vertical distance to the screen edge (in px)
* @type {number}
*/
distance: 12,
/**
* Defines the vertical gap, existing between multiple notifications (in px)
* @type {number}
*/
gap: 10
}
}
};

View File

@@ -0,0 +1,14 @@
export enum NotificationType {
Default,
Success,
Error,
Warning,
Info
}
export interface Notification {
type: NotificationType;
title?: string;
message: string;
extra?: any;
}

View File

@@ -1,15 +1,7 @@
import {Injectable, InjectionToken} from '@angular/core';
export interface ILogService {
error(...args: any[]): void;
info(...args: any[]): void;
}
export let LOG_SERVICE = new InjectionToken('logger-service');
import {Injectable} from '@angular/core';
@Injectable()
export class ConsoleLogService implements ILogService {
export class LogService {
error(...args: any[]): void {
console.error(args);
}

View File

@@ -0,0 +1,32 @@
import { Action } from '@ngrx/store';
import { type } from '../../util';
import {Notification} from '../../models/notification';
const PREFIX = '[app] ';
// tslint:disable-next-line:variable-name
export const ActionTypes = {
APP_BOOTSRAPPED: type(PREFIX + 'bootstrapped'),
APP_STARTED: type(PREFIX + 'started'),
APP_SHOW_NOTIFICATION: type(PREFIX + 'show notification')
};
export class AppBootsrappedAction implements Action {
type = ActionTypes.APP_BOOTSRAPPED;
}
export class AppStartedAction implements Action {
type = ActionTypes.APP_STARTED;
}
export class ShowNotificationAction implements Action {
type = ActionTypes.APP_SHOW_NOTIFICATION;
constructor(public payload: Notification) {}
}
export type Actions
= AppStartedAction
| AppBootsrappedAction
| ShowNotificationAction;

View File

@@ -0,0 +1,48 @@
import { Injectable } from '@angular/core';
import { Action } from '@ngrx/store';
import { Actions, Effect, toPayload } from '@ngrx/effects';
import { Observable } from 'rxjs/Observable';
import { NotifierService } from 'angular-notifier';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/map';
import { ActionTypes } from '../actions/app.action';
import { Notification, NotificationType } from '../../models/notification';
@Injectable()
export class ApplicationEffects {
@Effect({ dispatch: false })
appStart$: Observable<Action> = this.actions$
.ofType(ActionTypes.APP_SHOW_NOTIFICATION)
.map(toPayload)
.do((notification: Notification) => {
const type = ApplicationEffects.mapNotificationType(notification.type);
this.notifierService.notify(type, notification.message);
});
// TODO: Change typescript -> 2.4 and use string enum.
// Corrently ngrx store is not compatible witn typescript 2.4
private static mapNotificationType(type: NotificationType): string {
switch (type) {
case NotificationType.Success:
return 'success';
case NotificationType.Error:
return 'error';
case NotificationType.Info:
return 'info';
case NotificationType.Warning:
return 'warning';
default:
return 'default';
}
}
constructor(private actions$: Actions,
private notifierService: NotifierService) { }
}

View File

@@ -3,6 +3,11 @@ import { Actions, Effect } from '@ngrx/effects';
import { Observable } from 'rxjs/Observable';
import { Action, Store } from '@ngrx/store';
import 'rxjs/add/operator/startWith';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/withLatestFrom';
import 'rxjs/add/operator/map';
import {
ActionTypes,
LoadAutoUpdateSettingsAction,
@@ -11,7 +16,7 @@ import {
} from '../actions/auto-update-settings';
import { DATA_STORAGE_REPOSITORY, DataStorageRepositoryService } from '../../services/datastorage-repository.service';
import { AppState, getAutoUpdateSettings } from '../index';
import { initialState, State } from '../reducers/auto-update-settings';
import { initialState } from '../reducers/auto-update-settings';
import { AutoUpdateSettings } from '../../models/auto-update-settings';
@Injectable()

View File

@@ -2,3 +2,4 @@ export * from './keymap';
export * from './macro';
export * from './user-config';
export * from './auto-update-settings';
export * from './app';