Upload recipe step images from mobile devices (#2025)

* Upload recipe step images from mobile devices

This adds a button in the recipe step dropdown, as not all mobile
devices can drag and drop a file into the web page

See #885

* Add progress bar
This commit is contained in:
Philipp 2023-01-29 02:27:40 +01:00 committed by GitHub
parent 0acc260447
commit 59f43a58d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -146,6 +146,10 @@
text: 'Merge Above', text: 'Merge Above',
event: 'merge-above', event: 'merge-above',
}, },
{
text: 'Upload image',
event: 'upload-image'
},
{ {
icon: previewStates[index] ? $globals.icons.edit : $globals.icons.eye, icon: previewStates[index] ? $globals.icons.edit : $globals.icons.eye,
text: previewStates[index] ? 'Edit Markdown' : 'Preview Markdown', text: previewStates[index] ? 'Edit Markdown' : 'Preview Markdown',
@ -158,6 +162,7 @@
@toggle-section="toggleShowTitle(step.id)" @toggle-section="toggleShowTitle(step.id)"
@link-ingredients="openDialog(index, step.text, step.ingredientReferences)" @link-ingredients="openDialog(index, step.text, step.ingredientReferences)"
@preview-step="togglePreviewState(index)" @preview-step="togglePreviewState(index)"
@upload-image="openImageUpload(index)"
@delete="value.splice(index, 1)" @delete="value.splice(index, 1)"
/> />
</div> </div>
@ -169,6 +174,8 @@
</v-fade-transition> </v-fade-transition>
</v-card-title> </v-card-title>
<v-progress-linear v-if="isEditForm && loadingStates[index]" :active="true" :indeterminate="true" />
<!-- Content --> <!-- Content -->
<DropZone @drop="(f) => handleImageDrop(index, f)"> <DropZone @drop="(f) => handleImageDrop(index, f)">
<v-card-text <v-card-text
@ -548,6 +555,8 @@ export default defineComponent({
} }
}); });
const loadingStates = ref<{ [key: number]: boolean }>({});
async function handleImageDrop(index: number, files: File[]) { async function handleImageDrop(index: number, files: File[]) {
if (!files) { if (!files) {
return; return;
@ -559,6 +568,8 @@ export default defineComponent({
return; return;
} }
loadingStates.value[index] = true;
const { data } = await api.recipes.createAsset(props.recipe.slug, { const { data } = await api.recipes.createAsset(props.recipe.slug, {
name: file.name, name: file.name,
icon: "mdi-file-image", icon: "mdi-file-image",
@ -566,6 +577,8 @@ export default defineComponent({
extension: file.name.split(".").pop() || "", extension: file.name.split(".").pop() || "",
}); });
loadingStates.value[index] = false;
if (!data) { if (!data) {
return; // TODO: Handle error return; // TODO: Handle error
} }
@ -576,11 +589,26 @@ export default defineComponent({
props.value[index].text += text; props.value[index].text += text;
} }
function openImageUpload(index: number) {
const input = document.createElement("input");
input.type = "file";
input.accept = "image/*";
input.onchange = async () => {
if (input.files) {
await handleImageDrop(index, Array.from(input.files));
input.remove();
}
};
input.click();
}
return { return {
// Image Uploader // Image Uploader
toggleDragMode, toggleDragMode,
handleImageDrop, handleImageDrop,
imageUploadMode, imageUploadMode,
openImageUpload,
loadingStates,
// Rest // Rest
drag, drag,