diff --git a/web/src/components/AddNovelCondensate.vue b/web/src/components/AddNovelCondensate.vue index b8705eab734b116f40d163d16cae42fb9f1feaf1..2c1fc8bf89bee562ac127c51c65d1fc3ae4116ea 100644 --- a/web/src/components/AddNovelCondensate.vue +++ b/web/src/components/AddNovelCondensate.vue @@ -1,10 +1,7 @@ <template> <div class="flex flex-wrap bg-white"> <div class="w-5/6"> - <form - autocomplete="off" - @submit.prevent="addCondensate()" - > + <form autocomplete="off" @submit.prevent="addCondensate()"> <div v-if="isLoading"> <base-spinner /> </div> @@ -19,10 +16,9 @@ gap-y-4 " > - <label - class="text-right" - for="condensate_is_experimental" - >Synthetic/Biomolecular</label> + <label class="text-right" for="condensate_is_experimental" + >Synthetic/Biomolecular</label + > <div class="col-span-2"> <input id="condensate_is_experimental_true" @@ -30,28 +26,25 @@ type="radio" name="condensate_is_experimental" value="true" + /> + <label for="condensate_is_experimental_true" class="ml-2 mr-3" + >Synthetic</label > - <label - for="condensate_is_experimental_true" - class="ml-2 mr-3" - >Synthetic</label> <input id="condensate_is_experimental_false" v-model="condensate.is_experimental" type="radio" name="condensate_is_experimental" value="false" + /> + <label for="condensate_is_experimental_false" class="ml-2 mr-3" + >Biomolecular</label > - <label - for="condensate_is_experimental_false" - class="ml-2 mr-3" - >Biomolecular</label> </div> - <label - class="text-right" - for="condensate_name" - >Condensate Name</label> + <label class="text-right" for="condensate_name" + >Condensate Name</label + > <div class="col-span-2"> <input id="condensate_name" @@ -70,7 +63,7 @@ " type="text" placeholder="Name" - > + /> <p v-if="condensate.errors.name" @@ -80,28 +73,19 @@ </p> </div> - <label - class="text-right" - for="condensate_protein" - >Proteins</label> + <label class="text-right" for="condensate_protein">Proteins</label> <div class="col-span-2"> <tags-input v-model="proteinNameList" class="w-1/3 w-full" @proteinNotFound="notFound" /> - <p - v-if="searchProtein.errors" - class="text-red-500 font-bold" - > + <p v-if="searchProtein.errors" class="text-red-500 font-bold"> {{ searchProtein.message }} </p> </div> - <label - class="text-right" - for="protein_table" - /> + <label class="text-right" for="protein_table" /> <div class="col-span-2 relative sm:rounded-lg"> <table class="w-full text-sm text-left text-gray-500 dark:text-gray-400" @@ -115,40 +99,12 @@ " > <tr> - <th - scope="col" - class="px-6 py-3" - > - Uniprot - </th> - <th - scope="col" - class="px-6 py-3" - > - Functional type - </th> - <th - scope="col" - class="px-6 py-3" - > - Pubmed - </th> - <th - scope="col" - class="px-6 py-3" - > - Driver criterion - </th> - <th - scope="col" - class="px-6 py-3" - > - Experimental evidences - </th> - <th - scope="col" - class="px-6 py-3" - > + <th scope="col" class="px-6 py-3">Uniprot</th> + <th scope="col" class="px-6 py-3">Functional type</th> + <th scope="col" class="px-6 py-3">Pubmed</th> + <th scope="col" class="px-6 py-3">Driver criterion</th> + <th scope="col" class="px-6 py-3">Experimental evidences</th> + <th scope="col" class="px-6 py-3"> <span class="sr-only">Edit</span> </th> </tr> @@ -198,17 +154,15 @@ hover:underline " @click="editProtein(item)" - >Edit</a> + >Edit</a + > </td> </tr> </tbody> </table> </div> - <div - v-if="showAddNewProtein" - id="deleteModal" - > + <div v-if="showAddNewProtein" id="deleteModal"> <div class="fixed z-40 h-full inset-0 opacity-25 bg-black" /> <div class=" @@ -307,7 +261,8 @@ newProtein.uniprot_id === "" ? "new protein" : newProtein.uniprot_id - }}</b>. + }}</b + >. </h2> <form @@ -316,17 +271,15 @@ @submit.prevent="addUniprot" > <div class="form-group"> - <label - class="control-label col-sm-3" - for="uniprot_id" - >Uniprot ID * + <label class="control-label col-sm-3" for="uniprot_id" + >Uniprot ID * <a class="uniprot-link tooltipped tooltipped-e" - aria-label="The UniProt ID (accession) is the 6 to the 10-character-long name displayed on the heading of the protein page from Uniprot. + aria-label='The UniProt ID (accession) is the 6 to the 10-character-long name displayed on the heading of the protein page from Uniprot. It is a unique identifier for a protein from the whole Uniprot database (https://www.uniprot.org/help/accession_numbers). Please note that different proteins from the same gene will also have different Uniprot IDs. - For example, The Uniprot ID of "FUS Human" is P35637 (https://www.uniprot.org/uniprot/P35637). - It is usually the last part of the URI of the HTTPS link of the protein page." + For example, The Uniprot ID of "FUS Human" is P35637 (https://www.uniprot.org/uniprot/P35637). + It is usually the last part of the URI of the HTTPS link of the protein page.' > <span class="fa fa-info-circle" /> </a> @@ -349,7 +302,7 @@ " type="text" placeholder="Uniprot ID" - > + /> <p v-if="newProtein.errors.uniprot_id" @@ -363,7 +316,8 @@ <label class="control-label col-sm-3" for="functional_type" - >Functional Type</label> + >Functional Type</label + > <div class="col-sm-8"> <select id="functional_type" @@ -382,18 +336,10 @@ hover:border-blue-700 " > - <option value=""> - Select Functional Type - </option> - <option value="client"> - client - </option> - <option value="driver"> - driver - </option> - <option value="regulator"> - regulator - </option> + <option value="">Select Functional Type</option> + <option value="client">client</option> + <option value="driver">driver</option> + <option value="regulator">regulator</option> </select> <p @@ -405,10 +351,9 @@ </div> </div> <div class="form-group"> - <label - class="control-label col-sm-3" - for="pubmed_ids" - >PubMed IDs *</label> + <label class="control-label col-sm-3" for="pubmed_ids" + >PubMed IDs *</label + > <div class="col-sm-8"> <input id="pubmed_ids" @@ -426,7 +371,7 @@ " type="text" placeholder="PubMed IDs (separated by comma)" - > + /> <p v-if="newProtein.errors.pubmed_ids" @@ -440,39 +385,35 @@ <label class="control-label col-sm-3" for="driver_criterion" - >Driver Criterion</label> + >Driver Criterion</label + > <div class="col-sm-8"> <input id="self_ps" v-model="newProtein.driver_criterion" type="checkbox" value="self_ps" - > - <label - for="self_ps" - class="px-2" - >Self-PS</label> + /> + <label for="self_ps" class="px-2">Self-PS</label> <input id="induces_assembly" v-model="newProtein.driver_criterion" type="checkbox" value="induces_assembly" + /> + <label for="induces_assembly" class="px-2" + >Induces Assembly</label > - <label - for="induces_assembly" - class="px-2" - >Induces Assembly</label> - <br> + <br /> <input id="essential_for_integrity" v-model="newProtein.driver_criterion" type="checkbox" value="essential_for_integrity" + /> + <label for="essential_for_integrity" class="px-2" + >Essential For Integrity</label > - <label - for="essential_for_integrity" - class="px-2" - >Essential For Integrity</label> </div> <p v-if="newProtein.errors.driver_criterion" @@ -485,81 +426,67 @@ <label class="control-label col-sm-3" for="experimental_evidences" - >Experimental Evidences</label> + >Experimental Evidences</label + > <div class="col-sm-6"> <input id="in_vitro" v-model="newProtein.experimental_evidences" type="checkbox" value="in_vitro" - > - <label - for="in_vitro" - class="px-2" - >In Vitro</label> + /> + <label for="in_vitro" class="px-2">In Vitro</label> <input id="in_vivo" v-model="newProtein.experimental_evidences" type="checkbox" value="in_vivo" - > - <label - for="in_vivo" - class="px-2" - >In Vivo</label> - <br> + /> + <label for="in_vivo" class="px-2">In Vivo</label> + <br /> <input id="in_cellulo" v-model="newProtein.experimental_evidences" type="checkbox" value="in_cellulo" + /> + <label for="in_cellulo" class="px-2" + >In Cellulo</label > - <label - for="in_cellulo" - class="px-2" - >In Cellulo</label> - <br> + <br /> <input id="mass_spectrometry" v-model="newProtein.experimental_evidences" type="checkbox" value="mass_spectrometry" + /> + <label for="mass_spectrometry" class="px-2" + >Mass Spectrometry</label > - <label - for="mass_spectrometry" - class="px-2" - >Mass Spectrometry</label> - <br> + <br /> <input id="colocalization" v-model="newProtein.experimental_evidences" type="checkbox" value="colocalization" + /> + <label for="colocalization" class="px-2" + >Colocalization</label > - <label - for="colocalization" - class="px-2" - >Colocalization</label> <input id="frap" v-model="newProtein.experimental_evidences" type="checkbox" value="frap" - > - <label - for="frap" - class="px-2" - >FRAP</label> + /> + <label for="frap" class="px-2">FRAP</label> <input id="others" v-model="newProtein.experimental_evidences" type="checkbox" value="others" - > - <label - for="others" - class="px-2" - >Others</label> + /> + <label for="others" class="px-2">Others</label> </div> <p v-if="newProtein.errors.experimental_evidences" @@ -617,10 +544,7 @@ </div> </div> - <label - class="text-right" - for="condensate_synonyms" - >Synonyms</label> + <label class="text-right" for="condensate_synonyms">Synonyms</label> <div class="col-span-2"> <input id="condensate_synonyms" @@ -639,7 +563,7 @@ " type="text" placeholder="Synonyms (comma-separated)" - > + /> <p v-if="condensate.errors.synonyms" @@ -649,10 +573,9 @@ </p> </div> - <label - class="text-right" - for="condensate_description" - >Description</label> + <label class="text-right" for="condensate_description" + >Description</label + > <div class="col-span-2"> <input id="condensate_description" @@ -671,13 +594,11 @@ " type="text" placeholder="Description" - > + /> </div> - <label - class="text-right" - for="condensate_comments" - >Comments <span v-show="getUserData !== 'Maintainer'">*</span> + <label class="text-right" for="condensate_comments" + >Comments <span v-show="getUserData !== 'Maintainer'">*</span> </label> <div class="col-span-2"> <textarea @@ -745,10 +666,7 @@ </div> <div> - <h3 - v-if="fetchError" - class="text-red-500" - > + <h3 v-if="fetchError" class="text-red-500"> {{ fetchError }} </h3> </div> @@ -760,13 +678,13 @@ <script> // require modules /* eslint-disable no-unused-vars */ -import TagsInput from '@/components/TagsInput.vue'; -import BaseSpinner from './UI/BaseSpinner.vue'; -import { apikey } from '@/components/js/const'; -const _ = require('lodash'); +import TagsInput from "@/components/TagsInput.vue"; +import BaseSpinner from "./UI/BaseSpinner.vue"; +import { apikey } from "@/components/js/const"; +const _ = require("lodash"); export default { - name: 'AddNovelCondensate', + name: "AddNovelCondensate", components: { TagsInput, BaseSpinner, @@ -777,12 +695,12 @@ export default { showAddNewProtein: false, searchProtein: { errors: false, - message: '', + message: "", }, newProtein: { - uniprot_id: '', - functional_type: '', - pubmed_ids: '', + uniprot_id: "", + functional_type: "", + pubmed_ids: "", driver_criterion: [], experimental_evidences: [], errors: { @@ -792,35 +710,35 @@ export default { driver_criterion: false, experimental_evidences: false, }, - errorMsg: '', + errorMsg: "", }, condensate: { - name: '', + name: "", is_experimental: false, proteins: [], - synonyms: '', - comments: '', - description: '', + synonyms: "", + comments: "", + description: "", errors: { name: false, species: false, synonyms: false, comments: false, }, - errorMsg: '', + errorMsg: "", }, isLoading: false, - proteinList: this.$store.getters['Param/proteinList'], - fetchError: '', - isDev: process.env.NODE_ENV === 'development', + proteinList: this.$store.getters["Param/proteinList"], + fetchError: "", + isDev: process.env.NODE_ENV === "development", }; }, computed: { jwt: function () { - return this.$store.getters['User/jwt']; + return this.$store.getters["User/jwt"]; }, getUserData() { - const userRole = this.$store.getters['User/userRole']; + const userRole = this.$store.getters["User/userRole"]; // console.log('role is', userRole); return userRole; }, @@ -834,7 +752,7 @@ export default { const idx = this.proteinList.findIndex( (d) => d.uniprot_id === obj.tag.text ); - this.$store.dispatch('Param/removeProtein', idx); + this.$store.dispatch("Param/removeProtein", idx); obj.deleteTag(); // console.log(this.$store.getters['Param/proteinList']) }, @@ -843,7 +761,7 @@ export default { mounted: function () { const vm = this; // vm.proteinNameList.push(vm.protein); - vm.$store.dispatch('Param/resetProteins'); + vm.$store.dispatch("Param/resetProteins"); }, methods: { editProtein(protein) { @@ -855,7 +773,7 @@ export default { this.newProtein.driver_criterion.length ); protein.driver_criterion - .split(',') + .split(",") .forEach((c) => this.newProtein.driver_criterion.push(c)); this.newProtein.experimental_evidences.splice( @@ -863,40 +781,40 @@ export default { this.newProtein.experimental_evidences.length ); protein.experimental_evidences - .split(',') + .split(",") .forEach((c) => this.newProtein.experimental_evidences.push(c)); - this.newProtein.errorMsg = ''; + this.newProtein.errorMsg = ""; this.showAddNewProtein = true; }, notFound(val, isEmpty) { if (!val && !isEmpty) { this.searchProtein.errors = true; this.searchProtein.message = - 'Protein not found. Try adding new protein.'; + "Protein not found. Try adding new protein."; } else { this.searchProtein.errors = false; - this.searchProtein.message = ''; + this.searchProtein.message = ""; } }, close() { - this.condensate.name = ''; + this.condensate.name = ""; this.condensate.is_experimental = false; - this.condensate.species = ''; + this.condensate.species = ""; this.condensate.proteins = []; - this.condensate.synonyms = ''; - this.condensate.comments = ''; - this.condensate.description = ''; - this.condensate.errorMsg = ''; - this.$router.push('/'); + this.condensate.synonyms = ""; + this.condensate.comments = ""; + this.condensate.description = ""; + this.condensate.errorMsg = ""; + this.$router.push("/"); }, async addUniprot() { const vm = this; - + console.log("adding uniprot"); Object.keys(vm.newProtein.errors).forEach( (v) => (vm.newProtein.errors[v] = false) ); - console.log('uniprot is', this.newProtein.uniprot_id); + console.log("uniprot is", this.newProtein.uniprot_id); const validUniprot = await this.uniprotIdValidation( this.newProtein.uniprot_id ); @@ -907,8 +825,8 @@ export default { return; } - if (vm.newProtein.pubmed_ids === '') { - vm.newProtein.errorMsg = 'Pubmed IDs should not be empty!'; + if (vm.newProtein.pubmed_ids === "") { + vm.newProtein.errorMsg = "Pubmed IDs should not be empty!"; vm.newProtein.errors.pubmed_ids = true; return; } @@ -916,14 +834,14 @@ export default { const idx = vm.proteinList.findIndex( (d) => d.uniprot_id === vm.newProtein.uniprot_id ); - vm.$store.dispatch('Param/removeProtein', idx); + vm.$store.dispatch("Param/removeProtein", idx); - vm.$store.dispatch('Param/addProtein', { + vm.$store.dispatch("Param/addProtein", { uniprot_id: vm.newProtein.uniprot_id, functional_type: vm.newProtein.functional_type, pubmed_ids: vm.newProtein.pubmed_ids, - driver_criterion: vm.newProtein.driver_criterion.join(','), - experimental_evidences: vm.newProtein.experimental_evidences.join(','), + driver_criterion: vm.newProtein.driver_criterion.join(","), + experimental_evidences: vm.newProtein.experimental_evidences.join(","), }); vm.newProtein.driver_criterion.splice( @@ -934,8 +852,8 @@ export default { 0, vm.newProtein.experimental_evidences.length ); - vm.newProtein.pubmed_ids = ''; - vm.newProtein.functional_type = ''; + vm.newProtein.pubmed_ids = ""; + vm.newProtein.functional_type = ""; vm.showAddNewProtein = false; }, @@ -953,23 +871,24 @@ export default { 0, vm.newProtein.experimental_evidences.length ); - vm.newProtein.pubmed_ids = ''; - vm.newProtein.functional_type = ''; + vm.newProtein.pubmed_ids = ""; + vm.newProtein.functional_type = ""; vm.showAddNewProtein = false; }, async uniprotIdValidation(id) { + console.log("validation hitting"); try { - const res = await fetch(`https://www.uniprot.org/uniprot/${id}`, { - method: 'HEAD', + const res = await fetch(`https://rest.uniprot.org/uniprotkb/${id}`, { + method: "HEAD", }); const response = await res; - if (!response.ok && response.status === 404) { + if (!response.ok && response.status === 400) { return { valid: false, msg: `No protein record was found at Uniprot with the given ID. Please check the URL <a class='text-blue-500 hover:text-blue-700' href='https://www.uniprot.org/uniprot/' target='_blank'> https://www.uniprot.org/uniprot/ </a>`, }; - } else if (!response.ok) { + } else if (!response.ok && response.status === 500) { return { valid: false, msg: `Not able to validate at the moment. Please check the URL <a class='text-blue-500 hover:text-blue-700' href='https://www.uniprot.org/uniprot/' target='_blank'> https://www.uniprot.org/uniprot/ </a>. Please contact CD-CODE admin <a @@ -978,15 +897,15 @@ export default { >mail@cd-code.org</a> for further assist. `, }; } else { - return { valid: true, msg: 'Valid Uniprot ID.' }; + return { valid: true, msg: "Valid Uniprot ID." }; } } catch (err) { - console.log('error', err); + console.log("error", err); return { valid: false, msg: err.message + - '.' + + "." + `Please contact CD-CODE admin <a href="mailto:mail@cd-code.org" class="text-blue-500 hover:text-blue-700" @@ -999,41 +918,41 @@ export default { const vm = this; let host = vm.isDev - ? require('./js/const').devHost - : require('./js/const').host; + ? require("./js/const").devHost + : require("./js/const").host; Object.keys(vm.newProtein.errors).forEach( (v) => (vm.newProtein.errors[v] = false) ); - if (vm.newProtein.uniprot_id === '') { - vm.newProtein.errorMsg = 'Uniprot ID should not be empty!'; + if (vm.newProtein.uniprot_id === "") { + vm.newProtein.errorMsg = "Uniprot ID should not be empty!"; vm.newProtein.errors.uniprot_id = true; return; } else if (vm.newProtein.uniprot_id.length < 6) { - vm.newProtein.errorMsg = 'Uniprot ID should be minimum of 6 character.'; + vm.newProtein.errorMsg = "Uniprot ID should be minimum of 6 character."; vm.newProtein.errors.uniprot_id = true; return; } else if (vm.newProtein.uniprot_id.length > 10) { vm.newProtein.errorMsg = - 'Uniprot ID should be maximum of 10 character.'; + "Uniprot ID should be maximum of 10 character."; vm.newProtein.errors.uniprot_id = true; return; } else if (/(\s)/.test(vm.newProtein.uniprot_id)) { - vm.newProtein.errorMsg = 'Uniprot ID should not have space in between.'; + vm.newProtein.errorMsg = "Uniprot ID should not have space in between."; vm.newProtein.errors.uniprot_id = true; return; } else { let host = vm.isDev - ? require('./js/const').devHost - : require('./js/const').host; + ? require("./js/const").devHost + : require("./js/const").host; let url = `${host}/proteins?fields=uniprot_id,gene_name,name&query=${vm.newProtein.uniprot_id}`; const ret = await fetch(url, { - method: 'GET', - mode: 'cors', - cache: 'no-cache', + method: "GET", + mode: "cors", + cache: "no-cache", headers: { Authorization: `Bearer ${apikey}`, }, @@ -1041,14 +960,14 @@ export default { if (ret.count !== 0) { vm.newProtein.errorMsg = - 'Uniprot ID already exists in the database. Add the tag!'; + "Uniprot ID already exists in the database. Add the tag!"; vm.newProtein.errors.uniprot_id = true; return; } } - if (vm.newProtein.pubmed_ids === '') { - vm.newProtein.errorMsg = 'Pubmed IDs should not be empty!'; + if (vm.newProtein.pubmed_ids === "") { + vm.newProtein.errorMsg = "Pubmed IDs should not be empty!"; vm.newProtein.errors.pubmed_ids = true; return; } @@ -1065,7 +984,7 @@ export default { // return; // } - vm.$store.dispatch('Param/addProtein', { + vm.$store.dispatch("Param/addProtein", { uniprot_id: vm.newProtein.uniprot_id, functional_type: vm.newProtein.functional_type, proteins: vm.newProtein.proteins, @@ -1077,7 +996,7 @@ export default { vm.newProtein.uniprot_id = vm.newProtein.functional_type = vm.newProtein.pubmed_ids = - ''; + ""; vm.newProtein.driver_criterion = []; vm.newProtein.experimental_evidences = []; vm.showAddNewProtein = false; @@ -1089,32 +1008,32 @@ export default { (v) => (vm.condensate.errors[v] = false) ); - if (vm.condensate.name === '') { - vm.condensate.errorMsg = 'Condensate name should not be empty!'; + if (vm.condensate.name === "") { + vm.condensate.errorMsg = "Condensate name should not be empty!"; vm.condensate.errors.name = true; return; } else if (vm.proteinList.length === 0) { vm.searchProtein.errors = true; - vm.searchProtein.message = 'Proteins field should not be empty.'; + vm.searchProtein.message = "Proteins field should not be empty."; return; } let host = vm.isDev - ? require('./js/const').devApiHost - : require('./js/const').apiHost; + ? require("./js/const").devApiHost + : require("./js/const").apiHost; let url = `${host}/api/novel-condensates`; let data; - if (this.getUserData === 'Maintainer') { + if (this.getUserData === "Maintainer") { data = { Name: vm.condensate.name, IsExperimental: vm.condensate.is_experimental, Proteins: vm.proteinList, Synonyms: vm.condensate.synonyms, Description: vm.condensate.description, - Status: 'accepted', + Status: "accepted", SubmissionComments: - 'Maintainer do not need to provide a reason for such change at the moment!', + "Maintainer do not need to provide a reason for such change at the moment!", }; } else { data = { @@ -1123,7 +1042,7 @@ export default { Proteins: vm.proteinList, Synonyms: vm.condensate.synonyms, Description: vm.condensate.description, - Status: 'requested', + Status: "requested", SubmissionComments: vm.condensate.comments, }; } @@ -1147,18 +1066,18 @@ export default { vm.condensate.synonyms = vm.condensate.comments = vm.condensate.description = - ''; - vm.$store.dispatch('Param/resetProteins'); - vm.$emit('showToaster', 'Condensate added successfully!'); + ""; + vm.$store.dispatch("Param/resetProteins"); + vm.$emit("showToaster", "Condensate added successfully!"); setTimeout(() => { - vm.$emit('hideToaster'); + vm.$emit("hideToaster"); }, 2000); } catch (e) { console.error(e); vm.isLoading = false; vm.fetchError = - e.message || 'Something went wrong, please try again later!'; + e.message || "Something went wrong, please try again later!"; vm.isSubmitted = true; vm.error = true; } diff --git a/web/src/components/CondensateDetailPage.vue b/web/src/components/CondensateDetailPage.vue index a896f762a354f76b7d54bbcd898f294b3aa978d8..dc63ec6da8f7934dcbd915a3dab9c59e58bb14bf 100644 --- a/web/src/components/CondensateDetailPage.vue +++ b/web/src/components/CondensateDetailPage.vue @@ -1,9 +1,6 @@ <template> <div> - <base-toaster - :open="toasterIsOpen" - @close="hideDialog" - > + <base-toaster :open="toasterIsOpen" @close="hideDialog"> <div class="flex justify-between items-center"> <font-awesome-icon class="ml-3" @@ -12,14 +9,8 @@ /> <h4>Request submitted successfully!</h4> - <button - class="btn btn-outline" - @click="hideDialog" - > - <font-awesome-icon - icon="fa-regular fa-circle-xmark" - size="2x" - /> + <button class="btn btn-outline" @click="hideDialog"> + <font-awesome-icon icon="fa-regular fa-circle-xmark" size="2x" /> </button> </div> </base-toaster> @@ -50,10 +41,7 @@ <base-spinner /> </div> <div> - <h2 - v-if="fetchError" - class="text-red-500" - > + <h2 v-if="fetchError" class="text-red-500"> {{ fetchError }} </h2> </div> @@ -67,7 +55,7 @@ <button v-if=" getUserData !== null && - (getUserData === 'Maintainer' || + (getUserData === 'Maintainer' || getUserData === 'Contributor') " class="rounded-lg px-5 py-4 text-center" @@ -99,7 +87,8 @@ <label for="condensateName" class="control-label col-sm-2" - >Name</label> + >Name</label + > <div class="col-sm-10"> <div class="w-1/4"> <input @@ -109,7 +98,7 @@ type="text" placeholder="Enter condensate name." @keyup="validateName" - > + /> <p v-if="nameError && nameErrMsg" class="text-red-500 mt-2 text-2xl font-bold" @@ -124,7 +113,8 @@ <label for="condensateName" class="control-label col-sm-2" - >Reason</label> + >Reason</label + > <div class="col-sm-10"> <div class="w-3/4"> <textarea @@ -207,9 +197,7 @@ </div> </form> </div> - <h4 class="round"> - General Information - </h4> + <h4 class="round">General Information</h4> <div class=" bg-white @@ -229,9 +217,7 @@ </div> </div> --> <div class="row"> - <div class="text col-sm-3 text-2xl"> - Species - </div> + <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 @@ -239,15 +225,13 @@ </div> </div> <div class="row text-2xl"> - <div class="text col-sm-3"> - Description - </div> + <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 === 'Maintainer' || getUserData === 'Contributor') " class="btn btn-primary btn-link" @@ -277,7 +261,8 @@ <label class="control-label col-sm-2" for="keyword" - >Update description</label> + >Update description</label + > <div class="col-sm-10"> <textarea id="comment" @@ -318,7 +303,8 @@ <label class="control-label col-sm-2" for="funComment" - >Reason</label> + >Reason</label + > <div class="col-sm-10"> <textarea @@ -453,7 +439,7 @@ <button v-if=" getUserData !== null && - (getUserData === 'Maintainer' || + (getUserData === 'Maintainer' || getUserData === 'Contributor') " class="btn btn-primary btn-link" @@ -475,17 +461,13 @@ </div> <div class="row text-2xl"> - <div class="text col-sm-3"> - No. of Proteins - </div> + <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="text col-sm-3 text-2xl">Evidence star</div> <div class="flex col-sm-9"> <star-rating :star-size="20" @@ -505,9 +487,7 @@ </div> <div v-show="response.data.experiments.length > 0"> - <h4 class="round"> - Experiments - </h4> + <h4 class="round">Experiments</h4> <div class="panel panel-default"> <table class="csi table table-hover table-responsive"> <thead> @@ -603,8 +583,8 @@ <button v-if=" getUserData !== null && - !response.data.is_experimental && - (getUserData === 'Maintainer' || + !response.data.is_experimental && + (getUserData === 'Maintainer' || getUserData === 'Contributor') " class=" @@ -625,10 +605,7 @@ > Add a protein to this condensate </button> - <div - v-if="showAddProtein" - class="panel panel-default mt-4" - > + <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"> @@ -640,10 +617,9 @@ @submit.prevent="addProtein(response)" > <div class="form-group"> - <label - class="control-label col-sm-2" - for="species" - >Add protein with uniprot ID</label> + <label class="control-label col-sm-2" for="species" + >Add protein with uniprot ID</label + > <div class="col-sm-4 text-2xl"> <div class="flex"> <input @@ -653,7 +629,7 @@ type="text" placeholder="Uniprot ID. (e.g. P35637)" @keyup="uniprotKeyup" - > + /> <a class=" @@ -676,10 +652,9 @@ </div> </div> <div class="form-group"> - <label - class="control-label col-sm-2" - for="keyword" - >Reason</label> + <label class="control-label col-sm-2" for="keyword" + >Reason</label + > <div class="col-sm-8"> <textarea id="comment" @@ -825,9 +800,7 @@ /> </div> <div class="my-14 border border-gray-300 rounded-lg p-8"> - <h4 class="round mb-8"> - Top Contributors - </h4> + <h4 class="round mb-8">Top Contributors</h4> <contributor-list-table :id="response.data.canonical_id" entity="condensate" @@ -885,26 +858,26 @@ </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 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'); +const _ = require("lodash"); +require("./js/clipboard"); -let host = require('./js/const').apiHost; +let host = require("./js/const").apiHost; export default { - name: 'CondensateDetailPage', + name: "CondensateDetailPage", components: { fetchCondensate, llpsTable, @@ -919,39 +892,39 @@ export default { // RequestUpdateItemTable, }, - props: ['condensateId'], + 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', + dbNames: require("./js/const").db, + isDev: process.env.NODE_ENV === "development", showAddProtein: false, - uniprotId: '', - comment: '', - proteinComment: '', - condensateNameComment: '', - condensateNameCommentErrMsg: '', - markerComment: '', - descriptionComment: '', - description: '', - descriptionMsg: '', - condensateName: '', - descriptionErrorMsg: '', + uniprotId: "", + comment: "", + proteinComment: "", + condensateNameComment: "", + condensateNameCommentErrMsg: "", + markerComment: "", + descriptionComment: "", + description: "", + descriptionMsg: "", + condensateName: "", + descriptionErrorMsg: "", isUniProtIdError: false, isCommentError: false, isSubmitted: false, error: false, showUpdateDescription: false, showAddDeleteMarker: false, - commentErrorMsg: '', + commentErrorMsg: "", descriptionCommentErr: false, nameCommentErr: false, proteinCommentErr: false, markerCommentErr: false, - uniprotIdErrorMsg: '', - message: '', + uniprotIdErrorMsg: "", + message: "", whitespaceRegex: /(\s)/, nameError: false, toggleModel: false, @@ -963,10 +936,10 @@ export default { }, computed: { jwt: function () { - return this.$store.getters['User/jwt']; + return this.$store.getters["User/jwt"]; }, getUserData() { - const userRole = this.$store.getters['User/userRole']; + const userRole = this.$store.getters["User/userRole"]; return userRole; }, @@ -974,7 +947,7 @@ export default { methods: { validateName() { - (this.nameErrMsg = ''), (this.nameError = false); + (this.nameErrMsg = ""), (this.nameError = false); }, showDialog() { this.toasterIsOpen = true; @@ -990,83 +963,83 @@ export default { }, toggleChangeName() { this.changeName = !this.changeName; - this.condensateName = ''; + this.condensateName = ""; }, closeAddDeleteMarker() { - this.comment = ''; + this.comment = ""; this.showAddDeleteMarker = false; }, uniprotKeyup() { - this.message = ''; + this.message = ""; this.isUniProtIdError = false; }, commentKeyup() { - this.message = ''; + this.message = ""; this.descriptionCommentErr = false; this.isCommentError = false; }, descriptionKeyup() { - this.descriptionMsg = ''; - this.descriptionErrorMsg = ''; + this.descriptionMsg = ""; + this.descriptionErrorMsg = ""; }, toggleUpdateDescription(res) { this.description = res; - this.descriptionMsg = ''; - this.descriptionErrorMsg = ''; + this.descriptionMsg = ""; + this.descriptionErrorMsg = ""; this.descriptionCommentErr = false; - this.descriptionComment = ''; + this.descriptionComment = ""; this.showUpdateDescription = !this.showUpdateDescription; }, validateProteinComment() { this.proteinCommentErr = false; - this.commentErrorMsg = ''; + this.commentErrorMsg = ""; }, async changeCondensateName(response) { if (!this.condensateName) { this.nameError = true; - this.nameErrMsg = 'Enter a condensate name.'; + this.nameErrMsg = "Enter a condensate name."; return; } this.nameError = false; - this.nameErrMsg = ''; + this.nameErrMsg = ""; if (this.isDev) { - host = require('./js/const').devApiHost; + host = require("./js/const").devApiHost; } let url = `${host}/api/update-items`; let data; - if (this.getUserData === 'Maintainer') { + if (this.getUserData === "Maintainer") { data = { - Entity: 'condensate', + Entity: "condensate", EntityId: response.data.canonical_id, - ChangeOperation: 'update', - Attribute: 'name', + ChangeOperation: "update", + Attribute: "name", Value: this.condensateName, SubmissionComments: this.condensateNameComment ? this.condensateNameComment - : 'Maintainer do not need to provide a reason for such change at the moment!', - Status: 'accepted', + : "Maintainer do not need to provide a reason for such change at the moment!", + Status: "accepted", }; } else { if ( - this.condensateNameComment === '' || + this.condensateNameComment === "" || this.condensateNameComment.length < 50 ) { this.nameCommentErr = true; this.condensateNameCommentErrMsg = - 'Reason should not be empty or less than 50 characters!'; + "Reason should not be empty or less than 50 characters!"; return; } data = { - Entity: 'condensate', + Entity: "condensate", EntityId: response.data.canonical_id, - ChangeOperation: 'update', - Attribute: 'name', + ChangeOperation: "update", + Attribute: "name", Value: this.condensateName, SubmissionComments: this.condensateNameComment, - Status: 'requested', + Status: "requested", }; } this.isLoading = true; @@ -1083,9 +1056,9 @@ export default { this.isLoading = false; this.toasterIsOpen = true; this.nameCommentErr = false; - this.condensateNameCommentErrMsg = ''; - this.condensateNameComment = ''; - this.condensateName = ''; + this.condensateNameCommentErrMsg = ""; + this.condensateNameComment = ""; + this.condensateName = ""; this.updatedKey += 1; setTimeout(() => { this.toasterIsOpen = false; @@ -1095,56 +1068,56 @@ export default { this.isLoading = false; this.nameCommentErr = true; this.condensateNameCommentErrMsg = - e.message || 'Something went wrong, please try again later!'; + e.message || "Something went wrong, please try again later!"; } }, async updateDescription(response) { - if (this.description === '') { - this.descriptionErrorMsg = 'Description should not be empty!'; + 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 = ''; + "You have not added any description. Please modify the existing description."; + this.descriptionMsg = ""; return; } if (this.isDev) { - host = require('./js/const').devApiHost; + host = require("./js/const").devApiHost; } let url = `${host}/api/update-items`; let data; - if (this.getUserData === 'Maintainer') { + if (this.getUserData === "Maintainer") { data = { - Entity: 'condensate', + Entity: "condensate", EntityId: response.data.canonical_id, - ChangeOperation: 'update', - Attribute: 'description', + ChangeOperation: "update", + Attribute: "description", Value: this.description, SubmissionComments: this.descriptionComment ? this.descriptionComment - : 'Maintainer do not need to provide a reason for such change at the moment!', - Status: 'accepted', + : "Maintainer do not need to provide a reason for such change at the moment!", + Status: "accepted", }; } else { if ( - this.descriptionComment === '' || + this.descriptionComment === "" || this.descriptionComment.length < 50 ) { this.descriptionCommentErr = true; this.commentErrorMsg = - 'Reason should not be empty or less than 50 characters!'; + "Reason should not be empty or less than 50 characters!"; return; } data = { - Entity: 'condensate', + Entity: "condensate", EntityId: response.data.canonical_id, - ChangeOperation: 'update', - Attribute: 'description', + ChangeOperation: "update", + Attribute: "description", Value: this.description, SubmissionComments: this.descriptionComment, - Status: 'requested', + Status: "requested", }; } this.isLoading = true; @@ -1161,11 +1134,11 @@ export default { this.isLoading = false; this.toasterIsOpen = true; this.descriptionCommentErr = false; - this.descriptionComment = ''; - this.descriptionErrorMsg = ''; + this.descriptionComment = ""; + this.descriptionErrorMsg = ""; this.description = response.data.description; - this.commentErrorMsg = ''; - this.comment = ''; + this.commentErrorMsg = ""; + this.comment = ""; this.isCommentError = false; this.updatedKey += 1; setTimeout(() => { @@ -1173,23 +1146,24 @@ export default { }, 2000); } catch (e) { console.error(e); - this.descriptionMsg = ''; + this.descriptionMsg = ""; this.descriptionErrorMsg = - e.message || 'Something went wrong, please try again later!'; + e.message || "Something went wrong, please try again later!"; } }, async uniprotIdValidation(id) { try { - const res = await fetch(`https://www.uniprot.org/uniprot/${id}`, { - method: 'HEAD', + const res = await fetch(`https://rest.uniprot.org/uniprotkb/${id}`, { + method: "HEAD", }); const response = await res; - if (!response.ok && response.status === 404) { + + if (!response.ok && response.status === 400) { return { valid: false, msg: `No protein record was found at Uniprot with the given ID. Please check the URL <a class='text-blue-500 hover:text-blue-700' href='https://www.uniprot.org/uniprot/' target='_blank'> https://www.uniprot.org/uniprot/ </a>`, }; - } else if (!response.ok) { + } else if (!response.ok && response.status === 500) { return { valid: false, msg: `Not able to validate at the moment. Please check the URL <a class='text-blue-500 hover:text-blue-700' href='https://www.uniprot.org/uniprot/' target='_blank'> https://www.uniprot.org/uniprot/ </a>. Please contact CD-CODE admin <a @@ -1198,15 +1172,15 @@ export default { >mail@cd-code.org</a> for further assist. `, }; } else { - return { valid: true, msg: 'Valid Uniprot ID.' }; + return { valid: true, msg: "Valid Uniprot ID." }; } } catch (err) { - console.log('error', err); + console.log("error", err); return { valid: false, msg: err.message + - '.' + + "." + `Please contact CD-CODE admin <a href="mailto:mail@cd-code.org" class="text-blue-500 hover:text-blue-700" @@ -1215,21 +1189,21 @@ export default { } }, async addProtein(response) { - if (this.uniprotId === '') { - this.uniprotIdErrorMsg = 'Uniprot ID should not be empty!'; + 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.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.'; + "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.uniprotIdErrorMsg = "Uniprot ID should not have space in between."; this.isUniProtIdError = true; return; } @@ -1237,7 +1211,7 @@ export default { const validUniprot = await this.uniprotIdValidation(this.uniprotId); if (!validUniprot.valid) { - this.message = ''; + this.message = ""; this.uniprotIdErrorMsg = validUniprot.msg; this.isUniProtIdError = true; return; @@ -1247,46 +1221,46 @@ export default { (u) => u.uniprot_id === this.uniprotId ); if (findUniprotId) { - this.message = ''; - this.uniprotIdErrorMsg = 'The Uniprot ID already exists!'; + this.message = ""; + this.uniprotIdErrorMsg = "The Uniprot ID already exists!"; this.isUniProtIdError = true; return; } this.isError = false; if (this.isDev) { - host = require('./js/const').devApiHost; + host = require("./js/const").devApiHost; } let url = `${host}/api/update-items`; let data; - if (this.getUserData === 'Maintainer') { + if (this.getUserData === "Maintainer") { data = { - Entity: 'condensate', + Entity: "condensate", EntityId: response.data.canonical_id, - ChangeOperation: 'add', - Attribute: 'proteins', + ChangeOperation: "add", + Attribute: "proteins", Value: this.uniprotId, SubmissionComments: this.proteinComment ? this.proteinComment - : 'Maintainer do not need to provide a reason for such change at the moment!', - Status: 'accepted', + : "Maintainer do not need to provide a reason for such change at the moment!", + Status: "accepted", }; } else { - if (this.proteinComment === '' || this.proteinComment.length < 50) { + if (this.proteinComment === "" || this.proteinComment.length < 50) { this.proteinCommentErr = true; this.commentErrorMsg = - 'Reason should not be empty or less than 50 characters!'; + "Reason should not be empty or less than 50 characters!"; return; } data = { - Entity: 'condensate', + Entity: "condensate", EntityId: response.data.canonical_id, - ChangeOperation: 'add', - Attribute: 'proteins', + ChangeOperation: "add", + Attribute: "proteins", Value: this.uniprotId, SubmissionComments: this.proteinComment, - Status: 'requested', + Status: "requested", }; } this.isLoading = true; @@ -1306,10 +1280,10 @@ export default { this.error = false; this.isSubmitted = true; - this.uniprotId = ''; - this.comment = ''; + this.uniprotId = ""; + this.comment = ""; this.proteinCommentErr = false; - this.commentErrorMsg = ''; + this.commentErrorMsg = ""; this.updatedKey += 1; setTimeout(() => { this.toasterIsOpen = false; @@ -1317,7 +1291,7 @@ export default { } catch (e) { console.error(e); this.message = - e.message || 'Something went wrong, please try again later!'; + e.message || "Something went wrong, please try again later!"; this.isSubmitted = true; this.error = true; } @@ -1379,17 +1353,17 @@ export default { (a) => `<a href='/protein/${a}' class="link" target='_blank'>${a}</a>` ) - .join(', '); - else return ''; + .join(", "); + else return ""; }, getDbNames(names) { - return _.map(names, (i) => this.dbNames[i]).join(', '); + return _.map(names, (i) => this.dbNames[i]).join(", "); }, getTitleAuthors(title, data) { - return `${title}\n\n${_.map(data, (a) => a.name).join(', ')}`; + return `${title}\n\n${_.map(data, (a) => a.name).join(", ")}`; }, tokenize(input, token) { - return input.replaceAll(token, '<br/>'); + return input.replaceAll(token, "<br/>"); }, }, }; diff --git a/web/src/components/TagsInput.vue b/web/src/components/TagsInput.vue index f0535da2f0c713eb2bcdbd2dd839f2f731407036..37849c83d5366727ca498c2fceabf7669519a97c 100644 --- a/web/src/components/TagsInput.vue +++ b/web/src/components/TagsInput.vue @@ -1,50 +1,49 @@ <template> <div> - <div - v-if="show" - id="deleteModal" - > + <div v-if="show" id="deleteModal"> <div class="fixed z-40 h-full inset-0 opacity-25 bg-black" /> <div class=" - fixed - overflow-x-hidden overflow-y-auto - inset-0 - flex - justify-center - items-center - z-50 - " + fixed + overflow-x-hidden overflow-y-auto + inset-0 + flex + justify-center + items-center + z-50 + " > - <div class="relative px-4 w-full max-w-3xl 2xl:max-w-5xl h-auto md:h-auto"> + <div + class="relative px-4 w-full max-w-3xl 2xl:max-w-5xl h-auto md:h-auto" + > <div class=" - relative - bg-white - p-6 - w-full - flex flex-col - rounded-lg - shadow - dark:bg-gray-700 - " + relative + bg-white + p-6 + w-full + flex flex-col + rounded-lg + shadow + dark:bg-gray-700 + " > <!-- Modal header --> <div class="flex justify-end p-2"> <button type="button" class=" - text-gray-400 - bg-transparent - hover:bg-gray-200 hover:text-gray-900 - rounded-lg - text-sm - p-1.5 - ml-auto - inline-flex - items-center - dark:hover:bg-gray-800 dark:hover:text-white - " + text-gray-400 + bg-transparent + hover:bg-gray-200 hover:text-gray-900 + rounded-lg + text-sm + p-1.5 + ml-auto + inline-flex + items-center + dark:hover:bg-gray-800 dark:hover:text-white + " @click="close" > <svg @@ -78,9 +77,14 @@ /> </svg> <h2 class="mb-5 text-2xl dark:text-gray-400 text-center"> - Please, specify <b>Functional Type</b>, <b>PubMed IDs</b>, <b>Driver Criterion</b> and <b>Experimental Evidences</b> for <b>{{ - newProtein.uniprot_id === '' ? 'new protein' : newProtein.uniprot_id - }}</b>. + Please, specify <b>Functional Type</b>, <b>PubMed IDs</b>, + <b>Driver Criterion</b> and <b>Experimental Evidences</b> for + <b>{{ + newProtein.uniprot_id === "" + ? "new protein" + : newProtein.uniprot_id + }}</b + >. </h2> <form @@ -89,17 +93,15 @@ @submit.prevent="addUniprot" > <div class="form-group"> - <label - class="control-label col-sm-3" - for="uniprot_id" - >Uniprot ID * + <label class="control-label col-sm-3" for="uniprot_id" + >Uniprot ID * <a class="uniprot-link tooltipped tooltipped-e" - aria-label="The UniProt ID (accession) is the 6 to the 10-character-long name displayed on the heading of the protein page from Uniprot. + aria-label='The UniProt ID (accession) is the 6 to the 10-character-long name displayed on the heading of the protein page from Uniprot. It is a unique identifier for a protein from the whole Uniprot database (https://www.uniprot.org/help/accession_numbers). Please note that different proteins from the same gene will also have different Uniprot IDs. - For example, The Uniprot ID of "FUS Human" is P35637 (https://www.uniprot.org/uniprot/P35637). - It is usually the last part of the URI of the HTTPS link of the protein page." + For example, The Uniprot ID of "FUS Human" is P35637 (https://www.uniprot.org/uniprot/P35637). + It is usually the last part of the URI of the HTTPS link of the protein page.' > <span class="fa fa-info-circle" /> </a> @@ -110,63 +112,53 @@ v-model.trim="newProtein.uniprot_id" :disabled="!addNewProtein" class=" - bg-white - py-3 - px-3 - w-full - rounded-lg - text-gray-700 - bg-transparent - border border-gray-500 - hover:border-gray-700 - " + bg-white + py-3 + px-3 + w-full + rounded-lg + text-gray-700 + bg-transparent + border border-gray-500 + hover:border-gray-700 + " type="text" placeholder="Uniprot ID" - > + /> <p v-if="newProtein.errors.uniprot_id" class="text-red-600 mt-4 font-bold" v-html="newProtein.errorMsg" - > - </p> + ></p> </div> </div> <div class="form-group"> - <label - class="control-label col-sm-3" - for="functional_type" - >Functional Type</label> + <label class="control-label col-sm-3" for="functional_type" + >Functional Type</label + > <div class="col-sm-8"> <select id="functional_type" v-model="newProtein.functional_type" class=" - bg-white - px-3 - py-4 - rounded-lg - border border-gray-400 - w-full - text-gray-700 - outline-none - bg-transparent - border-b - hover:border-blue-700 - " + bg-white + px-3 + py-4 + rounded-lg + border border-gray-400 + w-full + text-gray-700 + outline-none + bg-transparent + border-b + hover:border-blue-700 + " > - <option value=""> - Select Functional Type - </option> - <option value="client"> - client - </option> - <option value="driver"> - driver - </option> - <option value="regulator"> - regulator - </option> + <option value="">Select Functional Type</option> + <option value="client">client</option> + <option value="driver">driver</option> + <option value="regulator">regulator</option> </select> <p @@ -178,28 +170,27 @@ </div> </div> <div class="form-group"> - <label - class="control-label col-sm-3" - for="pubmed_ids" - >PubMed IDs *</label> + <label class="control-label col-sm-3" for="pubmed_ids" + >PubMed IDs *</label + > <div class="col-sm-8"> <input id="pubmed_ids" v-model.trim="newProtein.pubmed_ids" class=" - bg-white - py-3 - px-3 - w-full - rounded-lg - text-gray-700 - bg-transparent - border border-gray-500 - hover:border-gray-700 - " + bg-white + py-3 + px-3 + w-full + rounded-lg + text-gray-700 + bg-transparent + border border-gray-500 + hover:border-gray-700 + " type="text" placeholder="PubMed IDs (separated by comma)" - > + /> <p v-if="newProtein.errors.pubmed_ids" @@ -210,42 +201,36 @@ </div> </div> <div class="form-group"> - <label - class="control-label col-sm-3" - for="driver_criterion" - >Driver Criterion</label> + <label class="control-label col-sm-3" for="driver_criterion" + >Driver Criterion</label + > <div class="col-sm-8"> <input id="self_ps" v-model="newProtein.driver_criterion" type="checkbox" value="self_ps" - > - <label - for="self_ps" - class="px-2" - >Self-PS</label> + /> + <label for="self_ps" class="px-2">Self-PS</label> <input id="induces_assembly" v-model="newProtein.driver_criterion" type="checkbox" value="induces_assembly" + /> + <label for="induces_assembly" class="px-2" + >Induces Assembly</label > - <label - for="induces_assembly" - class="px-2" - >Induces Assembly</label> - <br> + <br /> <input id="essential_for_integrity" v-model="newProtein.driver_criterion" type="checkbox" value="essential_for_integrity" + /> + <label for="essential_for_integrity" class="px-2" + >Essential For Integrity</label > - <label - for="essential_for_integrity" - class="px-2" - >Essential For Integrity</label> </div> <p v-if="newProtein.errors.driver_criterion" @@ -258,81 +243,65 @@ <label class="control-label col-sm-3" for="experimental_evidences" - >Experimental Evidences</label> + >Experimental Evidences</label + > <div class="col-sm-6"> <input id="in_vitro" v-model="newProtein.experimental_evidences" type="checkbox" value="in_vitro" - > - <label - for="in_vitro" - class="px-2" - >In Vitro</label> + /> + <label for="in_vitro" class="px-2">In Vitro</label> <input id="in_vivo" v-model="newProtein.experimental_evidences" type="checkbox" value="in_vivo" - > - <label - for="in_vivo" - class="px-2" - >In Vivo</label> - <br> + /> + <label for="in_vivo" class="px-2">In Vivo</label> + <br /> <input id="in_cellulo" v-model="newProtein.experimental_evidences" type="checkbox" value="in_cellulo" - > - <label - for="in_cellulo" - class="px-2" - >In Cellulo</label> - <br> + /> + <label for="in_cellulo" class="px-2">In Cellulo</label> + <br /> <input id="mass_spectrometry" v-model="newProtein.experimental_evidences" type="checkbox" value="mass_spectrometry" + /> + <label for="mass_spectrometry" class="px-2" + >Mass Spectrometry</label > - <label - for="mass_spectrometry" - class="px-2" - >Mass Spectrometry</label> - <br> + <br /> <input id="colocalization" v-model="newProtein.experimental_evidences" type="checkbox" value="colocalization" + /> + <label for="colocalization" class="px-2" + >Colocalization</label > - <label - for="colocalization" - class="px-2" - >Colocalization</label> <input id="frap" v-model="newProtein.experimental_evidences" type="checkbox" value="frap" - > - <label - for="frap" - class="px-2" - >FRAP</label> + /> + <label for="frap" class="px-2">FRAP</label> <input id="others" v-model="newProtein.experimental_evidences" type="checkbox" value="others" - > - <label - for="others" - class="px-2" - >Others</label> + /> + <label for="others" class="px-2">Others</label> </div> <p v-if="newProtein.errors.experimental_evidences" @@ -391,34 +360,36 @@ </div> <vue-tags-input v-model="labelTag" - class="bg-white - w-1/3 - py-4 - px-4 - w-full - rounded-lg - text-gray-700 - bg-transparent - border border-gray-500 - hover:border-gray-700" + class=" + bg-white + w-1/3 + py-4 + px-4 + w-full + rounded-lg + text-gray-700 + bg-transparent + border border-gray-500 + hover:border-gray-700 + " placeholder="Search" :tags="value" :autocomplete-items="autocompleteItems" :add-only-from-autocomplete="true" @input="search(labelTag)" - @before-adding-tag="obj => addObj(obj)" - @before-deleting-tag="obj => removeObj(obj)" + @before-adding-tag="(obj) => addObj(obj)" + @before-deleting-tag="(obj) => removeObj(obj)" /> </div> </template> <script> -import VueTagsInput from '@johmun/vue-tags-input'; -import _ from 'lodash'; -const apikey = require('./js/const').apikey; +import VueTagsInput from "@johmun/vue-tags-input"; +import _ from "lodash"; +const apikey = require("./js/const").apikey; export default { - name: 'TagsInput', + name: "TagsInput", components: { VueTagsInput, }, @@ -428,9 +399,9 @@ export default { data() { return { newProtein: { - uniprot_id: '', - functional_type: '', - pubmed_ids: '', + uniprot_id: "", + functional_type: "", + pubmed_ids: "", driver_criterion: [], experimental_evidences: [], errors: { @@ -440,21 +411,19 @@ export default { driver_criterion: false, experimental_evidences: false, }, - errorMsg: '', + errorMsg: "", }, addNewProtein: false, foundProtein: false, isEmpty: false, show: false, - uniprotId: '', - labelTag: '', + uniprotId: "", + labelTag: "", autocompleteItems: [], - isDev: process.env.NODE_ENV === 'development', + isDev: process.env.NODE_ENV === "development", }; }, - computed: { - - }, + computed: {}, // watch: { // labelTag: function (newVal, oldVal) { // const vm = this; @@ -480,25 +449,30 @@ export default { return; } - if (vm.newProtein.pubmed_ids === '') { - vm.newProtein.errorMsg = 'Pubmed IDs should not be empty!'; + if (vm.newProtein.pubmed_ids === "") { + vm.newProtein.errorMsg = "Pubmed IDs should not be empty!"; vm.newProtein.errors.pubmed_ids = true; return; } - vm.$store.dispatch('Param/addProtein', { + vm.$store.dispatch("Param/addProtein", { uniprot_id: vm.newProtein.uniprot_id, functional_type: vm.newProtein.functional_type, pubmed_ids: vm.newProtein.pubmed_ids, - driver_criterion: vm.newProtein.driver_criterion.join(','), - experimental_evidences: vm.newProtein.experimental_evidences.join(','), + driver_criterion: vm.newProtein.driver_criterion.join(","), + experimental_evidences: vm.newProtein.experimental_evidences.join(","), }); - vm.newProtein.driver_criterion.splice(0, vm.newProtein.driver_criterion.length); - vm.newProtein.experimental_evidences.splice(0, vm.newProtein.experimental_evidences.length); - vm.newProtein.pubmed_ids = ''; - vm.newProtein.functional_type = ''; - + vm.newProtein.driver_criterion.splice( + 0, + vm.newProtein.driver_criterion.length + ); + vm.newProtein.experimental_evidences.splice( + 0, + vm.newProtein.experimental_evidences.length + ); + vm.newProtein.pubmed_ids = ""; + vm.newProtein.functional_type = ""; vm.show = false; }, @@ -508,86 +482,101 @@ export default { (v) => (vm.newProtein.errors[v] = false) ); - vm.newProtein.driver_criterion.splice(0, vm.newProtein.driver_criterion.length); - vm.newProtein.experimental_evidences.splice(0, vm.newProtein.experimental_evidences.length); - vm.newProtein.pubmed_ids = ''; - vm.newProtein.functional_type = ''; + vm.newProtein.driver_criterion.splice( + 0, + vm.newProtein.driver_criterion.length + ); + vm.newProtein.experimental_evidences.splice( + 0, + vm.newProtein.experimental_evidences.length + ); + vm.newProtein.pubmed_ids = ""; + vm.newProtein.functional_type = ""; this.show = false; }, addObj(obj) { const vm = this; vm.newProtein.uniprot_id = obj.tag.uniprot_id; - if (obj.tag.name === 'new_protein') { + if (obj.tag.name === "new_protein") { vm.newProtein.uniprot_id = vm.labelTag; vm.addNewProtein = true; vm.show = true; - vm.labelTag = ''; - vm.searchProtein = false + vm.labelTag = ""; + vm.searchProtein = false; } else if (vm.newProtein.uniprot_id) { vm.addNewProtein = false; vm.show = true; - vm.labelTag = ''; + vm.labelTag = ""; vm.searchProtein = false; } // this.show = true; // vm.labelTag = ''; }, removeObj(obj) { - this.$emit('input', obj); + this.$emit("input", obj); }, search(query) { - const vm = this - + const vm = this; let host = vm.isDev - ? require('./js/const').devHost - : require('./js/const').host; + ? require("./js/const").devHost + : require("./js/const").host; let url = `${host}/proteins?fields=uniprot_id,gene_name,name&query=${query}&size=10`; fetch(url, { - method: 'GET', - mode: 'cors', - cache: 'no-cache', + method: "GET", + mode: "cors", + cache: "no-cache", headers: { Authorization: `Bearer ${apikey}`, }, }) .then((response) => response.json()) .then((json) => { - vm.autocompleteItems = []; if (json.count > 0) { - vm.autocompleteItems = _.uniq(_.map(json.data, (c) => { - return { 'text': c.uniprot_id, 'name': c.name, 'gene_name': c.gene_name, 'uniprot_id': c.uniprot_id } - }), 'text') + vm.autocompleteItems = _.uniq( + _.map(json.data, (c) => { + return { + text: c.uniprot_id, + name: c.name, + gene_name: c.gene_name, + uniprot_id: c.uniprot_id, + }; + }), + "text" + ); this.foundProtein = true; - } else { this.foundProtein = false; } - vm.autocompleteItems.push({'text': 'Add new protein', 'name': 'new_protein', 'uniprot_id': 'new_protein'}) - if (query === '') { + vm.autocompleteItems.push({ + text: "Add new protein", + name: "new_protein", + uniprot_id: "new_protein", + }); + if (query === "") { this.isEmpty = true; } - + // this.$emit('proteinNotFound', this.foundProtein, this.isEmpty) - }) + }); }, async uniprotIdValidation(id) { try { - const res = await fetch(`https://www.uniprot.org/uniprot/${id}`, { - method: 'HEAD', + const res = await fetch(`https://rest.uniprot.org/uniprotkb/${id}`, { + method: "HEAD", }); const response = await res; - if (!response.ok && response.status === 404) { + if (!response.ok && response.status === 400) { return { valid: false, msg: `No protein record was found at Uniprot with the given ID. Please check the URL <a class='text-blue-500 hover:text-blue-700' href='https://www.uniprot.org/uniprot/' target='_blank'> https://www.uniprot.org/uniprot/ </a>`, }; - } else if (!response.ok) { + } else if (!response.ok && response.status === 500) { return { valid: false, msg: `Not able to validate at the moment. Please check the URL <a class='text-blue-500 hover:text-blue-700' href='https://www.uniprot.org/uniprot/' target='_blank'> https://www.uniprot.org/uniprot/ </a>. Please contact CD-CODE admin <a @@ -596,15 +585,15 @@ export default { >mail@cd-code.org</a> for further assist. `, }; } else { - return { valid: true, msg: 'Valid Uniprot ID.' }; + return { valid: true, msg: "Valid Uniprot ID." }; } } catch (err) { - console.log('error', err); + console.log("error", err); return { valid: false, msg: err.message + - '.' + + "." + `Please contact CD-CODE admin <a href="mailto:mail@cd-code.org" class="text-blue-500 hover:text-blue-700" @@ -621,7 +610,6 @@ export default { border: none; /* border-bottom: 1px solid #a4b1b6; */ /* padding: .7rem; */ - } .ti-new-tag-input-wrapper[data-v-61d92e31] { @@ -629,7 +617,7 @@ export default { flex: 1 0 auto; padding: 0px; margin: 2px; - font-size: .85em; + font-size: 0.85em; } .ti-new-tag-input-wrapper input[data-v-61d92e31] { diff --git a/web/src/views/ForgotPassword.vue b/web/src/views/ForgotPassword.vue index b92226d1a6ea122d1fcda33a07ba7fecd608701a..cb470967087317266116373465ba2226ebf34bd1 100644 --- a/web/src/views/ForgotPassword.vue +++ b/web/src/views/ForgotPassword.vue @@ -1,9 +1,6 @@ <template> <div> - <base-toaster - :open="toasterIsOpen" - @close="hideDialog" - > + <base-toaster :open="toasterIsOpen" @close="hideDialog"> <div class="flex justify-between space-x-4 items-center"> <font-awesome-icon class="ml-3" @@ -12,14 +9,8 @@ /> <h4>Password reset link has been sent to {{ email.val }}.</h4> - <button - class="btn btn-outline" - @click="hideDialog" - > - <font-awesome-icon - icon="fa-regular fa-circle-xmark" - size="2x" - /> + <button class="btn btn-outline" @click="hideDialog"> + <font-awesome-icon icon="fa-regular fa-circle-xmark" size="2x" /> </button> </div> </base-toaster> @@ -89,17 +80,11 @@ " placeholder="Enter email address." @blur="clearValidity('email')" - > - <p - v-if="!email.isValid" - class="text-red-500 mt-2" - > + /> + <p v-if="!email.isValid" class="text-red-500 mt-2"> Email must not be empty. </p> - <p - v-show="error" - class="mt-2 text-red-500" - > + <p v-show="error" class="mt-2 text-red-500"> {{ errorMsg }} </p> </div> @@ -126,27 +111,27 @@ </div> </template> <script> -import BaseSpinner from '../components/UI/BaseSpinner.vue'; -import BaseToaster from '../components/UI/BaseToaster.vue'; -let host = require('@/components/js/const').apiHost; +import BaseSpinner from "../components/UI/BaseSpinner.vue"; +import BaseToaster from "../components/UI/BaseToaster.vue"; +let host = require("@/components/js/const").apiHost; export default { - name: 'ForgotPassword', + name: "ForgotPassword", components: { BaseSpinner, BaseToaster }, data() { return { email: { - val: '', + val: "", isValid: true, }, formIsValid: true, done: false, error: false, - isDev: process.env.NODE_ENV === 'development', + isDev: process.env.NODE_ENV === "development", isLoading: false, toasterIsOpen: false, - errorMsg: '', + errorMsg: "", }; }, methods: { @@ -155,14 +140,14 @@ export default { }, hideDialog() { this.toasterIsOpen = false; - this.$router.push('login'); + this.$router.push("login"); }, clearValidity(input) { this[input].isValid = true; }, validateForm() { this.formIsValid = true; - if (this.email.val === '') { + if (this.email.val === "") { this.email.isValid = false; this.formIsValid = false; } @@ -178,7 +163,7 @@ export default { } if (vm.isDev) { - host = require('@/components/js/const').devApiHost; + host = require("@/components/js/const").devApiHost; } this.isLoading = true; this.done = false; @@ -188,24 +173,18 @@ export default { // }) try { const res = await fetch(`${host}/api/auth/forgot-password`, { - method: 'POST', - mode: 'cors', // no-cors, *cors, same-origin - cache: 'no-cache', // *default, no-cache, reload, force-cache, + method: "POST", + mode: "cors", // no-cors, *cors, same-origin + cache: "no-cache", // *default, no-cache, reload, force-cache, headers: { - 'Content-Type': 'application/json', + "Content-Type": "application/json", // 'Content-Type': 'application/x-www-form-urlencoded', }, body: JSON.stringify({ email: this.email.val, }), }); - if (!res.ok) { - this.isLoading = false; - this.error = true; - this.errorMsg = `${res.status} Internal Error, please write a mail to CDCode Admin`; - return; - } if (!res.ok && res.status === 500) { this.isLoading = false; this.error = true; @@ -222,15 +201,10 @@ export default { } const response = await res.json(); - if ( - !res.ok && - response.error.status === 400 && - response.error.message === 'This email does not exist' - ) { + if (!res.ok && response.error.status === 400) { this.isLoading = false; this.error = true; - this.errorMsg = - 'Provided email address is not yet registered with any existing account (User has not signed up yet)'; + this.errorMsg = response.error.message; return; } diff --git a/web/src/views/Login.vue b/web/src/views/Login.vue index 49ffa6be6ce3b454518a117ecb9f7830cf245151..99b8bf99a97260421937c08c22454f59ddca6764 100644 --- a/web/src/views/Login.vue +++ b/web/src/views/Login.vue @@ -29,10 +29,7 @@ </h1> <form @submit="login"> - <div - class="my-4" - :class="{ invalid: !email.isValid }" - > + <div class="my-4" :class="{ invalid: !email.isValid }"> <h1 class=" text-left @@ -61,18 +58,12 @@ " placeholder="Enter email." @blur="clearValidity('email')" - > - <p - v-if="!email.isValid" - class="text-red-500" - > + /> + <p v-if="!email.isValid" class="text-red-500"> Email must not be empty. </p> </div> - <div - class="my-4" - :class="{ invalid: !password.isValid }" - > + <div class="my-4" :class="{ invalid: !password.isValid }"> <h1 class=" text-left @@ -102,18 +93,12 @@ " placeholder="Enter password." @blur="clearValidity('password')" - > - <p - v-if="!password.isValid" - class="text-red-500" - > + /> + <p v-if="!password.isValid" class="text-red-500"> Password must not be empty. </p> </div> - <p - v-show="error" - class="text-red-500" - > + <p v-show="error" class="text-red-500"> {{ errorMsg }} </p> <button @@ -155,37 +140,37 @@ </div> </template> <script> -let host = require('@/components/js/const').apiHost; +let host = require("@/components/js/const").apiHost; export default { - name: 'Login', + name: "Login", data() { return { email: { - val: '', + val: "", isValid: true, }, password: { - val: '', + val: "", isValid: true, }, formIsValid: true, error: false, errorMsg: ``, - isDev: process.env.NODE_ENV === 'development', + isDev: process.env.NODE_ENV === "development", isLoading: false, }; }, computed: { userData: function () { - return this.$store.getters['User/userData']; + return this.$store.getters["User/userData"]; }, }, mounted: function () { const vm = this; if (vm.userData !== null) { - this.$router.push('/profile'); + this.$router.push("/profile"); } }, methods: { @@ -194,11 +179,11 @@ export default { }, validateForm() { this.formIsValid = true; - if (this.email.val === '') { + if (this.email.val === "") { this.email.isValid = false; this.formIsValid = false; } - if (this.password.val === '') { + if (this.password.val === "") { this.password.isValid = false; this.formIsValid = false; } @@ -212,17 +197,17 @@ export default { return; } if (vm.isDev) { - host = require('@/components/js/const').devApiHost; + host = require("@/components/js/const").devApiHost; } - console.log('url is', host); + console.log("url is", host); this.isLoading = true; try { const res = await fetch(`${host}/api/auth/local`, { - method: 'POST', - mode: 'cors', // no-cors, *cors, same-origin - cache: 'no-cache', // *default, no-cache, reload, force-cache, + method: "POST", + mode: "cors", // no-cors, *cors, same-origin + cache: "no-cache", // *default, no-cache, reload, force-cache, headers: { - 'Content-Type': 'application/json', + "Content-Type": "application/json", // 'Content-Type': 'application/x-www-form-urlencoded', }, body: JSON.stringify({ @@ -231,14 +216,6 @@ export default { }), }); - if (!res.ok) { - this.isLoading = false; - this.error = true; - this.errorMsg = `${res.status} Internal Error, please write a mail to CDCode Admin`; - - return; - } - if (!res.ok && res.status === 500) { this.isLoading = false; this.error = true; @@ -253,32 +230,27 @@ export default { return; } - const response = await res.json(); - if ( - !res.ok && - response.error.status === 400 && - response.error.message === 'Invalid identifier or password' - ) { + if (!res.ok && response.error.status === 400) { this.isLoading = false; this.error = true; - this.errorMsg = 'Email Address & Password mismatch.'; - this.password.val = ''; + this.errorMsg = response.error.message; + this.password.val = ""; return; } const { jwt, user } = response; - window.localStorage.setItem('jwt', jwt); - window.localStorage.setItem('userData', JSON.stringify(user)); + window.localStorage.setItem("jwt", jwt); + window.localStorage.setItem("userData", JSON.stringify(user)); - this.$store.dispatch('User/setJwt', jwt); - this.$store.dispatch('User/setUserData', JSON.stringify(user)); + this.$store.dispatch("User/setJwt", jwt); + this.$store.dispatch("User/setUserData", JSON.stringify(user)); this.isLoading = false; this.error = false; - this.$router.push('/profile'); + this.$router.push("/profile"); } catch (err) { - console.log('catch error', err); + console.log("catch error", err); this.isLoading = false; this.error = true; this.errorMsg = `${err.message} Internal Error, please write a mail to CDCode Admin`;