mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
### Summary (#28056)
Moved "Add data" and the theme switcher from the footer to a settings gear / style cleanup
### Details
* Moved the "Add data" button and the theme switcher from the page footer to a settings gear popover in the header
**Before:**

**After:**

* Fixed broken theming after a merge from `master` in commit `06be9aba69
` brought in angular code that is not theme
-friendly https://github.com/elastic/ingest-dev/issues/186
**This was fixed:**

* Removed whitespace above navigation
**Before:**

**After:**

* Removed some global CSS overrides of EUI styles via usage of the className API https://github.com/elastic/ingest-dev/issues/178
* Fixed incorrect text wrapping of the "empty data providers" message https://github.com/elastic/ingest-dev/issues/158
* Fixed alignment of "drop anything" text https://github.com/elastic/ingest-dev/issues/180
**Before:**

**After:**

This commit is contained in:
parent
be1f8fd876
commit
bc8013e81a
8 changed files with 215 additions and 58 deletions
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { mount } from 'enzyme';
|
||||
import { noop } from 'lodash/fp';
|
||||
import * as React from 'react';
|
||||
|
||||
import { AppSettingsPopover } from './app_settings_popover';
|
||||
|
||||
describe('AppSettingsPopover', () => {
|
||||
describe('rendering', () => {
|
||||
test('it renders a settings gear icon', () => {
|
||||
const wrapper = mount(
|
||||
<AppSettingsPopover onClick={noop} onClose={noop} showPopover={false} />
|
||||
);
|
||||
|
||||
expect(wrapper.find('[data-test-subj="gear"]').exists()).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onClick', () => {
|
||||
test('it invokes onClick when clicked', () => {
|
||||
const onClick = jest.fn();
|
||||
|
||||
const wrapper = mount(
|
||||
<AppSettingsPopover onClick={onClick} onClose={noop} showPopover={false} />
|
||||
);
|
||||
|
||||
wrapper
|
||||
.find('[data-test-subj="gear"]')
|
||||
.first()
|
||||
.simulate('click');
|
||||
|
||||
expect(onClick).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiIcon, EuiPopover, EuiTitle } from '@elastic/eui';
|
||||
import * as React from 'react';
|
||||
import { pure } from 'recompose';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { ThemeSwitcher } from '../theme_switcher';
|
||||
|
||||
interface Props {
|
||||
showPopover: boolean;
|
||||
onClick: () => void;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
const SettingsPopover = styled(EuiPopover)`
|
||||
cursor: pointer;
|
||||
`;
|
||||
|
||||
const Title = styled(EuiTitle)`
|
||||
margin-bottom: 5px;
|
||||
`;
|
||||
|
||||
const TitleText = styled.h1`
|
||||
text-align: center;
|
||||
`;
|
||||
|
||||
export const AppSettingsPopover = pure<Props>(({ showPopover, onClick, onClose }) => (
|
||||
<SettingsPopover
|
||||
anchorPosition="downRight"
|
||||
button={<EuiIcon data-test-subj="gear" type="gear" size="l" onClick={onClick} />}
|
||||
closePopover={onClose}
|
||||
data-test-subj="app-settings-popover"
|
||||
id="timelineSettingsPopover"
|
||||
isOpen={showPopover}
|
||||
>
|
||||
<EuiFlexGroup direction="column" alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton
|
||||
data-test-subj="add-data"
|
||||
href="kibana#home/tutorial_directory/security"
|
||||
target="_blank"
|
||||
>
|
||||
Add data
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<Title size="xs">
|
||||
<TitleText>Theme</TitleText>
|
||||
</Title>
|
||||
<ThemeSwitcher />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</SettingsPopover>
|
||||
));
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import * as React from 'react';
|
||||
|
||||
import { AppSettingsPopover } from './app_settings_popover';
|
||||
|
||||
export interface State {
|
||||
showPopover: boolean;
|
||||
}
|
||||
|
||||
export class AppSettings extends React.PureComponent<{}, State> {
|
||||
public readonly state = {
|
||||
showPopover: false,
|
||||
};
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<AppSettingsPopover
|
||||
onClick={this.onClick}
|
||||
onClose={this.onClose}
|
||||
showPopover={this.state.showPopover}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
private onClick = () => {
|
||||
this.setState({
|
||||
showPopover: !this.state.showPopover,
|
||||
});
|
||||
};
|
||||
|
||||
private onClose = () => {
|
||||
this.setState({
|
||||
showPopover: false,
|
||||
});
|
||||
};
|
||||
}
|
|
@ -21,25 +21,22 @@ interface FlyoutPaneProps {
|
|||
width: number;
|
||||
}
|
||||
|
||||
/** SIDE EFFECT: This container has selectors that override EUI flyout styles */
|
||||
const EuiFlyoutContainer = styled.div<{ headerHeight: number; width: number }>`
|
||||
& > span > div {
|
||||
.euiFlyout {
|
||||
min-width: 150px !important;
|
||||
width: ${({ width }) => `${width}px !important`};
|
||||
}
|
||||
.euiFlyoutHeader {
|
||||
align-items: center !important;
|
||||
display: flex !important;
|
||||
flex-direction: row !important;
|
||||
height: ${({ headerHeight }) => `${headerHeight}px !important`};
|
||||
max-height: ${({ headerHeight }) => `${headerHeight}px !important`};
|
||||
overflow: hidden;
|
||||
}
|
||||
.euiFlyoutBody {
|
||||
overflow-y: hidden !important;
|
||||
padding: 10px 24px 24px 24px !important;
|
||||
}
|
||||
.timeline-flyout {
|
||||
min-width: 150px;
|
||||
width: ${({ width }) => `${width}px`};
|
||||
}
|
||||
.timeline-flyout-header {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: ${({ headerHeight }) => `${headerHeight}px`};
|
||||
max-height: ${({ headerHeight }) => `${headerHeight}px`};
|
||||
overflow: hidden;
|
||||
}
|
||||
.timeline-flyout-body {
|
||||
overflow-y: hidden;
|
||||
padding: 10px 24px 24px 24px;
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -63,6 +60,7 @@ export const FlyoutPane = pure<FlyoutPaneProps>(
|
|||
width={width}
|
||||
>
|
||||
<EuiFlyout
|
||||
className="timeline-flyout"
|
||||
size="l"
|
||||
maxWidth="95%"
|
||||
onClose={onClose}
|
||||
|
@ -71,7 +69,7 @@ export const FlyoutPane = pure<FlyoutPaneProps>(
|
|||
hideCloseButton={true}
|
||||
>
|
||||
<ResizeHandle height={flyoutHeight} timelineId={timelineId} />
|
||||
<EuiFlyoutHeader hasBorder>
|
||||
<EuiFlyoutHeader hasBorder className="timeline-flyout-header">
|
||||
<FlyoutHeaderContainer>
|
||||
<WrappedCloseButton>
|
||||
<EuiToolTip content="Close">
|
||||
|
@ -85,7 +83,9 @@ export const FlyoutPane = pure<FlyoutPaneProps>(
|
|||
<FlyoutHeader timelineId={timelineId} />
|
||||
</FlyoutHeaderContainer>
|
||||
</EuiFlyoutHeader>
|
||||
<EuiFlyoutBody data-test-subj="flyoutChildren">{children}</EuiFlyoutBody>
|
||||
<EuiFlyoutBody data-test-subj="flyoutChildren" className="timeline-flyout-body">
|
||||
{children}
|
||||
</EuiFlyoutBody>
|
||||
</EuiFlyout>
|
||||
</EuiFlyoutContainer>
|
||||
)
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
*/
|
||||
|
||||
import {
|
||||
EuiButton,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
// @ts-ignore
|
||||
|
@ -17,7 +16,6 @@ import { pure } from 'recompose';
|
|||
|
||||
import { FooterContainer } from '.';
|
||||
import { WhoAmI } from '../../containers/who_am_i';
|
||||
import { ThemeSwitcher } from '../theme_switcher';
|
||||
|
||||
export const Footer = pure(() => (
|
||||
<FooterContainer data-test-subj="footer">
|
||||
|
@ -27,18 +25,6 @@ export const Footer = pure(() => (
|
|||
{({ appName }) => <EuiHealth color="success">Live {appName} data</EuiHealth>}
|
||||
</WhoAmI>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFlexGroup alignItems="center">
|
||||
<EuiFlexItem>
|
||||
<ThemeSwitcher />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiButton href="kibana#home/tutorial_directory/security" target="_blank">
|
||||
Add data
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</FooterContainer>
|
||||
));
|
||||
|
|
|
@ -6,6 +6,19 @@
|
|||
|
||||
import { EuiPage } from '@elastic/eui';
|
||||
import styled from 'styled-components';
|
||||
import { injectGlobal } from 'styled-components';
|
||||
|
||||
// SIDE EFFECT: the following `injectGlobal` overrides default styling in angular code that was not theme-friendly
|
||||
// tslint:disable-next-line:no-unused-expression
|
||||
injectGlobal`
|
||||
div.app-wrapper {
|
||||
background-color: rgba(0,0,0,0);
|
||||
}
|
||||
|
||||
div.application {
|
||||
background-color: rgba(0,0,0,0);
|
||||
}
|
||||
`;
|
||||
|
||||
export const PageContainer = styled.div`
|
||||
display: flex;
|
||||
|
|
|
@ -9,50 +9,58 @@ import * as React from 'react';
|
|||
import { pure } from 'recompose';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const Text = styled.span`
|
||||
const Text = styled.div`
|
||||
color: #999999;
|
||||
overflow: hidden;
|
||||
padding: 3px;
|
||||
white-space: nowrap;
|
||||
`;
|
||||
|
||||
const BadgeHighlighted = styled(EuiBadge)`
|
||||
height: 20px;
|
||||
margin: 0 5px 0 12px;
|
||||
margin: 0 5px 0 5px;
|
||||
max-width: 70px;
|
||||
min-width: 70px;
|
||||
`;
|
||||
|
||||
const BadgeOr = styled(EuiBadge)`
|
||||
height: 20px;
|
||||
margin: 0 5px 0 12px;
|
||||
margin: 0 5px 0 5px;
|
||||
max-width: 20px;
|
||||
min-width: 20px;
|
||||
`;
|
||||
|
||||
const Hint = styled.div`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
`;
|
||||
|
||||
const Flex = styled.div`
|
||||
const EmptyContainer = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100px;
|
||||
padding: 10px;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
min-height: 100px;
|
||||
user-select: none;
|
||||
`;
|
||||
|
||||
const NoWrap = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: no-wrap;
|
||||
`;
|
||||
|
||||
/**
|
||||
* Prompts the user to drop anything with a facet count into the data providers section.
|
||||
*/
|
||||
export const Empty = pure(() => (
|
||||
<Flex data-test-subj="empty">
|
||||
<Hint>
|
||||
<EmptyContainer data-test-subj="empty">
|
||||
<NoWrap>
|
||||
<Text>Drop anything</Text>
|
||||
<BadgeHighlighted color="#d9d9d9">highlighted</BadgeHighlighted>
|
||||
</NoWrap>
|
||||
|
||||
<NoWrap>
|
||||
<Text>here to build an</Text>
|
||||
<BadgeOr color="#d9d9d9">OR</BadgeOr>
|
||||
<Text>query</Text>
|
||||
</Hint>
|
||||
</Flex>
|
||||
</NoWrap>
|
||||
</EmptyContainer>
|
||||
));
|
||||
|
|
|
@ -22,6 +22,7 @@ import { Dispatch } from 'redux';
|
|||
import styled, { ThemeProvider } from 'styled-components';
|
||||
import chrome from 'ui/chrome';
|
||||
|
||||
import { AppSettings } from '../../components/app_settings';
|
||||
import { AutoSizer } from '../../components/auto_sizer';
|
||||
import { DragDropContextWrapper } from '../../components/drag_and_drop/drag_drop_context_wrapper';
|
||||
import { Flyout, flyoutHeaderHeight } from '../../components/flyout';
|
||||
|
@ -105,13 +106,22 @@ const HomePageComponent = pure<Props>(({ theme }) => (
|
|||
headers={headers}
|
||||
/>
|
||||
</Flyout>
|
||||
<MyEuiFlexGroup justifyContent="flexEnd" alignItems="center">
|
||||
<EuiFlexItem grow={false} data-test-subj="datePickerContainer">
|
||||
<RangeDatePicker id="global" />
|
||||
</EuiFlexItem>
|
||||
</MyEuiFlexGroup>
|
||||
<PageHeader data-test-subj="pageHeader">
|
||||
<Navigation data-test-subj="navigation" />
|
||||
<HeaderFlexGroup justifyContent="spaceBetween" alignItems="center">
|
||||
<EuiFlexItem grow={false} data-test-subj="datePickerContainer">
|
||||
<Navigation data-test-subj="navigation" />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFlexGroup alignItems="center" wrap={false}>
|
||||
<EuiFlexItem grow={false} data-test-subj="datePickerContainer">
|
||||
<RangeDatePicker id="global" />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false} data-test-subj="appSettingsContainer">
|
||||
<AppSettings />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
</HeaderFlexGroup>
|
||||
</PageHeader>
|
||||
<PageContent data-test-subj="pageContent">
|
||||
<Pane data-test-subj="pane">
|
||||
|
@ -145,6 +155,6 @@ const mapStateToProps = (state: State) => ({
|
|||
|
||||
export const HomePage = connect(mapStateToProps)(HomePageComponent);
|
||||
|
||||
const MyEuiFlexGroup = styled(EuiFlexGroup)`
|
||||
margin: 2px 0px;
|
||||
const HeaderFlexGroup = styled(EuiFlexGroup)`
|
||||
margin-bottom: 2px;
|
||||
`;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue