/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @format */ import { Button, ManagedTable, Text, Glyph, styled, colors, Panel, } from 'flipper'; import React, {useContext, useState, useMemo, useEffect} from 'react'; import {Route, Requests} from './types'; import {MockResponseDetails} from './MockResponseDetails'; import {NetworkRouteContext} from './index'; import {RequestId} from './types'; import {message, Checkbox, Modal, Tooltip} from 'antd'; import {NUX, Layout} from 'flipper-plugin'; type Props = { routes: {[id: string]: Route}; highlightedRows: Set | null | undefined; requests: Requests; }; const ColumnSizes = {route: 'flex'}; const Columns = {route: {value: 'Route', resizable: false}}; const TextEllipsis = styled(Text)({ overflowX: 'hidden', textOverflow: 'ellipsis', maxWidth: '100%', lineHeight: '18px', paddingTop: 4, display: 'block', whiteSpace: 'nowrap', }); const Icon = styled(Glyph)({ marginTop: 5, marginRight: 8, }); // return ids that have the same pair of requestUrl and method; this will return only the duplicate function _duplicateIds(routes: {[id: string]: Route}): Array { const idSet: {[id: string]: {[method: string]: boolean}} = {}; return Object.entries(routes).reduce((acc: Array, [id, route]) => { if (idSet.hasOwnProperty(route.requestUrl)) { if (idSet[route.requestUrl].hasOwnProperty(route.requestMethod)) { return acc.concat(id); } idSet[route.requestUrl] = { ...idSet[route.requestUrl], [route.requestMethod]: true, }; return acc; } else { idSet[route.requestUrl] = {[route.requestMethod]: true}; return acc; } }, []); } function _buildRows( routes: {[id: string]: Route}, duplicatedIds: Array, handleRemoveId: (id: string) => void, handleEnableId: (id: string) => void, ) { return Object.entries(routes).map(([id, route]) => ({ columns: { route: { value: ( handleRemoveId(id)} handleEnableId={() => handleEnableId(id)} enabled={route.enabled} /> ), }, }, key: id, })); } function RouteRow(props: { text: string; showWarning: boolean; handleRemoveId: () => void; handleEnableId: () => void; enabled: boolean; }) { const tip = props.enabled ? 'Un-check to disable mock route' : 'Check to enable mock route'; return ( {props.showWarning && ( )} {props.text.length === 0 ? ( untitled ) : ( {props.text} )} ); } function ManagedMockResponseRightPanel(props: { id: string; route: Route; isDuplicated: boolean; }) { const {id, route, isDuplicated} = props; return ( ); } export function ManageMockResponsePanel(props: Props) { const networkRouteManager = useContext(NetworkRouteContext); const [selectedId, setSelectedId] = useState(null); useEffect(() => { setSelectedId((selectedId) => { const keys = Object.keys(props.routes); let returnValue: string | null = null; // selectId is null when there are no rows or it is the first time rows are shown if (selectedId === null) { if (keys.length === 0) { // there are no rows returnValue = null; } else { // first time rows are shown returnValue = keys[0]; } } else { if (keys.includes(selectedId)) { returnValue = selectedId; } else { // selectedId row value not in routes so default to first line returnValue = keys[0]; } } return returnValue; }); }, [props.routes]); const duplicatedIds = useMemo(() => _duplicateIds(props.routes), [ props.routes, ]); function getSelectedIds(): Set { const newSet = new Set(); newSet.add(selectedId ?? ''); return newSet; } function getPreviousId(id: string): string | null { const keys = Object.keys(props.routes); const currentIndex = keys.indexOf(id); if (currentIndex == 0) { return null; } else { return keys[currentIndex - 1]; } } function getNextId(id: string): string | null { const keys = Object.keys(props.routes); const currentIndex = keys.indexOf(id); if (currentIndex >= keys.length - 1) { return getPreviousId(id); } else { return keys[currentIndex + 1]; } } return ( { Modal.confirm({ title: 'Are you sure you want to delete this item?', icon: '', onOk() { const nextId = getNextId(id); networkRouteManager.removeRoute(id); setSelectedId(nextId); }, onCancel() {}, }); }, (id) => { networkRouteManager.enableRoute(id); }, )} stickyBottom={true} autoHeight={false} floating={false} zebra={false} onRowHighlighted={(selectedIds) => { const newSelectedId = selectedIds.length === 1 ? selectedIds[0] : null; setSelectedId(newSelectedId); }} highlightedRows={getSelectedIds()} /> {selectedId && props.routes.hasOwnProperty(selectedId) && ( )} ); }