From 2de2c70f75687ad7ec76e374ed1ff66381718dbb Mon Sep 17 00:00:00 2001 From: Wylie Conlon Date: Tue, 6 Oct 2020 11:50:44 -0400 Subject: [PATCH 01/62] [Lens] Break long titles into multiple lines (#79580) --- .../editor_frame/config_panel/layer_panel.scss | 1 + .../dimension_panel/dimension_panel.tsx | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.scss b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.scss index c77db2e65ce2d..54c922957d29b 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.scss +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.scss @@ -50,6 +50,7 @@ width: 100%; padding: $euiSizeS; min-height: $euiSizeXXL - 2; + word-break: break-word; &:focus { background-color: transparent !important; // sass-lint:disable-line no-important diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx index 12b8d91c35ade..ff6840bc16a59 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx @@ -229,6 +229,13 @@ export function onDrop(props: DatasourceDimensionDropHandlerProps - {uniqueLabel} + {formattedLabel} ); }; From 24e4536b99b9404b06eb3591528ed869d1366210 Mon Sep 17 00:00:00 2001 From: Mikhail Shustov Date: Tue, 6 Oct 2020 18:52:24 +0300 Subject: [PATCH 02/62] hint that we export type only (#79635) --- src/plugins/dashboard/public/application/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/dashboard/public/application/index.ts b/src/plugins/dashboard/public/application/index.ts index fcd92da33aa5f..2558c49648b10 100644 --- a/src/plugins/dashboard/public/application/index.ts +++ b/src/plugins/dashboard/public/application/index.ts @@ -19,4 +19,4 @@ export * from './embeddable'; export * from './actions'; -export { RenderDeps } from './application'; +export type { RenderDeps } from './application'; From c355dfebab3cc46a218d3e64f194910deb1e21c9 Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Tue, 6 Oct 2020 11:58:09 -0400 Subject: [PATCH 03/62] [Ingest Manager] Move config from xpack.ingestManager to xpack.fleet (#79406) --- docs/developer/plugin-list.asciidoc | 2 +- docs/settings/ingest-manager-settings.asciidoc | 14 +++++++------- x-pack/plugins/ingest_manager/README.md | 14 +++++++------- .../plugins/ingest_manager/common/types/index.ts | 2 +- x-pack/plugins/ingest_manager/kibana.json | 2 +- .../ingest_manager/hooks/use_fleet_status.tsx | 2 +- .../public/applications/ingest_manager/index.tsx | 5 +++-- .../ingest_manager/layouts/default.tsx | 4 ++-- .../components/agent_policy_delete_provider.tsx | 2 +- .../components/package_policy_delete_provider.tsx | 2 +- .../create_package_policy_page/index.tsx | 2 +- .../details_page/components/settings/index.tsx | 2 +- .../edit_package_policy_page/index.tsx | 2 +- .../sections/agent_policy/list_page/index.tsx | 2 +- .../ingest_manager/sections/fleet/index.tsx | 4 ++-- .../sections/fleet/setup_page/index.tsx | 2 +- .../server/collectors/config_collectors.ts | 2 +- x-pack/plugins/ingest_manager/server/index.ts | 12 ++++++++---- x-pack/plugins/ingest_manager/server/plugin.ts | 2 +- .../ingest_manager/server/routes/agent/index.ts | 2 +- .../server/routes/limited_concurrency.test.ts | 6 +++--- .../server/routes/limited_concurrency.ts | 2 +- .../ingest_manager/server/routes/setup/handlers.ts | 2 +- .../ingest_manager/server/routes/setup/index.ts | 2 +- .../services/agents/checkin/state_new_actions.ts | 7 +++---- .../ingest_manager/server/services/output.ts | 4 ++-- .../ingest_manager/server/services/settings.ts | 2 +- x-pack/test/api_integration/config.ts | 4 ++-- .../test/ingest_manager_api_integration/config.ts | 4 +--- x-pack/test/saved_objects_field_count/config.ts | 2 +- x-pack/test/security_solution_endpoint/config.ts | 2 +- .../security_solution_endpoint_api_int/registry.ts | 4 ++-- 32 files changed, 62 insertions(+), 60 deletions(-) diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index d6d938bfc97de..1d4b80407cfc0 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -402,7 +402,7 @@ the infrastructure monitoring use-case within Kibana. |{kib-repo}blob/{branch}/x-pack/plugins/ingest_manager/README.md[ingestManager] -|Fleet needs to have Elasticsearch API keys enabled, and also to have TLS enabled on kibana, (if you want to run Kibana without TLS you can provide the following config flag --xpack.ingestManager.fleet.tlsCheckDisabled=false) +|Fleet needs to have Elasticsearch API keys enabled, and also to have TLS enabled on kibana, (if you want to run Kibana without TLS you can provide the following config flag --xpack.fleet.agents.tlsCheckDisabled=false) |{kib-repo}blob/{branch}/x-pack/plugins/ingest_pipelines/README.md[ingestPipelines] diff --git a/docs/settings/ingest-manager-settings.asciidoc b/docs/settings/ingest-manager-settings.asciidoc index 30e11f726c26b..9fa83fc242b4a 100644 --- a/docs/settings/ingest-manager-settings.asciidoc +++ b/docs/settings/ingest-manager-settings.asciidoc @@ -7,7 +7,7 @@ experimental[] -You can configure `xpack.ingestManager` settings in your `kibana.yml`. +You can configure `xpack.fleet` settings in your `kibana.yml`. By default, {ingest-manager} is enabled. To use {fleet}, you also need to configure {kib} and {es} hosts. See the {ingest-guide}/index.html[Ingest Management] docs for more information. @@ -17,9 +17,9 @@ See the {ingest-guide}/index.html[Ingest Management] docs for more information. [cols="2*<"] |=== -| `xpack.ingestManager.enabled` {ess-icon} +| `xpack.fleet.enabled` {ess-icon} | Set to `true` (default) to enable {ingest-manager}. -| `xpack.ingestManager.fleet.enabled` {ess-icon} +| `xpack.fleet.agents.enabled` {ess-icon} | Set to `true` (default) to enable {fleet}. |=== @@ -29,7 +29,7 @@ See the {ingest-guide}/index.html[Ingest Management] docs for more information. [cols="2*<"] |=== -| `xpack.ingestManager.registryUrl` +| `xpack.fleet.registryUrl` | The address to use to reach {package-manager} registry. |=== @@ -37,11 +37,11 @@ See the {ingest-guide}/index.html[Ingest Management] docs for more information. [cols="2*<"] |=== -| `xpack.ingestManager.fleet.kibana.host` +| `xpack.fleet.agents.kibana.host` | The hostname used by {agent} for accessing {kib}. -| `xpack.ingestManager.fleet.elasticsearch.host` +| `xpack.fleet.agents.elasticsearch.host` | The hostname used by {agent} for accessing {es}. -| `xpack.ingestManager.fleet.tlsCheckDisabled` +| `xpack.fleet.agents.tlsCheckDisabled` | Set to `true` to allow {fleet} to run on a {kib} instance without TLS enabled. |=== diff --git a/x-pack/plugins/ingest_manager/README.md b/x-pack/plugins/ingest_manager/README.md index 65df682c23659..ade5985782c89 100644 --- a/x-pack/plugins/ingest_manager/README.md +++ b/x-pack/plugins/ingest_manager/README.md @@ -3,23 +3,23 @@ ## Plugin - The plugin is enabled by default. See the TypeScript type for the [the available plugin configuration options](https://github.com/elastic/kibana/blob/master/x-pack/plugins/ingest_manager/common/types/index.ts#L9-L27) -- Adding `xpack.ingestManager.enabled=false` will disable the plugin including the EPM and Fleet features. It will also remove the `PACKAGE_POLICY_API_ROUTES` and `AGENT_POLICY_API_ROUTES` values in [`common/constants/routes.ts`](./common/constants/routes.ts) -- Adding `--xpack.ingestManager.fleet.enabled=false` will disable the Fleet API & UI +- Adding `xpack.fleet.enabled=false` will disable the plugin including the EPM and Fleet features. It will also remove the `PACKAGE_POLICY_API_ROUTES` and `AGENT_POLICY_API_ROUTES` values in [`common/constants/routes.ts`](./common/constants/routes.ts) +- Adding `--xpack.fleet.agents.enabled=false` will disable the Fleet API & UI - [code for adding the routes](https://github.com/elastic/kibana/blob/1f27d349533b1c2865c10c45b2cf705d7416fb36/x-pack/plugins/ingest_manager/server/plugin.ts#L115-L133) - [Integration tests](server/integration_tests/router.test.ts) - Both EPM and Fleet require `ingestManager` be enabled. They are not standalone features. -- For Enterprise license, a custom package registry URL can be used by setting `xpack.ingestManager.registryUrl=http://localhost:8080` +- For Enterprise license, a custom package registry URL can be used by setting `xpack.fleet.registryUrl=http://localhost:8080` - This property is currently only for internal Elastic development and is unsupported ## Fleet Requirements -Fleet needs to have Elasticsearch API keys enabled, and also to have TLS enabled on kibana, (if you want to run Kibana without TLS you can provide the following config flag `--xpack.ingestManager.fleet.tlsCheckDisabled=false`) +Fleet needs to have Elasticsearch API keys enabled, and also to have TLS enabled on kibana, (if you want to run Kibana without TLS you can provide the following config flag `--xpack.fleet.agents.tlsCheckDisabled=false`) Also you need to configure the hosts your agent is going to use to comunication with Elasticsearch and Kibana (Not needed if you use Elastic cloud). You can use the following flags: ``` ---xpack.ingestManager.fleet.elasticsearch.host=http://localhost:9200 ---xpack.ingestManager.fleet.kibana.host=http://localhost:5601 +--xpack.fleet.agents.elasticsearch.host=http://localhost:9200 +--xpack.fleet.agents.kibana.host=http://localhost:5601 ``` ## Development @@ -40,7 +40,7 @@ One common development workflow is: ``` - Start Kibana in another shell ``` - yarn start --xpack.ingestManager.enabled=true --no-base-path + yarn start --xpack.fleet.enabled=true --no-base-path ``` This plugin follows the `common`, `server`, `public` structure from the [Architecture Style Guide diff --git a/x-pack/plugins/ingest_manager/common/types/index.ts b/x-pack/plugins/ingest_manager/common/types/index.ts index d62f4fbb023dc..49be48ef542f5 100644 --- a/x-pack/plugins/ingest_manager/common/types/index.ts +++ b/x-pack/plugins/ingest_manager/common/types/index.ts @@ -9,7 +9,7 @@ export * from './rest_spec'; export interface IngestManagerConfigType { enabled: boolean; registryUrl?: string; - fleet: { + agents: { enabled: boolean; tlsCheckDisabled: boolean; pollingRequestTimeout: number; diff --git a/x-pack/plugins/ingest_manager/kibana.json b/x-pack/plugins/ingest_manager/kibana.json index 3a47da9fee01f..5ea6d21e1282e 100644 --- a/x-pack/plugins/ingest_manager/kibana.json +++ b/x-pack/plugins/ingest_manager/kibana.json @@ -3,7 +3,7 @@ "version": "kibana", "server": true, "ui": true, - "configPath": ["xpack", "ingestManager"], + "configPath": ["xpack", "fleet"], "requiredPlugins": ["licensing", "data", "encryptedSavedObjects"], "optionalPlugins": ["security", "features", "cloud", "usageCollection", "home"], "extraPublicDirs": ["common"], diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_fleet_status.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_fleet_status.tsx index 8290dfb8691cf..18bcb4539c740 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_fleet_status.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/hooks/use_fleet_status.tsx @@ -25,7 +25,7 @@ const FleetStatusContext = React.createContext(undefine export const FleetStatusProvider: React.FC = ({ children }) => { const config = useConfig(); const [state, setState] = useState({ - enabled: config.fleet.enabled, + enabled: config.agents.enabled, isLoading: false, isReady: false, }); diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/index.tsx index 1262644382f37..563c4b4750c37 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/index.tsx @@ -68,7 +68,8 @@ const ErrorLayout = ({ children }: { children: JSX.Element }) => ( const IngestManagerRoutes = memo<{ history: AppMountParameters['history']; basepath: string }>( ({ history, ...rest }) => { useBreadcrumbs('base'); - const { fleet } = useConfig(); + const { agents } = useConfig(); + const { notifications } = useCore(); const [isPermissionsLoading, setIsPermissionsLoading] = useState(false); @@ -209,7 +210,7 @@ const IngestManagerRoutes = memo<{ history: AppMountParameters['history']; basep - + diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx index 5de47ee4f410b..d71b90d16725d 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/layouts/default.tsx @@ -41,7 +41,7 @@ export const DefaultLayout: React.FunctionComponent = ({ children, }) => { const { getHref } = useLink(); - const { fleet } = useConfig(); + const { agents } = useConfig(); const [isSettingsFlyoutOpen, setIsSettingsFlyoutOpen] = React.useState(false); return ( @@ -80,7 +80,7 @@ export const DefaultLayout: React.FunctionComponent = ({ void; export const AgentPolicyDeleteProvider: React.FunctionComponent = ({ children }) => { const { notifications } = useCore(); const { - fleet: { enabled: isFleetEnabled }, + agents: { enabled: isFleetEnabled }, } = useConfig(); const [agentPolicy, setAgentPolicy] = useState(); const [isModalOpen, setIsModalOpen] = useState(false); diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/package_policy_delete_provider.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/package_policy_delete_provider.tsx index 3a6852de873f8..9242c6eb86225 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/package_policy_delete_provider.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/components/package_policy_delete_provider.tsx @@ -30,7 +30,7 @@ export const PackagePolicyDeleteProvider: React.FunctionComponent = ({ }) => { const { notifications } = useCore(); const { - fleet: { enabled: isFleetEnabled }, + agents: { enabled: isFleetEnabled }, } = useConfig(); const [packagePolicies, setPackagePolicies] = useState([]); const [isModalOpen, setIsModalOpen] = useState(false); diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/index.tsx index 39f35fed56ef5..70e11d46aa7f6 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/create_package_policy_page/index.tsx @@ -59,7 +59,7 @@ export const CreatePackagePolicyPage: React.FunctionComponent = () => { application: { navigateToApp }, } = useCore(); const { - fleet: { enabled: isFleetEnabled }, + agents: { enabled: isFleetEnabled }, } = useConfig(); const { params: { policyId, pkgkey }, diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/settings/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/settings/index.tsx index 58941c25c0fae..bc0457ffa0d43 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/settings/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/details_page/components/settings/index.tsx @@ -35,7 +35,7 @@ export const SettingsView = memo<{ agentPolicy: AgentPolicy }>( ({ agentPolicy: originalAgentPolicy }) => { const { notifications } = useCore(); const { - fleet: { enabled: isFleetEnabled }, + agents: { enabled: isFleetEnabled }, } = useConfig(); const history = useHistory(); const { getPath } = useLink(); diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/edit_package_policy_page/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/edit_package_policy_page/index.tsx index 816cf66d63413..af4ffab12a791 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/edit_package_policy_page/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/edit_package_policy_page/index.tsx @@ -45,7 +45,7 @@ import { StepDefinePackagePolicy } from '../create_package_policy_page/step_defi export const EditPackagePolicyPage: React.FunctionComponent = () => { const { notifications } = useCore(); const { - fleet: { enabled: isFleetEnabled }, + agents: { enabled: isFleetEnabled }, } = useConfig(); const { params: { policyId, packagePolicyId }, diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/list_page/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/list_page/index.tsx index fb963dc67ae1c..aa4b42986a4f5 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/list_page/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/agent_policy/list_page/index.tsx @@ -74,7 +74,7 @@ export const AgentPolicyListPage: React.FunctionComponent<{}> = () => { const { getHref, getPath } = useLink(); const hasWriteCapabilites = useCapabilities().write; const { - fleet: { enabled: isFleetEnabled }, + agents: { enabled: isFleetEnabled }, } = useConfig(); // Table and search states diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/index.tsx index 9bb77ca44b848..c0b765c4c3496 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/index.tsx @@ -18,11 +18,11 @@ import { ListLayout } from './components/list_layout'; export const FleetApp: React.FunctionComponent = () => { useBreadcrumbs('fleet'); const core = useCore(); - const { fleet } = useConfig(); + const { agents } = useConfig(); const fleetStatus = useFleetStatus(); - if (!fleet.enabled) return null; + if (!agents.enabled) return null; if (fleetStatus.isLoading) { return ; } diff --git a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/setup_page/index.tsx b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/setup_page/index.tsx index 7f0a23caa5fa2..bac551818ec87 100644 --- a/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/setup_page/index.tsx +++ b/x-pack/plugins/ingest_manager/public/applications/ingest_manager/sections/fleet/setup_page/index.tsx @@ -222,7 +222,7 @@ xpack.security.authc.api_key.enabled: true`} /> ), - tlsFlag: xpack.ingestManager.fleet.tlsCheckDisabled, + tlsFlag: xpack.fleet.agents.tlsCheckDisabled, true: true, }} /> diff --git a/x-pack/plugins/ingest_manager/server/collectors/config_collectors.ts b/x-pack/plugins/ingest_manager/server/collectors/config_collectors.ts index 514984f7f859d..c201d1d4dfa25 100644 --- a/x-pack/plugins/ingest_manager/server/collectors/config_collectors.ts +++ b/x-pack/plugins/ingest_manager/server/collectors/config_collectors.ts @@ -7,5 +7,5 @@ import { IngestManagerConfigType } from '..'; export const getIsFleetEnabled = (config: IngestManagerConfigType) => { - return config.fleet.enabled; + return config.agents.enabled; }; diff --git a/x-pack/plugins/ingest_manager/server/index.ts b/x-pack/plugins/ingest_manager/server/index.ts index f87ebb3d2c404..70685cf818b08 100644 --- a/x-pack/plugins/ingest_manager/server/index.ts +++ b/x-pack/plugins/ingest_manager/server/index.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import { schema, TypeOf } from '@kbn/config-schema'; -import { PluginInitializerContext } from 'src/core/server'; +import { PluginConfigDescriptor, PluginInitializerContext } from 'src/core/server'; import { IngestManagerPlugin } from './plugin'; import { AGENT_POLICY_ROLLOUT_RATE_LIMIT_INTERVAL_MS, @@ -19,15 +19,19 @@ export { ExternalCallback, } from './plugin'; -export const config = { +export const config: PluginConfigDescriptor = { exposeToBrowser: { epm: true, - fleet: true, + agents: true, }, + deprecations: ({ renameFromRoot }) => [ + renameFromRoot('xpack.ingestManager.fleet', 'xpack.fleet.agents'), + renameFromRoot('xpack.ingestManager', 'xpack.fleet'), + ], schema: schema.object({ enabled: schema.boolean({ defaultValue: true }), registryUrl: schema.maybe(schema.uri()), - fleet: schema.object({ + agents: schema.object({ enabled: schema.boolean({ defaultValue: true }), tlsCheckDisabled: schema.boolean({ defaultValue: false }), pollingRequestTimeout: schema.number({ diff --git a/x-pack/plugins/ingest_manager/server/plugin.ts b/x-pack/plugins/ingest_manager/server/plugin.ts index 6237b6d9ba357..e3757b46ed715 100644 --- a/x-pack/plugins/ingest_manager/server/plugin.ts +++ b/x-pack/plugins/ingest_manager/server/plugin.ts @@ -231,7 +231,7 @@ export class IngestManagerPlugin registerEPMRoutes(router); // Conditional config routes - if (config.fleet.enabled) { + if (config.agents.enabled) { const isESOUsingEphemeralEncryptionKey = deps.encryptedSavedObjects.usingEphemeralEncryptionKey; if (isESOUsingEphemeralEncryptionKey) { diff --git a/x-pack/plugins/ingest_manager/server/routes/agent/index.ts b/x-pack/plugins/ingest_manager/server/routes/agent/index.ts index f7b0c536d1a0d..2f97a6bcde42c 100644 --- a/x-pack/plugins/ingest_manager/server/routes/agent/index.ts +++ b/x-pack/plugins/ingest_manager/server/routes/agent/index.ts @@ -119,7 +119,7 @@ export const registerRoutes = (router: IRouter, config: IngestManagerConfigType) getAgentsHandler ); - const pollingRequestTimeout = config.fleet.pollingRequestTimeout; + const pollingRequestTimeout = config.agents.pollingRequestTimeout; // Agent checkin router.post( { diff --git a/x-pack/plugins/ingest_manager/server/routes/limited_concurrency.test.ts b/x-pack/plugins/ingest_manager/server/routes/limited_concurrency.test.ts index e5b5a83743287..cc358c32528c9 100644 --- a/x-pack/plugins/ingest_manager/server/routes/limited_concurrency.test.ts +++ b/x-pack/plugins/ingest_manager/server/routes/limited_concurrency.test.ts @@ -15,7 +15,7 @@ import { IngestManagerConfigType } from '../index'; describe('registerLimitedConcurrencyRoutes', () => { test(`doesn't call registerOnPreAuth if maxConcurrentConnections is 0`, async () => { const mockSetup = coreMock.createSetup(); - const mockConfig = { fleet: { maxConcurrentConnections: 0 } } as IngestManagerConfigType; + const mockConfig = { agents: { maxConcurrentConnections: 0 } } as IngestManagerConfigType; registerLimitedConcurrencyRoutes(mockSetup, mockConfig); expect(mockSetup.http.registerOnPreAuth).not.toHaveBeenCalled(); @@ -23,7 +23,7 @@ describe('registerLimitedConcurrencyRoutes', () => { test(`calls registerOnPreAuth once if maxConcurrentConnections is 1`, async () => { const mockSetup = coreMock.createSetup(); - const mockConfig = { fleet: { maxConcurrentConnections: 1 } } as IngestManagerConfigType; + const mockConfig = { agents: { maxConcurrentConnections: 1 } } as IngestManagerConfigType; registerLimitedConcurrencyRoutes(mockSetup, mockConfig); expect(mockSetup.http.registerOnPreAuth).toHaveBeenCalledTimes(1); @@ -31,7 +31,7 @@ describe('registerLimitedConcurrencyRoutes', () => { test(`calls registerOnPreAuth once if maxConcurrentConnections is 1000`, async () => { const mockSetup = coreMock.createSetup(); - const mockConfig = { fleet: { maxConcurrentConnections: 1000 } } as IngestManagerConfigType; + const mockConfig = { agents: { maxConcurrentConnections: 1000 } } as IngestManagerConfigType; registerLimitedConcurrencyRoutes(mockSetup, mockConfig); expect(mockSetup.http.registerOnPreAuth).toHaveBeenCalledTimes(1); diff --git a/x-pack/plugins/ingest_manager/server/routes/limited_concurrency.ts b/x-pack/plugins/ingest_manager/server/routes/limited_concurrency.ts index 7ba8e151b726c..609428f5477f1 100644 --- a/x-pack/plugins/ingest_manager/server/routes/limited_concurrency.ts +++ b/x-pack/plugins/ingest_manager/server/routes/limited_concurrency.ts @@ -75,7 +75,7 @@ export function createLimitedPreAuthHandler({ } export function registerLimitedConcurrencyRoutes(core: CoreSetup, config: IngestManagerConfigType) { - const max = config.fleet.maxConcurrentConnections; + const max = config.agents.maxConcurrentConnections; if (!max) return; core.http.registerOnPreAuth( diff --git a/x-pack/plugins/ingest_manager/server/routes/setup/handlers.ts b/x-pack/plugins/ingest_manager/server/routes/setup/handlers.ts index ee7dab6ef1a8b..0bd7b4e875062 100644 --- a/x-pack/plugins/ingest_manager/server/routes/setup/handlers.ts +++ b/x-pack/plugins/ingest_manager/server/routes/setup/handlers.ts @@ -19,7 +19,7 @@ export const getFleetStatusHandler: RequestHandler = async (context, request, re const isTLSEnabled = appContextService.getHttpSetup().getServerInfo().protocol === 'https'; const isProductionMode = appContextService.getIsProductionMode(); const isCloud = appContextService.getCloud()?.isCloudEnabled ?? false; - const isTLSCheckDisabled = appContextService.getConfig()?.fleet?.tlsCheckDisabled ?? false; + const isTLSCheckDisabled = appContextService.getConfig()?.agents?.tlsCheckDisabled ?? false; const isUsingEphemeralEncryptionKey = appContextService.getEncryptedSavedObjectsSetup() .usingEphemeralEncryptionKey; diff --git a/x-pack/plugins/ingest_manager/server/routes/setup/index.ts b/x-pack/plugins/ingest_manager/server/routes/setup/index.ts index b71e9983f494f..6672a7e8933a8 100644 --- a/x-pack/plugins/ingest_manager/server/routes/setup/index.ts +++ b/x-pack/plugins/ingest_manager/server/routes/setup/index.ts @@ -53,7 +53,7 @@ export const registerRoutes = (router: IRouter, config: IngestManagerConfigType) // Ingest manager setup registerIngestManagerSetupRoute(router); - if (!config.fleet.enabled) { + if (!config.agents.enabled) { return; } diff --git a/x-pack/plugins/ingest_manager/server/services/agents/checkin/state_new_actions.ts b/x-pack/plugins/ingest_manager/server/services/agents/checkin/state_new_actions.ts index 4862852e0cc71..1871cd2cb04f6 100644 --- a/x-pack/plugins/ingest_manager/server/services/agents/checkin/state_new_actions.ts +++ b/x-pack/plugins/ingest_manager/server/services/agents/checkin/state_new_actions.ts @@ -171,13 +171,12 @@ export async function createAgentActionFromPolicyAction( } function getPollingTimeoutMs() { - const pollingTimeoutMs = appContextService.getConfig()?.fleet.pollingRequestTimeout ?? 0; + const pollingTimeoutMs = appContextService.getConfig()?.agents.pollingRequestTimeout ?? 0; // If polling timeout is too short do not use margin if (pollingTimeoutMs <= AGENT_POLLING_REQUEST_TIMEOUT_MARGIN_MS) { return pollingTimeoutMs; } - // Set a timeout 20s before the real timeout to have a chance to respond an empty response before socket timeout return Math.max( pollingTimeoutMs - AGENT_POLLING_REQUEST_TIMEOUT_MARGIN_MS, @@ -193,10 +192,10 @@ export function agentCheckinStateNewActionsFactory() { const pollingTimeoutMs = getPollingTimeoutMs(); const rateLimiterIntervalMs = - appContextService.getConfig()?.fleet.agentPolicyRolloutRateLimitIntervalMs ?? + appContextService.getConfig()?.agents.agentPolicyRolloutRateLimitIntervalMs ?? AGENT_POLICY_ROLLOUT_RATE_LIMIT_INTERVAL_MS; const rateLimiterRequestPerInterval = - appContextService.getConfig()?.fleet.agentPolicyRolloutRateLimitRequestPerInterval ?? + appContextService.getConfig()?.agents.agentPolicyRolloutRateLimitRequestPerInterval ?? AGENT_POLICY_ROLLOUT_RATE_LIMIT_REQUEST_PER_INTERVAL; const rateLimiterMaxDelay = pollingTimeoutMs; diff --git a/x-pack/plugins/ingest_manager/server/services/output.ts b/x-pack/plugins/ingest_manager/server/services/output.ts index 1e5632719fb72..f780bd95faedc 100644 --- a/x-pack/plugins/ingest_manager/server/services/output.ts +++ b/x-pack/plugins/ingest_manager/server/services/output.ts @@ -27,7 +27,7 @@ class OutputService { const cloud = appContextService.getCloud(); const cloudId = cloud?.isCloudEnabled && cloud.cloudId; const cloudUrl = cloudId && decodeCloudId(cloudId)?.elasticsearchUrl; - const flagsUrl = appContextService.getConfig()!.fleet.elasticsearch.host; + const flagsUrl = appContextService.getConfig()!.agents.elasticsearch.host; const defaultUrl = 'http://localhost:9200'; const defaultOutputUrl = cloudUrl || flagsUrl || defaultUrl; @@ -35,7 +35,7 @@ class OutputService { const newDefaultOutput = { ...DEFAULT_OUTPUT, hosts: [defaultOutputUrl], - ca_sha256: appContextService.getConfig()!.fleet.elasticsearch.ca_sha256, + ca_sha256: appContextService.getConfig()!.agents.elasticsearch.ca_sha256, } as NewOutput; return await this.create(soClient, newDefaultOutput); diff --git a/x-pack/plugins/ingest_manager/server/services/settings.ts b/x-pack/plugins/ingest_manager/server/services/settings.ts index 25223fbc08535..44aece1c83a18 100644 --- a/x-pack/plugins/ingest_manager/server/services/settings.ts +++ b/x-pack/plugins/ingest_manager/server/services/settings.ts @@ -73,7 +73,7 @@ export function createDefaultSettings(): BaseSettings { const cloud = appContextService.getCloud(); const cloudId = cloud?.isCloudEnabled && cloud.cloudId; const cloudUrl = cloudId && decodeCloudId(cloudId)?.kibanaUrl; - const flagsUrl = appContextService.getConfig()?.fleet?.kibana?.host; + const flagsUrl = appContextService.getConfig()?.agents?.kibana?.host; const defaultUrl = url.format({ protocol: serverInfo.protocol, hostname: serverInfo.hostname, diff --git a/x-pack/test/api_integration/config.ts b/x-pack/test/api_integration/config.ts index 3b4654fc357c0..97fd968ce7992 100644 --- a/x-pack/test/api_integration/config.ts +++ b/x-pack/test/api_integration/config.ts @@ -27,8 +27,8 @@ export async function getApiIntegrationConfig({ readConfigFile }: FtrConfigProvi ...xPackFunctionalTestsConfig.get('kbnTestServer.serverArgs'), '--xpack.security.session.idleTimeout=3600000', // 1 hour '--telemetry.optIn=true', - '--xpack.ingestManager.enabled=true', - '--xpack.ingestManager.fleet.pollingRequestTimeout=5000', // 5 seconds + '--xpack.fleet.enabled=true', + '--xpack.fleet.agents.pollingRequestTimeout=5000', // 5 seconds ], }, esTestCluster: { diff --git a/x-pack/test/ingest_manager_api_integration/config.ts b/x-pack/test/ingest_manager_api_integration/config.ts index 193ac0d5974e6..15b68b8c8208d 100644 --- a/x-pack/test/ingest_manager_api_integration/config.ts +++ b/x-pack/test/ingest_manager_api_integration/config.ts @@ -63,9 +63,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { ...xPackAPITestsConfig.get('kbnTestServer'), serverArgs: [ ...xPackAPITestsConfig.get('kbnTestServer.serverArgs'), - ...(registryPort - ? [`--xpack.ingestManager.registryUrl=http://localhost:${registryPort}`] - : []), + ...(registryPort ? [`--xpack.fleet.registryUrl=http://localhost:${registryPort}`] : []), ], }, }; diff --git a/x-pack/test/saved_objects_field_count/config.ts b/x-pack/test/saved_objects_field_count/config.ts index a0e9f7a62e2c9..f3f80426c2aae 100644 --- a/x-pack/test/saved_objects_field_count/config.ts +++ b/x-pack/test/saved_objects_field_count/config.ts @@ -29,7 +29,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { ...kibanaCommonTestsConfig.get('kbnTestServer.serverArgs'), // Enable plugins that are disabled by default to include their metrics // TODO: Find a way to automatically enable all discovered plugins - '--xpack.ingestManager.enabled=true', + '--xpack.fleet.enabled=true', '--xpack.lists.enabled=true', '--xpack.securitySolution.enabled=true', ], diff --git a/x-pack/test/security_solution_endpoint/config.ts b/x-pack/test/security_solution_endpoint/config.ts index 840862ab00560..9ee9e061edf4c 100644 --- a/x-pack/test/security_solution_endpoint/config.ts +++ b/x-pack/test/security_solution_endpoint/config.ts @@ -39,7 +39,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { ...xpackFunctionalConfig.get('kbnTestServer'), serverArgs: [ ...xpackFunctionalConfig.get('kbnTestServer.serverArgs'), - '--xpack.ingestManager.enabled=true', + '--xpack.fleet.enabled=true', // if you return an empty string here the kibana server will not start properly but an empty array works ...getRegistryUrlAsArray(), ], diff --git a/x-pack/test/security_solution_endpoint_api_int/registry.ts b/x-pack/test/security_solution_endpoint_api_int/registry.ts index 9a9d184b9c297..9c5a8e98e3e2b 100644 --- a/x-pack/test/security_solution_endpoint_api_int/registry.ts +++ b/x-pack/test/security_solution_endpoint_api_int/registry.ts @@ -60,9 +60,9 @@ export function createEndpointDockerConfig( export function getRegistryUrlFromTestEnv(): string | undefined { let registryUrl: string | undefined; if (dockerRegistryPort !== undefined) { - registryUrl = `--xpack.ingestManager.registryUrl=http://localhost:${dockerRegistryPort}`; + registryUrl = `--xpack.fleet.registryUrl=http://localhost:${dockerRegistryPort}`; } else if (packageRegistryOverride !== undefined) { - registryUrl = `--xpack.ingestManager.registryUrl=${packageRegistryOverride}`; + registryUrl = `--xpack.fleet.registryUrl=${packageRegistryOverride}`; } return registryUrl; } From d9ca4c562e0357a5b5289fc90a0d4f09b96a31f5 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 6 Oct 2020 10:09:58 -0600 Subject: [PATCH 04/62] [ML] avoid full page reload for links following CSV import (#79539) * [ML] avoid full page reload for links following CSV import * cleanup * review feedback Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../results_links/results_links.tsx | 47 ++++++++++++++----- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/results_links/results_links.tsx b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/results_links/results_links.tsx index 5cba714afe47b..374d434708f4a 100644 --- a/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/results_links/results_links.tsx +++ b/x-pack/plugins/ml/public/application/datavisualizer/file_based/components/results_links/results_links.tsx @@ -45,16 +45,12 @@ export const ResultsLinks: FC = ({ const [globalState, setGlobalState] = useState(); const [discoverLink, setDiscoverLink] = useState(''); - const { - services: { - http: { basePath }, - }, - } = useMlKibana(); const mlUrlGenerator = useMlUrlGenerator(); const navigateToPath = useNavigateToPath(); const { services: { + application: { navigateToApp, navigateToUrl }, share: { urlGenerators: { getUrlGenerator }, }, @@ -72,9 +68,19 @@ export const ResultsLinks: FC = ({ if (globalState?.time) { state.timeRange = globalState.time; } + + let discoverUrlGenerator; + try { + discoverUrlGenerator = getUrlGenerator(DISCOVER_APP_URL_GENERATOR); + } catch (error) { + // ignore error thrown when url generator is not available + } + + if (!discoverUrlGenerator) { + return; + } + const discoverUrl = await discoverUrlGenerator.createUrl(state); if (!unmounted) { - const discoverUrlGenerator = getUrlGenerator(DISCOVER_APP_URL_GENERATOR); - const discoverUrl = await discoverUrlGenerator.createUrl(state); setDiscoverLink(discoverUrl); } }; @@ -142,9 +148,26 @@ export const ResultsLinks: FC = ({ } } + function openInDiscover(e: React.MouseEvent) { + e.preventDefault(); + navigateToUrl(discoverLink); + } + + function openIndexManagement(e: React.MouseEvent) { + e.preventDefault(); + navigateToApp('management', { path: '/data/index_management/indices' }); + } + + function openIndexPatternManagement(e: React.MouseEvent) { + e.preventDefault(); + navigateToApp('management', { + path: `/kibana/indexPatterns${createIndexPattern ? `/patterns/${indexPatternId}` : ''}`, + }); + } + return ( - {createIndexPattern && ( + {createIndexPattern && discoverLink && ( } @@ -155,7 +178,7 @@ export const ResultsLinks: FC = ({ /> } description="" - href={discoverLink} + onClick={openInDiscover} /> )} @@ -205,7 +228,7 @@ export const ResultsLinks: FC = ({ /> } description="" - href={`${basePath.get()}/app/management/data/index_management/indices`} + onClick={openIndexManagement} /> @@ -219,9 +242,7 @@ export const ResultsLinks: FC = ({ /> } description="" - href={`${basePath.get()}/app/management/kibana/indexPatterns${ - createIndexPattern ? `/patterns/${indexPatternId}` : '' - }`} + onClick={openIndexPatternManagement} /> From 63b76f2cd5d1b37c9ee3d23982ed22c4f621d4f4 Mon Sep 17 00:00:00 2001 From: Catherine Liu Date: Tue, 6 Oct 2020 09:13:31 -0700 Subject: [PATCH 05/62] [Core UI] Kibana Overview Page (#75827) * Added kibana landing page Created kivana_overview plugin Removed test from home plugin Added CSS Fixed page header links Added news feed Fixed spacers between news items [Core UI] Kibana Overview Page Style Tweaks (#76712) Fixed link to index management Added solution cards to kibana landing page Added solution links Fixed ts errors Using publishReplay() to support multiple consumers in newsfeed plugin Added createNewsFeed$ to newsfeed plugin start Added tests Removed unnecessary export Hides overview link when other Kibana apps are not available Added icon to overview plugin Removed question mark from news feed title Updated plugin-list Fixed i18n errors Revert snapshot Updated getting started page copy Hide news feed when no news feed results Disables Kibana overview page when kibana apps are unavailable Updated snapshots Refactor to use KibanaContextProvider Fixed security tests Fixed newsfeed api test Moved overview_footer and overview_header to kibana-react plugin [Core UI] Kibana Overview Page Style Fixes (#78677) * Fixed a11y issues * Made newsfeed optional dep of kibana overview plugin * Removed duplicate license copy * Fixed management security test * Added toast to change default route button * Updated snapshots * Simplified toast notification * Fixed i18n error * Assigned kibana_overview plugin to Core UI in CODEOWNERS * Updated snapshots * Fix import * [Core UI] Kibana Overview Page Style Fixes, Part 3 (#78970) * fix overview cards not stretching height equally * change var name for better specificity * [Core UI] Kibana Overview Page Style Fixes, Part 4 (#79136) * Adds support for all newsfeed plugin config settings in createNewsFeed$ * Fixed type * Updated kibana overview page route * Fixed imports in page_footer and page_header * Update Kibana overview graphics (#79534) * Updated snapshots * Updated snapshots * Changes newsfeed endpoint to kibana analytics in kibana_overview plugin * Renamed components * Fixed overview page footer and header component class names * Removed extraneous files * Fixed import * Replaced SVGs with optimized SVGs * Fixed header and footer in home and kibana overview pages * Updated snapshots * Changed url_forwarding plugin appRoute * Fixed aria-labelledby value * Updated snapshots * Added base paths Co-authored-by: Michael Marcialis Co-authored-by: Ryan Keairns --- .github/CODEOWNERS | 1 + .i18nrc.json | 1 + docs/developer/plugin-list.asciidoc | 4 + .../management_app/advanced_settings.tsx | 13 +- src/plugins/dashboard/public/plugin.tsx | 5 + .../discover/public/register_feature.ts | 5 + .../__snapshots__/home.test.js.snap | 1432 ++++------------- .../__snapshots__/synopsis.test.js.snap | 1 + .../application/components/_add_data.scss | 5 +- .../public/application/components/_home.scss | 33 +- .../public/application/components/_index.scss | 1 - .../components/_solutions_section.scss | 26 +- .../__snapshots__/add_data.test.tsx.snap | 29 +- .../components/add_data/add_data.test.tsx | 25 +- .../components/add_data/add_data.tsx | 29 +- .../public/application/components/home.js | 139 +- .../application/components/home.test.js | 13 +- .../public/application/components/home_app.js | 5 +- .../manage_data/manage_data.test.tsx | 4 - .../solution_panel.test.tsx.snap | 1 + .../solution_title.test.tsx.snap | 2 +- .../solutions_section.test.tsx.snap | 102 +- .../solutions_section/solution_panel.test.tsx | 3 +- .../solutions_section/solution_panel.tsx | 17 +- .../solutions_section/solution_title.tsx | 2 +- .../solutions_section.test.tsx | 58 +- .../solutions_section/solutions_section.tsx | 54 +- .../public/application/components/synopsis.js | 2 +- src/plugins/home/public/index.ts | 1 + src/plugins/home/public/plugin.test.ts | 17 - src/plugins/home/public/plugin.ts | 45 +- .../feature_catalogue_registry.mock.ts | 1 + .../feature_catalogue_registry.test.ts | 2 +- .../feature_catalogue_registry.ts | 16 +- src/plugins/kibana_overview/README.md | 9 + src/plugins/kibana_overview/common/index.ts | 23 + src/plugins/kibana_overview/kibana.json | 9 + .../kibana_overview/public/application.tsx | 62 + .../public/assets/kibana_canvas_dark.svg | 69 + .../public/assets/kibana_canvas_light.svg | 69 + .../public/assets/kibana_dashboard_dark.svg | 116 ++ .../public/assets/kibana_dashboard_light.svg | 116 ++ .../public/assets/kibana_discover_dark.svg | 145 ++ .../public/assets/kibana_discover_light.svg | 145 ++ .../public/assets/kibana_graph_dark.svg | 68 + .../public/assets/kibana_graph_light.svg | 68 + .../public/assets/kibana_maps_dark.svg | 57 + .../public/assets/kibana_maps_light.svg | 57 + .../public/assets/kibana_ml_dark.svg | 141 ++ .../public/assets/kibana_ml_light.svg | 141 ++ .../public/assets/kibana_montage_dark.svg | 178 ++ .../public/assets/kibana_montage_light.svg | 218 +++ .../solutions_enterprise_search_dark_2x.png | Bin 0 -> 2566 bytes .../solutions_enterprise_search_light_2x.png | Bin 0 -> 2503 bytes .../solutions_observability_dark_2x.png | Bin 0 -> 1484 bytes .../solutions_observability_light_2x.png | Bin 0 -> 1487 bytes .../solutions_security_solution_dark_2x.png | Bin 0 -> 1999 bytes .../solutions_security_solution_light_2x.png | Bin 0 -> 2041 bytes .../public/components/_index.scss | 1 + .../public/components/_overview.scss | 120 ++ .../__snapshots__/add_data.test.tsx.snap | 102 ++ .../components/add_data/add_data.test.tsx | 67 + .../public/components/add_data/add_data.tsx | 108 ++ .../public/components/add_data/index.ts} | 4 +- .../kibana_overview/public/components/app.tsx | 69 + .../getting_started.test.tsx.snap | 391 +++++ .../getting_started/getting_started.test.tsx | 118 ++ .../getting_started/getting_started.tsx | 126 ++ .../components/getting_started/index.ts | 20 + .../__snapshots__/manage_data.test.tsx.snap | 103 ++ .../public/components/manage_data/index.tsx | 20 + .../manage_data/manage_data.test.tsx | 83 + .../components/manage_data/manage_data.tsx | 95 ++ .../__snapshots__/news_feed.test.tsx.snap | 149 ++ .../public/components/news_feed/index.ts | 20 + .../components/news_feed/news_feed.test.tsx | 68 + .../public/components/news_feed/news_feed.tsx | 69 + .../__snapshots__/overview.test.tsx.snap | 1222 ++++++++++++++ .../public/components/overview/index.ts | 20 + .../components/overview/overview.test.tsx | 180 +++ .../public/components/overview/overview.tsx | 259 +++ .../__snapshots__/synopsis.test.js.snap | 72 + .../public/components/synopsis/index.js | 20 + .../public/components/synopsis/synopsis.js | 77 + .../components/synopsis/synopsis.test.js | 76 + src/plugins/kibana_overview/public/index.scss | 1 + src/plugins/kibana_overview/public/index.ts | 29 + src/plugins/kibana_overview/public/plugin.ts | 139 ++ src/plugins/kibana_overview/public/types.ts | 40 + src/plugins/kibana_react/public/index.ts | 1 + .../public/overview_page/index.ts | 21 + .../overview_page_footer.test.tsx.snap | 49 + .../overview_page_footer/index.ts | 20 + .../overview_page_footer.test.tsx | 52 + .../overview_page_footer.tsx | 114 ++ .../overview_page_header.test.tsx.snap | 68 + .../_overview_page_header.scss | 33 + .../overview_page_header/index.scss | 20 + .../overview_page_header/index.ts | 20 + .../overview_page_header.test.tsx | 49 + .../overview_page_header.tsx | 149 ++ src/plugins/newsfeed/common/constants.ts | 2 + src/plugins/newsfeed/public/index.ts | 16 +- src/plugins/newsfeed/public/lib/api.test.ts | 16 +- src/plugins/newsfeed/public/lib/api.ts | 33 +- src/plugins/newsfeed/public/plugin.tsx | 35 +- src/plugins/newsfeed/public/types.ts | 4 +- .../public/forward_app/forward_app.ts | 1 + .../canvas/public/feature_catalogue_entry.ts | 5 + .../enterprise_search/common/constants.ts | 5 +- .../enterprise_search/public/plugin.ts | 3 +- x-pack/plugins/graph/public/plugin.ts | 12 +- .../maps/public/feature_catalogue_entry.ts | 5 + x-pack/plugins/ml/public/register_feature.ts | 5 + x-pack/plugins/observability/public/plugin.ts | 8 +- .../security_solution/public/plugin.tsx | 6 +- .../plugins/security_solution/public/types.ts | 4 +- .../advanced_settings_security.ts | 2 +- .../feature_controls/canvas_security.ts | 4 +- .../feature_controls/dashboard_security.ts | 6 +- .../feature_controls/discover_security.ts | 6 +- .../graph/feature_controls/graph_security.ts | 4 +- .../index_patterns_security.ts | 2 +- .../feature_controls/management_security.ts | 2 +- .../maps/feature_controls/maps_security.ts | 4 +- .../feature_controls/timelion_security.ts | 4 +- .../feature_controls/visualize_security.ts | 6 +- 127 files changed, 6874 insertions(+), 1575 deletions(-) create mode 100644 src/plugins/kibana_overview/README.md create mode 100644 src/plugins/kibana_overview/common/index.ts create mode 100644 src/plugins/kibana_overview/kibana.json create mode 100644 src/plugins/kibana_overview/public/application.tsx create mode 100644 src/plugins/kibana_overview/public/assets/kibana_canvas_dark.svg create mode 100644 src/plugins/kibana_overview/public/assets/kibana_canvas_light.svg create mode 100644 src/plugins/kibana_overview/public/assets/kibana_dashboard_dark.svg create mode 100644 src/plugins/kibana_overview/public/assets/kibana_dashboard_light.svg create mode 100644 src/plugins/kibana_overview/public/assets/kibana_discover_dark.svg create mode 100644 src/plugins/kibana_overview/public/assets/kibana_discover_light.svg create mode 100644 src/plugins/kibana_overview/public/assets/kibana_graph_dark.svg create mode 100644 src/plugins/kibana_overview/public/assets/kibana_graph_light.svg create mode 100644 src/plugins/kibana_overview/public/assets/kibana_maps_dark.svg create mode 100644 src/plugins/kibana_overview/public/assets/kibana_maps_light.svg create mode 100644 src/plugins/kibana_overview/public/assets/kibana_ml_dark.svg create mode 100644 src/plugins/kibana_overview/public/assets/kibana_ml_light.svg create mode 100644 src/plugins/kibana_overview/public/assets/kibana_montage_dark.svg create mode 100644 src/plugins/kibana_overview/public/assets/kibana_montage_light.svg create mode 100644 src/plugins/kibana_overview/public/assets/solutions_enterprise_search_dark_2x.png create mode 100644 src/plugins/kibana_overview/public/assets/solutions_enterprise_search_light_2x.png create mode 100644 src/plugins/kibana_overview/public/assets/solutions_observability_dark_2x.png create mode 100644 src/plugins/kibana_overview/public/assets/solutions_observability_light_2x.png create mode 100644 src/plugins/kibana_overview/public/assets/solutions_security_solution_dark_2x.png create mode 100644 src/plugins/kibana_overview/public/assets/solutions_security_solution_light_2x.png create mode 100644 src/plugins/kibana_overview/public/components/_index.scss create mode 100644 src/plugins/kibana_overview/public/components/_overview.scss create mode 100644 src/plugins/kibana_overview/public/components/add_data/__snapshots__/add_data.test.tsx.snap create mode 100644 src/plugins/kibana_overview/public/components/add_data/add_data.test.tsx create mode 100644 src/plugins/kibana_overview/public/components/add_data/add_data.tsx rename src/plugins/{home/public/application/components/_manage_data.scss => kibana_overview/public/components/add_data/index.ts} (90%) create mode 100644 src/plugins/kibana_overview/public/components/app.tsx create mode 100644 src/plugins/kibana_overview/public/components/getting_started/__snapshots__/getting_started.test.tsx.snap create mode 100644 src/plugins/kibana_overview/public/components/getting_started/getting_started.test.tsx create mode 100644 src/plugins/kibana_overview/public/components/getting_started/getting_started.tsx create mode 100644 src/plugins/kibana_overview/public/components/getting_started/index.ts create mode 100644 src/plugins/kibana_overview/public/components/manage_data/__snapshots__/manage_data.test.tsx.snap create mode 100644 src/plugins/kibana_overview/public/components/manage_data/index.tsx create mode 100644 src/plugins/kibana_overview/public/components/manage_data/manage_data.test.tsx create mode 100644 src/plugins/kibana_overview/public/components/manage_data/manage_data.tsx create mode 100644 src/plugins/kibana_overview/public/components/news_feed/__snapshots__/news_feed.test.tsx.snap create mode 100644 src/plugins/kibana_overview/public/components/news_feed/index.ts create mode 100644 src/plugins/kibana_overview/public/components/news_feed/news_feed.test.tsx create mode 100644 src/plugins/kibana_overview/public/components/news_feed/news_feed.tsx create mode 100644 src/plugins/kibana_overview/public/components/overview/__snapshots__/overview.test.tsx.snap create mode 100644 src/plugins/kibana_overview/public/components/overview/index.ts create mode 100644 src/plugins/kibana_overview/public/components/overview/overview.test.tsx create mode 100644 src/plugins/kibana_overview/public/components/overview/overview.tsx create mode 100644 src/plugins/kibana_overview/public/components/synopsis/__snapshots__/synopsis.test.js.snap create mode 100644 src/plugins/kibana_overview/public/components/synopsis/index.js create mode 100644 src/plugins/kibana_overview/public/components/synopsis/synopsis.js create mode 100644 src/plugins/kibana_overview/public/components/synopsis/synopsis.test.js create mode 100644 src/plugins/kibana_overview/public/index.scss create mode 100644 src/plugins/kibana_overview/public/index.ts create mode 100644 src/plugins/kibana_overview/public/plugin.ts create mode 100644 src/plugins/kibana_overview/public/types.ts create mode 100644 src/plugins/kibana_react/public/overview_page/index.ts create mode 100644 src/plugins/kibana_react/public/overview_page/overview_page_footer/__snapshots__/overview_page_footer.test.tsx.snap create mode 100644 src/plugins/kibana_react/public/overview_page/overview_page_footer/index.ts create mode 100644 src/plugins/kibana_react/public/overview_page/overview_page_footer/overview_page_footer.test.tsx create mode 100644 src/plugins/kibana_react/public/overview_page/overview_page_footer/overview_page_footer.tsx create mode 100644 src/plugins/kibana_react/public/overview_page/overview_page_header/__snapshots__/overview_page_header.test.tsx.snap create mode 100644 src/plugins/kibana_react/public/overview_page/overview_page_header/_overview_page_header.scss create mode 100644 src/plugins/kibana_react/public/overview_page/overview_page_header/index.scss create mode 100644 src/plugins/kibana_react/public/overview_page/overview_page_header/index.ts create mode 100644 src/plugins/kibana_react/public/overview_page/overview_page_header/overview_page_header.test.tsx create mode 100644 src/plugins/kibana_react/public/overview_page/overview_page_header/overview_page_header.tsx diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index d21d6ad81a0c6..d522be908b69c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -137,6 +137,7 @@ /src/plugins/home/public @elastic/kibana-core-ui /src/plugins/home/server/*.ts @elastic/kibana-core-ui /src/plugins/home/server/services/ @elastic/kibana-core-ui +/src/plugins/kibana_overview/ @elastic/kibana-core-ui /x-pack/plugins/global_search_bar/ @elastic/kibana-core-ui #CC# /src/legacy/core_plugins/newsfeed @elastic/kibana-core-ui #CC# /src/legacy/server/sample_data/ @elastic/kibana-core-ui diff --git a/.i18nrc.json b/.i18nrc.json index 7ecaa89f66604..e0281b0a5bc21 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -29,6 +29,7 @@ "indexPatternManagement": "src/plugins/index_pattern_management", "advancedSettings": "src/plugins/advanced_settings", "kibana_legacy": "src/plugins/kibana_legacy", + "kibanaOverview": "src/plugins/kibana_overview", "kibana_react": "src/legacy/core_plugins/kibana_react", "kibana-react": "src/plugins/kibana_react", "kibana_utils": "src/plugins/kibana_utils", diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index 1d4b80407cfc0..167c3fc70fdda 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -110,6 +110,10 @@ in Kibana, e.g. visualizations. It has the form of a flyout panel. |This plugin contains several helpers and services to integrate pieces of the legacy Kibana app with the new Kibana platform. +|{kib-repo}blob/{branch}/src/plugins/kibana_overview/README.md[kibanaOverview] +|An overview page highlighting Kibana apps + + |{kib-repo}blob/{branch}/src/plugins/kibana_react/README.md[kibanaReact] |Tools for building React applications in Kibana. diff --git a/src/plugins/advanced_settings/public/management_app/advanced_settings.tsx b/src/plugins/advanced_settings/public/management_app/advanced_settings.tsx index 8c9e3847844d9..afdd90959eabd 100644 --- a/src/plugins/advanced_settings/public/management_app/advanced_settings.tsx +++ b/src/plugins/advanced_settings/public/management_app/advanced_settings.tsx @@ -121,7 +121,18 @@ export class AdvancedSettingsComponent extends Component< setTimeout(() => { const id = hash.replace('#', ''); const element = document.getElementById(id); - const globalNavOffset = document.getElementById('globalHeaderBars')?.offsetHeight || 0; + + let globalNavOffset = 0; + + const globalNavBars = document + .getElementById('globalHeaderBars') + ?.getElementsByClassName('euiHeader'); + + if (globalNavBars) { + Array.from(globalNavBars).forEach((navBar) => { + globalNavOffset += (navBar as HTMLDivElement).offsetHeight; + }); + } if (element) { element.scrollIntoView(); diff --git a/src/plugins/dashboard/public/plugin.tsx b/src/plugins/dashboard/public/plugin.tsx index 91f603dfc6c77..3325d193e56ed 100644 --- a/src/plugins/dashboard/public/plugin.tsx +++ b/src/plugins/dashboard/public/plugin.tsx @@ -395,6 +395,9 @@ export class DashboardPlugin title: i18n.translate('dashboard.featureCatalogue.dashboardTitle', { defaultMessage: 'Dashboard', }), + subtitle: i18n.translate('dashboard.featureCatalogue.dashboardSubtitle', { + defaultMessage: 'Analyze data in dashboards.', + }), description: i18n.translate('dashboard.featureCatalogue.dashboardDescription', { defaultMessage: 'Display and share a collection of visualizations and saved searches.', }), @@ -402,6 +405,8 @@ export class DashboardPlugin path: `/app/dashboards#${DashboardConstants.LANDING_PAGE_PATH}`, showOnHomePage: false, category: FeatureCatalogueCategory.DATA, + solutionId: 'kibana', + order: 100, }); } } diff --git a/src/plugins/discover/public/register_feature.ts b/src/plugins/discover/public/register_feature.ts index 5443bb261ab10..9a66936233692 100644 --- a/src/plugins/discover/public/register_feature.ts +++ b/src/plugins/discover/public/register_feature.ts @@ -25,6 +25,9 @@ export function registerFeature(home: HomePublicPluginSetup) { title: i18n.translate('discover.discoverTitle', { defaultMessage: 'Discover', }), + subtitle: i18n.translate('discover.discoverSubtitle', { + defaultMessage: 'Search and find insights.', + }), description: i18n.translate('discover.discoverDescription', { defaultMessage: 'Interactively explore your data by querying and filtering raw documents.', }), @@ -32,5 +35,7 @@ export function registerFeature(home: HomePublicPluginSetup) { path: '/app/discover#/', showOnHomePage: false, category: FeatureCatalogueCategory.DATA, + solutionId: 'kibana', + order: 200, }); } diff --git a/src/plugins/home/public/application/components/__snapshots__/home.test.js.snap b/src/plugins/home/public/application/components/__snapshots__/home.test.js.snap index bf1e8c8f0b401..e9b0494105e12 100644 --- a/src/plugins/home/public/application/components/__snapshots__/home.test.js.snap +++ b/src/plugins/home/public/application/components/__snapshots__/home.test.js.snap @@ -2,57 +2,26 @@ exports[`home change home route should render a link to change the default route in advanced settings if advanced settings is enabled 1`] = `
-
-
- - - -

- -

-
-
- - - - - Add data - - - - -
-
-
+ + } + />
- 0 @@ -73,115 +42,36 @@ exports[`home change home route should render a link to change the default route aria-hidden="true" margin="xl" /> -
- - - - - - - - - - - - -
+
`; exports[`home directories should not render directory entry when showOnHomePage is false 1`] = `
-
-
- - - -

- -

-
-
- - - - - Add data - - - - - Manage - - - - -
-
-
+ + } + />
- 0 @@ -202,92 +92,36 @@ exports[`home directories should not render directory entry when showOnHomePage aria-hidden="true" margin="xl" /> -
- - - - - - - - -
+
`; exports[`home directories should render ADMIN directory entry in "Manage your data" panel 1`] = `
-
-
- - - -

- -

-
-
- - - - - Add data - - - - -
-
-
+ + } + />
- 0 @@ -320,92 +154,36 @@ exports[`home directories should render ADMIN directory entry in "Manage your da aria-hidden="true" margin="xl" /> -
- - - - - - - - -
+
`; exports[`home directories should render DATA directory entry in "Ingest your data" panel 1`] = `
-
-
- - - -

- -

-
-
- - - - - Add data - - - - -
-
-
+ + } + />
- 0 @@ -438,97 +216,43 @@ exports[`home directories should render DATA directory entry in "Ingest your dat aria-hidden="true" margin="xl" /> -
- - - - - - - - -
+
`; exports[`home directories should render solutions in the "solution section" 1`] = `
-
-
- - - -

- -

-
-
- - - - - Add data - - - - -
-
-
+ + } + />
`; exports[`home header render 1`] = `
-
-
- - - -

