diff --git a/client/pages/batch/index.vue b/client/pages/batch/index.vue
index 5cc83176..263dee58 100644
--- a/client/pages/batch/index.vue
+++ b/client/pages/batch/index.vue
@@ -86,7 +86,12 @@
-
+
+
{{ $strings.ButtonReset }}
+
+ {{ $strings.ButtonBatchEditPopulateFromExisting }}
+
+
{{ $strings.ButtonApply }}
@@ -97,6 +102,11 @@
+
+
+ {{ $strings.ButtonBatchEditPopulateMapDetails }}
+
+
@@ -228,6 +238,88 @@ export default {
}
},
methods: {
+ resetMapDetails() {
+ this.blurBatchForm()
+ this.batchDetails = {
+ subtitle: null,
+ authors: null,
+ publishedYear: null,
+ series: [],
+ genres: [],
+ tags: [],
+ narrators: [],
+ publisher: null,
+ language: null,
+ explicit: false,
+ abridged: false
+ }
+ this.selectedBatchUsage = {
+ subtitle: false,
+ authors: false,
+ publishedYear: false,
+ series: false,
+ genres: false,
+ tags: false,
+ narrators: false,
+ publisher: false,
+ language: false,
+ explicit: false,
+ abridged: false
+ }
+ },
+ populateFromExisting(libraryItemId) {
+ this.blurBatchForm()
+
+ let libraryItemsToMap = this.libraryItemCopies
+ if (libraryItemId) {
+ libraryItemsToMap = this.libraryItemCopies.filter((li) => li.id === libraryItemId)
+ }
+
+ for (const key in this.selectedBatchUsage) {
+ if (!this.selectedBatchUsage[key]) continue
+ if (this.isMapAppend && !this.appendableKeys.includes(key)) continue
+
+ let existingValues = undefined
+ libraryItemsToMap.forEach((li) => {
+ if (key === 'tags') {
+ if (!existingValues) existingValues = []
+ li.media.tags.forEach((tag) => {
+ if (!existingValues.includes(tag)) {
+ existingValues.push(tag)
+ }
+ })
+ } else if (key === 'authors') {
+ if (!existingValues) existingValues = []
+ li.media.metadata[key].forEach((entity) => {
+ if (!existingValues.some((au) => au.id === entity.id)) {
+ existingValues.push({
+ id: entity.id,
+ name: entity.name
+ })
+ }
+ })
+ } else if (key === 'series') {
+ if (!existingValues) existingValues = []
+ li.media.metadata[key].forEach((entity) => {
+ if (!existingValues.includes(entity.name)) {
+ existingValues.push(entity.name)
+ }
+ })
+ } else if (key === 'genres' || key === 'narrators') {
+ if (!existingValues) existingValues = []
+ li.media.metadata[key].forEach((item) => {
+ if (!existingValues.includes(item)) {
+ existingValues.push(item)
+ }
+ })
+ } else if (existingValues === undefined) {
+ existingValues = li.media.metadata[key]
+ }
+ })
+
+ this.batchDetails[key] = existingValues
+ }
+ },
handleItemChange(itemChange) {
if (!itemChange.hasChanges) {
this.itemsWithChanges = this.itemsWithChanges.filter((id) => id !== itemChange.libraryItemId)
diff --git a/client/strings/en-us.json b/client/strings/en-us.json
index 37a3aae3..d8d5ead9 100644
--- a/client/strings/en-us.json
+++ b/client/strings/en-us.json
@@ -10,6 +10,8 @@
"ButtonApplyChapters": "Apply Chapters",
"ButtonAuthors": "Authors",
"ButtonBack": "Back",
+ "ButtonBatchEditPopulateFromExisting": "Populate from existing",
+ "ButtonBatchEditPopulateMapDetails": "Populate map details",
"ButtonBrowseForFolder": "Browse for Folder",
"ButtonCancel": "Cancel",
"ButtonCancelEncode": "Cancel Encode",
@@ -705,6 +707,8 @@
"MessageBackupsLocationNoEditNote": "Note: The backup location is set through an environment variable and cannot be changed here.",
"MessageBackupsLocationPathEmpty": "Backup location path cannot be empty",
"MessageBatchQuickMatchDescription": "Quick Match will attempt to add missing covers and metadata for the selected items. Enable the options below to allow Quick Match to overwrite existing covers and/or metadata.",
+ "MessageBatchEditPopulateMapDetailsAllHelp": "Populate enabled fields with data from all items. Fields with multiple values will be merged",
+ "MessageBatchEditPopulateMapDetailsItemHelp": "Populate enabled map details fields with data from this item",
"MessageBookshelfNoCollections": "You haven't made any collections yet",
"MessageBookshelfNoRSSFeeds": "No RSS feeds are open",
"MessageBookshelfNoResultsForFilter": "No results for filter \"{0}: {1}\"",