123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- import {Component} from 'react';
- // eslint-disable-next-line no-restricted-imports
- import {withRouter, WithRouterProps} from 'react-router';
- import {loadSearchMap} from 'sentry/actionCreators/formSearch';
- import FormSearchStore, {FormSearchField} from 'sentry/stores/formSearchStore';
- import {createFuzzySearch, Fuse} from 'sentry/utils/fuzzySearch';
- import replaceRouterParams from 'sentry/utils/replaceRouterParams';
- import {ChildProps, Result, ResultItem} from './types';
- import {strGetFn} from './utils';
- type Props = WithRouterProps<{orgId: string}> & {
- children: (props: ChildProps) => React.ReactElement;
- /**
- * search term
- */
- query: string;
- /**
- * List of form fields to search
- */
- searchMap?: null | FormSearchField[];
- /**
- * fusejs options.
- */
- searchOptions?: Fuse.IFuseOptions<FormSearchField>;
- };
- type State = {
- fuzzy: null | Fuse<FormSearchField>;
- };
- class FormSource extends Component<Props, State> {
- static defaultProps = {
- searchOptions: {},
- };
- state: State = {
- fuzzy: null,
- };
- componentDidMount() {
- this.createSearch(this.props.searchMap);
- }
- componentDidUpdate(prevProps: Props) {
- if (this.props.searchMap !== prevProps.searchMap) {
- this.createSearch(this.props.searchMap);
- }
- }
- async createSearch(searchMap: Props['searchMap']) {
- this.setState({
- fuzzy: await createFuzzySearch(searchMap || [], {
- ...this.props.searchOptions,
- keys: ['title', 'description'],
- getFn: strGetFn,
- }),
- });
- }
- render() {
- const {searchMap, query, params, children} = this.props;
- const {fuzzy} = this.state;
- const results =
- fuzzy?.search(query).map<Result>(value => {
- const {item, ...rest} = value;
- return {
- item: {
- ...item,
- sourceType: 'field',
- resultType: 'field',
- to: `${replaceRouterParams(item.route, params)}#${encodeURIComponent(
- item.field.name
- )}`,
- } as ResultItem,
- ...rest,
- };
- }) ?? [];
- return children({
- isLoading: searchMap === null,
- results,
- });
- }
- }
- type ContainerProps = Omit<Props, 'searchMap'>;
- type ContainerState = Pick<Props, 'searchMap'>;
- class FormSourceContainer extends Component<ContainerProps, ContainerState> {
- state = {
- searchMap: FormSearchStore.get(),
- };
- componentDidMount() {
- // Loads form fields
- loadSearchMap();
- }
- componentWillUnmount() {
- this.unsubscribe();
- }
- unsubscribe = FormSearchStore.listen(
- (searchMap: ContainerState['searchMap']) => this.setState({searchMap}),
- undefined
- );
- render() {
- return <FormSource searchMap={this.state.searchMap} {...this.props} />;
- }
- }
- export default withRouter(FormSourceContainer);
|