<template> <div> <base-toaster :open="toasterIsOpen" @close="hideDialog" > <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 && !jwt" class="text-2xl text-red-500" > {{ errorMsg }} </h3> <div v-if="item === 'new' || loaded" class="md:flex w-3/5 border border-gray-300 rounded-lg 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 class="w-full md:w-auto" @submit.prevent="updateReview" > <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 id="inline-entity-type" 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 " > <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 id="inline-entity-id" v-model="entityId" disabled 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 " 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 id="inline-change-operation" v-model="changeOperation" disabled 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 " > <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 id="inline-attribute-name" v-model="attribute" disabled 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 " 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 id="inline-attribute-value" v-model="attributeValue" disabled 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 " 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 id="inline-comment" v-model="submissionComments" disabled rows="5" 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 " type="text" placeholder="your comments here" /> </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="colorChange" class="rounded-full mt-3 px-4 mr-2 w-40 text-white p-2 rounded flex items-center justify-center" > <!-- <div class="rounded-full px-4 mr-2 bg-gray-500 text-white p-2 rounded flex items-center justify-center">${sData}</div> --> {{ 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 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 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"> Synced At </label> </div> <div class="md:w-2/3"> <p class="mt-3"> {{syncedAt}} </p> </div> </div> <div v-if=" userRole === 'Maintainer' && item !== 'new' && status!='synced' " class="mt-10" > <div class="relative flex py-5 items-center"> <div class="flex-grow border-t border-gray-400" /> <span class="flex-shrink mx-4 text-gray-400" >Reviewer Section</span> <div class="flex-grow border-t border-gray-400" /> </div> <div v-if="isLoading"> <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 id="inline-status" v-model="reviewerStatus" class=" w-full rounded-lg py-2 text-gray-700 border bg-transparent border-gray-500 hover:border-gray-700 focus:bg-gray-200 focus:border-gray-700 " @change="validateStatusChange" > <!-- <option value="Select" selected disabled>Select</option> <option>accepted</option> <option>rejected</option> --> <option v-for="action in reqActions" :key="action" :value="action" > {{ action }} </option> </select> <p v-if="error && statusErrMsg" class="text-2xl p-2 text-red-500" > {{ statusErrMsg }} </p> </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 id="inline-reviewer-comment" v-model.trim="reviewComments" rows="5" class=" bg-white w-full py-2 px-2 rounded-lg text-gray-700 border bg-transparent border-gray-500 hover:border-gray-700 " type="text" placeholder="Reviewer comments here" @keyup="validateReviewerCmt" /> </div> <p v-if="error && reviewerCmtErrMsg" class="text-2xl text-red-500" > {{ reviewerCmtErrMsg }} </p> </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' && status!='synced'" type="submit" :disabled="entityId.length < 3" class="bg-blue-500 font-bold rounded-lg px-5 py-4 text-white hover:bg-blue-700" > {{ "Update Review" }} </button> <button type="button" class=" text-white text-2xl font-bold rounded-lg bg-gray-500 hover:bg-gray-700 focus:ring-4 focus:ring-blue-300 rounded-lg items-center px-5 py-3 text-center mr-2 " @click="$router.go(-1)" > 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 { name: "UpdateItem", components: { BaseSpinner, BaseToaster }, 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: "Choose an action", 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, actionErrMsg:"", isDev: process.env.NODE_ENV === "development", reqActions:["Choose an action","accepted", "rejected"] }; }, 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"]; }, colorChange(){ if(this.status==='rejected'){ return `bg-red-500` }else if(this.status==='requested'){ return `bg-yellow-500` } else if(this.status==='synced'){ return `bg-gray-500` }else if(this.status==='accepted'){ return `bg-green-500` } return '' } }, 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); } } }, 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) vm.isLoading= true; 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: vm.syncedAt=d.SyncedAt; vm.syncResponse=d.SyncResponse } vm.isLoading=false; vm.loaded = true; } catch (error) { // console.error(error) this.error = true; this.errorMsg = "You are not authorized to access this item."; vm.isLoading=false; 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 === "Choose an action") { console.log("in update review true"); this.error = true; this.statusErrMsg = "Please select an action."; return; }else if (this.reviewerStatus===this.status) { this.error = true; this.statusErrMsg = "The new change status is same as previous. Please select another value."; 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; vm.isLoading=false; } }, }, }; </script> <style> @import url("~@/assets/bootstrap.css"); a { color: #42b983; } </style>