aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/+my-account
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2019-03-13 14:18:58 +0100
committerChocobozzz <chocobozzz@cpy.re>2019-03-18 11:17:59 +0100
commite2f01c47e08d26a30ad47068d195b3d21d0df8a1 (patch)
tree21f18ed462d313bfb4ba7a1b5221fdb6b2c35bc1 /client/src/app/+my-account
parent15e9d5ca39e0b792f61453fbf3885a0fc446afa7 (diff)
downloadPeerTube-e2f01c47e08d26a30ad47068d195b3d21d0df8a1.tar.gz
PeerTube-e2f01c47e08d26a30ad47068d195b3d21d0df8a1.tar.zst
PeerTube-e2f01c47e08d26a30ad47068d195b3d21d0df8a1.zip
Playlist support in watch page
Diffstat (limited to 'client/src/app/+my-account')
-rw-r--r--client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.html57
-rw-r--r--client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.scss94
-rw-r--r--client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.ts102
3 files changed, 6 insertions, 247 deletions
diff --git a/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.html b/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.html
index 67a8b1a91..bc26e198e 100644
--- a/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.html
+++ b/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.html
@@ -5,60 +5,7 @@
5 cdkDropList (cdkDropListDropped)="drop($event)" 5 cdkDropList (cdkDropListDropped)="drop($event)"
6> 6>
7 <div class="video" *ngFor="let video of videos" cdkDrag (cdkDragMoved)="onDragMove($event)"> 7 <div class="video" *ngFor="let video of videos" cdkDrag (cdkDragMoved)="onDragMove($event)">
8 <div class="position">{{ video.playlistElement.position }}</div> 8 <my-video-playlist-element-miniature [video]="video" [playlist]="playlist" [owned]="true" (elementRemoved)="onElementRemoved($event)">
9 9 </my-video-playlist-element-miniature>
10 <my-video-thumbnail [video]="video" [nsfw]="isVideoBlur(video)"></my-video-thumbnail>
11
12 <div class="video-info">
13 <a tabindex="-1" class="video-info-name" [routerLink]="['/videos/watch', video.uuid]" [attr.title]="video.name">{{ video.name }}</a>
14 <a tabindex="-1" class="video-info-account" [routerLink]="[ '/accounts', video.byAccount ]">{{ video.byAccount }}</a>
15 <span tabindex="-1" class="video-info-timestamp">{{ formatTimestamp(video)}}</span>
16 </div>
17
18 <div class="more" ngbDropdown #moreDropdown="ngbDropdown" placement="bottom-right" (openChange)="onDropdownOpenChange()" autoClose="outside">
19 <my-global-icon iconName="more-vertical" ngbDropdownToggle role="button" class="icon-more"></my-global-icon>
20
21 <div ngbDropdownMenu>
22 <div class="dropdown-item" (click)="toggleDisplayTimestampsOptions($event, video)">
23 <my-global-icon iconName="edit"></my-global-icon> <ng-container i18n>Edit starts/stops at</ng-container>
24 </div>
25
26 <div class="timestamp-options" *ngIf="displayTimestampOptions">
27 <div>
28 <my-peertube-checkbox
29 inputName="startAt" [(ngModel)]="timestampOptions.startTimestampEnabled"
30 i18n-labelText labelText="Start at"
31 ></my-peertube-checkbox>
32
33 <my-timestamp-input
34 [timestamp]="timestampOptions.startTimestamp"
35 [maxTimestamp]="video.duration"
36 [disabled]="!timestampOptions.startTimestampEnabled"
37 [(ngModel)]="timestampOptions.startTimestamp"
38 ></my-timestamp-input>
39 </div>
40
41 <div>
42 <my-peertube-checkbox
43 inputName="stopAt" [(ngModel)]="timestampOptions.stopTimestampEnabled"
44 i18n-labelText labelText="Stop at"
45 ></my-peertube-checkbox>
46
47 <my-timestamp-input
48 [timestamp]="timestampOptions.stopTimestamp"
49 [maxTimestamp]="video.duration"
50 [disabled]="!timestampOptions.stopTimestampEnabled"
51 [(ngModel)]="timestampOptions.stopTimestamp"
52 ></my-timestamp-input>
53 </div>
54
55 <input type="submit" i18n-value value="Save" (click)="updateTimestamps(video)">
56 </div>
57
58 <span class="dropdown-item" (click)="removeFromPlaylist(video)">
59 <my-global-icon iconName="delete"></my-global-icon> <ng-container i18n>Delete from {{playlist?.displayName}}</ng-container>
60 </span>
61 </div>
62 </div>
63 </div> 10 </div>
64</div> 11</div>
diff --git a/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.scss b/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.scss
index 4ac89d08f..b05af0490 100644
--- a/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.scss
+++ b/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.scss
@@ -2,100 +2,6 @@
2@import '_mixins'; 2@import '_mixins';
3@import '_miniature'; 3@import '_miniature';
4 4
5.video, .cdk-drag-preview {
6 display: flex;
7 align-items: center;
8 background-color: var(--mainBackgroundColor);
9 cursor: pointer;
10 padding: 10px;
11 border-bottom: 1px solid $separator-border-color;
12
13 &:hover {
14 background-color: rgba(0, 0, 0, 0.05);
15
16 .more {
17 display: block;
18 }
19 }
20
21 .position {
22 font-weight: $font-semibold;
23 margin-right: 10px;
24 color: $grey-foreground-color;
25 min-width: 20px;
26 }
27
28 my-video-thumbnail {
29 display: flex; // Avoids an issue with line-height that adds space below the element
30 margin-right: 10px;
31
32 /deep/ .video-thumbnail {
33 @include miniature-thumbnail(130px, 72px);
34 }
35 }
36
37 .video-info {
38 display: flex;
39 flex-direction: column;
40
41 a {
42 @include disable-default-a-behaviour;
43
44 color: var(--mainForegroundColor);
45 }
46
47 .video-info-name {
48 font-size: 18px;
49 font-weight: $font-semibold;
50 }
51
52 .video-info-account, .video-info-timestamp {
53 color: $grey-foreground-color;
54 }
55 }
56
57 .more {
58 justify-self: flex-end;
59 margin-left: auto;
60 cursor: pointer;
61 display: none;
62
63 &.show {
64 display: block;
65 }
66
67 .icon-more {
68 @include apply-svg-color($grey-foreground-color);
69
70 &::after {
71 border: none;
72 }
73 }
74
75 .dropdown-item {
76 @include dropdown-with-icon-item;
77 }
78
79 .timestamp-options {
80 padding-top: 0;
81 padding-left: 35px;
82 margin-bottom: 15px;
83
84 > div {
85 display: flex;
86 align-items: center;
87 }
88
89 input {
90 @include peertube-button;
91 @include orange-button;
92
93 margin-top: 10px;
94 }
95 }
96 }
97}
98
99// Thanks Angular CDK <3 https://material.angular.io/cdk/drag-drop/examples 5// Thanks Angular CDK <3 https://material.angular.io/cdk/drag-drop/examples
100.cdk-drag-preview { 6.cdk-drag-preview {
101 box-sizing: border-box; 7 box-sizing: border-box;
diff --git a/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.ts b/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.ts
index 4076a3721..dcf470be3 100644
--- a/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.ts
+++ b/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.ts
@@ -1,4 +1,4 @@
1import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core' 1import { Component, OnDestroy, OnInit } from '@angular/core'
2import { Notifier, ServerService } from '@app/core' 2import { Notifier, ServerService } from '@app/core'
3import { AuthService } from '../../core/auth' 3import { AuthService } from '../../core/auth'
4import { ConfirmService } from '../../core/confirm' 4import { ConfirmService } from '../../core/confirm'
@@ -10,9 +10,6 @@ import { VideoService } from '@app/shared/video/video.service'
10import { VideoPlaylistService } from '@app/shared/video-playlist/video-playlist.service' 10import { VideoPlaylistService } from '@app/shared/video-playlist/video-playlist.service'
11import { VideoPlaylist } from '@app/shared/video-playlist/video-playlist.model' 11import { VideoPlaylist } from '@app/shared/video-playlist/video-playlist.model'
12import { I18n } from '@ngx-translate/i18n-polyfill' 12import { I18n } from '@ngx-translate/i18n-polyfill'
13import { secondsToTime } from '../../../assets/player/utils'
14import { VideoPlaylistElementUpdate } from '@shared/models'
15import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap'
16import { CdkDragDrop, CdkDragMove } from '@angular/cdk/drag-drop' 13import { CdkDragDrop, CdkDragMove } from '@angular/cdk/drag-drop'
17import { throttleTime } from 'rxjs/operators' 14import { throttleTime } from 'rxjs/operators'
18 15
@@ -22,8 +19,6 @@ import { throttleTime } from 'rxjs/operators'
22 styleUrls: [ './my-account-video-playlist-elements.component.scss' ] 19 styleUrls: [ './my-account-video-playlist-elements.component.scss' ]
23}) 20})
24export class MyAccountVideoPlaylistElementsComponent implements OnInit, OnDestroy { 21export class MyAccountVideoPlaylistElementsComponent implements OnInit, OnDestroy {
25 @ViewChild('moreDropdown') moreDropdown: NgbDropdown
26
27 videos: Video[] = [] 22 videos: Video[] = []
28 playlist: VideoPlaylist 23 playlist: VideoPlaylist
29 24
@@ -33,15 +28,6 @@ export class MyAccountVideoPlaylistElementsComponent implements OnInit, OnDestro
33 totalItems: null 28 totalItems: null
34 } 29 }
35 30
36 displayTimestampOptions = false
37
38 timestampOptions: {
39 startTimestampEnabled: boolean
40 startTimestamp: number
41 stopTimestampEnabled: boolean
42 stopTimestamp: number
43 } = {} as any
44
45 private videoPlaylistId: string | number 31 private videoPlaylistId: string | number
46 private paramsSub: Subscription 32 private paramsSub: Subscription
47 private dragMoveSubject = new Subject<number>() 33 private dragMoveSubject = new Subject<number>()
@@ -124,45 +110,9 @@ export class MyAccountVideoPlaylistElementsComponent implements OnInit, OnDestro
124 // } 110 // }
125 } 111 }
126 112
127 isVideoBlur (video: Video) { 113 onElementRemoved (video: Video) {
128 return video.isVideoNSFWForUser(this.authService.getUser(), this.serverService.getConfig()) 114 this.videos = this.videos.filter(v => v.id !== video.id)
129 } 115 this.reorderClientPositions()
130
131 removeFromPlaylist (video: Video) {
132 this.videoPlaylistService.removeVideoFromPlaylist(this.playlist.id, video.id)
133 .subscribe(
134 () => {
135 this.notifier.success(this.i18n('Video removed from {{name}}', { name: this.playlist.displayName }))
136
137 this.videos = this.videos.filter(v => v.id !== video.id)
138 this.reorderClientPositions()
139 },
140
141 err => this.notifier.error(err.message)
142 )
143
144 this.moreDropdown.close()
145 }
146
147 updateTimestamps (video: Video) {
148 const body: VideoPlaylistElementUpdate = {}
149
150 body.startTimestamp = this.timestampOptions.startTimestampEnabled ? this.timestampOptions.startTimestamp : null
151 body.stopTimestamp = this.timestampOptions.stopTimestampEnabled ? this.timestampOptions.stopTimestamp : null
152
153 this.videoPlaylistService.updateVideoOfPlaylist(this.playlist.id, video.id, body)
154 .subscribe(
155 () => {
156 this.notifier.success(this.i18n('Timestamps updated'))
157
158 video.playlistElement.startTimestamp = body.startTimestamp
159 video.playlistElement.stopTimestamp = body.stopTimestamp
160 },
161
162 err => this.notifier.error(err.message)
163 )
164
165 this.moreDropdown.close()
166 } 116 }
167 117
168 onNearOfBottom () { 118 onNearOfBottom () {
@@ -173,50 +123,6 @@ export class MyAccountVideoPlaylistElementsComponent implements OnInit, OnDestro
173 this.loadElements() 123 this.loadElements()
174 } 124 }
175 125
176 formatTimestamp (video: Video) {
177 const start = video.playlistElement.startTimestamp
178 const stop = video.playlistElement.stopTimestamp
179
180 const startFormatted = secondsToTime(start, true, ':')
181 const stopFormatted = secondsToTime(stop, true, ':')
182
183 if (start === null && stop === null) return ''
184
185 if (start !== null && stop === null) return this.i18n('Starts at ') + startFormatted
186 if (start === null && stop !== null) return this.i18n('Stops at ') + stopFormatted
187
188 return this.i18n('Starts at ') + startFormatted + this.i18n(' and stops at ') + stopFormatted
189 }
190
191 onDropdownOpenChange () {
192 this.displayTimestampOptions = false
193 }
194
195 toggleDisplayTimestampsOptions (event: Event, video: Video) {
196 event.preventDefault()
197
198 this.displayTimestampOptions = !this.displayTimestampOptions
199
200 if (this.displayTimestampOptions === true) {
201 this.timestampOptions = {
202 startTimestampEnabled: false,
203 stopTimestampEnabled: false,
204 startTimestamp: 0,
205 stopTimestamp: video.duration
206 }
207
208 if (video.playlistElement.startTimestamp) {
209 this.timestampOptions.startTimestampEnabled = true
210 this.timestampOptions.startTimestamp = video.playlistElement.startTimestamp
211 }
212
213 if (video.playlistElement.stopTimestamp) {
214 this.timestampOptions.stopTimestampEnabled = true
215 this.timestampOptions.stopTimestamp = video.playlistElement.stopTimestamp
216 }
217 }
218 }
219
220 private loadElements () { 126 private loadElements () {
221 this.videoService.getPlaylistVideos(this.videoPlaylistId, this.pagination) 127 this.videoService.getPlaylistVideos(this.videoPlaylistId, this.pagination)
222 .subscribe(({ totalVideos, videos }) => { 128 .subscribe(({ totalVideos, videos }) => {