Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Maps] fix Kibana does not recognize a valid geo_shape index when attempting to create a Tracking Containment alert #96633

Merged
merged 10 commits into from
Apr 9, 2021
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ export type IndexPatternSelectProps = Required<
indexPatternId: string;
fieldTypes?: string[];
onNoIndexPatterns?: () => void;
maxIndexPatterns?: number;
};

export type IndexPatternSelectInternalProps = IndexPatternSelectProps & {
Expand All @@ -42,10 +41,6 @@ interface IndexPatternSelectState {
// Needed for React.lazy
// eslint-disable-next-line import/no-default-export
export default class IndexPatternSelect extends Component<IndexPatternSelectInternalProps> {
static defaultProps: {
maxIndexPatterns: 1000;
};

private isMounted: boolean = false;
state: IndexPatternSelectState;

Expand All @@ -67,7 +62,8 @@ export default class IndexPatternSelect extends Component<IndexPatternSelectInte

componentDidMount() {
this.isMounted = true;
this.fetchOptions();
// force index pattern cache refresh on first search after component mount so newly created index patterns show up
this.fetchOptions('', true);
this.fetchSelectedIndexPattern(this.props.indexPatternId);
}

Expand Down Expand Up @@ -106,50 +102,84 @@ export default class IndexPatternSelect extends Component<IndexPatternSelectInte
});
};

debouncedFetch = _.debounce(async (searchValue: string) => {
const { fieldTypes, onNoIndexPatterns, indexPatternService } = this.props;
const indexPatterns = await indexPatternService.find(
`${searchValue}*`,
this.props.maxIndexPatterns
);
debouncedFetch = _.debounce(
async (searchValue: string, forceIndexPatternCacheRefresh: boolean) => {
const isCurrentSearch = () => {
return this.isMounted && searchValue === this.state.searchValue;
};

const idsAndTitles = await this.props.indexPatternService.getIdsWithTitle(
forceIndexPatternCacheRefresh
);
if (!isCurrentSearch()) {
return;
}

const options = [];
for (let i = 0; i < idsAndTitles.length; i++) {
if (
searchValue.length &&
!idsAndTitles[i].title.toLowerCase().includes(searchValue.toLowerCase())
) {
// index pattern excluded due to title not matching search
continue;
}

if (this.props.fieldTypes) {
try {
const indexPattern = await this.props.indexPatternService.get(idsAndTitles[i].id);
if (!isCurrentSearch()) {
return;
}
const hasRequiredFieldTypes = indexPattern.fields.some((field) => {
return this.props.fieldTypes.includes(field.type);
});
if (!hasRequiredFieldTypes) {
continue;
}
} catch (err) {
// could not load index pattern, exclude it from list.
continue;
}
}

options.push({
label: idsAndTitles[i].title,
value: idsAndTitles[i].id,
});

// Loading each index pattern object requires a network call so just find small number of matching index patterns
// Users can use 'searchValue' to further refine the list and locate their index pattern.
if (options.length > 15) {
break;
}
}

// We need this check to handle the case where search results come back in a different
// order than they were sent out. Only load results for the most recent search.
if (searchValue !== this.state.searchValue || !this.isMounted) {
return;
}

const options = indexPatterns
.filter((indexPattern) => {
return fieldTypes
? indexPattern.fields.some((field) => {
return fieldTypes.includes(field.type);
})
: true;
})
.map((indexPattern) => {
return {
label: indexPattern.title,
value: indexPattern.id,
};
this.setState({
isLoading: false,
options,
});
this.setState({
isLoading: false,
options,
});

if (onNoIndexPatterns && searchValue === '' && options.length === 0) {
onNoIndexPatterns();
}
}, 300);
if (this.props.onNoIndexPatterns && searchValue === '' && options.length === 0) {
this.props.onNoIndexPatterns();
}
},
300
);

onSearchChange = (searchValue = '') => {
this.fetchOptions(searchValue, false);
};

fetchOptions = (searchValue = '') => {
fetchOptions = (searchValue: string, forceIndexPatternCacheRefresh: boolean) => {
this.setState(
{
isLoading: true,
searchValue,
},
this.debouncedFetch.bind(null, searchValue)
() => {
this.debouncedFetch(searchValue, forceIndexPatternCacheRefresh);
}
);
};

Expand All @@ -174,7 +204,7 @@ export default class IndexPatternSelect extends Component<IndexPatternSelectInte
placeholder={placeholder}
singleSelection={true}
isLoading={this.state.isLoading}
onSearchChange={this.fetchOptions}
onSearchChange={this.onSearchChange}
options={this.state.options}
selectedOptions={this.state.selectedIndexPattern ? [this.state.selectedIndexPattern] : []}
onChange={this.onChange}
Expand Down