Skip to content

Commit

Permalink
feat: :spakles: metakg preview on registry items
Browse files Browse the repository at this point in the history
  • Loading branch information
marcodarko committed Jan 25, 2024
1 parent 171907c commit bcc869b
Show file tree
Hide file tree
Showing 7 changed files with 437 additions and 4 deletions.
100 changes: 100 additions & 0 deletions web-app/src/assets/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,18 @@ code {
0 0 0 6px rgba(34, 237, 176, 0.2);
}

.metakg-cy {
width: 300px;
height: 300px;
display: block;
overflow: hidden;
margin: auto;
}

.metakg-card {
border-top: rgb(255, 115, 0) 5px solid !important;
}

.edge-table tr td {
padding: 2px;
}
Expand Down Expand Up @@ -182,6 +194,10 @@ code {
align-items: center;
}

.p-0 {
padding: 0 !important;
}

.p-1 {
padding: 1em !important;
}
Expand Down Expand Up @@ -492,6 +508,32 @@ a.middle-indicator-text {
transition: 0.7s;
}

.clearButtonSmall {
background-color: rgba(255, 255, 255, 0.1);
padding: 3px 5px;
border: solid rgb(250, 109, 0) 2px;
border-radius: 10px;
text-decoration: none;
color: rgb(250, 109, 0);
font-size: 0.9em;
font-weight: light;
font-variant: small-caps;
}

.clearButtonSmall:hover {
background-color: rgba(33, 163, 255, 0.3);
border: solid #7eccf0 2px;
color: rgb(50, 50, 148);
transition: 0.3s;
}

.clearButtonSmall:focus {
background-color: rgba(33, 163, 255, 0.3);
border: solid #7eccf0 2px;
color: rgb(39, 39, 39);
transition: 0.3s;
}

