ValueMappings: UX Feedback and fixes (#34011)

* ValueMappings: UX Feedback and fixes

* minor update to texts

* Update
This commit is contained in:
Torkel Ödegaard 2021-05-12 19:26:30 +02:00 committed by GitHub
parent d1a44044e5
commit 1601f12cf1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 42 additions and 46 deletions

View File

@ -154,7 +154,7 @@ export function ValueMappingEditRow({ mapping, index, onChange, onRemove }: Prop
)}
</td>
<td>
<Input type="text" value={result.text ?? ''} onChange={onChangeText} placeholder="Display text" />
<Input type="text" value={result.text ?? ''} onChange={onChangeText} placeholder="Optional display text" />
</td>
<td className={styles.textAlignCenter}>
{result.color && (

View File

@ -2,6 +2,8 @@ import React from 'react';
import { fireEvent, render, screen } from '@testing-library/react';
import { ValueMappingsEditorModal, Props } from './ValueMappingsEditorModal';
import { MappingType } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import selectEvent from 'react-select-event';
const setup = (spy?: any, propOverrides?: object) => {
const props: Props = {
@ -75,12 +77,14 @@ describe('When adding and updating value mapp', () => {
const onChangeSpy = jest.fn();
setup(onChangeSpy);
fireEvent.click(screen.getByTestId('add value map'));
fireEvent.click(screen.getByLabelText(selectors.components.ValuePicker.button('Add a new mapping')));
const selectComponent = await screen.findByLabelText(selectors.components.ValuePicker.select('Add a new mapping'));
await selectEvent.select(selectComponent, 'Value');
const input = (await screen.findAllByPlaceholderText('Exact value to match'))[1];
fireEvent.change(input, { target: { value: 'New' } });
fireEvent.change(screen.getAllByPlaceholderText('Display text')[2], { target: { value: 'display' } });
fireEvent.change(screen.getAllByPlaceholderText('Optional display text')[2], { target: { value: 'display' } });
fireEvent.click(screen.getByText('Update'));
expect(onChangeSpy).toBeCalledWith([
@ -117,11 +121,13 @@ describe('When adding and updating range map', () => {
const onChangeSpy = jest.fn();
setup(onChangeSpy, { value: [] });
fireEvent.click(screen.getByTestId('add range map'));
fireEvent.click(screen.getByLabelText(selectors.components.ValuePicker.button('Add a new mapping')));
const selectComponent = await screen.findByLabelText(selectors.components.ValuePicker.select('Add a new mapping'));
await selectEvent.select(selectComponent, 'Range');
fireEvent.change(screen.getByPlaceholderText('Range start'), { target: { value: '10' } });
fireEvent.change(screen.getByPlaceholderText('Range end'), { target: { value: '20' } });
fireEvent.change(screen.getByPlaceholderText('Display text'), { target: { value: 'display' } });
fireEvent.change(screen.getByPlaceholderText('Optional display text'), { target: { value: 'display' } });
fireEvent.click(screen.getByText('Update'));

View File

@ -1,12 +1,12 @@
import React, { useEffect, useState } from 'react';
import { GrafanaTheme2, MappingType, SpecialValueMatch, ValueMapping } from '@grafana/data';
import { GrafanaTheme2, MappingType, SelectableValue, SpecialValueMatch, ValueMapping } from '@grafana/data';
import { Button } from '../Button/Button';
import { Modal } from '../Modal/Modal';
import { useStyles2 } from '../../themes';
import { ValueMappingEditRow, ValueMappingEditRowModel } from './ValueMappingEditRow';
import { DragDropContext, Droppable, DropResult } from 'react-beautiful-dnd';
import { HorizontalGroup } from '../Layout/Layout';
import { css } from '@emotion/css';
import { ValuePicker } from '../ValuePicker/ValuePicker';
export interface Props {
value: ValueMapping[];
@ -46,39 +46,23 @@ export function ValueMappingsEditorModal({ value, onChange, onClose }: Props) {
updateRows(newList);
};
const onAddValueMap = () => {
updateRows([
...rows,
{
type: MappingType.ValueToText,
isNew: true,
result: {},
},
]);
};
const mappingTypes: Array<SelectableValue<MappingType>> = [
{ label: 'Value', value: MappingType.ValueToText, description: 'Match a specific text value' },
{ label: 'Range', value: MappingType.RangeToText, description: 'Match a numerical range of values' },
{ label: 'Special', value: MappingType.SpecialValue, description: 'Match on null, NaN, boolean and empty values' },
];
const onAddRangeMap = () => {
const onAddValueMapping = (value: SelectableValue<MappingType>) => {
updateRows([
...rows,
{
type: MappingType.RangeToText,
type: value.value!,
isNew: true,
result: {},
},
]);
};
const onAddSpecialValueMap = () => {
updateRows([
...rows,
{
type: MappingType.SpecialValue,
specialMatch: SpecialValueMatch.Null,
result: {},
},
]);
};
const onUpdate = () => {
onChange(editModelToSaveModel(rows));
onClose();
@ -90,10 +74,11 @@ export function ValueMappingsEditorModal({ value, onChange, onClose }: Props) {
<thead>
<tr>
<th style={{ width: '1%' }}></th>
<th style={{ width: '1%' }}>Type</th>
<th style={{ width: '40%' }}>Match</th>
<th>Display text</th>
<th>Color</th>
<th style={{ width: '40%', textAlign: 'left' }} colSpan={2}>
Condition
</th>
<th style={{ textAlign: 'left' }}>Display text</th>
<th style={{ width: '10%' }}>Color</th>
<th style={{ width: '1%' }}></th>
</tr>
</thead>
@ -116,17 +101,16 @@ export function ValueMappingsEditorModal({ value, onChange, onClose }: Props) {
</Droppable>
</DragDropContext>
</table>
<HorizontalGroup>
<Button variant="secondary" icon="plus" onClick={onAddValueMap} data-testid="add value map">
Value map
</Button>
<Button variant="secondary" icon="plus" onClick={onAddRangeMap} data-testid="add range map">
Range map
</Button>
<Button variant="secondary" icon="plus" onClick={onAddSpecialValueMap} data-testid="add special map">
Special value map
</Button>
</HorizontalGroup>
<ValuePicker
label="Add a new mapping"
variant="secondary"
size="md"
icon="plus"
menuPlacement="auto"
isFullWidth={false}
options={mappingTypes}
onChange={onAddValueMapping}
/>
<Modal.ButtonRow>
<Button variant="secondary" fill="outline" onClick={onClose}>
Cancel
@ -171,6 +155,11 @@ export function editModelToSaveModel(rows: ValueMappingEditRowModel[]) {
index,
};
// Set empty texts to undefined
if (!result.text || result.text.trim().length === 0) {
result.text = undefined;
}
switch (item.type) {
case MappingType.ValueToText:
if (item.key != null) {

View File

@ -54,10 +54,11 @@ export function ValuePicker<T>({
{!isPicking && (isFullWidth ? <FullWidthButtonContainer>{buttonEl}</FullWidthButtonContainer> : buttonEl)}
{isPicking && (
<span aria-label={selectors.components.ValuePicker.select(label)}>
<span>
<Select
placeholder={label}
options={options}
aria-label={selectors.components.ValuePicker.select(label)}
isOpen
onCloseMenu={() => setIsPicking(false)}
autoFocus={true}