mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-27 11:18:14 +01:00 
			
		
		
		
	Merge pull request #448 from rasmuslos/bulk-download
Added select all option to the episode selector
This commit is contained in:
		
						commit
						fc228013d3
					
				
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -4,6 +4,7 @@ node_modules/
 | 
				
			|||||||
/config/
 | 
					/config/
 | 
				
			||||||
/audiobooks/
 | 
					/audiobooks/
 | 
				
			||||||
/audiobooks2/
 | 
					/audiobooks2/
 | 
				
			||||||
 | 
					/podcasts/
 | 
				
			||||||
/media/
 | 
					/media/
 | 
				
			||||||
/metadata/
 | 
					/metadata/
 | 
				
			||||||
test/
 | 
					test/
 | 
				
			||||||
 | 
				
			|||||||
@ -29,6 +29,14 @@
 | 
				
			|||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      <div class="flex justify-end pt-4">
 | 
					      <div class="flex justify-end pt-4">
 | 
				
			||||||
 | 
					        <div class="relative">
 | 
				
			||||||
 | 
					          <div class="absolute top-0 left-0 h-full flex items-center p-2">
 | 
				
			||||||
 | 
					            <ui-checkbox small checkbox-bg="primary" border-color="gray-600" v-on:input="selectedEpisodes = episodes.map(episode => episode.enclosure && itemEpisodeMap[episode.enclosure.url] ? false : !allSelected)" v-bind:value="allSelected" v-bind:disabled="allDownloaded" />
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					          <div class="px-8 py-2">
 | 
				
			||||||
 | 
					            <p :class="!allDownloaded ? 'font-semibold text-gray-200' : 'text-gray-400'">Select all episodes</p>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
        <ui-btn :disabled="!episodesSelected.length" @click="submit">{{ buttonText }}</ui-btn>
 | 
					        <ui-btn :disabled="!episodesSelected.length" @click="submit">{{ buttonText }}</ui-btn>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
@ -67,6 +75,20 @@ export default {
 | 
				
			|||||||
      if (!this.libraryItem) return ''
 | 
					      if (!this.libraryItem) return ''
 | 
				
			||||||
      return this.libraryItem.media.metadata.title || 'Unknown'
 | 
					      return this.libraryItem.media.metadata.title || 'Unknown'
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    allSelected() {
 | 
				
			||||||
 | 
					      try {
 | 
				
			||||||
 | 
					        const values = Object.values(this.selectedEpisodes).filter((_, index) => !(this.episodes[index].enclosure && this.itemEpisodeMap[this.episodes[index].enclosure.url]))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(!values.length) return false
 | 
				
			||||||
 | 
					        return values.filter(episode => !episode).length === 0
 | 
				
			||||||
 | 
					      } catch(error) {
 | 
				
			||||||
 | 
					        console.error("Error while filtering selected episodes", error);
 | 
				
			||||||
 | 
					        return false
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    allDownloaded() {
 | 
				
			||||||
 | 
					      return Object.values(this.episodes).filter(episode => !(episode.enclosure && this.itemEpisodeMap[episode.enclosure.url])).length === 0
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    episodesSelected() {
 | 
					    episodesSelected() {
 | 
				
			||||||
      return Object.keys(this.selectedEpisodes).filter((key) => !!this.selectedEpisodes[key])
 | 
					      return Object.keys(this.selectedEpisodes).filter((key) => !!this.selectedEpisodes[key])
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
				
			|||||||
@ -39,6 +39,14 @@
 | 
				
			|||||||
        <div class="w-full md:w-1/2 p-4">
 | 
					        <div class="w-full md:w-1/2 p-4">
 | 
				
			||||||
          <p class="text-lg font-semibold mb-2">Episodes</p>
 | 
					          <p class="text-lg font-semibold mb-2">Episodes</p>
 | 
				
			||||||
          <div ref="episodeContainer" id="episodes-scroll" class="w-full overflow-x-hidden overflow-y-auto">
 | 
					          <div ref="episodeContainer" id="episodes-scroll" class="w-full overflow-x-hidden overflow-y-auto">
 | 
				
			||||||
 | 
					            <div class="relative">
 | 
				
			||||||
 | 
					              <div class="absolute top-0 left-0 h-full flex items-center p-2">
 | 
				
			||||||
 | 
					                <ui-checkbox small checkbox-bg="primary" border-color="gray-600" v-on:input="selectedEpisodes = episodes.map(_ => !allSelected)" v-bind:value="allSelected" />
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					              <div class="px-8 py-2">
 | 
				
			||||||
 | 
					                <p class="font-semibold text-gray-200">Select all episodes</p>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
            <div v-for="(episode, index) in episodes" :key="index" class="relative cursor-pointer" :class="selectedEpisodes[String(index)] ? 'bg-success bg-opacity-10' : index % 2 == 0 ? 'bg-primary bg-opacity-25 hover:bg-opacity-40' : 'bg-primary bg-opacity-5 hover:bg-opacity-25'" @click="toggleSelectEpisode(index)">
 | 
					            <div v-for="(episode, index) in episodes" :key="index" class="relative cursor-pointer" :class="selectedEpisodes[String(index)] ? 'bg-success bg-opacity-10' : index % 2 == 0 ? 'bg-primary bg-opacity-25 hover:bg-opacity-40' : 'bg-primary bg-opacity-5 hover:bg-opacity-25'" @click="toggleSelectEpisode(index)">
 | 
				
			||||||
              <div class="absolute top-0 left-0 h-full flex items-center p-2">
 | 
					              <div class="absolute top-0 left-0 h-full flex items-center p-2">
 | 
				
			||||||
                <ui-checkbox v-model="selectedEpisodes[String(index)]" small checkbox-bg="primary" border-color="gray-600" />
 | 
					                <ui-checkbox v-model="selectedEpisodes[String(index)]" small checkbox-bg="primary" border-color="gray-600" />
 | 
				
			||||||
@ -149,6 +157,9 @@ export default {
 | 
				
			|||||||
      if (!this.podcastFeedData) return []
 | 
					      if (!this.podcastFeedData) return []
 | 
				
			||||||
      return this.podcastFeedData.episodes || []
 | 
					      return this.podcastFeedData.episodes || []
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    allSelected() {
 | 
				
			||||||
 | 
					      return Object.values(this.selectedEpisodes).filter(episode => !episode).length === 0
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    episodesSelected() {
 | 
					    episodesSelected() {
 | 
				
			||||||
      return Object.keys(this.selectedEpisodes).filter((key) => !!this.selectedEpisodes[key])
 | 
					      return Object.keys(this.selectedEpisodes).filter((key) => !!this.selectedEpisodes[key])
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
				
			|||||||
@ -150,8 +150,8 @@ class Server {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    app.use(this.auth.cors)
 | 
					    app.use(this.auth.cors)
 | 
				
			||||||
    app.use(fileUpload())
 | 
					    app.use(fileUpload())
 | 
				
			||||||
    app.use(express.urlencoded({ extended: true }));
 | 
					    app.use(express.urlencoded({ extended: true, limit: "3mb" }));
 | 
				
			||||||
    app.use(express.json())
 | 
					    app.use(express.json({ limit: "3mb" }))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Static path to generated nuxt
 | 
					    // Static path to generated nuxt
 | 
				
			||||||
    const distPath = Path.join(global.appRoot, '/client/dist')
 | 
					    const distPath = Path.join(global.appRoot, '/client/dist')
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user