-
-
+
+
+
+
+
+
+
{{ series.name }}
+
+
+
+
+
+ {{ $strings.LabelDescription }}
+
+
{{ series.description }}
+
+
+
+ {{ authors.length > 1 ? $strings.LabelAuthors : $strings.LabelAuthor }}
+
+
{{ authors.join(', ') }}
+
+
+
{{ this.$strings.LabelTotalDuration }}
+
{{ totalDuration.hours }}hrs {{ totalDuration.minutes }}min
+
+
+
+
+
+
+
+
@@ -19,7 +51,7 @@ export default {
return redirect(`/library/${libraryId}`)
}
- const series = await app.$axios.$get(`/api/libraries/${library.id}/series/${params.id}?include=progress,rssfeed`).catch((error) => {
+ const series = await app.$axios.$get(`/api/libraries/${library.id}/series/${params.id}?include=progress,rssfeed&expanded=1`).catch((error) => {
console.error('Failed', error)
return false
})
@@ -33,16 +65,37 @@ export default {
}
},
data() {
- return {}
+ return {
+ showEditSeriesModal: false
+ }
},
computed: {
streamLibraryItem() {
return this.$store.state.streamLibraryItem
+ },
+ totalDuration() {
+ const totalSeconds = this.series.books.reduce((acc, book) => acc + book.duration, 0)
+ const hours = Math.floor(totalSeconds / 3600)
+ const minuteRemainder = totalSeconds % 3600
+ const minutes = Math.floor(minuteRemainder / 60)
+
+ return { hours, minutes }
+ },
+ authors() {
+ // Get nested array of authors
+ const nestedAuthors = this.series.books.map((book) => book.authors.map((author) => author.name))
+ // Flatten to one array
+ const authors = nestedAuthors.flat(1)
+ // Remove duplicates
+ return [...new Set(authors)]
}
},
methods: {
seriesUpdated(series) {
this.series = series
+ },
+ showEditSeries() {
+ this.showEditSeriesModal = !this.showEditSeriesModal
}
},
mounted() {
@@ -57,3 +110,12 @@ export default {
}
}
+
+
diff --git a/client/strings/en-us.json b/client/strings/en-us.json
index 6dba7adb..8a7718a1 100644
--- a/client/strings/en-us.json
+++ b/client/strings/en-us.json
@@ -324,6 +324,7 @@
"LabelEbook": "Ebook",
"LabelEbooks": "Ebooks",
"LabelEdit": "Edit",
+ "LabelEditSeries": "Edit Series",
"LabelEmail": "Email",
"LabelEmailSettingsFromAddress": "From Address",
"LabelEmailSettingsRejectUnauthorized": "Reject unauthorized certificates",
@@ -567,6 +568,7 @@
"LabelSequence": "Sequence",
"LabelSerial": "Serial",
"LabelSeries": "Series",
+ "LabelSeriesDescription": "Series Description",
"LabelSeriesName": "Series Name",
"LabelSeriesProgress": "Series Progress",
"LabelServerLogLevel": "Server Log Level",
diff --git a/server/controllers/LibraryController.js b/server/controllers/LibraryController.js
index e63441f0..f0aecf2c 100644
--- a/server/controllers/LibraryController.js
+++ b/server/controllers/LibraryController.js
@@ -783,12 +783,16 @@ class LibraryController {
.map((v) => v.trim().toLowerCase())
.filter((v) => !!v)
- const series = await Database.seriesModel.findByPk(req.params.seriesId)
+ const series = req.query.expanded ? await Database.seriesModel.getExpandedById(req.params.seriesId) : await Database.seriesModel.findByPk(req.params.seriesId)
if (!series) return res.sendStatus(404)
const libraryItemsInSeries = await libraryItemsBookFilters.getLibraryItemsForSeries(series, req.user)
const seriesJson = series.toOldJSON()
+ if (req.query.expanded) {
+ seriesJson.books = series.books
+ }
+
if (include.includes('progress')) {
const libraryItemsFinished = libraryItemsInSeries.filter((li) => !!req.user.getMediaProgress(li.media.id)?.isFinished)
seriesJson.progress = {