diff --git a/package.json b/package.json index 9e747f3e6e..fec6349d2c 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "@angular/platform-browser": "^4.0.0", "@ngx-translate/core": "^6.0.1", "@types/jspdf": "^1.1.31", + "angular2-notifications": "^0.4.46", "core-js": "^2.4.1", "hammerjs": "^2.0.8", "jspdf": "^1.3.3", diff --git a/src/demo-app/app/app.component.html b/src/demo-app/app/app.component.html index 8b44db9e82..1923961f3d 100644 --- a/src/demo-app/app/app.component.html +++ b/src/demo-app/app/app.component.html @@ -1,4 +1,5 @@ + @@ -101,8 +102,6 @@ print.component - -

{{message.text}}

diff --git a/src/lib/context/shared/context.service.spec.ts b/src/lib/context/shared/context.service.spec.ts index dc8f5aed2e..4495590b04 100644 --- a/src/lib/context/shared/context.service.spec.ts +++ b/src/lib/context/shared/context.service.spec.ts @@ -1,7 +1,7 @@ import { TestBed, inject } from '@angular/core/testing'; import { HttpModule } from '@angular/http'; -import { ActivityService, RequestService, MessageService } from '../../core'; +import { IgoCoreModule } from '../../core'; import { ToolService } from '../../tool'; import { ContextService, @@ -12,17 +12,15 @@ describe('ContextService', () => { beforeEach(() => { TestBed.configureTestingModule({ imports: [ - HttpModule + HttpModule, + IgoCoreModule.forRoot() ], providers: [ provideContextServiceOptions({ basePath: 'contexts', contextListFile: '_contexts.json' }), - ActivityService, ContextService, - MessageService, - RequestService, ToolService ] }); diff --git a/src/lib/core/message/index.ts b/src/lib/core/message/index.ts index c3da79f741..6738f67dd6 100644 --- a/src/lib/core/message/index.ts +++ b/src/lib/core/message/index.ts @@ -1 +1,2 @@ +export * from './message-center'; export * from './shared'; diff --git a/src/lib/core/message/message-center/index.ts b/src/lib/core/message/message-center/index.ts new file mode 100644 index 0000000000..d15fadf122 --- /dev/null +++ b/src/lib/core/message/message-center/index.ts @@ -0,0 +1 @@ +export * from './message-center.component'; diff --git a/src/lib/core/message/message-center/message-center.component.html b/src/lib/core/message/message-center/message-center.component.html new file mode 100644 index 0000000000..f992cdec82 --- /dev/null +++ b/src/lib/core/message/message-center/message-center.component.html @@ -0,0 +1 @@ + diff --git a/src/lib/core/message/message-center/message-center.component.spec.ts b/src/lib/core/message/message-center/message-center.component.spec.ts new file mode 100644 index 0000000000..d9e9ab3839 --- /dev/null +++ b/src/lib/core/message/message-center/message-center.component.spec.ts @@ -0,0 +1,31 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { SimpleNotificationsModule } from 'angular2-notifications'; + +import { MessageCenterComponent } from './message-center.component'; + +describe('NotificationComponent', () => { + let component: MessageCenterComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + imports: [ + SimpleNotificationsModule.forRoot() + ], + declarations: [ + MessageCenterComponent + ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(MessageCenterComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/lib/core/message/message-center/message-center.component.styl b/src/lib/core/message/message-center/message-center.component.styl new file mode 100644 index 0000000000..f04f669b89 --- /dev/null +++ b/src/lib/core/message/message-center/message-center.component.styl @@ -0,0 +1,43 @@ +@require '../../../../style/media.styl'; + +:host >>> simple-notifications { + + div.simple-notification { + min-height: 50px; + margin-bottom: 5px; + + +media(mobile) { + margin-bottom: 0; + } + + svg { + width: 63px; + height: 63px; + padding: 15px; + } + + .sn-title { + line-height: 23px; + font-size: 15px; + font-weight: bold; + } + + .sn-content { + line-height: 18px; + font-size: 15px; + } + + &.error { + background-color: #d32f2f; + .sn-progress-loader span { + background-color: #c41515; + } + } + + md-icon { + position: absolute; + top: 10px; + right: 10px; + } + } +} diff --git a/src/lib/core/message/message-center/message-center.component.ts b/src/lib/core/message/message-center/message-center.component.ts new file mode 100644 index 0000000000..51e804988c --- /dev/null +++ b/src/lib/core/message/message-center/message-center.component.ts @@ -0,0 +1,36 @@ +import { Component, Input } from '@angular/core'; + +import { Options } from 'angular2-notifications/src/options.type'; + + +@Component({ + selector: 'igo-message-center', + templateUrl: './message-center.component.html', + styleUrls: ['./message-center.component.styl'], +}) + +export class MessageCenterComponent { + + static defaultOptions = { + timeOut: 500000, + showProgressBar: true, + pauseOnHover: true, + clickToClose: true, + maxLength: 100, + maxStack: 3, + preventDuplicates: true + }; + + @Input() + get options(): Options { + return Object.assign( + {}, MessageCenterComponent.defaultOptions, this._options); + } + set options(value: Options) { + this._options = value; + } + private _options: Options = ''; + + constructor() { } + +} diff --git a/src/lib/core/message/shared/message.enum.ts b/src/lib/core/message/shared/message.enum.ts index cbf62d5d32..4c4d73e220 100644 --- a/src/lib/core/message/shared/message.enum.ts +++ b/src/lib/core/message/shared/message.enum.ts @@ -1,6 +1,6 @@ export enum MessageType { ERROR = 'error', - WARN = 'warn', + ALERT = 'alert', INFO = 'info', SUCCESS = 'success' } diff --git a/src/lib/core/message/shared/message.interface.ts b/src/lib/core/message/shared/message.interface.ts index 8ecc8e3823..3df722895c 100644 --- a/src/lib/core/message/shared/message.interface.ts +++ b/src/lib/core/message/shared/message.interface.ts @@ -3,6 +3,7 @@ import { MessageType } from './message.enum'; export interface Message { title?: string; text: string; + icon?: string; type?: MessageType; format?: 'text' | 'html'; } diff --git a/src/lib/core/message/shared/message.service.spec.ts b/src/lib/core/message/shared/message.service.spec.ts index fe72ecf1dd..800e22dc27 100644 --- a/src/lib/core/message/shared/message.service.spec.ts +++ b/src/lib/core/message/shared/message.service.spec.ts @@ -1,4 +1,5 @@ import { TestBed, inject } from '@angular/core/testing'; +import { NotificationsService } from 'angular2-notifications'; import { MessageService } from '.'; @@ -7,6 +8,7 @@ describe('MessageService', () => { TestBed.configureTestingModule({ imports: [], providers: [ + NotificationsService, MessageService ] }); diff --git a/src/lib/core/message/shared/message.service.ts b/src/lib/core/message/shared/message.service.ts index 112150435d..a58cbd9212 100644 --- a/src/lib/core/message/shared/message.service.ts +++ b/src/lib/core/message/shared/message.service.ts @@ -1,4 +1,6 @@ import { Injectable } from '@angular/core'; +import { NotificationsService } from 'angular2-notifications'; +import { Notification } from 'angular2-notifications/src/notification.type'; import { BehaviorSubject } from 'rxjs/BehaviorSubject'; import { Message } from './message.interface'; @@ -10,29 +12,51 @@ export class MessageService { public messages$ = new BehaviorSubject([]); - constructor() { } + constructor(private notificationService: NotificationsService) { } message(message: Message) { - const messages_ = this.messages$.value; - messages_.push(message); + this.messages$.next(this.messages$.value.concat([message])); - this.messages$.next(messages_); + const notification = this.notificationService.create( + message.title, message.text, message.type as any as string); + + if (message.icon !== undefined) { + this.addIcon(notification, message.icon); + } + } + + html(message: Message) { + this.messages$.next(this.messages$.value.concat([message])); + + this.notificationService.html(message.title, message.text); } - success(text: string, title?: string) { + success(text: string, title?: string, icon?: string) { this.message({ text: text, title: title, + icon: icon, type: MessageType.SUCCESS }); } - error(text: string, title?: string) { + error(text: string, title?: string, icon?: string) { this.message({ text: text, title: title, + icon: icon, type: MessageType.ERROR }); } + private addIcon(notification: Notification, icon: string) { + // There is no way to add an icon to a notification when reating + // it so we simply set it on the notification directly. + // See https://github.com/flauc/angular2-notifications/issues/165 + notification.icon = ` + + ${icon} + `; + } + } diff --git a/src/lib/core/module.ts b/src/lib/core/module.ts index d1fb7ef622..176e55e35e 100644 --- a/src/lib/core/module.ts +++ b/src/lib/core/module.ts @@ -1,5 +1,7 @@ import { NgModule, ModuleWithProviders } from '@angular/core'; +import { SimpleNotificationsModule } from 'angular2-notifications'; + import { TranslateModule, MissingTranslationHandler, TranslateService } from '@ngx-translate/core'; @@ -9,11 +11,12 @@ import { LanguageService, IgoMissingTranslationHandler, import { ActivityService } from './activity'; import { MediaService } from './media'; import { RequestService } from './request'; -import { MessageService } from './message'; +import { MessageCenterComponent, MessageService } from './message'; @NgModule({ imports: [ + SimpleNotificationsModule.forRoot(), TranslateModule.forRoot({ missingTranslationHandler: { provide: MissingTranslationHandler, @@ -21,7 +24,12 @@ import { MessageService } from './message'; } }) ], - exports: [] + declarations: [ + MessageCenterComponent + ], + exports: [ + MessageCenterComponent + ] }) export class IgoCoreModule { static forRoot(): ModuleWithProviders { diff --git a/src/lib/core/request/request.service.spec.ts b/src/lib/core/request/request.service.spec.ts index b47c64db8e..059403bb9e 100644 --- a/src/lib/core/request/request.service.spec.ts +++ b/src/lib/core/request/request.service.spec.ts @@ -1,4 +1,5 @@ import { TestBed, inject } from '@angular/core/testing'; +import { NotificationsService } from 'angular2-notifications'; import { HttpModule, JsonpModule } from '@angular/http'; import { MessageService } from '../message'; @@ -13,6 +14,7 @@ describe('RequestService', () => { JsonpModule ], providers: [ + NotificationsService, ActivityService, MessageService, RequestService diff --git a/src/lib/datasource/shared/capabilities.service.spec.ts b/src/lib/datasource/shared/capabilities.service.spec.ts index 62a751e659..d1ecfdd9b6 100644 --- a/src/lib/datasource/shared/capabilities.service.spec.ts +++ b/src/lib/datasource/shared/capabilities.service.spec.ts @@ -1,7 +1,7 @@ import { TestBed, inject } from '@angular/core/testing'; import { HttpModule } from '@angular/http'; -import { ActivityService, RequestService, MessageService } from '../../core'; +import { IgoCoreModule } from '../../core'; import { CapabilitiesService } from './capabilities.service'; @@ -9,12 +9,10 @@ describe('CapabilitiesService', () => { beforeEach(() => { TestBed.configureTestingModule({ imports: [ - HttpModule + HttpModule, + IgoCoreModule.forRoot() ], providers: [ - ActivityService, - RequestService, - MessageService, CapabilitiesService ] }); diff --git a/src/lib/datasource/shared/datasource.service.spec.ts b/src/lib/datasource/shared/datasource.service.spec.ts index 47d171f639..5129e56f4b 100644 --- a/src/lib/datasource/shared/datasource.service.spec.ts +++ b/src/lib/datasource/shared/datasource.service.spec.ts @@ -1,7 +1,7 @@ import { TestBed, inject } from '@angular/core/testing'; import { HttpModule } from '@angular/http'; -import { ActivityService, RequestService, MessageService } from '../../core'; +import { IgoCoreModule } from '../../core'; import { CapabilitiesService } from './capabilities.service'; import { DataSourceService } from './datasource.service'; @@ -11,12 +11,10 @@ describe('DataSourceService', () => { beforeEach(() => { TestBed.configureTestingModule({ imports: [ - HttpModule + HttpModule, + IgoCoreModule.forRoot() ], providers: [ - ActivityService, - RequestService, - MessageService, CapabilitiesService, DataSourceService ] diff --git a/src/lib/print/shared/print.service.spec.ts b/src/lib/print/shared/print.service.spec.ts index 440d00c434..83557d1192 100644 --- a/src/lib/print/shared/print.service.spec.ts +++ b/src/lib/print/shared/print.service.spec.ts @@ -1,17 +1,16 @@ import { TestBed, inject } from '@angular/core/testing'; -import { ActivityService, MessageService, RequestService } from '../../core'; +import { IgoCoreModule } from '../../core'; import { PrintService } from './print.service'; describe('PrintService', () => { beforeEach(() => { TestBed.configureTestingModule({ - imports: [], + imports: [ + IgoCoreModule.forRoot() + ], providers: [ - ActivityService, - MessageService, - RequestService, PrintService ] }); diff --git a/src/lib/print/shared/print.service.ts b/src/lib/print/shared/print.service.ts index db82f2ae70..e461c772b3 100644 --- a/src/lib/print/shared/print.service.ts +++ b/src/lib/print/shared/print.service.ts @@ -40,12 +40,14 @@ export class PrintService { this.addMap(doc, map, resolution, size, margins) .subscribe((status: SubjectStatus) => { - if (status === SubjectStatus.Done || status === SubjectStatus.Error) { + if (status === SubjectStatus.Done) { doc.save('map.pdf'); } - this.activityService.unregister(activityId); - status$.next(SubjectStatus.Done); + if (status === SubjectStatus.Done || status === SubjectStatus.Error) { + this.activityService.unregister(activityId); + status$.next(SubjectStatus.Done); + } }); return status$; @@ -75,8 +77,11 @@ export class PrintService { try { image = canvas.toDataURL('image/jpeg'); } catch (err) { - this.messageService.error(err, 'Print'); - throw new Error('Security error: This map cannot be printed.'); + this.messageService.error( + 'Security error: This map cannot be printed.', + 'Print', 'print'); + + throw new Error(err); } if (image !== undefined) { diff --git a/src/lib/query/shared/query.service.spec.ts b/src/lib/query/shared/query.service.spec.ts index c06e34ecba..96494dd26f 100644 --- a/src/lib/query/shared/query.service.spec.ts +++ b/src/lib/query/shared/query.service.spec.ts @@ -1,7 +1,7 @@ import { TestBed, inject } from '@angular/core/testing'; import { HttpModule } from '@angular/http'; -import { ActivityService, RequestService, MessageService } from '../../core'; +import { IgoCoreModule } from '../../core'; import { FeatureService } from '../../feature'; import { QueryService } from './query.service'; @@ -10,12 +10,10 @@ describe('QueryService', () => { beforeEach(() => { TestBed.configureTestingModule({ imports: [ - HttpModule + HttpModule, + IgoCoreModule.forRoot() ], providers: [ - ActivityService, - RequestService, - MessageService, FeatureService, QueryService ] diff --git a/src/lib/search/search-bar/search-bar.component.spec.ts b/src/lib/search/search-bar/search-bar.component.spec.ts index 704e3bf8d3..a753b4a5cf 100644 --- a/src/lib/search/search-bar/search-bar.component.spec.ts +++ b/src/lib/search/search-bar/search-bar.component.spec.ts @@ -1,7 +1,7 @@ import { async, ComponentFixture, TestBed, inject } from '@angular/core/testing'; +import { IgoCoreModule } from '../../core'; import { IgoSharedModule } from '../../shared'; -import { ActivityService, RequestService, MessageService } from '../../core'; import { FeatureService } from '../../feature'; import { provideSearchSourceService, @@ -16,13 +16,11 @@ describe('SearchBarComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [ + IgoCoreModule.forRoot(), IgoSharedModule ], declarations: [ SearchBarComponent ], providers: [ - ActivityService, - RequestService, - MessageService, FeatureService, SearchService, SearchSource, diff --git a/src/lib/search/shared/search.service.spec.ts b/src/lib/search/shared/search.service.spec.ts index 4df59c2836..714c43ede8 100644 --- a/src/lib/search/shared/search.service.spec.ts +++ b/src/lib/search/shared/search.service.spec.ts @@ -1,7 +1,7 @@ import { TestBed, inject } from '@angular/core/testing'; import { HttpModule, JsonpModule } from '@angular/http'; -import { ActivityService, RequestService, MessageService } from '../../core'; +import { IgoCoreModule } from '../../core'; import { SearchService } from './search.service'; import { provideSearchSourceService } from './search-source.service'; @@ -14,12 +14,10 @@ describe('SearchService', () => { TestBed.configureTestingModule({ imports: [ HttpModule, - JsonpModule + JsonpModule, + IgoCoreModule.forRoot() ], providers: [ - ActivityService, - RequestService, - MessageService, FeatureService, SearchService, provideSearchSourceOptions({ diff --git a/src/lib/tool/tools/context-manager-tool/context-manager-tool.component.spec.ts b/src/lib/tool/tools/context-manager-tool/context-manager-tool.component.spec.ts index 3e2a2ae3ff..b6a825e47c 100644 --- a/src/lib/tool/tools/context-manager-tool/context-manager-tool.component.spec.ts +++ b/src/lib/tool/tools/context-manager-tool/context-manager-tool.component.spec.ts @@ -1,8 +1,8 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { IgoCoreModule } from '../../../core'; import { IgoSharedModule } from '../../../shared'; import { IgoContextModule } from '../../../context'; -import { ActivityService, RequestService, MessageService } from '../../../core'; import { ToolService } from '../../shared/tool.service'; import { ContextManagerToolComponent } from './context-manager-tool.component'; @@ -14,6 +14,7 @@ describe('ContextManagerToolComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [ + IgoCoreModule.forRoot(), IgoSharedModule, IgoContextModule.forRoot(), ], @@ -21,9 +22,6 @@ describe('ContextManagerToolComponent', () => { ContextManagerToolComponent ], providers: [ - ActivityService, - MessageService, - RequestService, ToolService ] })