From daae119ac497b5435220d710d6ad56416d67331b Mon Sep 17 00:00:00 2001 From: Ahmed Awan Date: Fri, 25 Aug 2023 00:14:23 -0500 Subject: [PATCH] replace `IndexFilter` in `WorkflowList` with `FilterMenu` also: - create `WorkflowFilters.js` that exports reusable `Filtering` - allow `MultiTags` filter type for `FilterMenu`, which allows you to add a `StatelessTags` field in the menu, allowing for array values as filter - allow `is:filter` filters that are Boolean filters, except, they only be set to true - apart from `q=filter1&qv=val&q=filter2&qv=val&...` query strings for the backend, the `Filtering` class can now also create `backendFormatted` strings in the form `filter1:val filter2:val` --- client/src/components/Common/DelayedInput.vue | 5 + client/src/components/Common/FilterMenu.vue | 43 +++++- .../History/Modals/SelectorModal.vue | 2 +- .../components/Indices/SharingIndicators.vue | 12 +- client/src/components/Page/PageList.vue | 2 +- .../components/Panels/Common/ToolSearch.vue | 3 +- client/src/components/Panels/WorkflowBox.vue | 71 +--------- .../components/Workflow/WorkflowFilters.js | 102 ++++++++++++++ .../src/components/Workflow/WorkflowList.vue | 126 ++++++++--------- client/src/utils/filtering.ts | 130 ++++++++++++++---- 10 files changed, 321 insertions(+), 175 deletions(-) create mode 100644 client/src/components/Workflow/WorkflowFilters.js diff --git a/client/src/components/Common/DelayedInput.vue b/client/src/components/Common/DelayedInput.vue index bb36d5f8fb92..090e2c57f292 100644 --- a/client/src/components/Common/DelayedInput.vue +++ b/client/src/components/Common/DelayedInput.vue @@ -80,6 +80,11 @@ export default { this.setQuery(queryNew); }, }, + created() { + if (this.query) { + this.setQuery(this.query); + } + }, methods: { clearTimer() { if (this.queryTimer) { diff --git a/client/src/components/Common/FilterMenu.vue b/client/src/components/Common/FilterMenu.vue index d529aab49ce4..b0e8d1250eb7 100644 --- a/client/src/components/Common/FilterMenu.vue +++ b/client/src/components/Common/FilterMenu.vue @@ -7,6 +7,7 @@ import { type Alias, getOperatorForAlias } from "@/utils/filtering"; import DelayedInput from "@/components/Common/DelayedInput.vue"; import FilterMenuBoolean from "@/components/Common/FilterMenuBoolean.vue"; +import StatelessTags from "@/components/TagsMultiselect/StatelessTags.vue"; interface BackendFilterError { err_msg: string; @@ -26,6 +27,8 @@ const props = withDefaults( name?: string; /** A placeholder for the main search input */ placeholder?: string; + /** The delay (in ms) before the main filter is applied */ + debounceDelay?: number; /** The `Filtering` class to use */ filterClass: Filtering; /** The current filter text in the main field */ @@ -46,6 +49,7 @@ const props = withDefaults( { name: "Menu", placeholder: "search for items", + debounceDelay: 500, filterText: "", menuType: "linked", showAdvanced: false, @@ -82,7 +86,8 @@ const showHelp = ref(false); /** * Reactively storing and getting all filters from validFilters which are `.type == Date` - * (This was done to make the datepickers store values in the `filters` object) + * and .type == 'MultiTags' + * (This was done to make the datepickers and tags store values in the `filters` object) */ const dateFilters: Ref<{ [key: string]: string }> = ref({}); const dateKeys = Object.keys(validFilters.value).filter((key) => validFilters.value[key]?.type == Date); @@ -92,6 +97,15 @@ dateKeys.forEach((key: string) => { dateKeys.push(key + "_gt"); } }); +const multiTagFilters: Ref<{ [key: string]: Ref }> = ref({}); +const multiTagKeys = Object.keys(validFilters.value).filter((key) => validFilters.value[key]?.type == "MultiTags"); +multiTagKeys.forEach((key: string) => { + if (filters.value[key] !== undefined) { + multiTagFilters.value[key] = ref(filters.value[key] as string[]); + } else { + multiTagFilters.value[key] = ref([]); + } +}); watch( () => filters.value, (newFilters: { [k: string]: any }) => { @@ -102,6 +116,13 @@ watch( delete dateFilters.value[key]; } }); + multiTagKeys.forEach((key: string) => { + if (newFilters[key]) { + (multiTagFilters.value[key] as Ref).value = newFilters[key]; + } else { + (multiTagFilters.value[key] as Ref).value = []; + } + }); } ); @@ -149,6 +170,9 @@ function onSearch() { Object.keys(dateFilters.value).forEach((key) => { onOption(key, dateFilters.value[key]); }); + Object.keys(multiTagFilters.value).forEach((key) => { + onOption(key, (multiTagFilters.value[key] as Ref).value); + }); const newFilterText = props.filterClass.getFilterText(filters.value); if (props.menuType !== "linked") { emit("on-search", filters.value, newFilterText); @@ -157,6 +181,10 @@ function onSearch() { } } +function onTags(filter: string, tags: string[]) { + (multiTagFilters.value[filter] as Ref).value = tags; +} + function onToggle() { emit("update:show-advanced", !props.showAdvanced); } @@ -173,7 +201,7 @@ function updateFilterText(newFilterText: string) { v-show="props.menuType == 'linked' || (props.menuType == 'separate' && !props.showAdvanced)" :class="props.filterText && 'font-weight-bold'" :query="props.filterText" - :delay="400" + :delay="props.debounceDelay" :loading="props.loading" :show-advanced="props.showAdvanced" enable-advanced @@ -187,7 +215,6 @@ function updateFilterText(newFilterText: string) { aria-haspopup="true" size="sm" :pressed="props.showAdvanced" - :variant="props.showAdvanced ? 'info' : 'secondary'" :title="`Toggle Advanced Search`" data-description="reset query" @click="onToggle"> @@ -273,6 +300,16 @@ function updateFilterText(newFilterText: string) { + + + Filter by {{ validFilters[filter]?.placeholder }}: + + + + + Filter by {{ validFilters[filter]?.placeholder }}: diff --git a/client/src/components/History/Modals/SelectorModal.vue b/client/src/components/History/Modals/SelectorModal.vue index 0f52deee8b02..9888c4c0fbef 100644 --- a/client/src/components/History/Modals/SelectorModal.vue +++ b/client/src/components/History/Modals/SelectorModal.vue @@ -240,7 +240,7 @@ async function loadMore(noScroll = false) { Search string too short! No histories found. -
+
(); diff --git a/client/src/components/Page/PageList.vue b/client/src/components/Page/PageList.vue index ef446e41ea67..31acb3ae2a19 100644 --- a/client/src/components/Page/PageList.vue +++ b/client/src/components/Page/PageList.vue @@ -52,7 +52,7 @@