<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 font-bold capitalize 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 v-if="status != 'rejected'" 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 v-if="!syncResponse" class=" mt-3 px-4 mr-2 w-full bg-gray-300 p-2 flex items-center justify-center " > Yet to be synced. </p> <p v-else class="mt-3" > {{ syncResponse }} </p> </div> </div> <div v-if="status != 'rejected'" 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 v-if="!syncedAt" class=" mt-3 px-4 mr-2 w-full bg-gray-300 p-2 flex items-center justify-center " > Yet to be synced. </p> <p v-else 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=" text-white bg-blue-500 hover:bg-blue-700 focus:ring-2 focus:ring-blue-300 rounded-lg inline-flex items-center px-5 py-2.5 text-center font-bold " > {{ "Update Review" }} </button> <div class="group"> <button type="button" class=" bg-gray group-hover:bg-gray-400 group-hover:text-white focus:ring-2 focus:ring-gray-300 rounded-lg border border-gray-300 px-5 py-3 hover:text-gray-900 font-bold " @click="$router.go(-1)" > Back </button> </div> </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; }, 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; setTimeout(() => { this.toasterIsOpen = false; this.load(this.item); }, 2000); } catch (error) { // console.log(error.response.data.error.message) // console.log(error.response) this.error = true; this.errorMsg = error; vm.isLoading = false; } }, }, }; </script> <style scoped> @import url("~@/assets/bootstrap.css"); a { color: #ef0087 !important; } </style>