upload file, work on delete file
This commit is contained in:
parent
e3fd809820
commit
631c066415
@ -2,15 +2,8 @@
|
|||||||
<div>
|
<div>
|
||||||
<Menu />
|
<Menu />
|
||||||
<b-container class="browser">
|
<b-container class="browser">
|
||||||
<loading
|
|
||||||
:active.sync="isLoading"
|
|
||||||
:can-cancel="false"
|
|
||||||
:is-full-page="false"
|
|
||||||
background-color="#485159"
|
|
||||||
color="#ff9c36"
|
|
||||||
/>
|
|
||||||
<div v-if="folderTree.tree" class="browser">
|
<div v-if="folderTree.tree" class="browser">
|
||||||
<div>
|
<div class="bread-div">
|
||||||
<b-breadcrumb>
|
<b-breadcrumb>
|
||||||
<b-breadcrumb-item
|
<b-breadcrumb-item
|
||||||
v-for="(crumb, index) in crumbs"
|
v-for="(crumb, index) in crumbs"
|
||||||
@ -23,57 +16,166 @@
|
|||||||
</b-breadcrumb>
|
</b-breadcrumb>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<b-row>
|
<splitpanes class="browser-row default-theme pane-row">
|
||||||
<b-col class="folder-col">
|
<pane min-size="20" size="24">
|
||||||
<div class="browser-div">
|
<div class="browser-div">
|
||||||
<b-list-group>
|
<perfect-scrollbar>
|
||||||
|
<b-list-group class="folder-list">
|
||||||
<b-list-group-item
|
<b-list-group-item
|
||||||
v-for="folder in folderTree.tree[1]"
|
v-for="folder in folderTree.tree[1]"
|
||||||
:key="folder.key"
|
:key="folder.key"
|
||||||
class="browser-item"
|
class="browser-item folder"
|
||||||
>
|
>
|
||||||
|
<b-row>
|
||||||
|
<b-col cols="1" class="browser-icons-col">
|
||||||
|
<b-icon-folder-fill class="browser-icons" />
|
||||||
|
</b-col>
|
||||||
|
<b-col class="browser-item-text">
|
||||||
<b-link @click="getPath(extensions, `${folderTree.tree[0]}/${folder}`)">
|
<b-link @click="getPath(extensions, `${folderTree.tree[0]}/${folder}`)">
|
||||||
<b-icon-folder-fill class="browser-icons" /> {{ folder }}
|
{{ folder }}
|
||||||
</b-link>
|
</b-link>
|
||||||
|
</b-col>
|
||||||
|
<b-col v-if="folder !== '..'" cols="1" class="folder-delete">
|
||||||
|
<b-link @click="showDeleteModal('Folder', `/${folderTree.tree[0]}/${folder}`)">
|
||||||
|
<b-icon-x-circle-fill />
|
||||||
|
</b-link>
|
||||||
|
</b-col>
|
||||||
|
</b-row>
|
||||||
</b-list-group-item>
|
</b-list-group-item>
|
||||||
</b-list-group>
|
</b-list-group>
|
||||||
|
</perfect-scrollbar>
|
||||||
</div>
|
</div>
|
||||||
</b-col>
|
</pane>
|
||||||
<b-col class="files-col">
|
<pane class="files-col">
|
||||||
|
<loading
|
||||||
|
:active.sync="isLoading"
|
||||||
|
:can-cancel="false"
|
||||||
|
:is-full-page="false"
|
||||||
|
background-color="#485159"
|
||||||
|
color="#ff9c36"
|
||||||
|
/>
|
||||||
<div class="browser-div">
|
<div class="browser-div">
|
||||||
<b-list-group>
|
<perfect-scrollbar>
|
||||||
|
<b-list-group class="files-list">
|
||||||
<b-list-group-item
|
<b-list-group-item
|
||||||
v-for="file in folderTree.tree[2]"
|
v-for="file in folderTree.tree[2]"
|
||||||
:key="file.key"
|
:key="file.key"
|
||||||
class="browser-item"
|
class="browser-item"
|
||||||
>
|
>
|
||||||
<b-link>
|
<b-row>
|
||||||
<b-icon-film class="browser-icons" /> {{ file.file }}
|
<b-col cols="1" class="browser-icons-col">
|
||||||
<span class="duration">{{ file.duration | toMin }}</span>
|
<b-icon-film class="browser-icons" />
|
||||||
|
</b-col>
|
||||||
|
<b-col class="browser-item-text">
|
||||||
|
{{ file.file }}
|
||||||
|
</b-col>
|
||||||
|
<b-col cols="1" class="browser-play-col">
|
||||||
|
<b-link @click="showPreviewModal(`/${folderTree.tree[0]}/${file.file}`)">
|
||||||
|
<b-icon-play-fill />
|
||||||
</b-link>
|
</b-link>
|
||||||
|
</b-col>
|
||||||
|
<b-col cols="1" class="browser-dur-col">
|
||||||
|
<span class="duration">{{ file.duration | toMin }}</span>
|
||||||
|
</b-col>
|
||||||
|
<b-col cols="1" class="text-center">
|
||||||
|
<b-link @click="showDeleteModal('File', `/${folderTree.tree[0]}/${file.file}`)">
|
||||||
|
<b-icon-x-circle-fill />
|
||||||
|
</b-link>
|
||||||
|
</b-col>
|
||||||
|
</b-row>
|
||||||
</b-list-group-item>
|
</b-list-group-item>
|
||||||
</b-list-group>
|
</b-list-group>
|
||||||
|
</perfect-scrollbar>
|
||||||
|
</div>
|
||||||
|
</pane>
|
||||||
|
</splitpanes>
|
||||||
|
<b-button class="upload-button" variant="primary" @click="showUploadModal()">
|
||||||
|
File Upload
|
||||||
|
</b-button>
|
||||||
|
</div>
|
||||||
|
</b-container>
|
||||||
|
<b-modal
|
||||||
|
id="preview-modal"
|
||||||
|
ref="prev-modal"
|
||||||
|
size="xl"
|
||||||
|
centered
|
||||||
|
:title="`Preview: ${previewName}`"
|
||||||
|
hide-footer
|
||||||
|
>
|
||||||
|
<b-img v-if="isImage" :src="previewSource" fluid :alt="previewName" />
|
||||||
|
<video-player v-else-if="!isImage && previewOptions" reference="previewPlayer" :options="previewOptions" />
|
||||||
|
</b-modal>
|
||||||
|
|
||||||
|
<b-modal
|
||||||
|
id="upload-modal"
|
||||||
|
ref="up-modal"
|
||||||
|
size="xl"
|
||||||
|
centered
|
||||||
|
title="File Upload"
|
||||||
|
hide-footer
|
||||||
|
>
|
||||||
|
<b-form @submit="onSubmitUpload" @reset="onResetUpload">
|
||||||
|
<b-form-file
|
||||||
|
v-model="inputFiles"
|
||||||
|
:state="Boolean(inputFiles)"
|
||||||
|
placeholder="Choose files or drop them here..."
|
||||||
|
drop-placeholder="Drop files here..."
|
||||||
|
multiple
|
||||||
|
:accept="extensions.replace(/ /g, ', ')"
|
||||||
|
:file-name-formatter="formatNames"
|
||||||
|
/>
|
||||||
|
<b-row>
|
||||||
|
<b-col cols="10">
|
||||||
|
<b-row class="progress-row">
|
||||||
|
<b-col cols="1">
|
||||||
|
Overall:
|
||||||
|
</b-col>
|
||||||
|
<b-col cols="10">
|
||||||
|
<b-progress :value="overallProgress" />
|
||||||
|
</b-col>
|
||||||
|
<div class="w-100" />
|
||||||
|
<b-col cols="1">
|
||||||
|
Current:
|
||||||
|
</b-col>
|
||||||
|
<b-col cols="10">
|
||||||
|
<b-progress :value="currentProgress" />
|
||||||
|
</b-col>
|
||||||
|
<div class="w-100" />
|
||||||
|
<b-col cols="1">
|
||||||
|
Uploading:
|
||||||
|
</b-col>
|
||||||
|
<b-col cols="10">
|
||||||
|
<strong>{{ uploadTask }}</strong>
|
||||||
|
</b-col>
|
||||||
|
</b-row>
|
||||||
|
</b-col>
|
||||||
|
<b-col cols="2">
|
||||||
|
<div class="upload-button">
|
||||||
|
<b-button type="submit" variant="primary">
|
||||||
|
Upload
|
||||||
|
</b-button>
|
||||||
|
<b-button type="reset" variant="primary">
|
||||||
|
Cancel
|
||||||
|
</b-button>
|
||||||
</div>
|
</div>
|
||||||
</b-col>
|
</b-col>
|
||||||
</b-row>
|
</b-row>
|
||||||
</div>
|
|
||||||
</b-container>
|
|
||||||
<!--
|
|
||||||
<b-form @submit="onSubmit">
|
|
||||||
<b-form-file
|
|
||||||
v-model="inputFile"
|
|
||||||
:state="Boolean(inputFile)"
|
|
||||||
placeholder="Choose a file or drop it here..."
|
|
||||||
drop-placeholder="Drop file here..."
|
|
||||||
/>
|
|
||||||
<b-button type="submit" variant="primary">
|
|
||||||
Submit
|
|
||||||
</b-button>
|
|
||||||
</b-form>
|
</b-form>
|
||||||
<div class="mt-3">
|
</b-modal>
|
||||||
Selected file: {{ inputFile ? inputFile.name : '' }}
|
<b-modal id="delete-modal" :title="`Delete ${deleteType}`" centered hide-footer>
|
||||||
|
<p>
|
||||||
|
Are you sure that you want to delete:<br>
|
||||||
|
<strong>{{ previewName }}</strong>
|
||||||
|
</p>
|
||||||
|
<div class="upload-button">
|
||||||
|
<b-button variant="primary" @click="deleteFileOrFolder()">
|
||||||
|
Ok
|
||||||
|
</b-button>
|
||||||
|
<b-button variant="primary" @click="cancelDelete()">
|
||||||
|
Cancel
|
||||||
|
</b-button>
|
||||||
</div>
|
</div>
|
||||||
-->
|
</b-modal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -92,7 +194,19 @@ export default {
|
|||||||
return {
|
return {
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
extensions: '',
|
extensions: '',
|
||||||
inputFile: null
|
inputFiles: null,
|
||||||
|
previewOptions: {},
|
||||||
|
previewComp: null,
|
||||||
|
previewName: '',
|
||||||
|
previewSource: '',
|
||||||
|
deleteType: 'File',
|
||||||
|
deleteSource: '',
|
||||||
|
isImage: false,
|
||||||
|
uploadTask: '',
|
||||||
|
overallProgress: 0,
|
||||||
|
currentProgress: 0,
|
||||||
|
cancelTokenSource: this.$axios.CancelToken.source(),
|
||||||
|
lastPath: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -112,32 +226,143 @@ export default {
|
|||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
async getPath (extensions, path) {
|
async getPath (extensions, path) {
|
||||||
|
this.lastPath = path
|
||||||
this.isLoading = true
|
this.isLoading = true
|
||||||
await this.$store.dispatch('auth/inspectToken')
|
await this.$store.dispatch('auth/inspectToken')
|
||||||
await this.$store.dispatch('media/getTree', { extensions, path })
|
await this.$store.dispatch('media/getTree', { extensions, path })
|
||||||
this.isLoading = false
|
this.isLoading = false
|
||||||
},
|
},
|
||||||
|
|
||||||
async onSubmit (evt) {
|
showUploadModal () {
|
||||||
|
this.uploadTask = ''
|
||||||
|
this.currentProgress = 0
|
||||||
|
this.overallProgress = 0
|
||||||
|
this.$root.$emit('bv::show::modal', 'upload-modal')
|
||||||
|
},
|
||||||
|
|
||||||
|
formatNames (files) {
|
||||||
|
if (files.length === 1) {
|
||||||
|
return files[0].name
|
||||||
|
} else {
|
||||||
|
return `${files.length} files selected`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async onSubmitUpload (evt) {
|
||||||
evt.preventDefault()
|
evt.preventDefault()
|
||||||
await this.$store.dispatch('auth/inspectToken')
|
await this.$store.dispatch('auth/inspectToken')
|
||||||
|
|
||||||
|
const uploadProgress = fileName => (progressEvent) => {
|
||||||
|
const progress = Math.round((progressEvent.loaded * 100) / progressEvent.total)
|
||||||
|
this.currentProgress = progress
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [i, file] of this.inputFiles.entries()) {
|
||||||
|
this.uploadTask = file.name
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
onUploadProgress: (progressEvent) => {
|
onUploadProgress: uploadProgress(file.name),
|
||||||
const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total)
|
cancelToken: this.cancelTokenSource.token,
|
||||||
console.log(percentCompleted)
|
|
||||||
},
|
|
||||||
headers: { Authorization: 'Bearer ' + this.$store.state.auth.jwtToken }
|
headers: { Authorization: 'Bearer ' + this.$store.state.auth.jwtToken }
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$axios.put(
|
await this.$axios.put(
|
||||||
`/upload/${encodeURIComponent(this.inputFile.name)}?path=${encodeURIComponent(this.crumbs.map(e => e.text).join('/'))}`,
|
`/upload/${encodeURIComponent(file.name)}?path=${encodeURIComponent(this.crumbs.map(e => e.text).join('/'))}`,
|
||||||
this.inputFile,
|
file,
|
||||||
config
|
config
|
||||||
)
|
)
|
||||||
.then(res => console.log(res))
|
.then(
|
||||||
|
this.overallProgress = (i + 1) * 100 / this.inputFiles.length,
|
||||||
|
this.currentProgress = 0,
|
||||||
|
await this.$store.dispatch('auth/inspectToken')
|
||||||
|
)
|
||||||
.catch(err => console.log(err))
|
.catch(err => console.log(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.uploadTask = 'Done...'
|
||||||
|
this.getPath(this.extensions, this.lastPath)
|
||||||
|
},
|
||||||
|
|
||||||
|
onResetUpload (evt) {
|
||||||
|
evt.preventDefault()
|
||||||
|
this.inputFiles = null
|
||||||
|
this.overallProgress = 0
|
||||||
|
this.currentProgress = 0
|
||||||
|
this.uploadTask = ''
|
||||||
|
|
||||||
|
this.cancelTokenSource.cancel('Upload cancelled')
|
||||||
|
this.getPath(this.extensions, this.lastPath)
|
||||||
|
|
||||||
|
this.$root.$emit('bv::hide::modal', 'upload-modal')
|
||||||
|
},
|
||||||
|
|
||||||
|
showPreviewModal (src) {
|
||||||
|
this.previewSource = src
|
||||||
|
this.previewName = src.split('/').slice(-1)[0]
|
||||||
|
const ext = this.previewName.split('.').slice(-1)[0]
|
||||||
|
|
||||||
|
if (this.configPlayout.storage.extensions.includes(`.${ext}`)) {
|
||||||
|
this.isImage = false
|
||||||
|
this.previewOptions = {
|
||||||
|
liveui: false,
|
||||||
|
controls: true,
|
||||||
|
suppressNotSupportedError: true,
|
||||||
|
autoplay: false,
|
||||||
|
preload: 'auto',
|
||||||
|
sources: [
|
||||||
|
{
|
||||||
|
type: `video/${ext}`,
|
||||||
|
src: encodeURIComponent(src)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.isImage = true
|
||||||
|
}
|
||||||
|
this.$root.$emit('bv::show::modal', 'preview-modal')
|
||||||
|
},
|
||||||
|
|
||||||
|
showDeleteModal (type, src) {
|
||||||
|
this.deleteSource = src
|
||||||
|
|
||||||
|
if (type === 'File') {
|
||||||
|
this.previewName = src.split('/').slice(-1)[0]
|
||||||
|
} else {
|
||||||
|
this.previewName = src
|
||||||
|
}
|
||||||
|
|
||||||
|
this.deleteType = type
|
||||||
|
this.$root.$emit('bv::show::modal', 'delete-modal')
|
||||||
|
},
|
||||||
|
|
||||||
|
async deleteFileOrFolder () {
|
||||||
|
await this.$store.dispatch('auth/inspectToken')
|
||||||
|
let file
|
||||||
|
|
||||||
|
if (this.deleteType === 'File') {
|
||||||
|
file = this.deleteSource.split('/').slice(-1)[0]
|
||||||
|
} else {
|
||||||
|
file = null
|
||||||
|
}
|
||||||
|
|
||||||
|
const pathName = this.deleteSource.substring(0, this.deleteSource.lastIndexOf('/') + 1)
|
||||||
|
|
||||||
|
await this.$axios.delete(
|
||||||
|
`/delete/?file=${encodeURIComponent(file)}&path=${encodeURIComponent(pathName)}`,
|
||||||
|
{ headers: { Authorization: 'Bearer ' + this.$store.state.auth.jwtToken } }
|
||||||
|
)
|
||||||
|
.then(response => console.log(response))
|
||||||
|
.catch(err => console.log(err))
|
||||||
|
|
||||||
|
this.$root.$emit('bv::hide::modal', 'delete-modal')
|
||||||
|
|
||||||
|
this.getPath(this.extensions, this.lastPath)
|
||||||
|
},
|
||||||
|
|
||||||
|
cancelDelete () {
|
||||||
|
this.deleteSource = ''
|
||||||
|
this.$root.$emit('bv::hide::modal', 'delete-modal')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@ -146,19 +371,11 @@ export default {
|
|||||||
.browser {
|
.browser {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
height: calc(100% - 40px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.folder-col {
|
.bread-div {
|
||||||
min-width: 320px;
|
height: 50px;
|
||||||
max-width: 460px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.folder {
|
|
||||||
padding: .3em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.files-col {
|
|
||||||
min-width: 320px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.browser-div {
|
.browser-div {
|
||||||
@ -167,4 +384,57 @@ export default {
|
|||||||
border: 1px solid #000;
|
border: 1px solid #000;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.browser-row {
|
||||||
|
height: calc(100% - 90px);
|
||||||
|
min-height: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.folder-col {
|
||||||
|
min-width: 320px;
|
||||||
|
max-width: 460px;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.folder:hover > div > .folder-delete {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.folder-list {
|
||||||
|
height: 100%;
|
||||||
|
padding: .5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.folder-delete {
|
||||||
|
margin-right: .5em;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.files-col {
|
||||||
|
min-width: 320px;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.files-list {
|
||||||
|
width: 99.5%;
|
||||||
|
height: 100%;
|
||||||
|
padding: .5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-button {
|
||||||
|
float: right;
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-row {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-row .col-1 {
|
||||||
|
min-width: 60px
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-row .col-10 {
|
||||||
|
margin: auto 0 auto 0
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -18,7 +18,6 @@ export const mutations = {
|
|||||||
|
|
||||||
export const actions = {
|
export const actions = {
|
||||||
async getTree ({ commit, dispatch, state, rootState }, { extensions, path }) {
|
async getTree ({ commit, dispatch, state, rootState }, { extensions, path }) {
|
||||||
if ((path !== state.currentPath || !state.folderTree)) {
|
|
||||||
const crumbs = []
|
const crumbs = []
|
||||||
let root = '/'
|
let root = '/'
|
||||||
const response = await this.$axios.get(`api/media/?extensions=${extensions}&path=${path}`, { headers: { Authorization: 'Bearer ' + rootState.auth.jwtToken } })
|
const response = await this.$axios.get(`api/media/?extensions=${extensions}&path=${path}`, { headers: { Authorization: 'Bearer ' + rootState.auth.jwtToken } })
|
||||||
@ -47,5 +46,4 @@ export const actions = {
|
|||||||
commit('UPDATE_FOLDER_TREE', response.data)
|
commit('UPDATE_FOLDER_TREE', response.data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user