- -

-
-
- - - - - Add data - - - - -
-
-
+ + } + />
- 0 @@ -700,102 +368,36 @@ exports[`home header render 1`] = ` aria-hidden="true" margin="xl" /> -
- - - - - - - - -
+
`; exports[`home header should show "Dev tools" link if console is available 1`] = `
-
-
- - - -

- -

-
-
- - - - - Add data - - - - - Dev tools - - - - -
-
-
+ + } + />
- 0 @@ -828,103 +430,36 @@ exports[`home header should show "Dev tools" link if console is available 1`] = aria-hidden="true" margin="xl" /> -
- - - - - - - - -
+
`; exports[`home header should show "Manage" link if stack management is available 1`] = `
-
-
- - - -

- -

-
-
- - - - - Add data - - - - - Manage - - - - -
-
-
+ + } + />
- 0 @@ -945,92 +480,36 @@ exports[`home header should show "Manage" link if stack management is available aria-hidden="true" margin="xl" /> -
- - - - - - - - -
+
`; exports[`home isNewKibanaInstance should safely handle execeptions 1`] = `
-
-
- - - -

- -

-
-
- - - - - Add data - - - - -
-
-
+ + } + />
- 0 @@ -1051,92 +530,36 @@ exports[`home isNewKibanaInstance should safely handle execeptions 1`] = ` aria-hidden="true" margin="xl" /> -
- - - - - - - - -
+
`; exports[`home isNewKibanaInstance should set isNewKibanaInstance to false when there are index patterns 1`] = `
-
-
- - - -

- -

-
-
- - - - - Add data - - - - -
-
-
+ + } + />
- 0 @@ -1157,92 +580,36 @@ exports[`home isNewKibanaInstance should set isNewKibanaInstance to false when t aria-hidden="true" margin="xl" /> -
- - - - - - - - -
+
`; exports[`home isNewKibanaInstance should set isNewKibanaInstance to true when there are no index patterns 1`] = `
-
-
- - - -

