Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Serverless Elasticsearch] Fix user is blocked from moving forward when opening Discover, Dashboard, or Visualize Library #164709

Merged
merged 17 commits into from
Aug 28, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions config/serverless.es.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,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'
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
4 changes: 3 additions & 1 deletion packages/shared-ux/card/no_data/impl/src/no_data_card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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>
);
};
2 changes: 1 addition & 1 deletion packages/shared-ux/card/no_data/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.analytics', {
defaultMessage: 'Elasticsearch',
}),
pageTitle: i18n.translate('sharedUXPackages.noDataConfig.analyticsPageTitle', {
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/'),
Copy link
Contributor Author

@Dosant Dosant Aug 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

href on this level is added only for "serverless_search" flavor, but not for "kibana" flavor because the integrations page is already hardcoded inside the component. The NoDataCard must be refactored to be fully configurable and don't hardcode fleet stuff.

/** force the no data card to be shown **/
canAccessFleet: true,
Copy link
Contributor Author

@Dosant Dosant Aug 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Passing/faking this explicitly so that NoDataCard doesn't fallback to the "no access to fleet" page. This needs to be refactored.

Currently, it is ugly: even though the NoDataCard seems to be generic and text and links can be configured through props, some "fleet" logic parts are still hardcoded inside the component. For example, the component checks the access to fleet through context.

},
},
}),
};

/**
* A pure component of an entire page that can be displayed when Kibana "has no data", specifically for Analytics.
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -32,6 +32,8 @@ export const AnalyticsNoDataPage = ({
allowAdHocDataView,
kibanaGuideDocLink,
showPlainSpinner,
prependBasePath,
pageFlavor,
}}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>
);
Expand All @@ -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(),
};
return (
<Context.Provider {...{ value }}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"@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",
],
"exclude": [
"target/**/*",
Expand Down
12 changes: 12 additions & 0 deletions packages/shared-ux/page/analytics_no_data/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,17 @@ import { Observable } from 'rxjs';
export interface Services {
kibanaGuideDocLink: string;
customBranding: { hasCustomBranding$: Observable<boolean> };
prependBasePath: (path: string) => string;
pageFlavor: AnalyticsNoDataPageFlavor;
}

/**
* Services that are consumed by this component and any dependencies.
*/
export type AnalyticsNoDataPageServices = Services & KibanaNoDataPageServices;

export type AnalyticsNoDataPageFlavor = 'kibana' | 'serverless_search';

export interface KibanaDependencies {
coreStart: {
docLinks: {
Expand All @@ -36,6 +40,14 @@ export interface KibanaDependencies {
customBranding: {
hasCustomBranding$: Observable<boolean>;
};
http: {
basePath: {
prepend: (path: string) => string;
};
};
};
noDataPage: {
getAnalyticsNoDataPageFlavor: () => AnalyticsNoDataPageFlavor;
};
}

Expand Down
11 changes: 8 additions & 3 deletions packages/shared-ux/page/no_data/impl/src/no_data_page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@ export const NoDataPage = ({
values: { solution },
});

const link = (
const link = docsLink ? (
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Making docsLink here optional to skip the docs link for serverless search empty page for now

<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}."
Expand All @@ -48,6 +48,11 @@ export const NoDataPage = ({
link,
}}
/>
) : (
<FormattedMessage
id="sharedUXPackages.noDataPage.introNoDocLink"
defaultMessage="Add your data to get started."
/>
);

return (
Expand Down
2 changes: 1 addition & 1 deletion packages/shared-ux/page/no_data/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export interface NoDataPageProps extends CommonProps, ActionCardProps {
/**
* Required to set the docs link for the whole solution
*/
docsLink: string;
docsLink?: string;
/**
* Optionally replace the auto-generated logo
*/
Expand Down
1 change: 1 addition & 0 deletions src/plugins/discover/kibana.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"unifiedSearch",
"unifiedHistogram",
"contentManagement",
"noDataPage"
],
"optionalPlugins": [
"home",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ export function DiscoverMainRoute({
},
},
dataViewEditor,
noDataPage: services.noDataPage,
};

return (
Expand Down
3 changes: 3 additions & 0 deletions src/plugins/discover/public/build_services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -111,6 +112,7 @@ export interface DiscoverServices {
uiActions: UiActionsStart;
contentClient: ContentClient;
serverless?: ServerlessPluginStart;
noDataPage: NoDataPagePluginStart;
}

export const buildServices = memoize(function (
Expand Down Expand Up @@ -171,5 +173,6 @@ export const buildServices = memoize(function (
uiActions: plugins.uiActions,
contentClient: plugins.contentManagement.client,
serverless: plugins.serverless,
noDataPage: plugins.noDataPage,
};
});
2 changes: 2 additions & 0 deletions src/plugins/discover/public/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -213,6 +214,7 @@ export interface DiscoverStartPlugins {
lens: LensPublicStart;
contentManagement: ContentManagementPublicStart;
serverless?: ServerlessPluginStart;
noDataPage: NoDataPagePluginStart;
}

/**
Expand Down
3 changes: 2 additions & 1 deletion src/plugins/discover/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -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/**/*"
Expand Down
3 changes: 3 additions & 0 deletions src/plugins/no_data_page/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# No Data Page

Helps to globally configure the no data page components
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need this dummy plugin to create a config for configuring the analytics empty pages "flavor"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An alternative could be that all discover, visualize, dashboards expose this config on their own and pass it to the component.

19 changes: 19 additions & 0 deletions src/plugins/no_data_page/config.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 16 additions & 0 deletions src/plugins/no_data_page/jest.config.js
Original file line number Diff line number Diff line change
@@ -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'],
coverageDirectory: '<rootDir>/target/kibana-coverage/jest/src/plugins/no_data',
coverageReporters: ['text', 'html'],
collectCoverageFrom: ['<rootDir>/src/plugins/no_data/{common,public,server}/**/*.{ts,tsx}'],
};
10 changes: 10 additions & 0 deletions src/plugins/no_data_page/kibana.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"type": "plugin",
"id": "@kbn/no-data-page-plugin",
"owner": "@elastic/appex-sharedux",
"plugin": {
"id": "noDataPage",
"server": true,
"browser": true
}
}
Loading