mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +01:00 
			
		
		
		
	Playlist and collections cleanup
This commit is contained in:
		
							parent
							
								
									eb2ea9950a
								
							
						
					
					
						commit
						29a6434fdc
					
				| @ -20,42 +20,67 @@ | |||||||
|   transition-timing-function: cubic-bezier(0, 1, 0.5, 1); |   transition-timing-function: cubic-bezier(0, 1, 0.5, 1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .slide-enter-to, .slide-leave { | .slide-enter-to, | ||||||
|  | .slide-leave { | ||||||
|   max-height: 600px; |   max-height: 600px; | ||||||
|   overflow: hidden; |   overflow: hidden; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .slide-enter, .slide-leave-to { | .slide-enter, | ||||||
|  | .slide-leave-to { | ||||||
|   overflow: hidden; |   overflow: hidden; | ||||||
|   max-height: 0; |   max-height: 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| .menu-enter, .menu-leave-active { | .menu-enter, | ||||||
|  | .menu-leave-active { | ||||||
|   transform: translateY(-15px); |   transform: translateY(-15px); | ||||||
| } | } | ||||||
|  | 
 | ||||||
| .menu-enter-active { | .menu-enter-active { | ||||||
|   transition: all 0.2s; |   transition: all 0.2s; | ||||||
| } | } | ||||||
|  | 
 | ||||||
| .menu-leave-active { | .menu-leave-active { | ||||||
|   transition: all 0.1s; |   transition: all 0.1s; | ||||||
| } | } | ||||||
|  | 
 | ||||||
| .menu-enter, | .menu-enter, | ||||||
| .menu-leave-active { | .menu-leave-active { | ||||||
|   opacity: 0; |   opacity: 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .menux-enter, .menux-leave-active { | .menux-enter, | ||||||
|  | .menux-leave-active { | ||||||
|   transform: translateX(15px); |   transform: translateX(15px); | ||||||
| } | } | ||||||
|  | 
 | ||||||
| .menux-enter-active { | .menux-enter-active { | ||||||
|   transition: all 0.2s; |   transition: all 0.2s; | ||||||
| } | } | ||||||
|  | 
 | ||||||
| .menux-leave-active { | .menux-leave-active { | ||||||
|   transition: all 0.1s; |   transition: all 0.1s; | ||||||
| } | } | ||||||
|  | 
 | ||||||
| .menux-enter, | .menux-enter, | ||||||
| .menux-leave-active { | .menux-leave-active { | ||||||
|   opacity: 0; |   opacity: 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | .list-complete-item { | ||||||
|  |   transition: all 0.8s ease; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .list-complete-enter-from, | ||||||
|  | .list-complete-leave-to { | ||||||
|  |   opacity: 0; | ||||||
|  |   transform: translateY(30px); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .list-complete-leave-active { | ||||||
|  |   position: absolute; | ||||||
| } | } | ||||||
| @ -2,7 +2,7 @@ | |||||||
|   <div ref="card" :id="`playlist-card-${index}`" :style="{ width: width + 'px', height: height + 'px' }" class="absolute top-0 left-0 rounded-sm z-30 cursor-pointer" @mousedown.prevent @mouseup.prevent @mousemove.prevent @mouseover="mouseover" @mouseleave="mouseleave" @click="clickCard"> |   <div ref="card" :id="`playlist-card-${index}`" :style="{ width: width + 'px', height: height + 'px' }" class="absolute top-0 left-0 rounded-sm z-30 cursor-pointer" @mousedown.prevent @mouseup.prevent @mousemove.prevent @mouseover="mouseover" @mouseleave="mouseleave" @click="clickCard"> | ||||||
|     <div class="absolute top-0 left-0 w-full box-shadow-book shadow-height" /> |     <div class="absolute top-0 left-0 w-full box-shadow-book shadow-height" /> | ||||||
|     <div class="w-full h-full bg-primary relative rounded overflow-hidden"> |     <div class="w-full h-full bg-primary relative rounded overflow-hidden"> | ||||||
|       <covers-playlist-cover ref="cover" :items="items" :width="width" :height="height" :book-cover-aspect-ratio="bookCoverAspectRatio" /> |       <covers-playlist-cover ref="cover" :items="items" :width="width" :height="height" /> | ||||||
|     </div> |     </div> | ||||||
|     <div v-show="isHovering && userCanUpdate" class="w-full h-full absolute top-0 left-0 z-10 bg-black bg-opacity-40 pointer-events-none"> |     <div v-show="isHovering && userCanUpdate" class="w-full h-full absolute top-0 left-0 z-10 bg-black bg-opacity-40 pointer-events-none"> | ||||||
|       <div class="absolute pointer-events-auto" :style="{ top: 0.5 * sizeMultiplier + 'rem', right: 0.5 * sizeMultiplier + 'rem' }" @click.stop.prevent="clickEdit"> |       <div class="absolute pointer-events-auto" :style="{ top: 0.5 * sizeMultiplier + 'rem', right: 0.5 * sizeMultiplier + 'rem' }" @click.stop.prevent="clickEdit"> | ||||||
|  | |||||||
| @ -2,7 +2,7 @@ | |||||||
|   <div class="relative rounded-sm overflow-hidden" :style="{ width: width + 'px', height: height + 'px' }"> |   <div class="relative rounded-sm overflow-hidden" :style="{ width: width + 'px', height: height + 'px' }"> | ||||||
|     <div v-if="items.length" class="flex flex-wrap justify-center h-full relative bg-primary bg-opacity-95 rounded-sm"> |     <div v-if="items.length" class="flex flex-wrap justify-center h-full relative bg-primary bg-opacity-95 rounded-sm"> | ||||||
|       <div class="absolute top-0 left-0 w-full h-full bg-gray-400 bg-opacity-5" /> |       <div class="absolute top-0 left-0 w-full h-full bg-gray-400 bg-opacity-5" /> | ||||||
|       <covers-book-cover v-for="li in libraryItemCovers" :key="li.id" :library-item="li" :width="itemCoverWidth" :book-cover-aspect-ratio="1" /> |       <covers-book-cover v-for="(li, index) in libraryItemCovers" :key="index" :library-item="li" :width="itemCoverWidth" :book-cover-aspect-ratio="1" /> | ||||||
|     </div> |     </div> | ||||||
|     <div v-else class="relative w-full h-full flex items-center justify-center p-2 bg-primary rounded-sm"> |     <div v-else class="relative w-full h-full flex items-center justify-center p-2 bg-primary rounded-sm"> | ||||||
|       <div class="absolute top-0 left-0 w-full h-full bg-gray-400 bg-opacity-5" /> |       <div class="absolute top-0 left-0 w-full h-full bg-gray-400 bg-opacity-5" /> | ||||||
| @ -18,8 +18,7 @@ export default { | |||||||
|       default: () => [] |       default: () => [] | ||||||
|     }, |     }, | ||||||
|     width: Number, |     width: Number, | ||||||
|     height: Number, |     height: Number | ||||||
|     bookCoverAspectRatio: Number |  | ||||||
|   }, |   }, | ||||||
|   data() { |   data() { | ||||||
|     return {} |     return {} | ||||||
|  | |||||||
| @ -112,23 +112,21 @@ export default { | |||||||
|   }, |   }, | ||||||
|   methods: { |   methods: { | ||||||
|     loadCollections() { |     loadCollections() { | ||||||
|       if (!this.collections.length) { |       this.processing = true | ||||||
|         this.processing = true |       this.$axios | ||||||
|         this.$axios |         .$get(`/api/libraries/${this.currentLibraryId}/collections`) | ||||||
|           .$get(`/api/libraries/${this.currentLibraryId}/collections`) |         .then((data) => { | ||||||
|           .then((data) => { |           if (data.results) { | ||||||
|             if (data.results) { |             this.$store.commit('libraries/setCollections', data.results || []) | ||||||
|               this.$store.commit('libraries/setCollections', data.results || []) |           } | ||||||
|             } |         }) | ||||||
|           }) |         .catch((error) => { | ||||||
|           .catch((error) => { |           console.error('Failed to get collections', error) | ||||||
|             console.error('Failed to get collections', error) |           this.$toast.error('Failed to load collections') | ||||||
|             this.$toast.error('Failed to load collections') |         }) | ||||||
|           }) |         .finally(() => { | ||||||
|           .finally(() => { |           this.processing = false | ||||||
|             this.processing = false |         }) | ||||||
|           }) |  | ||||||
|       } |  | ||||||
|     }, |     }, | ||||||
|     removeFromCollection(collection) { |     removeFromCollection(collection) { | ||||||
|       if (!this.selectedLibraryItemId && !this.selectedBookIds.length) return |       if (!this.selectedLibraryItemId && !this.selectedBookIds.length) return | ||||||
| @ -231,19 +229,3 @@ export default { | |||||||
|   mounted() {} |   mounted() {} | ||||||
| } | } | ||||||
| </script> | </script> | ||||||
| 
 |  | ||||||
| <style> |  | ||||||
| .list-complete-item { |  | ||||||
|   transition: all 0.8s ease; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .list-complete-enter-from, |  | ||||||
| .list-complete-leave-to { |  | ||||||
|   opacity: 0; |  | ||||||
|   transform: translateY(30px); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .list-complete-leave-active { |  | ||||||
|   position: absolute; |  | ||||||
| } |  | ||||||
| </style> |  | ||||||
| @ -15,7 +15,7 @@ | |||||||
|         <div class="w-full overflow-y-auto overflow-x-hidden max-h-96"> |         <div class="w-full overflow-y-auto overflow-x-hidden max-h-96"> | ||||||
|           <transition-group name="list-complete" tag="div"> |           <transition-group name="list-complete" tag="div"> | ||||||
|             <template v-for="playlist in sortedPlaylists"> |             <template v-for="playlist in sortedPlaylists"> | ||||||
|               <modals-playlists-user-playlist-item :key="playlist.id" :playlist="playlist" :book-cover-aspect-ratio="bookCoverAspectRatio" class="list-complete-item" @add="addToPlaylist" @remove="removeFromPlaylist" @close="show = false" /> |               <modals-playlists-user-playlist-item :key="playlist.id" :playlist="playlist" class="list-complete-item" @add="addToPlaylist" @remove="removeFromPlaylist" @close="show = false" /> | ||||||
|             </template> |             </template> | ||||||
|           </transition-group> |           </transition-group> | ||||||
|         </div> |         </div> | ||||||
| @ -77,9 +77,6 @@ export default { | |||||||
|     playlists() { |     playlists() { | ||||||
|       return this.$store.state.libraries.userPlaylists || [] |       return this.$store.state.libraries.userPlaylists || [] | ||||||
|     }, |     }, | ||||||
|     bookCoverAspectRatio() { |  | ||||||
|       return this.$store.getters['libraries/getBookCoverAspectRatio'] |  | ||||||
|     }, |  | ||||||
|     sortedPlaylists() { |     sortedPlaylists() { | ||||||
|       return this.playlists |       return this.playlists | ||||||
|         .map((playlist) => { |         .map((playlist) => { | ||||||
| @ -110,21 +107,19 @@ export default { | |||||||
|       return playlist.items.some((i) => i.libraryItemId === item.libraryItem.id) |       return playlist.items.some((i) => i.libraryItemId === item.libraryItem.id) | ||||||
|     }, |     }, | ||||||
|     loadPlaylists() { |     loadPlaylists() { | ||||||
|       if (!this.playlists.length) { |       this.processing = true | ||||||
|         this.processing = true |       this.$axios | ||||||
|         this.$axios |         .$get(`/api/libraries/${this.currentLibraryId}/playlists`) | ||||||
|           .$get(`/api/libraries/${this.currentLibraryId}/playlists`) |         .then((data) => { | ||||||
|           .then((data) => { |           this.$store.commit('libraries/setUserPlaylists', data.results || []) | ||||||
|             this.$store.commit('libraries/setUserPlaylists', data.results || []) |         }) | ||||||
|           }) |         .catch((error) => { | ||||||
|           .catch((error) => { |           console.error('Failed to get playlists', error) | ||||||
|             console.error('Failed to get playlists', error) |           this.$toast.error('Failed to load user playlists') | ||||||
|             this.$toast.error('Failed to load user playlists') |         }) | ||||||
|           }) |         .finally(() => { | ||||||
|           .finally(() => { |           this.processing = false | ||||||
|             this.processing = false |         }) | ||||||
|           }) |  | ||||||
|       } |  | ||||||
|     }, |     }, | ||||||
|     removeFromPlaylist(playlist) { |     removeFromPlaylist(playlist) { | ||||||
|       if (!this.selectedPlaylistItems.length) return |       if (!this.selectedPlaylistItems.length) return | ||||||
| @ -194,19 +189,3 @@ export default { | |||||||
|   mounted() {} |   mounted() {} | ||||||
| } | } | ||||||
| </script> | </script> | ||||||
| 
 |  | ||||||
| <style> |  | ||||||
| .list-complete-item { |  | ||||||
|   transition: all 0.8s ease; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .list-complete-enter-from, |  | ||||||
| .list-complete-leave-to { |  | ||||||
|   opacity: 0; |  | ||||||
|   transform: translateY(30px); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| .list-complete-leave-active { |  | ||||||
|   position: absolute; |  | ||||||
| } |  | ||||||
| </style> |  | ||||||
| @ -9,7 +9,7 @@ | |||||||
|       <form @submit.prevent="submitForm"> |       <form @submit.prevent="submitForm"> | ||||||
|         <div class="flex"> |         <div class="flex"> | ||||||
|           <div> |           <div> | ||||||
|             <covers-playlist-cover :items="items" :width="200" :height="100 * bookCoverAspectRatio" :book-cover-aspect-ratio="bookCoverAspectRatio" /> |             <covers-playlist-cover :items="items" :width="200" :height="200" /> | ||||||
|           </div> |           </div> | ||||||
|           <div class="flex-grow px-4"> |           <div class="flex-grow px-4"> | ||||||
|             <ui-text-input-with-label v-model="newPlaylistName" :label="$strings.LabelName" class="mb-2" /> |             <ui-text-input-with-label v-model="newPlaylistName" :label="$strings.LabelName" class="mb-2" /> | ||||||
| @ -55,9 +55,6 @@ export default { | |||||||
|         this.$store.commit('globals/setShowEditPlaylistModal', val) |         this.$store.commit('globals/setShowEditPlaylistModal', val) | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     bookCoverAspectRatio() { |  | ||||||
|       return this.$store.getters['libraries/getBookCoverAspectRatio'] |  | ||||||
|     }, |  | ||||||
|     playlist() { |     playlist() { | ||||||
|       return this.$store.state.globals.selectedPlaylist || {} |       return this.$store.state.globals.selectedPlaylist || {} | ||||||
|     }, |     }, | ||||||
|  | |||||||
| @ -1,8 +1,8 @@ | |||||||
| <template> | <template> | ||||||
|   <div class="flex items-center px-4 py-2 justify-start relative hover:bg-bg" @mouseover="mouseover" @mouseleave="mouseleave"> |   <div class="flex items-center px-4 py-2 justify-start relative hover:bg-bg" @mouseover="mouseover" @mouseleave="mouseleave"> | ||||||
|     <div v-if="isItemIncluded" class="absolute top-0 left-0 h-full w-1 bg-success z-10" /> |     <div v-if="isItemIncluded" class="absolute top-0 left-0 h-full w-1 bg-success z-10" /> | ||||||
|     <div class="w-20 max-w-20 text-center"> |     <div class="w-16 max-w-16 text-center"> | ||||||
|       <covers-playlist-cover :items="items" :width="80" :height="40 * bookCoverAspectRatio" :book-cover-aspect-ratio="bookCoverAspectRatio" /> |       <covers-playlist-cover :items="items" :width="64" :height="64" /> | ||||||
|     </div> |     </div> | ||||||
|     <div class="flex-grow overflow-hidden px-2"> |     <div class="flex-grow overflow-hidden px-2"> | ||||||
|       <nuxt-link :to="`/playlist/${playlist.id}`" class="pl-2 pr-2 truncate hover:underline cursor-pointer" @click.native="clickNuxtLink">{{ playlist.name }}</nuxt-link> |       <nuxt-link :to="`/playlist/${playlist.id}`" class="pl-2 pr-2 truncate hover:underline cursor-pointer" @click.native="clickNuxtLink">{{ playlist.name }}</nuxt-link> | ||||||
| @ -20,8 +20,7 @@ export default { | |||||||
|     playlist: { |     playlist: { | ||||||
|       type: Object, |       type: Object, | ||||||
|       default: () => {} |       default: () => {} | ||||||
|     }, |     } | ||||||
|     bookCoverAspectRatio: Number |  | ||||||
|   }, |   }, | ||||||
|   data() { |   data() { | ||||||
|     return { |     return { | ||||||
|  | |||||||
| @ -85,6 +85,8 @@ export default { | |||||||
|       if (localStorage.getItem('token')) { |       if (localStorage.getItem('token')) { | ||||||
|         localStorage.removeItem('token') |         localStorage.removeItem('token') | ||||||
|       } |       } | ||||||
|  |       this.$store.commit('libraries/setUserPlaylists', []) | ||||||
|  |       this.$store.commit('libraries/setCollections', []) | ||||||
|       this.$router.push('/login') |       this.$router.push('/login') | ||||||
|     }, |     }, | ||||||
|     resetForm() { |     resetForm() { | ||||||
|  | |||||||
| @ -4,7 +4,7 @@ | |||||||
|       <div class="flex flex-col sm:flex-row max-w-6xl mx-auto"> |       <div class="flex flex-col sm:flex-row max-w-6xl mx-auto"> | ||||||
|         <div class="w-full flex justify-center md:block sm:w-32 md:w-52" style="min-width: 200px"> |         <div class="w-full flex justify-center md:block sm:w-32 md:w-52" style="min-width: 200px"> | ||||||
|           <div class="relative" style="height: fit-content"> |           <div class="relative" style="height: fit-content"> | ||||||
|             <covers-playlist-cover :items="playlistItems" :width="200" :height="200 * bookCoverAspectRatio" :book-cover-aspect-ratio="bookCoverAspectRatio" /> |             <covers-playlist-cover :items="playlistItems" :width="200" :height="200" /> | ||||||
|           </div> |           </div> | ||||||
|         </div> |         </div> | ||||||
|         <div class="flex-grow px-2 py-6 md:py-0 md:px-10"> |         <div class="flex-grow px-2 py-6 md:py-0 md:px-10"> | ||||||
| @ -68,9 +68,6 @@ export default { | |||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   computed: { |   computed: { | ||||||
|     bookCoverAspectRatio() { |  | ||||||
|       return this.$store.getters['libraries/getBookCoverAspectRatio'] |  | ||||||
|     }, |  | ||||||
|     streamLibraryItem() { |     streamLibraryItem() { | ||||||
|       return this.$store.state.streamLibraryItem |       return this.$store.state.streamLibraryItem | ||||||
|     }, |     }, | ||||||
|  | |||||||
| @ -108,7 +108,6 @@ export const actions = { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     const libraryChanging = state.currentLibraryId !== libraryId |     const libraryChanging = state.currentLibraryId !== libraryId | ||||||
| 
 |  | ||||||
|     return this.$axios |     return this.$axios | ||||||
|       .$get(`/api/libraries/${libraryId}?include=filterdata`) |       .$get(`/api/libraries/${libraryId}?include=filterdata`) | ||||||
|       .then((data) => { |       .then((data) => { | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user