diff --git a/client/src/components/Grid/GridList.vue b/client/src/components/Grid/GridList.vue index 42ce5ca1e9cb..8c73ba0e5d44 100644 --- a/client/src/components/Grid/GridList.vue +++ b/client/src/components/Grid/GridList.vue @@ -82,7 +82,8 @@ const filterClass = props.gridConfig.filtering; const rawFilters = computed(() => Object.fromEntries(filterClass.getFiltersForText(filterText.value, true, false))); const validFilters = computed(() => filterClass.getValidFilters(rawFilters.value, true).validFilters); const invalidFilters = computed(() => filterClass.getValidFilters(rawFilters.value, true).invalidFilters); -const hasInvalidFilters = computed(() => Object.keys(invalidFilters.value).length > 0); +const isSurroundedByQuotes = computed(() => /^["'].*["']$/.test(filterText.value)); +const hasInvalidFilters = computed(() => !isSurroundedByQuotes.value && Object.keys(invalidFilters.value).length > 0); // hide message helper const hideMessage = useDebounceFn(() => { @@ -221,8 +222,11 @@ function onSelectAll(current: boolean): void { * A valid filter/query for the backend */ function validatedFilterText() { - // there are no filters derived from the `filterText`; return the `filterText` as is - if (Object.keys(rawFilters.value).length === 0) { + if (isSurroundedByQuotes.value) { + // the filterText is surrounded by quotes, remove them + return filterText.value.slice(1, -1); + } else if (Object.keys(rawFilters.value).length === 0) { + // there are no filters derived from the `filterText` return filterText.value; } // there are valid filters derived from the `filterText` @@ -311,6 +315,15 @@ watch(operationMessage, () => { Remove invalid filters from query + or + + Match the exact query provided + diff --git a/client/src/components/Workflow/WorkflowList.vue b/client/src/components/Workflow/WorkflowList.vue index 85b93caeb86f..45a1b9dee14d 100644 --- a/client/src/components/Workflow/WorkflowList.vue +++ b/client/src/components/Workflow/WorkflowList.vue @@ -57,7 +57,7 @@ const searchPlaceHolder = computed(() => { placeHolder = "Search workflows shared with me"; } - placeHolder += " by name or use the advanced filtering options"; + placeHolder += " by query or use the advanced filtering options"; return placeHolder; }); @@ -72,13 +72,15 @@ const sortBy = computed(() => (listHeader.value && listHeader.value.sortBy) || " const noItems = computed(() => !loading.value && workflowsLoaded.value.length === 0 && !filterText.value); const noResults = computed(() => !loading.value && workflowsLoaded.value.length === 0 && filterText.value); +// Filtering computed refs const workflowFilters = computed(() => WorkflowFilters(props.activeList)); const rawFilters = computed(() => Object.fromEntries(workflowFilters.value.getFiltersForText(filterText.value, true, false)) ); const validFilters = computed(() => workflowFilters.value.getValidFilters(rawFilters.value, true).validFilters); const invalidFilters = computed(() => workflowFilters.value.getValidFilters(rawFilters.value, true).invalidFilters); -const hasInvalidFilters = computed(() => Object.keys(invalidFilters.value).length > 0); +const isSurroundedByQuotes = computed(() => /^["'].*["']$/.test(filterText.value)); +const hasInvalidFilters = computed(() => !isSurroundedByQuotes.value && Object.keys(invalidFilters.value).length > 0); function updateFilterValue(filterKey: string, newValue: any) { const currentFilterText = filterText.value; @@ -155,8 +157,11 @@ async function onPageChange(page: number) { } function validatedFilterText() { - // there are no filters derived from the `filterText` - if (Object.keys(rawFilters.value).length === 0) { + if (isSurroundedByQuotes.value) { + // the `filterText` is surrounded by quotes, remove them + return filterText.value.slice(1, -1); + } else if (Object.keys(rawFilters.value).length === 0) { + // there are no filters derived from the `filterText` return filterText.value; } // there are valid filters derived from the `filterText` @@ -277,6 +282,15 @@ onMounted(() => { Remove invalid filters from query + or + + Match the exact query provided + diff --git a/test/integration_selenium/test_trs_import.py b/test/integration_selenium/test_trs_import.py index 7d6f4395227a..d6031a805377 100644 --- a/test/integration_selenium/test_trs_import.py +++ b/test/integration_selenium/test_trs_import.py @@ -49,7 +49,8 @@ def trs_config_dir(cls): return cls.temp_config_dir("trs") def assert_workflow_imported(self, name): - self.workflow_index_search_for(name) + # surround name with quotes to consider case where name contains colons + self.workflow_index_search_for(f'"{name}"') assert len(self.workflow_card_elements()) == 1, f"workflow ${name} not imported" def test_import_workflow_by_url_dockstore(self):