CondensateDetailPage.vue 51.95 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 submitted 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 flex-wrap justify-center">
<!-- Sidebar -->
<!--<div class="bg-light border-right" id="sidebar-wrapper">-->
<!--<!–<div class="sidebar-heading">Menu </div>–>-->
<!--<div class="list-group list-group-flush">-->
<!--<a href="#" class="list-group-item list-group-item-action bg-light">Search</a>-->
<!--<a href="#" class="list-group-item list-group-item-action bg-light">Columns</a>-->
<!--<a href="#" class="list-group-item list-group-item-action bg-light">Filters</a>-->
<!--<a href="#" class="list-group-item list-group-item-action bg-light">Download</a>-->
<!--<a href="#" class="list-group-item list-group-item-action bg-light">Contacts</a>-->
<!--</div>-->
<!--</div>-->
<!-- /#sidebar-wrapper -->
<div class="w-5/6">
<fetch-condensate :condensate="condensate">
<template slot-scope="{ response, loading, fetchError }">
<slot
:response="response"
:loading="loading"
:fetchError="fetchError"
>
<div v-if="loading || response === null">
<base-spinner />
</div>
<div>
<h2
v-if="fetchError"
class="text-red-500"
>
{{ fetchError }}
</h2>
</div>
<!-- <div v-if="loading">
<base-spinner></base-spinner>
</div> -->
<div v-if="response">
<div class="flex space-x-4">
<h2>{{ response.data.name }}</h2>
<button
v-if="
getUserData !== null &&
(getUserData === 'Maintainer' ||
getUserData === 'Contributor')
"
class="rounded-lg px-5 py-4 text-center"
@click="toggleChangeName"
>
<font-awesome-icon
size="lg"
icon="fa-solid fa-pen-to-square fa-xl"
/>
</button>
</div>
<div
v-if="changeName"
class="
bg-white
p-4
border border-gray-300
rounded-lg
bg-opacity-80
"
>
<form
class="form-horizontal"
@submit.prevent="changeCondensateName(response)"
>
<div class="form-group space-y-4">
<div class="row">
<label
for="condensateName"
class="control-label col-sm-2"
>Name</label>
<div class="col-sm-10">
<div class="w-1/4">
<input
id="condensateName"
v-model.trim="condensateName"
class="form-control"
type="text"
placeholder="Enter condensate name."
@keyup="validateName"
>
<p
v-if="nameError && nameErrMsg"
class="text-red-500 mt-2 text-2xl font-bold"
>
{{ nameErrMsg }}
</p>
</div>
</div>
</div>
<div class="row">
<label
for="condensateName"
class="control-label col-sm-2"
>Reason</label>
<div class="col-sm-10">
<div class="w-3/4">
<textarea
v-model.trim="condensateNameComment"
class="
form-control
block
px-3
py-1.5
text-base
font-normal
text-gray-700
bg-white bg-clip-padding
border border-solid border-gray-300
rounded
transition
ease-in-out
m-0
focus:text-gray-700
focus:bg-white
focus:border-blue-600
focus:outline-none
"
rows="5"
:placeholder="
getUserData === 'Maintainer'
? 'Optional'
: 'Mandatory'
"
@keyup="descriptionKeyup"
/>
<p
v-if="
nameCommentErr && condensateNameCommentErrMsg
"
class="text-red-500 mt-2 text-2xl font-bold"
>
{{ condensateNameCommentErrMsg }}
</p>
</div>
<div class="flex space-x-4 mt-4">
<button
type="submit"
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
"
>
Save
</button>
<button
class="
bg-white
hover:bg-gray-200
focus:ring-2 focus:ring-gray-300
rounded-lg
border border-gray-300
px-5
py-2.5
hover:text-gray-900
font-bold
"
@click="toggleChangeName"
>
Cancel
</button>
</div>
</div>
</div>
</div>
</form>
</div>
<h4 class="round">
General Information
</h4>
<div
class="
bg-white
border border-gray-300
rounded-lg
bg-opacity-80
"
>
<div class="panel-body">
<div class="container-fluid col-md-12">
<!-- <div class="row">
<div class="text col-sm-3">
Canonical ID
</div>
<div class="col-sm-9">
{{ response.data.canonical_id }}
</div>
</div> -->
<div class="row">
<div class="text col-sm-3 text-2xl">
Species
</div>
<div class="col-sm-9 text-2xl">
{{ response.data.species_name }} ({{
response.data.species_tax_id
}})
</div>
</div>
<div class="row text-2xl">
<div class="text col-sm-3">
Description
</div>
<div class="col-sm-9 text-2xl">
{{ response.data.description }}
<button
v-if="
getUserData !== null &&
(getUserData === 'Maintainer' ||
getUserData === 'Contributor')
"
class="btn btn-primary btn-link"
@click="
toggleUpdateDescription(response.data.description)
"
>
<font-awesome-icon
icon="fa-solid fa-pen-to-square fa-xl"
/>
</button>
<div
v-if="showUpdateDescription"
class="panel panel-default"
>
<div class="panel-body">
<div class="container-fluid col-md-12">
<form
class="form-horizontal"
autocomplete="off"
@submit.prevent="updateDescription(response)"
>
<div v-if="isLoading">
<base-spinner />
</div>
<div class="form-group">
<label
class="control-label col-sm-2"
for="keyword"
>Update description</label>
<div class="col-sm-10">
<textarea
id="comment"
v-model.trim="description"
class="
form-control
block
px-3
py-1.5
text-base
font-normal
text-gray-700
bg-white bg-clip-padding
border border-solid border-gray-300
rounded
transition
ease-in-out
m-0
focus:text-gray-700
focus:bg-white
focus:border-blue-600
focus:outline-none
"
rows="5"
placeholder="Description"
@keyup="descriptionKeyup"
/>
<p
v-if="descriptionErrorMsg"
class="text-red-600 font-bold"
>
{{ descriptionErrorMsg }}
</p>
</div>
</div>
<div class="form-group">
<label
class="control-label col-sm-2"
for="funComment"
>Reason</label>
<div class="col-sm-10">
<textarea
id="funComment"
v-model.trim="descriptionComment"
class="
form-control
block
px-3
py-1.5
text-base
font-normal
text-gray-700
bg-white bg-clip-padding
border border-solid border-gray-300
rounded
transition
ease-in-out
m-0
focus:text-gray-700
focus:bg-white
focus:border-blue-600
focus:outline-none
"
rows="5"
:placeholder="
getUserData === 'Maintainer'
? 'Optional'
: 'Mandatory'
"
@keyup="commentKeyup"
/>
<p
v-if="descriptionCommentErr"
class="text-red-600 font-bold"
>
{{ commentErrorMsg }}
</p>
<p
v-if="descriptionMsg"
class="text-green-600 font-bold"
>
{{ descriptionMsg }}
</p>
<div class="flex space-x-4">
<button
id="dropdownMenuButton"
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
"
type="submit"
>
Update
</button>
<button
id="dropdownMenuButton"
class="
bg-white
hover:bg-gray-200
focus:ring-2 focus:ring-gray-300
rounded-lg
border border-gray-300
px-5
py-2.5
hover:text-gray-900
font-bold
"
type="button"
@click="toggleUpdateDescription"
>
Cancel
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<!-- <div
v-show="response.data.synonyms"
class="row"
>
<div class="text col-sm-3">
Also Known As
</div>
<div class="col-sm-9">
{{
response.data.synonyms
? response.data.synonyms
.map((a) =>
a
.replace("-", " ")
.replace(/\b\w/g, (l) => l.toUpperCase())
)
.join(", ")
: ""
}}
</div>
</div> -->
<div class="row text-2xl">
<div class="text col-sm-3 text-2xl">
Markers
<a
class="uniprot-link tooltipped tooltipped-e"
aria-label="Proteins which can help in unique identification of the condensate organelle"
>
<span class="fa fa-info-circle" />
</a>
</div>
<div class="col-sm-9">
<span v-if="!response.data.biomarkers"> None </span>
<span
v-else
v-html="getProteinLinks(response.data.biomarkers)"
/>
<button
v-if="
getUserData !== null &&
(getUserData === 'Maintainer' ||
getUserData === 'Contributor')
"
class="btn btn-primary btn-link"
@click="showAddDeleteMarker = !showAddDeleteMarker"
>
<font-awesome-icon
icon="fa-solid fa-pen-to-square fa-xl"
/>
</button>
<add-delete-marker
v-if="showAddDeleteMarker"
:marker-data="response.data.biomarkers"
:condensate-id="response.data.canonical_id"
:proteins="response.data.proteins"
@update-key="updatedKey += 1"
@close="closeAddDeleteMarker"
/>
</div>
</div>
<div class="row text-2xl">
<div class="text col-sm-3">
No. of Proteins
</div>
<div class="col-sm-9">
{{ response.data.protein_count }}
</div>
</div>
<div class="row text-2xl">
<div class="text col-sm-3 text-2xl">
Evidence star
</div>
<div class="flex col-sm-9">
<star-rating
:star-size="20"
:show-rating="false"
:rating="
response.data.confidence_score
? response.data.confidence_score
: 0
"
:read-only="true"
:increment="0.01"
/>
</div>
</div>
</div>
</div>
</div>
<div v-show="response.data.experiments.length > 0">
<h4 class="round">
Experiments
</h4>
<div class="panel panel-default">
<table class="csi table table-hover table-responsive">
<thead>
<tr class="active">
<!-- <th>Exp. ID</th>-->
<th>Method</th>
<th>Phase Separated</th>
<th>pH value</th>
<th>Morphology</th>
<th>PubMed</th>
<th>Solute Concentration</th>
<th>Temperature</th>
<th>Salts</th>
</tr>
</thead>
<tbody>
<tr
v-for="(item, index) in response.data.experiments"
:key="index"
>
<!-- <td>{{item.exp_id}}</td>-->
<td class="text-nowrap">
{{ item.detection_method }}
</td>
<td>{{ item.is_phase_separated }}</td>
<td>{{ item.ph_value }}</td>
<td>{{ item.morphology }}</td>
<td>
<fetch-pub-med :link="item.publication_link">
<template
slot-scope="{
response: pubmed_response,
loading: pubmed_loading,
}"
>
<slot
:response="pubmed_response"
:loading="pubmed_loading"
>
<div v-if="pubmed_loading" />
<div v-else>
<a
:href="item.publication_link"
class="
uniprot-link
tooltipped
tooltipped-n
tooltipped-multiline
"
:aria-label="
getTitleAuthors(
pubmed_response.title,
pubmed_response.authors
)
"
target="_blank"
>
PubMed
<i class="glyphicon glyphicon-link" />
</a>
</div>
</slot>
</template>
</fetch-pub-med>
</td>
<td>
{{ tokenize(item.solute_concentrations, ";") }}
</td>
<td>
{{ item.temperature }}
</td>
<td>
<ul
v-for="(item_salt, index_salt) in item.salts"
:key="index_salt"
>
<li
v-for="(value, key, index_li) in item_salt"
:key="index_li"
>
{{ key }} : {{ value }}
</li>
</ul>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="my-14 border border-gray-300 rounded-lg p-8">
<h4>Proteins</h4>
<button
v-if="
getUserData !== null &&
!response.data.is_experimental &&
(getUserData === 'Maintainer' ||
getUserData === 'Contributor')
"
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-3
text-center
font-bold
"
type="button"
@click="showAddProtein = !showAddProtein"
>
Add a protein to this condensate
</button>
<div
v-if="showAddProtein"
class="panel panel-default mt-4"
>
<div class="panel-body">
<div class="container-fluid col-md-12">
<div v-if="isLoading">
<base-spinner />
</div>
<form
class="form-horizontal"
autocomplete="off"
@submit.prevent="addProtein(response)"
>
<div class="form-group">
<label
class="control-label col-sm-2"
for="species"
>Add protein with uniprot ID</label>
<div class="col-sm-4">
<input
id="keyword"
v-model.trim="uniprotId"
class="form-control input-sm"
type="text"
placeholder="Uniprot ID"
@keyup="uniprotKeyup"
>
<p
v-if="isUniProtIdError"
class="text-red-600 mt-4 font-bold"
>
{{ uniprotIdErrorMsg }}
</p>
</div>
</div>
<div class="form-group">
<label
class="control-label col-sm-2"
for="keyword"
>Reason</label>
<div class="col-sm-8">
<textarea
id="comment"
v-model.trim="proteinComment"
class="
form-control
block
px-3
py-1.5
text-base
font-normal
text-gray-700
bg-white bg-clip-padding
border border-solid border-gray-300
rounded
transition
ease-in-out
m-0
focus:text-gray-700
focus:bg-white
focus:border-blue-600
focus:outline-none
"
rows="5"
:placeholder="
getUserData === 'Maintainer'
? 'Optional.'
: 'Mandatory.'
"
@keyup="validateProteinComment"
/>
<p
v-if="proteinCommentErr"
class="text-red-600 font-bold"
>
{{ commentErrorMsg }}
</p>
<p
v-if="isSubmitted"
:class="
error
? 'text-red-600 font-bold'
: 'text-green-600 font-bold'
"
>
{{ message }}
</p>
<div class="flex space-x-4">
<button
id="dropdownMenuButton"
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
"
type="submit"
>
Add
</button>
<button
id="dropdownMenuButton"
class="
bg-white
hover:bg-gray-200
focus:ring-2 focus:ring-gray-300
rounded-lg
border border-gray-300
px-5
py-2.5
hover:text-gray-900
font-bold
"
type="button"
@click="showAddProtein = !showAddProtein"
>
Cancel
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
<llps-table
id="protein-table"
:data="response.data.proteins"
:canonical-id="response.data.canonical_id"
:map="response.data.protein_confidence_score"
:is-experimental="response.data.is_experimental"
:pubmed="response.data.protein_pubmed_ids"
:db-tags="response.data.protein_source_db_tags"
:protein-driver-criterion="
response.data.protein_driver_criterion
"
:protein-experimental-evidence="
response.data.protein_exp_evidence
"
:protein-functional-type="
response.data.protein_functional_type
"
@update-key="updatedKey += 1"
/>
</div>
<!-- for above llps table protein functiona type data -->
<!-- :protein-driver-criterion="response.data.protein_driver_criterion"
:protein-experimental-evidence="response.data.protein_exp_evidence" -->
<!-- :protein-functional-type="response.data.protein_functional_type" -->
<!-- <fetch-user-specific-update-items :id="response.data.canonical_id">
<template slot-scope="{ response, loading }">
<slot :response="response" :loading="loading">
<div v-if="loading || response === null">Loading...</div>
<div v-else>
<h4 class="round">Requests</h4>
<condensate-update-items-table id="condensateUpdateItem" :data="response" />
</div>
</slot>
</template>
</fetch-user-specific-update-items> -->
<div
v-if="getUserData && !response.data.is_experimental"
class="border border-gray-300 rounded-lg p-8"
>
<h4 class="round mb-8">
All submitted changes for this condensate
</h4>
<condensate-update-items-table
id="condensateUpdateItem"
:key="updatedKey"
:data="response.data.canonical_id"
/>
</div>
<div class="my-14 border border-gray-300 rounded-lg p-8">
<h4 class="round mb-8">
Top Contributors
</h4>
<contributor-list-table
:id="response.data.canonical_id"
entity="condensate"
/>
</div>
<!-- <request-update-item-table
id="protein-table"
:data="response.data.proteins"
/> -->
<!-- {{response.data.experiments}}-->
<!--<div class="panel panel-default">-->
<!--<table class="csi table table-hover table-responsive">-->
<!--<thead>-->
<!--<tr class="active">-->
<!--<th>Name</th>-->
<!--<th>Species</th>-->
<!--<th>Uniprot</th>-->
<!--<th>Sequence</th>-->
<!--</tr>-->
<!--</thead>-->
<!--<tbody>-->
<!--<tr v-for="(item, index) in response.data.llps_ptms" v-bind:key="index">-->
<!--<td class="col-sm-6">{{item.name}}</td>-->
<!--<td>{{item.species_name}}</td>-->
<!--<td>{{item.uniprot_id}}</td>-->
<!--<td>-->
<!--<input type="text" :value="item.sequence">-->
<!--<button class="copy-button" :name="'item.uniprot_id'" :id="'item.uniprot_id'" :data-clipboard-text="item.sequence">Copy</button>-->
<!--</td>-->
<!--</tr>-->
<!--</tbody>-->
<!--</table>-->
<!--</div>-->
<!--<h4 class="round">Additional Information</h4>-->
<!--<div class="panel panel-default">-->
<!--<div class="panel-body">-->
<!--<div class="row">-->
<!--<div class="text col-sm-3">Proteins</div>-->
<!--<div class="col-sm-9">-->
<!--{{response.data.proteins}}-->
<!--</div>-->
<!--</div>-->
<!--</div>-->
<!--</div>-->
</div>
</slot>
</template>
</fetch-condensate>
</div>
</div>
</div>
<!-- /#wrapper -->
</template>
<script>
import fetchCondensate from '@/components/DDCODE/fetchCondensate.vue';
import llpsTable from '@/components/LlpsTable.vue';
import fetchPubMed from '@/components/DDCODE/fetchPubMed';
import AddDeleteMarker from './CMS/addDeleteMarker.vue';
import BaseSpinner from './UI/BaseSpinner.vue';
import CondensateUpdateItemsTable from './CondensateUpdateItemsTable.vue';
import BaseToaster from './UI/BaseToaster.vue';
import StarRating from 'vue-star-rating';
import ContributorListTable from './ContributorListTable.vue';
//import FetchUserSpecificUpdateItems from './CMS/fetchUserSpecificUpdateItems.vue';
//import RequestUpdateItemTable from "./RequestUpdateItemTable.vue";
// import TheModal from './UI/TheModal.vue';
const _ = require('lodash');
require('./js/clipboard');
let host = require('./js/const').apiHost;
export default {
name: 'CondensateDetailPage',
components: {
fetchCondensate,
llpsTable,
fetchPubMed,
AddDeleteMarker,
BaseSpinner,
CondensateUpdateItemsTable,
BaseToaster,
StarRating,
ContributorListTable,
// FetchUserSpecificUpdateItems,
// RequestUpdateItemTable,
},
props: ['condensateId'],
data() {
return {
condensate: this.$route.params.condensate
? this.$route.params.condensate
: this.condensateId,
dbNames: require('./js/const').db,
isDev: process.env.NODE_ENV === 'development',
showAddProtein: false,
uniprotId: '',
comment: '',
proteinComment: '',
condensateNameComment: '',
condensateNameCommentErrMsg: '',
markerComment: '',
descriptionComment: '',
description: '',
descriptionMsg: '',
condensateName: '',
descriptionErrorMsg: '',
isUniProtIdError: false,
isCommentError: false,
isSubmitted: false,
error: false,
showUpdateDescription: false,
showAddDeleteMarker: false,
commentErrorMsg: '',
descriptionCommentErr: false,
nameCommentErr: false,
proteinCommentErr: false,
markerCommentErr: false,
uniprotIdErrorMsg: '',
message: '',
whitespaceRegex: /(\s)/,
nameError: false,
toggleModel: false,
isLoading: false,
toasterIsOpen: false,
changeName: false,
updatedKey: 0,
};
},
computed: {
jwt: function () {
return this.$store.getters['User/jwt'];
},
getUserData() {
const userRole = this.$store.getters['User/userRole'];
return userRole;
},
},
methods: {
validateName() {
(this.nameErrMsg = ''), (this.nameError = false);
},
showDialog() {
this.toasterIsOpen = true;
},
hideDialog() {
this.toasterIsOpen = false;
},
confirm() {
this.toggleModel = false;
},
cancel() {
this.toggleModel = false;
},
toggleChangeName() {
this.changeName = !this.changeName;
this.condensateName = '';
},
closeAddDeleteMarker() {
this.comment = '';
this.showAddDeleteMarker = false;
},
uniprotKeyup() {
this.message = '';
this.isUniProtIdError = false;
},
commentKeyup() {
this.message = '';
this.descriptionCommentErr = false;
this.isCommentError = false;
},
descriptionKeyup() {
this.descriptionMsg = '';
this.descriptionErrorMsg = '';
},
toggleUpdateDescription(res) {
this.description = res;
this.descriptionMsg = '';
this.descriptionErrorMsg = '';
this.descriptionCommentErr = false;
this.descriptionComment = '';
this.showUpdateDescription = !this.showUpdateDescription;
},
validateProteinComment() {
this.proteinCommentErr = false;
this.commentErrorMsg = '';
},
async changeCondensateName(response) {
if (!this.condensateName) {
this.nameError = true;
this.nameErrMsg = 'Enter a condensate name.';
return;
}
this.nameError = false;
this.nameErrMsg = '';
if (this.isDev) {
host = require('./js/const').devApiHost;
}
let url = `${host}/api/update-items`;
let data;
if (this.getUserData === 'Maintainer') {
data = {
Entity: 'condensate',
EntityId: response.data.canonical_id,
ChangeOperation: 'update',
Attribute: 'name',
Value: this.condensateName,
SubmissionComments:
'Maintainer do not need to provide a reason for such change at the moment!',
Status: 'accepted',
};
} else {
if (
this.condensateNameComment === '' ||
this.condensateNameComment.length < 50
) {
this.nameCommentErr = true;
this.condensateNameCommentErrMsg =
'Reason should not be empty or less than 50 characters!';
return;
}
data = {
Entity: 'condensate',
EntityId: response.data.canonical_id,
ChangeOperation: 'update',
Attribute: 'name',
Value: this.condensateName,
SubmissionComments: this.condensateNameComment,
Status: 'requested',
};
}
this.isLoading = true;
try {
await this.axios.post(
url,
{ data: data },
{
headers: {
Authorization: `Bearer ${this.jwt}`,
},
}
);
this.isLoading = false;
this.toasterIsOpen = true;
this.nameCommentErr = false;
this.condensateNameCommentErrMsg = '';
this.condensateNameComment = '';
this.condensateName = '';
this.updatedKey += 1;
setTimeout(() => {
this.toasterIsOpen = false;
}, 2000);
} catch (e) {
console.error(e);
this.isLoading = false;
this.nameCommentErr = true;
this.condensateNameCommentErrMsg =
e.message || 'Something went wrong, please try again later!';
}
},
async updateDescription(response) {
if (this.description === '') {
this.descriptionErrorMsg = 'Description should not be empty!';
return;
} else if (this.description === response.data.description) {
this.descriptionErrorMsg =
'You have not added any description. Please modify the existing description.';
this.descriptionMsg = '';
return;
}
if (this.isDev) {
host = require('./js/const').devApiHost;
}
let url = `${host}/api/update-items`;
let data;
if (this.getUserData === 'Maintainer') {
data = {
Entity: 'condensate',
EntityId: response.data.canonical_id,
ChangeOperation: 'update',
Attribute: 'description',
Value: this.description,
SubmissionComments:
'Maintainer do not need to provide a reason for such change at the moment!',
Status: 'accepted',
};
} else {
if (
this.descriptionComment === '' ||
this.descriptionComment.length < 50
) {
this.descriptionCommentErr = true;
this.commentErrorMsg =
'Reason should not be empty or less than 50 characters!';
return;
}
data = {
Entity: 'condensate',
EntityId: response.data.canonical_id,
ChangeOperation: 'update',
Attribute: 'description',
Value: this.description,
SubmissionComments: this.descriptionComment,
Status: 'requested',
};
}
this.isLoading = true;
try {
await this.axios.post(
url,
{ data: data },
{
headers: {
Authorization: `Bearer ${this.jwt}`,
},
}
);
this.isLoading = false;
this.toasterIsOpen = true;
this.descriptionCommentErr = false;
this.descriptionComment = '';
this.descriptionErrorMsg = '';
this.description = response.data.description;
this.commentErrorMsg = '';
this.comment = '';
this.isCommentError = false;
this.updatedKey += 1;
setTimeout(() => {
this.toasterIsOpen = false;
}, 2000);
} catch (e) {
console.error(e);
this.descriptionMsg = '';
this.descriptionErrorMsg =
e.message || 'Something went wrong, please try again later!';
}
},
async addProtein(response) {
if (this.uniprotId === '') {
this.uniprotIdErrorMsg = 'Uniprot ID should not be empty!';
this.isUniProtIdError = true;
return;
} else if (this.uniprotId.length < 6) {
this.uniprotIdErrorMsg = 'Uniprot ID should be minimum of 6 character.';
this.isUniProtIdError = true;
return;
} else if (this.uniprotId.length > 10) {
this.uniprotIdErrorMsg =
'Uniprot ID should be maximum of 10 character.';
this.isUniProtIdError = true;
return;
} else if (this.whitespaceRegex.test(this.uniprotId)) {
this.uniprotIdErrorMsg = 'Uniprot ID should not have space in between.';
this.isUniProtIdError = true;
return;
}
const findUniprotId = response.data.proteins.find(
(u) => u.uniprot_id === this.uniprotId
);
if (findUniprotId) {
this.message = '';
this.uniprotIdErrorMsg = 'The Uniprot ID already exists!';
this.isUniProtIdError = true;
return;
}
this.isError = false;
if (this.isDev) {
host = require('./js/const').devApiHost;
}
let url = `${host}/api/update-items`;
let data;
if (this.getUserData === 'Maintainer') {
data = {
Entity: 'condensate',
EntityId: response.data.canonical_id,
ChangeOperation: 'add',
Attribute: 'proteins',
Value: this.uniprotId,
SubmissionComments:
'Maintainer do not need to provide a reason for such change at the moment!',
Status: 'accepted',
};
} else {
if (this.proteinComment === '' || this.proteinComment.length < 50) {
this.proteinCommentErr = true;
this.commentErrorMsg =
'Reason should not be empty or less than 50 characters!';
return;
}
data = {
Entity: 'condensate',
EntityId: response.data.canonical_id,
ChangeOperation: 'add',
Attribute: 'proteins',
Value: this.uniprotId,
SubmissionComments: this.proteinComment,
Status: 'requested',
};
}
this.isLoading = true;
try {
await this.axios.post(
url,
{ data: data },
{
headers: {
Authorization: `Bearer ${this.jwt}`,
},
}
);
this.isLoading = false;
this.toasterIsOpen = true;
this.error = false;
this.isSubmitted = true;
this.uniprotId = '';
this.comment = '';
this.proteinCommentErr = false;
this.commentErrorMsg = '';
this.updatedKey += 1;
setTimeout(() => {
this.toasterIsOpen = false;
}, 2000);
} catch (e) {
console.error(e);
this.message =
e.message || 'Something went wrong, please try again later!';
this.isSubmitted = true;
this.error = true;
}
// try {
// const res=await this.axios.get(
// `${host}
// /api/update-item/findCondensate/${response.data.canonical_id}`,
// {
// headers: {
// Authorization: `Bearer ${this.jwt}`,
// },
// }
// );
// console.log(await res)
// } catch (e) {
// console.error(e);
// }
},
// async getRequest() {
// if (this.isDev) {
// host = require("./js/const").devApiHost;
// }
// let url = `${host}/api/update-items`;
// try {
// const response = await this.axios.get(
// url,
// {
// headers: {
// Authorization: `Bearer ${this.jwt}`,
// },
// }
// );
// return response.data.data;
// } catch (e) {
// console.error(e);
// this.message =
// e.message || "Something went wrong, please try again later!";
// this.isSubmitted = true;
// this.error = true;
// }
// },
// async getSumittedRequest() {
// const requestData = await this.getRequest();
// console.log("get req", requestData);
// },
getProteinLinks(uniprots) {
if (uniprots)
return uniprots
.map(
(a) =>
`<a href='/protein/${a}' class="link" target='_blank'>${a}</a>`
)
.join(', ');
else return '';
},
getDbNames(names) {
return _.map(names, (i) => this.dbNames[i]).join(', ');
},
getTitleAuthors(title, data) {
return `${title}\n\n${_.map(data, (a) => a.name).join(', ')}`;
},
tokenize(input, token) {
return input.replaceAll(token, '<br/>');
},
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style>
@import url("~@/assets/bootstrap.css");
@import url("~@/assets/datatable.css");
@import url("~@/assets/tooltip.css");
/* .star-custom-text {
font-size: 1.5em;
align-items: center;
padding-left: 10px;
padding-right: 10px;
} */
.main {
/*margin-left: 200px;*/
margin-left: 20px;
}
h3 {
margin: 40px 0 0;
}
#wrapper {
overflow-x: hidden;
}
.checked {
color: orange;
}
.uniprot-link {
font-weight: bold;
color: #ef0087 !important;
}
#sidebar-wrapper {
min-height: 100vh;
margin-left: -15rem;
-webkit-transition: margin 0.25s ease-out;
-moz-transition: margin 0.25s ease-out;
-o-transition: margin 0.25s ease-out;
transition: margin 0.25s ease-out;
position: absolute;
z-index: 1; /* Stay on top */
left: 0;
}
#sidebar-wrapper .sidebar-heading {
padding: 0.875rem 1.25rem;
font-size: 1.2rem;
}
#sidebar-wrapper .list-group {
position: -webkit-sticky;
position: sticky;
top: 0;
width: 15rem;
}
#wrapper.toggled #sidebar-wrapper {
margin-left: 0;
}
@media (min-width: 768px) {
#sidebar-wrapper {
margin-left: 0;
}
#wrapper.toggled #sidebar-wrapper {
margin-left: -15rem;
}
}
.d-flex {
display: -ms-flexbox !important;
display: flex !important;
}
.panel {
font-size: 1.2rem;
}
.table-dark {
color: #fff;
background-color: #212529;
}
</style>