@media only screen and (max-width: 500px) {
.hideOnSmall {
display: none;
Expand Down Expand Up @@ -1072,6 +1114,64 @@ body {
opacity 300ms;
}

.align-items-start {
align-items: start;
}

.entityPill {
outline: none !important;
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
display: flex;
align-items: stretch;
margin: 5px;
/* Permalink - use to edit and share this gradient: https://colorzilla.com/gradient-editor/#eeeeee+0,eeeeee+100;Grey+Flat */
background: linear-gradient(
to bottom,
#eeeeee 0%,
#eeeeee 100%
); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
border-radius: 10px;
}

.entityPill div:first-child {
color: white;
text-shadow: 1px 1px 1px rgb(104, 104, 104);
font-weight: bold;
font-size: 13px;
display: flex;
align-items: center;
padding: 5px;
border-top-left-radius: 10px;
border-bottom-left-radius: 10px;
}

.entityPill div:nth-child(2) {
width: 20px;
background-color: rgb(208, 208, 208);
clip-path: polygon(0% 0%, 18% 0, 100% 50%, 17% 100%, 0% 100%);
}

.entityPill div:nth-child(3) {
font-weight: bold;
font-size: 10px;
/* Permalink - use to edit and share this gradient: https://colorzilla.com/gradient-editor/#eeeeee+0,eeeeee+100;Grey+Flat */
background: linear-gradient(
to bottom,
#eeeeee 0%,
#eeeeee 100%
); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */

display: flex;
align-items: center;
border-top-right-radius: 10px;
border-bottom-right-radius: 10px;
padding: 5px;
}

.apiStatus {
outline: none !important;
-moz-user-select: none;
Expand Down
30 changes: 30 additions & 0 deletions web-app/src/components/EntityPill.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<template>
<div class="entityPill" :class="'ep' + badgeID">
<div :style="{ 'background-color': color }">
{{ object }}
</div>
<div></div>
<div class="yellow">
<ul>
<li v-for="item in subjects" :key="item">{{ item }}</li>
</ul>
</div>
</div>
</template>

<script>
export default {
name: 'EntityPill',
data: function () {
return {
badgeID: Math.floor(Math.random() * 90000) + 10000
};
},
props: ['object', 'subjects'],
computed: {
color: function () {
return this.$store.getters.getEntityColor(this.object);
}
}
};
</script>
8 changes: 6 additions & 2 deletions web-app/src/components/RegistryItem.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div class="card">
<div class="card-content">
<div class="card-content" style="padding-bottom: 0px">
<span class="card-title">
<span class="blue-grey-text bold" v-text="api.info.title"></span>&nbsp;
<small class="grey-text lighter" v-text="api.info.version"> </small>
Expand Down Expand Up @@ -68,6 +68,8 @@
</template>
</div>
</div>
<!-- METAKG -->
<RegistryMetaKG :api="api"></RegistryMetaKG>
<!-- TOGGLE DETAILS -->
<div class="card-action grey lighten-3" v-if="total > 1" :class="showDetails ? 'blue' : 'grey'">
<button
Expand Down Expand Up @@ -277,6 +279,7 @@
<script>
import SourceStatus from '../components/SourceStatus.vue';
import UptimeStatus from '../components/UptimeStatus.vue';
import RegistryMetaKG from '../components/RegistryMetaKG.vue';
import CollapsibleText from '../components/CollapsibleText.vue';
import { truncate } from 'lodash';
import tippy from 'tippy.js';
Expand All @@ -289,7 +292,8 @@ export default {
components: {
SourceStatus,
UptimeStatus,
CollapsibleText
CollapsibleText,
RegistryMetaKG
},
data: function () {
return {
Expand Down
177 changes: 177 additions & 0 deletions web-app/src/components/RegistryMetaKG.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
<template>
<div class="p-1">
<p class="orange-text m-0" style="padding-bottom: 10px">
View biomedical entity knowledge available
<button @click="open = !open" type="button" class="clearButtonSmall">
{{ open ? 'CLOSE' : 'OPEN' }}
</button>
</p>
<div v-if="open" class="grey lighten-2 metakg-card p-0 row d-flex align-items-stretch">
<h3 class="p-2 grey-text" v-if="loading">Loading...</h3>
<template v-if="!loading && !noHits">
<div class="col s12 m8">
<h5 style="font-weight: lighter">Entity Relationship Overview</h5>
<div v-if="graphData" style="max-height: 500px; overflow-y: scroll">
<div class="d-flex flex-wrap align-items-start">
<template v-for="(subjects, object) in graphData" :key="object">
<EntityPill :object="object" :subjects="subjects"></EntityPill>
</template>
</div>
</div>
</div>
<div class="col s12 m4 grey darken-3">
<div class="d-flex justify-content-center">
<img class="scale-in-center" src="@/assets/img/metakg-01.png" width="80" />
<h5 class="white-text center" style="font-weight: lighter">MetaKG Explorer</h5>
</div>
<template v-if="networkData">
<SimpleNetwork :nodes="networkData.nodes" :edges="networkData.edges"></SimpleNetwork>
</template>
<p class="center">
<span class="white-text caps"> Explore {{ api.info.title }}'s MetaKG </span>
</p>
<div class="d-flex justify-content-center align-items-center p-1">
<router-link
class="btn btn-large purple white-text"
target="_blank"
:to="{
path: '/portal/translator/metakg',
query: {
'api.x-translator.component': api?.info?.['x-translator']?.component,
'api.name': api.info.title
}
}"
>Try It Now</router-link
>
</div>
</div>
</template>
<div v-if="!loading && noHits">
<p class="center grey-text p-2">Oops...Can't load this right now...</p>
</div>
</div>
</div>
</template>

<script>
import axios from 'axios';
import EntityPill from './EntityPill.vue';
import SimpleNetwork from './SimpleNetwork.vue';
export default {
name: 'RegistryMetaKG',
components: {
EntityPill,
SimpleNetwork
},
props: {
api: {
type: Object,
default: {}
}
},
data: function () {
return {
open: false,
loading: true,
graphData: null,
networkData: null,
noHits: false
};
},
watch: {
open: function (v) {
if (v) {
if (!this.graphData) {
this.sendRequest();
}
}
}
},
methods: {
getNetworkData(hits) {
let self = this;
let nodes = new Set();
let edges = [];
let nodeData = [];
let nodeWeight = {};
hits.forEach((hit) => {
if (hit.object in nodeWeight) {
nodeWeight[hit.object] += 1;
} else {
nodeWeight[hit.object] = 1;
}
if (hit.subject in nodeWeight) {
nodeWeight[hit.subject] += 1;
} else {
nodeWeight[hit.subject] = 1;
}
nodes.add(hit.object);
nodes.add(hit.subject);
edges.push({
group: 'edges',
data: {
id: Math.floor(100000 + Math.random() * 900000),
source: hit.subject,
target: hit.object
}
});
});
nodeData = [...nodes].map((node) => {
return {
group: 'nodes',
data: {
weight: nodeWeight[node] + 100,
id: node,
color: self.$store.getters.getEntityColor(node)
}
};
});
this.networkData = {
nodes: nodeData,
edges: edges
};
},
sendRequest() {
let self = this;
let base = process.env.NODE_ENV == 'development' ? 'https://dev.smart-api.info' : '';
axios
.get(
base +
'/api/metakg?size=20&q=(api.name:"' +
self.api.info.title +
'")&size=300&fields=object,subject'
)
.then((res) => {
let data = {};
if (res.data?.hits && res.data?.hits?.length) {
self.getNetworkData(res.data.hits);
res.data.hits.forEach((item) => {
if (!(item.subject in data)) {
data[item.subject] = [item.object];
} else {
if (item.subject in data && !data[item.subject].includes(item.object)) {
data[item.subject].push(item.object);
}
}
});
self.graphData = data;
self.loading = false;
self.noHits = false;
} else {
self.noHits = true;
self.loading = false;
}
})
.catch((err) => {
self.loading = false;
self.noHits = true;
throw err;
});
}
}
};
</script>
Loading

0 comments on commit bcc869b

Please sign in to comment.