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:
committed by
Facebook GitHub Bot
parent
fe1c52f2f7
commit
fd84820ee5
@@ -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}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user