Skip to content

Commit

Permalink
NN-630 complete term view
Browse files Browse the repository at this point in the history
  • Loading branch information
anlisha-maharjan committed Dec 12, 2024
1 parent 878e5b2 commit 30744b2
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 204 deletions.
4 changes: 2 additions & 2 deletions frontend/src/components/pathwaytools/PathwayGraphGraphs.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<template>
<!-- <template>
<div id="pathways-graphs">
<div class="tool-section-term">
<div
Expand Down Expand Up @@ -56,4 +56,4 @@ export default {
z-index: 999;
font-family: "ABeeZee", sans-serif;
}
</style>
</style> -->
290 changes: 90 additions & 200 deletions frontend/src/components/pathwaytools/PathwayGraphList.vue
Original file line number Diff line number Diff line change
@@ -1,121 +1,102 @@
<template>
<div id="pathways-list">
<div class="tool-section-term">
<div class="pathway-search">
<img class="pathway-search-icon" src="@/assets/toolbar/search.png" />
<input
type="text"
v-model="search_raw"
class="empty"
placeholder="Find your pathways"
/>
</div>
<div class="filter-section">
<div
id="pathway-filter"
class="pre-full"
v-on:click="handling_filter_menu()"
:class="{ full: category_filtering == true }"
>
<span>{{ category }}</span>
<img
class="remove-filter"
src="@/assets/pathwaybar/cross.png"
v-on:click.stop="active_categories(null)"
v-if="category !== 'Filter'"
/>
</div>
<EmptyState v-if="term_data == null" message="There is no generated terms.">
</EmptyState>

<Listbox v-if="term_data !== null" v-model="selected_pathway" optionLabel="name" :options="filt_terms" :pt="{
header: { class: 'sticky top-0 flex-1 !px-0 bg-[var(--card-bg)] z-[1] order-1' },
listContainer: { class: 'order-3' },
list: { class: '!p-0' },
emptyMessage: { class: '!flex !justify-center !items-center !text-sm !text-slate-500 dark:!text-slate-300' },
option: {
class:
'!px-0 !py-1.5 !text-slate-500 dark:!text-slate-300 leading-tight transition-all duration-300 ease-in-out',
},
}" listStyle="max-height:100%" class="h-full flex flex-col !p-0 !bg-transparent !border-0"
@update:modelValue="select_term" :tabindex="0" emptyMessage="No terms available.">

<template #footer>
<header class="sticky top-0 bg-[var(--card-bg)] pt-3 items-center gap-2 z-[1] order-1">
<!-- filter -->
<InputGroup>
<InputGroupAddon class="!px-3">
<MultiSelect v-model="selected_categories" optionLabel="label" placeholder="Filter" showClear
resetFilterOnClear filterPlaceholder="Search categories" filter class="!w-60 !p-0 !border-0"
emptyMessage="No categories available" emptyFilterMessage="No categories available"
:selectedItemsLabel="`${selected_categories?.length} categories`" :options="filter_terms"
:maxSelectedLabels="1" :pt="{
clearIcon: { class: '!w-3.5 !h-3.5 !absolute !right-5 rounded-full z-[1]' },
overlay: { class: '!w-[18rem]' },
label: { class: 'max-w-[100px] !py-0 !px-0 text-[15px] !line-clamp-1' },
dropdown: { class: '!w-auto ml-6' },
optionLabel: { class: 'whitespace-normal' }
}" />
</InputGroupAddon>

<IconField class="w-full">
<InputText v-model="search_raw" placeholder="Search pathway" class="w-full" />
<InputIcon class="z-10 pi pi-search" />
</IconField>
</InputGroup>

<!-- sorting -->
<div
id="pathway-filter-categories"
v-show="category_filtering == true && terms !== null"
>
<div
class="element"
v-for="(entry, index) in filter_terms"
:key="index"
v-on:click="active_categories(entry.label)"
:class="{ active_cat: active_categories_set.has(entry.label) }"
>
<a>{{ entry.label }}</a>
</div>
</div>
</div>
</div>
<div class="list-section">
<div class="sorting">
<a
class="enrichment_filter"
v-on:click="
class="grid grid-cols-12 items-center gap-2 py-2 bg-[var(--card-bg)] shadow-[0_10px_30px_-18px_#34343D] dark:shadow-[0_10px_30px_-18px_#ffffff] z-[1]">
<a class="flex items-center justify-start col-span-9 gap-1 text-right cursor-pointer" v-on:click="
sort_alph = sort_alph === 'asc' ? 'dsc' : 'asc';
sort_fdr = '';
"
>functional enrichment pathways ({{ filt_terms.size }})</a
>
<a
class="fdr_filter"
v-on:click="
sort_fdr = '';
">
Functional enrichment pathways ({{ filt_terms.length }})

