mirror of
				https://github.com/advplyr/audiobookshelf.git
				synced 2025-10-31 10:27:01 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			266 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			266 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <template>
 | |
|   <modals-modal v-model="show" name="edit-library" :width="800" :height="'unset'" :processing="processing">
 | |
|     <template #outer>
 | |
|       <div class="absolute top-0 left-0 p-5 w-2/3 overflow-hidden">
 | |
|         <p class="text-xl md:text-3xl text-white truncate">{{ title }}</p>
 | |
|       </div>
 | |
|     </template>
 | |
|     <div class="absolute -top-10 left-0 z-10 w-full flex">
 | |
|       <template v-for="tab in tabs">
 | |
|         <div :key="tab.id" class="w-28 rounded-t-lg flex items-center justify-center mr-1 cursor-pointer hover:bg-bg border-t border-l border-r border-black-300 tab text-xs sm:text-base" :class="selectedTab === tab.id ? 'tab-selected bg-bg pb-px' : 'bg-primary text-gray-400'" @click="selectTab(tab.id)">{{ tab.title }}</div>
 | |
|       </template>
 | |
|     </div>
 | |
| 
 | |
|     <div class="px-2 md:px-4 w-full text-sm pt-2 md:pt-6 pb-20 rounded-b-lg rounded-tr-lg bg-bg shadow-lg border border-black-300 relative overflow-hidden" style="min-height: 400px; max-height: 80vh">
 | |
|       <component v-if="libraryCopy && show" ref="tabComponent" :is="tabName" :is-new="!library" :library="libraryCopy" :library-id="libraryId" :processing.sync="processing" @update="updateLibrary" @close="show = false" />
 | |
| 
 | |
|       <div v-show="selectedTab !== 'tools'" class="absolute bottom-0 left-0 w-full px-4 py-4 border-t border-white border-opacity-10">
 | |
|         <div class="flex justify-end">
 | |
|           <ui-btn @click="submit">{{ buttonText }}</ui-btn>
 | |
|         </div>
 | |
|       </div>
 | |
|     </div>
 | |
|   </modals-modal>
 | |
| </template>
 | |
| 
 | |
| <script>
 | |
