mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-21 13:50:20 +08:00
Merge pull request #17847 from ahmedhamidawan/tool_panel_slow_computed
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { BAlert } from "bootstrap-vue";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { computed, type ComputedRef, onMounted, onUnmounted, type PropType, type Ref, ref, watch } from "vue";
|
||||
import { computed, type ComputedRef, onMounted, onUnmounted, type PropType, watch } from "vue";
|
||||
import { useRouter } from "vue-router/composables";
|
||||
|
||||
import { type Tool, type ToolSection, useToolStore } from "@/stores/toolStore";
|
||||
@@ -12,6 +13,7 @@ import { type ToolSearchKeys } from "../utilities";
|
||||
|
||||
import DelayedInput from "@/components/Common/DelayedInput.vue";
|
||||
import FilterMenu from "@/components/Common/FilterMenu.vue";
|
||||
import LoadingSpan from "@/components/LoadingSpan.vue";
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
@@ -67,8 +69,6 @@ const emit = defineEmits<{
|
||||
(e: "onQuery", query: string): void;
|
||||
}>();
|
||||
|
||||
const searchWorker: Ref<Worker | undefined> = ref(undefined);
|
||||
|
||||
const localFilterText = computed({
|
||||
get: () => {
|
||||
return props.query !== null ? props.query : "";
|
||||
@@ -112,6 +112,7 @@ const ToolFilters: ComputedRef<Filtering<string>> = computed(() => new Filtering
|
||||
|
||||
const { currentFavorites } = storeToRefs(useUserStore());
|
||||
const toolStore = useToolStore();
|
||||
const { searchWorker } = storeToRefs(toolStore);
|
||||
|
||||
const sectionNames = toolStore.sectionDatalist("default").map((option: { value: string; text: string }) => option.text);
|
||||
const ontologyList = toolStore
|
||||
@@ -119,8 +120,10 @@ const ontologyList = toolStore
|
||||
.concat(toolStore.sectionDatalist("ontology:edam_operations"));
|
||||
|
||||
onMounted(() => {
|
||||
searchWorker.value = new Worker(new URL("../toolSearch.worker.js", import.meta.url));
|
||||
|
||||
// initialize worker
|
||||
if (!searchWorker.value) {
|
||||
searchWorker.value = new Worker(new URL("components/Panels/toolSearch.worker.js", import.meta.url));
|
||||
}
|
||||
searchWorker.value.onmessage = ({ data }) => {
|
||||
const { type, payload, sectioned, query, closestTerm } = data;
|
||||
if (type === "searchToolsByKeysResult" && query === props.query) {
|
||||
@@ -134,7 +137,10 @@ onMounted(() => {
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
searchWorker.value?.terminate();
|
||||
// The worker is not terminated but it will not be listening to messages
|
||||
if (searchWorker.value?.onmessage) {
|
||||
searchWorker.value.onmessage = null;
|
||||
}
|
||||
});
|
||||
|
||||
watch(
|
||||
@@ -178,7 +184,7 @@ function onAdvancedSearch(filters: any) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="searchWorker">
|
||||
<FilterMenu
|
||||
v-if="props.enableAdvanced"
|
||||
:class="!propShowAdvanced && 'mb-3'"
|
||||
@@ -245,4 +251,7 @@ function onAdvancedSearch(filters: any) {
|
||||
:placeholder="placeholder"
|
||||
@change="checkQuery" />
|
||||
</div>
|
||||
<BAlert v-else class="mb-3" variant="info" show>
|
||||
<LoadingSpan message="Loading Tool Search" />
|
||||
</BAlert>
|
||||
</template>
|
||||
|
||||
@@ -135,8 +135,6 @@ const localPanel: ComputedRef<Record<string, Tool | ToolSectionType> | null> = c
|
||||
}
|
||||
});
|
||||
|
||||
const sectionIds = computed(() => Object.keys(localPanel.value || {}));
|
||||
|
||||
const favWorkflows = computed(() => {
|
||||
const Galaxy = getGalaxyInstance();
|
||||
const storedWorkflowMenuEntries = Galaxy && Galaxy.config.stored_workflow_menu_entries;
|
||||
@@ -298,10 +296,10 @@ function setButtonText() {
|
||||
:query-filter="queryFilter || undefined"
|
||||
:disable-filter="true"
|
||||
@onClick="onToolClick" />
|
||||
<div v-for="(sectionId, key) in sectionIds" :key="key">
|
||||
<div v-for="(panel, key) in localPanel" :key="key">
|
||||
<ToolSection
|
||||
v-if="localPanel[sectionId]"
|
||||
:category="localPanel[sectionId] || {}"
|
||||
v-if="panel"
|
||||
:category="panel || {}"
|
||||
:query-filter="queryFilter || undefined"
|
||||
@onClick="onToolClick" />
|
||||
</div>
|
||||
|
||||
@@ -34,7 +34,8 @@ const emit = defineEmits<{
|
||||
|
||||
const arePanelsFetched = ref(false);
|
||||
const toolStore = useToolStore();
|
||||
const { currentPanelView, defaultPanelView, isPanelPopulated, loading, panel, panelViews } = storeToRefs(toolStore);
|
||||
const { currentPanelView, defaultPanelView, isPanelPopulated, loading, panel, panelViews, currentPanel } =
|
||||
storeToRefs(toolStore);
|
||||
|
||||
const loadingView = ref<string | undefined>(undefined);
|
||||
const query = ref("");
|
||||
@@ -192,6 +193,9 @@ function onInsertWorkflowSteps(workflowId: string, workflowStepCount: number | u
|
||||
</b-badge>
|
||||
</div>
|
||||
</div>
|
||||
<b-alert v-else-if="currentPanel" class="m-2" variant="info" show>
|
||||
<LoadingSpan message="Loading Toolbox" />
|
||||
</b-alert>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -158,16 +158,22 @@ export function getValidToolsInCurrentView(
|
||||
isWorkflowPanel = false,
|
||||
excludedSectionIds: string[] = []
|
||||
) {
|
||||
const toolEntries = Object.entries(toolsById).filter(([, tool]) => {
|
||||
// filter on non-hidden, non-disabled, and workflow compatibile (based on props.workflow)
|
||||
return (
|
||||
!tool.hidden &&
|
||||
tool.disabled !== true &&
|
||||
!(isWorkflowPanel && !tool.is_workflow_compatible) &&
|
||||
!excludedSectionIds.includes(tool.panel_section_id)
|
||||
);
|
||||
});
|
||||
return Object.fromEntries(toolEntries);
|
||||
const excludeSet = new Set(excludedSectionIds);
|
||||
const validTools: Record<string, Tool> = {};
|
||||
|
||||
for (const [toolId, tool] of Object.entries(toolsById)) {
|
||||
const { panel_section_id, hidden, disabled, is_workflow_compatible } = tool;
|
||||
if (
|
||||
!excludeSet.has(panel_section_id) &&
|
||||
!hidden &&
|
||||
disabled !== true &&
|
||||
!(isWorkflowPanel && !is_workflow_compatible)
|
||||
) {
|
||||
validTools[toolId] = tool;
|
||||
}
|
||||
}
|
||||
|
||||
return validTools;
|
||||
}
|
||||
|
||||
/** Looks in each section of `currentPanel` and filters `section.tools` on `validToolIdsInCurrentView` */
|
||||
@@ -175,12 +181,16 @@ export function getValidToolsInEachSection(
|
||||
validToolIdsInCurrentView: string[],
|
||||
currentPanel: Record<string, Tool | ToolSection>
|
||||
) {
|
||||
// use a set for fast membership lookup
|
||||
const idSet = new Set(validToolIdsInCurrentView);
|
||||
return Object.entries(currentPanel).map(([id, section]) => {
|
||||
const validatedSection = { ...section } as ToolSection;
|
||||
if (validatedSection.tools && Array.isArray(validatedSection.tools)) {
|
||||
// assign sectionTools to avoid repeated getter access
|
||||
const sectionTools = validatedSection.tools;
|
||||
if (sectionTools && Array.isArray(sectionTools)) {
|
||||
// filter on valid tools and panel labels in this section
|
||||
validatedSection.tools = validatedSection.tools.filter((toolId) => {
|
||||
if (typeof toolId === "string" && validToolIdsInCurrentView.includes(toolId)) {
|
||||
validatedSection.tools = sectionTools.filter((toolId) => {
|
||||
if (typeof toolId === "string" && idSet.has(toolId)) {
|
||||
return true;
|
||||
} else if (typeof toolId !== "string") {
|
||||
// is a special case where there is a label within a section
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import axios from "axios";
|
||||
import { defineStore } from "pinia";
|
||||
import Vue, { computed, Ref, ref } from "vue";
|
||||
import Vue, { computed, Ref, ref, shallowRef } from "vue";
|
||||
|
||||
import { createWhooshQuery, filterTools, types_to_icons } from "@/components/Panels/utilities";
|
||||
import { useUserLocalStorage } from "@/composables/userLocalStorage";
|
||||
@@ -75,12 +75,14 @@ export interface PanelView {
|
||||
export const useToolStore = defineStore("toolStore", () => {
|
||||
const currentPanelView: Ref<string> = useUserLocalStorage("tool-store-view", "");
|
||||
const defaultPanelView: Ref<string> = ref("");
|
||||
const toolsById = ref<Record<string, Tool>>({});
|
||||
const toolsById = shallowRef<Record<string, Tool>>({});
|
||||
const toolResults = ref<Record<string, string[]>>({});
|
||||
const panel = ref<Record<string, Record<string, Tool | ToolSection>>>({});
|
||||
const panelViews = ref<Record<string, PanelView>>({});
|
||||
const loading = ref(false);
|
||||
|
||||
const searchWorker = ref<Worker | undefined>(undefined);
|
||||
|
||||
const getToolForId = computed(() => {
|
||||
return (toolId: string) => toolsById.value[toolId];
|
||||
});
|
||||
@@ -278,6 +280,7 @@ export const useToolStore = defineStore("toolStore", () => {
|
||||
currentPanel,
|
||||
isPanelPopulated,
|
||||
sectionDatalist,
|
||||
searchWorker,
|
||||
fetchToolForId,
|
||||
fetchTools,
|
||||
fetchPanelViews,
|
||||
|
||||
Reference in New Issue
Block a user