Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Observability] Landing page for Observability #67467

Merged
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
fe63501
creating overview page and menu
cauemarcondes May 27, 2020
fe9d636
styling the home page
cauemarcondes May 28, 2020
377a3f3
adjusting breadcrumb
cauemarcondes May 28, 2020
df6410b
renaming isnt working
cauemarcondes May 28, 2020
5b55b84
renaming isnt working
cauemarcondes May 28, 2020
e790500
renaming isnt working
cauemarcondes May 28, 2020
3035d48
fixing import
cauemarcondes May 29, 2020
1aaeb79
fixing scroll when resize window
cauemarcondes May 29, 2020
f60716d
fixing eslint errors
cauemarcondes May 29, 2020
bae11f4
prepending links
cauemarcondes May 29, 2020
47170f2
adding target option
cauemarcondes May 29, 2020
69d4e3d
refactoring
cauemarcondes Jun 1, 2020
405491a
adding dark mode support
cauemarcondes Jun 2, 2020
69ca82e
Merge branch 'master' of github.com:elastic/kibana into observability…
cauemarcondes Jun 2, 2020
d382091
fixing prettier format
cauemarcondes Jun 2, 2020
0636b5f
fixing i18n
cauemarcondes Jun 2, 2020
d9d1d6a
reverting some unnecessary changes
cauemarcondes Jun 2, 2020
9111811
addressing PR comments
cauemarcondes Jun 3, 2020
0d5b98d
fixing functional tests
cauemarcondes Jun 3, 2020
94bf0fc
ordering observability menu
cauemarcondes Jun 3, 2020
1067fad
fixing tests
cauemarcondes Jun 3, 2020
3ce844f
addressing PR comments
cauemarcondes Jun 4, 2020
f3b8cd8
fixing test
cauemarcondes Jun 4, 2020
6f59f71
fixing scroll
cauemarcondes Jun 4, 2020
e302e33
Merge branch 'master' into observability-landing-page
elasticmachine Jun 4, 2020
f2443fe
addressing pr comments
cauemarcondes Jun 5, 2020
be5e21c
addressing pr comments
cauemarcondes Jun 5, 2020
f1676a9
Merge branch 'master' into observability-landing-page
elasticmachine Jun 6, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions x-pack/plugins/observability/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"singleQuote": true,
"semi": true
}
cauemarcondes marked this conversation as resolved.
Show resolved Hide resolved
16 changes: 16 additions & 0 deletions x-pack/plugins/observability/public/application/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* 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 React from 'react';
import ReactDOM from 'react-dom';
import { AppMountParameters, CoreStart } from '../../../../../src/core/public';
import { Home } from '../pages/home';

export const renderApp = (core: CoreStart, { element }: AppMountParameters) => {
ReactDOM.render(<Home core={core} />, element);
return () => {
ReactDOM.unmountComponentAtNode(element);
};
};
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ export const SectionLink: React.FC<EuiListGroupItemProps> = (props) => (
<EuiListGroupItem style={{ padding: 0 }} size={'s'} {...props} />
);

export const ActionMenuDivider: React.FC<{}> = (props) => <EuiHorizontalRule margin={'s'} />;
export const ActionMenuDivider: React.FC<{}> = (props) => (
<EuiHorizontalRule margin={'s'} />
);

