diff --git a/src/app/components/custom-playlists/custom-playlists.component.ts b/src/app/components/custom-playlists/custom-playlists.component.ts index 1c4aa3b..3dec80a 100644 --- a/src/app/components/custom-playlists/custom-playlists.component.ts +++ b/src/app/components/custom-playlists/custom-playlists.component.ts @@ -45,6 +45,9 @@ export class CustomPlaylistsComponent implements OnInit { // creating a playlist openCreatePlaylistDialog(): void { const dialogRef = this.dialog.open(CreatePlaylistComponent, { + data: { + create_mode: true + }, minWidth: '90vw', minHeight: '95vh' }); @@ -103,9 +106,10 @@ export class CustomPlaylistsComponent implements OnInit { editPlaylistDialog(args: { playlist: Playlist; index: number; }): void { const playlist = args.playlist; const index = args.index; - const dialogRef = this.dialog.open(ModifyPlaylistComponent, { + const dialogRef = this.dialog.open(CreatePlaylistComponent, { data: { - playlist_id: playlist.id + playlist_id: playlist.id, + create_mode: false }, minWidth: '85vw' }); @@ -113,7 +117,7 @@ export class CustomPlaylistsComponent implements OnInit { dialogRef.afterClosed().subscribe(() => { // updates playlist in file manager if it changed if (dialogRef.componentInstance.playlist_updated) { - this.playlists[index] = dialogRef.componentInstance.original_playlist; + this.playlists[index] = dialogRef.componentInstance.playlist; } }); } diff --git a/src/app/components/recent-videos/recent-videos.component.html b/src/app/components/recent-videos/recent-videos.component.html index 5603378..9741911 100644 --- a/src/app/components/recent-videos/recent-videos.component.html +++ b/src/app/components/recent-videos/recent-videos.component.html @@ -48,31 +48,53 @@
- - -
-
-
- {{(file.type === 'audio' || file.isAudio) ? 'audiotrack' : 'movie'}} - {{file.title}} -
-
{{file.registered | date:'shortDate'}}
-
+ + +
+ Normal order  + Reverse order  +
- - - - - - - - - - + + + +
{{file.title}}
+
+ +
+

No files selected!

+
+ +
+ + + +
+
+
+ {{(file.type === 'audio' || file.isAudio) ? 'audiotrack' : 'movie'}} + {{file.title}} +
+
{{file.registered | date:'shortDate'}}
+
+
+ +
+
+ + + + + + + + +
+
-
+
File type diff --git a/src/app/components/recent-videos/recent-videos.component.scss b/src/app/components/recent-videos/recent-videos.component.scss index b9fd2fb..ab5e741 100644 --- a/src/app/components/recent-videos/recent-videos.component.scss +++ b/src/app/components/recent-videos/recent-videos.component.scss @@ -71,4 +71,42 @@ .audio-video-icon { position: relative; top: 6px; +} + +.cdk-drag-preview { + box-sizing: border-box; + border-radius: 4px; + box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2), + 0 8px 10px 1px rgba(0, 0, 0, 0.14), + 0 3px 14px 2px rgba(0, 0, 0, 0.12); +} + +.cdk-drag-placeholder { + opacity: 0; +} + +.cdk-drag-animating { + transition: transform 250ms cubic-bezier(0, 0, 0.2, 1); +} + +.media-box:last-child { + border: none; +} + +.media-list.cdk-drop-list-dragging .media-box:not(.cdk-drag-placeholder) { + transition: transform 250ms cubic-bezier(0, 0, 0.2, 1); +} + +.remove-item-button { + right: 10px; + position: absolute; + top: 4px; +} + +.playlist-item-text { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + max-width: 70%; + margin: 0 auto; } \ No newline at end of file diff --git a/src/app/components/recent-videos/recent-videos.component.ts b/src/app/components/recent-videos/recent-videos.component.ts index 7437524..0463140 100644 --- a/src/app/components/recent-videos/recent-videos.component.ts +++ b/src/app/components/recent-videos/recent-videos.component.ts @@ -5,6 +5,7 @@ import { DatabaseFile, FileType, FileTypeFilter } from '../../../api-types'; import { MatPaginator } from '@angular/material/paginator'; import { Subject } from 'rxjs'; import { distinctUntilChanged } from 'rxjs/operators'; +import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop'; @Component({ selector: 'app-recent-videos', @@ -14,11 +15,25 @@ import { distinctUntilChanged } from 'rxjs/operators'; export class RecentVideosComponent implements OnInit { @Input() usePaginator = true; + + // File selection + @Input() selectMode = false; + @Input() defaultSelected: DatabaseFile[] = []; @Input() sub_id = null; @Input() customHeader = null; + @Input() selectedIndex = 1; @Output() fileSelectionEmitter = new EventEmitter<{new_selection: string[], thumbnailURL: string}>(); + pageSize = 10; + paged_data: DatabaseFile[] = null; + + selected_data: string[] = []; + selected_data_objs: DatabaseFile[] = []; + reverse_order = false; + + // File listing (with cards) + cached_file_count = 0; loading_files = null; @@ -63,20 +78,32 @@ export class RecentVideosComponent implements OnInit { playlists = null; - pageSize = 10; - paged_data: DatabaseFile[] = null; - - selected_data: string[] = []; - @ViewChild('paginator') paginator: MatPaginator constructor(public postsService: PostsService, private router: Router) { // get cached file count if (localStorage.getItem('cached_file_count')) { this.cached_file_count = +localStorage.getItem('cached_file_count') <= 10 ? +localStorage.getItem('cached_file_count') : 10; - this.loading_files = Array(this.cached_file_count).fill(0); } + + // set filter property to cached value + const cached_filter_property = localStorage.getItem('filter_property'); + if (cached_filter_property && this.filterProperties[cached_filter_property]) { + this.filterProperty = this.filterProperties[cached_filter_property]; + } + + // set file type filter to cached value + const cached_file_type_filter = localStorage.getItem('file_type_filter'); + if (this.usePaginator && cached_file_type_filter) { + this.fileTypeFilter = cached_file_type_filter; + } + + const sort_order = localStorage.getItem('recent_videos_sort_order'); + + if (sort_order) { + this.descendingMode = sort_order === 'descending'; + } } ngOnInit(): void { @@ -104,23 +131,9 @@ export class RecentVideosComponent implements OnInit { } }); - // set filter property to cached value - const cached_filter_property = localStorage.getItem('filter_property'); - if (cached_filter_property && this.filterProperties[cached_filter_property]) { - this.filterProperty = this.filterProperties[cached_filter_property]; - } - - // set file type filter to cached value - const cached_file_type_filter = localStorage.getItem('file_type_filter'); - if (this.usePaginator && cached_file_type_filter) { - this.fileTypeFilter = cached_file_type_filter; - } - - const sort_order = localStorage.getItem('recent_videos_sort_order'); - - if (sort_order) { - this.descendingMode = sort_order === 'descending'; - } + + this.selected_data = this.defaultSelected.map(file => file.uid); + this.selected_data_objs = this.defaultSelected; this.searchChangedSubject .debounceTime(500) @@ -364,20 +377,41 @@ export class RecentVideosComponent implements OnInit { this.getAllFiles(); } - fileSelectionChanged(event): void { + fileSelectionChanged(event: { option: { _selected: boolean; value: DatabaseFile; } }): void { const adding = event.option._selected; const value = event.option.value; - if (adding) - this.selected_data.push(value); - else - this.selected_data = this.selected_data.filter(e => e !== value); - - let thumbnail_url = null; - if (this.selected_data.length) { - const file_obj = this.paged_data.find(file => file.uid === this.selected_data[0]); - if (file_obj) { thumbnail_url = file_obj['thumbnailURL'] } + if (adding) { + this.selected_data.push(value.uid); + this.selected_data_objs.push(value); + } else { + this.selected_data = this.selected_data.filter(e => e !== value.uid); + this.selected_data_objs = this.selected_data_objs.filter(e => e.uid !== value.uid); } - this.fileSelectionEmitter.emit({new_selection: this.selected_data, thumbnailURL: thumbnail_url}); + this.fileSelectionEmitter.emit({new_selection: this.selected_data, thumbnailURL: this.selected_data_objs[0].thumbnailURL}); + } + + toggleSelectionOrder(): void { + this.reverse_order = !this.reverse_order; + localStorage.setItem('default_playlist_order_reversed', '' + this.reverse_order); + } + + drop(event: CdkDragDrop): void { + if (this.reverse_order) { + event.previousIndex = this.selected_data.length - 1 - event.previousIndex; + event.currentIndex = this.selected_data.length - 1 - event.currentIndex; + } + moveItemInArray(this.selected_data, event.previousIndex, event.currentIndex); + moveItemInArray(this.selected_data_objs, event.previousIndex, event.currentIndex); + this.fileSelectionEmitter.emit({new_selection: this.selected_data, thumbnailURL: this.selected_data_objs[0].thumbnailURL}); + } + + removeSelectedFile(index: number): void { + if (this.reverse_order) { + index = this.selected_data.length - 1 - index; + } + this.selected_data.splice(index, 1); + this.selected_data_objs.splice(index, 1); + this.fileSelectionEmitter.emit({new_selection: this.selected_data, thumbnailURL: this.selected_data_objs[0].thumbnailURL}); } } diff --git a/src/app/create-playlist/create-playlist.component.html b/src/app/create-playlist/create-playlist.component.html index d82c23e..cdc40ad 100644 --- a/src/app/create-playlist/create-playlist.component.html +++ b/src/app/create-playlist/create-playlist.component.html @@ -1,14 +1,29 @@ -

