From 7b7b9ff4a77fd57fdc9b18ed72d227bfe3ca2550 Mon Sep 17 00:00:00 2001 From: Leo <108552997+lpskdl@users.noreply.github.com> Date: Mon, 18 Jul 2022 16:19:32 +0200 Subject: [PATCH] ValueMappings: Make value mapping row focusable (#52337) * Dimensions: Move drag handle to draggable container * Accessibility: Added unique ids to preserve focus when dragging items using keyboard --- .../ValueMappingEditRow.tsx | 9 +- .../ValueMappingsEditorModal.tsx | 85 ++++++++++++------- 2 files changed, 59 insertions(+), 35 deletions(-) diff --git a/public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingEditRow.tsx b/public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingEditRow.tsx index 7fb56b7a572..68b3b59364b 100644 --- a/public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingEditRow.tsx +++ b/public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingEditRow.tsx @@ -17,6 +17,7 @@ export interface ValueMappingEditRowModel { isNew?: boolean; specialMatch?: SpecialValueMatch; result: ValueMappingResult; + id: string; } interface Props { @@ -29,7 +30,7 @@ interface Props { } export function ValueMappingEditRow({ mapping, index, onChange, onRemove, onDuplicate, showIconPicker }: Props) { - const { key, result } = mapping; + const { key, result, id } = mapping; const styles = useStyles2(getStyles); const inputRef = useRef(null); @@ -126,11 +127,11 @@ export function ValueMappingEditRow({ mapping, index, onChange, onRemove, onDupl ]; return ( - + {(provided) => ( - + -
+
diff --git a/public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingsEditorModal.tsx b/public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingsEditorModal.tsx index aacb26e065a..0c1eef75097 100644 --- a/public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingsEditorModal.tsx +++ b/public/app/features/dimensions/editors/ValueMappingsEditor/ValueMappingsEditorModal.tsx @@ -1,4 +1,5 @@ import { css } from '@emotion/css'; +import { uniqueId } from 'lodash'; import React, { useEffect, useState } from 'react'; import { DragDropContext, Droppable, DropResult } from 'react-beautiful-dnd'; @@ -54,18 +55,11 @@ export function ValueMappingsEditorModal({ value, onChange, onClose, showIconPic ]; const onAddValueMapping = (value: SelectableValue) => { - updateRows([ - ...rows, - { - type: value.value!, - isNew: true, - result: {}, - }, - ]); + updateRows([...rows, createRow({ type: value.value!, result: {}, isNew: true })]); }; const onDuplicateMapping = (index: number) => { - const sourceRow = rows[index]; + const sourceRow = duplicateRow(rows[index]); const copy = [...rows]; copy.splice(index, 0, { ...sourceRow }); @@ -111,7 +105,7 @@ export function ValueMappingsEditorModal({ value, onChange, onClose, showIconPic {rows.map((row, index) => ( ({ }), }); +function getRowUniqueId(): string { + return uniqueId('mapping-'); +} + +function createRow(row: Partial): ValueMappingEditRowModel { + return { + type: MappingType.ValueToText, + result: {}, + id: getRowUniqueId(), + ...row, + }; +} + +function duplicateRow(row: Partial): ValueMappingEditRowModel { + return { + ...createRow(row), + // provide a new unique id to the duplicated row, to preserve focus when dragging 2 duplicated rows + id: getRowUniqueId(), + }; +} + export function editModelToSaveModel(rows: ValueMappingEditRowModel[]) { const mappings: ValueMapping[] = []; const valueMaps: ValueMapping = { @@ -250,34 +265,42 @@ export function buildEditRowModels(value: ValueMapping[]) { switch (mapping.type) { case MappingType.ValueToText: for (const key of Object.keys(mapping.options)) { - editRows.push({ - type: mapping.type, - result: mapping.options[key], - key, - }); + editRows.push( + createRow({ + type: mapping.type, + result: mapping.options[key], + key, + }) + ); } break; case MappingType.RangeToText: - editRows.push({ - type: mapping.type, - result: mapping.options.result, - from: mapping.options.from ?? 0, - to: mapping.options.to ?? 0, - }); + editRows.push( + createRow({ + type: mapping.type, + result: mapping.options.result, + from: mapping.options.from ?? 0, + to: mapping.options.to ?? 0, + }) + ); break; case MappingType.RegexToText: - editRows.push({ - type: mapping.type, - result: mapping.options.result, - pattern: mapping.options.pattern, - }); + editRows.push( + createRow({ + type: mapping.type, + result: mapping.options.result, + pattern: mapping.options.pattern, + }) + ); break; case MappingType.SpecialValue: - editRows.push({ - type: mapping.type, - result: mapping.options.result, - specialMatch: mapping.options.match ?? SpecialValueMatch.Null, - }); + editRows.push( + createRow({ + type: mapping.type, + result: mapping.options.result, + specialMatch: mapping.options.match ?? SpecialValueMatch.Null, + }) + ); } } }