Add filter and highlight to JSON

Summary:
Large GraphQL responses feel pretty unwieldy, added a search option.

Added filter functionality to ManagedDataInspector, and use it in GraphQL

changelog: It is now possible to search inside GraphQL responses

making it slightly more efficient, and scrolling to the matches will be done in a next diff

Reviewed By: jknoxville

Differential Revision: D21347880

fbshipit-source-id: 85c95be0964515e737de2ab41bbdd8cc6a87544e
This commit is contained in:
Michel Weststrate
2020-05-04 04:14:29 -07:00
committed by Facebook GitHub Bot
parent fe1c52f2f7
commit fd84820ee5
6 changed files with 210 additions and 15 deletions

View File

@@ -48,12 +48,19 @@ type ManagedDataInspectorProps = {
* Object of all properties that will have tooltips
*/
tooltips?: Object;
/**
* Filter nodes by some search text
*/
filter?: string;
};
type ManagedDataInspectorState = {
expanded: DataInspectorExpanded;
filter: string;
};
const MAX_RESULTS = 50;
/**
* Wrapper around `DataInspector` that handles expanded state.
*
@@ -68,6 +75,69 @@ export default class ManagedDataInspector extends PureComponent<
super(props, context);
this.state = {
expanded: {},
filter: '',
};
}
static getDerivedStateFromProps(
nextProps: ManagedDataInspectorProps,
currentState: ManagedDataInspectorState,
) {
if (nextProps.filter === currentState.filter) {
return null;
}
if (!nextProps.filter) {
return {
filter: '',
// reset expanded when removing filter
expanded: currentState.filter ? {} : currentState.expanded,
};
}
const filter = nextProps.filter!.toLowerCase();
const paths: (number | string)[][] = [];
function walk(value: any, path: (number | string)[]) {
if (paths.length > MAX_RESULTS) {
return;
}
if (!value) {
return;
}
if (typeof value !== 'object') {
if (('' + value).toLowerCase().includes(filter!)) {
paths.push(path.slice());
}
} else if (Array.isArray(value)) {
value.forEach((value, index) => {
path.push(index);
walk(value, path);
path.pop();
});
} else {
// a plain object
Object.keys(value).forEach((key) => {
path.push(key);
walk(key, path); // is the key interesting?
walk(value[key], path);
path.pop();
});
}
}
if (filter.length >= 2) {
walk(nextProps.data, []);
}
const expanded: Record<string, boolean> = {};
paths.forEach((path) => {
for (let i = 1; i < path.length; i++)
expanded[path.slice(0, i).join('.')] = true;
});
return {
expanded,
filter,
};
}
@@ -86,8 +156,9 @@ export default class ManagedDataInspector extends PureComponent<
onExpanded={this.onExpanded}
onDelete={this.props.onDelete}
expandRoot={this.props.expandRoot}
collapsed={this.props.collapsed}
collapsed={this.props.filter ? true : this.props.collapsed}
tooltips={this.props.tooltips}
highlight={this.props.filter}
/>
);
}