SignalR auth working

This commit is contained in:
Fergal Moran
2018-05-09 09:48:07 +01:00
parent 8725d632f0
commit fd22da93b8
54 changed files with 333 additions and 167 deletions

View File

@@ -24,6 +24,7 @@
"@angular/platform-browser": "6.0.0",
"@angular/platform-browser-dynamic": "6.0.0",
"@angular/router": "6.0.0",
"@aspnet/signalr": "^1.0.0-rtm-30751",
"@ngrx/effects": "^5.1.0",
"@ngrx/store": "^5.1.0",
"@ngrx/store-devtools": "^5.1.0",

View File

@@ -23,12 +23,29 @@ export const ADD_SUCCESS = '[Chat] Add Chat Success';
export const ADD_FAIL = '[Chat] Add Chat Fail';
export class AddAction implements Action {
readonly type = ADD;
constructor(public payload: ChatModel) {
}
constructor(public payload: ChatModel) {}
}
export class AddSuccessAction implements Action {
readonly type = ADD_SUCCESS;
constructor(public payload: ChatModel) {}
}
//#endregion
//#region Add
// the receive action is for messages from signalR
// we don't want to initiate a POST to the server.
export const RECEIVE = '[Chat] Receive Chat';
export const RECEIVE_SUCCESS = '[Chat] Receive Chat Success';
export const RECEIVE_FAIL = '[Chat] Receive Chat Fail';
export class ReceiveAction implements Action {
readonly type = RECEIVE;
constructor(public payload: ChatModel) {
console.log('chat.actions', 'RECEIVE', payload);
}
}
export class ReceiveSuccessAction implements Action {
readonly type = RECEIVE_SUCCESS;
constructor(public payload: ChatModel) {
console.log('chat.actions', 'RECEIVE_SUCESS', payload);
}
}
//#endregion
@@ -37,5 +54,6 @@ export type Actions =
| LoadSuccessAction
| LoadFailAction
| AddAction
| AddSuccessAction;
| AddSuccessAction
| ReceiveAction
| ReceiveSuccessAction;

View File

