mirror of
https://github.com/hay-kot/mealie.git
synced 2025-08-22 14:33:33 -07:00
feat: Handle uploading multiple images in AppButtonUpload if !props.post
This commit is contained in:
parent
b2d9c6c8b4
commit
86d146c762
3 changed files with 63 additions and 35 deletions
|
@ -1,10 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<v-form ref="file">
|
<v-form ref="files">
|
||||||
<input
|
<input
|
||||||
ref="uploader"
|
ref="uploader"
|
||||||
class="d-none"
|
class="d-none"
|
||||||
type="file"
|
type="file"
|
||||||
:accept="accept"
|
:accept="accept"
|
||||||
|
:multiple="multiple"
|
||||||
@change="onFileChanged"
|
@change="onFileChanged"
|
||||||
>
|
>
|
||||||
<slot v-bind="{ isSelecting, onButtonClick }">
|
<slot v-bind="{ isSelecting, onButtonClick }">
|
||||||
|
@ -72,9 +73,13 @@ export default defineNuxtComponent({
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
multiple: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
setup(props, context) {
|
setup(props, context) {
|
||||||
const file = ref<File | null>(null);
|
const files = ref<File[]>([]);
|
||||||
const uploader = ref<HTMLInputElement | null>(null);
|
const uploader = ref<HTMLInputElement | null>(null);
|
||||||
const isSelecting = ref(false);
|
const isSelecting = ref(false);
|
||||||
|
|
||||||
|
@ -86,35 +91,52 @@ export default defineNuxtComponent({
|
||||||
|
|
||||||
const api = useUserApi();
|
const api = useUserApi();
|
||||||
async function upload() {
|
async function upload() {
|
||||||
if (file.value != null) {
|
if (files.value.length === 0) {
|
||||||
isSelecting.value = true;
|
return;
|
||||||
|
|
||||||
if (!props.post) {
|
|
||||||
context.emit(UPLOAD_EVENT, file.value);
|
|
||||||
isSelecting.value = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append(props.fileName, file.value);
|
|
||||||
try {
|
|
||||||
const response = await api.upload.file(props.url, formData);
|
|
||||||
if (response) {
|
|
||||||
context.emit(UPLOAD_EVENT, response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
context.emit(UPLOAD_EVENT, null);
|
|
||||||
}
|
|
||||||
isSelecting.value = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isSelecting.value = true;
|
||||||
|
|
||||||
|
if (!props.post) {
|
||||||
|
// NOTE: To preserve behaviour for other parents of this component,
|
||||||
|
// we emit a single File if !props.multiple.
|
||||||
|
context.emit(UPLOAD_EVENT, props.multiple ? files.value : files.value[0]);
|
||||||
|
isSelecting.value = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// WARN: My change is only for !props.post.
|
||||||
|
// I have not added support for multiple files in the API.
|
||||||
|
// Existing call-sites never passed the `multiple` prop,
|
||||||
|
// so this case will only be hit if the prop is set to true.
|
||||||
|
if (props.multiple && files.value.length > 1) {
|
||||||
|
console.warn("Multiple file uploads are not supported by the API.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const file = files.value[0];
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append(props.fileName, file);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await api.upload.file(props.url, formData);
|
||||||
|
if (response) {
|
||||||
|
context.emit(UPLOAD_EVENT, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
context.emit(UPLOAD_EVENT, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
isSelecting.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function onFileChanged(e: Event) {
|
function onFileChanged(e: Event) {
|
||||||
const target = e.target as HTMLInputElement;
|
const target = e.target as HTMLInputElement;
|
||||||
if (target.files !== null && target.files.length > 0 && file.value !== null) {
|
|
||||||
file.value = target.files[0];
|
if (target.files !== null && target.files.length > 0) {
|
||||||
|
files.value = Array.from(target.files);
|
||||||
upload();
|
upload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,7 +154,7 @@ export default defineNuxtComponent({
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
file,
|
files,
|
||||||
uploader,
|
uploader,
|
||||||
isSelecting,
|
isSelecting,
|
||||||
effIcon,
|
effIcon,
|
||||||
|
|
|
@ -662,7 +662,9 @@
|
||||||
},
|
},
|
||||||
"reset-servings-count": "Reset Servings Count",
|
"reset-servings-count": "Reset Servings Count",
|
||||||
"not-linked-ingredients": "Additional Ingredients",
|
"not-linked-ingredients": "Additional Ingredients",
|
||||||
"upload-another-image": "Upload another image"
|
"upload-another-image": "Upload another image",
|
||||||
|
"upload-images": "Upload images",
|
||||||
|
"upload-more-images": "Upload more images"
|
||||||
},
|
},
|
||||||
"recipe-finder": {
|
"recipe-finder": {
|
||||||
"recipe-finder": "Recipe Finder",
|
"recipe-finder": "Recipe Finder",
|
||||||
|
|
|
@ -15,10 +15,11 @@
|
||||||
url="none"
|
url="none"
|
||||||
file-name="images"
|
file-name="images"
|
||||||
accept="image/*"
|
accept="image/*"
|
||||||
:text="uploadedImages.length ? $t('recipe.upload-another-image') : $t('recipe.upload-image')"
|
:text="uploadedImages.length ? $t('recipe.upload-more-images') : $t('recipe.upload-images')"
|
||||||
:text-btn="false"
|
:text-btn="false"
|
||||||
:post="false"
|
:post="false"
|
||||||
@uploaded="uploadImage"
|
:multiple="true"
|
||||||
|
@uploaded="uploadImages"
|
||||||
/>
|
/>
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-spacer />
|
<v-spacer />
|
||||||
|
@ -110,10 +111,13 @@ export default defineNuxtComponent({
|
||||||
const uploadedImagesPreviewUrls = ref<string[]>([]);
|
const uploadedImagesPreviewUrls = ref<string[]>([]);
|
||||||
const shouldTranslate = ref(true);
|
const shouldTranslate = ref(true);
|
||||||
|
|
||||||
function uploadImage(fileObject: File) {
|
function uploadImages(files: File[]) {
|
||||||
uploadedImages.value = [...uploadedImages.value, fileObject];
|
uploadedImages.value = [...uploadedImages.value, ...files];
|
||||||
uploadedImageNames.value = [...uploadedImageNames.value, fileObject.name];
|
uploadedImageNames.value = [...uploadedImageNames.value, ...files.map(file => file.name)];
|
||||||
uploadedImagesPreviewUrls.value = [...uploadedImagesPreviewUrls.value, URL.createObjectURL(fileObject)];
|
uploadedImagesPreviewUrls.value = [
|
||||||
|
...uploadedImagesPreviewUrls.value,
|
||||||
|
...files.map(file => URL.createObjectURL(file)),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearImage(index: number) {
|
function clearImage(index: number) {
|
||||||
|
@ -151,7 +155,7 @@ export default defineNuxtComponent({
|
||||||
uploadedImages,
|
uploadedImages,
|
||||||
uploadedImagesPreviewUrls,
|
uploadedImagesPreviewUrls,
|
||||||
shouldTranslate,
|
shouldTranslate,
|
||||||
uploadImage,
|
uploadImages,
|
||||||
clearImage,
|
clearImage,
|
||||||
createRecipe,
|
createRecipe,
|
||||||
updateUploadedImage,
|
updateUploadedImage,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue