diff --git a/client/components/modals/edit-tabs/Details.vue b/client/components/modals/edit-tabs/Details.vue index 2703514e..9b9cec3f 100644 --- a/client/components/modals/edit-tabs/Details.vue +++ b/client/components/modals/edit-tabs/Details.vue @@ -115,6 +115,9 @@ export default { }, methods: { async submitForm() { + if (this.isProcessing) { + return + } this.isProcessing = true const updatePayload = { book: this.details, diff --git a/client/components/ui/Tooltip.vue b/client/components/ui/Tooltip.vue index 9a4420c3..a6ca5f67 100644 --- a/client/components/ui/Tooltip.vue +++ b/client/components/ui/Tooltip.vue @@ -10,6 +10,10 @@ export default { text: { type: String, required: true + }, + direction: { + type: String, + default: 'right' } }, data() { @@ -21,11 +25,17 @@ export default { methods: { createTooltip() { var boxChow = this.$refs.box.getBoundingClientRect() - var top = boxChow.top - var left = boxChow.left + boxChow.width + 4 - + var top = 0 + var left = 0 + if (this.direction === 'right') { + top = boxChow.top + left = boxChow.left + boxChow.width + 4 + } else if (this.direction === 'bottom') { + top = boxChow.top + boxChow.height + 4 + left = boxChow.left + } var tooltip = document.createElement('div') - tooltip.className = 'absolute px-2 bg-black bg-opacity-60 py-1 text-white pointer-events-none text-xs' + tooltip.className = 'absolute px-2 bg-black bg-opacity-90 py-1 text-white pointer-events-none text-xs rounded shadow-lg' tooltip.style.top = top + 'px' tooltip.style.left = left + 'px' tooltip.style.zIndex = 100 diff --git a/client/package.json b/client/package.json index f64ab72a..a882616f 100644 --- a/client/package.json +++ b/client/package.json @@ -1,6 +1,6 @@ { "name": "audiobookshelf-client", - "version": "0.9.74-beta", + "version": "0.9.75-beta", "description": "Audiobook manager and player", "main": "index.js", "scripts": { diff --git a/client/pages/audiobook/_id/index.vue b/client/pages/audiobook/_id/index.vue index 4ae592b7..26ed371d 100644 --- a/client/pages/audiobook/_id/index.vue +++ b/client/pages/audiobook/_id/index.vue @@ -13,7 +13,9 @@

{{ title }}

{{ seriesText }}

-

by {{ author }}

+ +

by {{ author }}

+
@@ -137,6 +139,16 @@ export default { author() { return this.book.author || 'Unknown' }, + authorFL() { + return this.book.authorFL + }, + authorLF() { + return this.book.authorLF + }, + authorTooltipText() { + var txt = ['FL: ' + this.authorFL || 'Not Set', 'LF: ' + this.authorLF || 'Not Set'] + return txt.join('\n') + }, series() { return this.book.series || null }, diff --git a/package.json b/package.json index f3f421ab..211b5b05 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "audiobookshelf", - "version": "0.9.74-beta", + "version": "0.9.75-beta", "description": "Self-hosted audiobook server for managing and playing audiobooks.", "main": "index.js", "scripts": { diff --git a/server/Audiobook.js b/server/Audiobook.js index 1908c55e..b99762cc 100644 --- a/server/Audiobook.js +++ b/server/Audiobook.js @@ -310,10 +310,6 @@ class Audiobook { return hasUpdates } - syncAuthorNames(audiobookData) { - return this.book.syncAuthorNames(audiobookData.authorFL, audiobookData.authorLF) - } - isSearchMatch(search) { return this.book.isSearchMatch(search.toLowerCase().trim()) } diff --git a/server/Book.js b/server/Book.js index b5275c6e..14619853 100644 --- a/server/Book.js +++ b/server/Book.js @@ -1,4 +1,6 @@ const Path = require('path') +const Logger = require('./Logger') +const parseAuthors = require('./utils/parseAuthors') class Book { constructor(book = null) { this.olid = null @@ -55,12 +57,29 @@ class Book { } } + setParseAuthor(author) { + if (!author) { + var hasUpdated = this.authorFL || this.authorLF + this.authorFL = null + this.authorLF = null + return hasUpdated + } + try { + var { authorLF, authorFL } = parseAuthors(author) + var hasUpdated = authorLF !== this.authorLF || authorFL !== this.authorFL + this.authorFL = authorFL || null + this.authorLF = authorLF || null + return hasUpdated + } catch (err) { + Logger.error('[Book] Parse authors failed', err) + return false + } + } + setData(data) { this.olid = data.olid || null this.title = data.title || null this.author = data.author || null - this.authorLF = data.authorLF || null - this.authorFL = data.authorFL || null this.series = data.series || null this.volumeNumber = data.volumeNumber || null this.publishYear = data.publishYear || null @@ -68,6 +87,10 @@ class Book { this.cover = data.cover || null this.genres = data.genres || [] + if (data.author) { + this.setParseAuthor(this.author) + } + // Use first image file as cover if (data.otherFiles && data.otherFiles.length) { var imageFile = data.otherFiles.find(f => f.filetype === 'image') @@ -90,6 +113,14 @@ class Book { this.genres = payload['genres'] hasUpdates = true } + } else if (key === 'author') { + if (this.author !== payload.author) { + this.author = payload.author || null + hasUpdates = true + } + if (this.setParseAuthor(this.author)) { + hasUpdates = true + } } else if (this[key] !== undefined && payload[key] !== this[key]) { this[key] = payload[key] hasUpdates = true @@ -98,19 +129,6 @@ class Book { return hasUpdates } - syncAuthorNames(authorFL, authorLF) { - var hasUpdates = false - if (authorFL !== this.authorFL) { - this.authorFL = authorFL - hasUpdates = true - } - if (authorLF !== this.authorLF) { - this.authorLF = authorLF - hasUpdates = true - } - return hasUpdates - } - isSearchMatch(search) { return this._title.toLowerCase().includes(search) || this._author.toLowerCase().includes(search) || this._series.toLowerCase().includes(search) } diff --git a/server/Scanner.js b/server/Scanner.js index fd051f22..7f9ee98a 100644 --- a/server/Scanner.js +++ b/server/Scanner.js @@ -1,4 +1,3 @@ -const Path = require('path') const Logger = require('./Logger') const BookFinder = require('./BookFinder') const Audiobook = require('./Audiobook') @@ -120,11 +119,6 @@ class Scanner { hasUpdates = true } - if (audiobookData.author && existingAudiobook.syncAuthorNames(audiobookData)) { - Logger.info(`[Scanner] "${existingAudiobook.title}" author names updated, "${existingAudiobook.authorLF}"`) - hasUpdates = true - } - if (hasUpdates) { Logger.info(`[Scanner] "${existingAudiobook.title}" was updated - saving`) existingAudiobook.lastUpdate = Date.now() diff --git a/server/utils/scandir.js b/server/utils/scandir.js index 0439d571..4cb1537b 100644 --- a/server/utils/scandir.js +++ b/server/utils/scandir.js @@ -1,7 +1,6 @@ const Path = require('path') const dir = require('node-dir') const Logger = require('../Logger') -const parseAuthors = require('./parseAuthors') const { cleanString } = require('./index') const AUDIOBOOK_PARTS_FORMATS = ['m4b', 'mp3'] @@ -75,14 +74,6 @@ async function getAllAudiobookFiles(abRootPath) { parts: [], otherFiles: [] } - if (author) { - var parsedAuthors = parseAuthors(author) - if (parsedAuthors) { - var { authorLF, authorFL } = parsedAuthors - audiobooks[path].authorLF = authorLF || null - audiobooks[path].authorFL = authorFL || null - } - } } var filetype = getFileType(pathformat.ext)