aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorkontrollanten <6680299+kontrollanten@users.noreply.github.com>2022-10-24 14:48:03 +0200
committerGitHub <noreply@github.com>2022-10-24 14:48:03 +0200
commit38a3ccc7f8ad0ea94362b58c732af7c387ab46be (patch)
treeccbd200c4b95d0fcfa56b7d5fc3c9490887187b1
parent01a3c07a7913891d4830797403b3865d53f0af61 (diff)
downloadPeerTube-38a3ccc7f8ad0ea94362b58c732af7c387ab46be.tar.gz
PeerTube-38a3ccc7f8ad0ea94362b58c732af7c387ab46be.tar.zst
PeerTube-38a3ccc7f8ad0ea94362b58c732af7c387ab46be.zip
feat: show contained playlists under My videos (#5125)
* feat: show contained playlists under My videos closes #4769 * refactor(server): remove unused types * fixes after code review * fix(client/video-miniature): add to playlist * fix(server/user/me): shortUUID response * Revert "fix(client/video-miniature): add to playlist" This reverts commit f1a0412391c7e2370b87df2594c9fe3f39a40ddc. * fix(client/PlaylistService): caching * Revert "fix(server/user/me): shortUUID response" This reverts commit e3f1ee4e335739b895bced938540c003df24af73. * Fix fetching playlists Co-authored-by: Chocobozzz <me@florianbigard.com>
-rw-r--r--client/src/app/+my-library/my-videos/my-videos.component.html1
-rw-r--r--client/src/app/+my-library/my-videos/my-videos.component.ts28
-rw-r--r--client/src/app/shared/shared-video-miniature/video-miniature.component.html6
-rw-r--r--client/src/app/shared/shared-video-miniature/video-miniature.component.scss4
-rw-r--r--client/src/app/shared/shared-video-miniature/video-miniature.component.ts3
-rw-r--r--client/src/app/shared/shared-video-miniature/videos-selection.component.html1
-rw-r--r--client/src/app/shared/shared-video-miniature/videos-selection.component.ts3
-rw-r--r--client/src/app/shared/shared-video-playlist/video-add-to-playlist.component.ts4
-rw-r--r--client/src/app/shared/shared-video-playlist/video-playlist.service.ts12
-rw-r--r--server/controllers/api/users/my-video-playlists.ts5
-rw-r--r--server/models/video/video-playlist.ts6
-rw-r--r--server/tests/api/videos/video-playlists.ts12
-rw-r--r--server/types/models/video/video-playlist.ts12
-rw-r--r--shared/models/videos/playlist/video-exist-in-playlist.model.ts10
14 files changed, 79 insertions, 28 deletions
diff --git a/client/src/app/+my-library/my-videos/my-videos.component.html b/client/src/app/+my-library/my-videos/my-videos.component.html
index 146dcf41e..995f6b75b 100644
--- a/client/src/app/+my-library/my-videos/my-videos.component.html
+++ b/client/src/app/+my-library/my-videos/my-videos.component.html
@@ -34,6 +34,7 @@
34</div> 34</div>
35 35
36<my-videos-selection 36<my-videos-selection
37 [videosContainedInPlaylists]="videosContainedInPlaylists"
37 [pagination]="pagination" 38 [pagination]="pagination"
38 [(selection)]="selection" 39 [(selection)]="selection"
39 [(videosModel)]="videos" 40 [(videosModel)]="videos"
diff --git a/client/src/app/+my-library/my-videos/my-videos.component.ts b/client/src/app/+my-library/my-videos/my-videos.component.ts
index 3ff0ee248..f5262da86 100644
--- a/client/src/app/+my-library/my-videos/my-videos.component.ts
+++ b/client/src/app/+my-library/my-videos/my-videos.component.ts
@@ -1,10 +1,11 @@
1import { uniqBy } from 'lodash'
1import { concat, Observable } from 'rxjs' 2import { concat, Observable } from 'rxjs'
2import { tap, toArray } from 'rxjs/operators' 3import { tap, toArray } from 'rxjs/operators'
3import { Component, OnInit, ViewChild } from '@angular/core' 4import { Component, OnInit, ViewChild } from '@angular/core'
4import { ActivatedRoute, Router } from '@angular/router' 5import { ActivatedRoute, Router } from '@angular/router'
5import { AuthService, ComponentPagination, ConfirmService, Notifier, ScreenService, ServerService, User } from '@app/core' 6import { AuthService, ComponentPagination, ConfirmService, Notifier, ScreenService, ServerService, User } from '@app/core'
6import { DisableForReuseHook } from '@app/core/routing/disable-for-reuse-hook' 7import { DisableForReuseHook } from '@app/core/routing/disable-for-reuse-hook'
7import { prepareIcu, immutableAssign } from '@app/helpers' 8import { immutableAssign, prepareIcu } from '@app/helpers'
8import { AdvancedInputFilter } from '@app/shared/shared-forms' 9import { AdvancedInputFilter } from '@app/shared/shared-forms'
9import { DropdownAction, Video, VideoService } from '@app/shared/shared-main' 10import { DropdownAction, Video, VideoService } from '@app/shared/shared-main'
10import { LiveStreamInformationComponent } from '@app/shared/shared-video-live' 11import { LiveStreamInformationComponent } from '@app/shared/shared-video-live'
@@ -14,7 +15,8 @@ import {
14 VideoActionsDisplayType, 15 VideoActionsDisplayType,
15 VideosSelectionComponent 16 VideosSelectionComponent
16} from '@app/shared/shared-video-miniature' 17} from '@app/shared/shared-video-miniature'
17import { VideoChannel, VideoSortField } from '@shared/models' 18import { VideoPlaylistService } from '@app/shared/shared-video-playlist'
19import { VideoChannel, VideoExistInPlaylist, VideosExistInPlaylists, VideoSortField } from '@shared/models'
18import { VideoChangeOwnershipComponent } from './modals/video-change-ownership.component' 20import { VideoChangeOwnershipComponent } from './modals/video-change-ownership.component'
19 21
20@Component({ 22@Component({
@@ -26,6 +28,7 @@ export class MyVideosComponent implements OnInit, DisableForReuseHook {
26 @ViewChild('videoChangeOwnershipModal', { static: true }) videoChangeOwnershipModal: VideoChangeOwnershipComponent 28 @ViewChild('videoChangeOwnershipModal', { static: true }) videoChangeOwnershipModal: VideoChangeOwnershipComponent
27 @ViewChild('liveStreamInformationModal', { static: true }) liveStreamInformationModal: LiveStreamInformationComponent 29 @ViewChild('liveStreamInformationModal', { static: true }) liveStreamInformationModal: LiveStreamInformationComponent
28 30
31 videosContainedInPlaylists: VideosExistInPlaylists = {}
29 titlePage: string 32 titlePage: string
30 selection: SelectionType = {} 33 selection: SelectionType = {}
31 pagination: ComponentPagination = { 34 pagination: ComponentPagination = {
@@ -83,7 +86,8 @@ export class MyVideosComponent implements OnInit, DisableForReuseHook {
83 protected notifier: Notifier, 86 protected notifier: Notifier,
84 protected screenService: ScreenService, 87 protected screenService: ScreenService,
85 private confirmService: ConfirmService, 88 private confirmService: ConfirmService,
86 private videoService: VideoService 89 private videoService: VideoService,
90 private playlistService: VideoPlaylistService
87 ) { 91 ) {
88 this.titlePage = $localize`My videos` 92 this.titlePage = $localize`My videos`
89 } 93 }
@@ -156,10 +160,20 @@ export class MyVideosComponent implements OnInit, DisableForReuseHook {
156 sort: this.sort, 160 sort: this.sort,
157 userChannels: this.userChannels, 161 userChannels: this.userChannels,
158 search: this.search 162 search: this.search
159 }) 163 }).pipe(
160 .pipe( 164 tap(res => this.pagination.totalItems = res.total),
161 tap(res => this.pagination.totalItems = res.total) 165 tap(({ data }) => this.fetchVideosContainedInPlaylists(data))
162 ) 166 )
167 }
168
169 private fetchVideosContainedInPlaylists (videos: Video[]) {
170 this.playlistService.doVideosExistInPlaylist(videos.map(v => v.id))
171 .subscribe(result => {
172 this.videosContainedInPlaylists = Object.keys(result).reduce((acc, videoId) => ({
173 ...acc,
174 [videoId]: uniqBy(result[videoId], (p: VideoExistInPlaylist) => p.playlistId)
175 }), this.videosContainedInPlaylists)
176 })
163 } 177 }
164 178
165 async deleteSelectedVideos () { 179 async deleteSelectedVideos () {
diff --git a/client/src/app/shared/shared-video-miniature/video-miniature.component.html b/client/src/app/shared/shared-video-miniature/video-miniature.component.html
index e8d2ca1c4..6fdf24b2d 100644
--- a/client/src/app/shared/shared-video-miniature/video-miniature.component.html
+++ b/client/src/app/shared/shared-video-miniature/video-miniature.component.html
@@ -52,6 +52,12 @@
52 <ng-container *ngIf="displayOptions.privacyText && displayOptions.state && getStateLabel(video)"> - </ng-container> 52 <ng-container *ngIf="displayOptions.privacyText && displayOptions.state && getStateLabel(video)"> - </ng-container>
53 <ng-container *ngIf="displayOptions.state">{{ getStateLabel(video) }}</ng-container> 53 <ng-container *ngIf="displayOptions.state">{{ getStateLabel(video) }}</ng-container>
54 </div> 54 </div>
55
56 <div *ngIf="containedInPlaylists" class="video-contained-in-playlists">
57 <a *ngFor="let playlist of containedInPlaylists" class="chip rectangular bg-secondary text-light" [routerLink]="['/w/p/', playlist.playlistShortUUID]">
58 {{ playlist.playlistDisplayName }}
59 </a>
60 </div>
55 </div> 61 </div>
56 </div> 62 </div>
57 63
diff --git a/client/src/app/shared/shared-video-miniature/video-miniature.component.scss b/client/src/app/shared/shared-video-miniature/video-miniature.component.scss
index a397efdca..ba2adfc5a 100644
--- a/client/src/app/shared/shared-video-miniature/video-miniature.component.scss
+++ b/client/src/app/shared/shared-video-miniature/video-miniature.component.scss
@@ -4,6 +4,10 @@
4 4
5$more-button-width: 40px; 5$more-button-width: 40px;
6 6
7.chip {
8 @include chip;
9}
10
7.video-miniature { 11.video-miniature {
8 font-size: 14px; 12 font-size: 14px;
9} 13}
diff --git a/client/src/app/shared/shared-video-miniature/video-miniature.component.ts b/client/src/app/shared/shared-video-miniature/video-miniature.component.ts
index 20596d6d0..85c63c173 100644
--- a/client/src/app/shared/shared-video-miniature/video-miniature.component.ts
+++ b/client/src/app/shared/shared-video-miniature/video-miniature.component.ts
@@ -11,7 +11,7 @@ import {
11 Output 11 Output
12} from '@angular/core' 12} from '@angular/core'
13import { AuthService, ScreenService, ServerService, User } from '@app/core' 13import { AuthService, ScreenService, ServerService, User } from '@app/core'
14import { HTMLServerConfig, VideoPlaylistType, VideoPrivacy, VideoState } from '@shared/models' 14import { HTMLServerConfig, VideoExistInPlaylist, VideoPlaylistType, VideoPrivacy, VideoState } from '@shared/models'
15import { LinkType } from '../../../types/link.type' 15import { LinkType } from '../../../types/link.type'
16import { ActorAvatarSize } from '../shared-actor-image/actor-avatar.component' 16import { ActorAvatarSize } from '../shared-actor-image/actor-avatar.component'
17import { Video } from '../shared-main' 17import { Video } from '../shared-main'
@@ -40,6 +40,7 @@ export type MiniatureDisplayOptions = {
40export class VideoMiniatureComponent implements OnInit { 40export class VideoMiniatureComponent implements OnInit {
41 @Input() user: User 41 @Input() user: User
42 @Input() video: Video 42 @Input() video: Video
43 @Input() containedInPlaylists: VideoExistInPlaylist[]
43 44
44 @Input() displayOptions: MiniatureDisplayOptions = { 45 @Input() displayOptions: MiniatureDisplayOptions = {
45 date: true, 46 date: true,
diff --git a/client/src/app/shared/shared-video-miniature/videos-selection.component.html b/client/src/app/shared/shared-video-miniature/videos-selection.component.html
index 6ea2661e4..6c6db4b96 100644
--- a/client/src/app/shared/shared-video-miniature/videos-selection.component.html
+++ b/client/src/app/shared/shared-video-miniature/videos-selection.component.html
@@ -12,6 +12,7 @@
12 </div> 12 </div>
13 13
14 <my-video-miniature 14 <my-video-miniature
15 [containedInPlaylists]="videosContainedInPlaylists ? videosContainedInPlaylists[video.id] : undefined"
15 [video]="video" [displayAsRow]="true" [displayOptions]="miniatureDisplayOptions" 16 [video]="video" [displayAsRow]="true" [displayOptions]="miniatureDisplayOptions"
16 [displayVideoActions]="false" [user]="user" 17 [displayVideoActions]="false" [user]="user"
17 ></my-video-miniature> 18 ></my-video-miniature>
diff --git a/client/src/app/shared/shared-video-miniature/videos-selection.component.ts b/client/src/app/shared/shared-video-miniature/videos-selection.component.ts
index fa3c79bbb..460a0080e 100644
--- a/client/src/app/shared/shared-video-miniature/videos-selection.component.ts
+++ b/client/src/app/shared/shared-video-miniature/videos-selection.component.ts
@@ -2,7 +2,7 @@ import { Observable, Subject } from 'rxjs'
2import { AfterContentInit, Component, ContentChildren, EventEmitter, Input, Output, QueryList, TemplateRef } from '@angular/core' 2import { AfterContentInit, Component, ContentChildren, EventEmitter, Input, Output, QueryList, TemplateRef } from '@angular/core'
3import { ComponentPagination, Notifier, User } from '@app/core' 3import { ComponentPagination, Notifier, User } from '@app/core'
4import { logger } from '@root-helpers/logger' 4import { logger } from '@root-helpers/logger'
5import { ResultList, VideoSortField } from '@shared/models' 5import { ResultList, VideosExistInPlaylists, VideoSortField } from '@shared/models'
6import { PeerTubeTemplateDirective, Video } from '../shared-main' 6import { PeerTubeTemplateDirective, Video } from '../shared-main'
7import { MiniatureDisplayOptions } from './video-miniature.component' 7import { MiniatureDisplayOptions } from './video-miniature.component'
8 8
@@ -14,6 +14,7 @@ export type SelectionType = { [ id: number ]: boolean }
14 styleUrls: [ './videos-selection.component.scss' ] 14 styleUrls: [ './videos-selection.component.scss' ]
15}) 15})
16export class VideosSelectionComponent implements AfterContentInit { 16export class VideosSelectionComponent implements AfterContentInit {
17 @Input() videosContainedInPlaylists: VideosExistInPlaylists
17 @Input() user: User 18 @Input() user: User
18 @Input() pagination: ComponentPagination 19 @Input() pagination: ComponentPagination
19 20
diff --git a/client/src/app/shared/shared-video-playlist/video-add-to-playlist.component.ts b/client/src/app/shared/shared-video-playlist/video-add-to-playlist.component.ts
index f81de7c6b..2fc39fc75 100644
--- a/client/src/app/shared/shared-video-playlist/video-add-to-playlist.component.ts
+++ b/client/src/app/shared/shared-video-playlist/video-add-to-playlist.component.ts
@@ -6,8 +6,8 @@ import { AuthService, DisableForReuseHook, Notifier } from '@app/core'
6import { FormReactive, FormReactiveService } from '@app/shared/shared-forms' 6import { FormReactive, FormReactiveService } from '@app/shared/shared-forms'
7import { secondsToTime } from '@shared/core-utils' 7import { secondsToTime } from '@shared/core-utils'
8import { 8import {
9 CachedVideoExistInPlaylist,
9 Video, 10 Video,
10 VideoExistInPlaylist,
11 VideoPlaylistCreate, 11 VideoPlaylistCreate,
12 VideoPlaylistElementCreate, 12 VideoPlaylistElementCreate,
13 VideoPlaylistElementUpdate, 13 VideoPlaylistElementUpdate,
@@ -330,7 +330,7 @@ export class VideoAddToPlaylistComponent extends FormReactive implements OnInit,
330 } 330 }
331 } 331 }
332 332
333 private rebuildPlaylists (existResult: VideoExistInPlaylist[]) { 333 private rebuildPlaylists (existResult: CachedVideoExistInPlaylist[]) {
334 debugLogger('Got existing results for %d.', this.video.id, existResult) 334 debugLogger('Got existing results for %d.', this.video.id, existResult)
335 335
336 const oldPlaylists = this.videoPlaylists 336 const oldPlaylists = this.videoPlaylists
diff --git a/client/src/app/shared/shared-video-playlist/video-playlist.service.ts b/client/src/app/shared/shared-video-playlist/video-playlist.service.ts
index d71f8f72e..330a51f91 100644
--- a/client/src/app/shared/shared-video-playlist/video-playlist.service.ts
+++ b/client/src/app/shared/shared-video-playlist/video-playlist.service.ts
@@ -8,6 +8,8 @@ import { buildBulkObservable, objectToFormData } from '@app/helpers'
8import { Account, AccountService, VideoChannel, VideoChannelService } from '@app/shared/shared-main' 8import { Account, AccountService, VideoChannel, VideoChannelService } from '@app/shared/shared-main'
9import { NGX_LOADING_BAR_IGNORED } from '@ngx-loading-bar/http-client' 9import { NGX_LOADING_BAR_IGNORED } from '@ngx-loading-bar/http-client'
10import { 10import {
11 CachedVideoExistInPlaylist,
12 CachedVideosExistInPlaylists,
11 ResultList, 13 ResultList,
12 VideoExistInPlaylist, 14 VideoExistInPlaylist,
13 VideoPlaylist as VideoPlaylistServerModel, 15 VideoPlaylist as VideoPlaylistServerModel,
@@ -34,11 +36,11 @@ export class VideoPlaylistService {
34 36
35 // Use a replay subject because we "next" a value before subscribing 37 // Use a replay subject because we "next" a value before subscribing
36 private videoExistsInPlaylistNotifier = new ReplaySubject<number>(1) 38 private videoExistsInPlaylistNotifier = new ReplaySubject<number>(1)
37 private videoExistsInPlaylistCacheSubject = new Subject<VideosExistInPlaylists>() 39 private videoExistsInPlaylistCacheSubject = new Subject<CachedVideosExistInPlaylists>()
38 private readonly videoExistsInPlaylistObservable: Observable<VideosExistInPlaylists> 40 private readonly videoExistsInPlaylistObservable: Observable<CachedVideosExistInPlaylists>
39 41
40 private videoExistsObservableCache: { [ id: number ]: Observable<VideoExistInPlaylist[]> } = {} 42 private videoExistsObservableCache: { [ id: number ]: Observable<CachedVideoExistInPlaylist[]> } = {}
41 private videoExistsCache: { [ id: number ]: VideoExistInPlaylist[] } = {} 43 private videoExistsCache: { [ id: number ]: CachedVideoExistInPlaylist[] } = {}
42 44
43 private myAccountPlaylistCache: ResultList<CachedPlaylist> = undefined 45 private myAccountPlaylistCache: ResultList<CachedPlaylist> = undefined
44 private myAccountPlaylistCacheRunning: Observable<ResultList<CachedPlaylist>> 46 private myAccountPlaylistCacheRunning: Observable<ResultList<CachedPlaylist>>
@@ -346,7 +348,7 @@ export class VideoPlaylistService {
346 ) 348 )
347 } 349 }
348 350
349 private doVideosExistInPlaylist (videoIds: number[]): Observable<VideosExistInPlaylists> { 351 doVideosExistInPlaylist (videoIds: number[]): Observable<VideosExistInPlaylists> {
350 const url = VideoPlaylistService.MY_VIDEO_PLAYLIST_URL + 'videos-exist' 352 const url = VideoPlaylistService.MY_VIDEO_PLAYLIST_URL + 'videos-exist'
351 353
352 let params = new HttpParams() 354 let params = new HttpParams()
diff --git a/server/controllers/api/users/my-video-playlists.ts b/server/controllers/api/users/my-video-playlists.ts
index f55ea2ec4..715717610 100644
--- a/server/controllers/api/users/my-video-playlists.ts
+++ b/server/controllers/api/users/my-video-playlists.ts
@@ -1,3 +1,4 @@
1import { uuidToShort } from '@shared/extra-utils'
1import express from 'express' 2import express from 'express'
2import { VideosExistInPlaylists } from '../../../../shared/models/videos/playlist/video-exist-in-playlist.model' 3import { VideosExistInPlaylists } from '../../../../shared/models/videos/playlist/video-exist-in-playlist.model'
3import { asyncMiddleware, authenticate } from '../../../middlewares' 4import { asyncMiddleware, authenticate } from '../../../middlewares'
@@ -24,7 +25,7 @@ async function doVideosInPlaylistExist (req: express.Request, res: express.Respo
24 const videoIds = req.query.videoIds.map(i => parseInt(i + '', 10)) 25 const videoIds = req.query.videoIds.map(i => parseInt(i + '', 10))
25 const user = res.locals.oauth.token.User 26 const user = res.locals.oauth.token.User
26 27
27 const results = await VideoPlaylistModel.listPlaylistIdsOf(user.Account.id, videoIds) 28 const results = await VideoPlaylistModel.listPlaylistSummariesOf(user.Account.id, videoIds)
28 29
29 const existObject: VideosExistInPlaylists = {} 30 const existObject: VideosExistInPlaylists = {}
30 31
@@ -37,6 +38,8 @@ async function doVideosInPlaylistExist (req: express.Request, res: express.Respo
37 existObject[element.videoId].push({ 38 existObject[element.videoId].push({
38 playlistElementId: element.id, 39 playlistElementId: element.id,
39 playlistId: result.id, 40 playlistId: result.id,
41 playlistDisplayName: result.name,
42 playlistShortUUID: uuidToShort(result.uuid),
40 startTimestamp: element.startTimestamp, 43 startTimestamp: element.startTimestamp,
41 stopTimestamp: element.stopTimestamp 44 stopTimestamp: element.stopTimestamp
42 }) 45 })
diff --git a/server/models/video/video-playlist.ts b/server/models/video/video-playlist.ts
index 81ce3dc9e..8bbe54c49 100644
--- a/server/models/video/video-playlist.ts
+++ b/server/models/video/video-playlist.ts
@@ -49,7 +49,7 @@ import {
49 MVideoPlaylistFormattable, 49 MVideoPlaylistFormattable,
50 MVideoPlaylistFull, 50 MVideoPlaylistFull,
51 MVideoPlaylistFullSummary, 51 MVideoPlaylistFullSummary,
52 MVideoPlaylistIdWithElements 52 MVideoPlaylistSummaryWithElements
53} from '../../types/models/video/video-playlist' 53} from '../../types/models/video/video-playlist'
54import { AccountModel, ScopeNames as AccountScopeNames, SummaryOptions } from '../account/account' 54import { AccountModel, ScopeNames as AccountScopeNames, SummaryOptions } from '../account/account'
55import { ActorModel } from '../actor/actor' 55import { ActorModel } from '../actor/actor'
@@ -470,9 +470,9 @@ export class VideoPlaylistModel extends Model<Partial<AttributesOnly<VideoPlayli
470 })) 470 }))
471 } 471 }
472 472
473 static listPlaylistIdsOf (accountId: number, videoIds: number[]): Promise<MVideoPlaylistIdWithElements[]> { 473 static listPlaylistSummariesOf (accountId: number, videoIds: number[]): Promise<MVideoPlaylistSummaryWithElements[]> {
474 const query = { 474 const query = {
475 attributes: [ 'id' ], 475 attributes: [ 'id', 'name', 'uuid' ],
476 where: { 476 where: {
477 ownerAccountId: accountId 477 ownerAccountId: accountId
478 }, 478 },
diff --git a/server/tests/api/videos/video-playlists.ts b/server/tests/api/videos/video-playlists.ts
index 9d223de48..a3de73ba5 100644
--- a/server/tests/api/videos/video-playlists.ts
+++ b/server/tests/api/videos/video-playlists.ts
@@ -23,6 +23,7 @@ import {
23 setDefaultVideoChannel, 23 setDefaultVideoChannel,
24 waitJobs 24 waitJobs
25} from '@shared/server-commands' 25} from '@shared/server-commands'
26import { uuidToShort } from '@shared/extra-utils'
26 27
27async function checkPlaylistElementType ( 28async function checkPlaylistElementType (
28 servers: PeerTubeServer[], 29 servers: PeerTubeServer[],
@@ -56,6 +57,7 @@ describe('Test video playlists', function () {
56 let playlistServer2UUID2: string 57 let playlistServer2UUID2: string
57 58
58 let playlistServer1Id: number 59 let playlistServer1Id: number
60 let playlistServer1DisplayName: string
59 let playlistServer1UUID: string 61 let playlistServer1UUID: string
60 let playlistServer1UUID2: string 62 let playlistServer1UUID2: string
61 63
@@ -489,15 +491,17 @@ describe('Test video playlists', function () {
489 return commands[0].addElement({ playlistId: playlistServer1Id, attributes }) 491 return commands[0].addElement({ playlistId: playlistServer1Id, attributes })
490 } 492 }
491 493
494 const playlistDisplayName = 'playlist 4'
492 const playlist = await commands[0].create({ 495 const playlist = await commands[0].create({
493 attributes: { 496 attributes: {
494 displayName: 'playlist 4', 497 displayName: playlistDisplayName,
495 privacy: VideoPlaylistPrivacy.PUBLIC, 498 privacy: VideoPlaylistPrivacy.PUBLIC,
496 videoChannelId: servers[0].store.channel.id 499 videoChannelId: servers[0].store.channel.id
497 } 500 }
498 }) 501 })
499 502
500 playlistServer1Id = playlist.id 503 playlistServer1Id = playlist.id
504 playlistServer1DisplayName = playlistDisplayName
501 playlistServer1UUID = playlist.uuid 505 playlistServer1UUID = playlist.uuid
502 506
503 await addVideo({ videoId: servers[0].store.videos[0].uuid, startTimestamp: 15, stopTimestamp: 28 }) 507 await addVideo({ videoId: servers[0].store.videos[0].uuid, startTimestamp: 15, stopTimestamp: 28 })
@@ -908,6 +912,8 @@ describe('Test video playlists', function () {
908 const elem = obj[servers[0].store.videos[0].id] 912 const elem = obj[servers[0].store.videos[0].id]
909 expect(elem).to.have.lengthOf(1) 913 expect(elem).to.have.lengthOf(1)
910 expect(elem[0].playlistElementId).to.exist 914 expect(elem[0].playlistElementId).to.exist
915 expect(elem[0].playlistDisplayName).to.equal(playlistServer1DisplayName)
916 expect(elem[0].playlistShortUUID).to.equal(uuidToShort(playlistServer1UUID))
911 expect(elem[0].playlistId).to.equal(playlistServer1Id) 917 expect(elem[0].playlistId).to.equal(playlistServer1Id)
912 expect(elem[0].startTimestamp).to.equal(15) 918 expect(elem[0].startTimestamp).to.equal(15)
913 expect(elem[0].stopTimestamp).to.equal(28) 919 expect(elem[0].stopTimestamp).to.equal(28)
@@ -917,6 +923,8 @@ describe('Test video playlists', function () {
917 const elem = obj[servers[0].store.videos[3].id] 923 const elem = obj[servers[0].store.videos[3].id]
918 expect(elem).to.have.lengthOf(1) 924 expect(elem).to.have.lengthOf(1)
919 expect(elem[0].playlistElementId).to.equal(playlistElementServer1Video4) 925 expect(elem[0].playlistElementId).to.equal(playlistElementServer1Video4)
926 expect(elem[0].playlistDisplayName).to.equal(playlistServer1DisplayName)
927 expect(elem[0].playlistShortUUID).to.equal(uuidToShort(playlistServer1UUID))
920 expect(elem[0].playlistId).to.equal(playlistServer1Id) 928 expect(elem[0].playlistId).to.equal(playlistServer1Id)
921 expect(elem[0].startTimestamp).to.equal(1) 929 expect(elem[0].startTimestamp).to.equal(1)
922 expect(elem[0].stopTimestamp).to.equal(35) 930 expect(elem[0].stopTimestamp).to.equal(35)
@@ -926,6 +934,8 @@ describe('Test video playlists', function () {
926 const elem = obj[servers[0].store.videos[4].id] 934 const elem = obj[servers[0].store.videos[4].id]
927 expect(elem).to.have.lengthOf(1) 935 expect(elem).to.have.lengthOf(1)
928 expect(elem[0].playlistId).to.equal(playlistServer1Id) 936 expect(elem[0].playlistId).to.equal(playlistServer1Id)
937 expect(elem[0].playlistDisplayName).to.equal(playlistServer1DisplayName)
938 expect(elem[0].playlistShortUUID).to.equal(uuidToShort(playlistServer1UUID))
929 expect(elem[0].startTimestamp).to.equal(45) 939 expect(elem[0].startTimestamp).to.equal(45)
930 expect(elem[0].stopTimestamp).to.equal(null) 940 expect(elem[0].stopTimestamp).to.equal(null)
931 } 941 }
diff --git a/server/types/models/video/video-playlist.ts b/server/types/models/video/video-playlist.ts
index 33fe5416a..40f0dfc14 100644
--- a/server/types/models/video/video-playlist.ts
+++ b/server/types/models/video/video-playlist.ts
@@ -14,6 +14,10 @@ export type MVideoPlaylist = Omit<VideoPlaylistModel, 'OwnerAccount' | 'VideoCha
14// ############################################################################ 14// ############################################################################
15 15
16export type MVideoPlaylistId = Pick<MVideoPlaylist, 'id'> 16export type MVideoPlaylistId = Pick<MVideoPlaylist, 'id'>
17export type MVideoPlaylistSummary =
18 Pick<MVideoPlaylist, 'id'> &
19 Pick<MVideoPlaylist, 'name'> &
20 Pick<MVideoPlaylist, 'uuid'>
17export type MVideoPlaylistPrivacy = Pick<MVideoPlaylist, 'privacy'> 21export type MVideoPlaylistPrivacy = Pick<MVideoPlaylist, 'privacy'>
18export type MVideoPlaylistUUID = Pick<MVideoPlaylist, 'uuid'> 22export type MVideoPlaylistUUID = Pick<MVideoPlaylist, 'uuid'>
19export type MVideoPlaylistVideosLength = MVideoPlaylist & { videosLength?: number } 23export type MVideoPlaylistVideosLength = MVideoPlaylist & { videosLength?: number }
@@ -22,12 +26,8 @@ export type MVideoPlaylistVideosLength = MVideoPlaylist & { videosLength?: numbe
22 26
23// With elements 27// With elements
24 28
25export type MVideoPlaylistWithElements = 29export type MVideoPlaylistSummaryWithElements =
26 MVideoPlaylist & 30 MVideoPlaylistSummary &
27 Use<'VideoPlaylistElements', MVideoPlaylistElementLight[]>
28
29export type MVideoPlaylistIdWithElements =
30 MVideoPlaylistId &
31 Use<'VideoPlaylistElements', MVideoPlaylistElementLight[]> 31 Use<'VideoPlaylistElements', MVideoPlaylistElementLight[]>
32 32
33// ############################################################################ 33// ############################################################################
diff --git a/shared/models/videos/playlist/video-exist-in-playlist.model.ts b/shared/models/videos/playlist/video-exist-in-playlist.model.ts
index fc979c8c0..bc803a99c 100644
--- a/shared/models/videos/playlist/video-exist-in-playlist.model.ts
+++ b/shared/models/videos/playlist/video-exist-in-playlist.model.ts
@@ -1,10 +1,18 @@
1export type VideosExistInPlaylists = { 1export type VideosExistInPlaylists = {
2 [videoId: number ]: VideoExistInPlaylist[] 2 [videoId: number ]: VideoExistInPlaylist[]
3} 3}
4export type CachedVideosExistInPlaylists = {
5 [videoId: number ]: CachedVideoExistInPlaylist[]
6}
4 7
5export type VideoExistInPlaylist = { 8export type CachedVideoExistInPlaylist = {
6 playlistElementId: number 9 playlistElementId: number
7 playlistId: number 10 playlistId: number
8 startTimestamp?: number 11 startTimestamp?: number
9 stopTimestamp?: number 12 stopTimestamp?: number
10} 13}
14
15export type VideoExistInPlaylist = CachedVideoExistInPlaylist & {
16 playlistDisplayName: string
17 playlistShortUUID: string
18}