Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { UserPrivilegesProvider } from '../common/components/user_privileges/use
import { ReactQueryClientProvider } from '../common/containers/query_client/query_client_provider';
import { DiscoverInTimelineContextProvider } from '../common/components/discover_in_timeline/provider';
import { AssistantProvider } from '../assistant/provider';
import { DefaultDataViewProvider } from '../data_view_manager/containers/data_view_provider';

interface StartAppComponent {
children: React.ReactNode;
Expand All @@ -55,27 +56,29 @@ const StartAppComponent: FC<StartAppComponent> = ({ children, history, store, th
<ManageGlobalToaster>
<ReduxStoreProvider store={store}>
<EuiThemeProvider darkMode={darkMode}>
<MlCapabilitiesProvider>
<UserPrivilegesProvider kibanaCapabilities={capabilities}>
<ManageUserInfo>
<NavigationProvider core={services}>
<ReactQueryClientProvider>
<CellActionsProvider
getTriggerCompatibleActions={uiActions.getTriggerCompatibleActions}
>
<UpsellingProvider upsellingService={upselling}>
<DiscoverInTimelineContextProvider>
<AssistantProvider>
<PageRouter history={history}>{children}</PageRouter>
</AssistantProvider>
</DiscoverInTimelineContextProvider>
</UpsellingProvider>
</CellActionsProvider>
</ReactQueryClientProvider>
</NavigationProvider>
</ManageUserInfo>
</UserPrivilegesProvider>
</MlCapabilitiesProvider>
<DefaultDataViewProvider>
<MlCapabilitiesProvider>
<UserPrivilegesProvider kibanaCapabilities={capabilities}>
<ManageUserInfo>
<NavigationProvider core={services}>
<ReactQueryClientProvider>
<CellActionsProvider
getTriggerCompatibleActions={uiActions.getTriggerCompatibleActions}
>
<UpsellingProvider upsellingService={upselling}>
<DiscoverInTimelineContextProvider>
<AssistantProvider>
<PageRouter history={history}>{children}</PageRouter>
</AssistantProvider>
</DiscoverInTimelineContextProvider>
</UpsellingProvider>
</CellActionsProvider>
</ReactQueryClientProvider>
</NavigationProvider>
</ManageUserInfo>
</UserPrivilegesProvider>
</MlCapabilitiesProvider>
</DefaultDataViewProvider>
</EuiThemeProvider>
<ErrorToastDispatcher />
<GlobalToaster />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import type { DataView } from '@kbn/data-views-plugin/public';
import type { FC, PropsWithChildren } from 'react';
import React, { createContext, useContext, useEffect, useState } from 'react';
import { useKibana } from '../../common/lib/kibana';
import { createDefaultDataView } from '../utils/create_default_data_view';

const DefaultDataViewContext = createContext<DataView | undefined>(undefined);

export const useDefaultDataView = () => {
const defaultDataView = useContext(DefaultDataViewContext);

if (!defaultDataView) {
throw new Error('Could not fetch default data view');
}

return defaultDataView;
};

export const DefaultDataViewProvider: FC<PropsWithChildren> = ({ children }) => {
const { dataViews, uiSettings, spaces, application, http } = useKibana().services;

const [defaultDataView, setDefaultDataView] = useState<DataView>();

useEffect(() => {
(async () => {
Comment thread
lgestc marked this conversation as resolved.
const { defaultDataView: dv } = await createDefaultDataView({
dataViewService: dataViews,
uiSettings,
spaces,
application,
http,
});

const dataView = await dataViews?.get(dv.id);
Comment thread
lgestc marked this conversation as resolved.
Outdated

setDefaultDataView(dataView);
})();
}, [application, dataViews, http, spaces, uiSettings]);

return (
<DefaultDataViewContext.Provider value={defaultDataView}>
{defaultDataView ? children : null}
</DefaultDataViewContext.Provider>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,49 @@
*/

import { useEffect, useMemo, useState } from 'react';
import { type DataView } from '@kbn/data-views-plugin/public';
import type { DataView } from '@kbn/data-views-plugin/public';

import { useSelector } from 'react-redux';
import { useKibana } from '../../common/lib/kibana';
import { DataViewManagerScopeName } from '../constants';
import { useIsExperimentalFeatureEnabled } from '../../common/hooks/use_experimental_features';
import { sourcererAdapterSelector } from '../redux/selectors';
import type { SharedDataViewSelectionState } from '../redux/types';
import { useDefaultDataView } from '../containers/data_view_provider';

export interface UseDataViewValue {
dataView: DataView;
status: SharedDataViewSelectionState['status'];
}

/*
* This hook should be used whenever we need the actual DataView and not just the spec for the
* selected data view.
*/
export const useDataView = (
dataViewManagerScope: DataViewManagerScopeName = DataViewManagerScopeName.default
): { dataView: DataView | undefined; status: SharedDataViewSelectionState['status'] } => {
): UseDataViewValue => {
const {
services: { dataViews },
notifications,
} = useKibana();
const defaultDataView = useDefaultDataView();

const { dataViewId, status: internalStatus } = useSelector(
sourcererAdapterSelector(dataViewManagerScope)
);
const newDataViewPickerEnabled = useIsExperimentalFeatureEnabled('newDataViewPickerEnabled');
const [retrievedDataView, setRetrievedDataView] = useState<DataView | undefined>();

const [retrievedDataView, setRetrievedDataView] = useState<DataView>(defaultDataView);
Comment thread
lgestc marked this conversation as resolved.
Outdated

useEffect(() => {
(async () => {
if (!newDataViewPickerEnabled) {
return;
}

if (!dataViewId || internalStatus !== 'ready') {
return setRetrievedDataView(undefined);
return;
}

try {
Expand All @@ -46,21 +58,16 @@ export const useDataView = (
const currDv = await dataViews?.get(dataViewId);
setRetrievedDataView(currDv);
} catch (error) {
setRetrievedDataView(undefined);
// TODO: (remove conditional call when feature flag is on (mocks are broken for some tests))
notifications?.toasts?.danger({
title: 'Error retrieving data view',
body: `Error: ${error?.message ?? 'unknown'}`,
});
}
})();
}, [dataViews, dataViewId, internalStatus, notifications]);
}, [dataViews, dataViewId, internalStatus, notifications, newDataViewPickerEnabled]);

return useMemo(() => {
if (!newDataViewPickerEnabled) {
return { dataView: undefined, status: internalStatus };
}

return { dataView: retrievedDataView, status: retrievedDataView ? internalStatus : 'loading' };
}, [newDataViewPickerEnabled, retrievedDataView, internalStatus]);
}, [retrievedDataView, internalStatus]);
};
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { type SelectDataViewAsyncPayload } from '../redux/actions';
import { DataViewManagerScopeName } from '../constants';
import { useIsExperimentalFeatureEnabled } from '../../common/hooks/use_experimental_features';
import { useUserInfo } from '../../detections/components/user_info';
import { useDefaultDataView } from '../containers/data_view_provider';

type OriginalListener = Parameters<typeof originalAddListener>[0];

Expand Down Expand Up @@ -73,6 +74,8 @@ export const useInitDataViewManager = () => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [signalIndexName]);

const defaultDataView = useDefaultDataView();
Comment thread
lgestc marked this conversation as resolved.
Outdated

useEffect(() => {
// TODO: (new data view picker) remove this in cleanup phase https://github.com/elastic/security-team/issues/12665
if (!newDataViewPickerEnabled) {
Expand All @@ -82,10 +85,7 @@ export const useInitDataViewManager = () => {
// NOTE: init listener contains logic that preloads default security solution data view
const dataViewsLoadingListener = createInitListener({
dataViews: services.dataViews,
http: services.http,
uiSettings: services.uiSettings,
application: services.application,
spaces: services.spaces,
defaultDataView,
});

dispatch(addListener(dataViewsLoadingListener));
Expand Down Expand Up @@ -115,15 +115,7 @@ export const useInitDataViewManager = () => {
dispatch(removeListener(dataViewSelectedListener));
});
};
}, [
dispatch,
newDataViewPickerEnabled,
services.application,
services.dataViews,
services.http,
services.spaces,
services.uiSettings,
]);
}, [defaultDataView, dispatch, newDataViewPickerEnabled, services.dataViews]);

