diff --git a/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap b/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap index 2cfe232bf5653c..fe959e570ab986 100644 --- a/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap +++ b/src/core/public/chrome/ui/header/__snapshots__/collapsible_nav.test.tsx.snap @@ -147,7 +147,7 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` "baseUrl": "/", "category": Object { "euiIconType": "logoSecurity", - "id": "security", + "id": "securitySolution", "label": "Security", "order": 4000, }, @@ -1393,11 +1393,11 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` @@ -1433,7 +1433,7 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` } className="euiCollapsibleNavGroup euiCollapsibleNavGroup--withHeading" - data-test-subj="collapsibleNavGroup-security" + data-test-subj="collapsibleNavGroup-securitySolution" id="mockId" initialIsOpen={true} onToggle={[Function]} @@ -1441,7 +1441,7 @@ exports[`CollapsibleNav renders links grouped by category 1`] = ` >
- + {navType === 'modern' ? ( diff --git a/src/core/public/overlays/banners/_banners_list.scss b/src/core/public/overlays/banners/_banners_list.scss index ff260f7dc42fd8..9d4df065a0a4fa 100644 --- a/src/core/public/overlays/banners/_banners_list.scss +++ b/src/core/public/overlays/banners/_banners_list.scss @@ -3,5 +3,5 @@ } .kbnGlobalBannerList__item + .kbnGlobalBannerList__item { - margin-top: $euiSize; + margin-top: $euiSizeS; } diff --git a/src/core/utils/default_app_categories.ts b/src/core/utils/default_app_categories.ts index cc9bfb1db04d5e..1fb7c284c0dfda 100644 --- a/src/core/utils/default_app_categories.ts +++ b/src/core/utils/default_app_categories.ts @@ -46,7 +46,7 @@ export const DEFAULT_APP_CATEGORIES = Object.freeze({ order: 3000, }, security: { - id: 'security', + id: 'securitySolution', label: i18n.translate('core.ui.securityNavList.label', { defaultMessage: 'Security', }), diff --git a/src/plugins/advanced_settings/kibana.json b/src/plugins/advanced_settings/kibana.json index 8cf9b9c656d8f2..0e49fe17089f0b 100644 --- a/src/plugins/advanced_settings/kibana.json +++ b/src/plugins/advanced_settings/kibana.json @@ -4,5 +4,6 @@ "server": true, "ui": true, "requiredPlugins": ["management"], - "requiredBundles": ["kibanaReact"] + "optionalPlugins": ["home"], + "requiredBundles": ["kibanaReact", "home"] } 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 d8853015d362a5..4afcba14abef48 100644 --- a/src/plugins/advanced_settings/public/management_app/advanced_settings.tsx +++ b/src/plugins/advanced_settings/public/management_app/advanced_settings.tsx @@ -114,6 +114,21 @@ export class AdvancedSettingsComponent extends Component< filteredSettings: this.mapSettings(Query.execute(query, this.settings)), }); }); + + // scrolls to setting provided in the URL hash + const { hash } = window.location; + if (hash !== '') { + setTimeout(() => { + const id = hash.replace('#', ''); + const element = document.getElementById(id); + const globalNavOffset = document.getElementById('headerGlobalNav')?.offsetHeight || 0; + + if (element) { + element.scrollIntoView(); + window.scrollBy(0, -globalNavOffset); // offsets scroll by height of the global nav + } + }, 0); + } } componentWillUnmount() { diff --git a/src/plugins/advanced_settings/public/management_app/components/field/__snapshots__/field.test.tsx.snap b/src/plugins/advanced_settings/public/management_app/components/field/__snapshots__/field.test.tsx.snap index da18eb70e5874c..2aabacb061667f 100644 --- a/src/plugins/advanced_settings/public/management_app/components/field/__snapshots__/field.test.tsx.snap +++ b/src/plugins/advanced_settings/public/management_app/components/field/__snapshots__/field.test.tsx.snap @@ -15,6 +15,7 @@ exports[`Field for array setting should render as read only if saving is disable } fullWidth={true} + id="array:test:setting" title={

} fullWidth={true} + id="array:test:setting" title={

} fullWidth={true} + id="array:test:setting" title={

} fullWidth={true} + id="array:test:setting" title={

} fullWidth={true} + id="array:test:setting" title={

} fullWidth={true} + id="array:test:setting" title={

} fullWidth={true} + id="boolean:test:setting" title={

} fullWidth={true} + id="boolean:test:setting" title={

} fullWidth={true} + id="boolean:test:setting" title={

} fullWidth={true} + id="boolean:test:setting" title={

} fullWidth={true} + id="boolean:test:setting" title={

} fullWidth={true} + id="boolean:test:setting" title={

} fullWidth={true} + id="image:test:setting" title={

} fullWidth={true} + id="image:test:setting" title={

} fullWidth={true} + id="image:test:setting" title={

} fullWidth={true} + id="image:test:setting" title={

} fullWidth={true} + id="image:test:setting" title={

} fullWidth={true} + id="image:test:setting" title={

} fullWidth={true} + id="json:test:setting" title={

} fullWidth={true} + id="json:test:setting" title={

} fullWidth={true} + id="json:test:setting" title={

} fullWidth={true} + id="json:test:setting" title={

} fullWidth={true} + id="json:test:setting" title={

} fullWidth={true} + id="json:test:setting" title={

} fullWidth={true} + id="markdown:test:setting" title={

} fullWidth={true} + id="markdown:test:setting" title={

} fullWidth={true} + id="markdown:test:setting" title={

} fullWidth={true} + id="markdown:test:setting" title={

} fullWidth={true} + id="markdown:test:setting" title={

} fullWidth={true} + id="markdown:test:setting" title={

} fullWidth={true} + id="number:test:setting" title={

} fullWidth={true} + id="number:test:setting" title={

} fullWidth={true} + id="number:test:setting" title={

} fullWidth={true} + id="number:test:setting" title={

} fullWidth={true} + id="number:test:setting" title={

} fullWidth={true} + id="number:test:setting" title={

} fullWidth={true} + id="select:test:setting" title={

} fullWidth={true} + id="select:test:setting" title={

} fullWidth={true} + id="select:test:setting" title={

} fullWidth={true} + id="select:test:setting" title={

} fullWidth={true} + id="select:test:setting" title={

} fullWidth={true} + id="select:test:setting" title={

} fullWidth={true} + id="string:test:setting" title={

} fullWidth={true} + id="string:test:setting" title={

} fullWidth={true} + id="string:test:setting" title={

} fullWidth={true} + id="string:test:setting" title={

} fullWidth={true} + id="string:test:setting" title={

} fullWidth={true} + id="string:test:setting" title={

} fullWidth={true} + id="string:test-validation:setting" title={

} fullWidth={true} + id="string:test-validation:setting" title={

} fullWidth={true} + id="string:test-validation:setting" title={

} fullWidth={true} + id="string:test-validation:setting" title={

} fullWidth={true} + id="string:test-validation:setting" title={

} fullWidth={true} + id="string:test-validation:setting" title={

{ return ( { - public setup(core: CoreSetup, { management }: AdvancedSettingsPluginSetup) { + public setup(core: CoreSetup, { management, home }: AdvancedSettingsPluginSetup) { const kibanaSection = management.sections.section.kibana; kibanaSection.registerApp({ @@ -44,6 +45,21 @@ export class AdvancedSettingsPlugin }, }); + if (home) { + home.featureCatalogue.register({ + id: 'advanced_settings', + title, + description: i18n.translate('advancedSettings.featureCatalogueTitle', { + defaultMessage: + 'Customize your Kibana experience — change the date format, turn on dark mode, and more.', + }), + icon: 'gear', + path: '/app/management/kibana/settings', + showOnHomePage: false, + category: FeatureCatalogueCategory.ADMIN, + }); + } + return { component: component.setup, }; diff --git a/src/plugins/advanced_settings/public/types.ts b/src/plugins/advanced_settings/public/types.ts index a233b3debab8d0..cc59f52b1f30fb 100644 --- a/src/plugins/advanced_settings/public/types.ts +++ b/src/plugins/advanced_settings/public/types.ts @@ -18,6 +18,8 @@ */ import { ComponentRegistry } from './component_registry'; +import { HomePublicPluginSetup } from '../../home/public'; + import { ManagementSetup } from '../../management/public'; export interface AdvancedSettingsSetup { @@ -29,6 +31,7 @@ export interface AdvancedSettingsStart { export interface AdvancedSettingsPluginSetup { management: ManagementSetup; + home?: HomePublicPluginSetup; } export { ComponentRegistry }; diff --git a/src/plugins/console/kibana.json b/src/plugins/console/kibana.json index 031aa00eb6613d..ca43e4f258adda 100644 --- a/src/plugins/console/kibana.json +++ b/src/plugins/console/kibana.json @@ -3,7 +3,7 @@ "version": "kibana", "server": true, "ui": true, - "requiredPlugins": ["devTools", "home"], - "optionalPlugins": ["usageCollection"], - "requiredBundles": ["esUiShared", "kibanaReact", "kibanaUtils"] + "requiredPlugins": ["devTools"], + "optionalPlugins": ["usageCollection", "home"], + "requiredBundles": ["esUiShared", "kibanaReact", "kibanaUtils", "home"] } diff --git a/src/plugins/console/public/plugin.ts b/src/plugins/console/public/plugin.ts index 03b65a8bd145c5..f3421aefaf38df 100644 --- a/src/plugins/console/public/plugin.ts +++ b/src/plugins/console/public/plugin.ts @@ -28,19 +28,21 @@ export class ConsoleUIPlugin implements Plugin { const homeTitle = i18n.translate('home.breadcrumbs.homeTitle', { defaultMessage: 'Home' }); const { featureCatalogue, chrome } = getServices(); + const navLinks = chrome.navLinks.getAll(); // all the directories could be get in "start" phase of plugin after all of the legacy plugins will be moved to a NP const directories = featureCatalogue.get(); + // Filters solutions by available nav links + const solutions = featureCatalogue + .getSolutions() + .filter(({ id }) => navLinks.find(({ category, hidden }) => !hidden && category?.id === id)); + chrome.setBreadcrumbs([{ text: homeTitle }]); render( - + , element ); diff --git a/src/plugins/home/public/application/components/__snapshots__/add_data.test.js.snap b/src/plugins/home/public/application/components/__snapshots__/add_data.test.js.snap deleted file mode 100644 index 9178d0e08f3e04..00000000000000 --- a/src/plugins/home/public/application/components/__snapshots__/add_data.test.js.snap +++ /dev/null @@ -1,1163 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`apmUiEnabled 1`] = ` - - - - - - - - - - -

- -

-
-
-
- - - - - APM automatically collects in-depth performance metrics and errors from inside your applications. -
- } - footer={ - - - - } - textAlign="left" - title="APM" - titleSize="xs" - /> - - - - Ingest logs from popular data sources and easily visualize in preconfigured dashboards. - - } - footer={ - - - - } - textAlign="left" - title="Logs" - titleSize="xs" - /> - - - - Collect metrics from the operating system and services running on your servers. - - } - footer={ - - - - } - textAlign="left" - title="Metrics" - titleSize="xs" - /> - - - - - - - - - - -

- -

-
-
-
- - - Protect hosts, analyze security information and events, hunt threats, automate detections, and create cases. - - } - footer={ - - - - } - textAlign="left" - title="SIEM + Endpoint Security" - titleSize="xs" - /> -
- - - - - - - - - - - - - - - - - - - - - - - - - -`; - -exports[`isNewKibanaInstance 1`] = ` - - - - - - - - - - -

- -

-
-
-
- - - - - Ingest logs from popular data sources and easily visualize in preconfigured dashboards. - - } - footer={ - - - - } - textAlign="left" - title="Logs" - titleSize="xs" - /> - - - - Collect metrics from the operating system and services running on your servers. - - } - footer={ - - - - } - textAlign="left" - title="Metrics" - titleSize="xs" - /> - - -
- - - - - - - -

- -

-
-
-
- - - Protect hosts, analyze security information and events, hunt threats, automate detections, and create cases. - - } - footer={ - - - - } - textAlign="left" - title="SIEM + Endpoint Security" - titleSize="xs" - /> -
-
- - - - - - - - - - - - - - - - - - - - - - - -
-`; - -exports[`mlEnabled 1`] = ` - - - - - - - - - - -

