diff --git a/src/plugins/dashboard/public/dashboard_app/top_nav/share/show_share_modal.tsx b/src/plugins/dashboard/public/dashboard_app/top_nav/share/show_share_modal.tsx
index cc25ac920899..eee127d51fdd 100644
--- a/src/plugins/dashboard/public/dashboard_app/top_nav/share/show_share_modal.tsx
+++ b/src/plugins/dashboard/public/dashboard_app/top_nav/share/show_share_modal.tsx
@@ -159,7 +159,7 @@ export function ShowShareModal({
if (_g?.filters && _g.filters.length === 0) {
_g = omit(_g, 'filters');
}
- const baseUrl = setStateToKbnUrl('_g', _g);
+ const baseUrl = setStateToKbnUrl('_g', _g, undefined, window.location.href);
const shareableUrl = setStateToKbnUrl(
'_a',
diff --git a/src/plugins/dashboard/public/dashboard_app/url/search_sessions_integration.ts b/src/plugins/dashboard/public/dashboard_app/url/search_sessions_integration.ts
index 752ee39724de..79e6742a793c 100644
--- a/src/plugins/dashboard/public/dashboard_app/url/search_sessions_integration.ts
+++ b/src/plugins/dashboard/public/dashboard_app/url/search_sessions_integration.ts
@@ -11,10 +11,10 @@ import { History } from 'history';
import {
getQueryParams,
- replaceUrlHashQuery,
IKbnUrlStateStorage,
createQueryParamObservable,
} from '@kbn/kibana-utils-plugin/public';
+import { replaceUrlHashQuery } from '@kbn/kibana-utils-plugin/common';
import type { Query } from '@kbn/es-query';
import { SearchSessionInfoProvider } from '@kbn/data-plugin/public';
diff --git a/src/plugins/dashboard/public/dashboard_app/url/sync_dashboard_url_state.ts b/src/plugins/dashboard/public/dashboard_app/url/sync_dashboard_url_state.ts
index b0d37de482de..6d90316098fb 100644
--- a/src/plugins/dashboard/public/dashboard_app/url/sync_dashboard_url_state.ts
+++ b/src/plugins/dashboard/public/dashboard_app/url/sync_dashboard_url_state.ts
@@ -10,7 +10,8 @@ import _ from 'lodash';
import { debounceTime } from 'rxjs/operators';
import semverSatisfies from 'semver/functions/satisfies';
-import { IKbnUrlStateStorage, replaceUrlHashQuery } from '@kbn/kibana-utils-plugin/public';
+import { IKbnUrlStateStorage } from '@kbn/kibana-utils-plugin/public';
+import { replaceUrlHashQuery } from '@kbn/kibana-utils-plugin/common';
import {
DashboardPanelMap,
diff --git a/src/plugins/dashboard/public/plugin.tsx b/src/plugins/dashboard/public/plugin.tsx
index 84689c8feecc..fa457c425440 100644
--- a/src/plugins/dashboard/public/plugin.tsx
+++ b/src/plugins/dashboard/public/plugin.tsx
@@ -33,8 +33,8 @@ import type {
import { APP_WRAPPER_CLASS } from '@kbn/core/public';
import type { SpacesPluginStart } from '@kbn/spaces-plugin/public';
import type { HomePublicPluginSetup } from '@kbn/home-plugin/public';
+import { replaceUrlHashQuery } from '@kbn/kibana-utils-plugin/common';
import { createKbnUrlTracker } from '@kbn/kibana-utils-plugin/public';
-import { replaceUrlHashQuery } from '@kbn/kibana-utils-plugin/public';
import type { SavedObjectsStart } from '@kbn/saved-objects-plugin/public';
import type { VisualizationsStart } from '@kbn/visualizations-plugin/public';
import type { DataViewEditorStart } from '@kbn/data-view-editor-plugin/public';
diff --git a/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx b/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx
index 208871f77022..811222ef71e8 100644
--- a/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx
+++ b/src/plugins/data_view_management/public/components/edit_index_pattern/edit_index_pattern.tsx
@@ -210,7 +210,9 @@ export const EditIndexPattern = withRouter(
{indexPatternHeading}
- {indexPattern.title}
+
+ {indexPattern.title}
+
)}
@@ -218,7 +220,9 @@ export const EditIndexPattern = withRouter(
{timeFilterHeading}
- {indexPattern.timeFieldName}
+
+ {indexPattern.timeFieldName}
+
)}
diff --git a/src/plugins/data_views/public/mocks.ts b/src/plugins/data_views/public/mocks.ts
index 61db42e18a9b..2178cf450300 100644
--- a/src/plugins/data_views/public/mocks.ts
+++ b/src/plugins/data_views/public/mocks.ts
@@ -37,6 +37,7 @@ const createStartContract = (): Start => {
getCanSaveSync: jest.fn(),
getIdsWithTitle: jest.fn(),
getFieldsForIndexPattern: jest.fn(),
+ create: jest.fn().mockReturnValue(Promise.resolve({})),
} as unknown as jest.Mocked;
};
diff --git a/src/plugins/discover/common/constants.ts b/src/plugins/discover/common/constants.ts
index 76cf8b8f8f3c..8e61baa8ba6f 100644
--- a/src/plugins/discover/common/constants.ts
+++ b/src/plugins/discover/common/constants.ts
@@ -8,3 +8,7 @@
export const DEFAULT_ROWS_PER_PAGE = 100;
export const ROWS_PER_PAGE_OPTIONS = [10, 25, 50, DEFAULT_ROWS_PER_PAGE, 250, 500];
+export enum VIEW_MODE {
+ DOCUMENT_LEVEL = 'documents',
+ AGGREGATED_LEVEL = 'aggregated',
+}
diff --git a/src/plugins/discover/common/index.ts b/src/plugins/discover/common/index.ts
index 1e204683c0cf..97180412d67f 100644
--- a/src/plugins/discover/common/index.ts
+++ b/src/plugins/discover/common/index.ts
@@ -30,3 +30,6 @@ export const SEARCH_EMBEDDABLE_TYPE = 'search';
export const HIDE_ANNOUNCEMENTS = 'hideAnnouncements';
export const SHOW_LEGACY_FIELD_TOP_VALUES = 'discover:showLegacyFieldTopValues';
export const ENABLE_SQL = 'discover:enableSql';
+
+export { DISCOVER_APP_LOCATOR, DiscoverAppLocatorDefinition } from './locator';
+export type { DiscoverAppLocator, DiscoverAppLocatorParams } from './locator';
diff --git a/src/plugins/discover/public/locator.test.ts b/src/plugins/discover/common/locator.test.ts
similarity index 97%
rename from src/plugins/discover/public/locator.test.ts
rename to src/plugins/discover/common/locator.test.ts
index 221c7a4958fa..9152b99072de 100644
--- a/src/plugins/discover/public/locator.test.ts
+++ b/src/plugins/discover/common/locator.test.ts
@@ -6,7 +6,11 @@
* Side Public License, v 1.
*/
-import { hashedItemStore, getStatesFromKbnUrl } from '@kbn/kibana-utils-plugin/public';
+import {
+ hashedItemStore,
+ getStatesFromKbnUrl,
+ setStateToKbnUrl,
+} from '@kbn/kibana-utils-plugin/public';
import { mockStorage } from '@kbn/kibana-utils-plugin/public/storage/hashed_item_store/mock';
import { FilterStateStore } from '@kbn/es-query';
import { DiscoverAppLocatorDefinition } from './locator';
@@ -20,7 +24,7 @@ interface SetupParams {
}
const setup = async ({ useHash = false }: SetupParams = {}) => {
- const locator = new DiscoverAppLocatorDefinition({ useHash });
+ const locator = new DiscoverAppLocatorDefinition({ useHash, setStateToKbnUrl });
return {
locator,
diff --git a/src/plugins/discover/public/locator.ts b/src/plugins/discover/common/locator.ts
similarity index 88%
rename from src/plugins/discover/public/locator.ts
rename to src/plugins/discover/common/locator.ts
index e803433c4d70..77e501dbe40d 100644
--- a/src/plugins/discover/public/locator.ts
+++ b/src/plugins/discover/common/locator.ts
@@ -10,9 +10,9 @@ import type { SerializableRecord } from '@kbn/utility-types';
import type { Filter, TimeRange, Query, AggregateQuery } from '@kbn/es-query';
import type { GlobalQueryStateFromUrl, RefreshInterval } from '@kbn/data-plugin/public';
import type { LocatorDefinition, LocatorPublic } from '@kbn/share-plugin/public';
-import { setStateToKbnUrl } from '@kbn/kibana-utils-plugin/public';
-import { DataViewSpec } from '@kbn/data-views-plugin/public';
-import type { VIEW_MODE } from './components/view_mode_toggle';
+import { DataViewSpec } from '@kbn/data-views-plugin/common';
+import { setStateToKbnUrl } from '@kbn/kibana-utils-plugin/common';
+import { VIEW_MODE } from './constants';
export const DISCOVER_APP_LOCATOR = 'DISCOVER_APP_LOCATOR';
@@ -95,12 +95,17 @@ export interface DiscoverAppLocatorParams extends SerializableRecord {
* Breakdown field
*/
breakdownField?: string;
+ /**
+ * Used when navigating to particular alert results
+ */
+ isAlertResults?: boolean;
}
export type DiscoverAppLocator = LocatorPublic;
export interface DiscoverAppLocatorDependencies {
useHash: boolean;
+ setStateToKbnUrl: typeof setStateToKbnUrl;
}
/**
@@ -108,6 +113,7 @@ export interface DiscoverAppLocatorDependencies {
*/
export interface MainHistoryLocationState {
dataViewSpec?: DataViewSpec;
+ isAlertResults?: boolean;
}
export class DiscoverAppLocatorDefinition implements LocatorDefinition {
@@ -134,6 +140,7 @@ export class DiscoverAppLocatorDefinition implements LocatorDefinition('_g', queryState, { useHash }, path);
- path = setStateToKbnUrl('_a', appState, { useHash }, path);
+ path = this.deps.setStateToKbnUrl('_g', queryState, { useHash }, path);
+ path = this.deps.setStateToKbnUrl('_a', appState, { useHash }, path);
if (searchSessionId) {
path = `${path}&searchSessionId=${searchSessionId}`;
diff --git a/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx b/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx
index 56ef50615b25..c9f52bd548f2 100644
--- a/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx
+++ b/src/plugins/discover/public/application/main/components/layout/discover_layout.tsx
@@ -23,6 +23,7 @@ import { isOfQueryType } from '@kbn/es-query';
import classNames from 'classnames';
import { generateFilters } from '@kbn/data-plugin/public';
import { DataView, DataViewField, DataViewType } from '@kbn/data-views-plugin/public';
+import { VIEW_MODE } from '../../../../../common/constants';
import { useInternalStateSelector } from '../../services/discover_internal_state_container';
import { useAppStateSelector } from '../../services/discover_app_state_container';
import { useInspector } from '../../hooks/use_inspector';
@@ -41,7 +42,6 @@ import { DataMainMsg, RecordRawType } from '../../hooks/use_saved_search';
import { useColumns } from '../../../../hooks/use_data_grid_columns';
import { FetchStatus } from '../../../types';
import { useDataState } from '../../hooks/use_data_state';
-import { VIEW_MODE } from '../../../../components/view_mode_toggle';
import { hasActiveFilter } from './utils';
import { getRawRecordType } from '../../utils/get_raw_record_type';
import { SavedSearchURLConflictCallout } from '../../../../components/saved_search_url_conflict_callout/saved_search_url_conflict_callout';
diff --git a/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx b/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx
index b085e61f348d..f91de3b2a02d 100644
--- a/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx
+++ b/src/plugins/discover/public/application/main/components/layout/discover_main_content.tsx
@@ -11,9 +11,10 @@ import { SavedSearch } from '@kbn/saved-search-plugin/public';
import React, { useCallback } from 'react';
import { DataView } from '@kbn/data-views-plugin/common';
import { METRIC_TYPE } from '@kbn/analytics';
+import { VIEW_MODE } from '../../../../../common/constants';
import { useDiscoverServices } from '../../../../hooks/use_discover_services';
import { DataTableRecord } from '../../../../types';
-import { DocumentViewModeToggle, VIEW_MODE } from '../../../../components/view_mode_toggle';
+import { DocumentViewModeToggle } from '../../../../components/view_mode_toggle';
import { DocViewFilterFn } from '../../../../services/doc_views/doc_views_types';
import { DataRefetch$, SavedSearchData } from '../../hooks/use_saved_search';
import { DiscoverStateContainer } from '../../services/discover_state';
diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.test.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.test.tsx
index 8799e82d7e8a..e688f1120526 100644
--- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.test.tsx
+++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.test.tsx
@@ -20,12 +20,12 @@ import type { AggregateQuery, Query } from '@kbn/es-query';
import { getDefaultFieldFilter } from './lib/field_filter';
import { createDiscoverServicesMock } from '../../../../__mocks__/services';
import { stubLogstashDataView } from '@kbn/data-plugin/common/stubs';
-import { VIEW_MODE } from '../../../../components/view_mode_toggle';
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
import { BehaviorSubject } from 'rxjs';
import { FetchStatus } from '../../../types';
import { AvailableFields$, DataDocuments$ } from '../../hooks/use_saved_search';
import { getDiscoverStateMock } from '../../../../__mocks__/discover_state.mock';
+import { VIEW_MODE } from '../../../../../common/constants';
import { DiscoverMainProvider } from '../../services/discover_state_provider';
import * as ExistingFieldsHookApi from '@kbn/unified-field-list-plugin/public/hooks/use_existing_fields';
import { ExistenceFetchStatus } from '@kbn/unified-field-list-plugin/public';
diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx
index 75bfdffa7962..51cdaadd1cda 100644
--- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx
+++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.tsx
@@ -27,6 +27,7 @@ import {
triggerVisualizeActionsTextBasedLanguages,
useGroupedFields,
} from '@kbn/unified-field-list-plugin/public';
+import { VIEW_MODE } from '../../../../../common/constants';
import { useAppStateSelector } from '../../services/discover_app_state_container';
import { useDiscoverServices } from '../../../../hooks/use_discover_services';
import { DiscoverField } from './discover_field';
@@ -40,7 +41,6 @@ import {
} from './lib/group_fields';
import { doesFieldMatchFilters, FieldFilterState, setFieldFilterProp } from './lib/field_filter';
import { DiscoverSidebarResponsiveProps } from './discover_sidebar_responsive';
-import { VIEW_MODE } from '../../../../components/view_mode_toggle';
import { getUiActions } from '../../../../kibana_services';
import { getRawRecordType } from '../../utils/get_raw_record_type';
import { RecordRawType } from '../../hooks/use_saved_search';
diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx
index 6a1c2af61bcf..3a56fcb8c211 100644
--- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx
+++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx
@@ -22,10 +22,10 @@ import { DiscoverServices } from '../../../../build_services';
import { FetchStatus } from '../../../types';
import { AvailableFields$, DataDocuments$, RecordRawType } from '../../hooks/use_saved_search';
import { stubLogstashDataView } from '@kbn/data-plugin/common/stubs';
-import { VIEW_MODE } from '../../../../components/view_mode_toggle';
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
import { getDiscoverStateMock } from '../../../../__mocks__/discover_state.mock';
import { DiscoverAppStateProvider } from '../../services/discover_app_state_container';
+import { VIEW_MODE } from '../../../../../common/constants';
import * as ExistingFieldsServiceApi from '@kbn/unified-field-list-plugin/public/services/field_existing/load_field_existing';
import { resetExistingFieldsCache } from '@kbn/unified-field-list-plugin/public/hooks/use_existing_fields';
import { createDiscoverServicesMock } from '../../../../__mocks__/services';
diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx
index e89efc988235..89ccef3cde93 100644
--- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx
+++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.tsx
@@ -28,11 +28,12 @@ import {
useExistingFieldsFetcher,
useQuerySubscriber,
} from '@kbn/unified-field-list-plugin/public';
+import { VIEW_MODE } from '../../../../../common/constants';
import { useDiscoverServices } from '../../../../hooks/use_discover_services';
import { getDefaultFieldFilter } from './lib/field_filter';
import { DiscoverSidebar } from './discover_sidebar';
import { AvailableFields$, DataDocuments$, RecordRawType } from '../../hooks/use_saved_search';
-import { VIEW_MODE } from '../../../../components/view_mode_toggle';
+import { calcFieldCounts } from '../../utils/calc_field_counts';
import { FetchStatus } from '../../../types';
import { DISCOVER_TOUR_STEP_ANCHOR_IDS } from '../../../../components/discover_tour';
import { getRawRecordType } from '../../utils/get_raw_record_type';
@@ -43,7 +44,6 @@ import {
DiscoverSidebarReducerActionType,
DiscoverSidebarReducerStatus,
} from './lib/sidebar_reducer';
-import { calcFieldCounts } from '../../utils/calc_field_counts';
export interface DiscoverSidebarResponsiveProps {
/**
diff --git a/src/plugins/discover/public/application/main/discover_main_route.tsx b/src/plugins/discover/public/application/main/discover_main_route.tsx
index a50c596b4dfd..b317c0e5cffd 100644
--- a/src/plugins/discover/public/application/main/discover_main_route.tsx
+++ b/src/plugins/discover/public/application/main/discover_main_route.tsx
@@ -21,6 +21,7 @@ import {
getSavedSearch,
getSavedSearchFullPathUrl,
} from '@kbn/saved-search-plugin/public';
+import { MainHistoryLocationState } from '../../../common/locator';
import { getDiscoverStateContainer } from './services/discover_state';
import { loadDataView, resolveDataView } from './utils/resolve_data_view';
import { DiscoverMainApp } from './discover_main_app';
@@ -30,7 +31,7 @@ import { DiscoverError } from '../../components/common/error_alert';
import { useDiscoverServices } from '../../hooks/use_discover_services';
import { getScopedHistory, getUrlTracker } from '../../kibana_services';
import { restoreStateFromSavedSearch } from '../../services/saved_searches/restore_from_saved_search';
-import { MainHistoryLocationState } from '../../locator';
+import { useAlertResultsToast } from './hooks/use_alert_results_toast';
const DiscoverMainAppMemoized = memo(DiscoverMainApp);
@@ -72,6 +73,11 @@ export function DiscoverMainRoute(props: Props) {
[]
);
+ useAlertResultsToast({
+ isAlertResults: historyLocationState?.isAlertResults,
+ toastNotifications,
+ });
+
useExecutionContext(core.executionContext, {
type: 'application',
page: 'app',
diff --git a/src/plugins/discover/public/application/main/hooks/use_alert_results_toast.tsx b/src/plugins/discover/public/application/main/hooks/use_alert_results_toast.tsx
new file mode 100644
index 000000000000..424cd554ecd1
--- /dev/null
+++ b/src/plugins/discover/public/application/main/hooks/use_alert_results_toast.tsx
@@ -0,0 +1,41 @@
+/*
+ * 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 and the Server Side Public License, v 1; you may not use this file except
+ * in compliance with, at your election, the Elastic License 2.0 or the Server
+ * Side Public License, v 1.
+ */
+
+import { ToastsStart } from '@kbn/core/public';
+import { i18n } from '@kbn/i18n';
+import { MarkdownSimple, toMountPoint } from '@kbn/kibana-react-plugin/public';
+import React, { useEffect } from 'react';
+
+export const displayPossibleDocsDiffInfoAlert = (toastNotifications: ToastsStart) => {
+ const infoTitle = i18n.translate('discover.viewAlert.documentsMayVaryInfoTitle', {
+ defaultMessage: 'Displayed documents may vary',
+ });
+ const infoDescription = i18n.translate('discover.viewAlert.documentsMayVaryInfoDescription', {
+ defaultMessage: `The displayed documents might differ from the documents that triggered the alert.
+ Some documents might have been added or deleted.`,
+ });
+
+ toastNotifications.addInfo({
+ title: infoTitle,
+ text: toMountPoint({infoDescription}),
+ });
+};
+
+export const useAlertResultsToast = ({
+ isAlertResults,
+ toastNotifications,
+}: {
+ isAlertResults?: boolean;
+ toastNotifications: ToastsStart;
+}) => {
+ useEffect(() => {
+ if (isAlertResults) {
+ displayPossibleDocsDiffInfoAlert(toastNotifications);
+ }
+ }, [isAlertResults, toastNotifications]);
+};
diff --git a/src/plugins/discover/public/application/main/services/discover_app_state_container.ts b/src/plugins/discover/public/application/main/services/discover_app_state_container.ts
index ddfd7950f6eb..0c1c94f72eb9 100644
--- a/src/plugins/discover/public/application/main/services/discover_app_state_container.ts
+++ b/src/plugins/discover/public/application/main/services/discover_app_state_container.ts
@@ -11,8 +11,8 @@ import {
ReduxLikeStateContainer,
} from '@kbn/kibana-utils-plugin/common';
import { AggregateQuery, Filter, Query } from '@kbn/es-query';
+import { VIEW_MODE } from '@kbn/saved-search-plugin/public';
import { DiscoverGridSettings } from '../../../components/discover_grid/types';
-import { VIEW_MODE } from '../../../components/view_mode_toggle';
export interface AppState {
/**
diff --git a/src/plugins/discover/public/application/main/services/discover_state.ts b/src/plugins/discover/public/application/main/services/discover_state.ts
index b4a1bcbf0f1f..52e0d6e72fbf 100644
--- a/src/plugins/discover/public/application/main/services/discover_state.ts
+++ b/src/plugins/discover/public/application/main/services/discover_state.ts
@@ -29,6 +29,7 @@ import {
} from '@kbn/data-plugin/public';
import { DataView } from '@kbn/data-views-plugin/public';
import { SavedSearch } from '@kbn/saved-search-plugin/public';
+import { DiscoverAppLocatorParams, DISCOVER_APP_LOCATOR } from '../../../../common';
import { AppState } from './discover_app_state_container';
import {
getInternalStateContainer,
@@ -37,7 +38,6 @@ import {
import { getStateDefaults } from '../utils/get_state_defaults';
import { DiscoverServices } from '../../../build_services';
import { handleSourceColumnState } from '../../../utils/state_helpers';
-import { DISCOVER_APP_LOCATOR, DiscoverAppLocatorParams } from '../../../locator';
import { cleanupUrlState } from '../utils/cleanup_url_state';
import { getValidFilters } from '../../../utils/get_valid_filters';
diff --git a/src/plugins/discover/public/application/view_alert/view_alert_route.tsx b/src/plugins/discover/public/application/view_alert/view_alert_route.tsx
index 0fdd58c05823..84e65e8d672d 100644
--- a/src/plugins/discover/public/application/view_alert/view_alert_route.tsx
+++ b/src/plugins/discover/public/application/view_alert/view_alert_route.tsx
@@ -8,41 +8,19 @@
import { useEffect, useMemo } from 'react';
import { useHistory, useLocation, useParams } from 'react-router-dom';
-import { sha256 } from 'js-sha256';
-import type { Rule } from '@kbn/alerting-plugin/common';
-import { getTime } from '@kbn/data-plugin/common';
-import type { DataView } from '@kbn/data-views-plugin/public';
-import type { Filter } from '@kbn/es-query';
-import { DiscoverAppLocatorParams } from '../../locator';
+import { DiscoverAppLocatorParams } from '../../../common/locator';
import { useDiscoverServices } from '../../hooks/use_discover_services';
-import { getAlertUtils, QueryParams, SearchThresholdAlertParams } from './view_alert_utils';
+import { displayPossibleDocsDiffInfoAlert } from '../main/hooks/use_alert_results_toast';
+import { getAlertUtils, QueryParams } from './view_alert_utils';
-type NonNullableEntry = { [K in keyof T]: NonNullable };
+const DISCOVER_MAIN_ROUTE = '/';
-const getCurrentChecksum = (params: SearchThresholdAlertParams) =>
- sha256.create().update(JSON.stringify(params)).hex();
+type NonNullableEntry = { [K in keyof T]: NonNullable };
const isActualAlert = (queryParams: QueryParams): queryParams is NonNullableEntry => {
- return Boolean(queryParams.from && queryParams.to && queryParams.checksum);
-};
-
-const buildTimeRangeFilter = (
- dataView: DataView,
- fetchedAlert: Rule,
- timeFieldName: string
-) => {
- const filter = getTime(dataView, {
- from: `now-${fetchedAlert.params.timeWindowSize}${fetchedAlert.params.timeWindowUnit}`,
- to: 'now',
- });
- return {
- from: filter?.query.range[timeFieldName].gte,
- to: filter?.query.range[timeFieldName].lte,
- };
+ return Boolean(queryParams.from && queryParams.to);
};
-const DISCOVER_MAIN_ROUTE = '/';
-
export function ViewAlertRoute() {
const { core, data, locator, toastNotifications } = useDiscoverServices();
const { id } = useParams<{ id: string }>();
@@ -55,100 +33,39 @@ export function ViewAlertRoute() {
() => ({
from: query.get('from'),
to: query.get('to'),
- checksum: query.get('checksum'),
}),
[query]
);
+ /**
+ * This flag indicates whether we should open the actual alert results or current state of documents.
+ */
const openActualAlert = useMemo(() => isActualAlert(queryParams), [queryParams]);
useEffect(() => {
- const {
- fetchAlert,
- fetchSearchSource,
- displayRuleChangedWarn,
- displayPossibleDocsDiffInfoAlert,
- showDataViewFetchError,
- showDataViewUpdatedWarning,
- } = getAlertUtils(toastNotifications, core, data);
-
- const navigateToResults = async () => {
- const fetchedAlert = await fetchAlert(id);
- if (!fetchedAlert) {
- history.push(DISCOVER_MAIN_ROUTE);
- return;
- }
- const fetchedSearchSource = await fetchSearchSource(fetchedAlert);
- if (!fetchedSearchSource) {
- history.push(DISCOVER_MAIN_ROUTE);
- return;
- }
- const dataView = fetchedSearchSource.getField('index');
- const timeFieldName = dataView?.timeFieldName;
- // data view fetch error
- if (!dataView || !timeFieldName) {
- showDataViewFetchError(fetchedAlert.id);
- history.push(DISCOVER_MAIN_ROUTE);
- return;
+ const { fetchAlert, fetchSearchSource, buildLocatorParams } = getAlertUtils(
+ openActualAlert,
+ queryParams,
+ toastNotifications,
+ core,
+ data
+ );
+
+ const navigateWithDiscoverState = (state: DiscoverAppLocatorParams) => {
+ if (openActualAlert) {
+ displayPossibleDocsDiffInfoAlert(toastNotifications);
}
-
- if (dataView.isPersisted()) {
- const dataViewSavedObject = await core.savedObjects.client.get(
- 'index-pattern',
- dataView.id!
- );
-
- const alertUpdatedAt = fetchedAlert.updatedAt;
- const dataViewUpdatedAt = dataViewSavedObject.updatedAt!;
- // data view updated after the last update of the alert rule
- if (
- openActualAlert &&
- new Date(dataViewUpdatedAt).valueOf() > new Date(alertUpdatedAt).valueOf()
- ) {
- showDataViewUpdatedWarning();
- }
- }
-
- const calculatedChecksum = getCurrentChecksum(fetchedAlert.params);
- // rule params changed
- if (openActualAlert && calculatedChecksum !== queryParams.checksum) {
- displayRuleChangedWarn();
- } else if (openActualAlert && calculatedChecksum === queryParams.checksum) {
- // documents might be updated or deleted
- displayPossibleDocsDiffInfoAlert();
- }
-
- const timeRange = openActualAlert
- ? { from: queryParams.from, to: queryParams.to }
- : buildTimeRangeFilter(dataView, fetchedAlert, timeFieldName);
- const state: DiscoverAppLocatorParams = {
- query: fetchedSearchSource.getField('query') || data.query.queryString.getDefaultQuery(),
- dataViewSpec: dataView.toSpec(false),
- timeRange,
- };
-
- const filters = fetchedSearchSource.getField('filter');
- if (filters) {
- state.filters = filters as Filter[];
- }
-
- await locator.navigate(state);
+ locator.navigate(state);
};
- navigateToResults();
- }, [
- toastNotifications,
- data.query.queryString,
- data.search.searchSource,
- core.http,
- locator,
- id,
- queryParams,
- history,
- openActualAlert,
- core,
- data,
- ]);
+ const navigateToDiscoverRoot = () => history.push(DISCOVER_MAIN_ROUTE);
+
+ fetchAlert(id)
+ .then(fetchSearchSource)
+ .then(buildLocatorParams)
+ .then(navigateWithDiscoverState)
+ .catch(navigateToDiscoverRoot);
+ }, [core, data, history, id, locator, openActualAlert, queryParams, toastNotifications]);
return null;
}
diff --git a/src/plugins/discover/public/application/view_alert/view_alert_utils.tsx b/src/plugins/discover/public/application/view_alert/view_alert_utils.tsx
index d5b6aac22d3b..f29fd7d40b51 100644
--- a/src/plugins/discover/public/application/view_alert/view_alert_utils.tsx
+++ b/src/plugins/discover/public/application/view_alert/view_alert_utils.tsx
@@ -9,11 +9,14 @@
import React from 'react';
import { i18n } from '@kbn/i18n';
import { CoreStart, ToastsStart } from '@kbn/core/public';
+import type { DataView } from '@kbn/data-views-plugin/public';
import type { Rule } from '@kbn/alerting-plugin/common';
import type { RuleTypeParams } from '@kbn/alerting-plugin/common';
-import { SerializedSearchSourceFields } from '@kbn/data-plugin/common';
+import { ISearchSource, SerializedSearchSourceFields, getTime } from '@kbn/data-plugin/common';
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
import { MarkdownSimple, toMountPoint } from '@kbn/kibana-react-plugin/public';
+import { Filter } from '@kbn/es-query';
+import { DiscoverAppLocatorParams } from '../../../common/locator';
export interface SearchThresholdAlertParams extends RuleTypeParams {
searchConfiguration: SerializedSearchSourceFields;
@@ -22,12 +25,28 @@ export interface SearchThresholdAlertParams extends RuleTypeParams {
export interface QueryParams {
from: string | null;
to: string | null;
- checksum: string | null;
}
const LEGACY_BASE_ALERT_API_PATH = '/api/alerts';
+const buildTimeRangeFilter = (
+ dataView: DataView,
+ fetchedAlert: Rule,
+ timeFieldName: string
+) => {
+ const filter = getTime(dataView, {
+ from: `now-${fetchedAlert.params.timeWindowSize}${fetchedAlert.params.timeWindowUnit}`,
+ to: 'now',
+ });
+ return {
+ from: filter?.query.range[timeFieldName].gte,
+ to: filter?.query.range[timeFieldName].lte,
+ };
+};
+
export const getAlertUtils = (
+ openActualAlert: boolean,
+ queryParams: QueryParams,
toastNotifications: ToastsStart,
core: CoreStart,
data: DataPublicPluginStart
@@ -46,36 +65,6 @@ export const getAlertUtils = (
});
};
- const displayRuleChangedWarn = () => {
- const warnTitle = i18n.translate('discover.viewAlert.alertRuleChangedWarnTitle', {
- defaultMessage: 'Alert rule has changed',
- });
- const warnDescription = i18n.translate('discover.viewAlert.alertRuleChangedWarnDescription', {
- defaultMessage: `The displayed documents might not match the documents that triggered the alert
- because the rule configuration changed.`,
- });
-
- toastNotifications.addWarning({
- title: warnTitle,
- text: toMountPoint({warnDescription}),
- });
- };
-
- const displayPossibleDocsDiffInfoAlert = () => {
- const infoTitle = i18n.translate('discover.viewAlert.documentsMayVaryInfoTitle', {
- defaultMessage: 'Displayed documents may vary',
- });
- const infoDescription = i18n.translate('discover.viewAlert.documentsMayVaryInfoDescription', {
- defaultMessage: `The displayed documents might differ from the documents that triggered the alert.
- Some documents might have been added or deleted.`,
- });
-
- toastNotifications.addInfo({
- title: infoTitle,
- text: toMountPoint({infoDescription}),
- });
- };
-
const fetchAlert = async (id: string) => {
try {
return await core.http.get>(
@@ -89,12 +78,18 @@ export const getAlertUtils = (
title: errorTitle,
text: toMountPoint({error.message}),
});
+ throw new Error(errorTitle);
}
};
const fetchSearchSource = async (fetchedAlert: Rule) => {
try {
- return await data.search.searchSource.create(fetchedAlert.params.searchConfiguration);
+ return {
+ alert: fetchedAlert,
+ searchSource: await data.search.searchSource.create(
+ fetchedAlert.params.searchConfiguration
+ ),
+ };
} catch (error) {
const errorTitle = i18n.translate('discover.viewAlert.searchSourceErrorTitle', {
defaultMessage: 'Error fetching search source',
@@ -103,29 +98,40 @@ export const getAlertUtils = (
title: errorTitle,
text: toMountPoint({error.message}),
});
+ throw new Error(errorTitle);
}
};
- const showDataViewUpdatedWarning = async () => {
- const warnTitle = i18n.translate('discover.viewAlert.dataViewChangedWarnTitle', {
- defaultMessage: 'Data View has changed',
- });
- const warnDescription = i18n.translate('discover.viewAlert.dataViewChangedWarnDescription', {
- defaultMessage: `Data view has been updated after the last update of the alert rule.`,
- });
+ const buildLocatorParams = ({
+ alert,
+ searchSource,
+ }: {
+ alert: Rule;
+ searchSource: ISearchSource;
+ }): DiscoverAppLocatorParams => {
+ const dataView = searchSource.getField('index');
+ const timeFieldName = dataView?.timeFieldName;
+ // data view fetch error
+ if (!dataView || !timeFieldName) {
+ showDataViewFetchError(alert.id);
+ throw new Error('Data view fetch error');
+ }
- toastNotifications.addWarning({
- title: warnTitle,
- text: toMountPoint({warnDescription}),
- });
+ const timeRange = openActualAlert
+ ? { from: queryParams.from, to: queryParams.to }
+ : buildTimeRangeFilter(dataView, alert, timeFieldName);
+
+ return {
+ query: searchSource.getField('query') || data.query.queryString.getDefaultQuery(),
+ dataViewSpec: dataView.toSpec(false),
+ timeRange,
+ filters: searchSource.getField('filter') as Filter[],
+ };
};
return {
fetchAlert,
fetchSearchSource,
- displayRuleChangedWarn,
- displayPossibleDocsDiffInfoAlert,
- showDataViewFetchError,
- showDataViewUpdatedWarning,
+ buildLocatorParams,
};
};
diff --git a/src/plugins/discover/public/build_services.ts b/src/plugins/discover/public/build_services.ts
index 27f5d59b07e1..5975805522f4 100644
--- a/src/plugins/discover/public/build_services.ts
+++ b/src/plugins/discover/public/build_services.ts
@@ -47,11 +47,11 @@ import type { SavedObjectsTaggingApi } from '@kbn/saved-objects-tagging-oss-plug
import type { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public';
import type { LensPublicStart } from '@kbn/lens-plugin/public';
-import { DiscoverAppLocator } from './locator';
import { getHistory } from './kibana_services';
import { DiscoverStartPlugins } from './plugin';
import { DiscoverContextAppLocator } from './application/context/services/locator';
import { DiscoverSingleDocLocator } from './application/doc/locator';
+import { DiscoverAppLocator } from '../common';
/**
* Location state of internal Discover history instance
diff --git a/src/plugins/discover/public/components/view_mode_toggle/constants.ts b/src/plugins/discover/public/components/view_mode_toggle/constants.ts
deleted file mode 100644
index d03c0710d12b..000000000000
--- a/src/plugins/discover/public/components/view_mode_toggle/constants.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * 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 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-export enum VIEW_MODE {
- DOCUMENT_LEVEL = 'documents',
- AGGREGATED_LEVEL = 'aggregated',
-}
diff --git a/src/plugins/discover/public/components/view_mode_toggle/index.ts b/src/plugins/discover/public/components/view_mode_toggle/index.ts
index 95b76f5879d1..06aab965b97b 100644
--- a/src/plugins/discover/public/components/view_mode_toggle/index.ts
+++ b/src/plugins/discover/public/components/view_mode_toggle/index.ts
@@ -7,4 +7,3 @@
*/
export { DocumentViewModeToggle } from './view_mode_toggle';
-export { VIEW_MODE } from './constants';
diff --git a/src/plugins/discover/public/components/view_mode_toggle/view_mode_toggle.test.tsx b/src/plugins/discover/public/components/view_mode_toggle/view_mode_toggle.test.tsx
index 450d7c2816d7..7c17e5e1a31e 100644
--- a/src/plugins/discover/public/components/view_mode_toggle/view_mode_toggle.test.tsx
+++ b/src/plugins/discover/public/components/view_mode_toggle/view_mode_toggle.test.tsx
@@ -7,10 +7,10 @@
*/
import { EuiTab } from '@elastic/eui';
+import { VIEW_MODE } from '../../../common/constants';
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
import { mountWithIntl } from '@kbn/test-jest-helpers';
import React from 'react';
-import { VIEW_MODE } from './constants';
import { DocumentViewModeToggle } from './view_mode_toggle';
describe('Document view mode toggle component', () => {
diff --git a/src/plugins/discover/public/components/view_mode_toggle/view_mode_toggle.tsx b/src/plugins/discover/public/components/view_mode_toggle/view_mode_toggle.tsx
index 99c7403c3fbf..befe62ef42fb 100644
--- a/src/plugins/discover/public/components/view_mode_toggle/view_mode_toggle.tsx
+++ b/src/plugins/discover/public/components/view_mode_toggle/view_mode_toggle.tsx
@@ -11,7 +11,7 @@ import React from 'react';
import { FormattedMessage } from '@kbn/i18n-react';
import { css } from '@emotion/react';
import { euiThemeVars } from '@kbn/ui-theme';
-import { VIEW_MODE } from './constants';
+import { VIEW_MODE } from '../../../common/constants';
import { SHOW_FIELD_STATISTICS } from '../../../common';
import { useDiscoverServices } from '../../hooks/use_discover_services';
diff --git a/src/plugins/discover/public/embeddable/saved_search_embeddable.test.ts b/src/plugins/discover/public/embeddable/saved_search_embeddable.test.ts
index 77bb0d98fd21..0e30156381ad 100644
--- a/src/plugins/discover/public/embeddable/saved_search_embeddable.test.ts
+++ b/src/plugins/discover/public/embeddable/saved_search_embeddable.test.ts
@@ -20,8 +20,8 @@ import { of, throwError } from 'rxjs';
import { ReactWrapper } from 'enzyme';
import { SHOW_FIELD_STATISTICS } from '../../common';
import { IUiSettingsClient } from '@kbn/core-ui-settings-browser';
-import { VIEW_MODE } from '../components/view_mode_toggle';
import { SavedSearchEmbeddableComponent } from './saved_search_embeddable_component';
+import { VIEW_MODE } from '../../common/constants';
let discoverComponent: ReactWrapper;
diff --git a/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx b/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx
index 81e25fd3c6b8..96c23d085afc 100644
--- a/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx
+++ b/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx
@@ -35,6 +35,7 @@ import { UiActionsStart } from '@kbn/ui-actions-plugin/public';
import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
import { SavedSearch } from '@kbn/saved-search-plugin/public';
import { METRIC_TYPE } from '@kbn/analytics';
+import { VIEW_MODE } from '../../common/constants';
import { getSortForEmbeddable, SortPair } from '../utils/sorting';
import { RecordRawType } from '../application/main/hooks/use_saved_search';
import { buildDataTableRecord } from '../utils/build_data_record';
@@ -56,7 +57,6 @@ import { handleSourceColumnState } from '../utils/state_helpers';
import { DiscoverGridProps } from '../components/discover_grid/discover_grid';
import { DiscoverGridSettings } from '../components/discover_grid/types';
import { DocTableProps } from '../components/doc_table/doc_table_wrapper';
-import { VIEW_MODE } from '../components/view_mode_toggle';
import { updateSearchSource } from './utils/update_search_source';
import { FieldStatisticsTable } from '../application/main/components/field_stats_table';
import { getRawRecordType } from '../application/main/utils/get_raw_record_type';
diff --git a/src/plugins/discover/public/index.ts b/src/plugins/discover/public/index.ts
index 451bf3303216..bafa6b603d6e 100644
--- a/src/plugins/discover/public/index.ts
+++ b/src/plugins/discover/public/index.ts
@@ -18,9 +18,6 @@ export type { ISearchEmbeddable, SearchInput } from './embeddable';
export { SEARCH_EMBEDDABLE_TYPE } from './embeddable';
export { loadSharingDataHelpers } from './utils';
-export { DISCOVER_APP_LOCATOR } from './locator';
-export type { DiscoverAppLocator, DiscoverAppLocatorParams } from './locator';
-
// re-export types and static functions to give other plugins time to migrate away
export {
type SavedSearch,
diff --git a/src/plugins/discover/public/plugin.tsx b/src/plugins/discover/public/plugin.tsx
index 407584df5787..1d106309641a 100644
--- a/src/plugins/discover/public/plugin.tsx
+++ b/src/plugins/discover/public/plugin.tsx
@@ -40,6 +40,7 @@ import { TriggersAndActionsUIPublicPluginStart } from '@kbn/triggers-actions-ui-
import type { SavedObjectTaggingOssPluginStart } from '@kbn/saved-objects-tagging-oss-plugin/public';
import type { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public';
+import { setStateToKbnUrl } from '@kbn/kibana-utils-plugin/public';
import type { LensPublicStart } from '@kbn/lens-plugin/public';
import { PLUGIN_ID } from '../common';
import { DocViewInput, DocViewInputFn } from './services/doc_views/doc_views_types';
@@ -54,7 +55,6 @@ import {
} from './kibana_services';
import { registerFeature } from './register_feature';
import { buildServices } from './build_services';
-import { DiscoverAppLocator, DiscoverAppLocatorDefinition } from './locator';
import { SearchEmbeddableFactory } from './embeddable';
import { DeferredSpinner } from './components';
import { ViewSavedSearchAction } from './embeddable/view_saved_search_action';
@@ -70,6 +70,7 @@ import {
DiscoverSingleDocLocator,
DiscoverSingleDocLocatorDefinition,
} from './application/doc/locator';
+import { DiscoverAppLocator, DiscoverAppLocatorDefinition } from '../common';
const DocViewerLegacyTable = React.lazy(
() => import('./services/doc_views/components/doc_viewer_table/legacy')
@@ -218,7 +219,7 @@ export class DiscoverPlugin
if (plugins.share) {
const useHash = core.uiSettings.get('state:storeInSessionStorage');
this.locator = plugins.share.url.locators.create(
- new DiscoverAppLocatorDefinition({ useHash })
+ new DiscoverAppLocatorDefinition({ useHash, setStateToKbnUrl })
);
this.contextLocator = plugins.share.url.locators.create(
diff --git a/src/plugins/discover/public/utils/initialize_kbn_url_tracking.ts b/src/plugins/discover/public/utils/initialize_kbn_url_tracking.ts
index f53537cd5351..87ffd52d5891 100644
--- a/src/plugins/discover/public/utils/initialize_kbn_url_tracking.ts
+++ b/src/plugins/discover/public/utils/initialize_kbn_url_tracking.ts
@@ -8,11 +8,8 @@
import { AppUpdater, CoreSetup } from '@kbn/core/public';
import type { BehaviorSubject } from 'rxjs';
import { filter, map } from 'rxjs/operators';
-import {
- createGetterSetter,
- createKbnUrlTracker,
- replaceUrlHashQuery,
-} from '@kbn/kibana-utils-plugin/public';
+import { createGetterSetter, createKbnUrlTracker } from '@kbn/kibana-utils-plugin/public';
+import { replaceUrlHashQuery } from '@kbn/kibana-utils-plugin/common';
import { getScopedHistory } from '../kibana_services';
import { SEARCH_SESSION_ID_QUERY_PARAM } from '../constants';
import type { DiscoverSetupPlugins } from '../plugin';
diff --git a/src/plugins/discover/server/plugin.ts b/src/plugins/discover/server/plugin.ts
index cfd62312fb6d..a2ee1d79b6a1 100644
--- a/src/plugins/discover/server/plugin.ts
+++ b/src/plugins/discover/server/plugin.ts
@@ -9,9 +9,12 @@
import { CoreSetup, CoreStart, Plugin } from '@kbn/core/server';
import type { PluginSetup as DataPluginSetup } from '@kbn/data-plugin/server';
import type { HomeServerPluginSetup } from '@kbn/home-plugin/server';
+import { SharePluginSetup } from '@kbn/share-plugin/server';
+import { setStateToKbnUrl } from '@kbn/kibana-utils-plugin/common';
import { getUiSettings } from './ui_settings';
import { capabilitiesProvider } from './capabilities_provider';
import { registerSampleData } from './sample_data';
+import { DiscoverAppLocatorDefinition } from '../common/locator';
export class DiscoverServerPlugin implements Plugin