From fab8b6c85f4b1364ed6c20a97f79027f95d3e1a1 Mon Sep 17 00:00:00 2001 From: Ahmed Awan Date: Mon, 16 Oct 2023 15:32:00 -0500 Subject: [PATCH] allow partial matches in workflow name tag search do not require quotations for name tags --- client/src/components/Page/PageList.vue | 4 ++-- .../components/Workflow/WorkflowFilters.js | 4 ++-- client/src/utils/filtering.ts | 24 ++++--------------- lib/galaxy/util/search.py | 7 ++++-- 4 files changed, 14 insertions(+), 25 deletions(-) diff --git a/client/src/components/Page/PageList.vue b/client/src/components/Page/PageList.vue index e7e0f3ac311c..d1e430b26b0e 100644 --- a/client/src/components/Page/PageList.vue +++ b/client/src/components/Page/PageList.vue @@ -100,7 +100,7 @@ import StatelessTags from "components/TagsMultiselect/StatelessTags"; import UtcDate from "components/UtcDate"; import paginationMixin from "components/Workflow/paginationMixin"; import { getAppRoot } from "onload/loadConfig"; -import Filtering, { contains, equals, expandNameTagWithQuotes, toBool } from "utils/filtering"; +import Filtering, { contains, equals, expandNameTag, toBool } from "utils/filtering"; import _l from "utils/localization"; import { useRouter } from "vue-router/composables"; @@ -155,7 +155,7 @@ const validFilters = { tag: { placeholder: "tag(s)", type: "MultiTags", - handler: contains("tag", "tag", expandNameTagWithQuotes), + handler: contains("tag", "tag", expandNameTag), menuItem: true, }, published: { diff --git a/client/src/components/Workflow/WorkflowFilters.js b/client/src/components/Workflow/WorkflowFilters.js index cc25891fafef..d91c8ca14ffd 100644 --- a/client/src/components/Workflow/WorkflowFilters.js +++ b/client/src/components/Workflow/WorkflowFilters.js @@ -1,4 +1,4 @@ -import Filtering, { contains, equals, expandNameTagWithQuotes, toBool } from "utils/filtering"; +import Filtering, { contains, equals, expandNameTag, toBool } from "utils/filtering"; export const helpHtml = `

This input can be used to filter the workflows displayed.

@@ -56,7 +56,7 @@ const validFilters = { tag: { placeholder: "tag(s)", type: "MultiTags", - handler: contains("tag", "tag", expandNameTagWithQuotes), + handler: contains("tag", "tag", expandNameTag), menuItem: true, }, published: { diff --git a/client/src/utils/filtering.ts b/client/src/utils/filtering.ts index 905b41a4fd41..c3cd711f4ada 100644 --- a/client/src/utils/filtering.ts +++ b/client/src/utils/filtering.ts @@ -108,25 +108,13 @@ export function toLowerNoQuotes(value: T): string { * */ export function expandNameTag(value: T): string { if (value && typeof value === "string") { - value = value.replace(/^#/, "name:") as T; - } - return toLower(value); -} - -/** Converts name tags starting with "#" to "'name:...'"; forces quotation marks - * and **is also case-sensitive** - * @param value - * @returns Lowercase value with 'name:' replaced with '#' - */ -export function expandNameTagWithQuotes(value: T): string { - if (value && typeof value === "string") { - if (value.startsWith("'#") && value.endsWith("'")) { - value = value.replace(/^'#/g, "'name:") as T; - } else if (value.startsWith("#")) { - value = `'name:${value.slice(1)}'` as T; + if ((value.startsWith("'#") || value.startsWith('"#')) && (value.endsWith('"') || value.endsWith("'"))) { + value = value.replace(/^['"]#/g, "'name:") as T; + } else { + value = value.replace(/^#/, "name:") as T; } } - return value as string; + return toLower(value); } /** Converts string alias to string operator, e.g.: 'gt' to '>' @@ -569,8 +557,6 @@ export default class Filtering { return filterValue; } else if (!backendFormatted && ([expandNameTag, toDate] as Converter[]).includes(converter)) { return toLower(filterValue) as T; - } else if (!backendFormatted && converter == expandNameTagWithQuotes) { - return (filterValue as string).startsWith("#") ? (`'${filterValue}'` as T) : filterValue; } return converter(filterValue); } else { diff --git a/lib/galaxy/util/search.py b/lib/galaxy/util/search.py index b0db7505619e..11f072489e81 100644 --- a/lib/galaxy/util/search.py +++ b/lib/galaxy/util/search.py @@ -36,7 +36,7 @@ def parse_filters_structured( search_space = search_term.replace('"', "'") filters = filters or {} filter_keys = "|".join(list(filters.keys())) - pattern = rf"({filter_keys}):(?:\s+)?([\w-]+|\'.*?\')" + pattern = rf"({filter_keys}):(?:\s+)?([\w-]+|'.*?')(:\w+)?" reserved = re.compile(pattern) parsed_search = ParsedSearch() while True: @@ -52,8 +52,11 @@ def parse_filters_structured( else: first_group = match.groups()[0] if first_group in filters: + if match.groups()[0] == "tag" and match.groups()[1] == "name" and match.groups()[2] is not None: + group = match.groups()[1] + match.groups()[2].strip() + else: + group = match.groups()[1].strip() filter_as = filters[first_group] - group = match.groups()[1].strip() quoted = preserve_quotes and group.startswith("'") parsed_search.add_keyed_term(filter_as, group.replace("'", ""), quoted) parsed_search.add_unfiltered_text_terms(search_space[0 : match.start()])