Undo nativeplugin changes to createTablePlugin.js

Summary: Now that it has been inlined into TableNativePlugin, I'm reverting it back to it was before to keep it simple.

Reviewed By: passy

Differential Revision: D14800383

fbshipit-source-id: 81725134b6598c03e3ddfb1eb9269d463815dc82
This commit is contained in:
John Knox
2019-04-09 06:39:41 -07:00
committed by Facebook Github Bot
parent 287cad2f4b
commit 40b1c569ad
2 changed files with 41 additions and 199 deletions

View File

@@ -8,57 +8,42 @@
import {createTablePlugin} from '../createTablePlugin.js'; import {createTablePlugin} from '../createTablePlugin.js';
import {FlipperPlugin} from '../plugin.js'; import {FlipperPlugin} from '../plugin.js';
const KNOWN_METADATA_PROPS = { const PROPS = {
method: 'method', method: 'method',
resetMethod: 'resetMethod', resetMethod: 'resetMethod',
columns: {}, columns: {},
columnSizes: {}, columnSizes: {},
renderSidebar: () => {}, renderSidebar: () => {},
buildRow: () => { buildRow: () => {},
return {columns: {}, key: 'someKey'};
},
};
const DYNAMIC_METADATA_PROPS = {
method: 'method',
resetMethod: 'resetMethod',
id: 'testytest',
title: 'TestPlugin',
renderSidebar: () => {},
buildRow: () => {
return {columns: {}, key: 'someKey'};
},
}; };
test('createTablePlugin returns FlipperPlugin', () => { test('createTablePlugin returns FlipperPlugin', () => {
const tablePlugin = createTablePlugin({...KNOWN_METADATA_PROPS}); const tablePlugin = createTablePlugin({...PROPS});
expect(tablePlugin.prototype).toBeInstanceOf(FlipperPlugin); expect(tablePlugin.prototype).toBeInstanceOf(FlipperPlugin);
}); });
test('persistedStateReducer is resetting data', () => { test('persistedStateReducer is resetting data', () => {
const resetMethod = 'resetMethod'; const resetMethod = 'resetMethod';
const tablePlugin = createTablePlugin({...KNOWN_METADATA_PROPS, resetMethod}); const tablePlugin = createTablePlugin({...PROPS, resetMethod});
const ps = { // $FlowFixMe persistedStateReducer exists for createTablePlugin
datas: {'1': {id: '1', rowNumber: 0}}, const {rows, datas} = tablePlugin.persistedStateReducer(
rows: [ {
{ datas: {'1': {id: '1'}},
key: '1', rows: [
columns: { {
id: { key: '1',
value: '1', columns: {
id: {
value: '1',
},
}, },
}, },
}, ],
], },
tableMetadata: null, resetMethod,
}; {},
);
if (!tablePlugin.persistedStateReducer) {
expect(tablePlugin.persistedStateReducer).toBeDefined();
return;
}
const {rows, datas} = tablePlugin.persistedStateReducer(ps, resetMethod, {});
expect(datas).toEqual({}); expect(datas).toEqual({});
expect(rows).toEqual([]); expect(rows).toEqual([]);
@@ -66,44 +51,18 @@ test('persistedStateReducer is resetting data', () => {
test('persistedStateReducer is adding data', () => { test('persistedStateReducer is adding data', () => {
const method = 'method'; const method = 'method';
const tablePlugin = createTablePlugin({...KNOWN_METADATA_PROPS, method}); const tablePlugin = createTablePlugin({...PROPS, method});
const id = '1'; const id = '1';
const ps = { // $FlowFixMe persistedStateReducer exists for createTablePlugin
datas: {}, const {rows, datas} = tablePlugin.persistedStateReducer(
rows: [], {
tableMetadata: null, datas: {},
}; rows: [],
},
if (!tablePlugin.persistedStateReducer) { method,
expect(tablePlugin.persistedStateReducer).toBeDefined(); {id},
return; );
}
const {rows, datas} = tablePlugin.persistedStateReducer(ps, method, {id});
expect(rows.length).toBe(1);
expect(Object.keys(datas)).toEqual([id]);
});
test('dyn persistedStateReducer is adding data', () => {
const method = 'method';
const tablePlugin = createTablePlugin({...DYNAMIC_METADATA_PROPS, method});
const id = '1';
const ps = {
datas: {},
rows: [],
tableMetadata: null,
};
if (!tablePlugin.persistedStateReducer) {
expect(tablePlugin.persistedStateReducer).toBeDefined();
return;
}
const {rows, datas} = tablePlugin.persistedStateReducer(ps, method, {
id,
columns: {},
});
expect(rows.length).toBe(1); expect(rows.length).toBe(1);
expect(Object.keys(datas)).toEqual([id]); expect(Object.keys(datas)).toEqual([id]);

View File

@@ -10,9 +10,6 @@ import type {
TableRows, TableRows,
TableColumnSizes, TableColumnSizes,
TableColumns, TableColumns,
TableColumnOrder,
TableColumnOrderVal,
TableBodyRow,
} from 'flipper'; } from 'flipper';
import FlexColumn from './ui/components/FlexColumn'; import FlexColumn from './ui/components/FlexColumn';
@@ -27,45 +24,20 @@ type ID = string;
type RowData = { type RowData = {
id: ID, id: ID,
columns?: {[key: string]: any},
details?: Object,
};
type Numbered<T> = {
...T,
id: ID,
rowNumber: number,
};
type TableMetadata = {
columns: TableColumns,
columnSizes?: TableColumnSizes,
columnOrder?: Array<TableColumnOrderVal>,
filterableColumns?: Set<string>,
}; };
type Props<T> = {| type Props<T> = {|
method: string, method: string,
resetMethod?: string, resetMethod?: string,
... columns: TableColumns,
| {| columnSizes: TableColumnSizes,
columns: TableColumns,
columnSizes?: TableColumnSizes,
columnOrder?: TableColumnOrder,
filterableColumns?: Set<string>,
|}
| {|
id: string,
title: string,
|},
renderSidebar: (row: T) => any, renderSidebar: (row: T) => any,
buildRow: (row: T, previousData: ?T) => TableBodyRow, buildRow: (row: T) => any,
|}; |};
type PersistedState<T> = {| type PersistedState<T> = {|
rows: TableRows, rows: TableRows,
datas: {[key: ID]: Numbered<T>}, datas: {[key: ID]: T},
tableMetadata: ?TableMetadata,
|}; |};
type State = {| type State = {|
@@ -81,9 +53,6 @@ type State = {|
* of data objects or a single data object. Each data object represents a row in the table which is * 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. * build by calling the `buildRow` function argument.
* *
* The component can be constructed directly with the table metadata in props,
or if omitted, will call the mobile plugin to dynamically determine the table metadata.
*
* An optional resetMethod argument can be provided which will replace the current rows with the * 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 * data provided. This is useful when connecting to Flipper for this first time, or reconnecting to
* the client in an unknown state. * the client in an unknown state.
@@ -91,27 +60,17 @@ type State = {|
export function createTablePlugin<T: RowData>(props: Props<T>) { export function createTablePlugin<T: RowData>(props: Props<T>) {
return class extends FlipperPlugin<State, *, PersistedState<T>> { return class extends FlipperPlugin<State, *, PersistedState<T>> {
static keyboardActions = ['clear', 'createPaste']; static keyboardActions = ['clear', 'createPaste'];
static id = props.id || '';
static title = props.title || '';
static defaultPersistedState: PersistedState<T> = { static defaultPersistedState: PersistedState<T> = {
rows: [], rows: [],
datas: {}, datas: {},
tableMetadata: props.columns
? {
columns: props.columns,
columnSizes: props.columnSizes,
columnOrder: props.columnOrder,
filterableColumns: props.filterableColumns,
}
: null,
}; };
static persistedStateReducer = ( static persistedStateReducer = (
persistedState: PersistedState<T>, persistedState: PersistedState<T>,
method: string, method: string,
payload: T | Array<T>, payload: T | Array<T>,
): $Shape<PersistedState<T>> => { ): $Shape<PersistedState<RowData>> => {
if (method === props.method) { if (method === props.method) {
const newRows = []; const newRows = [];
const newData = {}; const newData = {};
@@ -121,33 +80,17 @@ export function createTablePlugin<T: RowData>(props: Props<T>) {
if (data.id == null) { if (data.id == null) {
console.warn('The data sent did not contain an ID.', data); console.warn('The data sent did not contain an ID.', data);
} }
const previousRowData: ?Numbered<T> = persistedState.datas[data.id];
const newRow = props.buildRow(data, previousRowData);
if (persistedState.datas[data.id] == null) { if (persistedState.datas[data.id] == null) {
newData[data.id] = { newData[data.id] = data;
...data, newRows.push(props.buildRow(data));
rowNumber: persistedState.rows.length + newRows.length,
};
newRows.push(newRow);
} else {
persistedState.rows = persistedState.rows
.slice(0, persistedState.datas[data.id].rowNumber)
.concat(
[newRow],
persistedState.rows.slice(
persistedState.datas[data.id].rowNumber + 1,
),
);
} }
} }
return { return {
...persistedState,
datas: {...persistedState.datas, ...newData}, datas: {...persistedState.datas, ...newData},
rows: [...persistedState.rows, ...newRows], rows: [...persistedState.rows, ...newRows],
}; };
} else if (method === props.resetMethod) { } else if (method === props.resetMethod) {
return { return {
...persistedState,
rows: [], rows: [],
datas: {}, datas: {},
}; };
@@ -160,23 +103,6 @@ export function createTablePlugin<T: RowData>(props: Props<T>) {
selectedIds: [], selectedIds: [],
}; };
init() {
this.getTableMetadata();
}
getTableMetadata = () => {
if (!this.props.persistedState.tableMetadata) {
this.client.call('getMetadata').then(metadata => {
this.props.setPersistedState({
tableMetadata: {
...metadata,
filterableColumns: new Set(metadata.filterableColumns),
},
});
});
}
};
onKeyboardAction = (action: string) => { onKeyboardAction = (action: string) => {
if (action === 'clear') { if (action === 'clear') {
this.clear(); this.clear();
@@ -196,16 +122,9 @@ export function createTablePlugin<T: RowData>(props: Props<T>) {
}; };
createPaste = () => { createPaste = () => {
if (!this.props.persistedState.tableMetadata) {
return;
}
let paste = ''; let paste = '';
const mapFn = row => const mapFn = row =>
( Object.keys(props.columns)
(this.props.persistedState.tableMetadata &&
Object.keys(this.props.persistedState.tableMetadata.columns)) ||
[]
)
.map(key => textContent(row.columns[key].value)) .map(key => textContent(row.columns[key].value))
.join('\t'); .join('\t');
@@ -228,36 +147,8 @@ export function createTablePlugin<T: RowData>(props: Props<T>) {
}); });
}; };
// We don't necessarily have the table metadata at the time when buildRow
// is being used. This includes presentation layer info like which
// columns should be filterable. This does a pass over the built rows and
// applies that presentation layer information.
applyMetadataToRows(rows: TableRows): TableRows {
if (!this.props.persistedState.tableMetadata) {
console.error(
'applyMetadataToRows called without tableMetadata present',
);
return rows;
}
return rows.map(r => {
return {
...r,
columns: Object.keys(r.columns).reduce((map, columnName) => {
map[columnName].isFilterable =
this.props.persistedState.tableMetadata &&
this.props.persistedState.tableMetadata.filterableColumns
? this.props.persistedState.tableMetadata.filterableColumns.has(
columnName,
)
: false;
return map;
}, r.columns),
};
});
}
renderSidebar = () => { renderSidebar = () => {
const renderSidebar = props.renderSidebar; const {renderSidebar} = props;
const {selectedIds} = this.state; const {selectedIds} = this.state;
const {datas} = this.props.persistedState; const {datas} = this.props.persistedState;
const selectedId = selectedIds.length !== 1 ? null : selectedIds[0]; const selectedId = selectedIds.length !== 1 ? null : selectedIds[0];
@@ -270,14 +161,7 @@ export function createTablePlugin<T: RowData>(props: Props<T>) {
}; };
render() { render() {
if (!this.props.persistedState.tableMetadata) { const {columns, columnSizes} = props;
return 'Loading...';
}
const {
columns,
columnSizes,
columnOrder,
} = this.props.persistedState.tableMetadata;
const {rows} = this.props.persistedState; const {rows} = this.props.persistedState;
return ( return (
@@ -288,11 +172,10 @@ export function createTablePlugin<T: RowData>(props: Props<T>) {
floating={false} floating={false}
multiline={true} multiline={true}
columnSizes={columnSizes} columnSizes={columnSizes}
columnOrder={columnOrder}
columns={columns} columns={columns}
onRowHighlighted={this.onRowHighlighted} onRowHighlighted={this.onRowHighlighted}
multiHighlight={true} multiHighlight={true}
rows={this.applyMetadataToRows(rows)} rows={rows}
stickyBottom={true} stickyBottom={true}
actions={<Button onClick={this.clear}>Clear Table</Button>} actions={<Button onClick={this.clear}>Clear Table</Button>}
/> />