TableNativePlugin

Summary: _typescript_

Reviewed By: priteshrnandgaonkar

Differential Revision: D16828096

fbshipit-source-id: 5850ac4dbf120d2e6b38761701b44d20565d00e7
This commit is contained in:
Daniel Büchele
2019-08-20 03:18:32 -07:00
committed by Facebook Github Bot
parent 3730167b77
commit 0ebacecaf6
2 changed files with 95 additions and 80 deletions

View File

@@ -246,7 +246,7 @@ export default class Client extends EventEmitter {
} }
}) })
.filter(Boolean); .filter(Boolean);
this.store.dispatch(registerPlugins(nativeplugins)); this.store.dispatch(registerPlugins(nativeplugins as any));
return plugins; return plugins;
} }

View File

@@ -5,89 +5,86 @@
* @format * @format
*/ */
import { import ManagedDataInspector from '../ui/components/data-inspector/ManagedDataInspector';
ManagedDataInspector, import Panel from '../ui/components/Panel';
Panel, import {colors} from '../ui/components/colors';
colors, import styled from 'react-emotion';
styled, import Text from '../ui/components/Text';
Text, import Toolbar from '../ui/components/Toolbar';
Toolbar, import Spacer from '../ui/components/Toolbar';
Spacer, import Button from '../ui/components/Button';
Button, import Select from '../ui/components/Select';
Select,
} from 'flipper';
import ErrorBlock from '../ui/components/ErrorBlock'; import ErrorBlock from '../ui/components/ErrorBlock';
import FlexColumn from '../ui/components/FlexColumn'; import FlexColumn from '../ui/components/FlexColumn';
import DetailSidebar from '../chrome/DetailSidebar.tsx';
import {FlipperPlugin} from '../plugin.tsx';
import SearchableTable from '../ui/components/searchable/SearchableTable'; import SearchableTable from '../ui/components/searchable/SearchableTable';
import textContent from '../utils/textContent.tsx'; import TableHighlightedRows from '../ui/components/table/types';
import createPaste from '../fb-stubs/createPaste.tsx'; import TableRows from '../ui/components/table/types';
import TableColumnSizes from '../ui/components/table/types';
import type {Node} from 'react'; import TableColumns from '../ui/components/table/types';
import type { import TableColumnOrderVal from '../ui/components/table/types';
TableHighlightedRows, import TableBodyRow from '../ui/components/table/types';
TableRows, import DetailSidebar from '../chrome/DetailSidebar';
TableColumnSizes, import {FlipperPlugin} from '../plugin';
TableColumns, import textContent from '../utils/textContent';
TableColumnOrderVal, import createPaste from '../fb-stubs/createPaste';
TableBodyRow, import {ReactNode} from 'react';
} from 'flipper'; import React from 'react';
import {KeyboardActions} from 'src/MenuBar';
type ID = string; type ID = string;
type TableMetadata = { type TableMetadata = {
topToolbar?: ToolbarSection, topToolbar?: ToolbarSection;
bottomToolbar?: ToolbarSection, bottomToolbar?: ToolbarSection;
columns: TableColumns, columns: TableColumns;
columnSizes?: TableColumnSizes, columnSizes?: TableColumnSizes;
columnOrder?: Array<TableColumnOrderVal>, columnOrder?: Array<TableColumnOrderVal>;
filterableColumns?: Set<string>, filterableColumns?: Set<string>;
}; };
type PersistedState = {| type PersistedState = {
rows: TableRows, rows: TableRows;
datas: {[key: ID]: NumberedRowData}, datas: {[key: string]: NumberedRowData};
tableMetadata: ?TableMetadata, tableMetadata: TableMetadata | null | undefined;
|}; };
type State = {| type State = {
selectedIds: Array<ID>, selectedIds: Array<ID>;
error: ?string, error: string | null | undefined;
|}; };
type RowData = { type RowData = {
id: string, id: string;
columns: {[key: string]: any}, columns: {[key: string]: any};
sidebar?: Array<SidebarSection>, sidebar?: Array<SidebarSection>;
}; };
type NumberedRowData = { type NumberedRowData = {
id: string, id: string;
columns: {[key: string]: any}, columns: {[key: string]: any};
sidebar?: Array<SidebarSection>, sidebar?: Array<SidebarSection>;
rowNumber: number, rowNumber: number;
}; };
type SidebarSection = JsonSection | ToolbarSection; type SidebarSection = JsonSection | ToolbarSection;
type JsonSection = { type JsonSection = {
type: 'json', type: 'json';
title: string, title: string;
content: string, content: string;
}; };
type ToolbarSection = { type ToolbarSection = {
type: 'toolbar', type: 'toolbar';
items: Array<ToolbarItem>, items: Array<ToolbarItem>;
}; };
type ToolbarItem = type ToolbarItem =
| {type: 'link', destination: string, label: string} | {type: 'link'; destination: string; label: string}
| { | {
type: 'input', type: 'input';
inputType: 'select', inputType: 'select';
id: string, id: string;
label: string, label: string;
options: Array<string>, options: Array<string>;
value: string, value: string;
}; };
const NonWrappingText = styled(Text)({ const NonWrappingText = styled(Text)({
@@ -97,7 +94,7 @@ const NonWrappingText = styled(Text)({
userSelect: 'none', userSelect: 'none',
}); });
const BooleanValue = styled(NonWrappingText)(props => ({ const BooleanValue = styled(NonWrappingText)((props: {active?: boolean}) => ({
'&::before': { '&::before': {
content: '""', content: '""',
display: 'inline-block', display: 'inline-block',
@@ -110,7 +107,7 @@ const BooleanValue = styled(NonWrappingText)(props => ({
}, },
})); }));
const Label = styled('Span')({ const Label = styled('span')({
fontSize: 12, fontSize: 12,
color: '#90949c', color: '#90949c',
fontWeight: 'bold', fontWeight: 'bold',
@@ -119,7 +116,7 @@ const Label = styled('Span')({
marginRight: 12, marginRight: 12,
}); });
function renderValue({type, value}: {type: string, value: any}) { function renderValue({type, value}: {type: string; value: any}) {
switch (type) { switch (type) {
case 'boolean': case 'boolean':
return ( return (
@@ -132,7 +129,10 @@ function renderValue({type, value}: {type: string, value: any}) {
} }
} }
function buildRow(rowData: RowData, previousRowData: ?RowData): TableBodyRow { function buildRow(
rowData: RowData,
previousRowData: RowData | null | undefined,
): TableBodyRow {
if (!rowData.columns) { if (!rowData.columns) {
throw new Error('defaultBuildRow used with incorrect data format.'); throw new Error('defaultBuildRow used with incorrect data format.');
} }
@@ -140,8 +140,13 @@ function buildRow(rowData: RowData, previousRowData: ?RowData): TableBodyRow {
previousRowData && previousRowData.columns previousRowData && previousRowData.columns
? Object.keys(previousRowData.columns).reduce((map, key) => { ? Object.keys(previousRowData.columns).reduce((map, key) => {
if (key !== 'id') { if (key !== 'id') {
let value = null;
if (previousRowData && previousRowData.columns) {
value = previousRowData.columns[key].value;
}
map[key] = { map[key] = {
value: (previousRowData?.columns || {})[key].value, value,
isFilterable: true, isFilterable: true,
}; };
} }
@@ -183,7 +188,7 @@ function renderToolbar(section: ToolbarSection) {
obj[item] = item; obj[item] = item;
return obj; return obj;
}, {})} }, {})}
value={item.value} selected={item.value}
onChange={() => {}} onChange={() => {}}
/>, />,
]; ];
@@ -197,7 +202,7 @@ function renderToolbar(section: ToolbarSection) {
); );
} }
function renderSidebarForRow(rowData: RowData): Node { function renderSidebarForRow(rowData: RowData): ReactNode {
if (!rowData.sidebar) { if (!rowData.sidebar) {
return null; return null;
} }
@@ -207,7 +212,10 @@ function renderSidebarForRow(rowData: RowData): Node {
return rowData.sidebar.map(renderSidebarSection); return rowData.sidebar.map(renderSidebarSection);
} }
function renderSidebarSection(section: SidebarSection, index: number): Node { function renderSidebarSection(
section: SidebarSection,
index: number,
): ReactNode {
switch (section.type) { switch (section.type) {
case 'json': case 'json':
return ( return (
@@ -227,12 +235,13 @@ function renderSidebarSection(section: SidebarSection, index: number): Node {
} }
type IncomingMessage = type IncomingMessage =
| {method: 'updateRows', data: Array<RowData>} | {method: 'updateRows'; data: Array<RowData>}
| {method: 'clearTable'}; | {method: 'clearTable'};
export default function createTableNativePlugin(id: string, title: string) { export default function createTableNativePlugin(id: string, title: string) {
return class extends FlipperPlugin<State, *, PersistedState> { // @ts-ignore
static keyboardActions = ['clear', 'createPaste']; return class extends FlipperPlugin<State, any, PersistedState> {
static keyboardActions: KeyboardActions = ['clear', 'createPaste'];
static id = id || ''; static id = id || '';
static title = title || ''; static title = title || '';
@@ -245,7 +254,7 @@ export default function createTableNativePlugin(id: string, title: string) {
static typedPersistedStateReducer = ( static typedPersistedStateReducer = (
persistedState: PersistedState, persistedState: PersistedState,
message: IncomingMessage, message: IncomingMessage,
): $Shape<PersistedState> => { ): Partial<PersistedState> => {
if (message.method === 'updateRows') { if (message.method === 'updateRows') {
const newRows = []; const newRows = [];
const newData = {}; const newData = {};
@@ -256,7 +265,7 @@ export default function createTableNativePlugin(id: string, title: string) {
`updateRows: row is missing id: ${JSON.stringify(rowData)}`, `updateRows: row is missing id: ${JSON.stringify(rowData)}`,
); );
} }
const previousRowData: ?NumberedRowData = const previousRowData: NumberedRowData | null | undefined =
persistedState.datas[rowData.id]; persistedState.datas[rowData.id];
const newRow: TableBodyRow = buildRow(rowData, previousRowData); const newRow: TableBodyRow = buildRow(rowData, previousRowData);
if (persistedState.datas[rowData.id] == null) { if (persistedState.datas[rowData.id] == null) {
@@ -292,14 +301,20 @@ export default function createTableNativePlugin(id: string, title: string) {
} }
}; };
static persistedStateReducer = ( static persistedStateReducer(
persistedState: PersistedState, persistedState: PersistedState,
method: string, method: 'updateRows' | 'clearTable',
data: any, data: Array<RowData> | undefined,
): $Shape<PersistedState> => { ): Partial<PersistedState> {
// $FlowFixMe Unsafely treat the recieved message as what we're expecting. const message: IncomingMessage =
return this.typedPersistedStateReducer(persistedState, {method, data}); method === 'updateRows'
}; ? {
method,
data,
}
: {method};
return this.typedPersistedStateReducer(persistedState, message);
}
state = { state = {
selectedIds: [], selectedIds: [],