Skip to content

Commit

Permalink
remove bookmarked workflows from WorkflowBox
Browse files Browse the repository at this point in the history
  • Loading branch information
ahmedhamidawan committed May 30, 2023
1 parent 30481e1 commit a93ca37
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 185 deletions.
146 changes: 29 additions & 117 deletions client/src/components/Panels/WorkflowBox.vue
@@ -1,146 +1,58 @@
<script setup lang="ts">
import { getGalaxyInstance } from "@/app";
import { getAppRoot } from "@/onload";
import { withPrefix } from "@/utils/redirect";
import { useRouter } from "vue-router/composables";
import { ref, computed, onMounted, type ComputedRef } from "vue";
import { useWorkflowStore, type Workflow } from "@/stores/workflowStore";
import { computed, type ComputedRef } from "vue";
import WorkflowSearch from "@/components/Workflow/WorkflowSearch.vue";
import FavoritesButton from "@/components/Panels/Buttons/FavoritesButton.vue";
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import { faUpload } from "@fortawesome/free-solid-svg-icons";
import { faUpload, faGlobe } from "@fortawesome/free-solid-svg-icons";
import { library } from "@fortawesome/fontawesome-svg-core";
const workflowStore = useWorkflowStore();
const router = useRouter();
const query = ref("");
const queryPending = ref(false);
const showAdvanced = ref(false);
const panelFilter: ComputedRef<any> = computed(() => {
return { name: query.value };
});
// on Mount, load all Workflows
onMounted(async () => {
queryPending.value = true;
await workflowStore.fetchWorkflows(panelFilter.value);
queryPending.value = false;
});
//@ts-ignore bad library types
library.add(faUpload);
// @ts-ignore bad library types
library.add(faUpload, faGlobe);
// computed
const isUser: ComputedRef<boolean> = computed(() => {
const Galaxy = getGalaxyInstance();
return !!(Galaxy.user && Galaxy.user.id);
});
const workflows = computed(() => {
if (isUser.value) {
let results: Workflow[] = [];
if (query.value === "#favorites") {
const Galaxy = getGalaxyInstance();
results = Galaxy.config.stored_workflow_menu_entries;
} else if (!queryTooShort.value) {
results = workflowStore.getWorkflows(panelFilter.value);
}
return [
...results.map((wf) => {
return {
id: wf.id,
name: wf.name,
href: `${getAppRoot()}workflows/run?id=${wf.id}`,
};
}),
];
}
return [];
});
const hasWorkflows: ComputedRef<boolean> = computed(() => workflows.value.length !== 0);
const hasQuery: ComputedRef<boolean> = computed(() => query.value !== "");
const queryTooShort: ComputedRef<boolean> = computed(() => query.value !== "" && query.value.length < 3);
// functions
async function onQuery(q: string) {
query.value = !q ? "" : q;
queryPending.value = true;
if (!queryTooShort.value && q !== "#favorites") {
await workflowStore.fetchWorkflows(panelFilter.value);
}
queryPending.value = false;
}
function onOpen(route: string) {
router.push(route);
}
</script>

<template>
<div class="unified-panel" aria-labelledby="workflowbox-heading">
<div unselectable="on">
<div class="unified-panel-header-inner">
<nav class="d-flex justify-content-between mx-3 my-2">
<h2 v-if="!showAdvanced" id="workflowbox-heading" v-localize class="m-1 h-sm">Workflows</h2>
<h2 v-else id="workflowbox-heading" v-localize class="m-1 h-sm">Advanced Workflow Search</h2>

