From 1984aeb78e66acb610b9bd5d8a27adbb1c36f7d4 Mon Sep 17 00:00:00 2001 From: raghosh <raghosh@loaner-laptop-13.local> Date: Fri, 18 Mar 2022 17:58:48 +0100 Subject: [PATCH] #52: Edit button added next to condensate name to change the name. Added species tax id beside species. Condensate ID is removed. confidence_score for a condensate pending. --- web/src/components/CondensateDetailPage.vue | 392 +++++++++++++++----- web/src/components/js/const.js | 12 +- 2 files changed, 299 insertions(+), 105 deletions(-) diff --git a/web/src/components/CondensateDetailPage.vue b/web/src/components/CondensateDetailPage.vue index 7595e0e..38f4368 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,22 +9,13 @@ /> <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> - - <div - id="wrapper" - class="d-flex" - > + + <div id="wrapper" class="d-flex"> <!-- Sidebar --> <!--<div class="bg-light border-right" id="sidebar-wrapper">--> <!--<!–<div class="sidebar-heading">Menu </div>–>--> @@ -41,16 +29,10 @@ <!--</div>--> <!-- /#sidebar-wrapper --> - <div - id="page-content-wrapper" - class="main" - > + <div id="page-content-wrapper" class="main"> <fetch-condensate :condensate="condensate"> <template slot-scope="{ response, loading }"> - <slot - :response="response" - :loading="loading" - > + <slot :response="response" :loading="loading"> <div v-if="loading || response === null"> <base-spinner /> </div> @@ -58,39 +40,169 @@ <base-spinner></base-spinner> </div> --> <div v-else> - <h2>{{ response.data.name }}</h2> - <h4 class="round"> - General Information - </h4> + <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 class="panel panel-default" v-if="changeName"> + <div class="panel-body"> + <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" + >Name</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=" + bg-green-500 + text-xl + font-bold + rounded-lg + px-5 + py-4 + text-white + " + > + Save + </button> + <button + @click="toggleChangeName" + class=" + bg-red-500 + text-xl + font-bold + rounded-lg + px-5 + py-4 + text-white + " + > + Cancel + </button> + </div> + </div> + </div> + </div> + </form> + </div> + </div> + <h4 class="round">General Information</h4> <div class="panel panel-default"> <div class="panel-body"> <div class="container-fluid col-md-12"> - <div class="row"> + <!-- <div class="row"> <div class="text col-sm-3"> Canonical ID </div> <div class="col-sm-9"> {{ response.data.canonical_id }} </div> - </div> + </div> --> <div class="row"> - <div class="text col-sm-3"> - Species - </div> + <div class="text col-sm-3">Species</div> <div class="col-sm-9"> - {{ response.data.species_name }} + {{ response.data.species_name }} ({{ + response.data.species_tax_id + }}) </div> </div> <div class="row"> - <div class="text col-sm-3"> - Description - </div> + <div class="text col-sm-3">Description</div> <div class="col-sm-9"> {{ response.data.description }} <button v-if=" getUserData !== null && - (getUserData === 'Maintainer' || + (getUserData === 'Maintainer' || getUserData === 'Contributor') " class="btn btn-primary btn-link" @@ -120,7 +232,8 @@ <label class="control-label col-sm-2" for="keyword" - >Update description</label> + >Update description</label + > <div class="col-sm-10"> <textarea id="comment" @@ -161,12 +274,13 @@ <label class="control-label col-sm-2" for="funComment" - >Reason</label> + >Reason</label + > <div class="col-sm-10"> <textarea id="funComment" - v-model.trim="comment" + v-model.trim="descriptionComment" class=" form-control block @@ -195,7 +309,7 @@ @keyup="commentKeyup" /> <p - v-if="isCommentError" + v-if="descriptionCommentErr" class="text-red-600 font-bold" > {{ commentErrorMsg }} @@ -238,23 +352,18 @@ <!--<span v-for="(item, index) in getRating(response.data.data_sources)" :class="item" v-bind:key="index"/>--> <!--</div>--> <!--</div>--> - <div - v-show="response.data.synonyms" - class="row" - > - <div class="text col-sm-3"> - Also Known As - </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(", ") + .map((a) => + a + .replace("-", " ") + .replace(/\b\w/g, (l) => l.toUpperCase()) + ) + .join(", ") : "" }} </div> @@ -281,7 +390,7 @@ <button v-if=" getUserData !== null && - (getUserData === 'Maintainer' || + (getUserData === 'Maintainer' || getUserData === 'Contributor') " class="btn btn-primary btn-link" @@ -302,9 +411,7 @@ </div> <div class="row"> - <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> @@ -314,9 +421,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> @@ -347,10 +452,7 @@ <td> <fetch-pub-med :link="item.publication_link"> <template slot-scope="{ response, loading }"> - <slot - :response="response" - :loading="loading" - > + <slot :response="response" :loading="loading"> <div v-if="loading" /> <div v-else> <a @@ -402,14 +504,12 @@ </div> </div> - <h4 class="round"> - Proteins - </h4> + <h4 class="round">Proteins</h4> <button v-if=" getUserData !== null && - (getUserData === 'Maintainer' || + (getUserData === 'Maintainer' || getUserData === 'Contributor') " class="btn btn-primary dropdown-toggle" @@ -418,10 +518,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"> @@ -433,10 +530,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"> <input id="keyword" @@ -445,7 +541,7 @@ type="text" placeholder="Uniprot ID" @keyup="uniprotKeyup" - > + /> <p v-if="isUniProtIdError" class="text-red-600 mt-4 font-bold" @@ -455,14 +551,13 @@ </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" - v-model.trim="comment" + v-model.trim="proteinComment" class=" form-control block @@ -488,10 +583,10 @@ ? 'Optional.' : 'Mandatory.' " - @keyup="commentKeyup" + @keyup="validateProteinComment" /> <p - v-if="isCommentError" + v-if="proteinCommentErr" class="text-red-600 font-bold" > {{ commentErrorMsg }} @@ -550,15 +645,12 @@ </template> </fetch-user-specific-update-items> --> <div v-if="getUserData"> - <h4 class="round"> - Requests - </h4> + <h4 class="round">Requests</h4> <condensate-update-items-table id="condensateUpdateItem" :data="response.data.canonical_id" /> </div> - <!-- <request-update-item-table id="protein-table" @@ -652,8 +744,14 @@ export default { showAddProtein: false, uniprotId: "", comment: "", + proteinComment: "", + condensateNameComment: "", + condensateNameCommentErrMsg: "", + markerComment: "", + descriptionComment: "", description: "", descriptionMsg: "", + condensateName: "", descriptionErrorMsg: "", isUniProtIdError: false, isCommentError: false, @@ -662,12 +760,18 @@ export default { 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, }; }, computed: { @@ -682,6 +786,9 @@ export default { }, methods: { + validateName() { + (this.nameErrMsg = ""), (this.nameError = false); + }, showDialog() { this.toasterIsOpen = true; }, @@ -694,6 +801,10 @@ export default { cancel() { this.toggleModel = false; }, + toggleChangeName() { + this.changeName = !this.changeName; + this.condensateName = ""; + }, closeAddDeleteMarker() { this.comment = ""; this.showAddDeleteMarker = false; @@ -704,6 +815,7 @@ export default { }, commentKeyup() { this.message = ""; + this.descriptionCommentErr = false; this.isCommentError = false; }, descriptionKeyup() { @@ -714,9 +826,84 @@ export default { this.description = res; this.descriptionMsg = ""; this.descriptionErrorMsg = ""; - this.comment = ""; + 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 = ""; + console.log("name", this.condensateName); + 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.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 = ""; + } catch (e) { + console.error(e); + this.nameCommentErr = true; + this.condensateNameCommentErrMsg = + e.message || "Something went wrong, please try again later!"; + } + }, async updateDescription(response) { if (this.description === "") { @@ -746,8 +933,11 @@ export default { Status: "accepted", }; } else { - if (this.comment === "" || this.comment.length < 50) { - this.isCommentError = true; + if ( + this.descriptionComment === "" || + this.descriptionComment.length < 50 + ) { + this.descriptionCommentErr = true; this.commentErrorMsg = "Reason should not be empty or less than 50 characters!"; return; @@ -758,7 +948,7 @@ export default { ChangeOperation: "update", Attribute: "description", Value: this.description, - SubmissionComments: this.comment, + SubmissionComments: this.descriptionComment, Status: "requested", }; } @@ -775,7 +965,8 @@ export default { ); this.isLoading = false; this.toasterIsOpen = true; - + this.descriptionCommentErr = false; + this.descriptionComment = ""; this.descriptionErrorMsg = ""; this.description = response.data.description; this.commentErrorMsg = ""; @@ -836,10 +1027,11 @@ export default { Status: "accepted", }; } else { - if (this.comment === "" || this.comment.length < 50) { + if (this.proteinComment === "" || this.proteinComment.length < 50) { + this.proteinCommentErr = true; this.commentErrorMsg = "Reason should not be empty or less than 50 characters!"; - this.isCommentError = true; + return; } data = { @@ -848,7 +1040,7 @@ export default { ChangeOperation: "add", Attribute: "proteins", Value: this.uniprotId, - SubmissionComments: this.comment, + SubmissionComments: this.proteinComment, Status: "requested", }; } @@ -871,6 +1063,8 @@ export default { this.isSubmitted = true; this.uniprotId = ""; this.comment = ""; + this.proteinCommentErr = false; + this.commentErrorMsg = ""; } catch (e) { console.error(e); this.message = diff --git a/web/src/components/js/const.js b/web/src/components/js/const.js index 68137d1..0f3c239 100644 --- a/web/src/components/js/const.js +++ b/web/src/components/js/const.js @@ -1,12 +1,12 @@ export const host = '/api'; -export const devHost = '/api'; -export const apiHost = '/cms'; -export const devApiHost = '/cms'; +// export const devHost = '/api'; +// export const apiHost = '/cms'; +// export const devApiHost = '/cms'; -// export const devHost = 'https://dev.ddcode.org/api'; +export const devHost = 'https://dev.ddcode.org/api'; // export const devHost = 'http://localhost:5001'; -// export const apiHost = 'http://localhost:1337'; -// export const devApiHost = 'http://localhost:1337'; +export const apiHost = 'http://localhost:1337'; +export const devApiHost = 'http://localhost:1337'; // apikey should be give here: export const apikey = process.env.VUE_APP_API_KEY; -- GitLab