UpdateItem.vue 26.65 KiB
<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
bg-white bg-opacity-90
border-gray-300
rounded-lg
p-2
my-14
"
>
<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="!syncedAt && status !== 'synced' && status !== 'failed'"
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 && status !== 'synced' && status !== 'failed'"
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="showReviewerSection"
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="showReviewerSection"
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-pink-500`;
} else if (this.status === 'synced') {
return `bg-blue-500`;
} else if (this.status === 'accepted') {
return `bg-green-500`;
} else if (this.status === 'failed') {
return `bg-gray-500`;
}
return '';
},
showReviewerSection() {
if (
this.userRole === 'Maintainer' &&
this.status !== 'failed' &&
this.status !== 'synced'
) {
return true;
}
// else if (this.userRole === "Maintainer" && this.status !== "failed") {
// console.log("in failed check");
// return true;
// }
return false;
},
},
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>