diff --git a/src/App.vue b/src/App.vue index 2396e43b6a0a2d401d3415e71e85f617ea755c19..c6a2c269fd20f2408e7577ce8b898902076f4649 100644 --- a/src/App.vue +++ b/src/App.vue @@ -8,10 +8,4 @@ </header> <router-view /> </div> -</template> - -<style> -.inputBox { - @apply border-2 focus:outline-none focus:ring-2 focus:ring-blue-300; -} -</style> \ No newline at end of file +</template> \ No newline at end of file diff --git a/src/components/ImageMetadataFields.vue b/src/components/ImageMetadataFields.vue new file mode 100644 index 0000000000000000000000000000000000000000..7f5179e319cc6e7e2982813eac76910c5782f188 --- /dev/null +++ b/src/components/ImageMetadataFields.vue @@ -0,0 +1,105 @@ +<template> + <div class="flex flex-col flex-1"> + <form id="payloadFields" class="flex flex-col flex-1"> + <input + type="text" + placeholder="Source" + name="source" + autocomplete="off" + class="imageInfoFields" + /> + <input + type="text" + placeholder="Parent" + name="parent" + autocomplete="off" + class="imageInfoFields" + /> + <textarea + type="text" + placeholder="Commentary" + name="commentary" + autocomplete="off" + class="imageInfoFields resize-none flex-1" + /> + <textarea + type="text" + placeholder="Commentary translation" + name="commentary_translation" + autocomplete="off" + class="imageInfoFields resize-none flex-1" + /> + </form> + <input + id="tagField" + type="text" + placeholder="Tags" + name="tags" + autocomplete="off" + class="imageInfoFields" + /> + </div> +</template> + +<script> +import { mapState } from "vuex"; +import paths from "@/assets/js/paths.js"; + +export default { + props: { + id: { + required: true, + }, + }, + created() { + this.$parent.$on(`update-image-info-${this.id}`, this.updateImageMetadata); + }, + computed: { + ...mapState(["stateUser"]), + }, + methods: { + updateImageMetadata(flake) { + this.updateImageInfo(flake, this.serializeForm("payloadFields")); + this.updateImageTags(flake, "tagField"); + }, + // Serialize form inputs into JSON object that can be sent to API endpoints + serializeForm(formID) { + return JSON.stringify( + Object.fromEntries(new FormData(document.getElementById(formID))) + ); + }, + // Send an image update payload including 4 fields: + // "source", "parent", "commentary", "commentary translation" to paths.ImageField + async updateImageInfo(flake, imageUpdatePayload) { + const options = { + method: "PATCH", + headers: { + secret: this.stateUser.secret, + }, + body: imageUpdatePayload, + }; + await fetch(`/api/image/${flake}`, options); + }, + async updateImageTags(flake, tagsInputID) { + // Multiple tags are delimited by a white space + const tags = document + .getElementById(tagsInputID) + .value.split(" ") + .filter((element) => element.length > 0); + const options = { + method: "PUT", + }; + + for (let i = 0; i < tags.length; i++) { + await fetch(paths.ImageTagField(flake, tags[i]), options); + } + }, + }, +}; +</script> + +<style scoped> +.imageInfoFields { + @apply border-2 focus:outline-none focus:ring-2 focus:ring-blue-300 pl-1 my-2; +} +</style> \ No newline at end of file diff --git a/src/components/ImageUpload.vue b/src/components/ImageUpload.vue index 5f0a996c2f788f4c0e1a3239fce3428da11f983a..418f132f742931bb6a73449a64cea4387ea0c64c 100644 --- a/src/components/ImageUpload.vue +++ b/src/components/ImageUpload.vue @@ -68,46 +68,7 @@ alt="" class="max-w-xs m-4" /> - <div class="flex flex-col flex-1"> - <form :id="'image-update-form-' + id" class="flex flex-col flex-1"> - <input - type="text" - placeholder="Source" - name="source" - autocomplete="off" - class="inputBox inputPayload" - /> - <input - type="text" - placeholder="Parent" - name="parent" - autocomplete="off" - class="inputBox inputPayload" - /> - <textarea - type="text" - placeholder="Commentary" - name="commentary" - autocomplete="off" - class="inputBox inputPayload resize-none flex-1" - /> - <textarea - type="text" - placeholder="Commentary translation" - name="commentary_translation" - autocomplete="off" - class="inputBox inputPayload resize-none flex-1" - /> - </form> - <input - type="text" - placeholder="Tags" - name="tags" - autocomplete="off" - :id="'tagsInput' + id" - class="inputBox inputPayload" - /> - </div> + <ImageMetadataFields :id="id"></ImageMetadataFields> </div> </div> </template> @@ -115,11 +76,13 @@ <script> import { mapActions, mapState } from "vuex"; import WarningBox from "@/components/WarningBox.vue"; +import ImageMetadataFields from "@/components/ImageMetadataFields.vue"; import paths from "@/assets/js/paths.js"; export default { components: { WarningBox, + ImageMetadataFields, }, data: () => { return { @@ -173,47 +136,14 @@ export default { for (let i = 0; i < this.imageUploadList.length; i++) { formData.set("image", this.imageUploadList[i].file); let data = await this.postImageFile(formData); - this.setImageInfo( - data.snowflake, - this.serializeForm("image-update-form-" + i) - ); - this.setImageTags(data.snowflake, "tagsInput" + i); + // Signal ImageUpdateFields along with sending the image's snowflake + // to update corresponding image information + this.$emit(`update-image-info-${i}`, data.snowflake); } // Clean up this.invalidType = false; this.imageUploadList = []; }, - // Serialize form inputs into JSON object that can be sent to API - serializeForm(formID) { - return JSON.stringify( - Object.fromEntries(new FormData(document.getElementById(formID))) - ); - }, - // Send an image update payload including 4 fields: "source", "parent", "commentary", - // "commentary translation" to paths.ImageField - async setImageInfo(flake, imageUpdatePayload) { - const options = { - method: "PATCH", - headers: { - secret: this.stateUser.secret, - }, - body: imageUpdatePayload, - }; - await fetch(`/api/image/${flake}`, options); - }, - async setImageTags(flake, tagsInputID) { - const tags = document - .getElementById(tagsInputID) - .value.split(" ") - .filter((element) => element.length > 0); - const options = { - method: "PUT", - }; - - for (let i = 0; i < tags.length; i++) { - await fetch(paths.ImageTagField(flake, tags[i]), options); - } - }, async postImageFile(fd) { const options = { method: "POST", @@ -230,10 +160,4 @@ export default { ...mapActions(["addStateImageSnowflake"]), }, }; -</script> - -<style scoped> -.inputPayload { - @apply pl-1 my-2; -} -</style> \ No newline at end of file +</script> \ No newline at end of file