- -

-
-
-
- - - - - APM automatically collects in-depth performance metrics and errors from inside your applications. - - } - footer={ - - - - } - textAlign="left" - title="APM" - titleSize="xs" - /> - - - - Ingest logs from popular data sources and easily visualize in preconfigured dashboards. - - } - footer={ - - - - } - textAlign="left" - title="Logs" - titleSize="xs" - /> - - - - Collect metrics from the operating system and services running on your servers. - - } - footer={ - - - - } - textAlign="left" - title="Metrics" - titleSize="xs" - /> - - -
- - - - - - - -

- -

-
-
-
- - - Protect hosts, analyze security information and events, hunt threats, automate detections, and create cases. - - } - footer={ - - - - } - textAlign="left" - title="SIEM + Endpoint Security" - titleSize="xs" - /> -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-`; - -exports[`render 1`] = ` - - - - - - - - - - -

- -

-
-
-
- - - - - Ingest logs from popular data sources and easily visualize in preconfigured dashboards. - - } - footer={ - - - - } - textAlign="left" - title="Logs" - titleSize="xs" - /> - - - - Collect metrics from the operating system and services running on your servers. - - } - footer={ - - - - } - textAlign="left" - title="Metrics" - titleSize="xs" - /> - - -
- - - - - - - -

- -

