@@ -265,8 +265,24 @@ export default {
this.isProcessing = false
this.hasSearched = true
},
- setCover(cover) {
- this.updateCover(cover)
+ setCover(coverFile) {
+ this.isProcessing = true
+ this.$axios
+ .$patch(`/api/audiobook/${this.audiobook.id}/coverfile`, coverFile)
+ .then((data) => {
+ console.log('response data', data)
+ if (data && typeof data === 'string') {
+ this.$toast.success(data)
+ }
+ this.isProcessing = false
+ })
+ .catch((error) => {
+ console.error('Failed to update', error)
+ if (error.response && error.response.data) {
+ this.$toast.error(error.response.data)
+ }
+ this.isProcessing = false
+ })
}
}
}
diff --git a/client/components/modals/edit-tabs/Details.vue b/client/components/modals/edit-tabs/Details.vue
index 0373b329..bf92a54d 100644
--- a/client/components/modals/edit-tabs/Details.vue
+++ b/client/components/modals/edit-tabs/Details.vue
@@ -214,8 +214,6 @@ export default {
this.details.volumeNumber = this.book.volumeNumber
this.details.publishYear = this.book.publishYear
- console.log('INIT', this.details)
-
this.newTags = this.audiobook.tags || []
},
resetProgress() {
diff --git a/client/components/modals/edit-tabs/Files.vue b/client/components/modals/edit-tabs/Files.vue
new file mode 100644
index 00000000..39393cff
--- /dev/null
+++ b/client/components/modals/edit-tabs/Files.vue
@@ -0,0 +1,21 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/client/components/modals/edit-tabs/Tracks.vue b/client/components/modals/edit-tabs/Tracks.vue
index 1618dc75..e1eafbad 100644
--- a/client/components/modals/edit-tabs/Tracks.vue
+++ b/client/components/modals/edit-tabs/Tracks.vue
@@ -53,7 +53,6 @@ export default {
data() {
return {
tracks: null,
- audioFiles: null,
showFullPath: false
}
},
@@ -104,7 +103,6 @@ export default {
},
methods: {
init() {
- this.audioFiles = this.audiobook.audioFiles
this.tracks = this.audiobook.tracks
}
}
diff --git a/client/components/tables/AllFilesTable.vue b/client/components/tables/AllFilesTable.vue
new file mode 100644
index 00000000..7071aa40
--- /dev/null
+++ b/client/components/tables/AllFilesTable.vue
@@ -0,0 +1,109 @@
+
+
+
+
Files
+
{{ allFiles.length }}
+
+
+
Full Path
+
+
+
+
+ Path
+ Filetype
+ Download
+
+
+
+
+ {{ showFullPath ? file.fullPath : file.path }}
+
+
+ {{ file.filetype }}
+
+
+ download
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/components/tables/OtherFilesTable.vue b/client/components/tables/OtherFilesTable.vue
index 8506ac70..377d588b 100644
--- a/client/components/tables/OtherFilesTable.vue
+++ b/client/components/tables/OtherFilesTable.vue
@@ -20,7 +20,7 @@
Path
Filetype
- Download
+ Download
@@ -28,9 +28,12 @@
{{ showFullPath ? file.fullPath : file.path }}
- {{ file.filetype }}
+
+
auto_stories
+
{{ file.filetype }}
+
-
+
download
@@ -83,11 +86,17 @@ export default {
userToken() {
return this.$store.getters['user/getToken']
},
+ isMissing() {
+ return this.audiobook.isMissing
+ },
userCanDownload() {
return this.$store.getters['user/getUserCanDownload']
}
},
methods: {
+ readEbookClick(file) {
+ this.$store.commit('showEReaderForFile', { audiobook: this.audiobook, file })
+ },
clickBar() {
this.showFiles = !this.showFiles
}
diff --git a/client/components/ui/InputDropdown.vue b/client/components/ui/InputDropdown.vue
index 53729f98..6836679c 100644
--- a/client/components/ui/InputDropdown.vue
+++ b/client/components/ui/InputDropdown.vue
@@ -116,9 +116,6 @@ export default {
this.textInput = null
this.currentSearch = null
this.input = item
-
- // this.input = this.textInput ? this.textInput.trim() : null
- console.log('Clicked option', item)
if (this.$refs.input) this.$refs.input.blur()
}
},
diff --git a/client/components/ui/MultiSelect.vue b/client/components/ui/MultiSelect.vue
index 15a458f5..8cd27902 100644
--- a/client/components/ui/MultiSelect.vue
+++ b/client/components/ui/MultiSelect.vue
@@ -127,6 +127,7 @@ export default {
return
}
this.isFocused = false
+ if (this.textInput) this.submitForm()
}, 50)
},
focus() {
@@ -145,6 +146,7 @@ export default {
var newSelected = null
if (this.selected.includes(itemValue)) {
newSelected = this.selected.filter((s) => s !== itemValue)
+ this.$emit('removedItem', itemValue)
} else {
newSelected = this.selected.concat([itemValue])
}
@@ -164,6 +166,7 @@ export default {
removeItem(item) {
var remaining = this.selected.filter((i) => i !== item)
this.$emit('input', remaining)
+ this.$emit('removedItem', item)
this.$nextTick(() => {
this.recalcMenuPos()
})
@@ -171,6 +174,7 @@ export default {
insertNewItem(item) {
this.selected.push(item)
this.$emit('input', this.selected)
+ this.$emit('newItem', item)
this.textInput = null
this.currentSearch = null
this.$nextTick(() => {
diff --git a/client/components/ui/ReadIconBtn.vue b/client/components/ui/ReadIconBtn.vue
index d8141c33..1eccf2ba 100644
--- a/client/components/ui/ReadIconBtn.vue
+++ b/client/components/ui/ReadIconBtn.vue
@@ -1,7 +1,7 @@
-
+
diff --git a/client/package-lock.json b/client/package-lock.json
index c2b50e62..8c5c4466 100644
--- a/client/package-lock.json
+++ b/client/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "audiobookshelf-client",
- "version": "1.4.6",
+ "version": "1.4.8",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -3415,6 +3415,11 @@
"@babel/helper-define-polyfill-provider": "^0.2.2"
}
},
+ "babel-plugin-syntax-dynamic-import": {
+ "version": "6.18.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz",
+ "integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo="
+ },
"backo2": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
@@ -8494,6 +8499,11 @@
"sha.js": "^2.4.8"
}
},
+ "pdfjs-dist": {
+ "version": "2.6.347",
+ "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.6.347.tgz",
+ "integrity": "sha512-QC+h7hG2su9v/nU1wEI3SnpPIrqJODL7GTDFvR74ANKGq1AFJW16PH8VWnhpiTi9YcLSFV9xLeWSgq+ckHLdVQ=="
+ },
"picomatch": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
@@ -11239,6 +11249,37 @@
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
},
+ "raw-loader": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz",
+ "integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==",
+ "requires": {
+ "loader-utils": "^2.0.0",
+ "schema-utils": "^3.0.0"
+ },
+ "dependencies": {
+ "loader-utils": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
+ "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
+ "requires": {
+ "big.js": "^5.2.2",
+ "emojis-list": "^3.0.0",
+ "json5": "^2.1.2"
+ }
+ },
+ "schema-utils": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
+ "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==",
+ "requires": {
+ "@types/json-schema": "^7.0.8",
+ "ajv": "^6.12.5",
+ "ajv-keywords": "^3.5.2"
+ }
+ }
+ }
+ },
"rc9": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/rc9/-/rc9-1.2.0.tgz",
@@ -13314,6 +13355,24 @@
"resolved": "https://registry.npmjs.org/vue-no-ssr/-/vue-no-ssr-1.1.1.tgz",
"integrity": "sha512-ZMjqRpWabMPqPc7gIrG0Nw6vRf1+itwf0Itft7LbMXs2g3Zs/NFmevjZGN1x7K3Q95GmIjWbQZTVerxiBxI+0g=="
},
+ "vue-pdf": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/vue-pdf/-/vue-pdf-4.3.0.tgz",
+ "integrity": "sha512-zd3lJj6CbtrawgaaDDciTDjkJMUKiLWtbEmBg5CvFn9Noe9oAO/GNy/fc5c59qGuFCJ14ibIV1baw4S07e5bSQ==",
+ "requires": {
+ "babel-plugin-syntax-dynamic-import": "^6.18.0",
+ "loader-utils": "^1.4.0",
+ "pdfjs-dist": "2.6.347",
+ "raw-loader": "^4.0.2",
+ "vue-resize-sensor": "^2.0.0",
+ "worker-loader": "^2.0.0"
+ }
+ },
+ "vue-resize-sensor": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/vue-resize-sensor/-/vue-resize-sensor-2.0.0.tgz",
+ "integrity": "sha512-W+y2EAI/BxS4Vlcca9scQv8ifeBFck56DRtSwWJ2H4Cw1GLNUYxiZxUHHkuzuI5JPW/cYtL1bPO5xPyEXx4LmQ=="
+ },
"vue-router": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.5.2.tgz",
@@ -14181,6 +14240,26 @@
"errno": "~0.1.7"
}
},
+ "worker-loader": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/worker-loader/-/worker-loader-2.0.0.tgz",
+ "integrity": "sha512-tnvNp4K3KQOpfRnD20m8xltE3eWh89Ye+5oj7wXEEHKac1P4oZ6p9oTj8/8ExqoSBnk9nu5Pr4nKfQ1hn2APJw==",
+ "requires": {
+ "loader-utils": "^1.0.0",
+ "schema-utils": "^0.4.0"
+ },
+ "dependencies": {
+ "schema-utils": {
+ "version": "0.4.7",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz",
+ "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==",
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-keywords": "^3.1.0"
+ }
+ }
+ }
+ },
"wrap-ansi": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
diff --git a/client/package.json b/client/package.json
index 80675f82..e353a81b 100644
--- a/client/package.json
+++ b/client/package.json
@@ -1,6 +1,6 @@
{
"name": "audiobookshelf-client",
- "version": "1.4.8",
+ "version": "1.4.9",
"description": "Audiobook manager and player",
"main": "index.js",
"scripts": {
@@ -21,6 +21,7 @@
"hls.js": "^1.0.7",
"nuxt": "^2.15.7",
"nuxt-socket-io": "^1.1.18",
+ "vue-pdf": "^4.3.0",
"vue-toastification": "^1.7.11",
"vuedraggable": "^2.24.3"
},
diff --git a/client/pages/audiobook/_id/index.vue b/client/pages/audiobook/_id/index.vue
index 822e0225..00407cf3 100644
--- a/client/pages/audiobook/_id/index.vue
+++ b/client/pages/audiobook/_id/index.vue
@@ -411,6 +411,7 @@ export default {
this.$root.socket.emit('open_stream', this.audiobook.id)
},
editClick() {
+ this.$store.commit('setBookshelfBookIds', [])
this.$store.commit('showEditModal', this.audiobook)
},
lookupMetadata(index) {
diff --git a/client/pages/batch/index.vue b/client/pages/batch/index.vue
index 9307bab3..d8c54281 100644
--- a/client/pages/batch/index.vue
+++ b/client/pages/batch/index.vue
@@ -33,10 +33,10 @@
@@ -76,7 +76,9 @@ export default {
isProcessing: false,
audiobookCopies: [],
isScrollable: false,
- newSeriesItems: []
+ newSeriesItems: [],
+ newTagItems: [],
+ newGenreItems: []
}
},
computed: {
@@ -86,9 +88,15 @@ export default {
genres() {
return this.$store.state.audiobooks.genres
},
+ genreItems() {
+ return this.genres.concat(this.newGenreItems)
+ },
tags() {
return this.$store.state.audiobooks.tags
},
+ tagItems() {
+ return this.tags.concat(this.newTagItems)
+ },
series() {
return this.$store.state.audiobooks.series
},
@@ -100,9 +108,42 @@ export default {
}
},
methods: {
+ newTagItem(item) {
+ if (item && !this.newTagItems.includes(item)) {
+ this.newTagItems.push(item)
+ }
+ },
+ removedTagItem(item) {
+ // If newly added, remove if not used on any other audiobooks
+ if (item && this.newTagItems.includes(item)) {
+ var usedByOtherAb = this.audiobookCopies.find((ab) => {
+ return ab.tags && ab.tags.includes(item)
+ })
+ if (!usedByOtherAb) {
+ this.newTagItems = this.newTagItems.filter((t) => t !== item)
+ }
+ }
+ },
+ newGenreItem(item) {
+ if (item && !this.newGenreItems.includes(item)) {
+ this.newGenreItems.push(item)
+ }
+ },
+ removedGenreItem(item) {
+ // If newly added, remove if not used on any other audiobooks
+ if (item && this.newGenreItems.includes(item)) {
+ var usedByOtherAb = this.audiobookCopies.find((ab) => {
+ return ab.book.genres && ab.book.genres.includes(item)
+ })
+ if (!usedByOtherAb) {
+ this.newGenreItems = this.newGenreItems.filter((t) => t !== item)
+ }
+ }
+ },
newSeriesItem(item) {
- if (!item) return
- this.newSeriesItems.push(item)
+ if (item && !this.newSeriesItems.includes(item)) {
+ this.newSeriesItems.push(item)
+ }
},
seriesChanged() {
this.newSeriesItems = this.newSeriesItems.filter((item) => {
diff --git a/client/pages/index.vue b/client/pages/index.vue
index a93130dd..06dc613b 100644
--- a/client/pages/index.vue
+++ b/client/pages/index.vue
@@ -21,9 +21,7 @@