Skip to content

Commit c578d81

Browse files
authored
Merge pull request monarch-initiative#363 from iimpulse/feature/disease-carousel
Feature/disease carousel
2 parents 5be6108 + af9562a commit c578d81

10 files changed

+427
-56
lines changed

Diff for: package-lock.json

+77
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: package.json

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"dependencies": {
2323
"@babel/polyfill": "^7.8.7",
2424
"acorn": "^6.4.1",
25+
"apexcharts": "^3.21.0",
2526
"axios": "^0.19.2",
2627
"babel-eslint": "^10.0.3",
2728
"bbop-graph": "0.0.19",

Diff for: public/mondo_ids.txt

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
MONDO:0100096
2-
MONDO:0010726
3-
MONDO:0008265
4-
MONDO:0017048
1+
MONDO:0100096 2020-08-04
2+
MONDO:0010726 2020-06-24
3+
MONDO:0008265 2020-06-23
4+
MONDO:0017048 2020-05-19

Diff for: src/api/BioLink.js

+18-2
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,6 @@ export function getCurrentServerEnvironment() {
113113

114114
export async function getNode(nodeId, nodeType) {
115115
let bioentityUrl = `${biolink}bioentity/${nodeType}/${nodeId}`;
116-
// console.log('getNodeSummary', nodeId, nodeType, bioentityUrl);
117-
118116
if (nodeType === 'function') {
119117
bioentityUrl = `${biolink}bioentity/${nodeId}`;
120118
}
@@ -762,3 +760,21 @@ export async function getEvidence(evidenceId, nodeType) {
762760
});
763761
});
764762
}
763+
764+
export async function getPhenotypeCategories(diseaseId) {
765+
const biolinkUrl = `${biolink}bioentity/disease/${diseaseId}/phenotypes`;
766+
const params = new URLSearchParams();
767+
params.append('rows', 0);
768+
params.append('facet', true);
769+
params.append('unselect_evidence', false);
770+
params.append('exclude_automatic_assertions', false);
771+
params.append('fetch_objects', false);
772+
params.append('use_compact_associations', false);
773+
params.append('direct', false);
774+
params.append('direct_taxon', false);
775+
const response = await axios.get(biolinkUrl, { params });
776+
if (response.data.facet_counts.closure_bin) {
777+
return response.data.facet_counts.closure_bin;
778+
}
779+
return {};
780+
}

Diff for: src/api/Team.js renamed to src/api/Resources.js

+22-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import axios from 'axios';
22
import yaml from 'js-yaml';
33

