<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 id="wrapper" class="d-flex"> <!-- 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 id="page-content-wrapper" class="main"> <fetch-condensate :condensate="condensate"> <template slot-scope="{ response, loading }"> <slot :response="response" :loading="loading"> <div v-if="loading || response === null"> <base-spinner /> </div> <!-- <div v-if="loading"> <base-spinner></base-spinner> </div> --> <div v-else> <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" >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-600 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 @click="toggleChangeName" 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 " > 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="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">Species</div> <div class="col-sm-9"> {{ response.data.species_name }} ({{ response.data.species_tax_id }}) </div> </div> <div class="row"> <div class="text col-sm-3">Description</div> <div class="col-sm-9"> {{ 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-600 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"> <div class="text col-sm-3"> 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" @close="closeAddDeleteMarker" /> </div> </div> <div class="row"> <div class="text col-sm-3">No. of Proteins</div> <div class="col-sm-9"> {{ response.data.protein_count }} </div> </div> <div class="row"> <div class="text col-sm-3">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" ></star-rating> </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, loading }"> <slot :response="response" :loading="loading"> <div v-if="loading" /> <div v-else> <a :href="item.publication_link" class=" uniprot-link tooltipped tooltipped-n tooltipped-multiline " :aria-label=" getTitleAuthors( response.title, response.authors ) " target="_blank" > PubMed <i class="glyphicon glyphicon-link" /> </a> </div> </slot> </template> </fetch-pub-med> </td> <td v-html="tokenize(item.solute_concentrations, ';')" /> <td> {{ item.temperature }} </td> <td> <ul v-for="(item, index) in item.salts" :key="index" > <li v-for="(value, key, index) in item" :key="index" > {{ key }} : {{ value }} </li> </ul> </td> </tr> </tbody> </table> </div> </div> <h4 class="round">Proteins</h4> <button v-if=" getUserData !== null && (getUserData === 'Maintainer' || getUserData === 'Contributor') " class=" text-white bg-blue-600 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-600 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" /> <!-- <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"> <h4 class="round">Requests</h4> <condensate-update-items-table id="condensateUpdateItem" :data="response.data.canonical_id" /> </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 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, // 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, }; }, 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 = ""; 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: "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 = ""; } 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 === "") { 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; } 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 emplty!"; 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 = ""; } 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}' 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; } a { color: #42b983; } #wrapper { overflow-x: hidden; } .checked { color: orange; } #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; } #page-content-wrapper { min-width: 100vw; } #wrapper.toggled #sidebar-wrapper { margin-left: 0; } @media (min-width: 768px) { #sidebar-wrapper { margin-left: 0; } #page-content-wrapper { min-width: 0; width: 100%; } #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>