mealie/frontend/components/global/AppButtonUpload.vue
Michael Genson 2151451634
feat: Timeline Image Uploader Improvements (#2494)
* improved UI responsiveness and added image preview

* added global image cropper component

* added image cropper to last made dialog

* style tweaks

* added more specific text for creating event

* mopped up some slop

* renamed height and width vars

---------

Co-authored-by: Hayden <64056131+hay-kot@users.noreply.github.com>
2023-08-21 15:00:37 +00:00

129 lines
2.8 KiB
Vue

<template>
<v-form ref="file">
<input ref="uploader" class="d-none" type="file" :accept="accept" @change="onFileChanged" />
<slot v-bind="{ isSelecting, onButtonClick }">
<v-btn :loading="isSelecting" :small="small" :color="color" :text="textBtn" :disabled="disabled" @click="onButtonClick">
<v-icon left> {{ effIcon }}</v-icon>
{{ text ? text : defaultText }}
</v-btn>
</slot>
</v-form>
</template>
<script lang="ts">
import { defineComponent, ref, useContext } from "@nuxtjs/composition-api";
import { useUserApi } from "~/composables/api";
const UPLOAD_EVENT = "uploaded";
export default defineComponent({
props: {
small: {
type: Boolean,
default: false,
},
post: {
type: Boolean,
default: true,
},
url: {
type: String,
default: "",
},
text: {
type: String,
default: "",
},
icon: {
type: String,
default: null,
},
fileName: {
type: String,
default: "archive",
},
textBtn: {
type: Boolean,
default: true,
},
accept: {
type: String,
default: "",
},
color: {
type: String,
default: "info",
},
disabled: {
type: Boolean,
default: false,
}
},
setup(props, context) {
const file = ref<File | null>(null);
const uploader = ref<HTMLInputElement | null>(null);
const isSelecting = ref(false);
const { i18n, $globals } = useContext();
const effIcon = props.icon ? props.icon : $globals.icons.upload;
const defaultText = i18n.t("general.upload");
const api = useUserApi();
async function upload() {
if (file.value != null) {
isSelecting.value = true;
if (!props.post) {
context.emit(UPLOAD_EVENT, file.value);
isSelecting.value = false;
return;
}
const formData = new FormData();
formData.append(props.fileName, file.value);
const response = await api.upload.file(props.url, formData);
if (response) {
context.emit(UPLOAD_EVENT, response);
}
isSelecting.value = false;
}
}
function onFileChanged(e: Event) {
const target = e.target as HTMLInputElement;
if (target.files !== null && target.files.length > 0 && file.value !== null) {
file.value = target.files[0];
upload();
}
}
function onButtonClick() {
isSelecting.value = true;
window.addEventListener(
"focus",
() => {
isSelecting.value = false;
},
{ once: true }
);
uploader.value?.click();
}
return {
file,
uploader,
isSelecting,
effIcon,
defaultText,
onFileChanged,
onButtonClick,
};
},
});
</script>
<style></style>