mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 18:51:07 -04:00
[Serverless Elasticsearch] Fix user is blocked from moving forward when opening Discover, Dashboard, or Visualize Library
This commit is contained in:
parent
84b683bd7a
commit
243142d9c1
52 changed files with 496 additions and 56 deletions
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
|
@ -517,6 +517,7 @@ x-pack/plugins/monitoring @elastic/infra-monitoring-ui
|
|||
src/plugins/navigation @elastic/appex-sharedux
|
||||
src/plugins/newsfeed @elastic/kibana-core
|
||||
test/common/plugins/newsfeed @elastic/kibana-core
|
||||
src/plugins/no_data_page @elastic/appex-sharedux
|
||||
x-pack/plugins/notifications @elastic/appex-sharedux
|
||||
packages/kbn-object-versioning @elastic/appex-sharedux
|
||||
x-pack/plugins/observability_ai_assistant @elastic/obs-ai-assistant
|
||||
|
|
|
@ -32,3 +32,6 @@ telemetry.labels.serverless: search
|
|||
|
||||
# Alerts config
|
||||
xpack.actions.enabledActionTypes: ['.email', '.index', '.slack', '.jira', '.webhook', '.teams']
|
||||
|
||||
# Customize empty page state for analytics apps
|
||||
no_data_page.analyticsNoDataPageFlavor: 'serverless_search'
|
||||
|
|
|
@ -254,6 +254,10 @@ It also provides a stateful version of it on the start contract.
|
|||
Content is fetched from the remote (https://feeds.elastic.co) once a day, with periodic checks if the content needs to be refreshed. All newsfeed content is hosted remotely.
|
||||
|
||||
|
||||
|{kib-repo}blob/{branch}/src/plugins/no_data_page/README.md[noDataPage]
|
||||
|Helps to globally configure the no data page components
|
||||
|
||||
|
||||
|{kib-repo}blob/{branch}/src/plugins/presentation_util/README.mdx[presentationUtil]
|
||||
|The Presentation Utility Plugin is a set of common, shared components and toolkits for solutions within the Presentation space, (e.g. Dashboards, Canvas).
|
||||
|
||||
|
|
|
@ -535,6 +535,7 @@
|
|||
"@kbn/navigation-plugin": "link:src/plugins/navigation",
|
||||
"@kbn/newsfeed-plugin": "link:src/plugins/newsfeed",
|
||||
"@kbn/newsfeed-test-plugin": "link:test/common/plugins/newsfeed",
|
||||
"@kbn/no-data-page-plugin": "link:src/plugins/no_data_page",
|
||||
"@kbn/notifications-plugin": "link:x-pack/plugins/notifications",
|
||||
"@kbn/object-versioning": "link:packages/kbn-object-versioning",
|
||||
"@kbn/observability-ai-assistant-plugin": "link:x-pack/plugins/observability_ai_assistant",
|
||||
|
|
|
@ -96,6 +96,7 @@ pageLoadAssetSize:
|
|||
monitoring: 80000
|
||||
navigation: 37269
|
||||
newsfeed: 42228
|
||||
noDataPage: 5000
|
||||
observability: 115443
|
||||
observabilityAIAssistant: 25000
|
||||
observabilityOnboarding: 19573
|
||||
|
|
|
@ -35,7 +35,9 @@ export const NoDataCard = ({ href: srcHref, category, description, ...props }: P
|
|||
|
||||
return (
|
||||
<RedirectAppLinksContainer>
|
||||
<Component {...{ ...props, href, canAccessFleet, description }} />
|
||||
<Component
|
||||
{...{ ...props, href, canAccessFleet: props.canAccessFleet ?? canAccessFleet, description }}
|
||||
/>
|
||||
</RedirectAppLinksContainer>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -79,4 +79,4 @@ export type NoDataCardComponentProps = Partial<
|
|||
/**
|
||||
* Props for the `NoDataCard` sevice-connected component.
|
||||
*/
|
||||
export type NoDataCardProps = Omit<NoDataCardComponentProps, 'canAccessFleet'>;
|
||||
export type NoDataCardProps = NoDataCardComponentProps;
|
||||
|
|
|
@ -10,7 +10,10 @@ import React from 'react';
|
|||
import { act } from 'react-dom/test-utils';
|
||||
|
||||
import { mountWithIntl } from '@kbn/test-jest-helpers';
|
||||
import { I18nProvider } from '@kbn/i18n-react';
|
||||
|
||||
import { KibanaNoDataPage } from '@kbn/shared-ux-page-kibana-no-data';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
|
||||
import { AnalyticsNoDataPage } from './analytics_no_data_page.component';
|
||||
import { AnalyticsNoDataPageProvider } from './services';
|
||||
|
@ -28,6 +31,7 @@ describe('AnalyticsNoDataPageComponent', () => {
|
|||
onDataViewCreated={onDataViewCreated}
|
||||
kibanaGuideDocLink={'http://www.test.com'}
|
||||
showPlainSpinner={false}
|
||||
prependBasePath={(path: string) => path}
|
||||
/>
|
||||
</AnalyticsNoDataPageProvider>
|
||||
);
|
||||
|
@ -52,6 +56,7 @@ describe('AnalyticsNoDataPageComponent', () => {
|
|||
kibanaGuideDocLink={'http://www.test.com'}
|
||||
allowAdHocDataView={true}
|
||||
showPlainSpinner={false}
|
||||
prependBasePath={(path: string) => path}
|
||||
/>
|
||||
</AnalyticsNoDataPageProvider>
|
||||
);
|
||||
|
@ -61,4 +66,86 @@ describe('AnalyticsNoDataPageComponent', () => {
|
|||
expect(component.find(KibanaNoDataPage).length).toBe(1);
|
||||
expect(component.find(KibanaNoDataPage).props().allowAdHocDataView).toBe(true);
|
||||
});
|
||||
|
||||
describe('no data state', () => {
|
||||
describe('kibana flavor', () => {
|
||||
it('renders add integrations card', async () => {
|
||||
render(
|
||||
<I18nProvider>
|
||||
<AnalyticsNoDataPageProvider {...{ ...services, hasESData: async () => false }}>
|
||||
<AnalyticsNoDataPage
|
||||
onDataViewCreated={onDataViewCreated}
|
||||
kibanaGuideDocLink={'http://www.test.com'}
|
||||
showPlainSpinner={false}
|
||||
prependBasePath={(path: string) => path}
|
||||
/>
|
||||
</AnalyticsNoDataPageProvider>
|
||||
</I18nProvider>
|
||||
);
|
||||
|
||||
await screen.findByTestId('kbnOverviewAddIntegrations');
|
||||
await screen.getAllByText('Add integrations');
|
||||
});
|
||||
|
||||
it('renders disabled add integrations card when fleet is not available', async () => {
|
||||
render(
|
||||
<I18nProvider>
|
||||
<AnalyticsNoDataPageProvider
|
||||
{...{ ...services, hasESData: async () => false, canAccessFleet: false }}
|
||||
>
|
||||
<AnalyticsNoDataPage
|
||||
onDataViewCreated={onDataViewCreated}
|
||||
kibanaGuideDocLink={'http://www.test.com'}
|
||||
showPlainSpinner={false}
|
||||
prependBasePath={(path: string) => path}
|
||||
/>
|
||||
</AnalyticsNoDataPageProvider>
|
||||
</I18nProvider>
|
||||
);
|
||||
|
||||
await screen.findByTestId('kbnOverviewAddIntegrations');
|
||||
await screen.getByText('Contact your administrator');
|
||||
});
|
||||
});
|
||||
|
||||
describe('serverless_search flavor', () => {
|
||||
it('renders getting started card', async () => {
|
||||
render(
|
||||
<I18nProvider>
|
||||
<AnalyticsNoDataPageProvider {...{ ...services, hasESData: async () => false }}>
|
||||
<AnalyticsNoDataPage
|
||||
pageFlavor={'serverless_search'}
|
||||
onDataViewCreated={onDataViewCreated}
|
||||
kibanaGuideDocLink={'http://www.test.com'}
|
||||
showPlainSpinner={false}
|
||||
prependBasePath={(path: string) => path}
|
||||
/>
|
||||
</AnalyticsNoDataPageProvider>
|
||||
</I18nProvider>
|
||||
);
|
||||
|
||||
await screen.findByTestId('kbnOverviewElasticsearchGettingStarted');
|
||||
});
|
||||
|
||||
it('renders the same getting started card when fleet is not available', async () => {
|
||||
render(
|
||||
<I18nProvider>
|
||||
<AnalyticsNoDataPageProvider
|
||||
{...{ ...services, hasESData: async () => false, canAccessFleet: false }}
|
||||
>
|
||||
<AnalyticsNoDataPage
|
||||
onDataViewCreated={onDataViewCreated}
|
||||
kibanaGuideDocLink={'http://www.test.com'}
|
||||
showPlainSpinner={false}
|
||||
prependBasePath={(path: string) => path}
|
||||
pageFlavor={'serverless_search'}
|
||||
/>
|
||||
</AnalyticsNoDataPageProvider>
|
||||
</I18nProvider>
|
||||
);
|
||||
|
||||
await screen.findByTestId('kbnOverviewElasticsearchGettingStarted');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
import React from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { KibanaNoDataPage } from '@kbn/shared-ux-page-kibana-no-data';
|
||||
import { KibanaNoDataPageProps } from '@kbn/shared-ux-page-kibana-no-data-types';
|
||||
import { AnalyticsNoDataPageFlavor } from '@kbn/shared-ux-page-analytics-no-data-types';
|
||||
|
||||
/**
|
||||
* Props for the pure component.
|
||||
|
@ -21,26 +23,63 @@ export interface Props {
|
|||
allowAdHocDataView?: boolean;
|
||||
/** if the kibana instance is customly branded */
|
||||
showPlainSpinner: boolean;
|
||||
/** The flavor of the empty page to use. */
|
||||
pageFlavor?: AnalyticsNoDataPageFlavor;
|
||||
prependBasePath: (path: string) => string;
|
||||
}
|
||||
|
||||
const solution = i18n.translate('sharedUXPackages.noDataConfig.analytics', {
|
||||
defaultMessage: 'Analytics',
|
||||
});
|
||||
|
||||
const pageTitle = i18n.translate('sharedUXPackages.noDataConfig.analyticsPageTitle', {
|
||||
defaultMessage: 'Welcome to Analytics!',
|
||||
});
|
||||
|
||||
const addIntegrationsTitle = i18n.translate('sharedUXPackages.noDataConfig.addIntegrationsTitle', {
|
||||
defaultMessage: 'Add integrations',
|
||||
});
|
||||
|
||||
const addIntegrationsDescription = i18n.translate(
|
||||
'sharedUXPackages.noDataConfig.addIntegrationsDescription',
|
||||
{
|
||||
defaultMessage: 'Use Elastic Agent to collect data and build out Analytics solutions.',
|
||||
}
|
||||
);
|
||||
const flavors: {
|
||||
[K in AnalyticsNoDataPageFlavor]: (deps: {
|
||||
kibanaGuideDocLink: string;
|
||||
prependBasePath: (path: string) => string;
|
||||
}) => KibanaNoDataPageProps['noDataConfig'];
|
||||
} = {
|
||||
kibana: ({ kibanaGuideDocLink }) => ({
|
||||
solution: i18n.translate('sharedUXPackages.noDataConfig.analytics', {
|
||||
defaultMessage: 'Analytics',
|
||||
}),
|
||||
pageTitle: i18n.translate('sharedUXPackages.noDataConfig.analyticsPageTitle', {
|
||||
defaultMessage: 'Welcome to Analytics!',
|
||||
}),
|
||||
logo: 'logoKibana',
|
||||
action: {
|
||||
elasticAgent: {
|
||||
title: i18n.translate('sharedUXPackages.noDataConfig.addIntegrationsTitle', {
|
||||
defaultMessage: 'Add integrations',
|
||||
}),
|
||||
description: i18n.translate('sharedUXPackages.noDataConfig.addIntegrationsDescription', {
|
||||
defaultMessage: 'Use Elastic Agent to collect data and build out Analytics solutions.',
|
||||
}),
|
||||
'data-test-subj': 'kbnOverviewAddIntegrations',
|
||||
},
|
||||
},
|
||||
docsLink: kibanaGuideDocLink,
|
||||
}),
|
||||
serverless_search: ({ prependBasePath }) => ({
|
||||
solution: i18n.translate('sharedUXPackages.noDataConfig.elasticsearch', {
|
||||
defaultMessage: 'Elasticsearch',
|
||||
}),
|
||||
pageTitle: i18n.translate('sharedUXPackages.noDataConfig.elasticsearchPageTitle', {
|
||||
defaultMessage: 'Welcome to Elasticsearch!',
|
||||
}),
|
||||
logo: 'logoElasticsearch',
|
||||
action: {
|
||||
elasticsearch: {
|
||||
title: i18n.translate('sharedUXPackages.noDataConfig.elasticsearchTitle', {
|
||||
defaultMessage: 'Get started',
|
||||
}),
|
||||
description: i18n.translate('sharedUXPackages.noDataConfig.elasticsearchDescription', {
|
||||
defaultMessage:
|
||||
'Set up your programming language client, ingest some data, and start searching.',
|
||||
}),
|
||||
'data-test-subj': 'kbnOverviewElasticsearchGettingStarted',
|
||||
href: prependBasePath('/app/elasticsearch/'),
|
||||
/** force the no data card to be shown **/
|
||||
canAccessFleet: true,
|
||||
},
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
/**
|
||||
* A pure component of an entire page that can be displayed when Kibana "has no data", specifically for Analytics.
|
||||
|
@ -50,20 +89,13 @@ export const AnalyticsNoDataPage = ({
|
|||
onDataViewCreated,
|
||||
allowAdHocDataView,
|
||||
showPlainSpinner,
|
||||
prependBasePath,
|
||||
pageFlavor = 'kibana',
|
||||
}: Props) => {
|
||||
const noDataConfig = {
|
||||
solution,
|
||||
pageTitle,
|
||||
logo: 'logoKibana',
|
||||
action: {
|
||||
elasticAgent: {
|
||||
title: addIntegrationsTitle,
|
||||
description: addIntegrationsDescription,
|
||||
'data-test-subj': 'kbnOverviewAddIntegrations',
|
||||
},
|
||||
},
|
||||
docsLink: kibanaGuideDocLink,
|
||||
};
|
||||
const noDataConfig: KibanaNoDataPageProps['noDataConfig'] = flavors[pageFlavor]({
|
||||
kibanaGuideDocLink,
|
||||
prependBasePath,
|
||||
});
|
||||
|
||||
return (
|
||||
<KibanaNoDataPage
|
||||
|
|
|
@ -41,6 +41,8 @@ describe('AnalyticsNoDataPage', () => {
|
|||
expect(component.find(Component).props().kibanaGuideDocLink).toBe(services.kibanaGuideDocLink);
|
||||
expect(component.find(Component).props().onDataViewCreated).toBe(onDataViewCreated);
|
||||
expect(component.find(Component).props().allowAdHocDataView).toBe(true);
|
||||
expect(component.find(Component).props().prependBasePath).toBe(services.prependBasePath);
|
||||
expect(component.find(Component).props().pageFlavor).toBe(services.pageFlavor);
|
||||
});
|
||||
|
||||
it('passes correct boolean value to showPlainSpinner', () => {
|
||||
|
|
|
@ -21,7 +21,7 @@ export const AnalyticsNoDataPage = ({
|
|||
allowAdHocDataView,
|
||||
}: AnalyticsNoDataPageProps) => {
|
||||
const services = useServices();
|
||||
const { kibanaGuideDocLink, customBranding } = services;
|
||||
const { kibanaGuideDocLink, customBranding, prependBasePath, pageFlavor } = services;
|
||||
const { hasCustomBranding$ } = customBranding;
|
||||
const showPlainSpinner = useObservable(hasCustomBranding$) ?? false;
|
||||
|
||||
|
@ -32,6 +32,8 @@ export const AnalyticsNoDataPage = ({
|
|||
allowAdHocDataView,
|
||||
kibanaGuideDocLink,
|
||||
showPlainSpinner,
|
||||
prependBasePath,
|
||||
pageFlavor,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -27,10 +27,10 @@ export const AnalyticsNoDataPageProvider: FC<AnalyticsNoDataPageServices> = ({
|
|||
children,
|
||||
...services
|
||||
}) => {
|
||||
const { kibanaGuideDocLink, customBranding } = services;
|
||||
const { kibanaGuideDocLink, customBranding, prependBasePath, pageFlavor } = services;
|
||||
|
||||
return (
|
||||
<Context.Provider value={{ kibanaGuideDocLink, customBranding }}>
|
||||
<Context.Provider value={{ kibanaGuideDocLink, customBranding, prependBasePath, pageFlavor }}>
|
||||
<KibanaNoDataPageProvider {...services}>{children}</KibanaNoDataPageProvider>
|
||||
</Context.Provider>
|
||||
);
|
||||
|
@ -48,6 +48,8 @@ export const AnalyticsNoDataPageKibanaProvider: FC<AnalyticsNoDataPageKibanaDepe
|
|||
customBranding: {
|
||||
hasCustomBranding$: dependencies.coreStart.customBranding.hasCustomBranding$,
|
||||
},
|
||||
prependBasePath: dependencies.coreStart.http.basePath.prepend,
|
||||
pageFlavor: dependencies.noDataPage?.getAnalyticsNoDataPageFlavor() ?? 'kibana',
|
||||
};
|
||||
return (
|
||||
<Context.Provider {...{ value }}>
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
"@kbn/shared-ux-page-analytics-no-data-types",
|
||||
"@kbn/test-jest-helpers",
|
||||
"@kbn/shared-ux-page-analytics-no-data-mocks",
|
||||
"@kbn/shared-ux-page-kibana-no-data-types",
|
||||
"@kbn/i18n-react",
|
||||
],
|
||||
"exclude": [
|
||||
"target/**/*",
|
||||
|
|
|
@ -15,6 +15,8 @@ export const getServicesMock = () => {
|
|||
...getKibanaNoDataPageServicesMock(),
|
||||
kibanaGuideDocLink: 'Kibana guide',
|
||||
customBranding: { hasCustomBranding$: of(false) },
|
||||
prependBasePath: (path) => path,
|
||||
pageFlavor: 'kibana',
|
||||
};
|
||||
|
||||
return services;
|
||||
|
@ -26,6 +28,8 @@ export const getServicesMockCustomBranding = () => {
|
|||
// this mock will have custom branding set to true
|
||||
customBranding: { hasCustomBranding$: of(true) },
|
||||
kibanaGuideDocLink: 'Kibana guide',
|
||||
prependBasePath: (path) => path,
|
||||
pageFlavor: 'kibana',
|
||||
};
|
||||
|
||||
return services;
|
||||
|
|
|
@ -51,6 +51,8 @@ export class StorybookMock extends AbstractStorybookMock<
|
|||
customBranding: {
|
||||
hasCustomBranding$: of(false),
|
||||
},
|
||||
pageFlavor: 'kibana',
|
||||
prependBasePath: (path) => path,
|
||||
...kibanaNoDataMock.getServices(params),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ import { Observable } from 'rxjs';
|
|||
export interface Services {
|
||||
kibanaGuideDocLink: string;
|
||||
customBranding: { hasCustomBranding$: Observable<boolean> };
|
||||
prependBasePath: (path: string) => string;
|
||||
pageFlavor: AnalyticsNoDataPageFlavor;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -24,6 +26,8 @@ export interface Services {
|
|||
*/
|
||||
export type AnalyticsNoDataPageServices = Services & KibanaNoDataPageServices;
|
||||
|
||||
export type AnalyticsNoDataPageFlavor = 'kibana' | 'serverless_search';
|
||||
|
||||
export interface KibanaDependencies {
|
||||
coreStart: {
|
||||
docLinks: {
|
||||
|
@ -36,6 +40,14 @@ export interface KibanaDependencies {
|
|||
customBranding: {
|
||||
hasCustomBranding$: Observable<boolean>;
|
||||
};
|
||||
http: {
|
||||
basePath: {
|
||||
prepend: (path: string) => string;
|
||||
};
|
||||
};
|
||||
};
|
||||
noDataPage?: {
|
||||
getAnalyticsNoDataPageFlavor: () => AnalyticsNoDataPageFlavor;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -33,13 +33,13 @@ export const NoDataPage = ({
|
|||
values: { solution },
|
||||
});
|
||||
|
||||
const link = (
|
||||
const link = docsLink ? (
|
||||
<EuiLink href={docsLink} target="_blank">
|
||||
<FormattedMessage id="sharedUXPackages.noDataPage.intro.link" defaultMessage="learn more" />
|
||||
</EuiLink>
|
||||
);
|
||||
) : null;
|
||||
|
||||
const message = (
|
||||
const message = link ? (
|
||||
<FormattedMessage
|
||||
id="sharedUXPackages.noDataPage.intro"
|
||||
defaultMessage="Add your data to get started, or {link} about {solution}."
|
||||
|
@ -48,6 +48,11 @@ export const NoDataPage = ({
|
|||
link,
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<FormattedMessage
|
||||
id="sharedUXPackages.noDataPage.introNoDocLink"
|
||||
defaultMessage="Add your data to get started."
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -31,9 +31,9 @@ export interface NoDataPageProps extends CommonProps, ActionCardProps {
|
|||
*/
|
||||
solution: string;
|
||||
/**
|
||||
* Required to set the docs link for the whole solution
|
||||
* Required in "kibana" flavor to set the docs link for the whole solution, otherwise optional
|
||||
*/
|
||||
docsLink: string;
|
||||
docsLink?: string;
|
||||
/**
|
||||
* Optionally replace the auto-generated logo
|
||||
*/
|
||||
|
|
|
@ -34,7 +34,8 @@
|
|||
"screenshotMode",
|
||||
"usageCollection",
|
||||
"taskManager",
|
||||
"serverless"
|
||||
"serverless",
|
||||
"noDataPage"
|
||||
],
|
||||
"requiredBundles": ["kibanaReact", "kibanaUtils", "presentationUtil"]
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ export const DashboardAppNoDataPage = ({
|
|||
http: { basePath },
|
||||
documentationLinks: { indexPatternsDocLink, kibanaGuideDocLink },
|
||||
customBranding,
|
||||
noDataPage,
|
||||
} = pluginServices.getServices();
|
||||
|
||||
const analyticsServices = {
|
||||
|
@ -44,6 +45,7 @@ export const DashboardAppNoDataPage = ({
|
|||
},
|
||||
dataViews,
|
||||
dataViewEditor,
|
||||
noDataPage,
|
||||
};
|
||||
return (
|
||||
<AnalyticsNoDataPageKibanaProvider {...analyticsServices}>
|
||||
|
|
|
@ -52,6 +52,7 @@ import type { DataPublicPluginSetup, DataPublicPluginStart } from '@kbn/data-plu
|
|||
import type { UrlForwardingSetup, UrlForwardingStart } from '@kbn/url-forwarding-plugin/public';
|
||||
import type { SavedObjectTaggingOssPluginStart } from '@kbn/saved-objects-tagging-oss-plugin/public';
|
||||
import type { ServerlessPluginStart } from '@kbn/serverless/public';
|
||||
import type { NoDataPagePluginStart } from '@kbn/no-data-page-plugin/public';
|
||||
|
||||
import { CustomBrandingStart } from '@kbn/core-custom-branding-browser';
|
||||
import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public';
|
||||
|
@ -108,6 +109,7 @@ export interface DashboardStartDependencies {
|
|||
visualizations: VisualizationsStart;
|
||||
customBranding: CustomBrandingStart;
|
||||
serverless?: ServerlessPluginStart;
|
||||
noDataPage?: NoDataPagePluginStart;
|
||||
}
|
||||
|
||||
export interface DashboardSetup {
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* 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 { PluginServiceFactory } from '@kbn/presentation-util-plugin/public';
|
||||
import { NoDataPageService } from './types';
|
||||
|
||||
export type NoDataPageServiceFactory = PluginServiceFactory<NoDataPageService>;
|
||||
|
||||
export const noDataPageServiceFactory: NoDataPageServiceFactory = () => {
|
||||
return { getAnalyticsNoDataPageFlavor: () => 'kibana' };
|
||||
};
|
|
@ -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 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 { KibanaPluginServiceFactory } from '@kbn/presentation-util-plugin/public';
|
||||
import { DashboardStartDependencies } from '../../plugin';
|
||||
import { NoDataPageService } from './types';
|
||||
|
||||
export type NoDataPageServiceFactory = KibanaPluginServiceFactory<
|
||||
NoDataPageService,
|
||||
DashboardStartDependencies
|
||||
>;
|
||||
|
||||
export const noDataPageServiceFactory: NoDataPageServiceFactory = ({ startPlugins }) => {
|
||||
const { noDataPage } = startPlugins;
|
||||
|
||||
return {
|
||||
getAnalyticsNoDataPageFlavor: noDataPage?.getAnalyticsNoDataPageFlavor ?? (() => 'kibana'),
|
||||
};
|
||||
};
|
13
src/plugins/dashboard/public/services/no_data_page/types.ts
Normal file
13
src/plugins/dashboard/public/services/no_data_page/types.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* 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 type { NoDataPagePluginStart } from '@kbn/no-data-page-plugin/public';
|
||||
|
||||
export interface NoDataPageService {
|
||||
getAnalyticsNoDataPageFlavor: NoDataPagePluginStart['getAnalyticsNoDataPageFlavor'];
|
||||
}
|
|
@ -42,6 +42,7 @@ import { customBrandingServiceFactory } from './custom_branding/custom_branding.
|
|||
import { savedObjectsManagementServiceFactory } from './saved_objects_management/saved_objects_management_service.stub';
|
||||
import { contentManagementServiceFactory } from './content_management/content_management_service.stub';
|
||||
import { serverlessServiceFactory } from './serverless/serverless_service.stub';
|
||||
import { noDataPageServiceFactory } from './no_data_page/no_data_page_service.stub';
|
||||
|
||||
export const providers: PluginServiceProviders<DashboardServices> = {
|
||||
dashboardContentManagement: new PluginServiceProvider(dashboardContentManagementServiceFactory),
|
||||
|
@ -72,6 +73,7 @@ export const providers: PluginServiceProviders<DashboardServices> = {
|
|||
savedObjectsManagement: new PluginServiceProvider(savedObjectsManagementServiceFactory),
|
||||
contentManagement: new PluginServiceProvider(contentManagementServiceFactory),
|
||||
serverless: new PluginServiceProvider(serverlessServiceFactory),
|
||||
noDataPage: new PluginServiceProvider(noDataPageServiceFactory),
|
||||
};
|
||||
|
||||
export const registry = new PluginServiceRegistry<DashboardServices>(providers);
|
||||
|
|
|
@ -43,6 +43,7 @@ import { savedObjectsManagementServiceFactory } from './saved_objects_management
|
|||
import { dashboardContentManagementServiceFactory } from './dashboard_content_management/dashboard_content_management_service';
|
||||
import { contentManagementServiceFactory } from './content_management/content_management_service';
|
||||
import { serverlessServiceFactory } from './serverless/serverless_service';
|
||||
import { noDataPageServiceFactory } from './no_data_page/no_data_page_service';
|
||||
|
||||
const providers: PluginServiceProviders<DashboardServices, DashboardPluginServiceParams> = {
|
||||
dashboardContentManagement: new PluginServiceProvider(dashboardContentManagementServiceFactory, [
|
||||
|
@ -86,6 +87,7 @@ const providers: PluginServiceProviders<DashboardServices, DashboardPluginServic
|
|||
savedObjectsManagement: new PluginServiceProvider(savedObjectsManagementServiceFactory),
|
||||
contentManagement: new PluginServiceProvider(contentManagementServiceFactory),
|
||||
serverless: new PluginServiceProvider(serverlessServiceFactory),
|
||||
noDataPage: new PluginServiceProvider(noDataPageServiceFactory),
|
||||
};
|
||||
|
||||
export const pluginServices = new PluginServices<DashboardServices>();
|
||||
|
|
|
@ -38,6 +38,7 @@ import { DashboardUrlForwardingService } from './url_forwarding/types';
|
|||
import { DashboardUsageCollectionService } from './usage_collection/types';
|
||||
import { DashboardVisualizationsService } from './visualizations/types';
|
||||
import { DashboardServerlessService } from './serverless/types';
|
||||
import { NoDataPageService } from './no_data_page/types';
|
||||
|
||||
export type DashboardPluginServiceParams = KibanaPluginServiceParams<DashboardStartDependencies> & {
|
||||
initContext: PluginInitializerContext; // need a custom type so that initContext is a required parameter for initializerContext
|
||||
|
@ -72,4 +73,5 @@ export interface DashboardServices {
|
|||
savedObjectsManagement: SavedObjectsManagementPluginStart;
|
||||
contentManagement: ContentManagementPublicStart;
|
||||
serverless: DashboardServerlessService; // TODO: make this optional in follow up
|
||||
noDataPage: NoDataPageService;
|
||||
}
|
||||
|
|
|
@ -64,7 +64,8 @@
|
|||
"@kbn/content-management-table-list-view-table",
|
||||
"@kbn/shared-ux-prompt-not-found",
|
||||
"@kbn/content-management-content-editor",
|
||||
"@kbn/serverless"
|
||||
"@kbn/serverless",
|
||||
"@kbn/no-data-page-plugin"
|
||||
],
|
||||
"exclude": ["target/**/*"]
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
"expressions",
|
||||
"unifiedSearch",
|
||||
"unifiedHistogram",
|
||||
"contentManagement",
|
||||
"contentManagement"
|
||||
],
|
||||
"optionalPlugins": [
|
||||
"home",
|
||||
|
@ -36,7 +36,8 @@
|
|||
"triggersActionsUi",
|
||||
"savedObjectsTaggingOss",
|
||||
"lens",
|
||||
"serverless"
|
||||
"serverless",
|
||||
"noDataPage"
|
||||
],
|
||||
"requiredBundles": ["kibanaUtils", "kibanaReact", "unifiedSearch"],
|
||||
"extraPublicDirs": ["common"]
|
||||
|
|
|
@ -48,11 +48,7 @@ export interface MainRouteProps {
|
|||
mode?: DiscoverDisplayMode;
|
||||
}
|
||||
|
||||
export function DiscoverMainRoute({
|
||||
customizationCallbacks,
|
||||
isDev,
|
||||
mode = 'standalone',
|
||||
}: MainRouteProps) {
|
||||
export function DiscoverMainRoute({ customizationCallbacks, mode = 'standalone' }: MainRouteProps) {
|
||||
const history = useHistory();
|
||||
const services = useDiscoverServices();
|
||||
const {
|
||||
|
@ -109,7 +105,7 @@ export function DiscoverMainRoute({
|
|||
const hasUserDataViewValue = await data.dataViews.hasData
|
||||
.hasUserDataView()
|
||||
.catch(() => false);
|
||||
const hasESDataValue = isDev || (await data.dataViews.hasData.hasESData().catch(() => false));
|
||||
const hasESDataValue = await data.dataViews.hasData.hasESData().catch(() => false);
|
||||
setHasUserDataView(hasUserDataViewValue);
|
||||
setHasESData(hasESDataValue);
|
||||
|
||||
|
@ -134,7 +130,7 @@ export function DiscoverMainRoute({
|
|||
setError(e);
|
||||
return false;
|
||||
}
|
||||
}, [data.dataViews, isDev, savedSearchId]);
|
||||
}, [data.dataViews, savedSearchId]);
|
||||
|
||||
const loadSavedSearch = useCallback(
|
||||
async (nextDataView?: DataView) => {
|
||||
|
@ -256,11 +252,12 @@ export function DiscoverMainRoute({
|
|||
|
||||
// We've already called this, so we can optimize the analytics services to
|
||||
// use the already-retrieved data to avoid a double-call.
|
||||
hasESData: () => Promise.resolve(isDev ? true : hasESData),
|
||||
hasESData: () => Promise.resolve(hasESData),
|
||||
hasUserDataView: () => Promise.resolve(hasUserDataView),
|
||||
},
|
||||
},
|
||||
dataViewEditor,
|
||||
noDataPage: services.noDataPage,
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
@ -53,6 +53,7 @@ import type { UiActionsStart } from '@kbn/ui-actions-plugin/public';
|
|||
import type { SettingsStart } from '@kbn/core-ui-settings-browser';
|
||||
import type { ContentClient } from '@kbn/content-management-plugin/public';
|
||||
import type { ServerlessPluginStart } from '@kbn/serverless/public';
|
||||
import type { NoDataPagePluginStart } from '@kbn/no-data-page-plugin/public';
|
||||
import { getHistory } from './kibana_services';
|
||||
import { DiscoverStartPlugins } from './plugin';
|
||||
import { DiscoverContextAppLocator } from './application/context/services/locator';
|
||||
|
@ -111,6 +112,7 @@ export interface DiscoverServices {
|
|||
uiActions: UiActionsStart;
|
||||
contentClient: ContentClient;
|
||||
serverless?: ServerlessPluginStart;
|
||||
noDataPage?: NoDataPagePluginStart;
|
||||
}
|
||||
|
||||
export const buildServices = memoize(function (
|
||||
|
@ -171,5 +173,6 @@ export const buildServices = memoize(function (
|
|||
uiActions: plugins.uiActions,
|
||||
contentClient: plugins.contentManagement.client,
|
||||
serverless: plugins.serverless,
|
||||
noDataPage: plugins.noDataPage,
|
||||
};
|
||||
});
|
||||
|
|
|
@ -46,6 +46,7 @@ import { setStateToKbnUrl } from '@kbn/kibana-utils-plugin/public';
|
|||
import type { LensPublicStart } from '@kbn/lens-plugin/public';
|
||||
import type { ServerlessPluginStart } from '@kbn/serverless/public';
|
||||
import { DOC_TABLE_LEGACY, TRUNCATE_MAX_HEIGHT } from '@kbn/discover-utils';
|
||||
import { NoDataPagePluginStart } from '@kbn/no-data-page-plugin/public';
|
||||
import { PLUGIN_ID } from '../common';
|
||||
import { DocViewInput, DocViewInputFn } from './services/doc_views/doc_views_types';
|
||||
import { DocViewsRegistry } from './services/doc_views/doc_views_registry';
|
||||
|
@ -213,6 +214,7 @@ export interface DiscoverStartPlugins {
|
|||
lens: LensPublicStart;
|
||||
contentManagement: ContentManagementPublicStart;
|
||||
serverless?: ServerlessPluginStart;
|
||||
noDataPage?: NoDataPagePluginStart;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -70,7 +70,8 @@
|
|||
"@kbn/content-management-plugin",
|
||||
"@kbn/serverless",
|
||||
"@kbn/react-kibana-mount",
|
||||
"@kbn/react-kibana-context-render"
|
||||
"@kbn/react-kibana-context-render",
|
||||
"@kbn/no-data-page-plugin"
|
||||
],
|
||||
"exclude": [
|
||||
"target/**/*"
|
||||
|
|
3
src/plugins/no_data_page/README.md
Executable file
3
src/plugins/no_data_page/README.md
Executable file
|
@ -0,0 +1,3 @@
|
|||
# No Data Page
|
||||
|
||||
Helps to globally configure the no data page components
|
19
src/plugins/no_data_page/config.ts
Normal file
19
src/plugins/no_data_page/config.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* 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 { schema, TypeOf, offeringBasedSchema } from '@kbn/config-schema';
|
||||
|
||||
export const configSchema = schema.object({
|
||||
analyticsNoDataPageFlavor: offeringBasedSchema({
|
||||
serverless: schema.oneOf(
|
||||
[schema.oneOf([schema.literal('kibana'), schema.literal('serverless_search')])],
|
||||
{ defaultValue: 'kibana' as const }
|
||||
),
|
||||
}),
|
||||
});
|
||||
export type NoDataPageConfig = TypeOf<typeof configSchema>;
|
16
src/plugins/no_data_page/jest.config.js
Normal file
16
src/plugins/no_data_page/jest.config.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
preset: '@kbn/test',
|
||||
rootDir: '../../..',
|
||||
roots: ['<rootDir>/src/plugins/no_data_page'],
|
||||
coverageDirectory: '<rootDir>/target/kibana-coverage/jest/src/plugins/no_data_page',
|
||||
coverageReporters: ['text', 'html'],
|
||||
collectCoverageFrom: ['<rootDir>/src/plugins/no_data_page/{common,public,server}/**/*.{ts,tsx}'],
|
||||
};
|
10
src/plugins/no_data_page/kibana.jsonc
Normal file
10
src/plugins/no_data_page/kibana.jsonc
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"type": "plugin",
|
||||
"id": "@kbn/no-data-page-plugin",
|
||||
"owner": "@elastic/appex-sharedux",
|
||||
"plugin": {
|
||||
"id": "noDataPage",
|
||||
"server": true,
|
||||
"browser": true
|
||||
}
|
||||
}
|
16
src/plugins/no_data_page/public/index.ts
Normal file
16
src/plugins/no_data_page/public/index.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* 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 { PluginInitializerContext } from '@kbn/core-plugins-browser';
|
||||
import { NoDataPagePlugin } from './plugin';
|
||||
|
||||
export function plugin(ctx: PluginInitializerContext) {
|
||||
return new NoDataPagePlugin(ctx);
|
||||
}
|
||||
|
||||
export type { NoDataPagePluginSetup, NoDataPagePluginStart } from './types';
|
31
src/plugins/no_data_page/public/plugin.ts
Normal file
31
src/plugins/no_data_page/public/plugin.ts
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* 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 type { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from '@kbn/core/public';
|
||||
import type { NoDataPagePluginSetup, NoDataPagePluginStart } from './types';
|
||||
import type { NoDataPageConfig } from '../config';
|
||||
|
||||
export class NoDataPagePlugin implements Plugin<NoDataPagePluginSetup> {
|
||||
constructor(private initializerContext: PluginInitializerContext<NoDataPageConfig>) {}
|
||||
|
||||
public setup(core: CoreSetup): NoDataPagePluginSetup {
|
||||
return {
|
||||
getAnalyticsNoDataPageFlavor: () => {
|
||||
return this.initializerContext.config.get().analyticsNoDataPageFlavor;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
public start(core: CoreStart): NoDataPagePluginStart {
|
||||
return {
|
||||
getAnalyticsNoDataPageFlavor: () => {
|
||||
return this.initializerContext.config.get().analyticsNoDataPageFlavor;
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
13
src/plugins/no_data_page/public/types.ts
Normal file
13
src/plugins/no_data_page/public/types.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* 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 interface NoDataPagePluginSetup {
|
||||
getAnalyticsNoDataPageFlavor: () => 'kibana' | 'serverless_search';
|
||||
}
|
||||
|
||||
export type NoDataPagePluginStart = NoDataPagePluginSetup;
|
25
src/plugins/no_data_page/server/index.ts
Normal file
25
src/plugins/no_data_page/server/index.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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 { PluginConfigDescriptor } from '@kbn/core-plugins-server';
|
||||
|
||||
import { configSchema, NoDataPageConfig } from '../config';
|
||||
|
||||
export const config: PluginConfigDescriptor<NoDataPageConfig> = {
|
||||
exposeToBrowser: {
|
||||
analyticsNoDataPageFlavor: true,
|
||||
},
|
||||
schema: configSchema,
|
||||
};
|
||||
|
||||
export function plugin() {
|
||||
return new (class NoDataPagePlugin {
|
||||
setup() {}
|
||||
start() {}
|
||||
})();
|
||||
}
|
14
src/plugins/no_data_page/tsconfig.json
Normal file
14
src/plugins/no_data_page/tsconfig.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "target/types"
|
||||
},
|
||||
"include": ["common/**/*", "public/**/*", "server/**/*", "config.ts"],
|
||||
"kbn_references": [
|
||||
"@kbn/core",
|
||||
"@kbn/core-plugins-browser",
|
||||
"@kbn/core-plugins-server",
|
||||
"@kbn/config-schema",
|
||||
],
|
||||
"exclude": ["target/**/*"]
|
||||
}
|
|
@ -34,7 +34,8 @@
|
|||
"share",
|
||||
"spaces",
|
||||
"savedObjectsTaggingOss",
|
||||
"serverless"
|
||||
"serverless",
|
||||
"noDataPage"
|
||||
],
|
||||
"requiredBundles": [
|
||||
"kibanaUtils",
|
||||
|
|
|
@ -64,6 +64,7 @@ import {
|
|||
ContentManagementPublicSetup,
|
||||
ContentManagementPublicStart,
|
||||
} from '@kbn/content-management-plugin/public';
|
||||
import type { NoDataPagePluginStart } from '@kbn/no-data-page-plugin/public';
|
||||
import type { TypesSetup, TypesStart } from './vis_types';
|
||||
import type { VisualizeServices } from './visualize_app/types';
|
||||
import {
|
||||
|
@ -166,6 +167,7 @@ export interface VisualizationsStartDeps {
|
|||
savedObjectsManagement: SavedObjectsManagementPluginStart;
|
||||
contentManagement: ContentManagementPublicStart;
|
||||
serverless?: ServerlessPluginStart;
|
||||
noDataPage?: NoDataPagePluginStart;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -330,6 +332,7 @@ export class VisualizationsPlugin
|
|||
listingViewRegistry,
|
||||
unifiedSearch: pluginsStart.unifiedSearch,
|
||||
serverless: pluginsStart.serverless,
|
||||
noDataPage: pluginsStart.noDataPage,
|
||||
};
|
||||
|
||||
params.element.classList.add('visAppWrapper');
|
||||
|
|
|
@ -14,6 +14,7 @@ import { EuiLoadingSpinner } from '@elastic/eui';
|
|||
import { AppMountParameters, CoreStart } from '@kbn/core/public';
|
||||
import type { DataViewEditorStart } from '@kbn/data-view-editor-plugin/public';
|
||||
import { syncGlobalQueryStateWithUrl } from '@kbn/data-plugin/public';
|
||||
import type { NoDataPagePluginStart } from '@kbn/no-data-page-plugin/public';
|
||||
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||
import {
|
||||
AnalyticsNoDataPageKibanaProvider,
|
||||
|
@ -38,6 +39,7 @@ interface NoDataComponentProps {
|
|||
dataViews: DataViewsContract;
|
||||
dataViewEditor: DataViewEditorStart;
|
||||
onDataViewCreated: (dataView: unknown) => void;
|
||||
noDataPage?: NoDataPagePluginStart;
|
||||
}
|
||||
|
||||
const NoDataComponent = ({
|
||||
|
@ -45,11 +47,13 @@ const NoDataComponent = ({
|
|||
dataViews,
|
||||
dataViewEditor,
|
||||
onDataViewCreated,
|
||||
noDataPage,
|
||||
}: NoDataComponentProps) => {
|
||||
const analyticsServices = {
|
||||
coreStart: core,
|
||||
dataViews,
|
||||
dataViewEditor,
|
||||
noDataPage,
|
||||
};
|
||||
return (
|
||||
<AnalyticsNoDataPageKibanaProvider {...analyticsServices}>
|
||||
|
@ -65,6 +69,7 @@ export const VisualizeApp = ({ onAppLeave }: VisualizeAppProps) => {
|
|||
core,
|
||||
kbnUrlStateStorage,
|
||||
dataViewEditor,
|
||||
noDataPage,
|
||||
},
|
||||
} = useKibana<VisualizeServices>();
|
||||
const { pathname } = useLocation();
|
||||
|
@ -125,6 +130,7 @@ export const VisualizeApp = ({ onAppLeave }: VisualizeAppProps) => {
|
|||
dataViewEditor={dataViewEditor}
|
||||
dataViews={dataViews}
|
||||
onDataViewCreated={onDataViewCreated}
|
||||
noDataPage={noDataPage}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ import type { SpacesPluginStart } from '@kbn/spaces-plugin/public';
|
|||
import type { SavedObjectsTaggingApi } from '@kbn/saved-objects-tagging-oss-plugin/public';
|
||||
import type { SavedSearch, SavedSearchPublicPluginStart } from '@kbn/saved-search-plugin/public';
|
||||
import type { ServerlessPluginStart } from '@kbn/serverless/public';
|
||||
import type { NoDataPagePluginStart } from '@kbn/no-data-page-plugin/public';
|
||||
import type {
|
||||
Vis,
|
||||
VisualizeEmbeddableContract,
|
||||
|
@ -117,6 +118,7 @@ export interface VisualizeServices extends CoreStart {
|
|||
listingViewRegistry: ListingViewRegistry;
|
||||
unifiedSearch: UnifiedSearchPublicPluginStart;
|
||||
serverless?: ServerlessPluginStart;
|
||||
noDataPage?: NoDataPagePluginStart;
|
||||
}
|
||||
|
||||
export interface VisInstance {
|
||||
|
|
|
@ -62,7 +62,8 @@
|
|||
"@kbn/content-management-tabbed-table-list-view",
|
||||
"@kbn/content-management-table-list-view",
|
||||
"@kbn/content-management-utils",
|
||||
"@kbn/serverless"
|
||||
"@kbn/serverless",
|
||||
"@kbn/no-data-page-plugin"
|
||||
],
|
||||
"exclude": [
|
||||
"target/**/*",
|
||||
|
|
|
@ -145,6 +145,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) {
|
|||
'newsfeed.mainInterval (duration)',
|
||||
'newsfeed.service.pathTemplate (string)',
|
||||
'newsfeed.service.urlRoot (string)',
|
||||
'no_data_page.analyticsNoDataPageFlavor (any)', // It's a string (any because schema.conditional)
|
||||
'telemetry.allowChangingOptInStatus (boolean)',
|
||||
'telemetry.appendServerlessChannelsSuffix (any)', // It's a boolean (any because schema.conditional)
|
||||
'telemetry.banner (boolean)',
|
||||
|
|
|
@ -1028,6 +1028,8 @@
|
|||
"@kbn/newsfeed-plugin/*": ["src/plugins/newsfeed/*"],
|
||||
"@kbn/newsfeed-test-plugin": ["test/common/plugins/newsfeed"],
|
||||
"@kbn/newsfeed-test-plugin/*": ["test/common/plugins/newsfeed/*"],
|
||||
"@kbn/no-data-page-plugin": ["src/plugins/no_data_page"],
|
||||
"@kbn/no-data-page-plugin/*": ["src/plugins/no_data_page/*"],
|
||||
"@kbn/notifications-plugin": ["x-pack/plugins/notifications"],
|
||||
"@kbn/notifications-plugin/*": ["x-pack/plugins/notifications/*"],
|
||||
"@kbn/object-versioning": ["packages/kbn-object-versioning"],
|
||||
|
|
|
@ -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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
|
||||
export default function ({ getPageObject, getService }: FtrProviderContext) {
|
||||
const svlSearchNavigation = getService('svlSearchNavigation');
|
||||
const testSubjects = getService('testSubjects');
|
||||
const svlCommonNavigation = getPageObject('svlCommonNavigation');
|
||||
|
||||
describe('empty pages', function () {
|
||||
before(async () => {
|
||||
await svlSearchNavigation.navigateToLandingPage();
|
||||
});
|
||||
|
||||
it('should show search specific empty page in discover', async () => {
|
||||
await svlCommonNavigation.sidenav.clickLink({ deepLinkId: 'discover' });
|
||||
await testSubjects.existOrFail('kbnOverviewElasticsearchGettingStarted');
|
||||
await testSubjects.click('kbnOverviewElasticsearchGettingStarted');
|
||||
await svlCommonNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Getting started' });
|
||||
});
|
||||
|
||||
it('should show search specific empty page in visualize', async () => {
|
||||
await svlCommonNavigation.sidenav.clickLink({ deepLinkId: 'visualize' });
|
||||
await testSubjects.existOrFail('kbnOverviewElasticsearchGettingStarted');
|
||||
await testSubjects.click('kbnOverviewElasticsearchGettingStarted');
|
||||
await svlCommonNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Getting started' });
|
||||
});
|
||||
|
||||
it('should show search specific empty page in dashboards', async () => {
|
||||
await svlCommonNavigation.sidenav.clickLink({ deepLinkId: 'dashboards' });
|
||||
await testSubjects.existOrFail('kbnOverviewElasticsearchGettingStarted');
|
||||
await testSubjects.click('kbnOverviewElasticsearchGettingStarted');
|
||||
await svlCommonNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Getting started' });
|
||||
});
|
||||
});
|
||||
}
|
|
@ -10,6 +10,7 @@ import { FtrProviderContext } from '../../ftr_provider_context';
|
|||
export default function ({ loadTestFile }: FtrProviderContext) {
|
||||
describe('serverless search UI', function () {
|
||||
loadTestFile(require.resolve('./landing_page'));
|
||||
loadTestFile(require.resolve('./empty_page'));
|
||||
loadTestFile(require.resolve('./navigation'));
|
||||
loadTestFile(require.resolve('./cases/attachment_framework'));
|
||||
});
|
||||
|
|
|
@ -4962,6 +4962,10 @@
|
|||
version "0.0.0"
|
||||
uid ""
|
||||
|
||||
"@kbn/no-data-page-plugin@link:src/plugins/no_data_page":
|
||||
version "0.0.0"
|
||||
uid ""
|
||||
|
||||
"@kbn/notifications-plugin@link:x-pack/plugins/notifications":
|
||||
version "0.0.0"
|
||||
uid ""
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue