Skip to content

Commit 08e8a4b

Browse files
committed
Added signalr client service to SPA app
1 parent f1f1779 commit 08e8a4b

17 files changed

Lines changed: 157 additions & 43 deletions

File tree

src/Web/WebMVC/Views/Shared/_Layout.cshtml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@
9797
var timerId;
9898
9999
let connection = stablishConnection();
100-
100+
101101
connection.start().then(function () {
102102
console.log('User Registered to Signalr Hub');
103103
});

src/Web/WebSPA/.angular-cli.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
"prefix": "app",
2121
"styles": [
2222
"globals.scss",
23-
"../node_modules/bootstrap/scss/bootstrap.scss"
23+
"../node_modules/bootstrap/scss/bootstrap.scss",
24+
"../node_modules/ng2-toastr/bundles/ng2-toastr.min.css"
2425
],
2526
"scripts": [],
2627
"environmentSource": "environments/environment.ts",

src/Web/WebSPA/Client/modules/app.component.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import { Title } from '@angular/platform-browser';
2-
import { Component, ViewEncapsulation, OnInit } from '@angular/core';
2+
import { Component, ViewEncapsulation, OnInit, ViewContainerRef } from '@angular/core';
33
import { RouterModule } from '@angular/router';
44
import { Subscription } from 'rxjs/Subscription';
55

66
import { DataService } from './shared/services/data.service';
77
import { SecurityService } from './shared/services/security.service';
88
import { ConfigurationService } from './shared/services/configuration.service';
9+
import { SignalrService } from './shared/services/signalr.service';
10+
import { ToastsManager } from 'ng2-toastr';
911

