ScalarDimensionEditor.tsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import { css } from '@emotion/css';
  2. import React, { FC, useCallback } from 'react';
  3. import { FieldType, GrafanaTheme2, SelectableValue, StandardEditorProps } from '@grafana/data';
  4. import { InlineField, InlineFieldRow, RadioButtonGroup, Select, useStyles2 } from '@grafana/ui';
  5. import { useFieldDisplayNames, useSelectOptions } from '@grafana/ui/src/components/MatchersUI/utils';
  6. import { ScalarDimensionConfig, ScalarDimensionMode, ScalarDimensionOptions } from '../types';
  7. import { NumberInput } from './NumberInput';
  8. const fixedValueOption: SelectableValue<string> = {
  9. label: 'Fixed value',
  10. value: '_____fixed_____',
  11. };
  12. const scalarOptions = [
  13. { label: 'Mod', value: ScalarDimensionMode.Mod, description: 'Use field values, mod from max' },
  14. { label: 'Clamped', value: ScalarDimensionMode.Clamped, description: 'Use field values, clamped to max and min' },
  15. ];
  16. export const ScalarDimensionEditor: FC<StandardEditorProps<ScalarDimensionConfig, ScalarDimensionOptions, any>> = (
  17. props
  18. ) => {
  19. const { value, context, onChange, item } = props;
  20. const { settings } = item;
  21. const DEFAULT_VALUE = 0;
  22. const fieldName = value?.field;
  23. const isFixed = Boolean(!fieldName);
  24. const names = useFieldDisplayNames(context.data);
  25. const selectOptions = useSelectOptions(names, fieldName, fixedValueOption, FieldType.number);
  26. const styles = useStyles2(getStyles);
  27. const onSelectChange = useCallback(
  28. (selection: SelectableValue<string>) => {
  29. const field = selection.value;
  30. if (field && field !== fixedValueOption.value) {
  31. onChange({
  32. ...value,
  33. field,
  34. });
  35. } else {
  36. const fixed = value.fixed ?? DEFAULT_VALUE;
  37. onChange({
  38. ...value,
  39. field: undefined,
  40. fixed,
  41. });
  42. }
  43. },
  44. [onChange, value]
  45. );
  46. const onModeChange = useCallback(
  47. (mode) => {
  48. onChange({
  49. ...value,
  50. mode,
  51. });
  52. },
  53. [onChange, value]
  54. );
  55. const onValueChange = useCallback(
  56. (v: number | undefined) => {
  57. onChange({
  58. ...value,
  59. field: undefined,
  60. fixed: v ?? DEFAULT_VALUE,
  61. });
  62. },
  63. [onChange, value]
  64. );
  65. const val = value ?? {};
  66. const mode = value?.mode ?? ScalarDimensionMode.Mod;
  67. const selectedOption = isFixed ? fixedValueOption : selectOptions.find((v) => v.value === fieldName);
  68. return (
  69. <>
  70. <div>
  71. <InlineFieldRow>
  72. <InlineField label="Limit" labelWidth={8} grow={true}>
  73. <RadioButtonGroup value={mode} options={scalarOptions} onChange={onModeChange} fullWidth />
  74. </InlineField>
  75. </InlineFieldRow>
  76. <Select
  77. value={selectedOption}
  78. options={selectOptions}
  79. onChange={onSelectChange}
  80. noOptionsMessage="No fields found"
  81. />
  82. </div>
  83. <div className={styles.range}>
  84. {isFixed && (
  85. <InlineFieldRow>
  86. <InlineField label="Value" labelWidth={8} grow={true}>
  87. <NumberInput
  88. value={val?.fixed ?? DEFAULT_VALUE}
  89. onChange={onValueChange}
  90. max={settings?.max}
  91. min={settings?.min}
  92. />
  93. </InlineField>
  94. </InlineFieldRow>
  95. )}
  96. </div>
  97. </>
  98. );
  99. };
  100. const getStyles = (theme: GrafanaTheme2) => ({
  101. range: css`
  102. padding-top: 8px;
  103. `,
  104. });