Skip to content

Commit

Permalink
[APM] Fixing service inventory responsive design (#107690)
Browse files Browse the repository at this point in the history
* fixing service inventory responsive design

* truncate service name

* adding unit test

* addressing PR comments

* fixing test

* fixing merge problem

Co-authored-by: Kibana Machine <[email protected]>
  • Loading branch information
cauemarcondes and kibanamachine authored Aug 10, 2021
1 parent ff9611b commit 97e345f
Show file tree
Hide file tree
Showing 5 changed files with 207 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* 2.0.
*/

import { EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui';
import React from 'react';
import { Coordinate } from '../../../../../typings/timeseries';
import { SparkPlot } from '../../../shared/charts/spark_plot';
Expand All @@ -14,18 +15,32 @@ export function ServiceListMetric({
series,
valueLabel,
comparisonSeries,
hideSeries = false,
}: {
color: 'euiColorVis1' | 'euiColorVis0' | 'euiColorVis7';
series?: Coordinate[];
comparisonSeries?: Coordinate[];
valueLabel: React.ReactNode;
hideSeries?: boolean;
}) {
if (!hideSeries) {
return (
<SparkPlot
valueLabel={valueLabel}
series={series}
color={color}
comparisonSeries={comparisonSeries}
/>
);
}

return (
<SparkPlot
valueLabel={valueLabel}
series={series}
color={color}
comparisonSeries={comparisonSeries}
/>
<EuiFlexGroup gutterSize="none" alignItems="flexEnd">
<EuiFlexItem>
<EuiText size="s" textAlign="right">
{valueLabel}
</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ import { TypeOf } from '@kbn/typed-react-router-config';
import { orderBy } from 'lodash';
import React, { useMemo } from 'react';
import { ValuesType } from 'utility-types';
import { euiStyled } from '../../../../../../../../src/plugins/kibana_react/common';
import {
BreakPoints,
useBreakPoints,
} from '../../../../hooks/use_break_points';
import { NOT_AVAILABLE_LABEL } from '../../../../../common/i18n';
import { ServiceHealthStatus } from '../../../../../common/service_health_status';
import {
Expand All @@ -38,6 +41,7 @@ import { ITableColumn, ManagedTable } from '../../../shared/managed_table';
import { ServiceLink } from '../../../shared/service_link';
import { HealthBadge } from './HealthBadge';
import { ServiceListMetric } from './ServiceListMetric';
import { TruncateWithTooltip } from '../../../shared/truncate_with_tooltip';

type ServiceListAPIResponse = APIReturnType<'GET /api/apm/services'>;
type Items = ServiceListAPIResponse['items'];
Expand All @@ -49,13 +53,6 @@ function formatString(value?: string | null) {
return value || NOT_AVAILABLE_LABEL;
}

const ToolTipWrapper = euiStyled.span`
width: 100%;
.apmServiceList__serviceNameTooltip {
width: 100%;
}
`;

const SERVICE_HEALTH_STATUS_ORDER = [
ServiceHealthStatus.unknown,
ServiceHealthStatus.healthy,
Expand All @@ -67,11 +64,16 @@ export function getServiceColumns({
query,
showTransactionTypeColumn,
comparisonData,
breakPoints,
}: {
query: TypeOf<ApmRoutes, '/services'>['query'];
showTransactionTypeColumn: boolean;
breakPoints: BreakPoints;
comparisonData?: ServicesDetailedStatisticsAPIResponse;
}): Array<ITableColumn<ServiceListItem>> {
const { isSmall, isLarge, isXl } = breakPoints;
const showWhenSmallOrGreaterThanLarge = isSmall || !isLarge;
const showWhenSmallOrGreaterThanXL = isSmall || !isXl;
return [
{
field: 'healthStatus',
Expand All @@ -96,34 +98,38 @@ export function getServiceColumns({
width: '40%',
sortable: true,
render: (_, { serviceName, agentName }) => (
<ToolTipWrapper data-test-subj="apmServiceListAppLink">
<EuiToolTip
delay="long"
content={formatString(serviceName)}
id="service-name-tooltip"
anchorClassName="apmServiceList__serviceNameTooltip"
>
<TruncateWithTooltip
data-test-subj="apmServiceListAppLink"
text={formatString(serviceName)}
content={
<ServiceLink
agentName={agentName}
query={query}
serviceName={serviceName}
/>
</EuiToolTip>
</ToolTipWrapper>
),
},
{
field: 'environments',
name: i18n.translate('xpack.apm.servicesTable.environmentColumnLabel', {
defaultMessage: 'Environment',
}),
width: `${unit * 10}px`,
sortable: true,
render: (_, { environments }) => (
<EnvironmentBadge environments={environments ?? []} />
}
/>
),
},
...(showTransactionTypeColumn
...(showWhenSmallOrGreaterThanLarge
? [
{
field: 'environments',
name: i18n.translate(
'xpack.apm.servicesTable.environmentColumnLabel',
{
defaultMessage: 'Environment',
}
),
width: `${unit * 10}px`,
sortable: true,
render: (_, { environments }) => (
<EnvironmentBadge environments={environments ?? []} />
),
} as ITableColumn<ServiceListItem>,
]
: []),
...(showTransactionTypeColumn && showWhenSmallOrGreaterThanXL
? [
{
field: 'transactionType',
Expand All @@ -149,12 +155,13 @@ export function getServiceColumns({
comparisonSeries={
comparisonData?.previousPeriod[serviceName]?.latency
}
hideSeries={!showWhenSmallOrGreaterThanLarge}
color="euiColorVis1"
valueLabel={asMillisecondDuration(latency || 0)}
/>
),
align: 'left',
width: `${unit * 10}px`,
width: showWhenSmallOrGreaterThanLarge ? `${unit * 10}px` : 'auto',
},
{
field: 'throughput',
Expand All @@ -169,12 +176,13 @@ export function getServiceColumns({
comparisonSeries={
comparisonData?.previousPeriod[serviceName]?.throughput
}
hideSeries={!showWhenSmallOrGreaterThanLarge}
color="euiColorVis0"
valueLabel={asTransactionRate(throughput)}
/>
),
align: 'left',
width: `${unit * 10}px`,
width: showWhenSmallOrGreaterThanLarge ? `${unit * 10}px` : 'auto',
},
{
field: 'transactionErrorRate',
Expand All @@ -193,13 +201,14 @@ export function getServiceColumns({
comparisonSeries={
comparisonData?.previousPeriod[serviceName]?.transactionErrorRate
}
hideSeries={!showWhenSmallOrGreaterThanLarge}
color="euiColorVis7"
valueLabel={valueLabel}
/>
);
},
align: 'left',
width: `${unit * 10}px`,
width: showWhenSmallOrGreaterThanLarge ? `${unit * 10}px` : 'auto',
},
];
}
Expand All @@ -217,6 +226,7 @@ export function ServiceList({
comparisonData,
isLoading,
}: Props) {
const breakPoints = useBreakPoints();
const displayHealthStatus = items.some((item) => 'healthStatus' in item);

const showTransactionTypeColumn = items.some(
Expand All @@ -229,8 +239,13 @@ export function ServiceList({

const serviceColumns = useMemo(
() =>
getServiceColumns({ query, showTransactionTypeColumn, comparisonData }),
[query, showTransactionTypeColumn, comparisonData]
getServiceColumns({
query,
showTransactionTypeColumn,
comparisonData,
breakPoints,
}),
[query, showTransactionTypeColumn, comparisonData, breakPoints]
);

const columns = displayHealthStatus
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import React, { ReactNode } from 'react';
import { MemoryRouter } from 'react-router-dom';
import { BreakPoints } from '../../../../hooks/use_break_points';
import { ServiceHealthStatus } from '../../../../../common/service_health_status';
import { MockApmPluginContextWrapper } from '../../../../context/apm_plugin/mock_apm_plugin_context';
import { mockMoment, renderWithTheme } from '../../../../utils/testHelpers';
Expand Down Expand Up @@ -42,7 +43,12 @@ describe('ServiceList', () => {
).not.toThrowError();
});

it('renders columns correctly', () => {
describe('responsive columns', () => {
const query = {
rangeFrom: 'now-15m',
rangeTo: 'now',
};

const service: any = {
serviceName: 'opbeans-python',
agentName: 'python',
Expand All @@ -59,20 +65,132 @@ describe('ServiceList', () => {
timeseries: [],
},
environments: ['test'],
transactionType: 'request',
};
const renderedColumns = getServiceColumns({
query: {
rangeFrom: 'now-15m',
rangeTo: 'now',
},
showTransactionTypeColumn: false,
}).map((c) => c.render!(service[c.field!], service));

expect(renderedColumns[0]).toMatchInlineSnapshot(`
<HealthBadge
healthStatus="unknown"
/>
`);
describe('when small', () => {
it('shows environment, transaction type and sparklines', () => {
const renderedColumns = getServiceColumns({
query,
showTransactionTypeColumn: true,
breakPoints: {
isSmall: true,
isLarge: true,
isXl: true,
} as BreakPoints,
}).map((c) =>
c.render ? c.render!(service[c.field!], service) : service[c.field!]
);
expect(renderedColumns.length).toEqual(7);
expect(renderedColumns[2]).toMatchInlineSnapshot(`
<EnvironmentBadge
environments={
Array [
"test",
]
}
/>
`);
expect(renderedColumns[3]).toMatchInlineSnapshot(`"request"`);
expect(renderedColumns[4]).toMatchInlineSnapshot(`
<ServiceListMetric
color="euiColorVis1"
hideSeries={false}
valueLabel="0 ms"
/>
`);
});
});

describe('when Large', () => {
it('hides environment, transaction type and sparklines', () => {
const renderedColumns = getServiceColumns({
query,
showTransactionTypeColumn: true,
breakPoints: {
isSmall: false,
isLarge: true,
isXl: true,
} as BreakPoints,
}).map((c) =>
c.render ? c.render!(service[c.field!], service) : service[c.field!]
);
expect(renderedColumns.length).toEqual(5);
expect(renderedColumns[2]).toMatchInlineSnapshot(`
<ServiceListMetric
color="euiColorVis1"
hideSeries={true}
valueLabel="0 ms"
/>
`);
});

describe('when XL', () => {
it('hides transaction type', () => {
const renderedColumns = getServiceColumns({
query,
showTransactionTypeColumn: true,
breakPoints: {
isSmall: false,
isLarge: false,
isXl: true,
} as BreakPoints,
}).map((c) =>
c.render ? c.render!(service[c.field!], service) : service[c.field!]
);
expect(renderedColumns.length).toEqual(6);
expect(renderedColumns[2]).toMatchInlineSnapshot(`
<EnvironmentBadge
environments={
Array [
"test",
]
}
/>
`);
expect(renderedColumns[3]).toMatchInlineSnapshot(`
<ServiceListMetric
color="euiColorVis1"
hideSeries={false}
valueLabel="0 ms"
/>
`);
});
});

describe('when XXL', () => {
it('hides transaction type', () => {
const renderedColumns = getServiceColumns({
query,
showTransactionTypeColumn: true,
breakPoints: {
isSmall: false,
isLarge: false,
isXl: false,
} as BreakPoints,
}).map((c) =>
c.render ? c.render!(service[c.field!], service) : service[c.field!]
);
expect(renderedColumns.length).toEqual(7);
expect(renderedColumns[2]).toMatchInlineSnapshot(`
<EnvironmentBadge
environments={
Array [
"test",
]
}
/>
`);
expect(renderedColumns[3]).toMatchInlineSnapshot(`"request"`);
expect(renderedColumns[4]).toMatchInlineSnapshot(`
<ServiceListMetric
color="euiColorVis1"
hideSeries={false}
valueLabel="0 ms"
/>
`);
});
});
});
});

describe('without ML data', () => {
Expand Down
Loading

0 comments on commit 97e345f

Please sign in to comment.