mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2024-08-17 17:30:32 +03:00
Use typescript standard and lint all files
This commit is contained in:
parent
46757b477c
commit
df98563e21
@ -13,7 +13,7 @@
|
||||
"url": "git://github.com/Chocobozzz/PeerTube.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "standard && tslint -c ./tslint.json src/**/*.ts",
|
||||
"test": "standard && tslint --type-check --project ./tsconfig.json -c ./tslint.json 'src/app/**/*.ts'",
|
||||
"webpack": "webpack",
|
||||
"webpack-dev-server": "webpack-dev-server"
|
||||
},
|
||||
@ -78,7 +78,7 @@
|
||||
"tslib": "^1.5.0",
|
||||
"tslint": "~5.4.3",
|
||||
"tslint-loader": "^3.3.0",
|
||||
"typescript": "~2.3.0",
|
||||
"typescript": "~2.4.0",
|
||||
"url-loader": "^0.5.7",
|
||||
"video.js": "^5.19.2",
|
||||
"videojs-dock": "^2.0.2",
|
||||
@ -93,6 +93,7 @@
|
||||
"codelyzer": "^3.0.0-beta.4",
|
||||
"ng2-completer": "1.2.2",
|
||||
"standard": "^10.0.0",
|
||||
"tslint-config-standard": "^6.0.1",
|
||||
"webpack-bundle-analyzer": "^2.8.2",
|
||||
"webpack-dev-server": "^2.4.5",
|
||||
"webpack-dll-bundles-plugin": "^1.0.0-beta.5"
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { NgModule } from '@angular/core'
|
||||
import { RouterModule, Routes } from '@angular/router'
|
||||
|
||||
import { AdminComponent } from './admin.component';
|
||||
import { FriendsRoutes } from './friends';
|
||||
import { RequestsRoutes } from './requests';
|
||||
import { UsersRoutes } from './users';
|
||||
import { VideoAbusesRoutes } from './video-abuses';
|
||||
import { AdminComponent } from './admin.component'
|
||||
import { FriendsRoutes } from './friends'
|
||||
import { RequestsRoutes } from './requests'
|
||||
import { UsersRoutes } from './users'
|
||||
import { VideoAbusesRoutes } from './video-abuses'
|
||||
|
||||
const adminRoutes: Routes = [
|
||||
{
|
||||
@ -23,7 +23,7 @@ const adminRoutes: Routes = [
|
||||
...VideoAbusesRoutes
|
||||
]
|
||||
}
|
||||
];
|
||||
]
|
||||
|
||||
@NgModule({
|
||||
imports: [ RouterModule.forChild(adminRoutes) ],
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Component } from '@angular/core'
|
||||
|
||||
@Component({
|
||||
template: '<router-outlet></router-outlet>'
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { NgModule } from '@angular/core'
|
||||
|
||||
import { AdminComponent } from './admin.component';
|
||||
import { AdminRoutingModule } from './admin-routing.module';
|
||||
import { FriendsComponent, FriendAddComponent, FriendListComponent, FriendService } from './friends';
|
||||
import { RequestsComponent, RequestStatsComponent, RequestService } from './requests';
|
||||
import { UsersComponent, UserAddComponent, UserListComponent, UserService } from './users';
|
||||
import { VideoAbusesComponent, VideoAbuseListComponent } from './video-abuses';
|
||||
import { SharedModule } from '../shared';
|
||||
import { AdminComponent } from './admin.component'
|
||||
import { AdminRoutingModule } from './admin-routing.module'
|
||||
import { FriendsComponent, FriendAddComponent, FriendListComponent, FriendService } from './friends'
|
||||
import { RequestsComponent, RequestStatsComponent, RequestService } from './requests'
|
||||
import { UsersComponent, UserAddComponent, UserListComponent, UserService } from './users'
|
||||
import { VideoAbusesComponent, VideoAbuseListComponent } from './video-abuses'
|
||||
import { SharedModule } from '../shared'
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FormControl, FormGroup } from '@angular/forms';
|
||||
import { Router } from '@angular/router';
|
||||
import { Component, OnInit } from '@angular/core'
|
||||
import { FormControl, FormGroup } from '@angular/forms'
|
||||
import { Router } from '@angular/router'
|
||||
|
||||
import { NotificationsService } from 'angular2-notifications';
|
||||
import { NotificationsService } from 'angular2-notifications'
|
||||
|
||||
import { ConfirmService } from '../../../core';
|
||||
import { validateHost } from '../../../shared';
|
||||
import { FriendService } from '../shared';
|
||||
import { ConfirmService } from '../../../core'
|
||||
import { validateHost } from '../../../shared'
|
||||
import { FriendService } from '../shared'
|
||||
|
||||
@Component({
|
||||
selector: 'my-friend-add',
|
||||
@ -14,107 +14,107 @@ import { FriendService } from '../shared';
|
||||
styleUrls: [ './friend-add.component.scss' ]
|
||||
})
|
||||
export class FriendAddComponent implements OnInit {
|
||||
form: FormGroup;
|
||||
hosts = [ ];
|
||||
error: string = null;
|
||||
form: FormGroup
|
||||
hosts = [ ]
|
||||
error: string = null
|
||||
|
||||
constructor(
|
||||
constructor (
|
||||
private router: Router,
|
||||
private notificationsService: NotificationsService,
|
||||
private confirmService: ConfirmService,
|
||||
private friendService: FriendService
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.form = new FormGroup({});
|
||||
this.addField();
|
||||
ngOnInit () {
|
||||
this.form = new FormGroup({})
|
||||
this.addField()
|
||||
}
|
||||
|
||||
addField() {
|
||||
this.form.addControl(`host-${this.hosts.length}`, new FormControl('', [ validateHost ]));
|
||||
this.hosts.push('');
|
||||
addField () {
|
||||
this.form.addControl(`host-${this.hosts.length}`, new FormControl('', [ validateHost ]))
|
||||
this.hosts.push('')
|
||||
}
|
||||
|
||||
canMakeFriends() {
|
||||
return window.location.protocol === 'https:';
|
||||
canMakeFriends () {
|
||||
return window.location.protocol === 'https:'
|
||||
}
|
||||
|
||||
customTrackBy(index: number, obj: any): any {
|
||||
return index;
|
||||
customTrackBy (index: number, obj: any): any {
|
||||
return index
|
||||
}
|
||||
|
||||
displayAddField(index: number) {
|
||||
return index === (this.hosts.length - 1);
|
||||
displayAddField (index: number) {
|
||||
return index === (this.hosts.length - 1)
|
||||
}
|
||||
|
||||
displayRemoveField(index: number) {
|
||||
return (index !== 0 || this.hosts.length > 1) && index !== (this.hosts.length - 1);
|
||||
displayRemoveField (index: number) {
|
||||
return (index !== 0 || this.hosts.length > 1) && index !== (this.hosts.length - 1)
|
||||
}
|
||||
|
||||
isFormValid() {
|
||||
isFormValid () {
|
||||
// Do not check the last input
|
||||
for (let i = 0; i < this.hosts.length - 1; i++) {
|
||||
if (!this.form.controls[`host-${i}`].valid) return false;
|
||||
if (!this.form.controls[`host-${i}`].valid) return false
|
||||
}
|
||||
|
||||
const lastIndex = this.hosts.length - 1;
|
||||
const lastIndex = this.hosts.length - 1
|
||||
// If the last input (which is not the first) is empty, it's ok
|
||||
if (this.hosts[lastIndex] === '' && lastIndex !== 0) {
|
||||
return true;
|
||||
return true
|
||||
} else {
|
||||
return this.form.controls[`host-${lastIndex}`].valid;
|
||||
return this.form.controls[`host-${lastIndex}`].valid
|
||||
}
|
||||
}
|
||||
|
||||
removeField(index: number) {
|
||||
removeField (index: number) {
|
||||
// Remove the last control
|
||||
this.form.removeControl(`host-${this.hosts.length - 1}`);
|
||||
this.hosts.splice(index, 1);
|
||||
this.form.removeControl(`host-${this.hosts.length - 1}`)
|
||||
this.hosts.splice(index, 1)
|
||||
}
|
||||
|
||||
makeFriends() {
|
||||
this.error = '';
|
||||
makeFriends () {
|
||||
this.error = ''
|
||||
|
||||
const notEmptyHosts = this.getNotEmptyHosts();
|
||||
const notEmptyHosts = this.getNotEmptyHosts()
|
||||
if (notEmptyHosts.length === 0) {
|
||||
this.error = 'You need to specify at least 1 host.';
|
||||
return;
|
||||
this.error = 'You need to specify at least 1 host.'
|
||||
return
|
||||
}
|
||||
|
||||
if (!this.isHostsUnique(notEmptyHosts)) {
|
||||
this.error = 'Hosts need to be unique.';
|
||||
return;
|
||||
this.error = 'Hosts need to be unique.'
|
||||
return
|
||||
}
|
||||
|
||||
const confirmMessage = 'Are you sure to make friends with:<br /> - ' + notEmptyHosts.join('<br /> - ');
|
||||
const confirmMessage = 'Are you sure to make friends with:<br /> - ' + notEmptyHosts.join('<br /> - ')
|
||||
this.confirmService.confirm(confirmMessage, 'Make friends').subscribe(
|
||||
res => {
|
||||
if (res === false) return;
|
||||
if (res === false) return
|
||||
|
||||
this.friendService.makeFriends(notEmptyHosts).subscribe(
|
||||
status => {
|
||||
this.notificationsService.success('Sucess', 'Make friends request sent!');
|
||||
this.router.navigate([ '/admin/friends/list' ]);
|
||||
this.notificationsService.success('Sucess', 'Make friends request sent!')
|
||||
this.router.navigate([ '/admin/friends/list' ])
|
||||
},
|
||||
|
||||
err => this.notificationsService.error('Error', err.text)
|
||||
);
|
||||
)
|
||||
}
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
private getNotEmptyHosts() {
|
||||
const notEmptyHosts = [];
|
||||
private getNotEmptyHosts () {
|
||||
const notEmptyHosts = []
|
||||
|
||||
Object.keys(this.form.value).forEach((hostKey) => {
|
||||
const host = this.form.value[hostKey];
|
||||
if (host !== '') notEmptyHosts.push(host);
|
||||
});
|
||||
const host = this.form.value[hostKey]
|
||||
if (host !== '') notEmptyHosts.push(host)
|
||||
})
|
||||
|
||||
return notEmptyHosts;
|
||||
return notEmptyHosts
|
||||
}
|
||||
|
||||
private isHostsUnique(hosts: string[]) {
|
||||
return hosts.every(host => hosts.indexOf(host) === hosts.lastIndexOf(host));
|
||||
private isHostsUnique (hosts: string[]) {
|
||||
return hosts.every(host => hosts.indexOf(host) === hosts.lastIndexOf(host))
|
||||
}
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
export * from './friend-add.component';
|
||||
export * from './friend-add.component'
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Component } from '@angular/core'
|
||||
|
||||
import { NotificationsService } from 'angular2-notifications';
|
||||
import { ServerDataSource } from 'ng2-smart-table';
|
||||
import { NotificationsService } from 'angular2-notifications'
|
||||
import { ServerDataSource } from 'ng2-smart-table'
|
||||
|
||||
import { ConfirmService } from '../../../core';
|
||||
import { Utils } from '../../../shared';
|
||||
import { Friend, FriendService } from '../shared';
|
||||
import { ConfirmService } from '../../../core'
|
||||
import { Utils } from '../../../shared'
|
||||
import { Friend, FriendService } from '../shared'
|
||||
|
||||
@Component({
|
||||
selector: 'my-friend-list',
|
||||
@ -13,7 +13,7 @@ import { Friend, FriendService } from '../shared';
|
||||
styleUrls: [ './friend-list.component.scss' ]
|
||||
})
|
||||
export class FriendListComponent {
|
||||
friendsSource = null;
|
||||
friendsSource = null
|
||||
tableSettings = {
|
||||
attr: {
|
||||
class: 'table-hover'
|
||||
@ -49,36 +49,36 @@ export class FriendListComponent {
|
||||
valuePrepareFunction: Utils.dateToHuman
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
constructor(
|
||||
constructor (
|
||||
private notificationsService: NotificationsService,
|
||||
private confirmService: ConfirmService,
|
||||
private friendService: FriendService
|
||||
) {
|
||||
this.friendsSource = this.friendService.getDataSource();
|
||||
this.friendsSource = this.friendService.getDataSource()
|
||||
}
|
||||
|
||||
hasFriends() {
|
||||
return this.friendsSource.count() !== 0;
|
||||
hasFriends () {
|
||||
return this.friendsSource.count() !== 0
|
||||
}
|
||||
|
||||
quitFriends() {
|
||||
const confirmMessage = 'Do you really want to quit your friends? All their videos will be deleted.';
|
||||
quitFriends () {
|
||||
const confirmMessage = 'Do you really want to quit your friends? All their videos will be deleted.'
|
||||
this.confirmService.confirm(confirmMessage, 'Quit friends').subscribe(
|
||||
res => {
|
||||
if (res === false) return;
|
||||
if (res === false) return
|
||||
|
||||
this.friendService.quitFriends().subscribe(
|
||||
status => {
|
||||
this.notificationsService.success('Sucess', 'Friends left!');
|
||||
this.notificationsService.success('Sucess', 'Friends left!')
|
||||
|
||||
this.friendsSource.refresh();
|
||||
this.friendsSource.refresh()
|
||||
},
|
||||
|
||||
err => this.notificationsService.error('Error', err.text)
|
||||
);
|
||||
)
|
||||
}
|
||||
);
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
export * from './friend-list.component';
|
||||
export * from './friend-list.component'
|
||||
|
@ -1,8 +1,7 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Component } from '@angular/core'
|
||||
|
||||
@Component({
|
||||
template: '<router-outlet></router-outlet>'
|
||||
template: '<router-outlet></router-outlet>'
|
||||
})
|
||||
|
||||
export class FriendsComponent {
|
||||
}
|
||||
|
@ -1,37 +1,37 @@
|
||||
import { Routes } from '@angular/router';
|
||||
import { Routes } from '@angular/router'
|
||||
|
||||
import { FriendsComponent } from './friends.component';
|
||||
import { FriendAddComponent } from './friend-add';
|
||||
import { FriendListComponent } from './friend-list';
|
||||
import { FriendsComponent } from './friends.component'
|
||||
import { FriendAddComponent } from './friend-add'
|
||||
import { FriendListComponent } from './friend-list'
|
||||
|
||||
export const FriendsRoutes: Routes = [
|
||||
{
|
||||
path: 'friends',
|
||||
component: FriendsComponent,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
redirectTo: 'list',
|
||||
pathMatch: 'full'
|
||||
},
|
||||
{
|
||||
path: 'list',
|
||||
component: FriendListComponent,
|
||||
data: {
|
||||
meta: {
|
||||
title: 'Friends list'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'add',
|
||||
component: FriendAddComponent,
|
||||
data: {
|
||||
meta: {
|
||||
title: 'Add friends'
|
||||
}
|
||||
path: 'friends',
|
||||
component: FriendsComponent,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
redirectTo: 'list',
|
||||
pathMatch: 'full'
|
||||
},
|
||||
{
|
||||
path: 'list',
|
||||
component: FriendListComponent,
|
||||
data: {
|
||||
meta: {
|
||||
title: 'Friends list'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
},
|
||||
{
|
||||
path: 'add',
|
||||
component: FriendAddComponent,
|
||||
data: {
|
||||
meta: {
|
||||
title: 'Add friends'
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
@ -1,5 +1,5 @@
|
||||
export * from './friend-add';
|
||||
export * from './friend-list';
|
||||
export * from './shared';
|
||||
export * from './friends.component';
|
||||
export * from './friends.routes';
|
||||
export * from './friend-add'
|
||||
export * from './friend-list'
|
||||
export * from './shared'
|
||||
export * from './friends.component'
|
||||
export * from './friends.routes'
|
||||
|
@ -1,7 +1,7 @@
|
||||
export interface Friend {
|
||||
id: string;
|
||||
host: string;
|
||||
score: number;
|
||||
email: string;
|
||||
createdAt: Date;
|
||||
id: string
|
||||
host: string
|
||||
score: number
|
||||
email: string
|
||||
createdAt: Date
|
||||
}
|
||||
|
@ -1,39 +1,39 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import 'rxjs/add/operator/catch';
|
||||
import 'rxjs/add/operator/map';
|
||||
import { Injectable } from '@angular/core'
|
||||
import { Observable } from 'rxjs/Observable'
|
||||
import 'rxjs/add/operator/catch'
|
||||
import 'rxjs/add/operator/map'
|
||||
|
||||
import { ServerDataSource } from 'ng2-smart-table';
|
||||
import { ServerDataSource } from 'ng2-smart-table'
|
||||
|
||||
import { Friend } from './friend.model';
|
||||
import { AuthHttp, RestExtractor, RestDataSource, ResultList } from '../../../shared';
|
||||
import { Friend } from './friend.model'
|
||||
import { AuthHttp, RestExtractor, RestDataSource, ResultList } from '../../../shared'
|
||||
|
||||
@Injectable()
|
||||
export class FriendService {
|
||||
private static BASE_FRIEND_URL = API_URL + '/api/v1/pods/';
|
||||
private static BASE_FRIEND_URL = API_URL + '/api/v1/pods/'
|
||||
|
||||
constructor (
|
||||
private authHttp: AuthHttp,
|
||||
private restExtractor: RestExtractor
|
||||
) {}
|
||||
|
||||
getDataSource() {
|
||||
return new RestDataSource(this.authHttp, FriendService.BASE_FRIEND_URL);
|
||||
getDataSource () {
|
||||
return new RestDataSource(this.authHttp, FriendService.BASE_FRIEND_URL)
|
||||
}
|
||||
|
||||
makeFriends(notEmptyHosts) {
|
||||
makeFriends (notEmptyHosts) {
|
||||
const body = {
|
||||
hosts: notEmptyHosts
|
||||
};
|
||||
}
|
||||
|
||||
return this.authHttp.post(FriendService.BASE_FRIEND_URL + 'makefriends', body)
|
||||
.map(this.restExtractor.extractDataBool)
|
||||
.catch((res) => this.restExtractor.handleError(res));
|
||||
.catch((res) => this.restExtractor.handleError(res))
|
||||
}
|
||||
|
||||
quitFriends() {
|
||||
quitFriends () {
|
||||
return this.authHttp.get(FriendService.BASE_FRIEND_URL + 'quitfriends')
|
||||
.map(res => res.status)
|
||||
.catch((res) => this.restExtractor.handleError(res));
|
||||
.catch((res) => this.restExtractor.handleError(res))
|
||||
}
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
export * from './friend.model';
|
||||
export * from './friend.service';
|
||||
export * from './friend.model'
|
||||
export * from './friend.service'
|
||||
|
@ -1,6 +1,6 @@
|
||||
export * from './friends';
|
||||
export * from './requests';
|
||||
export * from './users';
|
||||
export * from './admin-routing.module';
|
||||
export * from './admin.module';
|
||||
export * from './admin.component';
|
||||
export * from './friends'
|
||||
export * from './requests'
|
||||
export * from './users'
|
||||
export * from './admin-routing.module'
|
||||
export * from './admin.module'
|
||||
export * from './admin.component'
|
||||
|
@ -1,4 +1,4 @@
|
||||
export * from './request-stats';
|
||||
export * from './shared';
|
||||
export * from './requests.component';
|
||||
export * from './requests.routes';
|
||||
export * from './request-stats'
|
||||
export * from './shared'
|
||||
export * from './requests.component'
|
||||
export * from './requests.routes'
|
||||
|
@ -1 +1 @@
|
||||
export * from './request-stats.component';
|
||||
export * from './request-stats.component'
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||
import { Component, OnInit, OnDestroy } from '@angular/core'
|
||||
|
||||
import { NotificationsService } from 'angular2-notifications';
|
||||
import { NotificationsService } from 'angular2-notifications'
|
||||
|
||||
import { RequestService, RequestStats } from '../shared';
|
||||
import { RequestService, RequestStats } from '../shared'
|
||||
|
||||
@Component({
|
||||
selector: 'my-request-stats',
|
||||
templateUrl: './request-stats.component.html',
|
||||
selector: 'my-request-stats',
|
||||
templateUrl: './request-stats.component.html',
|
||||
styleUrls: [ './request-stats.component.scss' ]
|
||||
})
|
||||
export class RequestStatsComponent implements OnInit, OnDestroy {
|
||||
@ -14,70 +14,67 @@ export class RequestStatsComponent implements OnInit, OnDestroy {
|
||||
requestScheduler: 'Basic request scheduler',
|
||||
requestVideoEventScheduler: 'Video events request scheduler',
|
||||
requestVideoQaduScheduler: 'Quick and dirty video updates request scheduler'
|
||||
};
|
||||
}
|
||||
|
||||
stats: { [ id: string ]: RequestStats } = {
|
||||
requestScheduler: null,
|
||||
requestVideoEventScheduler: null,
|
||||
requestVideoQaduScheduler: null
|
||||
};
|
||||
}
|
||||
|
||||
private intervals: { [ id: string ]: number } = {
|
||||
requestScheduler: null,
|
||||
requestVideoEventScheduler: null,
|
||||
requestVideoQaduScheduler: null
|
||||
};
|
||||
}
|
||||
|
||||
private timeouts: { [ id: string ]: number } = {
|
||||
requestScheduler: null,
|
||||
requestVideoEventScheduler: null,
|
||||
requestVideoQaduScheduler: null
|
||||
};
|
||||
|
||||
|
||||
constructor(
|
||||
private notificationsService: NotificationsService,
|
||||
private requestService: RequestService
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.getStats();
|
||||
this.runIntervals();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
constructor (
|
||||
private notificationsService: NotificationsService,
|
||||
private requestService: RequestService
|
||||
) { }
|
||||
|
||||
ngOnInit () {
|
||||
this.getStats()
|
||||
this.runIntervals()
|
||||
}
|
||||
|
||||
ngOnDestroy () {
|
||||
Object.keys(this.stats).forEach(requestSchedulerName => {
|
||||
if (this.intervals[requestSchedulerName] !== null) {
|
||||
window.clearInterval(this.intervals[requestSchedulerName]);
|
||||
window.clearInterval(this.intervals[requestSchedulerName])
|
||||
}
|
||||
|
||||
if (this.timeouts[requestSchedulerName] !== null) {
|
||||
window.clearTimeout(this.timeouts[requestSchedulerName]);
|
||||
window.clearTimeout(this.timeouts[requestSchedulerName])
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
getStats() {
|
||||
getStats () {
|
||||
this.requestService.getStats().subscribe(
|
||||
stats => this.stats = stats,
|
||||
|
||||
err => this.notificationsService.error('Error', err.text)
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
private runIntervals() {
|
||||
private runIntervals () {
|
||||
Object.keys(this.intervals).forEach(requestSchedulerName => {
|
||||
this.intervals[requestSchedulerName] = window.setInterval(() => {
|
||||
const stats = this.stats[requestSchedulerName];
|
||||
const stats = this.stats[requestSchedulerName]
|
||||
|
||||
stats.remainingMilliSeconds -= 1000;
|
||||
stats.remainingMilliSeconds -= 1000
|
||||
|
||||
if (stats.remainingMilliSeconds <= 0) {
|
||||
this.timeouts[requestSchedulerName] = window.setTimeout(() => this.getStats(), stats.remainingMilliSeconds + 100);
|
||||
this.timeouts[requestSchedulerName] = window.setTimeout(() => this.getStats(), stats.remainingMilliSeconds + 100)
|
||||
}
|
||||
}, 1000);
|
||||
});
|
||||
}, 1000)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Component } from '@angular/core'
|
||||
|
||||
@Component({
|
||||
template: '<router-outlet></router-outlet>'
|
||||
template: '<router-outlet></router-outlet>'
|
||||
})
|
||||
|
||||
export class RequestsComponent {
|
||||
}
|
||||
|
@ -1,27 +1,27 @@
|
||||
import { Routes } from '@angular/router';
|
||||
import { Routes } from '@angular/router'
|
||||
|
||||
import { RequestsComponent } from './requests.component';
|
||||
import { RequestStatsComponent } from './request-stats';
|
||||
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,
|
||||
data: {
|
||||
meta: {
|
||||
title: 'Request stats'
|
||||
}
|
||||
path: 'requests',
|
||||
component: RequestsComponent,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
redirectTo: 'stats',
|
||||
pathMatch: 'full'
|
||||
},
|
||||
{
|
||||
path: 'stats',
|
||||
component: RequestStatsComponent,
|
||||
data: {
|
||||
meta: {
|
||||
title: 'Request stats'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
@ -1,2 +1,2 @@
|
||||
export * from './request-stats.model';
|
||||
export * from './request.service';
|
||||
export * from './request-stats.model'
|
||||
export * from './request.service'
|
||||
|
@ -1,35 +1,35 @@
|
||||
export interface Request {
|
||||
request: any;
|
||||
to: any;
|
||||
request: any
|
||||
to: any
|
||||
}
|
||||
|
||||
export class RequestStats {
|
||||
requestsLimitPods: number;
|
||||
requestsLimitPerPod: number;
|
||||
milliSecondsInterval: number;
|
||||
remainingMilliSeconds: number;
|
||||
totalRequests: number;
|
||||
requestsLimitPods: number
|
||||
requestsLimitPerPod: number
|
||||
milliSecondsInterval: number
|
||||
remainingMilliSeconds: number
|
||||
totalRequests: number
|
||||
|
||||
constructor(hash: {
|
||||
constructor (hash: {
|
||||
requestsLimitPods: number,
|
||||
requestsLimitPerPod: number,
|
||||
milliSecondsInterval: number,
|
||||
remainingMilliSeconds: number,
|
||||
totalRequests: number;
|
||||
totalRequests: number
|
||||
}) {
|
||||
this.requestsLimitPods = hash.requestsLimitPods;
|
||||
this.requestsLimitPerPod = hash.requestsLimitPerPod;
|
||||
this.milliSecondsInterval = hash.milliSecondsInterval;
|
||||
this.remainingMilliSeconds = hash.remainingMilliSeconds;
|
||||
this.totalRequests = hash.totalRequests;
|
||||
this.requestsLimitPods = hash.requestsLimitPods
|
||||
this.requestsLimitPerPod = hash.requestsLimitPerPod
|
||||
this.milliSecondsInterval = hash.milliSecondsInterval
|
||||
this.remainingMilliSeconds = hash.remainingMilliSeconds
|
||||
this.totalRequests = hash.totalRequests
|
||||
}
|
||||
|
||||
get remainingSeconds() {
|
||||
return Math.floor(this.remainingMilliSeconds / 1000);
|
||||
get remainingSeconds () {
|
||||
return Math.floor(this.remainingMilliSeconds / 1000)
|
||||
}
|
||||
|
||||
get secondsInterval() {
|
||||
return Math.floor(this.milliSecondsInterval / 1000);
|
||||
get secondsInterva () {
|
||||
return Math.floor(this.milliSecondsInterval / 1000)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,34 +1,34 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import 'rxjs/add/operator/catch';
|
||||
import 'rxjs/add/operator/map';
|
||||
import { Injectable } from '@angular/core'
|
||||
import { Observable } from 'rxjs/Observable'
|
||||
import 'rxjs/add/operator/catch'
|
||||
import 'rxjs/add/operator/map'
|
||||
|
||||
import { RequestStats } from './request-stats.model';
|
||||
import { AuthHttp, RestExtractor } from '../../../shared';
|
||||
import { RequestStats } from './request-stats.model'
|
||||
import { AuthHttp, RestExtractor } from '../../../shared'
|
||||
|
||||
@Injectable()
|
||||
export class RequestService {
|
||||
private static BASE_REQUEST_URL = API_URL + '/api/v1/requests/';
|
||||
private static BASE_REQUEST_URL = API_URL + '/api/v1/requests/'
|
||||
|
||||
constructor (
|
||||
private authHttp: AuthHttp,
|
||||
private restExtractor: RestExtractor
|
||||
) {}
|
||||
|
||||
getStats(): Observable<{ [ id: string ]: RequestStats }> {
|
||||
getStats (): Observable<{ [ id: string ]: RequestStats }> {
|
||||
return this.authHttp.get(RequestService.BASE_REQUEST_URL + 'stats')
|
||||
.map(this.restExtractor.extractDataGet)
|
||||
.map(this.buildRequestObjects)
|
||||
.catch((res) => this.restExtractor.handleError(res));
|
||||
.catch((res) => this.restExtractor.handleError(res))
|
||||
}
|
||||
|
||||
private buildRequestObjects(data: any) {
|
||||
const requestSchedulers = {};
|
||||
private buildRequestObjects (data: any) {
|
||||
const requestSchedulers = {}
|
||||
|
||||
Object.keys(data).forEach(requestSchedulerName => {
|
||||
requestSchedulers[requestSchedulerName] = new RequestStats(data[requestSchedulerName]);
|
||||
});
|
||||
requestSchedulers[requestSchedulerName] = new RequestStats(data[requestSchedulerName])
|
||||
})
|
||||
|
||||
return requestSchedulers;
|
||||
return requestSchedulers
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
export * from './shared';
|
||||
export * from './user-add';
|
||||
export * from './user-list';
|
||||
export * from './users.component';
|
||||
export * from './users.routes';
|
||||
export * from './shared'
|
||||
export * from './user-add'
|
||||
export * from './user-list'
|
||||
export * from './users.component'
|
||||
export * from './users.routes'
|
||||
|
@ -1 +1 @@
|
||||
export * from './user.service';
|
||||
export * from './user.service'
|
||||
|
@ -1,35 +1,35 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import 'rxjs/add/operator/catch';
|
||||
import 'rxjs/add/operator/map';
|
||||
import { Injectable } from '@angular/core'
|
||||
import 'rxjs/add/operator/catch'
|
||||
import 'rxjs/add/operator/map'
|
||||
|
||||
import { AuthHttp, RestExtractor, RestDataSource, User } from '../../../shared';
|
||||
import { AuthHttp, RestExtractor, RestDataSource, User } from '../../../shared'
|
||||
|
||||
@Injectable()
|
||||
export class UserService {
|
||||
private static BASE_USERS_URL = API_URL + '/api/v1/users/';
|
||||
private static BASE_USERS_URL = API_URL + '/api/v1/users/'
|
||||
|
||||
constructor(
|
||||
constructor (
|
||||
private authHttp: AuthHttp,
|
||||
private restExtractor: RestExtractor
|
||||
) {}
|
||||
|
||||
addUser(username: string, password: string, email: string) {
|
||||
addUser (username: string, password: string, email: string) {
|
||||
const body = {
|
||||
username,
|
||||
email,
|
||||
password
|
||||
};
|
||||
}
|
||||
|
||||
return this.authHttp.post(UserService.BASE_USERS_URL, body)
|
||||
.map(this.restExtractor.extractDataBool)
|
||||
.catch(this.restExtractor.handleError);
|
||||
.catch(this.restExtractor.handleError)
|
||||
}
|
||||
|
||||
getDataSource() {
|
||||
return new RestDataSource(this.authHttp, UserService.BASE_USERS_URL);
|
||||
getDataSource () {
|
||||
return new RestDataSource(this.authHttp, UserService.BASE_USERS_URL)
|
||||
}
|
||||
|
||||
removeUser(user: User) {
|
||||
return this.authHttp.delete(UserService.BASE_USERS_URL + user.id);
|
||||
removeUser (user: User) {
|
||||
return this.authHttp.delete(UserService.BASE_USERS_URL + user.id)
|
||||
}
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
export * from './user-add.component';
|
||||
export * from './user-add.component'
|
||||
|
@ -1,71 +1,71 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { Router } from '@angular/router';
|
||||
import { Component, OnInit } from '@angular/core'
|
||||
import { FormBuilder, FormGroup } from '@angular/forms'
|
||||
import { Router } from '@angular/router'
|
||||
|
||||
import { NotificationsService } from 'angular2-notifications';
|
||||
import { NotificationsService } from 'angular2-notifications'
|
||||
|
||||
import { UserService } from '../shared';
|
||||
import { UserService } from '../shared'
|
||||
import {
|
||||
FormReactive,
|
||||
USER_USERNAME,
|
||||
USER_EMAIL,
|
||||
USER_PASSWORD
|
||||
} from '../../../shared';
|
||||
} from '../../../shared'
|
||||
|
||||
@Component({
|
||||
selector: 'my-user-add',
|
||||
templateUrl: './user-add.component.html'
|
||||
})
|
||||
export class UserAddComponent extends FormReactive implements OnInit {
|
||||
error: string = null;
|
||||
error: string = null
|
||||
|
||||
form: FormGroup;
|
||||
form: FormGroup
|
||||
formErrors = {
|
||||
'username': '',
|
||||
'email': '',
|
||||
'password': ''
|
||||
};
|
||||
}
|
||||
validationMessages = {
|
||||
'username': USER_USERNAME.MESSAGES,
|
||||
'email': USER_EMAIL.MESSAGES,
|
||||
'password': USER_PASSWORD.MESSAGES,
|
||||
};
|
||||
'password': USER_PASSWORD.MESSAGES
|
||||
}
|
||||
|
||||
constructor(
|
||||
constructor (
|
||||
private formBuilder: FormBuilder,
|
||||
private router: Router,
|
||||
private notificationsService: NotificationsService,
|
||||
private userService: UserService
|
||||
) {
|
||||
super();
|
||||
super()
|
||||
}
|
||||
|
||||
buildForm() {
|
||||
buildForm () {
|
||||
this.form = this.formBuilder.group({
|
||||
username: [ '', USER_USERNAME.VALIDATORS ],
|
||||
email: [ '', USER_EMAIL.VALIDATORS ],
|
||||
password: [ '', USER_PASSWORD.VALIDATORS ],
|
||||
});
|
||||
password: [ '', USER_PASSWORD.VALIDATORS ]
|
||||
})
|
||||
|
||||
this.form.valueChanges.subscribe(data => this.onValueChanged(data));
|
||||
this.form.valueChanges.subscribe(data => this.onValueChanged(data))
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.buildForm();
|
||||
ngOnInit () {
|
||||
this.buildForm()
|
||||
}
|
||||
|
||||
addUser() {
|
||||
this.error = null;
|
||||
addUser () {
|
||||
this.error = null
|
||||
|
||||
const { username, password, email } = this.form.value;
|
||||
const { username, password, email } = this.form.value
|
||||
|
||||
this.userService.addUser(username, password, email).subscribe(
|
||||
() => {
|
||||
this.notificationsService.success('Success', `User ${username} created.`);
|
||||
this.router.navigate([ '/admin/users/list' ]);
|
||||
this.notificationsService.success('Success', `User ${username} created.`)
|
||||
this.router.navigate([ '/admin/users/list' ])
|
||||
},
|
||||
|
||||
err => this.error = err.text
|
||||
);
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
export * from './user-list.component';
|
||||
export * from './user-list.component'
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Component } from '@angular/core'
|
||||
|
||||
import { NotificationsService } from 'angular2-notifications';
|
||||
import { NotificationsService } from 'angular2-notifications'
|
||||
|
||||
import { ConfirmService } from '../../../core';
|
||||
import { User, Utils } from '../../../shared';
|
||||
import { UserService } from '../shared';
|
||||
import { ConfirmService } from '../../../core'
|
||||
import { User, Utils } from '../../../shared'
|
||||
import { UserService } from '../shared'
|
||||
|
||||
@Component({
|
||||
selector: 'my-user-list',
|
||||
@ -12,7 +12,7 @@ import { UserService } from '../shared';
|
||||
styleUrls: [ './user-list.component.scss' ]
|
||||
})
|
||||
export class UserListComponent {
|
||||
usersSource = null;
|
||||
usersSource = null
|
||||
tableSettings = {
|
||||
mode: 'external',
|
||||
attr: {
|
||||
@ -52,37 +52,37 @@ export class UserListComponent {
|
||||
valuePrepareFunction: Utils.dateToHuman
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
constructor(
|
||||
constructor (
|
||||
private notificationsService: NotificationsService,
|
||||
private confirmService: ConfirmService,
|
||||
private userService: UserService
|
||||
) {
|
||||
this.usersSource = this.userService.getDataSource();
|
||||
this.usersSource = this.userService.getDataSource()
|
||||
}
|
||||
|
||||
removeUser({ data }) {
|
||||
const user: User = data;
|
||||
removeUser ({ data }) {
|
||||
const user: User = data
|
||||
|
||||
if (user.username === 'root') {
|
||||
this.notificationsService.error('Error', 'You cannot delete root.');
|
||||
return;
|
||||
this.notificationsService.error('Error', 'You cannot delete root.')
|
||||
return
|
||||
}
|
||||
|
||||
this.confirmService.confirm('Do you really want to delete this user?', 'Delete').subscribe(
|
||||
res => {
|
||||
if (res === false) return;
|
||||
if (res === false) return
|
||||
|
||||
this.userService.removeUser(user).subscribe(
|
||||
() => {
|
||||
this.notificationsService.success('Success', `User ${user.username} deleted.`);
|
||||
this.usersSource.refresh();
|
||||
this.notificationsService.success('Success', `User ${user.username} deleted.`)
|
||||
this.usersSource.refresh()
|
||||
},
|
||||
|
||||
err => this.notificationsService.error('Error', err.text)
|
||||
);
|
||||
)
|
||||
}
|
||||
);
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Component } from '@angular/core'
|
||||
|
||||
@Component({
|
||||
template: '<router-outlet></router-outlet>'
|
||||
template: '<router-outlet></router-outlet>'
|
||||
})
|
||||
|
||||
export class UsersComponent {
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Routes } from '@angular/router';
|
||||
import { Routes } from '@angular/router'
|
||||
|
||||
import { UsersComponent } from './users.component';
|
||||
import { UserAddComponent } from './user-add';
|
||||
import { UserListComponent } from './user-list';
|
||||
import { UsersComponent } from './users.component'
|
||||
import { UserAddComponent } from './user-add'
|
||||
import { UserListComponent } from './user-list'
|
||||
|
||||
export const UsersRoutes: Routes = [
|
||||
{
|
||||
@ -34,4 +34,4 @@ export const UsersRoutes: Routes = [
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
]
|
||||
|
@ -1,3 +1,3 @@
|
||||
export * from './video-abuse-list';
|
||||
export * from './video-abuses.component';
|
||||
export * from './video-abuses.routes';
|
||||
export * from './video-abuse-list'
|
||||
export * from './video-abuses.component'
|
||||
export * from './video-abuses.routes'
|
||||
|
@ -1 +1 @@
|
||||
export * from './video-abuse-list.component';
|
||||
export * from './video-abuse-list.component'
|
||||
|
@ -1,15 +1,15 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Component } from '@angular/core'
|
||||
|
||||
import { NotificationsService } from 'angular2-notifications';
|
||||
import { NotificationsService } from 'angular2-notifications'
|
||||
|
||||
import { Utils, VideoAbuseService, VideoAbuse } from '../../../shared';
|
||||
import { Utils, VideoAbuseService, VideoAbuse } from '../../../shared'
|
||||
|
||||
@Component({
|
||||
selector: 'my-video-abuse-list',
|
||||
templateUrl: './video-abuse-list.component.html'
|
||||
selector: 'my-video-abuse-list',
|
||||
templateUrl: './video-abuse-list.component.html'
|
||||
})
|
||||
export class VideoAbuseListComponent {
|
||||
videoAbusesSource = null;
|
||||
videoAbusesSource = null
|
||||
tableSettings = {
|
||||
mode: 'external',
|
||||
attr: {
|
||||
@ -54,18 +54,18 @@ export class VideoAbuseListComponent {
|
||||
valuePrepareFunction: Utils.dateToHuman
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
constructor(
|
||||
constructor (
|
||||
private notificationsService: NotificationsService,
|
||||
private videoAbuseService: VideoAbuseService
|
||||
) {
|
||||
this.videoAbusesSource = this.videoAbuseService.getDataSource();
|
||||
}
|
||||
this.videoAbusesSource = this.videoAbuseService.getDataSource()
|
||||
}
|
||||
|
||||
buildVideoLink(videoId: string) {
|
||||
buildVideoLink (videoId: string) {
|
||||
// TODO: transform to routerLink
|
||||
// https://github.com/akveo/ng2-smart-table/issues/57
|
||||
return `<a href="/videos/${videoId}" title="Go to the video">${videoId}</a>`;
|
||||
return `<a href="/videos/${videoId}" title="Go to the video">${videoId}</a>`
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Component } from '@angular/core'
|
||||
|
||||
@Component({
|
||||
template: '<router-outlet></router-outlet>'
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Routes } from '@angular/router';
|
||||
import { Routes } from '@angular/router'
|
||||
|
||||
import { VideoAbusesComponent } from './video-abuses.component';
|
||||
import { VideoAbuseListComponent } from './video-abuse-list';
|
||||
import { VideoAbusesComponent } from './video-abuses.component'
|
||||
import { VideoAbuseListComponent } from './video-abuse-list'
|
||||
|
||||
export const VideoAbusesRoutes: Routes = [
|
||||
{
|
||||
@ -25,4 +25,4 @@ export const VideoAbusesRoutes: Routes = [
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
]
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { Router } from '@angular/router';
|
||||
import { Component, OnInit } from '@angular/core'
|
||||
import { FormBuilder, FormGroup } from '@angular/forms'
|
||||
import { Router } from '@angular/router'
|
||||
|
||||
import { NotificationsService } from 'angular2-notifications';
|
||||
import { NotificationsService } from 'angular2-notifications'
|
||||
|
||||
import { FormReactive, UserService, USER_PASSWORD } from '../../shared';
|
||||
import { FormReactive, UserService, USER_PASSWORD } from '../../shared'
|
||||
|
||||
@Component({
|
||||
selector: 'my-account-change-password',
|
||||
@ -12,55 +12,55 @@ import { FormReactive, UserService, USER_PASSWORD } from '../../shared';
|
||||
})
|
||||
|
||||
export class AccountChangePasswordComponent extends FormReactive implements OnInit {
|
||||
error: string = null;
|
||||
error: string = null
|
||||
|
||||
form: FormGroup;
|
||||
form: FormGroup
|
||||
formErrors = {
|
||||
'new-password': '',
|
||||
'new-confirmed-password': ''
|
||||
};
|
||||
}
|
||||
validationMessages = {
|
||||
'new-password': USER_PASSWORD.MESSAGES,
|
||||
'new-confirmed-password': USER_PASSWORD.MESSAGES
|
||||
};
|
||||
}
|
||||
|
||||
constructor(
|
||||
constructor (
|
||||
private formBuilder: FormBuilder,
|
||||
private router: Router,
|
||||
private notificationsService: NotificationsService,
|
||||
private userService: UserService
|
||||
) {
|
||||
super();
|
||||
super()
|
||||
}
|
||||
|
||||
buildForm() {
|
||||
buildForm () {
|
||||
this.form = this.formBuilder.group({
|
||||
'new-password': [ '', USER_PASSWORD.VALIDATORS ],
|
||||
'new-confirmed-password': [ '', USER_PASSWORD.VALIDATORS ],
|
||||
});
|
||||
'new-confirmed-password': [ '', USER_PASSWORD.VALIDATORS ]
|
||||
})
|
||||
|
||||
this.form.valueChanges.subscribe(data => this.onValueChanged(data));
|
||||
this.form.valueChanges.subscribe(data => this.onValueChanged(data))
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.buildForm();
|
||||
ngOnInit () {
|
||||
this.buildForm()
|
||||
}
|
||||
|
||||
changePassword() {
|
||||
const newPassword = this.form.value['new-password'];
|
||||
const newConfirmedPassword = this.form.value['new-confirmed-password'];
|
||||
changePassword () {
|
||||
const newPassword = this.form.value['new-password']
|
||||
const newConfirmedPassword = this.form.value['new-confirmed-password']
|
||||
|
||||
this.error = null;
|
||||
this.error = null
|
||||
|
||||
if (newPassword !== newConfirmedPassword) {
|
||||
this.error = 'The new password and the confirmed password do not correspond.';
|
||||
return;
|
||||
this.error = 'The new password and the confirmed password do not correspond.'
|
||||
return
|
||||
}
|
||||
|
||||
this.userService.changePassword(newPassword).subscribe(
|
||||
() => this.notificationsService.success('Success', 'Password updated.'),
|
||||
|
||||
err => this.error = err
|
||||
);
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
export * from './account-change-password.component';
|
||||
export * from './account-change-password.component'
|
||||
|
@ -1,16 +1,16 @@
|
||||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { Router } from '@angular/router';
|
||||
import { Component, OnInit, Input } from '@angular/core'
|
||||
import { FormBuilder, FormGroup } from '@angular/forms'
|
||||
import { Router } from '@angular/router'
|
||||
|
||||
import { NotificationsService } from 'angular2-notifications';
|
||||
import { NotificationsService } from 'angular2-notifications'
|
||||
|
||||
import { AuthService } from '../../core';
|
||||
import { AuthService } from '../../core'
|
||||
import {
|
||||
FormReactive,
|
||||
User,
|
||||
UserService,
|
||||
USER_PASSWORD
|
||||
} from '../../shared';
|
||||
} from '../../shared'
|
||||
|
||||
@Component({
|
||||
selector: 'my-account-details',
|
||||
@ -18,51 +18,51 @@ import {
|
||||
})
|
||||
|
||||
export class AccountDetailsComponent extends FormReactive implements OnInit {
|
||||
@Input() user: User = null;
|
||||
@Input() user: User = null
|
||||
|
||||
error: string = null;
|
||||
error: string = null
|
||||
|
||||
form: FormGroup;
|
||||
formErrors = {};
|
||||
validationMessages = {};
|
||||
form: FormGroup
|
||||
formErrors = {}
|
||||
validationMessages = {}
|
||||
|
||||
constructor(
|
||||
constructor (
|
||||
private authService: AuthService,
|
||||
private formBuilder: FormBuilder,
|
||||
private router: Router,
|
||||
private notificationsService: NotificationsService,
|
||||
private userService: UserService
|
||||
) {
|
||||
super();
|
||||
super()
|
||||
}
|
||||
|
||||
buildForm() {
|
||||
buildForm () {
|
||||
this.form = this.formBuilder.group({
|
||||
displayNSFW: [ this.user.displayNSFW ],
|
||||
});
|
||||
displayNSFW: [ this.user.displayNSFW ]
|
||||
})
|
||||
|
||||
this.form.valueChanges.subscribe(data => this.onValueChanged(data));
|
||||
this.form.valueChanges.subscribe(data => this.onValueChanged(data))
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.buildForm();
|
||||
ngOnInit () {
|
||||
this.buildForm()
|
||||
}
|
||||
|
||||
updateDetails() {
|
||||
const displayNSFW = this.form.value['displayNSFW'];
|
||||
updateDetails () {
|
||||
const displayNSFW = this.form.value['displayNSFW']
|
||||
const details = {
|
||||
displayNSFW
|
||||
};
|
||||
}
|
||||
|
||||
this.error = null;
|
||||
this.error = null
|
||||
this.userService.updateDetails(details).subscribe(
|
||||
() => {
|
||||
this.notificationsService.success('Success', 'Informations updated.');
|
||||
this.notificationsService.success('Success', 'Informations updated.')
|
||||
|
||||
this.authService.refreshUserInformations();
|
||||
this.authService.refreshUserInformations()
|
||||
},
|
||||
|
||||
err => this.error = err
|
||||
);
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
export * from './account-details.component';
|
||||
export * from './account-details.component'
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { NgModule } from '@angular/core'
|
||||
import { RouterModule, Routes } from '@angular/router'
|
||||
|
||||
import { AccountComponent } from './account.component';
|
||||
import { AccountComponent } from './account.component'
|
||||
|
||||
const accountRoutes: Routes = [
|
||||
{
|
||||
@ -13,7 +13,7 @@ const accountRoutes: Routes = [
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
]
|
||||
|
||||
@NgModule({
|
||||
imports: [ RouterModule.forChild(accountRoutes) ],
|
||||
|
@ -1,16 +1,16 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { Router } from '@angular/router';
|
||||
import { Component, OnInit } from '@angular/core'
|
||||
import { FormBuilder, FormGroup } from '@angular/forms'
|
||||
import { Router } from '@angular/router'
|
||||
|
||||
import { NotificationsService } from 'angular2-notifications';
|
||||
import { NotificationsService } from 'angular2-notifications'
|
||||
|
||||
import { AuthService } from '../core';
|
||||
import { AuthService } from '../core'
|
||||
import {
|
||||
FormReactive,
|
||||
User,
|
||||
UserService,
|
||||
USER_PASSWORD
|
||||
} from '../shared';
|
||||
} from '../shared'
|
||||
|
||||
@Component({
|
||||
selector: 'my-account',
|
||||
@ -18,11 +18,11 @@ import {
|
||||
styleUrls: [ './account.component.scss' ]
|
||||
})
|
||||
export class AccountComponent implements OnInit {
|
||||
user: User = null;
|
||||
user: User = null
|
||||
|
||||
constructor(private authService: AuthService) {}
|
||||
constructor (private authService: AuthService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.user = this.authService.getUser();
|
||||
ngOnInit () {
|
||||
this.user = this.authService.getUser()
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { NgModule } from '@angular/core'
|
||||
|
||||
import { AccountRoutingModule } from './account-routing.module';
|
||||
import { AccountComponent } from './account.component';
|
||||
import { AccountChangePasswordComponent } from './account-change-password';
|
||||
import { AccountDetailsComponent } from './account-details';
|
||||
import { AccountService } from './account.service';
|
||||
import { SharedModule } from '../shared';
|
||||
import { AccountRoutingModule } from './account-routing.module'
|
||||
import { AccountComponent } from './account.component'
|
||||
import { AccountChangePasswordComponent } from './account-change-password'
|
||||
import { AccountDetailsComponent } from './account-details'
|
||||
import { AccountService } from './account.service'
|
||||
import { SharedModule } from '../shared'
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
|
@ -1,3 +1,3 @@
|
||||
export * from './account-routing.module';
|
||||
export * from './account.component';
|
||||
export * from './account.module';
|
||||
export * from './account-routing.module'
|
||||
export * from './account.component'
|
||||
export * from './account.module'
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
import { NgModule } from '@angular/core'
|
||||
import { Routes, RouterModule } from '@angular/router'
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
@ -11,11 +11,10 @@ const routes: Routes = [
|
||||
path: 'admin',
|
||||
loadChildren: './+admin#AdminModule'
|
||||
}
|
||||
];
|
||||
]
|
||||
|
||||
@NgModule({
|
||||
imports: [ RouterModule.forRoot(routes) ],
|
||||
exports: [ RouterModule ]
|
||||
})
|
||||
export class AppRoutingModule {}
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { Component, OnInit, ViewContainerRef } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { Component, OnInit, ViewContainerRef } from '@angular/core'
|
||||
import { Router } from '@angular/router'
|
||||
|
||||
import { AuthService, ConfigService } from './core';
|
||||
import { VideoService } from './videos';
|
||||
import { UserService } from './shared';
|
||||
import { AuthService, ConfigService } from './core'
|
||||
import { VideoService } from './videos'
|
||||
import { UserService } from './shared'
|
||||
|
||||
@Component({
|
||||
selector: 'my-app',
|
||||
@ -22,11 +22,11 @@ export class AppComponent implements OnInit {
|
||||
preventDuplicates: false,
|
||||
preventLastDuplicates: 'visible',
|
||||
rtl: false
|
||||
};
|
||||
}
|
||||
|
||||
isMenuDisplayed = true;
|
||||
isMenuDisplayed = true
|
||||
|
||||
constructor(
|
||||
constructor (
|
||||
private router: Router,
|
||||
private authService: AuthService,
|
||||
private configService: ConfigService,
|
||||
@ -35,46 +35,46 @@ export class AppComponent implements OnInit {
|
||||
viewContainerRef: ViewContainerRef
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
ngOnInit () {
|
||||
if (this.authService.isLoggedIn()) {
|
||||
// The service will automatically redirect to the login page if the token is not valid anymore
|
||||
this.userService.checkTokenValidity();
|
||||
this.userService.checkTokenValidity()
|
||||
}
|
||||
|
||||
this.configService.loadConfig();
|
||||
this.videoService.loadVideoCategories();
|
||||
this.videoService.loadVideoLicences();
|
||||
this.videoService.loadVideoLanguages();
|
||||
this.configService.loadConfig()
|
||||
this.videoService.loadVideoCategories()
|
||||
this.videoService.loadVideoLicences()
|
||||
this.videoService.loadVideoLanguages()
|
||||
|
||||
// Do not display menu on small screens
|
||||
if (window.innerWidth < 600) {
|
||||
this.isMenuDisplayed = false;
|
||||
this.isMenuDisplayed = false
|
||||
}
|
||||
}
|
||||
|
||||
isInAdmin() {
|
||||
return this.router.url.indexOf('/admin/') !== -1;
|
||||
isInAdmin () {
|
||||
return this.router.url.indexOf('/admin/') !== -1
|
||||
}
|
||||
|
||||
toggleMenu() {
|
||||
this.isMenuDisplayed = !this.isMenuDisplayed;
|
||||
toggleMenu () {
|
||||
this.isMenuDisplayed = !this.isMenuDisplayed
|
||||
}
|
||||
|
||||
getMainColClasses() {
|
||||
getMainColClasses () {
|
||||
const colSizes = {
|
||||
md: 10,
|
||||
sm: 9,
|
||||
xs: 9
|
||||
};
|
||||
}
|
||||
|
||||
// Take all width is the menu is not displayed
|
||||
if (this.isMenuDisplayed === false) {
|
||||
Object.keys(colSizes).forEach(col => colSizes[col] = 12);
|
||||
Object.keys(colSizes).forEach(col => colSizes[col] = 12)
|
||||
}
|
||||
|
||||
const classes = [ 'main-col' ];
|
||||
Object.keys(colSizes).forEach(col => classes.push(`col-${col}-${colSizes[col]}`));
|
||||
const classes = [ 'main-col' ]
|
||||
Object.keys(colSizes).forEach(col => classes.push(`col-${col}-${colSizes[col]}`))
|
||||
|
||||
return classes;
|
||||
return classes
|
||||
}
|
||||
}
|
||||
|
@ -1,29 +1,29 @@
|
||||
import { ApplicationRef, NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { ApplicationRef, NgModule } from '@angular/core'
|
||||
import { BrowserModule } from '@angular/platform-browser'
|
||||
import {
|
||||
removeNgStyles,
|
||||
createNewHosts,
|
||||
createInputTransfer
|
||||
} from '@angularclass/hmr';
|
||||
} from '@angularclass/hmr'
|
||||
|
||||
import { MetaModule, MetaLoader, MetaStaticLoader, PageTitlePositioning } from '@nglibs/meta';
|
||||
import { MetaModule, MetaLoader, MetaStaticLoader, PageTitlePositioning } from '@nglibs/meta'
|
||||
// TODO: remove, we need this to avoid error in ng2-smart-table
|
||||
import 'rxjs/add/operator/toPromise';
|
||||
import 'bootstrap-loader';
|
||||
import 'rxjs/add/operator/toPromise'
|
||||
import 'bootstrap-loader'
|
||||
|
||||
import { ENV_PROVIDERS } from './environment';
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { AppComponent } from './app.component';
|
||||
import { AppState, InternalStateType } from './app.service';
|
||||
import { ENV_PROVIDERS } from './environment'
|
||||
import { AppRoutingModule } from './app-routing.module'
|
||||
import { AppComponent } from './app.component'
|
||||
import { AppState, InternalStateType } from './app.service'
|
||||
|
||||
import { AccountModule } from './account';
|
||||
import { CoreModule } from './core';
|
||||
import { LoginModule } from './login';
|
||||
import { SignupModule } from './signup';
|
||||
import { SharedModule } from './shared';
|
||||
import { VideosModule } from './videos';
|
||||
import { AccountModule } from './account'
|
||||
import { CoreModule } from './core'
|
||||
import { LoginModule } from './login'
|
||||
import { SignupModule } from './signup'
|
||||
import { SharedModule } from './shared'
|
||||
import { VideosModule } from './videos'
|
||||
|
||||
export function metaFactory(): MetaLoader {
|
||||
export function metaFactory (): MetaLoader {
|
||||
return new MetaStaticLoader({
|
||||
pageTitlePositioning: PageTitlePositioning.PrependPageTitle,
|
||||
pageTitleSeparator: ' - ',
|
||||
@ -32,19 +32,19 @@ export function metaFactory(): MetaLoader {
|
||||
title: 'PeerTube',
|
||||
description: 'PeerTube, a decentralized video streaming platform using P2P (BitTorrent) directly in the web browser'
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
type StoreType = {
|
||||
state: InternalStateType,
|
||||
restoreInputValues: () => void,
|
||||
disposeOldHosts: () => void
|
||||
};
|
||||
}
|
||||
|
||||
// Application wide providers
|
||||
const APP_PROVIDERS = [
|
||||
AppState
|
||||
];
|
||||
]
|
||||
|
||||
@NgModule({
|
||||
bootstrap: [ AppComponent ],
|
||||
@ -77,59 +77,59 @@ const APP_PROVIDERS = [
|
||||
]
|
||||
})
|
||||
export class AppModule {
|
||||
constructor(
|
||||
constructor (
|
||||
public appRef: ApplicationRef,
|
||||
public appState: AppState
|
||||
) {}
|
||||
|
||||
public hmrOnInit(store: StoreType) {
|
||||
public hmrOnInit (store: StoreType) {
|
||||
if (!store || !store.state) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
console.log('HMR store', JSON.stringify(store, null, 2));
|
||||
console.log('HMR store', JSON.stringify(store, null, 2))
|
||||
/**
|
||||
* Set state
|
||||
*/
|
||||
this.appState._state = store.state;
|
||||
this.appState._state = store.state
|
||||
/**
|
||||
* Set input values
|
||||
*/
|
||||
if ('restoreInputValues' in store) {
|
||||
let restoreInputValues = store.restoreInputValues;
|
||||
setTimeout(restoreInputValues);
|
||||
let restoreInputValues = store.restoreInputValues
|
||||
setTimeout(restoreInputValues)
|
||||
}
|
||||
|
||||
this.appRef.tick();
|
||||
delete store.state;
|
||||
delete store.restoreInputValues;
|
||||
this.appRef.tick()
|
||||
delete store.state
|
||||
delete store.restoreInputValues
|
||||
}
|
||||
|
||||
public hmrOnDestroy(store: StoreType) {
|
||||
const cmpLocation = this.appRef.components.map((cmp) => cmp.location.nativeElement);
|
||||
public hmrOnDestroy (store: StoreType) {
|
||||
const cmpLocation = this.appRef.components.map((cmp) => cmp.location.nativeElement)
|
||||
/**
|
||||
* Save state
|
||||
*/
|
||||
const state = this.appState._state;
|
||||
store.state = state;
|
||||
const state = this.appState._state
|
||||
store.state = state
|
||||
/**
|
||||
* Recreate root elements
|
||||
*/
|
||||
store.disposeOldHosts = createNewHosts(cmpLocation);
|
||||
store.disposeOldHosts = createNewHosts(cmpLocation)
|
||||
/**
|
||||
* Save input values
|
||||
*/
|
||||
store.restoreInputValues = createInputTransfer();
|
||||
store.restoreInputValues = createInputTransfer()
|
||||
/**
|
||||
* Remove styles
|
||||
*/
|
||||
removeNgStyles();
|
||||
removeNgStyles()
|
||||
}
|
||||
|
||||
public hmrAfterDestroy(store: StoreType) {
|
||||
public hmrAfterDestroy (store: StoreType) {
|
||||
/**
|
||||
* Display new elements
|
||||
*/
|
||||
store.disposeOldHosts();
|
||||
delete store.disposeOldHosts;
|
||||
store.disposeOldHosts ()
|
||||
delete store.disposeOldHosts
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,14 @@
|
||||
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import 'rxjs/add/observable/of';
|
||||
/* tslint:disable */
|
||||
|
||||
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { Observable } from 'rxjs/Observable'
|
||||
import 'rxjs/add/observable/of'
|
||||
|
||||
@Injectable()
|
||||
export class DataResolver implements Resolve<any> {
|
||||
public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
return Observable.of({ res: 'I am data'});
|
||||
return Observable.of({ res: 'I am data'})
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,4 +17,4 @@ export class DataResolver implements Resolve<any> {
|
||||
*/
|
||||
export const APP_RESOLVER_PROVIDERS = [
|
||||
DataResolver
|
||||
];
|
||||
]
|
||||
|
@ -1,46 +1,48 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
/* tslint:disable */
|
||||
|
||||
import { Injectable } from '@angular/core'
|
||||
|
||||
export type InternalStateType = {
|
||||
[key: string]: any
|
||||
};
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class AppState {
|
||||
|
||||
public _state: InternalStateType = { };
|
||||
public _state: InternalStateType = { }
|
||||
|
||||
/**
|
||||
* Already return a clone of the current state.
|
||||
*/
|
||||
public get state() {
|
||||
return this._state = this._clone(this._state);
|
||||
return this._state = this._clone(this._state)
|
||||
}
|
||||
/**
|
||||
* Never allow mutation
|
||||
*/
|
||||
public set state(value) {
|
||||
throw new Error('do not mutate the `.state` directly');
|
||||
throw new Error('do not mutate the `.state` directly')
|
||||
}
|
||||
|
||||
public get(prop?: any) {
|
||||
/**
|
||||
* Use our state getter for the clone.
|
||||
*/
|
||||
const state = this.state;
|
||||
return state.hasOwnProperty(prop) ? state[prop] : state;
|
||||
const state = this.state
|
||||
return state.hasOwnProperty(prop) ? state[prop] : state
|
||||
}
|
||||
|
||||
public set(prop: string, value: any) {
|
||||
/**
|
||||
* Internally mutate our state.
|
||||
*/
|
||||
return this._state[prop] = value;
|
||||
return this._state[prop] = value
|
||||
}
|
||||
|
||||
private _clone(object: InternalStateType) {
|
||||
/**
|
||||
* Simple object clone.
|
||||
*/
|
||||
return JSON.parse(JSON.stringify( object ));
|
||||
return JSON.parse(JSON.stringify( object ))
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,66 @@
|
||||
// Do not use the barrel (dependency loop)
|
||||
import { UserRole } from '../../../../../shared/models/user.model'
|
||||
import { User } from '../../shared/users/user.model';
|
||||
import { User } from '../../shared/users/user.model'
|
||||
|
||||
export type TokenOptions = {
|
||||
accessToken: string
|
||||
refreshToken: string
|
||||
tokenType: string
|
||||
}
|
||||
|
||||
// Private class only used by User
|
||||
class Tokens {
|
||||
private static KEYS = {
|
||||
ACCESS_TOKEN: 'access_token',
|
||||
REFRESH_TOKEN: 'refresh_token',
|
||||
TOKEN_TYPE: 'token_type'
|
||||
}
|
||||
|
||||
accessToken: string
|
||||
refreshToken: string
|
||||
tokenType: string
|
||||
|
||||
static load () {
|
||||
const accessTokenLocalStorage = localStorage.getItem(this.KEYS.ACCESS_TOKEN)
|
||||
const refreshTokenLocalStorage = localStorage.getItem(this.KEYS.REFRESH_TOKEN)
|
||||
const tokenTypeLocalStorage = localStorage.getItem(this.KEYS.TOKEN_TYPE)
|
||||
|
||||
if (accessTokenLocalStorage && refreshTokenLocalStorage && tokenTypeLocalStorage) {
|
||||
return new Tokens({
|
||||
accessToken: accessTokenLocalStorage,
|
||||
refreshToken: refreshTokenLocalStorage,
|
||||
tokenType: tokenTypeLocalStorage
|
||||
})
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
static flush () {
|
||||
localStorage.removeItem(this.KEYS.ACCESS_TOKEN)
|
||||
localStorage.removeItem(this.KEYS.REFRESH_TOKEN)
|
||||
localStorage.removeItem(this.KEYS.TOKEN_TYPE)
|
||||
}
|
||||
|
||||
constructor (hash?: TokenOptions) {
|
||||
if (hash) {
|
||||
this.accessToken = hash.accessToken
|
||||
this.refreshToken = hash.refreshToken
|
||||
|
||||
if (hash.tokenType === 'bearer') {
|
||||
this.tokenType = 'Bearer'
|
||||
} else {
|
||||
this.tokenType = hash.tokenType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
save () {
|
||||
localStorage.setItem(Tokens.KEYS.ACCESS_TOKEN, this.accessToken)
|
||||
localStorage.setItem(Tokens.KEYS.REFRESH_TOKEN, this.refreshToken)
|
||||
localStorage.setItem(Tokens.KEYS.TOKEN_TYPE, this.tokenType)
|
||||
}
|
||||
}
|
||||
|
||||
export class AuthUser extends User {
|
||||
private static KEYS = {
|
||||
@ -9,123 +69,69 @@ export class AuthUser extends User {
|
||||
EMAIL: 'email',
|
||||
USERNAME: 'username',
|
||||
DISPLAY_NSFW: 'display_nsfw'
|
||||
};
|
||||
}
|
||||
|
||||
tokens: Tokens;
|
||||
tokens: Tokens
|
||||
|
||||
static load() {
|
||||
const usernameLocalStorage = localStorage.getItem(this.KEYS.USERNAME);
|
||||
static load () {
|
||||
const usernameLocalStorage = localStorage.getItem(this.KEYS.USERNAME)
|
||||
if (usernameLocalStorage) {
|
||||
return new AuthUser(
|
||||
{
|
||||
id: parseInt(localStorage.getItem(this.KEYS.ID)),
|
||||
id: parseInt(localStorage.getItem(this.KEYS.ID), 10),
|
||||
username: localStorage.getItem(this.KEYS.USERNAME),
|
||||
email: localStorage.getItem(this.KEYS.EMAIL),
|
||||
role: localStorage.getItem(this.KEYS.ROLE) as UserRole,
|
||||
displayNSFW: localStorage.getItem(this.KEYS.DISPLAY_NSFW) === 'true'
|
||||
},
|
||||
Tokens.load()
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
|
||||
static flush() {
|
||||
localStorage.removeItem(this.KEYS.USERNAME);
|
||||
localStorage.removeItem(this.KEYS.ID);
|
||||
localStorage.removeItem(this.KEYS.ROLE);
|
||||
localStorage.removeItem(this.KEYS.DISPLAY_NSFW);
|
||||
Tokens.flush();
|
||||
static flush () {
|
||||
localStorage.removeItem(this.KEYS.USERNAME)
|
||||
localStorage.removeItem(this.KEYS.ID)
|
||||
localStorage.removeItem(this.KEYS.ROLE)
|
||||
localStorage.removeItem(this.KEYS.DISPLAY_NSFW)
|
||||
Tokens.flush()
|
||||
}
|
||||
|
||||
constructor(userHash: {
|
||||
constructor (userHash: {
|
||||
id: number,
|
||||
username: string,
|
||||
role: UserRole,
|
||||
email: string,
|
||||
displayNSFW: boolean
|
||||
}, hashTokens: any) {
|
||||
super(userHash);
|
||||
this.tokens = new Tokens(hashTokens);
|
||||
}, hashTokens: TokenOptions) {
|
||||
super(userHash)
|
||||
this.tokens = new Tokens(hashTokens)
|
||||
}
|
||||
|
||||
getAccessToken() {
|
||||
return this.tokens.access_token;
|
||||
getAccessToken () {
|
||||
return this.tokens.accessToken
|
||||
}
|
||||
|
||||
getRefreshToken() {
|
||||
return this.tokens.refresh_token;
|
||||
getRefreshToken () {
|
||||
return this.tokens.refreshToken
|
||||
}
|
||||
|
||||
getTokenType() {
|
||||
return this.tokens.token_type;
|
||||
getTokenType () {
|
||||
return this.tokens.tokenType
|
||||
}
|
||||
|
||||
refreshTokens(access_token: string, refresh_token: string) {
|
||||
this.tokens.access_token = access_token;
|
||||
this.tokens.refresh_token = refresh_token;
|
||||
refreshTokens (accessToken: string, refreshToken: string) {
|
||||
this.tokens.accessToken = accessToken
|
||||
this.tokens.refreshToken = refreshToken
|
||||
}
|
||||
|
||||
save() {
|
||||
localStorage.setItem(AuthUser.KEYS.ID, this.id.toString());
|
||||
localStorage.setItem(AuthUser.KEYS.USERNAME, this.username);
|
||||
localStorage.setItem(AuthUser.KEYS.ROLE, this.role);
|
||||
localStorage.setItem(AuthUser.KEYS.DISPLAY_NSFW, JSON.stringify(this.displayNSFW));
|
||||
this.tokens.save();
|
||||
}
|
||||
}
|
||||
|
||||
// Private class only used by User
|
||||
class Tokens {
|
||||
private static KEYS = {
|
||||
ACCESS_TOKEN: 'access_token',
|
||||
REFRESH_TOKEN: 'refresh_token',
|
||||
TOKEN_TYPE: 'token_type',
|
||||
};
|
||||
|
||||
access_token: string;
|
||||
refresh_token: string;
|
||||
token_type: string;
|
||||
|
||||
static load() {
|
||||
const accessTokenLocalStorage = localStorage.getItem(this.KEYS.ACCESS_TOKEN);
|
||||
const refreshTokenLocalStorage = localStorage.getItem(this.KEYS.REFRESH_TOKEN);
|
||||
const tokenTypeLocalStorage = localStorage.getItem(this.KEYS.TOKEN_TYPE);
|
||||
|
||||
if (accessTokenLocalStorage && refreshTokenLocalStorage && tokenTypeLocalStorage) {
|
||||
return new Tokens({
|
||||
access_token: accessTokenLocalStorage,
|
||||
refresh_token: refreshTokenLocalStorage,
|
||||
token_type: tokenTypeLocalStorage
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static flush() {
|
||||
localStorage.removeItem(this.KEYS.ACCESS_TOKEN);
|
||||
localStorage.removeItem(this.KEYS.REFRESH_TOKEN);
|
||||
localStorage.removeItem(this.KEYS.TOKEN_TYPE);
|
||||
}
|
||||
|
||||
constructor(hash?: any) {
|
||||
if (hash) {
|
||||
this.access_token = hash.access_token;
|
||||
this.refresh_token = hash.refresh_token;
|
||||
|
||||
if (hash.token_type === 'bearer') {
|
||||
this.token_type = 'Bearer';
|
||||
} else {
|
||||
this.token_type = hash.token_type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
save() {
|
||||
localStorage.setItem('access_token', this.access_token);
|
||||
localStorage.setItem('refresh_token', this.refresh_token);
|
||||
localStorage.setItem('token_type', this.token_type);
|
||||
save () {
|
||||
localStorage.setItem(AuthUser.KEYS.ID, this.id.toString())
|
||||
localStorage.setItem(AuthUser.KEYS.USERNAME, this.username)
|
||||
localStorage.setItem(AuthUser.KEYS.ROLE, this.role)
|
||||
localStorage.setItem(AuthUser.KEYS.DISPLAY_NSFW, JSON.stringify(this.displayNSFW))
|
||||
this.tokens.save()
|
||||
}
|
||||
}
|
||||
|
@ -1,40 +1,40 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Headers, Http, Response, URLSearchParams } from '@angular/http';
|
||||
import { Router } from '@angular/router';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { Subject } from 'rxjs/Subject';
|
||||
import 'rxjs/add/operator/map';
|
||||
import 'rxjs/add/operator/mergeMap';
|
||||
import 'rxjs/add/observable/throw';
|
||||
import { Injectable } from '@angular/core'
|
||||
import { Headers, Http, Response, URLSearchParams } from '@angular/http'
|
||||
import { Router } from '@angular/router'
|
||||
import { Observable } from 'rxjs/Observable'
|
||||
import { Subject } from 'rxjs/Subject'
|
||||
import 'rxjs/add/operator/map'
|
||||
import 'rxjs/add/operator/mergeMap'
|
||||
import 'rxjs/add/observable/throw'
|
||||
|
||||
import { NotificationsService } from 'angular2-notifications';
|
||||
import { NotificationsService } from 'angular2-notifications'
|
||||
|
||||
import { AuthStatus } from './auth-status.model';
|
||||
import { AuthUser } from './auth-user.model';
|
||||
import { AuthStatus } from './auth-status.model'
|
||||
import { AuthUser } from './auth-user.model'
|
||||
// Do not use the barrel (dependency loop)
|
||||
import { RestExtractor } from '../../shared/rest';
|
||||
import { RestExtractor } from '../../shared/rest'
|
||||
|
||||
@Injectable()
|
||||
export class AuthService {
|
||||
private static BASE_CLIENT_URL = API_URL + '/api/v1/clients/local';
|
||||
private static BASE_TOKEN_URL = API_URL + '/api/v1/users/token';
|
||||
private static BASE_USER_INFORMATIONS_URL = API_URL + '/api/v1/users/me';
|
||||
private static BASE_CLIENT_URL = API_URL + '/api/v1/clients/local'
|
||||
private static BASE_TOKEN_URL = API_URL + '/api/v1/users/token'
|
||||
private static BASE_USER_INFORMATIONS_URL = API_URL + '/api/v1/users/me'
|
||||
|
||||
loginChangedSource: Observable<AuthStatus>;
|
||||
loginChangedSource: Observable<AuthStatus>
|
||||
|
||||
private clientId: string;
|
||||
private clientSecret: string;
|
||||
private loginChanged: Subject<AuthStatus>;
|
||||
private user: AuthUser = null;
|
||||
private clientId: string
|
||||
private clientSecret: string
|
||||
private loginChanged: Subject<AuthStatus>
|
||||
private user: AuthUser = null
|
||||
|
||||
constructor(
|
||||
constructor (
|
||||
private http: Http,
|
||||
private notificationsService: NotificationsService,
|
||||
private restExtractor: RestExtractor,
|
||||
private router: Router
|
||||
) {
|
||||
this.loginChanged = new Subject<AuthStatus>();
|
||||
this.loginChangedSource = this.loginChanged.asObservable();
|
||||
this.loginChanged = new Subject<AuthStatus>()
|
||||
this.loginChangedSource = this.loginChanged.asObservable()
|
||||
|
||||
// Fetch the client_id/client_secret
|
||||
// FIXME: save in local storage?
|
||||
@ -43,120 +43,120 @@ export class AuthService {
|
||||
.catch((res) => this.restExtractor.handleError(res))
|
||||
.subscribe(
|
||||
result => {
|
||||
this.clientId = result.client_id;
|
||||
this.clientSecret = result.client_secret;
|
||||
console.log('Client credentials loaded.');
|
||||
this.clientId = result.client_id
|
||||
this.clientSecret = result.client_secret
|
||||
console.log('Client credentials loaded.')
|
||||
},
|
||||
|
||||
error => {
|
||||
let errorMessage = `Cannot retrieve OAuth Client credentials: ${error.text}. \n`;
|
||||
errorMessage += 'Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.';
|
||||
let errorMessage = `Cannot retrieve OAuth Client credentials: ${error.text}. \n`
|
||||
errorMessage += 'Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.'
|
||||
|
||||
// We put a bigger timeout
|
||||
// This is an important message
|
||||
this.notificationsService.error('Error', errorMessage, { timeOut: 7000 });
|
||||
this.notificationsService.error('Error', errorMessage, { timeOut: 7000 })
|
||||
}
|
||||
);
|
||||
)
|
||||
|
||||
// Return null if there is nothing to load
|
||||
this.user = AuthUser.load();
|
||||
this.user = AuthUser.load()
|
||||
}
|
||||
|
||||
getRefreshToken() {
|
||||
if (this.user === null) return null;
|
||||
getRefreshToken () {
|
||||
if (this.user === null) return null
|
||||
|
||||
return this.user.getRefreshToken();
|
||||
return this.user.getRefreshToken()
|
||||
}
|
||||
|
||||
getRequestHeaderValue() {
|
||||
return `${this.getTokenType()} ${this.getAccessToken()}`;
|
||||
getRequestHeaderValue () {
|
||||
return `${this.getTokenType()} ${this.getAccessToken()}`
|
||||
}
|
||||
|
||||
getAccessToken() {
|
||||
if (this.user === null) return null;
|
||||
getAccessToken () {
|
||||
if (this.user === null) return null
|
||||
|
||||
return this.user.getAccessToken();
|
||||
return this.user.getAccessToken()
|
||||
}
|
||||
|
||||
getTokenType() {
|
||||
if (this.user === null) return null;
|
||||
getTokenType () {
|
||||
if (this.user === null) return null
|
||||
|
||||
return this.user.getTokenType();
|
||||
return this.user.getTokenType()
|
||||
}
|
||||
|
||||
getUser(): AuthUser {
|
||||
return this.user;
|
||||
getUser () {
|
||||
return this.user
|
||||
}
|
||||
|
||||
isAdmin() {
|
||||
if (this.user === null) return false;
|
||||
isAdmin () {
|
||||
if (this.user === null) return false
|
||||
|
||||
return this.user.isAdmin();
|
||||
return this.user.isAdmin()
|
||||
}
|
||||
|
||||
isLoggedIn() {
|
||||
isLoggedIn () {
|
||||
if (this.getAccessToken()) {
|
||||
return true;
|
||||
return true
|
||||
} else {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
login(username: string, password: string) {
|
||||
let body = new URLSearchParams();
|
||||
body.set('client_id', this.clientId);
|
||||
body.set('client_secret', this.clientSecret);
|
||||
body.set('response_type', 'code');
|
||||
body.set('grant_type', 'password');
|
||||
body.set('scope', 'upload');
|
||||
body.set('username', username);
|
||||
body.set('password', password);
|
||||
login (username: string, password: string) {
|
||||
let body = new URLSearchParams()
|
||||
body.set('client_id', this.clientId)
|
||||
body.set('client_secret', this.clientSecret)
|
||||
body.set('response_type', 'code')
|
||||
body.set('grant_type', 'password')
|
||||
body.set('scope', 'upload')
|
||||
body.set('username', username)
|
||||
body.set('password', password)
|
||||
|
||||
let headers = new Headers();
|
||||
headers.append('Content-Type', 'application/x-www-form-urlencoded');
|
||||
let headers = new Headers()
|
||||
headers.append('Content-Type', 'application/x-www-form-urlencoded')
|
||||
|
||||
let options = {
|
||||
headers: headers
|
||||
};
|
||||
}
|
||||
|
||||
return this.http.post(AuthService.BASE_TOKEN_URL, body.toString(), options)
|
||||
.map(this.restExtractor.extractDataGet)
|
||||
.map(res => {
|
||||
res.username = username;
|
||||
return res;
|
||||
res.username = username
|
||||
return res
|
||||
})
|
||||
.flatMap(res => this.mergeUserInformations(res))
|
||||
.map(res => this.handleLogin(res))
|
||||
.catch((res) => this.restExtractor.handleError(res));
|
||||
.catch((res) => this.restExtractor.handleError(res))
|
||||
}
|
||||
|
||||
logout() {
|
||||
logout () {
|
||||
// TODO: make an HTTP request to revoke the tokens
|
||||
this.user = null;
|
||||
this.user = null
|
||||
|
||||
AuthUser.flush();
|
||||
AuthUser.flush()
|
||||
|
||||
this.setStatus(AuthStatus.LoggedOut);
|
||||
this.setStatus(AuthStatus.LoggedOut)
|
||||
}
|
||||
|
||||
refreshAccessToken() {
|
||||
console.log('Refreshing token...');
|
||||
refreshAccessToken () {
|
||||
console.log('Refreshing token...')
|
||||
|
||||
const refreshToken = this.getRefreshToken();
|
||||
const refreshToken = this.getRefreshToken()
|
||||
|
||||
let body = new URLSearchParams();
|
||||
body.set('refresh_token', refreshToken);
|
||||
body.set('client_id', this.clientId);
|
||||
body.set('client_secret', this.clientSecret);
|
||||
body.set('response_type', 'code');
|
||||
body.set('grant_type', 'refresh_token');
|
||||
let body = new URLSearchParams()
|
||||
body.set('refresh_token', refreshToken)
|
||||
body.set('client_id', this.clientId)
|
||||
body.set('client_secret', this.clientSecret)
|
||||
body.set('response_type', 'code')
|
||||
body.set('grant_type', 'refresh_token')
|
||||
|
||||
let headers = new Headers();
|
||||
headers.append('Content-Type', 'application/x-www-form-urlencoded');
|
||||
let headers = new Headers()
|
||||
headers.append('Content-Type', 'application/x-www-form-urlencoded')
|
||||
|
||||
let options = {
|
||||
headers: headers
|
||||
};
|
||||
}
|
||||
|
||||
return this.http.post(AuthService.BASE_TOKEN_URL, body.toString(), options)
|
||||
.map(this.restExtractor.extractDataGet)
|
||||
@ -164,41 +164,41 @@ export class AuthService {
|
||||
.catch((res: Response) => {
|
||||
// The refresh token is invalid?
|
||||
if (res.status === 400 && res.json() && res.json().error === 'invalid_grant') {
|
||||
console.error('Cannot refresh token -> logout...');
|
||||
this.logout();
|
||||
this.router.navigate(['/login']);
|
||||
console.error('Cannot refresh token -> logout...')
|
||||
this.logout()
|
||||
this.router.navigate(['/login'])
|
||||
|
||||
return Observable.throw({
|
||||
json: () => '',
|
||||
text: () => 'You need to reconnect.'
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
return this.restExtractor.handleError(res);
|
||||
});
|
||||
return this.restExtractor.handleError(res)
|
||||
})
|
||||
}
|
||||
|
||||
refreshUserInformations() {
|
||||
refreshUserInformations () {
|
||||
const obj = {
|
||||
access_token: this.user.getAccessToken()
|
||||
};
|
||||
}
|
||||
|
||||
this.mergeUserInformations(obj)
|
||||
this.mergeUserInformations (obj)
|
||||
.subscribe(
|
||||
res => {
|
||||
this.user.displayNSFW = res.displayNSFW;
|
||||
this.user.role = res.role;
|
||||
this.user.displayNSFW = res.displayNSFW
|
||||
this.user.role = res.role
|
||||
|
||||
this.user.save();
|
||||
this.user.save()
|
||||
}
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
private mergeUserInformations(obj: { access_token: string }) {
|
||||
private mergeUserInformations (obj: { access_token: string }) {
|
||||
// Do not call authHttp here to avoid circular dependencies headaches
|
||||
|
||||
const headers = new Headers();
|
||||
headers.set('Authorization', `Bearer ${obj.access_token}`);
|
||||
const headers = new Headers()
|
||||
headers.set('Authorization', `Bearer ${obj.access_token}`)
|
||||
|
||||
return this.http.get(AuthService.BASE_USER_INFORMATIONS_URL, { headers })
|
||||
.map(res => res.json())
|
||||
@ -207,38 +207,38 @@ export class AuthService {
|
||||
id: res.id,
|
||||
role: res.role,
|
||||
displayNSFW: res.displayNSFW
|
||||
};
|
||||
}
|
||||
|
||||
return Object.assign(obj, newProperties);
|
||||
return Object.assign(obj, newProperties)
|
||||
}
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
private handleLogin (obj: any) {
|
||||
const id = obj.id;
|
||||
const username = obj.username;
|
||||
const role = obj.role;
|
||||
const email = obj.email;
|
||||
const displayNSFW = obj.displayNSFW;
|
||||
const id = obj.id
|
||||
const username = obj.username
|
||||
const role = obj.role
|
||||
const email = obj.email
|
||||
const displayNSFW = obj.displayNSFW
|
||||
const hashTokens = {
|
||||
access_token: obj.access_token,
|
||||
token_type: obj.token_type,
|
||||
refresh_token: obj.refresh_token
|
||||
};
|
||||
accessToken: obj.access_token,
|
||||
tokenType: obj.token_type,
|
||||
refreshToken: obj.refresh_token
|
||||
}
|
||||
|
||||
this.user = new AuthUser({ id, username, role, displayNSFW, email }, hashTokens);
|
||||
this.user.save();
|
||||
this.user = new AuthUser({ id, username, role, displayNSFW, email }, hashTokens)
|
||||
this.user.save()
|
||||
|
||||
this.setStatus(AuthStatus.LoggedIn);
|
||||
this.setStatus(AuthStatus.LoggedIn)
|
||||
}
|
||||
|
||||
private handleRefreshToken (obj: any) {
|
||||
this.user.refreshTokens(obj.access_token, obj.refresh_token);
|
||||
this.user.save();
|
||||
this.user.refreshTokens(obj.access_token, obj.refresh_token)
|
||||
this.user.save()
|
||||
}
|
||||
|
||||
private setStatus(status: AuthStatus) {
|
||||
this.loginChanged.next(status);
|
||||
private setStatus (status: AuthStatus) {
|
||||
this.loginChanged.next(status)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
export * from './auth-status.model';
|
||||
export * from './auth-user.model';
|
||||
export * from './auth-status.model'
|
||||
export * from './auth-user.model'
|
||||
export * from './auth.service'
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Http } from '@angular/http';
|
||||
import { Injectable } from '@angular/core'
|
||||
import { Http } from '@angular/http'
|
||||
|
||||
import { RestExtractor } from '../../shared/rest';
|
||||
import { RestExtractor } from '../../shared/rest'
|
||||
|
||||
@Injectable()
|
||||
export class ConfigService {
|
||||
private static BASE_CONFIG_URL = API_URL + '/api/v1/config/';
|
||||
private static BASE_CONFIG_URL = API_URL + '/api/v1/config/'
|
||||
|
||||
private config: {
|
||||
signup: {
|
||||
@ -15,22 +15,22 @@ export class ConfigService {
|
||||
signup: {
|
||||
enabled: false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
constructor(
|
||||
constructor (
|
||||
private http: Http,
|
||||
private restExtractor: RestExtractor,
|
||||
private restExtractor: RestExtractor
|
||||
) {}
|
||||
|
||||
loadConfig() {
|
||||
loadConfig () {
|
||||
this.http.get(ConfigService.BASE_CONFIG_URL)
|
||||
.map(this.restExtractor.extractDataGet)
|
||||
.subscribe(data => {
|
||||
this.config = data;
|
||||
});
|
||||
this.config = data
|
||||
})
|
||||
}
|
||||
|
||||
getConfig() {
|
||||
return this.config;
|
||||
getConfig () {
|
||||
return this.config
|
||||
}
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
export * from './config.service';
|
||||
export * from './config.service'
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { Component, HostListener, OnInit, ViewChild } from '@angular/core';
|
||||
import { Component, HostListener, OnInit, ViewChild } from '@angular/core'
|
||||
|
||||
import { ModalDirective } from 'ngx-bootstrap/modal';
|
||||
import { ModalDirective } from 'ngx-bootstrap/modal'
|
||||
|
||||
import { ConfirmService } from './confirm.service';
|
||||
import { ConfirmService } from './confirm.service'
|
||||
|
||||
export interface ConfigChangedEvent {
|
||||
columns: { [id: string]: { isDisplayed: boolean }; };
|
||||
config: { resultsPerPage: number };
|
||||
columns: { [id: string]: { isDisplayed: boolean } }
|
||||
config: { resultsPerPage: number }
|
||||
}
|
||||
|
||||
@Component({
|
||||
@ -14,48 +14,48 @@ export interface ConfigChangedEvent {
|
||||
templateUrl: './confirm.component.html'
|
||||
})
|
||||
export class ConfirmComponent implements OnInit {
|
||||
@ViewChild('confirmModal') confirmModal: ModalDirective;
|
||||
@ViewChild('confirmModal') confirmModal: ModalDirective
|
||||
|
||||
title = '';
|
||||
message = '';
|
||||
title = ''
|
||||
message = ''
|
||||
|
||||
constructor (private confirmService: ConfirmService) {
|
||||
// Empty
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
ngOnInit () {
|
||||
this.confirmModal.config = {
|
||||
backdrop: 'static',
|
||||
keyboard: false
|
||||
};
|
||||
}
|
||||
|
||||
this.confirmService.showConfirm.subscribe(
|
||||
({ title, message }) => {
|
||||
this.title = title;
|
||||
this.message = message;
|
||||
this.title = title
|
||||
this.message = message
|
||||
|
||||
this.showModal();
|
||||
this.showModal()
|
||||
}
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
@HostListener('keydown.enter')
|
||||
confirm() {
|
||||
this.confirmService.confirmResponse.next(true);
|
||||
this.hideModal();
|
||||
confirm () {
|
||||
this.confirmService.confirmResponse.next(true)
|
||||
this.hideModal()
|
||||
}
|
||||
|
||||
@HostListener('keydown.esc')
|
||||
abort() {
|
||||
this.confirmService.confirmResponse.next(false);
|
||||
this.hideModal();
|
||||
abort () {
|
||||
this.confirmService.confirmResponse.next(false)
|
||||
this.hideModal()
|
||||
}
|
||||
|
||||
showModal() {
|
||||
this.confirmModal.show();
|
||||
showModal () {
|
||||
this.confirmModal.show()
|
||||
}
|
||||
|
||||
hideModal() {
|
||||
this.confirmModal.hide();
|
||||
hideModal () {
|
||||
this.confirmModal.hide()
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,15 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Subject } from 'rxjs/Subject';
|
||||
import 'rxjs/add/operator/first';
|
||||
import { Injectable } from '@angular/core'
|
||||
import { Subject } from 'rxjs/Subject'
|
||||
import 'rxjs/add/operator/first'
|
||||
|
||||
@Injectable()
|
||||
export class ConfirmService {
|
||||
showConfirm = new Subject<{ title, message }>();
|
||||
confirmResponse = new Subject<boolean>();
|
||||
showConfirm = new Subject<{ title, message }>()
|
||||
confirmResponse = new Subject<boolean>()
|
||||
|
||||
confirm(message = '', title = '') {
|
||||
this.showConfirm.next({ title, message });
|
||||
confirm (message = '', title = '') {
|
||||
this.showConfirm.next({ title, message })
|
||||
|
||||
return this.confirmResponse.asObservable().first();
|
||||
return this.confirmResponse.asObservable().first()
|
||||
}
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
export * from './confirm.component';
|
||||
export * from './confirm.service';
|
||||
export * from './confirm.component'
|
||||
export * from './confirm.service'
|
||||
|
@ -1,16 +1,16 @@
|
||||
import { NgModule, Optional, SkipSelf } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { HttpModule } from '@angular/http';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { NgModule, Optional, SkipSelf } from '@angular/core'
|
||||
import { CommonModule } from '@angular/common'
|
||||
import { HttpModule } from '@angular/http'
|
||||
import { RouterModule } from '@angular/router'
|
||||
|
||||
import { SimpleNotificationsModule } from 'angular2-notifications';
|
||||
import { ModalModule } from 'ngx-bootstrap/modal';
|
||||
import { SimpleNotificationsModule } from 'angular2-notifications'
|
||||
import { ModalModule } from 'ngx-bootstrap/modal'
|
||||
|
||||
import { AuthService } from './auth';
|
||||
import { ConfigService } from './config';
|
||||
import { ConfirmComponent, ConfirmService } from './confirm';
|
||||
import { MenuComponent, MenuAdminComponent } from './menu';
|
||||
import { throwIfAlreadyLoaded } from './module-import-guard';
|
||||
import { AuthService } from './auth'
|
||||
import { ConfigService } from './config'
|
||||
import { ConfirmComponent, ConfirmService } from './confirm'
|
||||
import { MenuComponent, MenuAdminComponent } from './menu'
|
||||
import { throwIfAlreadyLoaded } from './module-import-guard'
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@ -43,7 +43,7 @@ import { throwIfAlreadyLoaded } from './module-import-guard';
|
||||
]
|
||||
})
|
||||
export class CoreModule {
|
||||
constructor( @Optional() @SkipSelf() parentModule: CoreModule) {
|
||||
throwIfAlreadyLoaded(parentModule, 'CoreModule');
|
||||
constructor ( @Optional() @SkipSelf() parentModule: CoreModule) {
|
||||
throwIfAlreadyLoaded(parentModule, 'CoreModule')
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
export * from './auth';
|
||||
export * from './config';
|
||||
export * from './confirm';
|
||||
export * from './menu';
|
||||
export * from './auth'
|
||||
export * from './config'
|
||||
export * from './confirm'
|
||||
export * from './menu'
|
||||
export * from './core.module'
|
||||
|
@ -1,2 +1,2 @@
|
||||
export * from './menu.component';
|
||||
export * from './menu-admin.component';
|
||||
export * from './menu.component'
|
||||
export * from './menu-admin.component'
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Component } from '@angular/core'
|
||||
|
||||
@Component({
|
||||
selector: 'my-menu-admin',
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { Component, OnInit } from '@angular/core'
|
||||
import { Router } from '@angular/router'
|
||||
|
||||
import { AuthService, AuthStatus } from '../auth';
|
||||
import { ConfigService } from '../config';
|
||||
import { AuthService, AuthStatus } from '../auth'
|
||||
import { ConfigService } from '../config'
|
||||
|
||||
@Component({
|
||||
selector: 'my-menu',
|
||||
@ -10,7 +10,7 @@ import { ConfigService } from '../config';
|
||||
styleUrls: [ './menu.component.scss' ]
|
||||
})
|
||||
export class MenuComponent implements OnInit {
|
||||
isLoggedIn: boolean;
|
||||
isLoggedIn: boolean
|
||||
|
||||
constructor (
|
||||
private authService: AuthService,
|
||||
@ -18,35 +18,35 @@ export class MenuComponent implements OnInit {
|
||||
private router: Router
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.isLoggedIn = this.authService.isLoggedIn();
|
||||
ngOnInit () {
|
||||
this.isLoggedIn = this.authService.isLoggedIn()
|
||||
|
||||
this.authService.loginChangedSource.subscribe(
|
||||
status => {
|
||||
if (status === AuthStatus.LoggedIn) {
|
||||
this.isLoggedIn = true;
|
||||
console.log('Logged in.');
|
||||
this.isLoggedIn = true
|
||||
console.log('Logged in.')
|
||||
} else if (status === AuthStatus.LoggedOut) {
|
||||
this.isLoggedIn = false;
|
||||
console.log('Logged out.');
|
||||
this.isLoggedIn = false
|
||||
console.log('Logged out.')
|
||||
} else {
|
||||
console.error('Unknown auth status: ' + status);
|
||||
console.error('Unknown auth status: ' + status)
|
||||
}
|
||||
}
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
isRegistrationEnabled() {
|
||||
return this.configService.getConfig().signup.enabled;
|
||||
isRegistrationEnabled () {
|
||||
return this.configService.getConfig().signup.enabled
|
||||
}
|
||||
|
||||
isUserAdmin() {
|
||||
return this.authService.isAdmin();
|
||||
isUserAdmin () {
|
||||
return this.authService.isAdmin()
|
||||
}
|
||||
|
||||
logout() {
|
||||
this.authService.logout();
|
||||
logout () {
|
||||
this.authService.logout()
|
||||
// Redirect to home page
|
||||
this.router.navigate(['/videos/list']);
|
||||
this.router.navigate(['/videos/list'])
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
export function throwIfAlreadyLoaded(parentModule: any, moduleName: string) {
|
||||
export function throwIfAlreadyLoaded (parentModule: any, moduleName: string) {
|
||||
if (parentModule) {
|
||||
throw new Error(`${moduleName} has already been loaded. Import Core modules in the AppModule only.`);
|
||||
throw new Error(`${moduleName} has already been loaded. Import Core modules in the AppModule only.`)
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
/* tslint:disable */
|
||||
|
||||
/**
|
||||
* Angular 2
|
||||
*/
|
||||
|
@ -1 +1 @@
|
||||
export * from './app.module';
|
||||
export * from './app.module'
|
||||
|
@ -1,3 +1,3 @@
|
||||
export * from './login-routing.module';
|
||||
export * from './login.component';
|
||||
export * from './login.module';
|
||||
export * from './login-routing.module'
|
||||
export * from './login.component'
|
||||
export * from './login.module'
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { NgModule } from '@angular/core'
|
||||
import { RouterModule, Routes } from '@angular/router'
|
||||
|
||||
import { LoginComponent } from './login.component';
|
||||
import { LoginComponent } from './login.component'
|
||||
|
||||
const loginRoutes: Routes = [
|
||||
{
|
||||
@ -13,7 +13,7 @@ const loginRoutes: Routes = [
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
]
|
||||
|
||||
@NgModule({
|
||||
imports: [ RouterModule.forChild(loginRoutes) ],
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { Router } from '@angular/router';
|
||||
import { Component, OnInit } from '@angular/core'
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms'
|
||||
import { Router } from '@angular/router'
|
||||
|
||||
import { AuthService } from '../core';
|
||||
import { FormReactive } from '../shared';
|
||||
import { AuthService } from '../core'
|
||||
import { FormReactive } from '../shared'
|
||||
|
||||
@Component({
|
||||
selector: 'my-login',
|
||||
@ -11,60 +11,60 @@ import { FormReactive } from '../shared';
|
||||
})
|
||||
|
||||
export class LoginComponent extends FormReactive implements OnInit {
|
||||
error: string = null;
|
||||
error: string = null
|
||||
|
||||
form: FormGroup;
|
||||
form: FormGroup
|
||||
formErrors = {
|
||||
'username': '',
|
||||
'password': ''
|
||||
};
|
||||
}
|
||||
validationMessages = {
|
||||
'username': {
|
||||
'required': 'Username is required.',
|
||||
'required': 'Username is required.'
|
||||
},
|
||||
'password': {
|
||||
'required': 'Password is required.'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
constructor(
|
||||
constructor (
|
||||
private authService: AuthService,
|
||||
private formBuilder: FormBuilder,
|
||||
private router: Router
|
||||
) {
|
||||
super();
|
||||
super()
|
||||
}
|
||||
|
||||
buildForm() {
|
||||
buildForm () {
|
||||
this.form = this.formBuilder.group({
|
||||
username: [ '', Validators.required ],
|
||||
password: [ '', Validators.required ],
|
||||
});
|
||||
password: [ '', Validators.required ]
|
||||
})
|
||||
|
||||
this.form.valueChanges.subscribe(data => this.onValueChanged(data));
|
||||
this.form.valueChanges.subscribe(data => this.onValueChanged(data))
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.buildForm();
|
||||
ngOnInit () {
|
||||
this.buildForm()
|
||||
}
|
||||
|
||||
login() {
|
||||
this.error = null;
|
||||
login () {
|
||||
this.error = null
|
||||
|
||||
const { username, password } = this.form.value;
|
||||
const { username, password } = this.form.value
|
||||
|
||||
this.authService.login(username, password).subscribe(
|
||||
result => this.router.navigate(['/videos/list']),
|
||||
|
||||
error => {
|
||||
console.error(error.json);
|
||||
console.error(error.json)
|
||||
|
||||
if (error.json.error === 'invalid_grant') {
|
||||
this.error = 'Credentials are invalid.';
|
||||
this.error = 'Credentials are invalid.'
|
||||
} else {
|
||||
this.error = `${error.json.error}: ${error.json.error_description}`;
|
||||
this.error = `${error.json.error}: ${error.json.error_description}`
|
||||
}
|
||||
}
|
||||
);
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { NgModule } from '@angular/core'
|
||||
|
||||
import { LoginRoutingModule } from './login-routing.module';
|
||||
import { LoginComponent } from './login.component';
|
||||
import { SharedModule } from '../shared';
|
||||
import { LoginRoutingModule } from './login-routing.module'
|
||||
import { LoginComponent } from './login.component'
|
||||
import { SharedModule } from '../shared'
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable } from '@angular/core'
|
||||
import {
|
||||
ConnectionBackend,
|
||||
Headers,
|
||||
@ -9,79 +9,79 @@ import {
|
||||
RequestOptionsArgs,
|
||||
Response,
|
||||
XHRBackend
|
||||
} from '@angular/http';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
} from '@angular/http'
|
||||
import { Observable } from 'rxjs/Observable'
|
||||
|
||||
import { AuthService } from '../../core';
|
||||
import { AuthService } from '../../core'
|
||||
|
||||
@Injectable()
|
||||
export class AuthHttp extends Http {
|
||||
constructor(backend: ConnectionBackend, defaultOptions: RequestOptions, private authService: AuthService) {
|
||||
super(backend, defaultOptions);
|
||||
constructor (backend: ConnectionBackend, defaultOptions: RequestOptions, private authService: AuthService) {
|
||||
super(backend, defaultOptions)
|
||||
}
|
||||
|
||||
request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
|
||||
if (!options) options = {};
|
||||
request (url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
|
||||
if (!options) options = {}
|
||||
|
||||
options.headers = new Headers();
|
||||
this.setAuthorizationHeader(options.headers);
|
||||
options.headers = new Headers()
|
||||
this.setAuthorizationHeader(options.headers)
|
||||
|
||||
return super.request(url, options)
|
||||
.catch((err) => {
|
||||
if (err.status === 401) {
|
||||
return this.handleTokenExpired(url, options);
|
||||
return this.handleTokenExpired(url, options)
|
||||
}
|
||||
|
||||
return Observable.throw(err);
|
||||
});
|
||||
return Observable.throw(err)
|
||||
})
|
||||
}
|
||||
|
||||
delete(url: string, options?: RequestOptionsArgs): Observable<Response> {
|
||||
if (!options) options = {};
|
||||
options.method = RequestMethod.Delete;
|
||||
delete (url: string, options?: RequestOptionsArgs): Observable<Response> {
|
||||
if (!options) options = {}
|
||||
options.method = RequestMethod.Delete
|
||||
|
||||
return this.request(url, options);
|
||||
return this.request(url, options)
|
||||
}
|
||||
|
||||
get(url: string, options?: RequestOptionsArgs): Observable<Response> {
|
||||
if (!options) options = {};
|
||||
options.method = RequestMethod.Get;
|
||||
get (url: string, options?: RequestOptionsArgs): Observable<Response> {
|
||||
if (!options) options = {}
|
||||
options.method = RequestMethod.Get
|
||||
|
||||
return this.request(url, options);
|
||||
return this.request(url, options)
|
||||
}
|
||||
|
||||
post(url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
|
||||
if (!options) options = {};
|
||||
options.method = RequestMethod.Post;
|
||||
options.body = body;
|
||||
post (url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
|
||||
if (!options) options = {}
|
||||
options.method = RequestMethod.Post
|
||||
options.body = body
|
||||
|
||||
return this.request(url, options);
|
||||
return this.request(url, options)
|
||||
}
|
||||
|
||||
put(url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
|
||||
if (!options) options = {};
|
||||
options.method = RequestMethod.Put;
|
||||
options.body = body;
|
||||
put (url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
|
||||
if (!options) options = {}
|
||||
options.method = RequestMethod.Put
|
||||
options.body = body
|
||||
|
||||
return this.request(url, options);
|
||||
return this.request(url, options)
|
||||
}
|
||||
|
||||
private handleTokenExpired(url: string | Request, options: RequestOptionsArgs) {
|
||||
private handleTokenExpired (url: string | Request, options: RequestOptionsArgs) {
|
||||
return this.authService.refreshAccessToken()
|
||||
.flatMap(() => {
|
||||
this.setAuthorizationHeader(options.headers);
|
||||
this.setAuthorizationHeader(options.headers)
|
||||
|
||||
return super.request(url, options);
|
||||
});
|
||||
return super.request(url, options)
|
||||
})
|
||||
}
|
||||
|
||||
private setAuthorizationHeader(headers: Headers) {
|
||||
headers.set('Authorization', this.authService.getRequestHeaderValue());
|
||||
private setAuthorizationHeader (headers: Headers) {
|
||||
headers.set('Authorization', this.authService.getRequestHeaderValue())
|
||||
}
|
||||
}
|
||||
|
||||
export function useFactory(backend: XHRBackend, defaultOptions: RequestOptions, authService: AuthService) {
|
||||
return new AuthHttp(backend, defaultOptions, authService);
|
||||
export function useFactory (backend: XHRBackend, defaultOptions: RequestOptions, authService: AuthService) {
|
||||
return new AuthHttp(backend, defaultOptions, authService)
|
||||
}
|
||||
|
||||
export const AUTH_HTTP_PROVIDERS = [
|
||||
@ -89,5 +89,5 @@ export const AUTH_HTTP_PROVIDERS = [
|
||||
provide: AuthHttp,
|
||||
useFactory,
|
||||
deps: [ XHRBackend, RequestOptions, AuthService ]
|
||||
},
|
||||
];
|
||||
}
|
||||
]
|
||||
|
@ -1 +1 @@
|
||||
export * from './auth-http.service';
|
||||
export * from './auth-http.service'
|
||||
|
@ -1,38 +1,38 @@
|
||||
import { FormGroup } from '@angular/forms';
|
||||
import { FormGroup } from '@angular/forms'
|
||||
|
||||
export abstract class FormReactive {
|
||||
abstract form: FormGroup;
|
||||
abstract formErrors: Object;
|
||||
abstract validationMessages: Object;
|
||||
abstract form: FormGroup
|
||||
abstract formErrors: Object
|
||||
abstract validationMessages: Object
|
||||
|
||||
abstract buildForm(): void;
|
||||
abstract buildForm (): void
|
||||
|
||||
protected onValueChanged(data?: any) {
|
||||
protected onValueChanged (data?: any) {
|
||||
for (const field in this.formErrors) {
|
||||
// clear previous error message (if any)
|
||||
this.formErrors[field] = '';
|
||||
const control = this.form.get(field);
|
||||
this.formErrors[field] = ''
|
||||
const control = this.form.get(field)
|
||||
|
||||
if (control && control.dirty && !control.valid) {
|
||||
const messages = this.validationMessages[field];
|
||||
const messages = this.validationMessages[field]
|
||||
for (const key in control.errors) {
|
||||
this.formErrors[field] += messages[key] + ' ';
|
||||
this.formErrors[field] += messages[key] + ' '
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Same as onValueChanged but force checking even if the field is not dirty
|
||||
protected forceCheck() {
|
||||
protected forceCheck () {
|
||||
for (const field in this.formErrors) {
|
||||
// clear previous error message (if any)
|
||||
this.formErrors[field] = '';
|
||||
const control = this.form.get(field);
|
||||
this.formErrors[field] = ''
|
||||
const control = this.form.get(field)
|
||||
|
||||
if (control && !control.valid) {
|
||||
const messages = this.validationMessages[field];
|
||||
const messages = this.validationMessages[field]
|
||||
for (const key in control.errors) {
|
||||
this.formErrors[field] += messages[key] + ' ';
|
||||
this.formErrors[field] += messages[key] + ' '
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,14 @@
|
||||
import { FormControl } from '@angular/forms';
|
||||
import { FormControl } from '@angular/forms'
|
||||
|
||||
export function validateHost(c: FormControl) {
|
||||
export function validateHost (c: FormControl) {
|
||||
// Thanks to http://stackoverflow.com/a/106223
|
||||
const HOST_REGEXP = new RegExp(
|
||||
'^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$'
|
||||
);
|
||||
)
|
||||
|
||||
return HOST_REGEXP.test(c.value) ? null : {
|
||||
validateHost: {
|
||||
valid: false
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
export * from './host.validator';
|
||||
export * from './user';
|
||||
export * from './video-abuse';
|
||||
export * from './video';
|
||||
export * from './host.validator'
|
||||
export * from './user'
|
||||
export * from './video-abuse'
|
||||
export * from './video'
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Validators } from '@angular/forms';
|
||||
import { Validators } from '@angular/forms'
|
||||
|
||||
export const USER_USERNAME = {
|
||||
VALIDATORS: [ Validators.required, Validators.minLength(3), Validators.maxLength(20) ],
|
||||
@ -7,18 +7,18 @@ export const USER_USERNAME = {
|
||||
'minlength': 'Username must be at least 3 characters long.',
|
||||
'maxlength': 'Username cannot be more than 20 characters long.'
|
||||
}
|
||||
};
|
||||
}
|
||||
export const USER_EMAIL = {
|
||||
VALIDATORS: [ Validators.required, Validators.email ],
|
||||
MESSAGES: {
|
||||
'required': 'Email is required.',
|
||||
'email': 'Email must be valid.',
|
||||
'email': 'Email must be valid.'
|
||||
}
|
||||
};
|
||||
}
|
||||
export const USER_PASSWORD = {
|
||||
VALIDATORS: [ Validators.required, Validators.minLength(6) ],
|
||||
MESSAGES: {
|
||||
'required': 'Password is required.',
|
||||
'minlength': 'Password must be at least 6 characters long.',
|
||||
'minlength': 'Password must be at least 6 characters long.'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Validators } from '@angular/forms';
|
||||
import { Validators } from '@angular/forms'
|
||||
|
||||
export const VIDEO_ABUSE_REASON = {
|
||||
VALIDATORS: [ Validators.required, Validators.minLength(2), Validators.maxLength(300) ],
|
||||
@ -7,4 +7,4 @@ export const VIDEO_ABUSE_REASON = {
|
||||
'minlength': 'Report reson must be at least 2 characters long.',
|
||||
'maxlength': 'Report reson cannot be more than 300 characters long.'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Validators } from '@angular/forms';
|
||||
import { Validators } from '@angular/forms'
|
||||
|
||||
export const VIDEO_NAME = {
|
||||
VALIDATORS: [ Validators.required, Validators.minLength(3), Validators.maxLength(50) ],
|
||||
@ -7,26 +7,26 @@ export const VIDEO_NAME = {
|
||||
'minlength': 'Video name must be at least 3 characters long.',
|
||||
'maxlength': 'Video name cannot be more than 50 characters long.'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export const VIDEO_CATEGORY = {
|
||||
VALIDATORS: [ Validators.required ],
|
||||
MESSAGES: {
|
||||
'required': 'Video category is required.'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export const VIDEO_LICENCE = {
|
||||
VALIDATORS: [ Validators.required ],
|
||||
MESSAGES: {
|
||||
'required': 'Video licence is required.'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export const VIDEO_LANGUAGE = {
|
||||
VALIDATORS: [ ],
|
||||
MESSAGES: {}
|
||||
};
|
||||
}
|
||||
|
||||
export const VIDEO_DESCRIPTION = {
|
||||
VALIDATORS: [ Validators.required, Validators.minLength(3), Validators.maxLength(250) ],
|
||||
@ -35,7 +35,7 @@ export const VIDEO_DESCRIPTION = {
|
||||
'minlength': 'Video description must be at least 3 characters long.',
|
||||
'maxlength': 'Video description cannot be more than 250 characters long.'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export const VIDEO_TAGS = {
|
||||
VALIDATORS: [ Validators.minLength(2), Validators.maxLength(10) ],
|
||||
@ -43,4 +43,4 @@ export const VIDEO_TAGS = {
|
||||
'minlength': 'A tag should be more than 2 characters long.',
|
||||
'maxlength': 'A tag should be less than 10 characters long.'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
export * from './form-validators';
|
||||
export * from './form-reactive';
|
||||
export * from './form-validators'
|
||||
export * from './form-reactive'
|
||||
|
@ -1,8 +1,8 @@
|
||||
export * from './auth';
|
||||
export * from './forms';
|
||||
export * from './rest';
|
||||
export * from './search';
|
||||
export * from './users';
|
||||
export * from './video-abuse';
|
||||
export * from './shared.module';
|
||||
export * from './utils';
|
||||
export * from './auth'
|
||||
export * from './forms'
|
||||
export * from './rest'
|
||||
export * from './search'
|
||||
export * from './users'
|
||||
export * from './video-abuse'
|
||||
export * from './shared.module'
|
||||
export * from './utils'
|
||||
|
@ -1,4 +1,4 @@
|
||||
export * from './rest-data-source';
|
||||
export * from './rest-extractor.service';
|
||||
export * from './rest-pagination';
|
||||
export * from './rest.service';
|
||||
export * from './rest-data-source'
|
||||
export * from './rest-extractor.service'
|
||||
export * from './rest-pagination'
|
||||
export * from './rest.service'
|
||||
|
@ -1,51 +1,51 @@
|
||||
import { Http, RequestOptionsArgs, URLSearchParams, } from '@angular/http';
|
||||
import { Http, RequestOptionsArgs, URLSearchParams, Response } from '@angular/http'
|
||||
|
||||
import { ServerDataSource } from 'ng2-smart-table';
|
||||
import { ServerDataSource } from 'ng2-smart-table'
|
||||
|
||||
export class RestDataSource extends ServerDataSource {
|
||||
constructor(http: Http, endpoint: string) {
|
||||
const options = {
|
||||
endPoint: endpoint,
|
||||
sortFieldKey: 'sort',
|
||||
dataKey: 'data'
|
||||
};
|
||||
constructor (http: Http, endpoint: string) {
|
||||
const options = {
|
||||
endPoint: endpoint,
|
||||
sortFieldKey: 'sort',
|
||||
dataKey: 'data'
|
||||
}
|
||||
|
||||
super(http, options);
|
||||
}
|
||||
|
||||
protected extractTotalFromResponse(res) {
|
||||
const rawData = res.json();
|
||||
return rawData ? parseInt(rawData.total) : 0;
|
||||
super(http, options)
|
||||
}
|
||||
|
||||
protected addSortRequestOptions(requestOptions: RequestOptionsArgs) {
|
||||
let searchParams: URLSearchParams = <URLSearchParams> requestOptions.search;
|
||||
protected extractTotalFromResponse (res: Response) {
|
||||
const rawData = res.json()
|
||||
return rawData ? parseInt(rawData.total, 10) : 0
|
||||
}
|
||||
|
||||
protected addSortRequestOptions (requestOptions: RequestOptionsArgs) {
|
||||
const searchParams = requestOptions.search as URLSearchParams
|
||||
|
||||
if (this.sortConf) {
|
||||
this.sortConf.forEach((fieldConf) => {
|
||||
const sortPrefix = fieldConf.direction === 'desc' ? '-' : '';
|
||||
const sortPrefix = fieldConf.direction === 'desc' ? '-' : ''
|
||||
|
||||
searchParams.set(this.conf.sortFieldKey, sortPrefix + fieldConf.field);
|
||||
});
|
||||
searchParams.set(this.conf.sortFieldKey, sortPrefix + fieldConf.field)
|
||||
})
|
||||
}
|
||||
|
||||
return requestOptions;
|
||||
return requestOptions
|
||||
}
|
||||
|
||||
protected addPagerRequestOptions(requestOptions: RequestOptionsArgs) {
|
||||
let searchParams: URLSearchParams = <URLSearchParams> requestOptions.search;
|
||||
protected addPagerRequestOptions (requestOptions: RequestOptionsArgs) {
|
||||
const searchParams = requestOptions.search as URLSearchParams
|
||||
|
||||
if (this.pagingConf && this.pagingConf['page'] && this.pagingConf['perPage']) {
|
||||
const perPage = this.pagingConf['perPage'];
|
||||
const page = this.pagingConf['page'];
|
||||
const perPage = this.pagingConf['perPage']
|
||||
const page = this.pagingConf['page']
|
||||
|
||||
const start = (page - 1) * perPage;
|
||||
const count = perPage;
|
||||
const start = (page - 1) * perPage
|
||||
const count = perPage
|
||||
|
||||
searchParams.set('start', start.toString());
|
||||
searchParams.set('count', count.toString());
|
||||
searchParams.set('start', start.toString())
|
||||
searchParams.set('count', count.toString())
|
||||
}
|
||||
|
||||
return requestOptions;
|
||||
return requestOptions
|
||||
}
|
||||
}
|
||||
|
@ -1,52 +1,52 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Response } from '@angular/http';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { Injectable } from '@angular/core'
|
||||
import { Response } from '@angular/http'
|
||||
import { Observable } from 'rxjs/Observable'
|
||||
|
||||
export interface ResultList {
|
||||
data: any[];
|
||||
total: number;
|
||||
data: any[]
|
||||
total: number
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class RestExtractor {
|
||||
|
||||
constructor () { ; }
|
||||
|
||||
extractDataBool(res: Response) {
|
||||
return true;
|
||||
extractDataBool (res: Response) {
|
||||
return true
|
||||
}
|
||||
|
||||
extractDataList(res: Response) {
|
||||
const body = res.json();
|
||||
extractDataList (res: Response) {
|
||||
const body = res.json()
|
||||
|
||||
const ret: ResultList = {
|
||||
data: body.data,
|
||||
total: body.total
|
||||
};
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret
|
||||
}
|
||||
|
||||
extractDataGet(res: Response) {
|
||||
return res.json();
|
||||
extractDataGet (res: Response) {
|
||||
return res.json()
|
||||
}
|
||||
|
||||
handleError(res: Response) {
|
||||
let text = 'Server error: ';
|
||||
text += res.text();
|
||||
let json = '';
|
||||
handleError (res: Response) {
|
||||
let text = 'Server error: '
|
||||
text += res.text()
|
||||
let json = ''
|
||||
|
||||
try {
|
||||
json = res.json();
|
||||
} catch (err) { ; }
|
||||
json = res.json()
|
||||
} catch (err) {
|
||||
console.error('Cannot get JSON from response.')
|
||||
}
|
||||
|
||||
const error = {
|
||||
json,
|
||||
text
|
||||
};
|
||||
}
|
||||
|
||||
console.error(error);
|
||||
console.error(error)
|
||||
|
||||
return Observable.throw(error);
|
||||
return Observable.throw(error)
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
export interface RestPagination {
|
||||
currentPage: number;
|
||||
itemsPerPage: number;
|
||||
totalItems: number;
|
||||
};
|
||||
currentPage: number
|
||||
itemsPerPage: number
|
||||
totalItems: number
|
||||
}
|
||||
|
@ -1,27 +1,27 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { URLSearchParams } from '@angular/http';
|
||||
import { Injectable } from '@angular/core'
|
||||
import { URLSearchParams } from '@angular/http'
|
||||
|
||||
import { RestPagination } from './rest-pagination';
|
||||
import { RestPagination } from './rest-pagination'
|
||||
|
||||
@Injectable()
|
||||
export class RestService {
|
||||
|
||||
buildRestGetParams(pagination?: RestPagination, sort?: string) {
|
||||
const params = new URLSearchParams();
|
||||
buildRestGetParams (pagination?: RestPagination, sort?: string) {
|
||||
const params = new URLSearchParams()
|
||||
|
||||
if (pagination) {
|
||||
const start: number = (pagination.currentPage - 1) * pagination.itemsPerPage;
|
||||
const count: number = pagination.itemsPerPage;
|
||||
const start: number = (pagination.currentPage - 1) * pagination.itemsPerPage
|
||||
const count: number = pagination.itemsPerPage
|
||||
|
||||
params.set('start', start.toString());
|
||||
params.set('count', count.toString());
|
||||
params.set('start', start.toString())
|
||||
params.set('count', count.toString())
|
||||
}
|
||||
|
||||
if (sort) {
|
||||
params.set('sort', sort);
|
||||
params.set('sort', sort)
|
||||
}
|
||||
|
||||
return params;
|
||||
return params
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
export * from './search-field.type';
|
||||
export * from './search.component';
|
||||
export * from './search.model';
|
||||
export * from './search.service';
|
||||
export * from './search-field.type'
|
||||
export * from './search.component'
|
||||
export * from './search.model'
|
||||
export * from './search.service'
|
||||
|
@ -1 +1 @@
|
||||
export type SearchField = "name" | "author" | "host" | "magnetUri" | "tags";
|
||||
export type SearchField = 'name' | 'author' | 'host' | 'magnetUri' | 'tags'
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { Component, OnInit } from '@angular/core'
|
||||
import { Router } from '@angular/router'
|
||||
|
||||
import { Search } from './search.model';
|
||||
import { SearchField } from './search-field.type';
|
||||
import { SearchService } from './search.service';
|
||||
import { Search } from './search.model'
|
||||
import { SearchField } from './search-field.type'
|
||||
import { SearchService } from './search.service'
|
||||
|
||||
@Component({
|
||||
selector: 'my-search',
|
||||
@ -18,53 +18,53 @@ export class SearchComponent implements OnInit {
|
||||
host: 'Pod Host',
|
||||
magnetUri: 'Magnet URI',
|
||||
tags: 'Tags'
|
||||
};
|
||||
}
|
||||
searchCriterias: Search = {
|
||||
field: 'name',
|
||||
value: ''
|
||||
};
|
||||
}
|
||||
|
||||
constructor(private searchService: SearchService, private router: Router) {}
|
||||
constructor (private searchService: SearchService, private router: Router) {}
|
||||
|
||||
ngOnInit() {
|
||||
ngOnInit () {
|
||||
// Subscribe if the search changed
|
||||
// Usually changed by videos list component
|
||||
this.searchService.updateSearch.subscribe(
|
||||
newSearchCriterias => {
|
||||
// Put a field by default
|
||||
if (!newSearchCriterias.field) {
|
||||
newSearchCriterias.field = 'name';
|
||||
newSearchCriterias.field = 'name'
|
||||
}
|
||||
|
||||
this.searchCriterias = newSearchCriterias;
|
||||
this.searchCriterias = newSearchCriterias
|
||||
}
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
get choiceKeys() {
|
||||
return Object.keys(this.fieldChoices);
|
||||
get choiceKeys () {
|
||||
return Object.keys(this.fieldChoices)
|
||||
}
|
||||
|
||||
choose($event: MouseEvent, choice: SearchField) {
|
||||
$event.preventDefault();
|
||||
$event.stopPropagation();
|
||||
choose ($event: MouseEvent, choice: SearchField) {
|
||||
$event.preventDefault()
|
||||
$event.stopPropagation()
|
||||
|
||||
this.searchCriterias.field = choice;
|
||||
this.searchCriterias.field = choice
|
||||
|
||||
if (this.searchCriterias.value) {
|
||||
this.doSearch();
|
||||
this.doSearch()
|
||||
}
|
||||
}
|
||||
|
||||
doSearch() {
|
||||
doSearch () {
|
||||
if (this.router.url.indexOf('/videos/list') === -1) {
|
||||
this.router.navigate([ '/videos/list' ]);
|
||||
this.router.navigate([ '/videos/list' ])
|
||||
}
|
||||
|
||||
this.searchService.searchUpdated.next(this.searchCriterias);
|
||||
this.searchService.searchUpdated.next(this.searchCriterias)
|
||||
}
|
||||
|
||||
getStringChoice(choiceKey: SearchField) {
|
||||
return this.fieldChoices[choiceKey];
|
||||
getStringChoice (choiceKey: SearchField) {
|
||||
return this.fieldChoices[choiceKey]
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { SearchField } from './search-field.type';
|
||||
import { SearchField } from './search-field.type'
|
||||
|
||||
export interface Search {
|
||||
field: SearchField;
|
||||
value: string;
|
||||
field: SearchField
|
||||
value: string
|
||||
}
|
||||
|
@ -1,18 +1,18 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Subject } from 'rxjs/Subject';
|
||||
import { ReplaySubject } from 'rxjs/ReplaySubject';
|
||||
import { Injectable } from '@angular/core'
|
||||
import { Subject } from 'rxjs/Subject'
|
||||
import { ReplaySubject } from 'rxjs/ReplaySubject'
|
||||
|
||||
import { Search } from './search.model';
|
||||
import { Search } from './search.model'
|
||||
|
||||
// This class is needed to communicate between videos/ and search component
|
||||
// Remove it when we'll be able to subscribe to router changes
|
||||
@Injectable()
|
||||
export class SearchService {
|
||||
searchUpdated: Subject<Search>;
|
||||
updateSearch: Subject<Search>;
|
||||
searchUpdated: Subject<Search>
|
||||
updateSearch: Subject<Search>
|
||||
|
||||
constructor() {
|
||||
this.updateSearch = new Subject<Search>();
|
||||
this.searchUpdated = new ReplaySubject<Search>(1);
|
||||
constructor () {
|
||||
this.updateSearch = new Subject<Search>()
|
||||
this.searchUpdated = new ReplaySubject<Search>(1)
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +1,23 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { HttpModule } from '@angular/http';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { NgModule } from '@angular/core'
|
||||
import { CommonModule } from '@angular/common'
|
||||
import { HttpModule } from '@angular/http'
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
|
||||
import { RouterModule } from '@angular/router'
|
||||
|
||||
import { BytesPipe } from 'angular-pipes/src/math/bytes.pipe';
|
||||
import { KeysPipe } from 'angular-pipes/src/object/keys.pipe';
|
||||
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
|
||||
import { ProgressbarModule } from 'ngx-bootstrap/progressbar';
|
||||
import { PaginationModule } from 'ngx-bootstrap/pagination';
|
||||
import { ModalModule } from 'ngx-bootstrap/modal';
|
||||
import { FileUploadModule } from 'ng2-file-upload/ng2-file-upload';
|
||||
import { Ng2SmartTableModule } from 'ng2-smart-table';
|
||||
import { BytesPipe } from 'angular-pipes/src/math/bytes.pipe'
|
||||
import { KeysPipe } from 'angular-pipes/src/object/keys.pipe'
|
||||
import { BsDropdownModule } from 'ngx-bootstrap/dropdown'
|
||||
import { ProgressbarModule } from 'ngx-bootstrap/progressbar'
|
||||
import { PaginationModule } from 'ngx-bootstrap/pagination'
|
||||
import { ModalModule } from 'ngx-bootstrap/modal'
|
||||
import { FileUploadModule } from 'ng2-file-upload/ng2-file-upload'
|
||||
import { Ng2SmartTableModule } from 'ng2-smart-table'
|
||||
|
||||
import { AUTH_HTTP_PROVIDERS } from './auth';
|
||||
import { RestExtractor, RestService } from './rest';
|
||||
import { SearchComponent, SearchService } from './search';
|
||||
import { UserService } from './users';
|
||||
import { VideoAbuseService } from './video-abuse';
|
||||
import { AUTH_HTTP_PROVIDERS } from './auth'
|
||||
import { RestExtractor, RestService } from './rest'
|
||||
import { SearchComponent, SearchService } from './search'
|
||||
import { UserService } from './users'
|
||||
import { VideoAbuseService } from './video-abuse'
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
|
@ -1,2 +1,2 @@
|
||||
export * from './user.model';
|
||||
export * from './user.service';
|
||||
export * from './user.model'
|
||||
export * from './user.service'
|
||||
|
@ -1,33 +1,33 @@
|
||||
import { User as UserServerModel, UserRole } from '../../../../../shared';
|
||||
import { User as UserServerModel, UserRole } from '../../../../../shared'
|
||||
|
||||
export class User implements UserServerModel {
|
||||
id: number;
|
||||
username: string;
|
||||
email: string;
|
||||
role: UserRole;
|
||||
displayNSFW: boolean;
|
||||
createdAt: Date;
|
||||
id: number
|
||||
username: string
|
||||
email: string
|
||||
role: UserRole
|
||||
displayNSFW: boolean
|
||||
createdAt: Date
|
||||
|
||||
constructor(hash: {
|
||||
constructor (hash: {
|
||||
id: number,
|
||||
username: string,
|
||||
email: string,
|
||||
role: UserRole,
|
||||
displayNSFW?: boolean,
|
||||
createdAt?: Date,
|
||||
createdAt?: Date
|
||||
}) {
|
||||
this.id = hash.id;
|
||||
this.username = hash.username;
|
||||
this.email = hash.email;
|
||||
this.role = hash.role;
|
||||
this.displayNSFW = hash.displayNSFW;
|
||||
this.id = hash.id
|
||||
this.username = hash.username
|
||||
this.email = hash.email
|
||||
this.role = hash.role
|
||||
this.displayNSFW = hash.displayNSFW
|
||||
|
||||
if (hash.createdAt) {
|
||||
this.createdAt = hash.createdAt;
|
||||
this.createdAt = hash.createdAt
|
||||
}
|
||||
}
|
||||
|
||||
isAdmin() {
|
||||
return this.role === 'admin';
|
||||
isAdmin () {
|
||||
return this.role === 'admin'
|
||||
}
|
||||
}
|
||||
|
@ -1,58 +1,58 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Http } from '@angular/http';
|
||||
import 'rxjs/add/operator/catch';
|
||||
import 'rxjs/add/operator/map';
|
||||
import { Injectable } from '@angular/core'
|
||||
import { Http } from '@angular/http'
|
||||
import 'rxjs/add/operator/catch'
|
||||
import 'rxjs/add/operator/map'
|
||||
|
||||
import { AuthService } from '../../core';
|
||||
import { AuthHttp } from '../auth';
|
||||
import { RestExtractor } from '../rest';
|
||||
import { AuthService } from '../../core'
|
||||
import { AuthHttp } from '../auth'
|
||||
import { RestExtractor } from '../rest'
|
||||
|
||||
@Injectable()
|
||||
export class UserService {
|
||||
static BASE_USERS_URL = API_URL + '/api/v1/users/';
|
||||
static BASE_USERS_URL = API_URL + '/api/v1/users/'
|
||||
|
||||
constructor(
|
||||
constructor (
|
||||
private http: Http,
|
||||
private authHttp: AuthHttp,
|
||||
private authService: AuthService,
|
||||
private restExtractor: RestExtractor
|
||||
) {}
|
||||
|
||||
checkTokenValidity() {
|
||||
const url = UserService.BASE_USERS_URL + 'me';
|
||||
checkTokenValidity () {
|
||||
const url = UserService.BASE_USERS_URL + 'me'
|
||||
|
||||
// AuthHttp will redirect us to the login page if the oken is not valid anymore
|
||||
this.authHttp.get(url).subscribe(() => { ; });
|
||||
this.authHttp.get(url).subscribe()
|
||||
}
|
||||
|
||||
changePassword(newPassword: string) {
|
||||
const url = UserService.BASE_USERS_URL + this.authService.getUser().id;
|
||||
changePassword (newPassword: string) {
|
||||
const url = UserService.BASE_USERS_URL + this.authService.getUser().id
|
||||
const body = {
|
||||
password: newPassword
|
||||
};
|
||||
}
|
||||
|
||||
return this.authHttp.put(url, body)
|
||||
.map(this.restExtractor.extractDataBool)
|
||||
.catch((res) => this.restExtractor.handleError(res));
|
||||
.catch((res) => this.restExtractor.handleError(res))
|
||||
}
|
||||
|
||||
updateDetails(details: { displayNSFW: boolean }) {
|
||||
const url = UserService.BASE_USERS_URL + this.authService.getUser().id;
|
||||
updateDetails (details: { displayNSFW: boolean }) {
|
||||
const url = UserService.BASE_USERS_URL + this.authService.getUser().id
|
||||
|
||||
return this.authHttp.put(url, details)
|
||||
.map(this.restExtractor.extractDataBool)
|
||||
.catch((res) => this.restExtractor.handleError(res));
|
||||
.catch((res) => this.restExtractor.handleError(res))
|
||||
}
|
||||
|
||||
signup(username: string, password: string, email: string) {
|
||||
signup (username: string, password: string, email: string) {
|
||||
const body = {
|
||||
username,
|
||||
email,
|
||||
password
|
||||
};
|
||||
}
|
||||
|
||||
return this.http.post(UserService.BASE_USERS_URL + 'register', body)
|
||||
.map(this.restExtractor.extractDataBool)
|
||||
.catch(this.restExtractor.handleError);
|
||||
.catch(this.restExtractor.handleError)
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { DatePipe } from '@angular/common';
|
||||
import { DatePipe } from '@angular/common'
|
||||
|
||||
export class Utils {
|
||||
|
||||
static dateToHuman(date: String) {
|
||||
return new DatePipe('en').transform(date, 'medium');
|
||||
static dateToHuman (date: String) {
|
||||
return new DatePipe('en').transform(date, 'medium')
|
||||
}
|
||||
|
||||
static getRowDeleteButton() {
|
||||
return '<span class="glyphicon glyphicon-remove glyphicon-black"></span>';
|
||||
static getRowDeleteButton () {
|
||||
return '<span class="glyphicon glyphicon-remove glyphicon-black"></span>'
|
||||
}
|
||||
}
|
||||
|
@ -1,2 +1,2 @@
|
||||
export * from './video-abuse.service';
|
||||
export * from './video-abuse.model';
|
||||
export * from './video-abuse.service'
|
||||
export * from './video-abuse.model'
|
||||
|
@ -1,8 +1,8 @@
|
||||
export interface VideoAbuse {
|
||||
id: string;
|
||||
reason: string;
|
||||
reporterPodHost: string;
|
||||
reporterUsername: string;
|
||||
videoId: string;
|
||||
createdAt: Date;
|
||||
id: string
|
||||
reason: string
|
||||
reporterPodHost: string
|
||||
reporterUsername: string
|
||||
videoId: string
|
||||
createdAt: Date
|
||||
}
|
||||
|
@ -1,42 +1,42 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Http } from '@angular/http';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import 'rxjs/add/operator/catch';
|
||||
import 'rxjs/add/operator/map';
|
||||
import { Injectable } from '@angular/core'
|
||||
import { Http } from '@angular/http'
|
||||
import { Observable } from 'rxjs/Observable'
|
||||
import 'rxjs/add/operator/catch'
|
||||
import 'rxjs/add/operator/map'
|
||||
|
||||
import { AuthService } from '../core';
|
||||
import { AuthHttp } from '../auth';
|
||||
import { RestDataSource, RestExtractor, ResultList } from '../rest';
|
||||
import { VideoAbuse } from './video-abuse.model';
|
||||
import { AuthService } from '../core'
|
||||
import { AuthHttp } from '../auth'
|
||||
import { RestDataSource, RestExtractor, ResultList } from '../rest'
|
||||
import { VideoAbuse } from './video-abuse.model'
|
||||
|
||||
@Injectable()
|
||||
export class VideoAbuseService {
|
||||
private static BASE_VIDEO_ABUSE_URL = API_URL + '/api/v1/videos/';
|
||||
private static BASE_VIDEO_ABUSE_URL = API_URL + '/api/v1/videos/'
|
||||
|
||||
constructor(
|
||||
constructor (
|
||||
private authHttp: AuthHttp,
|
||||
private restExtractor: RestExtractor
|
||||
) {}
|
||||
|
||||
getDataSource() {
|
||||
return new RestDataSource(this.authHttp, VideoAbuseService.BASE_VIDEO_ABUSE_URL + 'abuse');
|
||||
getDataSource () {
|
||||
return new RestDataSource(this.authHttp, VideoAbuseService.BASE_VIDEO_ABUSE_URL + 'abuse')
|
||||
}
|
||||
|
||||
reportVideo(id: string, reason: string) {
|
||||
reportVideo (id: string, reason: string) {
|
||||
const body = {
|
||||
reason
|
||||
};
|
||||
const url = VideoAbuseService.BASE_VIDEO_ABUSE_URL + id + '/abuse';
|
||||
}
|
||||
const url = VideoAbuseService.BASE_VIDEO_ABUSE_URL + id + '/abuse'
|
||||
|
||||
return this.authHttp.post(url, body)
|
||||
.map(this.restExtractor.extractDataBool)
|
||||
.catch((res) => this.restExtractor.handleError(res));
|
||||
.catch((res) => this.restExtractor.handleError(res))
|
||||
}
|
||||
|
||||
private extractVideoAbuses(result: ResultList) {
|
||||
const videoAbuses: VideoAbuse[] = result.data;
|
||||
const totalVideoAbuses = result.total;
|
||||
private extractVideoAbuses (result: ResultList) {
|
||||
const videoAbuses: VideoAbuse[] = result.data
|
||||
const totalVideoAbuses = result.total
|
||||
|
||||
return { videoAbuses, totalVideoAbuses };
|
||||
return { videoAbuses, totalVideoAbuses }
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,3 @@
|
||||
export * from './signup-routing.module';
|
||||
export * from './signup.component';
|
||||
export * from './signup.module';
|
||||
export * from './signup-routing.module'
|
||||
export * from './signup.component'
|
||||
export * from './signup.module'
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { NgModule } from '@angular/core'
|
||||
import { RouterModule, Routes } from '@angular/router'
|
||||
|
||||
import { SignupComponent } from './signup.component';
|
||||
import { SignupComponent } from './signup.component'
|
||||
|
||||
const signupRoutes: Routes = [
|
||||
{
|
||||
@ -13,7 +13,7 @@ const signupRoutes: Routes = [
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
]
|
||||
|
||||
@NgModule({
|
||||
imports: [ RouterModule.forChild(signupRoutes) ],
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user