255 lines
5.8 KiB
Vue
255 lines
5.8 KiB
Vue
<template>
|
|
<div
|
|
:class="{ 'has-files': alreadyAddedFiles }"
|
|
class="uploader-wrapper">
|
|
<b-select
|
|
v-if="loggedIn"
|
|
v-model="selectedAlbum"
|
|
placeholder="Upload to album"
|
|
size="is-medium"
|
|
expanded>
|
|
<option
|
|
v-for="album in albums"
|
|
:key="album.id"
|
|
:value="album.id">
|
|
{{ album.name }}
|
|
</option>
|
|
</b-select>
|
|
<dropzone
|
|
v-if="showDropzone"
|
|
id="dropzone"
|
|
ref="el"
|
|
:options="dropzoneOptions"
|
|
:include-styling="false"
|
|
@vdropzone-success="dropzoneSuccess"
|
|
@vdropzone-error="dropzoneError"
|
|
@vdropzone-files-added="dropzoneFilesAdded" />
|
|
<label class="add-more">
|
|
Add or drop more files
|
|
</label>
|
|
|
|
<div
|
|
id="template"
|
|
ref="template">
|
|
<div class="dz-preview dz-file-preview">
|
|
<div class="dz-details">
|
|
<div class="dz-filename">
|
|
<span data-dz-name />
|
|
</div>
|
|
<div class="dz-size">
|
|
<span data-dz-size />
|
|
</div>
|
|
</div>
|
|
<div class="result">
|
|
<div class="openLink">
|
|
<a
|
|
class="link"
|
|
target="_blank">
|
|
Link
|
|
</a>
|
|
</div>
|
|
</div>
|
|
<div class="error">
|
|
<div>
|
|
<span>
|
|
<span
|
|
class="error-message"
|
|
data-dz-errormessage />
|
|
<i class="icon-web-warning" />
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div class="dz-progress">
|
|
<span
|
|
class="dz-upload"
|
|
data-dz-uploadprogress />
|
|
</div>
|
|
<!--
|
|
<div class="dz-error-message"><span data-dz-errormessage/></div>
|
|
<div class="dz-success-mark"><i class="fa fa-check"/></div>
|
|
<div class="dz-error-mark"><i class="fa fa-close"/></div>
|
|
-->
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { mapState, mapGetters } from 'vuex';
|
|
|
|
import Dropzone from 'nuxt-dropzone';
|
|
import '~/assets/styles/dropzone.scss';
|
|
|
|
export default {
|
|
components: { Dropzone },
|
|
data() {
|
|
return {
|
|
alreadyAddedFiles: false,
|
|
files: [],
|
|
dropzoneOptions: {},
|
|
showDropzone: false,
|
|
selectedAlbum: null
|
|
};
|
|
},
|
|
computed: {
|
|
...mapState({
|
|
config: state => state.config,
|
|
albums: state => state.albums.tinyDetails
|
|
}),
|
|
...mapGetters({ loggedIn: 'auth/isLoggedIn', token: 'auth/getToken' })
|
|
},
|
|
watch: {
|
|
loggedIn() {
|
|
this.getAlbums();
|
|
},
|
|
selectedAlbum() {
|
|
this.updateDropzoneConfig();
|
|
}
|
|
},
|
|
mounted() {
|
|
this.dropzoneOptions = {
|
|
url: `${this.config.baseURL}/upload`,
|
|
timeout: 600000, // 10 minutes
|
|
autoProcessQueue: true,
|
|
addRemoveLinks: false,
|
|
parallelUploads: 5,
|
|
uploadMultiple: false,
|
|
maxFiles: 1000,
|
|
createImageThumbnails: false,
|
|
paramName: 'files[]',
|
|
forceChunking: false,
|
|
chunking: true,
|
|
retryChunks: true,
|
|
retryChunksLimit: 3,
|
|
parallelChunkUploads: true,
|
|
chunkSize: this.config.chunkSize * 1000000,
|
|
chunksUploaded: this.dropzoneChunksUploaded,
|
|
maxFilesize: this.config.maxFileSize,
|
|
previewTemplate: this.$refs.template.innerHTML,
|
|
dictDefaultMessage: 'Drag & Drop your files or click to browse',
|
|
headers: { Accept: 'application/vnd.chibisafe.json' }
|
|
};
|
|
this.showDropzone = true;
|
|
if (this.loggedIn) this.getAlbums();
|
|
},
|
|
methods: {
|
|
/*
|
|
Get all available albums so the user can upload directly to one (or several soon™) of them.
|
|
*/
|
|
async getAlbums() {
|
|
try {
|
|
await this.$store.dispatch('albums/getTinyDetails');
|
|
} catch (e) {
|
|
this.$store.dispatch('alert/set', { text: e.message, error: true }, { root: true });
|
|
}
|
|
this.updateDropzoneConfig();
|
|
},
|
|
|
|
/*
|
|
This method needs to be called after the token or selectedAlbum changes
|
|
since dropzone doesn't seem to update the config values unless you force it.
|
|
Tch.
|
|
*/
|
|
updateDropzoneConfig() {
|
|
this.$refs.el.setOption('headers', {
|
|
Accept: 'application/vnd.chibisafe.json',
|
|
Authorization: this.token ? `Bearer ${this.token}` : '',
|
|
albumId: this.selectedAlbum ? this.selectedAlbum : null
|
|
});
|
|
},
|
|
|
|
/*
|
|
Dropzone stuff
|
|
*/
|
|
dropzoneFilesAdded() {
|
|
this.alreadyAddedFiles = true;
|
|
},
|
|
dropzoneSuccess(file, response) {
|
|
this.processResult(file, response);
|
|
},
|
|
dropzoneError(file, message, xhr) {
|
|
this.$store.dispatch('alert', {
|
|
text: 'There was an error uploading this file. Check the console.',
|
|
error: true
|
|
});
|
|
// eslint-disable-next-line no-console
|
|
console.error(file, message, xhr);
|
|
},
|
|
async dropzoneChunksUploaded(file, done) {
|
|
const { data } = await this.$axios.post(`${this.config.baseURL}/upload/chunks`, {
|
|
files: [{
|
|
uuid: file.upload.uuid,
|
|
original: file.name,
|
|
size: file.size,
|
|
type: file.type,
|
|
count: file.upload.totalChunkCount
|
|
}]
|
|
});
|
|
|
|
this.processResult(file, data);
|
|
return done();
|
|
},
|
|
|
|
/*
|
|
If upload/s was/were successfull we modify the template so that the buttons for
|
|
copying the returned url or opening it in a new window appear.
|
|
*/
|
|
processResult(file, response) {
|
|
if (!response.url) return;
|
|
file.previewTemplate.querySelector('.link').setAttribute('href', response.url);
|
|
/*
|
|
file.previewTemplate.querySelector('.copyLink').addEventListener('click', () => {
|
|
this.$store.dispatch('alert', {
|
|
text: 'Link copied!'
|
|
});
|
|
this.$clipboard(response.url);
|
|
});
|
|
*/
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
<style lang="scss" scoped>
|
|
#template { display: none; }
|
|
.uploader-wrapper {
|
|
display: block;
|
|
width: 400px;
|
|
margin: 0 auto;
|
|
max-width: 100%;
|
|
position: relative;
|
|
}
|
|
</style>
|
|
<style lang="scss">
|
|
@import '~/assets/styles/_colors.scss';
|
|
|
|
div.uploader-wrapper {
|
|
&.has-files {
|
|
#dropzone {
|
|
padding-bottom: 50px;
|
|
}
|
|
label.add-more {
|
|
position: absolute;
|
|
bottom: 23px;
|
|
width: 100%;
|
|
text-align: center;
|
|
color: #797979;
|
|
display: block;
|
|
pointer-events: none;
|
|
}
|
|
}
|
|
div.control {
|
|
margin-bottom: 5px;
|
|
span.select {
|
|
select {
|
|
border: 1px solid #00000061;
|
|
background: rgba(0, 0, 0, 0.15);
|
|
border-radius: .3em;
|
|
color: $uploaderDropdownColor;
|
|
padding: 0 0 0 1rem;
|
|
}
|
|
}
|
|
}
|
|
label.add-more { display: none; }
|
|
}
|
|
</style>
|