diff --git a/src/components/ImageUpload.vue b/src/components/ImageUpload.vue index 8ee4ad45f2296097ef58ff6b336f4f7e9fbe1221..1adc2293e8be2febdefafcced503c01cb967d0e4 100644 --- a/src/components/ImageUpload.vue +++ b/src/components/ImageUpload.vue @@ -1,5 +1,46 @@ <template> <div> + <div class="m-2"> + Click on the image's preview to remove the entry from uploading + </div> + <div + v-for="(image, id) in imageList" + :key="image.url" + class="flex flex-row" + > + <img + :src="image.url" + @click="removeImage(id)" + alt="" + class="max-w-xs m-4" + /> + <form :id="'image-update-form-' + id" class="flex flex-col"> + <input + type="text" + placeholder="Source" + name="source" + class="payloadInput" + /> + <input + type="text" + placeholder="Parent" + name="parent" + class="payloadInput" + /> + <textarea + type="text" + placeholder="Commentary" + name="commentary" + class="payloadInput" + /> + <textarea + type="text" + placeholder="Commentary translation" + name="commentary_translation" + class="payloadInput" + /> + </form> + </div> <div class="h-48 m-4 border-dotted border-4 border-gray-400" @drop.prevent=" @@ -20,7 +61,6 @@ class="h-full w-full opacity-0 absolute z-10 cursor-pointer" /> <div - v-show="!imageList.length" class=" h-full font-semibold @@ -32,19 +72,6 @@ > Drag and drop images here or click here to browse. </div> - <div - v-show="imageList.length" - class="h-full flex flex-row flex-wrap content-start overflow-y-auto" - > - <img - v-for="(preview, index) in previews" - :key="index" - :src="preview.url" - @click="removeImage(preview.image)" - alt="" - class="max-h-28 relative z-10" - /> - </div> </div> </div> <div class="flex flex-col items-center m-4"> @@ -61,7 +88,8 @@ mx-auto font-semibold text-gray-800 - hover:bg-gray-800 hover:text-gray-100 + hover:bg-gray-800 + hover:text-gray-100 " > Submit @@ -85,13 +113,6 @@ export default { }; }, computed: { - previews: function () { - let tempArray = []; - this.imageList.forEach((image) => - tempArray.push({ url: URL.createObjectURL(image), image }) - ); - return tempArray; - }, ...mapState(["stateUser"]), }, methods: { @@ -102,9 +123,18 @@ export default { }, updateImageList(event) { this.imageList = this.imageList.concat( - event ? [...event.dataTransfer.files] : [...this.$refs.imageInput.files] + event + ? this.addMetadata([...event.dataTransfer.files]) + : this.addMetadata([...this.$refs.imageInput.files]) ); }, + addMetadata(files) { + let tempArray = []; + files.forEach((file) => { + tempArray.push({ file, url: URL.createObjectURL(file) }); + }); + return tempArray; + }, checkImageType(event) { const acceptedTypes = ["image/png", "image/jpeg", "image/gif"]; let imageList = event @@ -119,36 +149,59 @@ export default { this.invalidType = false; return true; }, - removeImage(image) { - this.imageList.splice(this.imageList.indexOf(image), 1); + removeImage(id) { + this.imageList.splice(id, 1); }, - submitImage() { + async submitImage() { let formData = new FormData(); for (let i = 0; i < this.imageList.length; i++) { - formData.set("image", this.imageList[i]); - this.postImage(formData); + formData.set("image", this.imageList[i].file); + let data = await this.postImage(formData); + this.updateImage( + data.snowflake, + this.serializeForm("image-update-form-" + i) + ); } // Clean up this.invalidType = false; this.imageList = []; }, + // Serialize form inputs into JSON object that can be sent to API + serializeForm(formID) { + return JSON.stringify( + Object.fromEntries(new FormData(document.getElementById(formID))) + ); + }, + async updateImage(flake, imageUpdatePayload) { + const options = { + method: "PATCH", + headers: { + secret: this.stateUser.secret, + }, + body: imageUpdatePayload, + }; + await fetch(`/api/image/${flake}`, options); + }, async postImage(fd) { - try { - const options = { - method: "POST", - headers: { - secret: this.stateUser.secret, - }, - body: fd, - }; - const response = await fetch("/api/image", options); - const data = await response.json(); - this.addStateImageSnowflake(data.snowflake); - } catch { - (error) => console.error(error); - } + const options = { + method: "POST", + headers: { + secret: this.stateUser.secret, + }, + body: fd, + }; + const response = await fetch("/api/image", options); + const data = await response.json(); + this.addStateImageSnowflake(data.snowflake); + return data; }, ...mapActions(["addStateImageSnowflake"]), }, }; </script> + +<style> +.payloadInput { + @apply border-2 focus:outline-none focus:ring-2 focus:ring-blue-300 pl-1 my-2; +} +</style> \ No newline at end of file