-
-
-
- - - Protect hosts, analyze security information and events, hunt threats, automate detections, and create cases. - - } - footer={ - - - - } - textAlign="left" - title="SIEM + Endpoint Security" - titleSize="xs" - /> -
-
- - - - - - - - - - - - - - - - - - - - - - - -
-`; 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 4fa04bb64b1777..1b10756c2975c3 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 @@ -1,1066 +1,1615 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`home directories should not render directory entry when showOnHomePage is false 1`] = ` - - - -

- -

-
- - - - - +
+ + -

+

-

+

- - - - - - + - -

- -

-
- - -
+ + + Add data + + + +
+ +

+ +
+ 0 + + + + + + -
+ `; -exports[`home directories should render ADMIN directory entry in "Manage" panel 1`] = ` - - - -

- -

-
- - - - - +
+ + -

+

-

+
- - - +
+ + + + + Add data + + + + + Manage + + + + +
+
+ +
+ 0 + + + - + + +
+ +`; + +exports[`home directories should render ADMIN directory entry in "Manage your data" panel 1`] = ` +
+
+
+ + -

+

-

+
- - + + - + + Add data + - - +
+ + +
+
+
+ 0 + + + + + + -
+
`; -exports[`home directories should render DATA directory entry in "Explore Data" panel 1`] = ` - - - -

- -

-
- - - - - +
+ + -

+

-

+
- - + + - + + Add data + - - +
+ + +
+ +
+ 0 + + + - + + +
+ +`; + +exports[`home directories should render solutions in the "solution section" 1`] = ` +
+
+
+ + -

+

-

+
- - - +
+ + + + + Add data + + + + +
+
+
+
+ + + + + + + -
+
`; -exports[`home isNewKibanaInstance should safely handle execeptions 1`] = ` - - - -

- -

-
- - - - - +
+ + -

+

-

+
- - - +
+ + + + + Add data + + + + +
+
+ +
+ 0 + + + - + + +
+ +`; + +exports[`home header should show "Dev tools" link if console is available 1`] = ` +
+
+
+ + -

+

-

+
- - - +
+ + + + + Add data + + + + + Dev tools + + + + +
+
+
+
+ 0 + + + + + + -
+
`; -exports[`home isNewKibanaInstance should set isNewKibanaInstance to false when there are index patterns 1`] = ` - - - -

- -

-
- - - - - +
+ + -

+

-

+
- - - +
+ + + + + Add data + + + + + Manage + + + + +
+
+ +
+ 0 + + + - + + +
+ +`; + +exports[`home isNewKibanaInstance should safely handle execeptions 1`] = ` +
+
+
+ + -

+

-

+
- - - +
+ + + + + Add data + + + + +
+
+
+
+ 0 + + + + + + -
+
`; -exports[`home isNewKibanaInstance should set isNewKibanaInstance to true when there are no index patterns 1`] = ` - - - -

- -

-
- - - - - +
+ + -

+

-

+
- - - +
+ + + + + Add data + + + + +
+
+ +
+ 0 + + + - + + +
+ +`; + +exports[`home isNewKibanaInstance should set isNewKibanaInstance to true when there are no index patterns 1`] = ` +
+
+
+ + -

+

-

+
- - - +
+ + + + + Add data + + + + +
+
+
+
+ 0 + + + + + + -
+
`; exports[`home should render home component 1`] = ` - - - -

- -

-
- - - - - +
+ + -

+

-

+
- - - -
- - + - -

- -

-
- - -
+ + + Add data + + +
+ + +
+ +
+ 0 + + + + + + -
+ `; exports[`home welcome should show the normal home page if loading fails 1`] = ` - - - -

- -

-
- - - - - +
+ + -

+

-

+
- - - -
- - + - -

- -

-
- - -
+ + + Add data + + +
+ + +
+ +
+ 0 + + + + + + -
+ `; exports[`home welcome should show the normal home page if welcome screen is disabled locally 1`] = ` - - - -

- -

-
- - - - - +
+ + -

+

-

+
- - - -
- - + - -

- -

