mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Enterprise Search] [Analytics] Analytics Collection list view (#139554)
Implements the analytics collection list view. Co-authored-by: Casey Zumwalt <casey.zumwalt@elastic.co> Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
dc43193d73
commit
48ad65f992
28 changed files with 968 additions and 3 deletions
|
@ -135,6 +135,7 @@ export const applicationUsageSchema = {
|
|||
canvas: commonSchema,
|
||||
enterpriseSearch: commonSchema,
|
||||
enterpriseSearchContent: commonSchema,
|
||||
enterpriseSearchAnalytics: commonSchema,
|
||||
elasticsearch: commonSchema,
|
||||
appSearch: commonSchema,
|
||||
workplaceSearch: commonSchema,
|
||||
|
|
|
@ -2354,6 +2354,137 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"enterpriseSearchAnalytics": {
|
||||
"properties": {
|
||||
"appId": {
|
||||
"type": "keyword",
|
||||
"_meta": {
|
||||
"description": "The application being tracked"
|
||||
}
|
||||
},
|
||||
"viewId": {
|
||||
"type": "keyword",
|
||||
"_meta": {
|
||||
"description": "Always `main`"
|
||||
}
|
||||
},
|
||||
"clicks_total": {
|
||||
"type": "long",
|
||||
"_meta": {
|
||||
"description": "General number of clicks in the application since we started counting them"
|
||||
}
|
||||
},
|
||||
"clicks_7_days": {
|
||||
"type": "long",
|
||||
"_meta": {
|
||||
"description": "General number of clicks in the application over the last 7 days"
|
||||
}
|
||||
},
|
||||
"clicks_30_days": {
|
||||
"type": "long",
|
||||
"_meta": {
|
||||
"description": "General number of clicks in the application over the last 30 days"
|
||||
}
|
||||
},
|
||||
"clicks_90_days": {
|
||||
"type": "long",
|
||||
"_meta": {
|
||||
"description": "General number of clicks in the application over the last 90 days"
|
||||
}
|
||||
},
|
||||
"minutes_on_screen_total": {
|
||||
"type": "float",
|
||||
"_meta": {
|
||||
"description": "Minutes the application is active and on-screen since we started counting them."
|
||||
}
|
||||
},
|
||||
"minutes_on_screen_7_days": {
|
||||
"type": "float",
|
||||
"_meta": {
|
||||
"description": "Minutes the application is active and on-screen over the last 7 days"
|
||||
}
|
||||
},
|
||||
"minutes_on_screen_30_days": {
|
||||
"type": "float",
|
||||
"_meta": {
|
||||
"description": "Minutes the application is active and on-screen over the last 30 days"
|
||||
}
|
||||
},
|
||||
"minutes_on_screen_90_days": {
|
||||
"type": "float",
|
||||
"_meta": {
|
||||
"description": "Minutes the application is active and on-screen over the last 90 days"
|
||||
}
|
||||
},
|
||||
"views": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"properties": {
|
||||
"appId": {
|
||||
"type": "keyword",
|
||||
"_meta": {
|
||||
"description": "The application being tracked"
|
||||
}
|
||||
},
|
||||
"viewId": {
|
||||
"type": "keyword",
|
||||
"_meta": {
|
||||
"description": "The application view being tracked"
|
||||
}
|
||||
},
|
||||
"clicks_total": {
|
||||
"type": "long",
|
||||
"_meta": {
|
||||
"description": "General number of clicks in the application sub view since we started counting them"
|
||||
}
|
||||
},
|
||||
"clicks_7_days": {
|
||||
"type": "long",
|
||||
"_meta": {
|
||||
"description": "General number of clicks in the active application sub view over the last 7 days"
|
||||
}
|
||||
},
|
||||
"clicks_30_days": {
|
||||
"type": "long",
|
||||
"_meta": {
|
||||
"description": "General number of clicks in the active application sub view over the last 30 days"
|
||||
}
|
||||
},
|
||||
"clicks_90_days": {
|
||||
"type": "long",
|
||||
"_meta": {
|
||||
"description": "General number of clicks in the active application sub view over the last 90 days"
|
||||
}
|
||||
},
|
||||
"minutes_on_screen_total": {
|
||||
"type": "float",
|
||||
"_meta": {
|
||||
"description": "Minutes the application sub view is active and on-screen since we started counting them."
|
||||
}
|
||||
},
|
||||
"minutes_on_screen_7_days": {
|
||||
"type": "float",
|
||||
"_meta": {
|
||||
"description": "Minutes the application is active and on-screen active application sub view over the last 7 days"
|
||||
}
|
||||
},
|
||||
"minutes_on_screen_30_days": {
|
||||
"type": "float",
|
||||
"_meta": {
|
||||
"description": "Minutes the application is active and on-screen active application sub view over the last 30 days"
|
||||
}
|
||||
},
|
||||
"minutes_on_screen_90_days": {
|
||||
"type": "float",
|
||||
"_meta": {
|
||||
"description": "Minutes the application is active and on-screen active application sub view over the last 90 days"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"elasticsearch": {
|
||||
"properties": {
|
||||
"appId": {
|
||||
|
|
|
@ -39,6 +39,23 @@ export const ENTERPRISE_SEARCH_CONTENT_PLUGIN = {
|
|||
SUPPORT_URL: 'https://discuss.elastic.co/c/enterprise-search/',
|
||||
};
|
||||
|
||||
export const ANALYTICS_PLUGIN = {
|
||||
ID: 'enterpriseSearchAnalytics',
|
||||
NAME: i18n.translate('xpack.enterpriseSearch.analytics.productName', {
|
||||
defaultMessage: 'Analytics',
|
||||
}),
|
||||
DESCRIPTION: i18n.translate('xpack.enterpriseSearch.analytics.productDescription', {
|
||||
defaultMessage:
|
||||
'Dashboards and tools for visualizing end-user behavior and measuring the performance of your search applications.',
|
||||
}),
|
||||
CARD_DESCRIPTION: i18n.translate('xpack.enterpriseSearch.analytics.productCardDescription', {
|
||||
defaultMessage:
|
||||
'Dashboards and tools for visualizing end-user behavior and measuring the performance of your search applications.',
|
||||
}),
|
||||
URL: '/app/enterprise_search/analytics',
|
||||
SUPPORT_URL: 'https://discuss.elastic.co/c/enterprise-search/',
|
||||
};
|
||||
|
||||
export const ELASTICSEARCH_PLUGIN = {
|
||||
ID: 'elasticsearch',
|
||||
NAME: i18n.translate('xpack.enterpriseSearch.elasticsearch.productName', {
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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 { mockHttpValues } from '../../../__mocks__/kea_logic';
|
||||
|
||||
import { nextTick } from '@kbn/test-jest-helpers';
|
||||
|
||||
import { fetchAnalyticsCollections } from './fetch_analytics_collections_api_logic';
|
||||
|
||||
describe('FetchAnalyticsCollectionsApiLogic', () => {
|
||||
const { http } = mockHttpValues;
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('FetchAnalyticsCollectionsApiLogic', () => {
|
||||
it('calls the analytics collections list api', async () => {
|
||||
const promise = Promise.resolve([{ name: 'result' }]);
|
||||
http.get.mockReturnValue(promise);
|
||||
const result = fetchAnalyticsCollections();
|
||||
await nextTick();
|
||||
expect(http.get).toHaveBeenCalledWith('/internal/enterprise_search/analytics/collections');
|
||||
await expect(result).resolves.toEqual([{ name: 'result' }]);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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 { AnalyticsCollection } from '../../../../../common/types/analytics';
|
||||
|
||||
import { createApiLogic } from '../../../shared/api_logic/create_api_logic';
|
||||
import { HttpLogic } from '../../../shared/http';
|
||||
|
||||
export const fetchAnalyticsCollections = async () => {
|
||||
const { http } = HttpLogic.values;
|
||||
const route = '/internal/enterprise_search/analytics/collections';
|
||||
const response = await http.get<AnalyticsCollection[]>(route);
|
||||
|
||||
return response;
|
||||
};
|
||||
|
||||
export const FetchAnalyticsCollectionsAPILogic = createApiLogic(
|
||||
['analytics', 'analytics_collections_api_logic'],
|
||||
fetchAnalyticsCollections
|
||||
);
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* 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 '../../../__mocks__/kea_logic';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { EuiBasicTable } from '@elastic/eui';
|
||||
|
||||
import { AnalyticsCollection } from '../../../../../common/types/analytics';
|
||||
|
||||
import { EuiLinkTo } from '../../../shared/react_router_helpers';
|
||||
|
||||
import { AnalyticsCollectionTable } from './analytics_collection_table';
|
||||
|
||||
describe('AnalyticsCollectionTable', () => {
|
||||
const analyticsCollections: AnalyticsCollection[] = [
|
||||
{ event_retention_day_length: 180, id: '1', name: 'example' },
|
||||
];
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('renders and provides navigation to the view detail pages', () => {
|
||||
const wrapper = shallow(
|
||||
<AnalyticsCollectionTable collections={analyticsCollections} isLoading={false} />
|
||||
);
|
||||
|
||||
expect(wrapper.find(EuiBasicTable)).toHaveLength(1);
|
||||
|
||||
const rows = wrapper.find(EuiBasicTable).prop('items');
|
||||
expect(rows).toHaveLength(1);
|
||||
expect(rows[0]).toMatchObject(analyticsCollections[0]);
|
||||
|
||||
expect(wrapper.dive().find(EuiLinkTo).first().prop('to')).toBe('/collections/example');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
|
||||
import { useValues } from 'kea';
|
||||
|
||||
import { EuiBasicTable, EuiBasicTableColumn } from '@elastic/eui';
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { AnalyticsCollection } from '../../../../../common/types/analytics';
|
||||
import { generateEncodedPath } from '../../../shared/encode_path_params';
|
||||
import { KibanaLogic } from '../../../shared/kibana';
|
||||
import { EuiLinkTo } from '../../../shared/react_router_helpers';
|
||||
|
||||
import { COLLECTION_VIEW_PATH } from '../../routes';
|
||||
|
||||
interface AnalyticsCollectionTableProps {
|
||||
collections: AnalyticsCollection[];
|
||||
isLoading: boolean;
|
||||
}
|
||||
|
||||
export const AnalyticsCollectionTable: React.FC<AnalyticsCollectionTableProps> = ({
|
||||
collections,
|
||||
isLoading,
|
||||
}) => {
|
||||
const { navigateToUrl } = useValues(KibanaLogic);
|
||||
|
||||
const columns: Array<EuiBasicTableColumn<AnalyticsCollection>> = [
|
||||
{
|
||||
field: 'name',
|
||||
name: 'Name',
|
||||
render: (name: string) => (
|
||||
<EuiLinkTo
|
||||
to={generateEncodedPath(COLLECTION_VIEW_PATH, {
|
||||
name,
|
||||
})}
|
||||
>
|
||||
{name}
|
||||
</EuiLinkTo>
|
||||
),
|
||||
width: '60%',
|
||||
},
|
||||
{
|
||||
actions: [
|
||||
{
|
||||
description: 'View this analytics collection',
|
||||
icon: 'eye',
|
||||
isPrimary: true,
|
||||
name: (collection) => `View ${collection.name}`,
|
||||
onClick: (collection) =>
|
||||
navigateToUrl(
|
||||
generateEncodedPath(COLLECTION_VIEW_PATH, {
|
||||
name: collection.name,
|
||||
})
|
||||
),
|
||||
type: 'icon',
|
||||
},
|
||||
],
|
||||
align: 'right',
|
||||
name: i18n.translate('xpack.enterpriseSearch.analytics.collections.actions.columnTitle', {
|
||||
defaultMessage: 'Actions',
|
||||
}),
|
||||
width: '40%',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<EuiBasicTable items={collections} columns={columns} tableLayout="fixed" loading={isLoading} />
|
||||
);
|
||||
};
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* 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 { LogicMounter, mockFlashMessageHelpers } from '../../../__mocks__/kea_logic';
|
||||
|
||||
import { nextTick } from '@kbn/test-jest-helpers';
|
||||
|
||||
import { HttpError, Status } from '../../../../../common/types/api';
|
||||
|
||||
import { AnalyticsCollectionsLogic } from './analytics_collections_logic';
|
||||
|
||||
describe('analyticsCollectionsLogic', () => {
|
||||
const { mount } = new LogicMounter(AnalyticsCollectionsLogic);
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
jest.useRealTimers();
|
||||
mount();
|
||||
});
|
||||
|
||||
const DEFAULT_VALUES = {
|
||||
analyticsCollections: [],
|
||||
data: undefined,
|
||||
hasNoAnalyticsCollections: false,
|
||||
isLoading: true,
|
||||
status: Status.IDLE,
|
||||
};
|
||||
|
||||
it('has expected default values', () => {
|
||||
expect(AnalyticsCollectionsLogic.values).toEqual(DEFAULT_VALUES);
|
||||
});
|
||||
|
||||
describe('reducers', () => {
|
||||
describe('hasNoAnalyticsCollections', () => {
|
||||
it('updates to true when apiSuccess returns empty analytics collections array', () => {
|
||||
AnalyticsCollectionsLogic.actions.apiSuccess([]);
|
||||
expect(AnalyticsCollectionsLogic.values.hasNoAnalyticsCollections).toBe(true);
|
||||
expect(AnalyticsCollectionsLogic.values).toEqual({
|
||||
...DEFAULT_VALUES,
|
||||
analyticsCollections: [],
|
||||
hasNoAnalyticsCollections: true,
|
||||
data: [],
|
||||
isLoading: false,
|
||||
status: Status.SUCCESS,
|
||||
});
|
||||
});
|
||||
|
||||
it('updates to false when apiSuccess returns analytics collections array', () => {
|
||||
const collections = [
|
||||
{ event_retention_day_length: 19, id: 'collection1', name: 'collection1' },
|
||||
];
|
||||
AnalyticsCollectionsLogic.actions.apiSuccess(collections);
|
||||
expect(AnalyticsCollectionsLogic.values.hasNoAnalyticsCollections).toBe(false);
|
||||
expect(AnalyticsCollectionsLogic.values).toEqual({
|
||||
...DEFAULT_VALUES,
|
||||
analyticsCollections: collections,
|
||||
data: collections,
|
||||
isLoading: false,
|
||||
status: Status.SUCCESS,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('listeners', () => {
|
||||
it('calls clearFlashMessages on new makeRequest', () => {
|
||||
AnalyticsCollectionsLogic.actions.makeRequest({});
|
||||
expect(mockFlashMessageHelpers.clearFlashMessages).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('calls flashAPIErrors on apiError', () => {
|
||||
AnalyticsCollectionsLogic.actions.apiError({} as HttpError);
|
||||
expect(mockFlashMessageHelpers.flashAPIErrors).toHaveBeenCalledTimes(1);
|
||||
expect(mockFlashMessageHelpers.flashAPIErrors).toHaveBeenCalledWith({});
|
||||
});
|
||||
|
||||
it('calls makeRequest on fetchAnalyticsCollections', async () => {
|
||||
jest.useFakeTimers();
|
||||
AnalyticsCollectionsLogic.actions.makeRequest = jest.fn();
|
||||
AnalyticsCollectionsLogic.actions.fetchAnalyticsCollections();
|
||||
jest.advanceTimersByTime(150);
|
||||
await nextTick();
|
||||
expect(AnalyticsCollectionsLogic.actions.makeRequest).toHaveBeenCalledWith({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('selectors', () => {
|
||||
describe('analyticsCollections', () => {
|
||||
it('updates when apiSuccess listener triggered', () => {
|
||||
AnalyticsCollectionsLogic.actions.apiSuccess([]);
|
||||
|
||||
expect(AnalyticsCollectionsLogic.values).toEqual({
|
||||
...DEFAULT_VALUES,
|
||||
analyticsCollections: [],
|
||||
data: [],
|
||||
hasNoAnalyticsCollections: true,
|
||||
isLoading: false,
|
||||
status: Status.SUCCESS,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* 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 { kea, MakeLogicType } from 'kea';
|
||||
|
||||
import { AnalyticsCollection } from '../../../../../common/types/analytics';
|
||||
import { HttpError, Status } from '../../../../../common/types/api';
|
||||
import { flashAPIErrors, clearFlashMessages } from '../../../shared/flash_messages';
|
||||
import { FetchAnalyticsCollectionsAPILogic } from '../../api/index/fetch_analytics_collections_api_logic';
|
||||
|
||||
export interface AnalyticsCollectionsActions {
|
||||
apiError(error: HttpError): HttpError;
|
||||
apiSuccess(collections: AnalyticsCollection[]): AnalyticsCollection[];
|
||||
fetchAnalyticsCollections(): void;
|
||||
makeRequest: typeof FetchAnalyticsCollectionsAPILogic.actions.makeRequest;
|
||||
}
|
||||
export interface AnalyticsCollectionsValues {
|
||||
analyticsCollections: AnalyticsCollection[];
|
||||
data: typeof FetchAnalyticsCollectionsAPILogic.values.data;
|
||||
hasNoAnalyticsCollections: boolean;
|
||||
isLoading: boolean;
|
||||
status: typeof FetchAnalyticsCollectionsAPILogic.values.status;
|
||||
}
|
||||
|
||||
export const AnalyticsCollectionsLogic = kea<
|
||||
MakeLogicType<AnalyticsCollectionsValues, AnalyticsCollectionsActions>
|
||||
>({
|
||||
actions: {
|
||||
fetchAnalyticsCollections: () => {},
|
||||
},
|
||||
connect: {
|
||||
actions: [FetchAnalyticsCollectionsAPILogic, ['makeRequest', 'apiSuccess', 'apiError']],
|
||||
values: [FetchAnalyticsCollectionsAPILogic, ['data', 'status']],
|
||||
},
|
||||
listeners: ({ actions }) => ({
|
||||
apiError: (e) => flashAPIErrors(e),
|
||||
fetchAnalyticsCollections: () => {
|
||||
actions.makeRequest({});
|
||||
},
|
||||
makeRequest: () => clearFlashMessages(),
|
||||
}),
|
||||
path: ['enterprise_search', 'analytics', 'collections'],
|
||||
selectors: ({ selectors }) => ({
|
||||
analyticsCollections: [() => [selectors.data], (data) => data || []],
|
||||
hasNoAnalyticsCollections: [() => [selectors.data], (data) => data?.length === 0],
|
||||
isLoading: [
|
||||
() => [selectors.status],
|
||||
(status) => [Status.LOADING, Status.IDLE].includes(status),
|
||||
],
|
||||
}),
|
||||
});
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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 '../../../__mocks__/shallow_useeffect.mock';
|
||||
|
||||
import { setMockValues, setMockActions } from '../../../__mocks__/kea_logic';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { AnalyticsCollection } from '../../../../../common/types/analytics';
|
||||
|
||||
import { AnalyticsCollectionTable } from './analytics_collection_table';
|
||||
|
||||
import { AnalyticsOverview } from './analytics_overview';
|
||||
|
||||
const mockValues = {
|
||||
analyticsCollections: [
|
||||
{
|
||||
event_retention_day_length: 180,
|
||||
id: '1',
|
||||
name: 'Analytics Collection 1',
|
||||
},
|
||||
] as AnalyticsCollection[],
|
||||
hasNoAnalyticsCollections: false,
|
||||
};
|
||||
|
||||
const mockActions = {
|
||||
fetchAnalyticsCollections: jest.fn(),
|
||||
};
|
||||
|
||||
describe('AnalyticsOverview', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('empty state', () => {
|
||||
it('renders when analytics collections are empty on inital query', () => {
|
||||
setMockValues({
|
||||
...mockValues,
|
||||
analyticsCollections: [],
|
||||
hasNoAnalyticsCollections: true,
|
||||
});
|
||||
setMockActions(mockActions);
|
||||
const wrapper = shallow(<AnalyticsOverview />);
|
||||
|
||||
expect(mockActions.fetchAnalyticsCollections).toHaveBeenCalled();
|
||||
|
||||
expect(wrapper.find(AnalyticsCollectionTable)).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('renders with Data', async () => {
|
||||
setMockValues(mockValues);
|
||||
setMockActions(mockActions);
|
||||
|
||||
const wrapper = shallow(<AnalyticsOverview />);
|
||||
|
||||
expect(wrapper.find(AnalyticsCollectionTable)).toHaveLength(1);
|
||||
expect(mockActions.fetchAnalyticsCollections).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* 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 React, { useEffect } from 'react';
|
||||
|
||||
import { useActions, useValues } from 'kea';
|
||||
|
||||
import { EuiEmptyPrompt, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiTitle } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { EuiButtonTo } from '../../../shared/react_router_helpers';
|
||||
import { COLLECTION_CREATION_PATH } from '../../routes';
|
||||
|
||||
import { EnterpriseSearchAnalyticsPageTemplate } from '../layout/page_template';
|
||||
|
||||
import { AnalyticsCollectionTable } from './analytics_collection_table';
|
||||
import { AnalyticsCollectionsLogic } from './analytics_collections_logic';
|
||||
|
||||
export const baseBreadcrumbs = [
|
||||
i18n.translate('xpack.enterpriseSearch.analytics.collections.breadcrumb', {
|
||||
defaultMessage: 'Analytics collections',
|
||||
}),
|
||||
];
|
||||
|
||||
export const AnalyticsOverview: React.FC = () => {
|
||||
const { fetchAnalyticsCollections } = useActions(AnalyticsCollectionsLogic);
|
||||
const { analyticsCollections, isLoading, hasNoAnalyticsCollections } =
|
||||
useValues(AnalyticsCollectionsLogic);
|
||||
|
||||
useEffect(() => {
|
||||
fetchAnalyticsCollections();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<EnterpriseSearchAnalyticsPageTemplate
|
||||
pageChrome={baseBreadcrumbs}
|
||||
restrictWidth
|
||||
isLoading={isLoading}
|
||||
pageViewTelemetry="Analytics Collections Overview"
|
||||
pageHeader={{
|
||||
description: i18n.translate(
|
||||
'xpack.enterpriseSearch.analytics.collections.pageDescription',
|
||||
{
|
||||
defaultMessage:
|
||||
'Dashboards and tools for visualizing end-user behavior and measuring the performance of your search applications. Track trends over time, identify and investigate anomalies, and make optimizations.',
|
||||
}
|
||||
),
|
||||
pageTitle: i18n.translate('xpack.enterpriseSearch.analytics.collections.pageTitle', {
|
||||
defaultMessage: 'Behaviorial Analytics',
|
||||
}),
|
||||
}}
|
||||
>
|
||||
{!hasNoAnalyticsCollections && (
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem>
|
||||
<EuiTitle>
|
||||
<h2>
|
||||
{i18n.translate('xpack.enterpriseSearch.analytics.collections.headingTitle', {
|
||||
defaultMessage: 'Collections',
|
||||
})}
|
||||
</h2>
|
||||
</EuiTitle>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonTo fill iconType="plusInCircle" to={COLLECTION_CREATION_PATH}>
|
||||
{i18n.translate('xpack.enterpriseSearch.analytics.collections.create.buttonTitle', {
|
||||
defaultMessage: 'Create new collection',
|
||||
})}
|
||||
</EuiButtonTo>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
)}
|
||||
|
||||
<EuiSpacer size="l" />
|
||||
{hasNoAnalyticsCollections ? (
|
||||
<EuiEmptyPrompt
|
||||
iconType="search"
|
||||
title={
|
||||
<h2>
|
||||
{i18n.translate(
|
||||
'xpack.enterpriseSearch.analytics.collections.emptyState.headingTitle',
|
||||
{
|
||||
defaultMessage: 'You dont have any collections yet',
|
||||
}
|
||||
)}
|
||||
</h2>
|
||||
}
|
||||
body={
|
||||
<p>
|
||||
{i18n.translate(
|
||||
'xpack.enterpriseSearch.analytics.collections.emptyState.subHeading',
|
||||
{
|
||||
defaultMessage:
|
||||
'An analytics collection provides a place to store the analytics events for any given search application you are building. Create a new collection to get started.',
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
}
|
||||
actions={[
|
||||
<EuiButtonTo fill iconType="plusInCircle" to={COLLECTION_CREATION_PATH}>
|
||||
{i18n.translate('xpack.enterpriseSearch.analytics.collections.create.buttonTitle', {
|
||||
defaultMessage: 'Create new collection',
|
||||
})}
|
||||
</EuiButtonTo>,
|
||||
]}
|
||||
/>
|
||||
) : (
|
||||
<AnalyticsCollectionTable collections={analyticsCollections} isLoading={isLoading} />
|
||||
)}
|
||||
</EnterpriseSearchAnalyticsPageTemplate>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
|
||||
jest.mock('../../../shared/layout/nav', () => ({
|
||||
useEnterpriseSearchNav: () => [],
|
||||
}));
|
||||
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { SetAnalyticsChrome } from '../../../shared/kibana_chrome';
|
||||
import { EnterpriseSearchPageTemplateWrapper } from '../../../shared/layout';
|
||||
import { SendEnterpriseSearchTelemetry } from '../../../shared/telemetry';
|
||||
|
||||
import { EnterpriseSearchAnalyticsPageTemplate } from './page_template';
|
||||
|
||||
describe('EnterpriseSearchAnalyticsPageTemplate', () => {
|
||||
it('renders', () => {
|
||||
const wrapper = shallow(
|
||||
<EnterpriseSearchAnalyticsPageTemplate>
|
||||
<div className="hello">world</div>
|
||||
</EnterpriseSearchAnalyticsPageTemplate>
|
||||
);
|
||||
|
||||
expect(wrapper.type()).toEqual(EnterpriseSearchPageTemplateWrapper);
|
||||
expect(wrapper.prop('solutionNav')).toEqual({ name: 'Enterprise Search', items: [] });
|
||||
expect(wrapper.find('.hello').text()).toEqual('world');
|
||||
});
|
||||
|
||||
describe('page chrome', () => {
|
||||
it('takes a breadcrumb array & renders a product-specific page chrome', () => {
|
||||
const wrapper = shallow(<EnterpriseSearchAnalyticsPageTemplate pageChrome={['Some page']} />);
|
||||
const setPageChrome = wrapper
|
||||
.find(EnterpriseSearchPageTemplateWrapper)
|
||||
.prop('setPageChrome') as any;
|
||||
|
||||
expect(setPageChrome.type).toEqual(SetAnalyticsChrome);
|
||||
expect(setPageChrome.props.trail).toEqual(['Some page']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('page telemetry', () => {
|
||||
it('takes a metric & renders product-specific telemetry viewed event', () => {
|
||||
const wrapper = shallow(
|
||||
<EnterpriseSearchAnalyticsPageTemplate pageViewTelemetry="some_page" />
|
||||
);
|
||||
|
||||
expect(wrapper.find(SendEnterpriseSearchTelemetry).prop('action')).toEqual('viewed');
|
||||
expect(wrapper.find(SendEnterpriseSearchTelemetry).prop('metric')).toEqual('some_page');
|
||||
});
|
||||
});
|
||||
|
||||
describe('props', () => {
|
||||
it('passes down any ...pageTemplateProps that EnterpriseSearchPageTemplateWrapper accepts', () => {
|
||||
const wrapper = shallow(
|
||||
<EnterpriseSearchAnalyticsPageTemplate
|
||||
pageHeader={{ pageTitle: 'hello world' }}
|
||||
isLoading={false}
|
||||
emptyState={<div />}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(
|
||||
wrapper.find(EnterpriseSearchPageTemplateWrapper).prop('pageHeader')!.pageTitle
|
||||
).toEqual('hello world');
|
||||
expect(wrapper.find(EnterpriseSearchPageTemplateWrapper).prop('isLoading')).toEqual(false);
|
||||
expect(wrapper.find(EnterpriseSearchPageTemplateWrapper).prop('emptyState')).toEqual(<div />);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
|
||||
import { ENTERPRISE_SEARCH_CONTENT_PLUGIN } from '../../../../../common/constants';
|
||||
import { SetAnalyticsChrome } from '../../../shared/kibana_chrome';
|
||||
import {
|
||||
EnterpriseSearchPageTemplateWrapper,
|
||||
PageTemplateProps,
|
||||
useEnterpriseSearchNav,
|
||||
} from '../../../shared/layout';
|
||||
import { SendEnterpriseSearchTelemetry } from '../../../shared/telemetry';
|
||||
|
||||
export const EnterpriseSearchAnalyticsPageTemplate: React.FC<PageTemplateProps> = ({
|
||||
children,
|
||||
pageChrome,
|
||||
pageViewTelemetry,
|
||||
...pageTemplateProps
|
||||
}) => {
|
||||
return (
|
||||
<EnterpriseSearchPageTemplateWrapper
|
||||
{...pageTemplateProps}
|
||||
solutionNav={{
|
||||
items: useEnterpriseSearchNav(),
|
||||
name: ENTERPRISE_SEARCH_CONTENT_PLUGIN.NAME,
|
||||
}}
|
||||
setPageChrome={pageChrome && <SetAnalyticsChrome trail={pageChrome} />}
|
||||
>
|
||||
{pageViewTelemetry && (
|
||||
<SendEnterpriseSearchTelemetry action="viewed" metric={pageViewTelemetry} />
|
||||
)}
|
||||
{children}
|
||||
</EnterpriseSearchPageTemplateWrapper>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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 '../../../common/__mocks__';
|
||||
import '../__mocks__/kea_logic';
|
||||
import '../__mocks__/shallow_useeffect.mock';
|
||||
import '../__mocks__/enterprise_search_url.mock';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { VersionMismatchPage } from '../shared/version_mismatch';
|
||||
|
||||
import { AnalyticsOverview } from './components/analytics_overview/analytics_overview';
|
||||
|
||||
import { Analytics } from '.';
|
||||
|
||||
describe('EnterpriseSearchAnalytics', () => {
|
||||
it('always renders the overview', () => {
|
||||
const wrapper = shallow(<Analytics />);
|
||||
|
||||
expect(wrapper.find(AnalyticsOverview)).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('renders VersionMismatchPage when there are mismatching versions', () => {
|
||||
const wrapper = shallow(<Analytics enterpriseSearchVersion="7.15.0" kibanaVersion="7.16.0" />);
|
||||
|
||||
expect(wrapper.find(VersionMismatchPage)).toHaveLength(1);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
import { Route, Switch } from 'react-router-dom';
|
||||
|
||||
import { isVersionMismatch } from '../../../common/is_version_mismatch';
|
||||
import { InitialAppData } from '../../../common/types';
|
||||
import { VersionMismatchPage } from '../shared/version_mismatch';
|
||||
|
||||
import { AnalyticsOverview } from './components/analytics_overview/analytics_overview';
|
||||
|
||||
import { ROOT_PATH } from './routes';
|
||||
|
||||
export const Analytics: React.FC<InitialAppData> = (props) => {
|
||||
const { enterpriseSearchVersion, kibanaVersion } = props;
|
||||
const incompatibleVersions = isVersionMismatch(enterpriseSearchVersion, kibanaVersion);
|
||||
|
||||
return (
|
||||
<Switch>
|
||||
<Route exact path={ROOT_PATH}>
|
||||
{incompatibleVersions ? (
|
||||
<VersionMismatchPage
|
||||
enterpriseSearchVersion={enterpriseSearchVersion}
|
||||
kibanaVersion={kibanaVersion}
|
||||
/>
|
||||
) : (
|
||||
<AnalyticsOverview />
|
||||
)}
|
||||
</Route>
|
||||
</Switch>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export const ROOT_PATH = '/';
|
||||
export const COLLECTIONS_PATH = '/collections';
|
||||
export const COLLECTION_CREATION_PATH = `${COLLECTIONS_PATH}/new`;
|
||||
export const COLLECTION_VIEW_PATH = `${COLLECTIONS_PATH}/:name`;
|
|
@ -11,6 +11,7 @@ import { EuiBreadcrumb } from '@elastic/eui';
|
|||
|
||||
import {
|
||||
ENTERPRISE_SEARCH_OVERVIEW_PLUGIN,
|
||||
ANALYTICS_PLUGIN,
|
||||
APP_SEARCH_PLUGIN,
|
||||
WORKPLACE_SEARCH_PLUGIN,
|
||||
ENTERPRISE_SEARCH_CONTENT_PLUGIN,
|
||||
|
@ -105,6 +106,9 @@ export const useEnterpriseSearchBreadcrumbs = (breadcrumbs: Breadcrumbs = []) =>
|
|||
...breadcrumbs,
|
||||
]);
|
||||
|
||||
export const useAnalyticsBreadcrumbs = (breadcrumbs: Breadcrumbs = []) =>
|
||||
useEnterpriseSearchBreadcrumbs([{ text: ANALYTICS_PLUGIN.NAME, path: '/' }, ...breadcrumbs]);
|
||||
|
||||
export const useElasticsearchBreadcrumbs = (breadcrumbs: Breadcrumbs = []) =>
|
||||
useEnterpriseSearchBreadcrumbs([
|
||||
{ text: 'Getting started with Elasticsearch', path: '/' },
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import {
|
||||
ENTERPRISE_SEARCH_OVERVIEW_PLUGIN,
|
||||
ANALYTICS_PLUGIN,
|
||||
APP_SEARCH_PLUGIN,
|
||||
WORKPLACE_SEARCH_PLUGIN,
|
||||
} from '../../../../common/constants';
|
||||
|
@ -32,6 +33,8 @@ export const generateTitle = (pages: Title) => pages.join(' - ');
|
|||
export const enterpriseSearchTitle = (page: Title = []) =>
|
||||
generateTitle([...page, ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.NAME]);
|
||||
|
||||
export const analyticsTitle = (page: Title = []) => generateTitle([...page, ANALYTICS_PLUGIN.NAME]);
|
||||
|
||||
export const elasticsearchTitle = (page: Title = []) =>
|
||||
generateTitle([...page, 'Getting started with Elasticsearch']);
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
export {
|
||||
SetEnterpriseSearchChrome,
|
||||
SetAnalyticsChrome,
|
||||
SetEnterpriseSearchContentChrome,
|
||||
SetElasticsearchChrome,
|
||||
SetAppSearchChrome,
|
||||
|
|
|
@ -14,6 +14,7 @@ import { KibanaLogic } from '../kibana';
|
|||
import {
|
||||
useGenerateBreadcrumbs,
|
||||
useEnterpriseSearchBreadcrumbs,
|
||||
useAnalyticsBreadcrumbs,
|
||||
useEnterpriseSearchContentBreadcrumbs,
|
||||
useElasticsearchBreadcrumbs,
|
||||
useAppSearchBreadcrumbs,
|
||||
|
@ -22,6 +23,7 @@ import {
|
|||
} from './generate_breadcrumbs';
|
||||
import {
|
||||
enterpriseSearchTitle,
|
||||
analyticsTitle,
|
||||
elasticsearchTitle,
|
||||
appSearchTitle,
|
||||
workplaceSearchTitle,
|
||||
|
@ -63,6 +65,23 @@ export const SetEnterpriseSearchChrome: React.FC<SetChromeProps> = ({ trail = []
|
|||
return null;
|
||||
};
|
||||
|
||||
export const SetAnalyticsChrome: React.FC<SetChromeProps> = ({ trail = [] }) => {
|
||||
const { setBreadcrumbs, setDocTitle } = useValues(KibanaLogic);
|
||||
|
||||
const title = reverseArray(trail);
|
||||
const docTitle = analyticsTitle(title);
|
||||
|
||||
const crumbs = useGenerateBreadcrumbs(trail);
|
||||
const breadcrumbs = useAnalyticsBreadcrumbs(crumbs);
|
||||
|
||||
useEffect(() => {
|
||||
setBreadcrumbs(breadcrumbs);
|
||||
setDocTitle(docTitle);
|
||||
}, [trail]);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export const SetElasticsearchChrome: React.FC<SetChromeProps> = ({ trail = [] }) => {
|
||||
const { setBreadcrumbs, setDocTitle } = useValues(KibanaLogic);
|
||||
|
||||
|
|
|
@ -44,6 +44,17 @@ describe('useEnterpriseSearchContentNav', () => {
|
|||
],
|
||||
name: 'Content',
|
||||
},
|
||||
{
|
||||
id: 'enterpriseSearchAnalytics',
|
||||
name: 'Analytics',
|
||||
items: [
|
||||
{
|
||||
href: '/app/enterprise_search/analytics',
|
||||
id: 'analytics_collections',
|
||||
name: 'Collections',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'search',
|
||||
items: [
|
||||
|
@ -76,7 +87,7 @@ describe('useEnterpriseSearchContentNav', () => {
|
|||
|
||||
setMockValues({ productAccess: noProductAccess });
|
||||
|
||||
expect(useEnterpriseSearchNav()[2]).toEqual({
|
||||
expect(useEnterpriseSearchNav()[3]).toEqual({
|
||||
id: 'search',
|
||||
items: [
|
||||
{
|
||||
|
@ -97,7 +108,7 @@ describe('useEnterpriseSearchContentNav', () => {
|
|||
|
||||
setMockValues({ productAccess: workplaceSearchProductAccess });
|
||||
|
||||
expect(useEnterpriseSearchNav()[2]).toEqual({
|
||||
expect(useEnterpriseSearchNav()[3]).toEqual({
|
||||
id: 'search',
|
||||
items: [
|
||||
{
|
||||
|
@ -123,7 +134,7 @@ describe('useEnterpriseSearchContentNav', () => {
|
|||
|
||||
setMockValues({ productAccess: appSearchProductAccess });
|
||||
|
||||
expect(useEnterpriseSearchNav()[2]).toEqual({
|
||||
expect(useEnterpriseSearchNav()[3]).toEqual({
|
||||
id: 'search',
|
||||
items: [
|
||||
{
|
||||
|
|
|
@ -11,6 +11,7 @@ import { EuiSideNavItemType } from '@elastic/eui';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import {
|
||||
ANALYTICS_PLUGIN,
|
||||
APP_SEARCH_PLUGIN,
|
||||
ELASTICSEARCH_PLUGIN,
|
||||
ENTERPRISE_SEARCH_CONTENT_PLUGIN,
|
||||
|
@ -55,6 +56,25 @@ export const useEnterpriseSearchNav = () => {
|
|||
defaultMessage: 'Content',
|
||||
}),
|
||||
},
|
||||
{
|
||||
id: 'enterpriseSearchAnalytics',
|
||||
items: [
|
||||
{
|
||||
id: 'analytics_collections',
|
||||
name: i18n.translate('xpack.enterpriseSearch.nav.analyticsCollectionsTitle', {
|
||||
defaultMessage: 'Collections',
|
||||
}),
|
||||
...generateNavLink({
|
||||
shouldNotCreateHref: true,
|
||||
shouldShowActiveForSubroutes: true,
|
||||
to: ANALYTICS_PLUGIN.URL,
|
||||
}),
|
||||
},
|
||||
],
|
||||
name: i18n.translate('xpack.enterpriseSearch.nav.analyticsTitle', {
|
||||
defaultMessage: 'Analytics',
|
||||
}),
|
||||
},
|
||||
{
|
||||
id: 'search',
|
||||
items: [
|
||||
|
|
|
@ -22,6 +22,7 @@ import { LicensingPluginStart } from '@kbn/licensing-plugin/public';
|
|||
import { SecurityPluginSetup, SecurityPluginStart } from '@kbn/security-plugin/public';
|
||||
|
||||
import {
|
||||
ANALYTICS_PLUGIN,
|
||||
APP_SEARCH_PLUGIN,
|
||||
ELASTICSEARCH_PLUGIN,
|
||||
ENTERPRISE_SEARCH_CONTENT_PLUGIN,
|
||||
|
@ -113,6 +114,27 @@ export class EnterpriseSearchPlugin implements Plugin {
|
|||
},
|
||||
});
|
||||
|
||||
core.application.register({
|
||||
id: ANALYTICS_PLUGIN.ID,
|
||||
title: ANALYTICS_PLUGIN.NAME,
|
||||
euiIconType: ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.LOGO,
|
||||
appRoute: ANALYTICS_PLUGIN.URL,
|
||||
category: DEFAULT_APP_CATEGORIES.enterpriseSearch,
|
||||
mount: async (params: AppMountParameters) => {
|
||||
const kibanaDeps = await this.getKibanaDeps(core, params, cloud);
|
||||
const { chrome, http } = kibanaDeps.core;
|
||||
chrome.docTitle.change(ANALYTICS_PLUGIN.NAME);
|
||||
|
||||
await this.getInitialData(http);
|
||||
const pluginData = this.getPluginData();
|
||||
|
||||
const { renderApp } = await import('./applications');
|
||||
const { Analytics } = await import('./applications/analytics');
|
||||
|
||||
return renderApp(Analytics, kibanaDeps, pluginData);
|
||||
},
|
||||
});
|
||||
|
||||
core.application.register({
|
||||
id: ELASTICSEARCH_PLUGIN.ID,
|
||||
title: ELASTICSEARCH_PLUGIN.NAME,
|
||||
|
@ -189,6 +211,16 @@ export class EnterpriseSearchPlugin implements Plugin {
|
|||
order: 100,
|
||||
});
|
||||
|
||||
plugins.home.featureCatalogue.register({
|
||||
id: ANALYTICS_PLUGIN.ID,
|
||||
title: ANALYTICS_PLUGIN.NAME,
|
||||
icon: 'appAnalytics',
|
||||
description: ANALYTICS_PLUGIN.DESCRIPTION,
|
||||
path: ANALYTICS_PLUGIN.URL,
|
||||
category: 'data',
|
||||
showOnHomePage: false,
|
||||
});
|
||||
|
||||
plugins.home.featureCatalogue.register({
|
||||
id: APP_SEARCH_PLUGIN.ID,
|
||||
title: APP_SEARCH_PLUGIN.NAME,
|
||||
|
|
|
@ -26,6 +26,7 @@ import {
|
|||
ENTERPRISE_SEARCH_OVERVIEW_PLUGIN,
|
||||
ENTERPRISE_SEARCH_CONTENT_PLUGIN,
|
||||
ELASTICSEARCH_PLUGIN,
|
||||
ANALYTICS_PLUGIN,
|
||||
APP_SEARCH_PLUGIN,
|
||||
WORKPLACE_SEARCH_PLUGIN,
|
||||
ENTERPRISE_SEARCH_RELEVANCE_LOGS_SOURCE_ID,
|
||||
|
@ -100,6 +101,7 @@ export class EnterpriseSearchPlugin implements Plugin {
|
|||
ENTERPRISE_SEARCH_OVERVIEW_PLUGIN.ID,
|
||||
ENTERPRISE_SEARCH_CONTENT_PLUGIN.ID,
|
||||
ELASTICSEARCH_PLUGIN.ID,
|
||||
ANALYTICS_PLUGIN.ID,
|
||||
APP_SEARCH_PLUGIN.ID,
|
||||
WORKPLACE_SEARCH_PLUGIN.ID,
|
||||
];
|
||||
|
@ -141,6 +143,7 @@ export class EnterpriseSearchPlugin implements Plugin {
|
|||
navLinks: {
|
||||
enterpriseSearch: showEnterpriseSearch,
|
||||
enterpriseSearchContent: showEnterpriseSearch,
|
||||
enterpriseSearchAnalytics: showEnterpriseSearch,
|
||||
elasticsearch: showEnterpriseSearch,
|
||||
appSearch: hasAppSearchAccess,
|
||||
workplaceSearch: hasWorkplaceSearchAccess,
|
||||
|
@ -148,6 +151,7 @@ export class EnterpriseSearchPlugin implements Plugin {
|
|||
catalogue: {
|
||||
enterpriseSearch: showEnterpriseSearch,
|
||||
enterpriseSearchContent: showEnterpriseSearch,
|
||||
enterpriseSearchAnalytics: showEnterpriseSearch,
|
||||
elasticsearch: showEnterpriseSearch,
|
||||
appSearch: hasAppSearchAccess,
|
||||
workplaceSearch: hasWorkplaceSearchAccess,
|
||||
|
|
|
@ -64,6 +64,7 @@ export default function catalogueTests({ getService }: FtrProviderContext) {
|
|||
'monitoring',
|
||||
'enterpriseSearch',
|
||||
'enterpriseSearchContent',
|
||||
'enterpriseSearchAnalytics',
|
||||
'elasticsearch',
|
||||
'appSearch',
|
||||
'workplaceSearch',
|
||||
|
@ -89,6 +90,7 @@ export default function catalogueTests({ getService }: FtrProviderContext) {
|
|||
'monitoring',
|
||||
'enterpriseSearch',
|
||||
'enterpriseSearchContent',
|
||||
'enterpriseSearchAnalytics',
|
||||
'elasticsearch',
|
||||
'appSearch',
|
||||
'workplaceSearch',
|
||||
|
|
|
@ -54,6 +54,7 @@ export default function navLinksTests({ getService }: FtrProviderContext) {
|
|||
'monitoring',
|
||||
'enterpriseSearch',
|
||||
'enterpriseSearchContent',
|
||||
'enterpriseSearchAnalytics',
|
||||
'appSearch',
|
||||
'workplaceSearch'
|
||||
)
|
||||
|
|
|
@ -28,6 +28,7 @@ export default function catalogueTests({ getService }: FtrProviderContext) {
|
|||
// enterprise_search plugin is loaded but disabled because security isn't enabled in ES. That means the following capabilities are disabled
|
||||
'enterpriseSearch',
|
||||
'enterpriseSearchContent',
|
||||
'enterpriseSearchAnalytics',
|
||||
'elasticsearch',
|
||||
'appSearch',
|
||||
'workplaceSearch',
|
||||
|
|
|
@ -20,6 +20,7 @@ export default function navLinksTests({ getService }: FtrProviderContext) {
|
|||
// enterprise_search plugin is loaded but disabled because security isn't enabled in ES. That means the following capabilities are disabled
|
||||
'enterpriseSearch',
|
||||
'enterpriseSearchContent',
|
||||
'enterpriseSearchAnalytics',
|
||||
'appSearch',
|
||||
'workplaceSearch',
|
||||
];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue