(0);
-
- useEffect(() => {
- if (containerElement.current) {
- const currentHeight = containerElement.current.clientHeight;
- if (minHeight.current < currentHeight) {
- minHeight.current = currentHeight;
- }
- }
- });
-
- return (
-
- );
-};
diff --git a/x-pack/plugins/apm/public/components/shared/Links/ElasticDocsLink.tsx b/x-pack/plugins/apm/public/components/shared/Links/ElasticDocsLink.tsx
new file mode 100644
index 00000000000000..b63671f63a1e7f
--- /dev/null
+++ b/x-pack/plugins/apm/public/components/shared/Links/ElasticDocsLink.tsx
@@ -0,0 +1,25 @@
+/*
+ * 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 { EuiLink, EuiLinkAnchorProps } from '@elastic/eui';
+import { metadata } from 'ui/metadata';
+
+// TODO: metadata should be read from a useContext hook in new platform
+const STACK_VERSION = metadata.branch;
+
+// union type constisting of valid guide sections that we link to
+type DocsSection = '/apm/get-started' | '/x-pack';
+
+interface Props extends EuiLinkAnchorProps {
+ section: DocsSection;
+ path: string;
+}
+
+export function ElasticDocsLink({ section, path, ...rest }: Props) {
+ const href = `https://www.elastic.co/guide/en${section}/${STACK_VERSION}${path}`;
+ return ;
+}
diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/__test__/ErrorMetadata.test.tsx b/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/__test__/ErrorMetadata.test.tsx
new file mode 100644
index 00000000000000..0ecf133f23e730
--- /dev/null
+++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/__test__/ErrorMetadata.test.tsx
@@ -0,0 +1,126 @@
+/*
+ * 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 { ErrorMetadata } from '..';
+import { render, cleanup } from 'react-testing-library';
+import { APMError } from '../../../../../../typings/es_schemas/ui/APMError';
+import 'jest-dom/extend-expect';
+import {
+ expectTextsInDocument,
+ expectTextsNotInDocument
+} from '../../../../../utils/testHelpers';
+
+function getError() {
+ return ({
+ labels: { someKey: 'labels value' },
+ http: { someKey: 'http value' },
+ host: { someKey: 'host value' },
+ container: { someKey: 'container value' },
+ service: { someKey: 'service value' },
+ process: { someKey: 'process value' },
+ agent: { someKey: 'agent value' },
+ url: { someKey: 'url value' },
+ user: { someKey: 'user value' },
+ notIncluded: 'not included value',
+ error: {
+ notIncluded: 'error not included value',
+ custom: {
+ someKey: 'custom value'
+ }
+ }
+ } as unknown) as APMError;
+}
+
+describe('ErrorMetadata', () => {
+ afterEach(cleanup);
+
+ it('should render a error with all sections', () => {
+ const error = getError();
+ const output = render();
+
+ // sections
+ expectTextsInDocument(output, [
+ 'Labels',
+ 'HTTP',
+ 'Host',
+ 'Container',
+ 'Service',
+ 'Process',
+ 'Agent',
+ 'URL',
+ 'User',
+ 'Custom'
+ ]);
+ });
+
+ it('should render a error with all included dot notation keys', () => {
+ const error = getError();
+ const output = render();
+
+ // included keys
+ expectTextsInDocument(output, [
+ 'labels.someKey',
+ 'http.someKey',
+ 'host.someKey',
+ 'container.someKey',
+ 'service.someKey',
+ 'process.someKey',
+ 'agent.someKey',
+ 'url.someKey',
+ 'user.someKey',
+ 'error.custom.someKey'
+ ]);
+
+ // excluded keys
+ expectTextsNotInDocument(output, ['notIncluded', 'error.notIncluded']);
+ });
+
+ it('should render a error with all included values', () => {
+ const error = getError();
+ const output = render();
+
+ // included values
+ expectTextsInDocument(output, [
+ 'labels value',
+ 'http value',
+ 'host value',
+ 'container value',
+ 'service value',
+ 'process value',
+ 'agent value',
+ 'url value',
+ 'user value',
+ 'custom value'
+ ]);
+
+ // excluded values
+ expectTextsNotInDocument(output, [
+ 'not included value',
+ 'error not included value'
+ ]);
+ });
+
+ it('should render a error with only the required sections', () => {
+ const error = {} as APMError;
+ const output = render();
+
+ // required sections should be found
+ expectTextsInDocument(output, ['Labels', 'User']);
+
+ // optional sections should NOT be found
+ expectTextsNotInDocument(output, [
+ 'HTTP',
+ 'Host',
+ 'Container',
+ 'Service',
+ 'Process',
+ 'Agent',
+ 'URL',
+ 'Custom'
+ ]);
+ });
+});
diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/index.tsx b/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/index.tsx
new file mode 100644
index 00000000000000..4891dbcfa921db
--- /dev/null
+++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/index.tsx
@@ -0,0 +1,18 @@
+/*
+ * 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 { MetadataTable } from '..';
+import { ERROR_METADATA_SECTIONS } from './sections';
+import { APMError } from '../../../../../typings/es_schemas/ui/APMError';
+
+interface Props {
+ error: APMError;
+}
+
+export function ErrorMetadata({ error }: Props) {
+ return ;
+}
diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/sections.ts b/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/sections.ts
new file mode 100644
index 00000000000000..de733579b1d34d
--- /dev/null
+++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/ErrorMetadata/sections.ts
@@ -0,0 +1,52 @@
+/*
+ * 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 SECTION_LABELS from '../sectionLabels';
+
+export const ERROR_METADATA_SECTIONS = [
+ {
+ key: 'labels',
+ label: SECTION_LABELS.LABELS,
+ required: true
+ },
+ {
+ key: 'http',
+ label: SECTION_LABELS.HTTP
+ },
+ {
+ key: 'host',
+ label: SECTION_LABELS.HOST
+ },
+ {
+ key: 'container',
+ label: SECTION_LABELS.CONTAINER
+ },
+ {
+ key: 'service',
+ label: SECTION_LABELS.SERVICE
+ },
+ {
+ key: 'process',
+ label: SECTION_LABELS.PROCESS
+ },
+ {
+ key: 'agent',
+ label: SECTION_LABELS.AGENT
+ },
+ {
+ key: 'url',
+ label: SECTION_LABELS.URL
+ },
+ {
+ key: 'user',
+ label: SECTION_LABELS.USER,
+ required: true
+ },
+ {
+ key: 'error.custom',
+ label: SECTION_LABELS.CUSTOM
+ }
+];
diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/__test__/TransactionMetadata.test.tsx b/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/__test__/TransactionMetadata.test.tsx
new file mode 100644
index 00000000000000..8fa6424a7f9fdf
--- /dev/null
+++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/__test__/TransactionMetadata.test.tsx
@@ -0,0 +1,129 @@
+/*
+ * 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 { TransactionMetadata } from '..';
+import { render, cleanup } from 'react-testing-library';
+import { Transaction } from '../../../../../../typings/es_schemas/ui/Transaction';
+import 'jest-dom/extend-expect';
+import {
+ expectTextsInDocument,
+ expectTextsNotInDocument
+} from '../../../../../utils/testHelpers';
+
+function getTransaction() {
+ return ({
+ labels: { someKey: 'labels value' },
+ http: { someKey: 'http value' },
+ host: { someKey: 'host value' },
+ container: { someKey: 'container value' },
+ service: { someKey: 'service value' },
+ process: { someKey: 'process value' },
+ agent: { someKey: 'agent value' },
+ url: { someKey: 'url value' },
+ user: { someKey: 'user value' },
+ notIncluded: 'not included value',
+ transaction: {
+ notIncluded: 'transaction not included value',
+ custom: {
+ someKey: 'custom value'
+ }
+ }
+ } as unknown) as Transaction;
+}
+
+describe('TransactionMetadata', () => {
+ afterEach(cleanup);
+
+ it('should render a transaction with all sections', () => {
+ const transaction = getTransaction();
+ const output = render();
+
+ // sections
+ expectTextsInDocument(output, [
+ 'Labels',
+ 'HTTP',
+ 'Host',
+ 'Container',
+ 'Service',
+ 'Process',
+ 'Agent',
+ 'URL',
+ 'User',
+ 'Custom'
+ ]);
+ });
+
+ it('should render a transaction with all included dot notation keys', () => {
+ const transaction = getTransaction();
+ const output = render();
+
+ // included keys
+ expectTextsInDocument(output, [
+ 'labels.someKey',
+ 'http.someKey',
+ 'host.someKey',
+ 'container.someKey',
+ 'service.someKey',
+ 'process.someKey',
+ 'agent.someKey',
+ 'url.someKey',
+ 'user.someKey',
+ 'transaction.custom.someKey'
+ ]);
+
+ // excluded keys
+ expectTextsNotInDocument(output, [
+ 'notIncluded',
+ 'transaction.notIncluded'
+ ]);
+ });
+
+ it('should render a transaction with all included values', () => {
+ const transaction = getTransaction();
+ const output = render();
+
+ // included values
+ expectTextsInDocument(output, [
+ 'labels value',
+ 'http value',
+ 'host value',
+ 'container value',
+ 'service value',
+ 'process value',
+ 'agent value',
+ 'url value',
+ 'user value',
+ 'custom value'
+ ]);
+
+ // excluded values
+ expectTextsNotInDocument(output, [
+ 'not included value',
+ 'transaction not included value'
+ ]);
+ });
+
+ it('should render a transaction with only the required sections', () => {
+ const transaction = {} as Transaction;
+ const output = render();
+
+ // required sections should be found
+ expectTextsInDocument(output, ['Labels', 'User']);
+
+ // optional sections should NOT be found
+ expectTextsNotInDocument(output, [
+ 'HTTP',
+ 'Host',
+ 'Container',
+ 'Service',
+ 'Process',
+ 'Agent',
+ 'URL',
+ 'Custom'
+ ]);
+ });
+});
diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/index.tsx b/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/index.tsx
new file mode 100644
index 00000000000000..95072490b0f380
--- /dev/null
+++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/index.tsx
@@ -0,0 +1,23 @@
+/*
+ * 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 { MetadataTable } from '..';
+import { TRANSACTION_METADATA_SECTIONS } from './sections';
+import { Transaction } from '../../../../../typings/es_schemas/ui/Transaction';
+
+interface Props {
+ transaction: Transaction;
+}
+
+export function TransactionMetadata({ transaction }: Props) {
+ return (
+
+ );
+}
diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/sections.ts b/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/sections.ts
new file mode 100644
index 00000000000000..d299838a6c0070
--- /dev/null
+++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/TransactionMetadata/sections.ts
@@ -0,0 +1,52 @@
+/*
+ * 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 SECTION_LABELS from '../sectionLabels';
+
+export const TRANSACTION_METADATA_SECTIONS = [
+ {
+ key: 'labels',
+ label: SECTION_LABELS.LABELS,
+ required: true
+ },
+ {
+ key: 'http',
+ label: SECTION_LABELS.HTTP
+ },
+ {
+ key: 'host',
+ label: SECTION_LABELS.HOST
+ },
+ {
+ key: 'container',
+ label: SECTION_LABELS.CONTAINER
+ },
+ {
+ key: 'service',
+ label: SECTION_LABELS.SERVICE
+ },
+ {
+ key: 'process',
+ label: SECTION_LABELS.PROCESS
+ },
+ {
+ key: 'agent',
+ label: SECTION_LABELS.AGENT
+ },
+ {
+ key: 'url',
+ label: SECTION_LABELS.URL
+ },
+ {
+ key: 'user',
+ label: SECTION_LABELS.USER,
+ required: true
+ },
+ {
+ key: 'transaction.custom',
+ label: SECTION_LABELS.CUSTOM
+ }
+];
diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/index.tsx b/x-pack/plugins/apm/public/components/shared/MetadataTable/index.tsx
new file mode 100644
index 00000000000000..216a7a5997f100
--- /dev/null
+++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/index.tsx
@@ -0,0 +1,87 @@
+/*
+ * 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 {
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiIcon,
+ EuiSpacer,
+ EuiTitle
+} from '@elastic/eui';
+import React from 'react';
+import { get, has } from 'lodash';
+import { EuiText } from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import { Transaction } from '../../../../typings/es_schemas/ui/Transaction';
+import { APMError } from '../../../../typings/es_schemas/ui/APMError';
+import { StringMap } from '../../../../typings/common';
+import { DottedKeyValueTable } from '../DottedKeyValueTable';
+import { ElasticDocsLink } from '../../shared/Links/ElasticDocsLink';
+
+type MetadataItem = Transaction | APMError;
+
+interface Props {
+ item: MetadataItem;
+ sections: MetadataSection[];
+}
+
+export interface MetadataSection {
+ key: string;
+ label: string;
+ required?: boolean;
+}
+
+export function MetadataTable({ item, sections }: Props) {
+ const filteredSections = sections.filter(
+ ({ key, required }) => required || has(item, key)
+ );
+ return (
+
+
+
+
+
+ How to add labels and other data
+
+
+
+
+ {filteredSections.map(section => (
+
+
+ {section.label}
+
+
+
+
+
+ ))}
+
+ );
+}
+
+function Section({
+ propData,
+ propKey
+}: {
+ propData?: StringMap;
+ propKey?: string;
+}) {
+ return (
+
+ {propData ? (
+
+ ) : (
+
+ {i18n.translate(
+ 'xpack.apm.propertiesTable.agentFeature.noDataAvailableLabel',
+ { defaultMessage: 'No data available' }
+ )}
+
+ )}
+
+ );
+}
diff --git a/x-pack/plugins/apm/public/components/shared/MetadataTable/sectionLabels.ts b/x-pack/plugins/apm/public/components/shared/MetadataTable/sectionLabels.ts
new file mode 100644
index 00000000000000..4c892bb36623d3
--- /dev/null
+++ b/x-pack/plugins/apm/public/components/shared/MetadataTable/sectionLabels.ts
@@ -0,0 +1,74 @@
+/*
+ * 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 { i18n } from '@kbn/i18n';
+
+export const LABELS = i18n.translate(
+ 'xpack.apm.metadataTable.section.labelsLabel',
+ {
+ defaultMessage: 'Labels'
+ }
+);
+
+export const HTTP = i18n.translate(
+ 'xpack.apm.metadataTable.section.httpLabel',
+ {
+ defaultMessage: 'HTTP'
+ }
+);
+
+export const HOST = i18n.translate(
+ 'xpack.apm.metadataTable.section.hostLabel',
+ {
+ defaultMessage: 'Host'
+ }
+);
+
+export const CONTAINER = i18n.translate(
+ 'xpack.apm.metadataTable.section.containerLabel',
+ {
+ defaultMessage: 'Container'
+ }
+);
+
+export const SERVICE = i18n.translate(
+ 'xpack.apm.metadataTable.section.serviceLabel',
+ {
+ defaultMessage: 'Service'
+ }
+);
+
+export const PROCESS = i18n.translate(
+ 'xpack.apm.metadataTable.section.processLabel',
+ {
+ defaultMessage: 'Process'
+ }
+);
+
+export const AGENT = i18n.translate(
+ 'xpack.apm.metadataTable.section.agentLabel',
+ {
+ defaultMessage: 'Agent'
+ }
+);
+
+export const URL = i18n.translate('xpack.apm.metadataTable.section.urlLabel', {
+ defaultMessage: 'URL'
+});
+
+export const USER = i18n.translate(
+ 'xpack.apm.metadataTable.section.userLabel',
+ {
+ defaultMessage: 'User'
+ }
+);
+
+export const CUSTOM = i18n.translate(
+ 'xpack.apm.metadataTable.section.customLabel',
+ {
+ defaultMessage: 'Custom'
+ }
+);
diff --git a/x-pack/plugins/apm/public/components/shared/PropertiesTable/NestedKeyValueTable.tsx b/x-pack/plugins/apm/public/components/shared/PropertiesTable/NestedKeyValueTable.tsx
deleted file mode 100644
index 4db5018dad859c..00000000000000
--- a/x-pack/plugins/apm/public/components/shared/PropertiesTable/NestedKeyValueTable.tsx
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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 theme from '@elastic/eui/dist/eui_theme_light.json';
-import { isBoolean, isNumber, isObject } from 'lodash';
-import React from 'react';
-import styled from 'styled-components';
-import { NOT_AVAILABLE_LABEL } from '../../../../common/i18n';
-import { StringMap } from '../../../../typings/common';
-import { fontFamilyCode, fontSize, px, units } from '../../../style/variables';
-import { sortKeysByConfig } from './tabConfig';
-
-const Table = styled.table`
- font-family: ${fontFamilyCode};
- font-size: ${fontSize};
- width: 100%;
-`;
-
-const Row = styled.tr`
- border-bottom: ${px(1)} solid ${theme.euiColorLightShade};
- &:last-child {
- border: 0;
- }
-`;
-
-const Cell = styled.td`
- vertical-align: top;
- padding: ${px(units.half)} 0;
- line-height: 1.5;
-
- ${Row}:first-child> & {
- padding-top: 0;
- }
-
- ${Row}:last-child> & {
- padding-bottom: 0;
- }
-
- &:first-child {
- width: ${px(units.unit * 12)};
- font-weight: bold;
- }
-`;
-
-const EmptyValue = styled.span`
- color: ${theme.euiColorMediumShade};
-`;
-
-export function FormattedKey({
- k,
- value
-}: {
- k: string;
- value: unknown;
-}): JSX.Element {
- if (value == null) {
- return {k};
- }
-
- return {k};
-}
-
-export function FormattedValue({ value }: { value: any }): JSX.Element {
- if (isObject(value)) {
- return {JSON.stringify(value, null, 4)}
;
- } else if (isBoolean(value) || isNumber(value)) {
- return {String(value)};
- } else if (!value) {
- return {NOT_AVAILABLE_LABEL};
- }
-
- return {value};
-}
-
-export function NestedValue({
- parentKey,
- value,
- depth
-}: {
- value: unknown;
- depth: number;
- parentKey?: string;
-}): JSX.Element {
- const MAX_LEVEL = 3;
- if (depth < MAX_LEVEL && isObject(value)) {
- return (
-
- );
- }
-
- return ;
-}
-
-export function NestedKeyValueTable({
- data,
- parentKey,
- depth
-}: {
- data: StringMap;
- parentKey?: string;
- depth: number;
-}): JSX.Element {
- return (
-
-
- {sortKeysByConfig(data, parentKey).map(key => (
-
-
-
- |
-
-
- |
-
- ))}
-
-
- );
-}
diff --git a/x-pack/plugins/apm/public/components/shared/PropertiesTable/__test__/NestedKeyValueTable.test.tsx b/x-pack/plugins/apm/public/components/shared/PropertiesTable/__test__/NestedKeyValueTable.test.tsx
deleted file mode 100644
index a749a741b93cfd..00000000000000
--- a/x-pack/plugins/apm/public/components/shared/PropertiesTable/__test__/NestedKeyValueTable.test.tsx
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * 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, shallow } from 'enzyme';
-import 'jest-styled-components';
-import React from 'react';
-import {
- FormattedKey,
- FormattedValue,
- NestedKeyValueTable,
- NestedValue
-} from '../NestedKeyValueTable';
-
-describe('NestedKeyValueTable component', () => {
- it('should render with data', () => {
- const testData = {
- a: 1,
- b: 2,
- c: [3, 4, 5],
- d: { aa: 1, bb: 2 }
- };
- expect(
- shallow()
- ).toMatchSnapshot();
- });
-
- it('should render an empty table if there is no data', () => {
- expect(
- shallow()
- ).toMatchSnapshot();
- });
-});
-
-describe('NestedValue component', () => {
- it('should render a formatted value when depth is 0', () => {
- const wrapper = shallow(
-
- );
-
- expect(
- wrapper.equals(
-
- )
- ).toBe(true);
- });
-
- it('should render a formatted value when depth > 0 but value is not an object', () => {
- expect(
- shallow()
- ).toMatchSnapshot();
- });
-
- it('should render a nested KV Table when depth > 0 and value is an object', () => {
- expect(
- shallow(
-
- )
- ).toMatchSnapshot();
- });
-});
-
-describe('FormattedValue component', () => {
- it('should render an object', () => {
- expect(mount()).toMatchSnapshot();
- });
-
- it('should render an array', () => {
- expect(mount()).toMatchSnapshot();
- });
-
- it('should render a boolean', () => {
- expect(mount()).toMatchSnapshot();
- expect(mount()).toMatchSnapshot();
- });
-
- it('should render a number', () => {
- expect(mount()).toMatchSnapshot();
- });
-
- it('should render a string', () => {
- expect(mount()).toMatchSnapshot();
- });
-
- it('should render null', () => {
- expect(mount()).toMatchSnapshot();
- });
-
- it('should render undefined', () => {
- expect(mount()).toMatchSnapshot();
- });
-});
-
-describe('FormattedKey component', () => {
- it('should render when the value is null or undefined', () => {
- expect(mount()).toMatchSnapshot();
- expect(
- mount()
- ).toMatchSnapshot();
- });
-
- it('should render when the value is defined', () => {
- expect(mount()).toMatchSnapshot();
- expect(mount()).toMatchSnapshot();
- expect(mount()).toMatchSnapshot();
- });
-});
diff --git a/x-pack/plugins/apm/public/components/shared/PropertiesTable/__test__/PropertiesTable.test.tsx b/x-pack/plugins/apm/public/components/shared/PropertiesTable/__test__/PropertiesTable.test.tsx
deleted file mode 100644
index 0549bd3145e29e..00000000000000
--- a/x-pack/plugins/apm/public/components/shared/PropertiesTable/__test__/PropertiesTable.test.tsx
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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 { shallow } from 'enzyme';
-import React from 'react';
-import { PropertiesTable, TabHelpMessage } from '..';
-import * as agentDocs from '../../../../utils/documentation/agents';
-
-describe('PropertiesTable', () => {
- describe('PropertiesTable component', () => {
- it('should render with data', () => {
- expect(
- shallow(
-
- )
- ).toMatchSnapshot();
- });
-
- it("should render empty when data isn't present", () => {
- expect(
- shallow()
- ).toMatchSnapshot();
- });
-
- it('should still render NestedKeyValueTable even when data has no keys', () => {
- expect(
- shallow(
-
- )
- ).toMatchSnapshot();
- });
- });
-
- describe('TabHelpMessage component', () => {
- const tabKey = 'user';
- const agentName = 'nodejs';
-
- it('should render when docs are returned', () => {
- jest
- .spyOn(agentDocs, 'getAgentDocUrlForTab')
- .mockImplementation(() => 'mock-url');
-
- expect(
- shallow()
- ).toMatchSnapshot();
- expect(agentDocs.getAgentDocUrlForTab).toHaveBeenCalledWith(
- tabKey,
- agentName
- );
- });
-
- it('should render null empty string when no docs are returned', () => {
- jest
- .spyOn(agentDocs, 'getAgentDocUrlForTab')
- .mockImplementation(() => undefined);
-
- expect(
- shallow()
- ).toMatchSnapshot();
- });
- });
-});
diff --git a/x-pack/plugins/apm/public/components/shared/PropertiesTable/__test__/__snapshots__/NestedKeyValueTable.test.tsx.snap b/x-pack/plugins/apm/public/components/shared/PropertiesTable/__test__/__snapshots__/NestedKeyValueTable.test.tsx.snap
deleted file mode 100644
index 55f330b9b9322f..00000000000000
--- a/x-pack/plugins/apm/public/components/shared/PropertiesTable/__test__/__snapshots__/NestedKeyValueTable.test.tsx.snap
+++ /dev/null
@@ -1,288 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`FormattedKey component should render when the value is defined 1`] = `
-
- testKey
-
-`;
-
-exports[`FormattedKey component should render when the value is defined 2`] = `
-
- testKey
-
-`;
-
-exports[`FormattedKey component should render when the value is defined 3`] = `
-
- testKey
-
-`;
-
-exports[`FormattedKey component should render when the value is null or undefined 1`] = `
-.c0 {
- color: #98a2b3;
-}
-
-
-
-
- testKey
-
-
-
-`;
-
-exports[`FormattedKey component should render when the value is null or undefined 2`] = `
-.c0 {
- color: #98a2b3;
-}
-
-
-
-
- testKey
-
-
-
-`;
-
-exports[`FormattedValue component should render a boolean 1`] = `
-
- true
-
-`;
-
-exports[`FormattedValue component should render a boolean 2`] = `
-
- false
-
-`;
-
-exports[`FormattedValue component should render a number 1`] = `
-
- 243
-
-`;
-
-exports[`FormattedValue component should render a string 1`] = `
-
- hey ok cool
-
-`;
-
-exports[`FormattedValue component should render an array 1`] = `
-
-
- [
- 1,
- 2,
- 3
-]
-
-
-`;
-
-exports[`FormattedValue component should render an object 1`] = `
-
-
- {
- "a": "ok"
-}
-
-
-`;
-
-exports[`FormattedValue component should render null 1`] = `
-.c0 {
- color: #98a2b3;
-}
-
-
-
-
- N/A
-
-
-
-`;
-
-exports[`FormattedValue component should render undefined 1`] = `
-.c0 {
- color: #98a2b3;
-}
-
-
-
-
- N/A
-
-
-
-`;
-
-exports[`NestedKeyValueTable component should render an empty table if there is no data 1`] = `
-
-
-
-`;
-
-exports[`NestedKeyValueTable component should render with data 1`] = `
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-`;
-
-exports[`NestedValue component should render a formatted value when depth > 0 but value is not an object 1`] = `
-
-`;
-
-exports[`NestedValue component should render a nested KV Table when depth > 0 and value is an object 1`] = `
-
-`;
diff --git a/x-pack/plugins/apm/public/components/shared/PropertiesTable/__test__/__snapshots__/PropertiesTable.test.tsx.snap b/x-pack/plugins/apm/public/components/shared/PropertiesTable/__test__/__snapshots__/PropertiesTable.test.tsx.snap
deleted file mode 100644
index e9a6d7f2733ffe..00000000000000
--- a/x-pack/plugins/apm/public/components/shared/PropertiesTable/__test__/__snapshots__/PropertiesTable.test.tsx.snap
+++ /dev/null
@@ -1,67 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`PropertiesTable PropertiesTable component should render empty when data isn't present 1`] = `
-
-
- No data available
-
-
-
-`;
-
-exports[`PropertiesTable PropertiesTable component should render with data 1`] = `
-
-
-
-
-`;
-
-exports[`PropertiesTable PropertiesTable component should still render NestedKeyValueTable even when data has no keys 1`] = `
-
-
-
-
-`;
-
-exports[`PropertiesTable TabHelpMessage component should render null empty string when no docs are returned 1`] = `""`;
-
-exports[`PropertiesTable TabHelpMessage component should render when docs are returned 1`] = `
-
-
- You can configure your agent to add contextual information about your users.
-
-
- Learn more in the documentation.
-
-
-`;
diff --git a/x-pack/plugins/apm/public/components/shared/PropertiesTable/__test__/tabConfig.test.tsx b/x-pack/plugins/apm/public/components/shared/PropertiesTable/__test__/tabConfig.test.tsx
deleted file mode 100644
index 61d2fcf026652b..00000000000000
--- a/x-pack/plugins/apm/public/components/shared/PropertiesTable/__test__/tabConfig.test.tsx
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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.
- */
-
-jest.mock('../tabConfigConst', () => {
- return {
- TAB_CONFIG: [
- {
- key: 'testProperty',
- label: 'testPropertyLabel',
- required: false,
- presortedKeys: ['name', 'age']
- },
- {
- key: 'optionalProperty',
- label: 'optionalPropertyLabel',
- required: false
- },
- {
- key: 'requiredProperty',
- label: 'requiredPropertyLabel',
- required: true
- }
- ]
- };
-});
-
-import * as propertyConfig from '../tabConfig';
-const { getTabsFromObject, sortKeysByConfig } = propertyConfig;
-
-describe('tabConfig', () => {
- describe('getTabsFromObject', () => {
- it('should return selected and required keys only', () => {
- const expectedTabs = [
- {
- key: 'testProperty',
- label: 'testPropertyLabel'
- },
- {
- key: 'requiredProperty',
- label: 'requiredPropertyLabel'
- }
- ];
- expect(getTabsFromObject({ testProperty: {} } as any)).toEqual(
- expectedTabs
- );
- });
- });
-
- describe('sortKeysByConfig', () => {
- const testData = {
- color: 'blue',
- name: 'Jess',
- age: '39',
- numbers: [1, 2, 3],
- _id: '44x099z'
- };
-
- it('should sort with presorted keys first', () => {
- expect(sortKeysByConfig(testData, 'testProperty')).toEqual([
- 'name',
- 'age',
- '_id',
- 'color',
- 'numbers'
- ]);
- });
-
- it('should alpha-sort keys when there is no config value found', () => {
- expect(sortKeysByConfig(testData, 'nonExistentKey')).toEqual([
- '_id',
- 'age',
- 'color',
- 'name',
- 'numbers'
- ]);
- });
- });
-});
diff --git a/x-pack/plugins/apm/public/components/shared/PropertiesTable/index.tsx b/x-pack/plugins/apm/public/components/shared/PropertiesTable/index.tsx
deleted file mode 100644
index 9fc4ccfe30c6a6..00000000000000
--- a/x-pack/plugins/apm/public/components/shared/PropertiesTable/index.tsx
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * 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 { EuiIcon } from '@elastic/eui';
-import { EuiLink } 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';
-import { StringMap } from '../../../../typings/common';
-import { AgentName } from '../../../../typings/es_schemas/ui/fields/Agent';
-import { fontSize, fontSizes, px, unit, units } from '../../../style/variables';
-import { getAgentDocUrlForTab } from '../../../utils/documentation/agents';
-import { NestedKeyValueTable } from './NestedKeyValueTable';
-import { PropertyTabKey } from './tabConfig';
-
-const TableContainer = styled.div`
- padding-bottom: ${px(units.double)};
-`;
-
-const TableInfo = styled.div`
- padding: ${px(unit)} 0 0;
- text-align: center;
- font-size: ${fontSize};
- color: ${theme.euiColorDarkShade};
- line-height: 1.5;
-`;
-
-const TableInfoHeader = styled(TableInfo)`
- font-size: ${fontSizes.large};
- color: ${theme.euiColorDarkestShade};
-`;
-
-const EuiIconWithSpace = styled(EuiIcon)`
- margin-right: ${px(units.half)};
-`;
-
-function getTabHelpText(tabKey: PropertyTabKey) {
- switch (tabKey) {
- case 'user':
- return i18n.translate(
- 'xpack.apm.propertiesTable.userTab.agentFeatureText',
- {
- defaultMessage:
- 'You can configure your agent to add contextual information about your users.'
- }
- );
- case 'labels':
- return i18n.translate(
- 'xpack.apm.propertiesTable.labelsTab.agentFeatureText',
- {
- defaultMessage:
- 'You can configure your agent to add filterable tags on transactions.'
- }
- );
- case 'transaction.custom':
- case 'error.custom':
- return i18n.translate(
- 'xpack.apm.propertiesTable.customTab.agentFeatureText',
- {
- defaultMessage:
- 'You can configure your agent to add custom contextual information on transactions.'
- }
- );
- }
-}
-
-export function TabHelpMessage({
- tabKey,
- agentName
-}: {
- tabKey?: PropertyTabKey;
- agentName?: AgentName;
-}) {
- if (!tabKey) {
- return null;
- }
- const docsUrl = getAgentDocUrlForTab(tabKey, agentName);
- if (!docsUrl) {
- return null;
- }
-
- return (
-
-
- {getTabHelpText(tabKey)}{' '}
-
- {i18n.translate(
- 'xpack.apm.propertiesTable.agentFeature.learnMoreLinkLabel',
- { defaultMessage: 'Learn more in the documentation.' }
- )}
-
-
- );
-}
-
-export function PropertiesTable({
- propData,
- propKey,
- agentName
-}: {
- propData?: StringMap;
- propKey?: PropertyTabKey;
- agentName?: AgentName;
-}) {
- return (
-
- {propData ? (
-
- ) : (
-
- {i18n.translate(
- 'xpack.apm.propertiesTable.agentFeature.noDataAvailableLabel',
- { defaultMessage: 'No data available' }
- )}
-
- )}
-
-
-
- );
-}
diff --git a/x-pack/plugins/apm/public/components/shared/PropertiesTable/propertyConfig.ts b/x-pack/plugins/apm/public/components/shared/PropertiesTable/propertyConfig.ts
deleted file mode 100644
index 9c11c89a476191..00000000000000
--- a/x-pack/plugins/apm/public/components/shared/PropertiesTable/propertyConfig.ts
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * 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 { i18n } from '@kbn/i18n';
-
-export interface Tab {
- key: string;
- label: string;
-}
-
-export const PROPERTY_CONFIG = [
- {
- key: 'http',
- label: i18n.translate('xpack.apm.propertiesTable.tabs.httpLabel', {
- defaultMessage: 'HTTP'
- }),
- required: false,
- presortedKeys: []
- },
- {
- key: 'host',
- label: i18n.translate('xpack.apm.propertiesTable.tabs.hostLabel', {
- defaultMessage: 'Host'
- }),
- required: false,
- presortedKeys: ['hostname', 'architecture', 'platform']
- },
- {
- key: 'service',
- label: i18n.translate('xpack.apm.propertiesTable.tabs.serviceLabel', {
- defaultMessage: 'Service'
- }),
- required: false,
- presortedKeys: ['runtime', 'framework', 'version']
- },
- {
- key: 'process',
- label: i18n.translate('xpack.apm.propertiesTable.tabs.processLabel', {
- defaultMessage: 'Process'
- }),
- required: false,
- presortedKeys: ['pid', 'title', 'args']
- },
- {
- key: 'agent',
- label: i18n.translate('xpack.apm.propertiesTable.tabs.agentLabel', {
- defaultMessage: 'Agent'
- }),
- required: false,
- presortedKeys: []
- },
- {
- key: 'url',
- label: i18n.translate('xpack.apm.propertiesTable.tabs.urlLabel', {
- defaultMessage: 'URL'
- }),
- required: false,
- presortedKeys: []
- },
- {
- key: 'container',
- label: i18n.translate('xpack.apm.propertiesTable.tabs.containerLabel', {
- defaultMessage: 'Container'
- }),
- required: false,
- presortedKeys: []
- },
- {
- key: 'user',
- label: i18n.translate('xpack.apm.propertiesTable.tabs.userLabel', {
- defaultMessage: 'User'
- }),
- required: true,
- presortedKeys: ['id', 'username', 'email']
- },
- {
- key: 'labels',
- label: i18n.translate('xpack.apm.propertiesTable.tabs.labelsLabel', {
- defaultMessage: 'Labels'
- }),
- required: true,
- presortedKeys: []
- },
- {
- key: 'transaction.custom',
- label: i18n.translate(
- 'xpack.apm.propertiesTable.tabs.transactionCustomLabel',
- {
- defaultMessage: 'Custom'
- }
- ),
- required: false,
- presortedKeys: []
- },
- {
- key: 'error.custom',
- label: i18n.translate('xpack.apm.propertiesTable.tabs.errorCustomLabel', {
- defaultMessage: 'Custom'
- }),
- required: false,
- presortedKeys: []
- }
-];
diff --git a/x-pack/plugins/apm/public/components/shared/PropertiesTable/tabConfig.ts b/x-pack/plugins/apm/public/components/shared/PropertiesTable/tabConfig.ts
deleted file mode 100644
index 0f5a64580b46b2..00000000000000
--- a/x-pack/plugins/apm/public/components/shared/PropertiesTable/tabConfig.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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 { get, indexBy, uniq } from 'lodash';
-import { first, has } from 'lodash';
-import { StringMap } from '../../../../typings/common';
-import { APMError } from '../../../../typings/es_schemas/ui/APMError';
-import { Transaction } from '../../../../typings/es_schemas/ui/Transaction';
-import {
- PropertyTab,
- PropertyTabKey,
- TAB_CONFIG,
- TabConfig
-} from './tabConfigConst';
-
-export function getTabsFromObject(obj: Transaction | APMError): PropertyTab[] {
- return TAB_CONFIG.filter(
- ({ key, required }) => required || has(obj, key)
- ).map(({ key, label }) => ({ key, label }));
-}
-
-export type KeySorter = (data: StringMap, parentKey?: string) => string[];
-
-export const sortKeysByConfig: KeySorter = (object, currentKey) => {
- const indexedPropertyConfig = indexBy(TAB_CONFIG, 'key');
- const presorted = get(
- indexedPropertyConfig,
- `${currentKey}.presortedKeys`,
- []
- );
- return uniq([...presorted, ...Object.keys(object).sort()]);
-};
-
-export function getCurrentTab(
- tabs: T[] = [],
- currentTabKey: string | undefined
-): T {
- const selectedTab = tabs.find(({ key }) => key === currentTabKey);
- return selectedTab ? selectedTab : first(tabs) || {};
-}
-
-export { TAB_CONFIG, TabConfig, PropertyTab, PropertyTabKey };
diff --git a/x-pack/plugins/apm/public/components/shared/PropertiesTable/tabConfigConst.ts b/x-pack/plugins/apm/public/components/shared/PropertiesTable/tabConfigConst.ts
deleted file mode 100644
index cd3cc7bd112901..00000000000000
--- a/x-pack/plugins/apm/public/components/shared/PropertiesTable/tabConfigConst.ts
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * 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 { i18n } from '@kbn/i18n';
-import { APMError } from '../../../../typings/es_schemas/ui/APMError';
-import { Transaction } from '../../../../typings/es_schemas/ui/Transaction';
-
-export type PropertyTabKey =
- | keyof Transaction
- | keyof APMError
- | 'transaction.custom'
- | 'error.custom';
-
-export interface PropertyTab {
- key: PropertyTabKey;
- label: string;
-}
-
-export interface TabConfig extends PropertyTab {
- required: boolean;
- presortedKeys: string[];
-}
-
-export const TAB_CONFIG: TabConfig[] = [
- {
- key: 'http',
- label: i18n.translate('xpack.apm.propertiesTable.tabs.httpLabel', {
- defaultMessage: 'HTTP'
- }),
- required: false,
- presortedKeys: []
- },
- {
- key: 'host',
- label: i18n.translate('xpack.apm.propertiesTable.tabs.hostLabel', {
- defaultMessage: 'Host'
- }),
- required: false,
- presortedKeys: ['hostname', 'architecture', 'platform']
- },
- {
- key: 'service',
- label: i18n.translate('xpack.apm.propertiesTable.tabs.serviceLabel', {
- defaultMessage: 'Service'
- }),
- required: false,
- presortedKeys: ['runtime', 'framework', 'version']
- },
- {
- key: 'process',
- label: i18n.translate('xpack.apm.propertiesTable.tabs.processLabel', {
- defaultMessage: 'Process'
- }),
- required: false,
- presortedKeys: ['pid', 'title', 'args']
- },
- {
- key: 'agent',
- label: i18n.translate('xpack.apm.propertiesTable.tabs.agentLabel', {
- defaultMessage: 'Agent'
- }),
- required: false,
- presortedKeys: []
- },
- {
- key: 'url',
- label: i18n.translate('xpack.apm.propertiesTable.tabs.urlLabel', {
- defaultMessage: 'URL'
- }),
- required: false,
- presortedKeys: []
- },
- {
- key: 'container',
- label: i18n.translate('xpack.apm.propertiesTable.tabs.containerLabel', {
- defaultMessage: 'Container'
- }),
- required: false,
- presortedKeys: []
- },
- {
- key: 'user',
- label: i18n.translate('xpack.apm.propertiesTable.tabs.userLabel', {
- defaultMessage: 'User'
- }),
- required: true,
- presortedKeys: ['id', 'username', 'email']
- },
- {
- key: 'labels',
- label: i18n.translate('xpack.apm.propertiesTable.tabs.labelsLabel', {
- defaultMessage: 'Labels'
- }),
- required: true,
- presortedKeys: []
- },
- {
- key: 'transaction.custom',
- label: i18n.translate(
- 'xpack.apm.propertiesTable.tabs.transactionCustomLabel',
- {
- defaultMessage: 'Custom'
- }
- ),
- required: false,
- presortedKeys: []
- },
- {
- key: 'error.custom',
- label: i18n.translate('xpack.apm.propertiesTable.tabs.errorCustomLabel', {
- defaultMessage: 'Custom'
- }),
- required: false,
- presortedKeys: []
- }
-];
diff --git a/x-pack/plugins/apm/public/components/shared/Stacktrace/Variables.tsx b/x-pack/plugins/apm/public/components/shared/Stacktrace/Variables.tsx
index 1961327661f8a9..dfc9c95c9143a0 100644
--- a/x-pack/plugins/apm/public/components/shared/Stacktrace/Variables.tsx
+++ b/x-pack/plugins/apm/public/components/shared/Stacktrace/Variables.tsx
@@ -17,7 +17,7 @@ import {
units
} from '../../../style/variables';
import { Ellipsis } from '../Icons';
-import { PropertiesTable } from '../PropertiesTable';
+import { DottedKeyValueTable } from '../DottedKeyValueTable';
const VariablesContainer = styled.div`
background: ${theme.euiColorEmptyShade};
@@ -66,7 +66,7 @@ export class Variables extends React.Component {
{this.state.isVisible && (
-
+
)}
diff --git a/x-pack/plugins/apm/public/utils/documentation/agents.ts b/x-pack/plugins/apm/public/utils/documentation/agents.ts
deleted file mode 100644
index 8ebbbf6464d929..00000000000000
--- a/x-pack/plugins/apm/public/utils/documentation/agents.ts
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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 { AgentName } from '../../../typings/es_schemas/ui/fields/Agent';
-import { PropertyTabKey } from '../../components/shared/PropertiesTable/tabConfig';
-
-const AGENT_URL_ROOT = 'https://www.elastic.co/guide/en/apm/agent';
-
-type DocUrls = {
- [tabKey in PropertyTabKey]?: { [agentName in AgentName]: string | undefined }
-};
-
-const customUrls = {
- 'js-base': `${AGENT_URL_ROOT}/js-base/4.x/api.html#apm-set-custom-context`,
- 'rum-js': `${AGENT_URL_ROOT}/js-base/4.x/api.html#apm-set-custom-context`,
- java: undefined,
- nodejs: `${AGENT_URL_ROOT}/nodejs/2.x/agent-api.html#apm-set-custom-context`,
- python: `${AGENT_URL_ROOT}/python/4.x/api.html#api-set-custom-context`,
- dotnet: undefined,
- ruby: `${AGENT_URL_ROOT}/ruby/2.x/context.html#_adding_custom_context`,
- go: undefined
-};
-
-const AGENT_DOC_URLS: DocUrls = {
- user: {
- 'js-base': `${AGENT_URL_ROOT}/js-base/4.x/api.html#apm-set-user-context`,
- 'rum-js': `${AGENT_URL_ROOT}/js-base/4.x/api.html#apm-set-user-context`,
- java: `${AGENT_URL_ROOT}/java/1.x/public-api.html#api-transaction-set-user`,
- nodejs: `${AGENT_URL_ROOT}/nodejs/2.x/agent-api.html#apm-set-user-context`,
- python: `${AGENT_URL_ROOT}/python/4.x/api.html#api-set-user-context`,
- dotnet: undefined,
- ruby: `${AGENT_URL_ROOT}/ruby/2.x/context.html#_providing_info_about_the_user`,
- go: undefined
- },
- labels: {
- 'js-base': `${AGENT_URL_ROOT}/js-base/4.x/api.html#apm-add-tags`,
- 'rum-js': `${AGENT_URL_ROOT}/js-base/4.x/api.html#apm-add-tags`,
- java: `${AGENT_URL_ROOT}/java/1.x/public-api.html#api-transaction-add-tag`,
- nodejs: `${AGENT_URL_ROOT}/nodejs/2.x/agent-api.html#apm-set-tag`,
- python: `${AGENT_URL_ROOT}/python/4.x/api.html#api-tag`,
- dotnet: `${AGENT_URL_ROOT}/dotnet/current/public-api.html#api-transaction-tags`,
- ruby: `${AGENT_URL_ROOT}/ruby/2.x/context.html#_adding_tags`,
- go: undefined
- },
- 'transaction.custom': customUrls,
- 'error.custom': customUrls
-};
-
-export function getAgentDocUrlForTab(
- tabKey: PropertyTabKey,
- agentName?: AgentName
-) {
- const agentUrls = AGENT_DOC_URLS[tabKey];
- if (agentUrls && agentName) {
- return agentUrls[agentName];
- }
-}
diff --git a/x-pack/plugins/apm/public/utils/documentation/apm-get-started.ts b/x-pack/plugins/apm/public/utils/documentation/apm-get-started.ts
deleted file mode 100644
index 7b8c185c41e244..00000000000000
--- a/x-pack/plugins/apm/public/utils/documentation/apm-get-started.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * 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 { metadata } from 'ui/metadata';
-const STACK_VERSION = metadata.branch;
-
-export const DROPPED_SPANS_DOCS = `https://www.elastic.co/guide/en/apm/get-started/${STACK_VERSION}/transaction-spans.html#dropped-spans`;
diff --git a/x-pack/plugins/apm/public/utils/documentation/xpack.ts b/x-pack/plugins/apm/public/utils/documentation/xpack.ts
deleted file mode 100644
index 58960dd2d88c75..00000000000000
--- a/x-pack/plugins/apm/public/utils/documentation/xpack.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * 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 { metadata } from 'ui/metadata';
-const STACK_VERSION = metadata.branch;
-
-const XPACK_URL_ROOT = `https://www.elastic.co/guide/en/x-pack/${STACK_VERSION}`;
-
-export const XPACK_DOCS = {
- xpackEmails: `${XPACK_URL_ROOT}/actions-email.html#configuring-email`,
- xpackWatcher: `${XPACK_URL_ROOT}/watcher-getting-started.html`
-};
diff --git a/x-pack/plugins/apm/public/utils/testHelpers.tsx b/x-pack/plugins/apm/public/utils/testHelpers.tsx
index 2072fa69e66fd7..a0c8c1305a78ad 100644
--- a/x-pack/plugins/apm/public/utils/testHelpers.tsx
+++ b/x-pack/plugins/apm/public/utils/testHelpers.tsx
@@ -72,3 +72,25 @@ export function delay(ms: number) {
// Await this when you need to "flush" promises to immediately resolve or throw in tests
export const tick = () => new Promise(resolve => setImmediate(resolve, 0));
+
+export function expectTextsNotInDocument(output: any, texts: string[]) {
+ texts.forEach(text => {
+ try {
+ output.getByText(text);
+ } catch (err) {
+ if (err.message.startsWith('Unable to find an element with the text:')) {
+ return;
+ } else {
+ throw err;
+ }
+ }
+
+ throw new Error(`Unexpected text found: ${text}`);
+ });
+}
+
+export function expectTextsInDocument(output: any, texts: string[]) {
+ texts.forEach(text => {
+ expect(output.getByText(text)).toBeInTheDocument();
+ });
+}
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index fceb0ec92048ce..bf63c99b9045bd 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -3287,16 +3287,10 @@
"xpack.apm.metrics.transactionChart.transactionDurationLabel": "事务持续时间",
"xpack.apm.metrics.transactionChart.transactionsPerMinuteLabel": "每分钟事务数",
"xpack.apm.notAvailableLabel": "不适用",
- "xpack.apm.propertiesTable.agentFeature.learnMoreLinkLabel": "在文档中详细了解。",
"xpack.apm.propertiesTable.agentFeature.noDataAvailableLabel": "没有可用数据",
- "xpack.apm.propertiesTable.customTab.agentFeatureText": "您可以配置代理以添加有关事务的定制上下文信息。",
"xpack.apm.propertiesTable.tabs.exceptionStacktraceLabel": "异常堆栈追溯",
"xpack.apm.propertiesTable.tabs.logStacktraceLabel": "日志堆栈追溯",
- "xpack.apm.propertiesTable.tabs.processLabel": "进程",
- "xpack.apm.propertiesTable.tabs.serviceLabel": "服务",
"xpack.apm.propertiesTable.tabs.timelineLabel": "时间线",
- "xpack.apm.propertiesTable.tabs.userLabel": "用户",
- "xpack.apm.propertiesTable.userTab.agentFeatureText": "您可以配置代理以添加有关用户的上下文信息。",
"xpack.apm.serviceDetails.enableAnomalyDetectionPanel.callout.jobExistsDescription": "当前有 {serviceName}({transactionType})的作业正在运行。",
"xpack.apm.serviceDetails.enableAnomalyDetectionPanel.callout.jobExistsDescription.viewJobLinkText": "查看现有作业",
"xpack.apm.serviceDetails.enableAnomalyDetectionPanel.callout.jobExistsTitle": "作业已存在",
diff --git a/yarn.lock b/yarn.lock
index dd8ab8f5f58d76..81ccb3ca79b178 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -8151,7 +8151,12 @@ css-what@2.1, css-what@^2.1.2:
resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2"
integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==
-css@2.X, css@^2.2.1, css@^2.2.4:
+css.escape@^1.5.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb"
+ integrity sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s=
+
+css@2.X, css@^2.2.1, css@^2.2.3, css@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/css/-/css-2.2.4.tgz#c646755c73971f2bba6a601e2cf2fd71b1298929"
integrity sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==
@@ -14770,6 +14775,20 @@ jest-docblock@^24.0.0:
dependencies:
detect-newline "^2.1.0"
+jest-dom@^3.1.3:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/jest-dom/-/jest-dom-3.1.3.tgz#9490de549c02366fe586f23bdafffd8374bd1d65"
+ integrity sha512-V9LdySiA74/spcAKEG3FRMRKnisKlcYr3EeCNYI4n7CWNE7uYg5WoBUHeGXirjWjRYLLZ5vx8rUaR/6x6o75oQ==
+ dependencies:
+ chalk "^2.4.1"
+ css "^2.2.3"
+ css.escape "^1.5.1"
+ jest-diff "^24.0.0"
+ jest-matcher-utils "^24.0.0"
+ lodash "^4.17.11"
+ pretty-format "^24.0.0"
+ redent "^2.0.0"
+
jest-each@^24.0.0:
version "24.0.0"
resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-24.0.0.tgz#10987a06b21c7ffbfb7706c89d24c52ed864be55"