Skip to content

Commit

Permalink
[APM] Add support for dark mode (elastic#69362)
Browse files Browse the repository at this point in the history
* Use theme colors for stacktrace

* [APM] Use theme for all components

* Switch HoC withTheme to useTheme and convert classes to hooks

* Change hardcoded white to euiColorEmptyShade for ServiceMap

* Snapshots and Legends fix

* Switch to context and add test helper

* Fix tests and update snaps

* New snaps + new anomaly detection

* Remove shallow from testHelpers

* Remove commented tests

* Fix prettier

* Pass correct theme to cytoscape

* Fix ServiceMap

* fixes some rendering issues in service maps

* removed the old anomaly detection logic from service map popover contents, since it's been moved to a new component.

* Fix eslint, tsc lint issues and unit tests

* Remove types for styled-components default theme

* Update x-pack/plugins/apm/public/components/shared/KueryBar/Typeahead/Suggestions.js

Co-authored-by: Casper Hübertz <casper@formgeist.com>

* fix OuterTheme

* Ise function declaration instead of expression

Co-authored-by: Balthazar Gronon <git@balthazar.dev>
Co-authored-by: Balthazar Gronon <bgronon@gmail.com>
Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
Co-authored-by: Oliver Gupte <olivergupte@gmail.com>
Co-authored-by: Casper Hübertz <casper@formgeist.com>
# Conflicts:
#	x-pack/plugins/apm/public/components/app/ServiceMap/index.tsx
  • Loading branch information
sorenlouv committed Jun 20, 2020
1 parent 49ebf03 commit 1fb00c4
Show file tree
Hide file tree
Showing 55 changed files with 602 additions and 531 deletions.
15 changes: 11 additions & 4 deletions x-pack/plugins/apm/public/application/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import { ApmRoute } from '@elastic/apm-rum-react';
import React from 'react';
import ReactDOM from 'react-dom';
import { Route, Router, Switch } from 'react-router-dom';
import styled from 'styled-components';
import { EuiThemeProvider } from '../../../observability/public';
import styled, { ThemeProvider, DefaultTheme } from 'styled-components';
import euiDarkVars from '@elastic/eui/dist/eui_theme_dark.json';
import euiLightVars from '@elastic/eui/dist/eui_theme_light.json';
import { CoreStart, AppMountParameters } from '../../../../../src/core/public';
import { ApmPluginSetupDeps } from '../plugin';
import { ApmPluginContext } from '../context/ApmPluginContext';
Expand Down Expand Up @@ -42,7 +43,13 @@ const App = () => {
const [darkMode] = useUiSetting$<boolean>('theme:darkMode');

return (
<EuiThemeProvider darkMode={darkMode}>
<ThemeProvider
theme={(outerTheme?: DefaultTheme) => ({
...outerTheme,
eui: darkMode ? euiDarkVars : euiLightVars,
darkMode,
})}
>
<MainContainer data-test-subj="apmMainContainer" role="main">
<UpdateBreadcrumbs routes={routes} />
<Route component={ScrollToTopOnPathChange} />
Expand All @@ -54,7 +61,7 @@ const App = () => {
</Switch>
</APMIndicesPermission>
</MainContainer>
</EuiThemeProvider>
</ThemeProvider>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
EuiText,
EuiTitle,
} from '@elastic/eui';
import theme from '@elastic/eui/dist/eui_theme_light.json';
import { i18n } from '@kbn/i18n';
import React, { Fragment } from 'react';
import styled from 'styled-components';
Expand All @@ -34,7 +33,7 @@ const Titles = styled.div`
const Label = styled.div`
margin-bottom: ${px(units.quarter)};
font-size: ${fontSizes.small};
color: ${theme.euiColorMediumShade};
color: ${({ theme }) => theme.eui.euiColorMediumShade};
`;

const Message = styled.div`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@
*/

import { EuiBetaBadge } from '@elastic/eui';
import theme from '@elastic/eui/dist/eui_theme_light.json';
import { i18n } from '@kbn/i18n';
import React from 'react';
import styled from 'styled-components';

const BetaBadgeContainer = styled.div`
right: ${theme.gutterTypes.gutterMedium};
right: ${({ theme }) => theme.eui.gutterTypes.gutterMedium};
position: absolute;
top: ${theme.gutterTypes.gutterSmall};
top: ${({ theme }) => theme.eui.gutterTypes.gutterSmall};
z-index: 1; /* The element containing the cytoscape canvas has z-index = 0. */
`;

Expand Down
33 changes: 19 additions & 14 deletions x-pack/plugins/apm/public/components/app/ServiceMap/Controls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,41 +4,44 @@
* you may not use this file except in compliance with the Elastic License.
*/

import React, { useContext, useEffect, useState } from 'react';
import { EuiButtonIcon, EuiPanel, EuiToolTip } from '@elastic/eui';
import theme from '@elastic/eui/dist/eui_theme_light.json';
import { i18n } from '@kbn/i18n';
import React, { useContext, useEffect, useState } from 'react';
import styled from 'styled-components';
import { CytoscapeContext } from './Cytoscape';
import { animationOptions, nodeHeight } from './cytoscapeOptions';
import { getAnimationOptions, getNodeHeight } from './cytoscapeOptions';
import { getAPMHref } from '../../shared/Links/apm/APMLink';
import { useUrlParams } from '../../../hooks/useUrlParams';
import { APMQueryParams } from '../../shared/Links/url_helpers';
import { useTheme } from '../../../hooks/useTheme';

const ControlsContainer = styled('div')`
left: ${theme.gutterTypes.gutterMedium};
left: ${({ theme }) => theme.eui.gutterTypes.gutterMedium};
position: absolute;
top: ${theme.gutterTypes.gutterSmall};
top: ${({ theme }) => theme.eui.gutterTypes.gutterSmall};
z-index: 1; /* The element containing the cytoscape canvas has z-index = 0. */
`;

const Button = styled(EuiButtonIcon)`
display: block;
margin: ${theme.paddingSizes.xs};
margin: ${({ theme }) => theme.eui.paddingSizes.xs};
`;

const ZoomInButton = styled(Button)`
margin-bottom: ${theme.paddingSizes.s};
margin-bottom: ${({ theme }) => theme.eui.paddingSizes.s};
`;

const Panel = styled(EuiPanel)`
margin-bottom: ${theme.paddingSizes.s};
margin-bottom: ${({ theme }) => theme.eui.paddingSizes.s};
`;

const duration = parseInt(theme.euiAnimSpeedFast, 10);
const steps = 5;

function doZoom(cy: cytoscape.Core | undefined, increment: number) {
function doZoom(
cy: cytoscape.Core | undefined,
increment: number,
duration: number
) {
if (cy) {
const level = cy.zoom() + increment;
// @ts-ignore `.position()` _does_ work on a NodeCollection. It returns the position of the first element in the collection.
Expand Down Expand Up @@ -93,10 +96,12 @@ function useDebugDownloadUrl(cy?: cytoscape.Core) {
}

export function Controls() {
const theme = useTheme();
const cy = useContext(CytoscapeContext);
const { urlParams } = useUrlParams();
const currentSearch = urlParams.kuery ?? '';
const [zoom, setZoom] = useState((cy && cy.zoom()) || 1);
const duration = parseInt(theme.eui.euiAnimSpeedFast, 10);
const downloadUrl = useDebugDownloadUrl(cy);

// Handle zoom events
Expand All @@ -120,19 +125,19 @@ export function Controls() {
if (cy) {
const eles = cy.nodes();
cy.animate({
...animationOptions,
...getAnimationOptions(theme),
center: { eles },
fit: { eles, padding: nodeHeight },
fit: { eles, padding: getNodeHeight(theme) },
});
}
}

function zoomIn() {
doZoom(cy, increment);
doZoom(cy, increment, duration);
}

function zoomOut() {
doZoom(cy, -increment);
doZoom(cy, -increment, duration);
}

if (!cy) {
Expand Down
32 changes: 23 additions & 9 deletions x-pack/plugins/apm/public/components/app/ServiceMap/Cytoscape.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/

import cytoscape from 'cytoscape';
import React, {
createContext,
CSSProperties,
Expand All @@ -13,11 +12,13 @@ import React, {
useRef,
useState,
} from 'react';
import cytoscape from 'cytoscape';
import { debounce } from 'lodash';
import { useTheme } from '../../../hooks/useTheme';
import {
animationOptions,
cytoscapeOptions,
nodeHeight,
getAnimationOptions,
getCytoscapeOptions,
getNodeHeight,
} from './cytoscapeOptions';
import { useUiTracker } from '../../../../../observability/public';

Expand Down Expand Up @@ -73,7 +74,8 @@ function rotatePoint(
function getLayoutOptions(
selectedRoots: string[],
height: number,
width: number
width: number,
nodeHeight: number
): cytoscape.LayoutOptions {
return {
name: 'breadthfirst',
Expand Down Expand Up @@ -111,11 +113,14 @@ export function Cytoscape({
serviceName,
style,
}: CytoscapeProps) {
const theme = useTheme();
const [ref, cy] = useCytoscape({
...cytoscapeOptions,
...getCytoscapeOptions(theme),
elements,
});

const nodeHeight = getNodeHeight(theme);

// Add the height to the div style. The height is a separate prop because it
// is required and can trigger rendering when changed.
const divStyle = { ...style, height };
Expand Down Expand Up @@ -149,7 +154,7 @@ export function Cytoscape({

const selectedRoots = selectRoots(event.cy);
const layout = cy.layout(
getLayoutOptions(selectedRoots, height, width)
getLayoutOptions(selectedRoots, height, width, nodeHeight)
);

layout.run();
Expand All @@ -162,7 +167,7 @@ export function Cytoscape({
layoutstopDelayTimeout = setTimeout(() => {
if (serviceName) {
event.cy.animate({
...animationOptions,
...getAnimationOptions(theme),
fit: {
eles: event.cy.elements(),
padding: nodeHeight,
Expand Down Expand Up @@ -237,7 +242,16 @@ export function Cytoscape({
}
clearTimeout(layoutstopDelayTimeout);
};
}, [cy, elements, height, serviceName, trackApmEvent, width]);
}, [
cy,
elements,
height,
serviceName,
trackApmEvent,
width,
nodeHeight,
theme,
]);

return (
<CytoscapeContext.Provider value={cy}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { act, render, wait } from '@testing-library/react';
import cytoscape from 'cytoscape';
import React, { FunctionComponent } from 'react';
import { act, wait } from '@testing-library/react';
import cytoscape from 'cytoscape';
import { CytoscapeContext } from './Cytoscape';
import { EmptyBanner } from './EmptyBanner';
import { MockApmPluginContextWrapper } from '../../../context/ApmPluginContext/MockApmPluginContext';
import { renderWithTheme } from '../../../utils/testHelpers';

const cy = cytoscape({});

Expand All @@ -29,7 +30,7 @@ describe('EmptyBanner', () => {
</CytoscapeContext.Provider>
</MockApmPluginContextWrapper>
);
const component = render(<EmptyBanner />, {
const component = renderWithTheme(<EmptyBanner />, {
wrapper: noCytoscapeWrapper,
});

Expand All @@ -39,7 +40,7 @@ describe('EmptyBanner', () => {

describe('with no nodes', () => {
it('renders null', () => {
const component = render(<EmptyBanner />, {
const component = renderWithTheme(<EmptyBanner />, {
wrapper,
});

Expand All @@ -49,7 +50,7 @@ describe('EmptyBanner', () => {

describe('with one node', () => {
it('does not render null', async () => {
const component = render(<EmptyBanner />, { wrapper });
const component = renderWithTheme(<EmptyBanner />, { wrapper });

await act(async () => {
cy.add({ data: { id: 'test id' } });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,27 @@
* you may not use this file except in compliance with the Elastic License.
*/

import React, { useContext, useEffect, useState } from 'react';
import { EuiCallOut } from '@elastic/eui';
import lightTheme from '@elastic/eui/dist/eui_theme_light.json';
import { i18n } from '@kbn/i18n';
import React, { useContext, useEffect, useState } from 'react';
import styled from 'styled-components';
import { ElasticDocsLink } from '../../shared/Links/ElasticDocsLink';
import { CytoscapeContext } from './Cytoscape';
import { useTheme } from '../../../hooks/useTheme';

const EmptyBannerContainer = styled.div`
margin: ${lightTheme.gutterTypes.gutterSmall};
margin: ${({ theme }) => theme.eui.gutterTypes.gutterSmall};
/* Add some extra margin so it displays to the right of the controls. */
left: calc(
${lightTheme.gutterTypes.gutterExtraLarge} +
${lightTheme.gutterTypes.gutterSmall}
${({ theme }) => theme.eui.gutterTypes.gutterExtraLarge} +
${({ theme }) => theme.eui.gutterTypes.gutterSmall}
);
position: absolute;
z-index: 1;
`;

export function EmptyBanner() {
const theme = useTheme();
const cy = useContext(CytoscapeContext);
const [nodeCount, setNodeCount] = useState(0);

Expand Down Expand Up @@ -51,8 +52,8 @@ export function EmptyBanner() {
// subtract the space for controls and margins.
const width =
cy.width() -
parseInt(lightTheme.gutterTypes.gutterExtraLarge, 10) -
parseInt(lightTheme.gutterTypes.gutterLarge, 10);
parseInt(theme.eui.gutterTypes.gutterExtraLarge, 10) -
parseInt(theme.eui.gutterTypes.gutterLarge, 10);

return (
<EmptyBannerContainer style={{ width }}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/

import theme from '@elastic/eui/dist/eui_theme_light.json';
import React from 'react';
import { EuiProgress, EuiText, EuiSpacer } from '@elastic/eui';
import styled from 'styled-components';
Expand All @@ -22,7 +21,7 @@ const Overlay = styled.div`
flex-direction: column;
align-items: center;
width: 100%;
padding: ${theme.gutterTypes.gutterMedium};
padding: ${({ theme }) => theme.eui.gutterTypes.gutterMedium};
`;

const ProgressBarContainer = styled.div`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/

import lightTheme from '@elastic/eui/dist/eui_theme_light.json';
import { i18n } from '@kbn/i18n';
import cytoscape from 'cytoscape';
import React from 'react';
Expand All @@ -19,7 +18,7 @@ const ItemRow = styled.div`
`;

const ItemTitle = styled.dt`
color: ${lightTheme.textColors.subdued};
color: ${({ theme }) => theme.eui.textColors.subdued};
`;

const ItemDescription = styled.dd``;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
*/

import { EuiFlexGroup, EuiLoadingSpinner } from '@elastic/eui';
import lightTheme from '@elastic/eui/dist/eui_theme_light.json';
import { i18n } from '@kbn/i18n';
import { isNumber } from 'lodash';
import React from 'react';
Expand All @@ -30,7 +29,7 @@ export const ItemRow = styled('tr')`
`;

export const ItemTitle = styled('td')`
color: ${lightTheme.textColors.subdued};
color: ${({ theme }) => theme.eui.textColors.subdued};
padding-right: 1rem;
`;

Expand Down
Loading

0 comments on commit 1fb00c4

Please sign in to comment.