| export default {
 | |
|   props: {
 | |
|     value: Boolean,
 | |
|     library: {
 | |
|       type: Object,
 | |
|       default: () => {}
 | |
|     }
 | |
|   },
 | |
|   data() {
 | |
|     return {
 | |
|       processing: false,
 | |
|       selectedTab: 'details',
 | |
|       libraryCopy: null
 | |
|     }
 | |
|   },
 | |
|   computed: {
 | |
|     show: {
 | |
|       get() {
 | |
|         return this.value
 | |
|       },
 | |
|       set(val) {
 | |
|         this.$emit('input', val)
 | |
|       }
 | |
|     },
 | |
|     title() {
 | |
|       return this.library ? this.$strings.HeaderUpdateLibrary : this.$strings.HeaderNewLibrary
 | |
|     },
 | |
|     buttonText() {
 | |
|       return this.library ? this.$strings.ButtonSave : this.$strings.ButtonCreate
 | |
|     },
 | |
|     mediaType() {
 | |
|       return this.libraryCopy?.mediaType
 | |
|     },
 | |
|     libraryId() {
 | |
|       return this.library?.id
 | |
|     },
 | |
|     tabs() {
 | |
|       return [
 | |
|         {
 | |
|           id: 'details',
 | |
|           title: this.$strings.HeaderDetails,
 | |
|           component: 'modals-libraries-edit-library'
 | |
|         },
 | |
|         {
 | |
|           id: 'settings',
 | |
|           title: this.$strings.HeaderSettings,
 | |
|           component: 'modals-libraries-library-settings'
 | |
|         },
 | |
|         {
 | |
|           id: 'scanner',
 | |
|           title: this.$strings.HeaderSettingsScanner,
 | |
|           component: 'modals-libraries-library-scanner-settings'
 | |
|         },
 | |
|         {
 | |
|           id: 'schedule',
 | |
|           title: this.$strings.HeaderSchedule,
 | |
|           component: 'modals-libraries-schedule-scan'
 | |
|         },
 | |
|         {
 | |
|           id: 'tools',
 | |
|           title: this.$strings.HeaderTools,
 | |
|           component: 'modals-libraries-library-tools'
 | |
|         }
 | |
|       ].filter((tab) => {
 | |
|         // Do not show tools tab for new libraries
 | |
|         if (tab.id === 'tools' && !this.library) return false
 | |
|         return tab.id !== 'scanner' || this.mediaType === 'book'
 | |
|       })
 | |
|     },
 | |
|     tabName() {
 | |
|       var _tab = this.tabs.find((t) => t.id === this.selectedTab)
 | |
|       return _tab ? _tab.component : ''
 | |
|     }
 | |
|   },
 | |
|   watch: {
 | |
|     show: {
 | |
|       handler(newVal) {
 | |
|         if (newVal) this.init()
 | |
|       }
 | |
|     }
 | |
|   },
 | |
|   methods: {
 | |
|     selectTab(tab) {
 | |
|       this.selectedTab = tab
 | |
|     },
 | |
|     updateLibrary(library) {
 | |
|       this.mapLibraryToCopy(library)
 | |
|       console.log('Updated library', this.libraryCopy)
 | |
|     },
 | |
|     getNewLibraryData() {
 | |
|       return {
 | |
|         name: '',
 | |
|         provider: 'google',
 | |
|         folders: [],
 | |
|         icon: 'database',
 | |
|         mediaType: 'book',
 | |
|         settings: {
 | |
|           coverAspectRatio: this.$constants.BookCoverAspectRatio.SQUARE,
 | |
|           disableWatcher: false,
 | |
|           skipMatchingMediaWithAsin: false,
 | |
|           skipMatchingMediaWithIsbn: false,
 | |
|           autoScanCronExpression: null,
 | |
|           hideSingleBookSeries: false,
 | |
|           metadataPrecedence: ['folderStructure', 'audioMetatags', 'nfoFile', 'txtFiles', 'opfFile', 'absMetadata']
 | |
|         }
 | |
|       }
 | |
|     },
 | |
|     init() {
 | |
|       this.selectedTab = 'details'
 | |
|       this.libraryCopy = this.getNewLibraryData()
 | |
|       if (this.library) {
 | |
|         this.mapLibraryToCopy(this.library)
 | |
|       }
 | |
|     },
 | |
|     mapLibraryToCopy(library) {
 | |
|       for (const key in this.libraryCopy) {
 | |
|         if (library[key] !== undefined) {
 | |
|           if (key === 'folders') {
 | |
|             this.libraryCopy.folders = library.folders.map((f) => ({ ...f })).filter((f) => !!f.fullPath?.trim())
 | |
|           } else if (key === 'settings') {
 | |
|             for (const settingKey in library.settings) {
 | |
|               this.libraryCopy.settings[settingKey] = library.settings[settingKey]
 | |
|             }
 | |
|           } else {
 | |
|             this.libraryCopy[key] = library[key]
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     },
 | |
|     validate() {
 | |
|       if (!this.libraryCopy.name) {
 | |
|         this.$toast.error('Library must have a name')
 | |
|         return false
 | |
|       }
 | |
|       if (!this.libraryCopy.folders.length) {
 | |
|         this.$toast.error('Library must have at least 1 path')
 | |
|         return false
 | |
|       }
 | |
| 
 | |
|       return true
 | |
|     },
 | |
|     submit() {
 | |
|       // If custom expression input is focused then unfocus it instead of submitting
 | |
|       if (this.$refs.tabComponent && this.$refs.tabComponent.checkBlurExpressionInput) {
 | |
|         if (this.$refs.tabComponent.checkBlurExpressionInput()) {
 | |
|           return
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       if (!this.validate()) return
 | |
| 
 | |
|       if (this.library) {
 | |
|         this.submitUpdateLibrary()
 | |
|       } else {
 | |
|         this.submitCreateLibrary()
 | |
|       }
 | |
|     },
 | |
|     getLibraryUpdatePayload() {
 | |
|       var updatePayload = {}
 | |
|       for (const key in this.libraryCopy) {
 | |
|         if (key === 'folders') {
 | |
|           if (this.libraryCopy.folders.map((f) => f.fullPath).join(',') !== this.library.folders.map((f) => f.fullPath).join(',')) {
 | |
|             updatePayload.folders = [...this.libraryCopy.folders]
 | |
|           }
 | |
|         } else if (key === 'settings') {
 | |
|           for (const settingsKey in this.libraryCopy.settings) {
 | |
|             if (this.libraryCopy.settings[settingsKey] !== this.library.settings[settingsKey]) {
 | |
|               if (!updatePayload.settings) updatePayload.settings = {}
 | |
|               updatePayload.settings[settingsKey] = this.libraryCopy.settings[settingsKey]
 | |
|             }
 | |
|           }
 | |
|         } else if (key !== 'mediaType' && this.libraryCopy[key] !== this.library[key]) {
 | |
|           updatePayload[key] = this.libraryCopy[key]
 | |
|         }
 | |
|       }
 | |
|       return updatePayload
 | |
|     },
 | |
|     submitUpdateLibrary() {
 | |
|       var newLibraryPayload = this.getLibraryUpdatePayload()
 | |
|       if (!Object.keys(newLibraryPayload).length) {
 | |
|         this.$toast.info('No updates are necessary')
 | |
|         return
 | |
|       }
 | |
| 
 | |
|       this.processing = true
 | |
|       this.$axios
 | |
|         .$patch(`/api/libraries/${this.library.id}`, newLibraryPayload)
 | |
|         .then((res) => {
 | |
|           this.processing = false
 | |
|           this.show = false
 | |
|           this.$toast.success(this.$getString('ToastLibraryUpdateSuccess', [res.name]))
 | |
|         })
 | |
|         .catch((error) => {
 | |
|           console.error(error)
 | |
|           if (error.response && error.response.data) {
 | |
|             this.$toast.error(error.response.data)
 | |
|           } else {
 | |
|             this.$toast.error(this.$strings.ToastLibraryUpdateFailed)
 | |
|           }
 | |
|           this.processing = false
 | |
|         })
 | |
|     },
 | |
|     submitCreateLibrary() {
 | |
|       this.processing = true
 | |
|       this.$axios
 | |
|         .$post('/api/libraries', this.libraryCopy)
 | |
|         .then((res) => {
 | |
|           this.processing = false
 | |
|           this.show = false
 | |
|           this.$toast.success(this.$getString('ToastLibraryCreateSuccess', [res.name]))
 | |
|           if (!this.$store.state.libraries.currentLibraryId) {
 | |
|             console.log('Setting initially library id', res.id)
 | |
|             // First library added
 | |
|             this.$store.dispatch('libraries/fetch', res.id)
 | |
|           }
 | |
|         })
 | |
|         .catch((error) => {
 | |
|           console.error(error)
 | |
|           if (error.response && error.response.data) {
 | |
|             this.$toast.error(error.response.data)
 | |
|           } else {
 | |
|             this.$toast.error(this.$strings.ToastLibraryCreateFailed)
 | |
|           }
 | |
|           this.processing = false
 | |
|         })
 | |
|     }
 | |
|   },
 | |
|   mounted() {},
 | |
|   beforeDestroy() {}
 | |
| }
 | |
| </script>
 | |
| 
 | |
| <style scoped>
 | |
| .tab {
 | |
|   height: 40px;
 | |
| }
 | |
| .tab.tab-selected {
 | |
|   height: 41px;
 | |
| }
 | |
| </style> |