audiobookshelf/client/components/modals/item/tabs/Details.vue

220 lines
7.1 KiB
Vue
Raw Normal View History

2021-08-18 00:01:11 +02:00
<template>
<div class="w-full h-full relative">
<div id="formWrapper" class="w-full overflow-y-auto">
<widgets-book-details-edit v-if="mediaType == 'book'" ref="itemDetailsEdit" :library-item="libraryItem" @submit="saveAndClose" />
<widgets-podcast-details-edit v-else ref="itemDetailsEdit" :library-item="libraryItem" @submit="saveAndClose" />
</div>
<div class="absolute bottom-0 left-0 w-full py-2 md:py-4 bg-bg" :class="isScrollable ? 'box-shadow-md-up' : 'border-t border-white border-opacity-5'">
<div class="flex items-center px-4">
2022-11-08 01:27:17 +01:00
<ui-tooltip :disabled="!!quickMatching" :text="$getString('MessageQuickMatchDescription', [libraryProvider])" direction="bottom" class="mr-2 md:mr-4">
<ui-btn v-if="userIsAdminOrUp" :loading="quickMatching" color="bg" type="button" class="h-full" small @click.stop.prevent="quickMatch">{{ $strings.ButtonQuickMatch }}</ui-btn>
</ui-tooltip>
2021-08-18 00:01:11 +02:00
2022-09-03 00:50:09 +02:00
<ui-tooltip :disabled="!!libraryScan" text="Rescan library item including metadata" direction="bottom" class="mr-2 md:mr-4">
2022-11-08 01:27:17 +01:00
<ui-btn v-if="userIsAdminOrUp && !isFile" :loading="rescanning" :disabled="!!libraryScan" color="bg" type="button" class="h-full" small @click.stop.prevent="rescan">{{ $strings.ButtonReScan }}</ui-btn>
</ui-tooltip>
<div class="flex-grow" />
2022-11-08 01:27:17 +01:00
<!-- desktop -->
<ui-btn @click="save" class="mx-2 hidden md:block">{{ $strings.ButtonSave }}</ui-btn>
<ui-btn @click="saveAndClose" class="mx-2 hidden md:block">{{ $strings.ButtonSaveAndClose }}</ui-btn>
<!-- mobile -->
<ui-btn @click="saveAndClose" class="mx-2 md:hidden">{{ $strings.ButtonSave }}</ui-btn>
2021-09-06 23:11:37 +02:00
</div>
</div>
2021-08-18 00:01:11 +02:00
</div>
</template>
<script>
export default {
props: {
processing: Boolean,
libraryItem: {
2021-08-18 00:01:11 +02:00
type: Object,
default: () => {}
}
},
data() {
return {
resettingProgress: false,
isScrollable: false,
2022-02-15 23:15:09 +01:00
rescanning: false,
quickMatching: false
2021-08-18 00:01:11 +02:00
}
},
computed: {
isProcessing: {
get() {
return this.processing
},
set(val) {
this.$emit('update:processing', val)
}
},
isFile() {
return !!this.libraryItem && this.libraryItem.isFile
},
userIsAdminOrUp() {
return this.$store.getters['user/getIsAdminOrUp']
},
2021-10-27 00:55:48 +02:00
isMissing() {
return !!this.libraryItem && !!this.libraryItem.isMissing
2021-10-27 00:55:48 +02:00
},
libraryItemId() {
return this.libraryItem ? this.libraryItem.id : null
2021-08-18 00:01:11 +02:00
},
media() {
return this.libraryItem ? this.libraryItem.media || {} : {}
},
mediaType() {
return this.libraryItem ? this.libraryItem.mediaType : null
},
mediaMetadata() {
return this.media.metadata || {}
2021-08-18 00:01:11 +02:00
},
2021-10-06 04:10:49 +02:00
libraryId() {
return this.libraryItem ? this.libraryItem.libraryId : null
2021-10-06 04:10:49 +02:00
},
2022-02-15 23:15:09 +01:00
libraryProvider() {
return this.$store.getters['libraries/getLibraryProvider'](this.libraryId) || 'google'
},
2021-10-06 04:10:49 +02:00
libraryScan() {
if (!this.libraryId) return null
return this.$store.getters['scanners/getLibraryScan'](this.libraryId)
2021-08-18 00:01:11 +02:00
}
},
methods: {
2022-02-15 23:15:09 +01:00
quickMatch() {
if (this.quickMatching) return
if (!this.$refs.itemDetailsEdit) return
var { title, author } = this.$refs.itemDetailsEdit.getTitleAndAuthorName()
if (!title) {
this.$toast.error('Must have a title for quick match')
return
}
2022-02-15 23:15:09 +01:00
this.quickMatching = true
var matchOptions = {
provider: this.libraryProvider,
title: title || null,
author: author || null
2022-02-15 23:15:09 +01:00
}
this.$axios
.$post(`/api/items/${this.libraryItemId}/match`, matchOptions)
2022-02-15 23:15:09 +01:00
.then((res) => {
this.quickMatching = false
if (res.warning) {
this.$toast.warning(res.warning)
} else if (res.updated) {
this.$toast.success('Item details updated')
2022-02-15 23:15:09 +01:00
} else {
this.$toast.info('No updates were made')
}
})
.catch((error) => {
var errMsg = error.response ? error.response.data || '' : ''
console.error('Failed to match', error)
this.$toast.error(errMsg || 'Failed to match')
this.quickMatching = false
})
},
rescan() {
this.rescanning = true
this.$axios
.$post(`/api/items/${this.libraryItemId}/scan`)
.then((data) => {
this.rescanning = false
var result = data.result
if (!result) {
this.$toast.error(`Re-Scan Failed for "${this.title}"`)
} else if (result === 'UPDATED') {
this.$toast.success(`Re-Scan complete item was updated`)
} else if (result === 'UPTODATE') {
this.$toast.success(`Re-Scan complete item was up to date`)
} else if (result === 'REMOVED') {
this.$toast.error(`Re-Scan complete item was removed`)
}
})
.catch((error) => {
console.error('Failed to scan library item', error)
this.$toast.error('Failed to scan library item')
this.rescanning = false
})
},
async saveAndClose() {
const wasUpdated = await this.save()
if (wasUpdated !== null) this.$emit('close')
},
async save() {
if (this.isProcessing) {
return null
}
if (!this.$refs.itemDetailsEdit) {
return null
2021-12-02 02:07:03 +01:00
}
var updatedDetails = this.$refs.itemDetailsEdit.getDetails()
if (!updatedDetails.hasChanges) {
this.$toast.info('No changes were made')
return false
2021-12-02 02:07:03 +01:00
}
return this.updateDetails(updatedDetails)
2021-12-02 02:07:03 +01:00
},
async updateDetails(updatedDetails) {
this.isProcessing = true
2022-03-14 14:12:28 +01:00
var updateResult = await this.$axios.$patch(`/api/items/${this.libraryItemId}/media`, updatedDetails.updatePayload).catch((error) => {
2021-08-18 00:01:11 +02:00
console.error('Failed to update', error)
return false
})
this.isProcessing = false
2022-03-14 14:12:28 +01:00
if (updateResult) {
if (updateResult.updated) {
this.$toast.success('Item details updated')
return true
2022-03-14 14:12:28 +01:00
} else {
2022-11-09 00:10:08 +01:00
this.$toast.info(this.$strings.MessageNoUpdatesWereNecessary)
2022-03-14 14:12:28 +01:00
}
2021-08-18 00:01:11 +02:00
}
return false
2021-08-18 00:01:11 +02:00
},
checkIsScrollable() {
this.$nextTick(() => {
var formWrapper = document.getElementById('formWrapper')
if (formWrapper) {
if (formWrapper.scrollHeight > formWrapper.clientHeight) {
this.isScrollable = true
} else {
this.isScrollable = false
}
}
})
},
setResizeObserver() {
try {
var formWrapper = document.getElementById('formWrapper')
if (formWrapper) {
this.$nextTick(() => {
const resizeObserver = new ResizeObserver(() => {
this.checkIsScrollable()
})
resizeObserver.observe(formWrapper)
})
}
} catch (error) {
console.error('Failed to set resize observer')
}
2021-08-18 00:01:11 +02:00
}
},
mounted() {
this.setResizeObserver()
2021-08-18 00:01:11 +02:00
}
}
</script>
<style scoped>
#formWrapper {
height: calc(100% - 80px);
max-height: calc(100% - 80px);
}
</style>