<h2 id="workflowbox-heading" v-localize class="m-1 h-sm">Workflows</h2>
<div v-if="isUser" class="panel-header-buttons">
<b-button-group>
<favorites-button v-if="!showAdvanced" :query="query" @onFavorites="onQuery" />
<b-button
v-b-tooltip.bottom.hover
data-description="create new workflow"
size="sm"
variant="link"
title="Create new workflow"
@click="$router.push('/workflows/create')">
<Icon fixed-width icon="plus" />
</b-button>
</b-button-group>
<b-button
v-b-tooltip.bottom.hover
data-description="create new workflow"
size="sm"
variant="link"
title="Create new workflow"
@click="$router.push('/workflows/create')">
<Icon fixed-width icon="plus" />
</b-button>
</div>
</nav>
</div>
</div>
<div v-if="!isUser">
<b-badge class="alert-info w-100">
Please <a :href="withPrefix('/login')">log in or register</a> to use this feature.
</b-badge>
</div>
<div v-else>
<div class="unified-panel-controls">
<WorkflowSearch
enable-advanced
:loading="queryPending"
:show-advanced.sync="showAdvanced"
:query="query"
@onQuery="onQuery" />
<div v-if="!showAdvanced">
<b-button
id="workflow-import"
class="upload-button"
size="sm"
@click="$router.push('/workflows/import')">
<FontAwesomeIcon icon="upload" />
Import Workflow
</b-button>
<div v-if="!queryPending" class="pb-2">
<b-badge class="alert-danger w-100">
<span v-if="queryTooShort">Search string too short!</span>
<span v-else-if="!hasQuery && !hasWorkflows">No workflows found!</span>
<span v-else-if="hasQuery && !hasWorkflows">No results found!</span>
</b-badge>
</div>
</div>
<div class="unified-panel-controls">
<div v-if="!isUser">
<b-badge class="alert-info w-100">
Please <a :href="withPrefix('/login')">log in or register</a> to create workflows.
</b-badge>
</div>
<div v-if="!showAdvanced" class="unified-panel-body">
<div class="toolMenuContainer">
<div id="internal-workflows" class="toolSectionBody">
<div class="toolSectionBg" />
<div v-for="wf in workflows" :key="wf.id" class="toolTitle">
<a class="title-link" href="javascript:void(0)" @click="onOpen(wf.href)">{{ wf.name }}</a>
</div>
</div>
</div>
<div v-else>
<b-button v-if="isUser" class="upload-button" size="sm" @click="$router.push('/workflows/import')">
<FontAwesomeIcon icon="upload" />
Import Workflow
</b-button>
<b-button class="upload-button" size="sm" @click="$router.push('/workflows/list_published')">
<FontAwesomeIcon icon="fa-globe" />
Published Workflows
</b-button>
<WorkflowSearch />
</div>
</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions client/src/components/Workflow/WorkflowList.vue
Expand Up @@ -186,6 +186,7 @@ export default {
// Render the published workflows version of this grid.
type: Boolean,
default: false,
},
query: {
type: String,
required: false,
Expand Down
63 changes: 23 additions & 40 deletions client/src/components/Workflow/WorkflowSearch.vue
@@ -1,9 +1,11 @@
<script setup lang="ts">
import { ref, type Ref } from "vue";
import { useRouter } from "vue-router/composables";
import DelayedInput from "@/components/Common/DelayedInput.vue";
import _l from "@/utils/localization";
import { createWorkflowQuery } from "@/components/Panels/utilities";
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import { faAngleDoubleUp, faAngleDoubleDown } from "@fortawesome/free-solid-svg-icons";
import { library } from "@fortawesome/fontawesome-svg-core";
const router = useRouter();
Expand All @@ -15,42 +17,22 @@ type FilterSettings = {
deleted?: boolean;
};
const emit = defineEmits<{
(e: "onQuery", query: string): void;
(e: "update:show-advanced", showAdvanced: boolean): void;
}>();
// @ts-ignore bad library types
library.add(faAngleDoubleUp, faAngleDoubleDown);
const props = defineProps({
enableAdvanced: { type: Boolean, default: false },
loading: { type: Boolean, default: false },
placeholder: { type: String, default: _l("search workflows") },
query: { type: String, default: null },
showAdvanced: { type: Boolean, default: false },
});
const favorites = ["#favs", "#favorites", "#favourites"];
const options = [
{ text: "Yes", value: true },
{ text: "No", value: false },
];
const filterSettings: Ref<FilterSettings> = ref({
published: false,
shared: false,
shared_with_me: false,
deleted: false,
});
function checkQuery(q: string) {
filterSettings.value.name = q;
if (favorites.includes(q)) {
emit("onQuery", "#favorites");
} else {
emit("onQuery", q);
}
}
function onToggle(toggleAdvanced: boolean) {
emit("update:show-advanced", toggleAdvanced);
}
const showAdvanced = ref(true);
function onSearch() {
const query = createWorkflowQuery(filterSettings.value);
const path = "/workflows/list";
Expand All @@ -60,22 +42,23 @@ function onSearch() {
</script>
<template>
<div>
<small v-if="props.showAdvanced">Filter by name:</small>
<DelayedInput
:class="!props.showAdvanced && 'mb-3'"
:query="props.query"
:delay="100"
:loading="props.loading"
:show-advanced="props.showAdvanced"
:enable-advanced="props.enableAdvanced"
:placeholder="props.showAdvanced ? 'any name' : props.placeholder"
@change="checkQuery"
@onToggle="onToggle" />
<b-button
class="upload-button"
size="sm"
:pressed="showAdvanced"
:variant="showAdvanced ? 'info' : 'secondary'"
@click="showAdvanced = !showAdvanced">
<FontAwesomeIcon v-if="!showAdvanced" icon="angle-double-down" />
<FontAwesomeIcon v-else icon="angle-double-up" />
Search for Workflows
</b-button>
<div
v-if="props.showAdvanced"
v-if="showAdvanced"
description="advanced workflow filters"
@keyup.enter="onSearch"
@keyup.esc="onToggle(false)">
@keyup.esc="showAdvanced = false">
<small class="mt-1">Filter by name:</small>
<b-form-input v-model="filterSettings.name" size="sm" placeholder="any name" />
<small class="mt-1">Filter by tag:</small>
<b-form-input v-model="filterSettings.tag" size="sm" placeholder="any tag" />
<small>Published:</small>
Expand Down Expand Up @@ -110,7 +93,7 @@ function onSearch() {
<icon icon="search" />
<span>{{ _l("Search") }}</span>
</b-button>
<b-button size="sm" @click="onToggle(false)">
<b-button size="sm" @click="showAdvanced = false">
<icon icon="redo" />
<span>{{ _l("Cancel") }}</span>
</b-button>
Expand Down
29 changes: 1 addition & 28 deletions client/src/stores/workflowStore.ts
@@ -1,18 +1,15 @@
import { defineStore } from "pinia";
import axios from "axios";
import type { Steps } from "@/stores/workflowStepStore";
import { createWorkflowQuery } from "@/components/Panels/utilities";
import { getAppRoot } from "@/onload/loadConfig";

export interface Workflow {
interface Workflow {
[index: string]: any;
steps: Steps;
}

export const useWorkflowStore = defineStore("workflowStore", {
state: () => ({
allWorkflows: [] as Workflow[],
workflowResults: [] as Workflow[],
workflowsByInstanceId: {} as { [index: string]: Workflow },
}),
getters: {
Expand All @@ -37,15 +34,6 @@ export const useWorkflowStore = defineStore("workflowStore", {
return storedWorkflow?.id;
};
},
getWorkflows: (state) => {
return (filterSettings: Record<string, string | boolean>) => {
if (Object.keys(filterSettings).length === 0) {
return state.allWorkflows;
} else {
return state.workflowResults;
}
};
},
},
actions: {
async fetchWorkflowForInstanceId(workflowId: string) {
Expand All @@ -56,20 +44,5 @@ export const useWorkflowStore = defineStore("workflowStore", {
state.workflowsByInstanceId[workflowId] = data as Workflow;
});
},
async fetchWorkflows(filterSettings: Record<string, string | boolean>) {
if (Object.keys(filterSettings).length !== 0) {
const query = createWorkflowQuery(filterSettings); // remove from here?
const { data } = await axios.get(`${getAppRoot()}api/workflows`, {
params: { search: query, skip_step_counts: true },
});
this.workflowResults = data;
} else if (this.allWorkflows.length === 0) {
// TODO: add all params: ?limit=50&offset=0&search=&skip_step_counts=true
const { data } = await axios.get(`${getAppRoot()}api/workflows`, {
params: { skip_step_counts: true },
});
this.allWorkflows = data;
}
},
},
});

0 comments on commit a93ca37

Please sign in to comment.