Summary: Some lifecycle methods are deprecated now. Where they can be replaced easily I replaced them. Where they can't be updated easily I marked them as unsafe, as if a bigger refactoring is required for those components, we'd better convert them to function components instead. Didn't update the plugins as they are ideally updated by their owners. Didn't update styled components, there is a separate task for that. Reviewed By: jknoxville Differential Revision: D18780579 fbshipit-source-id: 132a3789875ab6a3caee582b0e5f7feb7dc4a4c1
160 lines
4.1 KiB
TypeScript
160 lines
4.1 KiB
TypeScript
/**
|
|
* 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 {Filter} from '../filter/types';
|
|
import ManagedTable, {ManagedTableProps} from '../table/ManagedTable';
|
|
import {TableBodyRow} from '../table/types';
|
|
import Searchable, {SearchableProps} from './Searchable';
|
|
import React, {PureComponent} from 'react';
|
|
import textContent from '../../../utils/textContent';
|
|
import deepEqual from 'deep-equal';
|
|
|
|
type Props = {
|
|
/** Reference to the table */
|
|
innerRef?: (ref: React.RefObject<any>) => void;
|
|
/** Filters that are added to the filterbar by default */
|
|
defaultFilters: Array<Filter>;
|
|
} & ManagedTableProps &
|
|
SearchableProps;
|
|
|
|
type State = {
|
|
filterRows: (row: TableBodyRow) => boolean;
|
|
};
|
|
|
|
const rowMatchesFilters = (filters: Array<Filter>, row: TableBodyRow) =>
|
|
filters
|
|
.map((filter: Filter) => {
|
|
if (filter.type === 'enum' && row.type != null) {
|
|
return filter.value.length === 0 || filter.value.indexOf(row.type) > -1;
|
|
} else if (filter.type === 'include') {
|
|
return (
|
|
textContent(row.columns[filter.key].value).toLowerCase() ===
|
|
filter.value.toLowerCase()
|
|
);
|
|
} else if (filter.type === 'exclude') {
|
|
return (
|
|
textContent(row.columns[filter.key].value).toLowerCase() !==
|
|
filter.value.toLowerCase()
|
|
);
|
|
} else {
|
|
return true;
|
|
}
|
|
})
|
|
.every(x => x === true);
|
|
|
|
function rowMatchesRegex(values: Array<string>, regex: string): boolean {
|
|
try {
|
|
const re = new RegExp(regex);
|
|
return values.some(x => re.test(x));
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function rowMatchesSearchTerm(
|
|
searchTerm: string,
|
|
isRegex: boolean,
|
|
isBodySearchEnabled: boolean,
|
|
row: TableBodyRow,
|
|
): boolean {
|
|
if (searchTerm == null || searchTerm.length === 0) {
|
|
return true;
|
|
}
|
|
const rowValues = Object.keys(row.columns).map(key =>
|
|
textContent(row.columns[key].value),
|
|
);
|
|
if (isBodySearchEnabled) {
|
|
if (row.requestBody) {
|
|
rowValues.push(row.requestBody);
|
|
}
|
|
if (row.responseBody) {
|
|
rowValues.push(row.responseBody);
|
|
}
|
|
}
|
|
if (isRegex) {
|
|
return rowMatchesRegex(rowValues, searchTerm);
|
|
}
|
|
return rowValues.some(x =>
|
|
x.toLowerCase().includes(searchTerm.toLowerCase()),
|
|
);
|
|
}
|
|
|
|
const filterRowsFactory = (
|
|
filters: Array<Filter>,
|
|
searchTerm: string,
|
|
regexSearch: boolean,
|
|
bodySearch: boolean,
|
|
) => (row: TableBodyRow): boolean =>
|
|
rowMatchesFilters(filters, row) &&
|
|
rowMatchesSearchTerm(searchTerm, regexSearch, bodySearch, row);
|
|
|
|
class SearchableManagedTable extends PureComponent<Props, State> {
|
|
static defaultProps = {
|
|
defaultFilters: [],
|
|
};
|
|
|
|
state = {
|
|
filterRows: filterRowsFactory(
|
|
this.props.filters,
|
|
this.props.searchTerm,
|
|
this.props.regexEnabled || false,
|
|
this.props.bodySearchEnabled || false,
|
|
),
|
|
};
|
|
|
|
componentDidMount() {
|
|
this.props.defaultFilters.map(this.props.addFilter);
|
|
}
|
|
|
|
UNSAFE_componentWillReceiveProps(nextProps: Props) {
|
|
if (
|
|
nextProps.searchTerm !== this.props.searchTerm ||
|
|
nextProps.regexEnabled != this.props.regexEnabled ||
|
|
nextProps.bodySearchEnabled != this.props.bodySearchEnabled ||
|
|
!deepEqual(this.props.filters, nextProps.filters)
|
|
) {
|
|
this.setState({
|
|
filterRows: filterRowsFactory(
|
|
nextProps.filters,
|
|
nextProps.searchTerm,
|
|
nextProps.regexEnabled || false,
|
|
nextProps.bodySearchEnabled || false,
|
|
),
|
|
});
|
|
}
|
|
}
|
|
|
|
render() {
|
|
const {
|
|
addFilter,
|
|
searchTerm: _searchTerm,
|
|
filters: _filters,
|
|
innerRef,
|
|
rows,
|
|
...props
|
|
} = this.props;
|
|
|
|
return (
|
|
<ManagedTable
|
|
{...props}
|
|
filter={this.state.filterRows}
|
|
rows={rows.filter(this.state.filterRows)}
|
|
onAddFilter={addFilter}
|
|
ref={innerRef}
|
|
/>
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Table with filter and searchbar, supports all properties a ManagedTable
|
|
* and Searchable supports.
|
|
*/
|
|
export default Searchable(SearchableManagedTable);
|