Extracted and memoized components
Summary: Just small refactoring to extract / memoize some of components Reviewed By: mweststrate Differential Revision: D28055699 fbshipit-source-id: 3d689a4e41e3f3c4c4e2e8cc2887cb255b4c4dc2
This commit is contained in:
committed by
Facebook GitHub Bot
parent
ae65e2ccb8
commit
00fb573ba2
@@ -10,7 +10,8 @@
|
|||||||
import {Button, ButtonGroup, Glyph, colors} from 'flipper';
|
import {Button, ButtonGroup, Glyph, colors} from 'flipper';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
export default function ButtonNavigation(props: {
|
export default React.memo(
|
||||||
|
(props: {
|
||||||
/** Back button is enabled */
|
/** Back button is enabled */
|
||||||
canGoBack: boolean;
|
canGoBack: boolean;
|
||||||
/** Forwards button is enabled */
|
/** Forwards button is enabled */
|
||||||
@@ -19,7 +20,7 @@ export default function ButtonNavigation(props: {
|
|||||||
onBack: () => void;
|
onBack: () => void;
|
||||||
/** Callback when forwards button is clicked */
|
/** Callback when forwards button is clicked */
|
||||||
onForward: () => void;
|
onForward: () => void;
|
||||||
}) {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<ButtonGroup>
|
<ButtonGroup>
|
||||||
<Button disabled={!props.canGoBack} onClick={props.onBack}>
|
<Button disabled={!props.canGoBack} onClick={props.onBack}>
|
||||||
@@ -46,4 +47,5 @@ export default function ButtonNavigation(props: {
|
|||||||
</Button>
|
</Button>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
|
);
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import {
|
|||||||
TableRowSortOrder,
|
TableRowSortOrder,
|
||||||
Value,
|
Value,
|
||||||
renderValue,
|
renderValue,
|
||||||
|
TableHighlightedRows,
|
||||||
} from 'flipper';
|
} from 'flipper';
|
||||||
import React, {KeyboardEvent, ChangeEvent, useState, useCallback} from 'react';
|
import React, {KeyboardEvent, ChangeEvent, useState, useCallback} from 'react';
|
||||||
import {Methods, Events} from './ClientProtocol';
|
import {Methods, Events} from './ClientProtocol';
|
||||||
@@ -143,7 +144,7 @@ function transformRow(
|
|||||||
return {key: String(index), columns: transformedColumns};
|
return {key: String(index), columns: transformedColumns};
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderQueryHistory(history: Array<Query>) {
|
const QueryHistory = React.memo(({history}: {history: Array<Query>}) => {
|
||||||
if (!history || typeof history === 'undefined') {
|
if (!history || typeof history === 'undefined') {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -181,7 +182,7 @@ function renderQueryHistory(history: Array<Query>) {
|
|||||||
/>
|
/>
|
||||||
</FlexRow>
|
</FlexRow>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|
||||||
type PageInfoProps = {
|
type PageInfoProps = {
|
||||||
currentRow: number;
|
currentRow: number;
|
||||||
@@ -190,27 +191,33 @@ type PageInfoProps = {
|
|||||||
onChange: (currentRow: number, count: number) => void;
|
onChange: (currentRow: number, count: number) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
function PageInfo(props: PageInfoProps) {
|
const PageInfo = React.memo((props: PageInfoProps) => {
|
||||||
const [state, setState] = useState({
|
const [state, setState] = useState({
|
||||||
isOpen: false,
|
isOpen: false,
|
||||||
inputValue: String(props.currentRow),
|
inputValue: String(props.currentRow),
|
||||||
});
|
});
|
||||||
|
|
||||||
const onOpen = () => {
|
const onOpen = useCallback(() => {
|
||||||
setState({...state, isOpen: true});
|
setState({...state, isOpen: true});
|
||||||
};
|
}, [state]);
|
||||||
|
|
||||||
const onInputChanged = (e: ChangeEvent<any>) => {
|
const onInputChanged = useCallback(
|
||||||
|
(e: ChangeEvent<any>) => {
|
||||||
setState({...state, inputValue: e.target.value});
|
setState({...state, inputValue: e.target.value});
|
||||||
};
|
},
|
||||||
|
[state],
|
||||||
|
);
|
||||||
|
|
||||||
const onSubmit = (e: KeyboardEvent) => {
|
const onSubmit = useCallback(
|
||||||
|
(e: KeyboardEvent) => {
|
||||||
if (e.key === 'Enter') {
|
if (e.key === 'Enter') {
|
||||||
const rowNumber = parseInt(state.inputValue, 10);
|
const rowNumber = parseInt(state.inputValue, 10);
|
||||||
props.onChange(rowNumber - 1, props.count);
|
props.onChange(rowNumber - 1, props.count);
|
||||||
setState({...state, isOpen: false});
|
setState({...state, isOpen: false});
|
||||||
}
|
}
|
||||||
};
|
},
|
||||||
|
[props, state],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageInfoContainer grow={true}>
|
<PageInfoContainer grow={true}>
|
||||||
@@ -236,7 +243,135 @@ function PageInfo(props: PageInfoProps) {
|
|||||||
)}
|
)}
|
||||||
</PageInfoContainer>
|
</PageInfoContainer>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|
||||||
|
const DataTable = React.memo(
|
||||||
|
({
|
||||||
|
page,
|
||||||
|
highlightedRowsChanged,
|
||||||
|
sortOrderChanged,
|
||||||
|
currentSort,
|
||||||
|
currentStructure,
|
||||||
|
onRowEdited,
|
||||||
|
}: {
|
||||||
|
page: Page | null;
|
||||||
|
highlightedRowsChanged: (highlightedRows: TableHighlightedRows) => void;
|
||||||
|
sortOrderChanged: (sortOrder: TableRowSortOrder) => void;
|
||||||
|
currentSort: TableRowSortOrder | null;
|
||||||
|
currentStructure: Structure | null;
|
||||||
|
onRowEdited: (changes: {[key: string]: string | null}) => void;
|
||||||
|
}) =>
|
||||||
|
page ? (
|
||||||
|
<FlexRow grow={true}>
|
||||||
|
<ManagedTable
|
||||||
|
tableKey={`databases-${page.databaseId}-${page.table}`}
|
||||||
|
floating={false}
|
||||||
|
columnOrder={page.columns.map((name) => ({
|
||||||
|
key: name,
|
||||||
|
visible: true,
|
||||||
|
}))}
|
||||||
|
columns={page.columns.reduce(
|
||||||
|
(acc, val) =>
|
||||||
|
Object.assign({}, acc, {
|
||||||
|
[val]: {value: val, resizable: true, sortable: true},
|
||||||
|
}),
|
||||||
|
{},
|
||||||
|
)}
|
||||||
|
zebra={true}
|
||||||
|
rows={page.rows.map((row: Array<Value>, index: number) =>
|
||||||
|
transformRow(page.columns, row, index),
|
||||||
|
)}
|
||||||
|
horizontallyScrollable={true}
|
||||||
|
multiHighlight={true}
|
||||||
|
onRowHighlighted={highlightedRowsChanged}
|
||||||
|
onSort={sortOrderChanged}
|
||||||
|
initialSortOrder={currentSort ?? undefined}
|
||||||
|
/>
|
||||||
|
{page.highlightedRows.length === 1 && (
|
||||||
|
<DatabaseDetailSidebar
|
||||||
|
columnLabels={page.columns}
|
||||||
|
columnValues={page.rows[page.highlightedRows[0]]}
|
||||||
|
onSave={
|
||||||
|
currentStructure &&
|
||||||
|
isUpdatable(currentStructure.columns, currentStructure.rows)
|
||||||
|
? onRowEdited
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</FlexRow>
|
||||||
|
) : null,
|
||||||
|
);
|
||||||
|
|
||||||
|
const QueryTable = React.memo(
|
||||||
|
({
|
||||||
|
query,
|
||||||
|
highlightedRowsChanged,
|
||||||
|
}: {
|
||||||
|
query: QueryResult | null;
|
||||||
|
highlightedRowsChanged: (highlightedRows: TableHighlightedRows) => void;
|
||||||
|
}) => {
|
||||||
|
if (!query || query === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
query.table &&
|
||||||
|
typeof query.table !== 'undefined' &&
|
||||||
|
query.table !== null
|
||||||
|
) {
|
||||||
|
const table = query.table;
|
||||||
|
const columns = table.columns;
|
||||||
|
const rows = table.rows;
|
||||||
|
return (
|
||||||
|
<FlexRow grow={true} style={{paddingTop: 18}}>
|
||||||
|
<ManagedTable
|
||||||
|
floating={false}
|
||||||
|
multiline={true}
|
||||||
|
columnOrder={columns.map((name) => ({
|
||||||
|
key: name,
|
||||||
|
visible: true,
|
||||||
|
}))}
|
||||||
|
columns={columns.reduce(
|
||||||
|
(acc, val) =>
|
||||||
|
Object.assign({}, acc, {[val]: {value: val, resizable: true}}),
|
||||||
|
{},
|
||||||
|
)}
|
||||||
|
zebra={true}
|
||||||
|
rows={rows.map((row: Array<Value>, index: number) =>
|
||||||
|
transformRow(columns, row, index),
|
||||||
|
)}
|
||||||
|
horizontallyScrollable={true}
|
||||||
|
onRowHighlighted={highlightedRowsChanged}
|
||||||
|
/>
|
||||||
|
{table.highlightedRows.length === 1 && (
|
||||||
|
<DatabaseDetailSidebar
|
||||||
|
columnLabels={table.columns}
|
||||||
|
columnValues={table.rows[table.highlightedRows[0]]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</FlexRow>
|
||||||
|
);
|
||||||
|
} else if (query.id && query.id !== null) {
|
||||||
|
return (
|
||||||
|
<FlexRow grow={true} style={{paddingTop: 18}}>
|
||||||
|
<Text style={{paddingTop: 8, paddingLeft: 8}}>
|
||||||
|
Row id: {query.id}
|
||||||
|
</Text>
|
||||||
|
</FlexRow>
|
||||||
|
);
|
||||||
|
} else if (query.count && query.count !== null) {
|
||||||
|
return (
|
||||||
|
<FlexRow grow={true} style={{paddingTop: 18}}>
|
||||||
|
<Text style={{paddingTop: 8, paddingLeft: 8}}>
|
||||||
|
Rows affected: {query.count}
|
||||||
|
</Text>
|
||||||
|
</FlexRow>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
export function plugin(client: PluginClient<Events, Methods>) {
|
export function plugin(client: PluginClient<Events, Methods>) {
|
||||||
const pluginState = createState<DatabasesPluginState>({
|
const pluginState = createState<DatabasesPluginState>({
|
||||||
@@ -523,6 +658,26 @@ export function plugin(client: PluginClient<Events, Methods>) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const pageHighlightedRowsChanged = (event: TableHighlightedRows) => {
|
||||||
|
pluginState.update((draftState: DatabasesPluginState) => {
|
||||||
|
if (draftState.currentPage !== null) {
|
||||||
|
draftState.currentPage.highlightedRows = event.map(parseInt);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const queryHighlightedRowsChanged = (event: TableHighlightedRows) => {
|
||||||
|
pluginState.update((state) => {
|
||||||
|
if (state.queryResult) {
|
||||||
|
if (state.queryResult.table) {
|
||||||
|
state.queryResult.table.highlightedRows = event.map(parseInt);
|
||||||
|
}
|
||||||
|
state.queryResult.id = null;
|
||||||
|
state.queryResult.count = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
pluginState.subscribe(
|
pluginState.subscribe(
|
||||||
(newState: DatabasesPluginState, previousState: DatabasesPluginState) => {
|
(newState: DatabasesPluginState, previousState: DatabasesPluginState) => {
|
||||||
const databaseId = newState.selectedDatabase;
|
const databaseId = newState.selectedDatabase;
|
||||||
@@ -651,6 +806,8 @@ export function plugin(client: PluginClient<Events, Methods>) {
|
|||||||
updateFavorites,
|
updateFavorites,
|
||||||
sortByChanged,
|
sortByChanged,
|
||||||
updateQuery,
|
updateQuery,
|
||||||
|
pageHighlightedRowsChanged,
|
||||||
|
queryHighlightedRowsChanged,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -755,6 +912,27 @@ export function Component() {
|
|||||||
[instance],
|
[instance],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const pageHighlightedRowsChanged = useCallback(
|
||||||
|
(rows: TableHighlightedRows) => {
|
||||||
|
instance.pageHighlightedRowsChanged(rows);
|
||||||
|
},
|
||||||
|
[instance],
|
||||||
|
);
|
||||||
|
|
||||||
|
const queryHighlightedRowsChanged = useCallback(
|
||||||
|
(rows: TableHighlightedRows) => {
|
||||||
|
instance.queryHighlightedRowsChanged(rows);
|
||||||
|
},
|
||||||
|
[instance],
|
||||||
|
);
|
||||||
|
|
||||||
|
const sortOrderChanged = useCallback(
|
||||||
|
(sortOrder: TableRowSortOrder) => {
|
||||||
|
instance.sortByChanged({sortOrder});
|
||||||
|
},
|
||||||
|
[instance],
|
||||||
|
);
|
||||||
|
|
||||||
const onRowEdited = useCallback(
|
const onRowEdited = useCallback(
|
||||||
(change: {[key: string]: string | null}) => {
|
(change: {[key: string]: string | null}) => {
|
||||||
const {
|
const {
|
||||||
@@ -858,142 +1036,6 @@ export function Component() {
|
|||||||
[instance],
|
[instance],
|
||||||
);
|
);
|
||||||
|
|
||||||
const renderTable = (page: Page | null) => {
|
|
||||||
if (!page) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<FlexRow grow={true}>
|
|
||||||
<ManagedTable
|
|
||||||
tableKey={`databases-${page.databaseId}-${page.table}`}
|
|
||||||
floating={false}
|
|
||||||
columnOrder={page.columns.map((name) => ({
|
|
||||||
key: name,
|
|
||||||
visible: true,
|
|
||||||
}))}
|
|
||||||
columns={page.columns.reduce(
|
|
||||||
(acc, val) =>
|
|
||||||
Object.assign({}, acc, {
|
|
||||||
[val]: {value: val, resizable: true, sortable: true},
|
|
||||||
}),
|
|
||||||
{},
|
|
||||||
)}
|
|
||||||
zebra={true}
|
|
||||||
rows={page.rows.map((row: Array<Value>, index: number) =>
|
|
||||||
transformRow(page.columns, row, index),
|
|
||||||
)}
|
|
||||||
horizontallyScrollable={true}
|
|
||||||
multiHighlight={true}
|
|
||||||
onRowHighlighted={(highlightedRows) =>
|
|
||||||
instance.state.update((draftState: DatabasesPluginState) => {
|
|
||||||
if (draftState.currentPage !== null) {
|
|
||||||
draftState.currentPage.highlightedRows = highlightedRows.map(
|
|
||||||
parseInt,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
onSort={(sortOrder: TableRowSortOrder) => {
|
|
||||||
instance.sortByChanged({
|
|
||||||
sortOrder,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
initialSortOrder={state.currentSort ?? undefined}
|
|
||||||
/>
|
|
||||||
{page.highlightedRows.length === 1 && (
|
|
||||||
<DatabaseDetailSidebar
|
|
||||||
columnLabels={page.columns}
|
|
||||||
columnValues={page.rows[page.highlightedRows[0]]}
|
|
||||||
onSave={
|
|
||||||
state.currentStructure &&
|
|
||||||
isUpdatable(
|
|
||||||
state.currentStructure.columns,
|
|
||||||
state.currentStructure.rows,
|
|
||||||
)
|
|
||||||
? onRowEdited
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</FlexRow>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderQuery = (query: QueryResult | null) => {
|
|
||||||
if (!query || query === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
query.table &&
|
|
||||||
typeof query.table !== 'undefined' &&
|
|
||||||
query.table !== null
|
|
||||||
) {
|
|
||||||
const table = query.table;
|
|
||||||
const columns = table.columns;
|
|
||||||
const rows = table.rows;
|
|
||||||
return (
|
|
||||||
<FlexRow grow={true} style={{paddingTop: 18}}>
|
|
||||||
<ManagedTable
|
|
||||||
floating={false}
|
|
||||||
multiline={true}
|
|
||||||
columnOrder={columns.map((name) => ({
|
|
||||||
key: name,
|
|
||||||
visible: true,
|
|
||||||
}))}
|
|
||||||
columns={columns.reduce(
|
|
||||||
(acc, val) =>
|
|
||||||
Object.assign({}, acc, {[val]: {value: val, resizable: true}}),
|
|
||||||
{},
|
|
||||||
)}
|
|
||||||
zebra={true}
|
|
||||||
rows={rows.map((row: Array<Value>, index: number) =>
|
|
||||||
transformRow(columns, row, index),
|
|
||||||
)}
|
|
||||||
horizontallyScrollable={true}
|
|
||||||
onRowHighlighted={(highlightedRows) => {
|
|
||||||
instance.state.set({
|
|
||||||
...instance.state.get(),
|
|
||||||
queryResult: {
|
|
||||||
table: {
|
|
||||||
columns: columns,
|
|
||||||
rows: rows,
|
|
||||||
highlightedRows: highlightedRows.map(parseInt),
|
|
||||||
},
|
|
||||||
id: null,
|
|
||||||
count: null,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{table.highlightedRows.length === 1 && (
|
|
||||||
<DatabaseDetailSidebar
|
|
||||||
columnLabels={table.columns}
|
|
||||||
columnValues={table.rows[table.highlightedRows[0]]}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</FlexRow>
|
|
||||||
);
|
|
||||||
} else if (query.id && query.id !== null) {
|
|
||||||
return (
|
|
||||||
<FlexRow grow={true} style={{paddingTop: 18}}>
|
|
||||||
<Text style={{paddingTop: 8, paddingLeft: 8}}>
|
|
||||||
Row id: {query.id}
|
|
||||||
</Text>
|
|
||||||
</FlexRow>
|
|
||||||
);
|
|
||||||
} else if (query.count && query.count !== null) {
|
|
||||||
return (
|
|
||||||
<FlexRow grow={true} style={{paddingTop: 18}}>
|
|
||||||
<Text style={{paddingTop: 8, paddingLeft: 8}}>
|
|
||||||
Rows affected: {query.count}
|
|
||||||
</Text>
|
|
||||||
</FlexRow>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const tableOptions =
|
const tableOptions =
|
||||||
(state.selectedDatabase &&
|
(state.selectedDatabase &&
|
||||||
state.databases[state.selectedDatabase - 1] &&
|
state.databases[state.selectedDatabase - 1] &&
|
||||||
@@ -1152,20 +1194,34 @@ export function Component() {
|
|||||||
) : null}
|
) : null}
|
||||||
<FlexRow grow={true}>
|
<FlexRow grow={true}>
|
||||||
<FlexColumn grow={true}>
|
<FlexColumn grow={true}>
|
||||||
{state.viewMode === 'data' ? renderTable(state.currentPage) : null}
|
{state.viewMode === 'data' ? (
|
||||||
|
<DataTable
|
||||||
|
page={state.currentPage}
|
||||||
|
highlightedRowsChanged={pageHighlightedRowsChanged}
|
||||||
|
onRowEdited={onRowEdited}
|
||||||
|
sortOrderChanged={sortOrderChanged}
|
||||||
|
currentSort={state.currentSort}
|
||||||
|
currentStructure={state.currentStructure}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
{state.viewMode === 'structure' ? (
|
{state.viewMode === 'structure' ? (
|
||||||
<DatabaseStructure structure={state.currentStructure} />
|
<DatabaseStructure structure={state.currentStructure} />
|
||||||
) : null}
|
) : null}
|
||||||
{state.viewMode === 'SQL' ? renderQuery(state.queryResult) : null}
|
{state.viewMode === 'SQL' ? (
|
||||||
|
<QueryTable
|
||||||
|
query={state.queryResult}
|
||||||
|
highlightedRowsChanged={queryHighlightedRowsChanged}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
{state.viewMode === 'tableInfo' ? (
|
{state.viewMode === 'tableInfo' ? (
|
||||||
<TableInfoTextArea
|
<TableInfoTextArea
|
||||||
value={sqlFormatter.format(state.tableInfo)}
|
value={sqlFormatter.format(state.tableInfo)}
|
||||||
readOnly
|
readOnly
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
{state.viewMode === 'queryHistory'
|
{state.viewMode === 'queryHistory' ? (
|
||||||
? renderQueryHistory(state.queryHistory)
|
<QueryHistory history={state.queryHistory} />
|
||||||
: null}
|
) : null}
|
||||||
</FlexColumn>
|
</FlexColumn>
|
||||||
</FlexRow>
|
</FlexRow>
|
||||||
<Toolbar position="bottom" style={{paddingLeft: 8}}>
|
<Toolbar position="bottom" style={{paddingLeft: 8}}>
|
||||||
|
|||||||
Reference in New Issue
Block a user