export const ActionMenu: React.FC<Props> = (props) => <EuiPopover {...props} ownFocus={true} />;
export const ActionMenu: React.FC<Props> = (props) => (
<EuiPopover {...props} ownFocus={true} />
);
24 changes: 19 additions & 5 deletions x-pack/plugins/observability/public/hooks/use_track_metric.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,14 @@ export { METRIC_TYPE };
export function useUiTracker<Services extends ServiceDeps>({
app: defaultApp,
}: { app?: ObservabilityApp } = {}) {
const reportUiStats = useKibana<Services>().services?.usageCollection?.reportUiStats;
const reportUiStats = useKibana<Services>().services?.usageCollection
?.reportUiStats;
const trackEvent = useMemo(() => {
return ({ app = defaultApp, metric, metricType = METRIC_TYPE.COUNT }: TrackMetricOptions) => {
return ({
app = defaultApp,
metric,
metricType = METRIC_TYPE.COUNT,
}: TrackMetricOptions) => {
if (reportUiStats) {
reportUiStats(app as string, metricType, metric);
}
Expand All @@ -50,10 +55,16 @@ export function useUiTracker<Services extends ServiceDeps>({
}

export function useTrackMetric<Services extends ServiceDeps>(
{ app, metric, metricType = METRIC_TYPE.COUNT, delay = 0 }: TrackMetricOptions,
{
app,
metric,
metricType = METRIC_TYPE.COUNT,
delay = 0,
}: TrackMetricOptions,
effectDependencies: EffectDeps = []
) {
const reportUiStats = useKibana<Services>().services?.usageCollection?.reportUiStats;
const reportUiStats = useKibana<Services>().services?.usageCollection
?.reportUiStats;

useEffect(() => {
if (!reportUiStats) {
Expand Down Expand Up @@ -88,5 +99,8 @@ export function useTrackPageview<Services extends ServiceDeps>(
{ path, ...rest }: TrackPageviewProps,
effectDependencies: EffectDeps = []
) {
useTrackMetric<Services>({ ...rest, metric: `pageview__${path}` }, effectDependencies);
useTrackMetric<Services>(
{ ...rest, metric: `pageview__${path}` },
effectDependencies
);
}
251 changes: 251 additions & 0 deletions x-pack/plugins/observability/public/pages/home/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
/*
* 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,
EuiFlexGrid,
EuiFlexGroup,
EuiFlexItem,
EuiHorizontalRule,
EuiIcon,
EuiImage,
EuiPanel,
EuiSpacer,
EuiText,
EuiTitle,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React, { useEffect } from 'react';
import styled from 'styled-components';
import { ISection, Section } from './section';
import { CoreStart } from '../../../../../../src/core/public';

const appsSection: ISection[] = [
{
id: 'logs',
title: 'Logs',
icon: 'logoLogging',
description:
'The Elastic Stack (sometimes known as the ELK Stack) is the most popular open source logging platform.',
},
{
id: 'apm',
title: 'APM',
icon: 'logoAPM',
description:
'See exactly where your application is spending time so you can quickly fix issues and feel good about the code you push.',
},
{
id: 'metrics',
title: 'Metrics',
icon: 'logoMetrics',
description:
'Already using the Elastic Stack for logs? Add metrics in just a few steps and correlate metrics and logs in one place.',
},
{
id: 'uptime',
title: 'Uptime',
icon: 'logoUptime',
description:
'React to availability issues across your apps and services before they affect users.',
},
];

const tryItOutItemsSection: ISection[] = [
{
id: 'demo',
title: 'Demo Playground',
icon: 'play',
description:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed sit amet magna at neque dictum.',
href: 'https://demo.elastic.co/',
cauemarcondes marked this conversation as resolved.
Show resolved Hide resolved
},
{
id: 'sampleData',
title: 'Add sample data',
icon: 'documents',
description:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed sit amet magna at neque dictum.',
href: '/app/home#/tutorial_directory/sampleData',
cauemarcondes marked this conversation as resolved.
Show resolved Hide resolved
},
];

const FixedContainer = styled.div`
position: fixed;
width: 100%;
top: 49px;
bottom: 0;
display: flex;
flex-direction: column;
`;

const OverflowContainer = styled.div`
height: 100%;
overflow-y: auto;
overflow-x: hidden;
background-color: #fff;
`;

const CentralizedContainer = styled.div`
width: 1200px;
margin: 0 auto;
`;

const TitleContainer = styled.div`
height: 124px;
display: flex;
align-items: center;
background-color: #fafbfd;
`;

const BodyContainer = styled.div`
border-top: 1px solid #d3dae6;
`;

interface Props {
core: CoreStart;
}

export const Home = ({ core }: Props) => {
useEffect(() => {
core.chrome.setBreadcrumbs([
{
text: i18n.translate('observability.home.breadcrumb.observability', {
defaultMessage: 'Observability',
}),
},
{
text: i18n.translate('observability.home.breadcrumb.gettingStarted', {
defaultMessage: 'Getting started',
}),
},
]);
}, [core.chrome]);
return (
<FixedContainer>
<OverflowContainer>
<TitleContainer>
<CentralizedContainer>
<EuiFlexGroup>
<EuiFlexItem grow={false}>
<EuiIcon type="logoObservability" size="xxl" />
</EuiFlexItem>
<EuiFlexItem>
<EuiTitle size="m">
<h1>
{i18n.translate('observability.home.title', {
defaultMessage: 'Observability',
})}
</h1>
</EuiTitle>
</EuiFlexItem>
</EuiFlexGroup>
</CentralizedContainer>
</TitleContainer>
<BodyContainer>
<CentralizedContainer>
<EuiSpacer size="xl" />
<EuiFlexGroup direction="column">
{/* title and description */}
<EuiFlexItem style={{ maxWidth: 567 }}>
<EuiTitle size="s">
<h2>
{i18n.translate('observability.home.sectionTitle', {
defaultMessage:
'Observability built on the Elastic Stack',
})}
</h2>
</EuiTitle>
<EuiSpacer size="m" />
<EuiText size="s" color="subdued">
{i18n.translate('observability.home.sectionsubtitle', {
defaultMessage:
'Bring your logs, metrics, and APM traces together at scale in a single stack so you can monitor and react to events happening anywhere in your environment.',
})}
</EuiText>
</EuiFlexItem>

{/* Apps sections */}
<EuiFlexItem>
<EuiSpacer size="s" />
<EuiFlexGroup>
<EuiFlexItem>
<EuiFlexGrid columns={2}>
{appsSection.map((app) => (
<Section section={app} key={app.id} />
))}
</EuiFlexGrid>
</EuiFlexItem>
<EuiFlexItem>
<EuiImage
size="xl"
alt="observability overview image"
url="/plugins/observability/assets/observability-overview.png"
cauemarcondes marked this conversation as resolved.
Show resolved Hide resolved
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>

{/* Get started button */}
<EuiFlexItem>
<EuiFlexGroup justifyContent="center" gutterSize="none">
<EuiFlexItem grow={false}>
<EuiButton
fill
iconType="sortRight"
iconSide="right"
style={{ width: 175 }}
href="/app/home#/tutorial_directory/logging"
>
{i18n.translate('observability.home.getStatedButton', {
defaultMessage: 'Get started',
})}
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>

<EuiHorizontalRule margin="xl" />

{/* Try it out */}
<EuiFlexItem>
<EuiFlexGroup justifyContent="center">
<EuiFlexItem grow={false}>
<EuiTitle size="s">
<h3>
{i18n.translate('observability.home.tryItOut', {
defaultMessage: 'Try it out',
})}
</h3>
</EuiTitle>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>

{/* Try it out sections */}
<EuiFlexItem>
<EuiFlexGroup justifyContent="center">
{tryItOutItemsSection.map((item) => (
<EuiFlexItem
grow={false}
key={item.id}
style={{ width: 260 }}
>
<EuiPanel hasShadow paddingSize="s">
<Section section={item} />
</EuiPanel>
</EuiFlexItem>
))}
</EuiFlexGroup>
<EuiSpacer />
</EuiFlexItem>
</EuiFlexGroup>
</CentralizedContainer>
</BodyContainer>
</OverflowContainer>
</FixedContainer>
);
};
62 changes: 62 additions & 0 deletions x-pack/plugins/observability/public/pages/home/section.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* 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 {
EuiButtonEmpty,
EuiFlexGroup,
EuiFlexItem,
EuiIcon,
EuiSpacer,
EuiText,
EuiTitle,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React from 'react';

export interface ISection {
id: string;
title: string;
icon: string;
description: string;
href?: string;
}

export const Section = ({ section }: { section: ISection }) => {
const { id, icon, title, description, href } = section;

const sectionContent = (
<EuiFlexGroup gutterSize="m">
<EuiFlexItem grow={false}>
<EuiIcon type={icon} size="l" color="black" />
</EuiFlexItem>
<EuiFlexItem style={{ textAlign: 'left' }}>
<EuiTitle size="xs">
<h3>
{i18n.translate(`observability.section.${id}.title`, {
defaultMessage: title,
})}
</h3>
</EuiTitle>
<EuiSpacer size="s" />
<EuiText size="s" style={{ whiteSpace: 'normal' }} color="default">
{i18n.translate(`observability.section.${id}.description`, {
defaultMessage: description,
})}
</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
);

if (href) {
return (
<EuiFlexItem>
<EuiButtonEmpty href={href} style={{ height: 'auto' }}>
{sectionContent}
</EuiButtonEmpty>
</EuiFlexItem>
);
}
return <EuiFlexItem>{sectionContent}</EuiFlexItem>;
};
Loading