<template> <div> <base-toaster @close="hideDialog" :open="toasterIsOpen"> <div class="flex justify-between items-center"> <font-awesome-icon class="ml-3" icon="fa-solid fa-thumbs-up " size="lg" /> <h4>Request updated successfully!</h4> <button class="btn btn-outline" @click="hideDialog"> <font-awesome-icon icon="fa-regular fa-circle-xmark" size="2x" /> </button> </div> </base-toaster> <div class="flex items-center justify-center"> <h3 v-show="error" class="text-2xl text-red-500">{{ errorMsg }}</h3> <div v-if="item === 'new' || loaded" class="md:flex w-3/5 card p-2 mt-5"> <div class="p-5 mx-auto text-left font-raleway container max-w-screen-md" > <h1 class=" font-bold text-left font-montserrat text-3xl sm:text-5xl mb-7 " > {{ item === "new" ? "Create new Update Item" : item }} </h1> <form @submit.prevent="updateReview" class="w-full md:w-auto"> <div class="md:flex md:items-center mx-3 mb-6"> <div class="md:w-1/3"> <label class="text-left font-bold md:text-right mb-1 md:mb-0 pr-4" for="inline-entity-type" > Entity Type </label> </div> <div class="md:w-2/3"> <select v-model="entity" disabled class=" bg-white w-full py-2 text-gray-700 bg-transparent border-b hover:border-gray-700 focus:bg-gray-200 focus:border-blue-700 " id="inline-entity-type" > <option disabled value="">Please select one</option> <option>protein</option> <option>condensate</option> <option>condensate_protein</option> </select> </div> </div> <div class="md:flex md:items-center mx-3 mb-6"> <div class="md:w-1/3"> <label class="text-left font-bold md:text-right mb-1 md:mb-0 pr-4" for="inline-entity-id" > Entity ID </label> </div> <div class="md:w-2/3"> <input disabled v-model="entityId" class=" bg-white w-full py-2 text-gray-700 outline-none bg-transparent border-b hover:border-gray-700 focus:bg-gray-200 focus:border-blue-700 " id="inline-entity-id" type="text" placeholder="UNE6" /> </div> </div> <div class="md:flex md:items-center mx-3 mb-6"> <div class="md:w-1/3"> <label class="text-left font-bold md:text-right mb-1 md:mb-0 pr-4" for="inline-change-operation" > Change Operation </label> </div> <div class="md:w-2/3"> <select disabled v-model="changeOperation" class=" bg-white w-full py-2 text-gray-700 outline-none bg-transparent border-b hover:border-gray-700 focus:bg-gray-200 focus:border-blue-700 " id="inline-change-operation" > <option disabled value="">Please select one</option> <option>add</option> <option>remove</option> <option>update</option> </select> </div> </div> <div class="md:flex md:items-center mx-3 mb-6"> <div class="md:w-1/3"> <label class="text-left font-bold md:text-right mb-1 md:mb-0 pr-4" for="inline-attribute-name" > Attribute Name </label> </div> <div class="md:w-2/3"> <input disabled v-model="attribute" class=" bg-white w-full py-2 text-gray-700 outline-none bg-transparent border-b hover:border-gray-700 focus:bg-gray-200 focus:border-blue-700 " id="inline-attribute-name" type="text" placeholder="functional_type" /> </div> </div> <div class="md:flex md:items-center mx-3 mb-6"> <div class="md:w-1/3"> <label class="text-left font-bold md:text-right mb-1 md:mb-0 pr-4" for="inline-attribute-value" > Attribute Value </label> </div> <div class="md:w-2/3"> <input disabled v-model="attributeValue" class=" bg-white w-full py-2 text-gray-700 outline-none bg-transparent border-b hover:border-gray-700 focus:bg-gray-200 focus:border-blue-700 " id="inline-attribute-value" type="text" placeholder="driver" /> </div> </div> <div class="md:flex md:items-center mx-3 mb-6"> <div class="md:w-1/3"> <label class="text-left font-bold md:text-right mb-1 md:mb-0 pr-4" for="inline-comment" > Comments </label> </div> <div class="md:w-2/3"> <textarea disabled rows="5" v-model="submissionComments" class=" bg-white w-full py-2 text-gray-700 outline-none bg-transparent border-b hover:border-gray-700 focus:bg-gray-200 focus:border-blue-700 " id="inline-comment" type="text" placeholder="your comments here" ></textarea> </div> </div> <div v-if="item !== 'new'" class="md:flex md:items-center mx-3 mb-6" > <div class="md:w-1/3"> <label class="text-left font-bold md:text-right mb-1 md:mb-0 pr-4" for="inline-status" > Status </label> </div> <div class="md:w-2/3"> <p v-if=" (userRole === 'Contributor' || userRole === 'Maintainer' || userRole === 'Administrator') && itemId !== 'new' " class="mt-3" > {{ status }} </p> </div> </div> <div v-if="item !== 'new' && reviewedBy.data" class="md:flex md:items-center mx-3 mb-6" > <div class="md:w-1/3"> <label class="text-left font-bold md:text-right mb-1 md:mb-0 pr-4" for="inline-status" > Reviewer </label> </div> <div class="md:w-2/3"> <p class="mt-3"> {{ reviewedBy.data.attributes.full_name }} </p> </div> </div> <div v-if="item !== 'new' && reviewedBy.data" class="md:flex md:items-center mx-3 mb-6" > <div class="md:w-1/3"> <label class="text-left font-bold md:text-right mb-1 md:mb-0 pr-4" for="inline-status" > Reviewer Comments </label> </div> <div class="md:w-2/3"> <p class="mt-3"> {{ reviewerComments }} </p> </div> </div> <!-- <button v-if="item !== 'new' && userRole !== 'Maintainer'" type="submit" :disabled="entityId.length < 3" class="bg-green-400 p-5 text-white" > {{ item === "new" ? "Submit" : "Update" }} <span class="fa fa-arrow-right" /> </button> --> <div v-if=" userRole === 'Maintainer' && item !== 'new' " class="mt-10" > <div class="relative flex py-5 items-center"> <div class="flex-grow border-t border-gray-400"></div> <span class="flex-shrink mx-4 text-gray-400" >Reviewer Section</span > <div class="flex-grow border-t border-gray-400"></div> </div> <div v-if="isLoading"> <base-spinner></base-spinner> </div> <h3 class="mb-6">Reviewer Action</h3> <div class="md:flex md:items-center mx-3 mb-6"> <div class="md:w-1/3"> <label class="text-left font-bold md:text-right mb-1 md:mb-0 pr-4" for="inline-status" > Change Status to </label> </div> <div class="md:w-2/3"> <div> <select @change="validateStatusChange" v-model="reviewerStatus" class=" w-full py-2 text-gray-700 outline-none bg-transparent border-b hover:border-gray-700 focus:bg-gray-200 focus:border-gray-700 " id="inline-status" > <option value="Select" selected disabled>Select</option> <option>accepted</option> <option>rejected</option> </select> <h3 v-if="error && statusErrMsg" class="text-2xl text-red-500" > {{ statusErrMsg }} </h3> </div> </div> </div> <div class="md:flex md:items-center mx-3 mb-6"> <div class="md:w-1/3"> <label class="text-left font-bold md:text-right mb-1 md:mb-0 pr-4" for="inline-reviewer-comment" > Reviewer Comment </label> </div> <div class="md:w-2/3"> <div> <textarea rows="5" v-model.trim="reviewComments" @keyup="validateReviewerCmt" class=" bg-white w-full py-2 text-gray-700 outline-none bg-transparent border-b hover:border-gray-700 focus:bg-gray-200 focus:border-gray-700 " id="inline-reviewer-comment" type="text" placeholder="reviewer comments here" ></textarea> </div> <h3 v-if="error && reviewerCmtErrMsg" class="text-2xl text-red-500" > {{ reviewerCmtErrMsg }} </h3> </div> </div> <!-- <div class="md:flex md:items-center mx-3 mb-6"> <div class="md:w-1/3"> <label class="text-left font-bold md:text-right mb-1 md:mb-0 pr-4" for="inline-reviewer-comment"> Sync Response </label> </div> <div class="md:w-2/3"> <p class="mt-3"> {{syncResponse}} </p> </div> </div> --> </div> <div class="flex space-x-4"> <button v-if=" userRole === 'Maintainer' && item !== 'new'" type="submit" :disabled="entityId.length < 3" class="bg-green-400 font-bold rounded-lg p-5 text-white" > {{ "Update Review" }} <font-awesome-icon icon="fa-solid fa-pen-to-square" /> </button> <button type="button" class=" text-white font-bold rounded-lg bg-blue-600 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 rounded-lg items-center px-5 py-4 text-center mr-2 " @click="$router.go(-1)" > <span class="fa fa-arrow-left" /> Back </button> </div> </form> </div> </div> </div> </div> </template> <script> import BaseSpinner from "../components/UI/BaseSpinner.vue"; import BaseToaster from "../components/UI/BaseToaster.vue"; let host = require("@/components/js/const").apiHost; export default { components: { BaseSpinner, BaseToaster }, name: "UpdateItem", props: ["itemId"], data() { return { item: this.$route.params.item ? this.$route.params.item : this.itemId, entity: "protein", // [protein, condensate, condensate_protein] entityId: "", // protein: <uniprot_id>, condensate: <canonical_id>, condensate_protein: <uniprot_id>==<canonical_id> changeOperation: "add", // add/remove/update/update_add/update_remove attribute: "", // protein: functional_type[driver/client/regulator], pubmed_ids[] // condensate: description, proteins // condensate_protein: confidence_score, pubmed_ids attributeValue: "", // the value of the attribute to be updated. Could be "null" for add/remove operations. The data type is dynamic status: "requested", // 1. requested, 2. accepted, 3. rejected, 4. synced reviewerStatus: "", submittedBy: "", submittedAt: "", // datetime submissionComments: "", reviewedBy: "", reviewedAt: "", // datetime reviewComments: "", reviewerComments: "", syncedAt: "", // datetime syncResponse: "", // response from the sync process (errors if any) loaded: false, error: false, errorMsg: `An error occurred, please try again`, statusErrMsg: "", reviewerCmtErrMsg: "", isLoading: false, toasterIsOpen: false, isDev: process.env.NODE_ENV === "development", }; }, computed: { jwt: function () { return this.$store.getters["User/jwt"]; }, userData: function () { return this.$store.getters["User/userData"]; }, userRole: function () { return this.$store.getters["User/userRole"]; }, }, methods: { showDialog() { this.toasterIsOpen = true; }, hideDialog() { this.toasterIsOpen = false; this.$router.go(-1) }, validateReviewerCmt() { this.error = false; this.reviewerCmtErrMsg = ""; }, validateStatusChange() { this.error = false; this.statusErrMsg = ""; }, async update(e) { e.preventDefault(); const vm = this; if (vm.isDev) { host = require("@/components/js/const").devApiHost; } const jwt = vm.jwt; if (jwt === null) { vm.loaded = false; return; } // console.log(vm.userData) let dat = { Entity: this.entity, EntityId: this.entityId, Attribute: this.attribute, Value: this.attributeValue, ChangeOperation: this.changeOperation, SubmissionComments: this.submissionComments, Status: vm.userRole === "Maintainer" ? "accepted" : this.status, // ReviewedBy: // ReviewedAt: // ReviewComment: // SyncedAt: // SyncResponse: }; try { if (vm.item !== "new") { const res = await this.axios.put( `${host}/api/update-items/` + vm.item, { data: dat, }, { headers: { Authorization: `Bearer ${jwt}`, }, } ); } else { const res = await this.axios.post( `${host}/api/update-items`, { data: dat, }, { headers: { Authorization: `Bearer ${jwt}`, }, } ); } // console.log(res) vm.$router.push("/profile"); } catch (error) { // console.log(error.response.data.error.message) // console.log(error.response) this.error = true; this.errorMsg = error; } }, async load(id) { const vm = this; if (vm.isDev) { host = require("@/components/js/const").devApiHost; } const jwt = vm.jwt; if (jwt === null) { vm.loaded = false; return; } // console.log(vm.userData) try { const res = await this.axios.get(`${host}/api/update-items/` + id, { headers: { Authorization: `Bearer ${jwt}`, }, }); console.log(res.data.data) if (res.data.data) { const d = res.data.data.attributes; vm.item = res.data.data.id; vm.entity = d.Entity; vm.entityId = d.EntityId; vm.attribute = d.Attribute; vm.attributeValue = d.Value; vm.changeOperation = d.ChangeOperation; vm.status = d.Status; vm.submissionComments = d.SubmissionComments; vm.reviewerComments = d.ReviewComments; vm.reviewedBy = d.reviewedBy; vm.reviewedAt = d.ReviewedAt; // ReviewedBy: // ReviewedAt: // ReviewComment: // SyncedAt: // SyncResponse: } vm.loaded = true; } catch (error) { // console.error(error) this.error = true; this.errorMsg = "You are not authorized to access this item."; setTimeout(() => vm.$router.go(-1), 2000); } }, async updateReview() { const vm = this; if (vm.isDev) { host = require("@/components/js/const").devApiHost; } const jwt = vm.jwt; if (jwt === null) { vm.loaded = false; return; } if (!this.reviewerStatus || this.reviewerStatus === "Select") { console.log("in update review true"); this.error = true; this.statusErrMsg = "Please change the status to either ACCEPTED or REJECTED!"; return; } else if (!this.reviewComments) { this.error = true; this.reviewerCmtErrMsg = "Comment should not be empty!"; return; } // console.log(vm.userData) let dat = { Status: this.reviewerStatus, ReviewComments: this.reviewComments, ReviewedAt: this.reviewedAt, }; this.isLoading = true; try { await this.axios.put( `${host}/api/update-item/review/` + vm.item, { data: dat, }, { headers: { Authorization: `Bearer ${jwt}`, }, } ); // console.log(res) this.reviewComments = ""; this.isLoading = false; this.toasterIsOpen = true; } catch (error) { // console.log(error.response.data.error.message) // console.log(error.response) this.error = true; this.errorMsg = error; } }, }, mounted: async function () { const vm = this; const jwt = vm.jwt; if (jwt === null) { vm.$router.push("/login"); } else { if (vm.item !== "new") { vm.load(vm.item); } } }, }; </script> <style> @import url("~@/assets/bootstrap.css"); a { color: #42b983; } </style>