mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-12-26 05:39:38 +00:00
New data model update stats page and routes, update users page
This commit is contained in:
parent
4bdef893af
commit
be1e1e7ba0
7 changed files with 62 additions and 62 deletions
|
|
@ -5,7 +5,7 @@
|
|||
<path fill="currentColor" d="M9 3V18H12V3H9M12 5L16 18L19 17L15 4L12 5M5 5V18H8V5H5M3 19V21H21V19H3Z" />
|
||||
</svg>
|
||||
<div class="px-2">
|
||||
<p class="text-4xl md:text-5xl font-bold">{{ totalBooks }}</p>
|
||||
<p class="text-4xl md:text-5xl font-bold">{{ totalItems }}</p>
|
||||
<p class="font-book text-xs md:text-sm text-white text-opacity-80">Books in Library</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
<div class="flex px-4">
|
||||
<span class="material-icons text-7xl">show_chart</span>
|
||||
<div class="px-1">
|
||||
<p class="text-4xl md:text-5xl font-bold">{{ totalAudiobookHours }}</p>
|
||||
<p class="text-4xl md:text-5xl font-bold">{{ totalHours }}</p>
|
||||
<p class="font-book text-xs md:text-sm text-white text-opacity-80">Overall Hours</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -61,8 +61,8 @@ export default {
|
|||
user() {
|
||||
return this.$store.state.user.user
|
||||
},
|
||||
totalBooks() {
|
||||
return this.libraryStats ? this.libraryStats.totalBooks : 0
|
||||
totalItems() {
|
||||
return this.libraryStats ? this.libraryStats.totalItems : 0
|
||||
},
|
||||
totalAuthors() {
|
||||
return this.libraryStats ? this.libraryStats.totalAuthors : 0
|
||||
|
|
@ -70,11 +70,11 @@ export default {
|
|||
numAudioTracks() {
|
||||
return this.libraryStats ? this.libraryStats.numAudioTracks : 0
|
||||
},
|
||||
totalAudiobookDuration() {
|
||||
totalDuration() {
|
||||
return this.libraryStats ? this.libraryStats.totalDuration : 0
|
||||
},
|
||||
totalAudiobookHours() {
|
||||
var totalHours = Math.round(this.totalAudiobookDuration / (60 * 60))
|
||||
totalHours() {
|
||||
var totalHours = Math.round(this.totalDuration / (60 * 60))
|
||||
return totalHours
|
||||
},
|
||||
totalSizePretty() {
|
||||
|
|
|
|||
|
|
@ -11,12 +11,12 @@
|
|||
<template v-for="genre in top5Genres">
|
||||
<div :key="genre.genre" class="w-full py-2">
|
||||
<div class="flex items-end mb-1">
|
||||
<p class="text-2xl font-bold">{{ Math.round((100 * genre.count) / totalBooks) }} %</p>
|
||||
<p class="text-2xl font-bold">{{ Math.round((100 * genre.count) / totalItems) }} %</p>
|
||||
<div class="flex-grow" />
|
||||
<p class="text-base font-book text-white text-opacity-70">{{ genre.genre }}</p>
|
||||
</div>
|
||||
<div class="w-full rounded-full h-3 bg-primary bg-opacity-50 overflow-hidden">
|
||||
<div class="bg-yellow-400 h-full rounded-full" :style="{ width: Math.round((100 * genre.count) / totalBooks) + '%' }" />
|
||||
<div class="bg-yellow-400 h-full rounded-full" :style="{ width: Math.round((100 * genre.count) / totalItems) + '%' }" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -39,14 +39,14 @@
|
|||
</template>
|
||||
</div>
|
||||
<div class="w-80 my-6 mx-auto">
|
||||
<h1 class="text-2xl mb-4 font-book">Longest Audiobooks (hrs)</h1>
|
||||
<p v-if="!top10LongestAudiobooks.length">No Audiobooks</p>
|
||||
<template v-for="(ab, index) in top10LongestAudiobooks">
|
||||
<h1 class="text-2xl mb-4 font-book">Longest Items (hrs)</h1>
|
||||
<p v-if="!top10LongestItems.length">No Items</p>
|
||||
<template v-for="(ab, index) in top10LongestItems">
|
||||
<div :key="index" class="w-full py-2">
|
||||
<div class="flex items-center mb-1">
|
||||
<p class="text-sm font-book text-white text-opacity-70 w-44 pr-2 truncate">{{ index + 1 }}. {{ ab.title }}</p>
|
||||
<div class="flex-grow rounded-full h-2.5 bg-primary bg-opacity-0 overflow-hidden">
|
||||
<div class="bg-yellow-400 h-full rounded-full" :style="{ width: Math.round((100 * ab.duration) / longestAudiobookDuration) + '%' }" />
|
||||
<div class="bg-yellow-400 h-full rounded-full" :style="{ width: Math.round((100 * ab.duration) / longestItemDuration) + '%' }" />
|
||||
</div>
|
||||
<div class="w-4 ml-3">
|
||||
<p class="text-sm font-bold">{{ (ab.duration / 3600).toFixed(1) }}</p>
|
||||
|
|
@ -77,8 +77,8 @@ export default {
|
|||
user() {
|
||||
return this.$store.state.user.user
|
||||
},
|
||||
totalBooks() {
|
||||
return this.libraryStats ? this.libraryStats.totalBooks : 0
|
||||
totalItems() {
|
||||
return this.libraryStats ? this.libraryStats.totalItems : 0
|
||||
},
|
||||
genresWithCount() {
|
||||
return this.libraryStats ? this.libraryStats.genresWithCount : []
|
||||
|
|
@ -86,12 +86,12 @@ export default {
|
|||
top5Genres() {
|
||||
return this.genresWithCount.slice(0, 5)
|
||||
},
|
||||
top10LongestAudiobooks() {
|
||||
return this.libraryStats ? this.libraryStats.longestAudiobooks || [] : []
|
||||
top10LongestItems() {
|
||||
return this.libraryStats ? this.libraryStats.longestItems || [] : []
|
||||
},
|
||||
longestAudiobookDuration() {
|
||||
if (!this.top10LongestAudiobooks.length) return 0
|
||||
return this.top10LongestAudiobooks[0].duration
|
||||
longestItemDuration() {
|
||||
if (!this.top10LongestItems.length) return 0
|
||||
return this.top10LongestItems[0].duration
|
||||
},
|
||||
authorsWithCount() {
|
||||
return this.libraryStats ? this.libraryStats.authorsWithCount : []
|
||||
|
|
|
|||
|
|
@ -59,8 +59,8 @@
|
|||
export default {
|
||||
data() {
|
||||
return {
|
||||
listeningStats: null,
|
||||
libraryStats: null
|
||||
listeningStats: null
|
||||
// libraryStats: null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
|
@ -103,11 +103,11 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
async init() {
|
||||
this.libraryStats = await this.$axios.$get(`/api/libraries/${this.currentLibraryId}/stats`).catch((err) => {
|
||||
console.error('Failed to get library stats', err)
|
||||
var errorMsg = err.response ? err.response.data || 'Unknown Error' : 'Unknown Error'
|
||||
this.$toast.error(`Failed to get library stats: ${errorMsg}`)
|
||||
})
|
||||
// this.libraryStats = await this.$axios.$get(`/api/libraries/${this.currentLibraryId}/stats`).catch((err) => {
|
||||
// console.error('Failed to get library stats', err)
|
||||
// var errorMsg = err.response ? err.response.data || 'Unknown Error' : 'Unknown Error'
|
||||
// this.$toast.error(`Failed to get library stats: ${errorMsg}`)
|
||||
// })
|
||||
this.listeningStats = await this.$axios.$get(`/api/me/listening-stats`).catch((err) => {
|
||||
console.error('Failed to load listening sesions', err)
|
||||
return []
|
||||
|
|
|
|||
|
|
@ -43,11 +43,11 @@
|
|||
</tr>
|
||||
<tr v-for="ab in userAudiobooks" :key="ab.audiobookId" :class="!ab.isRead ? '' : 'isRead'">
|
||||
<td>
|
||||
<covers-book-cover :width="50" :audiobook="ab" :book-cover-aspect-ratio="bookCoverAspectRatio" />
|
||||
<covers-book-cover :width="50" :library-item="ab" :book-cover-aspect-ratio="bookCoverAspectRatio" />
|
||||
</td>
|
||||
<td class="font-book">
|
||||
<p>{{ ab.book ? ab.book.title : ab.audiobookTitle || 'Unknown' }}</p>
|
||||
<p v-if="ab.book && ab.book.author" class="text-white text-opacity-50 text-sm font-sans">by {{ ab.book.author }}</p>
|
||||
<p>{{ ab.media && ab.media.metadata ? ab.media.metadata.title : ab.audiobookTitle || 'Unknown' }}</p>
|
||||
<p v-if="ab.media && ab.media.metadata && ab.media.metadata.authorName" class="text-white text-opacity-50 text-sm font-sans">by {{ ab.media.metadata.authorName }}</p>
|
||||
</td>
|
||||
<td class="text-center">{{ Math.floor(ab.progress * 100) }}%</td>
|
||||
<td class="text-center hidden sm:table-cell">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue