Use typescript standard and lint all files

This commit is contained in:
Chocobozzz 2017-06-16 14:32:15 +02:00
parent 46757b477c
commit df98563e21
143 changed files with 2016 additions and 1949 deletions

View File

@ -13,7 +13,7 @@
"url": "git://github.com/Chocobozzz/PeerTube.git"
},
"scripts": {
"test": "standard && tslint -c ./tslint.json src/**/*.ts",
"test": "standard && tslint --type-check --project ./tsconfig.json -c ./tslint.json 'src/app/**/*.ts'",
"webpack": "webpack",
"webpack-dev-server": "webpack-dev-server"
},
@ -78,7 +78,7 @@
"tslib": "^1.5.0",
"tslint": "~5.4.3",
"tslint-loader": "^3.3.0",
"typescript": "~2.3.0",
"typescript": "~2.4.0",
"url-loader": "^0.5.7",
"video.js": "^5.19.2",
"videojs-dock": "^2.0.2",
@ -93,6 +93,7 @@
"codelyzer": "^3.0.0-beta.4",
"ng2-completer": "1.2.2",
"standard": "^10.0.0",
"tslint-config-standard": "^6.0.1",
"webpack-bundle-analyzer": "^2.8.2",
"webpack-dev-server": "^2.4.5",
"webpack-dll-bundles-plugin": "^1.0.0-beta.5"

View File

