[ResponseOps][Rules] Add loading state to rule params data views selector (#203654)

## Summary

Introduces a loading state in the data views select popover and renders
a loading indicator when DVs are not available yet. This makes sure that
even if the `savedObjectsClient.find` call of the data views service
takes a long time, we don't show an empty popover in the meantime.


https://github.com/user-attachments/assets/5bbe0c68-3ceb-4d7f-91fd-357db4caa5c1

## References

Fixes #198502 

## Release note

Fix race condition in alerting rules data view selector
This commit is contained in:
Umberto Pepato 2024-12-16 16:43:13 +01:00 committed by GitHub
parent 8f6e3ca6f9
commit 713d4bbcb2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -18,6 +18,7 @@ import {
EuiPopover,
EuiPopoverFooter,
EuiPopoverTitle,
EuiLoadingSpinner,
EuiText,
useEuiPaddingCSS,
useIsWithinBreakpoints,
@ -63,6 +64,7 @@ export const DataViewSelectPopover: React.FunctionComponent<DataViewSelectPopove
onSelectDataView,
onChangeMetaData,
}) => {
const [loadingDataViews, setLoadingDataViews] = useState(false);
const [dataViewItems, setDataViewsItems] = useState<DataViewListItemEnhanced[]>([]);
const [dataViewPopoverOpen, setDataViewPopoverOpen] = useState(false);
@ -71,7 +73,7 @@ export const DataViewSelectPopover: React.FunctionComponent<DataViewSelectPopove
const closeDataViewEditor = useRef<() => void | undefined>();
const allDataViewItems = useMemo(
() => [...dataViewItems, ...metadata.adHocDataViewList.map(toDataViewListItem)],
() => [...(dataViewItems ?? []), ...metadata.adHocDataViewList.map(toDataViewListItem)],
[dataViewItems, metadata.adHocDataViewList]
);
@ -87,10 +89,16 @@ export const DataViewSelectPopover: React.FunctionComponent<DataViewSelectPopove
);
const loadPersistedDataViews = useCallback(async () => {
const ids = await dataViews.getIds();
const dataViewsList = await Promise.all(ids.map((id) => dataViews.get(id)));
setDataViewsItems(dataViewsList.map(toDataViewListItem));
setLoadingDataViews(true);
try {
// Calling getIds with refresh = true to make sure we don't get stale data
const ids = await dataViews.getIds(true);
const dataViewsList = await Promise.all(ids.map((id) => dataViews.get(id)));
setDataViewsItems(dataViewsList.map(toDataViewListItem));
} catch (e) {
// Error fetching data views
}
setLoadingDataViews(false);
}, [dataViews]);
const onAddAdHocDataView = useCallback(
@ -153,8 +161,10 @@ export const DataViewSelectPopover: React.FunctionComponent<DataViewSelectPopove
[dataViews, onAddAdHocDataView, onChangeDataView]
);
if (!allDataViewItems) {
return null;
if (loadingDataViews) {
// The loading indicator is to make sure we don't render an
// empty popover when the DV cache is initially loading
return <EuiLoadingSpinner />;
}
return (