-
- - -
+ + + Add data + + +
+ + +
+ +
+ 0 + + + + + + -
+ `; exports[`home welcome should show the welcome screen if enabled, and there are no index patterns defined 1`] = ` @@ -1071,116 +1620,107 @@ 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 + + + + + + -
+ `; 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 d757d6a8b73051..190985f70659d4 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 @@ -4,7 +4,7 @@ exports[`props iconType 1`] = ` `; @@ -24,7 +25,7 @@ exports[`props iconUrl 1`] = ` `; @@ -44,11 +46,12 @@ exports[`props isBeta 1`] = ` `; @@ -57,11 +60,12 @@ exports[`render 1`] = ` `; diff --git a/src/plugins/home/public/application/components/_add_data.scss b/src/plugins/home/public/application/components/_add_data.scss index 836b34227a37c2..e588edfe352406 100644 --- a/src/plugins/home/public/application/components/_add_data.scss +++ b/src/plugins/home/public/application/components/_add_data.scss @@ -1,63 +1,22 @@ -.homAddData__card { - border: none; - box-shadow: none; -} - -.homAddData__cardDivider { - position: relative; - - &:after { - position: absolute; - content: ''; - width: 1px; - right: -$euiSizeS; - top: 0; - bottom: 0; - background: $euiBorderColor; - } -} - -.homAddData__icon { - width: $euiSizeXL * 2; - height: $euiSizeXL * 2; -} - -.homAddData__footerItem--highlight { - background-color: tintOrShade($euiColorPrimary, 90%, 70%); - padding: $euiSize; -} - -.homAddData__footerItem { - text-align: center; -} - -.homAddData__logo { - margin-left: $euiSize; -} - -@include euiBreakpoint('xs', 's') { - .homeAddData__flexGroup { - flex-wrap: wrap; - } -} - -@include euiBreakpoint('xs', 's', 'm') { - .homAddDat__flexTablet { - flex-direction: column; - } - - .homAddData__cardDivider:after { - display: none; - } - - .homAddData__cardDivider { - flex-grow: 0 !important; - flex-basis: 100% !important; - } -} - -@include euiBreakpoint('l', 'xl') { - .homeAddData__flexGroup { - flex-wrap: nowrap; - } +/* + * 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. + */ + +.homDataAdd__content .euiIcon__fillSecondary { + fill: $euiColorDarkestShade; } diff --git a/src/plugins/home/public/application/components/_home.scss b/src/plugins/home/public/application/components/_home.scss index 4101f6519829b7..d9b7602971e8dd 100644 --- a/src/plugins/home/public/application/components/_home.scss +++ b/src/plugins/home/public/application/components/_home.scss @@ -1,5 +1,73 @@ -@include euiBreakpoint('xs', 's', 'm') { - .homHome__synopsisItem { - flex-basis: 100% !important; +/* + * 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. + */ + +// Local page variables +$homePageWidth: 1200px; + +.homWrapper { + background-color: $euiColorEmptyShade; + display: flex; + flex-direction: column; + min-height: calc(100vh - #{$euiHeaderHeightCompensation}); +} + +.homHeader { + background-color: $euiPageBackgroundColor; + border-bottom: $euiBorderWidthThin solid $euiColorLightShade; +} + +.homHeader__inner { + margin: 0 auto; + max-width: $homePageWidth; + padding: $euiSizeXL $euiSize; + + .homHeader--hasSolutions & { + padding-bottom: $euiSizeXL + $euiSizeL; + } +} + +#homHeader__title { + @include euiBreakpoint('xs', 's') { + text-align: center; + } +} + +.homHeader__actionItem { + @include euiBreakpoint('xs', 's') { + margin-bottom: 0 !important; + margin-top: 0 !important; + } +} + +.homContent { + margin: 0 auto; + max-width: $homePageWidth; + padding: $euiSizeXL $euiSize; + width: 100%; +} + +.homData--expanded { + flex-direction: column; + + &, + & > * { + margin-bottom: 0 !important; + margin-top: 0 !important; } } diff --git a/src/plugins/home/public/application/components/_index.scss b/src/plugins/home/public/application/components/_index.scss index 870099ffb350e4..a0547a45885611 100644 --- a/src/plugins/home/public/application/components/_index.scss +++ b/src/plugins/home/public/application/components/_index.scss @@ -5,9 +5,11 @@ // homChart__legend--small // homChart__legend-isLoading -@import 'add_data'; @import 'home'; +@import 'add_data'; +@import 'manage_data'; @import 'sample_data_set_cards'; +@import 'solutions_section'; @import 'synopsis'; @import 'welcome'; diff --git a/src/plugins/home/public/application/components/_manage_data.scss b/src/plugins/home/public/application/components/_manage_data.scss new file mode 100644 index 00000000000000..389d8c8b3bf0f0 --- /dev/null +++ b/src/plugins/home/public/application/components/_manage_data.scss @@ -0,0 +1,22 @@ +/* + * 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. + */ + +.homDataManage__content .euiIcon__fillSecondary { + fill: $euiColorDarkestShade; +} diff --git a/src/plugins/home/public/application/components/_solutions_section.scss b/src/plugins/home/public/application/components/_solutions_section.scss new file mode 100644 index 00000000000000..be693707e06b4c --- /dev/null +++ b/src/plugins/home/public/application/components/_solutions_section.scss @@ -0,0 +1,122 @@ +/* + * 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. + */ + +.homSolutions { + margin-top: -($euiSizeXL + $euiSizeL + $euiSizeM); +} + +.homSolutions__content { + min-height: $euiSize * 16; + + @include euiBreakpoint('xs', 's') { + flex-direction: column; + } +} + +.homSolutions__group { + max-width: 50%; + + @include euiBreakpoint('xs', 's') { + max-width: none; + } +} + +.homSolutionPanel { + border-radius: $euiBorderRadius; + color: inherit; + flex: 1; + transition: all $euiAnimSpeedFast $euiAnimSlightResistance; + + &:hover, + &:focus { + @include euiSlightShadowHover; + transform: translateY(-2px); + + .euiTitle { + text-decoration: underline; + } + } + + &, + .euiPanel { + display: flex; + flex-direction: column; + } + + .euiPanel { + overflow: hidden; + } +} + +.homSolutionPanel__header { + color: $euiColorEmptyShade; + padding: $euiSize; +} + +.homSolutionPanel__icon { + background-color: $euiColorEmptyShade !important; + box-shadow: none !important; + margin: 0 auto $euiSizeS; + padding: $euiSizeS; +} + +.homSolutionPanel__subtitle { + margin-top: $euiSizeXS; +} + +.homSolutionPanel__content { + flex-direction: column; + justify-content: center; + padding: $euiSize; + + @include euiBreakpoint('xs', 's') { + text-align: center; + } +} + +.homSolutionPanel__header { + background-color: $euiColorPrimary; + background-image: url('data:image/png;base64,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'), + url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAWgAAAFKCAYAAAAwgcXoAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAjGSURBVHgB7d27ctRaFoDh1WBzsQ9wLkVsngHHfglSIOUdgJQiJSfmIUjhJUwGjiGaU7hmzoB7vLA1GPCt21vSlvR9Vao+5lAFbbf+EktbUgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUaxYAEzCfz/NldX9biTK+zGaz/0aLSv1FAYbg6v52I8r4e39rNdCXAoAqCTRApQQaoFICDVApgQaolEADVEqgASol0ACVEmiASgk0QKUEGqBSAg1QKYEGqJRAA1RKoAEqJdAAlRJogEp5ogowJV/3t/9EGV8DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFjELABOMZ/Po6TZrL/sDO29rATA6Vb3t/UoY29/+1f04DDO1w63Ev59uLVGoIGz5GHi9Sjja/QU6EPZvFLv5Uu07FIAUCWBBqiUQANUSqABKiXQAJUSaIBKCTRApQQaoFICDVApgQaolEADVEqgASol0ACVEmiASgl0ANRJoAEqJdAAlfJEFeAs+RSUv6OMsg8FXNw/Ue69/BMAAAAAAAAAAAAAAAAAAAAAQCdmAcBpspNn3flzL1q4EZRAA2PRhLR5vXz4683ryk+/7+j/ixO+vqiM9t6Rr78e899ffvq9za9/FWigdhnNbNVqfA/wyuHr5fgxxqMi0EDfMq4Z3ya4K4fbaMN7XgINdKGJ8OUjW/M1JxBooKSj4c3X5mhYa5bgmwYsoxlHXA0hbo1vJnCW5gRds10Jo4lOCDTws4xvRjiPjvOoeDXohUDDtB09Or4W31dTUAE/CJiWJshNjK8E1RJoGDdBHjCBhvHJCBtZjIAfHAxf7scZ46uHr/brkfCDhGFqVllcCWOL0RJoGIajs+S16Hjfnc3K/XHzefG7cp7b0N6HQEO9qhhdbG5uxosXL6KET58+xb1796IPGef79+/Ho0ePooSXL1/Gq1evok0rAdSkiXIeJVdxgm9tbS22traihJ2dnejTxsZGsffy+vXraJtAQ/+qizJ1EGjoRzNTvhGizAkEGrqVKy56OdHH8Ag0tC9vPpRBXg9RZgECDe3IEGeU82jZOmWWItBQlhEGxQg0XFyG+Lc4CLN9imJ8mGB5ebScc+W8kMTRMsUJNCzGbJnOCDScj5UYdE6g4XR5lHwjHC3TA4GGXx299FqY6Y1Aw3fNagxjDKog0CDMVEqgmbIcX+QY43pAhQSaKXLij0EQaKZEmJfU52OqShvSexFopkCYL2B7ezsePnwYJezu7kZfMsz5FJQPHz5ECe/evYu2OSHCmAkzgybQjJEwMwoCzZgIM6Mi0IxB3ifjZhxc/QejIdAMWX5+84h5PWCEBJohcuUfk+DDzdBklPOo2WeX0fMhZyjyxN/vcTBvhkkQaGq3GgcnAK3MYHIEmlo5AcjkCTQ1MmeGsANQlxxj5DhjNQCBpgr5ObwV7ssMPxBo+macASewU9AX982AMwg0XbM6A85JoOmSi01gAQJNF9xtDpYg0LTNSUBYkp2GtuRRc44znASEJQk0bXDUDAXYgSjJUTMUJNCU4qgZCrMzcVGOmqElAs1F5LK5jLPPEbTAjsUyXA0IHRBoFuVqQOiIQLOIPGr+LZic2axcKubzefSl5PtIbb+XSwFny6Plv0KcJ2lrayv29vaKbO/fv4++ZJyfPHlS7L08fvw42rYScDonAqEnAs1JnAiEngk0x8mRxh/h2YDQK4HmZ2txcGtQIw3omUBzVIbZSAMqIdAkIw2okEDjwhOolEBPW44zbgZQJYGepjwBeGt/ux5AtQR6epqrAo00oHICPS05b/4zLKGDQRDo6TBvhoER6GmwvhkGSKDHzfpmGDCBHi8nA2HgBHqcnAyEERDo8XEyEEZCoMfFI6loRZ+PqSptSO/FP4HHI++n4cpAWrGxsRGl7OzsRF/W1tbi9u3bUcLHjx9jd3c32iTQw5c/wzwZaKUGjIxAD5uVGjBiAj1c4gwjJ9DDlOOMjLOfH4yYHXx4PDMQJsJOPiwZ51sBTIJAD4c1zjAxAj0M4gwTJND1E2eYKIGum/s4w4QJdL1cug0TJ9B1EmdAoCskzsA3Al0XcQb+T6DrIc7ADwS6DuIM/EKg+yfOwLEEul/iDJxIoPsjzsCpLgV9yCsExRk4lUB3L++t4fJt4ExGHN1y4yPg3AS6O+IMLESguyHOwMLMoNuXj6kSZ2BhAt2ua+EZgsCSBLo9q3Gw1hlgKStBGy7vb3+EGT8jsL6+Hpubm1HK27dvoy8bGxvfthJ2dna+bW0S6PIyzn8dvsLg3b17N968eRMlZNDu3LkTfZjNZvHgwYN49uxZlPD06dN4/vx5tMmIo6w8YhZnoAiBLuvPEGegEIEuJ++vcSUAChHoMtxfAyhOoC8uw+xCFKA4gb6YXOt8MwBaINDLa9Y6A7RCoJdjOR3QOoFeTl7CLc5AqwR6cbli41oAtEygF2PFBtAZgT4/KzaATgn0+VixAXROoM8n4+ykINApgT5bjjVWA6BjAn269XCPDaAnAn2yHGk4KQj8Yj6fRxc8UeV4zVNRYPJ2d3dje3s7Smj7EVFn+fz5c5H3koHO70vbPDPveHlS0MUoQK+MOH7lSkGgCgL9o3wiiisFgSoI9Hc5d/49ACoh0N+5Qx1QFYE+kHNnD3wFqiLQ5s5ApaYeaHNnoFpTD3SONsydgSpNOdB5j43rAVCpqQbafTaA6k010O6zAVRvioE2dwYGYWqBtqQOGIwpBdqSOmBQphRoow1gUKYS6OthSR0wMFMIdB413wiAgZlCoI02gEEae6CNNoDBGnOgjTaAQRtzoI02gEEba6CNNoDBG2OgZ2G0AYzA/wBP5hsF50HhogAAAABJRU5ErkJggg=='); + background-repeat: no-repeat; + background-position: top 0 left 0, bottom 0 right 0; + background-size: $euiSizeXL * 4, $euiSizeXL * 6; + + .homSolutionPanel--enterpriseSearch & { + background-color: $euiColorSecondary; + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAABKCAYAAADJwhY8AAAACXBIWXMAABYlAAAWJQFJUiTwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAANMSURBVHgBzZp7buIwEMYHKC1QuqsF7Up7Hs4Al+Ff4DCcAonrtPuAPjcL1B/YyA0p2JkZK580SuQm6Y+xx4+xiSqumrG+d7/z/rYx9t+WZdZ2lFhXxq4jngfkP2Ov9qquq8jnm9Zu6eBNgD6TImwsoC80ibY1NIe1sRcSVsPYHfFVN9Yy1jG2pUPbFZEUoJMP+kYHWJakAZ0AemuvrPZZJ10B8jsdHFFKWh70BSe07X1GkUoBCCHib+w1qsq1qzivLkU6JDUgTSaT7m63C4ZMCmjgaDwe4zYYMhmgB+cEyPal95IAFsA5fTGQZ4dbdcAzcO7/9wxk7bMH8AfMTvJDUsO+fG2tSfJwvp5qtdqKPgEMEYABekeBo0IEnNODgTzpI0MBfaFhnwUtAQdlBvA+X1gG0Kmw0y0J57QykE9+ASdIHo3hF29cARMO6uYDhhvFGPwfjG0E4BxPxy/gVPFR8/m8MRwOsTosPa3y9KEtigBCpmoAJwV5jGixjtp8EG3xD8noOASKjiT2V6+Jr5YLFo2hDuvkDfEErqa7EZXx4naxWKyIr9b+e6QkU0U/iBcw+2jWnM08E09NtMMqA0JNNUC0ReInlRraE9bodXBOzaoD1rQBuVku9SpmZ7eSL9wjVa864LbqgOpVzJ4bagNyv7/RBozZgymSOuAN8bRTA7RrFM4+DJRpepBbvZAqIDf3jQmrThXbxCS3i5FdduYksXOAjUp5QJt75npvK75whwwclopd4uvV3YgB2m7lG8nouK0rAojkEcnlZTZ+plUCsDEajfom9SYBB31InXA/is64h+8sl0vKsowGgwExBO/99QvKDkXISHQpFxCz2Wx/nU6nVFIniacyHkTOpGevJ2J48sR7UKgHnceCRoiSnvxVVOj2P6C6ZyjHVKljwb7a54KDKtKT2MgpPDECD/ZJSYGedEdaCqW+437BkzgcdG/zOIVKciTgDOTawL2dezfVmYUiyHV+V6lIyQAhDxJwjyHvoPv4SWmFgAiCg1JnFqLgIO6qK1SIVowS0afjUgCin/tNJZOZ2oCIUlRr6aOlWoDwFjZz2CczpQHhKXjsYv8WKilAeAwBgL0R0ZPCHECAvFirzCFb/5hyknPV7zL4DLH0CVGgAAAAAElFTkSuQmCC'), + url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAA+CAYAAACbQR1vAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAACBSURBVHgB7dpBDcAwDMVQdyzGH9xojEQjtbIfBEu5fGUx62WPjyEPcgVArgDIFQC5AiBXAOQKgFwBkCsAcgVATh9gsW+4vFIngFwBkCsAcgVArgDIFQC5AiBXAORahJjVm9zpCoBcAZArAHIFQK4AyBUAuQIgVwDkCoBcAZDTB/gBLrgCk8OhuvYAAAAASUVORK5CYII='); + background-position: top $euiSizeS left 0, bottom $euiSizeS right $euiSizeS; + background-size: $euiSize * 1.25, $euiSizeXL; + } + + .homSolutionPanel--observability & { + background-color: $euiColorAccent; + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAYAAABV7bNHAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAADNSURBVHgB7duxCcIAEEDR08IFrGyz/0pZwVYEIcYF/FWKwHtwXP/hyrvMQbZtu+3rPid3Hf4SKAgUBAoCBYGCQEGgIFAQKAgUBAoCBYGCQEGgIFAQKAgUBAoCBYGCQEGgIFAQKAgUBAoCBYGCQEGgIFAQKAgUBAoCBYGCQEGgIFAQKAgUBAoCBYGCQEGgcJmDnt6WZfms6/qak/sFeswx3vs85+ScWBAoCBQECgIFgYJAQaAgUBAoCBQECgIFgYJAQaAgUBAoCBQECgKFLx4KCqcIFEJnAAAAAElFTkSuQmCC'); + background-position: top $euiSizeS right $euiSizeS; + background-size: $euiSizeL * 1.5; + } + + .homSolutionPanel--securitySolution & { + background-color: $euiColorDarkestShade; + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGIAAABiCAYAAACrpQYOAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAKRSURBVHgB7d3tSgMxEIXhMeqPQoWC9f4vte5Z3dLvTbKZzCQ5LyxqKwg+tNjdUxQR+RJmXpiOvRDDvPD/kRjGhYvPgbETZlK4+fogxDApPLiNGAaFJ7cD40NYtcKL+76FGNUKK/cRo1Ih4n5gvAtTbQ1i+R5iKBcDgYBADMViIRAxFEuBQMRQKhUCEUOhHAi0YLwJK1IuBCJGwbZAoE8hRpG2QqAFg22oBAQCxkFYdqUgEE6dEyOzkhCIGJmVhkDA4PXvxDQgEMcIiWlBIGIkpAmBiBGZNgQiRkQ1IBAxVqoFgThge1FNCMTN1JNqQyBiPMgCAnHAdpMVBOJm6iJLCA7YLrKEWH4+r3+LPYQIMeY8QKDhlyFeINDQGJ4g0LAY3iDQkBgeIdBwmymvEGgoDM8QaJgBm3cINMSArQUI1P2ArRUI1PVmqiUI1C1GaxCoywFbixCouzFCqxCIyxBPnU6nLjBafkQs7YExHdJyPUCg+WmqZYxeIBAwmv3TticItJseFYcWHxm9QaD5RV9rGD1CIGAcJ4xmztr2CoHms7atYPQMgc4Y3p+qeodAwPiZjnfPGCNAoPMgwSvGKBDINcZIEMgtxmgQyCXGiBDIHcaoEAgYx+n48IAxMgQ6v1nGGmN0COQCgxB/4feAF307KwxCXDe/9dgCgxD3mWAQ4nHAqHrplRDPq3odnBCvq4ZBiPWqYBAiLnUMQsSnikGItObtlAYGIdJTmesQIq/iGITIr+h2ihDbKradIsT2imynCFGmzdspQpRr03VwQpQtG4MQ5cvCIIROyRiE0CsJgxC6RW+nCKFf1FyHEHVaxSBEvV5upwhRv4dzHULYdIdBCLuutlOEsO18HZz/u8E+YMgvrbKfmp8y7IEAAAAASUVORK5CYII='); + background-position: top $euiSizeS left $euiSizeS; + background-size: $euiSizeL * 2; + } +} diff --git a/src/plugins/home/public/application/components/_synopsis.scss b/src/plugins/home/public/application/components/_synopsis.scss index 49e71f159fe6ff..3eac2bc9705e01 100644 --- a/src/plugins/home/public/application/components/_synopsis.scss +++ b/src/plugins/home/public/application/components/_synopsis.scss @@ -5,6 +5,10 @@ box-shadow: none; } + .homSynopsis__cardTitle { + display: flex; + } + // SASSTODO: Fix in EUI .euiCard__content { padding-top: 0 !important; diff --git a/src/plugins/home/public/application/components/add_data.js b/src/plugins/home/public/application/components/add_data.js deleted file mode 100644 index c35b7b04932fbd..00000000000000 --- a/src/plugins/home/public/application/components/add_data.js +++ /dev/null @@ -1,320 +0,0 @@ -/* - * 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 PropTypes from 'prop-types'; -import classNames from 'classnames'; -import { injectI18n, FormattedMessage } from '@kbn/i18n/react'; -import { getServices } from '../kibana_services'; - -import { - EuiButton, - EuiLink, - EuiPanel, - EuiTitle, - EuiSpacer, - EuiFlexGroup, - EuiFlexItem, - EuiText, - EuiCard, - EuiIcon, - EuiHorizontalRule, - EuiFlexGrid, -} from '@elastic/eui'; - -const AddDataUi = ({ apmUiEnabled, isNewKibanaInstance, intl, mlEnabled }) => { - const basePath = getServices().getBasePath(); - - const renderCards = () => { - const apmData = { - title: intl.formatMessage({ - id: 'home.addData.apm.nameTitle', - defaultMessage: 'APM', - }), - description: intl.formatMessage({ - id: 'home.addData.apm.nameDescription', - defaultMessage: - 'APM automatically collects in-depth performance metrics and errors from inside your applications.', - }), - ariaDescribedby: 'aria-describedby.addAmpButtonLabel', - }; - const loggingData = { - title: intl.formatMessage({ - id: 'home.addData.logging.nameTitle', - defaultMessage: 'Logs', - }), - description: intl.formatMessage({ - id: 'home.addData.logging.nameDescription', - defaultMessage: - 'Ingest logs from popular data sources and easily visualize in preconfigured dashboards.', - }), - ariaDescribedby: 'aria-describedby.addLogDataButtonLabel', - }; - const metricsData = { - title: intl.formatMessage({ - id: 'home.addData.metrics.nameTitle', - defaultMessage: 'Metrics', - }), - description: intl.formatMessage({ - id: 'home.addData.metrics.nameDescription', - defaultMessage: - 'Collect metrics from the operating system and services running on your servers.', - }), - ariaDescribedby: 'aria-describedby.addMetricsButtonLabel', - }; - const siemData = { - title: intl.formatMessage({ - id: 'home.addData.securitySolution.nameTitle', - defaultMessage: 'SIEM + Endpoint Security', - }), - description: intl.formatMessage({ - id: 'home.addData.securitySolution.nameDescription', - defaultMessage: - 'Protect hosts, analyze security information and events, hunt threats, automate detections, and create cases.', - }), - ariaDescribedby: 'aria-describedby.addSiemButtonLabel', - }; - - const getApmCard = () => ( - - {apmData.description}} - footer={ - - - - } - /> - - ); - - return ( - - - - - - - - - -

- -

-
-
-
- - - {apmUiEnabled !== false && getApmCard()} - - - {loggingData.description} - } - footer={ - - - - } - /> - - - - {metricsData.description} - } - footer={ - - - - } - /> - - -
- - - - - - - - -

- -

-
-
-
- - {siemData.description}} - footer={ - - - - } - /> -
-
- ); - }; - - const footerItemClasses = classNames('homAddData__footerItem', { - 'homAddData__footerItem--highlight': isNewKibanaInstance, - }); - - return ( - - {renderCards()} - - - - - - - - - - - - - - - {mlEnabled !== false ? ( - - - - - - - - - - - ) : null} - - - - - - - - - - - - - ); -}; - -AddDataUi.propTypes = { - apmUiEnabled: PropTypes.bool.isRequired, - mlEnabled: PropTypes.bool.isRequired, - isNewKibanaInstance: PropTypes.bool.isRequired, -}; - -export const AddData = injectI18n(AddDataUi); diff --git a/src/plugins/home/public/application/components/add_data.test.js b/src/plugins/home/public/application/components/add_data.test.js deleted file mode 100644 index 9457f766409b8f..00000000000000 --- a/src/plugins/home/public/application/components/add_data.test.js +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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 { getServices } from '../kibana_services'; - -jest.mock('../kibana_services', () => { - const mock = { - getBasePath: jest.fn(() => 'path'), - }; - return { - getServices: () => mock, - }; -}); - -beforeEach(() => { - jest.clearAllMocks(); -}); - -test('render', () => { - const component = shallowWithIntl( - - ); - expect(component).toMatchSnapshot(); // eslint-disable-line - expect(getServices().getBasePath).toHaveBeenCalledTimes(1); -}); - -test('mlEnabled', () => { - const component = shallowWithIntl( - - ); - expect(component).toMatchSnapshot(); // eslint-disable-line - expect(getServices().getBasePath).toHaveBeenCalledTimes(1); -}); - -test('apmUiEnabled', () => { - const component = shallowWithIntl( - - ); - expect(component).toMatchSnapshot(); // eslint-disable-line - expect(getServices().getBasePath).toHaveBeenCalledTimes(1); -}); - -test('isNewKibanaInstance', () => { - const component = shallowWithIntl( - - ); - expect(component).toMatchSnapshot(); // eslint-disable-line - expect(getServices().getBasePath).toHaveBeenCalledTimes(1); -}); diff --git a/src/plugins/home/public/application/components/add_data/__snapshots__/add_data.test.tsx.snap b/src/plugins/home/public/application/components/add_data/__snapshots__/add_data.test.tsx.snap new file mode 100644 index 00000000000000..787802e508ca7b --- /dev/null +++ b/src/plugins/home/public/application/components/add_data/__snapshots__/add_data.test.tsx.snap @@ -0,0 +1,96 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`AddData render 1`] = ` +
+ + + +

