12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 |
- import {Component} from 'react';
- import flatten from 'lodash/flatten';
- import type {Fuse} from 'sentry/utils/fuzzySearch';
- import {Result} from './types';
- type ChildProps = {
- hasAnyResults: boolean;
- isLoading: boolean;
- results: Result[];
- };
- type Props = {
- children: (props: ChildProps) => React.ReactElement;
- params: {orgId: string};
- query: string;
- sources: React.ComponentType[];
- searchOptions?: Fuse.IFuseOptions<any>;
- };
- type SourceResult = {
- isLoading: boolean;
- results: Result[];
- };
- class SearchSources extends Component<Props> {
- // `allSources` will be an array of all result objects from each source
- renderResults(allSources: SourceResult[]) {
- const {children} = this.props;
- // loading means if any result has `isLoading` OR any result is null
- const isLoading = !!allSources.find(arg => arg.isLoading || arg.results === null);
- const foundResults = isLoading
- ? []
- : flatten(allSources.map(({results}) => results || [])).sort(
- (a, b) => (a.score ?? 0) - (b.score ?? 0)
- );
- const hasAnyResults = !!foundResults.length;
- return children({
- isLoading,
- results: foundResults,
- hasAnyResults,
- });
- }
- renderSources(sources: Props['sources'], results: SourceResult[], idx: number) {
- if (idx >= sources.length) {
- return this.renderResults(results);
- }
- const Source = sources[idx];
- return (
- <Source {...this.props}>
- {(args: SourceResult) => {
- // Mutate the array instead of pushing because we don't know how often
- // this child function will be called and pushing will cause duplicate
- // results to be pushed for all calls down the chain.
- results[idx] = args;
- return this.renderSources(sources, results, idx + 1);
- }}
- </Source>
- );
- }
- render() {
- return this.renderSources(
- this.props.sources,
- new Array(this.props.sources.length),
- 0
- );
- }
- }
- export default SearchSources;
|