return useCallback(
(initialSelection: SelectDataViewAsyncPayload[]) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,11 @@
*/

import type { AnyAction, Dispatch, ListenerEffectAPI } from '@reduxjs/toolkit';
import type { DataViewsServicePublic } from '@kbn/data-views-plugin/public';
import type { CoreStart } from '@kbn/core/public';
import type { SpacesPluginStart } from '@kbn/spaces-plugin/public';
import type { DataViewsServicePublic, DataView } from '@kbn/data-views-plugin/public';
import type { RootState } from '../reducer';
import { sharedDataViewManagerSlice } from '../slices';
import { DataViewManagerScopeName } from '../../constants';
import { selectDataViewAsync } from '../actions';
import { createDefaultDataView } from '../../utils/create_default_data_view';

/**
* Creates a Redux listener for initializing the Data View Manager state.
Expand All @@ -33,11 +30,8 @@ import { createDefaultDataView } from '../../utils/create_default_data_view';
* @returns An object with the actionCreator and effect for Redux listener middleware.
*/
export const createInitListener = (dependencies: {
http: CoreStart['http'];
application: CoreStart['application'];
uiSettings: CoreStart['uiSettings'];
dataViews: DataViewsServicePublic;
spaces: SpacesPluginStart;
defaultDataView: DataView;
}) => {
return {
actionCreator: sharedDataViewManagerSlice.actions.init,
Expand All @@ -46,17 +40,6 @@ export const createInitListener = (dependencies: {
listenerApi: ListenerEffectAPI<RootState, Dispatch<AnyAction>>
) => {
try {
// Initialize default security data view first
// Note: this is subject to change, as we might want to add specific data view just for alerts

const { defaultDataView } = await createDefaultDataView({
dataViewService: dependencies.dataViews,
uiSettings: dependencies.uiSettings,
spaces: dependencies.spaces,
application: dependencies.application,
http: dependencies.http,
});

// NOTE: This is later used in the data view manager drop-down selector
const dataViews = await dependencies.dataViews.getAllDataViewLazy();
const dataViewSpecs = await Promise.all(dataViews.map((dataView) => dataView.toSpec()));
Expand All @@ -66,7 +49,9 @@ export const createInitListener = (dependencies: {
// NOTE: save default dataview id for the given space in the store.
// this is used to identify the default selection in pickers across Kibana Space
listenerApi.dispatch(
sharedDataViewManagerSlice.actions.setDefaultDataViewId(defaultDataView.id)
sharedDataViewManagerSlice.actions.setDefaultDataViewId(
dependencies.defaultDataView.id as string
)
);

// Preload the default data view for all the scopes
Expand All @@ -84,7 +69,7 @@ export const createInitListener = (dependencies: {
.forEach((scope) => {
listenerApi.dispatch(
selectDataViewAsync({
id: defaultDataView.id,
id: dependencies.defaultDataView.id,
scope,
})
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ export const TimelinesPage = React.memo(() => {
const { indicesExist: oldIndicesExist } = useSourcererDataView();

const { dataView } = useDataView(DataViewManagerScopeName.default);
// NOTE: there should be a Suspense / some kind of loader here as this value is not settled immediately
const experimentalIndicesExist = !!dataView?.matchedIndices?.length;
const experimentalIndicesExist = !!dataView.matchedIndices?.length;
Comment thread
lgestc marked this conversation as resolved.

const indicesExist = newDataViewPickerEnabled ? experimentalIndicesExist : oldIndicesExist;

Expand Down