1012
/*
1113
* App Component
@@ -21,7 +23,14 @@ export class AppComponent implements OnInit {
2123
Authenticated: boolean = false;
2224
subscription: Subscription;
2325

24-
constructor(private titleService: Title, private securityService: SecurityService, private configurationService: ConfigurationService) {
26+
constructor(private titleService: Title,
27+
private securityService: SecurityService,
28+
private configurationService: ConfigurationService,
29+
private signalrService: SignalrService,
30+
private toastr: ToastsManager,
31+
vcr: ViewContainerRef
32+
) {
33+
this.toastr.setRootViewContainerRef(vcr);
2534
this.Authenticated = this.securityService.IsAuthorized;
2635
}
2736

@@ -31,10 +40,10 @@ export class AppComponent implements OnInit {
3140

3241
//Get configuration from server environment variables:
3342
console.log('configuration');
34-
this.configurationService.load();
43+
this.configurationService.load();
3544
}
3645

3746
public setTitle(newTitle: string) {
38-
this.titleService.setTitle('eShopOnContainers');
47+
this.titleService.setTitle('eShopOnContainers');
3948
}
4049
}

src/Web/WebSPA/Client/modules/app.module.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { NgModule, NgModuleFactoryLoader } from '@angular/core';
1+
import { NgModule, NgModuleFactoryLoader } from '@angular/core';
2+
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
23
import { BrowserModule } from '@angular/platform-browser';
34
// import { FormsModule } from '@angular/forms';
45
import { HttpModule } from '@angular/http';
@@ -12,19 +13,23 @@ import { CatalogModule } from './catalog/catalog.module';
1213
import { OrdersModule } from './orders/orders.module';
1314
import { BasketModule } from './basket/basket.module';
1415
import { CampaignsModule } from './campaigns/campaigns.module';
16+
import { ToastModule } from 'ng2-toastr/ng2-toastr';
17+
1518

1619
@NgModule({
1720
declarations: [AppComponent],
1821
imports: [
22+
BrowserAnimationsModule,
1923
BrowserModule,
24+
ToastModule.forRoot(),
2025
routing,
2126
HttpModule,
2227
// Only module that app module loads
2328
SharedModule.forRoot(),
2429
CatalogModule,
2530
OrdersModule,
2631
BasketModule,
27-
CampaignsModule
32+
CampaignsModule
2833
],
2934
providers: [
3035
AppService

src/Web/WebSPA/Client/modules/basket/basket.component.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,7 @@ export class BasketComponent implements OnInit {
5252
x => {
5353
this.errorMessages = [];
5454
this.basketwrapper.basket = this.basket;
55-
this.router.navigate(['order'],
56-
errMessage => this.errorMessages = errMessage.messages);
55+
this.router.navigate(['order']);
5756
});
5857
}
5958

src/Web/WebSPA/Client/modules/orders/orders.component.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { OrdersService } from './orders.service';
33
import { IOrder } from '../shared/models/order.model';
44
import { ConfigurationService } from '../shared/services/configuration.service';
55
import { Observable } from 'rxjs/Observable';
6+
import { SignalrService } from '../shared/services/signalr.service';
67

78
@Component({
89
selector: 'esh-orders',
@@ -16,7 +17,7 @@ export class OrdersComponent implements OnInit {
1617

1718
orders: IOrder[];
1819

19-
constructor(private service: OrdersService, private configurationService: ConfigurationService) { }
20+
constructor(private service: OrdersService, private configurationService: ConfigurationService, private signalrService: SignalrService) { }
2021

2122
ngOnInit() {
2223
if (this.configurationService.isReady) {
@@ -27,15 +28,8 @@ export class OrdersComponent implements OnInit {
2728
});
2829
}
2930

30-
// call orders until new order is retrieved
31-
this.interval = setTimeout(() => {
32-
this.service.getOrders().subscribe(orders => {
33-
this.orders = orders;
34-
if (this.orders.length !== this.oldOrders.length) {
35-
clearInterval(this.interval);
36-
}
37-
});
38-
}, 1000);
31+
this.signalrService.msgReceived$
32+
.subscribe(x => this.getOrders());
3933
}
4034

4135
getOrders() {

src/Web/WebSPA/Client/modules/shared/components/identity/identity.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import { Component, OnInit, OnChanges, Output, Input, EventEmitter } from '@angu
22
import { Subscription } from 'rxjs/Subscription';
33

44
import { IIdentity } from '../../models/identity.model';
5-
import { SecurityService } from '../../services/security.service';
5+
import { SecurityService } from '../../services/security.service';
6+
import { SignalrService } from '../../services/signalr.service';
67

78
@Component({
89
selector: 'esh-identity',
@@ -14,7 +15,7 @@ export class Identity implements OnInit {
1415
private subscription: Subscription;
1516
private userName: string = '';
1617

17-
constructor(private service: SecurityService) {
18+
constructor(private service: SecurityService, private signalrService: SignalrService) {
1819

1920
}
2021

@@ -48,6 +49,7 @@ export class Identity implements OnInit {
4849
}
4950

5051
logout() {
52+
this.signalrService.stop();
5153
this.service.Logoff();
5254
}
5355
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { Injectable } from '@angular/core';
2+
import { SecurityService } from './security.service';
3+
import { ConfigurationService } from './configuration.service';
4+
import { HubConnection, HttpConnection, TransportType } from '@aspnet/signalr';
5+
import { ToastsManager } from 'ng2-toastr/ng2-toastr';
6+
import { Subject } from 'rxjs';
7+
8+
@Injectable()
9+
export class SignalrService {
10+
11+
private _hubConnection: HubConnection;
12+
private _httpConnection: HttpConnection;
13+
private orderApiUrl: string = '';
14+
private msgSignalrSource = new Subject();
15+
msgReceived$ = this.msgSignalrSource.asObservable();
16+
17+
constructor(
18+
private securityService: SecurityService,
19+
private configurationService: ConfigurationService, private toastr: ToastsManager,
20+
) {
21+
if (this.configurationService.isReady) {
22+
this.orderApiUrl = this.configurationService.serverSettings.purchaseUrl;
23+
this.init();
24+
}
25+
else {
26+
this.configurationService.settingsLoaded$.subscribe(x => {
27+
this.orderApiUrl = this.configurationService.serverSettings.purchaseUrl;
28+
this.init();
29+
});
30+
}
31+
}
32+
33+
public stop() {
34+
this._hubConnection.stop();
35+
}
36+
37+
private init() {
38+
if (this.securityService.IsAuthorized == true) {
39+
this.register();
40+
this.stablishConnection();
41+
this.registerHandlers();
42+
}
43+
}
44+
45+
private register() {
46+
this._httpConnection = new HttpConnection(this.orderApiUrl + '/orders-api/notificationhub', {
47+
transport: TransportType.LongPolling,
48+
accessTokenFactory: () => this.securityService.GetToken()
49+
});
50+
this._hubConnection = new HubConnection(this._httpConnection);
51+
}
52+
53+
private stablishConnection() {
54+
this._hubConnection.start()
55+
.then(() => {
56+
console.log('Hub connection started')
57+
})
58+
.catch(() => {
59+
console.log('Error while establishing connection')
60+
});
61+
}
62+
63+
private registerHandlers() {
64+
this._hubConnection.on('UpdatedOrderState', (msg) => {
65+
this.toastr.success('Updated to status: ' + msg.status, 'Order Id: ' + msg.orderId);
66+
this.msgSignalrSource.next();
67+
});
68+
}
69+
70+
}

src/Web/WebSPA/Client/modules/shared/shared.module.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@ import { BasketWrapperService} from './services/basket.wrapper.service';
1111
import { SecurityService } from './services/security.service';
1212
import { ConfigurationService } from './services/configuration.service';
1313
import { StorageService } from './services/storage.service';
14+
import { SignalrService } from './services/signalr.service';
1415

1516
// Components:
1617
import { Pager } from './components/pager/pager';
1718
import { Header } from './components/header/header';
1819
import { Identity } from './components/identity/identity';
1920
import { PageNotFoundComponent } from './components/page-not-found/page-not-found.component';
2021

22+
2123
// Pipes:
2224
import { UppercasePipe } from './pipes/uppercase.pipe';
2325

@@ -64,7 +66,8 @@ export class SharedModule {
6466
BasketWrapperService,
6567
SecurityService,
6668
ConfigurationService,
67-
StorageService
69+
StorageService,
70+
SignalrService
6871
]
6972
};
7073
}

src/Web/WebSPA/WebSPA.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
<None Remove="Client\modules\shared\services\data.service.ts" />
6464
<None Remove="Client\modules\shared\services\notification.service.ts" />
6565
<None Remove="Client\modules\shared\services\security.service.ts" />
66+
<None Remove="Client\modules\shared\services\signalr.service.ts" />
6667
<None Remove="Client\modules\shared\services\storage.service.ts" />
6768
<None Remove="Client\modules\shared\shared.module.ts" />
6869
<None Remove="Client\polyfills.ts" />
@@ -178,6 +179,7 @@
178179
<TypeScriptCompile Include="Client\modules\shared\services\data.service.ts" />
179180
<TypeScriptCompile Include="Client\modules\shared\services\notification.service.ts" />
180181
<TypeScriptCompile Include="Client\modules\shared\services\security.service.ts" />
182+
<TypeScriptCompile Include="Client\modules\shared\services\signalr.service.ts" />
181183
<TypeScriptCompile Include="Client\modules\shared\services\storage.service.ts" />
182184
<TypeScriptCompile Include="Client\modules\shared\shared.module.ts" />
183185
<TypeScriptCompile Include="Client\polyfills.ts" />

0 commit comments

Comments
 (0)