/* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0 */ import React, { createRef } from "react"; import { Metric } from "../models"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faArrowUp, faArrowDown, faEllipsisV, faTrash, faGripVertical, } from "@fortawesome/free-solid-svg-icons"; import Button from "./Button"; import "./MetricsList.css"; import { useTranslation } from "react-i18next"; import DropdownMenu from "./DropdownMenu"; import { MenuItem } from "@reach/menu-button"; import { DragDropContext, Draggable, Droppable, DropResult, ResponderProvided, } from "react-beautiful-dnd"; interface Props { onClick: Function; onEdit?: Function; onDelete?: Function; onMoveUp?: Function; onMoveDown?: Function; metrics: Array; register?: Function; defaultChecked?: boolean; allowAddMetric: boolean; onDrag?: Function; onDrop?: Function; } function MetricsList(props: Props) { const caretUpRefs = props.metrics.map(() => createRef()); const caretDownRefs = props.metrics.map(() => createRef()); const { t } = useTranslation(); const onDelete = (metric: Metric) => { if (props.onDelete) { props.onDelete(metric); } }; const onEdit = (metric: Metric, position: number) => { if (props.onEdit) { props.onEdit(metric, position); } }; const onMoveDown = (index: number) => { if (props.onMoveDown) { setNextFocus(index, "Down"); props.onMoveDown(index); } }; const onMoveUp = (index: number) => { if (props.onMoveUp) { setNextFocus(index, "Up"); props.onMoveUp(index); } }; const setNextFocus = (index: number, direction: "Up" | "Down") => { let ref; /** * When moving a metric up or down, the focus should follow the * metric to its new position in the list. Determining the new * position depends on whether the metric is moving up or down * and if the metric has reached a boundary (i.e. beginning or * end of the list), in which case the focus should swap to the * opposite caret (careUp vs caretDown). * * We may not need this logic when we implement drag-n-drop * because most of the existing libraries already handle browser * focus when moving DOM objects. */ if (direction === "Up") { ref = index === 1 ? caretDownRefs[1] : caretUpRefs[index]; } else { const secondLast = props.metrics.length - 2; ref = index === secondLast ? caretUpRefs[secondLast] : caretDownRefs[index]; } if (ref.current) { ref.current.focus(); } }; function ActionMenu(metric: Metric) { return ( {}}> ); } const onDragEnd = (result: DropResult, provided: ResponderProvided) => { const { destination, source } = result; if (!destination) { return; } if (destination.droppableId === source.droppableId && destination.index === source.index) { return; } if (props.onDrag) { props.onDrag(source.index, destination.index); } }; return (

{t("MetricsGuidance")}

{props.metrics && props.metrics.length ? (
{(provided) => { return (
{props.metrics.map((metric, index) => { return ( {(provided, snapshot) => { return (
{index + 1}
{index > 0 ? ( ) : (
)}
{index < props.metrics.length - 1 ? ( ) : (
)}
{ActionMenu(metric)}
); }}
); })} {provided.placeholder}
); }}
{props.allowAddMetric && (
)}
) : (

{t("MetricsZero")}

)}
); } export default MetricsList;