From ec42a8f83ff525d49d548826192207b95a2ac17d Mon Sep 17 00:00:00 2001 From: Tobias Skarhed <1438972+tskarhed@users.noreply.github.com> Date: Mon, 13 Jan 2025 17:24:54 +0100 Subject: [PATCH 01/24] MultiCombobox: Add basic filtering (#98608) Add filtering to Multi --- .../src/components/Combobox/Combobox.tsx | 23 +------------------ .../src/components/Combobox/MultiCombobox.tsx | 17 +++++--------- .../src/components/Combobox/filter.ts | 23 +++++++++++++++++++ 3 files changed, 30 insertions(+), 33 deletions(-) create mode 100644 packages/grafana-ui/src/components/Combobox/filter.ts diff --git a/packages/grafana-ui/src/components/Combobox/Combobox.tsx b/packages/grafana-ui/src/components/Combobox/Combobox.tsx index 6a338006b08..6a18da04294 100644 --- a/packages/grafana-ui/src/components/Combobox/Combobox.tsx +++ b/packages/grafana-ui/src/components/Combobox/Combobox.tsx @@ -15,6 +15,7 @@ import { Stack } from '../Layout/Stack/Stack'; import { Portal } from '../Portal/Portal'; import { ScrollContainer } from '../ScrollContainer/ScrollContainer'; +import { itemFilter, itemToString } from './filter'; import { getComboboxStyles, MENU_OPTION_HEIGHT, MENU_OPTION_HEIGHT_DESCRIPTION } from './getComboboxStyles'; import { useComboboxFloat } from './useComboboxFloat'; import { StaleResultError, useLatestAsyncCall } from './useLatestAsyncCall'; @@ -86,28 +87,6 @@ export type AutoSizeConditionals = type ComboboxProps = ComboboxBaseProps & AutoSizeConditionals & ClearableConditionals; -export function itemToString(item?: ComboboxOption | null) { - if (!item) { - return ''; - } - if (item.label?.includes('Custom value: ')) { - return item.value.toString(); - } - return item.label ?? item.value.toString(); -} - -function itemFilter(inputValue: string) { - const lowerCasedInputValue = inputValue.toLowerCase(); - - return (item: ComboboxOption) => { - return ( - !inputValue || - item.label?.toLowerCase().includes(lowerCasedInputValue) || - item.value?.toString().toLowerCase().includes(lowerCasedInputValue) - ); - }; -} - const noop = () => {}; const asyncNoop = () => Promise.resolve([]); diff --git a/packages/grafana-ui/src/components/Combobox/MultiCombobox.tsx b/packages/grafana-ui/src/components/Combobox/MultiCombobox.tsx index 0af00d221e2..81abe9f6a00 100644 --- a/packages/grafana-ui/src/components/Combobox/MultiCombobox.tsx +++ b/packages/grafana-ui/src/components/Combobox/MultiCombobox.tsx @@ -13,15 +13,10 @@ import { Spinner } from '../Spinner/Spinner'; import { Text } from '../Text/Text'; import { Tooltip } from '../Tooltip'; -import { - ComboboxOption, - ComboboxBaseProps, - AutoSizeConditionals, - itemToString, - VIRTUAL_OVERSCAN_ITEMS, -} from './Combobox'; +import { ComboboxOption, ComboboxBaseProps, AutoSizeConditionals, VIRTUAL_OVERSCAN_ITEMS } from './Combobox'; import { OptionListItem } from './OptionListItem'; import { ValuePill } from './ValuePill'; +import { itemFilter, itemToString } from './filter'; import { getComboboxStyles, MENU_OPTION_HEIGHT, MENU_OPTION_HEIGHT_DESCRIPTION } from './getComboboxStyles'; import { getMultiComboboxStyles } from './getMultiComboboxStyles'; import { useComboboxFloat } from './useComboboxFloat'; @@ -48,8 +43,11 @@ export const MultiCombobox = (props: MultiComboboxPro }, [value, options, isAsync]); const styles = useStyles2(getComboboxStyles); + const [inputValue, setInputValue] = useState(''); - const [items, baseSetItems] = useState(isAsync ? [] : options); + const [baseItems, baseSetItems] = useState(isAsync ? [] : options); + + const items = useMemo(() => baseItems.filter(itemFilter(inputValue)), [baseItems, inputValue]); // TODO: Improve this with async useEffect(() => { @@ -73,8 +71,6 @@ export const MultiCombobox = (props: MultiComboboxPro [selectedItems] ); - const [inputValue, setInputValue] = useState(''); - const { getSelectedItemProps, getDropdownProps, removeSelectedItem } = useMultipleSelection({ selectedItems, //initally selected items, onStateChange: ({ type, selectedItems: newSelectedItems }) => { @@ -120,7 +116,6 @@ export const MultiCombobox = (props: MultiComboboxPro case useCombobox.stateChangeTypes.InputBlur: setInputValue(''); setIsOpen(false); - return changes; default: return changes; } diff --git a/packages/grafana-ui/src/components/Combobox/filter.ts b/packages/grafana-ui/src/components/Combobox/filter.ts new file mode 100644 index 00000000000..09ab4653051 --- /dev/null +++ b/packages/grafana-ui/src/components/Combobox/filter.ts @@ -0,0 +1,23 @@ +import { ComboboxOption } from './Combobox'; + +export function itemToString(item?: ComboboxOption | null) { + if (!item) { + return ''; + } + if (item.label?.includes('Custom value: ')) { + return item.value.toString(); + } + return item.label ?? item.value.toString(); +} + +export function itemFilter(inputValue: string) { + const lowerCasedInputValue = inputValue.toLowerCase(); + + return (item: ComboboxOption) => { + return ( + !inputValue || + item.label?.toLowerCase().includes(lowerCasedInputValue) || + item.value?.toString().toLowerCase().includes(lowerCasedInputValue) + ); + }; +} From c3b0eb627710b9be1ffa744b051cffd260d37dd6 Mon Sep 17 00:00:00 2001 From: Josh Hunt Date: Mon, 13 Jan 2025 16:44:35 +0000 Subject: [PATCH 02/24] Reverts "MetricCombobox: Fix overflowing parents" (#98868) Revert MetricCombobox: Fix overflowing parents https://github.com/grafana/grafana/pull/97049 --- .../components/MetricCombobox.tsx | 65 ++++--------------- .../components/PromQueryBuilder.tsx | 18 ++--- .../src/components/Forms/InlineField.tsx | 1 - .../src/components/Forms/InlineFieldRow.tsx | 1 - 4 files changed, 19 insertions(+), 66 deletions(-) diff --git a/packages/grafana-prometheus/src/querybuilder/components/MetricCombobox.tsx b/packages/grafana-prometheus/src/querybuilder/components/MetricCombobox.tsx index 81b3d830779..0c156da10f0 100644 --- a/packages/grafana-prometheus/src/querybuilder/components/MetricCombobox.tsx +++ b/packages/grafana-prometheus/src/querybuilder/components/MetricCombobox.tsx @@ -1,11 +1,9 @@ -import { css } from '@emotion/css'; import { useCallback, useState } from 'react'; -import { GrafanaTheme2, SelectableValue } from '@grafana/data'; +import { SelectableValue } from '@grafana/data'; import { EditorField, EditorFieldGroup, InputGroup } from '@grafana/experimental'; -import { Button, ComponentSize, InlineField, InlineFieldRow, useStyles2 } from '@grafana/ui'; +import { Button, InlineField, InlineFieldRow } from '@grafana/ui'; import { Combobox, ComboboxOption } from '@grafana/ui/src/components/Combobox/Combobox'; -import { getPropertiesForButtonSize } from '@grafana/ui/src/components/Forms/commonStyles'; import { PrometheusDatasource } from '../../datasource'; import { regexifyLabelValuesQueryString } from '../parsingUtils'; @@ -26,9 +24,6 @@ export interface MetricComboboxProps { variableEditor?: boolean; } -const INLINE_FIELD_WIDTH = 20; -const BUTTON_SIZE: ComponentSize = 'md'; - export function MetricCombobox({ datasource, query, @@ -88,8 +83,6 @@ export function MetricCombobox({ return metrics; }, [onGetMetrics]); - const styles = useStyles2(getMectricComboboxStyles); - const asyncSelect = () => { return ( @@ -103,7 +96,6 @@ export function MetricCombobox({ createCustomValue />