aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/app')
-rw-r--r--client/src/app/shared/forms/form-validators/index.ts1
-rw-r--r--client/src/app/shared/forms/form-validators/video-report.ts10
-rw-r--r--client/src/app/videos/shared/video.service.ts11
-rw-r--r--client/src/app/videos/video-watch/index.ts1
-rw-r--r--client/src/app/videos/video-watch/video-report.component.html38
-rw-r--r--client/src/app/videos/video-watch/video-report.component.ts68
-rw-r--r--client/src/app/videos/video-watch/video-watch.component.html20
-rw-r--r--client/src/app/videos/video-watch/video-watch.component.scss6
-rw-r--r--client/src/app/videos/video-watch/video-watch.component.ts15
-rw-r--r--client/src/app/videos/videos.module.ts9
10 files changed, 174 insertions, 5 deletions
diff --git a/client/src/app/shared/forms/form-validators/index.ts b/client/src/app/shared/forms/form-validators/index.ts
index 4c6cc6637..119b5d9bf 100644
--- a/client/src/app/shared/forms/form-validators/index.ts
+++ b/client/src/app/shared/forms/form-validators/index.ts
@@ -1,3 +1,4 @@
1export * from './host.validator'; 1export * from './host.validator';
2export * from './user'; 2export * from './user';
3export * from './video-report';
3export * from './video'; 4export * from './video';
diff --git a/client/src/app/shared/forms/form-validators/video-report.ts b/client/src/app/shared/forms/form-validators/video-report.ts
new file mode 100644
index 000000000..036ee1721
--- /dev/null
+++ b/client/src/app/shared/forms/form-validators/video-report.ts
@@ -0,0 +1,10 @@
1import { Validators } from '@angular/forms';
2
3export const VIDEO_REPORT_REASON = {
4 VALIDATORS: [ Validators.required, Validators.minLength(2), Validators.maxLength(300) ],
5 MESSAGES: {
6 'required': 'Report reason name is required.',
7 'minlength': 'Report reson must be at least 2 characters long.',
8 'maxlength': 'Report reson cannot be more than 300 characters long.'
9 }
10};
diff --git a/client/src/app/videos/shared/video.service.ts b/client/src/app/videos/shared/video.service.ts
index 9d79b2f5e..7094d9a34 100644
--- a/client/src/app/videos/shared/video.service.ts
+++ b/client/src/app/videos/shared/video.service.ts
@@ -55,6 +55,17 @@ export class VideoService {
55 .catch((res) => this.restExtractor.handleError(res)); 55 .catch((res) => this.restExtractor.handleError(res));
56 } 56 }
57 57
58 reportVideo(id: string, reason: string) {
59 const body = {
60 reason
61 };
62 const url = VideoService.BASE_VIDEO_URL + id + '/abuse';
63
64 return this.authHttp.post(url, body)
65 .map(this.restExtractor.extractDataBool)
66 .catch((res) => this.restExtractor.handleError(res));
67 }
68
58 private extractVideos(result: ResultList) { 69 private extractVideos(result: ResultList) {
59 const videosJson = result.data; 70 const videosJson = result.data;
60 const totalVideos = result.total; 71 const totalVideos = result.total;
diff --git a/client/src/app/videos/video-watch/index.ts b/client/src/app/videos/video-watch/index.ts
index 1a8403b0a..ed0ed2fc0 100644
--- a/client/src/app/videos/video-watch/index.ts
+++ b/client/src/app/videos/video-watch/index.ts
@@ -1,4 +1,5 @@
1export * from './video-magnet.component'; 1export * from './video-magnet.component';
2export * from './video-share.component'; 2export * from './video-share.component';
3export * from './video-report.component';
3export * from './video-watch.component'; 4export * from './video-watch.component';
4export * from './webtorrent.service'; 5export * from './webtorrent.service';
diff --git a/client/src/app/videos/video-watch/video-report.component.html b/client/src/app/videos/video-watch/video-report.component.html
new file mode 100644
index 000000000..741080ead
--- /dev/null
+++ b/client/src/app/videos/video-watch/video-report.component.html
@@ -0,0 +1,38 @@
1<div bsModal #modal="bs-modal" class="modal" tabindex="-1">
2 <div class="modal-dialog">
3 <div class="modal-content modal-lg">
4
5 <div class="modal-header">
6 <button type="button" class="close" aria-label="Close" (click)="hide()">
7 <span aria-hidden="true">&times;</span>
8 </button>
9 <h4 class="modal-title">Report video</h4>
10 </div>
11
12 <div class="modal-body">
13
14 <form novalidate [formGroup]="form">
15 <div class="form-group">
16 <label for="description">Reason</label>
17 <textarea
18 id="reason" class="form-control" placeholder="Reason..."
19 formControlName="reason"
20 >
21 </textarea>
22 <div *ngIf="formErrors.reason" class="alert alert-danger">
23 {{ formErrors.reason }}
24 </div>
25 </div>
26
27 <div class="form-group">
28 <input
29 type="button" value="Report" class="btn btn-default form-control"
30 [disabled]="!form.valid" (click)="report()"
31 >
32 </div>
33 </form>
34
35 </div>
36 </div>
37 </div>
38</div>
diff --git a/client/src/app/videos/video-watch/video-report.component.ts b/client/src/app/videos/video-watch/video-report.component.ts
new file mode 100644
index 000000000..7bc1677ab
--- /dev/null
+++ b/client/src/app/videos/video-watch/video-report.component.ts
@@ -0,0 +1,68 @@
1import { Component, Input, OnInit, ViewChild } from '@angular/core';
2import { FormBuilder, FormGroup } from '@angular/forms';
3
4import { ModalDirective } from 'ng2-bootstrap/modal';
5
6import { FormReactive, VIDEO_REPORT_REASON } from '../../shared';
7import { Video, VideoService } from '../shared';
8
9@Component({
10 selector: 'my-video-report',
11 templateUrl: './video-report.component.html'
12})
13export class VideoReportComponent extends FormReactive implements OnInit {
14 @Input() video: Video = null;
15
16 @ViewChild('modal') modal: ModalDirective;
17
18 error: string = null;
19 form: FormGroup;
20 formErrors = {
21 reason: ''
22 };
23 validationMessages = {
24 reason: VIDEO_REPORT_REASON.MESSAGES
25 };
26
27 constructor(
28 private formBuilder: FormBuilder,
29 private videoService: VideoService
30 ) {
31 super();
32 }
33
34 ngOnInit() {
35 this.buildForm();
36 }
37
38 buildForm() {
39 this.form = this.formBuilder.group({
40 reason: [ '', VIDEO_REPORT_REASON.VALIDATORS ]
41 });
42
43 this.form.valueChanges.subscribe(data => this.onValueChanged(data));
44 }
45
46 show() {
47 this.modal.show();
48 }
49
50 hide() {
51 this.modal.hide();
52 }
53
54 report() {
55 const reason = this.form.value['reason']
56
57 this.videoService.reportVideo(this.video.id, reason)
58 .subscribe(
59 // TODO: move alert to beautiful notifications
60 ok => {
61 alert('Video reported.');
62 this.hide();
63 },
64
65 err => alert(err.text)
66 )
67 }
68}
diff --git a/client/src/app/videos/video-watch/video-watch.component.html b/client/src/app/videos/video-watch/video-watch.component.html
index a726ef3ff..8cee9959d 100644
--- a/client/src/app/videos/video-watch/video-watch.component.html
+++ b/client/src/app/videos/video-watch/video-watch.component.html
@@ -60,6 +60,19 @@
60 <button title="Get magnet URI" id="magnet-uri" class="btn btn-default" (click)="showMagnetUriModal()"> 60 <button title="Get magnet URI" id="magnet-uri" class="btn btn-default" (click)="showMagnetUriModal()">
61 <span class="glyphicon glyphicon-magnet"></span> Magnet 61 <span class="glyphicon glyphicon-magnet"></span> Magnet
62 </button> 62 </button>
63
64 <div *ngIf="isUserLoggedIn()" class="btn-group" dropdown>
65 <button id="single-button" type="button" id="more" class="btn btn-default" dropdownToggle>
66 <span class="glyphicon glyphicon-option-horizontal"></span> More
67 </button>
68 <ul dropdownMenu id="more-menu" role="menu" aria-labelledby="single-button">
69 <li role="menuitem">
70 <a class="dropdown-item" href="#" (click)="showReportModal($event)">
71 <span class="glyphicon glyphicon-alert"></span> Report
72 </a>
73 </li>
74 </ul>
75 </div>
63 </div> 76 </div>
64 </div> 77 </div>
65 78
@@ -79,5 +92,8 @@
79 </div> 92 </div>
80</div> 93</div>
81 94
82<my-video-share #videoShareModal *ngIf="video !== null" [video]="video"></my-video-share> 95<template [ngIf]="video !== null">
83<my-video-magnet #videoMagnetModal *ngIf="video !== null" [video]="video"></my-video-magnet> 96 <my-video-share #videoShareModal [video]="video"></my-video-share>
97 <my-video-magnet #videoMagnetModal [video]="video"></my-video-magnet>
98 <my-video-report #videoReportModal [video]="video"></my-video-report>
99</template>
diff --git a/client/src/app/videos/video-watch/video-watch.component.scss b/client/src/app/videos/video-watch/video-watch.component.scss
index ac62b04e7..794412707 100644
--- a/client/src/app/videos/video-watch/video-watch.component.scss
+++ b/client/src/app/videos/video-watch/video-watch.component.scss
@@ -47,10 +47,14 @@
47 top: 2px; 47 top: 2px;
48 } 48 }
49 49
50 #magnet-uri, #share { 50 #magnet-uri, #share, #more {
51 font-weight: bold; 51 font-weight: bold;
52 opacity: 0.85; 52 opacity: 0.85;
53 } 53 }
54
55 #more-menu .dropdown-item .glyphicon {
56 margin-right: 5px;
57 }
54 } 58 }
55 59
56 #video-by-date { 60 #video-by-date {
diff --git a/client/src/app/videos/video-watch/video-watch.component.ts b/client/src/app/videos/video-watch/video-watch.component.ts
index 256ffef99..d83cc5a7a 100644
--- a/client/src/app/videos/video-watch/video-watch.component.ts
+++ b/client/src/app/videos/video-watch/video-watch.component.ts
@@ -5,8 +5,10 @@ import { ActivatedRoute } from '@angular/router';
5import { MetaService } from 'ng2-meta'; 5import { MetaService } from 'ng2-meta';
6import * as videojs from 'video.js'; 6import * as videojs from 'video.js';
7 7
8import { AuthService } from '../../core';
8import { VideoMagnetComponent } from './video-magnet.component'; 9import { VideoMagnetComponent } from './video-magnet.component';
9import { VideoShareComponent } from './video-share.component'; 10import { VideoShareComponent } from './video-share.component';
11import { VideoReportComponent } from './video-report.component';
10import { Video, VideoService } from '../shared'; 12import { Video, VideoService } from '../shared';
11import { WebTorrentService } from './webtorrent.service'; 13import { WebTorrentService } from './webtorrent.service';
12 14
@@ -21,6 +23,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
21 23
22 @ViewChild('videoMagnetModal') videoMagnetModal: VideoMagnetComponent; 24 @ViewChild('videoMagnetModal') videoMagnetModal: VideoMagnetComponent;
23 @ViewChild('videoShareModal') videoShareModal: VideoShareComponent; 25 @ViewChild('videoShareModal') videoShareModal: VideoShareComponent;
26 @ViewChild('videoReportModal') videoReportModal: VideoReportComponent;
24 27
25 downloadSpeed: number; 28 downloadSpeed: number;
26 error: boolean = false; 29 error: boolean = false;
@@ -42,7 +45,8 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
42 private route: ActivatedRoute, 45 private route: ActivatedRoute,
43 private videoService: VideoService, 46 private videoService: VideoService,
44 private metaService: MetaService, 47 private metaService: MetaService,
45 private webTorrentService: WebTorrentService 48 private webTorrentService: WebTorrentService,
49 private authService: AuthService
46 ) {} 50 ) {}
47 51
48 ngOnInit() { 52 ngOnInit() {
@@ -123,6 +127,11 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
123 }); 127 });
124 } 128 }
125 129
130 showReportModal(event: Event) {
131 event.preventDefault();
132 this.videoReportModal.show();
133 }
134
126 showShareModal() { 135 showShareModal() {
127 this.videoShareModal.show(); 136 this.videoShareModal.show();
128 } 137 }
@@ -131,6 +140,10 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
131 this.videoMagnetModal.show(); 140 this.videoMagnetModal.show();
132 } 141 }
133 142
143 isUserLoggedIn() {
144 return this.authService.isLoggedIn();
145 }
146
134 private loadTooLong() { 147 private loadTooLong() {
135 this.error = true; 148 this.error = true;
136 console.error('The video load seems to be abnormally long.'); 149 console.error('The video load seems to be abnormally long.');
diff --git a/client/src/app/videos/videos.module.ts b/client/src/app/videos/videos.module.ts
index fb2f453b0..03dea17b5 100644
--- a/client/src/app/videos/videos.module.ts
+++ b/client/src/app/videos/videos.module.ts
@@ -4,7 +4,13 @@ import { VideosRoutingModule } from './videos-routing.module';
4import { VideosComponent } from './videos.component'; 4import { VideosComponent } from './videos.component';
5import { VideoAddComponent } from './video-add'; 5import { VideoAddComponent } from './video-add';
6import { VideoListComponent, VideoMiniatureComponent, VideoSortComponent } from './video-list'; 6import { VideoListComponent, VideoMiniatureComponent, VideoSortComponent } from './video-list';
7import { VideoWatchComponent, VideoMagnetComponent, VideoShareComponent, WebTorrentService } from './video-watch'; 7import {
8 VideoWatchComponent,
9 VideoMagnetComponent,
10 VideoReportComponent,
11 VideoShareComponent,
12 WebTorrentService
13} from './video-watch';
8import { LoaderComponent, VideoService } from './shared'; 14import { LoaderComponent, VideoService } from './shared';
9import { SharedModule } from '../shared'; 15import { SharedModule } from '../shared';
10 16
@@ -26,6 +32,7 @@ import { SharedModule } from '../shared';
26 VideoWatchComponent, 32 VideoWatchComponent,
27 VideoMagnetComponent, 33 VideoMagnetComponent,
28 VideoShareComponent, 34 VideoShareComponent,
35 VideoReportComponent,
29 36
30 LoaderComponent 37 LoaderComponent
31 ], 38 ],