+ +

+
+
+ + + + + +
+ + + + + + + + + + + + +
+`; diff --git a/src/plugins/home/public/application/components/add_data/add_data.test.tsx b/src/plugins/home/public/application/components/add_data/add_data.test.tsx new file mode 100644 index 00000000000000..e76e8348022844 --- /dev/null +++ b/src/plugins/home/public/application/components/add_data/add_data.test.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. + */ + +/* + * 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'; + +jest.mock('../app_navigation_handler', () => { + return { + createAppNavigationHandler: jest.fn(() => () => {}), + }; +}); + +beforeEach(() => { + jest.clearAllMocks(); +}); + +const addBasePathMock = jest.fn((path: string) => (path ? path : 'path')); + +const mockFeatures = [ + { + category: 'data', + description: 'Ingest data from popular apps and services.', + homePageSection: 'add_data', + icon: 'indexOpen', + id: 'home_tutorial_directory', + order: 500, + path: '/app/home#/tutorial_directory', + title: 'Ingest data', + }, + { + category: 'admin', + description: 'Add and manage your fleet of Elastic Agents and integrations.', + homePageSection: 'add_data', + icon: 'indexManagementApp', + id: 'ingestManager', + order: 510, + path: '/app/ingestManager', + title: 'Add Elastic Agent', + }, + { + category: 'data', + description: 'Import your own CSV, NDJSON, or log file', + homePageSection: 'add_data', + icon: 'document', + id: 'ml_file_data_visualizer', + order: 520, + path: '/app/ml#/filedatavisualizer', + title: 'Upload a file', + }, +]; + +describe('AddData', () => { + test('render', () => { + const component = shallowWithIntl( + + ); + expect(component).toMatchSnapshot(); + }); +}); diff --git a/src/plugins/home/public/application/components/add_data/add_data.tsx b/src/plugins/home/public/application/components/add_data/add_data.tsx new file mode 100644 index 00000000000000..82f0020b1b3895 --- /dev/null +++ b/src/plugins/home/public/application/components/add_data/add_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 { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiTitle } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +// @ts-expect-error untyped service +import { FeatureCatalogueEntry } from '../../services'; +import { createAppNavigationHandler } from '../app_navigation_handler'; +// @ts-expect-error untyped component +import { Synopsis } from '../synopsis'; + +interface Props { + addBasePath: (path: string) => string; + features: FeatureCatalogueEntry[]; +} + +export const AddData: FC = ({ addBasePath, features }) => ( +
+ + + +

+ +

+
+
+ + + + + + +
+ + + + + {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/add_data/index.ts b/src/plugins/home/public/application/components/add_data/index.ts new file mode 100644 index 00000000000000..a7d465d1776366 --- /dev/null +++ b/src/plugins/home/public/application/components/add_data/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 './add_data'; diff --git a/src/plugins/home/public/application/components/app_navigation_handler.ts b/src/plugins/home/public/application/components/app_navigation_handler.ts index 6e78af7f42f52b..61d85c033b5448 100644 --- a/src/plugins/home/public/application/components/app_navigation_handler.ts +++ b/src/plugins/home/public/application/components/app_navigation_handler.ts @@ -17,6 +17,7 @@ * under the License. */ +import { MouseEvent } from 'react'; import { getServices } from '../kibana_services'; export const createAppNavigationHandler = (targetUrl: string) => (event: MouseEvent) => { diff --git a/src/plugins/home/public/application/components/feature_directory.js b/src/plugins/home/public/application/components/feature_directory.js index e9ab348f164c72..36ececcdfd8df5 100644 --- a/src/plugins/home/public/application/components/feature_directory.js +++ b/src/plugins/home/public/application/components/feature_directory.js @@ -115,6 +115,7 @@ export class FeatureDirectory extends React.Component { return ( { - const { addBasePath, directories } = this.props; - return directories - .filter((directory) => { - return directory.showOnHomePage && directory.category === category; - }) - .map((directory) => { - return ( - - - - ); - }); - }; + findDirectoryById = (id) => this.props.directories.find((directory) => directory.id === id); + + getFeaturesByCategory = (category) => + this.props.directories + .filter((directory) => directory.showOnHomePage && directory.category === category) + .sort((directoryA, directoryB) => directoryA.order - directoryB.order); renderNormal() { - const { apmUiEnabled, mlEnabled } = this.props; + const { addBasePath, solutions } = 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); + + // Show card for console if none of the manage data plugins are available, most likely in OSS + if (manageDataFeatures.length < 1 && devTools) { + manageDataFeatures.push(devTools); + } return ( - - - -

- -

-
- - - - - - - - - -

- -

+
+
+
+ + + +

+ +

- - - {this.renderDirectories(FeatureCatalogueCategory.DATA)} - - +
+ + + + + + {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 && } + + + + + - - -

- -

-
- - - {this.renderDirectories(FeatureCatalogueCategory.ADMIN)} - -
+
- +
+
); } @@ -260,13 +296,23 @@ Home.propTypes = { path: PropTypes.string.isRequired, showOnHomePage: PropTypes.bool.isRequired, category: PropTypes.string.isRequired, + order: PropTypes.number, + }) + ), + solutions: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.string.isRequired, + title: PropTypes.string.isRequired, + subtitle: PropTypes.string.isRequired, + descriptions: PropTypes.arrayOf(PropTypes.string).isRequired, + icon: PropTypes.string.isRequired, + path: PropTypes.string.isRequired, + order: PropTypes.number, }) ), - apmUiEnabled: PropTypes.bool.isRequired, find: PropTypes.func.isRequired, localStorage: PropTypes.object.isRequired, urlBasePath: PropTypes.string.isRequired, - mlEnabled: PropTypes.bool.isRequired, telemetry: PropTypes.shape({ telemetryService: PropTypes.any, telemetryNotifications: PropTypes.any, diff --git a/src/plugins/home/public/application/components/home.test.js b/src/plugins/home/public/application/components/home.test.js index 3bcfce513cb125..0d7596d92a5a14 100644 --- a/src/plugins/home/public/application/components/home.test.js +++ b/src/plugins/home/public/application/components/home.test.js @@ -41,6 +41,7 @@ describe('home', () => { beforeEach(() => { defaultProps = { directories: [], + solutions: [], apmUiEnabled: true, mlEnabled: true, kibanaVersion: '99.2.1', @@ -92,8 +93,96 @@ describe('home', () => { expect(component).toMatchSnapshot(); }); + describe('header', () => { + test('render', async () => { + const component = await renderHome(); + expect(component).toMatchSnapshot(); + }); + + test('should show "Manage" link if stack management is available', async () => { + const directoryEntry = { + id: 'stack-management', + title: 'Management', + description: 'Your center console for managing the Elastic Stack.', + icon: 'managementApp', + path: 'management_landing_page', + category: FeatureCatalogueCategory.ADMIN, + showOnHomePage: false, + }; + + const component = await renderHome({ + directories: [directoryEntry], + }); + + expect(component).toMatchSnapshot(); + }); + + test('should show "Dev tools" link if console is available', async () => { + const directoryEntry = { + id: 'console', + title: 'Console', + description: 'Skip cURL and use a JSON interface to work with your data in Console.', + icon: 'consoleApp', + path: 'path-to-dev-tools', + category: FeatureCatalogueCategory.ADMIN, + showOnHomePage: false, + }; + + const component = await renderHome({ + directories: [directoryEntry], + }); + + expect(component).toMatchSnapshot(); + }); + }); + describe('directories', () => { - test('should render DATA directory entry in "Explore Data" panel', async () => { + test('should render solutions in the "solution section"', async () => { + const solutionEntry1 = { + id: 'kibana', + title: 'Kibana', + subtitle: 'Visualize & analyze', + descriptions: ['Analyze data in dashboards'], + icon: 'logoKibana', + path: 'kibana_landing_page', + order: 1, + }; + const solutionEntry2 = { + id: 'solution-2', + title: 'Solution two', + subtitle: 'Subtitle for solution two', + descriptions: ['Example use case'], + icon: 'empty', + path: 'path-to-solution-two', + order: 2, + }; + const solutionEntry3 = { + id: 'solution-3', + title: 'Solution three', + subtitle: 'Subtitle for solution three', + descriptions: ['Example use case'], + icon: 'empty', + path: 'path-to-solution-three', + order: 3, + }; + const solutionEntry4 = { + id: 'solution-4', + title: 'Solution four', + subtitle: 'Subtitle for solution four', + descriptions: ['Example use case'], + icon: 'empty', + path: 'path-to-solution-four', + order: 4, + }; + + const component = await renderHome({ + solutions: [solutionEntry1, solutionEntry2, solutionEntry3, solutionEntry4], + }); + + expect(component).toMatchSnapshot(); + }); + + test('should render DATA directory entry in "Ingest your data" panel', async () => { const directoryEntry = { id: 'dashboard', title: 'Dashboard', @@ -111,7 +200,7 @@ describe('home', () => { expect(component).toMatchSnapshot(); }); - test('should render ADMIN directory entry in "Manage" panel', async () => { + test('should render ADMIN directory entry in "Manage your data" panel', async () => { const directoryEntry = { id: 'index_patterns', title: 'Index Patterns', @@ -148,6 +237,26 @@ describe('home', () => { }); }); + describe('change home route', () => { + test('should render a link to change the default route in advanced settings if advanced settings is enabled', async () => { + const component = await renderHome({ + directories: [ + { + description: 'Change your settings', + icon: 'gear', + id: 'advanced_settings', + path: 'path-to-advanced_settings', + showOnHomePage: false, + title: 'Advanced settings', + category: FeatureCatalogueCategory.ADMIN, + }, + ], + }); + + expect(component).toMatchSnapshot(); + }); + }); + describe('welcome', () => { test('should show the welcome screen if enabled, and there are no index patterns defined', async () => { defaultProps.localStorage.getItem = sinon.spy(() => 'true'); diff --git a/src/plugins/home/public/application/components/home_app.js b/src/plugins/home/public/application/components/home_app.js index 648915b6dae0c5..90e549c873436c 100644 --- a/src/plugins/home/public/application/components/home_app.js +++ b/src/plugins/home/public/application/components/home_app.js @@ -38,7 +38,7 @@ const RedirectToDefaultApp = () => { return null; }; -export function HomeApp({ directories }) { +export function HomeApp({ directories, solutions }) { const { savedObjectsClient, getBasePath, @@ -48,8 +48,6 @@ export function HomeApp({ directories }) { } = getServices(); const environment = environmentService.getEnvironment(); const isCloudEnabled = environment.cloud; - const mlEnabled = environment.ml; - const apmUiEnabled = environment.apmUi; const renderTutorialDirectory = (props) => { return ( @@ -87,8 +85,7 @@ export function HomeApp({ directories }) { +