Allow Long Text to Be Shown in The Sidebar

Summary:
This allows long text to be seen on the sidebar in database plugin. Also, remove weird padding in the sidebar and separate sidebar component to a new file

Refactoring is in the next diff

Reviewed By: mweststrate

Differential Revision: D21550672

fbshipit-source-id: 3e80be16783719e18392fe3d8f8068caf9283f8f
This commit is contained in:
Chaiwat Ekkaewnumchai
2020-05-19 09:11:12 -07:00
committed by Facebook GitHub Bot
parent f2b46e558f
commit 11b233b516
3 changed files with 144 additions and 115 deletions

View File

@@ -29,6 +29,14 @@ export type Value =
type: 'null';
};
const WrappingText = styled(Text)({
wordWrap: 'break-word',
width: '100%',
lineHeight: '125%',
padding: '3px 0',
});
WrappingText.displayName = 'TypeBasedValueRenderer:WrappingText';
const NonWrappingText = styled(Text)({
overflow: 'hidden',
textOverflow: 'ellipsis',
@@ -51,7 +59,8 @@ const BooleanValue = styled(NonWrappingText)<{active?: boolean}>((props) => ({
}));
BooleanValue.displayName = 'TypeBasedValueRenderer:BooleanValue';
export function renderValue(val: Value) {
export function renderValue(val: Value, wordWrap?: boolean) {
const TextComponent = wordWrap ? WrappingText : NonWrappingText;
switch (val.type) {
case 'boolean':
return (
@@ -61,15 +70,15 @@ export function renderValue(val: Value) {
);
case 'blob':
case 'string':
return <NonWrappingText>{val.value}</NonWrappingText>;
return <TextComponent>{val.value}</TextComponent>;
case 'integer':
case 'float':
case 'double':
case 'number':
return <NonWrappingText>{val.value}</NonWrappingText>;
return <TextComponent>{val.value}</TextComponent>;
case 'null':
return <NonWrappingText>NULL</NonWrappingText>;
return <TextComponent>NULL</TextComponent>;
default:
return <NonWrappingText />;
return <TextComponent />;
}
}

View File

@@ -0,0 +1,125 @@
/**
* 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 React from 'react';
import {QueriedTable} from '.';
import {
Text,
DetailSidebar,
Panel,
ManagedTable,
TableRows,
TableBodyRow,
ManagedDataInspector,
} from 'flipper';
function sidebarRows(id: number, table: QueriedTable): TableRows {
const columns = table.columns;
const row = table.rows[id];
if (columns.length === 1) {
const sidebarArray = [];
// TODO(T60896483): Narrow the scope of this try/catch block.
try {
const parsed = JSON.parse(row.columns[columns[0]].value.props.children);
for (const key in parsed) {
sidebarArray.push(
buildSidebarRow(key, {
props: {
children: parsed[key],
},
}),
);
}
} catch (e) {
sidebarArray.push(
buildSidebarRow(columns[0], row.columns[columns[0]].value),
);
}
return sidebarArray;
} else {
return columns.map((column, i) =>
buildSidebarRow(columns[i], row.columns[columns[i]].value),
);
}
}
function buildSidebarRow(key: string, val: any): TableBodyRow {
let output: any = '';
// TODO(T60896483): Narrow the scope of this try/catch block.
try {
const parsed = JSON.parse(val.props.children);
for (const key in parsed) {
try {
parsed[key] = JSON.parse(parsed[key]);
} catch (err) {}
}
output = (
<ManagedDataInspector data={parsed} expandRoot={false} collapsed />
);
} catch (error) {
output = val;
}
return {
columns: {
col: {value: <Text>{key}</Text>},
val: {
value: output,
},
},
key: key,
};
}
export default React.memo(function DatabaseDetailSidebar(props: {
table: QueriedTable;
}) {
const {table} = props;
if (
table.highlightedRows === null ||
typeof table.highlightedRows === 'undefined' ||
table.highlightedRows.length !== 1
) {
return null;
}
const id = table.highlightedRows[0];
const cols = {
col: {
value: 'Column',
resizable: true,
},
val: {
value: 'Value',
resizable: true,
},
};
const colSizes = {
col: '35%',
val: 'flex',
};
return (
<DetailSidebar>
<Panel
heading="Row details"
floating={false}
collapsable={true}
padded={false}>
<ManagedTable
highlightableRows={false}
columnSizes={colSizes}
multiline={true}
columns={cols}
autoHeight={true}
floating={false}
zebra={false}
rows={sidebarRows(id, table)}
/>
</Panel>
</DetailSidebar>
);
});

View File

@@ -23,9 +23,6 @@ import {
getStringFromErrorLike,
Spacer,
Textarea,
DetailSidebar,
Panel,
ManagedDataInspector,
TableBodyColumn,
TableRows,
Props as FlipperPluginProps,
@@ -37,6 +34,7 @@ import {DatabaseClient} from './ClientProtocol';
import {renderValue} from 'flipper';
import {Value} from 'flipper';
import ButtonNavigation from './ButtonNavigation';
import DatabaseDetailSidebar from './DatabaseDetailSidebar';
import sqlFormatter from 'sql-formatter';
import dateFormat from 'dateformat';
@@ -110,7 +108,7 @@ type QueryResult = {
count: number | null;
};
type QueriedTable = {
export type QueriedTable = {
columns: Array<string>;
rows: Array<TableBodyRow>;
highlightedRows: Array<number>;
@@ -252,7 +250,7 @@ function transformRow(
): TableBodyRow {
const transformedColumns: {[key: string]: TableBodyColumn} = {};
for (let i = 0; i < columns.length; i++) {
transformedColumns[columns[i]] = {value: renderValue(row[i])};
transformedColumns[columns[i]] = {value: renderValue(row[i], true)};
}
return {key: String(index), columns: transformedColumns};
}
@@ -1064,109 +1062,6 @@ export default class DatabasesPlugin extends FlipperPlugin<
);
}
renderSidebar = (table: QueriedTable) => {
if (
table.highlightedRows === null ||
typeof table.highlightedRows === 'undefined' ||
table.highlightedRows.length !== 1
) {
return null;
}
const id = table.highlightedRows[0];
const cols = {
col: {
value: 'Column',
resizable: true,
},
val: {
value: 'Value',
resizable: true,
},
};
const colSizes = {
col: '35%',
val: 'flex',
};
return (
<DetailSidebar width={500}>
<Panel
padded={true}
heading="Row details"
floating={false}
collapsable={true}
grow={true}>
<ManagedTable
highlightableRows={false}
columnSizes={colSizes}
multiline={true}
columns={cols}
autoHeight={true}
floating={false}
zebra={true}
rows={this.sidebarRows(id, table)}
/>
</Panel>
</DetailSidebar>
);
};
sidebarRows(id: number, table: QueriedTable): TableRows {
const columns = table.columns;
const row = table.rows[id];
if (columns.length === 1) {
const sidebarArray = [];
// TODO(T60896483): Narrow the scope of this try/catch block.
try {
const parsed = JSON.parse(row.columns[columns[0]].value.props.children);
for (const key in parsed) {
sidebarArray.push(
this.buildSidebarRow(key, {
props: {
children: parsed[key],
},
}),
);
}
} catch (e) {
sidebarArray.push(
this.buildSidebarRow(columns[0], row.columns[columns[0]].value),
);
}
return sidebarArray;
} else {
return columns.map((column, i) =>
this.buildSidebarRow(columns[i], row.columns[columns[i]].value),
);
}
}
buildSidebarRow(key: string, val: any): TableBodyRow {
let output: any = '';
// TODO(T60896483): Narrow the scope of this try/catch block.
try {
const parsed = JSON.parse(val.props.children);
for (const key in parsed) {
try {
parsed[key] = JSON.parse(parsed[key]);
} catch (err) {}
}
output = (
<ManagedDataInspector data={parsed} expandRoot={false} collapsed />
);
} catch (error) {
output = val;
}
return {
columns: {
col: {value: <Text>{key}</Text>},
val: {
value: output,
},
},
key: key,
};
}
renderTable(page: Page | null) {
if (!page) {
return null;
@@ -1210,7 +1105,7 @@ export default class DatabasesPlugin extends FlipperPlugin<
}}
initialSortOrder={this.state.currentSort ?? undefined}
/>
{this.renderSidebar(page)}
<DatabaseDetailSidebar table={page} />
</FlexRow>
);
}
@@ -1258,7 +1153,7 @@ export default class DatabasesPlugin extends FlipperPlugin<
});
}}
/>
{this.renderSidebar(table)}
<DatabaseDetailSidebar table={table} />
</FlexRow>
);
} else if (query.id && query.id !== null) {