Client: add ability to report a video

This commit is contained in:
Chocobozzz 2017-01-20 19:22:15 +01:00
parent 872a4c7cea
commit 4f8c0eb0e9
11 changed files with 174 additions and 6 deletions

View File

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

View File

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

View File

@ -55,6 +55,17 @@ export class VideoService {
.catch((res) => this.restExtractor.handleError(res));
}
reportVideo(id: string, reason: string) {
const body = {
reason
};
const url = VideoService.BASE_VIDEO_URL + id + '/abuse';
return this.authHttp.post(url, body)
.map(this.restExtractor.extractDataBool)
.catch((res) => this.restExtractor.handleError(res));
}
private extractVideos(result: ResultList) {
const videosJson = result.data;
const totalVideos = result.total;

View File

@ -1,4 +1,5 @@
export * from './video-magnet.component';
export * from './video-share.component';
export * from './video-report.component';
export * from './video-watch.component';
export * from './webtorrent.service';

View File

@ -0,0 +1,38 @@
<div bsModal #modal="bs-modal" class="modal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content modal-lg">
<div class="modal-header">
<button type="button" class="close" aria-label="Close" (click)="hide()">
<span aria-hidden="true">&times;</span>
</button>
<h4 class="modal-title">Report video</h4>
</div>
<div class="modal-body">
<form novalidate [formGroup]="form">
<div class="form-group">
<label for="description">Reason</label>
<textarea
id="reason" class="form-control" placeholder="Reason..."
formControlName="reason"
>
</textarea>
<div *ngIf="formErrors.reason" class="alert alert-danger">
{{ formErrors.reason }}
</div>
</div>
<div class="form-group">
<input
type="button" value="Report" class="btn btn-default form-control"
[disabled]="!form.valid" (click)="report()"
>
</div>
</form>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,68 @@
import { Component, Input, OnInit, ViewChild } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { ModalDirective } from 'ng2-bootstrap/modal';
import { FormReactive, VIDEO_REPORT_REASON } from '../../shared';
import { Video, VideoService } from '../shared';
@Component({
selector: 'my-video-report',
templateUrl: './video-report.component.html'
})
export class VideoReportComponent extends FormReactive implements OnInit {
@Input() video: Video = null;
@ViewChild('modal') modal: ModalDirective;
error: string = null;
form: FormGroup;
formErrors = {
reason: ''
};
validationMessages = {
reason: VIDEO_REPORT_REASON.MESSAGES
};
constructor(
private formBuilder: FormBuilder,
private videoService: VideoService
) {
super();
}
ngOnInit() {
this.buildForm();
}
buildForm() {
this.form = this.formBuilder.group({
reason: [ '', VIDEO_REPORT_REASON.VALIDATORS ]
});
this.form.valueChanges.subscribe(data => this.onValueChanged(data));
}
show() {
this.modal.show();
}
hide() {
this.modal.hide();
}
report() {
const reason = this.form.value['reason']
this.videoService.reportVideo(this.video.id, reason)
.subscribe(
// TODO: move alert to beautiful notifications
ok => {
alert('Video reported.');
this.hide();
},
err => alert(err.text)
)
}
}

View File

@ -60,6 +60,19 @@
<button title="Get magnet URI" id="magnet-uri" class="btn btn-default" (click)="showMagnetUriModal()">
<span class="glyphicon glyphicon-magnet"></span> Magnet
</button>
<div *ngIf="isUserLoggedIn()" class="btn-group" dropdown>
<button id="single-button" type="button" id="more" class="btn btn-default" dropdownToggle>
<span class="glyphicon glyphicon-option-horizontal"></span> More
</button>
<ul dropdownMenu id="more-menu" role="menu" aria-labelledby="single-button">
<li role="menuitem">
<a class="dropdown-item" href="#" (click)="showReportModal($event)">
<span class="glyphicon glyphicon-alert"></span> Report
</a>
</li>
</ul>
</div>
</div>
</div>
@ -79,5 +92,8 @@
</div>
</div>
<my-video-share #videoShareModal *ngIf="video !== null" [video]="video"></my-video-share>
<my-video-magnet #videoMagnetModal *ngIf="video !== null" [video]="video"></my-video-magnet>
<template [ngIf]="video !== null">
<my-video-share #videoShareModal [video]="video"></my-video-share>
<my-video-magnet #videoMagnetModal [video]="video"></my-video-magnet>
<my-video-report #videoReportModal [video]="video"></my-video-report>
</template>

View File

@ -47,10 +47,14 @@
top: 2px;
}
#magnet-uri, #share {
#magnet-uri, #share, #more {
font-weight: bold;
opacity: 0.85;
}
#more-menu .dropdown-item .glyphicon {
margin-right: 5px;
}
}
#video-by-date {

View File

@ -5,8 +5,10 @@ import { ActivatedRoute } from '@angular/router';
import { MetaService } from 'ng2-meta';
import * as videojs from 'video.js';
import { AuthService } from '../../core';
import { VideoMagnetComponent } from './video-magnet.component';
import { VideoShareComponent } from './video-share.component';
import { VideoReportComponent } from './video-report.component';
import { Video, VideoService } from '../shared';
import { WebTorrentService } from './webtorrent.service';
@ -21,6 +23,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
@ViewChild('videoMagnetModal') videoMagnetModal: VideoMagnetComponent;
@ViewChild('videoShareModal') videoShareModal: VideoShareComponent;
@ViewChild('videoReportModal') videoReportModal: VideoReportComponent;
downloadSpeed: number;
error: boolean = false;
@ -42,7 +45,8 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
private route: ActivatedRoute,
private videoService: VideoService,
private metaService: MetaService,
private webTorrentService: WebTorrentService
private webTorrentService: WebTorrentService,
private authService: AuthService
) {}
ngOnInit() {
@ -123,6 +127,11 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
});
}
showReportModal(event: Event) {
event.preventDefault();
this.videoReportModal.show();
}
showShareModal() {
this.videoShareModal.show();
}
@ -131,6 +140,10 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
this.videoMagnetModal.show();
}
isUserLoggedIn() {
return this.authService.isLoggedIn();
}
private loadTooLong() {
this.error = true;
console.error('The video load seems to be abnormally long.');

View File

@ -4,7 +4,13 @@ import { VideosRoutingModule } from './videos-routing.module';
import { VideosComponent } from './videos.component';
import { VideoAddComponent } from './video-add';
import { VideoListComponent, VideoMiniatureComponent, VideoSortComponent } from './video-list';
import { VideoWatchComponent, VideoMagnetComponent, VideoShareComponent, WebTorrentService } from './video-watch';
import {
VideoWatchComponent,
VideoMagnetComponent,
VideoReportComponent,
VideoShareComponent,
WebTorrentService
} from './video-watch';
import { LoaderComponent, VideoService } from './shared';
import { SharedModule } from '../shared';
@ -26,6 +32,7 @@ import { SharedModule } from '../shared';
VideoWatchComponent,
VideoMagnetComponent,
VideoShareComponent,
VideoReportComponent,
LoaderComponent
],

View File

@ -61,7 +61,6 @@ function transactionRetryer (func, callback) {
}
function startSerializableTransaction (callback) {
console.log(db)
db.sequelize.transaction({ isolationLevel: 'SERIALIZABLE' }).asCallback(function (err, t) {
// We force to return only two parameters
return callback(err, t)