diff --git a/.gitignore b/.gitignore index 3b2e468f4e2380a2888c83b0079b1e30f59caffa..8654348add0e5008ff0712aeb828d5ce358a9f71 100644 --- a/.gitignore +++ b/.gitignore @@ -67,6 +67,7 @@ typings/ # dotenv environment variables file .env .env.test +.env.* *venv # parcel-bundler cache (https://parceljs.org/) diff --git a/web/src/App.vue b/web/src/App.vue index 34a6276cda6090cba75c92ca31c8108933a8a10e..f9d903c4c79ba5543b4296a6318677c020ffbe7d 100644 --- a/web/src/App.vue +++ b/web/src/App.vue @@ -54,6 +54,7 @@ export default { </script> <style> +@import url("~@/assets/tooltip.css"); #app { font-family: neue-haas-grotesk-text, sans-serif, neue-haas-grotesk-text, sans-serif; diff --git a/web/src/assets/tooltip.css b/web/src/assets/tooltip.css index 0c570035c6fea0530400f7b40807e8d7c53e03d8..5c68fc57043b57d7dc13f626a88567ad36830a3a 100644 --- a/web/src/assets/tooltip.css +++ b/web/src/assets/tooltip.css @@ -7,7 +7,7 @@ z-index: 1000000; display: none; padding: .5em .75em; - font: normal normal 11px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + font: normal normal 15px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; -webkit-font-smoothing: subpixel-antialiased; color: #fff; text-align: justify; diff --git a/web/src/components/AboutPage.vue b/web/src/components/AboutPage.vue index 5a0d20b6f12116a48f2e72ba4d45315ca5765dbf..99a0901b0fd66f6f8e7ffde81c282b4aed9e63a6 100644 --- a/web/src/components/AboutPage.vue +++ b/web/src/components/AboutPage.vue @@ -1,9 +1,9 @@ <template> <div id="page-content-wrapper" - class="flex flex-wrap justify-center mb-14 text-justify" + class="flex flex-wrap justify-center mt-8 mb-14 text-justify" > - <div class="w-5/6 text-2xl tracking-wide"> + <div class="w-5/6 bg-white rounded-lg border p-6 text-2xl tracking-wide"> <h2 class="font-bold"> CD-CODE </h2> @@ -16,19 +16,7 @@ href="https://wiki.cd-code.org/" class="color-accent-color" >encyclopedia</a> for the scientific terms used to describe - them. Biomolecular condensates are membrane-less organelles that are formed by - <a - href="https://wiki.cd-code.org/Mechanisms_of_Condensate_Formation" - class="color-accent-color" - >liquid-liquid phase separation(LLPS)</a>. In cells, phase separation is driven by <a - href="https://wiki.cd-code.org/Scaffolds_and_Clients" - class="color-accent-color" - >driver</a> - proteins and nucleic acid, which recruit <a - href="https://wiki.cd-code.org/Scaffolds_and_Clients" - class="color-accent-color" - >client</a> molecules into the - condensate. + them. Biomolecular condensates are micron-scale compartments in eukaryotic cells that operate to concentrate proteins and nucleic acids but lack surrounding membranes (membraneless). </p> <p> CD-CODE allows for the dynamic and fast addition, and review of new condensates and proteins by contributing users. CD-CODE is a semi-manually curated and annotated database that aggregates information from primary literature and other protein and LLPS databases. @@ -118,7 +106,7 @@ <b>3. Regulators:</b> Proteins which biochemically or enzymatically regulate the formation of a condensate, but are structurally not part of it. </p> - <div class="flex justify-center rounded-lg border bg-white my-6 bg-opacity-90 border-gray-300"> + <div class="flex justify-center rounded-lg bg-white my-6 bg-opacity-90 border-gray-300"> <img src="../assets/figures/version_4.png" class="object-contain md:w-2/5 lg:w-3/5 rounded-lg" diff --git a/web/src/components/BarcodePlot.vue b/web/src/components/BarcodePlot.vue index 3c63b811d3bd4f844602c5c60bd7e1000c8d3f90..0ca6e44cc31e30a199b6a3d20b361183383a9868 100644 --- a/web/src/components/BarcodePlot.vue +++ b/web/src/components/BarcodePlot.vue @@ -34,7 +34,7 @@ export default { } ], layout: { - title: 'Barcode Plot', + title: 'Amino Acid Composition', xaxis: { title: 'Position', zeroline: false, diff --git a/web/src/components/CondensateDetailPage.vue b/web/src/components/CondensateDetailPage.vue index 77ebc0e11d0dd423345776ad67edc56e4923b812..3ac10e8afce92b6945dd23a02a01000743abe263 100644 --- a/web/src/components/CondensateDetailPage.vue +++ b/web/src/components/CondensateDetailPage.vue @@ -82,7 +82,7 @@ <div v-if="changeName && (getUserData === 'Maintainer' || - getUserData === 'Contributor')" + getUserData === 'Contributor')" class=" bg-white p-4 @@ -263,7 +263,7 @@ </button> <div v-if="showUpdateDescription && (getUserData === 'Maintainer' || - getUserData === 'Contributor')" + getUserData === 'Contributor')" class="panel panel-default" > <div class="panel-body"> @@ -447,7 +447,7 @@ </button> <add-delete-synonym v-if="showAddDeleteSynonym && (getUserData === 'Maintainer' || - getUserData === 'Contributor')" + getUserData === 'Contributor')" :synonym-data="response.data.synonyms" :condensate-id="response.data.canonical_id" @update-key="updatedKey += 1" @@ -492,7 +492,7 @@ </button> <add-delete-marker v-if="showAddDeleteMarker && (getUserData === 'Maintainer' || - getUserData === 'Contributor')" + getUserData === 'Contributor')" :marker-data="response.data.biomarkers" :condensate-id="response.data.canonical_id" :proteins="response.data.proteins" @@ -512,7 +512,7 @@ </div> <div class="row text-2xl"> <div class="text col-sm-3 text-2xl"> - Evidence star + Confidence Score </div> <div class="flex col-sm-9"> <star-rating @@ -635,7 +635,7 @@ </button> <div v-if="showAddProtein && (getUserData === 'Maintainer' || - getUserData === 'Contributor')" + getUserData === 'Contributor')" class="panel panel-default mt-4" > <div class="panel-body"> @@ -821,7 +821,7 @@ </fetch-user-specific-update-items> --> <div - v-if="getUserData && !response.data.is_experimental" + v-if="getUserData " class="border bg-white shadow-md rounded-lg p-8" > <h4 class="round mb-8"> @@ -833,15 +833,13 @@ :data="response.data.canonical_id" /> </div> - <div class="my-14 border bg-white shadow-md rounded-lg p-8"> - <h4 class="round mb-8"> - Top Contributors - </h4> - <contributor-list-table - :id="response.data.canonical_id" - entity="condensate" - /> - </div> + + <contributor-list-table + :id="response.data.canonical_id" + class="my-14" + entity="condensate" + /> + <!-- <request-update-item-table id="protein-table" diff --git a/web/src/components/ContributorListTable.vue b/web/src/components/ContributorListTable.vue index 73fdba0ec526c42225e932071e7d71f83b83b7b9..474517ba3991e9bbbdc8c7be48ac7cfb18b88c06 100644 --- a/web/src/components/ContributorListTable.vue +++ b/web/src/components/ContributorListTable.vue @@ -1,25 +1,41 @@ <template> <section> - <div class="h-1/2 overflow-y-auto shadow-md sm:rounded-lg"> + <div + v-if="showTable" + class="border bg-white shadow-md rounded-lg p-8" + > <h2 - v-if="error" - class="text-red-500" + v-if="entity ==='all'" + class="mb-10 text-3xl text-center" > - {{ errorMsg }} + All Contributors </h2> - <h5 - v-if="!showTable" - class="text-center" + <h4 + v-if="entity ==='condensate' || entity ==='protein'" + class="round mb-8" > - No contribution made yet. - </h5> + Top Contributors + </h4> + <div class="h-1/2 overflow-y-auto border sm:rounded-lg"> + <h2 + v-if="error" + class="text-red-500" + > + {{ errorMsg }} + </h2> + <h5 + v-if="!showTable" + class="text-center" + > + No contribution made yet. + </h5> - <table - v-else - class="w-full table-auto text-left text-gray-500 dark:text-gray-400" - > - <thead - class=" + <table + v-else + class="w-full table-auto text-left text-gray-500 dark:text-gray-400" + > + <thead + class=" sticky top-0 bg-gray-50 @@ -27,31 +43,31 @@ uppercase dark:bg-gray-700 dark:text-gray-400 " - > - <tr class="p-8 sticky top-0"> - <th - v-for="item in tableHeader" - :key="item" - scope="col" - class="px-6 py-3" - > - {{ item }} - </th> - </tr> - </thead> + > + <tr class="p-8 sticky top-0"> + <th + v-for="item in tableHeader" + :key="item" + scope="col" + class="px-6 py-3" + > + {{ item }} + </th> + </tr> + </thead> - <tbody - class="overflow-y-scroll w-full" - style="height: 2vh" - > - <tr - v-for="items in topContributors" - :key="items.id" - class="bg-white border-b dark:bg-gray-800 dark:border-gray-700" + <tbody + class="overflow-y-scroll w-full" + style="height: 2vh" > - <td - scope="row" - class=" + <tr + v-for="items in topContributors" + :key="items.id" + class="bg-white border-b dark:bg-gray-800 dark:border-gray-700" + > + <td + scope="row" + class=" px-6 py-4 font-medium @@ -59,12 +75,12 @@ dark:text-white whitespace-nowrap " - > - {{ items.username }} - </td> - <td - scope="row" - class=" + > + {{ items.username }} + </td> + <td + scope="row" + class=" px-6 py-4 font-medium @@ -72,9 +88,9 @@ dark:text-white whitespace-nowrap " - > - <span - class=" + > + <span + class=" bg-blue-100 text-blue-800 font-semibold @@ -84,13 +100,14 @@ rounded dark:bg-blue-200 dark:text-blue-800 " - > - {{ items.contribution }} - </span> - </td> - </tr> - </tbody> - </table> + > + {{ items.contribution }} + </span> + </td> + </tr> + </tbody> + </table> + </div> </div> </section> </template> @@ -134,7 +151,7 @@ export default { this.error = false; this.errorMsg = ''; const response = await res.json(); - + const convertedArray = response.filteredEntries.map((e) => ({ id: e.id, username: e.username, diff --git a/web/src/components/Datatable/ProteinDataTable.vue b/web/src/components/Datatable/ProteinDataTable.vue index 2cd83b77716dd234db3e5f059470ef5e5e688f24..eadd1195306073bfaff1b0de5031e96533d62738 100644 --- a/web/src/components/Datatable/ProteinDataTable.vue +++ b/web/src/components/Datatable/ProteinDataTable.vue @@ -90,23 +90,28 @@ export default { } $(nTd).html(`${n}`); }, - }, - { - title: 'Functional Type', - data: 'functional_type', - searchable: true, - render: function (data, type, row, meta) { - return data; - }, }, { - title: 'Presence in Biomolecular condensates', + title: 'Verified in Biomolecular Condensates', data: 'biomolecular_condensate_count', className: 'whitespace-normal break-words', render: function (data, type, row, meta) { return data ; }, }, + { + title: 'Verified in Synthetic Condensates', + data: 'synthetic_condensate_count', + className: 'whitespace-normal break-words', + render: function (data, type, row, meta) { + if(data > 0){ + return 'Yes' + }else{ + return 'No' + } + + }, + }, { title: 'Species', data: 'species_name', @@ -117,7 +122,7 @@ export default { ]; const doms = - '<"row"<"col-sm-4"f><"#function_filter.col-sm-4"><"#download.col-sm-4">><"row"t><"row"<"col-sm-4"i><"col-sm-8"p>>'; + '<"row"<"col-sm-4"f><"#download.col-sm-8">><"row"t><"row"<"col-sm-4"i><"col-sm-8"p>>'; const nTableOptions = { columns, @@ -166,8 +171,11 @@ export default { column.search(val, false).draw(); }); - $('<label>Functional Type</label>').prependTo('#function_filter'); + + + }); + }, }; @@ -244,13 +252,13 @@ export default { : ''); let url = - `${host}/proteins?fields=ensembl_gene_id,ensembl_id,biomolecular_condensate_count,functional_type,gene_name,name,species_name,species_tax_id,uniprot_id,uniprot_readable_id&size=50&page=${page}` + + `${host}/proteins?fields=ensembl_gene_id,ensembl_id,biomolecular_condensate_count,synthetic_condensate_count,functional_type,gene_name,name,species_name,species_tax_id,uniprot_id,uniprot_readable_id&size=50&page=${page}` + (order.length > 0 ? `&sort=${order.join(',')}` : '') + (search ? `&query=${search}` : '') + (functionalType.search.value ? `&functional_type=${functionalType.search.value}` : ''); - + try { const res = await this.axios.get(url, { headers: { diff --git a/web/src/components/IUPred2Chart.vue b/web/src/components/IUPred2Chart.vue index f1c1888c9164edfe570887e8dd3cbf262abd3765..9f5c32371e5ad5ad1da0bbf6939f637f09ccf0d8 100644 --- a/web/src/components/IUPred2Chart.vue +++ b/web/src/components/IUPred2Chart.vue @@ -34,7 +34,7 @@ export default { } ], layout: { - title: 'IUPred2A Plot', + title: 'Disordered Content', xaxis: { title: 'Position' // tickmode: 'array', tickvals: _.range(1, this.score.length + 1), diff --git a/web/src/components/LandingPage.vue b/web/src/components/LandingPage.vue index 520ba826544337b13050b871316ee76fbe7a1f32..3e72c9a76ff001016709e65b6090fb74d4cd19fe 100644 --- a/web/src/components/LandingPage.vue +++ b/web/src/components/LandingPage.vue @@ -4,7 +4,7 @@ class=" flex flex-wrap justify-center - mt-14 + mt-8 mb-24 text-2xl tracking-wide @@ -22,17 +22,17 @@ <br /> <br /> </p> --> - <div class="grid grid-cols-3 lg:grid-cols-4 gap-4"> + <div class="grid grid-cols-3 lg:grid-cols-4 gap-8"> <div class="col-span-2 lg:col-span-3"> <div class=" flex flex-col - space-y-4 - md:grid md:grid-cols-2 md:gap-x-4 + space-y-8 + md:grid md:grid-cols-2 md:gap-x-8 h-auto " > - <div class="border md:col-span-2 shadow-md bg-white rounded-lg p-6"> + <div class="border gap-6 md:col-span-2 shadow-md bg-white rounded-lg p-6"> <form class="form-horizontal" autocomplete="off" @@ -111,10 +111,31 @@ </div> </div> <div class="row"> - <label - class="control-label col-sm-2" - for="keyword" - >Search</label> + <div class="col-sm-2"> + <div class="h-16 font-bold justify-end flex items-center "> + Search + + + + + <a + class=" + + ml-2 + search-tooltip + text-3xl + tooltipped tooltipped-e tooltipped-multiline + " + aria-label=" Hint: Type a complete word to see a list of suggested entries. For proteins best matches are retrieved when using UniProt ID." + > + + <font-awesome-icon + icon="fa-solid fa-circle-info" + :style="{color: '#3b82f6'}" + /> + </a> + </div> + </div> <div class="col-sm-8"> <vue-simple-suggest v-model="selected" @@ -186,6 +207,7 @@ style="float: right" class="font-medium" > + Examples: <span class="text-pink-base font-medium"> <router-link to="/protein_example">UNE6</router-link>, @@ -226,56 +248,30 @@ </Search> </div> </div> - <div class="border p-8 shadow-md bg-white rounded-lg"> - <!-- <h4 class="round mb-8">All Contributors</h4> - <contributor-list-table id="all" entity="all" /> --> - <!-- <img - src="@/assets/figure_1a.png" - class=" - object-scale-down - transition - duration-500 - ease-in-out - transform - hover:-translate-y-1 hover:scale-110 - " - alt="Figure" - width="500" - height="600" - /> --> - - <p class="text-xl md:text-2xl lg:text-3xl text-justify"> - CD-CODE (CrowDsourcing COndensate Database and Encyclopedia) is - a comprehensive, semi-manually curated crowdsourcing database of - biomolecular condensates and their constituents as well as an - encyclopedia for the scientific terms used to describe them. - Biomolecular condensates are membrane-less organelles that are - formed by liquid-liquid phase separation(LLPS). In cells, phase - separation is driven by driver proteins and nucleic acid, which - recruit client molecules into the condensate. CD-CODE allows for - the dynamic and fast addition, and review of new condensates and - proteins by contributing users. CD-CODE is a semi-manually - curated and annotated database that aggregates information from - primary literature and other protein and LLPS databases. + <div class="border h-full p-8 shadow-md bg-white rounded-lg"> + <p class="text-xl my-6 md:text-2xl lg:text-3xl text-justify"> + CD-CODE (CrowDsourcing COndensate Database and Encyclopedia) is a comprehensive, semi-manually curated crowdsourcing database of biomolecular condensates and their constituents as well as an encyclopedia for the scientific terms used to describe them. Biomolecular condensates are micron-scale compartments in eukaryotic cells that operate to concentrate proteins and nucleic acids but lack surrounding membranes (membraneless). {{ isDev ? "(Dev)" : "" }} </p> <button class=" bg-blue-500 + font-bold rounded-lg py-4 px-5 text-white hover:bg-blue-700 - float-left + " @click="$router.push('/about')" > Read more </button> + </div> - <div class="border p-8 shadow-md bg-white rounded-lg"> + <div class="border h-full p-8 shadow-md bg-white rounded-lg"> <div class="flex justify-center"> <img src="@/assets/figures/Figure_1a_v2.png" @@ -296,32 +292,25 @@ </div> </div> - <!-- <img src="@/assets/CD-CODE_blobs.svg" alt="Logo" /> --> + <div class="h-full"> <a - class="twitter-timeline" - data-height="1050" + id="widget" + class="twitter-timeline" + data-height="1025" href="https://twitter.com/agnestothp?ref_src=twsrc%5Etfw" >Tweets by agnestothp</a> </div> <div class=" - border + mt-8 col-span-3 md:col-span-4 lg:col-span-4 - shadow-md - bg-white - rounded-lg - my-6 - p-8 " > - <h2 class="mb-10 text-3xl text-center"> - All Contributors - </h2> <contributor-list-table id="all" entity="all" @@ -463,6 +452,7 @@ export default { })(document, 'script', 'twitter-wjs'); if (window.twttr.widgets) { + window.twttr.widgets.load( document.getElementsByClassName('twitter-timeline') ); @@ -633,6 +623,7 @@ export default { + h3 { margin: 40px 0 0; } @@ -646,6 +637,14 @@ input[type="radio"] { margin-right: 5px; } +.twitter-height{ + height: 100%; +} +#widget { + float: none; + width: 100% !important; + } + .center-image { display: -webkit-box; -webkit-box-pack: center; /* justify-content */ diff --git a/web/src/components/LlpsTable.vue b/web/src/components/LlpsTable.vue index cc1b57bb297c2cd1856521f41293b9ef7d831c0a..0c4865a9f0f1023151ab036bffdfde97d78d4d2b 100644 --- a/web/src/components/LlpsTable.vue +++ b/web/src/components/LlpsTable.vue @@ -8,7 +8,7 @@ style="width: 100%" /> - <the-action-modal + <the-action-modal :protein-uniprot="uniprotId" @@ -142,6 +142,7 @@ export default { const vm = this; vm.createTable(vm.id, vm.data); + }, methods: { closeModal() { @@ -733,7 +734,8 @@ export default { oLanguage: { sSearch: 'Filter', }, - dom: '<"row"<"col-sm-2"l><"col-sm-2"f><"col-sm-6"p><"#download.col-sm-2">><"row"t><"row"<"col-sm-4"i><"col-sm-8"p>>', + dom: `<"row"${vm.data.length > 10 ? '<"col-sm-2"l>': ''}<"col-sm-${vm.data.length > 10 ? '2' : '4'}"f><"col-sm-6"p><"#download.col-sm-2">><"row"t><"row"<"col-sm-4"i><"col-sm-8"p>>`, + initComplete: function () { // this.api().columns().every( function () { // var column = this; diff --git a/web/src/components/Navigation/TheNavBar.vue b/web/src/components/Navigation/TheNavBar.vue index 014641848b8241affe756998e30ea9ab2f3d0dde..eabe37f7cad702ecb0a464922412e0038b52939a 100644 --- a/web/src/components/Navigation/TheNavBar.vue +++ b/web/src/components/Navigation/TheNavBar.vue @@ -624,4 +624,4 @@ a { .active { color: #ef0087 !important; } -</style> \ No newline at end of file +</style> diff --git a/web/src/components/ProteinDetailPage.vue b/web/src/components/ProteinDetailPage.vue index a2ade4558d14dc71225b0a81b8050842dab1dba6..60dde41309ecd1518fafb935ca565669f04987b4 100644 --- a/web/src/components/ProteinDetailPage.vue +++ b/web/src/components/ProteinDetailPage.vue @@ -159,6 +159,22 @@ </div> </div> <div class="row text-2xl"> + <div class="text col-sm-3"> + Verified in Biomolecular Condensates + </div> + <div class="col-sm-9"> + {{ response.data.biomolecular_condensate_count }} + </div> + </div> + <div class="row text-2xl"> + <div class="text col-sm-3"> + Verified in Synthetic Condensates + </div> + <div class="col-sm-9"> + {{ response.data.synthetic_condensate_count > 0 ? 'Yes' : 'No' }} + </div> + </div> + <!-- <div class="row text-2xl"> <div class="text col-sm-3"> Functional Type <a @@ -205,15 +221,8 @@ @close="closeUpdateFunctionalType" /> </div> - </div> - <!-- <div class="row"> - <div class="text col-sm-3"> - Primary Datasource - </div> - <div class="col-sm-9"> - {{ response.data.source_db_tags.join(", ") }} - </div> </div> --> + <div v-if="response.data.pubmed_ids" class="row text-2xl" @@ -252,6 +261,7 @@ {{ item }} <i class="glyphicon glyphicon-link" /> </a> + <br v-if="shownMore.pub && index % 7 === 6"> </span> <button v-if=" @@ -270,102 +280,65 @@ </button> <add-delete-pubmed v-if="showAddOrDeletePubmedId && - (getUserData === 'Maintainer' || - getUserData === 'Contributor')" + (getUserData === 'Maintainer' || + getUserData === 'Contributor')" :data="response.data" mode="protein" @update-key="updatedKey += 1" @cancel="cancelAddOrDeletePubmedId" /> </div> - <div - id="more" - :class="{ - active: response.data.pubmed_ids.length <= 7, - }" - > - <span - v-for="(item, index) in getMorePubIds( - response.data.pubmed_ids - )" - :key="index" - > - <a - :id="item" - :href="'https://pubmed.ncbi.nlm.nih.gov/' + item" - class=" - uniprot-link - tooltipped tooltipped-n tooltipped-multiline - " - target="_blank" - @mouseover="fetchPubMedId(item)" - > - {{ item }} - <i class="glyphicon glyphicon-link" /> - </a> - <br v-if="index % 7 === 6"> - </span> - </div> </div> <div - v-show="response.data.pubmed_ids.length > 7" + v-if="response.data.pubmed_ids.length > 7" class="col-sm-2" > - <a - v-show="!shownMore.pub" - class="uniprot-link" - @click="showMore('#more', 'pub', response.length)" - ><i - class="fa fa-angle-double-down" - aria-hidden="true" - style="color: royalblue" - /> - Show more</a> - <a - v-show="shownMore.pub" - class="uniprot-link" - @click="showLess('#more', 'pub')" - ><i - class="fa fa-angle-double-up" - aria-hidden="true" - style="color: royalblue" - /> - Show less</a> + <div v-if="shownMore.pub"> + <a + class="uniprot-link" + @click="showLess()" + ><i + class="fa fa-angle-double-up" + aria-hidden="true" + style="color: royalblue" + /> + Show less</a> + </div> + <div v-else> + <a + class="uniprot-link" + @click="showMore()" + ><i + class="fa fa-angle-double-down" + aria-hidden="true" + style="color: royalblue" + /> + Show more</a> + </div> </div> </div> + <div - v-if="sequenceFormatting(response.data.sequence)" + v-if="response.data.sequence" class="row text-2xl" > <div class="text col-sm-3"> Sequence </div> <div class="col-sm-9"> - <!-- <input - type="text" - :value="response.data.sequence" - > <button - :id="'sequence'" - class="copy-button" - :name="'sequence'" - :data-clipboard-text="response.data.sequence" - > - <i class="glyphicon glyphicon-copy" /> - </button> --> - <button - :id="'sequence'" + id="sequence" class="copy-button p-2 bg-gray-100 hover:bg-gray-300 rounded-lg" - :name="'sequence'" + name="sequence" :data-clipboard-text="response.data.sequence" > <span>Copy </span> <i class="glyphicon glyphicon-copy" /> </button> - + <div class="bg-gray-100 p-2 grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl-grid-cols-6 gap-2"> <div - v-for="(item, index) in sequenceFormat" + v-for="(item, index) in sequenceFormatting(response.data.sequence)" :key="index" > <div> @@ -383,14 +356,6 @@ </div> </div> </div> - <div class="row text-2xl"> - <div class="text col-sm-3"> - Presence in Biomolecular condensates - </div> - <div class="col-sm-9"> - {{ response.data.biomolecular_condensate_count }} - </div> - </div> </div> </div> </div> @@ -456,7 +421,7 @@ <h4 class="round"> Biomolecular Condensates </h4> - <h4>Count- {{ getBiomolecularCondensate(response.data.condensates) ? biomolecularCondenstaes.length : '0' }}</h4> + <h4>Count- {{ biomolecularCondenstaes ? biomolecularCondenstaes.length : getBiomolecularCondensate(response.data.condensates) ? biomolecularCondenstaes.length : '0' }}</h4> </div> @@ -482,13 +447,16 @@ </thead> <tbody v-if="!biomolecularCondenstaes"> <tr> - <td colspan="4" class="text-center"> No data </td> + <td + colspan="4" + class="text-center" + > + No data + </td> </tr> </tbody> <tbody> - - - <tr + <tr v-for="(item, index) in biomolecularCondenstaes" :key="index" > @@ -504,8 +472,6 @@ <td>{{ item.species_name }}</td> <td>{{ getFuntionalType(item.protein_functional_type, response.data.uniprot_id) }}</td> </tr> - - </tbody> </table> </div> @@ -520,11 +486,10 @@ <h4 class="round"> Synthetic Condensates </h4> - <h4>Count- {{ getSyntheticCondensate(response.data.condensates) ? syntheticCondensates.length : '0' }}</h4> + <h4>Count- {{ syntheticCondensates ? syntheticCondensates.length: getSyntheticCondensate(response.data.condensates) ? syntheticCondensates.length : '0' }}</h4> </div> <table class="border-collapse table-fixed border table table-hover table-responsive"> - <thead> <tr class="active"> <th class="w-2/5"> @@ -542,17 +507,19 @@ </thead> <tbody v-if="!syntheticCondensates"> <tr> - <td colspan="3" class="text-center"> No data </td> + <td + colspan="3" + class="text-center" + > + No data + </td> </tr> </tbody> <tbody v-else> - - - <tr + <tr v-for="(item, index) in syntheticCondensates" :key="index" > - <td> <a :href="'/condensate/' + item.canonical_id" @@ -564,8 +531,6 @@ <td>{{ item.species_name }}</td> </tr> - - </tbody> </table> </div> @@ -584,10 +549,8 @@ :data="protein" /> </div> - <div class="bg-white shadow-md border rounded-lg p-8"> - <h4 class="round mb-8"> - Top Contributors - </h4> + <div> + <contributor-list-table :id="protein" entity="protein" @@ -606,7 +569,7 @@ import fetchProtein from '@/components/DDCODE/fetchProtein.vue'; import IuPred2Chart from '@/components/IUPred2Chart'; import BarcodePlot from '@/components/BarcodePlot'; -import UpdateFunctionalType from './CMS/updateFunctionalType.vue'; +// import UpdateFunctionalType from './CMS/updateFunctionalType.vue'; import AddDeletePubmed from './CMS/addDeletePubmed.vue'; import ProteinUpdateItemTable from './ProteinUpdateItemTable.vue'; @@ -627,7 +590,7 @@ export default { fetchProtein, IuPred2Chart, BarcodePlot, - UpdateFunctionalType, + // UpdateFunctionalType, AddDeletePubmed, ProteinUpdateItemTable, ContributorListTable, @@ -709,7 +672,7 @@ export default { return }else if(filterSyntheticCondensate.length > 0){ - + this.syntheticCondensates = filterSyntheticCondensate return this.syntheticCondensates } @@ -721,7 +684,7 @@ export default { if(filterBioCondensate.length === 0){ return }else if(filterBioCondensate.length > 0){ - + this.biomolecularCondenstaes = filterBioCondensate return this.biomolecularCondenstaes @@ -744,30 +707,17 @@ export default { getPubMedIds(ids) { let outIds = []; - ids.forEach((i, idx) => { - outIds.push(`${i}`); - }); - - return outIds.slice(0, 7); - }, - getMorePubIds(ids) { - let outIds = []; - ids.forEach((i) => { outIds.push(`${i}`); }); - return outIds.slice(7); + return this.shownMore.pub ? outIds: outIds.slice(0, 7); }, - showLess(id, clazz) { - let $rows = $(id); - $rows.removeClass('active'); - this.shownMore[clazz] = false; + showLess() { + this.shownMore.pub = false; }, - showMore(id, clazz) { - let $rows = $(id); - $rows.addClass('active'); - this.shownMore[clazz] = true; + showMore() { + this.shownMore.pub = true; }, getDbNames(names) { return _.map(names, (i) => this.dbNames[i]).join(', '); @@ -1009,12 +959,4 @@ a { .panel { font-size: 1.2rem; } - -#more { - display: none; -} - -#more.active { - display: table-row; -} </style> diff --git a/web/src/components/js/const.js b/web/src/components/js/const.js index 01da015f1edda31ead02c78393a88a515eb5154d..03dc292b65bd88cb159d4d10b8d200294089e7cb 100644 --- a/web/src/components/js/const.js +++ b/web/src/components/js/const.js @@ -9,7 +9,10 @@ export const devApiHost = '/cms'; // export const devApiHost = 'http://localhost:1337'; // apikey should be given here according to production or development: -export const apikey = process.env.NODE_ENV === 'development' ? process.env.VUE_APP_API_KEY_DEV : process.env.VUE_APP_API_KEY_PROD; +export const apikey = process.env.VUE_APP_API_KEY; // wiki apikey should be given here: export const wikiApikey = process.env.VUE_APP_WIKI_KEY; + +// expire time +export const expireTime = process.env.VUE_APP_EXPIRE_TIME; diff --git a/web/src/main.js b/web/src/main.js index 1f98f2221903e7a673d73b2f5ae659a2d9af8c8e..21ba9a665da08b449b14dccc364959860b22d4b2 100644 --- a/web/src/main.js +++ b/web/src/main.js @@ -20,7 +20,7 @@ import { faRightToBracket } from '@fortawesome/free-solid-svg-icons'; import { faCircleArrowLeft } from '@fortawesome/free-solid-svg-icons'; import { faUserPen } from '@fortawesome/free-solid-svg-icons'; import { faTriangleExclamation } from '@fortawesome/free-solid-svg-icons'; -import { faEnvelope } from '@fortawesome/free-solid-svg-icons' +import { faEnvelope, faCircleInfo } from '@fortawesome/free-solid-svg-icons' /* import font awesome icon component */ @@ -30,7 +30,7 @@ import store from './store'; import router from './router'; /* add icons to the library */ -library.add(faPenToSquare, faThumbsUp, faCircleXmark, faRightToBracket, faCircleArrowLeft, faUserPen, faTriangleExclamation, faEnvelope); +library.add(faPenToSquare, faThumbsUp, faCircleXmark, faRightToBracket, faCircleArrowLeft, faUserPen, faTriangleExclamation, faEnvelope, faCircleInfo); /* add font awesome icon component */ Vue.component('FontAwesomeIcon', FontAwesomeIcon); diff --git a/web/src/store/modules/User.js b/web/src/store/modules/User.js index f5df4504abc34ccb2cbaafed669467e13c3985e3..22f9f573bee1abd3886d3c3521e3721c9d75578a 100644 --- a/web/src/store/modules/User.js +++ b/web/src/store/modules/User.js @@ -8,7 +8,8 @@ const state = { expirationDate: null, didAutoLogout: false, isLoggedIn: false, - lastPath: null + lastPath: null, + expireTime: 3600000, }; const mutations = { @@ -16,29 +17,24 @@ const mutations = { state.jwt = jwt; }, SET_USER_DATA(state, userData) { - state.userData = userData; - // state.tokenExpiration }, SET_USER_ROLE(state, userRole) { state.userRole = userRole; }, - // SET_TOKEN_EXPIRATION(state, tokenExpiration){ - // console.log("in action epiration data is", tokenExpiration); - // state.expirationDate = tokenExpiration - // }, LOG_OUT(state) { state.jwt = null; state.userData = null; state.userRole = null; }, - setAutoLogout(state){ + SET_AUTO_LOGOUT(state){ state.didAutoLogout = true }, - - setLastPath(state, payload){ - + SET_LAST_PATH(state, payload){ state.lastPath = payload + }, + SET_EXPIRE_TIME(state, expireTime) { + state.expireTime = expireTime } }; @@ -47,33 +43,34 @@ const getters = { userData: (state) => state.userData, userRole: (state) => state.userRole, didAutoLogout: (state) => state.didAutoLogout, - getLastPath : (state) => state.lastPath + getLastPath : (state) => state.lastPath, + expireTime : (state) => state.expireTime }; const actions = { setJwt({ commit }, jwt) { + localStorage.setItem('jwt', jwt); commit('SET_JWT', jwt); }, - setUserData({ commit, dispatch }, userData) { - localStorage.setItem('userData', userData); + setUserData({ commit, dispatch, state }, userData) { + + localStorage.setItem('userData', userData) + /* calulation of hours to millisec (hr*3600000) */ // const expiresIn = 60 * 1000 // const expiresIn = 20000 - let expiresIn = 20000 - if ( process.env.VUE_APP_USER_EXPIRE_SEC ) { - expiresIn = parseInt( process.env.VUE_APP_USER_EXPIRE_SEC ) - } else { - console.error( 'Please setup VUE_APP_USER_EXPIRE_SEC environment variable. Default expiration time is 20 seconds') - } + let expiresIn = state.expireTime const expirationDate = new Date().getTime() + expiresIn localStorage.setItem('tokenExpiration', expirationDate) commit('SET_USER_DATA', userData); + + timer= setTimeout(function(){ dispatch('autoLogout') }, expiresIn ) @@ -99,6 +96,7 @@ const actions = { const tokenExpiration = localStorage.getItem('tokenExpiration') const expiresIn= tokenExpiration - new Date().getTime() + if(expiresIn<0){ return @@ -114,11 +112,13 @@ const actions = { }, autoLogout(context){ context.dispatch('logOut') - context.commit('setAutoLogout') + context.commit('SET_AUTO_LOGOUT') }, setLastPath(context, path){ - - context.commit('setLastPath', path) + context.commit('SET_LAST_PATH', path) + }, + setExpireTime(context, expireTime) { + context.commit('SET_EXPIRE_TIME', expireTime) } }; diff --git a/web/src/views/Login.vue b/web/src/views/Login.vue index 5707f0b1a1282e0b5d8eee50913211daf24cf875..bde506d41b9c368b3edded5e3397db9fe39f537e 100644 --- a/web/src/views/Login.vue +++ b/web/src/views/Login.vue @@ -156,6 +156,7 @@ </template> <script> let host = require('@/components/js/const').apiHost; +const expireTime = parseInt(require('@/components/js/const').expireTime); export default { name: 'Login', @@ -257,16 +258,9 @@ export default { return; } - - - const { jwt, user } = response; - - - // window.localStorage.setItem('jwt', jwt); - // window.localStorage.setItem('userData', JSON.stringify(user)); - + this.$store.dispatch('User/setExpireTime', expireTime); this.$store.dispatch('User/setJwt', jwt); this.$store.dispatch('User/setUserData', JSON.stringify(user)); this.isLoading = false; diff --git a/web/src/views/Profile.vue b/web/src/views/Profile.vue index fc544c36e3f7593b57eac4f63b5d45a7a9be1e02..cf5a05dddfbd22a340f59848731c14366ee0c594 100644 --- a/web/src/views/Profile.vue +++ b/web/src/views/Profile.vue @@ -163,7 +163,7 @@ Role </div> <div class="col-sm-9"> - {{ response.role.name}} + {{ response.role.name }} </div> </div> <div class="row">