Commit edb4828e authored by Kenzo-Hugo Hillion's avatar Kenzo-Hugo Hillion
Browse files

add eggnog card and improve gene details page

parent 59ab8459
Pipeline #32078 passed with stages
in 3 minutes and 12 seconds
from rest_framework import serializers
from metagenedb.apps.catalog.models import EggNOG, Function, KeggOrthology
from metagenedb.apps.catalog.models import (
EggNOG, EggNogFunctionalCategory, Function, KeggOrthology
)
from .asymetricslugrelatedfield import AsymetricSlugRelatedField
from .bulk_list import BulkListSerializer
......@@ -24,7 +27,21 @@ class EggNOGListSerializer(BulkListSerializer):
model = EggNOG
class EggNogFunctionalCategorySerializer(serializers.ModelSerializer):
class Meta:
model = EggNogFunctionalCategory
fields = ('category_id', 'name', 'group')
class EggNOGSerializer(serializers.ModelSerializer):
functional_categories = AsymetricSlugRelatedField.from_serializer(
EggNogFunctionalCategorySerializer,
queryset=EggNogFunctionalCategory.objects.all(),
slug_field='category_id',
many=True,
required=False,
)
class Meta:
model = EggNOG
......
<v-flex xs12 md6 lg4>
<v-flex xs12 md6 lg4 xl3>
<v-card>
<v-toolbar class="eggnog white--text" dense>
<v-icon class="white--text">fa-braille</v-icon>
<v-toolbar-title class="eggnog white--text">
EggNOG
EggNOG {{displayVersion}}
</v-toolbar-title>
</v-toolbar>
<div class="text-xs-center" v-if="requestDone == false">
......@@ -27,49 +27,10 @@
<v-list-tile-title v-html="item.title"></v-list-tile-title>
<v-list-tile-sub-title v-html="item.content"></v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-action v-if="item.url">
<v-tooltip right>
<template v-slot:activator="{ on }">
<v-btn :href="item.url" flat icon class="eggnog--text text--darken-1" target="_blank" v-on="on">
<v-icon>open_in_new</v-icon>
</v-btn>
</template>
<span>Open in EggNOG</span>
</v-tooltip>
</v-list-tile-action>
</v-list-tile>
</template>
<!-- Expandable details (pathways and diseases) -->
<template v-for="(expanditem, expandindex) in eggnogExpandDetails">
<v-expansion-panel v-if="expanditem.content.length > 0" :key="expandindex">
<v-divider
:key="expanditem.title"
></v-divider>
<v-expansion-panel-content>
<template v-slot:header>
<div>{{ expanditem.title }}</div>
</template>
<v-card>
<v-list>
<template v-for="(item, index) in expanditem.content">
<v-divider
v-if="index > 0"
:key="index + '_expanded'"
></v-divider>
<v-list-tile :key="item.id" class="dropdown">
<v-list-tile-content>
<v-list-tile-sub-title v-html="item.name"></v-list-tile-sub-title>
</v-list-tile-content>
</v-list-tile>
</template>
</v-list>
</v-card>
</v-expansion-panel-content>
</v-expansion-panel>
</template>
</v-list>
<SimpleExpand :expandData="eggnogExpandDetails"/>
</v-card>
</v-flex>
\ No newline at end of file
import axios from 'axios';
import SimpleExpand from '@/components/listing/simpleexpand/simpleexpand.vue';
export default {
components: {
SimpleExpand,
},
name: 'EggNogCard',
props: {
eggnogId: String,
......@@ -14,8 +18,25 @@ export default {
eggnogExpandDetails: [],
eggnogReferences: [],
requestDone: false,
eggnogVersion: '',
};
},
computed: {
funcCatGroups() {
return {
'info_storage_processing': 'Information Storage and Processing',
'cellular_processes_signaling': 'Cellular Processes and Signaling',
'metabolism': 'Metabolism',
'poorly_characterized': 'Poorly Characterized',
}
},
displayVersion() {
if (this.eggnogVersion) {
return `v.${this.eggnogVersion}`;
}
return '';
},
},
methods: {
getEggNogDetail() {
if (this.eggnogId == 'no_eggnog') {
......@@ -30,7 +51,6 @@ export default {
.then((response) => {
this.buildEggNogDetails(response);
this.buildEggNogExpandDetails(response);
this.buildReferences(response);
})
.catch((error) => {
console.log(error);
......@@ -40,7 +60,7 @@ export default {
});
},
buildEggNogDetails(response) {
console.log(response.data)
this.eggnogVersion = response.data.version
this.eggnogDetails = [
{
title: 'ID',
......@@ -50,10 +70,6 @@ export default {
title: 'Name',
content: response.data.name,
},
{
title: 'EggNOG version',
content: response.data.version,
},
];
},
buildEggNogExpandDetails(response) {
......@@ -62,18 +78,21 @@ export default {
];
},
buildFunctionalCategories(response) {
const pathways = {
const funcCats = {
title: 'Functional Categories',
icon: 'fas fa-layer-group',
content: [],
};
Object.entries(response.data.functional_categories).forEach(value => {
pathways.content.push(
Object.entries(response.data.functional_categories).forEach(([key, value]) => {
const name = `(${value.category_id}) ${value.name}`;
funcCats.content.push(
{
name: value[1],
id: name,
name: this.funcCatGroups[value.group],
},
);
});
return pathways;
return funcCats;
},
},
};
\ No newline at end of file
<v-flex xs12 md6 lg4>
<v-flex xs12 md6 lg4 xl3>
<v-card>
<v-toolbar class="kegg white--text" dense>
<v-icon class="white--text">fa-braille</v-icon>
......@@ -40,81 +40,8 @@
</v-list-tile>
</template>
<!-- Expandable details (pathways and diseases) -->
<template v-for="(expanditem, expandindex) in keggExpandDetails">
<v-expansion-panel v-if="expanditem.content.length > 0" :key="expandindex">
<v-divider
:key="expanditem.title"
></v-divider>
<v-expansion-panel-content>
<template v-slot:header>
<div>{{ expanditem.title }}</div>
</template>
<v-card>
<v-list>
<template v-for="(item, index) in expanditem.content">
<v-divider
v-if="index > 0"
:key="index + '_expanded'"
></v-divider>
<v-list-tile :key="item.id" class="dropdown">
<v-list-tile-content>
<v-list-tile-title v-html="item.id"></v-list-tile-title>
<v-list-tile-sub-title v-html="item.name"></v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-action>
<v-tooltip right>
<template v-slot:activator="{ on }">
<v-btn :href="item.url" flat icon class="kegg--text text--darken-1" target="_blank" v-on="on">
<v-icon>open_in_new</v-icon>
</v-btn>
</template>
<span>Open in KEGG</span>
</v-tooltip>
</v-list-tile-action>
</v-list-tile>
</template>
</v-list>
</v-card>
</v-expansion-panel-content>
</v-expansion-panel>
</template>
<!-- References -->
<v-expansion-panel v-if="keggReferences.length > 0">
<v-divider/>
<v-expansion-panel-content>
<template v-slot:header>
<div>References</div>
</template>
<v-card>
<v-list>
<template v-for="(item, index) in keggReferences">
<v-divider
v-if="index > 0"
:key="index + '_ref'"
></v-divider>
<v-list-tile :key="item.id" class="dropdown">
<v-list-tile-content>
<v-list-tile-title v-html="item.title"></v-list-tile-title>
<v-list-tile-sub-title v-html="item.authors"></v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-action>
<v-tooltip right>
<template v-slot:activator="{ on }">
<v-btn :href="item.url" flat icon class="kegg--text text--darken-1" target="_blank" v-on="on">
<v-icon>open_in_new</v-icon>
</v-btn>
</template>
<span>Open in pubmed</span>
</v-tooltip>
</v-list-tile-action>
</v-list-tile>
</template>
</v-list>
</v-card>
</v-expansion-panel-content>
</v-expansion-panel>
<!-- Expandable details (pathways, diseases, references...) -->
<SimpleExpand :expandData="keggExpandDetails"/>
</v-list>
</v-card>
......
import axios from 'axios';
import SimpleExpand from '@/components/listing/simpleexpand/simpleexpand.vue';
export default {
components: {
SimpleExpand,
},
name: 'KeggCard',
props: {
keggId: String,
......@@ -47,7 +51,7 @@ export default {
url: `https://www.genome.jp/dbget-bin/www_bget?ko:${response.data.entry_id}`,
},
{
title: 'Name',
title: 'Name(s)',
content: response.data.name,
},
{
......@@ -60,11 +64,14 @@ export default {
this.keggExpandDetails = [
this.buildPathways(response),
this.buildDiseases(response),
this.buildModules(response),
this.buildReferences(response),
];
},
buildPathways(response) {
const pathways = {
var pathways = {
title: 'Pathways',
icon: 'fas fa-bezier-curve',
content: [],
};
Object.entries(response.data.pathways).forEach(([key, value]) => {
......@@ -73,14 +80,35 @@ export default {
id: key,
name: value,
url: `https://www.genome.jp/kegg-bin/show_pathway?${key}+${this.keggId}`,
url_label: "Open in KEGG",
fetch: true,
},
);
});
return pathways;
},
buildModules(response) {
var modules = {
title: 'Modules',
icon: 'fas fa-bezier-curve',
content: [],
};
Object.entries(response.data.modules).forEach(([key, value]) => {
modules.content.push(
{
id: key,
name: value,
url: `https://www.genome.jp/kegg-bin/show_module?${key}+${this.keggId}`,
url_label: "Open in KEGG"
},
);
});
return modules;
},
buildDiseases(response) {
const diseases = {
var diseases = {
title: 'Diseases',
icon: 'fas fa-laptop-medical',
content: [],
};
Object.entries(response.data.diseases).forEach(([key, value]) => {
......@@ -95,15 +123,22 @@ export default {
return diseases;
},
buildReferences(response) {
var references = {
title: 'References',
icon: 'fas fa-book-open',
content: [],
};
for (let i = 0; i < response.data.references.length; i++) {
this.keggReferences.push(
references.content.push(
{
title: response.data.references[i].title,
authors: `${response.data.references[i].authors[0]} et al. ${response.data.references[i].journal}`,
id: response.data.references[i].title,
name: `${response.data.references[i].authors[0]} et al. ${response.data.references[i].journal}`,
url: `https://www.ncbi.nlm.nih.gov/pubmed/${response.data.references[i].pubmed}`,
url_label: "Open in Pubmed"
},
);
}
};
return references;
},
},
};
\ No newline at end of file
<div name="simpleexpand">
<template v-for="(expanditem, expandindex) in expandData">
<v-expansion-panel v-if="expanditem.content.length > 0" :key="expandindex">
<v-divider
:key="expanditem.title"
></v-divider>
<v-expansion-panel-content>
<template v-slot:header>
<div>
<v-icon small color="primary">{{ expanditem.icon }}</v-icon>
<span class="subheading ml-3">{{ expanditem.title }}</span>
</div>
</template>
<v-card>
<v-list>
<template v-for="(item, index) in expanditem.content">
<v-divider
v-if="index > 0"
:key="index + '_expanded'"
></v-divider>
<v-list-tile :key="item.id" class="dropdown">
<v-list-tile-content>
<v-tooltip top>
<template v-slot:activator="{ on }">
<v-list-tile-title v-on="on" v-html="item.id"></v-list-tile-title>
</template>
<span>{{ item.id }}</span>
</v-tooltip>
<v-tooltip bottom>
<template v-slot:activator="{ on }">
<v-list-tile-sub-title v-on="on" v-html="item.name"></v-list-tile-sub-title>
</template>
<span>{{ item.name }}</span>
</v-tooltip>
</v-list-tile-content>
<v-list-tile-action v-if="item.url">
<v-tooltip right>
<template v-slot:activator="{ on }">
<v-tooltip top v-if='item.fetch'>
<template v-slot:activator="{ on }">
<v-btn flat small icon class="kegg--text text--darken-1 mr-1" target="_blank" v-on="on">
<v-icon>far fa-plus-square</v-icon>
</v-btn>
</template>
<span>Retrieve information here (future feature)</span>
</v-tooltip>
<v-btn :href="item.url" flat icon class="kegg--text text--darken-1" target="_blank" v-on="on">
<v-icon>open_in_new</v-icon>
</v-btn>
</template>
<span>{{ item.url_label }}</span>
</v-tooltip>
</v-list-tile-action>
</v-list-tile>
</template>
</v-list>
</v-card>
</v-expansion-panel-content>
</v-expansion-panel>
</template>
</div>
\ No newline at end of file
export default {
name: 'SimpleExpand',
props: {
expandData: Array,
},
};
\ No newline at end of file
<template src="./simpleexpand.html" lang="html"></template>
<script src="./simpleexpand.js" lang="js"></script>
\ No newline at end of file
<div name="simplelisting">
<template v-for="(expanditem, expandindex) in expandData">
<v-expansion-panel v-if="expanditem.content.length > 0" :key="expandindex">
<v-divider
:key="expanditem.title"
></v-divider>
<v-expansion-panel-content>
<template v-slot:header>
<div>
<span class="title">{{ expanditem.title }}</span>
</div>
</template>
<v-card>
<v-list>
<template v-for="(item, index) in expanditem.content">
<v-divider
v-if="index > 0"
:key="index + '_expanded'"
></v-divider>
<v-list-tile :key="item.id" class="dropdown">
<v-list-tile-content>
<v-tooltip top>
<template v-slot:activator="{ on }">
<v-list-tile-title v-on="on" v-html="item.id"></v-list-tile-title>
</template>
<span>{{ item.id }}</span>
</v-tooltip>
<v-tooltip bottom>
<template v-slot:activator="{ on }">
<v-list-tile-sub-title v-on="on" v-html="item.name"></v-list-tile-sub-title>
</template>
<span>{{ item.name }}</span>
</v-tooltip>
</v-list-tile-content>
<v-list-tile-action>
<v-tooltip right>
<template v-slot:activator="{ on }">
<v-btn :href="item.url" flat icon class="kegg--text text--darken-1" target="_blank" v-on="on">
<v-icon>open_in_new</v-icon>
</v-btn>
</template>
<span>{{ item.url_label }}</span>
</v-tooltip>
</v-list-tile-action>
</v-list-tile>
</template>
</v-list>
</v-card>
</v-expansion-panel-content>
</v-expansion-panel>
</template>
</div>
\ No newline at end of file
export default {
name: 'SimpleListing',
props: {
expandData: Array,
},
};
\ No newline at end of file
<template src="./simplelisting.html" lang="html"></template>
<script src="./simplelisting.js" lang="js"></script>
\ No newline at end of file
<v-flex xs12 md6 lg4>
<v-flex xs12 md6 lg4 xl3>
<v-card>
<v-toolbar class="taxonomy white--text" dense>
<v-icon class="white--text">fa-sitemap</v-icon>
......
......@@ -19,7 +19,7 @@
>
<v-layout row wrap>
<!-- General information -->
<v-flex xs12 md6 lg4>
<v-flex xs12 md6 lg4 xl3>
<v-card>
<v-toolbar class="primary white--text" dense>
<v-icon class="white--text">format_list_bulleted</v-icon>
......@@ -40,9 +40,14 @@
</v-list-tile-content>
</v-list-tile>
</template>
<v-expansion-panel>
<v-expansion-panel v-if="sequence">
<v-expansion-panel-content>
<template v-slot:header><div>FASTA sequence</div></template>
<template v-slot:header>
<div>
<v-icon small color="primary">fas fa-file-alt</v-icon>
<span class="subheading ml-3">FASTA sequence</span>
</div>
</template>
<div>
<v-textarea
readonly
......@@ -64,8 +69,14 @@
</v-card>
</v-flex>
<!-- KEGG Function -->
<KeggCard v-if="keggId" :keggId='keggId'></KeggCard>
<EggNogCard v-if="eggnogId" :eggnogId='eggnogId'></EggNogCard>
<template v-for="keggId in keggIds">
<KeggCard v-if="keggId" :keggId='keggId'></KeggCard>
</template>
<!-- EggNOG -->
<template v-if="eggnogId" v-for="eggnogId in eggnogIds">
<EggNogCard :eggnogId='eggnogId'></EggNogCard>
</template>
<!-- Taxonomy -->
<TaxonomyCard v-if="taxonomyId" :taxonomyId='taxonomyId'></TaxonomyCard>
</v-layout>
</v-container>
......
......@@ -11,9 +11,9 @@ export default {
geneId: '',
geneDetail: [],
sequence: '',
keggId: '',
keggIds: [],
taxonomyId: '',
eggnogId: '',
eggnogIds: [],
notFound: false,
};
},
......@@ -32,7 +32,7 @@ export default {
this.geneDetail = [
{
title: 'ID',
content: response.data.geneId,
content: response.data.gene_id,
},
{
title: 'Name',
......@@ -47,14 +47,16 @@ export default {
content: response.data.source,
},
];
this.sequence = '>' + response.data.geneId + '\n' + response.data.sequence;
if (response.data.sequence) {
this.sequence = '>' + response.data.gene_id + '\n' + response.data.sequence;
}
if (response.data.functions.length > 0) {
response.data.functions.forEach(funcAnnot => {
if (funcAnnot.source == 'kegg') {
this.keggId = funcAnnot.function_id;
this.keggIds.push(funcAnnot.function_id);
}
else if (funcAnnot.source == 'eggnog') {
this.eggnogId = funcAnnot.function_id;