Skip to content

Commit

Permalink
[ResponseOps][Rules] Add loading state to rule params data views sele…
Browse files Browse the repository at this point in the history
…ctor (elastic#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 elastic#198502 

## Release note

Fix race condition in alerting rules data view selector
  • Loading branch information
umbopepato authored and JoseLuisGJ committed Dec 19, 2024
1 parent 037d4c8 commit 520465a
Showing 1 changed file with 17 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
EuiPopover,
EuiPopoverFooter,
EuiPopoverTitle,
EuiLoadingSpinner,
EuiText,
useEuiPaddingCSS,
useIsWithinBreakpoints,
Expand Down Expand Up @@ -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);

Expand All @@ -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]
);

Expand All @@ -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(
Expand Down Expand Up @@ -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 (
Expand Down

0 comments on commit 520465a

Please sign in to comment.