- -

-
-
- - - - - Add data - - - - -
-
-
+ + } + />
- 0 @@ -1263,92 +630,36 @@ exports[`home isNewKibanaInstance should set isNewKibanaInstance to true when th aria-hidden="true" margin="xl" /> -
- - - - - - - - -
+
`; exports[`home should render home component 1`] = `
-
-
- - - -

- -

-
-
- - - - - Add data - - - - -
-
-
+ + } + />
- 0 @@ -1369,92 +680,36 @@ exports[`home should render home component 1`] = ` aria-hidden="true" margin="xl" /> -
- - - - - - - - -
+
`; exports[`home welcome should show the normal home page if loading fails 1`] = `
-
-
- - - -

- -

-
-
- - - - - Add data - - - - -
-
-
+ + } + />
- 0 @@ -1475,92 +730,36 @@ exports[`home welcome should show the normal home page if loading fails 1`] = ` aria-hidden="true" margin="xl" /> -
- - - - - - - - -
+
`; exports[`home welcome should show the normal home page if welcome screen is disabled locally 1`] = `
-
-
- - - -

- -

-
-
- - - - - Add data - - - - -
-
-
+ + } + />
- 0 @@ -1581,35 +780,10 @@ exports[`home welcome should show the normal home page if welcome screen is disa aria-hidden="true" margin="xl" /> -
- - - - - - - - -
+
`; @@ -1623,57 +797,26 @@ exports[`home welcome should show the welcome screen if enabled, and there are n exports[`home welcome stores skip welcome setting if skipped 1`] = `
-
-
- - - -

- -

-
-
- - - - - Add data - - - - -
-
-
+ + } + />
- 0 @@ -1694,35 +837,10 @@ exports[`home welcome stores skip welcome setting if skipped 1`] = ` aria-hidden="true" margin="xl" /> -
- - - - - - - - -
+
`; diff --git a/src/plugins/home/public/application/components/__snapshots__/synopsis.test.js.snap b/src/plugins/home/public/application/components/__snapshots__/synopsis.test.js.snap index 190985f70659d..ec192ce1eb32f 100644 --- a/src/plugins/home/public/application/components/__snapshots__/synopsis.test.js.snap +++ b/src/plugins/home/public/application/components/__snapshots__/synopsis.test.js.snap @@ -9,6 +9,7 @@ exports[`props iconType 1`] = ` href="link_to_item" icon={ - - - +
+ + + +
= ({ addBasePath, features }) => (
- +

@@ -43,18 +43,21 @@ export const AddData: FC = ({ addBasePath, features }) => ( - - - - + +
+ + + +
diff --git a/src/plugins/home/public/application/components/home.js b/src/plugins/home/public/application/components/home.js index becafb2560217..054f5a5344df4 100644 --- a/src/plugins/home/public/application/components/home.js +++ b/src/plugins/home/public/application/components/home.js @@ -20,18 +20,16 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { FormattedMessage } from '@kbn/i18n/react'; -import { - EuiButtonEmpty, - EuiTitle, - EuiFlexGroup, - EuiFlexItem, - EuiHorizontalRule, -} from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { + OverviewPageFooter, + OverviewPageHeader, +} from '../../../../../../src/plugins/kibana_react/public'; +import { HOME_APP_BASE_PATH } from '../../../common/constants'; import { FeatureCatalogueCategory } from '../../services'; import { getServices } from '../kibana_services'; import { AddData } from './add_data'; -import { createAppNavigationHandler } from './app_navigation_handler'; import { ManageData } from './manage_data'; import { SolutionsSection } from './solutions_section'; import { Welcome } from './welcome'; @@ -121,12 +119,9 @@ export class Home extends Component { .sort((directoryA, directoryB) => directoryA.order - directoryB.order); renderNormal() { - const { addBasePath, solutions } = this.props; + const { addBasePath, solutions, directories } = this.props; const devTools = this.findDirectoryById('console'); - const stackManagement = this.findDirectoryById('stack-management'); - const advancedSettings = this.findDirectoryById('advanced_settings'); - const addDataFeatures = this.getFeaturesByCategory(FeatureCatalogueCategory.DATA); const manageDataFeatures = this.getFeaturesByCategory(FeatureCatalogueCategory.ADMIN); @@ -136,68 +131,27 @@ export class Home extends Component { } return ( -
-
-
- - - -

- -

-
-
- - - - - - {i18n.translate('home.pageHeader.addDataButtonLabel', { - defaultMessage: 'Add data', - })} - - - - {stackManagement ? ( - - - {i18n.translate('home.pageHeader.stackManagementButtonLabel', { - defaultMessage: 'Manage', - })} - - - ) : null} - - {devTools ? ( - - - {i18n.translate('home.pageHeader.devToolsButtonLabel', { - defaultMessage: 'Dev tools', - })} - - - ) : null} - - -
-
-
+
+ } + />
- {solutions.length && } + {solutions.length ? ( + + ) : null}
); @@ -294,12 +214,14 @@ Home.propTypes = { PropTypes.shape({ id: PropTypes.string.isRequired, title: PropTypes.string.isRequired, + subtitle: PropTypes.string, description: PropTypes.string.isRequired, icon: PropTypes.string.isRequired, path: PropTypes.string.isRequired, showOnHomePage: PropTypes.bool.isRequired, category: PropTypes.string.isRequired, order: PropTypes.number, + solutionId: PropTypes.string, }) ), solutions: PropTypes.arrayOf( @@ -307,7 +229,8 @@ Home.propTypes = { id: PropTypes.string.isRequired, title: PropTypes.string.isRequired, subtitle: PropTypes.string.isRequired, - descriptions: PropTypes.arrayOf(PropTypes.string).isRequired, + description: PropTypes.string, + appDescriptions: PropTypes.arrayOf(PropTypes.string).isRequired, icon: PropTypes.string.isRequired, path: PropTypes.string.isRequired, order: PropTypes.number, diff --git a/src/plugins/home/public/application/components/home.test.js b/src/plugins/home/public/application/components/home.test.js index 0d7596d92a5a1..9c73bbf9b75ba 100644 --- a/src/plugins/home/public/application/components/home.test.js +++ b/src/plugins/home/public/application/components/home.test.js @@ -35,6 +35,11 @@ jest.mock('../kibana_services', () => ({ }), })); +jest.mock('../../../../../../src/plugins/kibana_react/public', () => ({ + OverviewPageFooter: jest.fn().mockReturnValue(<>), + OverviewPageHeader: jest.fn().mockReturnValue(<>), +})); + describe('home', () => { let defaultProps; @@ -142,7 +147,7 @@ describe('home', () => { id: 'kibana', title: 'Kibana', subtitle: 'Visualize & analyze', - descriptions: ['Analyze data in dashboards'], + appDescriptions: ['Analyze data in dashboards'], icon: 'logoKibana', path: 'kibana_landing_page', order: 1, @@ -151,7 +156,7 @@ describe('home', () => { id: 'solution-2', title: 'Solution two', subtitle: 'Subtitle for solution two', - descriptions: ['Example use case'], + appDescriptions: ['Example use case'], icon: 'empty', path: 'path-to-solution-two', order: 2, @@ -160,7 +165,7 @@ describe('home', () => { id: 'solution-3', title: 'Solution three', subtitle: 'Subtitle for solution three', - descriptions: ['Example use case'], + appDescriptions: ['Example use case'], icon: 'empty', path: 'path-to-solution-three', order: 3, @@ -169,7 +174,7 @@ describe('home', () => { id: 'solution-4', title: 'Solution four', subtitle: 'Subtitle for solution four', - descriptions: ['Example use case'], + appDescriptions: ['Example use case'], icon: 'empty', path: 'path-to-solution-four', order: 4, diff --git a/src/plugins/home/public/application/components/home_app.js b/src/plugins/home/public/application/components/home_app.js index 69cd68d553d03..7fe4f4351c35b 100644 --- a/src/plugins/home/public/application/components/home_app.js +++ b/src/plugins/home/public/application/components/home_app.js @@ -104,12 +104,14 @@ HomeApp.propTypes = { PropTypes.shape({ id: PropTypes.string.isRequired, title: PropTypes.string.isRequired, + subtitle: PropTypes.string, description: PropTypes.string.isRequired, icon: PropTypes.string.isRequired, path: PropTypes.string.isRequired, showOnHomePage: PropTypes.bool.isRequired, category: PropTypes.string.isRequired, order: PropTypes.number, + solutionId: PropTypes.string, }) ), solutions: PropTypes.arrayOf( @@ -117,7 +119,8 @@ HomeApp.propTypes = { id: PropTypes.string.isRequired, title: PropTypes.string.isRequired, subtitle: PropTypes.string.isRequired, - descriptions: PropTypes.arrayOf(PropTypes.string).isRequired, + description: PropTypes.string, + appDescriptions: PropTypes.arrayOf(PropTypes.string).isRequired, icon: PropTypes.string.isRequired, path: PropTypes.string.isRequired, order: PropTypes.number, diff --git a/src/plugins/home/public/application/components/manage_data/manage_data.test.tsx b/src/plugins/home/public/application/components/manage_data/manage_data.test.tsx index 0e86bf7dd3d84..18a58e86eaa3f 100644 --- a/src/plugins/home/public/application/components/manage_data/manage_data.test.tsx +++ b/src/plugins/home/public/application/components/manage_data/manage_data.test.tsx @@ -37,7 +37,6 @@ const mockFeatures = [ { category: 'admin', description: 'Control who has access and what tasks they can perform.', - homePageSection: 'manage_data', icon: 'securityApp', id: 'security', order: 600, @@ -48,7 +47,6 @@ const mockFeatures = [ { category: 'admin', description: 'Track the real-time health and performance of your deployment.', - homePageSection: 'manage_data', icon: 'monitoringApp', id: 'monitoring', order: 610, @@ -60,7 +58,6 @@ const mockFeatures = [ category: 'admin', description: 'Save snapshots to a backup repository, and restore to recover index and cluster state.', - homePageSection: 'manage_data', icon: 'storage', id: 'snapshot_restore', order: 630, @@ -71,7 +68,6 @@ const mockFeatures = [ { category: 'admin', description: 'Define lifecycle policies to automatically perform operations as an index ages.', - homePageSection: 'manage_data', icon: 'indexSettings', id: 'index_lifecycle_management', order: 640, diff --git a/src/plugins/home/public/application/components/solutions_section/__snapshots__/solution_panel.test.tsx.snap b/src/plugins/home/public/application/components/solutions_section/__snapshots__/solution_panel.test.tsx.snap index ad92aac67d51b..726d3dda4e9cc 100644 --- a/src/plugins/home/public/application/components/solutions_section/__snapshots__/solution_panel.test.tsx.snap +++ b/src/plugins/home/public/application/components/solutions_section/__snapshots__/solution_panel.test.tsx.snap @@ -13,6 +13,7 @@ exports[`SolutionPanel renders the solution panel for the given solution 1`] = ` onClick={[Function]} >

diff --git a/src/plugins/home/public/application/components/solutions_section/__snapshots__/solutions_section.test.tsx.snap b/src/plugins/home/public/application/components/solutions_section/__snapshots__/solutions_section.test.tsx.snap index 7015ebb40a71d..4052ffca9e56f 100644 --- a/src/plugins/home/public/application/components/solutions_section/__snapshots__/solutions_section.test.tsx.snap +++ b/src/plugins/home/public/application/components/solutions_section/__snapshots__/solutions_section.test.tsx.snap @@ -7,19 +7,15 @@ exports[`SolutionsSection only renders a spacer if no solutions are available 1` className="homSolutions" > - -

- -

-
+ +

- -

- -

-
+ +

- -

- -

-
+ +
- -

- -

-
+ +
- descriptions.map(getDescriptionText).reduce(addSpacersBetweenElementsReducer, []); +const getDescriptions = (appDescriptions: string[]) => + appDescriptions + .map(getDescriptionText) + .reduce(addSpacersBetweenElementsReducer, []); interface Props { addBasePath: (path: string) => string; solution: FeatureCatalogueSolution; + apps?: FeatureCatalogueEntry[]; } -export const SolutionPanel: FC = ({ addBasePath, solution }) => ( +export const SolutionPanel: FC = ({ addBasePath, solution, apps = [] }) => ( = ({ addBasePath, solution }) => ( href={addBasePath(solution.path)} onClick={createAppNavigationHandler(solution.path)} > - + = ({ addBasePath, solution }) => ( - {getDescriptions(solution.descriptions)} + {getDescriptions( + apps.length ? apps.map(({ subtitle = '' }) => subtitle) : solution.appDescriptions + )} diff --git a/src/plugins/home/public/application/components/solutions_section/solution_title.tsx b/src/plugins/home/public/application/components/solutions_section/solution_title.tsx index fb833a40807d2..a9874ff7ddbe7 100644 --- a/src/plugins/home/public/application/components/solutions_section/solution_title.tsx +++ b/src/plugins/home/public/application/components/solutions_section/solution_title.tsx @@ -45,7 +45,7 @@ export const SolutionTitle: FC = ({ title, subtitle, iconType }) => ( className="homSolutionPanel__icon" /> - +

{title}

diff --git a/src/plugins/home/public/application/components/solutions_section/solutions_section.test.tsx b/src/plugins/home/public/application/components/solutions_section/solutions_section.test.tsx index 17d721cc96c02..9ec5bf695b35c 100644 --- a/src/plugins/home/public/application/components/solutions_section/solutions_section.test.tsx +++ b/src/plugins/home/public/application/components/solutions_section/solutions_section.test.tsx @@ -20,12 +20,13 @@ import React from 'react'; import { shallow } from 'enzyme'; import { SolutionsSection } from './solutions_section'; +import { FeatureCatalogueCategory } from '../../../services'; const solutionEntry1 = { id: 'kibana', title: 'Kibana', subtitle: 'Visualize & analyze', - descriptions: ['Analyze data in dashboards'], + appDescriptions: ['Analyze data in dashboards'], icon: 'logoKibana', path: 'kibana_landing_page', order: 1, @@ -34,7 +35,8 @@ const solutionEntry2 = { id: 'solution-2', title: 'Solution two', subtitle: 'Subtitle for solution two', - descriptions: ['Example use case'], + description: 'Description for solution two', + appDescriptions: ['Example use case'], icon: 'empty', path: 'path-to-solution-two', order: 2, @@ -43,7 +45,8 @@ const solutionEntry3 = { id: 'solution-3', title: 'Solution three', subtitle: 'Subtitle for solution three', - descriptions: ['Example use case'], + description: 'Description for solution three', + appDescriptions: ['Example use case'], icon: 'empty', path: 'path-to-solution-three', order: 3, @@ -52,23 +55,64 @@ const solutionEntry4 = { id: 'solution-4', title: 'Solution four', subtitle: 'Subtitle for solution four', - descriptions: ['Example use case'], + description: 'Description for solution four', + appDescriptions: ['Example use case'], icon: 'empty', path: 'path-to-solution-four', order: 4, }; +const mockDirectories = [ + { + id: 'dashboard', + title: 'Dashboard', + description: 'Description of dashboard', + icon: 'dashboardApp', + path: 'dashboard_landing_page', + showOnHomePage: false, + category: FeatureCatalogueCategory.DATA, + }, + { + id: 'discover', + title: 'Discover', + description: 'Description of discover', + icon: 'discoverApp', + path: 'discover_landing_page', + showOnHomePage: false, + category: FeatureCatalogueCategory.DATA, + }, + { + id: 'canvas', + title: 'Canvas', + description: 'Description of canvas', + icon: 'canvasApp', + path: 'canvas_landing_page', + showOnHomePage: false, + category: FeatureCatalogueCategory.DATA, + }, +]; + const addBasePathMock = (path: string) => (path ? path : 'path'); describe('SolutionsSection', () => { test('only renders a spacer if no solutions are available', () => { - const component = shallow(); + const component = shallow( + + ); expect(component).toMatchSnapshot(); }); test('renders a single solution', () => { const component = shallow( - + ); expect(component).toMatchSnapshot(); }); @@ -78,6 +122,7 @@ describe('SolutionsSection', () => { ); expect(component).toMatchSnapshot(); @@ -87,6 +132,7 @@ describe('SolutionsSection', () => { ); expect(component).toMatchSnapshot(); diff --git a/src/plugins/home/public/application/components/solutions_section/solutions_section.tsx b/src/plugins/home/public/application/components/solutions_section/solutions_section.tsx index 1a78a6c71030a..13b70383147eb 100644 --- a/src/plugins/home/public/application/components/solutions_section/solutions_section.tsx +++ b/src/plugins/home/public/application/components/solutions_section/solutions_section.tsx @@ -19,16 +19,10 @@ import React, { FC } from 'react'; import PropTypes from 'prop-types'; -import { - EuiFlexGroup, - EuiFlexItem, - EuiHorizontalRule, - EuiScreenReaderOnly, - EuiTitle, -} from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule, EuiScreenReaderOnly } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { SolutionPanel } from './solution_panel'; -import { FeatureCatalogueSolution } from '../../../'; +import { FeatureCatalogueEntry, FeatureCatalogueSolution } from '../../../'; const sortByOrder = ( { order: orderA = 0 }: FeatureCatalogueSolution, @@ -38,25 +32,25 @@ const sortByOrder = ( interface Props { addBasePath: (path: string) => string; solutions: FeatureCatalogueSolution[]; + directories: FeatureCatalogueEntry[]; } -export const SolutionsSection: FC = ({ addBasePath, solutions }) => { +export const SolutionsSection: FC = ({ addBasePath, solutions, directories }) => { // Separate Kibana from other solutions const kibana = solutions.find(({ id }) => id === 'kibana'); + const kibanaApps = directories.filter(({ solutionId }) => solutionId === 'kibana'); solutions = solutions.sort(sortByOrder).filter(({ id }) => id !== 'kibana'); return ( <>
- -

- -

-
+

+ +

@@ -69,7 +63,13 @@ export const SolutionsSection: FC = ({ addBasePath, solutions }) => { ) : null} - {kibana ? : null} + {kibana ? ( + + ) : null}
@@ -79,12 +79,28 @@ export const SolutionsSection: FC = ({ addBasePath, solutions }) => { }; SolutionsSection.propTypes = { + addBasePath: PropTypes.func.isRequired, + directories: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.string.isRequired, + title: PropTypes.string.isRequired, + subtitle: PropTypes.string, + description: PropTypes.string.isRequired, + icon: PropTypes.string.isRequired, + path: PropTypes.string.isRequired, + showOnHomePage: PropTypes.bool.isRequired, + category: PropTypes.string.isRequired, + order: PropTypes.number, + solutionId: PropTypes.string, + }) + ), solutions: PropTypes.arrayOf( PropTypes.shape({ id: PropTypes.string.isRequired, title: PropTypes.string.isRequired, subtitle: PropTypes.string.isRequired, - descriptions: PropTypes.arrayOf(PropTypes.string).isRequired, + description: PropTypes.string, + appDescriptions: PropTypes.arrayOf(PropTypes.string).isRequired, icon: PropTypes.string.isRequired, path: PropTypes.string.isRequired, order: PropTypes.number, diff --git a/src/plugins/home/public/application/components/synopsis.js b/src/plugins/home/public/application/components/synopsis.js index fbe3bb3ed6769..0777c0db7210e 100644 --- a/src/plugins/home/public/application/components/synopsis.js +++ b/src/plugins/home/public/application/components/synopsis.js @@ -38,7 +38,7 @@ export function Synopsis({ if (iconUrl) { optionalImg = ; } else if (iconType) { - optionalImg = ; + optionalImg = ; } const classes = classNames('homSynopsis__card', { diff --git a/src/plugins/home/public/index.ts b/src/plugins/home/public/index.ts index 4459d187eead7..e4ca6fb1439e8 100644 --- a/src/plugins/home/public/index.ts +++ b/src/plugins/home/public/index.ts @@ -24,6 +24,7 @@ export { EnvironmentSetup, TutorialSetup, HomePublicPluginSetup, + HomePublicPluginStart, } from './plugin'; export { FeatureCatalogueEntry, diff --git a/src/plugins/home/public/plugin.test.ts b/src/plugins/home/public/plugin.test.ts index 7b56c6ec89b77..f8ff7c95aae08 100644 --- a/src/plugins/home/public/plugin.test.ts +++ b/src/plugins/home/public/plugin.test.ts @@ -52,23 +52,6 @@ describe('HomePublicPlugin', () => { ); }); - test('registers kibana solution to feature catalogue', async () => { - const setup = await new HomePublicPlugin(mockInitializerContext).setup( - coreMock.createSetup() as any, - { - urlForwarding: urlForwardingPluginMock.createSetupContract(), - } - ); - expect(setup).toHaveProperty('featureCatalogue'); - expect(setup.featureCatalogue.registerSolution).toHaveBeenCalledTimes(1); - expect(setup.featureCatalogue.registerSolution).toHaveBeenCalledWith( - expect.objectContaining({ - icon: 'logoKibana', - id: 'kibana', - }) - ); - }); - test('wires up and returns registry', async () => { const setup = await new HomePublicPlugin(mockInitializerContext).setup( coreMock.createSetup() as any, diff --git a/src/plugins/home/public/plugin.ts b/src/plugins/home/public/plugin.ts index b62ceae3d0d37..90f2f939101cb 100644 --- a/src/plugins/home/public/plugin.ts +++ b/src/plugins/home/public/plugin.ts @@ -58,7 +58,12 @@ export interface HomePluginSetupDependencies { export class HomePublicPlugin implements - Plugin { + Plugin< + HomePublicPluginSetup, + HomePublicPluginStart, + HomePluginSetupDependencies, + HomePluginStartDependencies + > { private readonly featuresCatalogueRegistry = new FeatureCatalogueRegistry(); private readonly environmentService = new EnvironmentService(); private readonly tutorialService = new TutorialService(); @@ -128,39 +133,6 @@ export class HomePublicPlugin order: 500, }); - featureCatalogue.registerSolution({ - id: 'kibana', - title: i18n.translate('home.kibana.featureCatalogue.title', { - defaultMessage: 'Kibana', - }), - subtitle: i18n.translate('home.kibana.featureCatalogue.subtitle', { - defaultMessage: 'Visualize & analyze', - }), - descriptions: [ - i18n.translate('home.kibana.featureCatalogueDescription1', { - defaultMessage: 'Analyze data in dashboards.', - }), - i18n.translate('home.kibana.featureCatalogueDescription2', { - defaultMessage: 'Search and find insights.', - }), - i18n.translate('home.kibana.featureCatalogueDescription3', { - defaultMessage: 'Design pixel-perfect reports.', - }), - i18n.translate('home.kibana.featureCatalogueDescription4', { - defaultMessage: 'Plot geographic data.', - }), - i18n.translate('home.kibana.featureCatalogueDescription5', { - defaultMessage: 'Model, predict, and detect.', - }), - i18n.translate('home.kibana.featureCatalogueDescription6', { - defaultMessage: 'Reveal patterns and relationships.', - }), - ], - icon: 'logoKibana', - path: '/app/dashboards', - order: 400, - }); - return { featureCatalogue, environment: { ...this.environmentService.setup() }, @@ -188,6 +160,8 @@ export class HomePublicPlugin } }); } + + return { featureCatalogue: this.featuresCatalogueRegistry }; } } @@ -212,3 +186,6 @@ export interface HomePublicPluginSetup { environment: EnvironmentSetup; } +export interface HomePublicPluginStart { + featureCatalogue: FeatureCatalogueRegistry; +} diff --git a/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.mock.ts b/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.mock.ts index 23f36cef89ee6..e1a415ba2d571 100644 --- a/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.mock.ts +++ b/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.mock.ts @@ -36,6 +36,7 @@ const createMock = (): jest.Mocked> => start: jest.fn(), get: jest.fn(() => []), getSolutions: jest.fn(() => []), + removeFeature: jest.fn(), }; service.setup.mockImplementation(createSetupMock); return service; diff --git a/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.test.ts b/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.test.ts index b9902e0b10fb1..b009041bbf15b 100644 --- a/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.test.ts +++ b/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.test.ts @@ -38,7 +38,7 @@ const KIBANA_SOLUTION: FeatureCatalogueSolution = { id: 'kibana', title: 'Kibana', subtitle: 'Visualize & analyze', - descriptions: ['Analyze data in dashboards.', 'Search and find insights.'], + appDescriptions: ['Analyze data in dashboards.', 'Search and find insights.'], icon: 'kibanaApp', path: `/app/home`, }; diff --git a/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.ts b/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.ts index d965042b65cef..845070da0db9f 100644 --- a/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.ts +++ b/src/plugins/home/public/services/feature_catalogue/feature_catalogue_registry.ts @@ -35,6 +35,8 @@ export interface FeatureCatalogueEntry { readonly title: string; /** {@link FeatureCatalogueCategory} to display this feature in. */ readonly category: FeatureCatalogueCategory; + /** A tagline of feature displayed to the user. */ + readonly subtitle?: string; /** One-line description of feature displayed to the user. */ readonly description: string; /** EUI `IconType` for icon to be displayed to the user. EUI supports any known EUI icon, SVG URL, or ReactElement. */ @@ -47,6 +49,8 @@ export interface FeatureCatalogueEntry { readonly order?: number; /** Optional function to control visibility of this feature. */ readonly visible?: () => boolean; + /** Unique string identifier of the solution this feature belongs to */ + readonly solutionId?: string; } /** @public */ @@ -57,8 +61,10 @@ export interface FeatureCatalogueSolution { readonly title: string; /** The tagline of the solution displayed to the user. */ readonly subtitle: string; + /** One-line description of the solution displayed to the user. */ + readonly description?: string; /** A list of use cases for this solution displayed to the user. */ - readonly descriptions: string[]; + readonly appDescriptions: string[]; /** EUI `IconType` for icon to be displayed to the user. EUI supports any known EUI icon, SVG URL, or ReactElement. */ readonly icon: IconType; /** URL path to link to this future. Should not include the basePath. */ @@ -99,7 +105,7 @@ export class FeatureCatalogueRegistry { this.capabilities = capabilities; } - public get(): readonly FeatureCatalogueEntry[] { + public get(): FeatureCatalogueEntry[] { if (this.capabilities === null) { throw new Error('Catalogue entries are only available after start phase'); } @@ -112,7 +118,7 @@ export class FeatureCatalogueRegistry { .sort(compareByKey('title')); } - public getSolutions(): readonly FeatureCatalogueSolution[] { + public getSolutions(): FeatureCatalogueSolution[] { if (this.capabilities === null) { throw new Error('Catalogue entries are only available after start phase'); } @@ -121,6 +127,10 @@ export class FeatureCatalogueRegistry { .filter((solution) => capabilities.catalogue[solution.id] !== false) .sort(compareByKey('title')); } + + public removeFeature(appId: string) { + this.features.delete(appId); + } } export type FeatureCatalogueRegistrySetup = ReturnType; diff --git a/src/plugins/kibana_overview/README.md b/src/plugins/kibana_overview/README.md new file mode 100644 index 0000000000000..ad0cbfdf7013b --- /dev/null +++ b/src/plugins/kibana_overview/README.md @@ -0,0 +1,9 @@ +# kibana-overview + +> An overview page highlighting Kibana apps + +--- + +## Development + +See the [kibana contributing guide](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md) for instructions setting up your development environment. diff --git a/src/plugins/kibana_overview/common/index.ts b/src/plugins/kibana_overview/common/index.ts new file mode 100644 index 0000000000000..3bdfbee1081ad --- /dev/null +++ b/src/plugins/kibana_overview/common/index.ts @@ -0,0 +1,23 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export const PLUGIN_ID = 'kibanaOverview'; +export const PLUGIN_NAME = 'Overview'; +export const PLUGIN_PATH = `/app/kibana_overview`; +export const PLUGIN_ICON = 'logoKibana'; diff --git a/src/plugins/kibana_overview/kibana.json b/src/plugins/kibana_overview/kibana.json new file mode 100644 index 0000000000000..9ddcaabdaed6b --- /dev/null +++ b/src/plugins/kibana_overview/kibana.json @@ -0,0 +1,9 @@ +{ + "id": "kibanaOverview", + "version": "kibana", + "server": false, + "ui": true, + "requiredPlugins": ["navigation", "data", "home"], + "optionalPlugins": ["newsfeed"], + "requiredBundles": ["kibanaReact", "newsfeed"] +} diff --git a/src/plugins/kibana_overview/public/application.tsx b/src/plugins/kibana_overview/public/application.tsx new file mode 100644 index 0000000000000..1bf3fe07c36a8 --- /dev/null +++ b/src/plugins/kibana_overview/public/application.tsx @@ -0,0 +1,62 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import ReactDOM from 'react-dom'; +import { I18nProvider } from '@kbn/i18n/react'; +import { KibanaContextProvider } from '../../../../src/plugins/kibana_react/public'; +import { NewsfeedApiEndpoint } from '../../../../src/plugins/newsfeed/public'; +import { AppMountParameters, CoreStart } from '../../../../src/core/public'; +import { AppPluginStartDependencies } from './types'; +import { KibanaOverviewApp } from './components/app'; + +export const renderApp = ( + core: CoreStart, + deps: AppPluginStartDependencies, + { appBasePath, element }: AppMountParameters +) => { + const { notifications, http } = core; + const { newsfeed, home, navigation } = deps; + const newsfeed$ = newsfeed?.createNewsFeed$(NewsfeedApiEndpoint.KIBANA_ANALYTICS); + const navLinks = core.chrome.navLinks.getAll(); + const solutions = home.featureCatalogue + .getSolutions() + .filter(({ id }) => id !== 'kibana') + .filter(({ id }) => navLinks.find(({ category, hidden }) => !hidden && category?.id === id)); + const features = home.featureCatalogue.get(); + + ReactDOM.render( + + + + + , + element + ); + + return () => ReactDOM.unmountComponentAtNode(element); +}; diff --git a/src/plugins/kibana_overview/public/assets/kibana_canvas_dark.svg b/src/plugins/kibana_overview/public/assets/kibana_canvas_dark.svg new file mode 100644 index 0000000000000..c86a3a89924c8 --- /dev/null +++ b/src/plugins/kibana_overview/public/assets/kibana_canvas_dark.svg @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/kibana_overview/public/assets/kibana_canvas_light.svg b/src/plugins/kibana_overview/public/assets/kibana_canvas_light.svg new file mode 100644 index 0000000000000..d51560cb915c9 --- /dev/null +++ b/src/plugins/kibana_overview/public/assets/kibana_canvas_light.svg @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/kibana_overview/public/assets/kibana_dashboard_dark.svg b/src/plugins/kibana_overview/public/assets/kibana_dashboard_dark.svg new file mode 100644 index 0000000000000..834dd98d60e4c --- /dev/null +++ b/src/plugins/kibana_overview/public/assets/kibana_dashboard_dark.svg @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/kibana_overview/public/assets/kibana_dashboard_light.svg b/src/plugins/kibana_overview/public/assets/kibana_dashboard_light.svg new file mode 100644 index 0000000000000..958d25362c439 --- /dev/null +++ b/src/plugins/kibana_overview/public/assets/kibana_dashboard_light.svg @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/kibana_overview/public/assets/kibana_discover_dark.svg b/src/plugins/kibana_overview/public/assets/kibana_discover_dark.svg new file mode 100644 index 0000000000000..cf3116ae7f36a --- /dev/null +++ b/src/plugins/kibana_overview/public/assets/kibana_discover_dark.svg @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/kibana_overview/public/assets/kibana_discover_light.svg b/src/plugins/kibana_overview/public/assets/kibana_discover_light.svg new file mode 100644 index 0000000000000..6e039d03bef89 --- /dev/null +++ b/src/plugins/kibana_overview/public/assets/kibana_discover_light.svg @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/kibana_overview/public/assets/kibana_graph_dark.svg b/src/plugins/kibana_overview/public/assets/kibana_graph_dark.svg new file mode 100644 index 0000000000000..ea43adf3390d0 --- /dev/null +++ b/src/plugins/kibana_overview/public/assets/kibana_graph_dark.svg @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/kibana_overview/public/assets/kibana_graph_light.svg b/src/plugins/kibana_overview/public/assets/kibana_graph_light.svg new file mode 100644 index 0000000000000..c4505209a20bd --- /dev/null +++ b/src/plugins/kibana_overview/public/assets/kibana_graph_light.svg @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/kibana_overview/public/assets/kibana_maps_dark.svg b/src/plugins/kibana_overview/public/assets/kibana_maps_dark.svg new file mode 100644 index 0000000000000..a6c53012a5e90 --- /dev/null +++ b/src/plugins/kibana_overview/public/assets/kibana_maps_dark.svg @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/kibana_overview/public/assets/kibana_maps_light.svg b/src/plugins/kibana_overview/public/assets/kibana_maps_light.svg new file mode 100644 index 0000000000000..06a3ee5177eb9 --- /dev/null +++ b/src/plugins/kibana_overview/public/assets/kibana_maps_light.svg @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/kibana_overview/public/assets/kibana_ml_dark.svg b/src/plugins/kibana_overview/public/assets/kibana_ml_dark.svg new file mode 100644 index 0000000000000..574760e523f51 --- /dev/null +++ b/src/plugins/kibana_overview/public/assets/kibana_ml_dark.svg @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/kibana_overview/public/assets/kibana_ml_light.svg b/src/plugins/kibana_overview/public/assets/kibana_ml_light.svg new file mode 100644 index 0000000000000..2375d78ce61f3 --- /dev/null +++ b/src/plugins/kibana_overview/public/assets/kibana_ml_light.svg @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/kibana_overview/public/assets/kibana_montage_dark.svg b/src/plugins/kibana_overview/public/assets/kibana_montage_dark.svg new file mode 100644 index 0000000000000..7a476e4b19ae1 --- /dev/null +++ b/src/plugins/kibana_overview/public/assets/kibana_montage_dark.svg @@ -0,0 +1,178 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/kibana_overview/public/assets/kibana_montage_light.svg b/src/plugins/kibana_overview/public/assets/kibana_montage_light.svg new file mode 100644 index 0000000000000..83f48a0d31a0c --- /dev/null +++ b/src/plugins/kibana_overview/public/assets/kibana_montage_light.svg @@ -0,0 +1,218 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/kibana_overview/public/assets/solutions_enterprise_search_dark_2x.png b/src/plugins/kibana_overview/public/assets/solutions_enterprise_search_dark_2x.png new file mode 100644 index 0000000000000000000000000000000000000000..86ac827f06a77ccd3f7949c22620882aee6494c0 GIT binary patch literal 2566 zcmeHJdr;GN65sGr9+pZ<5~x*&Ll_Ww9S=cKd_@>A7AU8@Bto$Q0U-#=BM|gzu>`@# z1py%~v53V>Ktl=P6)T~KR0T6B0)`;rA;tiPBpL!qf6mR^U-#eXfA`0CzOy^KpV^(= z{p?=+l5lXHnXMTBtP2j>9}ZxE13F#2ZCp*;XC<>o8LjS+{M;Qf2PI*XEvWn^@}&2KL@CcC_dNIGLG5Y5B$ohKCNmTdWE~yy)LcqLb%T?$#{1=HC&2!&GfaAxnMv4!Y}~48fTv9=jXc2FqUpr>$4rG4>00ZP43A%3v^@H z9(sN!CVZcCS^OP2KQoG_;sJb@G&oC;ofwo!c3)FDym#<;cOR2oow+o>>fpmNhYVcZ z^wgc@-hR0tGAcIC8i@J;+0c#Bfz-<=STiy5L|5l4l$*n|_#K-#t))v#OXOd2)BYLK zE+^@Xs1zj$O>>(}Nc5??#_XF;hUW6RX|ztp<@z#02W}>tL36x`CGC{pK%{W;EZWA( z5Y!?03dQgv$JNT(uqUj>aykoB8qUsQ`!>!`>IH(Xeh0T#_EPC+p#?m{%5PGLj9Fzw z24`tRyJ^*@?UT>(beY?6#i@ z-Ms3ouy2of3CSY4j}r;fYjQOR*e~!>DHWR6?mEgO|+RYsj{i) zj-dTvWC-}wW{>;zvbT-Nadww+;7&Mi+;>-2ME{oZZvh{-IZ8#d$VGwF>m}h~_b~f# zn$n0GW~)RO#O3W`rTiTQOs_>FrZS<%5olMv*TUxcTc22{3_+@lD7w(W`2za-D*#G9 z_i`r<8Brg2k%&qc8f!L@1^jZ4lf=;c$L@dB@`37M>*c;YUgGQq#2Y5&wB^354U#eT z789U7B^G<6E%&r;u>#z!`v!@-=KQ)|lHM3mTWsy!FZl>dyWf^PuQ~?&lk2Q-lv`L) zZPrc{kuzEBVHxW7>UBcWIV4Eyb+qLZ_xd@??BVyO*98X5?xB9pHq#JfikWm%+9NW) ztkfYx8$`+LRjdVC%mV-A-onDW$POSkmhCQH|X>f66_q@xK{L8%ysH=-pd~QeAwl?gMvD<=uIb{|I(z8wF zW;E?Zfnr8obNo$voSn2mtJ5Oo8bpTtX=u-=ti8(q4!!AacgI-wt0y}}5q3=1GVU`A zP#?@+((SW(m}tkmAV^3{HUf1&vF-MF)8))JlEHV;Z5K;rs-L;O)}S7kC=R1+^-Ld# zjs^b4JUYLz`x0#|J&sPt1JNzX)iU>{Ho)fIJ>lJ>`6&pF=$;9_RXphA3Pg6mm{qX% zjsS6}8vz+UNnO&pA+JMKwTw!p6ln&v1cA1E!_jKcUi zJ(`L-k^t0AqzZnc@OzCWs_OA2GsrkwU)&;2&CKD|#v+We)e4uLka>Egp5rz{-v?B& zA(OCmRMW|+X>R_^01D=Vi^CkPy&Y1HhK}A&HipF?a`KeJ${)wmqaD$rul>ax8|J%1RI|3AvdTA{7RP{J!%`o;c6S7Bt|LxkKu#>O7T!1ln( zQ{!}oxS~foB0G{4mG$7e5I?RNorUEc&)=YSoTes;O2hmabS6EtTq9+C-y@qM@PbS|wr6`|2tp zYuQvOTBQvtyi-3aNN0i)sa2c)5I<&KA}mZK^{d{m{nx)||Ls1{eeON?p7XiqIrluD zbFLin{c^48dQ$*cOWyBE1wi8fP|hY8W(ICDx_oSddMxaPY$_pp#a4k7$0B;_*p@)6ggXIKhoi0)>b2^qbU1Ij_nJr?`xBGPDj9C>A6e) z@K%}~+t)%cfC`G?z`cn@+0m&3ycW-Jv&dvZZnqTC0 z_09EeG~_9|R+6@`u;5ZKu)M5a$9`!DxIErLd=sBHH&N2(d)EkX`8-2uEsOPgr|j;} z>BMa|kXkYmtJk!)4%yoB9}mQ89=C@Mq8Nv6#C@f2JE~?D&z1_}M2Z~au%#ec-T|Fu z`a{*s=W;m$m0Gg+(!y(|nONA6#1O}1)Lw6z8Pn*0YV8W^$ucWO*!@7ca#jbxEz#bx?DF{$$tYOf+bZP88mkoj=aGl<*0*_HZr{ zRVcshaPfJ(lf^pxLNCGf5}G7v6_}o=IC?*uG9E4$Mq~jgwzavnwt+s!e9001n%O{x z!rI-|mgP0M&kv^ug%&x0_DF=erXIu?MX{ORY_*Qf9eMJc4A-H~}Ag+!wzYN%;ifQ^||(=_sg> z`!(|7++C4-k9na%Xu}Q^D%m5>b_CxFAg2A>iCwzFy=r`q`UIo%;Y%838=gwmO z?#4<_G%WR!8A$5fw|&r*@W34nNzcfP>YKp+lZO+=PD>~OKMvFT3~ z*LKkppb z;~$&W0Ir;e@n)N?x#SFtcIO(;xXJ?B24w%ldHbV#qkk|)a3TW@i=gBVE9&YRm2!&n z9w!uV@?s1^cN3kjh}qOFfDcp}df)t4-$b_ON-EO|&M-FUj&)^Zu7Sa*Fm#cxQ&a$f zKVlArUX0#vPwRX>l=V_gVCp-8k@wAj-s|@=)8>DOG=izr|COosC6%hSu9wa#dbZj7 zW)}kV-*U_IM}hgTTF1YhcUOnK|3+Em+DJPL$>puLJ-bGWMF&=`$iDkc2T{q<)qzt`diyQ;a{&ti}0@Z@AM)!&~QpNI`S&#ukKR9 exs#?q>i(_S&5>C~rl@8C8DuYC&x$V?U;iJgWu?ae literal 0 HcmV?d00001 diff --git a/src/plugins/kibana_overview/public/assets/solutions_observability_dark_2x.png b/src/plugins/kibana_overview/public/assets/solutions_observability_dark_2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c9dd85ee07f352f2dac633d6c094eb3627890747 GIT binary patch literal 1484 zcmeAS@N?(olHy`uVBq!ia0y~yV3J^9VASJa1B#sS&$b0poCO|{#S9E$svykh8Km+7 zD9BhGOy_gwATrb)e260R} zb}Dwaig}9i5(A-QYZM~xC~!VMaR2brzfXVvO_pY8IJXT*%s9ZnP{hQ{aDtPEK|$Ss zpOy_gvV94>a=3|S_) zr_udO*SuqHTLgJ_J!6ad;~I0XIdl2HGcxn!}PwR`UWcaMMOZhO*118ZpFcEW}NeV5Q4xBp%`_vxn=&!<0R zXJT%M-L+=^=FZo*O3iNVRgP1kQP}25GTd1B`*GzDYdu;!; gZRTTeNdLV6h6JZbQB6gE9{mbvI?y;QA!7l4X}VvK780s=BvlpzC>L2-Q-#r}<$;C3yUXNmh13 zL?|@>==um>NOeeT2taG4?H>oN0A5fzm!T_t4Pmj`uY_*HWstE!D1>hR1Jl!Tp!qoh&%T<$=4B2FN7Xa9Th? z@FfGlLy`jy5-Di>wJiAVKW)ibG~CVT5J1Zg$p&U*?vq~7oVzgX#n-W5RyGnqISH3@ zas(jl+Mlx6+114tLJM)VPUI-WRCq;GqUu*SH!;vLkjpN{5a6$Gze zv}G3g!jhhY1gzds(Hn8kTDqU~HaZo;z~@)k4V_^e7^s|KH|$XzNJ)-`;LX>qnXJM> zi45umW26EN4wN(#2p{ek;X>NJ9Bq6?$7?9+GW4E>aPG06v3o2w4H#OUR{kwm|bjRhUvT>D}?U`1;&6uR?K6v{;oQ-*zTXIU+&>3 z@=BSt0yztogl|Zr!;LxU|EkMQY4pt^6g25Y7GaZKY>9dLZI*cF?PR+8vtEB!djV8+ z+%{}Qvr2WlHvXd6jS?$V%KyHHxNIAEy%_BaPip=I5~)r>vQ}(>&;Ppw{Dc ztz#Jym{=l>UZWXD5d2tc$Tds%kHkoRADJ(V2?~(QYwSy=Na(DSP)Gdb^1?D6OstW{ z03=zVvucY|WNyv-rVzCB;7~$AXt?oa(bx9yPHJ?)Pxme$^YHnq z6n7a+49DE^%CBI`xv&yKlYxH4h}Bs$4%h*?HRFzxhg!FV6(O?0s8HE`XNnI9Qg#~EltNn}mGT z317XRSt4JR@2f;?%h|8k{klwVRp~lVzIZ&JMqi9poAL1<; zkZA{7%a|W#9zLq(LR%QktAFyn1H!lpMVPPkt}0{h(JzwE-mc6(q9QTcNnJJZH8<#4^{W1+og=n{|u~Vt)iXkdS(_JcwWYPT* zm5bc8J0dK43F%HaZPT@F#4sXhD#0*qX;POmEh5r)nNI)oU(;-gamSQG%^YsyB;K=Rw62%P=#nZ*FM9)^cVNOfO8BT<|h7YUj{ zr&)X<^CA)>0J`dV>p8{%CUptX5ou+_Z}&50j&a)#4_}P0Dvc6dx<=}Y|LEKP%P3J` zo{|vY_4SccbH8>^JPEP``I)6e0!(cv2tUIBOp$D`^rAr?q#)or zhYx}z2|y9c2#)@zkhv*EQHTotN<&LXNOK+U+n`{EsMx>H7f04O~ih$7k z0Qxz^_ws}3R##jsUtDEc&JIeQxG;3Ym(|=V95a}NO3mLMx_Di51Wbuxigz6o>)NF=3&LdZmecqHKsnujFzOi8G$CxPmzL^>8Xn` zj`a}1o)5ldZ~8^H&eUkV9w61$l^Pv6sf;2(MCt+$ zT-PEkU$JO`tZ3*9iP3cd6nfEzrb>d5Va1p={XSxuHt}lbyYp8*$s1X|P_eO|K|t0Z zSNDSYt#TzFCVwJzJVTVTVlmQRB%7Dih&LH@rV)3|(uvzxey*4C?mXK|C0xi7lU9l?_LOK#l zwJxA55kjn}9Naaji@~&pB#Ah_R{7}B8+Qu=jG-Y`A|A^BqFnqP_RFW1>7i8wW6e=| zx2U=%=D#o1K99r4nm#r+Cqv%j0$Q_MYOv(8{YC28C_XW3PVE0u%chzGUgHZfCZtJRMXy$LYH(=n1Mw=2jiDBQ_ajM^>E&V z)f|QTw>iorZ2W7Uba1+GdgD+=!0ALn-e9U6Y)`-3e}b~SW@?{rl@)jQ(p u+%(Tv{?B{-S#|%ty0WE(CLV+jt`^?j5L@RsOMk{cH6+9&MQb7@m45*)c4w{t literal 0 HcmV?d00001 diff --git a/src/plugins/kibana_overview/public/components/_index.scss b/src/plugins/kibana_overview/public/components/_index.scss new file mode 100644 index 0000000000000..b8857d171728f --- /dev/null +++ b/src/plugins/kibana_overview/public/components/_index.scss @@ -0,0 +1 @@ +@import 'overview'; diff --git a/src/plugins/kibana_overview/public/components/_overview.scss b/src/plugins/kibana_overview/public/components/_overview.scss new file mode 100644 index 0000000000000..74a58122d4851 --- /dev/null +++ b/src/plugins/kibana_overview/public/components/_overview.scss @@ -0,0 +1,120 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +.kbnOverviewWrapper { + background-color: $euiColorEmptyShade; + display: flex; + flex-direction: column; + min-height: calc(100vh - #{$euiHeaderHeightCompensation}); +} + +.kbnOverviewContent { + margin: 0 auto; + max-width: 1200px; + padding: $euiSizeXL $euiSize; + width: 100%; + + // Ensure card heights are stretched equally when wrapped with this element + .kbnRedirectCrossAppLinks { + align-items: flex-start; + display: flex; + flex: 1; + flex-direction: column; + } +} + +.kbnOverviewApps__item { + .kbnOverviewApps__group--primary & { + @include euiBreakpoint('m', 'l', 'xl') { + max-width: calc(50% - #{$euiSizeM * 2}); + } + } + + .kbnOverviewApps__group--secondary & { + @include euiBreakpoint('m', 'l', 'xl') { + max-width: calc(25% - #{$euiSizeM * 2}); + } + } +} + +.kbnOverviewNews__content article { + & + article { + margin-top: $euiSizeL; + } + + &, + header { + & > * + * { + margin-top: $euiSizeXS; + } + } + + h3 { + font-weight: inherit; + } +} + +.kbnOverviewMore__item { + @include euiBreakpoint('m', 'l', 'xl') { + max-width: calc(33.333333333333333% - #{$euiSizeM * 2}); + } +} + +.kbnOverviewSolution__icon { + background-color: $euiColorEmptyShade !important; + box-shadow: none !important; + height: $euiSizeL * 2; + padding: $euiSizeM; + width: $euiSizeL * 2; +} + +.kbnOverviewSupplements--noNews .kbnOverviewMore { + h2 { + @include euiBreakpoint('m', 'l', 'xl') { + text-align: center; + } + } + + .kbnOverviewMore__content { + @include euiBreakpoint('m', 'l', 'xl') { + justify-content: center; + } + } +} + +.kbnOverviewData--expanded { + flex-direction: column; + + &, + & > * { + margin-bottom: 0 !important; + margin-top: 0 !important; + } +} + +// Accounting for no `flush="both"` prop on EuiButtonEmpty +.kbnOverviewDataAdd__actionButton { + margin-right: 0; +} + +.kbnOverviewDataManage__item:not(:only-child) { + @include euiBreakpoint('m', 'l', 'xl') { + flex: 0 0 calc(50% - #{$euiSizeM * 2}); + } +} diff --git a/src/plugins/kibana_overview/public/components/add_data/__snapshots__/add_data.test.tsx.snap b/src/plugins/kibana_overview/public/components/add_data/__snapshots__/add_data.test.tsx.snap new file mode 100644 index 0000000000000..42623abd79ac0 --- /dev/null +++ b/src/plugins/kibana_overview/public/components/add_data/__snapshots__/add_data.test.tsx.snap @@ -0,0 +1,102 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`AddData render 1`] = ` +
+ + + +

+ +

+
+
+ +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + + +
+`; diff --git a/src/plugins/kibana_overview/public/components/add_data/add_data.test.tsx b/src/plugins/kibana_overview/public/components/add_data/add_data.test.tsx new file mode 100644 index 0000000000000..f5cdbd9e27e28 --- /dev/null +++ b/src/plugins/kibana_overview/public/components/add_data/add_data.test.tsx @@ -0,0 +1,67 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { AddData } from './add_data'; +import { shallowWithIntl } from 'test_utils/enzyme_helpers'; +import { FeatureCatalogueCategory } from 'src/plugins/home/public'; + +const mockFeatures = [ + { + category: FeatureCatalogueCategory.DATA, + description: 'Ingest data from popular apps and services.', + showOnHomePage: true, + icon: 'indexOpen', + id: 'home_tutorial_directory', + order: 500, + path: '/app/home#/tutorial_directory', + title: 'Ingest data', + }, + { + category: FeatureCatalogueCategory.ADMIN, + description: 'Add and manage your fleet of Elastic Agents and integrations.', + showOnHomePage: true, + icon: 'indexManagementApp', + id: 'ingestManager', + order: 510, + path: '/app/ingestManager', + title: 'Add Elastic Agent', + }, + { + category: FeatureCatalogueCategory.DATA, + description: 'Import your own CSV, NDJSON, or log file', + showOnHomePage: true, + icon: 'document', + id: 'ml_file_data_visualizer', + order: 520, + path: '/app/ml#/filedatavisualizer', + title: 'Upload a file', + }, +]; + +const addBasePathMock = jest.fn((path: string) => (path ? path : 'path')); + +describe('AddData', () => { + test('render', () => { + const component = shallowWithIntl( + + ); + expect(component).toMatchSnapshot(); + }); +}); diff --git a/src/plugins/kibana_overview/public/components/add_data/add_data.tsx b/src/plugins/kibana_overview/public/components/add_data/add_data.tsx new file mode 100644 index 0000000000000..e29c2a08395cf --- /dev/null +++ b/src/plugins/kibana_overview/public/components/add_data/add_data.tsx @@ -0,0 +1,108 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { FC } from 'react'; +import PropTypes from 'prop-types'; +import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiTitle } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { CoreStart } from 'kibana/public'; +import { RedirectAppLinks, useKibana } from '../../../../../../src/plugins/kibana_react/public'; +import { FeatureCatalogueEntry } from '../../../../../../src/plugins/home/public'; +// @ts-expect-error untyped component +import { Synopsis } from '../synopsis'; + +interface Props { + addBasePath: (path: string) => string; + features: FeatureCatalogueEntry[]; +} + +export const AddData: FC = ({ addBasePath, features }) => { + const { + services: { application }, + } = useKibana(); + + return ( +
+ + + +

+ +

+
+
+ + +
+ + + +
+
+
+ + + + + {features.map((feature) => ( + + + + + + ))} + +
+ ); +}; + +AddData.propTypes = { + addBasePath: PropTypes.func.isRequired, + features: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.string.isRequired, + title: PropTypes.string.isRequired, + description: PropTypes.string.isRequired, + icon: PropTypes.string.isRequired, + path: PropTypes.string.isRequired, + showOnHomePage: PropTypes.bool.isRequired, + category: PropTypes.string.isRequired, + order: PropTypes.number, + }) + ), +}; diff --git a/src/plugins/home/public/application/components/_manage_data.scss b/src/plugins/kibana_overview/public/components/add_data/index.ts similarity index 90% rename from src/plugins/home/public/application/components/_manage_data.scss rename to src/plugins/kibana_overview/public/components/add_data/index.ts index 389d8c8b3bf0f..a7d465d177636 100644 --- a/src/plugins/home/public/application/components/_manage_data.scss +++ b/src/plugins/kibana_overview/public/components/add_data/index.ts @@ -17,6 +17,4 @@ * under the License. */ -.homDataManage__content .euiIcon__fillSecondary { - fill: $euiColorDarkestShade; -} +export * from './add_data'; diff --git a/src/plugins/kibana_overview/public/components/app.tsx b/src/plugins/kibana_overview/public/components/app.tsx new file mode 100644 index 0000000000000..bf9211f49a18e --- /dev/null +++ b/src/plugins/kibana_overview/public/components/app.tsx @@ -0,0 +1,69 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { useEffect, useState } from 'react'; +import { Observable } from 'rxjs'; +import { I18nProvider } from '@kbn/i18n/react'; +import { HashRouter as Router, Switch, Route } from 'react-router-dom'; +import { CoreStart } from 'src/core/public'; +import { NavigationPublicPluginStart } from 'src/plugins/navigation/public'; +import { FetchResult } from 'src/plugins/newsfeed/public'; +import { FeatureCatalogueEntry, FeatureCatalogueSolution } from 'src/plugins/home/public'; +import { Overview } from './overview'; + +interface KibanaOverviewAppDeps { + basename: string; + notifications: CoreStart['notifications']; + http: CoreStart['http']; + navigation: NavigationPublicPluginStart; + newsfeed$?: Observable; + solutions: FeatureCatalogueSolution[]; + features: FeatureCatalogueEntry[]; +} + +export const KibanaOverviewApp = ({ + basename, + newsfeed$, + solutions, + features, +}: KibanaOverviewAppDeps) => { + const [newsFetchResult, setNewsFetchResult] = useState(null); + + useEffect(() => { + if (newsfeed$) { + const subscription = newsfeed$.subscribe((res: FetchResult | void | null) => { + setNewsFetchResult(res); + }); + + return () => subscription.unsubscribe(); + } + }, [newsfeed$]); + + return ( + + + + + + + + + + ); +}; diff --git a/src/plugins/kibana_overview/public/components/getting_started/__snapshots__/getting_started.test.tsx.snap b/src/plugins/kibana_overview/public/components/getting_started/__snapshots__/getting_started.test.tsx.snap new file mode 100644 index 0000000000000..374715a277ebc --- /dev/null +++ b/src/plugins/kibana_overview/public/components/getting_started/__snapshots__/getting_started.test.tsx.snap @@ -0,0 +1,391 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`GettingStarted dark mode on 1`] = ` +
+ + +
+ +

+ +

+
+ + +

+ +

+
+ + + + + } + layout="horizontal" + paddingSize="none" + title="Dashboard" + titleElement="h3" + titleSize="xs" + /> + + + + } + layout="horizontal" + paddingSize="none" + title="Discover" + titleElement="h3" + titleSize="xs" + /> + + + + } + layout="horizontal" + paddingSize="none" + title="Canvas" + titleElement="h3" + titleSize="xs" + /> + + + + } + layout="horizontal" + paddingSize="none" + title="Maps" + titleElement="h3" + titleSize="xs" + /> + + + + } + layout="horizontal" + paddingSize="none" + title="Machine Learning" + titleElement="h3" + titleSize="xs" + /> + + + + } + layout="horizontal" + paddingSize="none" + title="Graph" + titleElement="h3" + titleSize="xs" + /> + + + + + + + + +
+
+ + + +
+
+`; + +exports[`GettingStarted render 1`] = ` +
+ + +
+ +

+ +

+
+ + +

+ +

+
+ + + + + } + layout="horizontal" + paddingSize="none" + title="Dashboard" + titleElement="h3" + titleSize="xs" + /> + + + + } + layout="horizontal" + paddingSize="none" + title="Discover" + titleElement="h3" + titleSize="xs" + /> + + + + } + layout="horizontal" + paddingSize="none" + title="Canvas" + titleElement="h3" + titleSize="xs" + /> + + + + } + layout="horizontal" + paddingSize="none" + title="Maps" + titleElement="h3" + titleSize="xs" + /> + + + + } + layout="horizontal" + paddingSize="none" + title="Machine Learning" + titleElement="h3" + titleSize="xs" + /> + + + + } + layout="horizontal" + paddingSize="none" + title="Graph" + titleElement="h3" + titleSize="xs" + /> + + + + + + + + +
+
+ + + +
+
+`; diff --git a/src/plugins/kibana_overview/public/components/getting_started/getting_started.test.tsx b/src/plugins/kibana_overview/public/components/getting_started/getting_started.test.tsx new file mode 100644 index 0000000000000..7d40c4174f39b --- /dev/null +++ b/src/plugins/kibana_overview/public/components/getting_started/getting_started.test.tsx @@ -0,0 +1,118 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { GettingStarted } from './getting_started'; +import { shallowWithIntl } from 'test_utils/enzyme_helpers'; +import { FeatureCatalogueCategory } from 'src/plugins/home/public'; + +const addBasePathMock = jest.fn((path: string) => (path ? path : 'path')); + +const mockApps = [ + { + category: FeatureCatalogueCategory.DATA, + description: 'Display and share a collection of visualizations and saved searches.', + icon: 'dashboardApp', + id: 'dashboard', + order: 100, + path: 'path-to-dashboard', + showOnHomePage: false, + solutionId: 'kibana', + subtitle: 'Analyze data in dashboards.', + title: 'Dashboard', + }, + { + category: FeatureCatalogueCategory.DATA, + description: 'Interactively explore your data by querying and filtering raw documents.', + icon: 'discoverApp', + id: 'discover', + order: 200, + path: 'path-to-discover', + + showOnHomePage: false, + solutionId: 'kibana', + subtitle: 'Search and find insights.', + title: 'Discover', + }, + { + category: FeatureCatalogueCategory.DATA, + description: 'Showcase your data in a pixel-perfect way.', + icon: 'canvasApp', + id: 'canvas', + order: 300, + path: 'path-to-canvas', + + showOnHomePage: false, + solutionId: 'kibana', + subtitle: 'Design pixel-perfect reports.', + title: 'Canvas', + }, + { + category: FeatureCatalogueCategory.DATA, + description: 'Explore geospatial data from Elasticsearch and the Elastic Maps Service.', + icon: 'gisApp', + id: 'maps', + order: 400, + path: 'path-to-maps', + showOnHomePage: false, + solutionId: 'kibana', + subtitle: 'Plot geographic data.', + title: 'Maps', + }, + { + category: FeatureCatalogueCategory.DATA, + description: + 'Automatically model the normal behavior of your time series data to detect anomalies.', + icon: 'machineLearningApp', + id: 'ml', + order: 500, + path: 'path-to-ml', + showOnHomePage: false, + solutionId: 'kibana', + subtitle: 'Model, predict, and detect.', + title: 'Machine Learning', + }, + { + category: FeatureCatalogueCategory.DATA, + description: 'Surface and analyze relevant relationships in your Elasticsearch data.', + icon: 'graphApp', + id: 'graph', + order: 600, + path: 'path-to-graph', + showOnHomePage: false, + solutionId: 'kibana', + subtitle: 'Reveal patterns and relationships.', + title: 'Graph', + }, +]; + +describe('GettingStarted', () => { + test('render', () => { + const component = shallowWithIntl( + + ); + expect(component).toMatchSnapshot(); + }); + test('dark mode on', () => { + const component = shallowWithIntl( + + ); + expect(component).toMatchSnapshot(); + }); +}); diff --git a/src/plugins/kibana_overview/public/components/getting_started/getting_started.tsx b/src/plugins/kibana_overview/public/components/getting_started/getting_started.tsx new file mode 100644 index 0000000000000..9f2d714f43a53 --- /dev/null +++ b/src/plugins/kibana_overview/public/components/getting_started/getting_started.tsx @@ -0,0 +1,126 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { FC } from 'react'; +import { + EuiButton, + EuiCard, + EuiFlexGrid, + EuiFlexGroup, + EuiFlexItem, + EuiIcon, + EuiImage, + EuiSpacer, + EuiText, + EuiTitle, +} from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { CoreStart } from 'kibana/public'; +import { RedirectAppLinks, useKibana } from '../../../../../../src/plugins/kibana_react/public'; +import { FeatureCatalogueEntry } from '../../../../../../src/plugins/home/public'; +import { PLUGIN_ID } from '../../../common'; + +interface Props { + addBasePath: (path: string) => string; + isDarkTheme: boolean; + apps: FeatureCatalogueEntry[]; +} + +export const GettingStarted: FC = ({ addBasePath, isDarkTheme, apps }) => { + const { + services: { application }, + } = useKibana(); + const gettingStartedGraphicURL = `/plugins/${PLUGIN_ID}/assets/kibana_montage_${ + isDarkTheme ? 'dark' : 'light' + }.svg`; + + return ( +
+ + +
+ +

+ +

+
+ + + + +

+ +

+
+ + + + + {apps.map(({ subtitle = '', icon, title }) => ( + + } + layout="horizontal" + paddingSize="none" + title={title} + titleElement="h3" + titleSize="xs" + /> + + ))} + + + + + + + + + +
+
+ + + + +
+
+ ); +}; diff --git a/src/plugins/kibana_overview/public/components/getting_started/index.ts b/src/plugins/kibana_overview/public/components/getting_started/index.ts new file mode 100644 index 0000000000000..6a0df12de2d2d --- /dev/null +++ b/src/plugins/kibana_overview/public/components/getting_started/index.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from './getting_started'; diff --git a/src/plugins/kibana_overview/public/components/manage_data/__snapshots__/manage_data.test.tsx.snap b/src/plugins/kibana_overview/public/components/manage_data/__snapshots__/manage_data.test.tsx.snap new file mode 100644 index 0000000000000..4be9e4df6b736 --- /dev/null +++ b/src/plugins/kibana_overview/public/components/manage_data/__snapshots__/manage_data.test.tsx.snap @@ -0,0 +1,103 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ManageData render 1`] = ` + + +`; + +exports[`ManageData render empty without any features 1`] = ``; diff --git a/src/plugins/kibana_overview/public/components/manage_data/index.tsx b/src/plugins/kibana_overview/public/components/manage_data/index.tsx new file mode 100644 index 0000000000000..2845e3bd12023 --- /dev/null +++ b/src/plugins/kibana_overview/public/components/manage_data/index.tsx @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from './manage_data'; diff --git a/src/plugins/kibana_overview/public/components/manage_data/manage_data.test.tsx b/src/plugins/kibana_overview/public/components/manage_data/manage_data.test.tsx new file mode 100644 index 0000000000000..3ce2364c96083 --- /dev/null +++ b/src/plugins/kibana_overview/public/components/manage_data/manage_data.test.tsx @@ -0,0 +1,83 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { ManageData } from './manage_data'; +import { shallowWithIntl } from 'test_utils/enzyme_helpers'; +import { FeatureCatalogueCategory } from 'src/plugins/home/public'; + +const mockFeatures = [ + { + category: FeatureCatalogueCategory.ADMIN, + description: 'Control who has access and what tasks they can perform.', + icon: 'securityApp', + id: 'security', + order: 600, + path: 'path-to-security-roles', + title: 'Protect your data', + showOnHomePage: true, + }, + { + category: FeatureCatalogueCategory.ADMIN, + description: 'Track the real-time health and performance of your deployment.', + icon: 'monitoringApp', + id: 'monitoring', + order: 610, + path: 'path-to-monitoring', + title: 'Monitor the stack', + showOnHomePage: true, + }, + { + category: FeatureCatalogueCategory.ADMIN, + description: + 'Save snapshots to a backup repository, and restore to recover index and cluster state.', + icon: 'storage', + id: 'snapshot_restore', + order: 630, + path: 'path-to-snapshot-restore', + title: 'Store & recover backups', + showOnHomePage: true, + }, + { + category: FeatureCatalogueCategory.ADMIN, + description: 'Define lifecycle policies to automatically perform operations as an index ages.', + icon: 'indexSettings', + id: 'index_lifecycle_management', + order: 640, + path: 'path-to-index-lifecycle-management', + title: 'Manage index lifecycles', + showOnHomePage: true, + }, +]; + +const addBasePathMock = jest.fn((path: string) => (path ? path : 'path')); + +describe('ManageData', () => { + test('render', () => { + const component = shallowWithIntl( + + ); + expect(component).toMatchSnapshot(); + }); + + test('render empty without any features', () => { + const component = shallowWithIntl(); + expect(component).toMatchSnapshot(); + }); +}); diff --git a/src/plugins/kibana_overview/public/components/manage_data/manage_data.tsx b/src/plugins/kibana_overview/public/components/manage_data/manage_data.tsx new file mode 100644 index 0000000000000..f7a40b9370efd --- /dev/null +++ b/src/plugins/kibana_overview/public/components/manage_data/manage_data.tsx @@ -0,0 +1,95 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, { FC } from 'react'; +import PropTypes from 'prop-types'; +import { EuiFlexGroup, EuiFlexItem, EuiHorizontalRule, EuiSpacer, EuiTitle } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { CoreStart } from 'kibana/public'; +import { RedirectAppLinks, useKibana } from '../../../../../../src/plugins/kibana_react/public'; +import { FeatureCatalogueEntry } from '../../../../../../src/plugins/home/public'; +// @ts-expect-error untyped component +import { Synopsis } from '../synopsis'; + +interface Props { + addBasePath: (path: string) => string; + features: FeatureCatalogueEntry[]; +} + +export const ManageData: FC = ({ addBasePath, features }) => { + const { + services: { application }, + } = useKibana(); + return ( + <> + {features.length > 1 ?