Changeset View
Changeset View
Standalone View
Standalone View
src/resources/vue/File/List.vue
<template> | <template> | ||||
<div class="container"> | <div class="container"> | ||||
<div class="card" id="files"> | <div class="card" id="files"> | ||||
<div class="card-body"> | <div class="card-body"> | ||||
<div class="card-title"> | <div class="card-title" v-if="collectionId"> | ||||
{{ $t('dashboard.files') + ' - ' + collection.name }} | |||||
<small><sup class="badge bg-primary">{{ $t('dashboard.beta') }}</sup></small> | |||||
<div id="drop-area" class="file-drop-area float-end"> | |||||
<svg-icon icon="upload"></svg-icon> Click or drop file(s) here | |||||
</div> | |||||
<btn-router v-if="!$root.isDegraded()" class="float-end" :to="`/file/newCollection?parent=${collectionId}`" icon="folder"> | |||||
{{ $t('collection.create') }} | |||||
</btn-router> | |||||
</div> | |||||
<div class="card-title" v-else> | |||||
{{ $t('dashboard.files') }} | {{ $t('dashboard.files') }} | ||||
<small><sup class="badge bg-primary">{{ $t('dashboard.beta') }}</sup></small> | <small><sup class="badge bg-primary">{{ $t('dashboard.beta') }}</sup></small> | ||||
<div id="drop-area" class="file-drop-area float-end"> | <div id="drop-area" class="file-drop-area float-end"> | ||||
<svg-icon icon="upload"></svg-icon> Click or drop file(s) here | <svg-icon icon="upload"></svg-icon> Click or drop file(s) here | ||||
</div> | </div> | ||||
<btn-router v-if="!$root.isDegraded()" class="float-end" to="/file/newCollection" icon="folder"> | |||||
{{ $t('collection.create') }} | |||||
</btn-router> | |||||
</div> | </div> | ||||
<div class="card-text pt-4"> | <div class="card-text pt-4"> | ||||
<div class="mb-2 d-flex w-100"> | <div class="mb-2 d-flex w-100"> | ||||
<list-search :placeholder="$t('file.search')" :on-search="searchFiles"></list-search> | <list-search :placeholder="$t('file.search')" :on-search="searchFiles"></list-search> | ||||
</div> | </div> | ||||
<table class="table table-sm table-hover files"> | <table class="table table-sm table-hover files"> | ||||
<thead> | <thead> | ||||
<tr> | <tr> | ||||
<th scope="col" class="name">{{ $t('form.name') }}</th> | <th scope="col" class="name">{{ $t('form.name') }}</th> | ||||
<th scope="col" class="buttons"></th> | <th scope="col" class="buttons"></th> | ||||
</tr> | </tr> | ||||
</thead> | </thead> | ||||
<tbody> | <tbody> | ||||
<tr v-for="file in files" :key="file.id" @click="$root.clickRecord"> | <tr v-for="file in files" :key="file.id" @click="$root.clickRecord"> | ||||
<td class="name"> | <td class="name" v-if="file.type === 'collection'"> | ||||
<svg-icon icon="folder"></svg-icon> | |||||
<router-link :to="{ path: '/file/' + file.id }">{{ file.name }}</router-link> | |||||
machniak: fs -> files | |||||
</td> | |||||
<td class="name" v-else> | |||||
<svg-icon icon="file"></svg-icon> | <svg-icon icon="file"></svg-icon> | ||||
<router-link :to="{ path: 'file/' + file.id }">{{ file.name }}</router-link> | <router-link :to="{ path: '/file/' + file.id }">{{ file.name }}</router-link> | ||||
</td> | |||||
<td class="buttons" v-if="file.type === 'collection'"> | |||||
<btn class="button-delete text-danger p-0 ms-1" @click="fileDelete(file)" icon="trash-can" :title="$t('btn.delete')"></btn> | |||||
</td> | </td> | ||||
<td class="buttons"> | <td class="buttons" v-else> | ||||
<btn class="button-download p-0 ms-1" @click="fileDownload(file)" icon="download" :title="$t('btn.download')"></btn> | <btn class="button-download p-0 ms-1" @click="fileDownload(file)" icon="download" :title="$t('btn.download')"></btn> | ||||
<btn class="button-delete text-danger p-0 ms-1" @click="fileDelete(file)" icon="trash-can" :title="$t('btn.delete')"></btn> | <btn class="button-delete text-danger p-0 ms-1" @click="fileDelete(file)" icon="trash-can" :title="$t('btn.delete')"></btn> | ||||
</td> | </td> | ||||
</tr> | </tr> | ||||
</tbody> | </tbody> | ||||
<list-foot :colspan="2" :text="$t('file.list-empty')"></list-foot> | <list-foot :colspan="2" :text="$t('file.list-empty')"></list-foot> | ||||
</table> | </table> | ||||
<list-more v-if="hasMore" :on-click="loadFiles"></list-more> | <list-more v-if="hasMore" :on-click="loadFiles"></list-more> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</template> | </template> | ||||
<script> | <script> | ||||
import FileAPI from '../../js/files.js' | import FileAPI from '../../js/files.js' | ||||
import ListTools from '../Widgets/ListTools' | import ListTools from '../Widgets/ListTools' | ||||
import { library } from '@fortawesome/fontawesome-svg-core' | import { library } from '@fortawesome/fontawesome-svg-core' | ||||
library.add( | library.add( | ||||
require('@fortawesome/free-solid-svg-icons/faFile').definition, | require('@fortawesome/free-solid-svg-icons/faFile').definition, | ||||
require('@fortawesome/free-solid-svg-icons/faFolder').definition, | |||||
require('@fortawesome/free-solid-svg-icons/faDownload').definition, | require('@fortawesome/free-solid-svg-icons/faDownload').definition, | ||||
require('@fortawesome/free-solid-svg-icons/faUpload').definition, | require('@fortawesome/free-solid-svg-icons/faUpload').definition, | ||||
) | ) | ||||
export default { | export default { | ||||
mixins: [ ListTools ], | mixins: [ ListTools ], | ||||
beforeRouteUpdate (to, from, next) { | |||||
this.collectionId = this.$route.params.parent | |||||
// An event called when the route that renders this component has changed, | |||||
// but this component is reused in the new route. | |||||
// Required to handle links from /file/XXX to /file/YYY | |||||
next() | |||||
this.$parent.routerReload() | |||||
}, | |||||
data() { | data() { | ||||
return { | return { | ||||
api: {}, | api: {}, | ||||
files: [] | collection: {}, | ||||
files: [], | |||||
collectionId: null | |||||
} | |||||
}, | |||||
created() { | |||||
this.collectionId = this.$route.params.parent | |||||
if (this.collectionId) { | |||||
axios.get('/api/v4/fs/' + this.collectionId, { loader: true }) | |||||
.then(response => { | |||||
this.collection = response.data | |||||
}) | |||||
.catch(this.$root.errorHandler) | |||||
} | } | ||||
}, | }, | ||||
mounted() { | mounted() { | ||||
this.uploads = {} | this.uploads = {} | ||||
this.collectionId = this.$route.params.parent | |||||
this.api = new FileAPI({ | this.api = new FileAPI({ | ||||
dropArea: '#drop-area', | dropArea: '#drop-area', | ||||
eventHandler: this.eventHandler | eventHandler: this.eventHandler, | ||||
parent: this.collectionId | |||||
}) | }) | ||||
this.loadFiles({ init: true }) | this.loadFiles({ init: true }) | ||||
}, | }, | ||||
methods: { | methods: { | ||||
eventHandler(name, params) { | eventHandler(name, params) { | ||||
const camelCase = name.toLowerCase().replace(/[^a-zA-Z0-9]+(.)/g, (m, chr) => chr.toUpperCase()) | const camelCase = name.toLowerCase().replace(/[^a-zA-Z0-9]+(.)/g, (m, chr) => chr.toUpperCase()) | ||||
const method = camelCase + 'Handler' | const method = camelCase + 'Handler' | ||||
if (method in this) { | if (method in this) { | ||||
this[method](params) | this[method](params) | ||||
} | } | ||||
}, | }, | ||||
fileDelete(file) { | fileDelete(file) { | ||||
axios.delete('api/v4/files/' + file.id) | axios.delete('api/v4/fs/' + file.id) | ||||
.then(response => { | .then(response => { | ||||
if (response.data.status == 'success') { | if (response.data.status == 'success') { | ||||
this.$toast.success(response.data.message) | this.$toast.success(response.data.message) | ||||
// Refresh the list | // Refresh the list | ||||
this.loadFiles({ reset: true }) | this.loadFiles({ reset: true }) | ||||
} | } | ||||
}) | }) | ||||
}, | }, | ||||
fileDownload(file) { | fileDownload(file) { | ||||
// This is not an appropriate method for big files, we can consider | // This is not an appropriate method for big files, we can consider | ||||
// using it still for very small files. | // using it still for very small files. | ||||
// downloadFile('api/v4/files/' + file.id + '?download=1', file.name) | // downloadFile('api/v4/fs/' + file.id + '?download=1', file.name) | ||||
// This method first makes a request to the API to get the download URL (which does not | // This method first makes a request to the API to get the download URL (which does not | ||||
// require authentication) and then use it to download the file. | // require authentication) and then use it to download the file. | ||||
this.api.fileDownload(file.id) | this.api.fileDownload(file.id) | ||||
}, | }, | ||||
loadFiles(params) { | loadFiles(params) { | ||||
this.listSearch('files', 'api/v4/files', params) | if (this.collectionId) { | ||||
params['parent'] = this.collectionId | |||||
} | |||||
this.listSearch('files', 'api/v4/fs', params) | |||||
}, | }, | ||||
searchFiles(search) { | searchFiles(search) { | ||||
this.loadFiles({ reset: true, search }) | this.loadFiles({ reset: true, search }) | ||||
}, | }, | ||||
uploadProgressHandler(params) { | uploadProgressHandler(params) { | ||||
// Note: There might be more than one event with completed=0 | // Note: There might be more than one event with completed=0 | ||||
// e.g. if you upload multiple files at once | // e.g. if you upload multiple files at once | ||||
if (params.completed == 0 && !(params.id in this.uploads)) { | if (params.completed == 0 && !(params.id in this.uploads)) { | ||||
Show All 24 Lines |
fs -> files