Create a playlist

-
-
-
- - - -
- -
-
+
+

Create a playlist

+

Modify playlist

-
- + +
+
+
+ + + +
+ +
+
+
+ +
+ + +
+ + +
+
\ No newline at end of file diff --git a/src/app/create-playlist/create-playlist.component.scss b/src/app/create-playlist/create-playlist.component.scss index e69de29..82ffcce 100644 --- a/src/app/create-playlist/create-playlist.component.scss +++ b/src/app/create-playlist/create-playlist.component.scss @@ -0,0 +1,9 @@ +.fixActionRow { + height: 89vh; + display: flex; + flex-direction: column; +} + +.spacer { + flex-grow: 1; +} \ No newline at end of file diff --git a/src/app/create-playlist/create-playlist.component.ts b/src/app/create-playlist/create-playlist.component.ts index 6a5e308..7ec41b0 100644 --- a/src/app/create-playlist/create-playlist.component.ts +++ b/src/app/create-playlist/create-playlist.component.ts @@ -2,6 +2,7 @@ import { Component, OnInit, Inject } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { FormControl } from '@angular/forms'; import { PostsService } from 'app/posts.services'; +import { Playlist } from 'api-types'; @Component({ selector: 'app-create-playlist', @@ -20,9 +21,24 @@ export class CreatePlaylistComponent implements OnInit { cached_thumbnail_url = null; create_in_progress = false; + create_mode = false; - constructor(private postsService: PostsService, - public dialogRef: MatDialogRef) { } + // playlist modify mode + + playlist: Playlist = null; + playlist_id: string = null; + preselected_files = []; + playlist_updated = false; + + constructor(@Inject(MAT_DIALOG_DATA) public data: any, + private postsService: PostsService, + public dialogRef: MatDialogRef) { + if (this.data?.create_mode) this.create_mode = true; + if (this.data?.playlist_id) { + this.playlist_id = this.data.playlist_id; + this.getPlaylist(); + } + } ngOnInit(): void {} @@ -40,6 +56,17 @@ export class CreatePlaylistComponent implements OnInit { }); } + updatePlaylist(): void { + this.playlist['name'] = this.name; + this.playlist['uids'] = this.filesSelect.value; + this.playlist_updated = true; + this.postsService.updatePlaylist(this.playlist).subscribe(() => { + this.postsService.openSnackBar('Playlist updated successfully.'); + this.getPlaylist(); + this.postsService.playlists_changed.next(true); + }); + } + getThumbnailURL(): string { return this.cached_thumbnail_url; } @@ -49,4 +76,19 @@ export class CreatePlaylistComponent implements OnInit { if (new_selection.length) this.cached_thumbnail_url = thumbnailURL; else this.cached_thumbnail_url = null; } + + playlistChanged(): boolean { + return JSON.stringify(this.playlist.uids) !== JSON.stringify(this.filesSelect.value) || this.name !== this.playlist.name; + } + + getPlaylist(): void { + this.postsService.getPlaylist(this.playlist_id, null, true).subscribe(res => { + if (res['playlist']) { + this.filesSelect.setValue(res['file_objs'].map(file => file.uid)); + this.preselected_files = res['file_objs']; + this.playlist = res['playlist']; + this.name = this.playlist['name']; + } + }); + } }