diff --git a/src/components/ImageMetadataFields.vue b/src/components/ImageMetadataFields.vue index 7f5179e319cc6e7e2982813eac76910c5782f188..80ae272ae1c6150f741128cc9c21141868f68d76 100644 --- a/src/components/ImageMetadataFields.vue +++ b/src/components/ImageMetadataFields.vue @@ -1,11 +1,12 @@ <template> <div class="flex flex-col flex-1"> - <form id="payloadFields" class="flex flex-col flex-1"> + <form :id="formID" class="flex flex-col flex-1"> <input type="text" placeholder="Source" name="source" autocomplete="off" + :value="source" class="imageInfoFields" /> <input @@ -13,6 +14,7 @@ placeholder="Parent" name="parent" autocomplete="off" + :value="parent" class="imageInfoFields" /> <textarea @@ -20,6 +22,7 @@ placeholder="Commentary" name="commentary" autocomplete="off" + :value="commentary" class="imageInfoFields resize-none flex-1" /> <textarea @@ -27,15 +30,17 @@ placeholder="Commentary translation" name="commentary_translation" autocomplete="off" + :value="commentaryTranslation" class="imageInfoFields resize-none flex-1" /> </form> <input - id="tagField" + :id="tagFieldID" type="text" placeholder="Tags" name="tags" autocomplete="off" + :value="tags" class="imageInfoFields" /> </div> @@ -46,28 +51,54 @@ import { mapState } from "vuex"; import paths from "@/assets/js/paths.js"; export default { + data: function () { + return { + formID: "imageInfoFields", + tagFieldID: "imageTagField", + }; + }, props: { id: { required: true, }, + source: String, + parent: String, + commentary: String, + commentaryTranslation: String, + tags: "", }, created() { this.$parent.$on(`update-image-info-${this.id}`, this.updateImageMetadata); + this.$parent.$on(`update-image-info-${this.id}`, this.imageMetadataUpdated); }, computed: { ...mapState(["stateUser"]), }, methods: { + imageMetadataUpdated() { + this.$parent.$emit( + "image-info-updated", + this.serializeForm(this.formID), + this.sanitizeTagsField(this.tagFieldID) + ); + }, updateImageMetadata(flake) { - this.updateImageInfo(flake, this.serializeForm("payloadFields")); - this.updateImageTags(flake, "tagField"); + this.updateImageInfo(flake, this.serializeForm(this.formID)); + this.updateImageTags(flake, this.sanitizeTagsField(this.tagFieldID)); }, - // Serialize form inputs into JSON object that can be sent to API endpoints + // Serialize form inputs into JSON string that can be sent to API endpoints serializeForm(formID) { return JSON.stringify( Object.fromEntries(new FormData(document.getElementById(formID))) ); }, + sanitizeTagsField(tagFieldID) { + // Multiple tags are delimited by a white space + return document + .getElementById(tagFieldID) + .value.split(" ") + .filter((element) => element.length > 0); + }, // Send an image update payload including 4 fields: // "source", "parent", "commentary", "commentary translation" to paths.ImageField async updateImageInfo(flake, imageUpdatePayload) { @@ -80,18 +111,12 @@ export default { }; 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); + async updateImageTags(flake, tagsPayload) { const options = { method: "PUT", }; - - for (let i = 0; i < tags.length; i++) { - await fetch(paths.ImageTagField(flake, tags[i]), options); + for (let i = 0; i < tagsPayload.length; i++) { + await fetch(paths.ImageTagField(flake, tagsPayload[i]), options); } }, }, diff --git a/src/views/ImagePost.vue b/src/views/ImagePost.vue index 27ad847338b4f9055e3d165f5c2cae0805a4fa3b..7803a01f0bae516e926eb44caf05870c9386c510 100644 --- a/src/views/ImagePost.vue +++ b/src/views/ImagePost.vue @@ -22,12 +22,14 @@ <div> <strong>Options</strong> <ul class="pl-2"> + <li><button @click="editToggle = !editToggle">Edit</button></li> <li><button @click="removeImage">Remove</button></li> </ul> </div> </section> <section class="flex-auto ml-12"> <img :src="`/api/image/${flake}/file`" alt="" class="max-w-4xl" /> + <!-- Image's commentary and translated commentary --> <div v-if="imageInfo.commentary || imageInfo.commentary_translation" class="bg-gray-200 bg-opacity-60 p-4 m-2" @@ -55,6 +57,26 @@ }} </div> </div> + <!-- Metadata fields --> + <div v-if="editToggle"> + <strong>Edit image metadata</strong> + <ImageMetadataFields + :source="imageInfo.source" + :parent="imageInfo.parent" + :commentary="imageInfo.commentary" + :commentaryTranslation="imageInfo.commentary_translation" + :tags="imageTags === null ? '' : imageTags.join(' ')" + id="0" + ></ImageMetadataFields> + <button + @click=" + $emit('update-image-info-0', flake); + editToggle = false; + " + > + Submit + </button> + </div> </section> </div> </template> @@ -62,11 +84,16 @@ <script> import { mapState } from "vuex"; import paths from "@/assets/js/paths.js"; +import ImageMetadataFields from "@/components/ImageMetadataFields.vue"; export default { + components: { + ImageMetadataFields, + }, data: function () { return { imageTags: Array, + editToggle: false, originalComment: true, imageInfo: Object, flake: this.$route.params.flake, @@ -105,8 +132,12 @@ export default { }, }, async created() { - this.imageTags = await this.getImageTags(); this.imageInfo = await this.getImageInfo(); + this.imageTags = await this.getImageTags(); + this.$on("image-info-updated", (imageInfoFields, imageTagField) => { + this.imageInfo = JSON.parse(imageInfoFields); + this.imageTags = imageTagField; + }); }, }; </script> \ No newline at end of file