4-
export default async function getTeam() {
4+
export async function getTeam() {
55
const teamUrl = `${process.env.BASE_URL}team.yaml`;
66
const teamResponse = await axios.get(teamUrl);
77

@@ -29,3 +29,24 @@ export default async function getTeam() {
2929

3030
return team;
3131
}
32+
33+
export async function getRecentlyCurated() {
34+
const recentlyCuratedUrl = `${process.env.BASE_URL}mondo_ids.txt`;
35+
const curatedResponse = await axios.get(recentlyCuratedUrl);
36+
try {
37+
const curatedLines = [];
38+
curatedResponse.data.split('\n').forEach((line) => {
39+
const pieces = line.split('\t');
40+
const mondo = pieces[0];
41+
const date = pieces[1];
42+
line = {};
43+
line.mondo = mondo;
44+
line.date = Date.parse(date);
45+
curatedLines.push(line);
46+
});
47+
curatedLines.sort((a, b) => b.date - a.date);
48+
return curatedLines.length > 5 ? curatedLines.slice(6) : curatedLines;
49+
} catch (e) {
50+
return [];
51+
}
52+
}

Diff for: src/components/DiseaseCarousel.vue

+164
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
<template>
2+
<div>
3+
<div v-if="activeCarousel" class="disease-carousel">
4+
<h3 class="carousel-title">
5+
Featured Diseases {{ featureDate }}
6+
</h3>
7+
<p class="carousel-sub">
8+
We are always updating our corpus of disease - phenotype associations to support current scientific understanding of disease.
9+
</p><div v-if="activeCarousel.id" class="row carousel-row">
10+
<div class="col-6 disease-information">
11+
<h3 class="disease-name">
12+
<a :href="'/disease/' + activeCarousel.id">
13+
{{ activeCarousel.label }}
14+
</a>
15+
<span class="disease-id">
16+
{{ activeCarousel.id }}
17+
</span>
18+
</h3>
19+
<p class="disease-description">
20+
{{ activeCarousel.description }}
21+
</p>
22+
<b-button class="linked-data-btn" :to="'/disease/' + activeCarousel.id">
23+
View Linked Data
24+
<i class="fa fa-caret-right" />
25+
</b-button>
26+
</div>
27+
<div class="col-6 disease-phenotypes">
28+
<histo-pheno :active-item="activeCarousel" />
29+
</div>
30+
</div>
31+
<div v-else class="disease-loading">
32+
<b-spinner label="Loading..." variant="light" />
33+
</div>
34+
</div>
35+
</div>
36+
</template>
37+
<script>
38+
import HistoPheno from '@/components/HistoPheno.vue';
39+
import { getRecentlyCurated } from '@/api/Resources';
40+
import { getPhenotypeCategories, getBasicNode } from '@/api/BioLink';
41+
42+
export default {
43+
components: {
44+
'histo-pheno': HistoPheno
45+
},
46+
data() {
47+
return {
48+
carouselData: [],
49+
activeCarousel: {},
50+
featureDate: ''
51+
};
52+
},
53+
async mounted() {
54+
const recentlyCurated = await getRecentlyCurated();
55+
await Promise.all(recentlyCurated.map(async (curated) => {
56+
const categories = await getPhenotypeCategories(curated.mondo);
57+
const basicInfo = await getBasicNode(curated.mondo);
58+
if (!Object.values(categories).every(x => x === 0)) {
59+
this.carouselData.push({
60+
categories,
61+
label: basicInfo.label,
62+
id: curated.mondo,
63+
description: basicInfo.description,
64+
date: curated.date
65+
});
66+
}
67+
}));
68+
if (this.carouselData.length > 0) {
69+
this.setDate(this.carouselData[0].date);
70+
this.changeActiveCarouselItem();
71+
setInterval(this.changeActiveCarouselItem, 6000);
72+
}
73+
},
74+
methods: {
75+
changeActiveCarouselItem() {
76+
const pos = this.carouselData.map(x => x.id).indexOf(this.activeCarousel.id);
77+
const limit = this.carouselData.length - 1;
78+
const next = pos + 1;
79+
if (pos === limit || pos === -1) {
80+
this.activeCarousel = this.carouselData[0];
81+
} else {
82+
this.activeCarousel = this.carouselData[next];
83+
}
84+
},
85+
isEmpty() {
86+
return Object.keys(this.activeCarousel).length === 0;
87+
},
88+
setDate(date) {
89+
date = new Date(date);
90+
const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
91+
const month = months[date.getMonth()];
92+
const year = date.getFullYear();
93+
this.featureDate = '- ' + month + ' ' + year;
94+
}
95+
}
96+
};
97+
</script>
98+
99+
<style scoped>
100+
101+
.disease-carousel {
102+
height: 425px;
103+
}
104+
105+
.disease-carousel .carousel-title {
106+
margin: 0;
107+
padding: 1rem 0 .5rem 0;
108+
text-align: center;
109+
color: white;
110+
text-transform: uppercase;
111+
}
112+
113+
.disease-carousel .carousel-sub {
114+
color: white;
115+
text-align: center;
116+
margin-bottom: .5rem;
117+
font-style: italic;
118+
}
119+
120+
.disease-carousel .carousel-row {
121+
height: 80%;
122+
}
123+
124+
.disease-carousel .disease-information {
125+
padding: .5rem 1rem 2.5rem 5.5rem;
126+
color: white;
127+
}
128+
129+
.disease-carousel .disease-information .disease-name {
130+
text-transform: capitalize;
131+
}
132+
133+
.disease-carousel .disease-information .disease-name a {
134+
color: white !important;
135+
}
136+
137+
.disease-carousel .disease-information .disease-name .disease-id {
138+
font-size: 1rem;
139+
color: lightgray
140+
}
141+
142+
.disease-carousel .disease-information .disease-description {
143+
margin-top: 1.5rem;
144+
}
145+
146+
.disease-carousel .linked-data-btn {
147+
color: black;
148+
background: #CCE34C;
149+
border-radius: 0;
150+
}
151+
152+
.disease-carousel .linked-data-btn .fa-caret-right {
153+
margin-left: 15px;
154+
}
155+
156+
.disease-phenotypes {
157+
height: 100%;
158+
}
159+
160+
.disease-loading {
161+
text-align: center;
162+
margin-top: 2.5rem;
163+
}
164+
</style>

0 commit comments

Comments
 (0)