@ -1,11 +1,11 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { NgModule } from '@angular/core'
import { RouterModule, Routes } from '@angular/router'
import { AdminComponent } from './admin.component';
import { FriendsRoutes } from './friends';
import { RequestsRoutes } from './requests';
import { UsersRoutes } from './users';
import { VideoAbusesRoutes } from './video-abuses';
import { AdminComponent } from './admin.component'
import { FriendsRoutes } from './friends'
import { RequestsRoutes } from './requests'
import { UsersRoutes } from './users'
import { VideoAbusesRoutes } from './video-abuses'
const adminRoutes: Routes = [
{
@ -23,7 +23,7 @@ const adminRoutes: Routes = [
...VideoAbusesRoutes
]
}
];
]
@NgModule({
imports: [ RouterModule.forChild(adminRoutes) ],

View File

@ -1,4 +1,4 @@
import { Component } from '@angular/core';
import { Component } from '@angular/core'
@Component({
template: '<router-outlet></router-outlet>'

View File

@ -1,12 +1,12 @@
import { NgModule } from '@angular/core';
import { NgModule } from '@angular/core'
import { AdminComponent } from './admin.component';
import { AdminRoutingModule } from './admin-routing.module';
import { FriendsComponent, FriendAddComponent, FriendListComponent, FriendService } from './friends';
import { RequestsComponent, RequestStatsComponent, RequestService } from './requests';
import { UsersComponent, UserAddComponent, UserListComponent, UserService } from './users';
import { VideoAbusesComponent, VideoAbuseListComponent } from './video-abuses';
import { SharedModule } from '../shared';
import { AdminComponent } from './admin.component'
import { AdminRoutingModule } from './admin-routing.module'
import { FriendsComponent, FriendAddComponent, FriendListComponent, FriendService } from './friends'
import { RequestsComponent, RequestStatsComponent, RequestService } from './requests'
import { UsersComponent, UserAddComponent, UserListComponent, UserService } from './users'
import { VideoAbusesComponent, VideoAbuseListComponent } from './video-abuses'
import { SharedModule } from '../shared'
@NgModule({
imports: [

View File

@ -1,12 +1,12 @@
import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { Router } from '@angular/router';
import { Component, OnInit } from '@angular/core'
import { FormControl, FormGroup } from '@angular/forms'
import { Router } from '@angular/router'
import { NotificationsService } from 'angular2-notifications';
import { NotificationsService } from 'angular2-notifications'
import { ConfirmService } from '../../../core';
import { validateHost } from '../../../shared';
import { FriendService } from '../shared';
import { ConfirmService } from '../../../core'
import { validateHost } from '../../../shared'
import { FriendService } from '../shared'
@Component({
selector: 'my-friend-add',
@ -14,107 +14,107 @@ import { FriendService } from '../shared';
styleUrls: [ './friend-add.component.scss' ]
})
export class FriendAddComponent implements OnInit {
form: FormGroup;
hosts = [ ];
error: string = null;
form: FormGroup
hosts = [ ]
error: string = null
constructor(
constructor (
private router: Router,
private notificationsService: NotificationsService,
private confirmService: ConfirmService,
private friendService: FriendService
) {}
ngOnInit() {
this.form = new FormGroup({});
this.addField();
ngOnInit () {
this.form = new FormGroup({})
this.addField()
}
addField() {
this.form.addControl(`host-${this.hosts.length}`, new FormControl('', [ validateHost ]));
this.hosts.push('');
addField () {
this.form.addControl(`host-${this.hosts.length}`, new FormControl('', [ validateHost ]))
this.hosts.push('')
}
canMakeFriends() {
return window.location.protocol === 'https:';
canMakeFriends () {
return window.location.protocol === 'https:'
}
customTrackBy(index: number, obj: any): any {
return index;
customTrackBy (index: number, obj: any): any {
return index
}
displayAddField(index: number) {
return index === (this.hosts.length - 1);
displayAddField (index: number) {
return index === (this.hosts.length - 1)
}
displayRemoveField(index: number) {
return (index !== 0 || this.hosts.length > 1) && index !== (this.hosts.length - 1);
displayRemoveField (index: number) {
return (index !== 0 || this.hosts.length > 1) && index !== (this.hosts.length - 1)
}
isFormValid() {
isFormValid () {
// Do not check the last input
for (let i = 0; i < this.hosts.length - 1; i++) {
if (!this.form.controls[`host-${i}`].valid) return false;
if (!this.form.controls[`host-${i}`].valid) return false
}
const lastIndex = this.hosts.length - 1;
const lastIndex = this.hosts.length - 1
// If the last input (which is not the first) is empty, it's ok
if (this.hosts[lastIndex] === '' && lastIndex !== 0) {
return true;
return true
} else {
return this.form.controls[`host-${lastIndex}`].valid;
return this.form.controls[`host-${lastIndex}`].valid
}
}
removeField(index: number) {
removeField (index: number) {
// Remove the last control
this.form.removeControl(`host-${this.hosts.length - 1}`);
this.hosts.splice(index, 1);
this.form.removeControl(`host-${this.hosts.length - 1}`)
this.hosts.splice(index, 1)
}
makeFriends() {
this.error = '';
makeFriends () {
this.error = ''
const notEmptyHosts = this.getNotEmptyHosts();
const notEmptyHosts = this.getNotEmptyHosts()
if (notEmptyHosts.length === 0) {
this.error = 'You need to specify at least 1 host.';
return;
this.error = 'You need to specify at least 1 host.'
return
}
if (!this.isHostsUnique(notEmptyHosts)) {
this.error = 'Hosts need to be unique.';
return;
this.error = 'Hosts need to be unique.'
return
}
const confirmMessage = 'Are you sure to make friends with:<br /> - ' + notEmptyHosts.join('<br /> - ');
const confirmMessage = 'Are you sure to make friends with:<br /> - ' + notEmptyHosts.join('<br /> - ')
this.confirmService.confirm(confirmMessage, 'Make friends').subscribe(
res => {
if (res === false) return;
if (res === false) return
this.friendService.makeFriends(notEmptyHosts).subscribe(
status => {
this.notificationsService.success('Sucess', 'Make friends request sent!');
this.router.navigate([ '/admin/friends/list' ]);
this.notificationsService.success('Sucess', 'Make friends request sent!')
this.router.navigate([ '/admin/friends/list' ])
},
err => this.notificationsService.error('Error', err.text)
);
)
}
);
)
}
private getNotEmptyHosts() {
const notEmptyHosts = [];
private getNotEmptyHosts () {
const notEmptyHosts = []
Object.keys(this.form.value).forEach((hostKey) => {
const host = this.form.value[hostKey];
if (host !== '') notEmptyHosts.push(host);
});
const host = this.form.value[hostKey]
if (host !== '') notEmptyHosts.push(host)
})
return notEmptyHosts;
return notEmptyHosts
}
private isHostsUnique(hosts: string[]) {
return hosts.every(host => hosts.indexOf(host) === hosts.lastIndexOf(host));
private isHostsUnique (hosts: string[]) {
return hosts.every(host => hosts.indexOf(host) === hosts.lastIndexOf(host))
}
}

View File

@ -1 +1 @@
export * from './friend-add.component';
export * from './friend-add.component'

View File

@ -1,11 +1,11 @@
import { Component } from '@angular/core';
import { Component } from '@angular/core'
import { NotificationsService } from 'angular2-notifications';
import { ServerDataSource } from 'ng2-smart-table';
import { NotificationsService } from 'angular2-notifications'
import { ServerDataSource } from 'ng2-smart-table'
import { ConfirmService } from '../../../core';
import { Utils } from '../../../shared';
import { Friend, FriendService } from '../shared';
import { ConfirmService } from '../../../core'
import { Utils } from '../../../shared'
import { Friend, FriendService } from '../shared'
@Component({
selector: 'my-friend-list',
@ -13,7 +13,7 @@ import { Friend, FriendService } from '../shared';
styleUrls: [ './friend-list.component.scss' ]
})
export class FriendListComponent {
friendsSource = null;
friendsSource = null
tableSettings = {
attr: {
class: 'table-hover'
@ -49,36 +49,36 @@ export class FriendListComponent {
valuePrepareFunction: Utils.dateToHuman
}
}
};
}
constructor(
constructor (
private notificationsService: NotificationsService,
private confirmService: ConfirmService,
private friendService: FriendService
) {
this.friendsSource = this.friendService.getDataSource();
this.friendsSource = this.friendService.getDataSource()
}
hasFriends() {
return this.friendsSource.count() !== 0;
hasFriends () {
return this.friendsSource.count() !== 0
}
quitFriends() {
const confirmMessage = 'Do you really want to quit your friends? All their videos will be deleted.';
quitFriends () {
const confirmMessage = 'Do you really want to quit your friends? All their videos will be deleted.'
this.confirmService.confirm(confirmMessage, 'Quit friends').subscribe(
res => {
if (res === false) return;
if (res === false) return
this.friendService.quitFriends().subscribe(
status => {
this.notificationsService.success('Sucess', 'Friends left!');
this.notificationsService.success('Sucess', 'Friends left!')
this.friendsSource.refresh();
this.friendsSource.refresh()
},
err => this.notificationsService.error('Error', err.text)
);
)
}
);
)
}
}

View File

@ -1 +1 @@
export * from './friend-list.component';
export * from './friend-list.component'

View File

@ -1,8 +1,7 @@
import { Component } from '@angular/core';
import { Component } from '@angular/core'
@Component({
template: '<router-outlet></router-outlet>'
template: '<router-outlet></router-outlet>'
})
export class FriendsComponent {
}

View File

@ -1,37 +1,37 @@
import { Routes } from '@angular/router';
import { Routes } from '@angular/router'
import { FriendsComponent } from './friends.component';
import { FriendAddComponent } from './friend-add';
import { FriendListComponent } from './friend-list';
import { FriendsComponent } from './friends.component'
import { FriendAddComponent } from './friend-add'
import { FriendListComponent } from './friend-list'
export const FriendsRoutes: Routes = [
{
path: 'friends',
component: FriendsComponent,
children: [
{
path: '',
redirectTo: 'list',
pathMatch: 'full'
},
{
path: 'list',
component: FriendListComponent,
data: {
meta: {
title: 'Friends list'
}
}
},
{
path: 'add',
component: FriendAddComponent,
data: {
meta: {
title: 'Add friends'
}
path: 'friends',
component: FriendsComponent,
children: [
{
path: '',
redirectTo: 'list',
pathMatch: 'full'
},
{
path: 'list',
component: FriendListComponent,
data: {
meta: {
title: 'Friends list'
}
}
]
}
];
},
{
path: 'add',
component: FriendAddComponent,
data: {
meta: {
title: 'Add friends'
}
}
}
]
}
]

View File

@ -1,5 +1,5 @@
export * from './friend-add';
export * from './friend-list';
export * from './shared';
export * from './friends.component';
export * from './friends.routes';
export * from './friend-add'
export * from './friend-list'
export * from './shared'
export * from './friends.component'
export * from './friends.routes'

View File

@ -1,7 +1,7 @@
export interface Friend {
id: string;
host: string;
score: number;
email: string;
createdAt: Date;
id: string
host: string
score: number
email: string
createdAt: Date
}

View File

@ -1,39 +1,39 @@
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import { Injectable } from '@angular/core'
import { Observable } from 'rxjs/Observable'
import 'rxjs/add/operator/catch'
import 'rxjs/add/operator/map'
import { ServerDataSource } from 'ng2-smart-table';
import { ServerDataSource } from 'ng2-smart-table'
import { Friend } from './friend.model';
import { AuthHttp, RestExtractor, RestDataSource, ResultList } from '../../../shared';
import { Friend } from './friend.model'
import { AuthHttp, RestExtractor, RestDataSource, ResultList } from '../../../shared'
@Injectable()
export class FriendService {
private static BASE_FRIEND_URL = API_URL + '/api/v1/pods/';
private static BASE_FRIEND_URL = API_URL + '/api/v1/pods/'
constructor (
private authHttp: AuthHttp,
private restExtractor: RestExtractor
) {}
getDataSource() {
return new RestDataSource(this.authHttp, FriendService.BASE_FRIEND_URL);
getDataSource () {
return new RestDataSource(this.authHttp, FriendService.BASE_FRIEND_URL)
}
makeFriends(notEmptyHosts) {
makeFriends (notEmptyHosts) {
const body = {
hosts: notEmptyHosts
};
}
return this.authHttp.post(FriendService.BASE_FRIEND_URL + 'makefriends', body)
.map(this.restExtractor.extractDataBool)
.catch((res) => this.restExtractor.handleError(res));
.catch((res) => this.restExtractor.handleError(res))
}
quitFriends() {
quitFriends () {
return this.authHttp.get(FriendService.BASE_FRIEND_URL + 'quitfriends')
.map(res => res.status)
.catch((res) => this.restExtractor.handleError(res));
.catch((res) => this.restExtractor.handleError(res))
}
}

View File

@ -1,2 +1,2 @@
export * from './friend.model';
export * from './friend.service';
export * from './friend.model'
export * from './friend.service'

View File

@ -1,6 +1,6 @@
export * from './friends';
export * from './requests';
export * from './users';
export * from './admin-routing.module';
export * from './admin.module';
export * from './admin.component';
export * from './friends'
export * from './requests'
export * from './users'
export * from './admin-routing.module'
export * from './admin.module'
export * from './admin.component'

View File

@ -1,4 +1,4 @@
export * from './request-stats';
export * from './shared';
export * from './requests.component';
export * from './requests.routes';
export * from './request-stats'
export * from './shared'
export * from './requests.component'
export * from './requests.routes'

View File

@ -1 +1 @@
export * from './request-stats.component';
export * from './request-stats.component'

View File

@ -1,12 +1,12 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Component, OnInit, OnDestroy } from '@angular/core'
import { NotificationsService } from 'angular2-notifications';
import { NotificationsService } from 'angular2-notifications'
import { RequestService, RequestStats } from '../shared';
import { RequestService, RequestStats } from '../shared'
@Component({
selector: 'my-request-stats',
templateUrl: './request-stats.component.html',
selector: 'my-request-stats',
templateUrl: './request-stats.component.html',
styleUrls: [ './request-stats.component.scss' ]
})
export class RequestStatsComponent implements OnInit, OnDestroy {
@ -14,70 +14,67 @@ export class RequestStatsComponent implements OnInit, OnDestroy {
requestScheduler: 'Basic request scheduler',
requestVideoEventScheduler: 'Video events request scheduler',
requestVideoQaduScheduler: 'Quick and dirty video updates request scheduler'
};
}
stats: { [ id: string ]: RequestStats } = {
requestScheduler: null,
requestVideoEventScheduler: null,
requestVideoQaduScheduler: null
};
}
private intervals: { [ id: string ]: number } = {
requestScheduler: null,
requestVideoEventScheduler: null,
requestVideoQaduScheduler: null
};
}
private timeouts: { [ id: string ]: number } = {
requestScheduler: null,
requestVideoEventScheduler: null,
requestVideoQaduScheduler: null
};
constructor(
private notificationsService: NotificationsService,
private requestService: RequestService
) { }
ngOnInit() {
this.getStats();
this.runIntervals();
}
ngOnDestroy() {
constructor (
private notificationsService: NotificationsService,
private requestService: RequestService
) { }
ngOnInit () {
this.getStats()
this.runIntervals()
}
ngOnDestroy () {
Object.keys(this.stats).forEach(requestSchedulerName => {
if (this.intervals[requestSchedulerName] !== null) {
window.clearInterval(this.intervals[requestSchedulerName]);
window.clearInterval(this.intervals[requestSchedulerName])
}
if (this.timeouts[requestSchedulerName] !== null) {
window.clearTimeout(this.timeouts[requestSchedulerName]);
window.clearTimeout(this.timeouts[requestSchedulerName])
}
});
})
}
getStats() {
getStats () {
this.requestService.getStats().subscribe(
stats => this.stats = stats,
err => this.notificationsService.error('Error', err.text)
);
)
}
private runIntervals() {
private runIntervals () {
Object.keys(this.intervals).forEach(requestSchedulerName => {
this.intervals[requestSchedulerName] = window.setInterval(() => {
const stats = this.stats[requestSchedulerName];
const stats = this.stats[requestSchedulerName]
stats.remainingMilliSeconds -= 1000;
stats.remainingMilliSeconds -= 1000
if (stats.remainingMilliSeconds <= 0) {
this.timeouts[requestSchedulerName] = window.setTimeout(() => this.getStats(), stats.remainingMilliSeconds + 100);
this.timeouts[requestSchedulerName] = window.setTimeout(() => this.getStats(), stats.remainingMilliSeconds + 100)
}
}, 1000);
});
}, 1000)
})
}
}

View File

@ -1,8 +1,7 @@
import { Component } from '@angular/core';
import { Component } from '@angular/core'
@Component({
template: '<router-outlet></router-outlet>'
template: '<router-outlet></router-outlet>'
})
export class RequestsComponent {
}

View File

@ -1,27 +1,27 @@
import { Routes } from '@angular/router';
import { Routes } from '@angular/router'
import { RequestsComponent } from './requests.component';
import { RequestStatsComponent } from './request-stats';
import { RequestsComponent } from './requests.component'
import { RequestStatsComponent } from './request-stats'
export const RequestsRoutes: Routes = [
{
path: 'requests',
component: RequestsComponent,
children: [
{
path: '',
redirectTo: 'stats',
pathMatch: 'full'
},
{
path: 'stats',
component: RequestStatsComponent,
data: {
meta: {
title: 'Request stats'
}
path: 'requests',
component: RequestsComponent,
children: [
{
path: '',
redirectTo: 'stats',
pathMatch: 'full'
},
{
path: 'stats',
component: RequestStatsComponent,
data: {
meta: {
title: 'Request stats'
}
}
]
}
];
}
]
}
]

View File

@ -1,2 +1,2 @@
export * from './request-stats.model';
export * from './request.service';
export * from './request-stats.model'
export * from './request.service'

View File

@ -1,35 +1,35 @@
export interface Request {
request: any;
to: any;
request: any
to: any
}
export class RequestStats {
requestsLimitPods: number;
requestsLimitPerPod: number;
milliSecondsInterval: number;
remainingMilliSeconds: number;
totalRequests: number;
requestsLimitPods: number
requestsLimitPerPod: number
milliSecondsInterval: number
remainingMilliSeconds: number
totalRequests: number
constructor(hash: {
constructor (hash: {
requestsLimitPods: number,
requestsLimitPerPod: number,
milliSecondsInterval: number,
remainingMilliSeconds: number,
totalRequests: number;
totalRequests: number
}) {
this.requestsLimitPods = hash.requestsLimitPods;
this.requestsLimitPerPod = hash.requestsLimitPerPod;
this.milliSecondsInterval = hash.milliSecondsInterval;
this.remainingMilliSeconds = hash.remainingMilliSeconds;
this.totalRequests = hash.totalRequests;
this.requestsLimitPods = hash.requestsLimitPods
this.requestsLimitPerPod = hash.requestsLimitPerPod
this.milliSecondsInterval = hash.milliSecondsInterval
this.remainingMilliSeconds = hash.remainingMilliSeconds
this.totalRequests = hash.totalRequests
}
get remainingSeconds() {
return Math.floor(this.remainingMilliSeconds / 1000);
get remainingSeconds () {
return Math.floor(this.remainingMilliSeconds / 1000)
}
get secondsInterval() {
return Math.floor(this.milliSecondsInterval / 1000);
get secondsInterva () {
return Math.floor(this.milliSecondsInterval / 1000)
}
}

View File

@ -1,34 +1,34 @@
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import { Injectable } from '@angular/core'
import { Observable } from 'rxjs/Observable'
import 'rxjs/add/operator/catch'
import 'rxjs/add/operator/map'
import { RequestStats } from './request-stats.model';
import { AuthHttp, RestExtractor } from '../../../shared';
import { RequestStats } from './request-stats.model'
import { AuthHttp, RestExtractor } from '../../../shared'
@Injectable()
export class RequestService {
private static BASE_REQUEST_URL = API_URL + '/api/v1/requests/';
private static BASE_REQUEST_URL = API_URL + '/api/v1/requests/'
constructor (
private authHttp: AuthHttp,
private restExtractor: RestExtractor
) {}
getStats(): Observable<{ [ id: string ]: RequestStats }> {
getStats (): Observable<{ [ id: string ]: RequestStats }> {
return this.authHttp.get(RequestService.BASE_REQUEST_URL + 'stats')
.map(this.restExtractor.extractDataGet)
.map(this.buildRequestObjects)
.catch((res) => this.restExtractor.handleError(res));
.catch((res) => this.restExtractor.handleError(res))
}
private buildRequestObjects(data: any) {
const requestSchedulers = {};
private buildRequestObjects (data: any) {
const requestSchedulers = {}
Object.keys(data).forEach(requestSchedulerName => {
requestSchedulers[requestSchedulerName] = new RequestStats(data[requestSchedulerName]);
});
requestSchedulers[requestSchedulerName] = new RequestStats(data[requestSchedulerName])
})
return requestSchedulers;
return requestSchedulers
}
}

View File

@ -1,5 +1,5 @@
export * from './shared';
export * from './user-add';
export * from './user-list';
export * from './users.component';
export * from './users.routes';
export * from './shared'
export * from './user-add'
export * from './user-list'
export * from './users.component'
export * from './users.routes'

View File

@ -1 +1 @@
export * from './user.service';
export * from './user.service'

View File

@ -1,35 +1,35 @@
import { Injectable } from '@angular/core';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import { Injectable } from '@angular/core'
import 'rxjs/add/operator/catch'
import 'rxjs/add/operator/map'
import { AuthHttp, RestExtractor, RestDataSource, User } from '../../../shared';
import { AuthHttp, RestExtractor, RestDataSource, User } from '../../../shared'
@Injectable()
export class UserService {
private static BASE_USERS_URL = API_URL + '/api/v1/users/';
private static BASE_USERS_URL = API_URL + '/api/v1/users/'
constructor(
constructor (
private authHttp: AuthHttp,
private restExtractor: RestExtractor
) {}
addUser(username: string, password: string, email: string) {
addUser (username: string, password: string, email: string) {
const body = {
username,
email,
password
};
}
return this.authHttp.post(UserService.BASE_USERS_URL, body)
.map(this.restExtractor.extractDataBool)
.catch(this.restExtractor.handleError);
.catch(this.restExtractor.handleError)
}
getDataSource() {
return new RestDataSource(this.authHttp, UserService.BASE_USERS_URL);
getDataSource () {
return new RestDataSource(this.authHttp, UserService.BASE_USERS_URL)
}
removeUser(user: User) {
return this.authHttp.delete(UserService.BASE_USERS_URL + user.id);
removeUser (user: User) {
return this.authHttp.delete(UserService.BASE_USERS_URL + user.id)
}
}

View File

@ -1 +1 @@
export * from './user-add.component';
export * from './user-add.component'

View File

@ -1,71 +1,71 @@
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { Router } from '@angular/router';
import { Component, OnInit } from '@angular/core'
import { FormBuilder, FormGroup } from '@angular/forms'
import { Router } from '@angular/router'
import { NotificationsService } from 'angular2-notifications';
import { NotificationsService } from 'angular2-notifications'
import { UserService } from '../shared';
import { UserService } from '../shared'
import {
FormReactive,
USER_USERNAME,
USER_EMAIL,
USER_PASSWORD
} from '../../../shared';
} from '../../../shared'
@Component({
selector: 'my-user-add',
templateUrl: './user-add.component.html'
})
export class UserAddComponent extends FormReactive implements OnInit {
error: string = null;
error: string = null
form: FormGroup;
form: FormGroup
formErrors = {
'username': '',
'email': '',
'password': ''
};
}
validationMessages = {
'username': USER_USERNAME.MESSAGES,
'email': USER_EMAIL.MESSAGES,
'password': USER_PASSWORD.MESSAGES,
};
'password': USER_PASSWORD.MESSAGES
}
constructor(
constructor (
private formBuilder: FormBuilder,
private router: Router,
private notificationsService: NotificationsService,
private userService: UserService
) {
super();
super()
}
buildForm() {
buildForm () {
this.form = this.formBuilder.group({
username: [ '', USER_USERNAME.VALIDATORS ],
email: [ '', USER_EMAIL.VALIDATORS ],
password: [ '', USER_PASSWORD.VALIDATORS ],
});
password: [ '', USER_PASSWORD.VALIDATORS ]
})
this.form.valueChanges.subscribe(data => this.onValueChanged(data));
this.form.valueChanges.subscribe(data => this.onValueChanged(data))
}
ngOnInit() {
this.buildForm();
ngOnInit () {
this.buildForm()
}
addUser() {
this.error = null;
addUser () {
this.error = null
const { username, password, email } = this.form.value;
const { username, password, email } = this.form.value
this.userService.addUser(username, password, email).subscribe(
() => {
this.notificationsService.success('Success', `User ${username} created.`);
this.router.navigate([ '/admin/users/list' ]);
this.notificationsService.success('Success', `User ${username} created.`)
this.router.navigate([ '/admin/users/list' ])
},
err => this.error = err.text
);
)
}
}

View File

@ -1 +1 @@
export * from './user-list.component';
export * from './user-list.component'

View File

@ -1,10 +1,10 @@
import { Component } from '@angular/core';
import { Component } from '@angular/core'
import { NotificationsService } from 'angular2-notifications';
import { NotificationsService } from 'angular2-notifications'
import { ConfirmService } from '../../../core';
import { User, Utils } from '../../../shared';
import { UserService } from '../shared';
import { ConfirmService } from '../../../core'
import { User, Utils } from '../../../shared'
import { UserService } from '../shared'
@Component({
selector: 'my-user-list',
@ -12,7 +12,7 @@ import { UserService } from '../shared';
styleUrls: [ './user-list.component.scss' ]
})
export class UserListComponent {
usersSource = null;
usersSource = null
tableSettings = {
mode: 'external',
attr: {
@ -52,37 +52,37 @@ export class UserListComponent {
valuePrepareFunction: Utils.dateToHuman
}
}
};
}
constructor(
constructor (
private notificationsService: NotificationsService,
private confirmService: ConfirmService,
private userService: UserService
) {
this.usersSource = this.userService.getDataSource();
this.usersSource = this.userService.getDataSource()
}
removeUser({ data }) {
const user: User = data;
removeUser ({ data }) {
const user: User = data
if (user.username === 'root') {
this.notificationsService.error('Error', 'You cannot delete root.');
return;
this.notificationsService.error('Error', 'You cannot delete root.')
return
}
this.confirmService.confirm('Do you really want to delete this user?', 'Delete').subscribe(
res => {
if (res === false) return;
if (res === false) return
this.userService.removeUser(user).subscribe(
() => {
this.notificationsService.success('Success', `User ${user.username} deleted.`);
this.usersSource.refresh();
this.notificationsService.success('Success', `User ${user.username} deleted.`)
this.usersSource.refresh()
},
err => this.notificationsService.error('Error', err.text)
);
)
}
);
)
}
}

View File

@ -1,8 +1,7 @@
import { Component } from '@angular/core';
import { Component } from '@angular/core'
@Component({
template: '<router-outlet></router-outlet>'
template: '<router-outlet></router-outlet>'
})
export class UsersComponent {
}

View File

@ -1,8 +1,8 @@
import { Routes } from '@angular/router';
import { Routes } from '@angular/router'
import { UsersComponent } from './users.component';
import { UserAddComponent } from './user-add';
import { UserListComponent } from './user-list';
import { UsersComponent } from './users.component'
import { UserAddComponent } from './user-add'
import { UserListComponent } from './user-list'
export const UsersRoutes: Routes = [
{
@ -34,4 +34,4 @@ export const UsersRoutes: Routes = [
}
]
}
];
]

View File

@ -1,3 +1,3 @@
export * from './video-abuse-list';
export * from './video-abuses.component';
export * from './video-abuses.routes';
export * from './video-abuse-list'
export * from './video-abuses.component'
export * from './video-abuses.routes'

View File

@ -1 +1 @@
export * from './video-abuse-list.component';
export * from './video-abuse-list.component'

View File

@ -1,15 +1,15 @@
import { Component } from '@angular/core';
import { Component } from '@angular/core'
import { NotificationsService } from 'angular2-notifications';
import { NotificationsService } from 'angular2-notifications'
import { Utils, VideoAbuseService, VideoAbuse } from '../../../shared';
import { Utils, VideoAbuseService, VideoAbuse } from '../../../shared'
@Component({
selector: 'my-video-abuse-list',
templateUrl: './video-abuse-list.component.html'
selector: 'my-video-abuse-list',
templateUrl: './video-abuse-list.component.html'
})
export class VideoAbuseListComponent {
videoAbusesSource = null;
videoAbusesSource = null
tableSettings = {
mode: 'external',
attr: {
@ -54,18 +54,18 @@ export class VideoAbuseListComponent {
valuePrepareFunction: Utils.dateToHuman
}
}
};
}
constructor(
constructor (
private notificationsService: NotificationsService,
private videoAbuseService: VideoAbuseService
) {
this.videoAbusesSource = this.videoAbuseService.getDataSource();
}
this.videoAbusesSource = this.videoAbuseService.getDataSource()
}
buildVideoLink(videoId: string) {
buildVideoLink (videoId: string) {
// TODO: transform to routerLink
// https://github.com/akveo/ng2-smart-table/issues/57
return `<a href="/videos/${videoId}" title="Go to the video">${videoId}</a>`;
return `<a href="/videos/${videoId}" title="Go to the video">${videoId}</a>`
}
}

View File

@ -1,4 +1,4 @@
import { Component } from '@angular/core';
import { Component } from '@angular/core'
@Component({
template: '<router-outlet></router-outlet>'

View File

@ -1,7 +1,7 @@
import { Routes } from '@angular/router';
import { Routes } from '@angular/router'
import { VideoAbusesComponent } from './video-abuses.component';
import { VideoAbuseListComponent } from './video-abuse-list';
import { VideoAbusesComponent } from './video-abuses.component'
import { VideoAbuseListComponent } from './video-abuse-list'
export const VideoAbusesRoutes: Routes = [
{
@ -25,4 +25,4 @@ export const VideoAbusesRoutes: Routes = [
}
]
}
];
]

View File

@ -1,10 +1,10 @@
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { Router } from '@angular/router';
import { Component, OnInit } from '@angular/core'
import { FormBuilder, FormGroup } from '@angular/forms'
import { Router } from '@angular/router'
import { NotificationsService } from 'angular2-notifications';
import { NotificationsService } from 'angular2-notifications'
import { FormReactive, UserService, USER_PASSWORD } from '../../shared';
import { FormReactive, UserService, USER_PASSWORD } from '../../shared'
@Component({
selector: 'my-account-change-password',
@ -12,55 +12,55 @@ import { FormReactive, UserService, USER_PASSWORD } from '../../shared';
})
export class AccountChangePasswordComponent extends FormReactive implements OnInit {
error: string = null;
error: string = null
form: FormGroup;
form: FormGroup
formErrors = {
'new-password': '',
'new-confirmed-password': ''
};
}
validationMessages = {
'new-password': USER_PASSWORD.MESSAGES,
'new-confirmed-password': USER_PASSWORD.MESSAGES
};
}
constructor(
constructor (
private formBuilder: FormBuilder,
private router: Router,
private notificationsService: NotificationsService,
private userService: UserService
) {
super();
super()
}
buildForm() {
buildForm () {
this.form = this.formBuilder.group({
'new-password': [ '', USER_PASSWORD.VALIDATORS ],
'new-confirmed-password': [ '', USER_PASSWORD.VALIDATORS ],
});
'new-confirmed-password': [ '', USER_PASSWORD.VALIDATORS ]
})
this.form.valueChanges.subscribe(data => this.onValueChanged(data));
this.form.valueChanges.subscribe(data => this.onValueChanged(data))
}
ngOnInit() {
this.buildForm();
ngOnInit () {
this.buildForm()
}
changePassword() {
const newPassword = this.form.value['new-password'];
const newConfirmedPassword = this.form.value['new-confirmed-password'];
changePassword () {
const newPassword = this.form.value['new-password']
const newConfirmedPassword = this.form.value['new-confirmed-password']
this.error = null;
this.error = null
if (newPassword !== newConfirmedPassword) {
this.error = 'The new password and the confirmed password do not correspond.';
return;
this.error = 'The new password and the confirmed password do not correspond.'
return
}
this.userService.changePassword(newPassword).subscribe(
() => this.notificationsService.success('Success', 'Password updated.'),
err => this.error = err
);
)
}
}

View File

@ -1 +1 @@
export * from './account-change-password.component';
export * from './account-change-password.component'

View File

@ -1,16 +1,16 @@
import { Component, OnInit, Input } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { Router } from '@angular/router';
import { Component, OnInit, Input } from '@angular/core'
import { FormBuilder, FormGroup } from '@angular/forms'
import { Router } from '@angular/router'
import { NotificationsService } from 'angular2-notifications';
import { NotificationsService } from 'angular2-notifications'
import { AuthService } from '../../core';
import { AuthService } from '../../core'
import {
FormReactive,
User,
UserService,
USER_PASSWORD
} from '../../shared';
} from '../../shared'
@Component({
selector: 'my-account-details',
@ -18,51 +18,51 @@ import {
})
export class AccountDetailsComponent extends FormReactive implements OnInit {
@Input() user: User = null;
@Input() user: User = null
error: string = null;
error: string = null
form: FormGroup;
formErrors = {};
validationMessages = {};
form: FormGroup
formErrors = {}
validationMessages = {}
constructor(
constructor (
private authService: AuthService,
private formBuilder: FormBuilder,
private router: Router,
private notificationsService: NotificationsService,
private userService: UserService
) {
super();
super()
}
buildForm() {
buildForm () {
this.form = this.formBuilder.group({
displayNSFW: [ this.user.displayNSFW ],
});
displayNSFW: [ this.user.displayNSFW ]
})
this.form.valueChanges.subscribe(data => this.onValueChanged(data));
this.form.valueChanges.subscribe(data => this.onValueChanged(data))
}
ngOnInit() {
this.buildForm();
ngOnInit () {
this.buildForm()
}
updateDetails() {
const displayNSFW = this.form.value['displayNSFW'];
updateDetails () {
const displayNSFW = this.form.value['displayNSFW']
const details = {
displayNSFW
};
}
this.error = null;
this.error = null
this.userService.updateDetails(details).subscribe(
() => {
this.notificationsService.success('Success', 'Informations updated.');
this.notificationsService.success('Success', 'Informations updated.')
this.authService.refreshUserInformations();
this.authService.refreshUserInformations()
},
err => this.error = err
);
)
}
}

View File

@ -1 +1 @@
export * from './account-details.component';
export * from './account-details.component'

View File

@ -1,7 +1,7 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { NgModule } from '@angular/core'
import { RouterModule, Routes } from '@angular/router'
import { AccountComponent } from './account.component';
import { AccountComponent } from './account.component'
const accountRoutes: Routes = [
{
@ -13,7 +13,7 @@ const accountRoutes: Routes = [
}
}
}
];
]
@NgModule({
imports: [ RouterModule.forChild(accountRoutes) ],

View File

@ -1,16 +1,16 @@
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { Router } from '@angular/router';
import { Component, OnInit } from '@angular/core'
import { FormBuilder, FormGroup } from '@angular/forms'
import { Router } from '@angular/router'
import { NotificationsService } from 'angular2-notifications';
import { NotificationsService } from 'angular2-notifications'
import { AuthService } from '../core';
import { AuthService } from '../core'
import {
FormReactive,
User,
UserService,
USER_PASSWORD
} from '../shared';
} from '../shared'
@Component({
selector: 'my-account',
@ -18,11 +18,11 @@ import {
styleUrls: [ './account.component.scss' ]
})
export class AccountComponent implements OnInit {
user: User = null;
user: User = null
constructor(private authService: AuthService) {}
constructor (private authService: AuthService) {}
ngOnInit() {
this.user = this.authService.getUser();
ngOnInit () {
this.user = this.authService.getUser()
}
}

View File

@ -1,11 +1,11 @@
import { NgModule } from '@angular/core';
import { NgModule } from '@angular/core'
import { AccountRoutingModule } from './account-routing.module';
import { AccountComponent } from './account.component';
import { AccountChangePasswordComponent } from './account-change-password';
import { AccountDetailsComponent } from './account-details';
import { AccountService } from './account.service';
import { SharedModule } from '../shared';
import { AccountRoutingModule } from './account-routing.module'
import { AccountComponent } from './account.component'
import { AccountChangePasswordComponent } from './account-change-password'
import { AccountDetailsComponent } from './account-details'
import { AccountService } from './account.service'
import { SharedModule } from '../shared'
@NgModule({
imports: [

View File

@ -1,3 +1,3 @@
export * from './account-routing.module';
export * from './account.component';
export * from './account.module';
export * from './account-routing.module'
export * from './account.component'
export * from './account.module'

View File

@ -1,5 +1,5 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { NgModule } from '@angular/core'
import { Routes, RouterModule } from '@angular/router'
const routes: Routes = [
{
@ -11,11 +11,10 @@ const routes: Routes = [
path: 'admin',
loadChildren: './+admin#AdminModule'
}
];
]
@NgModule({
imports: [ RouterModule.forRoot(routes) ],
exports: [ RouterModule ]
})
export class AppRoutingModule {}

View File

@ -1,9 +1,9 @@
import { Component, OnInit, ViewContainerRef } from '@angular/core';
import { Router } from '@angular/router';
import { Component, OnInit, ViewContainerRef } from '@angular/core'
import { Router } from '@angular/router'
import { AuthService, ConfigService } from './core';
import { VideoService } from './videos';
import { UserService } from './shared';
import { AuthService, ConfigService } from './core'
import { VideoService } from './videos'
import { UserService } from './shared'
@Component({
selector: 'my-app',
@ -22,11 +22,11 @@ export class AppComponent implements OnInit {
preventDuplicates: false,
preventLastDuplicates: 'visible',
rtl: false
};
}
isMenuDisplayed = true;
isMenuDisplayed = true
constructor(
constructor (
private router: Router,
private authService: AuthService,
private configService: ConfigService,
@ -35,46 +35,46 @@ export class AppComponent implements OnInit {
viewContainerRef: ViewContainerRef
) {}
ngOnInit() {
ngOnInit () {
if (this.authService.isLoggedIn()) {
// The service will automatically redirect to the login page if the token is not valid anymore
this.userService.checkTokenValidity();
this.userService.checkTokenValidity()
}
this.configService.loadConfig();
this.videoService.loadVideoCategories();
this.videoService.loadVideoLicences();
this.videoService.loadVideoLanguages();
this.configService.loadConfig()
this.videoService.loadVideoCategories()
this.videoService.loadVideoLicences()
this.videoService.loadVideoLanguages()
// Do not display menu on small screens
if (window.innerWidth < 600) {
this.isMenuDisplayed = false;
this.isMenuDisplayed = false
}
}
isInAdmin() {
return this.router.url.indexOf('/admin/') !== -1;
isInAdmin () {
return this.router.url.indexOf('/admin/') !== -1
}
toggleMenu() {
this.isMenuDisplayed = !this.isMenuDisplayed;
toggleMenu () {
this.isMenuDisplayed = !this.isMenuDisplayed
}
getMainColClasses() {
getMainColClasses () {
const colSizes = {
md: 10,
sm: 9,
xs: 9
};
}
// Take all width is the menu is not displayed
if (this.isMenuDisplayed === false) {
Object.keys(colSizes).forEach(col => colSizes[col] = 12);
Object.keys(colSizes).forEach(col => colSizes[col] = 12)
}
const classes = [ 'main-col' ];
Object.keys(colSizes).forEach(col => classes.push(`col-${col}-${colSizes[col]}`));
const classes = [ 'main-col' ]
Object.keys(colSizes).forEach(col => classes.push(`col-${col}-${colSizes[col]}`))
return classes;
return classes
}
}

View File

@ -1,29 +1,29 @@
import { ApplicationRef, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ApplicationRef, NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import {
removeNgStyles,
createNewHosts,
createInputTransfer
} from '@angularclass/hmr';
} from '@angularclass/hmr'
import { MetaModule, MetaLoader, MetaStaticLoader, PageTitlePositioning } from '@nglibs/meta';
import { MetaModule, MetaLoader, MetaStaticLoader, PageTitlePositioning } from '@nglibs/meta'
// TODO: remove, we need this to avoid error in ng2-smart-table
import 'rxjs/add/operator/toPromise';
import 'bootstrap-loader';
import 'rxjs/add/operator/toPromise'
import 'bootstrap-loader'
import { ENV_PROVIDERS } from './environment';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { AppState, InternalStateType } from './app.service';
import { ENV_PROVIDERS } from './environment'
import { AppRoutingModule } from './app-routing.module'
import { AppComponent } from './app.component'
import { AppState, InternalStateType } from './app.service'
import { AccountModule } from './account';
import { CoreModule } from './core';
import { LoginModule } from './login';
import { SignupModule } from './signup';
import { SharedModule } from './shared';
import { VideosModule } from './videos';
import { AccountModule } from './account'
import { CoreModule } from './core'
import { LoginModule } from './login'
import { SignupModule } from './signup'
import { SharedModule } from './shared'
import { VideosModule } from './videos'
export function metaFactory(): MetaLoader {
export function metaFactory (): MetaLoader {
return new MetaStaticLoader({
pageTitlePositioning: PageTitlePositioning.PrependPageTitle,
pageTitleSeparator: ' - ',
@ -32,19 +32,19 @@ export function metaFactory(): MetaLoader {
title: 'PeerTube',
description: 'PeerTube, a decentralized video streaming platform using P2P (BitTorrent) directly in the web browser'
}
});
})
}
type StoreType = {
state: InternalStateType,
restoreInputValues: () => void,
disposeOldHosts: () => void
};
}
// Application wide providers
const APP_PROVIDERS = [
AppState
];
]
@NgModule({
bootstrap: [ AppComponent ],
@ -77,59 +77,59 @@ const APP_PROVIDERS = [
]
})
export class AppModule {
constructor(
constructor (
public appRef: ApplicationRef,
public appState: AppState
) {}
public hmrOnInit(store: StoreType) {
public hmrOnInit (store: StoreType) {
if (!store || !store.state) {
return;
return
}
console.log('HMR store', JSON.stringify(store, null, 2));
console.log('HMR store', JSON.stringify(store, null, 2))
/**
* Set state
*/
this.appState._state = store.state;
this.appState._state = store.state
/**
* Set input values
*/
if ('restoreInputValues' in store) {
let restoreInputValues = store.restoreInputValues;
setTimeout(restoreInputValues);
let restoreInputValues = store.restoreInputValues
setTimeout(restoreInputValues)
}
this.appRef.tick();
delete store.state;
delete store.restoreInputValues;
this.appRef.tick()
delete store.state
delete store.restoreInputValues
}
public hmrOnDestroy(store: StoreType) {
const cmpLocation = this.appRef.components.map((cmp) => cmp.location.nativeElement);
public hmrOnDestroy (store: StoreType) {
const cmpLocation = this.appRef.components.map((cmp) => cmp.location.nativeElement)
/**
* Save state
*/
const state = this.appState._state;
store.state = state;
const state = this.appState._state
store.state = state
/**
* Recreate root elements
*/
store.disposeOldHosts = createNewHosts(cmpLocation);
store.disposeOldHosts = createNewHosts(cmpLocation)
/**
* Save input values
*/
store.restoreInputValues = createInputTransfer();
store.restoreInputValues = createInputTransfer()
/**
* Remove styles
*/
removeNgStyles();
removeNgStyles()
}
public hmrAfterDestroy(store: StoreType) {
public hmrAfterDestroy (store: StoreType) {
/**
* Display new elements
*/
store.disposeOldHosts();
delete store.disposeOldHosts;
store.disposeOldHosts ()
delete store.disposeOldHosts
}
}

View File

@ -1,12 +1,14 @@
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
/* tslint:disable */
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'
import { Injectable } from '@angular/core'
import { Observable } from 'rxjs/Observable'
import 'rxjs/add/observable/of'
@Injectable()
export class DataResolver implements Resolve<any> {
public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
return Observable.of({ res: 'I am data'});
return Observable.of({ res: 'I am data'})
}
}
@ -15,4 +17,4 @@ export class DataResolver implements Resolve<any> {
*/
export const APP_RESOLVER_PROVIDERS = [
DataResolver
];
]

View File

@ -1,46 +1,48 @@
import { Injectable } from '@angular/core';
/* tslint:disable */
import { Injectable } from '@angular/core'
export type InternalStateType = {
[key: string]: any
};
}
@Injectable()
export class AppState {
public _state: InternalStateType = { };
public _state: InternalStateType = { }
/**
* Already return a clone of the current state.
*/
public get state() {
return this._state = this._clone(this._state);
return this._state = this._clone(this._state)
}
/**
* Never allow mutation
*/
public set state(value) {
throw new Error('do not mutate the `.state` directly');
throw new Error('do not mutate the `.state` directly')
}
public get(prop?: any) {
/**
* Use our state getter for the clone.
*/
const state = this.state;
return state.hasOwnProperty(prop) ? state[prop] : state;
const state = this.state
return state.hasOwnProperty(prop) ? state[prop] : state
}
public set(prop: string, value: any) {
/**
* Internally mutate our state.
*/
return this._state[prop] = value;
return this._state[prop] = value
}
private _clone(object: InternalStateType) {
/**
* Simple object clone.
*/
return JSON.parse(JSON.stringify( object ));
return JSON.parse(JSON.stringify( object ))
}
}

View File

@ -1,6 +1,66 @@
// Do not use the barrel (dependency loop)
import { UserRole } from '../../../../../shared/models/user.model'
import { User } from '../../shared/users/user.model';
import { User } from '../../shared/users/user.model'
export type TokenOptions = {
accessToken: string
refreshToken: string
tokenType: string
}
// Private class only used by User
class Tokens {
private static KEYS = {
ACCESS_TOKEN: 'access_token',
REFRESH_TOKEN: 'refresh_token',
TOKEN_TYPE: 'token_type'
}
accessToken: string
refreshToken: string
tokenType: string
static load () {
const accessTokenLocalStorage = localStorage.getItem(this.KEYS.ACCESS_TOKEN)
const refreshTokenLocalStorage = localStorage.getItem(this.KEYS.REFRESH_TOKEN)
const tokenTypeLocalStorage = localStorage.getItem(this.KEYS.TOKEN_TYPE)
if (accessTokenLocalStorage && refreshTokenLocalStorage && tokenTypeLocalStorage) {
return new Tokens({
accessToken: accessTokenLocalStorage,
refreshToken: refreshTokenLocalStorage,
tokenType: tokenTypeLocalStorage
})
}
return null
}
static flush () {
localStorage.removeItem(this.KEYS.ACCESS_TOKEN)
localStorage.removeItem(this.KEYS.REFRESH_TOKEN)
localStorage.removeItem(this.KEYS.TOKEN_TYPE)
}
constructor (hash?: TokenOptions) {
if (hash) {
this.accessToken = hash.accessToken
this.refreshToken = hash.refreshToken
if (hash.tokenType === 'bearer') {
this.tokenType = 'Bearer'
} else {
this.tokenType = hash.tokenType
}
}
}
save () {
localStorage.setItem(Tokens.KEYS.ACCESS_TOKEN, this.accessToken)
localStorage.setItem(Tokens.KEYS.REFRESH_TOKEN, this.refreshToken)
localStorage.setItem(Tokens.KEYS.TOKEN_TYPE, this.tokenType)
}
}
export class AuthUser extends User {
private static KEYS = {
@ -9,123 +69,69 @@ export class AuthUser extends User {
EMAIL: 'email',
USERNAME: 'username',
DISPLAY_NSFW: 'display_nsfw'
};
}
tokens: Tokens;
tokens: Tokens
static load() {
const usernameLocalStorage = localStorage.getItem(this.KEYS.USERNAME);
static load () {
const usernameLocalStorage = localStorage.getItem(this.KEYS.USERNAME)
if (usernameLocalStorage) {
return new AuthUser(
{
id: parseInt(localStorage.getItem(this.KEYS.ID)),
id: parseInt(localStorage.getItem(this.KEYS.ID), 10),
username: localStorage.getItem(this.KEYS.USERNAME),
email: localStorage.getItem(this.KEYS.EMAIL),
role: localStorage.getItem(this.KEYS.ROLE) as UserRole,
displayNSFW: localStorage.getItem(this.KEYS.DISPLAY_NSFW) === 'true'
},
Tokens.load()
);
)
}
return null;
return null
}
static flush() {
localStorage.removeItem(this.KEYS.USERNAME);
localStorage.removeItem(this.KEYS.ID);
localStorage.removeItem(this.KEYS.ROLE);
localStorage.removeItem(this.KEYS.DISPLAY_NSFW);
Tokens.flush();
static flush () {
localStorage.removeItem(this.KEYS.USERNAME)
localStorage.removeItem(this.KEYS.ID)
localStorage.removeItem(this.KEYS.ROLE)
localStorage.removeItem(this.KEYS.DISPLAY_NSFW)
Tokens.flush()
}
constructor(userHash: {
constructor (userHash: {
id: number,
username: string,
role: UserRole,
email: string,
displayNSFW: boolean
}, hashTokens: any) {
super(userHash);
this.tokens = new Tokens(hashTokens);
}, hashTokens: TokenOptions) {
super(userHash)
this.tokens = new Tokens(hashTokens)
}
getAccessToken() {
return this.tokens.access_token;
getAccessToken () {
return this.tokens.accessToken
}
getRefreshToken() {
return this.tokens.refresh_token;
getRefreshToken () {
return this.tokens.refreshToken
}
getTokenType() {
return this.tokens.token_type;
getTokenType () {
return this.tokens.tokenType
}
refreshTokens(access_token: string, refresh_token: string) {
this.tokens.access_token = access_token;
this.tokens.refresh_token = refresh_token;
refreshTokens (accessToken: string, refreshToken: string) {
this.tokens.accessToken = accessToken
this.tokens.refreshToken = refreshToken
}
save() {
localStorage.setItem(AuthUser.KEYS.ID, this.id.toString());
localStorage.setItem(AuthUser.KEYS.USERNAME, this.username);
localStorage.setItem(AuthUser.KEYS.ROLE, this.role);
localStorage.setItem(AuthUser.KEYS.DISPLAY_NSFW, JSON.stringify(this.displayNSFW));
this.tokens.save();
}
}
// Private class only used by User
class Tokens {
private static KEYS = {
ACCESS_TOKEN: 'access_token',
REFRESH_TOKEN: 'refresh_token',
TOKEN_TYPE: 'token_type',
};
access_token: string;
refresh_token: string;
token_type: string;
static load() {
const accessTokenLocalStorage = localStorage.getItem(this.KEYS.ACCESS_TOKEN);
const refreshTokenLocalStorage = localStorage.getItem(this.KEYS.REFRESH_TOKEN);
const tokenTypeLocalStorage = localStorage.getItem(this.KEYS.TOKEN_TYPE);
if (accessTokenLocalStorage && refreshTokenLocalStorage && tokenTypeLocalStorage) {
return new Tokens({
access_token: accessTokenLocalStorage,
refresh_token: refreshTokenLocalStorage,
token_type: tokenTypeLocalStorage
});
}
return null;
}
static flush() {
localStorage.removeItem(this.KEYS.ACCESS_TOKEN);
localStorage.removeItem(this.KEYS.REFRESH_TOKEN);
localStorage.removeItem(this.KEYS.TOKEN_TYPE);
}
constructor(hash?: any) {
if (hash) {
this.access_token = hash.access_token;
this.refresh_token = hash.refresh_token;
if (hash.token_type === 'bearer') {
this.token_type = 'Bearer';
} else {
this.token_type = hash.token_type;
}
}
}
save() {
localStorage.setItem('access_token', this.access_token);
localStorage.setItem('refresh_token', this.refresh_token);
localStorage.setItem('token_type', this.token_type);
save () {
localStorage.setItem(AuthUser.KEYS.ID, this.id.toString())
localStorage.setItem(AuthUser.KEYS.USERNAME, this.username)
localStorage.setItem(AuthUser.KEYS.ROLE, this.role)
localStorage.setItem(AuthUser.KEYS.DISPLAY_NSFW, JSON.stringify(this.displayNSFW))
this.tokens.save()
}
}

View File

@ -1,40 +1,40 @@
import { Injectable } from '@angular/core';
import { Headers, Http, Response, URLSearchParams } from '@angular/http';
import { Router } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/observable/throw';
import { Injectable } from '@angular/core'
import { Headers, Http, Response, URLSearchParams } from '@angular/http'
import { Router } from '@angular/router'
import { Observable } from 'rxjs/Observable'
import { Subject } from 'rxjs/Subject'
import 'rxjs/add/operator/map'
import 'rxjs/add/operator/mergeMap'
import 'rxjs/add/observable/throw'
import { NotificationsService } from 'angular2-notifications';
import { NotificationsService } from 'angular2-notifications'
import { AuthStatus } from './auth-status.model';
import { AuthUser } from './auth-user.model';
import { AuthStatus } from './auth-status.model'
import { AuthUser } from './auth-user.model'
// Do not use the barrel (dependency loop)
import { RestExtractor } from '../../shared/rest';
import { RestExtractor } from '../../shared/rest'
@Injectable()
export class AuthService {
private static BASE_CLIENT_URL = API_URL + '/api/v1/clients/local';
private static BASE_TOKEN_URL = API_URL + '/api/v1/users/token';
private static BASE_USER_INFORMATIONS_URL = API_URL + '/api/v1/users/me';
private static BASE_CLIENT_URL = API_URL + '/api/v1/clients/local'
private static BASE_TOKEN_URL = API_URL + '/api/v1/users/token'
private static BASE_USER_INFORMATIONS_URL = API_URL + '/api/v1/users/me'
loginChangedSource: Observable<AuthStatus>;
loginChangedSource: Observable<AuthStatus>
private clientId: string;
private clientSecret: string;
private loginChanged: Subject<AuthStatus>;
private user: AuthUser = null;
private clientId: string
private clientSecret: string
private loginChanged: Subject<AuthStatus>
private user: AuthUser = null
constructor(
constructor (
private http: Http,
private notificationsService: NotificationsService,
private restExtractor: RestExtractor,
private router: Router
) {
this.loginChanged = new Subject<AuthStatus>();
this.loginChangedSource = this.loginChanged.asObservable();
this.loginChanged = new Subject<AuthStatus>()
this.loginChangedSource = this.loginChanged.asObservable()
// Fetch the client_id/client_secret
// FIXME: save in local storage?
@ -43,120 +43,120 @@ export class AuthService {
.catch((res) => this.restExtractor.handleError(res))
.subscribe(
result => {
this.clientId = result.client_id;
this.clientSecret = result.client_secret;
console.log('Client credentials loaded.');
this.clientId = result.client_id
this.clientSecret = result.client_secret
console.log('Client credentials loaded.')
},
error => {
let errorMessage = `Cannot retrieve OAuth Client credentials: ${error.text}. \n`;
errorMessage += 'Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.';
let errorMessage = `Cannot retrieve OAuth Client credentials: ${error.text}. \n`
errorMessage += 'Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.'
// We put a bigger timeout
// This is an important message
this.notificationsService.error('Error', errorMessage, { timeOut: 7000 });
this.notificationsService.error('Error', errorMessage, { timeOut: 7000 })
}
);
)
// Return null if there is nothing to load
this.user = AuthUser.load();
this.user = AuthUser.load()
}
getRefreshToken() {
if (this.user === null) return null;
getRefreshToken () {
if (this.user === null) return null
return this.user.getRefreshToken();
return this.user.getRefreshToken()
}
getRequestHeaderValue() {
return `${this.getTokenType()} ${this.getAccessToken()}`;
getRequestHeaderValue () {
return `${this.getTokenType()} ${this.getAccessToken()}`
}
getAccessToken() {
if (this.user === null) return null;
getAccessToken () {
if (this.user === null) return null
return this.user.getAccessToken();
return this.user.getAccessToken()
}
getTokenType() {
if (this.user === null) return null;
getTokenType () {
if (this.user === null) return null
return this.user.getTokenType();
return this.user.getTokenType()
}
getUser(): AuthUser {
return this.user;
getUser () {
return this.user
}
isAdmin() {
if (this.user === null) return false;
isAdmin () {
if (this.user === null) return false
return this.user.isAdmin();
return this.user.isAdmin()
}
isLoggedIn() {
isLoggedIn () {
if (this.getAccessToken()) {
return true;
return true
} else {
return false;
return false
}
}
login(username: string, password: string) {
let body = new URLSearchParams();
body.set('client_id', this.clientId);
body.set('client_secret', this.clientSecret);
body.set('response_type', 'code');
body.set('grant_type', 'password');
body.set('scope', 'upload');
body.set('username', username);
body.set('password', password);
login (username: string, password: string) {
let body = new URLSearchParams()
body.set('client_id', this.clientId)
body.set('client_secret', this.clientSecret)
body.set('response_type', 'code')
body.set('grant_type', 'password')
body.set('scope', 'upload')
body.set('username', username)
body.set('password', password)
let headers = new Headers();
headers.append('Content-Type', 'application/x-www-form-urlencoded');
let headers = new Headers()
headers.append('Content-Type', 'application/x-www-form-urlencoded')
let options = {
headers: headers
};
}
return this.http.post(AuthService.BASE_TOKEN_URL, body.toString(), options)
.map(this.restExtractor.extractDataGet)
.map(res => {
res.username = username;
return res;
res.username = username
return res
})
.flatMap(res => this.mergeUserInformations(res))
.map(res => this.handleLogin(res))
.catch((res) => this.restExtractor.handleError(res));
.catch((res) => this.restExtractor.handleError(res))
}
logout() {
logout () {
// TODO: make an HTTP request to revoke the tokens
this.user = null;
this.user = null
AuthUser.flush();
AuthUser.flush()
this.setStatus(AuthStatus.LoggedOut);
this.setStatus(AuthStatus.LoggedOut)
}
refreshAccessToken() {
console.log('Refreshing token...');
refreshAccessToken () {
console.log('Refreshing token...')
const refreshToken = this.getRefreshToken();
const refreshToken = this.getRefreshToken()
let body = new URLSearchParams();
body.set('refresh_token', refreshToken);
body.set('client_id', this.clientId);
body.set('client_secret', this.clientSecret);
body.set('response_type', 'code');
body.set('grant_type', 'refresh_token');
let body = new URLSearchParams()
body.set('refresh_token', refreshToken)
body.set('client_id', this.clientId)
body.set('client_secret', this.clientSecret)
body.set('response_type', 'code')
body.set('grant_type', 'refresh_token')
let headers = new Headers();
headers.append('Content-Type', 'application/x-www-form-urlencoded');
let headers = new Headers()
headers.append('Content-Type', 'application/x-www-form-urlencoded')
let options = {
headers: headers
};
}
return this.http.post(AuthService.BASE_TOKEN_URL, body.toString(), options)
.map(this.restExtractor.extractDataGet)
@ -164,41 +164,41 @@ export class AuthService {
.catch((res: Response) => {
// The refresh token is invalid?
if (res.status === 400 && res.json() && res.json().error === 'invalid_grant') {
console.error('Cannot refresh token -> logout...');
this.logout();
this.router.navigate(['/login']);
console.error('Cannot refresh token -> logout...')
this.logout()
this.router.navigate(['/login'])
return Observable.throw({
json: () => '',
text: () => 'You need to reconnect.'
});
})
}
return this.restExtractor.handleError(res);
});
return this.restExtractor.handleError(res)
})
}
refreshUserInformations() {
refreshUserInformations () {
const obj = {
access_token: this.user.getAccessToken()
};
}
this.mergeUserInformations(obj)
this.mergeUserInformations (obj)
.subscribe(
res => {
this.user.displayNSFW = res.displayNSFW;
this.user.role = res.role;
this.user.displayNSFW = res.displayNSFW
this.user.role = res.role
this.user.save();
this.user.save()
}
);
)
}
private mergeUserInformations(obj: { access_token: string }) {
private mergeUserInformations (obj: { access_token: string }) {
// Do not call authHttp here to avoid circular dependencies headaches
const headers = new Headers();
headers.set('Authorization', `Bearer ${obj.access_token}`);
const headers = new Headers()
headers.set('Authorization', `Bearer ${obj.access_token}`)
return this.http.get(AuthService.BASE_USER_INFORMATIONS_URL, { headers })
.map(res => res.json())
@ -207,38 +207,38 @@ export class AuthService {
id: res.id,
role: res.role,
displayNSFW: res.displayNSFW
};
}
return Object.assign(obj, newProperties);
return Object.assign(obj, newProperties)
}
);
)
}
private handleLogin (obj: any) {
const id = obj.id;
const username = obj.username;
const role = obj.role;
const email = obj.email;
const displayNSFW = obj.displayNSFW;
const id = obj.id
const username = obj.username
const role = obj.role
const email = obj.email
const displayNSFW = obj.displayNSFW
const hashTokens = {
access_token: obj.access_token,
token_type: obj.token_type,
refresh_token: obj.refresh_token
};
accessToken: obj.access_token,
tokenType: obj.token_type,
refreshToken: obj.refresh_token
}
this.user = new AuthUser({ id, username, role, displayNSFW, email }, hashTokens);
this.user.save();
this.user = new AuthUser({ id, username, role, displayNSFW, email }, hashTokens)
this.user.save()
this.setStatus(AuthStatus.LoggedIn);
this.setStatus(AuthStatus.LoggedIn)
}
private handleRefreshToken (obj: any) {
this.user.refreshTokens(obj.access_token, obj.refresh_token);
this.user.save();
this.user.refreshTokens(obj.access_token, obj.refresh_token)
this.user.save()
}
private setStatus(status: AuthStatus) {
this.loginChanged.next(status);
private setStatus (status: AuthStatus) {
this.loginChanged.next(status)
}
}

View File

@ -1,3 +1,3 @@
export * from './auth-status.model';
export * from './auth-user.model';
export * from './auth-status.model'
export * from './auth-user.model'
export * from './auth.service'

View File

@ -1,11 +1,11 @@
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Injectable } from '@angular/core'
import { Http } from '@angular/http'
import { RestExtractor } from '../../shared/rest';
import { RestExtractor } from '../../shared/rest'
@Injectable()
export class ConfigService {
private static BASE_CONFIG_URL = API_URL + '/api/v1/config/';
private static BASE_CONFIG_URL = API_URL + '/api/v1/config/'
private config: {
signup: {
@ -15,22 +15,22 @@ export class ConfigService {
signup: {
enabled: false
}
};
}
constructor(
constructor (
private http: Http,
private restExtractor: RestExtractor,
private restExtractor: RestExtractor
) {}
loadConfig() {
loadConfig () {
this.http.get(ConfigService.BASE_CONFIG_URL)
.map(this.restExtractor.extractDataGet)
.subscribe(data => {
this.config = data;
});
this.config = data
})
}
getConfig() {
return this.config;
getConfig () {
return this.config
}
}

View File

@ -1 +1 @@
export * from './config.service';
export * from './config.service'

View File

@ -1,12 +1,12 @@
import { Component, HostListener, OnInit, ViewChild } from '@angular/core';
import { Component, HostListener, OnInit, ViewChild } from '@angular/core'
import { ModalDirective } from 'ngx-bootstrap/modal';
import { ModalDirective } from 'ngx-bootstrap/modal'
import { ConfirmService } from './confirm.service';
import { ConfirmService } from './confirm.service'
export interface ConfigChangedEvent {
columns: { [id: string]: { isDisplayed: boolean }; };
config: { resultsPerPage: number };
columns: { [id: string]: { isDisplayed: boolean } }
config: { resultsPerPage: number }
}
@Component({
@ -14,48 +14,48 @@ export interface ConfigChangedEvent {
templateUrl: './confirm.component.html'
})
export class ConfirmComponent implements OnInit {
@ViewChild('confirmModal') confirmModal: ModalDirective;
@ViewChild('confirmModal') confirmModal: ModalDirective
title = '';
message = '';
title = ''
message = ''
constructor (private confirmService: ConfirmService) {
// Empty
}
ngOnInit() {
ngOnInit () {
this.confirmModal.config = {
backdrop: 'static',
keyboard: false
};
}
this.confirmService.showConfirm.subscribe(
({ title, message }) => {
this.title = title;
this.message = message;
this.title = title
this.message = message
this.showModal();
this.showModal()
}
);
)
}
@HostListener('keydown.enter')
confirm() {
this.confirmService.confirmResponse.next(true);
this.hideModal();
confirm () {
this.confirmService.confirmResponse.next(true)
this.hideModal()
}
@HostListener('keydown.esc')
abort() {
this.confirmService.confirmResponse.next(false);
this.hideModal();
abort () {
this.confirmService.confirmResponse.next(false)
this.hideModal()
}
showModal() {
this.confirmModal.show();
showModal () {
this.confirmModal.show()
}
hideModal() {
this.confirmModal.hide();
hideModal () {
this.confirmModal.hide()
}
}

View File

@ -1,15 +1,15 @@
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import 'rxjs/add/operator/first';
import { Injectable } from '@angular/core'
import { Subject } from 'rxjs/Subject'
import 'rxjs/add/operator/first'
@Injectable()
export class ConfirmService {
showConfirm = new Subject<{ title, message }>();
confirmResponse = new Subject<boolean>();
showConfirm = new Subject<{ title, message }>()
confirmResponse = new Subject<boolean>()
confirm(message = '', title = '') {
this.showConfirm.next({ title, message });
confirm (message = '', title = '') {
this.showConfirm.next({ title, message })
return this.confirmResponse.asObservable().first();
return this.confirmResponse.asObservable().first()
}
}

View File

@ -1,2 +1,2 @@
export * from './confirm.component';
export * from './confirm.service';
export * from './confirm.component'
export * from './confirm.service'

View File

@ -1,16 +1,16 @@
import { NgModule, Optional, SkipSelf } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpModule } from '@angular/http';
import { RouterModule } from '@angular/router';
import { NgModule, Optional, SkipSelf } from '@angular/core'
import { CommonModule } from '@angular/common'
import { HttpModule } from '@angular/http'
import { RouterModule } from '@angular/router'
import { SimpleNotificationsModule } from 'angular2-notifications';
import { ModalModule } from 'ngx-bootstrap/modal';
import { SimpleNotificationsModule } from 'angular2-notifications'
import { ModalModule } from 'ngx-bootstrap/modal'
import { AuthService } from './auth';
import { ConfigService } from './config';
import { ConfirmComponent, ConfirmService } from './confirm';
import { MenuComponent, MenuAdminComponent } from './menu';
import { throwIfAlreadyLoaded } from './module-import-guard';
import { AuthService } from './auth'
import { ConfigService } from './config'
import { ConfirmComponent, ConfirmService } from './confirm'
import { MenuComponent, MenuAdminComponent } from './menu'
import { throwIfAlreadyLoaded } from './module-import-guard'
@NgModule({
imports: [
@ -43,7 +43,7 @@ import { throwIfAlreadyLoaded } from './module-import-guard';
]
})
export class CoreModule {
constructor( @Optional() @SkipSelf() parentModule: CoreModule) {
throwIfAlreadyLoaded(parentModule, 'CoreModule');
constructor ( @Optional() @SkipSelf() parentModule: CoreModule) {
throwIfAlreadyLoaded(parentModule, 'CoreModule')
}
}

View File

@ -1,5 +1,5 @@
export * from './auth';
export * from './config';
export * from './confirm';
export * from './menu';
export * from './auth'
export * from './config'
export * from './confirm'
export * from './menu'
export * from './core.module'

View File

@ -1,2 +1,2 @@
export * from './menu.component';
export * from './menu-admin.component';
export * from './menu.component'
export * from './menu-admin.component'

View File

@ -1,4 +1,4 @@
import { Component } from '@angular/core';
import { Component } from '@angular/core'
@Component({
selector: 'my-menu-admin',

View File

@ -1,8 +1,8 @@
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Component, OnInit } from '@angular/core'
import { Router } from '@angular/router'
import { AuthService, AuthStatus } from '../auth';
import { ConfigService } from '../config';
import { AuthService, AuthStatus } from '../auth'
import { ConfigService } from '../config'
@Component({
selector: 'my-menu',
@ -10,7 +10,7 @@ import { ConfigService } from '../config';
styleUrls: [ './menu.component.scss' ]
})
export class MenuComponent implements OnInit {
isLoggedIn: boolean;
isLoggedIn: boolean
constructor (
private authService: AuthService,
@ -18,35 +18,35 @@ export class MenuComponent implements OnInit {
private router: Router
) {}
ngOnInit() {
this.isLoggedIn = this.authService.isLoggedIn();
ngOnInit () {
this.isLoggedIn = this.authService.isLoggedIn()
this.authService.loginChangedSource.subscribe(
status => {
if (status === AuthStatus.LoggedIn) {
this.isLoggedIn = true;
console.log('Logged in.');
this.isLoggedIn = true
console.log('Logged in.')
} else if (status === AuthStatus.LoggedOut) {
this.isLoggedIn = false;
console.log('Logged out.');
this.isLoggedIn = false
console.log('Logged out.')
} else {
console.error('Unknown auth status: ' + status);
console.error('Unknown auth status: ' + status)
}
}
);
)
}
isRegistrationEnabled() {
return this.configService.getConfig().signup.enabled;
isRegistrationEnabled () {
return this.configService.getConfig().signup.enabled
}
isUserAdmin() {
return this.authService.isAdmin();
isUserAdmin () {
return this.authService.isAdmin()
}
logout() {
this.authService.logout();
logout () {
this.authService.logout()
// Redirect to home page
this.router.navigate(['/videos/list']);
this.router.navigate(['/videos/list'])
}
}

View File

@ -1,5 +1,5 @@
export function throwIfAlreadyLoaded(parentModule: any, moduleName: string) {
export function throwIfAlreadyLoaded (parentModule: any, moduleName: string) {
if (parentModule) {
throw new Error(`${moduleName} has already been loaded. Import Core modules in the AppModule only.`);
throw new Error(`${moduleName} has already been loaded. Import Core modules in the AppModule only.`)
}
}

View File

@ -1,3 +1,5 @@
/* tslint:disable */
/**
* Angular 2
*/

View File

@ -1 +1 @@
export * from './app.module';
export * from './app.module'

View File

@ -1,3 +1,3 @@
export * from './login-routing.module';
export * from './login.component';
export * from './login.module';
export * from './login-routing.module'
export * from './login.component'
export * from './login.module'

View File

@ -1,7 +1,7 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { NgModule } from '@angular/core'
import { RouterModule, Routes } from '@angular/router'
import { LoginComponent } from './login.component';
import { LoginComponent } from './login.component'
const loginRoutes: Routes = [
{
@ -13,7 +13,7 @@ const loginRoutes: Routes = [
}
}
}
];
]
@NgModule({
imports: [ RouterModule.forChild(loginRoutes) ],

View File

@ -1,9 +1,9 @@
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { Component, OnInit } from '@angular/core'
import { FormBuilder, FormGroup, Validators } from '@angular/forms'
import { Router } from '@angular/router'
import { AuthService } from '../core';
import { FormReactive } from '../shared';
import { AuthService } from '../core'
import { FormReactive } from '../shared'
@Component({
selector: 'my-login',
@ -11,60 +11,60 @@ import { FormReactive } from '../shared';
})
export class LoginComponent extends FormReactive implements OnInit {
error: string = null;
error: string = null
form: FormGroup;
form: FormGroup
formErrors = {
'username': '',
'password': ''
};
}
validationMessages = {
'username': {
'required': 'Username is required.',
'required': 'Username is required.'
},
'password': {
'required': 'Password is required.'
}
};
}
constructor(
constructor (
private authService: AuthService,
private formBuilder: FormBuilder,
private router: Router
) {
super();
super()
}
buildForm() {
buildForm () {
this.form = this.formBuilder.group({
username: [ '', Validators.required ],
password: [ '', Validators.required ],
});
password: [ '', Validators.required ]
})
this.form.valueChanges.subscribe(data => this.onValueChanged(data));
this.form.valueChanges.subscribe(data => this.onValueChanged(data))
}
ngOnInit() {
this.buildForm();
ngOnInit () {
this.buildForm()
}
login() {
this.error = null;
login () {
this.error = null
const { username, password } = this.form.value;
const { username, password } = this.form.value
this.authService.login(username, password).subscribe(
result => this.router.navigate(['/videos/list']),
error => {
console.error(error.json);
console.error(error.json)
if (error.json.error === 'invalid_grant') {
this.error = 'Credentials are invalid.';
this.error = 'Credentials are invalid.'
} else {
this.error = `${error.json.error}: ${error.json.error_description}`;
this.error = `${error.json.error}: ${error.json.error_description}`
}
}
);
)
}
}

View File

@ -1,8 +1,8 @@
import { NgModule } from '@angular/core';
import { NgModule } from '@angular/core'
import { LoginRoutingModule } from './login-routing.module';
import { LoginComponent } from './login.component';
import { SharedModule } from '../shared';
import { LoginRoutingModule } from './login-routing.module'
import { LoginComponent } from './login.component'
import { SharedModule } from '../shared'
@NgModule({
imports: [

View File

@ -1,4 +1,4 @@
import { Injectable } from '@angular/core';
import { Injectable } from '@angular/core'
import {
ConnectionBackend,
Headers,
@ -9,79 +9,79 @@ import {
RequestOptionsArgs,
Response,
XHRBackend
} from '@angular/http';
import { Observable } from 'rxjs/Observable';
} from '@angular/http'
import { Observable } from 'rxjs/Observable'
import { AuthService } from '../../core';
import { AuthService } from '../../core'
@Injectable()
export class AuthHttp extends Http {
constructor(backend: ConnectionBackend, defaultOptions: RequestOptions, private authService: AuthService) {
super(backend, defaultOptions);
constructor (backend: ConnectionBackend, defaultOptions: RequestOptions, private authService: AuthService) {
super(backend, defaultOptions)
}
request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
if (!options) options = {};
request (url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
if (!options) options = {}
options.headers = new Headers();
this.setAuthorizationHeader(options.headers);
options.headers = new Headers()
this.setAuthorizationHeader(options.headers)
return super.request(url, options)
.catch((err) => {
if (err.status === 401) {
return this.handleTokenExpired(url, options);
return this.handleTokenExpired(url, options)
}
return Observable.throw(err);
});
return Observable.throw(err)
})
}
delete(url: string, options?: RequestOptionsArgs): Observable<Response> {
if (!options) options = {};
options.method = RequestMethod.Delete;
delete (url: string, options?: RequestOptionsArgs): Observable<Response> {
if (!options) options = {}
options.method = RequestMethod.Delete
return this.request(url, options);
return this.request(url, options)
}
get(url: string, options?: RequestOptionsArgs): Observable<Response> {
if (!options) options = {};
options.method = RequestMethod.Get;
get (url: string, options?: RequestOptionsArgs): Observable<Response> {
if (!options) options = {}
options.method = RequestMethod.Get
return this.request(url, options);
return this.request(url, options)
}
post(url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
if (!options) options = {};
options.method = RequestMethod.Post;
options.body = body;
post (url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
if (!options) options = {}
options.method = RequestMethod.Post
options.body = body
return this.request(url, options);
return this.request(url, options)
}
put(url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
if (!options) options = {};
options.method = RequestMethod.Put;
options.body = body;
put (url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
if (!options) options = {}
options.method = RequestMethod.Put
options.body = body
return this.request(url, options);
return this.request(url, options)
}
private handleTokenExpired(url: string | Request, options: RequestOptionsArgs) {
private handleTokenExpired (url: string | Request, options: RequestOptionsArgs) {
return this.authService.refreshAccessToken()
.flatMap(() => {
this.setAuthorizationHeader(options.headers);
this.setAuthorizationHeader(options.headers)
return super.request(url, options);
});
return super.request(url, options)
})
}
private setAuthorizationHeader(headers: Headers) {
headers.set('Authorization', this.authService.getRequestHeaderValue());
private setAuthorizationHeader (headers: Headers) {
headers.set('Authorization', this.authService.getRequestHeaderValue())
}
}
export function useFactory(backend: XHRBackend, defaultOptions: RequestOptions, authService: AuthService) {
return new AuthHttp(backend, defaultOptions, authService);
export function useFactory (backend: XHRBackend, defaultOptions: RequestOptions, authService: AuthService) {
return new AuthHttp(backend, defaultOptions, authService)
}
export const AUTH_HTTP_PROVIDERS = [
@ -89,5 +89,5 @@ export const AUTH_HTTP_PROVIDERS = [
provide: AuthHttp,
useFactory,
deps: [ XHRBackend, RequestOptions, AuthService ]
},
];
}
]

View File

@ -1 +1 @@
export * from './auth-http.service';
export * from './auth-http.service'

View File

@ -1,38 +1,38 @@
import { FormGroup } from '@angular/forms';
import { FormGroup } from '@angular/forms'
export abstract class FormReactive {
abstract form: FormGroup;
abstract formErrors: Object;
abstract validationMessages: Object;
abstract form: FormGroup
abstract formErrors: Object
abstract validationMessages: Object
abstract buildForm(): void;
abstract buildForm (): void
protected onValueChanged(data?: any) {
protected onValueChanged (data?: any) {
for (const field in this.formErrors) {
// clear previous error message (if any)
this.formErrors[field] = '';
const control = this.form.get(field);
this.formErrors[field] = ''
const control = this.form.get(field)
if (control && control.dirty && !control.valid) {
const messages = this.validationMessages[field];
const messages = this.validationMessages[field]
for (const key in control.errors) {
this.formErrors[field] += messages[key] + ' ';
this.formErrors[field] += messages[key] + ' '
}
}
}
}
// Same as onValueChanged but force checking even if the field is not dirty
protected forceCheck() {
protected forceCheck () {
for (const field in this.formErrors) {
// clear previous error message (if any)
this.formErrors[field] = '';
const control = this.form.get(field);
this.formErrors[field] = ''
const control = this.form.get(field)
if (control && !control.valid) {
const messages = this.validationMessages[field];
const messages = this.validationMessages[field]
for (const key in control.errors) {
this.formErrors[field] += messages[key] + ' ';
this.formErrors[field] += messages[key] + ' '
}
}
}

View File

@ -1,14 +1,14 @@
import { FormControl } from '@angular/forms';
import { FormControl } from '@angular/forms'
export function validateHost(c: FormControl) {
export function validateHost (c: FormControl) {
// Thanks to http://stackoverflow.com/a/106223
const HOST_REGEXP = new RegExp(
'^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$'
);
)
return HOST_REGEXP.test(c.value) ? null : {
validateHost: {
valid: false
}
};
}
}

View File

@ -1,4 +1,4 @@
export * from './host.validator';
export * from './user';
export * from './video-abuse';
export * from './video';
export * from './host.validator'
export * from './user'
export * from './video-abuse'
export * from './video'

View File

@ -1,4 +1,4 @@
import { Validators } from '@angular/forms';
import { Validators } from '@angular/forms'
export const USER_USERNAME = {
VALIDATORS: [ Validators.required, Validators.minLength(3), Validators.maxLength(20) ],
@ -7,18 +7,18 @@ export const USER_USERNAME = {
'minlength': 'Username must be at least 3 characters long.',
'maxlength': 'Username cannot be more than 20 characters long.'
}
};
}
export const USER_EMAIL = {
VALIDATORS: [ Validators.required, Validators.email ],
MESSAGES: {
'required': 'Email is required.',
'email': 'Email must be valid.',
'email': 'Email must be valid.'
}
};
}
export const USER_PASSWORD = {
VALIDATORS: [ Validators.required, Validators.minLength(6) ],
MESSAGES: {
'required': 'Password is required.',
'minlength': 'Password must be at least 6 characters long.',
'minlength': 'Password must be at least 6 characters long.'
}
};
}

View File

@ -1,4 +1,4 @@
import { Validators } from '@angular/forms';
import { Validators } from '@angular/forms'
export const VIDEO_ABUSE_REASON = {
VALIDATORS: [ Validators.required, Validators.minLength(2), Validators.maxLength(300) ],
@ -7,4 +7,4 @@ export const VIDEO_ABUSE_REASON = {
'minlength': 'Report reson must be at least 2 characters long.',
'maxlength': 'Report reson cannot be more than 300 characters long.'
}
};
}

View File

@ -1,4 +1,4 @@
import { Validators } from '@angular/forms';
import { Validators } from '@angular/forms'
export const VIDEO_NAME = {
VALIDATORS: [ Validators.required, Validators.minLength(3), Validators.maxLength(50) ],
@ -7,26 +7,26 @@ export const VIDEO_NAME = {
'minlength': 'Video name must be at least 3 characters long.',
'maxlength': 'Video name cannot be more than 50 characters long.'
}
};
}
export const VIDEO_CATEGORY = {
VALIDATORS: [ Validators.required ],
MESSAGES: {
'required': 'Video category is required.'
}
};
}
export const VIDEO_LICENCE = {
VALIDATORS: [ Validators.required ],
MESSAGES: {
'required': 'Video licence is required.'
}
};
}
export const VIDEO_LANGUAGE = {
VALIDATORS: [ ],
MESSAGES: {}
};
}
export const VIDEO_DESCRIPTION = {
VALIDATORS: [ Validators.required, Validators.minLength(3), Validators.maxLength(250) ],
@ -35,7 +35,7 @@ export const VIDEO_DESCRIPTION = {
'minlength': 'Video description must be at least 3 characters long.',
'maxlength': 'Video description cannot be more than 250 characters long.'
}
};
}
export const VIDEO_TAGS = {
VALIDATORS: [ Validators.minLength(2), Validators.maxLength(10) ],
@ -43,4 +43,4 @@ export const VIDEO_TAGS = {
'minlength': 'A tag should be more than 2 characters long.',
'maxlength': 'A tag should be less than 10 characters long.'
}
};
}

View File

@ -1,2 +1,2 @@
export * from './form-validators';
export * from './form-reactive';
export * from './form-validators'
export * from './form-reactive'

View File

@ -1,8 +1,8 @@
export * from './auth';
export * from './forms';
export * from './rest';
export * from './search';
export * from './users';
export * from './video-abuse';
export * from './shared.module';
export * from './utils';
export * from './auth'
export * from './forms'
export * from './rest'
export * from './search'
export * from './users'
export * from './video-abuse'
export * from './shared.module'
export * from './utils'

View File

@ -1,4 +1,4 @@
export * from './rest-data-source';
export * from './rest-extractor.service';
export * from './rest-pagination';
export * from './rest.service';
export * from './rest-data-source'
export * from './rest-extractor.service'
export * from './rest-pagination'
export * from './rest.service'

View File

@ -1,51 +1,51 @@
import { Http, RequestOptionsArgs, URLSearchParams, } from '@angular/http';
import { Http, RequestOptionsArgs, URLSearchParams, Response } from '@angular/http'
import { ServerDataSource } from 'ng2-smart-table';
import { ServerDataSource } from 'ng2-smart-table'
export class RestDataSource extends ServerDataSource {
constructor(http: Http, endpoint: string) {
const options = {
endPoint: endpoint,
sortFieldKey: 'sort',
dataKey: 'data'
};
constructor (http: Http, endpoint: string) {
const options = {
endPoint: endpoint,
sortFieldKey: 'sort',
dataKey: 'data'
}
super(http, options);
}
protected extractTotalFromResponse(res) {
const rawData = res.json();
return rawData ? parseInt(rawData.total) : 0;
super(http, options)
}
protected addSortRequestOptions(requestOptions: RequestOptionsArgs) {
let searchParams: URLSearchParams = <URLSearchParams> requestOptions.search;
protected extractTotalFromResponse (res: Response) {
const rawData = res.json()
return rawData ? parseInt(rawData.total, 10) : 0
}
protected addSortRequestOptions (requestOptions: RequestOptionsArgs) {
const searchParams = requestOptions.search as URLSearchParams
if (this.sortConf) {
this.sortConf.forEach((fieldConf) => {
const sortPrefix = fieldConf.direction === 'desc' ? '-' : '';
const sortPrefix = fieldConf.direction === 'desc' ? '-' : ''
searchParams.set(this.conf.sortFieldKey, sortPrefix + fieldConf.field);
});
searchParams.set(this.conf.sortFieldKey, sortPrefix + fieldConf.field)
})
}
return requestOptions;
return requestOptions
}
protected addPagerRequestOptions(requestOptions: RequestOptionsArgs) {
let searchParams: URLSearchParams = <URLSearchParams> requestOptions.search;
protected addPagerRequestOptions (requestOptions: RequestOptionsArgs) {
const searchParams = requestOptions.search as URLSearchParams
if (this.pagingConf && this.pagingConf['page'] && this.pagingConf['perPage']) {
const perPage = this.pagingConf['perPage'];
const page = this.pagingConf['page'];
const perPage = this.pagingConf['perPage']
const page = this.pagingConf['page']
const start = (page - 1) * perPage;
const count = perPage;
const start = (page - 1) * perPage
const count = perPage
searchParams.set('start', start.toString());
searchParams.set('count', count.toString());
searchParams.set('start', start.toString())
searchParams.set('count', count.toString())
}
return requestOptions;
return requestOptions
}
}

View File

@ -1,52 +1,52 @@
import { Injectable } from '@angular/core';
import { Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { Injectable } from '@angular/core'
import { Response } from '@angular/http'
import { Observable } from 'rxjs/Observable'
export interface ResultList {
data: any[];
total: number;
data: any[]
total: number
}
@Injectable()
export class RestExtractor {
constructor () { ; }
extractDataBool(res: Response) {
return true;
extractDataBool (res: Response) {
return true
}
extractDataList(res: Response) {
const body = res.json();
extractDataList (res: Response) {
const body = res.json()
const ret: ResultList = {
data: body.data,
total: body.total
};
}
return ret;
return ret
}
extractDataGet(res: Response) {
return res.json();
extractDataGet (res: Response) {
return res.json()
}
handleError(res: Response) {
let text = 'Server error: ';
text += res.text();
let json = '';
handleError (res: Response) {
let text = 'Server error: '
text += res.text()
let json = ''
try {
json = res.json();
} catch (err) { ; }
json = res.json()
} catch (err) {
console.error('Cannot get JSON from response.')
}
const error = {
json,
text
};
}
console.error(error);
console.error(error)
return Observable.throw(error);
return Observable.throw(error)
}
}

View File

@ -1,5 +1,5 @@
export interface RestPagination {
currentPage: number;
itemsPerPage: number;
totalItems: number;
};
currentPage: number
itemsPerPage: number
totalItems: number
}

View File

@ -1,27 +1,27 @@
import { Injectable } from '@angular/core';
import { URLSearchParams } from '@angular/http';
import { Injectable } from '@angular/core'
import { URLSearchParams } from '@angular/http'
import { RestPagination } from './rest-pagination';
import { RestPagination } from './rest-pagination'
@Injectable()
export class RestService {
buildRestGetParams(pagination?: RestPagination, sort?: string) {
const params = new URLSearchParams();
buildRestGetParams (pagination?: RestPagination, sort?: string) {
const params = new URLSearchParams()
if (pagination) {
const start: number = (pagination.currentPage - 1) * pagination.itemsPerPage;
const count: number = pagination.itemsPerPage;
const start: number = (pagination.currentPage - 1) * pagination.itemsPerPage
const count: number = pagination.itemsPerPage
params.set('start', start.toString());
params.set('count', count.toString());
params.set('start', start.toString())
params.set('count', count.toString())
}
if (sort) {
params.set('sort', sort);
params.set('sort', sort)
}
return params;
return params
}
}

View File

@ -1,4 +1,4 @@
export * from './search-field.type';
export * from './search.component';
export * from './search.model';
export * from './search.service';
export * from './search-field.type'
export * from './search.component'
export * from './search.model'
export * from './search.service'

View File

@ -1 +1 @@
export type SearchField = "name" | "author" | "host" | "magnetUri" | "tags";
export type SearchField = 'name' | 'author' | 'host' | 'magnetUri' | 'tags'

View File

@ -1,9 +1,9 @@
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Component, OnInit } from '@angular/core'
import { Router } from '@angular/router'
import { Search } from './search.model';
import { SearchField } from './search-field.type';
import { SearchService } from './search.service';
import { Search } from './search.model'
import { SearchField } from './search-field.type'
import { SearchService } from './search.service'
@Component({
selector: 'my-search',
@ -18,53 +18,53 @@ export class SearchComponent implements OnInit {
host: 'Pod Host',
magnetUri: 'Magnet URI',
tags: 'Tags'
};
}
searchCriterias: Search = {
field: 'name',
value: ''
};
}
constructor(private searchService: SearchService, private router: Router) {}
constructor (private searchService: SearchService, private router: Router) {}
ngOnInit() {
ngOnInit () {
// Subscribe if the search changed
// Usually changed by videos list component
this.searchService.updateSearch.subscribe(
newSearchCriterias => {
// Put a field by default
if (!newSearchCriterias.field) {
newSearchCriterias.field = 'name';
newSearchCriterias.field = 'name'
}
this.searchCriterias = newSearchCriterias;
this.searchCriterias = newSearchCriterias
}
);
)
}
get choiceKeys() {
return Object.keys(this.fieldChoices);
get choiceKeys () {
return Object.keys(this.fieldChoices)
}
choose($event: MouseEvent, choice: SearchField) {
$event.preventDefault();
$event.stopPropagation();
choose ($event: MouseEvent, choice: SearchField) {
$event.preventDefault()
$event.stopPropagation()
this.searchCriterias.field = choice;
this.searchCriterias.field = choice
if (this.searchCriterias.value) {
this.doSearch();
this.doSearch()
}
}
doSearch() {
doSearch () {
if (this.router.url.indexOf('/videos/list') === -1) {
this.router.navigate([ '/videos/list' ]);
this.router.navigate([ '/videos/list' ])
}
this.searchService.searchUpdated.next(this.searchCriterias);
this.searchService.searchUpdated.next(this.searchCriterias)
}
getStringChoice(choiceKey: SearchField) {
return this.fieldChoices[choiceKey];
getStringChoice (choiceKey: SearchField) {
return this.fieldChoices[choiceKey]
}
}

View File

@ -1,6 +1,6 @@
import { SearchField } from './search-field.type';
import { SearchField } from './search-field.type'
export interface Search {
field: SearchField;
value: string;
field: SearchField
value: string
}

View File

@ -1,18 +1,18 @@
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { ReplaySubject } from 'rxjs/ReplaySubject';
import { Injectable } from '@angular/core'
import { Subject } from 'rxjs/Subject'
import { ReplaySubject } from 'rxjs/ReplaySubject'
import { Search } from './search.model';
import { Search } from './search.model'
// This class is needed to communicate between videos/ and search component
// Remove it when we'll be able to subscribe to router changes
@Injectable()
export class SearchService {
searchUpdated: Subject<Search>;
updateSearch: Subject<Search>;
searchUpdated: Subject<Search>
updateSearch: Subject<Search>
constructor() {
this.updateSearch = new Subject<Search>();
this.searchUpdated = new ReplaySubject<Search>(1);
constructor () {
this.updateSearch = new Subject<Search>()
this.searchUpdated = new ReplaySubject<Search>(1)
}
}

View File

@ -1,23 +1,23 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpModule } from '@angular/http';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { NgModule } from '@angular/core'
import { CommonModule } from '@angular/common'
import { HttpModule } from '@angular/http'
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { RouterModule } from '@angular/router'
import { BytesPipe } from 'angular-pipes/src/math/bytes.pipe';
import { KeysPipe } from 'angular-pipes/src/object/keys.pipe';
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
import { ProgressbarModule } from 'ngx-bootstrap/progressbar';
import { PaginationModule } from 'ngx-bootstrap/pagination';
import { ModalModule } from 'ngx-bootstrap/modal';
import { FileUploadModule } from 'ng2-file-upload/ng2-file-upload';
import { Ng2SmartTableModule } from 'ng2-smart-table';
import { BytesPipe } from 'angular-pipes/src/math/bytes.pipe'
import { KeysPipe } from 'angular-pipes/src/object/keys.pipe'
import { BsDropdownModule } from 'ngx-bootstrap/dropdown'
import { ProgressbarModule } from 'ngx-bootstrap/progressbar'
import { PaginationModule } from 'ngx-bootstrap/pagination'
import { ModalModule } from 'ngx-bootstrap/modal'
import { FileUploadModule } from 'ng2-file-upload/ng2-file-upload'
import { Ng2SmartTableModule } from 'ng2-smart-table'
import { AUTH_HTTP_PROVIDERS } from './auth';
import { RestExtractor, RestService } from './rest';
import { SearchComponent, SearchService } from './search';
import { UserService } from './users';
import { VideoAbuseService } from './video-abuse';
import { AUTH_HTTP_PROVIDERS } from './auth'
import { RestExtractor, RestService } from './rest'
import { SearchComponent, SearchService } from './search'
import { UserService } from './users'
import { VideoAbuseService } from './video-abuse'
@NgModule({
imports: [

View File

@ -1,2 +1,2 @@
export * from './user.model';
export * from './user.service';
export * from './user.model'
export * from './user.service'

View File

@ -1,33 +1,33 @@
import { User as UserServerModel, UserRole } from '../../../../../shared';
import { User as UserServerModel, UserRole } from '../../../../../shared'
export class User implements UserServerModel {
id: number;
username: string;
email: string;
role: UserRole;
displayNSFW: boolean;
createdAt: Date;
id: number
username: string
email: string
role: UserRole
displayNSFW: boolean
createdAt: Date
constructor(hash: {
constructor (hash: {
id: number,
username: string,
email: string,
role: UserRole,
displayNSFW?: boolean,
createdAt?: Date,
createdAt?: Date
}) {
this.id = hash.id;
this.username = hash.username;
this.email = hash.email;
this.role = hash.role;
this.displayNSFW = hash.displayNSFW;
this.id = hash.id
this.username = hash.username
this.email = hash.email
this.role = hash.role
this.displayNSFW = hash.displayNSFW
if (hash.createdAt) {
this.createdAt = hash.createdAt;
this.createdAt = hash.createdAt
}
}
isAdmin() {
return this.role === 'admin';
isAdmin () {
return this.role === 'admin'
}
}

View File

@ -1,58 +1,58 @@
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import { Injectable } from '@angular/core'
import { Http } from '@angular/http'
import 'rxjs/add/operator/catch'
import 'rxjs/add/operator/map'
import { AuthService } from '../../core';
import { AuthHttp } from '../auth';
import { RestExtractor } from '../rest';
import { AuthService } from '../../core'
import { AuthHttp } from '../auth'
import { RestExtractor } from '../rest'
@Injectable()
export class UserService {
static BASE_USERS_URL = API_URL + '/api/v1/users/';
static BASE_USERS_URL = API_URL + '/api/v1/users/'
constructor(
constructor (
private http: Http,
private authHttp: AuthHttp,
private authService: AuthService,
private restExtractor: RestExtractor
) {}
checkTokenValidity() {
const url = UserService.BASE_USERS_URL + 'me';
checkTokenValidity () {
const url = UserService.BASE_USERS_URL + 'me'
// AuthHttp will redirect us to the login page if the oken is not valid anymore
this.authHttp.get(url).subscribe(() => { ; });
this.authHttp.get(url).subscribe()
}
changePassword(newPassword: string) {
const url = UserService.BASE_USERS_URL + this.authService.getUser().id;
changePassword (newPassword: string) {
const url = UserService.BASE_USERS_URL + this.authService.getUser().id
const body = {
password: newPassword
};
}
return this.authHttp.put(url, body)
.map(this.restExtractor.extractDataBool)
.catch((res) => this.restExtractor.handleError(res));
.catch((res) => this.restExtractor.handleError(res))
}
updateDetails(details: { displayNSFW: boolean }) {
const url = UserService.BASE_USERS_URL + this.authService.getUser().id;
updateDetails (details: { displayNSFW: boolean }) {
const url = UserService.BASE_USERS_URL + this.authService.getUser().id
return this.authHttp.put(url, details)
.map(this.restExtractor.extractDataBool)
.catch((res) => this.restExtractor.handleError(res));
.catch((res) => this.restExtractor.handleError(res))
}
signup(username: string, password: string, email: string) {
signup (username: string, password: string, email: string) {
const body = {
username,
email,
password
};
}
return this.http.post(UserService.BASE_USERS_URL + 'register', body)
.map(this.restExtractor.extractDataBool)
.catch(this.restExtractor.handleError);
.catch(this.restExtractor.handleError)
}
}

View File

@ -1,12 +1,12 @@
import { DatePipe } from '@angular/common';
import { DatePipe } from '@angular/common'
export class Utils {
static dateToHuman(date: String) {
return new DatePipe('en').transform(date, 'medium');
static dateToHuman (date: String) {
return new DatePipe('en').transform(date, 'medium')
}
static getRowDeleteButton() {
return '<span class="glyphicon glyphicon-remove glyphicon-black"></span>';
static getRowDeleteButton () {
return '<span class="glyphicon glyphicon-remove glyphicon-black"></span>'
}
}

View File

@ -1,2 +1,2 @@
export * from './video-abuse.service';
export * from './video-abuse.model';
export * from './video-abuse.service'
export * from './video-abuse.model'

View File

@ -1,8 +1,8 @@
export interface VideoAbuse {
id: string;
reason: string;
reporterPodHost: string;
reporterUsername: string;
videoId: string;
createdAt: Date;
id: string
reason: string
reporterPodHost: string
reporterUsername: string
videoId: string
createdAt: Date
}

View File

@ -1,42 +1,42 @@
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
import { Injectable } from '@angular/core'
import { Http } from '@angular/http'
import { Observable } from 'rxjs/Observable'
import 'rxjs/add/operator/catch'
import 'rxjs/add/operator/map'
import { AuthService } from '../core';
import { AuthHttp } from '../auth';
import { RestDataSource, RestExtractor, ResultList } from '../rest';
import { VideoAbuse } from './video-abuse.model';
import { AuthService } from '../core'
import { AuthHttp } from '../auth'
import { RestDataSource, RestExtractor, ResultList } from '../rest'
import { VideoAbuse } from './video-abuse.model'
@Injectable()
export class VideoAbuseService {
private static BASE_VIDEO_ABUSE_URL = API_URL + '/api/v1/videos/';
private static BASE_VIDEO_ABUSE_URL = API_URL + '/api/v1/videos/'
constructor(
constructor (
private authHttp: AuthHttp,
private restExtractor: RestExtractor
) {}
getDataSource() {
return new RestDataSource(this.authHttp, VideoAbuseService.BASE_VIDEO_ABUSE_URL + 'abuse');
getDataSource () {
return new RestDataSource(this.authHttp, VideoAbuseService.BASE_VIDEO_ABUSE_URL + 'abuse')
}
reportVideo(id: string, reason: string) {
reportVideo (id: string, reason: string) {
const body = {
reason
};
const url = VideoAbuseService.BASE_VIDEO_ABUSE_URL + id + '/abuse';
}
const url = VideoAbuseService.BASE_VIDEO_ABUSE_URL + id + '/abuse'
return this.authHttp.post(url, body)
.map(this.restExtractor.extractDataBool)
.catch((res) => this.restExtractor.handleError(res));
.catch((res) => this.restExtractor.handleError(res))
}
private extractVideoAbuses(result: ResultList) {
const videoAbuses: VideoAbuse[] = result.data;
const totalVideoAbuses = result.total;
private extractVideoAbuses (result: ResultList) {
const videoAbuses: VideoAbuse[] = result.data
const totalVideoAbuses = result.total
return { videoAbuses, totalVideoAbuses };
return { videoAbuses, totalVideoAbuses }
}
}

View File

@ -1,3 +1,3 @@
export * from './signup-routing.module';
export * from './signup.component';
export * from './signup.module';
export * from './signup-routing.module'
export * from './signup.component'
export * from './signup.module'

View File

@ -1,7 +1,7 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { NgModule } from '@angular/core'
import { RouterModule, Routes } from '@angular/router'
import { SignupComponent } from './signup.component';
import { SignupComponent } from './signup.component'
const signupRoutes: Routes = [
{
@ -13,7 +13,7 @@ const signupRoutes: Routes = [
}
}
}
];
]
@NgModule({
imports: [ RouterModule.forChild(signupRoutes) ],

Some files were not shown because too many files have changed in this diff Show More