config/production.yaml
ffmpeg
.tags
+*.sublime-project
+*.sublime-workspace
+torrent/
import { AdminComponent } from './admin.component';
import { FriendsRoutes } from './friends';
+import { RequestsRoutes } from './requests';
import { UsersRoutes } from './users';
export const AdminRoutes: Routes = [
pathMatch: 'full'
},
...FriendsRoutes,
+ ...RequestsRoutes,
...UsersRoutes
]
}
export * from './friends';
+export * from './requests';
export * from './users';
export * from './admin.component';
export * from './admin.routes';
<span class="hidden-xs glyphicon glyphicon-cloud"></span>
<a [routerLink]="['/admin/friends/list']">List friends</a>
</div>
+
+ <div id="panel-request-stats" class="panel-button">
+ <span class="hidden-xs glyphicon glyphicon-stats"></span>
+ <a [routerLink]="['/admin/requests/stats']">Request stats</a>
+ </div>
</div>
<div class="panel-block">
--- /dev/null
+export * from './request-stats';
+export * from './shared';
+export * from './requests.component';
+export * from './requests.routes';
--- /dev/null
+export * from './request-stats.component';
--- /dev/null
+<h3>Requests stats</h3>
+
+<div *ngIf="stats !== null">
+ <div>
+ <span class="label-description">Interval seconds between requests:</span>
+ {{ secondsInterval }}
+ </div>
+
+ <div>
+ <span class="label-description">Remaining time before the scheduled request:</span>
+ {{ remainingSeconds }}
+ </div>
+
+ <div>
+ <span class="label-description">Total requests:</span>
+ {{ stats.requests.length }}
+ </div>
+</div>
--- /dev/null
+.label-description {
+ display: inline-block;
+ width: 350px;
+ font-weight: bold;
+ color: black;
+}
--- /dev/null
+import { Component, OnInit, OnDestroy } from '@angular/core';
+
+import { RequestService, RequestStats } from '../shared';
+
+@Component({
+ selector: 'my-request-stats',
+ templateUrl: './request-stats.component.html',
+ styleUrls: [ './request-stats.component.scss' ]
+})
+export class RequestStatsComponent implements OnInit, OnDestroy {
+ stats: RequestStats = null;
+
+ private interval: NodeJS.Timer = null;
+
+ constructor(private requestService: RequestService) { }
+
+ ngOnInit() {
+ this.getStats();
+ }
+
+ ngOnDestroy() {
+ if (this.secondsInterval !== null) {
+ clearInterval(this.interval);
+ }
+ }
+
+ get remainingSeconds() {
+ return Math.floor(this.stats.remainingMilliSeconds / 1000);
+ }
+
+ get secondsInterval() {
+ return Math.floor(this.stats.milliSecondsInterval / 1000);
+ }
+
+ getStats() {
+ this.requestService.getStats().subscribe(
+ stats => {
+ console.log(stats);
+ this.stats = stats;
+ this.runInterval();
+ },
+
+ err => alert(err)
+ );
+ }
+
+ private runInterval() {
+ this.interval = setInterval(() => {
+ this.stats.remainingMilliSeconds -= 1000;
+
+ if (this.stats.remainingMilliSeconds <= 0) {
+ setTimeout(() => this.getStats(), this.stats.remainingMilliSeconds + 100);
+ clearInterval(this.interval);
+ }
+ }, 1000);
+ }
+
+
+}
--- /dev/null
+import { Component } from '@angular/core';
+
+@Component({
+ template: '<router-outlet></router-outlet>'
+})
+
+export class RequestsComponent {
+}
--- /dev/null
+import { Routes } from '@angular/router';
+
+import { RequestsComponent } from './requests.component';
+import { RequestStatsComponent } from './request-stats';
+
+export const RequestsRoutes: Routes = [
+ {
+ path: 'requests',
+ component: RequestsComponent,
+ children: [
+ {
+ path: '',
+ redirectTo: 'stats',
+ pathMatch: 'full'
+ },
+ {
+ path: 'stats',
+ component: RequestStatsComponent
+ }
+ ]
+ }
+];
--- /dev/null
+export * from './request-stats.model';
+export * from './request.service';
--- /dev/null
+export interface RequestStats {
+ milliSecondsInterval: number;
+ remainingMilliSeconds: number;
+ requests: {
+ request: any,
+ to: any
+ }[];
+}
--- /dev/null
+import { Injectable } from '@angular/core';
+import { Observable } from 'rxjs/Observable';
+
+import { RequestStats } from './request-stats.model';
+import { AuthHttp, RestExtractor } from '../../../shared';
+
+@Injectable()
+export class RequestService {
+ private static BASE_REQUEST_URL: string = '/api/v1/requests/';
+
+ constructor (
+ private authHttp: AuthHttp,
+ private restExtractor: RestExtractor
+ ) {}
+
+ getStats(): Observable<RequestStats> {
+ return this.authHttp.get(RequestService.BASE_REQUEST_URL + 'stats')
+ .map(this.restExtractor.extractDataGet)
+ .catch((res) => this.restExtractor.handleError(res));
+ }
+}
FriendListComponent,
FriendService,
MenuAdminComponent,
+ RequestsComponent,
+ RequestStatsComponent,
+ RequestService,
UsersComponent,
UserAddComponent,
UserListComponent,
VideoService,
SearchService,
FriendService,
+ RequestService,
UserService,
AccountService,
WebTorrentService
LoginComponent,
MenuAdminComponent,
MenuComponent,
+ RequestsComponent,
+ RequestStatsComponent,
SearchComponent,
UserAddComponent,
UserListComponent,
return res.json({
requests: requests,
- remainingMilliSeconds: remainingMilliSeconds
+ remainingMilliSeconds: remainingMilliSeconds,
+ milliSecondsInterval: constants.REQUESTS_INTERVAL
})
})
}