Skip to content

Commit

Permalink
add basic evidence viewer section (#212)
Browse files Browse the repository at this point in the history
- fix table css bug, and safari header title bug
- rename selected association vars
- add basic evidence summary section
- change gene symbol to full name
- remove "table evidence viewer" e2e test because there will only be one
simplified evidence view now
  • Loading branch information
vincerubinetti authored Jul 14, 2023
1 parent 4593cf5 commit d05abbe
Show file tree
Hide file tree
Showing 9 changed files with 146 additions and 105 deletions.
59 changes: 2 additions & 57 deletions frontend/e2e/node.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,17 +273,11 @@ test("Association table has extra metadata columns", async ({ page }) => {
await expect(page.getByText(/Publisher/i).first()).toBeVisible();
});

test("Evidence summary viewer works", async ({ page }) => {
test.skip(true, "No fixture data yet");
test("Evidence viewer works", async ({ page }) => {
test.skip(true, "Fixture data not stable yet");

await page.goto("/node/MONDO:0007947");

/** click first evidence button (in first association in summary mode) */
await page
.locator("button", { hasText: /Evidence/i })
.first()
.click();

/** get evidence section */
const evidence = page.locator("#evidence").locator("..");

Expand Down Expand Up @@ -317,55 +311,6 @@ test("Evidence summary viewer works", async ({ page }) => {
).toHaveAttribute("href", "http://www.ncbi.nlm.nih.gov/pubmed/10489951");
});

test("Evidence table viewer works", async ({ page }) => {
test.skip(true, "No fixture data yet");

await page.goto("/node/MONDO:0007947");

/** go to first association evidence and switch to table mode */
await page
.locator("button", { hasText: /Evidence/ })
.first()
.click();
await page
.locator("#evidence")
.locator("..")
.getByText(/table/i)
.first()
.click();

/** check for all evidence columns */
await expect(page.getByText(/Subject/i).first()).toBeVisible();
await expect(page.getByText(/Relation/i).first()).toBeVisible();
await expect(page.getByText(/Object/i).first()).toBeVisible();
await expect(page.getByText(/Evidence Codes/i).first()).toBeVisible();
await expect(page.getByText(/Publications/i).first()).toBeVisible();
await expect(page.getByText(/Sources/i).first()).toBeVisible();
await expect(page.getByText(/References/i).first()).toBeVisible();

/** check links in cells */
await expect(
page.getByText(/experimental evidence used in manual assertion/i).first()
).toHaveAttribute("href", "http://purl.obolibrary.org/obo/ECO_0000269");
await expect(page.getByText(/#hpoa/i).first()).toHaveAttribute(
"href",
"https://archive.monarchinitiative.org/#hpoa"
);
await expect(page.getByText(/PMID:10489951/i).first()).toHaveAttribute(
"href",
"http://www.ncbi.nlm.nih.gov/pubmed/10489951"
);

/** check that all publications show on hover */
await page
.getByText(/and 2 more/i)
.first()
.dispatchEvent("mouseenter");
await expect(
page.getByText(/PMID:3189335.*Marfan syndrome/i).first()
).toBeVisible();
});

test("Breadcrumbs section works", async ({ page, browserName }) => {
test.skip(true, "No fixture data yet");

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/AppTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ const ariaSort = computed(() => {
}

.table {
display: grid;
display: inline-grid;
border-collapse: collapse;
}

Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/TheHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ $wrap: 600px;
letter-spacing: 1px;
line-height: $spacing - 0.3;
text-transform: uppercase;
white-space: nowrap;
}

@media (max-width: $wrap) {
Expand Down
1 change: 1 addition & 0 deletions frontend/src/global/icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ const icons: IconDefinition[] = [
fas.faMaximize,
fas.faMinimize,
fas.faNewspaper,
fas.faNotesMedical,
fas.faPaperPlane,
fas.faPauseCircle,
fas.faPersonRunning,
Expand Down
47 changes: 20 additions & 27 deletions frontend/src/pages/node/AssociationsSummary.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,49 +17,42 @@

<!-- result -->
<div
v-for="(association, index) in associations.items"
v-for="(item, index) in associations.items"
:key="index"
class="result"
>
<AppFlex direction="col" h-align="left" gap="small" class="details">
<AppNodeBadge
:node="{
id: association.subject,
name: association.subject_label,
category: association.subject_category,
id: item.subject,
name: item.subject_label,
category: item.subject_category,
}"
:link="node.id === association.object"
:link="node.id === item.object"
/>
<AppPredicateBadge :association="association" :vertical="true" />
<AppPredicateBadge :association="item" :vertical="true" />
<AppNodeBadge
:node="{
id: association.object,
name: association.object_label,
category: association.object_category,
id: item.object,
name: item.object_label,
category: item.object_category,
}"
:link="node.id === association.subject"
:link="node.id === item.subject"
/>
</AppFlex>

<AppButton
v-tooltip="
association.id === selectedAssociation?.id
item.id === association?.id
? 'Viewing supporting evidence. Click again to hide.'
: 'View supporting evidence for this association'
"
class="evidence"
:text="`Evidence (${association.evidence_count || 0})`"
:aria-pressed="association.id === selectedAssociation?.id"
:icon="association.id === selectedAssociation?.id ? 'check' : 'flask'"
:color="
association.id === selectedAssociation?.id ? 'primary' : 'secondary'
"
@click="
emit(
'select',
association.id === selectedAssociation?.id ? undefined : association
)
"
:text="`Evidence (${item?.evidence_count || 0})`"
:aria-pressed="item.id === association?.id"
:icon="item.id === association?.id ? 'check' : 'flask'"
:color="item.id === association?.id ? 'primary' : 'secondary'"
@click="emit('select', item.id === association?.id ? undefined : item)"
/>
</div>
</template>
Expand All @@ -78,9 +71,9 @@ type Props = {
/** current node */
node: Node;
/** selected association category */
selectedCategory: Option;
category: Option;
/** selected association */
selectedAssociation?: DirectionalAssociation;
association?: DirectionalAssociation;
};

const props = defineProps<Props>();
Expand All @@ -105,15 +98,15 @@ const {
throw new Error("No association info available");

/** get association data */
return await getTopAssociations(props.node.id, props.selectedCategory.id);
return await getTopAssociations(props.node.id, props.category.id);
},

/** default value */
{ items: [], limit: 0, offset: 0, total: 0 }
);

/** get associations when category changes */
watch(() => props.selectedCategory, getAssociations);
watch(() => props.category, getAssociations);

/** get associations on load */
onMounted(getAssociations);
Expand Down
25 changes: 12 additions & 13 deletions frontend/src/pages/node/AssociationsTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,19 @@
<template #evidence="{ cell, row }">
<AppButton
v-tooltip="
row.id === selectedAssociation?.id
row.id === association?.id
? 'Viewing supporting evidence. Click again to hide.'
: 'View supporting evidence for this association'
"
class="evidence"
:text="String(cell || 0)"
:aria-pressed="row.id === selectedAssociation?.id"
:icon="row.id === selectedAssociation?.id ? 'check' : 'flask'"
:color="row.id === selectedAssociation?.id ? 'primary' : 'secondary'"
:aria-pressed="row.id === association?.id"
:icon="row.id === association?.id ? 'check' : 'flask'"
:color="row.id === association?.id ? 'primary' : 'secondary'"
@click="
emit(
'select',
(row.id === selectedAssociation?.id
(row.id === association?.id
? undefined
: row) as DirectionalAssociation
)
Expand Down Expand Up @@ -122,9 +122,9 @@ interface Props {
/** current node */
node: Node;
/** selected association category */
selectedCategory: Option;
category: Option;
/** selected association */
selectedAssociation?: DirectionalAssociation;
association?: DirectionalAssociation;
}

const props = defineProps<Props>();
Expand Down Expand Up @@ -191,8 +191,7 @@ const cols = computed((): Cols => {

/** phenotype specific columns */
if (
props.selectedCategory.label ===
"biolink:DiseaseToPhenotypicFeatureAssociation"
props.category.label === "biolink:DiseaseToPhenotypicFeatureAssociation"
) {
extraCols.push(
{
Expand All @@ -211,7 +210,7 @@ const cols = computed((): Cols => {
}

/** publication specific columns */
if (props.selectedCategory.label === "biolink:Publication")
if (props.category.label === "biolink:Publication")
extraCols.push(
{
id: "author",
Expand Down Expand Up @@ -271,7 +270,7 @@ const {
/** get association data */
const response = await getAssociations(
props.node.id,
props.selectedCategory.id,
props.category.id,
start.value,
perPage.value,
search.value
Expand Down Expand Up @@ -301,7 +300,7 @@ async function download() {
/** attempt to request all rows */
const response = await getAssociations(
props.node.id,
props.selectedCategory.id,
props.category.id,
0,
max
);
Expand All @@ -310,7 +309,7 @@ async function download() {

/** get associations when category or table state changes */
watch(
() => props.selectedCategory,
() => props.category,
async () => await queryAssociations(true)
);
watch(
Expand Down
98 changes: 98 additions & 0 deletions frontend/src/pages/node/EvidenceViewer.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<!--
node page associations section, viewer for supporting evidence of an
association
-->

<template>
<AppSection>
<AppHeading icon="flask">Evidence</AppHeading>

<div>
Evidence for the selected association, <br />
<AppNodeBadge :node="node" />&nbsp;
<AppPredicateBadge :association="association" />&nbsp;
<AppNodeBadge
:node="{
id: association.subject,
name: association.subject_label,
category: association.subject_category,
}"
/>
</div>

<AppDetails>
<AppDetail
title="Evidence Codes"
:count="association.evidence_count"
icon="flask"
:big="true"
>
<AppFlex gap="small" h-align="left">
<span
v-for="(source, index) in association.has_evidence"
:key="index"
>{{ source }}</span
>
</AppFlex>
</AppDetail>

<AppDetail title="Primary Knowledge Source" icon="lightbulb">
<span>{{ association.primary_knowledge_source }}</span>
</AppDetail>

<AppDetail title="Provided By" icon="notes-medical">
<span>{{ association.provided_by }}</span>
</AppDetail>

<AppDetail
title="Publications"
:count="association.publications?.length"
icon="book"
:big="true"
>
<AppFlex gap="small" h-align="left">
<span
v-for="(publication, index) of association.publications"
:key="index"
>
{{ publication }}
</span>
</AppFlex>
</AppDetail>
</AppDetails>
</AppSection>
</template>

<script setup lang="ts">
import { onMounted, watch } from "vue";
import AppDetails from "@/components/AppDetails.vue";
import AppDetail from "@/components/AppDetail.vue";
import AppNodeBadge from "@/components/AppNodeBadge.vue";
import AppPredicateBadge from "@/components/AppPredicateBadge.vue";
import type { DirectionalAssociation, Node } from "@/api/model";
import { scrollToElement } from "@/router";
import { waitFor } from "@/util/dom";

interface Props {
/** current node */
node: Node;
/** selected association */
association: DirectionalAssociation;
}

const props = defineProps<Props>();

/** scroll evidence section into view */
async function scrollIntoView() {
scrollToElement(await waitFor("#evidence"));
}

watch(() => props.association, scrollIntoView);
onMounted(scrollIntoView);
</script>

<style lang="scss" scoped>
.arrow {
color: $gray;
}
</style>
Loading

0 comments on commit d05abbe

Please sign in to comment.