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