diff --git a/client/src/components/Common/FilterMenu.vue b/client/src/components/Common/FilterMenu.vue index 0f0596e2f422..66a5e4c823f4 100644 --- a/client/src/components/Common/FilterMenu.vue +++ b/client/src/components/Common/FilterMenu.vue @@ -4,7 +4,7 @@ import { faAngleDoubleUp, faQuestion, faSearch } from "@fortawesome/free-solid-s import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; import { BButton, BModal, BPopover } from "bootstrap-vue"; import { kebabCase } from "lodash"; -import { computed, ref } from "vue"; +import { computed, ref, set } from "vue"; import type Filtering from "@/utils/filtering"; import { type Alias, type ErrorType, getOperatorForAlias, type ValidFilter } from "@/utils/filtering"; @@ -91,6 +91,8 @@ const toggleMenuButton = computed(() => { // Boolean for showing the help modal for the whole filter menu (if provided) const showHelp = ref(false); +const isDisabled = ref>({}); + const formattedSearchError = computed(() => { if (props.searchError) { const { column, col, operation, op, value, val, err_msg, ValueError } = props.searchError; @@ -144,6 +146,8 @@ function getValidFilter(filter: string): ValidFilter { function onOption(filter: string, value: any) { filters.value[filter] = value; + setDisabled(filter, value); + // for the compact view, we want to immediately search if (props.view === "compact") { onSearch(); @@ -177,6 +181,21 @@ function onToggle() { emit("update:show-advanced", !props.showAdvanced); } +function setDisabled(filter: string, newVal: any) { + const disablesFilters = validFilters.value[filter]?.disablesFilters; + const type = validFilters.value[filter]?.type; + if (disablesFilters && type !== Boolean) { + for (const [disabledFilter, disablingValues] of Object.entries(disablesFilters)) { + if (newVal && (disablingValues === null || disablingValues.includes(newVal))) { + set(isDisabled.value, disabledFilter, true); + filters.value[disabledFilter] = undefined; + } else { + set(isDisabled.value, disabledFilter, false); + } + } + } +} + function updateFilterText(newFilterText: string) { emit("update:filter-text", newFilterText); } @@ -243,6 +262,7 @@ function updateFilterText(newFilterText: string) { :filters="filters" :error="formattedSearchError || undefined" :identifier="identifier" + :disabled="isDisabled[filter] || false" @change="onOption" @on-enter="onSearch" @on-esc="onToggle" /> @@ -269,6 +289,7 @@ function updateFilterText(newFilterText: string) { :filter="getValidFilter(filter)" :filters="filters" :identifier="identifier" + :disabled="isDisabled[filter] || false" @change="onOption" /> diff --git a/client/src/components/Common/FilterMenuDropdown.vue b/client/src/components/Common/FilterMenuDropdown.vue index cdcfd41c4c5b..b86b5ca5663e 100644 --- a/client/src/components/Common/FilterMenuDropdown.vue +++ b/client/src/components/Common/FilterMenuDropdown.vue @@ -31,6 +31,7 @@ interface Props { [k: string]: FilterValue; }; identifier: string; + disabled?: boolean; } const props = defineProps(); @@ -76,7 +77,9 @@ const helpToggle = ref(false); const modalTitle = `${capitalize(props.filter.placeholder)} Help`; function onHelp(_: string, value: string) { helpToggle.value = false; - localValue.value = value; + if (!props.disabled) { + localValue.value = value; + } } // Quota Source refs and operations @@ -140,6 +143,7 @@ function setValue(val: string | QuotaUsage | undefined) { menu-class="w-100" size="sm" boundary="window" + :disabled="props.disabled" :toggle-class="props.error ? 'text-danger' : ''"> (any) diff --git a/client/src/components/Common/FilterMenuInput.vue b/client/src/components/Common/FilterMenuInput.vue index 011e12a73ae0..71e6e496bf78 100644 --- a/client/src/components/Common/FilterMenuInput.vue +++ b/client/src/components/Common/FilterMenuInput.vue @@ -28,6 +28,7 @@ interface Props { filters: { [k: string]: FilterType; }; + disabled?: boolean; } const props = defineProps(); @@ -47,14 +48,18 @@ const modalTitle = `${capitalize(props.filter.placeholder)} Help`; function onHelp(_: string, value: string) { helpToggle.value = false; - localValue.value = value; + + if (!props.disabled) { + localValue.value = value; + } } watch( () => localValue.value, (newFilter) => { emit("change", props.name, newFilter); - } + }, + { immediate: true } ); watch( @@ -79,6 +84,7 @@ watch( size="sm" :state="props.error ? false : null" :placeholder="`any ${props.filter.placeholder}`" + :disabled="props.disabled" :list="props.filter.datalist ? `${identifier}-${props.name}-selectList` : null" @keyup.enter="emit('on-enter')" @keyup.esc="emit('on-esc')" /> @@ -99,6 +105,7 @@ watch( v-model="localValue" reset-button button-only + :disabled="props.disabled" size="sm" /> diff --git a/client/src/components/Common/FilterMenuRanged.vue b/client/src/components/Common/FilterMenuRanged.vue index 91e362bad359..72f013212dc5 100644 --- a/client/src/components/Common/FilterMenuRanged.vue +++ b/client/src/components/Common/FilterMenuRanged.vue @@ -14,6 +14,7 @@ interface Props { filters: { [k: string]: FilterType; }; + disabled?: boolean; } const props = defineProps(); @@ -93,11 +94,12 @@ watch( size="sm" :state="hasError(localNameGt) ? false : null" :placeholder="localPlaceholder('gt')" + :disabled="props.disabled" @keyup.enter="emit('on-enter')" @keyup.esc="emit('on-esc')" /> - + @@ -109,11 +111,12 @@ watch( size="sm" :state="hasError(localNameLt) ? false : null" :placeholder="localPlaceholder('lt')" + :disabled="props.disabled" @keyup.enter="emit('on-enter')" @keyup.esc="emit('on-esc')" /> - + diff --git a/client/src/components/Common/Heading.vue b/client/src/components/Common/Heading.vue index d31d0d033ce4..2ef53352d818 100644 --- a/client/src/components/Common/Heading.vue +++ b/client/src/components/Common/Heading.vue @@ -96,6 +96,10 @@ const element = computed(() => {