diff --git a/electron/src/app.module.ts b/electron/src/app.module.ts
index 87e8f5ff..40094b27 100644
--- a/electron/src/app.module.ts
+++ b/electron/src/app.module.ts
@@ -2,6 +2,7 @@ import { ErrorHandler, NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import { NotifierModule } from 'angular-notifier';
import { EffectsModule } from '@ngrx/effects';
import { StoreModule } from '@ngrx/store';
@@ -79,7 +80,13 @@ import { UhkLibUsbApiService } from './services/uhk-lib-usb-api.service';
import { UhkHidApiService } from './services/uhk-hid-api.service';
import { uhkDeviceProvider } from './services/uhk-device-provider';
-import { AutoUpdateSettingsEffects, KeymapEffects, MacroEffects, UserConfigEffects } from './shared/store/effects';
+import {
+ ApplicationEffects,
+ AutoUpdateSettingsEffects,
+ KeymapEffects,
+ MacroEffects,
+ UserConfigEffects
+} from './shared/store/effects';
import { ApplicationEffect, AppUpdateEffect } from './store/effects';
import { KeymapEditGuard } from './shared/components/keymap/edit';
@@ -93,11 +100,12 @@ import { DATA_STORAGE_REPOSITORY } from './shared/services/datastorage-repositor
import { ElectronDataStorageRepositoryService } from './services/electron-datastorage-repository.service';
import { DefaultUserConfigurationService } from './shared/services/default-user-configuration.service';
import { ElectronLogService } from './services/electron-log.service';
-import { LOG_SERVICE } from '../../shared/src/services/logger.service';
+import { LogService } from './shared/services/logger.service';
import { ElectronErrorHandlerService } from './services/electron-error-handler.service';
import { AppUpdateRendererService } from './services/app-update-renderer.service';
import { reducer } from './store';
import { AutoUpdateSettings } from './shared/components/auto-update-settings/auto-update-settings';
+import { angularNotifierConfig } from '../../shared/src/models/angular-notifier-config';
@NgModule({
declarations: [
@@ -172,12 +180,14 @@ import { AutoUpdateSettings } from './shared/components/auto-update-settings/aut
}),
StoreLogMonitorModule,
Select2Module,
+ NotifierModule.withConfig(angularNotifierConfig),
EffectsModule.runAfterBootstrap(KeymapEffects),
EffectsModule.runAfterBootstrap(MacroEffects),
EffectsModule.runAfterBootstrap(UserConfigEffects),
EffectsModule.runAfterBootstrap(AutoUpdateSettingsEffects),
EffectsModule.run(ApplicationEffect),
- EffectsModule.run(AppUpdateEffect)
+ EffectsModule.run(AppUpdateEffect),
+ EffectsModule.run(ApplicationEffects)
],
providers: [
UhkDeviceConnectedGuard,
@@ -192,7 +202,7 @@ import { AutoUpdateSettings } from './shared/components/auto-update-settings/aut
CaptureService,
{ provide: DATA_STORAGE_REPOSITORY, useClass: ElectronDataStorageRepositoryService },
DefaultUserConfigurationService,
- { provide: LOG_SERVICE, useClass: ElectronLogService },
+ { provide: LogService, useClass: ElectronLogService },
{ provide: ErrorHandler, useClass: ElectronErrorHandlerService },
AppUpdateRendererService,
UhkHidApiService,
diff --git a/electron/src/app/app.component.html b/electron/src/app/app.component.html
index 032f6141..7130d255 100644
--- a/electron/src/app/app.component.html
+++ b/electron/src/app/app.component.html
@@ -5,3 +5,4 @@
+
diff --git a/electron/src/components/privilege-checker/privilege-checker.component.ts b/electron/src/components/privilege-checker/privilege-checker.component.ts
index 3ca98aee..737993d9 100644
--- a/electron/src/components/privilege-checker/privilege-checker.component.ts
+++ b/electron/src/components/privilege-checker/privilege-checker.component.ts
@@ -15,7 +15,7 @@ import * as path from 'path';
import * as sudo from 'sudo-prompt';
import { UhkDeviceService } from '../../services/uhk-device.service';
-import { ILogService, LOG_SERVICE } from '../../../../shared/src/services/logger.service';
+import { LogService } from '../../shared/services/logger.service';
@Component({
selector: 'privilege-checker',
@@ -28,7 +28,7 @@ export class PrivilegeCheckerComponent {
constructor(private router: Router,
private uhkDevice: UhkDeviceService,
- @Inject(LOG_SERVICE) private logService: ILogService) {
+ private logService: LogService) {
if (isDev) {
this.rootDir = path.resolve(path.join(remote.process.cwd(), remote.process.argv[1]), '..');
} else {
diff --git a/electron/src/services/electron-error-handler.service.ts b/electron/src/services/electron-error-handler.service.ts
index 4be0533a..6e44c538 100644
--- a/electron/src/services/electron-error-handler.service.ts
+++ b/electron/src/services/electron-error-handler.service.ts
@@ -1,8 +1,9 @@
-import { ErrorHandler, Inject } from '@angular/core';
-import { ILogService, LOG_SERVICE } from '../../../shared/src/services/logger.service';
+import { ErrorHandler, Injectable } from '@angular/core';
+import { LogService} from '../shared/services/logger.service';
+@Injectable()
export class ElectronErrorHandlerService implements ErrorHandler {
- constructor(@Inject(LOG_SERVICE)private logService: ILogService) {}
+ constructor(private logService: LogService) {}
handleError(error: any) {
this.logService.error(error);
diff --git a/electron/src/services/electron-log.service.ts b/electron/src/services/electron-log.service.ts
index 75a8461f..3fc55764 100644
--- a/electron/src/services/electron-log.service.ts
+++ b/electron/src/services/electron-log.service.ts
@@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
import * as log from 'electron-log';
import * as util from 'util';
-import { ILogService } from '../../../shared/src/services/logger.service';
+import { LogService } from '../shared/services/logger.service';
/**
* This service use the electron-log package to write log in file.
@@ -14,7 +14,7 @@ import { ILogService } from '../../../shared/src/services/logger.service';
* The app name: UHK Agent. The up to date value in the scripts/release.js file.
*/
@Injectable()
-export class ElectronLogService implements ILogService {
+export class ElectronLogService implements LogService {
private static getErrorText(args: any) {
return util.inspect(args);
}
diff --git a/electron/src/services/uhk-device.service.ts b/electron/src/services/uhk-device.service.ts
index 9c1d4f95..e867e380 100644
--- a/electron/src/services/uhk-device.service.ts
+++ b/electron/src/services/uhk-device.service.ts
@@ -6,7 +6,7 @@ import { Subscriber } from 'rxjs/Subscriber';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Subscription } from 'rxjs/Subscription';
-import { ILogService, LOG_SERVICE } from '../shared/services/logger.service';
+import { LogService } from '../shared/services/logger.service';
import { SenderMessage } from '../models/sender-message';
import { Constants } from '../shared/util/constants';
@@ -24,7 +24,7 @@ export abstract class UhkDeviceService {
protected messageIn$: Observable;
protected messageOut$: Subject;
- constructor(@Inject(LOG_SERVICE) protected logService: ILogService) {
+ constructor(protected logService: LogService) {
this.messageOut$ = new Subject();
this.initialized$ = new BehaviorSubject(false);
this.connected$ = new BehaviorSubject(false);
diff --git a/electron/src/services/uhk-hid-api.service.ts b/electron/src/services/uhk-hid-api.service.ts
index e3f31668..b504d057 100644
--- a/electron/src/services/uhk-hid-api.service.ts
+++ b/electron/src/services/uhk-hid-api.service.ts
@@ -14,7 +14,7 @@ import 'rxjs/add/operator/concatMap';
import 'rxjs/add/operator/publish';
import 'rxjs/add/operator/do';
-import { ILogService, LOG_SERVICE } from '../shared/services/logger.service';
+import { LogService } from '../shared/services/logger.service';
import { Constants } from '../shared/util';
import { UhkDeviceService } from './uhk-device.service';
@@ -24,7 +24,7 @@ export class UhkHidApiService extends UhkDeviceService implements OnDestroy {
private pollTimer$: Subscription;
- constructor(@Inject(LOG_SERVICE) protected logService: ILogService) {
+ constructor(protected logService: LogService) {
super(logService);
this.pollUhkDevice();
diff --git a/electron/src/services/uhk-lib-usb-api.service.ts b/electron/src/services/uhk-lib-usb-api.service.ts
index 43408ac6..7ff956a3 100644
--- a/electron/src/services/uhk-lib-usb-api.service.ts
+++ b/electron/src/services/uhk-lib-usb-api.service.ts
@@ -14,7 +14,7 @@ import 'rxjs/add/operator/do';
import { Device, findByIds, InEndpoint, Interface, on, OutEndpoint } from 'usb';
-import { ILogService, LOG_SERVICE } from '../shared/services/logger.service';
+import { LogService} from '../shared/services/logger.service';
import { Constants } from '../shared/util';
import { UhkDeviceService } from './uhk-device.service';
@@ -28,7 +28,7 @@ export class UhkLibUsbApiService extends UhkDeviceService implements OnDestroy {
}
constructor(zone: NgZone,
- @Inject(LOG_SERVICE) protected logService: ILogService) {
+ protected logService: LogService) {
super(logService);
this.initialize();
diff --git a/electron/src/store/effects/app.effect.ts b/electron/src/store/effects/app.effect.ts
index 89e82cbb..4e898d27 100644
--- a/electron/src/store/effects/app.effect.ts
+++ b/electron/src/store/effects/app.effect.ts
@@ -4,7 +4,7 @@ import { Effect, Actions } from '@ngrx/effects';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/do';
-import * as app from '../actions/app.action';
+import * as app from '../../shared/store/actions/app.action';
import { AppUpdateRendererService } from '../../services/app-update-renderer.service';
@Injectable()
diff --git a/electron/src/store/reducers/app.reducer.ts b/electron/src/store/reducers/app.reducer.ts
index c4d6b356..08bc9529 100644
--- a/electron/src/store/reducers/app.reducer.ts
+++ b/electron/src/store/reducers/app.reducer.ts
@@ -1,4 +1,4 @@
-import { Actions, ActionTypes } from '../actions/app.action';
+import { Actions, ActionTypes } from '../../shared/store/actions/app.action';
export interface State {
started: boolean;
diff --git a/package.json b/package.json
index 559015f0..2faae105 100644
--- a/package.json
+++ b/package.json
@@ -62,6 +62,7 @@
"@ngrx/effects": "2.0.3",
"@ngrx/router-store": "^1.2.6",
"@ngrx/store": "2.2.2",
+ "angular-notifier": "^2.0.0",
"bootstrap": "^3.3.7",
"browser-stdout": "^1.3.0",
"buffer": "^5.0.6",
diff --git a/shared/src/main-app/main-app.component.scss b/shared/src/main-app/main-app.component.scss
index afd48d6e..3509b59f 100644
--- a/shared/src/main-app/main-app.component.scss
+++ b/shared/src/main-app/main-app.component.scss
@@ -1,3 +1,5 @@
+@import '~angular-notifier/styles.scss';
+
main-app {
display: block;
overflow: hidden;
diff --git a/shared/src/models/angular-notifier-config.ts b/shared/src/models/angular-notifier-config.ts
new file mode 100644
index 00000000..e89a7019
--- /dev/null
+++ b/shared/src/models/angular-notifier-config.ts
@@ -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
+
+ }
+ }
+};
diff --git a/shared/src/models/notification.ts b/shared/src/models/notification.ts
new file mode 100644
index 00000000..ad5d540a
--- /dev/null
+++ b/shared/src/models/notification.ts
@@ -0,0 +1,14 @@
+export enum NotificationType {
+ Default,
+ Success,
+ Error,
+ Warning,
+ Info
+}
+
+export interface Notification {
+ type: NotificationType;
+ title?: string;
+ message: string;
+ extra?: any;
+}
diff --git a/shared/src/services/logger.service.ts b/shared/src/services/logger.service.ts
index 468d6898..0843d646 100644
--- a/shared/src/services/logger.service.ts
+++ b/shared/src/services/logger.service.ts
@@ -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);
}
diff --git a/electron/src/store/actions/app.action.ts b/shared/src/store/actions/app.action.ts
similarity index 50%
rename from electron/src/store/actions/app.action.ts
rename to shared/src/store/actions/app.action.ts
index 63620373..3c7d9679 100644
--- a/electron/src/store/actions/app.action.ts
+++ b/shared/src/store/actions/app.action.ts
@@ -1,12 +1,15 @@
import { Action } from '@ngrx/store';
-import { type } from '../../shared/util/';
+
+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_STARTED: type(PREFIX + 'started'),
+ APP_SHOW_NOTIFICATION: type(PREFIX + 'show notification')
};
export class AppBootsrappedAction implements Action {
@@ -17,6 +20,13 @@ 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;
+ | AppBootsrappedAction
+ | ShowNotificationAction;
diff --git a/shared/src/store/effects/app.ts b/shared/src/store/effects/app.ts
new file mode 100644
index 00000000..91edb212
--- /dev/null
+++ b/shared/src/store/effects/app.ts
@@ -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 = 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) { }
+}
diff --git a/shared/src/store/effects/auto-update-settings.ts b/shared/src/store/effects/auto-update-settings.ts
index c505741d..f92a588d 100644
--- a/shared/src/store/effects/auto-update-settings.ts
+++ b/shared/src/store/effects/auto-update-settings.ts
@@ -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()
diff --git a/shared/src/store/effects/index.ts b/shared/src/store/effects/index.ts
index 71a99489..401079bb 100644
--- a/shared/src/store/effects/index.ts
+++ b/shared/src/store/effects/index.ts
@@ -2,3 +2,4 @@ export * from './keymap';
export * from './macro';
export * from './user-config';
export * from './auto-update-settings';
+export * from './app';
diff --git a/web/src/app.module.ts b/web/src/app.module.ts
index bd5b28cd..d107f1cc 100644
--- a/web/src/app.module.ts
+++ b/web/src/app.module.ts
@@ -2,6 +2,7 @@ import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import { NotifierModule } from 'angular-notifier';
import { EffectsModule } from '@ngrx/effects';
import { StoreModule } from '@ngrx/store';
@@ -69,16 +70,23 @@ import { CaptureService } from './shared/services/capture.service';
import { MapperService } from './shared/services/mapper.service';
import { SvgModuleProviderService } from './shared/services/svg-module-provider.service';
-import { AutoUpdateSettingsEffects, KeymapEffects, MacroEffects, UserConfigEffects } from './shared/store/effects';
+import {
+ ApplicationEffects,
+ AutoUpdateSettingsEffects,
+ KeymapEffects,
+ MacroEffects,
+ UserConfigEffects
+} from './shared/store/effects';
import { KeymapEditGuard } from './shared/components/keymap/edit';
import { MacroNotFoundGuard } from './shared/components/macro/not-found';
import { DATA_STORAGE_REPOSITORY } from './shared/services/datastorage-repository.service';
import { LocalDataStorageRepositoryService } from './shared/services/local-datastorage-repository.service';
import { DefaultUserConfigurationService } from './shared/services/default-user-configuration.service';
-import { reducer } from '../../shared/src/store/reducers/index';
-import { ConsoleLogService, LOG_SERVICE } from '../../shared/src/services/logger.service';
+import { reducer } from './shared/store/reducers/index';
+import { LogService } from './shared/services/logger.service';
import { AutoUpdateSettings } from './shared/components/auto-update-settings/auto-update-settings';
+import { angularNotifierConfig } from '../../shared/src/models/angular-notifier-config';
@NgModule({
declarations: [
@@ -148,10 +156,12 @@ import { AutoUpdateSettings } from './shared/components/auto-update-settings/aut
}),
StoreLogMonitorModule,
Select2Module,
+ NotifierModule.withConfig(angularNotifierConfig),
EffectsModule.runAfterBootstrap(KeymapEffects),
EffectsModule.runAfterBootstrap(MacroEffects),
EffectsModule.runAfterBootstrap(UserConfigEffects),
- EffectsModule.runAfterBootstrap(AutoUpdateSettingsEffects)
+ EffectsModule.runAfterBootstrap(AutoUpdateSettingsEffects),
+ EffectsModule.runAfterBootstrap(ApplicationEffects)
],
providers: [
SvgModuleProviderService,
@@ -160,11 +170,12 @@ import { AutoUpdateSettings } from './shared/components/auto-update-settings/aut
KeymapEditGuard,
MacroNotFoundGuard,
CaptureService,
- {provide: DATA_STORAGE_REPOSITORY, useClass: LocalDataStorageRepositoryService},
+ { provide: DATA_STORAGE_REPOSITORY, useClass: LocalDataStorageRepositoryService },
DefaultUserConfigurationService,
- { provide: LOG_SERVICE, useClass: ConsoleLogService },
+ LogService,
DefaultUserConfigurationService
],
bootstrap: [MainAppComponent]
})
-export class AppModule { }
+export class AppModule {
+}
diff --git a/web/src/main-app/main-app.component.html b/web/src/main-app/main-app.component.html
index 02f27225..ec134681 100644
--- a/web/src/main-app/main-app.component.html
+++ b/web/src/main-app/main-app.component.html
@@ -1,4 +1,3 @@
-
+