<span :class="`material-symbols-rounded text-base cursor-pointer
${sort_alph ? 'text-primary-500' : 'text-slate-600'}`">
{{ !sort_alph ? "swap_vert" : sort_alph === "asc" ? "south" : "north" }}
</span>
</a>

<a class="flex items-center justify-end col-span-3 gap-1 text-right cursor-pointer" v-on:click="
sort_fdr = sort_fdr === 'asc' ? 'dsc' : 'asc';
sort_alph = '';
"
>fdr rate</a
>
</div>
sort_alph = '';
">
Fdr rate

<span :class="`material-symbols-rounded text-base cursor-pointer
${sort_fdr ? 'text-primary-500' : 'text-slate-600'}`">
{{ !sort_fdr ? "swap_vert" : sort_fdr === "asc" ? "south" : "north" }}
</span>
</a>
</div>
</header>
</template>
<!-- options -->
<template #option="slotProps">
<div :class="`grid items-center w-full grid-cols-12 gap-2 ${slotProps.selected ? '!text-primary-400' : ''}`">
<span class="col-span-8">{{ slotProps.option?.attributes?.["Name"] }}</span>

<span class="col-span-3 text-right">{{ slotProps.option?.attributes?.["FDR"]?.toExponential(2) }}</span>

<div
class="results"
v-if="term_data !== null"
tabindex="0"
@keydown="handleKeyDown"
ref="resultsContainer"
>
<table>
<tbody>
<tr
v-for="(entry, index) in filt_terms"
:key="index"
class="option"
:class="{ selected: selectedIndex === index }"
v-on:click="select_term(entry, index)"
>
<td></td>
<td>
<div class="pathway-text">
<a href="#" ref="selectedNodes">{{
entry.attributes["Name"]
}}</a>
</div>
</td>
<td>
<a class="fdr-class">{{
entry.attributes["FDR"].toExponential(2)
}}</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</template>
</Listbox>
</template>

<script>
import EmptyState from "@/components/verticalpane/EmptyState.vue";
export default {
name: "PathwayGraphList",
props: ["term_data", "terms", "filtered_terms"],
props: ["term_data", "mode"],
components: {
EmptyState
},
data() {
return {
search_raw: "",
filter_raw: "",
sort_fdr: "",
sort_alph: "",
category: "Filter",
category_filtering: false,
active_categories_set: new Set(),
selected_categories: [],
filter_terms: [],
bookmark_off: true,
favourite_tab: new Set(),
selectedIndex: -1,
mode: "term",
selected_pathway: "",
};
},
mounted() {
Expand All @@ -132,10 +113,10 @@ export default {
var com = this;
var filtered = com.term_data.nodes;
if (com.category != "Filter") {
if (com.selected_categories?.length) {
// If category is set, filter by category
filtered = filtered.filter(function (term) {
return com.active_categories_set.has(term.attributes["Category"]);
return com.selected_categories.some(el => el.label === term.attributes["Category"]);
});
}
Expand All @@ -154,8 +135,8 @@ export default {
? 1
: t1.attributes["Name"].toLowerCase() ===
t2.attributes["Name"].toLowerCase()
? 0
: -1;
? 0
: -1;
});
} else if (com.sort_alph == "dsc") {
filtered.sort(function (t1, t2) {
Expand All @@ -164,8 +145,8 @@ export default {
? 1
: t1.attributes["Name"].toLowerCase() ===
t2.attributes["Name"].toLowerCase()
? 0
: -1;
? 0
: -1;
});
}
Expand All @@ -182,30 +163,12 @@ export default {
}
this.$emit("filtered_terms_changed", filtered);
return new Set(filtered);
return filtered;
// return new Set(filtered);
},
},
methods: {
active_categories(category) {
if (!category) {
this.reset_categories();
return;
}
if (this.active_categories_set.has(category)) {
if (this.active_categories_set.size == 1) {
this.reset_categories();
return;
}
this.active_categories_set.delete(category);
} else {
this.active_categories_set.add(category);
}
this.category = [...this.active_categories_set].join(", ");
},
reset_categories() {
this.category = "Filter";
this.active_categories_set = new Set();
},
filter_options(terms) {
var com = this;
com.filter_terms = [];
Expand All @@ -216,83 +179,10 @@ export default {
com.filter_terms.push({ label: term });
});
},
select_term(term, index) {
select_term(term) {
var com = this;
this.selectedIndex = index;
com.emitter.emit("searchNode", { node: term, mode: this.mode });
},
scrollToSelected(selectedDiv) {
const parent = this.$refs.resultsContainer; // Updated line to use this.$refs
if (!selectedDiv) {
return;
}
const selectedDivPosition = selectedDiv.getBoundingClientRect();
const parentBorders = parent.getBoundingClientRect();
if (selectedDivPosition.bottom >= parentBorders.bottom) {
selectedDiv.scrollIntoView(false);
}
if (selectedDivPosition.top <= parentBorders.top) {
selectedDiv.scrollIntoView(true);
}
},
handleKeyDown(event) {
const keyCode = event.keyCode;
if (keyCode === 38) {
event.preventDefault();
if (this.selectedIndex > 0) {
this.selectedIndex--;
this.scrollToSelected(this.$refs.selectedNodes[this.selectedIndex]);
this.clickNode();
}
} else if (keyCode === 40) {
event.preventDefault();
if (this.selectedIndex < this.filt_terms.size - 1) {
this.selectedIndex++;
this.scrollToSelected(this.$refs.selectedNodes[this.selectedIndex]);
this.clickNode();
}
}
},
clickNode() {
const selectedNode = this.$refs.selectedNodes[this.selectedIndex];
if (selectedNode) {
selectedNode.click();
}
},
handling_filter_menu() {
var com = this;
if (!com.category_filtering) {
com.category_filtering = true;
// Add the event listener
document.addEventListener("mouseup", com.handleMouseUp);
} else {
com.category_filtering = false;
document.removeEventListener("mouseup", com.handleMouseUp);
}
},
handleMouseUp(e) {
var com = this;
var container = document.getElementById("pathway-filter-categories");
var container_button = document.getElementById("pathway-filter");
if (
!container.contains(e.target) &&
!container_button.contains(e.target)
) {
com.category_filtering = false;
// Remove the event listener
document.removeEventListener("mouseup", com.handleMouseUp);
}
},
},
};
</script>

<style></style>
4 changes: 2 additions & 2 deletions frontend/src/components/pathwaytools/PathwayGraphMenu.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<template>
<!-- <template>
<div
id="menu-tools"
:class="{
Expand Down Expand Up @@ -93,4 +93,4 @@ export default {
};
</script>

<style></style>
<style></style> -->

0 comments on commit 30744b2

Please sign in to comment.