From dc8bc31be517a53e8fbe7100cfe45cd73f596de0 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 14 Mar 2016 13:50:19 +0100 Subject: [PATCH] Angular application :first draft --- .gitignore | 1 + client/.gitignore | 6 +- client/angular/app/app.component.html | 37 +++++++++ client/angular/app/app.component.scss | 28 +++++++ client/angular/app/app.component.ts | 63 ++++++++++++++ client/{components => angular}/bootstrap.ts | 0 .../friends/services/friends.service.ts | 27 ++++++ .../components/add/videos-add.component.html | 39 +++++++++ .../components/add/videos-add.component.scss | 25 ++++++ .../components/add/videos-add.component.ts | 52 ++++++++++++ .../list/videos-list.component.html | 11 +++ .../list/videos-list.component.scss | 34 ++++++++ .../components/list/videos-list.component.ts | 39 +++++++++ .../watch/videos-watch.component.html | 2 + .../watch/videos-watch.component.scss} | 0 .../watch/videos-watch.component.ts | 50 +++++++++++ client/angular/videos/models/video.ts | 6 ++ .../angular/videos/services/videos.service.ts | 37 +++++++++ client/components/app/app.component.html | 23 ----- client/components/app/app.component.ts | 43 ---------- .../videos/add/videos-add.component.ts | 1 - .../videos/list/videos-list.component.ts | 1 - .../videos/watch/videos-watch.component.ts | 1 - client/index.html | 32 ++++--- client/package.json | 6 +- client/stylesheets/application.scss | 6 +- client/stylesheets/bootstrap-variables.scss | 6 +- client/stylesheets/index.scss | 83 ------------------- client/typings.json | 5 +- package.json | 21 +++-- server/controllers/api/v1/index.js | 2 +- server/controllers/api/v1/pods.js | 6 +- server/controllers/api/v1/remoteVideos.js | 2 +- server/controllers/api/v1/videos.js | 6 +- 34 files changed, 509 insertions(+), 192 deletions(-) create mode 100644 client/angular/app/app.component.html create mode 100644 client/angular/app/app.component.scss create mode 100644 client/angular/app/app.component.ts rename client/{components => angular}/bootstrap.ts (100%) create mode 100644 client/angular/friends/services/friends.service.ts create mode 100644 client/angular/videos/components/add/videos-add.component.html create mode 100644 client/angular/videos/components/add/videos-add.component.scss create mode 100644 client/angular/videos/components/add/videos-add.component.ts create mode 100644 client/angular/videos/components/list/videos-list.component.html create mode 100644 client/angular/videos/components/list/videos-list.component.scss create mode 100644 client/angular/videos/components/list/videos-list.component.ts create mode 100644 client/angular/videos/components/watch/videos-watch.component.html rename client/{components/app/app.component.scss => angular/videos/components/watch/videos-watch.component.scss} (100%) create mode 100644 client/angular/videos/components/watch/videos-watch.component.ts create mode 100644 client/angular/videos/models/video.ts create mode 100644 client/angular/videos/services/videos.service.ts delete mode 100644 client/components/app/app.component.html delete mode 100644 client/components/app/app.component.ts delete mode 100644 client/components/videos/add/videos-add.component.ts delete mode 100644 client/components/videos/list/videos-list.component.ts delete mode 100644 client/components/videos/watch/videos-watch.component.ts diff --git a/.gitignore b/.gitignore index aaa4db4fb..6c0165c41 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ test5/ test6/ public/stylesheets/global.css public/stylesheets/vendor +uploads diff --git a/client/.gitignore b/client/.gitignore index 439f0c025..4bb21ebab 100644 --- a/client/.gitignore +++ b/client/.gitignore @@ -1,5 +1,5 @@ typings -components/**/*.js -components/**/*.map +angular/**/*.js +angular/**/*.map +angular/**/*.css stylesheets/index.css -components/**/*.css diff --git a/client/angular/app/app.component.html b/client/angular/app/app.component.html new file mode 100644 index 000000000..590efa0d6 --- /dev/null +++ b/client/angular/app/app.component.html @@ -0,0 +1,37 @@ +
+ +
+ + +
+ + Get videos +
+ + + +
+ + Make friends +
+ +
+ + Quit friends +
+
+ +
+ +
+ +
+ + +
+ PeerTube, CopyLeft 2015-2016 +
+
diff --git a/client/angular/app/app.component.scss b/client/angular/app/app.component.scss new file mode 100644 index 000000000..03ecba8f2 --- /dev/null +++ b/client/angular/app/app.component.scss @@ -0,0 +1,28 @@ +menu { + min-height: 300px; + height: 100%; + margin-right: 20px; + border-right: 1px solid rgba(0, 0, 0, 0.2); + + .panel_button { + margin: 8px; + cursor: pointer; + transition: margin 0.2s; + + &:hover { + margin-left: 15px; + } + + a { + color: #333333; + } + } + + .glyphicon { + margin: 5px; + } +} + +footer { + margin-top: 30px; +} diff --git a/client/angular/app/app.component.ts b/client/angular/app/app.component.ts new file mode 100644 index 000000000..3d41183f2 --- /dev/null +++ b/client/angular/app/app.component.ts @@ -0,0 +1,63 @@ +import { Component, ElementRef } from 'angular2/core'; +import { RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS } from 'angular2/router'; +import {HTTP_PROVIDERS} from 'angular2/http'; + +import { VideosAddComponent } from '../videos/components/add/videos-add.component'; +import { VideosListComponent } from '../videos/components/list/videos-list.component'; +import { VideosWatchComponent } from '../videos/components/watch/videos-watch.component'; +import { VideosService } from '../videos/services/videos.service'; +import { FriendsService } from '../friends/services/friends.service'; + +@RouteConfig([ + { + path: '/videos/list', + name: 'VideosList', + component: VideosListComponent, + useAsDefault: true + }, + { + path: '/videos/watch/:id', + name: 'VideosWatch', + component: VideosWatchComponent + }, + { + path: '/videos/add', + name: 'VideosAdd', + component: VideosAddComponent + } +]) + +@Component({ + selector: 'my-app', + templateUrl: 'app/angular/app/app.component.html', + styleUrls: [ 'app/angular/app/app.component.css' ], + directives: [ ROUTER_DIRECTIVES ], + providers: [ ROUTER_PROVIDERS, HTTP_PROVIDERS, ElementRef, VideosService, FriendsService ] +}) + +export class AppComponent { + constructor(private _friendsService: FriendsService) {} + + makeFriends() { + this._friendsService.makeFriends().subscribe( + status => { + if (status === 409) { + alert('Already made friends!'); + } + else { + alert('Made friends!'); + } + }, + error => alert(error) + ) + } + + quitFriends() { + this._friendsService.quitFriends().subscribe( + status => { + alert('Quit friends!'); + }, + error => alert(error) + ) + } +} diff --git a/client/components/bootstrap.ts b/client/angular/bootstrap.ts similarity index 100% rename from client/components/bootstrap.ts rename to client/angular/bootstrap.ts diff --git a/client/angular/friends/services/friends.service.ts b/client/angular/friends/services/friends.service.ts new file mode 100644 index 000000000..a34ef0d6f --- /dev/null +++ b/client/angular/friends/services/friends.service.ts @@ -0,0 +1,27 @@ +import {Injectable} from 'angular2/core'; +import {Http, Response, Headers, RequestOptions} from 'angular2/http'; +import {Observable} from 'rxjs/Rx'; + +@Injectable() +export class FriendsService { + private _baseFriendsUrl = '/api/v1/pods/'; + + constructor (private http: Http) {} + + makeFriends() { + return this.http.get(this._baseFriendsUrl + 'makefriends') + .map(res => res.status) + .catch(this.handleError); + } + + quitFriends() { + return this.http.get(this._baseFriendsUrl + 'quitfriends') + .map(res => res.status) + .catch(this.handleError); + } + + private handleError (error: Response) { + console.error(error); + return Observable.throw(error.json().error || 'Server error'); + } +} diff --git a/client/angular/videos/components/add/videos-add.component.html b/client/angular/videos/components/add/videos-add.component.html new file mode 100644 index 000000000..5f28ae650 --- /dev/null +++ b/client/angular/videos/components/add/videos-add.component.html @@ -0,0 +1,39 @@ +

Upload a video

+ +
+
+ + +
+ Name is required +
+
+ +
+ Select the video... + +
+ + {{ fileToUpload.name }} + +
+ + +
+ A description is required +
+
+ +
+ +
+ + +
diff --git a/client/angular/videos/components/add/videos-add.component.scss b/client/angular/videos/components/add/videos-add.component.scss new file mode 100644 index 000000000..f4187088b --- /dev/null +++ b/client/angular/videos/components/add/videos-add.component.scss @@ -0,0 +1,25 @@ +.btn-file { + position: relative; + overflow: hidden; +} + +.btn-file input[type=file] { + position: absolute; + top: 0; + right: 0; + min-width: 100%; + min-height: 100%; + font-size: 100px; + text-align: right; + filter: alpha(opacity=0); + opacity: 0; + outline: none; + background: white; + cursor: inherit; + display: block; +} + +.name_file { + display: inline-block; + margin-left: 10px; +} diff --git a/client/angular/videos/components/add/videos-add.component.ts b/client/angular/videos/components/add/videos-add.component.ts new file mode 100644 index 000000000..97e3bb3b5 --- /dev/null +++ b/client/angular/videos/components/add/videos-add.component.ts @@ -0,0 +1,52 @@ +import {Component, ElementRef, Inject, OnInit} from 'angular2/core'; +import {Router} from 'angular2/router'; +import {NgForm} from 'angular2/common'; + +import {Video} from '../../models/video'; + +declare var jQuery:any; + +@Component({ + selector: 'my-videos-add', + styleUrls: [ 'app/angular/videos/components/add/videos-add.component.css' ], + templateUrl: 'app/angular/videos/components/add/videos-add.component.html' +}) + +export class VideosAddComponent implements OnInit { + fileToUpload: any; + progressBar: { value: number; max: number; } = { value: 0, max: 0 }; + + private _form: any; + + constructor(private _router: Router, private _elementRef: ElementRef) {} + + ngOnInit() { + jQuery(this._elementRef.nativeElement).find('#input_video').fileupload({ + singleFileUploads: true, + multipart: true, + url: '/api/v1/videos', + autoupload: false, + + add: (e, data) => { + this._form = data; + this.fileToUpload = data['files'][0]; + }, + + progressall: (e, data) => { + this.progressBar.value = data.loaded; + this.progressBar.max= data.total; + }, + + done: (e, data) => { + console.log('finished'); + // Print all the videos once it's finished + this._router.navigate(['VideosList']); + } + }); + } + + uploadFile() { + this._form.formData = jQuery(this._elementRef.nativeElement).find('form').serializeArray(); + this._form.submit(); + } +} diff --git a/client/angular/videos/components/list/videos-list.component.html b/client/angular/videos/components/list/videos-list.component.html new file mode 100644 index 000000000..7ecdacee4 --- /dev/null +++ b/client/angular/videos/components/list/videos-list.component.html @@ -0,0 +1,11 @@ +
+
+ {{ video.name }} + {{ video.podUrl }} + +
+ +
+ {{ video.description }} +
+
diff --git a/client/angular/videos/components/list/videos-list.component.scss b/client/angular/videos/components/list/videos-list.component.scss new file mode 100644 index 000000000..82ddd80e5 --- /dev/null +++ b/client/angular/videos/components/list/videos-list.component.scss @@ -0,0 +1,34 @@ +.video { + margin-bottom: 10px; + transition: margin 0.5s ease; + + &:hover { + margin-left: 5px; + } + + a.video_name { + color: #333333; + margin-right: 5px; + } + + .video_pod_url { + font-size: small; + color: rgba(0, 0, 0, 0.5); + } + + .video_description { + font-size: small; + font-style: italic; + margin-left: 7px; + } + + .video_remove { + margin: 5px; + cursor: pointer; + } +} + +.loading { + display: inline-block; + margin-top: 100px; +} diff --git a/client/angular/videos/components/list/videos-list.component.ts b/client/angular/videos/components/list/videos-list.component.ts new file mode 100644 index 000000000..e5af87448 --- /dev/null +++ b/client/angular/videos/components/list/videos-list.component.ts @@ -0,0 +1,39 @@ +import {Component, OnInit} from 'angular2/core'; +import {ROUTER_DIRECTIVES} from 'angular2/router'; + +import {VideosService} from '../../services/videos.service'; +import {Video} from '../../models/video'; + +@Component({ + selector: 'my-videos-list', + styleUrls: [ 'app/angular/videos/components/list/videos-list.component.css' ], + templateUrl: 'app/angular/videos/components/list/videos-list.component.html', + directives: [ ROUTER_DIRECTIVES ] +}) + +export class VideosListComponent implements OnInit { + videos: Video[]; + + constructor( + private _videosService: VideosService + ) { } + + ngOnInit() { + this.getVideos(); + } + + getVideos() { + this._videosService.getVideos().subscribe( + videos => this.videos = videos, + error => alert(error) + ); + } + + removeVideo(id: string) { + this._videosService.removeVideo(id).subscribe( + status => this.getVideos(), + error => alert(error) + ) + } + +} diff --git a/client/angular/videos/components/watch/videos-watch.component.html b/client/angular/videos/components/watch/videos-watch.component.html new file mode 100644 index 000000000..e47222751 --- /dev/null +++ b/client/angular/videos/components/watch/videos-watch.component.html @@ -0,0 +1,2 @@ +
+
diff --git a/client/components/app/app.component.scss b/client/angular/videos/components/watch/videos-watch.component.scss similarity index 100% rename from client/components/app/app.component.scss rename to client/angular/videos/components/watch/videos-watch.component.scss diff --git a/client/angular/videos/components/watch/videos-watch.component.ts b/client/angular/videos/components/watch/videos-watch.component.ts new file mode 100644 index 000000000..e3a973820 --- /dev/null +++ b/client/angular/videos/components/watch/videos-watch.component.ts @@ -0,0 +1,50 @@ +/// + +import { Component, OnInit, ElementRef } from 'angular2/core'; +import { RouteParams } from 'angular2/router'; + +declare var WebTorrent: any; + +import { Video } from '../../models/video'; +import { VideosService } from '../../services/videos.service'; + +@Component({ + selector: 'my-video-watch', + templateUrl: 'app/angular/videos/components/watch/videos-watch.component.html', + styleUrls: [ 'app/angular/videos/components/watch/videos-watch.component.css' ] +}) + +export class VideosWatchComponent { + video: Video; + + private client: any; + + constructor( + private _videosService: VideosService, + private _routeParams: RouteParams, + private _elementRef: ElementRef + ) { + this.client = new WebTorrent({ dht: false }); + } + + ngOnInit() { + let id = this._routeParams.get('id'); + this._videosService.getVideo(id).subscribe( + video => this.loadVideo(video), + error => alert(error) + ); + } + + loadVideo(video: Video) { + this.video = video; + + this.client.add(this.video.magnetUri, (torrent) => { + torrent.files[0].appendTo(this._elementRef.nativeElement, (err) => { + if (err) { + alert('Cannot append the file.'); + console.error(err); + } + }) + }) + } +} diff --git a/client/angular/videos/models/video.ts b/client/angular/videos/models/video.ts new file mode 100644 index 000000000..2f998c49a --- /dev/null +++ b/client/angular/videos/models/video.ts @@ -0,0 +1,6 @@ +export interface Video { + _id: string; + name: string; + description: string; + magnetUri: string; +} diff --git a/client/angular/videos/services/videos.service.ts b/client/angular/videos/services/videos.service.ts new file mode 100644 index 000000000..784eec68d --- /dev/null +++ b/client/angular/videos/services/videos.service.ts @@ -0,0 +1,37 @@ +import {Injectable} from 'angular2/core'; +import {Http, Response} from 'angular2/http'; +import {Observable} from 'rxjs/Rx'; + +import {Video} from '../models/video'; + +@Injectable() +export class VideosService { + private _baseVideoUrl = '/api/v1/videos/'; + + constructor (private http: Http) {} + + getVideos() { + return this.http.get(this._baseVideoUrl) + .map(res => res.json()) + .catch(this.handleError); + } + + getVideo(id: string) { + return this.http.get(this._baseVideoUrl + id) + .map(res =>