[Page layouts] Some light fixes (#103197)

* [Solution Toolbar] Fixing button border on non-text color versions

* [Alerts] Removed extra wrappers and use EuiPageHeader

* [Logstash] Basic conversion to template

* [Reporting] Adding bottomBorder to page header

* [ML] Fix display of main navigation tabs

* [Stack Management] Fix side nav not updating when going back to landing page

* [Tags] Add spacing after page header

* [License Management] Full width on file uploader

* [Page Template] Fixed `emptyState` default template for pages with side nav

* [Infra] Removing some page header displays in empty states

* [Enterprise Search] Fix some error layouts

* [Index Patterns] Quick fix for empty state

* snaps

* [Page Template] Remove forced padding when `centeredBody`

* small hack for tab padding for ml

* scroll ML page to fix test

* fix test method type signature

Co-authored-by: Dave Snider <dave.snider@gmail.com>
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Michail Yasonik <michail.yasonik@elastic.co>
This commit is contained in:
Caroline Horn 2021-06-29 20:50:15 -04:00 committed by GitHub
parent 37e2d8a6c5
commit 7d45fcf8ee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 2461 additions and 2653 deletions

View file

@ -120,11 +120,10 @@ exports[`EmptyState should render normally 1`] = `
<div
className="inpEmptyState__footer"
>
<EuiFlexGrid
columns={3}
>
<EuiFlexGroup>
<EuiFlexItem
className="inpEmptyState__footerFlexItem"
grow={1}
>
<EuiDescriptionList
listItems={
@ -153,6 +152,7 @@ exports[`EmptyState should render normally 1`] = `
</EuiFlexItem>
<EuiFlexItem
className="inpEmptyState__footerFlexItem"
grow={2}
>
<EuiDescriptionList
listItems={
@ -183,7 +183,7 @@ exports[`EmptyState should render normally 1`] = `
}
/>
</EuiFlexItem>
</EuiFlexGrid>
</EuiFlexGroup>
</div>
</EuiPageContentBody>
</EuiPageContent>

View file

@ -24,6 +24,7 @@ import {
EuiCard,
EuiLink,
EuiText,
EuiFlexGroup,
} from '@elastic/eui';
import { useHistory } from 'react-router-dom';
import { reactRouterNavigate } from '../../../../../../plugins/kibana_react/public';
@ -143,8 +144,8 @@ export const EmptyState = ({
</EuiFlexGrid>
<EuiSpacer size="xxl" />
<div className="inpEmptyState__footer">
<EuiFlexGrid columns={3}>
<EuiFlexItem className="inpEmptyState__footerFlexItem">
<EuiFlexGroup>
<EuiFlexItem grow={1} className="inpEmptyState__footerFlexItem">
<EuiDescriptionList
listItems={[
{
@ -166,7 +167,7 @@ export const EmptyState = ({
]}
/>
</EuiFlexItem>
<EuiFlexItem className="inpEmptyState__footerFlexItem">
<EuiFlexItem grow={2} className="inpEmptyState__footerFlexItem">
<EuiDescriptionList
listItems={[
{
@ -189,7 +190,7 @@ export const EmptyState = ({
]}
/>
</EuiFlexItem>
</EuiFlexGrid>
</EuiFlexGroup>
</div>
</EuiPageContentBody>
</EuiPageContent>

View file

@ -2,7 +2,6 @@
exports[`KibanaPageTemplate render basic template 1`] = `
<EuiPageTemplate
paddingSize="l"
pageHeader={
Object {
"description": "test",
@ -25,7 +24,6 @@ exports[`KibanaPageTemplate render basic template 1`] = `
exports[`KibanaPageTemplate render custom empty prompt only 1`] = `
<EuiPageTemplate
paddingSize="none"
pageSideBarProps={
Object {
"className": "kbnPageTemplate__pageSideBar",
@ -47,7 +45,6 @@ exports[`KibanaPageTemplate render custom empty prompt only 1`] = `
exports[`KibanaPageTemplate render custom empty prompt with page header 1`] = `
<EuiPageTemplate
paddingSize="l"
pageHeader={
Object {
"description": "test",
@ -79,7 +76,6 @@ exports[`KibanaPageTemplate render custom empty prompt with page header 1`] = `
exports[`KibanaPageTemplate render default empty prompt 1`] = `
<EuiPageTemplate
paddingSize="none"
pageSideBarProps={
Object {
"className": "kbnPageTemplate__pageSideBar",
@ -108,7 +104,6 @@ exports[`KibanaPageTemplate render default empty prompt 1`] = `
exports[`KibanaPageTemplate render solutionNav 1`] = `
<EuiPageTemplate
paddingSize="l"
pageHeader={
Object {
"description": "test",

View file

@ -85,11 +85,13 @@ export const KibanaPageTemplate: FunctionComponent<KibanaPageTemplateProps> = ({
);
}
const emptyStateDefaultTemplate = pageSideBar ? 'centeredContent' : 'centeredBody';
/**
* An easy way to create the right content for empty pages
*/
if (isEmptyState && pageHeader && !children) {
template = template ?? 'centeredBody';
template = template ?? emptyStateDefaultTemplate;
const { iconType, pageTitle, description, rightSideItems } = pageHeader;
pageHeader = undefined;
children = (
@ -104,14 +106,13 @@ export const KibanaPageTemplate: FunctionComponent<KibanaPageTemplateProps> = ({
} else if (isEmptyState && pageHeader && children) {
template = template ?? 'centeredContent';
} else if (isEmptyState && !pageHeader) {
template = template ?? 'centeredBody';
template = template ?? emptyStateDefaultTemplate;
}
return (
<EuiPageTemplate
template={template}
restrictWidth={restrictWidth}
paddingSize={template === 'centeredBody' ? 'none' : 'l'}
pageHeader={pageHeader}
pageSideBar={pageSideBar}
pageSideBarProps={{

View file

@ -6,18 +6,27 @@
* Side Public License, v 1.
*/
import React from 'react';
import React, { useEffect } from 'react';
import { FormattedMessage } from '@kbn/i18n/react';
import { EuiEmptyPrompt, EuiHorizontalRule, EuiPageContent } from '@elastic/eui';
interface ManagementLandingPageProps {
version: string;
onAppMounted: (id: string) => void;
setBreadcrumbs: () => void;
}
export const ManagementLandingPage = ({ version, setBreadcrumbs }: ManagementLandingPageProps) => {
export const ManagementLandingPage = ({
version,
setBreadcrumbs,
onAppMounted,
}: ManagementLandingPageProps) => {
setBreadcrumbs();
useEffect(() => {
onAppMounted('');
}, [onAppMounted]);
return (
<EuiPageContent verticalPosition="center" horizontalPosition="center" color="subdued">
<EuiEmptyPrompt

View file

@ -49,6 +49,7 @@ export const ManagementRouter = memo(
<ManagementLandingPage
version={dependencies.kibanaVersion}
setBreadcrumbs={setBreadcrumbs}
onAppMounted={onAppMounted}
/>
)}
/>

View file

@ -6,7 +6,9 @@
border-color: $euiBorderColor !important; // sass-lint:disable-line no-important
@include kbnThemeStyle('v8') {
border-width: $euiBorderWidthThin;
border-style: solid;
&[class*='--text'] {
border-width: $euiBorderWidthThin;
border-style: solid;
}
}
}

View file

@ -312,9 +312,12 @@ export class TestSubjects extends FtrService {
return testSubjSelector(selector);
}
public async scrollIntoView(selector: string) {
public async scrollIntoView(
selector: string,
offset?: number | { topOffset?: number; bottomOffset?: number }
) {
const element = await this.find(selector);
await element.scrollIntoViewIfNecessary();
await element.scrollIntoViewIfNecessary(offset);
}
// isChecked always returns false when run on an euiSwitch, because they use the aria-checked attribute

View file

@ -7,7 +7,7 @@
import React from 'react';
import { EuiPage, EuiPageContent } from '@elastic/eui';
import { KibanaPageTemplate } from '../../../../../../../../src/plugins/kibana_react/public';
import { ErrorStatePrompt } from '../../../shared/error_state';
import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
@ -19,11 +19,9 @@ export const ErrorConnecting: React.FC = () => {
<SetPageChrome />
<SendTelemetry action="error" metric="cannot_connect" />
<EuiPage restrictWidth>
<EuiPageContent hasBorder>
<ErrorStatePrompt />
</EuiPageContent>
</EuiPage>
<KibanaPageTemplate isEmptyState>
<ErrorStatePrompt />
</KibanaPageTemplate>
</>
);
};

View file

@ -7,16 +7,15 @@
import React from 'react';
import { EuiPage, EuiPageContent } from '@elastic/eui';
import { KibanaPageTemplate } from '../../../../../../../../src/plugins/kibana_react/public';
import { ErrorStatePrompt } from '../../../shared/error_state';
import { SendEnterpriseSearchTelemetry as SendTelemetry } from '../../../shared/telemetry';
export const ErrorConnecting: React.FC = () => (
<EuiPage restrictWidth>
<KibanaPageTemplate isEmptyState>
<SendTelemetry action="error" metric="cannot_connect" />
<EuiPageContent>
<ErrorStatePrompt />
</EuiPageContent>
</EuiPage>
<ErrorStatePrompt />
</KibanaPageTemplate>
);

View file

@ -9,7 +9,7 @@
import React from 'react';
import { EuiPage, EuiPageBody, EuiPageContent } from '@elastic/eui';
import { KibanaPageTemplate } from '../../../../../../../../src/plugins/kibana_react/public';
import { WORKPLACE_SEARCH_PLUGIN } from '../../../../../common/constants';
import { ErrorStatePrompt } from '../../../shared/error_state';
@ -19,16 +19,14 @@ import { ViewContentHeader } from '../../components/shared/view_content_header';
export const ErrorState: React.FC = () => {
return (
<EuiPage restrictWidth>
<>
<SetPageChrome />
<SendTelemetry action="error" metric="cannot_connect" />
<EuiPageBody>
<KibanaPageTemplate isEmptyState>
<ViewContentHeader title={WORKPLACE_SEARCH_PLUGIN.NAME} />
<EuiPageContent>
<ErrorStatePrompt />
</EuiPageContent>
</EuiPageBody>
</EuiPage>
<ErrorStatePrompt />
</KibanaPageTemplate>
</>
);
};

View file

@ -116,9 +116,13 @@ const CategoriesPageTemplate: React.FC<LazyObservabilityPageTemplateProps> = ({
return (
<LogsPageTemplate
data-test-subj="logsLogEntryCategoriesPage"
pageHeader={{
pageTitle: logCategoriesTitle,
}}
pageHeader={
rest.isEmptyState
? undefined
: {
pageTitle: logCategoriesTitle,
}
}
{...rest}
>
{children}

View file

@ -158,9 +158,13 @@ const AnomaliesPageTemplate: React.FC<LazyObservabilityPageTemplateProps> = ({
return (
<LogsPageTemplate
data-test-subj="logsLogEntryRatePage"
pageHeader={{
pageTitle: anomaliesTitle,
}}
pageHeader={
rest.isEmptyState
? undefined
: {
pageTitle: anomaliesTitle,
}
}
{...rest}
>
{children}

View file

@ -703,106 +703,85 @@ exports[`UploadLicense should display a modal when license requires acknowledgem
<div
className="euiForm"
>
<EuiFlexGroup
justifyContent="center"
<EuiFilePicker
compressed={false}
display="large"
fullWidth={true}
id="licenseFile"
initialPromptText={
<FormattedMessage
defaultMessage="Select or drag your license file"
id="xpack.licenseMgmt.uploadLicense.selectLicenseFileDescription"
values={Object {}}
/>
}
onChange={[Function]}
>
<div
className="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--justifyContentCenter euiFlexGroup--directionRow euiFlexGroup--responsive"
<EuiI18n
defaults={
Array [
"Clear selected files",
"files selected",
]
}
tokens={
Array [
"euiFilePicker.clearSelectedFiles",
"euiFilePicker.filesSelected",
]
}
>
<EuiFlexItem
grow={false}
<div
className="euiFilePicker euiFilePicker--large euiFilePicker--fullWidth"
>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
className="euiFilePicker__wrap"
>
<EuiText>
<div
className="euiText euiText--medium"
<EuiValidatableControl>
<input
aria-describedby="licenseFile-filePicker__prompt"
className="euiFilePicker__input"
id="licenseFile"
onChange={[Function]}
onDragLeave={[Function]}
onDragOver={[Function]}
onDrop={[Function]}
type="file"
/>
</EuiValidatableControl>
<div
className="euiFilePicker__prompt"
id="licenseFile-filePicker__prompt"
>
<EuiIcon
aria-hidden="true"
className="euiFilePicker__icon"
size="l"
type="importAction"
>
<EuiFilePicker
compressed={false}
display="large"
id="licenseFile"
initialPromptText={
<FormattedMessage
defaultMessage="Select or drag your license file"
id="xpack.licenseMgmt.uploadLicense.selectLicenseFileDescription"
values={Object {}}
/>
}
onChange={[Function]}
<span
aria-hidden="true"
className="euiFilePicker__icon"
data-euiicon-type="importAction"
size="l"
/>
</EuiIcon>
<div
className="euiFilePicker__promptText"
>
<FormattedMessage
defaultMessage="Select or drag your license file"
id="xpack.licenseMgmt.uploadLicense.selectLicenseFileDescription"
values={Object {}}
>
<EuiI18n
defaults={
Array [
"Clear selected files",
"files selected",
]
}
tokens={
Array [
"euiFilePicker.clearSelectedFiles",
"euiFilePicker.filesSelected",
]
}
>
<div
className="euiFilePicker euiFilePicker--large"
>
<div
className="euiFilePicker__wrap"
>
<EuiValidatableControl>
<input
aria-describedby="licenseFile-filePicker__prompt"
className="euiFilePicker__input"
id="licenseFile"
onChange={[Function]}
onDragLeave={[Function]}
onDragOver={[Function]}
onDrop={[Function]}
type="file"
/>
</EuiValidatableControl>
<div
className="euiFilePicker__prompt"
id="licenseFile-filePicker__prompt"
>
<EuiIcon
aria-hidden="true"
className="euiFilePicker__icon"
size="l"
type="importAction"
>
<span
aria-hidden="true"
className="euiFilePicker__icon"
data-euiicon-type="importAction"
size="l"
/>
</EuiIcon>
<div
className="euiFilePicker__promptText"
>
<FormattedMessage
defaultMessage="Select or drag your license file"
id="xpack.licenseMgmt.uploadLicense.selectLicenseFileDescription"
values={Object {}}
>
Select or drag your license file
</FormattedMessage>
</div>
</div>
</div>
</div>
</EuiI18n>
</EuiFilePicker>
Select or drag your license file
</FormattedMessage>
</div>
</EuiText>
</div>
</div>
</EuiFlexItem>
</div>
</EuiFlexGroup>
</div>
</EuiI18n>
</EuiFilePicker>
<EuiSpacer
size="m"
>
@ -1445,106 +1424,85 @@ exports[`UploadLicense should display an error when ES says license is expired 1
</div>
</EuiCallOut>
</EuiI18n>
<EuiFlexGroup
justifyContent="center"
<EuiFilePicker
compressed={false}
display="large"
fullWidth={true}
id="licenseFile"
initialPromptText={
<FormattedMessage
defaultMessage="Select or drag your license file"
id="xpack.licenseMgmt.uploadLicense.selectLicenseFileDescription"
values={Object {}}
/>
}
onChange={[Function]}
>
<div
className="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--justifyContentCenter euiFlexGroup--directionRow euiFlexGroup--responsive"
<EuiI18n
defaults={
Array [
"Clear selected files",
"files selected",
]
}
tokens={
Array [
"euiFilePicker.clearSelectedFiles",
"euiFilePicker.filesSelected",
]
}
>
<EuiFlexItem
grow={false}
<div
className="euiFilePicker euiFilePicker--large euiFilePicker--fullWidth"
>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
className="euiFilePicker__wrap"
>
<EuiText>
<div
className="euiText euiText--medium"
<EuiValidatableControl>
<input
aria-describedby="licenseFile-filePicker__prompt"
className="euiFilePicker__input"
id="licenseFile"
onChange={[Function]}
onDragLeave={[Function]}
onDragOver={[Function]}
onDrop={[Function]}
type="file"
/>
</EuiValidatableControl>
<div
className="euiFilePicker__prompt"
id="licenseFile-filePicker__prompt"
>
<EuiIcon
aria-hidden="true"
className="euiFilePicker__icon"
size="l"
type="importAction"
>
<EuiFilePicker
compressed={false}
display="large"
id="licenseFile"
initialPromptText={
<FormattedMessage
defaultMessage="Select or drag your license file"
id="xpack.licenseMgmt.uploadLicense.selectLicenseFileDescription"
values={Object {}}
/>
}
onChange={[Function]}
<span
aria-hidden="true"
className="euiFilePicker__icon"
data-euiicon-type="importAction"
size="l"
/>
</EuiIcon>
<div
className="euiFilePicker__promptText"
>
<FormattedMessage
defaultMessage="Select or drag your license file"
id="xpack.licenseMgmt.uploadLicense.selectLicenseFileDescription"
values={Object {}}
>
<EuiI18n
defaults={
Array [
"Clear selected files",
"files selected",
]
}
tokens={
Array [
"euiFilePicker.clearSelectedFiles",
"euiFilePicker.filesSelected",
]
}
>
<div
className="euiFilePicker euiFilePicker--large"
>
<div
className="euiFilePicker__wrap"
>
<EuiValidatableControl>
<input
aria-describedby="licenseFile-filePicker__prompt"
className="euiFilePicker__input"
id="licenseFile"
onChange={[Function]}
onDragLeave={[Function]}
onDragOver={[Function]}
onDrop={[Function]}
type="file"
/>
</EuiValidatableControl>
<div
className="euiFilePicker__prompt"
id="licenseFile-filePicker__prompt"
>
<EuiIcon
aria-hidden="true"
className="euiFilePicker__icon"
size="l"
type="importAction"
>
<span
aria-hidden="true"
className="euiFilePicker__icon"
data-euiicon-type="importAction"
size="l"
/>
</EuiIcon>
<div
className="euiFilePicker__promptText"
>
<FormattedMessage
defaultMessage="Select or drag your license file"
id="xpack.licenseMgmt.uploadLicense.selectLicenseFileDescription"
values={Object {}}
>
Select or drag your license file
</FormattedMessage>
</div>
</div>
</div>
</div>
</EuiI18n>
</EuiFilePicker>
Select or drag your license file
</FormattedMessage>
</div>
</EuiText>
</div>
</div>
</EuiFlexItem>
</div>
</EuiFlexGroup>
</div>
</EuiI18n>
</EuiFilePicker>
<EuiSpacer
size="m"
>
@ -2187,106 +2145,85 @@ exports[`UploadLicense should display an error when ES says license is invalid 1
</div>
</EuiCallOut>
</EuiI18n>
<EuiFlexGroup
justifyContent="center"
<EuiFilePicker
compressed={false}
display="large"
fullWidth={true}
id="licenseFile"
initialPromptText={
<FormattedMessage
defaultMessage="Select or drag your license file"
id="xpack.licenseMgmt.uploadLicense.selectLicenseFileDescription"
values={Object {}}
/>
}
onChange={[Function]}
>
<div
className="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--justifyContentCenter euiFlexGroup--directionRow euiFlexGroup--responsive"
<EuiI18n
defaults={
Array [
"Clear selected files",
"files selected",
]
}
tokens={
Array [
"euiFilePicker.clearSelectedFiles",
"euiFilePicker.filesSelected",
]
}
>
<EuiFlexItem
grow={false}
<div
className="euiFilePicker euiFilePicker--large euiFilePicker--fullWidth"
>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
className="euiFilePicker__wrap"
>
<EuiText>
<div
className="euiText euiText--medium"
<EuiValidatableControl>
<input
aria-describedby="licenseFile-filePicker__prompt"
className="euiFilePicker__input"
id="licenseFile"
onChange={[Function]}
onDragLeave={[Function]}
onDragOver={[Function]}
onDrop={[Function]}
type="file"
/>
</EuiValidatableControl>
<div
className="euiFilePicker__prompt"
id="licenseFile-filePicker__prompt"
>
<EuiIcon
aria-hidden="true"
className="euiFilePicker__icon"
size="l"
type="importAction"
>
<EuiFilePicker
compressed={false}
display="large"
id="licenseFile"
initialPromptText={
<FormattedMessage
defaultMessage="Select or drag your license file"
id="xpack.licenseMgmt.uploadLicense.selectLicenseFileDescription"
values={Object {}}
/>
}
onChange={[Function]}
<span
aria-hidden="true"
className="euiFilePicker__icon"
data-euiicon-type="importAction"
size="l"
/>
</EuiIcon>
<div
className="euiFilePicker__promptText"
>
<FormattedMessage
defaultMessage="Select or drag your license file"
id="xpack.licenseMgmt.uploadLicense.selectLicenseFileDescription"
values={Object {}}
>
<EuiI18n
defaults={
Array [
"Clear selected files",
"files selected",
]
}
tokens={
Array [
"euiFilePicker.clearSelectedFiles",
"euiFilePicker.filesSelected",
]
}
>
<div
className="euiFilePicker euiFilePicker--large"
>
<div
className="euiFilePicker__wrap"
>
<EuiValidatableControl>
<input
aria-describedby="licenseFile-filePicker__prompt"
className="euiFilePicker__input"
id="licenseFile"
onChange={[Function]}
onDragLeave={[Function]}
onDragOver={[Function]}
onDrop={[Function]}
type="file"
/>
</EuiValidatableControl>
<div
className="euiFilePicker__prompt"
id="licenseFile-filePicker__prompt"
>
<EuiIcon
aria-hidden="true"
className="euiFilePicker__icon"
size="l"
type="importAction"
>
<span
aria-hidden="true"
className="euiFilePicker__icon"
data-euiicon-type="importAction"
size="l"
/>
</EuiIcon>
<div
className="euiFilePicker__promptText"
>
<FormattedMessage
defaultMessage="Select or drag your license file"
id="xpack.licenseMgmt.uploadLicense.selectLicenseFileDescription"
values={Object {}}
>
Select or drag your license file
</FormattedMessage>
</div>
</div>
</div>
</div>
</EuiI18n>
</EuiFilePicker>
Select or drag your license file
</FormattedMessage>
</div>
</EuiText>
</div>
</div>
</EuiFlexItem>
</div>
</EuiFlexGroup>
</div>
</EuiI18n>
</EuiFilePicker>
<EuiSpacer
size="m"
>
@ -2929,106 +2866,85 @@ exports[`UploadLicense should display an error when submitting invalid JSON 1`]
</div>
</EuiCallOut>
</EuiI18n>
<EuiFlexGroup
justifyContent="center"
<EuiFilePicker
compressed={false}
display="large"
fullWidth={true}
id="licenseFile"
initialPromptText={
<FormattedMessage
defaultMessage="Select or drag your license file"
id="xpack.licenseMgmt.uploadLicense.selectLicenseFileDescription"
values={Object {}}
/>
}
onChange={[Function]}
>
<div
className="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--justifyContentCenter euiFlexGroup--directionRow euiFlexGroup--responsive"
<EuiI18n
defaults={
Array [
"Clear selected files",
"files selected",
]
}
tokens={
Array [
"euiFilePicker.clearSelectedFiles",
"euiFilePicker.filesSelected",
]
}
>
<EuiFlexItem
grow={false}
<div
className="euiFilePicker euiFilePicker--large euiFilePicker--fullWidth"
>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
className="euiFilePicker__wrap"
>
<EuiText>
<div
className="euiText euiText--medium"
<EuiValidatableControl>
<input
aria-describedby="licenseFile-filePicker__prompt"
className="euiFilePicker__input"
id="licenseFile"
onChange={[Function]}
onDragLeave={[Function]}
onDragOver={[Function]}
onDrop={[Function]}
type="file"
/>
</EuiValidatableControl>
<div
className="euiFilePicker__prompt"
id="licenseFile-filePicker__prompt"
>
<EuiIcon
aria-hidden="true"
className="euiFilePicker__icon"
size="l"
type="importAction"
>
<EuiFilePicker
compressed={false}
display="large"
id="licenseFile"
initialPromptText={
<FormattedMessage
defaultMessage="Select or drag your license file"
id="xpack.licenseMgmt.uploadLicense.selectLicenseFileDescription"
values={Object {}}
/>
}
onChange={[Function]}
<span
aria-hidden="true"
className="euiFilePicker__icon"
data-euiicon-type="importAction"
size="l"
/>
</EuiIcon>
<div
className="euiFilePicker__promptText"
>
<FormattedMessage
defaultMessage="Select or drag your license file"
id="xpack.licenseMgmt.uploadLicense.selectLicenseFileDescription"
values={Object {}}
>
<EuiI18n
defaults={
Array [
"Clear selected files",
"files selected",
]
}
tokens={
Array [
"euiFilePicker.clearSelectedFiles",
"euiFilePicker.filesSelected",
]
}
>
<div
className="euiFilePicker euiFilePicker--large"
>
<div
className="euiFilePicker__wrap"
>
<EuiValidatableControl>
<input
aria-describedby="licenseFile-filePicker__prompt"
className="euiFilePicker__input"
id="licenseFile"
onChange={[Function]}
onDragLeave={[Function]}
onDragOver={[Function]}
onDrop={[Function]}
type="file"
/>
</EuiValidatableControl>
<div
className="euiFilePicker__prompt"
id="licenseFile-filePicker__prompt"
>
<EuiIcon
aria-hidden="true"
className="euiFilePicker__icon"
size="l"
type="importAction"
>
<span
aria-hidden="true"
className="euiFilePicker__icon"
data-euiicon-type="importAction"
size="l"
/>
</EuiIcon>
<div
className="euiFilePicker__promptText"
>
<FormattedMessage
defaultMessage="Select or drag your license file"
id="xpack.licenseMgmt.uploadLicense.selectLicenseFileDescription"
values={Object {}}
>
Select or drag your license file
</FormattedMessage>
</div>
</div>
</div>
</div>
</EuiI18n>
</EuiFilePicker>
Select or drag your license file
</FormattedMessage>
</div>
</EuiText>
</div>
</div>
</EuiFlexItem>
</div>
</EuiFlexGroup>
</div>
</EuiI18n>
</EuiFilePicker>
<EuiSpacer
size="m"
>
@ -3671,106 +3587,85 @@ exports[`UploadLicense should display error when ES returns error 1`] = `
</div>
</EuiCallOut>
</EuiI18n>
<EuiFlexGroup
justifyContent="center"
<EuiFilePicker
compressed={false}
display="large"
fullWidth={true}
id="licenseFile"
initialPromptText={
<FormattedMessage
defaultMessage="Select or drag your license file"
id="xpack.licenseMgmt.uploadLicense.selectLicenseFileDescription"
values={Object {}}
/>
}
onChange={[Function]}
>
<div
className="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--justifyContentCenter euiFlexGroup--directionRow euiFlexGroup--responsive"
<EuiI18n
defaults={
Array [
"Clear selected files",
"files selected",
]
}
tokens={
Array [
"euiFilePicker.clearSelectedFiles",
"euiFilePicker.filesSelected",
]
}
>
<EuiFlexItem
grow={false}
<div
className="euiFilePicker euiFilePicker--large euiFilePicker--fullWidth"
>
<div
className="euiFlexItem euiFlexItem--flexGrowZero"
className="euiFilePicker__wrap"
>
<EuiText>
<div
className="euiText euiText--medium"
<EuiValidatableControl>
<input
aria-describedby="licenseFile-filePicker__prompt"
className="euiFilePicker__input"
id="licenseFile"
onChange={[Function]}
onDragLeave={[Function]}
onDragOver={[Function]}
onDrop={[Function]}
type="file"
/>
</EuiValidatableControl>
<div
className="euiFilePicker__prompt"
id="licenseFile-filePicker__prompt"
>
<EuiIcon
aria-hidden="true"
className="euiFilePicker__icon"
size="l"
type="importAction"
>
<EuiFilePicker
compressed={false}
display="large"
id="licenseFile"
initialPromptText={
<FormattedMessage
defaultMessage="Select or drag your license file"
id="xpack.licenseMgmt.uploadLicense.selectLicenseFileDescription"
values={Object {}}
/>
}
onChange={[Function]}
<span
aria-hidden="true"
className="euiFilePicker__icon"
data-euiicon-type="importAction"
size="l"
/>
</EuiIcon>
<div
className="euiFilePicker__promptText"
>
<FormattedMessage
defaultMessage="Select or drag your license file"
id="xpack.licenseMgmt.uploadLicense.selectLicenseFileDescription"
values={Object {}}
>
<EuiI18n
defaults={
Array [
"Clear selected files",
"files selected",
]
}
tokens={
Array [
"euiFilePicker.clearSelectedFiles",
"euiFilePicker.filesSelected",
]
}
>
<div
className="euiFilePicker euiFilePicker--large"
>
<div
className="euiFilePicker__wrap"
>
<EuiValidatableControl>
<input
aria-describedby="licenseFile-filePicker__prompt"
className="euiFilePicker__input"
id="licenseFile"
onChange={[Function]}
onDragLeave={[Function]}
onDragOver={[Function]}
onDrop={[Function]}
type="file"
/>
</EuiValidatableControl>
<div
className="euiFilePicker__prompt"
id="licenseFile-filePicker__prompt"
>
<EuiIcon
aria-hidden="true"
className="euiFilePicker__icon"
size="l"
type="importAction"
>
<span
aria-hidden="true"
className="euiFilePicker__icon"
data-euiicon-type="importAction"
size="l"
/>
</EuiIcon>
<div
className="euiFilePicker__promptText"
>
<FormattedMessage
defaultMessage="Select or drag your license file"
id="xpack.licenseMgmt.uploadLicense.selectLicenseFileDescription"
values={Object {}}
>
Select or drag your license file
</FormattedMessage>
</div>
</div>
</div>
</div>
</EuiI18n>
</EuiFilePicker>
Select or drag your license file
</FormattedMessage>
</div>
</EuiText>
</div>
</div>
</EuiFlexItem>
</div>
</EuiFlexGroup>
</div>
</EuiI18n>
</EuiFilePicker>
<EuiSpacer
size="m"
>

View file

@ -160,22 +160,18 @@ export class UploadLicense extends React.PureComponent {
</EuiText>
<EuiSpacer />
<EuiForm isInvalid={!!this.errorMessage()} error={this.errorMessage()}>
<EuiFlexGroup justifyContent="center">
<EuiFlexItem grow={false}>
<EuiText>
<EuiFilePicker
id="licenseFile"
initialPromptText={
<FormattedMessage
id="xpack.licenseMgmt.uploadLicense.selectLicenseFileDescription"
defaultMessage="Select or drag your license file"
/>
}
onChange={this.handleFile}
/>
</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
<EuiFilePicker
fullWidth
id="licenseFile"
initialPromptText={
<FormattedMessage
id="xpack.licenseMgmt.uploadLicense.selectLicenseFileDescription"
defaultMessage="Select or drag your license file"
/>
}
onChange={this.handleFile}
/>
<EuiSpacer size="m" />
{shouldShowTelemetryOptIn(telemetry) && (
<TelemetryOptIn

View file

@ -25,10 +25,10 @@ import {
EuiFieldText,
EuiForm,
EuiFormRow,
EuiPageContent,
EuiPageContentBody,
EuiSelect,
EuiSpacer,
EuiTitle,
EuiPageHeader,
} from '@elastic/eui';
import { ConfirmDeletePipelineModal } from './confirm_delete_pipeline_modal';
import { FlexItemSetting } from './flex_item_setting';
@ -269,219 +269,211 @@ class PipelineEditorUi extends React.Component {
const { intl } = this.props;
return (
<div data-test-subj={`pipelineEdit pipelineEdit-${this.state.pipeline.id}`}>
<EuiPageContent
style={{
width: 1100,
}}
verticalPosition="center"
horizontalPosition="center"
>
<EuiTitle size="m">
<h2>{this.getPipelineHeadingText()}</h2>
</EuiTitle>
<EuiSpacer size="m" />
<EuiForm isInvalid={this.state.showPipelineIdError} error={this.state.pipelineIdErrors}>
{this.props.isNewPipeline && (
<EuiFormRow
fullWidth
label={
<FormattedMessage
id="xpack.logstash.pipelineEditor.pipelineIdFormRowLabel"
defaultMessage="Pipeline ID"
/>
}
>
<EuiFieldText
fullWidth
data-test-subj="inputId"
isInvalid={this.state.showPipelineIdError}
name="pipelineId"
onBlur={this.onPipelineIdChange}
onChange={this.onPipelineIdChange}
value={this.state.pipeline.id || ''}
/>
</EuiFormRow>
)}
<EuiPageContentBody
style={{ width: '100%' }}
restrictWidth
data-test-subj={`pipelineEdit pipelineEdit-${this.state.pipeline.id}`}
>
<EuiPageHeader pageTitle={this.getPipelineHeadingText()} bottomBorder />
<EuiSpacer size="l" />
<EuiForm isInvalid={this.state.showPipelineIdError} error={this.state.pipelineIdErrors}>
{this.props.isNewPipeline && (
<EuiFormRow
fullWidth
label={
<FormattedMessage
id="xpack.logstash.pipelineEditor.descriptionFormRowLabel"
defaultMessage="Description"
id="xpack.logstash.pipelineEditor.pipelineIdFormRowLabel"
defaultMessage="Pipeline ID"
/>
}
>
<EuiFieldText
data-test-subj="inputDescription"
fullWidth
name="pipelineDescription"
onChange={this.onPipelineDescriptionChange}
value={this.state.pipeline.description || ''}
data-test-subj="inputId"
isInvalid={this.state.showPipelineIdError}
name="pipelineId"
onBlur={this.onPipelineIdChange}
onChange={this.onPipelineIdChange}
value={this.state.pipeline.id || ''}
/>
</EuiFormRow>
<EuiFormRow
)}
<EuiFormRow
fullWidth
label={
<FormattedMessage
id="xpack.logstash.pipelineEditor.descriptionFormRowLabel"
defaultMessage="Description"
/>
}
>
<EuiFieldText
data-test-subj="inputDescription"
fullWidth
label={
<FormattedMessage
id="xpack.logstash.pipelineEditor.pipelineFormRowLabel"
defaultMessage="Pipeline"
/>
}
>
<div data-test-subj="acePipeline">
<EuiCodeEditor
mode="plain_text"
onChange={this.onPipelineChange}
setOptions={{
minLines: 25,
maxLines: Infinity,
readOnly: this.props.licenseService.isReadOnly,
}}
theme="github"
value={this.state.pipeline.pipeline}
width={'1017'}
/>
</div>
</EuiFormRow>
<EuiFormRow
label={
<FormLabelWithIconTip
formRowLabelText={intl.formatMessage({
id: 'xpack.logstash.pipelineEditor.pipelineWorkersFormRowLabel',
defaultMessage: 'Pipeline workers',
})}
formRowTooltipText={TOOLTIPS.settings['pipeline.workers']}
/>
}
name="pipelineDescription"
onChange={this.onPipelineDescriptionChange}
value={this.state.pipeline.description || ''}
/>
</EuiFormRow>
<EuiFormRow
fullWidth
label={
<FormattedMessage
id="xpack.logstash.pipelineEditor.pipelineFormRowLabel"
defaultMessage="Pipeline"
/>
}
>
<div data-test-subj="acePipeline">
<EuiCodeEditor
mode="plain_text"
onChange={this.onPipelineChange}
setOptions={{
minLines: 25,
maxLines: Infinity,
readOnly: this.props.licenseService.isReadOnly,
}}
theme="github"
value={this.state.pipeline.pipeline}
width={'1017'}
/>
</div>
</EuiFormRow>
<EuiFormRow
label={
<FormLabelWithIconTip
formRowLabelText={intl.formatMessage({
id: 'xpack.logstash.pipelineEditor.pipelineWorkersFormRowLabel',
defaultMessage: 'Pipeline workers',
})}
formRowTooltipText={TOOLTIPS.settings['pipeline.workers']}
/>
}
>
<EuiFieldNumber
data-test-subj="inputWorkers"
onChange={(e) => this.handleNumberChange('pipeline.workers', e.target.value)}
value={this.state.pipeline.settings['pipeline.workers']}
/>
</EuiFormRow>
<EuiSpacer />
<EuiFlexGroup>
<FlexItemSetting
formRowLabelText={intl.formatMessage({
id: 'xpack.logstash.pipelineEditor.pipelineBatchSizeFormRowLabel',
defaultMessage: 'Pipeline batch size',
})}
formRowTooltipText={TOOLTIPS.settings['pipeline.batch.size']}
>
<EuiFieldNumber
data-test-subj="inputWorkers"
onChange={(e) => this.handleNumberChange('pipeline.workers', e.target.value)}
value={this.state.pipeline.settings['pipeline.workers']}
data-test-subj="inputBatchSize"
onChange={(e) => this.handleNumberChange('pipeline.batch.size', e.target.value)}
value={this.state.pipeline.settings['pipeline.batch.size']}
/>
</EuiFormRow>
<EuiSpacer />
<EuiFlexGroup>
<FlexItemSetting
formRowLabelText={intl.formatMessage({
id: 'xpack.logstash.pipelineEditor.pipelineBatchSizeFormRowLabel',
defaultMessage: 'Pipeline batch size',
})}
formRowTooltipText={TOOLTIPS.settings['pipeline.batch.size']}
>
<EuiFieldNumber
data-test-subj="inputBatchSize"
onChange={(e) => this.handleNumberChange('pipeline.batch.size', e.target.value)}
value={this.state.pipeline.settings['pipeline.batch.size']}
/>
</FlexItemSetting>
<FlexItemSetting
formRowLabelText={intl.formatMessage({
id: 'xpack.logstash.pipelineEditor.pipelineBatchDelayFormRowLabel',
defaultMessage: 'Pipeline batch delay',
})}
formRowTooltipText={TOOLTIPS.settings['pipeline.batch.delay']}
>
<EuiFieldNumber
data-test-subj="inputBatchDelay"
onChange={(e) => this.handleNumberChange('pipeline.batch.delay', e.target.value)}
value={this.state.pipeline.settings['pipeline.batch.delay']}
/>
</FlexItemSetting>
</EuiFlexGroup>
<EuiFlexGroup>
<FlexItemSetting
formRowLabelText={intl.formatMessage({
id: 'xpack.logstash.pipelineEditor.queueTypeFormRowLabel',
defaultMessage: 'Queue type',
})}
formRowTooltipText={TOOLTIPS.settings['queue.type']}
>
<EuiSelect
data-test-subj="selectQueueType"
onChange={(e) => this.handleSettingChange('queue.type', e.target.value)}
options={PIPELINE_EDITOR.QUEUE_TYPES}
value={this.state.pipeline.settings['queue.type']}
/>
</FlexItemSetting>
<FlexItemSetting
formRowLabelText={intl.formatMessage({
id: 'xpack.logstash.pipelineEditor.queueMaxBytesFormRowLabel',
defaultMessage: 'Queue max bytes',
})}
formRowTooltipText={TOOLTIPS.settings['queue.max_bytes']}
>
<EuiFieldNumber
data-test-subj="inputQueueMaxBytesNumber"
onChange={(e) => this.handleMaxByteNumberChange(e.target.value)}
value={this.state.maxBytesNumber}
/>
</FlexItemSetting>
<FlexItemSetting>
<EuiSelect
data-test-subj="selectQueueMaxBytesUnits"
onChange={(e) => this.handleMaxByteUnitChange(e.target.value)}
options={PIPELINE_EDITOR.UNITS}
value={this.state.maxBytesUnit}
/>
</FlexItemSetting>
<FlexItemSetting
formRowLabelText={intl.formatMessage({
id: 'xpack.logstash.pipelineEditor.queueCheckpointWritesFormRowLabel',
defaultMessage: 'Queue checkpoint writes',
})}
formRowTooltipText={TOOLTIPS.settings['queue.checkpoint.writes']}
>
<EuiFieldNumber
data-test-subj="inputQueueCheckpointWrites"
onChange={(e) =>
this.handleNumberChange('queue.checkpoint.writes', e.target.value)
}
value={this.state.pipeline.settings['queue.checkpoint.writes']}
/>
</FlexItemSetting>
</EuiFlexGroup>
</EuiForm>
<EuiSpacer size="l" />
<EuiFlexGroup justifyContent="flexStart">
<EuiFlexItem grow={false}>
<EuiButton
data-test-subj="btnSavePipeline"
fill
isDisabled={this.isSaveDisabled()}
onClick={this.onPipelineSave}
>
<FormattedMessage
id="xpack.logstash.pipelineEditor.createAndDeployButtonLabel"
defaultMessage="Create and deploy"
/>
</EuiButton>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton data-test-subj="btnCancel" onClick={this.onClose}>
<FormattedMessage
id="xpack.logstash.pipelineEditor.cancelButtonLabel"
defaultMessage="Cancel"
/>
</EuiButton>
</EuiFlexItem>
{!this.props.isNewPipeline && (
<EuiFlexItem grow={false}>
<EuiButtonEmpty
color="danger"
data-test-subj="btnDeletePipeline"
onClick={this.showConfirmDeleteModal}
>
<FormattedMessage
id="xpack.logstash.pipelineEditor.deletePipelineButtonLabel"
defaultMessage="Delete pipeline"
/>
</EuiButtonEmpty>
</EuiFlexItem>
)}
</FlexItemSetting>
<FlexItemSetting
formRowLabelText={intl.formatMessage({
id: 'xpack.logstash.pipelineEditor.pipelineBatchDelayFormRowLabel',
defaultMessage: 'Pipeline batch delay',
})}
formRowTooltipText={TOOLTIPS.settings['pipeline.batch.delay']}
>
<EuiFieldNumber
data-test-subj="inputBatchDelay"
onChange={(e) => this.handleNumberChange('pipeline.batch.delay', e.target.value)}
value={this.state.pipeline.settings['pipeline.batch.delay']}
/>
</FlexItemSetting>
</EuiFlexGroup>
</EuiPageContent>
<EuiFlexGroup>
<FlexItemSetting
formRowLabelText={intl.formatMessage({
id: 'xpack.logstash.pipelineEditor.queueTypeFormRowLabel',
defaultMessage: 'Queue type',
})}
formRowTooltipText={TOOLTIPS.settings['queue.type']}
>
<EuiSelect
data-test-subj="selectQueueType"
onChange={(e) => this.handleSettingChange('queue.type', e.target.value)}
options={PIPELINE_EDITOR.QUEUE_TYPES}
value={this.state.pipeline.settings['queue.type']}
/>
</FlexItemSetting>
<FlexItemSetting
formRowLabelText={intl.formatMessage({
id: 'xpack.logstash.pipelineEditor.queueMaxBytesFormRowLabel',
defaultMessage: 'Queue max bytes',
})}
formRowTooltipText={TOOLTIPS.settings['queue.max_bytes']}
>
<EuiFieldNumber
data-test-subj="inputQueueMaxBytesNumber"
onChange={(e) => this.handleMaxByteNumberChange(e.target.value)}
value={this.state.maxBytesNumber}
/>
</FlexItemSetting>
<FlexItemSetting>
<EuiSelect
data-test-subj="selectQueueMaxBytesUnits"
onChange={(e) => this.handleMaxByteUnitChange(e.target.value)}
options={PIPELINE_EDITOR.UNITS}
value={this.state.maxBytesUnit}
/>
</FlexItemSetting>
<FlexItemSetting
formRowLabelText={intl.formatMessage({
id: 'xpack.logstash.pipelineEditor.queueCheckpointWritesFormRowLabel',
defaultMessage: 'Queue checkpoint writes',
})}
formRowTooltipText={TOOLTIPS.settings['queue.checkpoint.writes']}
>
<EuiFieldNumber
data-test-subj="inputQueueCheckpointWrites"
onChange={(e) => this.handleNumberChange('queue.checkpoint.writes', e.target.value)}
value={this.state.pipeline.settings['queue.checkpoint.writes']}
/>
</FlexItemSetting>
</EuiFlexGroup>
</EuiForm>
<EuiSpacer size="l" />
<EuiFlexGroup justifyContent="flexStart">
<EuiFlexItem grow={false}>
<EuiButton
data-test-subj="btnSavePipeline"
fill
isDisabled={this.isSaveDisabled()}
onClick={this.onPipelineSave}
>
<FormattedMessage
id="xpack.logstash.pipelineEditor.createAndDeployButtonLabel"
defaultMessage="Create and deploy"
/>
</EuiButton>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton data-test-subj="btnCancel" onClick={this.onClose}>
<FormattedMessage
id="xpack.logstash.pipelineEditor.cancelButtonLabel"
defaultMessage="Cancel"
/>
</EuiButton>
</EuiFlexItem>
{!this.props.isNewPipeline && (
<EuiFlexItem grow={false}>
<EuiButtonEmpty
color="danger"
data-test-subj="btnDeletePipeline"
onClick={this.showConfirmDeleteModal}
>
<FormattedMessage
id="xpack.logstash.pipelineEditor.deletePipelineButtonLabel"
defaultMessage="Delete pipeline"
/>
</EuiButtonEmpty>
</EuiFlexItem>
)}
</EuiFlexGroup>
{this.state.showConfirmDeleteModal && (
<ConfirmDeletePipelineModal
id={this.props.pipeline.id}
@ -489,7 +481,7 @@ class PipelineEditorUi extends React.Component {
confirmDeletePipeline={this.deletePipeline}
/>
)}
</div>
</EuiPageContentBody>
);
}
}

View file

@ -12,9 +12,8 @@ import {
EuiCallOut,
EuiEmptyPrompt,
EuiLoadingSpinner,
EuiPageContent,
EuiTitle,
EuiText,
EuiPageContentBody,
EuiPageHeader,
EuiSpacer,
} from '@elastic/eui';
@ -292,36 +291,34 @@ class PipelineListUi extends React.Component {
const { clonePipeline, createPipeline, isReadOnly, openPipeline } = this.props;
const { isSelectable, message, pipelines, selection, showConfirmDeleteModal } = this.state;
return (
<div data-test-subj="pipelineList">
<EuiPageContent horizontalPosition="center">
<EuiTitle size="m">
<h1>
<FormattedMessage id="xpack.logstash.pipelineList.head" defaultMessage="Pipelines" />
</h1>
</EuiTitle>
<EuiText color="subdued" size="s">
<p>
<FormattedMessage
id="xpack.logstash.pipelineList.subhead"
defaultMessage="Manage logstash event processing and see the result visually"
/>
</p>
</EuiText>
<EuiSpacer />
{this.renderNoPermissionCallOut()}
<PipelinesTable
clonePipeline={clonePipeline}
createPipeline={createPipeline}
isReadOnly={isReadOnly}
isSelectable={isSelectable}
message={message}
pipelines={pipelines}
selection={selection}
onDeleteSelectedPipelines={this.onDeleteSelectedPipelines}
onSelectionChange={this.onSelectionChange}
openPipeline={openPipeline}
/>
</EuiPageContent>
<EuiPageContentBody data-test-subj="pipelineList">
<EuiPageHeader
pageTitle={
<FormattedMessage id="xpack.logstash.pipelineList.head" defaultMessage="Pipelines" />
}
description={
<FormattedMessage
id="xpack.logstash.pipelineList.subhead"
defaultMessage="Manage logstash event processing and see the result visually"
/>
}
bottomBorder
/>
<EuiSpacer size="l" />
{this.renderNoPermissionCallOut()}
<PipelinesTable
clonePipeline={clonePipeline}
createPipeline={createPipeline}
isReadOnly={isReadOnly}
isSelectable={isSelectable}
message={message}
pipelines={pipelines}
selection={selection}
onDeleteSelectedPipelines={this.onDeleteSelectedPipelines}
onSelectionChange={this.onSelectionChange}
openPipeline={openPipeline}
/>
<ConfirmDeleteModal
cancelDeletePipelines={this.cancelDeletePipelines}
deleteSelectedPipelines={this.deleteSelectedPipelines}
@ -332,7 +329,7 @@ class PipelineListUi extends React.Component {
showAddRoleAlert={this.state.showAddRoleAlert}
showEnableMonitoringAlert={this.state.showEnableMonitoringAlert}
/>
</div>
</EuiPageContentBody>
);
}
}

View file

@ -25,7 +25,6 @@
@import 'components/items_grid/index';
@import 'components/job_selector/index';
@import 'components/loading_indicator/index'; // SASSTODO: This component should be replaced with EuiLoadingSpinner
@import 'components/navigation_menu/index';
@import 'components/rule_editor/index'; // SASSTODO: This file overwrites EUI directly
@import 'components/stats_bar/index';
@import 'components/ml_embedded_map/index';

View file

@ -1 +0,0 @@
@import 'navigation_menu'

View file

@ -1,5 +0,0 @@
.mlNavigationMenu {
padding: 0 $euiSizeM;
border-bottom: $euiBorderThin;
background-color: $euiColorEmptyShade;
}

View file

@ -0,0 +1,4 @@
.mlMainTabs {
// Hack to address https://github.com/elastic/kibana/pull/103197#discussion_r659645946
padding-bottom: 0 !important;
}

View file

@ -7,13 +7,14 @@
import React, { FC, useState, useEffect } from 'react';
import { EuiTabs, EuiTab } from '@elastic/eui';
import { EuiPageHeader } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { TabId } from './navigation_menu';
import { useMlKibana, useMlUrlGenerator, useNavigateToPath } from '../../contexts/kibana';
import { MlUrlGeneratorState } from '../../../../common/types/ml_url_generator';
import { useUrlState } from '../../util/url_state';
import { ML_APP_NAME } from '../../../../common/constants/app';
import './main_tabs.scss';
export interface Tab {
id: TabId;
@ -154,40 +155,26 @@ export const MainTabs: FC<Props> = ({ tabId, disableLinks }) => {
}, [selectedTabId]);
return (
<EuiTabs display="condensed">
{tabs.map((tab: Tab) => {
<EuiPageHeader
paddingSize="m"
className="mlMainTabs"
bottomBorder
tabs={tabs.map((tab: Tab) => {
const { id, disabled } = tab;
const testSubject = TAB_DATA[id].testSubject;
const defaultPathId = (TAB_DATA[id].pathId || id) as MlUrlGeneratorState['page'];
return disabled ? (
<div className="euiTab" key={`div-${id}-key`}>
<EuiTab
key={`tab-${id}-key`}
className={'mlNavigationMenu__mainTab'}
disabled={true}
data-test-subj={testSubject}
>
{tab.name}
</EuiTab>
</div>
) : (
<div className="euiTab" key={`div-${id}-key`}>
<EuiTab
data-test-subj={testSubject + (id === selectedTabId ? ' selected' : '')}
className={'mlNavigationMenu__mainTab'}
onClick={() => {
onSelectedTabChanged(id);
redirectToTab(defaultPathId);
}}
isSelected={id === selectedTabId}
key={`tab-${id}-key`}
>
{tab.name}
</EuiTab>
</div>
);
return {
label: tab.name,
disabled,
onClick: () => {
onSelectedTabChanged(id);
redirectToTab(defaultPathId);
},
'data-test-subj': testSubject + (id === selectedTabId ? ' selected' : ''),
isSelected: id === selectedTabId,
};
})}
</EuiTabs>
/>
);
};

View file

@ -5,8 +5,7 @@
* 2.0.
*/
import React, { Fragment, FC } from 'react';
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import React, { FC } from 'react';
import { isFullLicense } from '../../license';
@ -27,13 +26,5 @@ interface Props {
export const NavigationMenu: FC<Props> = ({ tabId }) => {
const disableLinks = isFullLicense() === false;
return (
<Fragment>
<EuiFlexGroup justifyContent="spaceBetween" className="mlNavigationMenu" gutterSize="none">
<EuiFlexItem grow={false}>
<MainTabs tabId={tabId} disableLinks={disableLinks} />
</EuiFlexItem>
</EuiFlexGroup>
</Fragment>
);
return <MainTabs tabId={tabId} disableLinks={disableLinks} />;
};

View file

@ -135,6 +135,7 @@ class ReportListingUi extends Component<Props, State> {
return (
<>
<EuiPageHeader
bottomBorder
pageTitle={
<FormattedMessage id="xpack.reporting.listing.reportstitle" defaultMessage="Reports" />
}

View file

@ -11,6 +11,7 @@ import useMount from 'react-use/lib/useMount';
import { Query } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { ChromeBreadcrumb, CoreStart } from 'src/core/public';
import { EuiSpacer } from '@elastic/eui';
import { TagWithRelations, TagsCapabilities } from '../../common';
import { getCreateModalOpener } from '../components/edition_modal';
import { ITagInternalClient, ITagAssignmentService, ITagsCache } from '../services';
@ -194,6 +195,7 @@ export const TagManagementPage: FC<TagManagementPageParams> = ({
return (
<>
<Header canCreate={capabilities.create} onCreate={openCreateModal} />
<EuiSpacer size="l" />
<TagTable
loading={loading}
tags={filteredTags}

View file

@ -8,18 +8,7 @@
import React, { lazy, useEffect } from 'react';
import { Route, RouteComponentProps, Switch } from 'react-router-dom';
import { FormattedMessage } from '@kbn/i18n/react';
import {
EuiPageBody,
EuiPageContent,
EuiSpacer,
EuiTab,
EuiTabs,
EuiTitle,
EuiText,
EuiButtonEmpty,
EuiFlexGroup,
EuiFlexItem,
} from '@elastic/eui';
import { EuiSpacer, EuiButtonEmpty, EuiPageHeader } from '@elastic/eui';
import { Section, routeToConnectors, routeToRules } from './constants';
import { getAlertingSectionBreadcrumb } from './lib/breadcrumb';
@ -89,78 +78,66 @@ export const TriggersActionsUIHome: React.FunctionComponent<RouteComponentProps<
}, [section, chrome, setBreadcrumbs]);
return (
<EuiPageBody>
<EuiPageContent color="transparent">
<EuiTitle size="m">
<EuiFlexGroup>
<EuiFlexItem>
<h1 data-test-subj="appTitle">
<FormattedMessage
id="xpack.triggersActionsUI.home.appTitle"
defaultMessage="Rules and Connectors"
/>
</h1>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButtonEmpty
href={docLinks.links.alerting.guide}
target="_blank"
iconType="help"
data-test-subj="documentationLink"
>
<FormattedMessage
id="xpack.triggersActionsUI.home.docsLinkText"
defaultMessage="Documentation"
/>
</EuiButtonEmpty>
</EuiFlexItem>
</EuiFlexGroup>
</EuiTitle>
<EuiSpacer size="s" />
<EuiText>
<p>
<>
<EuiPageHeader
bottomBorder
pageTitle={
<span data-test-subj="appTitle">
<FormattedMessage
id="xpack.triggersActionsUI.home.sectionDescription"
defaultMessage="Detect conditions using rules, and take actions using connectors."
id="xpack.triggersActionsUI.home.appTitle"
defaultMessage="Rules and Connectors"
/>
</p>
</EuiText>
</span>
}
rightSideItems={[
<EuiButtonEmpty
href={docLinks.links.alerting.guide}
target="_blank"
iconType="help"
data-test-subj="documentationLink"
>
<FormattedMessage
id="xpack.triggersActionsUI.home.docsLinkText"
defaultMessage="Documentation"
/>
</EuiButtonEmpty>,
]}
description={
<FormattedMessage
id="xpack.triggersActionsUI.home.sectionDescription"
defaultMessage="Detect conditions using rules, and take actions using connectors."
/>
}
tabs={tabs.map((tab) => ({
label: tab.name,
onClick: () => onSectionChange(tab.id),
isSelected: tab.id === section,
key: tab.id,
'data-test-subj': `${tab.id}Tab`,
}))}
/>
<EuiTabs>
{tabs.map((tab) => (
<EuiTab
onClick={() => onSectionChange(tab.id)}
isSelected={tab.id === section}
key={tab.id}
data-test-subj={`${tab.id}Tab`}
>
{tab.name}
</EuiTab>
))}
</EuiTabs>
<EuiSpacer size="l" />
<EuiSpacer size="s" />
<HealthContextProvider>
<HealthCheck waitForCheck={true}>
<Switch>
{canShowActions && (
<Route
exact
path={routeToConnectors}
component={suspendedComponentWithProps(ActionsConnectorsList, 'xl')}
/>
)}
<HealthContextProvider>
<HealthCheck waitForCheck={true}>
<Switch>
{canShowActions && (
<Route
exact
path={routeToRules}
component={suspendedComponentWithProps(AlertsList, 'xl')}
path={routeToConnectors}
component={suspendedComponentWithProps(ActionsConnectorsList, 'xl')}
/>
</Switch>
</HealthCheck>
</HealthContextProvider>
</EuiPageContent>
</EuiPageBody>
)}
<Route
exact
path={routeToRules}
component={suspendedComponentWithProps(AlertsList, 'xl')}
/>
</Switch>
</HealthCheck>
</HealthContextProvider>
</>
);
};

View file

@ -10,8 +10,6 @@ import React, { useState, useEffect, useReducer } from 'react';
import { keyBy } from 'lodash';
import { useHistory } from 'react-router-dom';
import {
EuiPageBody,
EuiPageContent,
EuiPageHeader,
EuiText,
EuiFlexGroup,
@ -149,213 +147,211 @@ export const AlertDetails: React.FunctionComponent<AlertDetailsProps> = ({
: [];
return (
<EuiPageBody>
<EuiPageContent color="transparent">
<EuiPageHeader
data-test-subj="alertDetailsTitle"
bottomBorder
pageTitle={
<>
<EuiPageHeader
data-test-subj="alertDetailsTitle"
bottomBorder
pageTitle={
<FormattedMessage
id="xpack.triggersActionsUI.sections.alertDetails.alertDetailsTitle"
defaultMessage="{alertName}"
values={{ alertName: alert.name }}
/>
}
rightSideItems={[
<ViewInApp alert={alert} />,
<EuiButtonEmpty
data-test-subj="refreshAlertsButton"
iconType="refresh"
onClick={requestRefresh}
name="refresh"
color="primary"
>
<FormattedMessage
id="xpack.triggersActionsUI.sections.alertDetails.alertDetailsTitle"
defaultMessage="{alertName}"
values={{ alertName: alert.name }}
id="xpack.triggersActionsUI.sections.alertsList.refreshAlertsButtonLabel"
defaultMessage="Refresh"
/>
}
rightSideItems={[
<ViewInApp alert={alert} />,
<EuiButtonEmpty
data-test-subj="refreshAlertsButton"
iconType="refresh"
onClick={requestRefresh}
name="refresh"
color="primary"
>
<FormattedMessage
id="xpack.triggersActionsUI.sections.alertsList.refreshAlertsButtonLabel"
defaultMessage="Refresh"
/>
</EuiButtonEmpty>,
...rightPageHeaderButtons,
]}
/>
<EuiSpacer size="l" />
<EuiPageContentBody>
<EuiFlexGroup wrap responsive={false} gutterSize="m">
<EuiFlexItem grow={false}>
<EuiText size="s">
<p>
<FormattedMessage
id="xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.alertTypeTitle"
defaultMessage="Type"
/>
</p>
</EuiText>
<EuiSpacer size="xs" />
<EuiBadge data-test-subj="alertTypeLabel">{alertType.name}</EuiBadge>
</EuiFlexItem>
<EuiFlexItem grow={1}>
{uniqueActions && uniqueActions.length ? (
<>
<EuiText size="s">
<p>
<FormattedMessage
id="xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.actionsTex"
defaultMessage="Actions"
/>
</p>
</EuiText>
<EuiSpacer size="xs" />
<EuiFlexGroup wrap gutterSize="s">
{uniqueActions.map((action, index) => (
<EuiFlexItem key={index} grow={false}>
<EuiBadge color="hollow" data-test-subj="actionTypeLabel">
{actionTypesByTypeId[action].name ?? action}
</EuiBadge>
</EuiFlexItem>
))}
</EuiFlexGroup>
</>
) : null}
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiSpacer />
<EuiFlexGroup justifyContent="flexEnd" wrap responsive={false} gutterSize="m">
<EuiFlexItem grow={false}>
<EuiSwitch
name="disable"
disabled={!canSaveAlert || !alertType.enabledInLicense}
checked={!isEnabled}
data-test-subj="disableSwitch"
onChange={async () => {
if (isEnabled) {
setIsEnabled(false);
await disableAlert(alert);
// Reset dismiss if previously clicked
setDissmissAlertErrors(false);
} else {
setIsEnabled(true);
await enableAlert(alert);
}
requestRefresh();
}}
label={
<FormattedMessage
id="xpack.triggersActionsUI.sections.alertDetails.collapsedItemActons.disableTitle"
defaultMessage="Disable"
/>
}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiSwitch
name="mute"
checked={isMuted}
disabled={!canSaveAlert || !isEnabled || !alertType.enabledInLicense}
data-test-subj="muteSwitch"
onChange={async () => {
if (isMuted) {
setIsMuted(false);
await unmuteAlert(alert);
} else {
setIsMuted(true);
await muteAlert(alert);
}
requestRefresh();
}}
label={
<FormattedMessage
id="xpack.triggersActionsUI.sections.alertDetails.collapsedItemActons.muteTitle"
defaultMessage="Mute"
/>
}
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
</EuiFlexGroup>
{alert.enabled && !dissmissAlertErrors && alert.executionStatus.status === 'error' ? (
<EuiFlexGroup>
<EuiFlexItem>
<EuiCallOut
color="danger"
data-test-subj="alertErrorBanner"
size="s"
title={getAlertStatusErrorReasonText()}
iconType="alert"
>
<EuiText size="s" color="danger" data-test-subj="alertErrorMessageText">
{alert.executionStatus.error?.message}
</EuiText>
<EuiSpacer size="s" />
<EuiFlexGroup gutterSize="s" wrap={true}>
<EuiFlexItem grow={false}>
<EuiButton
data-test-subj="dismiss-execution-error"
color="danger"
onClick={() => setDissmissAlertErrors(true)}
>
<FormattedMessage
id="xpack.triggersActionsUI.sections.alertDetails.dismissButtonTitle"
defaultMessage="Dismiss"
/>
</EuiButton>
</EuiButtonEmpty>,
...rightPageHeaderButtons,
]}
/>
<EuiSpacer size="l" />
<EuiPageContentBody>
<EuiFlexGroup wrap responsive={false} gutterSize="m">
<EuiFlexItem grow={false}>
<EuiText size="s">
<p>
<FormattedMessage
id="xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.alertTypeTitle"
defaultMessage="Type"
/>
</p>
</EuiText>
<EuiSpacer size="xs" />
<EuiBadge data-test-subj="alertTypeLabel">{alertType.name}</EuiBadge>
</EuiFlexItem>
<EuiFlexItem grow={1}>
{uniqueActions && uniqueActions.length ? (
<>
<EuiText size="s">
<p>
<FormattedMessage
id="xpack.triggersActionsUI.sections.alertsList.alertsListTable.columns.actionsTex"
defaultMessage="Actions"
/>
</p>
</EuiText>
<EuiSpacer size="xs" />
<EuiFlexGroup wrap gutterSize="s">
{uniqueActions.map((action, index) => (
<EuiFlexItem key={index} grow={false}>
<EuiBadge color="hollow" data-test-subj="actionTypeLabel">
{actionTypesByTypeId[action].name ?? action}
</EuiBadge>
</EuiFlexItem>
{alert.executionStatus.error?.reason ===
AlertExecutionStatusErrorReasons.License && (
<EuiFlexItem grow={false}>
<EuiButtonEmpty
href={`${http.basePath.get()}/app/management/stack/license_management`}
color="danger"
target="_blank"
>
<FormattedMessage
id="xpack.triggersActionsUI.sections.alertDetails.manageLicensePlanBannerLinkTitle"
defaultMessage="Manage license"
/>
</EuiButtonEmpty>
</EuiFlexItem>
)}
</EuiFlexGroup>
</EuiCallOut>
))}
</EuiFlexGroup>
</>
) : null}
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiSpacer />
<EuiFlexGroup justifyContent="flexEnd" wrap responsive={false} gutterSize="m">
<EuiFlexItem grow={false}>
<EuiSwitch
name="disable"
disabled={!canSaveAlert || !alertType.enabledInLicense}
checked={!isEnabled}
data-test-subj="disableSwitch"
onChange={async () => {
if (isEnabled) {
setIsEnabled(false);
await disableAlert(alert);
// Reset dismiss if previously clicked
setDissmissAlertErrors(false);
} else {
setIsEnabled(true);
await enableAlert(alert);
}
requestRefresh();
}}
label={
<FormattedMessage
id="xpack.triggersActionsUI.sections.alertDetails.collapsedItemActons.disableTitle"
defaultMessage="Disable"
/>
}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiSwitch
name="mute"
checked={isMuted}
disabled={!canSaveAlert || !isEnabled || !alertType.enabledInLicense}
data-test-subj="muteSwitch"
onChange={async () => {
if (isMuted) {
setIsMuted(false);
await unmuteAlert(alert);
} else {
setIsMuted(true);
await muteAlert(alert);
}
requestRefresh();
}}
label={
<FormattedMessage
id="xpack.triggersActionsUI.sections.alertDetails.collapsedItemActons.muteTitle"
defaultMessage="Mute"
/>
}
/>
</EuiFlexItem>
</EuiFlexGroup>
) : null}
</EuiFlexItem>
</EuiFlexGroup>
{alert.enabled && !dissmissAlertErrors && alert.executionStatus.status === 'error' ? (
<EuiFlexGroup>
<EuiFlexItem>
{alert.enabled ? (
<AlertInstancesRouteWithApi
requestRefresh={requestRefresh}
alert={alert}
alertType={alertType}
readOnly={!canSaveAlert}
/>
) : (
<>
<EuiSpacer />
<EuiCallOut
title={i18n.translate(
'xpack.triggersActionsUI.sections.alertDetails.alerts.disabledRuleTitle',
{
defaultMessage: 'Disabled Rule',
}
)}
color="warning"
iconType="help"
>
<p>
<EuiCallOut
color="danger"
data-test-subj="alertErrorBanner"
size="s"
title={getAlertStatusErrorReasonText()}
iconType="alert"
>
<EuiText size="s" color="danger" data-test-subj="alertErrorMessageText">
{alert.executionStatus.error?.message}
</EuiText>
<EuiSpacer size="s" />
<EuiFlexGroup gutterSize="s" wrap={true}>
<EuiFlexItem grow={false}>
<EuiButton
data-test-subj="dismiss-execution-error"
color="danger"
onClick={() => setDissmissAlertErrors(true)}
>
<FormattedMessage
id="xpack.triggersActionsUI.sections.alertDetails.alertInstances.disabledRule"
defaultMessage="This rule is disabled and cannot be displayed. Toggle Disable ↑ to activate it."
id="xpack.triggersActionsUI.sections.alertDetails.dismissButtonTitle"
defaultMessage="Dismiss"
/>
</p>
</EuiCallOut>
</>
)}
</EuiButton>
</EuiFlexItem>
{alert.executionStatus.error?.reason ===
AlertExecutionStatusErrorReasons.License && (
<EuiFlexItem grow={false}>
<EuiButtonEmpty
href={`${http.basePath.get()}/app/management/stack/license_management`}
color="danger"
target="_blank"
>
<FormattedMessage
id="xpack.triggersActionsUI.sections.alertDetails.manageLicensePlanBannerLinkTitle"
defaultMessage="Manage license"
/>
</EuiButtonEmpty>
</EuiFlexItem>
)}
</EuiFlexGroup>
</EuiCallOut>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPageContentBody>
</EuiPageContent>
</EuiPageBody>
) : null}
<EuiFlexGroup>
<EuiFlexItem>
{alert.enabled ? (
<AlertInstancesRouteWithApi
requestRefresh={requestRefresh}
alert={alert}
alertType={alertType}
readOnly={!canSaveAlert}
/>
) : (
<>
<EuiSpacer />
<EuiCallOut
title={i18n.translate(
'xpack.triggersActionsUI.sections.alertDetails.alerts.disabledRuleTitle',
{
defaultMessage: 'Disabled Rule',
}
)}
color="warning"
iconType="help"
>
<p>
<FormattedMessage
id="xpack.triggersActionsUI.sections.alertDetails.alertInstances.disabledRule"
defaultMessage="This rule is disabled and cannot be displayed. Toggle Disable ↑ to activate it."
/>
</p>
</EuiCallOut>
</>
)}
</EuiFlexItem>
</EuiFlexGroup>
</EuiPageContentBody>
</>
);
};

View file

@ -10,6 +10,8 @@ import expect from '@kbn/expect';
import { FtrProviderContext } from '../../ftr_provider_context';
import { MlCommonUI } from './common_ui';
const fixedFooterHeight = 72; // Size of EuiBottomBar more or less
export function MachineLearningDataVisualizerFileBasedProvider(
{ getService, getPageObjects }: FtrProviderContext,
mlCommonUI: MlCommonUI
@ -131,7 +133,9 @@ export function MachineLearningDataVisualizerFileBasedProvider(
},
async selectCreateFilebeatConfig() {
await testSubjects.scrollIntoView('fileDataVisFilebeatConfigLink');
await testSubjects.scrollIntoView('fileDataVisFilebeatConfigLink', {
bottomOffset: fixedFooterHeight,
});
await testSubjects.click('fileDataVisFilebeatConfigLink');
await testSubjects.existOrFail('fileDataVisFilebeatConfigPanel');
},