PronounsPage/components/FileUploader.vue
Theodore Dubois 3eb7091e15 Fix translation buttons inside file upload buttons
The invisible input element covering the button also covered the
translation text. I found a post on stackoverflow that suggested hiding
the input element entirely and instead attaching a label to it and
styling that. This seems to still work for uploads and can be translated
now.

https://stackoverflow.com/questions/572768/styling-an-input-type-file-button
2024-01-09 17:12:33 -08:00

98 lines
2.9 KiB
Vue

<template>
<div>
<input type="file"
:id="id"
:name="name + (multiple ? '[]' : '')"
:multiple="multiple"
:disabled="uploading"
@change="filesChange($event.target.name, $event.target.files)"
:accept="mime"/>
<label
:for="id"
:class="['uploader-container', form ? 'form-control p-2' : classes, drag ? 'drag' : '']"
@dragover="drag=true" @dragleave="drag=false"
>
<p v-if="errorMessage" class="text-danger mb-0">
<Icon v="exclamation-circle"/>
<T>{{errorMessage}}</T>
</p>
<p v-else-if="uploading" class="mb-0">
<Spinner/>
</p>
<p v-else class="mb-0">
<slot>
<Icon v="upload"/>
<T>images.upload.instructionShort</T>
</slot>
</p>
</label>
</div>
</template>
<script>
export default {
props: {
url: {required: true},
multiple: {type: Boolean},
mime: {'default': '*/*'},
name: {'default': 'files'},
form: {type: Boolean},
classes: {'default': 'btn btn-outline-primary btn-sm'},
},
data() {
return {
uploading: false,
drag: false,
errorMessage: '',
id: `upload-${this.name}`,
}
},
methods: {
async filesChange(fieldName, fileList) {
if (!fileList.length) {
return;
}
this.drag = false;
const formData = new FormData();
for (let file of fileList) {
formData.append(fieldName, file, file.name);
}
await this.save(formData);
},
async save(formData) {
this.uploading = true;
this.errorMessage = '';
try {
const ids = await this.$axios.$post(this.url, formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
});
this.$emit('uploaded', ids);
} catch (e) {
this.errorMessage = e?.response?.data?.error || 'error.invalidImage';
}
this.uploading = false;
},
},
}
</script>
<style lang="scss" scoped>
@import "../assets/style";
.uploader-container {
position: relative;
cursor: pointer;
&.form-control {
&:hover, &.drag {
background: lighten($primary, 50%);
}
}
}
input[type="file"] {
display: none;
}
</style>