]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - client/src/app/shared/video-playlist/video-add-to-playlist.component.ts
Add checkbox focus shadows, and admin resolution descriptions
[github/Chocobozzz/PeerTube.git] / client / src / app / shared / video-playlist / video-add-to-playlist.component.ts
CommitLineData
1c8ddbfa 1import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'
f0a39880
C
2import { VideoPlaylistService } from '@app/shared/video-playlist/video-playlist.service'
3import { AuthService, Notifier } from '@app/core'
c06af501
RK
4import { forkJoin, Subject } from 'rxjs'
5import { debounceTime } from 'rxjs/operators'
f0a39880
C
6import { Video, VideoPlaylistCreate, VideoPlaylistElementCreate, VideoPlaylistPrivacy } from '@shared/models'
7import { FormReactive, FormValidatorService, VideoPlaylistValidatorsService } from '@app/shared/forms'
8import { I18n } from '@ngx-translate/i18n-polyfill'
978c9d49 9import { secondsToTime } from '../../../assets/player/utils'
f0a39880
C
10
11type PlaylistSummary = {
12 id: number
13 inPlaylist: boolean
14 displayName: string
15
a3671f07 16 playlistElementId?: number
f0a39880
C
17 startTimestamp?: number
18 stopTimestamp?: number
19}
20
21@Component({
22 selector: 'my-video-add-to-playlist',
23 styleUrls: [ './video-add-to-playlist.component.scss' ],
8dfceec4
C
24 templateUrl: './video-add-to-playlist.component.html',
25 changeDetection: ChangeDetectionStrategy.OnPush
f0a39880 26})
1c8ddbfa 27export class VideoAddToPlaylistComponent extends FormReactive implements OnInit, OnChanges {
f0a39880
C
28 @Input() video: Video
29 @Input() currentVideoTimestamp: number
3a0fb65c 30 @Input() lazyLoad = false
f0a39880
C
31
32 isNewPlaylistBlockOpened = false
c06af501
RK
33 videoPlaylistSearch: string
34 videoPlaylistSearchChanged = new Subject<string>()
f0a39880
C
35 videoPlaylists: PlaylistSummary[] = []
36 timestampOptions: {
37 startTimestampEnabled: boolean
38 startTimestamp: number
39 stopTimestampEnabled: boolean
40 stopTimestamp: number
41 }
42 displayOptions = false
43
44 constructor (
45 protected formValidatorService: FormValidatorService,
46 private authService: AuthService,
47 private notifier: Notifier,
48 private i18n: I18n,
49 private videoPlaylistService: VideoPlaylistService,
8dfceec4
C
50 private videoPlaylistValidatorsService: VideoPlaylistValidatorsService,
51 private cd: ChangeDetectorRef
f0a39880
C
52 ) {
53 super()
54 }
55
56 get user () {
57 return this.authService.getUser()
58 }
59
60 ngOnInit () {
f0a39880 61 this.buildForm({
978c9d49 62 displayName: this.videoPlaylistValidatorsService.VIDEO_PLAYLIST_DISPLAY_NAME
f0a39880 63 })
c06af501
RK
64
65 this.videoPlaylistSearchChanged
66 .pipe(
67 debounceTime(500))
68 .subscribe(() => {
69 this.load()
70 })
1c8ddbfa
C
71 }
72
73 ngOnChanges (simpleChanges: SimpleChanges) {
74 if (simpleChanges['video']) {
8d51015b 75 this.reload()
1c8ddbfa
C
76 }
77 }
78
625a98bc 79 init () {
1c8ddbfa
C
80 this.resetOptions(true)
81
3a0fb65c
C
82 if (this.lazyLoad !== true) this.load()
83 }
84
8d51015b 85 reload () {
1c8ddbfa 86 this.videoPlaylists = []
c06af501 87 this.videoPlaylistSearch = undefined
1c8ddbfa 88
625a98bc 89 this.init()
1c8ddbfa
C
90
91 this.cd.markForCheck()
92 }
93
3a0fb65c 94 load () {
f0a39880 95 forkJoin([
c06af501 96 this.videoPlaylistService.listAccountPlaylists(this.user.account, undefined, '-updatedAt', this.videoPlaylistSearch),
f0a39880
C
97 this.videoPlaylistService.doesVideoExistInPlaylist(this.video.id)
98 ])
99 .subscribe(
100 ([ playlistsResult, existResult ]) => {
c06af501 101 this.videoPlaylists = []
f0a39880
C
102 for (const playlist of playlistsResult.data) {
103 const existingPlaylist = existResult[ this.video.id ].find(p => p.playlistId === playlist.id)
104
105 this.videoPlaylists.push({
106 id: playlist.id,
107 displayName: playlist.displayName,
108 inPlaylist: !!existingPlaylist,
a3671f07 109 playlistElementId: existingPlaylist ? existingPlaylist.playlistElementId : undefined,
f0a39880
C
110 startTimestamp: existingPlaylist ? existingPlaylist.startTimestamp : undefined,
111 stopTimestamp: existingPlaylist ? existingPlaylist.stopTimestamp : undefined
112 })
113 }
8dfceec4
C
114
115 this.cd.markForCheck()
f0a39880
C
116 }
117 )
118 }
119
120 openChange (opened: boolean) {
121 if (opened === false) {
122 this.isNewPlaylistBlockOpened = false
123 this.displayOptions = false
124 }
125 }
126
127 openCreateBlock (event: Event) {
128 event.preventDefault()
129
130 this.isNewPlaylistBlockOpened = true
131 }
132
133 togglePlaylist (event: Event, playlist: PlaylistSummary) {
134 event.preventDefault()
135
136 if (playlist.inPlaylist === true) {
137 this.removeVideoFromPlaylist(playlist)
138 } else {
139 this.addVideoInPlaylist(playlist)
140 }
141
142 playlist.inPlaylist = !playlist.inPlaylist
143 this.resetOptions()
8dfceec4
C
144
145 this.cd.markForCheck()
f0a39880
C
146 }
147
148 createPlaylist () {
978c9d49 149 const displayName = this.form.value[ 'displayName' ]
f0a39880
C
150
151 const videoPlaylistCreate: VideoPlaylistCreate = {
152 displayName,
153 privacy: VideoPlaylistPrivacy.PRIVATE
154 }
155
156 this.videoPlaylistService.createVideoPlaylist(videoPlaylistCreate).subscribe(
157 res => {
158 this.videoPlaylists.push({
159 id: res.videoPlaylist.id,
160 displayName,
161 inPlaylist: false
162 })
163
164 this.isNewPlaylistBlockOpened = false
8dfceec4
C
165
166 this.cd.markForCheck()
f0a39880
C
167 },
168
169 err => this.notifier.error(err.message)
170 )
171 }
172
173 resetOptions (resetTimestamp = false) {
174 this.displayOptions = false
175
176 this.timestampOptions = {} as any
177 this.timestampOptions.startTimestampEnabled = false
178 this.timestampOptions.stopTimestampEnabled = false
179
180 if (resetTimestamp) {
181 this.timestampOptions.startTimestamp = 0
182 this.timestampOptions.stopTimestamp = this.video.duration
183 }
184 }
185
186 formatTimestamp (playlist: PlaylistSummary) {
187 const start = playlist.startTimestamp ? secondsToTime(playlist.startTimestamp) : ''
188 const stop = playlist.stopTimestamp ? secondsToTime(playlist.stopTimestamp) : ''
189
190 return `(${start}-${stop})`
191 }
192
c06af501
RK
193 onVideoPlaylistSearchChanged () {
194 this.videoPlaylistSearchChanged.next()
195 }
196
f0a39880 197 private removeVideoFromPlaylist (playlist: PlaylistSummary) {
a3671f07 198 if (!playlist.playlistElementId) return
bfbd9128 199
a3671f07 200 this.videoPlaylistService.removeVideoFromPlaylist(playlist.id, playlist.playlistElementId)
f0a39880
C
201 .subscribe(
202 () => {
203 this.notifier.success(this.i18n('Video removed from {{name}}', { name: playlist.displayName }))
204
205 playlist.inPlaylist = false
a3671f07 206 playlist.playlistElementId = undefined
f0a39880
C
207 },
208
209 err => {
210 this.notifier.error(err.message)
211
212 playlist.inPlaylist = true
8dfceec4
C
213 },
214
215 () => this.cd.markForCheck()
f0a39880
C
216 )
217 }
218
219 private addVideoInPlaylist (playlist: PlaylistSummary) {
220 const body: VideoPlaylistElementCreate = { videoId: this.video.id }
221
222 if (this.timestampOptions.startTimestampEnabled) body.startTimestamp = this.timestampOptions.startTimestamp
223 if (this.timestampOptions.stopTimestampEnabled) body.stopTimestamp = this.timestampOptions.stopTimestamp
224
225 this.videoPlaylistService.addVideoInPlaylist(playlist.id, body)
226 .subscribe(
a3671f07 227 res => {
f0a39880 228 playlist.inPlaylist = true
a3671f07 229 playlist.playlistElementId = res.videoPlaylistElement.id
f0a39880
C
230
231 playlist.startTimestamp = body.startTimestamp
232 playlist.stopTimestamp = body.stopTimestamp
233
234 const message = body.startTimestamp || body.stopTimestamp
235 ? this.i18n('Video added in {{n}} at timestamps {{t}}', { n: playlist.displayName, t: this.formatTimestamp(playlist) })
236 : this.i18n('Video added in {{n}}', { n: playlist.displayName })
237
238 this.notifier.success(message)
239 },
240
241 err => {
242 this.notifier.error(err.message)
243
244 playlist.inPlaylist = false
8dfceec4
C
245 },
246
247 () => this.cd.markForCheck()
f0a39880
C
248 )
249 }
250}