@@ -58,13 +58,11 @@ export class AppComponent implements OnInit {
const chatterChannel = `${p.id}`;
this._signalrService
.init('userupdates')
.then((r) => {
this._signalrService.connection.on(
chatterChannel,
(result) => {
this._toastyService.info(result);
}
);
.then((listener) => {
listener.on<string>(chatterChannel)
.subscribe(result => {
this._toastyService.info(result);
});
})
.catch((err) => {
console.error(

View File

@@ -156,7 +156,7 @@ export function provideConfig() {
authDomain: 'podnoms-api.firebaseapp.com',
databaseURL: 'https://podnoms-api.firebaseio.com',
projectId: 'podnoms-api',
storageBucket: '',
storageBucket: 'podnoms-api.appspot.com',
messagingSenderId: '357461672895'
}),
AngularFireDatabaseModule,

View File

@@ -25,8 +25,9 @@
</div>
</div>
<div class="chat-controls" *ngIf="!loading">
<input class="message-input" placeholder="Type your message here..." type="text" #message (keyup.enter)="sendMessage(message)">
<div class="chat-controls">
<input #message class="message-input" placeholder="Type your message and press enter..." type="text"
(keyup.enter)="sendMessage(message)">
<div class="chat-extra">
<a href="#">
<span class="extra-tooltip">Attach Document</span>

View File

@@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core';
import { Component, ViewChild, ElementRef } from '@angular/core';
import { ProfileService } from '../../services/profile.service';
import { SignalRService } from '../../services/signalr.service';
import { ProfileModel } from 'app/models/profile.model';
@@ -15,11 +15,17 @@ import { Observable } from 'rxjs/Observable';
templateUrl: './chat-widget.component.html',
styleUrls: ['./chat-widget.component.css']
})
export class ChatWidgetComponent implements OnInit {
export class ChatWidgetComponent {
chatActive: boolean = false;
loading: boolean = false;
user: ProfileModel;
private user: ProfileModel;
messages$: Observable<ChatModel[]>;
private messageEl: ElementRef;
// have to handle ViewChild like this as it's hidden with ngIf
@ViewChild('message')
set content(content: ElementRef) {
this.messageEl = content;
}
constructor(
private _profileService: ProfileService,
@@ -28,25 +34,17 @@ export class ChatWidgetComponent implements OnInit {
) {
this._profileService.getProfile().subscribe((p) => (this.user = p));
this.messages$ = _store.select(fromChat.getChat);
this.messages$.subscribe((r) => {
if (r.length != 0) {
this.chatActive = true;
}
});
}
ngOnInit() {}
togglePopup() {
this.chatActive = !this.chatActive;
if (this.chatActive && this.user) {
this.loading = true;
this._signalRService.init('chat').then(() => {
this.loading = false;
this._signalRService.connection.on('SendMessage', (message) => {
console.log(
'chat-widget.component',
'SendMessage',
message
);
});
});
if (this.chatActive) {
setTimeout(() => this.messageEl.nativeElement.focus(), 0);
}
}

View File

@@ -10,6 +10,7 @@ import * as fromEntriesActions from 'app/actions/entries.actions';
import { PodcastService } from '../../../services/podcast.service';
import { AudioService } from 'app/services/audio.service';
import { Observable } from 'rxjs/Observable';
import { AudioProcessingMessageModel } from 'app/models/audioprocessingmessage.model';
@Component({
selector: '[app-entry-list-item]',
@@ -39,23 +40,22 @@ export class EntryListItemComponent implements OnInit {
) {
this._signalRService
.init('audioprocessing')
.then(() => {
.then((listener) => {
const updateChannel: string = `${
this.entry.uid
}__progress_update`;
const processedChannel: string = `${
this.entry.uid
}__info_processed`;
this._signalRService.connection.on(
updateChannel,
(result) => {
listener
.on<AudioProcessingMessageModel>(updateChannel)
.subscribe((result) => {
this.percentageProcessed = result.percentage;
this.currentSpeed = result.currentSpeed;
}
);
this._signalRService.connection.on(
processedChannel,
(result) => {
});
listener
.on<PodcastEntryModel>(processedChannel)
.subscribe((result) => {
this.entry = result;
if (this.entry.processingStatus === 'Processed') {
// only update the store when we're finished.
@@ -65,8 +65,7 @@ export class EntryListItemComponent implements OnInit {
)
);
}
}
);
});
})
.catch((err) =>
console.error(

View File

@@ -1,7 +1,4 @@
import {
LoadAction,
LOAD_FAIL
} from './../actions/chat.actions';
import { LoadAction, LOAD_FAIL } from './../actions/chat.actions';
import { Injectable } from '@angular/core';
import { Actions, Effect } from '@ngrx/effects';
import { Observable } from 'rxjs/Observable';
@@ -22,17 +19,26 @@ export class ChatEffects {
.switchMap((payload: chat.LoadAction) =>
this._service
.get()
.map(res => ({ type: chat.LOAD_SUCCESS, payload: res }))
.catch(err => {
.map((res) => ({ type: chat.LOAD_SUCCESS, payload: res }))
.catch((err) => {
console.error('ChatEffects', 'get$', err);
return Observable.of({ type: chat.LOAD_FAIL });
})
);
@Effect()
put$ = this.actions$
.ofType(chat.ADD)
.switchMap((action: chat.AddAction) => this._service.send(action.payload))
.map(res => ({ type: chat.ADD_SUCCESS, payload: res }));
@Effect()
put$ = this.actions$
.ofType(chat.ADD)
.switchMap((action: chat.AddAction) =>
this._service.send(action.payload)
)
.map((res) => ({ type: chat.ADD_SUCCESS, payload: res }));
@Effect()
receive$ = this.actions$
.ofType(chat.RECEIVE)
.map((res: chat.ReceiveAction) => ({ type: chat.RECEIVE_SUCCESS, payload: res.payload }));
// receive$ = this.actions$.ofType(chat.RECEIVE).map((res) => {
// return { type: chat.RECEIVE_SUCCESS, payload: res };
// });
constructor(private _service: ChatService, private actions$: Actions) {}
}

View File

@@ -0,0 +1,6 @@
export class AudioProcessingMessageModel {
percentage: number;
totalSize: string;
currentSpeed: string;
eTA: string;
}

View File

@@ -33,7 +33,8 @@ export function reducer(state = initialState, action: chat.Actions): State {
loading: false
};
}
case chat.ADD_SUCCESS: {
case chat.ADD_SUCCESS:
case chat.RECEIVE_SUCCESS: {
const newResults = _.clone(state.result);
newResults.push(action.payload);
const newState = {

View File

@@ -4,11 +4,35 @@ import { Observable } from 'rxjs/Observable';
import { environment } from 'environments/environment';
import { ChatModel } from 'app/models/chat.model';
import { HttpClient } from '@angular/common/http';
import { SignalRService } from './signalr.service';
import { Subject } from 'rxjs';
import * as fromChat from 'app/reducers';
import * as fromChatActions from 'app/actions/chat.actions';
import { ApplicationState } from '../store';
import { Store } from '@ngrx/store';
@Injectable()
export class ChatService extends BaseService {
constructor(private _http: HttpClient) {
constructor(
private _http: HttpClient,
private _signalRService: SignalRService,
private _store: Store<ApplicationState>
) {
super();
this._signalRService.init('chat').then((listener) => {
listener
.on<ChatModel>('SendMessage')
.subscribe((message: ChatModel) => {
console.log(
'chat-widget.component',
'SendMessage',
message
);
this._store.dispatch(
new fromChatActions.ReceiveAction(message)
);
});
});
}
get(): Observable<ChatModel[]> {

View File

@@ -18,7 +18,7 @@ export class MessagingService {
private _pushRegistrationServer: PushRegistrationService
) {
this.messaging.usePublicVapidKey(
'BKyhUqIVZLauKNA-DXPXbIVLj5XiWurHbRV_0Rd3BOjY5cU9GOrd5ptXVJ2CNExxdveKYzZevrep2CflKeqkyqo'
'BP05eVFzqeEh54DaL3TOe6x_8UFs60nw_gfSrI5tdILjb5VnHwas0n7c_075tsc1w5fm87u9d4Dawj_YN13PSAI'
);
}

View File

@@ -1,31 +1,37 @@
import { PodnomsAuthService } from './podnoms-auth.service';
import { Injectable } from '@angular/core';
import {
HubConnection,
HubConnectionBuilder,
JsonHubProtocol,
LogLevel
} from '@aspnet/signalr';
import { HubConnection, HubConnectionBuilder, LogLevel } from '@aspnet/signalr';
import { environment } from 'environments/environment';
import { Observable, Subscriber } from 'rxjs';
@Injectable()
export class SignalRService {
public connection: HubConnection;
private _connected: boolean = false;
private _connection: HubConnection;
constructor(private _auth: PodnomsAuthService) {}
public init(hub: string): Promise<void> {
const url = `${environment.SIGNALR_HOST}/hubs/${hub}`;
public init(hub: string): Promise<SignalRService> {
return new Promise((resolve) => {
const url = `${environment.SIGNALR_HOST}/hubs/${hub}`;
const token = this._auth.getToken();
this._connection = new HubConnectionBuilder()
.configureLogging(LogLevel.Debug)
.withUrl(url + '?token=' + token)
.build();
resolve(this);
});
}
const token = this._auth.getToken();
const options: any = {
transport: 0
};
this.connection = new HubConnectionBuilder()
.configureLogging(LogLevel.Error)
.withUrl(url + '?token=' + token, options)
.withHubProtocol(new JsonHubProtocol())
.build();
return this.connection.start();
public on<T>(channel: string): Observable<T> {
const listener = new Observable<T>((subscriber: Subscriber<T>) => {
this._connection.on(channel, (message) => {
const result: T = message as T;
subscriber.next(result);
});
});
if (!this._connected) {
this._connection.start().then(() => (this._connected = true));
}
return listener;
}
}

View File

@@ -32,9 +32,6 @@
ga('send', 'pageview');
</script>
<!-- End Google Analytics -->
<!-- Begin Crisp -->
<script type="text/javascript">window.$crisp = []; window.CRISP_WEBSITE_ID = "af7d6aa7-0cb8-4f74-89aa-7f3742058e85"; (function () { d = document; s = d.createElement("script"); s.src = "https://client.crisp.chat/l.js"; s.async = 1; d.getElementsByTagName("head")[0].appendChild(s); })();</script>
<!-- End Crisp -->
</body>
</html>