Files
grafana/packages/grafana-ui/src/components/Segment/SegmentSelect.tsx
Piotr Jamróz 31bb3522c8 Graphite: Migrate to React (part 3: migrate segments) (#37309)
* Add UMLs

* Add rendered diagrams

* Move QueryCtrl to flux

* Remove redundant param in the reducer

* Use named imports for lodash and fix typing for GraphiteTagOperator

* Add missing async/await

* Extract providers to a separate file

* Clean up async await

* Rename controller functions back to main

* Simplify creating actions

* Re-order controller functions

* Separate helpers from actions

* Rename vars

* Simplify helpers

* Move controller methods to state reducers

* Remove docs (they are added in design doc)

* Move actions.ts to state folder

* Add docs

* Add old methods stubs for easier review

* Check how state dependencies will be mapped

* Rename state to store

* Rename state to store

* Rewrite spec tests for Graphite Query Controller

* Update docs

* Update docs

* Add GraphiteTextEditor

* Add play button

* Add AddGraphiteFunction

* Use Segment to simplify AddGraphiteFunction

* Memoize function defs

* Fix useCallback deps

* Update public/app/plugins/datasource/graphite/state/helpers.ts

Co-authored-by: Giordano Ricci <me@giordanoricci.com>

* Update public/app/plugins/datasource/graphite/state/helpers.ts

Co-authored-by: Giordano Ricci <me@giordanoricci.com>

* Update public/app/plugins/datasource/graphite/state/helpers.ts

Co-authored-by: Giordano Ricci <me@giordanoricci.com>

* Update public/app/plugins/datasource/graphite/state/providers.ts

Co-authored-by: Giordano Ricci <me@giordanoricci.com>

* Update public/app/plugins/datasource/graphite/state/providers.ts

Co-authored-by: Giordano Ricci <me@giordanoricci.com>

* Update public/app/plugins/datasource/graphite/state/providers.ts

Co-authored-by: Giordano Ricci <me@giordanoricci.com>

* Update public/app/plugins/datasource/graphite/state/providers.ts

Co-authored-by: Giordano Ricci <me@giordanoricci.com>

* Update public/app/plugins/datasource/graphite/state/providers.ts

Co-authored-by: Giordano Ricci <me@giordanoricci.com>

* Update public/app/plugins/datasource/graphite/state/providers.ts

Co-authored-by: Giordano Ricci <me@giordanoricci.com>

* Add more type definitions

* Remove submitOnClickAwayOption

This behavior is actually needed to remove parameters in functions

* Load function definitions before parsing the target on initial load

* Add button padding

* Fix loading function definitions

* Change targetChanged to updateQuery to avoid mutating state directly

It's also needed for extra refresh/runQuery execution as handleTargetChanged doesn't handle changing the raw query

* Fix updating query after adding a function

* Simplify updating function params

* Migrate function editor to react

* Simplify setting Segment Select min width

* Remove unnecessary changes to SegmentInput

* Extract view logic to a helper and update types definitions

* Clean up types

* Update FuncDef types and add tests

* Show red border for unknown functions

* Autofocus on new params

* Extract params mapping to a helper

* Split code between params and function editor

* Focus on the first param when a function is added even if it's an optional argument

* Add function editor tests

* Remove todo marker

* Fix adding new functions

* Allow empty value in selects for removing function params

* Add placeholders and fix styling

* Add more docs

* Create basic implementation for metrics and tags

* Post merge fixes

These files are not .ts

* Remove mapping to Angular dropdowns

* Simplify mapping tag names, values and operators

* Simplify mapping metrics

* Fix removing tags and autocomplete

* Simplify debouncing providers

* Ensure options are loaded twice and segment is opened

* Remove focusing new segments logic (not supported by React's segment)

* Clean up

* Move debouncing to components

* Simplify mapping to selectable options

* Add docs

* use getStyles

* remove redundant async/await

* Remove

* remove redundant async/await

* Remove console.log and silent test console output

* Do not display the name of the selected dropdown option

* Use block docs for better doc generation

* Handle undefined values provided for autocomplete

Co-authored-by: Giordano Ricci <me@giordanoricci.com>
2021-08-11 09:13:55 +02:00

92 lines
3.1 KiB
TypeScript

import React, { HTMLProps, useRef } from 'react';
import { SelectableValue } from '@grafana/data';
import { AsyncSelect, Select } from '../Select/Select';
import { useTheme2 } from '../../themes/ThemeContext';
/** @internal
* Should be used only internally by Segment/SegmentAsync which can guarantee that SegmentSelect is hidden
* when a value is selected. See comment below on closeMenuOnSelect()
*/
export interface Props<T> extends Omit<HTMLProps<HTMLDivElement>, 'value' | 'onChange'> {
value?: SelectableValue<T>;
options: Array<SelectableValue<T>>;
onChange: (item: SelectableValue<T>) => void;
/**
* If provided - AsyncSelect will be used allowing to reload options when the value in the input changes
*/
loadOptions?: (inputValue: string) => Promise<Array<SelectableValue<T>>>;
onClickOutside: () => void;
width: number;
noOptionsMessage?: string;
allowCustomValue?: boolean;
/**
* If true, empty value will be passed to onChange callback otherwise using empty value
* will work as canceling and using the previous value
*/
allowEmptyValue?: boolean;
placeholder?: string;
}
/** @internal */
export function SegmentSelect<T>({
value,
placeholder = '',
options = [],
onChange,
onClickOutside,
loadOptions = undefined,
width: widthPixels,
noOptionsMessage = '',
allowCustomValue = false,
allowEmptyValue = false,
...rest
}: React.PropsWithChildren<Props<T>>) {
const ref = useRef<HTMLDivElement>(null);
const theme = useTheme2();
let width = widthPixels > 0 ? widthPixels / theme.spacing.gridSize : undefined;
let Component;
let asyncOptions = {};
if (loadOptions) {
Component = AsyncSelect;
asyncOptions = { loadOptions, defaultOptions: true };
} else {
Component = Select;
}
return (
<div {...rest} ref={ref}>
<Component
menuShouldPortal
width={width}
noOptionsMessage={noOptionsMessage}
placeholder={placeholder}
autoFocus={true}
isOpen={true}
onChange={onChange}
options={options}
value={value}
// Disable "close menu on select" option to avoid calling onChange() in onCloseMenu() when a value is selected.
// Once the value is selected the Select component (with the menu) will be hidden anyway by the parent component:
// Segment or SegmentAsync - hence setting this option has no UX effect.
closeMenuOnSelect={false}
onCloseMenu={() => {
if (ref && ref.current) {
// https://github.com/JedWatson/react-select/issues/188#issuecomment-279240292
// Unfortunately there's no other way of retrieving the value (not yet) created new option
const input = ref.current.querySelector('input[id^="react-select-"]') as HTMLInputElement;
if (input && (input.value || allowEmptyValue)) {
onChange({ value: input.value as any, label: input.value });
} else {
onClickOutside();
}
}
}}
allowCustomValue={allowCustomValue}
{...asyncOptions}
/>
</div>
);
}