aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/+my-account/my-account-videos
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2018-05-09 09:26:41 +0200
committerChocobozzz <me@florianbigard.com>2018-05-09 09:32:26 +0200
commit62e62f118d5da57acd3494fece2e8ed357564ffe (patch)
treeff5b7c6ec5708d71a76a2eb5744d810015ae29a5 /client/src/app/+my-account/my-account-videos
parent1952a538baa330b13bd11631b3975f7ef1c37e70 (diff)
downloadPeerTube-62e62f118d5da57acd3494fece2e8ed357564ffe.tar.gz
PeerTube-62e62f118d5da57acd3494fece2e8ed357564ffe.tar.zst
PeerTube-62e62f118d5da57acd3494fece2e8ed357564ffe.zip
Load my-account module lazily
Diffstat (limited to 'client/src/app/+my-account/my-account-videos')
-rw-r--r--client/src/app/+my-account/my-account-videos/my-account-videos.component.html45
-rw-r--r--client/src/app/+my-account/my-account-videos/my-account-videos.component.scss114
-rw-r--r--client/src/app/+my-account/my-account-videos/my-account-videos.component.ts131
3 files changed, 290 insertions, 0 deletions
diff --git a/client/src/app/+my-account/my-account-videos/my-account-videos.component.html b/client/src/app/+my-account/my-account-videos/my-account-videos.component.html
new file mode 100644
index 000000000..66ce3a77b
--- /dev/null
+++ b/client/src/app/+my-account/my-account-videos/my-account-videos.component.html
@@ -0,0 +1,45 @@
1<div *ngIf="pagination.totalItems === 0">No results.</div>
2
3<div
4 myInfiniteScroller
5 [pageHeight]="pageHeight"
6 (nearOfTop)="onNearOfTop()" (nearOfBottom)="onNearOfBottom()" (pageChanged)="onPageChanged($event)"
7 class="videos" #videosElement
8>
9 <div *ngFor="let videos of videoPages; let i = index" class="videos-page">
10 <div class="video" *ngFor="let video of videos; let j = index">
11 <div class="checkbox-container">
12 <input [id]="'video-check-' + video.id" type="checkbox" [(ngModel)]="checkedVideos[video.id]" />
13 <label [for]="'video-check-' + video.id"></label>
14 </div>
15
16 <my-video-thumbnail [video]="video"></my-video-thumbnail>
17
18 <div class="video-info">
19 <a class="video-info-name" [routerLink]="['/videos/watch', video.uuid]" [attr.title]="video.name">{{ video.name }}</a>
20 <span class="video-info-date-views">{{ video.createdAt | myFromNow }} - {{ video.views | myNumberFormatter }} views</span>
21 <div class="video-info-private">{{ video.privacy.label }}</div>
22 </div>
23
24 <!-- Display only once -->
25 <div class="action-selection-mode" *ngIf="isInSelectionMode() === true && i === 0 && j === 0">
26 <div class="action-selection-mode-child">
27 <span class="action-button action-button-cancel-selection" (click)="abortSelectionMode()">
28 Cancel
29 </span>
30
31 <span class="action-button action-button-delete-selection" (click)="deleteSelectedVideos()">
32 <span class="icon icon-delete-white"></span>
33 Delete
34 </span>
35 </div>
36 </div>
37
38 <div class="video-buttons" *ngIf="isInSelectionMode() === false">
39 <my-delete-button (click)="deleteVideo(video)"></my-delete-button>
40
41 <my-edit-button [routerLink]="[ '/videos', 'edit', video.uuid ]"></my-edit-button>
42 </div>
43 </div>
44 </div>
45</div>
diff --git a/client/src/app/+my-account/my-account-videos/my-account-videos.component.scss b/client/src/app/+my-account/my-account-videos/my-account-videos.component.scss
new file mode 100644
index 000000000..f276ea389
--- /dev/null
+++ b/client/src/app/+my-account/my-account-videos/my-account-videos.component.scss
@@ -0,0 +1,114 @@
1@import '_variables';
2@import '_mixins';
3
4.action-selection-mode {
5 width: 174px;
6 display: flex;
7 justify-content: flex-end;
8
9 .action-selection-mode-child {
10 position: fixed;
11
12 .action-button {
13 display: inline-block;
14 }
15
16 .action-button-cancel-selection {
17 @include peertube-button;
18 @include grey-button;
19
20 margin-right: 10px;
21 }
22
23 .action-button-delete-selection {
24 @include peertube-button;
25 @include orange-button;
26 }
27
28 .icon.icon-delete-white {
29 @include icon(21px);
30
31 position: relative;
32 top: -2px;
33 background-image: url('../../../assets/images/global/delete-white.svg');
34 }
35 }
36}
37
38/deep/ .action-button {
39 &.action-button-delete {
40 margin-right: 10px;
41 }
42}
43
44.video {
45 display: flex;
46 min-height: 130px;
47 padding-bottom: 20px;
48 margin-bottom: 20px;
49 border-bottom: 1px solid #C6C6C6;
50
51 &:first-child {
52 margin-top: 47px;
53 }
54
55 .checkbox-container {
56 display: flex;
57 align-items: center;
58 margin-right: 20px;
59 margin-left: 12px;
60
61 input[type=checkbox] {
62 @include peertube-checkbox(2px);
63 }
64 }
65
66 my-video-thumbnail {
67 margin-right: 10px;
68 }
69
70 .video-info {
71 flex-grow: 1;
72
73 .video-info-name {
74 @include disable-default-a-behaviour;
75
76 color: #000;
77 display: block;
78 font-size: 16px;
79 font-weight: $font-semibold;
80 }
81
82 .video-info-date-views, .video-info-private {
83 font-size: 13px;
84
85 &.video-info-private {
86 font-weight: $font-semibold;
87 }
88 }
89 }
90
91 .video-buttons {
92 min-width: 190px;
93 }
94}
95
96@media screen and (max-width: 800px) {
97 .video {
98 flex-direction: column;
99 height: auto;
100 text-align: center;
101
102 input[type=checkbox] {
103 display: none;
104 }
105
106 my-video-thumbnail {
107 margin-right: 0;
108 }
109
110 .video-buttons {
111 margin-top: 10px;
112 }
113 }
114}
diff --git a/client/src/app/+my-account/my-account-videos/my-account-videos.component.ts b/client/src/app/+my-account/my-account-videos/my-account-videos.component.ts
new file mode 100644
index 000000000..c1b53bcd5
--- /dev/null
+++ b/client/src/app/+my-account/my-account-videos/my-account-videos.component.ts
@@ -0,0 +1,131 @@
1import { Component, OnInit, OnDestroy } from '@angular/core'
2import { ActivatedRoute, Router } from '@angular/router'
3import { Location } from '@angular/common'
4import { immutableAssign } from '@app/shared/misc/utils'
5import { ComponentPagination } from '@app/shared/rest/component-pagination.model'
6import { NotificationsService } from 'angular2-notifications'
7import 'rxjs/add/observable/from'
8import 'rxjs/add/operator/concatAll'
9import { Observable } from 'rxjs/Observable'
10import { AuthService } from '../../core/auth'
11import { ConfirmService } from '../../core/confirm'
12import { AbstractVideoList } from '../../shared/video/abstract-video-list'
13import { Video } from '../../shared/video/video.model'
14import { VideoService } from '../../shared/video/video.service'
15
16@Component({
17 selector: 'my-account-videos',
18 templateUrl: './my-account-videos.component.html',
19 styleUrls: [ './my-account-videos.component.scss' ]
20})
21export class MyAccountVideosComponent extends AbstractVideoList implements OnInit, OnDestroy {
22 titlePage = 'My videos'
23 currentRoute = '/my-account/videos'
24 checkedVideos: { [ id: number ]: boolean } = {}
25 pagination: ComponentPagination = {
26 currentPage: 1,
27 itemsPerPage: 5,
28 totalItems: null
29 }
30
31 protected baseVideoWidth = -1
32 protected baseVideoHeight = 155
33
34 constructor (protected router: Router,
35 protected route: ActivatedRoute,
36 protected authService: AuthService,
37 protected notificationsService: NotificationsService,
38 protected confirmService: ConfirmService,
39 protected location: Location,
40 private videoService: VideoService) {
41 super()
42 }
43
44 ngOnInit () {
45 super.ngOnInit()
46 }
47
48 ngOnDestroy () {
49 super.ngOnDestroy()
50 }
51
52 abortSelectionMode () {
53 this.checkedVideos = {}
54 }
55
56 isInSelectionMode () {
57 return Object.keys(this.checkedVideos).some(k => this.checkedVideos[k] === true)
58 }
59
60 getVideosObservable (page: number) {
61 const newPagination = immutableAssign(this.pagination, { currentPage: page })
62
63 return this.videoService.getMyVideos(newPagination, this.sort)
64 }
65
66 generateSyndicationList () {
67 throw new Error('Method not implemented.')
68 }
69
70 async deleteSelectedVideos () {
71 const toDeleteVideosIds = Object.keys(this.checkedVideos)
72 .filter(k => this.checkedVideos[k] === true)
73 .map(k => parseInt(k, 10))
74
75 const res = await this.confirmService.confirm(`Do you really want to delete ${toDeleteVideosIds.length} videos?`, 'Delete')
76 if (res === false) return
77
78 const observables: Observable<any>[] = []
79 for (const videoId of toDeleteVideosIds) {
80 const o = this.videoService
81 .removeVideo(videoId)
82 .do(() => this.spliceVideosById(videoId))
83
84 observables.push(o)
85 }
86
87 Observable.from(observables)
88 .concatAll()
89 .subscribe(
90 res => {
91 this.notificationsService.success('Success', `${toDeleteVideosIds.length} videos deleted.`)
92 this.buildVideoPages()
93 },
94
95 err => this.notificationsService.error('Error', err.message)
96 )
97 }
98
99 async deleteVideo (video: Video) {
100 const res = await this.confirmService.confirm(`Do you really want to delete ${video.name}?`, 'Delete')
101 if (res === false) return
102
103 this.videoService.removeVideo(video.id)
104 .subscribe(
105 status => {
106 this.notificationsService.success('Success', `Video ${video.name} deleted.`)
107 this.spliceVideosById(video.id)
108 this.buildVideoPages()
109 },
110
111 error => this.notificationsService.error('Error', error.message)
112 )
113 }
114
115 protected buildVideoHeight () {
116 // In account videos, the video height is fixed
117 return this.baseVideoHeight
118 }
119
120 private spliceVideosById (id: number) {
121 for (const key of Object.keys(this.loadedPages)) {
122 const videos = this.loadedPages[key]
123 const index = videos.findIndex(v => v.id === id)
124
125 if (index !== -1) {
126 videos.splice(index, 1)
127 return
128 }
129 }
130 }
131}