mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-11-24 20:05:41 +01:00
Added progress to upload
This commit is contained in:
parent
e040396b20
commit
9ce6de3100
@ -62,7 +62,24 @@
|
|||||||
</widgets-alert>
|
</widgets-alert>
|
||||||
|
|
||||||
<div v-if="isNonInteractable" class="absolute top-0 left-0 w-full h-full bg-black/50 flex items-center justify-center z-20">
|
<div v-if="isNonInteractable" class="absolute top-0 left-0 w-full h-full bg-black/50 flex items-center justify-center z-20">
|
||||||
<ui-loading-indicator :text="nonInteractionLabel" />
|
<ui-loading-indicator>
|
||||||
|
<div class="mb-4">
|
||||||
|
<span class="text-lg font-medium text-white">
|
||||||
|
{{ nonInteractionLabel }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="isUploading" class="w-64 mx-auto mb-2">
|
||||||
|
<div class="flex items-center justify-center mb-2">
|
||||||
|
<span class="text-sm font-medium text-white/60 text-center w-full">
|
||||||
|
{{ uploadProgressText }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="w-full bg-primary/20 rounded-full h-2.5">
|
||||||
|
<div class="bg-green-500 h-2.5 rounded-full transition-all duration-300 ease-out" :style="{ width: uploadProgressPercent + '%' }"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ui-loading-indicator>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -91,7 +108,11 @@ export default {
|
|||||||
isUploading: false,
|
isUploading: false,
|
||||||
uploadFailed: false,
|
uploadFailed: false,
|
||||||
uploadSuccess: false,
|
uploadSuccess: false,
|
||||||
isFetchingMetadata: false
|
isFetchingMetadata: false,
|
||||||
|
uploadProgress: {
|
||||||
|
loaded: 0,
|
||||||
|
total: 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -116,13 +137,44 @@ export default {
|
|||||||
} else if (this.isFetchingMetadata) {
|
} else if (this.isFetchingMetadata) {
|
||||||
return this.$strings.LabelFetchingMetadata
|
return this.$strings.LabelFetchingMetadata
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
uploadProgressPercent() {
|
||||||
|
if (this.uploadProgress.total === 0) return 0
|
||||||
|
return Math.min(100, Math.round((this.uploadProgress.loaded / this.uploadProgress.total) * 100))
|
||||||
|
},
|
||||||
|
uploadProgressText() {
|
||||||
|
const loaded = this.formatBytes(this.uploadProgress.loaded)
|
||||||
|
const total = this.formatBytes(this.uploadProgress.total)
|
||||||
|
return `${this.uploadProgressPercent}% (${loaded} / ${total})`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
formatBytes(bytes) {
|
||||||
|
if (bytes === 0) return '0 Bytes'
|
||||||
|
const k = 1024
|
||||||
|
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']
|
||||||
|
const i = Math.floor(Math.log(bytes) / Math.log(k))
|
||||||
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
|
||||||
|
},
|
||||||
setUploadStatus(status) {
|
setUploadStatus(status) {
|
||||||
this.isUploading = status === 'uploading'
|
this.isUploading = status === 'uploading'
|
||||||
this.uploadFailed = status === 'failed'
|
this.uploadFailed = status === 'failed'
|
||||||
this.uploadSuccess = status === 'success'
|
this.uploadSuccess = status === 'success'
|
||||||
|
|
||||||
|
if (status !== 'uploading') {
|
||||||
|
this.uploadProgress = {
|
||||||
|
loaded: 0,
|
||||||
|
total: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setUploadProgress(progress) {
|
||||||
|
if (this.isUploading && progress) {
|
||||||
|
this.uploadProgress = {
|
||||||
|
loaded: progress.loaded || 0,
|
||||||
|
total: progress.total || 0
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
titleUpdated() {
|
titleUpdated() {
|
||||||
this.error = ''
|
this.error = ''
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="w-40">
|
<div :class="hasSlotContent ? 'w-auto' : 'w-40'">
|
||||||
<div class="bg-bg border border-gray-500 py-2 px-5 rounded-lg flex items-center flex-col box-shadow-md">
|
<div class="bg-bg border border-gray-500 py-2 px-5 rounded-lg flex items-center flex-col box-shadow-md">
|
||||||
<div class="loader-dots block relative w-20 h-5 mt-2">
|
<div class="loader-dots block relative w-20 h-5 mt-2">
|
||||||
<div class="absolute top-0 mt-1 w-3 h-3 rounded-full bg-green-500"></div>
|
<div class="absolute top-0 mt-1 w-3 h-3 rounded-full bg-green-500"></div>
|
||||||
@ -7,7 +7,9 @@
|
|||||||
<div class="absolute top-0 mt-1 w-3 h-3 rounded-full bg-green-500"></div>
|
<div class="absolute top-0 mt-1 w-3 h-3 rounded-full bg-green-500"></div>
|
||||||
<div class="absolute top-0 mt-1 w-3 h-3 rounded-full bg-green-500"></div>
|
<div class="absolute top-0 mt-1 w-3 h-3 rounded-full bg-green-500"></div>
|
||||||
</div>
|
</div>
|
||||||
|
<slot>
|
||||||
<div class="text-gray-200 text-xs font-light mt-2 text-center">{{ message }}</div>
|
<div class="text-gray-200 text-xs font-light mt-2 text-center">{{ message }}</div>
|
||||||
|
</slot>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -23,6 +25,9 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
message() {
|
message() {
|
||||||
return this.text || this.$strings.MessagePleaseWait
|
return this.text || this.$strings.MessagePleaseWait
|
||||||
|
},
|
||||||
|
hasSlotContent() {
|
||||||
|
return this.$slots.default && this.$slots.default.length > 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -297,6 +297,15 @@ export default {
|
|||||||
ref.setUploadStatus(status)
|
ref.setUploadStatus(status)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
updateItemCardProgress(index, progress) {
|
||||||
|
var ref = this.$refs[`itemCard-${index}`]
|
||||||
|
if (ref && ref.length) ref = ref[0]
|
||||||
|
if (!ref) {
|
||||||
|
console.error('Book card ref not found', index, this.$refs)
|
||||||
|
} else {
|
||||||
|
ref.setUploadProgress(progress)
|
||||||
|
}
|
||||||
|
},
|
||||||
async uploadItem(item) {
|
async uploadItem(item) {
|
||||||
var form = new FormData()
|
var form = new FormData()
|
||||||
form.set('title', item.title)
|
form.set('title', item.title)
|
||||||
@ -312,8 +321,20 @@ export default {
|
|||||||
form.set(`${index++}`, file)
|
form.set(`${index++}`, file)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
onUploadProgress: (progressEvent) => {
|
||||||
|
if (progressEvent.lengthComputable) {
|
||||||
|
const progress = {
|
||||||
|
loaded: progressEvent.loaded,
|
||||||
|
total: progressEvent.total
|
||||||
|
}
|
||||||
|
this.updateItemCardProgress(item.index, progress)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return this.$axios
|
return this.$axios
|
||||||
.$post('/api/upload', form)
|
.$post('/api/upload', form, config)
|
||||||
.then(() => true)
|
.then(() => true)
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error('Failed to upload item', error)
|
console.error('Failed to upload item', error)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user