clean up createTablePlugin abstraction
Summary: createTablePlugin isn't used anymore, since all FB plugins now use flipper-plugin's, version. Verified that no public OSS plugins use the abstraction either. This is part of a bigger stack to clean up immutable js usage / managed table duplication and export performance speed Reviewed By: jknoxville Differential Revision: D29265565 fbshipit-source-id: dd6671f0b3af857db1a512c6658e1ff75c49358d
This commit is contained in:
committed by
Facebook GitHub Bot
parent
2127dea447
commit
729922e8ad
@@ -1,77 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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 {createTablePlugin} from '../createTablePlugin';
|
|
||||||
import {FlipperPlugin} from '../plugin';
|
|
||||||
import {List, Map as ImmutableMap} from 'immutable';
|
|
||||||
import {TableRows_immutable} from '../ui/components/table/types';
|
|
||||||
|
|
||||||
const PROPS = {
|
|
||||||
method: 'method',
|
|
||||||
resetMethod: 'resetMethod',
|
|
||||||
columns: {},
|
|
||||||
columnSizes: {},
|
|
||||||
renderSidebar: () => {},
|
|
||||||
buildRow: () => {},
|
|
||||||
};
|
|
||||||
|
|
||||||
type PersistedState<T> = {
|
|
||||||
rows: TableRows_immutable;
|
|
||||||
datas: ImmutableMap<string, T>;
|
|
||||||
};
|
|
||||||
|
|
||||||
type RowData = {
|
|
||||||
id: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
test('createTablePlugin returns FlipperPlugin', () => {
|
|
||||||
const tablePlugin = createTablePlugin({...PROPS});
|
|
||||||
expect(tablePlugin.prototype).toBeInstanceOf(FlipperPlugin);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('persistedStateReducer is resetting data', () => {
|
|
||||||
const resetMethod = 'resetMethod';
|
|
||||||
const tablePlugin = createTablePlugin<RowData>({...PROPS, resetMethod});
|
|
||||||
|
|
||||||
const ps: PersistedState<RowData> = {
|
|
||||||
datas: ImmutableMap({'1': {id: '1'}}),
|
|
||||||
rows: List([
|
|
||||||
{
|
|
||||||
key: '1',
|
|
||||||
columns: {
|
|
||||||
id: {
|
|
||||||
value: '1',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
};
|
|
||||||
|
|
||||||
const {rows, datas} = tablePlugin.persistedStateReducer(ps, resetMethod, {
|
|
||||||
id: '0',
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(datas!.toJSON()).toEqual({});
|
|
||||||
expect(rows!.size).toBe(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('persistedStateReducer is adding data', () => {
|
|
||||||
const method = 'method';
|
|
||||||
const tablePlugin = createTablePlugin({...PROPS, method});
|
|
||||||
const id = '1';
|
|
||||||
|
|
||||||
const {rows, datas} = tablePlugin.persistedStateReducer(
|
|
||||||
tablePlugin.defaultPersistedState,
|
|
||||||
method,
|
|
||||||
{id},
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(rows!.size).toBe(1);
|
|
||||||
expect([...datas!.keys()]).toEqual([id]);
|
|
||||||
});
|
|
||||||
@@ -1,220 +0,0 @@
|
|||||||
/**
|
|
||||||
* 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 {
|
|
||||||
TableHighlightedRows,
|
|
||||||
TableRows_immutable,
|
|
||||||
TableColumnSizes,
|
|
||||||
TableColumns,
|
|
||||||
} from './ui';
|
|
||||||
import FlexColumn from './ui/components/FlexColumn';
|
|
||||||
import Button from './ui/components/Button';
|
|
||||||
import {DetailSidebar} from 'flipper-plugin';
|
|
||||||
import {FlipperPlugin} from './plugin';
|
|
||||||
import SearchableTable_immutable from './ui/components/searchable/SearchableTable_immutable';
|
|
||||||
import textContent from './utils/textContent';
|
|
||||||
import createPaste from './fb-stubs/createPaste';
|
|
||||||
import {List, Map as ImmutableMap} from 'immutable';
|
|
||||||
import React from 'react';
|
|
||||||
import {KeyboardActions} from './MenuBar';
|
|
||||||
import {TableBodyRow} from './ui';
|
|
||||||
import {Idler} from 'flipper-plugin';
|
|
||||||
|
|
||||||
type ID = string;
|
|
||||||
|
|
||||||
export interface RowData {
|
|
||||||
id: ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
type Props<T> = {
|
|
||||||
method: string;
|
|
||||||
resetMethod?: string;
|
|
||||||
columns: TableColumns;
|
|
||||||
columnSizes: TableColumnSizes;
|
|
||||||
renderSidebar: (row: T) => any;
|
|
||||||
buildRow: (row: T) => any;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type PersistedState<T> = {
|
|
||||||
rows: TableRows_immutable;
|
|
||||||
datas: ImmutableMap<ID, T>;
|
|
||||||
};
|
|
||||||
|
|
||||||
type State = {
|
|
||||||
selectedIds: Array<ID>;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* createTablePlugin creates a Plugin class which handles fetching data from the client and
|
|
||||||
* displaying in in a table. The table handles selection of items and rendering a sidebar where
|
|
||||||
* more detailed information can be presented about the selected row.
|
|
||||||
*
|
|
||||||
* The plugin expects the be able to subscribe to the `method` argument and recieve either an array
|
|
||||||
* of data objects or a single data object. Each data object represents a row in the table which is
|
|
||||||
* build by calling the `buildRow` function argument.
|
|
||||||
*
|
|
||||||
* An optional resetMethod argument can be provided which will replace the current rows with the
|
|
||||||
* data provided. This is useful when connecting to Flipper for this first time, or reconnecting to
|
|
||||||
* the client in an unknown state.
|
|
||||||
*
|
|
||||||
* @deprecated use createTablePlugin from flipper-plugin instead
|
|
||||||
*/
|
|
||||||
export function createTablePlugin<T extends RowData>(props: Props<T>) {
|
|
||||||
return class extends FlipperPlugin<State, any, PersistedState<T>> {
|
|
||||||
static keyboardActions: KeyboardActions = ['clear', 'createPaste'];
|
|
||||||
|
|
||||||
static defaultPersistedState = {
|
|
||||||
rows: List(),
|
|
||||||
datas: ImmutableMap<ID, T>(),
|
|
||||||
};
|
|
||||||
|
|
||||||
static persistedStateReducer = (
|
|
||||||
persistedState: PersistedState<T>,
|
|
||||||
method: string,
|
|
||||||
payload: T | Array<T>,
|
|
||||||
): Partial<PersistedState<T>> => {
|
|
||||||
if (method === props.method) {
|
|
||||||
return List(Array.isArray(payload) ? payload : [payload]).reduce(
|
|
||||||
(ps: PersistedState<any>, data: T) => {
|
|
||||||
if (data.id == null) {
|
|
||||||
console.warn('The data sent did not contain an ID.', data);
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
datas: ps.datas.set(data.id, data),
|
|
||||||
rows: ps.rows.push(props.buildRow(data)),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
persistedState,
|
|
||||||
);
|
|
||||||
} else if (method === props.resetMethod) {
|
|
||||||
return {
|
|
||||||
rows: List(),
|
|
||||||
datas: ImmutableMap(),
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static serializePersistedState: (
|
|
||||||
persistedState: PersistedState<T>,
|
|
||||||
statusUpdate?: (msg: string) => void,
|
|
||||||
idler?: Idler,
|
|
||||||
pluginName?: string,
|
|
||||||
) => Promise<string> = async (
|
|
||||||
persistedState: PersistedState<T>,
|
|
||||||
_statusUpdate?: (msg: string) => void,
|
|
||||||
_idler?: Idler,
|
|
||||||
_pluginName?: string,
|
|
||||||
) => {
|
|
||||||
const serializable = {
|
|
||||||
rows: persistedState.rows,
|
|
||||||
datas: persistedState.datas.toArray(),
|
|
||||||
};
|
|
||||||
return JSON.stringify(serializable);
|
|
||||||
};
|
|
||||||
|
|
||||||
static deserializePersistedState: (
|
|
||||||
serializedString: string,
|
|
||||||
) => PersistedState<T> = (serializedString: string) => {
|
|
||||||
const parse = JSON.parse(serializedString);
|
|
||||||
return {
|
|
||||||
rows: List(parse.rows) as TableRows_immutable,
|
|
||||||
datas: ImmutableMap(parse.datas) as ImmutableMap<ID, T>,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
state: State = {
|
|
||||||
selectedIds: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
onKeyboardAction = (action: string) => {
|
|
||||||
if (action === 'clear') {
|
|
||||||
this.clear();
|
|
||||||
} else if (action === 'createPaste') {
|
|
||||||
this.createPaste();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
clear = () => {
|
|
||||||
this.props.setPersistedState({
|
|
||||||
rows: List(),
|
|
||||||
datas: ImmutableMap(),
|
|
||||||
});
|
|
||||||
this.setState({
|
|
||||||
selectedIds: [],
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
createPaste = () => {
|
|
||||||
let paste = '';
|
|
||||||
const mapFn = (row: TableBodyRow) =>
|
|
||||||
Object.keys(props.columns)
|
|
||||||
.map((key) => textContent(row.columns[key].value))
|
|
||||||
.join('\t');
|
|
||||||
|
|
||||||
if (this.state.selectedIds.length > 0) {
|
|
||||||
// create paste from selection
|
|
||||||
paste = this.props.persistedState.rows
|
|
||||||
.filter(
|
|
||||||
(row: TableBodyRow) => this.state.selectedIds.indexOf(row.key) > -1,
|
|
||||||
)
|
|
||||||
.map(mapFn)
|
|
||||||
.join('\n');
|
|
||||||
} else {
|
|
||||||
// create paste with all rows
|
|
||||||
paste = this.props.persistedState.rows.map(mapFn).join('\n');
|
|
||||||
}
|
|
||||||
createPaste(paste);
|
|
||||||
};
|
|
||||||
|
|
||||||
onRowHighlighted = (keys: TableHighlightedRows) => {
|
|
||||||
this.setState({
|
|
||||||
selectedIds: keys,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
renderSidebar = () => {
|
|
||||||
const {renderSidebar} = props;
|
|
||||||
const {selectedIds} = this.state;
|
|
||||||
const {datas} = this.props.persistedState;
|
|
||||||
const selectedId = selectedIds.length !== 1 ? null : selectedIds[0];
|
|
||||||
|
|
||||||
if (selectedId != null) {
|
|
||||||
const data = datas.get(selectedId);
|
|
||||||
return data != null ? renderSidebar(data) : null;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {columns, columnSizes} = props;
|
|
||||||
const {rows} = this.props.persistedState;
|
|
||||||
return (
|
|
||||||
<FlexColumn grow>
|
|
||||||
<SearchableTable_immutable
|
|
||||||
key={this.constructor.id}
|
|
||||||
rowLineHeight={28}
|
|
||||||
floating={false}
|
|
||||||
multiline
|
|
||||||
columnSizes={columnSizes}
|
|
||||||
columns={columns}
|
|
||||||
onRowHighlighted={this.onRowHighlighted}
|
|
||||||
multiHighlight
|
|
||||||
rows={rows}
|
|
||||||
stickyBottom
|
|
||||||
actions={<Button onClick={this.clear}>Clear Table</Button>}
|
|
||||||
/>
|
|
||||||
<DetailSidebar>{this.renderSidebar()}</DetailSidebar>
|
|
||||||
</FlexColumn>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -47,7 +47,6 @@ export {default as BaseDevice} from './devices/BaseDevice';
|
|||||||
export {DeviceLogEntry, LogLevel, DeviceLogListener} from 'flipper-plugin';
|
export {DeviceLogEntry, LogLevel, DeviceLogListener} from 'flipper-plugin';
|
||||||
export {deconstructClientId} from './utils/clientUtils';
|
export {deconstructClientId} from './utils/clientUtils';
|
||||||
export {default as isProduction} from './utils/isProduction';
|
export {default as isProduction} from './utils/isProduction';
|
||||||
export {createTablePlugin} from './createTablePlugin';
|
|
||||||
export {DetailSidebar} from 'flipper-plugin';
|
export {DetailSidebar} from 'flipper-plugin';
|
||||||
export {default as Device} from './devices/BaseDevice';
|
export {default as Device} from './devices/BaseDevice';
|
||||||
export {default as AndroidDevice} from './devices/AndroidDevice';
|
export {default as AndroidDevice} from './devices/AndroidDevice';
|
||||||
|
|||||||
Reference in New Issue
Block a user