openvidu-testapp API REST features

pull/73/head
pabloFuente 2018-05-18 12:46:41 +02:00
parent 65fb9505e9
commit f0a53a7701
10 changed files with 295 additions and 38 deletions

View File

@ -18,7 +18,8 @@ import {
MatChipsModule,
MatExpansionModule,
MatSlideToggleModule,
MatSidenavModule
MatSidenavModule,
MatFormFieldModule
} from '@angular/material';
@NgModule({
@ -41,7 +42,8 @@ import {
MatChipsModule,
MatExpansionModule,
MatSlideToggleModule,
MatSidenavModule
MatSidenavModule,
MatFormFieldModule
],
})
export class AppMaterialModule { }

View File

@ -10,13 +10,15 @@ import { AppComponent } from './app.component';
import { TestSessionsComponent } from './components/test-sessions/test-sessions.component';
import { TestApirestComponent } from './components/test-apirest/test-apirest.component';
import { OpenviduInstanceComponent } from './components/openvidu-instance/openvidu-instance.component';
import { ExtensionDialogComponent } from './components/openvidu-instance/extension-dialog.component';
import { LocalRecordingDialogComponent } from './components/test-sessions/local-recording-dialog.component';
import { ExtensionDialogComponent } from './components/dialogs/extension-dialog.component';
import { LocalRecordingDialogComponent } from './components/dialogs/local-recording-dialog.component';
import { OpenviduRestService } from './services/openvidu-rest.service';
import { OpenviduParamsService } from './services/openvidu-params.service';
import { TestFeedService } from './services/test-feed.service';
import { MuteSubscribersService } from './services/mute-subscribers.service';
import { SessionPropertiesDialogComponent } from './components/dialogs/session-properties-dialog.component';
import { SessionApiDialogComponent } from './components/dialogs/session-api-dialog.component';
@NgModule({
declarations: [
@ -25,6 +27,8 @@ import { MuteSubscribersService } from './services/mute-subscribers.service';
TestSessionsComponent,
TestApirestComponent,
ExtensionDialogComponent,
SessionPropertiesDialogComponent,
SessionApiDialogComponent,
LocalRecordingDialogComponent
],
imports: [
@ -43,6 +47,8 @@ import { MuteSubscribersService } from './services/mute-subscribers.service';
],
entryComponents: [
ExtensionDialogComponent,
SessionPropertiesDialogComponent,
SessionApiDialogComponent,
LocalRecordingDialogComponent
],
bootstrap: [AppComponent]

View File

@ -0,0 +1,112 @@
import { Component, Inject } from '@angular/core';
import { MatDialog, MAT_DIALOG_DATA, MatDialogConfig, MatDialogRef } from '@angular/material';
import { Session } from 'openvidu-browser';
import { OpenVidu as OpenViduAPI } from 'openvidu-node-client';
@Component({
selector: 'app-session-properties-dialog',
template: `
<div>
<h2 mat-dialog-title>API REST</h2>
<mat-dialog-content>
<button mat-button (click)="startRecording()">Start recording</button>
<button mat-button (click)="listRecordings()">List recordings</button>
<mat-divider></mat-divider>
<mat-form-field>
<input matInput placeholder="recordingId" [(ngModel)]="recordingId">
</mat-form-field>
<button mat-button (click)="stopRecording()" [disabled]="!recordingId">Stop recording</button>
<button mat-button (click)="getRecording()" [disabled]="!recordingId">Get recording</button>
<button mat-button (click)="deleteRecording()" [disabled]="!recordingId">Delete recording</button>
<mat-form-field *ngIf="!!response" id="response-text-area">
<textarea [(ngModel)]="response" matInput readonly></textarea>
</mat-form-field>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-button [mat-dialog-close]="undefined">CLOSE</button>
</mat-dialog-actions>
</div>
`,
styles: [
'#response-text-area { width: 100%; color: #808080; }',
'#response-text-area textarea { resize: none; }',
'mat-dialog-content button, mat-divider { margin-bottom: 5px; }',
]
})
export class SessionApiDialogComponent {
OV: OpenViduAPI;
sessionId: string;
recordingId: string;
response: string;
constructor(public dialogRef: MatDialogRef<SessionApiDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data) {
this.OV = data.openVidu;
this.sessionId = data.sessionId;
}
startRecording() {
console.log('Starting recording');
this.OV.startRecording(this.sessionId)
.then(recording => {
this.response = 'Recording started [' + recording.id + ']';
})
.catch(error => {
this.response = 'Error [' + error.message + ']';
});
}
stopRecording() {
console.log('Stopping recording');
this.OV.stopRecording(this.recordingId)
.then(recording => {
this.response = 'Recording stopped [' + recording.id + ']';
})
.catch(error => {
this.response = 'Error [' + error.message + ']';
});
}
getRecording() {
console.log('Getting recording');
this.OV.getRecording(this.recordingId)
.then(recording => {
this.response = 'Recording got [' + recording.id + ']';
})
.catch(error => {
this.response = 'Error [' + error.message + ']';
});
}
listRecordings() {
console.log('Listing recordings');
this.OV.listRecordings()
.then(recordingList => {
let recordingIds = '';
recordingList.forEach((rec, index) => {
recordingIds += rec.id;
if (index !== recordingList.length - 1) {
recordingIds += ', ';
}
});
this.response = 'Recording list [' + recordingIds + ']';
})
.catch(error => {
this.response = 'Error [' + error.message + ']';
});
}
deleteRecording() {
console.log('Deleting recording');
this.OV.deleteRecording(this.recordingId)
.then(() => {
this.response = 'Recording deleted';
})
.catch(error => {
this.response = 'Error [' + error.message + ']';
});
}
}

View File

@ -0,0 +1,64 @@
import { Component, Inject } from '@angular/core';
import { MatDialog, MAT_DIALOG_DATA, MatDialogConfig, MatDialogRef } from '@angular/material';
import { SessionProperties, MediaMode, RecordingMode, RecordingLayout } from 'openvidu-node-client';
@Component({
selector: 'app-session-properties-dialog',
template: `
<div>
<h2 mat-dialog-title>Session properties</h2>
<mat-dialog-content>
<mat-form-field>
<mat-select placeholder="MediaMode" [(ngModel)]="sessionProperties.mediaMode">
<mat-option *ngFor="let enumerator of enumToArray(mediaMode)" [value]="enumerator">
{{ enumerator }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field>
<mat-select placeholder="RecordingMode" [(ngModel)]="sessionProperties.recordingMode">
<mat-option *ngFor="let enumerator of enumToArray(recordingMode)" [value]="enumerator">
{{ enumerator }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field>
<mat-select placeholder="DefaultRecordingLayout" [(ngModel)]="sessionProperties.defaultRecordingLayout">
<mat-option *ngFor="let enumerator of enumToArray(defaultRecordingLayout)" [value]="enumerator">
{{ enumerator }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field *ngIf="this.sessionProperties.defaultRecordingLayout === 'CUSTOM'">
<input matInput placeholder="DefaultCustomLayout" [(ngModel)]="sessionProperties.defaultCustomLayout">
</mat-form-field>
<mat-form-field>
<input matInput placeholder="CustomSessionId" [(ngModel)]="sessionProperties.customSessionId">
</mat-form-field>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-button [mat-dialog-close]="undefined">CANCEL</button>
<button mat-button [mat-dialog-close]="sessionProperties">SAVE</button>
</mat-dialog-actions>
</div>
`
})
export class SessionPropertiesDialogComponent {
sessionProperties: SessionProperties;
private mediaMode = MediaMode;
private recordingMode = RecordingMode;
private defaultRecordingLayout = RecordingLayout;
constructor(public dialogRef: MatDialogRef<SessionPropertiesDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: SessionProperties) {
this.sessionProperties = data;
}
enumToArray(enumerator: any) {
return Object.keys(enumerator);
}
}

View File

@ -18,11 +18,14 @@ mat-card.session-card {
}
.session-form mat-form-field {
width: 130px;
width: 110px;
}
.join-card {
width: fit-content;
min-height: 215px;
padding-top: 20px;
padding-bottom: 10px;
}
.join-card mat-card-content {
@ -33,6 +36,7 @@ mat-card.session-card {
border: 1px solid #e1e1e1;
padding: 10px 15px 10px 15px;
background: #ffffff;
margin-top: 5px;
}
.inner-card h4 {
@ -93,7 +97,7 @@ mat-radio-button {
.event-list-div {
display: inline-block;
width: 130px;
height: 183.5px;
height: 180px;
overflow-y: auto;
overflow-x: hidden;
}
@ -133,6 +137,20 @@ mat-expansion-panel-header {
padding: 0 7px 0 9px !important;
}
.secure-div mat-checkbox {
padding-right: 10px;
.mat-icon-custom {
width: 29px;
height: 29px;
line-height: 18px;
}
.mat-icon-custom-ic {
width: 20px;
height: 20px;
font-size: 20px;
line-height: 20px;
}
.session-btns-div {
margin-top: -14px;
margin-right: -14px;
}

View File

@ -6,14 +6,7 @@
<mat-card-content>
<form class="session-form">
<div class="secure-div">
<mat-checkbox class="secure-session-checkbox" [disabled]="session" [(ngModel)]="secureSession" name="secureSession">SECURE</mat-checkbox>
<mat-form-field>
<input class="tokenInput" matInput placeholder="TOKEN" name="tokenInput" [(ngModel)]="tokenInput" [disabled]="!secureSession">
</mat-form-field>
</div>
<div>
<div fxLayout="row">
<mat-form-field style="margin-right: 10px">
<input matInput placeholder="Session name" name="sessionName" [(ngModel)]="sessionName" [disabled]="session">
</mat-form-field>
@ -21,6 +14,16 @@
<mat-form-field>
<input matInput placeholder="Client data" name="clientData" [(ngModel)]="clientData" [disabled]="session">
</mat-form-field>
<div fxLayout="column" class="session-btns-div">
<button mat-icon-button title="Session properties" id="session-settings-btn" class="mat-icon-custom" (click)="openSessionPropertiesDialog()" [disabled]="session">
<mat-icon class="mat-icon-custom-ic" aria-label="Session properties button">settings</mat-icon>
</button>
<button mat-icon-button title="Session API" id="session-api-btn" class="mat-icon-custom" (click)="openSessionApiDialog()">
<mat-icon class="mat-icon-custom-ic" aria-label="Session API button">cloud_circle</mat-icon>
</button>
</div>
</div>
<div>

View File

@ -9,11 +9,21 @@ import {
LocalRecorder, VideoInsertMode, StreamEvent, ConnectionEvent,
SessionDisconnectedEvent, SignalEvent, RecordingEvent, VideoElementEvent
} from 'openvidu-browser';
import {
OpenVidu as OpenViduAPI,
Session as SessionAPI,
SessionProperties as SessionPropertiesAPI,
MediaMode,
RecordingMode,
RecordingLayout
} from 'openvidu-node-client';
import { MatDialog, MatDialogRef } from '@angular/material';
import { ExtensionDialogComponent } from './extension-dialog.component';
import { LocalRecordingDialogComponent } from '../test-sessions/local-recording-dialog.component';
import { ExtensionDialogComponent } from '../dialogs/extension-dialog.component';
import { LocalRecordingDialogComponent } from '../dialogs/local-recording-dialog.component';
import { TestFeedService } from '../../services/test-feed.service';
import { MuteSubscribersService } from '../../services/mute-subscribers.service';
import { SessionPropertiesDialogComponent } from '../dialogs/session-properties-dialog.component';
import { SessionApiDialogComponent } from '../dialogs/session-api-dialog.component';
declare var $: any;
@ -47,10 +57,8 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
sessionConf: SessionConf;
// Session join data
secureSession = false;
clientData: string;
sessionName: string;
tokenInput: string;
// Session options
subscribeTo;
@ -79,12 +87,21 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
disableActiveVideo = false;
disableRadioButtons = false;
// OpenVidu objects
// OpenVidu Browser objects
OV: OpenVidu;
session: Session;
publisher: Publisher;
subscribers = {};
// OpenVidu Node Client objects
sessionProperties: SessionPropertiesAPI = {
mediaMode: MediaMode.ROUTED,
recordingMode: RecordingMode.MANUAL,
defaultRecordingLayout: RecordingLayout.BEST_FIT,
defaultCustomLayout: '',
customSessionId: ''
};
// Session audio and video status
audioMuted = false;
videoMuted = false;
@ -108,7 +125,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
constructor(
private changeDetector: ChangeDetectorRef,
private extensionDialog: MatDialog,
private dialog: MatDialog,
private recordDialog: MatDialog,
private testFeedService: TestFeedService,
private muteSubscribersService: MuteSubscribersService,
@ -171,17 +188,9 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
this.leaveSession();
}
let token;
if (this.secureSession) {
token = this.tokenInput;
} else {
token = 'wss://'
+ this.removeHttps(this.openviduUrl)
+ '?sessionId=' + this.sessionName
+ '&secret=' + this.openviduSecret;
}
this.joinSessionShared(token);
this.getToken().then(token => {
this.joinSessionShared(token);
});
}
private joinSessionShared(token): void {
@ -580,7 +589,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
console.warn(err);
this.openviduError = err;
if (err.name === 'SCREEN_EXTENSION_NOT_INSTALLED') {
this.extensionDialog.open(ExtensionDialogComponent, {
this.dialog.open(ExtensionDialogComponent, {
data: { url: err.message },
disableClose: true,
width: '250px'
@ -856,7 +865,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
console.warn(err);
this.openviduError = err;
if (err.name === 'SCREEN_EXTENSION_NOT_INSTALLED') {
this.extensionDialog.open(ExtensionDialogComponent, {
this.dialog.open(ExtensionDialogComponent, {
data: { url: err.message },
disableClose: true,
width: '250px'
@ -905,7 +914,7 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
console.error(err);
this.openviduError = err;
if (err.name === 'SCREEN_EXTENSION_NOT_INSTALLED') {
this.extensionDialog.open(ExtensionDialogComponent, {
this.dialog.open(ExtensionDialogComponent, {
data: { url: err.message },
disableClose: true,
width: '250px'
@ -1027,4 +1036,47 @@ export class OpenviduInstanceComponent implements OnInit, OnChanges, OnDestroy {
});
}
openSessionPropertiesDialog() {
this.sessionProperties.customSessionId = this.sessionName;
const dialogRef = this.dialog.open(SessionPropertiesDialogComponent, {
data: this.sessionProperties,
width: '235px'
});
dialogRef.afterClosed().subscribe((result: SessionPropertiesAPI) => {
if (!!result) {
this.sessionProperties = result;
if (!!this.sessionProperties.customSessionId) {
this.sessionName = this.sessionProperties.customSessionId;
}
}
document.getElementById('session-settings-btn').classList.remove('cdk-program-focused');
});
}
openSessionApiDialog() {
const dialogRef = this.dialog.open(SessionApiDialogComponent, {
data: {
openVidu: new OpenViduAPI(this.openviduUrl, this.openviduSecret),
sessionId: !!this.session ? this.session.sessionId : this.sessionName
},
width: '280px'
});
dialogRef.afterClosed().subscribe((result: string) => {
document.getElementById('session-api-btn').classList.remove('cdk-program-focused');
});
}
getToken(): Promise<string> {
const OV_NodeClient = new OpenViduAPI(this.openviduUrl, this.openviduSecret);
if (!this.sessionProperties.customSessionId) {
this.sessionProperties.customSessionId = this.sessionName;
}
return OV_NodeClient.createSession(this.sessionProperties)
.then(session_NodeClient => {
return session_NodeClient.generateToken();
});
}
}

View File

@ -61,7 +61,7 @@
<div id="table-row" fxLayout="row" fxLayoutGap="20px" fxLayoutAlign="start">
<div fxLayout="column" fxFlex="65" fxFlexAlign="start" fxFill>
<table>
<table class="api-rest-table">
<tr>
<th *ngIf="this.data.length > 1">Selection</th>
<th class="first-col">Session IDs</th>