244 lines
7.5 KiB
Vue
244 lines
7.5 KiB
Vue
<template>
|
|
<modals-modal v-model="show" name="edit-library" :width="700" :height="'unset'" :processing="processing">
|
|
<template #outer>
|
|
<div class="absolute top-0 left-0 p-5 w-2/3 overflow-hidden">
|
|
<p class="font-book 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 font-book 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" :processing.sync="processing" @update="updateLibrary" @close="show = false" />
|
|
|
|
<div 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
|
|
},
|
|
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: 'schedule',
|
|
title: this.$strings.HeaderSchedule,
|
|
component: 'modals-libraries-schedule-scan'
|
|
}
|
|
]
|
|
},
|
|
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
|
|
}
|
|
}
|
|
},
|
|
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 }))
|
|
} 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 (!this.validate()) return
|
|
|
|
// 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.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> |