(Server) Add ManageMockResponsePanel

Summary:
- Add ManageMockResponsePanel to add, modify and remove mocked route

Note:
- This is a part of this PR: https://github.com/facebook/flipper/pull/488

Reviewed By: mweststrate

Differential Revision: D20440147

fbshipit-source-id: 3af127c4b091f288c13b41b74d78c07b4eb0e52f
This commit is contained in:
Chaiwat Ekkaewnumchai
2020-03-17 10:05:27 -07:00
committed by Facebook GitHub Bot
parent 95376a17b9
commit adb1d6e976

View File

@@ -0,0 +1,200 @@
/**
* 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 {
ManagedTable,
Text,
FlexBox,
FlexRow,
FlexColumn,
Glyph,
styled,
colors,
Panel,
} from 'flipper';
import React, {useContext, useState, useMemo, useEffect} from 'react';
import {Route} from './types';
import {MockResponseDetails} from './MockResponseDetails';
import {NetworkRouteContext} from './index';
import {RequestId} from './types';
type Props = {routes: {[id: string]: Route}};
const ColumnSizes = {route: 'flex'};
const Columns = {route: {value: 'Route', resizable: false}};
const AddRouteButton = styled(FlexBox)({
color: colors.blackAlpha50,
alignItems: 'center',
padding: 10,
flexShrink: 0,
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
});
const Container = styled(FlexRow)({
flex: 1,
justifyContent: 'space-around',
alignItems: 'stretch',
});
const LeftPanel = styled(FlexColumn)({
flex: 1,
});
const RightPanel = styled(FlexColumn)({
flex: 3,
height: '100%',
});
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<RequestId> {
const idSet: {[id: string]: {[method: string]: boolean}} = {};
return Object.entries(routes).reduce((acc: Array<RequestId>, [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<string>,
) {
return Object.entries(routes).map(([id, route]) => ({
columns: {
route: {
value: duplicatedIds.includes(id) ? (
<FlexRow>
<Icon name="caution-triangle" color={colors.yellow} />
<TextEllipsis>{route.requestUrl}</TextEllipsis>
</FlexRow>
) : (
<TextEllipsis>{route.requestUrl}</TextEllipsis>
),
},
},
key: id,
}));
}
function ManagedMockResponseRightPanel(props: {
id: string;
route: Route;
isDuplicated: boolean;
}) {
const {id, route, isDuplicated} = props;
return (
<Panel
grow={true}
collapsable={false}
floating={false}
heading={'Route Info'}>
<MockResponseDetails
key={id}
id={id}
route={route}
isDuplicated={isDuplicated}
/>
</Panel>
);
}
export function ManageMockResponsePanel(props: Props) {
const networkRouteManager = useContext(NetworkRouteContext);
const [selectedId, setSelectedId] = useState<RequestId | null>(null);
const [currentRouteSize, setCurrentRouteSize] = useState(0);
const {routes} = props;
useEffect(() => {
const keys = Object.keys(routes);
const routeSize = keys.length;
if (currentRouteSize === routeSize) {
return;
}
if (routeSize > 0 && routeSize > currentRouteSize) {
setSelectedId(keys[routeSize - 1]);
}
setCurrentRouteSize(routeSize);
}, [routes]);
const duplicatedIds = useMemo(() => _duplicateIds(routes), [routes]);
return (
<Container>
<LeftPanel>
<AddRouteButton
onClick={() => {
networkRouteManager.addRoute();
}}>
<Glyph
name="plus-circle"
size={16}
variant="outline"
color={colors.blackAlpha30}
/>
&nbsp;Add Route
</AddRouteButton>
<ManagedTable
hideHeader={true}
multiline={true}
columnSizes={ColumnSizes}
columns={Columns}
rows={_buildRows(routes, duplicatedIds)}
stickyBottom={true}
autoHeight={false}
floating={false}
zebra={false}
onRowHighlighted={selectedIds => {
const newSelectedId =
selectedIds.length === 1 ? selectedIds[0] : null;
setSelectedId(newSelectedId);
}}
highlightedRows={new Set(selectedId)}
/>
</LeftPanel>
<RightPanel>
{selectedId && routes.hasOwnProperty(selectedId) && (
<ManagedMockResponseRightPanel
id={selectedId}
route={routes[selectedId]}
isDuplicated={duplicatedIds.includes(selectedId)}
/>
)}
</RightPanel>
</Container>
);
}