[Shared UX] Complete package migration; delete plugin (#138962)

* [Shared UX] Complete package migration; delete plugin

* [CI] Auto-commit changed files from 'node scripts/generate packages_build_manifest'

* Fix types, fix tests

* Create Storybook config package; organize Storybook

* [CI] Auto-commit changed files from 'node scripts/build_plugin_list_docs'

* Revise Storybook config package; make mock packages compatible with web

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Clint Andrew Hall 2022-08-18 13:00:03 -05:00 committed by GitHub
parent 89d8802571
commit 0fbd0afdb1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
248 changed files with 2752 additions and 2755 deletions

1
.github/CODEOWNERS vendored
View file

@ -669,7 +669,6 @@ x-pack/test/threat_intelligence_cypress @elastic/protections-experience
# Application Experience # Application Experience
## Shared UX Team ## Shared UX Team
/src/plugins/shared_ux/ @elastic/shared-ux
/packages/shared-ux/ @elastic/shared-ux /packages/shared-ux/ @elastic/shared-ux
/packages/shared-ux-*/ @elastic/shared-ux /packages/shared-ux-*/ @elastic/shared-ux

View file

@ -67,8 +67,6 @@
"savedObjectsManagement": "src/plugins/saved_objects_management", "savedObjectsManagement": "src/plugins/saved_objects_management",
"server": "src/legacy/server", "server": "src/legacy/server",
"share": "src/plugins/share", "share": "src/plugins/share",
"sharedUX": "src/plugins/shared_ux",
"sharedUXComponents": "packages/kbn-shared-ux-components/src",
"sharedUXPackages": "packages/shared-ux", "sharedUXPackages": "packages/shared-ux",
"coloring": "packages/kbn-coloring/src", "coloring": "packages/kbn-coloring/src",
"statusPage": "src/legacy/core_plugins/status_page", "statusPage": "src/legacy/core_plugins/status_page",

View file

@ -259,10 +259,6 @@ oss plugins.
generating deep links to other apps using locators, and creating short URLs. generating deep links to other apps using locators, and creating short URLs.
|{kib-repo}blob/{branch}/src/plugins/shared_ux/README.md[sharedUX]
|Our mission is to make consistency in our user experience a product.
|{kib-repo}blob/{branch}/src/plugins/telemetry/README.md[telemetry] |{kib-repo}blob/{branch}/src/plugins/telemetry/README.md[telemetry]
|Telemetry allows Kibana features to have usage tracked in the wild. The general term "telemetry" refers to multiple things: |Telemetry allows Kibana features to have usage tracked in the wild. The general term "telemetry" refers to multiple things:

View file

@ -307,7 +307,6 @@
"@kbn/shared-ux-card-no-data": "link:bazel-bin/packages/shared-ux/card/no_data/impl", "@kbn/shared-ux-card-no-data": "link:bazel-bin/packages/shared-ux/card/no_data/impl",
"@kbn/shared-ux-card-no-data-mocks": "link:bazel-bin/packages/shared-ux/card/no_data/mocks", "@kbn/shared-ux-card-no-data-mocks": "link:bazel-bin/packages/shared-ux/card/no_data/mocks",
"@kbn/shared-ux-card-no-data-types": "link:bazel-bin/packages/shared-ux/card/no_data/types", "@kbn/shared-ux-card-no-data-types": "link:bazel-bin/packages/shared-ux/card/no_data/types",
"@kbn/shared-ux-components": "link:bazel-bin/packages/kbn-shared-ux-components",
"@kbn/shared-ux-link-redirect-app": "link:bazel-bin/packages/shared-ux/link/redirect_app/impl", "@kbn/shared-ux-link-redirect-app": "link:bazel-bin/packages/shared-ux/link/redirect_app/impl",
"@kbn/shared-ux-link-redirect-app-mocks": "link:bazel-bin/packages/shared-ux/link/redirect_app/mocks", "@kbn/shared-ux-link-redirect-app-mocks": "link:bazel-bin/packages/shared-ux/link/redirect_app/mocks",
"@kbn/shared-ux-link-redirect-app-types": "link:bazel-bin/packages/shared-ux/link/redirect_app/types", "@kbn/shared-ux-link-redirect-app-types": "link:bazel-bin/packages/shared-ux/link/redirect_app/types",
@ -317,12 +316,20 @@
"@kbn/shared-ux-page-kibana-no-data": "link:bazel-bin/packages/shared-ux/page/kibana_no_data/impl", "@kbn/shared-ux-page-kibana-no-data": "link:bazel-bin/packages/shared-ux/page/kibana_no_data/impl",
"@kbn/shared-ux-page-kibana-no-data-mocks": "link:bazel-bin/packages/shared-ux/page/kibana_no_data/mocks", "@kbn/shared-ux-page-kibana-no-data-mocks": "link:bazel-bin/packages/shared-ux/page/kibana_no_data/mocks",
"@kbn/shared-ux-page-kibana-no-data-types": "link:bazel-bin/packages/shared-ux/page/kibana_no_data/types", "@kbn/shared-ux-page-kibana-no-data-types": "link:bazel-bin/packages/shared-ux/page/kibana_no_data/types",
"@kbn/shared-ux-page-kibana-template": "link:bazel-bin/packages/shared-ux/page/kibana_template/impl",
"@kbn/shared-ux-page-kibana-template-mocks": "link:bazel-bin/packages/shared-ux/page/kibana_template/mocks",
"@kbn/shared-ux-page-kibana-template-types": "link:bazel-bin/packages/shared-ux/page/kibana_template/types",
"@kbn/shared-ux-page-no-data": "link:bazel-bin/packages/shared-ux/page/no_data/impl",
"@kbn/shared-ux-page-no-data-config": "link:bazel-bin/packages/shared-ux/page/no_data_config/impl",
"@kbn/shared-ux-page-no-data-config-mocks": "link:bazel-bin/packages/shared-ux/page/no_data_config/mocks",
"@kbn/shared-ux-page-no-data-config-types": "link:bazel-bin/packages/shared-ux/page/no_data_config/types",
"@kbn/shared-ux-page-no-data-mocks": "link:bazel-bin/packages/shared-ux/page/no_data/mocks",
"@kbn/shared-ux-page-no-data-types": "link:bazel-bin/packages/shared-ux/page/no_data/types",
"@kbn/shared-ux-page-solution-nav": "link:bazel-bin/packages/shared-ux/page/solution_nav", "@kbn/shared-ux-page-solution-nav": "link:bazel-bin/packages/shared-ux/page/solution_nav",
"@kbn/shared-ux-prompt-no-data-views": "link:bazel-bin/packages/shared-ux/prompt/no_data_views/impl", "@kbn/shared-ux-prompt-no-data-views": "link:bazel-bin/packages/shared-ux/prompt/no_data_views/impl",
"@kbn/shared-ux-prompt-no-data-views-mocks": "link:bazel-bin/packages/shared-ux/prompt/no_data_views/mocks", "@kbn/shared-ux-prompt-no-data-views-mocks": "link:bazel-bin/packages/shared-ux/prompt/no_data_views/mocks",
"@kbn/shared-ux-prompt-no-data-views-types": "link:bazel-bin/packages/shared-ux/prompt/no_data_views/types", "@kbn/shared-ux-prompt-no-data-views-types": "link:bazel-bin/packages/shared-ux/prompt/no_data_views/types",
"@kbn/shared-ux-services": "link:bazel-bin/packages/kbn-shared-ux-services", "@kbn/shared-ux-storybook-config": "link:bazel-bin/packages/shared-ux/storybook/config",
"@kbn/shared-ux-storybook": "link:bazel-bin/packages/kbn-shared-ux-storybook",
"@kbn/shared-ux-storybook-mock": "link:bazel-bin/packages/shared-ux/storybook/mock", "@kbn/shared-ux-storybook-mock": "link:bazel-bin/packages/shared-ux/storybook/mock",
"@kbn/shared-ux-utility": "link:bazel-bin/packages/kbn-shared-ux-utility", "@kbn/shared-ux-utility": "link:bazel-bin/packages/kbn-shared-ux-utility",
"@kbn/std": "link:bazel-bin/packages/kbn-std", "@kbn/std": "link:bazel-bin/packages/kbn-std",
@ -975,7 +982,6 @@
"@types/kbn__shared-ux-card-no-data": "link:bazel-bin/packages/shared-ux/card/no_data/impl/npm_module_types", "@types/kbn__shared-ux-card-no-data": "link:bazel-bin/packages/shared-ux/card/no_data/impl/npm_module_types",
"@types/kbn__shared-ux-card-no-data-mocks": "link:bazel-bin/packages/shared-ux/card/no_data/mocks/npm_module_types", "@types/kbn__shared-ux-card-no-data-mocks": "link:bazel-bin/packages/shared-ux/card/no_data/mocks/npm_module_types",
"@types/kbn__shared-ux-card-no-data-types": "link:bazel-bin/packages/shared-ux/card/no_data/types/npm_module_types", "@types/kbn__shared-ux-card-no-data-types": "link:bazel-bin/packages/shared-ux/card/no_data/types/npm_module_types",
"@types/kbn__shared-ux-components": "link:bazel-bin/packages/kbn-shared-ux-components/npm_module_types",
"@types/kbn__shared-ux-link-redirect-app": "link:bazel-bin/packages/shared-ux/link/redirect_app/impl/npm_module_types", "@types/kbn__shared-ux-link-redirect-app": "link:bazel-bin/packages/shared-ux/link/redirect_app/impl/npm_module_types",
"@types/kbn__shared-ux-link-redirect-app-mocks": "link:bazel-bin/packages/shared-ux/link/redirect_app/mocks/npm_module_types", "@types/kbn__shared-ux-link-redirect-app-mocks": "link:bazel-bin/packages/shared-ux/link/redirect_app/mocks/npm_module_types",
"@types/kbn__shared-ux-link-redirect-app-types": "link:bazel-bin/packages/shared-ux/link/redirect_app/types/npm_module_types", "@types/kbn__shared-ux-link-redirect-app-types": "link:bazel-bin/packages/shared-ux/link/redirect_app/types/npm_module_types",
@ -985,12 +991,20 @@
"@types/kbn__shared-ux-page-kibana-no-data": "link:bazel-bin/packages/shared-ux/page/kibana_no_data/impl/npm_module_types", "@types/kbn__shared-ux-page-kibana-no-data": "link:bazel-bin/packages/shared-ux/page/kibana_no_data/impl/npm_module_types",
"@types/kbn__shared-ux-page-kibana-no-data-mocks": "link:bazel-bin/packages/shared-ux/page/kibana_no_data/mocks/npm_module_types", "@types/kbn__shared-ux-page-kibana-no-data-mocks": "link:bazel-bin/packages/shared-ux/page/kibana_no_data/mocks/npm_module_types",
"@types/kbn__shared-ux-page-kibana-no-data-types": "link:bazel-bin/packages/shared-ux/page/kibana_no_data/types/npm_module_types", "@types/kbn__shared-ux-page-kibana-no-data-types": "link:bazel-bin/packages/shared-ux/page/kibana_no_data/types/npm_module_types",
"@types/kbn__shared-ux-page-kibana-template": "link:bazel-bin/packages/shared-ux/page/kibana_template/impl/npm_module_types",
"@types/kbn__shared-ux-page-kibana-template-mocks": "link:bazel-bin/packages/shared-ux/page/kibana_template/mocks/npm_module_types",
"@types/kbn__shared-ux-page-kibana-template-types": "link:bazel-bin/packages/shared-ux/page/kibana_template/types/npm_module_types",
"@types/kbn__shared-ux-page-no-data": "link:bazel-bin/packages/shared-ux/page/no_data/impl/npm_module_types",
"@types/kbn__shared-ux-page-no-data-config": "link:bazel-bin/packages/shared-ux/page/no_data_config/impl/npm_module_types",
"@types/kbn__shared-ux-page-no-data-config-mocks": "link:bazel-bin/packages/shared-ux/page/no_data_config/mocks/npm_module_types",
"@types/kbn__shared-ux-page-no-data-config-types": "link:bazel-bin/packages/shared-ux/page/no_data_config/types/npm_module_types",
"@types/kbn__shared-ux-page-no-data-mocks": "link:bazel-bin/packages/shared-ux/page/no_data/mocks/npm_module_types",
"@types/kbn__shared-ux-page-no-data-types": "link:bazel-bin/packages/shared-ux/page/no_data/types/npm_module_types",
"@types/kbn__shared-ux-page-solution-nav": "link:bazel-bin/packages/shared-ux/page/solution_nav/npm_module_types", "@types/kbn__shared-ux-page-solution-nav": "link:bazel-bin/packages/shared-ux/page/solution_nav/npm_module_types",
"@types/kbn__shared-ux-prompt-no-data-views": "link:bazel-bin/packages/shared-ux/prompt/no_data_views/impl/npm_module_types", "@types/kbn__shared-ux-prompt-no-data-views": "link:bazel-bin/packages/shared-ux/prompt/no_data_views/impl/npm_module_types",
"@types/kbn__shared-ux-prompt-no-data-views-mocks": "link:bazel-bin/packages/shared-ux/prompt/no_data_views/mocks/npm_module_types", "@types/kbn__shared-ux-prompt-no-data-views-mocks": "link:bazel-bin/packages/shared-ux/prompt/no_data_views/mocks/npm_module_types",
"@types/kbn__shared-ux-prompt-no-data-views-types": "link:bazel-bin/packages/shared-ux/prompt/no_data_views/types/npm_module_types", "@types/kbn__shared-ux-prompt-no-data-views-types": "link:bazel-bin/packages/shared-ux/prompt/no_data_views/types/npm_module_types",
"@types/kbn__shared-ux-services": "link:bazel-bin/packages/kbn-shared-ux-services/npm_module_types", "@types/kbn__shared-ux-storybook-config": "link:bazel-bin/packages/shared-ux/storybook/config/npm_module_types",
"@types/kbn__shared-ux-storybook": "link:bazel-bin/packages/kbn-shared-ux-storybook/npm_module_types",
"@types/kbn__shared-ux-storybook-mock": "link:bazel-bin/packages/shared-ux/storybook/mock/npm_module_types", "@types/kbn__shared-ux-storybook-mock": "link:bazel-bin/packages/shared-ux/storybook/mock/npm_module_types",
"@types/kbn__shared-ux-utility": "link:bazel-bin/packages/kbn-shared-ux-utility/npm_module_types", "@types/kbn__shared-ux-utility": "link:bazel-bin/packages/kbn-shared-ux-utility/npm_module_types",
"@types/kbn__some-dev-log": "link:bazel-bin/packages/kbn-some-dev-log/npm_module_types", "@types/kbn__some-dev-log": "link:bazel-bin/packages/kbn-some-dev-log/npm_module_types",
@ -1200,6 +1214,7 @@
"jest-diff": "^26.6.2", "jest-diff": "^26.6.2",
"jest-environment-jsdom": "^26.6.2", "jest-environment-jsdom": "^26.6.2",
"jest-environment-jsdom-thirteen": "^1.0.1", "jest-environment-jsdom-thirteen": "^1.0.1",
"jest-mock": "^26.6.2",
"jest-raw-loader": "^1.0.1", "jest-raw-loader": "^1.0.1",
"jest-runtime": "^26", "jest-runtime": "^26",
"jest-silent-reporter": "^0.5.0", "jest-silent-reporter": "^0.5.0",

View file

@ -210,9 +210,6 @@ filegroup(
"//packages/kbn-server-http-tools:build", "//packages/kbn-server-http-tools:build",
"//packages/kbn-server-route-repository:build", "//packages/kbn-server-route-repository:build",
"//packages/kbn-shared-svg:build", "//packages/kbn-shared-svg:build",
"//packages/kbn-shared-ux-components:build",
"//packages/kbn-shared-ux-services:build",
"//packages/kbn-shared-ux-storybook:build",
"//packages/kbn-shared-ux-utility:build", "//packages/kbn-shared-ux-utility:build",
"//packages/kbn-some-dev-log:build", "//packages/kbn-some-dev-log:build",
"//packages/kbn-sort-package-json:build", "//packages/kbn-sort-package-json:build",
@ -258,10 +255,20 @@ filegroup(
"//packages/shared-ux/page/kibana_no_data/impl:build", "//packages/shared-ux/page/kibana_no_data/impl:build",
"//packages/shared-ux/page/kibana_no_data/mocks:build", "//packages/shared-ux/page/kibana_no_data/mocks:build",
"//packages/shared-ux/page/kibana_no_data/types:build", "//packages/shared-ux/page/kibana_no_data/types:build",
"//packages/shared-ux/page/kibana_template/impl:build",
"//packages/shared-ux/page/kibana_template/mocks:build",
"//packages/shared-ux/page/kibana_template/types:build",
"//packages/shared-ux/page/no_data_config/impl:build",
"//packages/shared-ux/page/no_data_config/mocks:build",
"//packages/shared-ux/page/no_data_config/types:build",
"//packages/shared-ux/page/no_data/impl:build",
"//packages/shared-ux/page/no_data/mocks:build",
"//packages/shared-ux/page/no_data/types:build",
"//packages/shared-ux/page/solution_nav:build", "//packages/shared-ux/page/solution_nav:build",
"//packages/shared-ux/prompt/no_data_views/impl:build", "//packages/shared-ux/prompt/no_data_views/impl:build",
"//packages/shared-ux/prompt/no_data_views/mocks:build", "//packages/shared-ux/prompt/no_data_views/mocks:build",
"//packages/shared-ux/prompt/no_data_views/types:build", "//packages/shared-ux/prompt/no_data_views/types:build",
"//packages/shared-ux/storybook/config:build",
"//packages/shared-ux/storybook/mock:build", "//packages/shared-ux/storybook/mock:build",
"//x-pack/packages/ml/agg_utils:build", "//x-pack/packages/ml/agg_utils:build",
"//x-pack/packages/ml/aiops_components:build", "//x-pack/packages/ml/aiops_components:build",
@ -466,9 +473,6 @@ filegroup(
"//packages/kbn-server-http-tools:build_types", "//packages/kbn-server-http-tools:build_types",
"//packages/kbn-server-route-repository:build_types", "//packages/kbn-server-route-repository:build_types",
"//packages/kbn-shared-svg:build_types", "//packages/kbn-shared-svg:build_types",
"//packages/kbn-shared-ux-components:build_types",
"//packages/kbn-shared-ux-services:build_types",
"//packages/kbn-shared-ux-storybook:build_types",
"//packages/kbn-shared-ux-utility:build_types", "//packages/kbn-shared-ux-utility:build_types",
"//packages/kbn-some-dev-log:build_types", "//packages/kbn-some-dev-log:build_types",
"//packages/kbn-sort-package-json:build_types", "//packages/kbn-sort-package-json:build_types",
@ -503,9 +507,16 @@ filegroup(
"//packages/shared-ux/page/analytics_no_data/mocks:build_types", "//packages/shared-ux/page/analytics_no_data/mocks:build_types",
"//packages/shared-ux/page/kibana_no_data/impl:build_types", "//packages/shared-ux/page/kibana_no_data/impl:build_types",
"//packages/shared-ux/page/kibana_no_data/mocks:build_types", "//packages/shared-ux/page/kibana_no_data/mocks:build_types",
"//packages/shared-ux/page/kibana_template/impl:build_types",
"//packages/shared-ux/page/kibana_template/mocks:build_types",
"//packages/shared-ux/page/no_data_config/impl:build_types",
"//packages/shared-ux/page/no_data_config/mocks:build_types",
"//packages/shared-ux/page/no_data/impl:build_types",
"//packages/shared-ux/page/no_data/mocks:build_types",
"//packages/shared-ux/page/solution_nav:build_types", "//packages/shared-ux/page/solution_nav:build_types",
"//packages/shared-ux/prompt/no_data_views/impl:build_types", "//packages/shared-ux/prompt/no_data_views/impl:build_types",
"//packages/shared-ux/prompt/no_data_views/mocks:build_types", "//packages/shared-ux/prompt/no_data_views/mocks:build_types",
"//packages/shared-ux/storybook/config:build_types",
"//packages/shared-ux/storybook/mock:build_types", "//packages/shared-ux/storybook/mock:build_types",
"//x-pack/packages/ml/agg_utils:build_types", "//x-pack/packages/ml/agg_utils:build_types",
"//x-pack/packages/ml/aiops_components:build_types", "//x-pack/packages/ml/aiops_components:build_types",

View file

@ -41,7 +41,6 @@ NPM_MODULE_EXTRA_FILES = [
RUNTIME_DEPS = [ RUNTIME_DEPS = [
"//packages/kbn-i18n", "//packages/kbn-i18n",
"//packages/kbn-i18n-react", "//packages/kbn-i18n-react",
"//packages/kbn-shared-ux-storybook",
"//packages/kbn-interpreter", "//packages/kbn-interpreter",
"//packages/kbn-utility-types", "//packages/kbn-utility-types",
"//packages/kbn-shared-ux-utility", "//packages/kbn-shared-ux-utility",
@ -65,7 +64,6 @@ RUNTIME_DEPS = [
TYPES_DEPS = [ TYPES_DEPS = [
"//packages/kbn-i18n:npm_module_types", "//packages/kbn-i18n:npm_module_types",
"//packages/kbn-i18n-react:npm_module_types", "//packages/kbn-i18n-react:npm_module_types",
"//packages/kbn-shared-ux-storybook:npm_module_types",
"//packages/kbn-interpreter:npm_module_types", "//packages/kbn-interpreter:npm_module_types",
"//packages/kbn-utility-types:npm_module_types", "//packages/kbn-utility-types:npm_module_types",
"//packages/kbn-shared-ux-utility:npm_module_types", "//packages/kbn-shared-ux-utility:npm_module_types",

View file

@ -119,7 +119,6 @@ pageLoadAssetSize:
expressionGauge: 25000 expressionGauge: 25000
controls: 40000 controls: 40000
expressionPartitionVis: 26338 expressionPartitionVis: 26338
sharedUX: 16225
savedSearch: 16225 savedSearch: 16225
ux: 20784 ux: 20784
sessionView: 77750 sessionView: 77750

View file

@ -1,10 +0,0 @@
---
id: kibSharedUXComponents
slug: /kibana-dev-docs/shared-ux/packages/kbn-shared-ux-components
title: Shared UX Components
description:
date: 2022-03-11
tags: ['kibana', 'dev', 'sharedUX']
---
> TODO

View file

@ -1,13 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
// TODO: clintandrewhall - NoDataPageProps is a temporary addition until it is split into its own package
export type { KibanaPageTemplateProps, NoDataPageProps } from './page_template';
// TODO: clintandrewhall - NoDataConfigPage is a temporary addition until it is split into its own package
export { KibanaPageTemplate, NoDataConfigPage } from './page_template';

View file

@ -1,31 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`NoDataConfigPage renders 1`] = `
<EuiPageTemplate
className="kbnPageTemplate kbnPageTemplate--centeredBody"
pageContentProps={
Object {
"color": "transparent",
"hasShadow": false,
"paddingSize": "none",
}
}
restrictWidth={950}
template="centeredBody"
>
<NoDataPage
action={
Object {
"kibana": Object {
"button": "Click me",
"description": "Page with no data",
"onClick": [MockFunction],
},
}
}
docsLink="test-link"
logo="logoKibana"
solution="Kibana"
/>
</EuiPageTemplate>
`;

View file

@ -1,95 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import React, { useMemo, FunctionComponent } from 'react';
import useObservable from 'react-use/lib/useObservable';
import classNames from 'classnames';
import { EuiLink, EuiSpacer, EuiText, EuiTextColor } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { KibanaSolutionAvatar } from '@kbn/shared-ux-avatar-solution';
import { useSharedUxServices } from '@kbn/shared-ux-services';
import { NoDataCard, NoDataCardProvider } from '@kbn/shared-ux-card-no-data';
import { NoDataPageProps } from './types';
export const NoDataPage: FunctionComponent<NoDataPageProps> = ({
solution,
logo,
action,
docsLink,
pageTitle,
...rest
}) => {
const services = useSharedUxServices();
// TODO: clintandrewhall - including the `NoDataCardProvider` here is a temporary solution
// to consumers using this context to populate the NoDataPage. This will likely be removed soon,
// when NoDataPage is moved to its own package.
const currentAppId = useObservable(services.application.currentAppId$);
const noDataCardServices = {
currentAppId,
addBasePath: services.http.addBasePath,
canAccessFleet: services.permissions.canAccessFleet,
navigateToUrl: services.application.navigateToUrl,
};
const actionKeys = Object.keys(action);
const actionCard = useMemo(() => {
if (actionKeys.length !== 1) {
return null;
}
const actionKey = actionKeys[0];
const key =
actionKey === 'elasticAgent' ? 'empty-page-agent-action' : `empty-page-${actionKey}-action`;
return <NoDataCard key={key} {...action[actionKey]} />;
}, [action, actionKeys]);
const title =
pageTitle ||
i18n.translate('sharedUXComponents.noDataPage.welcomeTitle', {
defaultMessage: 'Welcome to Elastic {solution}!',
values: { solution },
});
return (
<div
className={classNames('kbnNoDataPageContents', rest.className)}
data-test-subj="kbnNoDataPage"
>
<EuiText textAlign="center">
<KibanaSolutionAvatar name={solution} iconType={logo || `logo${solution}`} size="xxl" />
<EuiSpacer size="l" />
<h1>{title}</h1>
<EuiTextColor color="subdued">
<p>
<FormattedMessage
id="sharedUXComponents.noDataPage.intro"
defaultMessage="Add your data to get started, or {link} about {solution}."
values={{
solution,
link: (
<EuiLink href={docsLink} target="_blank">
<FormattedMessage
id="sharedUXComponents.noDataPage.intro.link"
defaultMessage="learn more"
/>
</EuiLink>
),
}}
/>
</p>
</EuiTextColor>
</EuiText>
<EuiSpacer size="xxl" />
<NoDataCardProvider {...noDataCardServices}>{actionCard}</NoDataCardProvider>
</div>
);
};

View file

@ -1,154 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import React from 'react';
import { EuiButton, EuiText } from '@elastic/eui';
import { SolutionNavProps } from '@kbn/shared-ux-page-solution-nav';
import { KibanaPageTemplate } from './page_template';
import mdx from './page_template.mdx';
import { KibanaPageTemplateProps } from './types';
export default {
title: 'Page Template/Page Template',
description:
'A thin wrapper around `EuiTemplate`. Takes care of styling, empty state and no data config',
parameters: {
docs: {
page: mdx,
},
},
};
type Params = Pick<KibanaPageTemplateProps, 'isEmptyState' | 'pageHeader' | 'solutionNav'> & {
canBeCollapsed: boolean;
};
const noDataConfig = {
solution: 'Kibana',
action: {
elasticAgent: {},
},
docsLink: 'http://wwww.docs.elastic.co',
};
const items: SolutionNavProps['items'] = [
{
name: 'Ingest',
id: '1',
items: [
{
name: 'Ingest Node Pipelines',
id: '1.1',
},
{
name: 'Logstash Pipelines',
id: '1.2',
},
{
name: 'Beats Central Management',
id: '1.3',
},
],
},
{
name: 'Data',
id: '2',
items: [
{
name: 'Index Management',
id: '2.1',
},
{
name: 'Index Lifecycle Policies',
id: '2.2',
},
{
name: 'Snapshot and Restore',
id: '2.3',
},
],
},
];
const solutionNavBar = {
items,
logo: 'logoKibana',
name: 'Kibana',
action: { elasticAgent: {} },
};
const content = (
<EuiText textAlign="center">
<p>
<strong>Page Content goes here</strong>
</p>
</EuiText>
);
const header = {
iconType: 'logoKibana',
pageTitle: 'Kibana',
description: 'Welcome to Kibana!',
rightSideItems: [<EuiButton fill>Add something</EuiButton>, <EuiButton>Do something</EuiButton>],
};
export const WithNoDataConfig = () => {
return <KibanaPageTemplate noDataConfig={noDataConfig} />;
};
export const WithNoDataConfigAndSolutionNav = () => {
return <KibanaPageTemplate noDataConfig={noDataConfig} solutionNav={solutionNavBar} />;
};
export const PureComponent = (params: Params) => {
return (
<KibanaPageTemplate
{...params}
pageHeader={params.pageHeader ? header : undefined}
solutionNav={
params.solutionNav
? { ...solutionNavBar, canBeCollapsed: params.canBeCollapsed }
: undefined
}
>
{content}
</KibanaPageTemplate>
);
};
PureComponent.argTypes = {
isEmptyState: {
control: 'boolean',
defaultValue: false,
},
pageHeader: {
control: 'boolean',
defaultValue: true,
},
solutionNav: {
control: 'boolean',
defaultValue: true,
},
canBeCollapsed: {
control: 'boolean',
defaultValue: true,
},
};
PureComponent.parameters = {
layout: 'fullscreen',
};
WithNoDataConfig.parameters = {
layout: 'fullscreen',
};
WithNoDataConfigAndSolutionNav.parameters = {
layout: 'fullscreen',
};

View file

@ -1,13 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import classNames from 'classnames';
export const getClasses = (template: string | undefined, className: string | undefined) => {
return classNames('kbnPageTemplate', { [`kbnPageTemplate--${template}`]: template }, className);
};

View file

@ -1,203 +0,0 @@
---
id: kibSharedUXServices
slug: /kibana-dev-docs/shared-ux/packages/kbn-shared-ux-services
title: Shared UX Services
description: The `@kbn/shared-ux-services` package provides a thin service abstraction for components and solutions created by the Shared UX team.
date: 2022-03-11
tags: ['kibana', 'dev', 'sharedUX']
---
## About Shared UX Services
This package contains a set of services that are used by Shared UX components and solutions. This package serves as a thin abstraction layer between Kibana dependencies and the components in Shared UX that use them. It also allows us to "swap out" different implementations of the interfaces for different environments, (e.g. Storybook, Jest, etc). This decouples the components from what could be complicated or heavily-dependent logic that is difficult to mock.
## Implementations
Several implementations of these interfaces exist:
- `@kbn/shared-ux-services/src/services/stub`: A stub implementation free of dependencies, (and functionality).
- `@kbn/shared-ux-services/src/services/mock`: A Jest mock implementation used in `jest` tests.
- `@kbn/shared-ux-storybook/src/services/`: A Storybook implementation used in Storybook decorators and stories.
- `src/plugins/shared_ux/src/services/`: A Kibana implementation used in Kibana plugins.
Other implementations could easily be written to support other environments.
## Architecture
Lots of components require access to the services provided by other plugins. When we identify a routine that relies on these dependencies, we can write a new method and add it to a namespace, (e.g. `platform`, `user`, etc). These namespaces become interfaces of simple methods stored in `@kbn/shared-ux-services`. From there, we can create implementations for each environment we support.
Suppose we're creating a new service, `SharedUxFooService`:
```ts
interface SharedUxFooService {
getFoo(): string;
setBar(bar: string): void;
isBaz(): boolean;
}
```
Once defined, we create factories to create those services.
### Creating a `ServiceFactory`
A `ServiceFactory` is a simple type that describes 1/ what service is being created, and 2/ what parameters are required to create that service for a given environment.
### Stub and Mock Factories
Given the service definition above, we can create a `ServiceFactory` for a stubbed service that gives the bare minimum of functionality:
```ts
/**
* A factory function for creating a stubbed implementation of `SharedUxFooService`.
*/
export type FooServiceFactory = ServiceFactory<SharedUxFooService>;
/**
* A factory function for creating a stubbed implementation of `SharedUxFooService`.
*/
export const fooServiceFactory: FooServiceFactory = () => ({
getFoo: () => 'foo',
setBar: () => {},
isBaz: () => false,
});
```
We can also create a mock for Jest:
```ts
/**
* A factory function for creating a mock implementation of `SharedUxFooService`.
*/
export type FooServiceFactory = ServiceFactory<SharedUxFooService>;
/**
* A factory function for creating a stubbed implementation of `SharedUxFooService`.
*/
export const fooServiceFactory: FooServiceFactory = () => ({
getFoo: () => jest.fn(),
setBar: () => jest.fn(),
isBaz: () => jest.fn(),
});
```
### Storybook Factories
Storybook is where we can begin to take advantage of `Parameters` for a given service. Since stories can use controls to provide parameters, we can create a `ServiceFactory` that uses the `Parameters` generic and returns a `SharedUxFooService` that uses their values.
```ts
import { action } from '@storybook/addon-actions';
interface FooServiceStorybookParameters {
foo: string;
baz: boolean;
}
/**
* A factory function for creating a Storybook implementation of `SharedUxFooService`.
*/
export type FooServiceFactory = ServiceFactory<SharedUxFooService, StorybookParameters>;
/**
* A factory function for creating a stubbed implementation of `SharedUxFooService`.
*/
export const fooServiceFactory: FooServiceFactory = ({ foo, baz }) => ({
getFoo: () => foo,
setBar: () => action('setBar'),
isBaz: () => baz,
});
```
A story can then optionally provide values for those parameters as part of its controls.
```ts
type Params = Pick<FooServiceStorybookParameters, 'foo'>;
export const ComponentStory = ({ foo }: Params) => {
const service = fooServiceFactory({ foo, baz: false });
return (
<SharedUxServicesContext.Provider value={service}><Component /></SharedUxServicesContext.Provider>;
};
PureComponent.argTypes = {
foo: {
options: ['alpha', 'beta', 'gamma', 'delta'],
control: { type: 'radio' },
},
};
```
### Kibana Factories
Using these services in Kibana is a bit more complex, but is still relatively simple. First, we define what dependencies we'll need, (we use this interface in `src/plugins/shared_ux` as it relies on types found only in plugins, where packages cannot use them):
```ts
/**
* Parameters necessary to create a Kibana-based service, (e.g. during Plugin
* startup or setup).
*
* The `Start` generic refers to the specific Plugin `TPluginsStart`.
*/
export interface KibanaPluginServiceParams<Start extends {}> {
coreStart: CoreStart;
startPlugins: Start;
appUpdater?: BehaviorSubject<AppUpdater>;
initContext?: PluginInitializerContext;
}
/**
* A factory function for creating a Kibana-based service.
*
* The `Service` generic determines the shape of the Service being produced.
* The `Start` generic refers to the specific Plugin `TPluginsStart`.
*/
export type KibanaPluginServiceFactory<Service, Start extends {}> = (
params: KibanaPluginServiceParams<Start>
) => Service;
```
From there, a plugin might have a collection of dependencies on core or other plugins:
```ts
export interface MyPluginStartDeps {
bar: BarPluginStart;
baz: BazPluginStart;
}
```
We'd then use this dependency interface to create a `ServiceFactory` for our service in Kibana:
```ts
export type FooServiceFactory = KibanaPluginServiceFactory<
SharedUxFooService,
MyPluginStartDeps
>;
/**
* A factory function for creating a Kibana-based implementation of `SharedUxFooService`.
*/
export const fooServiceFactory: FooServiceFactory = ({ coreStart, startPlugins }) => ({
getFoo: startPlugins.bar.getSomeOtherFoo,
setBar: startPlugins.baz.setHappyPathBar,
isBaz: () => {
return coreStart.uiSettings.get('someSetting') === 'expectedValue';
}
});
```
From there, the pattern is the same: invoke the service factory with the required dependencies and provide them to the `SharedUxServicesContext` Provider:
```ts
// plugin.tsx
public start(coreStart: CoreStart, startPlugins: SharedUXPluginStartDeps): SharedUXPluginStart {
const fooService = fooServiceFactory({ coreStart, startPlugins });
const Context = <SharedUxServicesProvider services={{ fooService }}>{children}</SharedUxServicesProvider>;
// ...wrap React content with the context..
}
```
## Use in Kibana plugins
In order to make consumption of these services easy by Kibana plugins, `src/plugins/shared_ux` provides a pre-wired set of services as part of the `start` lifecycle. Plugins can simply make `sharedUX` a dependency, import `SharedUxServicesProvider` and wrap their solution root (or any component). See the documentation for `sharedUX` for more details.

View file

@ -1,70 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import React, { FC, createContext, useContext } from 'react';
import type { SharedUxServices } from './types';
// The React Context used to provide the services to the SharedUX components.
const SharedUxServicesContext = createContext<SharedUxServices | null>(null);
/**
* The `React.Context` Provider component for the `SharedUxServices` context. Any
* plugin or environment that consumes SharedUX components needs to wrap their React
* tree with this provider.
*
* Within a plugin, you can use use the Shared UX plugin and retrieve a fully-configured
* context from the `start` contract.
*/
export const SharedUxServicesProvider: FC<SharedUxServices> = ({ children, ...services }) => (
<SharedUxServicesContext.Provider value={services}>{children}</SharedUxServicesContext.Provider>
);
/**
* React hook for accessing pre-wired `SharedUxServices`.
*/
export function useSharedUxServices() {
const context = useContext(SharedUxServicesContext);
if (!context) {
throw new Error(
'SharedUxServicesContext missing. Ensure your component or React root is wrapped with SharedUxServicesProvider.'
);
}
return context;
}
/**
* React hook for accessing the pre-wired `SharedUxPlatformService`.
*/
export const usePlatformService = () => useSharedUxServices().platform;
/**
* React hook for accessing the pre-wired `SharedUxPermissionsService`.
*/
export const usePermissions = () => useSharedUxServices().permissions;
/**
* React hook for accessing the pre-wired `SharedUxEditorsService`.
*/
export const useEditors = () => useSharedUxServices().editors;
/**
* React hook for accessing the pre-wired `SharedUxDocLinksService`.
*/
export const useDocLinks = () => useSharedUxServices().docLinks;
export const useHttp = () => useSharedUxServices().http;
export const useApplication = () => useSharedUxServices().application;
/**
* React hook for accessing the pre-wired `SharedUxDataService`.
*/
export const useData = () => useSharedUxServices().data;

View file

@ -1,38 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
export type { ServiceFactory, SharedUxServices, SharedUxServicesContext } from './types';
export type {
MockServicesFactoryParams,
SharedUxApplicationService,
SharedUxDocLinksService,
SharedUxEditorsService,
SharedUxHttpService,
SharedUxPlatformService,
SharedUxUserPermissionsService,
SharedUxDataService,
} from './services';
export {
SharedUxServicesProvider,
useApplication,
useDocLinks,
useEditors,
useHttp,
usePermissions,
usePlatformService,
useData,
useSharedUxServices,
} from './context';
export {
mockServiceFactories,
mockServicesFactory,
stubServiceFactories,
stubServicesFactory,
} from './services';

View file

@ -1,19 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
/**
* A service providing data information. Typically used for handling of empty state..
*/
export interface SharedUxDataService {
/** True if the cluster contains data, false otherwise. */
hasESData: () => Promise<boolean>;
/** True if Kibana instance contains user-created data view, false otherwise. */
hasUserDataView: () => Promise<boolean>;
/** True if Kibana instance contains any data view, including system-created ones. */
hasDataView: () => Promise<boolean>;
}

View file

@ -1,15 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
/**
* A service providing links to documentation about various features in Kibana.
*/
export interface SharedUxDocLinksService {
/** A link to information about Data Views in Kibana */
dataViewsDocLink: string;
}

View file

@ -1,36 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
/**
* TODO: `DataView` is a class exported by `src/plugins/data_views/public`. Since this service
* is contained in this package-- and packages can only depend on other packages and never on
* plugins-- we have to set this to `unknown`. If and when `DataView` is exported from a
* stateless package, we can remove this.
*
* @see: https://github.com/elastic/kibana/issues/127695
*/
type DataView = unknown;
/**
* A subset of the `DataViewEditorOptions` interface relevant to our service and components.
*
* @see: src/plugins/data_view_editor/public/types.ts
*/
interface DataViewEditorOptions {
/** Handler to be invoked when the Data View Editor completes a save operation. */
onSave: (dataView: DataView) => void;
}
/**
* A service providing methods to invoke and interact with various editors provided
* in Kibana.
*/
export interface SharedUxEditorsService {
/** A method to open the Data View Editor flow. */
openDataViewEditor: (options: DataViewEditorOptions) => () => void;
}

View file

@ -1,11 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
export interface SharedUxHttpService {
addBasePath: (url: string) => string;
}

View file

@ -1,21 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
export type { SharedUxApplicationService } from './application';
export type { SharedUxDocLinksService } from './doc_links';
export type { SharedUxEditorsService } from './editors';
export type { SharedUxHttpService } from './http';
export type { SharedUxUserPermissionsService } from './permissions';
export type { SharedUxPlatformService } from './platform';
export type { SharedUxDataService } from './data';
export type { MockServicesFactoryParams } from './mock';
// eslint-disable-next-line @kbn/imports/no_boundary_crossing
export { mockServicesFactory, mockServiceFactories } from './mock';
// eslint-disable-next-line @kbn/imports/no_boundary_crossing
export { stubServicesFactory, stubServiceFactories } from './stub';

View file

@ -1,23 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { Observable } from 'rxjs';
import { ServiceFactory } from '../../types';
import { SharedUxApplicationService } from '../application';
export type MockApplicationServiceFactory = ServiceFactory<SharedUxApplicationService>;
/**
* A factory function for creating a Jest-based implementation of `SharedUXApplicationService`.
*/
export const applicationServiceFactory: MockApplicationServiceFactory = () => ({
navigateToUrl: () => Promise.resolve(),
currentAppId$: new Observable((subscriber) => {
subscriber.next('abc123');
}),
});

View file

@ -1,32 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { ServiceFactory } from '../../types';
import { SharedUxDataService } from '../data';
/**
* A factory function for creating a Jest-based implementation of `SharedUxDataService`.
*/
export type MockDataServiceFactory = ServiceFactory<SharedUxDataService>;
export interface MockDataServiceFactoryConfig {
hasESData: boolean;
hasDataView: boolean;
hasUserDataView: boolean;
}
/**
* A factory function for creating a Jest-based implementation of `SharedUxDataService`.
*/
export const dataServiceFactory: (config?: MockDataServiceFactoryConfig) => SharedUxDataService = (
config?: MockDataServiceFactoryConfig
) => ({
hasESData: () => Promise.resolve(config?.hasESData || false),
hasDataView: () => Promise.resolve(config?.hasDataView || false),
hasUserDataView: () => Promise.resolve(config?.hasUserDataView || false),
});

View file

@ -1,22 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import type { ServiceFactory } from '../../types';
import type { SharedUxDocLinksService } from '../doc_links';
/**
* A factory function for creating a Jest implementation of `SharedUxDocLinksService`.
*/
export type MockDocLinksServiceFactory = ServiceFactory<SharedUxDocLinksService>;
/**
* A factory function for creating a Jest-based implementation of `SharedUxDocLinksService`.
*/
export const docLinksServiceFactory: MockDocLinksServiceFactory = () => ({
dataViewsDocLink: 'dummy link',
});

View file

@ -1,22 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import type { ServiceFactory } from '../../types';
import type { SharedUxEditorsService } from '../editors';
/**
* A factory function for creating a Jest-based implementation of `SharedUxEditorsService`.
*/
export type MockEditorsServiceFactory = ServiceFactory<SharedUxEditorsService>;
/**
* A factory function for creating a Jest-based implementation of `SharedUxEditorsService`.
*/
export const editorsServiceFactory: MockEditorsServiceFactory = () => ({
openDataViewEditor: jest.fn(),
});

View file

@ -1,19 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { ServiceFactory } from '../../types';
import { SharedUxHttpService } from '../http';
export type MockHttpServiceFactory = ServiceFactory<SharedUxHttpService>;
/**
* A factory function for creating a Jest-based implementation of `SharedUXHttpService`.
*/
export const httpServiceFactory: MockHttpServiceFactory = () => ({
addBasePath: jest.fn((path: string) => (path ? path : 'path')),
});

View file

@ -1,64 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import type { SharedUxServices } from '../../types';
import { applicationServiceFactory } from './application.mock';
import { docLinksServiceFactory } from './doc_links.mock';
import { editorsServiceFactory } from './editors.mock';
import { httpServiceFactory } from './http.mock';
import { userPermissionsServiceFactory } from './permissions.mock';
import { platformServiceFactory } from './platform.mock';
import { dataServiceFactory, MockDataServiceFactoryConfig } from './data.mock';
export type { MockApplicationServiceFactory } from './application.mock';
export type { MockDocLinksServiceFactory } from './doc_links.mock';
export type { MockEditorsServiceFactory } from './editors.mock';
export type { MockHttpServiceFactory } from './http.mock';
export type { MockUserPermissionsServiceFactory } from './permissions.mock';
export type { MockPlatformServiceFactory } from './platform.mock';
export { applicationServiceFactory } from './application.mock';
export { docLinksServiceFactory } from './doc_links.mock';
export { editorsServiceFactory } from './editors.mock';
export { httpServiceFactory } from './http.mock';
export { userPermissionsServiceFactory } from './permissions.mock';
export { platformServiceFactory } from './platform.mock';
export { dataServiceFactory } from './data.mock';
export interface MockServicesFactoryParams {
config: MockDataServiceFactoryConfig;
}
/**
* A factory function for creating a Jest-based implementation of `SharedUxServices`.
*/
export const mockServicesFactory: (params?: MockServicesFactoryParams) => SharedUxServices = (
params?: MockServicesFactoryParams
) => ({
application: applicationServiceFactory(),
docLinks: docLinksServiceFactory(),
editors: editorsServiceFactory(),
http: httpServiceFactory(),
permissions: userPermissionsServiceFactory(),
platform: platformServiceFactory(),
data: dataServiceFactory(params?.config),
});
/**
* A collection of mock Service Factories.
*/
export const mockServiceFactories = {
applicationServiceFactory,
docLinksServiceFactory,
editorsServiceFactory,
httpServiceFactory,
platformServiceFactory,
userPermissionsServiceFactory,
dataServiceFactory,
};

View file

@ -1,23 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import type { ServiceFactory } from '../../types';
import type { SharedUxUserPermissionsService } from '../permissions';
/**
* A factory function for creating a Jest-based implementation of `SharedUxUserPermissionsService`.
*/
export type MockUserPermissionsServiceFactory = ServiceFactory<SharedUxUserPermissionsService>;
/**
* A factory function for creating a Jest-based implementation of `SharedUxUserPermissionsService`.
*/
export const userPermissionsServiceFactory: MockUserPermissionsServiceFactory = () => ({
canCreateNewDataView: true,
canAccessFleet: true,
});

View file

@ -1,22 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import type { ServiceFactory } from '../../types';
import type { SharedUxPlatformService } from '../platform';
/**
* A factory function for creating a Jest-based implementation of `SharedUxPlatformService`.
*/
export type MockPlatformServiceFactory = ServiceFactory<SharedUxPlatformService>;
/**
* A factory function for creating a Jest-based implementation of `SharedUxPlatformService`.
*/
export const platformServiceFactory: MockPlatformServiceFactory = () => ({
setIsFullscreen: jest.fn(),
});

View file

@ -1,16 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
/**
* A service providing permissions information, typically for the current user.
*/
export interface SharedUxUserPermissionsService {
/** True if the user has permission to create a new Data View, false otherwise. */
canCreateNewDataView: boolean;
canAccessFleet: boolean;
}

View file

@ -1,24 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
/**
* A service providing methods to interact with the platform in which this code is
* running, (almost always Kibana).
*
* Rather than provide the entire `CoreStart` contract to components, we provide simplified
* abstractions around a use case specific to Shared UX. This way, we know exactly how the
* `CoreStart` and other plugins are used. This makes mocking and refactoring easier when
* upstream dependencies change.
*/
export interface SharedUxPlatformService {
/**
* Sets the fullscreen state of the chrome.
* @param isFullscreen True if the chrome should be fullscreen, false otherwise.
*/
setIsFullscreen: (isFullscreen: boolean) => void;
}

View file

@ -1,27 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { Observable } from 'rxjs';
import { ServiceFactory } from '../../types';
import { SharedUxApplicationService } from '../application';
export type ApplicationServiceFactory = ServiceFactory<SharedUxApplicationService>;
/**
* A factory function for creating for creating a simple stubbed implementation of `SharedUXApplicationService`.
*/
export const applicationServiceFactory: ApplicationServiceFactory = () => ({
navigateToUrl: (url) => {
// eslint-disable-next-line no-console
console.log(url);
return Promise.resolve();
},
currentAppId$: new Observable((subscriber) => {
subscriber.next('123');
}),
});

View file

@ -1,24 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { ServiceFactory } from '../../types';
import { SharedUxDataService } from '../data';
/**
* A factory function for creating a simple stubbed implementation of `SharedUxDataSevice`.
*/
export type DataServiceFactory = ServiceFactory<SharedUxDataService>;
/**
* A factory function for creating a simple stubbed implementation of `SharedUxDataSevice`.
*/
export const dataServiceFactory: DataServiceFactory = () => ({
hasESData: () => Promise.resolve(true),
hasDataView: () => Promise.resolve(false),
hasUserDataView: () => Promise.resolve(false),
});

View file

@ -1,22 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import type { ServiceFactory } from '../../types';
import type { SharedUxDocLinksService } from '../doc_links';
/**
* A factory function for creating a stubbed implementation of `SharedUxDocLinksService`.
*/
export type DocLinksServiceFactory = ServiceFactory<SharedUxDocLinksService>;
/**
* A factory function for creating a stubbed implementation of `SharedUxDocLinksService`.
*/
export const docLinksServiceFactory: DocLinksServiceFactory = () => ({
dataViewsDocLink: 'docs',
});

View file

@ -1,22 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import type { ServiceFactory } from '../../types';
import type { SharedUxEditorsService } from '../editors';
/**
* A factory function for creating a simple stubbed implementation of `SharedUxEditorsService`.
*/
export type EditorsServiceFactory = ServiceFactory<SharedUxEditorsService>;
/**
* A factory function for creating a simple stubbed implementation of `SharedUxEditorsService`.
*/
export const editorsServiceFactory: EditorsServiceFactory = () => ({
openDataViewEditor: () => () => {},
});

View file

@ -1,24 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { ServiceFactory } from '../../types';
import { SharedUxHttpService } from '../http';
/**
* A factory function for creating a simple stubbed implementation of `SharedUXHttpService`.
*/
export type HttpServiceFactory = ServiceFactory<SharedUxHttpService>;
/**
* A factory function for creating a simple stubbed implementation of `SharedUXHttpService`.
*/
export const httpServiceFactory: HttpServiceFactory = () => ({
addBasePath: (url: string) => {
return url;
},
});

View file

@ -1,43 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import type { SharedUxServices, ServiceFactory } from '../../types';
import { applicationServiceFactory } from './application';
import { docLinksServiceFactory } from './doc_links';
import { editorsServiceFactory } from './editors';
import { httpServiceFactory } from './http';
import { platformServiceFactory } from './platform';
import { userPermissionsServiceFactory } from './permissions';
import { dataServiceFactory } from './data';
/**
* A factory function for creating simple stubbed implementations of all `SharedUxServices`.
*/
export const stubServicesFactory: ServiceFactory<SharedUxServices> = () => ({
application: applicationServiceFactory(),
docLinks: docLinksServiceFactory(),
editors: editorsServiceFactory(),
http: httpServiceFactory(),
permissions: userPermissionsServiceFactory(),
platform: platformServiceFactory(),
data: dataServiceFactory(),
});
/**
* A collection of stubbed service factories.
*/
export const stubServiceFactories = {
applicationServiceFactory,
docLinksServiceFactory,
editorsServiceFactory,
httpServiceFactory,
platformServiceFactory,
userPermissionsServiceFactory,
dataServiceFactory,
};

View file

@ -1,23 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import type { ServiceFactory } from '../../types';
import type { SharedUxUserPermissionsService } from '../permissions';
/**
* A factory function for creating a simple stubbed implementation of `SharedUxUserPermissionsService`.
*/
export type UserPermissionsServiceFactory = ServiceFactory<SharedUxUserPermissionsService>;
/**
* A factory function for creating a simple stubbed implementation of `SharedUxUserPermissionsService`.
*/
export const userPermissionsServiceFactory: UserPermissionsServiceFactory = () => ({
canCreateNewDataView: true,
canAccessFleet: true,
});

View file

@ -1,22 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import type { ServiceFactory } from '../../types';
import type { SharedUxPlatformService } from '../platform';
/**
* A factory function for creating a simple stubbed implementation of `SharedUxPlatformService`.
*/
export type PlatformServiceFactory = ServiceFactory<SharedUxPlatformService>;
/**
* A factory function for creating a simple stubbed implementation of `SharedUxPlatformService`.
*/
export const platformServiceFactory: PlatformServiceFactory = () => ({
setIsFullscreen: (_isFullscreen) => {},
});

View file

@ -1,52 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { FC } from 'react';
import {
SharedUxApplicationService,
SharedUxDataService,
SharedUxDocLinksService,
SharedUxEditorsService,
SharedUxHttpService,
SharedUxPlatformService,
SharedUxUserPermissionsService,
} from './services';
/**
* A collection of services utilized by SharedUX. This serves as a thin
* abstraction layer between services provided by Kibana and other plugins
* while allowing this plugin to be developed independently of those contracts.
*
* It also allows us to "swap out" differenct implementations of these services
* for different environments, (e.g. Jest, Storybook, etc.)
*/
export interface SharedUxServices {
application: SharedUxApplicationService;
docLinks: SharedUxDocLinksService;
editors: SharedUxEditorsService;
http: SharedUxHttpService;
permissions: SharedUxUserPermissionsService;
platform: SharedUxPlatformService;
data: SharedUxDataService;
}
/**
* A type representing a component that provides the `SharedUxServices` through a
* React Context.
*/
export type SharedUxServicesContext = FC<{}>;
/**
* A factory function for creating one or more services.
*
* The `S` generic determines the shape of the API being produced.
* The `Parameters` generic determines what parameters are expected to
* create the service.
*/
export type ServiceFactory<S, Parameters = void> = (params: Parameters) => S;

View file

@ -1,34 +0,0 @@
---
id: kibSharedUXStorybook
slug: /kibana-dev-docs/shared-ux/packages/kbn-shared-ux-storybook
title: Shared UX Storybook
description: The `@kbn/shared-ux-storybook` package provides Storybook assets for Shared UX and other teams.
date: 2022-03-11
tags: ['kibana', 'dev', 'sharedUX']
---
## About Shared UX Storybook
This package provides the Storybook implementation of `@kbn/shared-ux-services` as well as the configuration for the Shared UX Storybook site.
- `/src/services` The `@kbn/shared-ux-services` implementation.
- `src/config` The Storybook site configuration.
## Storybook site
Run `yarn storybook shared_ux` from `/kibana` to view the site. It pulls in `*.stories.tsx` from all Shared UX packages and plugins and combines them into a single configuration.
## Decorator
If you're writing stories for your own components that compose Shared UX components, you can use a pre-configured [Storybook Decorator](https://storybook.js.org/docs/react/writing-stories/decorators) in your Storybook configuration:
```ts
// preview.ts
import { addDecorator } from '@storybook/react';
import { servicesDecorator } from '@kbn/shared-ux-storybook';
addDecorator(servicesDecorator);
```
This will not only expose parameters, but also wrap your story in a pre-wired `SharedUxServicesProvider`.

View file

@ -1,12 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { addDecorator } from '@storybook/react';
import { servicesDecorator } from '../decorators';
addDecorator(servicesDecorator);

View file

@ -1,22 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import React from 'react';
import { DecoratorFn } from '@storybook/react';
import { SharedUxServicesProvider } from '@kbn/shared-ux-services';
import { servicesFactory } from './services';
/**
* A Storybook decorator that provides the Shared UX `ServicesProvider` with Storybook-specific
* implementations to stories.
*/
export const servicesDecorator: DecoratorFn = (storyFn) => (
<SharedUxServicesProvider {...servicesFactory({})}>{storyFn()}</SharedUxServicesProvider>
);

View file

@ -1,22 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
export { servicesDecorator } from './decorators';
export {
applicationServiceFactory,
docLinksServiceFactory,
editorsServiceFactory,
httpServiceFactory,
platformServiceFactory,
servicesFactory,
userPermissionsServiceFactory,
dataServiceFactory,
} from './services';
export type { DataServiceFactoryConfig } from './services';

View file

@ -1,24 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { BehaviorSubject } from 'rxjs';
import { action } from '@storybook/addon-actions';
import { ServiceFactory, SharedUxApplicationService } from '@kbn/shared-ux-services';
export type ApplicationServiceFactory = ServiceFactory<SharedUxApplicationService>;
/**
* A factory function for creating for creating a storybook implementation of `SharedUXApplicationService`.
*/
export const applicationServiceFactory: ApplicationServiceFactory = () => ({
navigateToUrl: (url) => {
action('navigateToUrl')(url);
return Promise.resolve();
},
currentAppId$: new BehaviorSubject('123'),
});

View file

@ -1,34 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { ServiceFactory, SharedUxDataService } from '@kbn/shared-ux-services';
export interface DataServiceFactoryConfig {
hasESData: boolean;
hasDataView: boolean;
hasUserDataView: boolean;
}
/**
* A factory function for creating a Storybook implementation of `SharedUxDataService`.
*/
export type SharedUxDataServiceFactory = ServiceFactory<
SharedUxDataService,
DataServiceFactoryConfig
>;
/**
* A factory function for creating a Storybook implementation of `SharedUxDataService`.
*/
export const dataServiceFactory: SharedUxDataServiceFactory = (params) => {
return {
hasESData: () => Promise.resolve(params.hasESData || false),
hasDataView: () => Promise.resolve(params.hasDataView || false),
hasUserDataView: () => Promise.resolve(params.hasUserDataView || false),
};
};

View file

@ -1,22 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { ServiceFactory, SharedUxDocLinksService } from '@kbn/shared-ux-services';
/**
* A factory function for creating a Storybook implementation of `SharedUxDocLinksService`.
*/
export type SharedUxDocLinksServiceFactory = ServiceFactory<SharedUxDocLinksService>;
/**
* A factory function for creating a Storybook implementation of `SharedUxDocLinksService`.
*/
export const docLinksServiceFactory: SharedUxDocLinksServiceFactory = () => ({
dataViewsDocLink: 'https://www.elastic.co/guide/en/kibana/master/data-views.html',
kibanaGuideDocLink: 'https://www.elastic.co/guide/en/kibana/master/index.html',
});

View file

@ -1,22 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { action } from '@storybook/addon-actions';
import { ServiceFactory, SharedUxEditorsService } from '@kbn/shared-ux-services';
/**
* A factory function for creating a Storybook implementation of `SharedUxEditorsService`.
*/
export type SharedUxEditorsServiceFactory = ServiceFactory<SharedUxEditorsService>;
/**
* A factory function for creating a Storybook implementation of `SharedUxEditorsService`.
*/
export const editorsServiceFactory: SharedUxEditorsServiceFactory = () => ({
openDataViewEditor: action('openEditor') as SharedUxEditorsService['openDataViewEditor'],
});

View file

@ -1,23 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { action } from '@storybook/addon-actions';
import { ServiceFactory, SharedUxHttpService } from '@kbn/shared-ux-services';
/**
* A factory function for creating a Storybook-based implementation of `SharedUXHttpService`.
*/
export type HttpServiceFactory = ServiceFactory<SharedUxHttpService, {}>;
/**
* A factory function for creating a Storybook-based implementation of `SharedUXHttpService`.
*/
export const httpServiceFactory: HttpServiceFactory = () => ({
addBasePath: action('addBasePath') as SharedUxHttpService['addBasePath'],
});

View file

@ -1,40 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import type { ServiceFactory, SharedUxServices } from '@kbn/shared-ux-services';
import { applicationServiceFactory } from './application';
import { docLinksServiceFactory } from './doc_links';
import { editorsServiceFactory } from './editors';
import { httpServiceFactory } from './http';
import { platformServiceFactory } from './platform';
import { userPermissionsServiceFactory } from './permissions';
import { dataServiceFactory, DataServiceFactoryConfig } from './data';
export { applicationServiceFactory } from './application';
export { docLinksServiceFactory } from './doc_links';
export { editorsServiceFactory } from './editors';
export { httpServiceFactory } from './http';
export { platformServiceFactory } from './platform';
export { userPermissionsServiceFactory } from './permissions';
export { dataServiceFactory } from './data';
/**
* A factory function for creating a Storybook implementation of `SharedUxServices`.
*/
export const servicesFactory: ServiceFactory<SharedUxServices, {}> = (params) => ({
application: applicationServiceFactory(),
docLinks: docLinksServiceFactory(),
editors: editorsServiceFactory(),
http: httpServiceFactory(params),
permissions: userPermissionsServiceFactory(),
platform: platformServiceFactory(params),
data: dataServiceFactory(params as DataServiceFactoryConfig),
});
export type { DataServiceFactoryConfig } from './data';

View file

@ -1,22 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { ServiceFactory, SharedUxUserPermissionsService } from '@kbn/shared-ux-services';
/**
* A factory function for creating a Storybook implementation of `SharedUxUserPermissionsService`.
*/
export type SharedUxUserPermissionsServiceFactory = ServiceFactory<SharedUxUserPermissionsService>;
/**
* A factory function for creating a Storybook implementation of `SharedUxUserPermissionsService`.
*/
export const userPermissionsServiceFactory: SharedUxUserPermissionsServiceFactory = () => ({
canCreateNewDataView: true,
canAccessFleet: true,
});

View file

@ -1,22 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { action } from '@storybook/addon-actions';
import { ServiceFactory, SharedUxPlatformService } from '@kbn/shared-ux-services';
/**
* A factory function for creating a Storybook implementation of `SharedUxPlatformService`.
*/
export type PlatformServiceFactory = ServiceFactory<SharedUxPlatformService, {}>;
/**
* A factory function for creating a Storybook implementation of `SharedUxPlatformService`.
*/
export const platformServiceFactory: PlatformServiceFactory = () => ({
setIsFullscreen: action('setIsChromeVisible'),
});

View file

@ -10,7 +10,7 @@ import React from 'react';
import { KibanaSolutionAvatar, IconTypeProps, KnownSolutionProps } from './solution_avatar'; import { KibanaSolutionAvatar, IconTypeProps, KnownSolutionProps } from './solution_avatar';
export default { export default {
title: 'Solution Avatar', title: 'Avatar/Solution',
description: 'A wrapper around EuiAvatar, specifically to stylize Elastic Solutions', description: 'A wrapper around EuiAvatar, specifically to stylize Elastic Solutions',
}; };
@ -24,11 +24,11 @@ const argTypes = {
type KnownSolutionParams = Pick<KnownSolutionProps, 'size' | 'name'>; type KnownSolutionParams = Pick<KnownSolutionProps, 'size' | 'name'>;
export const SolutionAvatar = (params: KnownSolutionParams) => { export const SolutionType = (params: KnownSolutionParams) => {
return <KibanaSolutionAvatar {...params} />; return <KibanaSolutionAvatar {...params} />;
}; };
SolutionAvatar.argTypes = { SolutionType.argTypes = {
name: { name: {
control: 'select', control: 'select',
options: ['Cloud', 'Elastic', 'Kibana', 'Observability', 'Security', 'Enterprise Search'], options: ['Cloud', 'Elastic', 'Kibana', 'Observability', 'Security', 'Enterprise Search'],
@ -39,11 +39,11 @@ SolutionAvatar.argTypes = {
type IconTypeParams = Pick<IconTypeProps, 'size' | 'name' | 'iconType'>; type IconTypeParams = Pick<IconTypeProps, 'size' | 'name' | 'iconType'>;
export const IconTypeAvatar = (params: IconTypeParams) => { export const IconType = (params: IconTypeParams) => {
return <KibanaSolutionAvatar {...params} />; return <KibanaSolutionAvatar {...params} />;
}; };
IconTypeAvatar.argTypes = { IconType.argTypes = {
iconType: { iconType: {
control: 'select', control: 'select',
options: [ options: [

View file

@ -10,8 +10,17 @@ SOURCE_FILES = glob(
"src/**/*.ts", "src/**/*.ts",
], ],
exclude = [ exclude = [
"**/*.config.js",
"**/*.mock.*",
"**/*.test.*", "**/*.test.*",
"**/*.stories.*", "**/*.stories.*",
"**/__snapshots__",
"**/integration_tests",
"**/mocks",
"**/scripts",
"**/storybook",
"**/test_fixtures",
"**/test_helpers",
], ],
) )
@ -38,6 +47,7 @@ NPM_MODULE_EXTRA_FILES = [
# eg. "@npm//lodash" # eg. "@npm//lodash"
RUNTIME_DEPS = [ RUNTIME_DEPS = [
"@npm//@storybook/addon-actions", "@npm//@storybook/addon-actions",
"@npm//react",
"//packages/shared-ux/storybook/mock", "//packages/shared-ux/storybook/mock",
] ]
@ -53,6 +63,7 @@ RUNTIME_DEPS = [
TYPES_DEPS = [ TYPES_DEPS = [
"@npm//@types/node", "@npm//@types/node",
"@npm//@types/jest", "@npm//@types/jest",
"@npm//@types/react",
"@npm//@storybook/addon-actions", "@npm//@storybook/addon-actions",
"//packages/shared-ux/button/exit_full_screen/types:npm_module_types", "//packages/shared-ux/button/exit_full_screen/types:npm_module_types",
"//packages/shared-ux/storybook/mock:npm_module_types", "//packages/shared-ux/storybook/mock:npm_module_types",
@ -65,6 +76,14 @@ jsts_transpiler(
root_input_dir = "src", root_input_dir = "src",
) )
jsts_transpiler(
name = "target_web",
srcs = SRCS,
build_pkg_name = package_name(),
root_input_dir = "src",
web = True,
)
ts_config( ts_config(
name = "tsconfig", name = "tsconfig",
src = "tsconfig.json", src = "tsconfig.json",
@ -90,7 +109,7 @@ ts_project(
js_library( js_library(
name = PKG_DIRNAME, name = PKG_DIRNAME,
srcs = NPM_MODULE_EXTRA_FILES, srcs = NPM_MODULE_EXTRA_FILES,
deps = RUNTIME_DEPS + [":target_node"], deps = RUNTIME_DEPS + [":target_node", ":target_web"],
package_name = PKG_REQUIRE_NAME, package_name = PKG_REQUIRE_NAME,
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
) )

View file

@ -1,13 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
module.exports = {
preset: '@kbn/test/jest_node',
rootDir: '../../../../..',
roots: ['<rootDir>/packages/shared-ux/button/exit_full_screen/mocks'],
};

View file

@ -3,5 +3,6 @@
"private": true, "private": true,
"version": "1.0.0", "version": "1.0.0",
"main": "./target_node/index.js", "main": "./target_node/index.js",
"browser": "./target_web/index.js",
"license": "SSPL-1.0 OR Elastic License 2.0" "license": "SSPL-1.0 OR Elastic License 2.0"
} }

View file

@ -9,10 +9,12 @@
"stripInternal": false, "stripInternal": false,
"types": [ "types": [
"jest", "jest",
"node" "node",
"react"
] ]
}, },
"include": [ "include": [
"src/**/*" "**/*.ts",
"**/*.tsx",
] ]
} }

View file

@ -11,8 +11,7 @@ import React from 'react';
import { NoDataCardStorybookMock } from '@kbn/shared-ux-card-no-data-mocks'; import { NoDataCardStorybookMock } from '@kbn/shared-ux-card-no-data-mocks';
import type { NoDataCardStorybookParams } from '@kbn/shared-ux-card-no-data-mocks'; import type { NoDataCardStorybookParams } from '@kbn/shared-ux-card-no-data-mocks';
import { NoDataCard as Component } from './no_data_card.component'; import { NoDataCard } from './no_data_card';
import { NoDataCard as ConnectedComponent } from './no_data_card';
import { NoDataCardProvider } from './services'; import { NoDataCardProvider } from './services';
import mdx from '../README.mdx'; import mdx from '../README.mdx';
@ -28,21 +27,14 @@ export default {
}; };
const mock = new NoDataCardStorybookMock(); const mock = new NoDataCardStorybookMock();
const argTypes = mock.getArgumentTypes(); const argTypes = mock.getArgumentTypes();
export const NoDataCard = (params: NoDataCardStorybookParams) => { export const Card = (params: NoDataCardStorybookParams) => {
return ( return (
<NoDataCardProvider {...mock.getServices(params)}> <NoDataCardProvider {...mock.getServices(params)}>
<ConnectedComponent {...params} /> <NoDataCard {...params} />
</NoDataCardProvider> </NoDataCardProvider>
); );
}; };
NoDataCard.argTypes = argTypes; Card.argTypes = argTypes;
export const NoDataCardComponent = (params: NoDataCardStorybookParams) => {
return <Component {...params} />;
};
NoDataCardComponent.argTypes = argTypes;

View file

@ -10,8 +10,17 @@ SOURCE_FILES = glob(
"src/**/*.ts", "src/**/*.ts",
], ],
exclude = [ exclude = [
"**/*.config.js",
"**/*.mock.*",
"**/*.test.*", "**/*.test.*",
"**/*.stories.*", "**/*.stories.*",
"**/__snapshots__",
"**/integration_tests",
"**/mocks",
"**/scripts",
"**/storybook",
"**/test_fixtures",
"**/test_helpers",
], ],
) )
@ -39,6 +48,8 @@ NPM_MODULE_EXTRA_FILES = [
RUNTIME_DEPS = [ RUNTIME_DEPS = [
"@npm//@storybook/addon-actions", "@npm//@storybook/addon-actions",
"@npm//deepmerge", "@npm//deepmerge",
"@npm//lodash",
"@npm//react",
"//packages/shared-ux/link/redirect_app/mocks", "//packages/shared-ux/link/redirect_app/mocks",
"//packages/shared-ux/storybook/mock", "//packages/shared-ux/storybook/mock",
] ]
@ -53,13 +64,15 @@ RUNTIME_DEPS = [
# #
# References to NPM packages work the same as RUNTIME_DEPS # References to NPM packages work the same as RUNTIME_DEPS
TYPES_DEPS = [ TYPES_DEPS = [
"@npm//@types/node",
"@npm//@types/jest",
"@npm//@storybook/addon-actions", "@npm//@storybook/addon-actions",
"@npm//@types/jest",
"@npm//@types/lodash",
"@npm//@types/node",
"@npm//@types/react",
"@npm//deepmerge", "@npm//deepmerge",
"//packages/shared-ux/storybook/mock:npm_module_types",
"//packages/shared-ux/link/redirect_app/mocks:npm_module_types",
"//packages/shared-ux/card/no_data/types:npm_module_types", "//packages/shared-ux/card/no_data/types:npm_module_types",
"//packages/shared-ux/link/redirect_app/mocks:npm_module_types",
"//packages/shared-ux/storybook/mock:npm_module_types",
] ]
jsts_transpiler( jsts_transpiler(
@ -69,6 +82,14 @@ jsts_transpiler(
root_input_dir = "src", root_input_dir = "src",
) )
jsts_transpiler(
name = "target_web",
srcs = SRCS,
build_pkg_name = package_name(),
root_input_dir = "src",
web = True,
)
ts_config( ts_config(
name = "tsconfig", name = "tsconfig",
src = "tsconfig.json", src = "tsconfig.json",
@ -94,7 +115,7 @@ ts_project(
js_library( js_library(
name = PKG_DIRNAME, name = PKG_DIRNAME,
srcs = NPM_MODULE_EXTRA_FILES, srcs = NPM_MODULE_EXTRA_FILES,
deps = RUNTIME_DEPS + [":target_node"], deps = RUNTIME_DEPS + [":target_node", ":target_web"],
package_name = PKG_REQUIRE_NAME, package_name = PKG_REQUIRE_NAME,
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
) )

View file

@ -3,5 +3,6 @@
"private": true, "private": true,
"version": "1.0.0", "version": "1.0.0",
"main": "./target_node/index.js", "main": "./target_node/index.js",
"browser": "./target_web/index.js",
"license": "SSPL-1.0 OR Elastic License 2.0" "license": "SSPL-1.0 OR Elastic License 2.0"
} }

View file

@ -5,7 +5,10 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import deepmerge from 'deepmerge'; import deepmerge from 'deepmerge';
import { isPlainObject } from 'lodash';
import type { import type {
NoDataCardServices, NoDataCardServices,
NoDataCardKibanaDependencies, NoDataCardKibanaDependencies,
@ -43,7 +46,7 @@ export const getKibanaDependenciesMock = (
const integrations = const integrations =
params.canAccessFleet !== undefined ? params.canAccessFleet : defaultParams.canAccessFleet; params.canAccessFleet !== undefined ? params.canAccessFleet : defaultParams.canAccessFleet;
return deepmerge( const result = deepmerge(
{ {
coreStart: { coreStart: {
http: { http: {
@ -60,6 +63,11 @@ export const getKibanaDependenciesMock = (
}, },
}, },
}, },
getRedirectAppLinksKibanaDependenciesMock() getRedirectAppLinksKibanaDependenciesMock(),
{
isMergeableObject: isPlainObject,
}
); );
return result;
}; };

View file

@ -9,10 +9,12 @@
"stripInternal": false, "stripInternal": false,
"types": [ "types": [
"jest", "jest",
"node" "node",
"react"
] ]
}, },
"include": [ "include": [
"src/**/*" "**/*.ts",
"**/*.tsx",
] ]
} }

View file

@ -10,10 +10,14 @@
import React, { MouseEvent } from 'react'; import React, { MouseEvent } from 'react';
import { mount as enzymeMount, ReactWrapper } from 'enzyme'; import { mount as enzymeMount, ReactWrapper } from 'enzyme';
import {
getRedirectAppLinksKibanaDependenciesMock,
getRedirectAppLinksServicesMock,
} from '@kbn/shared-ux-link-redirect-app-mocks';
import { RedirectAppLinksKibanaProvider, RedirectAppLinksProvider } from './services'; import { RedirectAppLinksKibanaProvider, RedirectAppLinksProvider } from './services';
import { RedirectAppLinks } from './redirect_app_links.container'; import { RedirectAppLinks } from './redirect_app_links.container';
import { RedirectAppLinks as ComposedWrapper } from './redirect_app_links'; import { RedirectAppLinks as ComposedWrapper } from './redirect_app_links';
import { Observable } from 'rxjs';
export type UnmountCallback = () => void; export type UnmountCallback = () => void;
export type MountPoint<T extends HTMLElement = HTMLElement> = (element: T) => UnmountCallback; export type MountPoint<T extends HTMLElement = HTMLElement> = (element: T) => UnmountCallback;
@ -251,21 +255,8 @@ describe('RedirectAppLinks', () => {
navigateToUrl.mockReset(); navigateToUrl.mockReset();
}); });
const kibana = { const kibana = getRedirectAppLinksKibanaDependenciesMock({ navigateToUrl });
coreStart: { const services = getRedirectAppLinksServicesMock({ navigateToUrl });
application: {
currentAppId$: new Observable<string>((subscriber) => {
subscriber.next('123');
}),
navigateToUrl,
},
},
};
const services = {
currentAppId: 'abc123',
navigateToUrl,
};
const provider = (node: React.ReactElement) => const provider = (node: React.ReactElement) =>
enzymeMount(<RedirectAppLinksProvider {...services}>{node}</RedirectAppLinksProvider>); enzymeMount(<RedirectAppLinksProvider {...services}>{node}</RedirectAppLinksProvider>);

View file

@ -8,10 +8,20 @@ PKG_REQUIRE_NAME = "@kbn/shared-ux-link-redirect-app-mocks"
SOURCE_FILES = glob( SOURCE_FILES = glob(
[ [
"src/**/*.ts", "src/**/*.ts",
"src/**/*.tsx",
], ],
exclude = [ exclude = [
"**/*.config.js",
"**/*.mock.*",
"**/*.test.*", "**/*.test.*",
"**/*.stories.*", "**/*.stories.*",
"**/__snapshots__",
"**/integration_tests",
"**/mocks",
"**/scripts",
"**/storybook",
"**/test_fixtures",
"**/test_helpers",
], ],
) )
@ -37,6 +47,7 @@ NPM_MODULE_EXTRA_FILES = [
# "@npm//name-of-package" # "@npm//name-of-package"
# eg. "@npm//lodash" # eg. "@npm//lodash"
RUNTIME_DEPS = [ RUNTIME_DEPS = [
"@npm//react",
"@npm//@storybook/addon-actions", "@npm//@storybook/addon-actions",
"@npm//rxjs", "@npm//rxjs",
"//packages/shared-ux/storybook/mock", "//packages/shared-ux/storybook/mock",
@ -52,6 +63,9 @@ RUNTIME_DEPS = [
# #
# References to NPM packages work the same as RUNTIME_DEPS # References to NPM packages work the same as RUNTIME_DEPS
TYPES_DEPS = [ TYPES_DEPS = [
"@npm//@types/node",
"@npm//@types/jest",
"@npm//@types/react",
"@npm//@storybook/addon-actions", "@npm//@storybook/addon-actions",
"@npm//rxjs", "@npm//rxjs",
"//packages/shared-ux/link/redirect_app/types", "//packages/shared-ux/link/redirect_app/types",
@ -65,6 +79,14 @@ jsts_transpiler(
root_input_dir = "src", root_input_dir = "src",
) )
jsts_transpiler(
name = "target_web",
srcs = SRCS,
build_pkg_name = package_name(),
root_input_dir = "src",
web = True,
)
ts_config( ts_config(
name = "tsconfig", name = "tsconfig",
src = "tsconfig.json", src = "tsconfig.json",
@ -90,7 +112,7 @@ ts_project(
js_library( js_library(
name = PKG_DIRNAME, name = PKG_DIRNAME,
srcs = NPM_MODULE_EXTRA_FILES, srcs = NPM_MODULE_EXTRA_FILES,
deps = RUNTIME_DEPS + [":target_node"], deps = RUNTIME_DEPS + [":target_node", ":target_web"],
package_name = PKG_REQUIRE_NAME, package_name = PKG_REQUIRE_NAME,
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
) )

View file

@ -7,7 +7,7 @@
*/ */
module.exports = { module.exports = {
preset: '@kbn/test/jest_node', preset: '@kbn/test',
rootDir: '../../../../..', rootDir: '../../../../..',
roots: ['<rootDir>/packages/shared-ux/link/redirect_app/mocks'], roots: ['<rootDir>/packages/shared-ux/link/redirect_app/mocks'],
}; };

View file

@ -3,5 +3,6 @@
"private": true, "private": true,
"version": "1.0.0", "version": "1.0.0",
"main": "./target_node/index.js", "main": "./target_node/index.js",
"browser": "./target_web/index.js",
"license": "SSPL-1.0 OR Elastic License 2.0" "license": "SSPL-1.0 OR Elastic License 2.0"
} }

View file

@ -6,31 +6,53 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import { Subject } from 'rxjs'; import { Observable } from 'rxjs';
import { import {
RedirectAppLinksServices, RedirectAppLinksServices,
RedirectAppLinksKibanaDependencies, RedirectAppLinksKibanaDependencies,
} from '@kbn/shared-ux-link-redirect-app-types'; } from '@kbn/shared-ux-link-redirect-app-types';
type Params = Pick<RedirectAppLinksServices, 'navigateToUrl'>;
const defaultParams: Params = {
navigateToUrl: jest.fn(),
};
/** /**
* Returns the Jest-compatible service abstractions for the `NoDataCard` Provider. * Returns the Jest-compatible service abstractions for the `NoDataCard` Provider.
*/ */
export const getRedirectAppLinksServicesMock = () => { export const getRedirectAppLinksServicesMock = (
params?: Partial<Params>
): RedirectAppLinksServices => {
const navigateToUrl =
params && params.navigateToUrl !== undefined
? params.navigateToUrl
: defaultParams.navigateToUrl;
const services: RedirectAppLinksServices = { const services: RedirectAppLinksServices = {
navigateToUrl: jest.fn(), navigateToUrl,
currentAppId: 'currentAppId', currentAppId: 'currentAppId',
}; };
return services; return services;
}; };
export const getRedirectAppLinksKibanaDependenciesMock = (): RedirectAppLinksKibanaDependencies => { export const getRedirectAppLinksKibanaDependenciesMock = (
params?: Partial<Params>
): RedirectAppLinksKibanaDependencies => {
const navigateToUrl =
params && params.navigateToUrl !== undefined
? params.navigateToUrl
: defaultParams.navigateToUrl;
return { return {
coreStart: { coreStart: {
application: { application: {
currentAppId$: new Subject<string>(), currentAppId$: new Observable<string>((subscriber) => {
navigateToUrl: jest.fn(), subscriber.next('currentAppId');
}),
navigateToUrl,
}, },
}, },
}; };

View file

@ -10,9 +10,11 @@
"types": [ "types": [
"jest", "jest",
"node", "node",
"react"
] ]
}, },
"include": [ "include": [
"src/**/*" "**/*.ts",
"**/*.tsx",
] ]
} }

View file

@ -7,7 +7,6 @@
*/ */
import React from 'react'; import React from 'react';
import { action } from '@storybook/addon-actions';
import { AnalyticsNoDataPageStorybookMock } from '@kbn/shared-ux-page-analytics-no-data-mocks'; import { AnalyticsNoDataPageStorybookMock } from '@kbn/shared-ux-page-analytics-no-data-mocks';
import type { AnalyticsNoDataPageStorybookParams } from '@kbn/shared-ux-page-analytics-no-data-mocks'; import type { AnalyticsNoDataPageStorybookParams } from '@kbn/shared-ux-page-analytics-no-data-mocks';
@ -18,7 +17,7 @@ import mdx from '../README.mdx';
const mock = new AnalyticsNoDataPageStorybookMock(); const mock = new AnalyticsNoDataPageStorybookMock();
export default { export default {
title: 'No Data/Analytics Page', title: 'No Data/Page/Kibana',
description: 'An Analytics-specific version of KibanaNoDataPage.', description: 'An Analytics-specific version of KibanaNoDataPage.',
parameters: { parameters: {
docs: { docs: {
@ -27,7 +26,7 @@ export default {
}, },
}; };
export const AnalyticsNoDataPage = (params: AnalyticsNoDataPageStorybookParams) => { export const Analytics = (params: AnalyticsNoDataPageStorybookParams) => {
return ( return (
<AnalyticsNoDataPageProvider {...mock.getServices(params)}> <AnalyticsNoDataPageProvider {...mock.getServices(params)}>
<Component {...mock.getProps()} /> <Component {...mock.getProps()} />
@ -35,22 +34,4 @@ export const AnalyticsNoDataPage = (params: AnalyticsNoDataPageStorybookParams)
); );
}; };
AnalyticsNoDataPage.argTypes = mock.getArgumentTypes(); Analytics.argTypes = mock.getArgumentTypes();
export const LoadingState = (params: AnalyticsNoDataPageStorybookParams) => {
// Simulate loading with a Promise that doesn't resolve.
const dataCheck = () => new Promise<boolean>((_reject, _resolve) => {});
const services = {
...mock.getServices(params),
hasESData: dataCheck,
hasUserDataView: dataCheck,
hasDataView: dataCheck,
};
return (
<AnalyticsNoDataPageProvider {...services}>
<Component onDataViewCreated={action('onDataViewCreated')} />
</AnalyticsNoDataPageProvider>
);
};

View file

@ -10,8 +10,17 @@ SOURCE_FILES = glob(
"src/**/*.ts", "src/**/*.ts",
], ],
exclude = [ exclude = [
"**/*.config.js",
"**/*.mock.*",
"**/*.test.*", "**/*.test.*",
"**/*.stories.*", "**/*.stories.*",
"**/__snapshots__",
"**/integration_tests",
"**/mocks",
"**/scripts",
"**/storybook",
"**/test_fixtures",
"**/test_helpers",
], ],
) )
@ -37,7 +46,9 @@ NPM_MODULE_EXTRA_FILES = [
# "@npm//name-of-package" # "@npm//name-of-package"
# eg. "@npm//lodash" # eg. "@npm//lodash"
RUNTIME_DEPS = [ RUNTIME_DEPS = [
"@npm//react",
"//packages/shared-ux/page/kibana_no_data/mocks", "//packages/shared-ux/page/kibana_no_data/mocks",
"//packages/shared-ux/storybook/mock",
] ]
# In this array place dependencies necessary to build the types, which will include the # In this array place dependencies necessary to build the types, which will include the
@ -50,10 +61,12 @@ RUNTIME_DEPS = [
# #
# References to NPM packages work the same as RUNTIME_DEPS # References to NPM packages work the same as RUNTIME_DEPS
TYPES_DEPS = [ TYPES_DEPS = [
"@npm//@types/node",
"@npm//@types/jest", "@npm//@types/jest",
"@npm//@types/node",
"@npm//@types/react",
"//packages/shared-ux/page/analytics_no_data/types:npm_module_types", "//packages/shared-ux/page/analytics_no_data/types:npm_module_types",
"//packages/shared-ux/page/kibana_no_data/mocks:npm_module_types", "//packages/shared-ux/page/kibana_no_data/mocks:npm_module_types",
"//packages/shared-ux/storybook/mock:npm_module_types",
] ]
jsts_transpiler( jsts_transpiler(
@ -63,6 +76,14 @@ jsts_transpiler(
root_input_dir = "src", root_input_dir = "src",
) )
jsts_transpiler(
name = "target_web",
srcs = SRCS,
build_pkg_name = package_name(),
root_input_dir = "src",
web = True,
)
ts_config( ts_config(
name = "tsconfig", name = "tsconfig",
src = "tsconfig.json", src = "tsconfig.json",
@ -88,7 +109,7 @@ ts_project(
js_library( js_library(
name = PKG_DIRNAME, name = PKG_DIRNAME,
srcs = NPM_MODULE_EXTRA_FILES, srcs = NPM_MODULE_EXTRA_FILES,
deps = RUNTIME_DEPS + [":target_node"], deps = RUNTIME_DEPS + [":target_node", ":target_web"],
package_name = PKG_REQUIRE_NAME, package_name = PKG_REQUIRE_NAME,
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
) )

View file

@ -1,13 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
module.exports = {
preset: '@kbn/test/jest_node',
rootDir: '../../../../..',
roots: ['<rootDir>/packages/shared-ux/page/analytics_no_data/mocks'],
};

View file

@ -3,5 +3,6 @@
"private": true, "private": true,
"version": "1.0.0", "version": "1.0.0",
"main": "./target_node/index.js", "main": "./target_node/index.js",
"browser": "./target_web/index.js",
"license": "SSPL-1.0 OR Elastic License 2.0" "license": "SSPL-1.0 OR Elastic License 2.0"
} }

View file

@ -9,10 +9,12 @@
"stripInternal": false, "stripInternal": false,
"types": [ "types": [
"jest", "jest",
"node" "node",
"react"
] ]
}, },
"include": [ "include": [
"src/**/*" "**/*.ts",
"**/*.tsx",
] ]
} }

View file

@ -44,9 +44,8 @@ RUNTIME_DEPS = [
"@npm//@emotion/react", "@npm//@emotion/react",
"@npm//react", "@npm//react",
"//packages/kbn-i18n", "//packages/kbn-i18n",
"//packages/kbn-shared-ux-components",
"//packages/kbn-shared-ux-services",
"//packages/shared-ux/prompt/no_data_views/impl", "//packages/shared-ux/prompt/no_data_views/impl",
"//packages/shared-ux/page/no_data_config/impl",
] ]
# In this array place dependencies necessary to build the types, which will include the # In this array place dependencies necessary to build the types, which will include the
@ -67,10 +66,10 @@ TYPES_DEPS = [
"@npm//@types/react", "@npm//@types/react",
"//packages/kbn-ambient-ui-types", "//packages/kbn-ambient-ui-types",
"//packages/kbn-i18n:npm_module_types", "//packages/kbn-i18n:npm_module_types",
"//packages/kbn-shared-ux-components:npm_module_types",
"//packages/kbn-shared-ux-services:npm_module_types",
"//packages/shared-ux/prompt/no_data_views/impl:npm_module_types", "//packages/shared-ux/prompt/no_data_views/impl:npm_module_types",
"//packages/shared-ux/page/kibana_no_data/types:npm_module_types", "//packages/shared-ux/page/no_data_config/impl:npm_module_types",
"//packages/shared-ux/page/no_data_config/types",
"//packages/shared-ux/page/kibana_no_data/types",
] ]
jsts_transpiler( jsts_transpiler(

View file

@ -14,7 +14,7 @@ The `KibanaNoDataPage` connected component uses:
- `hasUserDataView` and `hasData` API from the `HasData` service in the `data_views` plugin to check for existence of data an data views. - `hasUserDataView` and `hasData` API from the `HasData` service in the `data_views` plugin to check for existence of data an data views.
- `onDataViewCreated` callback once a data view has been created. - `onDataViewCreated` callback once a data view has been created.
- (noDataConfig)[https://github.com/elastic/kibana/blob/main/packages/kbn-shared-ux-components/src/page_template/no_data_page/types.ts] as configuration for the page in case of no data. - (noDataConfig)[https://github.com/elastic/kibana/blob/main/packages/shared-ux/page/no_data/types/index.d.ts] as configuration for the page in case of no data.
## API ## API

View file

@ -17,7 +17,7 @@ import { KibanaNoDataPageProvider } from './services';
import mdx from '../README.mdx'; import mdx from '../README.mdx';
export default { export default {
title: 'No Data/Kibana Page', title: 'No Data/Page/Kibana',
description: 'A component to display when there is no data available', description: 'A component to display when there is no data available',
parameters: { parameters: {
docs: { docs: {
@ -28,7 +28,7 @@ export default {
const mock = new KibanaNoDataPageStorybookMock(); const mock = new KibanaNoDataPageStorybookMock();
export const KibanaNoDataPage = (params: KibanaNoDataPageStorybookParams) => { export const Kibana = (params: KibanaNoDataPageStorybookParams) => {
return ( return (
<KibanaNoDataPageProvider {...mock.getServices(params)}> <KibanaNoDataPageProvider {...mock.getServices(params)}>
<Component {...mock.getProps(params)} /> <Component {...mock.getProps(params)} />
@ -36,7 +36,7 @@ export const KibanaNoDataPage = (params: KibanaNoDataPageStorybookParams) => {
); );
}; };
KibanaNoDataPage.argTypes = mock.getArgumentTypes(); Kibana.argTypes = mock.getArgumentTypes();
export const LoadingState = (params: KibanaNoDataPageStorybookParams) => { export const LoadingState = (params: KibanaNoDataPageStorybookParams) => {
// Simulate loading with a Promise that doesn't resolve. // Simulate loading with a Promise that doesn't resolve.

View file

@ -12,7 +12,7 @@ import { act } from 'react-dom/test-utils';
import { EuiLoadingElastic } from '@elastic/eui'; import { EuiLoadingElastic } from '@elastic/eui';
import { mountWithIntl } from '@kbn/test-jest-helpers'; import { mountWithIntl } from '@kbn/test-jest-helpers';
import { NoDataViewsPrompt } from '@kbn/shared-ux-prompt-no-data-views'; import { NoDataViewsPrompt } from '@kbn/shared-ux-prompt-no-data-views';
import { NoDataConfigPage } from '@kbn/shared-ux-components'; import { NoDataConfigPage } from '@kbn/shared-ux-page-no-data-config';
import { getKibanaNoDataPageServicesMock } from '@kbn/shared-ux-page-kibana-no-data-mocks'; import { getKibanaNoDataPageServicesMock } from '@kbn/shared-ux-page-kibana-no-data-mocks';
import { KibanaNoDataPage } from './kibana_no_data_page'; import { KibanaNoDataPage } from './kibana_no_data_page';
@ -43,7 +43,7 @@ describe('Kibana No Data Page', () => {
}); });
test('renders NoDataConfigPage', async () => { test('renders NoDataConfigPage', async () => {
const services = getKibanaNoDataPageServicesMock({ config: { ...config, hasESData: false } }); const services = getKibanaNoDataPageServicesMock(config);
const component = mountWithIntl( const component = mountWithIntl(
<KibanaNoDataPageProvider {...services}> <KibanaNoDataPageProvider {...services}>
<KibanaNoDataPage {...{ noDataConfig, onDataViewCreated }} /> <KibanaNoDataPage {...{ noDataConfig, onDataViewCreated }} />
@ -58,7 +58,7 @@ describe('Kibana No Data Page', () => {
}); });
test('renders NoDataViews', async () => { test('renders NoDataViews', async () => {
const services = getKibanaNoDataPageServicesMock({ config: { ...config, hasESData: true } }); const services = getKibanaNoDataPageServicesMock({ ...config, hasESData: true });
const component = mountWithIntl( const component = mountWithIntl(
<KibanaNoDataPageProvider {...services}> <KibanaNoDataPageProvider {...services}>
<KibanaNoDataPage noDataConfig={noDataConfig} onDataViewCreated={onDataViewCreated} /> <KibanaNoDataPage noDataConfig={noDataConfig} onDataViewCreated={onDataViewCreated} />

View file

@ -7,7 +7,7 @@
*/ */
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { EuiLoadingElastic } from '@elastic/eui'; import { EuiLoadingElastic } from '@elastic/eui';
import { NoDataConfigPage } from '@kbn/shared-ux-components'; import { NoDataConfigPage } from '@kbn/shared-ux-page-no-data-config';
import { NoDataViewsPrompt } from '@kbn/shared-ux-prompt-no-data-views'; import { NoDataViewsPrompt } from '@kbn/shared-ux-prompt-no-data-views';
import { KibanaNoDataPageProps } from '@kbn/shared-ux-page-kibana-no-data-types'; import { KibanaNoDataPageProps } from '@kbn/shared-ux-page-kibana-no-data-types';

View file

@ -1,49 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
export { SharedUxServicesProvider as LegacyServicesProvider } from '@kbn/shared-ux-services';
export type { SharedUxServices as LegacyServices } from '@kbn/shared-ux-services';
import { SharedUxServices as LegacyServices } from '@kbn/shared-ux-services';
import type { KibanaNoDataPageServices } from '@kbn/shared-ux-page-kibana-no-data-types';
/**
* This list is temporary, a stop-gap as we migrate to a package-based architecture, where
* services are not collected in a single package. In order to make the transition, this
* interface is intentionally "flat".
*
* Expect this list to dwindle to zero as `@kbn/shared-ux-components` are migrated to their
* own packages, (and `@kbn/shared-ux-services` is removed).
*/
export const getLegacyServices = (services: KibanaNoDataPageServices): LegacyServices => ({
application: {
currentAppId$: services.currentAppId$,
navigateToUrl: services.navigateToUrl,
},
data: {
hasESData: services.hasESData,
hasDataView: services.hasDataView,
hasUserDataView: services.hasUserDataView,
},
docLinks: {
dataViewsDocLink: services.dataViewsDocLink,
},
editors: {
openDataViewEditor: services.openDataViewEditor,
},
http: {
addBasePath: services.addBasePath,
},
permissions: {
canAccessFleet: services.canAccessFleet,
canCreateNewDataView: services.canCreateNewDataView,
},
platform: {
setIsFullscreen: services.setIsFullscreen,
},
});

View file

@ -15,13 +15,12 @@ import {
import { NoDataCardProvider, NoDataCardKibanaProvider } from '@kbn/shared-ux-card-no-data'; import { NoDataCardProvider, NoDataCardKibanaProvider } from '@kbn/shared-ux-card-no-data';
import { import {
Services,
KibanaNoDataPageServices, KibanaNoDataPageServices,
KibanaNoDataPageKibanaDependencies, KibanaNoDataPageKibanaDependencies,
} from '@kbn/shared-ux-page-kibana-no-data-types'; } from '@kbn/shared-ux-page-kibana-no-data-types';
import { LegacyServicesProvider, getLegacyServices } from './legacy_services'; const KibanaNoDataPageContext = React.createContext<Services | null>(null);
const KibanaNoDataPageContext = React.createContext<KibanaNoDataPageServices | null>(null);
/** /**
* A Context Provider that provides services to the component. * A Context Provider that provides services to the component.
@ -29,15 +28,17 @@ const KibanaNoDataPageContext = React.createContext<KibanaNoDataPageServices | n
export const KibanaNoDataPageProvider: FC<KibanaNoDataPageServices> = ({ export const KibanaNoDataPageProvider: FC<KibanaNoDataPageServices> = ({
children, children,
...services ...services
}) => ( }) => {
<KibanaNoDataPageContext.Provider value={services}> const { hasESData, hasUserDataView } = services;
return (
<KibanaNoDataPageContext.Provider value={{ hasESData, hasUserDataView }}>
<NoDataViewsPromptProvider {...services}> <NoDataViewsPromptProvider {...services}>
<NoDataCardProvider {...services}> <NoDataCardProvider {...services}>{children}</NoDataCardProvider>
<LegacyServicesProvider {...getLegacyServices(services)}>{children}</LegacyServicesProvider>
</NoDataCardProvider>
</NoDataViewsPromptProvider> </NoDataViewsPromptProvider>
</KibanaNoDataPageContext.Provider> </KibanaNoDataPageContext.Provider>
); );
};
/** /**
* Kibana-specific Provider that maps dependencies to services. * Kibana-specific Provider that maps dependencies to services.
@ -46,27 +47,16 @@ export const KibanaNoDataPageKibanaProvider: FC<KibanaNoDataPageKibanaDependenci
children, children,
...dependencies ...dependencies
}) => { }) => {
const { coreStart, dataViewEditor, dataViews } = dependencies; const { dataViews } = dependencies;
const value: KibanaNoDataPageServices = { const value: Services = {
addBasePath: coreStart.http.basePath.prepend,
canAccessFleet: coreStart.application.capabilities.navLinks.integrations,
canCreateNewDataView: dataViewEditor.userPermissions.editDataView(),
currentAppId$: coreStart.application.currentAppId$,
dataViewsDocLink: coreStart.docLinks.links.indexPatterns?.introduction,
hasDataView: dataViews.hasData.hasDataView,
hasESData: dataViews.hasData.hasESData, hasESData: dataViews.hasData.hasESData,
hasUserDataView: dataViews.hasData.hasUserDataView, hasUserDataView: dataViews.hasData.hasUserDataView,
navigateToUrl: coreStart.application.navigateToUrl,
openDataViewEditor: dataViewEditor.openEditor,
setIsFullscreen: (isVisible: boolean) => coreStart.chrome.setIsVisible(isVisible),
}; };
return ( return (
<KibanaNoDataPageContext.Provider value={value}> <KibanaNoDataPageContext.Provider value={value}>
<NoDataViewsPromptKibanaProvider {...dependencies}> <NoDataViewsPromptKibanaProvider {...dependencies}>
<NoDataCardKibanaProvider {...dependencies}> <NoDataCardKibanaProvider {...dependencies}>{children}</NoDataCardKibanaProvider>
<LegacyServicesProvider {...getLegacyServices(value)}>{children}</LegacyServicesProvider>
</NoDataCardKibanaProvider>
</NoDataViewsPromptKibanaProvider> </NoDataViewsPromptKibanaProvider>
</KibanaNoDataPageContext.Provider> </KibanaNoDataPageContext.Provider>
); );

View file

@ -10,8 +10,17 @@ SOURCE_FILES = glob(
"src/**/*.ts", "src/**/*.ts",
], ],
exclude = [ exclude = [
"**/*.config.js",
"**/*.mock.*",
"**/*.test.*", "**/*.test.*",
"**/*.stories.*", "**/*.stories.*",
"**/__snapshots__",
"**/integration_tests",
"**/mocks",
"**/scripts",
"**/storybook",
"**/test_fixtures",
"**/test_helpers",
], ],
) )
@ -37,8 +46,10 @@ NPM_MODULE_EXTRA_FILES = [
# "@npm//name-of-package" # "@npm//name-of-package"
# eg. "@npm//lodash" # eg. "@npm//lodash"
RUNTIME_DEPS = [ RUNTIME_DEPS = [
"//packages/shared-ux/prompt/no_data_views/mocks", "@npm//react",
"//packages/shared-ux/card/no_data/mocks", "//packages/shared-ux/card/no_data/mocks",
"//packages/shared-ux/prompt/no_data_views/mocks",
"//packages/shared-ux/storybook/mock",
] ]
# In this array place dependencies necessary to build the types, which will include the # In this array place dependencies necessary to build the types, which will include the
@ -51,12 +62,14 @@ RUNTIME_DEPS = [
# #
# References to NPM packages work the same as RUNTIME_DEPS # References to NPM packages work the same as RUNTIME_DEPS
TYPES_DEPS = [ TYPES_DEPS = [
"@npm//@types/node",
"@npm//@types/jest", "@npm//@types/jest",
"//packages/shared-ux/page/kibana_no_data/types:npm_module_types", "@npm//@types/node",
"//packages/kbn-shared-ux-components:npm_module_types", "@npm//@types/react",
"//packages/shared-ux/prompt/no_data_views/mocks:npm_module_types",
"//packages/shared-ux/card/no_data/mocks:npm_module_types", "//packages/shared-ux/card/no_data/mocks:npm_module_types",
"//packages/shared-ux/page/kibana_no_data/types:npm_module_types",
"//packages/shared-ux/page/no_data/types",
"//packages/shared-ux/prompt/no_data_views/mocks:npm_module_types",
"//packages/shared-ux/storybook/mock:npm_module_types",
] ]
jsts_transpiler( jsts_transpiler(
@ -66,6 +79,14 @@ jsts_transpiler(
root_input_dir = "src", root_input_dir = "src",
) )
jsts_transpiler(
name = "target_web",
srcs = SRCS,
build_pkg_name = package_name(),
root_input_dir = "src",
web = True,
)
ts_config( ts_config(
name = "tsconfig", name = "tsconfig",
src = "tsconfig.json", src = "tsconfig.json",
@ -91,7 +112,7 @@ ts_project(
js_library( js_library(
name = PKG_DIRNAME, name = PKG_DIRNAME,
srcs = NPM_MODULE_EXTRA_FILES, srcs = NPM_MODULE_EXTRA_FILES,
deps = RUNTIME_DEPS + [":target_node"], deps = RUNTIME_DEPS + [":target_node", ":target_web"],
package_name = PKG_REQUIRE_NAME, package_name = PKG_REQUIRE_NAME,
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
) )

View file

@ -1,13 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
module.exports = {
preset: '@kbn/test/jest_node',
rootDir: '../../../../..',
roots: ['<rootDir>/packages/shared-ux/page/kibana_no_data/mocks'],
};

View file

@ -3,5 +3,6 @@
"private": true, "private": true,
"version": "1.0.0", "version": "1.0.0",
"main": "./target_node/index.js", "main": "./target_node/index.js",
"browser": "./target_web/index.js",
"license": "SSPL-1.0 OR Elastic License 2.0" "license": "SSPL-1.0 OR Elastic License 2.0"
} }

View file

@ -9,33 +9,34 @@
import { getNoDataCardServicesMock } from '@kbn/shared-ux-card-no-data-mocks'; import { getNoDataCardServicesMock } from '@kbn/shared-ux-card-no-data-mocks';
import { KibanaNoDataPageServices } from '@kbn/shared-ux-page-kibana-no-data-types'; import { KibanaNoDataPageServices } from '@kbn/shared-ux-page-kibana-no-data-types';
import { getNoDataViewsPromptServicesMock } from '@kbn/shared-ux-prompt-no-data-views-mocks'; import { getNoDataViewsPromptServicesMock } from '@kbn/shared-ux-prompt-no-data-views-mocks';
import { mockServicesFactory, MockServicesFactoryParams } from '@kbn/shared-ux-services';
interface Params {
hasESData: boolean;
hasUserDataView: boolean;
}
const defaultParams = {
hasESData: true,
hasUserDataView: true,
};
/** /**
* Returns the Jest-compatible service abstractions for the `KibanaNoDataPage` Provider. * Returns the Jest-compatible service abstractions for the `KibanaNoDataPage` Provider.
*/ */
export const getServicesMock = (params?: MockServicesFactoryParams) => { export const getServicesMock = (params?: Partial<Params>) => {
const { canCreateNewDataView, dataViewsDocLink, openDataViewEditor } = const hasESData =
getNoDataViewsPromptServicesMock(); params && params.hasESData !== undefined ? params.hasESData : defaultParams.hasESData;
const { addBasePath, canAccessFleet } = getNoDataCardServicesMock(); const hasUserDataView =
params && params.hasUserDataView !== undefined
const { application, data, docLinks, editors, http, permissions, platform } = ? params.hasUserDataView
mockServicesFactory(params); : defaultParams.hasUserDataView;
const services: KibanaNoDataPageServices = { const services: KibanaNoDataPageServices = {
...application, ...getNoDataCardServicesMock(),
...data, ...getNoDataViewsPromptServicesMock(),
...docLinks, hasESData: async () => hasESData,
...editors, hasUserDataView: async () => hasUserDataView,
...http,
...permissions,
...platform,
canCreateNewDataView,
dataViewsDocLink,
openDataViewEditor,
addBasePath,
canAccessFleet,
}; };
return services; return services;

View file

@ -6,13 +6,14 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import { servicesFactory } from '@kbn/shared-ux-storybook'; import { action } from '@storybook/addon-actions';
import { AbstractStorybookMock, ArgumentParams } from '@kbn/shared-ux-storybook-mock'; import { AbstractStorybookMock, ArgumentParams } from '@kbn/shared-ux-storybook-mock';
import type { import type {
KibanaNoDataPageServices, KibanaNoDataPageServices,
KibanaNoDataPageProps, KibanaNoDataPageProps,
} from '@kbn/shared-ux-page-kibana-no-data-types'; } from '@kbn/shared-ux-page-kibana-no-data-types';
import type { NoDataPageProps } from '@kbn/shared-ux-components'; import type { NoDataPageProps } from '@kbn/shared-ux-page-no-data-types';
import { import {
NoDataViewsPromptStorybookMock, NoDataViewsPromptStorybookMock,
@ -23,7 +24,6 @@ import {
NoDataCardStorybookMock, NoDataCardStorybookMock,
NoDataCardStorybookParams, NoDataCardStorybookParams,
} from '@kbn/shared-ux-card-no-data-mocks'; } from '@kbn/shared-ux-card-no-data-mocks';
import { action } from '@storybook/addon-actions';
type PropArguments = Pick<NoDataPageProps, 'solution' | 'logo'>; type PropArguments = Pick<NoDataPageProps, 'solution' | 'logo'>;
type ServiceArguments = Pick<KibanaNoDataPageServices, 'hasUserDataView' | 'hasESData'>; type ServiceArguments = Pick<KibanaNoDataPageServices, 'hasUserDataView' | 'hasESData'>;
@ -83,22 +83,11 @@ export class StorybookMock extends AbstractStorybookMock<
} }
getServices(params: Params): KibanaNoDataPageServices { getServices(params: Params): KibanaNoDataPageServices {
// Workaround to leverage the services package.
const { application, data, docLinks, editors, http, permissions, platform } =
servicesFactory(params);
return { return {
...application,
...data,
...docLinks,
...editors,
...http,
...permissions,
...platform,
hasESData: () => params.hasESData,
hasUserDataView: () => params.hasUserDataView,
...noDataCardMock.getServices(params), ...noDataCardMock.getServices(params),
...noDataViewsMock.getServices(params), ...noDataViewsMock.getServices(params),
hasESData: () => params.hasESData,
hasUserDataView: () => params.hasUserDataView,
}; };
} }
} }

View file

@ -9,10 +9,12 @@
"stripInternal": false, "stripInternal": false,
"types": [ "types": [
"jest", "jest",
"node" "node",
"react"
] ]
}, },
"include": [ "include": [
"src/**/*" "**/*.ts",
"**/*.tsx",
] ]
} }

View file

@ -6,109 +6,44 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import { Observable } from 'rxjs'; import { NoDataPageProps } from '@kbn/shared-ux-page-no-data-types';
import { NoDataPageProps } from '@kbn/shared-ux-components';
/** import {
* TODO: `DataView` is a class exported by `src/plugins/data_views/public`. Since this service NoDataViewsPromptServices,
* is contained in this package-- and packages can only depend on other packages and never on NoDataViewsPromptKibanaDependencies,
* plugins-- we have to set this to `unknown`. If and when `DataView` is exported from a } from '@kbn/shared-ux-prompt-no-data-views-types';
* stateless package, we can remove this. import {
* NoDataCardServices,
* @see: https://github.com/elastic/kibana/issues/127695 NoDataCardKibanaDependencies,
*/ } from '@kbn/shared-ux-card-no-data-types';
type DataView = unknown;
/** export interface Services {
* A subset of the `DataViewEditorOptions` interface relevant to this component.
*
* @see: src/plugins/data_view_editor/public/types.ts
*/
interface DataViewEditorOptions {
/** Handler to be invoked when the Data View Editor completes a save operation. */
onSave: (dataView: DataView) => void;
}
/**
* A list of Services that are consumed by this component.
*
* This list is temporary, a stopgap as we migrate to a package-based architecture, where
* services are not collected in a single package. In order to make the transition, this
* interface is intentionally "flat".
*
* Expect this list to dwindle to zero as `@kbn/shared-ux-components` are migrated to their
* own packages, (and `@kbn/shared-ux-services` is removed).
*/
export interface KibanaNoDataPageServices {
/** True if the cluster contains data, false otherwise. */ /** True if the cluster contains data, false otherwise. */
hasESData: () => Promise<boolean>; hasESData: () => Promise<boolean>;
/** True if Kibana instance contains user-created data view, false otherwise. */ /** True if Kibana instance contains user-created data view, false otherwise. */
hasUserDataView: () => Promise<boolean>; hasUserDataView: () => Promise<boolean>;
// Provided to Legacy Services, not relevant to this component. Will be removed.
/** Append the server base path to a relative URL. */
addBasePath: (url: string) => string;
/** True if the user has permission to access Fleet, false otherwise. */
canAccessFleet: boolean;
/** True if the user has permission to create a new Data View, false otherwise. */
canCreateNewDataView: boolean;
/** Observable storing the active, current application ID. */
currentAppId$: Observable<string | undefined>;
/** A link to information about Data Views in Kibana */
dataViewsDocLink: string;
/** True if Kibana instance contains any data view, including system-created ones. */
hasDataView: () => Promise<boolean>;
/** Use Kibana to navigate async to a different URL. */
navigateToUrl: (url: string) => Promise<void> | void;
/** A method to open the Data View Editor flow. */
openDataViewEditor: (options: DataViewEditorOptions) => () => void;
/** Set the Kibana chrome and browser to full screen mode. */
setIsFullscreen: (isFullscreen: boolean) => void;
} }
/** /**
* An interface containing a collection of Kibana plugins and services required to * A list of Services that are consumed by this component..
* render this component and its dependencies.
*/ */
export interface KibanaNoDataPageKibanaDependencies { export type KibanaNoDataPageServices = Services & NoDataCardServices & NoDataViewsPromptServices;
coreStart: {
application: { export interface KibanaDependencies {
capabilities: {
navLinks: Record<string, boolean>;
};
currentAppId$: Observable<string | undefined>;
navigateToUrl: (url: string) => Promise<void>;
};
chrome: {
setIsVisible: (isVisible: boolean) => void;
};
docLinks: {
links: {
indexPatterns: {
introduction: string;
};
};
};
http: {
basePath: {
prepend: (url: string) => string;
};
};
};
dataViews: { dataViews: {
hasData: { hasData: {
hasDataView: () => Promise<boolean>;
hasESData: () => Promise<boolean>; hasESData: () => Promise<boolean>;
hasUserDataView: () => Promise<boolean>; hasUserDataView: () => Promise<boolean>;
}; };
}; };
dataViewEditor: {
openEditor: (options: DataViewEditorOptions) => () => void;
userPermissions: {
editDataView: () => boolean;
};
};
} }
/**
* An interface containing a collection of Kibana plugins and services required to
* render this component and its dependencies.
*/
export type KibanaNoDataPageKibanaDependencies = KibanaDependencies &
NoDataViewsPromptKibanaDependencies &
NoDataCardKibanaDependencies;
/** /**
* Props for `KibanaNoDataPage`. * Props for `KibanaNoDataPage`.

View file

@ -2,16 +2,18 @@ load("@npm//@bazel/typescript:index.bzl", "ts_config")
load("@build_bazel_rules_nodejs//:index.bzl", "js_library") load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project") load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project")
PKG_DIRNAME = "kbn-shared-ux-services" PKG_DIRNAME = "impl"
PKG_REQUIRE_NAME = "@kbn/shared-ux-services" PKG_REQUIRE_NAME = "@kbn/shared-ux-page-kibana-template"
SOURCE_FILES = glob( SOURCE_FILES = glob(
[ [
"src/**/*.ts", "src/**/*.ts",
"src/**/*.tsx", "src/**/*.tsx",
"src/**/*.mdx",
], ],
exclude = [ exclude = [
"**/*.test.*", "**/*.test.*",
"**/*.stories.*",
], ],
) )
@ -38,7 +40,7 @@ NPM_MODULE_EXTRA_FILES = [
# eg. "@npm//lodash" # eg. "@npm//lodash"
RUNTIME_DEPS = [ RUNTIME_DEPS = [
"@npm//react", "@npm//react",
"@npm//rxjs", "//packages/shared-ux/page/no_data_config/impl",
] ]
# In this array place dependencies necessary to build the types, which will include the # In this array place dependencies necessary to build the types, which will include the
@ -54,7 +56,9 @@ TYPES_DEPS = [
"@npm//@types/node", "@npm//@types/node",
"@npm//@types/jest", "@npm//@types/jest",
"@npm//@types/react", "@npm//@types/react",
"@npm//rxjs", "//packages/shared-ux/page/no_data_config/impl:npm_module_types",
"//packages/shared-ux/page/kibana_template/types",
"//packages/kbn-ambient-ui-types",
] ]
jsts_transpiler( jsts_transpiler(
@ -70,6 +74,10 @@ jsts_transpiler(
build_pkg_name = package_name(), build_pkg_name = package_name(),
root_input_dir = "src", root_input_dir = "src",
web = True, web = True,
additional_args = [
"--copy-files",
"--quiet"
],
) )
ts_config( ts_config(

View file

@ -1,6 +1,6 @@
--- ---
id: sharedUX/Components/PageTemplate id: sharedUX/Components/PageTemplate
slug: /shared-ux-components/page_template/page_template slug: /shared-ux/page_template
title: Page Template title: Page Template
description: A Kibana-specific wrapper around `EuiTemplate` description: A Kibana-specific wrapper around `EuiTemplate`
tags: ['shared-ux', 'component'] tags: ['shared-ux', 'component']
@ -124,7 +124,7 @@ Increases the consistency in messaging across all the solutions during the getti
This is a built-in configuration that displays a very specific UI and requires very specific keys. It will also ignore all other configurations of the template including `pageHeader` and `children`, with the exception of continuing to show `solutionNav`. This is a built-in configuration that displays a very specific UI and requires very specific keys. It will also ignore all other configurations of the template including `pageHeader` and `children`, with the exception of continuing to show `solutionNav`.
The `noDataConfig` is of type [`NoDataPageProps`](https://github.com/elastic/kibana/blob/main/packages/kbn-shared-ux-components/src/page_template/no_data_page/types.ts#L14): The `noDataConfig` is of type [`NoDataPageProps`](https://github.com/elastic/kibana/blob/main/packages/shared-ux/page/no_data/types/index.d.ts):
1. `solution: string`: Single name for the current solution, used to auto-generate the title, logo, and description *(required)* 1. `solution: string`: Single name for the current solution, used to auto-generate the title, logo, and description *(required)*
2. `docsLink: string`: Required to set the docs link for the whole solution *(required)* 2. `docsLink: string`: Required to set the docs link for the whole solution *(required)*

View file

@ -7,7 +7,7 @@
*/ */
module.exports = { module.exports = {
preset: '@kbn/test/jest_node', preset: '@kbn/test',
rootDir: '../../../../..', rootDir: '../../../../..',
roots: ['<rootDir>/packages/shared-ux/card/no_data/mocks'], roots: ['<rootDir>/packages/shared-ux/page/kibana_template/impl'],
}; };

View file

@ -0,0 +1,7 @@
{
"name": "@kbn/shared-ux-page-kibana-template",
"private": true,
"version": "1.0.0",
"main": "./target_node/index.js",
"license": "SSPL-1.0 OR Elastic License 2.0"
}

View file

@ -5,7 +5,12 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server * in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1. * Side Public License, v 1.
*/ */
export { NoDataPage, NoDataConfigPage } from './no_data_page';
export { KibanaPageTemplate } from './page_template'; export { KibanaPageTemplate } from './page_template';
export type { KibanaPageTemplateProps } from './types'; export { KibanaPageTemplateProvider, KibanaPageTemplateKibanaProvider } from './services';
export type { NoDataPageProps } from './no_data_page'; export type {
NoDataConfig,
KibanaPageTemplateProps,
KibanaPageTemplateServices,
KibanaPageTemplateKibanaDependencies,
} from '@kbn/shared-ux-page-kibana-template-types';

View file

@ -0,0 +1,82 @@
/*
* 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 React from 'react';
import {
KibanaPageTemplateStorybookMock,
NoDataConfigStorybookMock,
SolutionNavStorybookMock,
InnerPageTemplateStorybookMock,
} from '@kbn/shared-ux-page-kibana-template-mocks';
import type {
KibanaPageTemplateStorybookParams,
NoDataConfigStorybookParams,
SolutionNavStorybookParams,
InnerPageTemplateStorybookParams,
} from '@kbn/shared-ux-page-kibana-template-mocks';
import { KibanaPageTemplateProvider } from './services';
import { KibanaPageTemplate as Component } from './page_template';
import mdx from '../README.mdx';
export default {
title: 'Page/Page Template',
description:
'A thin wrapper around `EuiTemplate`. Takes care of styling, empty state and no data config',
parameters: {
docs: {
page: mdx,
},
},
};
const templateMock = new KibanaPageTemplateStorybookMock();
const solutionNavMock = new SolutionNavStorybookMock();
const noDataConfigMock = new NoDataConfigStorybookMock();
const innerMock = new InnerPageTemplateStorybookMock();
export const WithNoDataConfig = (params: NoDataConfigStorybookParams) => {
return (
<KibanaPageTemplateProvider {...noDataConfigMock.getServices(params)}>
<Component {...noDataConfigMock.getProps(params)} />
</KibanaPageTemplateProvider>
);
};
WithNoDataConfig.argTypes = noDataConfigMock.getArgumentTypes();
export const WithSolutionNav = (params: SolutionNavStorybookParams) => {
return (
<KibanaPageTemplateProvider {...solutionNavMock.getServices(params)}>
<Component {...solutionNavMock.getProps(params)} />
</KibanaPageTemplateProvider>
);
};
WithSolutionNav.argTypes = solutionNavMock.getArgumentTypes();
export const WithBoth = (params: KibanaPageTemplateStorybookParams) => {
return (
<KibanaPageTemplateProvider {...templateMock.getServices(params)}>
<Component {...templateMock.getProps(params)} />
</KibanaPageTemplateProvider>
);
};
WithBoth.argTypes = templateMock.getArgumentTypes();
export const WithNeither = (params: InnerPageTemplateStorybookParams) => {
return (
<KibanaPageTemplateProvider {...innerMock.getServices(params)}>
<Component {...innerMock.getProps(params)} />
</KibanaPageTemplateProvider>
);
};
WithNeither.argTypes = innerMock.getArgumentTypes();

View file

@ -9,9 +9,9 @@
import React from 'react'; import React from 'react';
import { shallow, render } from 'enzyme'; import { shallow, render } from 'enzyme';
import { SolutionNavProps } from '@kbn/shared-ux-page-solution-nav'; import { SolutionNavProps } from '@kbn/shared-ux-page-solution-nav';
import type { NoDataPageProps } from '@kbn/shared-ux-page-no-data-types';
import { KibanaPageTemplate } from './page_template'; import { KibanaPageTemplate } from './page_template';
import { NoDataPageProps } from './no_data_page';
const items: SolutionNavProps['items'] = [ const items: SolutionNavProps['items'] = [
{ {

View file

@ -6,13 +6,17 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import React, { FunctionComponent } from 'react'; import React, { FC } from 'react';
import {
NoDataConfigPage,
NoDataConfigPageWithSolutionNavBar,
} from '@kbn/shared-ux-page-no-data-config';
import { KibanaPageTemplateProps } from '@kbn/shared-ux-page-kibana-template-types';
import { NoDataConfigPage, NoDataConfigPageWithSolutionNavBar } from './no_data_page';
import { KibanaPageTemplateInner, KibanaPageTemplateWithSolutionNav } from './page_template_inner'; import { KibanaPageTemplateInner, KibanaPageTemplateWithSolutionNav } from './page_template_inner';
import { KibanaPageTemplateProps } from './types';
export const KibanaPageTemplate: FunctionComponent<KibanaPageTemplateProps> = ({ export const KibanaPageTemplate: FC<KibanaPageTemplateProps> = ({
template, template,
className, className,
children, children,

View file

@ -6,20 +6,25 @@
* Side Public License, v 1. * Side Public License, v 1.
*/ */
import React, { FunctionComponent } from 'react'; import React, { FC } from 'react';
import classNames from 'classnames';
import { EuiEmptyPrompt, EuiPageTemplate } from '@elastic/eui'; import { EuiEmptyPrompt, EuiPageTemplate } from '@elastic/eui';
import { withSolutionNav } from '@kbn/shared-ux-page-solution-nav'; import { withSolutionNav } from '@kbn/shared-ux-page-solution-nav';
import { KibanaPageTemplateProps as Props } from '@kbn/shared-ux-page-kibana-template-types';
import { KibanaPageTemplateProps } from './types'; const getClasses = (template?: string, className?: string) => {
import { getClasses } from './util'; return classNames(
'kbnPageTemplate',
type Props = KibanaPageTemplateProps; template ? { [`kbnPageTemplate--${template}`]: template } : '',
className || ''
);
};
/** /**
* A thin wrapper around EuiPageTemplate with a few Kibana specific additions * A thin wrapper around EuiPageTemplate with a few Kibana specific additions
*/ */
export const KibanaPageTemplateInner: FunctionComponent<Props> = ({ export const KibanaPageTemplateInner: FC<Props> = ({
template, template,
className, className,
pageHeader, pageHeader,

Some files were not shown because too many files have changed in this diff Show more