mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
* [APM] APM & Observability plugin lint improvements This is a large change, but most of it is automatic `eslint --fix` changes. * Apply the same ESLint ovderrides in APM and Observability plugins. * Remove the `no-unused-vars` rule. We can turn on the TypeScript check if needed. * Check both JS and TS files. * Add a rule for react function component definitions * Upgrade eslint-plugin-react to include that rule
This commit is contained in:
parent
aab54c0693
commit
74af87fcbb
140 changed files with 822 additions and 731 deletions
21
.eslintrc.js
21
.eslintrc.js
|
@ -775,19 +775,22 @@ module.exports = {
|
|||
},
|
||||
|
||||
/**
|
||||
* APM overrides
|
||||
* APM and Observability overrides
|
||||
*/
|
||||
{
|
||||
files: ['x-pack/plugins/apm/**/*.js'],
|
||||
files: [
|
||||
'x-pack/plugins/apm/**/*.{js,mjs,ts,tsx}',
|
||||
'x-pack/plugins/observability/**/*.{js,mjs,ts,tsx}',
|
||||
],
|
||||
rules: {
|
||||
'no-unused-vars': ['error', { ignoreRestSiblings: true }],
|
||||
'no-console': ['warn', { allow: ['error'] }],
|
||||
},
|
||||
},
|
||||
{
|
||||
plugins: ['react-hooks'],
|
||||
files: ['x-pack/plugins/apm/**/*.{ts,tsx}'],
|
||||
rules: {
|
||||
'react/function-component-definition': [
|
||||
'warn',
|
||||
{
|
||||
namedComponents: 'function-declaration',
|
||||
unnamedComponents: 'arrow-function',
|
||||
},
|
||||
],
|
||||
'react-hooks/rules-of-hooks': 'error', // Checks rules of Hooks
|
||||
'react-hooks/exhaustive-deps': ['error', { additionalHooks: '^useFetcher$' }],
|
||||
},
|
||||
|
|
|
@ -430,7 +430,7 @@
|
|||
"eslint-plugin-node": "^11.0.0",
|
||||
"eslint-plugin-prefer-object-spread": "^1.2.1",
|
||||
"eslint-plugin-prettier": "^3.1.3",
|
||||
"eslint-plugin-react": "^7.17.0",
|
||||
"eslint-plugin-react": "^7.20.3",
|
||||
"eslint-plugin-react-hooks": "^4.0.4",
|
||||
"eslint-plugin-react-perf": "^3.2.3",
|
||||
"exit-hook": "^2.2.0",
|
||||
|
|
|
@ -51,13 +51,13 @@ describe('Inspector Data View', () => {
|
|||
});
|
||||
|
||||
it('should render loading state', () => {
|
||||
const component = mountWithIntl(<DataView.component title="Test Data" adapters={adapters} />);
|
||||
const component = mountWithIntl(<DataView.component title="Test Data" adapters={adapters} />); // eslint-disable-line react/jsx-pascal-case
|
||||
|
||||
expect(component).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should render empty state', async () => {
|
||||
const component = mountWithIntl(<DataView.component title="Test Data" adapters={adapters} />);
|
||||
const component = mountWithIntl(<DataView.component title="Test Data" adapters={adapters} />); // eslint-disable-line react/jsx-pascal-case
|
||||
const tabularLoader = Promise.resolve(null);
|
||||
adapters.data.setTabularLoader(() => tabularLoader);
|
||||
await tabularLoader;
|
||||
|
|
|
@ -29,6 +29,8 @@ module.exports = (on) => {
|
|||
|
||||
// readFileMaybe
|
||||
on('task', {
|
||||
// ESLint thinks this is a react component for some reason.
|
||||
// eslint-disable-next-line react/function-component-definition
|
||||
readFileMaybe(filename) {
|
||||
if (fs.existsSync(filename)) {
|
||||
return fs.readFileSync(filename, 'utf8');
|
||||
|
|
|
@ -37,7 +37,7 @@ const MainContainer = styled.div`
|
|||
height: 100%;
|
||||
`;
|
||||
|
||||
const App = () => {
|
||||
function App() {
|
||||
const [darkMode] = useUiSetting$<boolean>('theme:darkMode');
|
||||
|
||||
return (
|
||||
|
@ -59,9 +59,9 @@ const App = () => {
|
|||
</MainContainer>
|
||||
</ThemeProvider>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
const ApmAppRoot = ({
|
||||
function ApmAppRoot({
|
||||
core,
|
||||
deps,
|
||||
routerHistory,
|
||||
|
@ -71,7 +71,7 @@ const ApmAppRoot = ({
|
|||
deps: ApmPluginSetupDeps;
|
||||
routerHistory: typeof history;
|
||||
config: ConfigSchema;
|
||||
}) => {
|
||||
}) {
|
||||
const i18nCore = core.i18n;
|
||||
const plugins = deps;
|
||||
const apmPluginContextValue = {
|
||||
|
@ -111,7 +111,7 @@ const ApmAppRoot = ({
|
|||
</AlertsContextProvider>
|
||||
</ApmPluginContext.Provider>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This module is rendered asynchronously in the Kibana platform.
|
||||
|
|
|
@ -53,7 +53,7 @@ interface Props {
|
|||
items: ErrorGroupListAPIResponse;
|
||||
}
|
||||
|
||||
const ErrorGroupList: React.FC<Props> = (props) => {
|
||||
function ErrorGroupList(props: Props) {
|
||||
const { items } = props;
|
||||
const { urlParams } = useUrlParams();
|
||||
const { serviceName } = urlParams;
|
||||
|
@ -213,6 +213,6 @@ const ErrorGroupList: React.FC<Props> = (props) => {
|
|||
sortItems={false}
|
||||
/>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export { ErrorGroupList };
|
||||
|
|
|
@ -22,7 +22,7 @@ import { LocalUIFilters } from '../../shared/LocalUIFilters';
|
|||
import { ErrorDistribution } from '../ErrorGroupDetails/Distribution';
|
||||
import { ErrorGroupList } from './List';
|
||||
|
||||
const ErrorGroupOverview: React.FC = () => {
|
||||
function ErrorGroupOverview() {
|
||||
const { urlParams, uiFilters } = useUrlParams();
|
||||
|
||||
const { serviceName, start, end, sortField, sortDirection } = urlParams;
|
||||
|
@ -123,6 +123,6 @@ const ErrorGroupOverview: React.FC = () => {
|
|||
</EuiFlexGroup>
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export { ErrorGroupOverview };
|
||||
|
|
|
@ -20,11 +20,11 @@ interface Props {
|
|||
onBreakdownChange: (values: BreakdownItem[]) => void;
|
||||
}
|
||||
|
||||
export const BreakdownFilter = ({
|
||||
export function BreakdownFilter({
|
||||
id,
|
||||
selectedBreakdowns,
|
||||
onBreakdownChange,
|
||||
}: Props) => {
|
||||
}: Props) {
|
||||
const categories: BreakdownItem[] = [
|
||||
{
|
||||
name: 'Browser',
|
||||
|
@ -65,4 +65,4 @@ export const BreakdownFilter = ({
|
|||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -22,12 +22,12 @@ export interface BreakdownGroupProps {
|
|||
onChange: (values: BreakdownItem[]) => void;
|
||||
}
|
||||
|
||||
export const BreakdownGroup = ({
|
||||
export function BreakdownGroup({
|
||||
id,
|
||||
disabled,
|
||||
onChange,
|
||||
items,
|
||||
}: BreakdownGroupProps) => {
|
||||
}: BreakdownGroupProps) {
|
||||
const [isOpen, setIsOpen] = useState<boolean>(false);
|
||||
|
||||
const [activeItems, setActiveItems] = useState<BreakdownItem[]>(items);
|
||||
|
@ -97,4 +97,4 @@ export const BreakdownGroup = ({
|
|||
</EuiPopover>
|
||||
</EuiFilterGroup>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { FC, HTMLAttributes } from 'react';
|
||||
import React, { HTMLAttributes, ReactNode } from 'react';
|
||||
import {
|
||||
EuiErrorBoundary,
|
||||
EuiFlexGroup,
|
||||
|
@ -13,6 +13,7 @@ import {
|
|||
} from '@elastic/eui';
|
||||
|
||||
interface Props {
|
||||
children?: ReactNode;
|
||||
/**
|
||||
* Height for the chart
|
||||
*/
|
||||
|
@ -27,12 +28,12 @@ interface Props {
|
|||
'aria-label'?: string;
|
||||
}
|
||||
|
||||
export const ChartWrapper: FC<Props> = ({
|
||||
export function ChartWrapper({
|
||||
loading = false,
|
||||
height = '100%',
|
||||
children,
|
||||
...rest
|
||||
}) => {
|
||||
}: Props) {
|
||||
const opacity = loading === true ? 0.3 : 1;
|
||||
|
||||
return (
|
||||
|
@ -60,4 +61,4 @@ export const ChartWrapper: FC<Props> = ({
|
|||
)}
|
||||
</EuiErrorBoundary>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -70,6 +70,7 @@ export function PageLoadDistChart({
|
|||
onPercentileChange(minX, maxX);
|
||||
};
|
||||
|
||||
// eslint-disable-next-line react/function-component-definition
|
||||
const headerFormatter: TooltipValueFormatter = (tooltip: TooltipValue) => {
|
||||
return (
|
||||
<div>
|
||||
|
|
|
@ -29,7 +29,7 @@ interface Props {
|
|||
}>;
|
||||
}
|
||||
|
||||
export const VisitorBreakdownChart = ({ options }: Props) => {
|
||||
export function VisitorBreakdownChart({ options }: Props) {
|
||||
const [darkMode] = useUiSetting$<boolean>('theme:darkMode');
|
||||
|
||||
return (
|
||||
|
@ -93,4 +93,4 @@ export const VisitorBreakdownChart = ({ options }: Props) => {
|
|||
</Chart>
|
||||
</ChartWrapper>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { FC, useEffect } from 'react';
|
||||
import { CurveType, LineSeries, ScaleType } from '@elastic/charts';
|
||||
import React, { useEffect } from 'react';
|
||||
import { PercentileRange } from './index';
|
||||
import { useBreakdowns } from './use_breakdowns';
|
||||
|
||||
|
@ -16,12 +16,12 @@ interface Props {
|
|||
onLoadingChange: (loading: boolean) => void;
|
||||
}
|
||||
|
||||
export const BreakdownSeries: FC<Props> = ({
|
||||
export function BreakdownSeries({
|
||||
field,
|
||||
value,
|
||||
percentileRange,
|
||||
onLoadingChange,
|
||||
}) => {
|
||||
}: Props) {
|
||||
const { data, status } = useBreakdowns({
|
||||
field,
|
||||
value,
|
||||
|
@ -47,4 +47,4 @@ export const BreakdownSeries: FC<Props> = ({
|
|||
))}
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ const PercentileMarker = styled.span`
|
|||
bottom: 205px;
|
||||
`;
|
||||
|
||||
export const PercentileAnnotations = ({ percentiles }: Props) => {
|
||||
export function PercentileAnnotations({ percentiles }: Props) {
|
||||
const dataValues = generateAnnotationData(percentiles) ?? [];
|
||||
|
||||
const style: Partial<LineAnnotationStyle> = {
|
||||
|
@ -44,17 +44,17 @@ export const PercentileAnnotations = ({ percentiles }: Props) => {
|
|||
},
|
||||
};
|
||||
|
||||
const PercentileTooltip = ({
|
||||
function PercentileTooltip({
|
||||
annotation,
|
||||
}: {
|
||||
annotation: LineAnnotationDatum;
|
||||
}) => {
|
||||
}) {
|
||||
return (
|
||||
<span data-cy="percentileTooltipTitle">
|
||||
{annotation.details}th Percentile
|
||||
</span>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -82,4 +82,4 @@ export const PercentileAnnotations = ({ percentiles }: Props) => {
|
|||
))}
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ export interface PercentileRange {
|
|||
max?: number | null;
|
||||
}
|
||||
|
||||
export const PageLoadDistribution = () => {
|
||||
export function PageLoadDistribution() {
|
||||
const { urlParams, uiFilters } = useUrlParams();
|
||||
|
||||
const { start, end, serviceName } = urlParams;
|
||||
|
@ -115,4 +115,4 @@ export const PageLoadDistribution = () => {
|
|||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ import { BreakdownFilter } from '../Breakdowns/BreakdownFilter';
|
|||
import { PageViewsChart } from '../Charts/PageViewsChart';
|
||||
import { BreakdownItem } from '../../../../../typings/ui_filters';
|
||||
|
||||
export const PageViewsTrend = () => {
|
||||
export function PageViewsTrend() {
|
||||
const { urlParams, uiFilters } = useUrlParams();
|
||||
|
||||
const { start, end, serviceName } = urlParams;
|
||||
|
@ -68,4 +68,4 @@ export const PageViewsTrend = () => {
|
|||
<PageViewsChart data={data} loading={status !== 'success'} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ import { PageLoadDistribution } from './PageLoadDistribution';
|
|||
import { I18LABELS } from './translations';
|
||||
import { VisitorBreakdown } from './VisitorBreakdown';
|
||||
|
||||
export const RumDashboard = () => {
|
||||
export function RumDashboard() {
|
||||
return (
|
||||
<EuiFlexGroup direction="column" gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
|
@ -54,4 +54,4 @@ export const RumDashboard = () => {
|
|||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -5,16 +5,18 @@
|
|||
*/
|
||||
|
||||
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
import React, { ReactNode } from 'react';
|
||||
import { DatePicker } from '../../../shared/DatePicker';
|
||||
|
||||
export const RumHeader: React.FC = ({ children }) => (
|
||||
<>
|
||||
<EuiFlexGroup alignItems="center" gutterSize="s">
|
||||
<EuiFlexItem>{children}</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<DatePicker />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</>
|
||||
);
|
||||
export function RumHeader({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<>
|
||||
<EuiFlexGroup alignItems="center" gutterSize="s">
|
||||
<EuiFlexItem>{children}</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<DatePicker />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import { VisitorBreakdownLabel } from '../translations';
|
|||
import { useFetcher } from '../../../../hooks/useFetcher';
|
||||
import { useUrlParams } from '../../../../hooks/useUrlParams';
|
||||
|
||||
export const VisitorBreakdown = () => {
|
||||
export function VisitorBreakdown() {
|
||||
const { urlParams, uiFilters } = useUrlParams();
|
||||
|
||||
const { start, end, serviceName } = urlParams;
|
||||
|
@ -62,4 +62,4 @@ export const VisitorBreakdown = () => {
|
|||
</EuiFlexGroup>
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,32 +4,38 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
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 React, { ReactNode } from 'react';
|
||||
import { MockApmPluginContextWrapper } from '../../../context/ApmPluginContext/MockApmPluginContext';
|
||||
import { renderWithTheme } from '../../../utils/testHelpers';
|
||||
import { CytoscapeContext } from './Cytoscape';
|
||||
import { EmptyBanner } from './EmptyBanner';
|
||||
|
||||
const cy = cytoscape({});
|
||||
|
||||
const wrapper: FunctionComponent = ({ children }) => (
|
||||
<MockApmPluginContextWrapper>
|
||||
<CytoscapeContext.Provider value={cy}>{children}</CytoscapeContext.Provider>
|
||||
</MockApmPluginContextWrapper>
|
||||
);
|
||||
function wrapper({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<MockApmPluginContextWrapper>
|
||||
<CytoscapeContext.Provider value={cy}>
|
||||
{children}
|
||||
</CytoscapeContext.Provider>
|
||||
</MockApmPluginContextWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
describe('EmptyBanner', () => {
|
||||
describe('when cy is undefined', () => {
|
||||
it('renders null', () => {
|
||||
const noCytoscapeWrapper: FunctionComponent = ({ children }) => (
|
||||
<MockApmPluginContextWrapper>
|
||||
<CytoscapeContext.Provider value={undefined}>
|
||||
{children}
|
||||
</CytoscapeContext.Provider>
|
||||
</MockApmPluginContextWrapper>
|
||||
);
|
||||
function noCytoscapeWrapper({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<MockApmPluginContextWrapper>
|
||||
<CytoscapeContext.Provider value={undefined}>
|
||||
{children}
|
||||
</CytoscapeContext.Provider>
|
||||
</MockApmPluginContextWrapper>
|
||||
);
|
||||
}
|
||||
const component = renderWithTheme(<EmptyBanner />, {
|
||||
wrapper: noCytoscapeWrapper,
|
||||
});
|
||||
|
|
|
@ -34,26 +34,28 @@ interface Props {
|
|||
percentageLoaded: number;
|
||||
}
|
||||
|
||||
export const LoadingOverlay = ({ isLoading, percentageLoaded }: Props) => (
|
||||
<Container>
|
||||
{isLoading && (
|
||||
<Overlay>
|
||||
<ProgressBarContainer>
|
||||
<EuiProgress
|
||||
value={percentageLoaded}
|
||||
max={100}
|
||||
color="primary"
|
||||
size="m"
|
||||
/>
|
||||
</ProgressBarContainer>
|
||||
<EuiSpacer size="s" />
|
||||
<EuiText size="s" textAlign="center">
|
||||
{i18n.translate('xpack.apm.loadingServiceMap', {
|
||||
defaultMessage:
|
||||
'Loading service map... This might take a short while.',
|
||||
})}
|
||||
</EuiText>
|
||||
</Overlay>
|
||||
)}
|
||||
</Container>
|
||||
);
|
||||
export function LoadingOverlay({ isLoading, percentageLoaded }: Props) {
|
||||
return (
|
||||
<Container>
|
||||
{isLoading && (
|
||||
<Overlay>
|
||||
<ProgressBarContainer>
|
||||
<EuiProgress
|
||||
value={percentageLoaded}
|
||||
max={100}
|
||||
color="primary"
|
||||
size="m"
|
||||
/>
|
||||
</ProgressBarContainer>
|
||||
<EuiSpacer size="s" />
|
||||
<EuiText size="s" textAlign="center">
|
||||
{i18n.translate('xpack.apm.loadingServiceMap', {
|
||||
defaultMessage:
|
||||
'Loading service map... This might take a short while.',
|
||||
})}
|
||||
</EuiText>
|
||||
</Overlay>
|
||||
)}
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -34,20 +34,21 @@ interface ContentsProps {
|
|||
// @ts-ignore `documentMode` is not recognized as a valid property of `document`.
|
||||
const isIE11 = !!window.MSInputMethodContext && !!document.documentMode;
|
||||
|
||||
const FlexColumnGroup = (props: {
|
||||
function FlexColumnGroup(props: {
|
||||
children: React.ReactNode;
|
||||
style: React.CSSProperties;
|
||||
direction: 'column';
|
||||
gutterSize: 's';
|
||||
}) => {
|
||||
}) {
|
||||
if (isIE11) {
|
||||
const { direction, gutterSize, ...rest } = props;
|
||||
return <div {...rest} />;
|
||||
}
|
||||
return <EuiFlexGroup {...props} />;
|
||||
};
|
||||
const FlexColumnItem = (props: { children: React.ReactNode }) =>
|
||||
isIE11 ? <div {...props} /> : <EuiFlexItem {...props} />;
|
||||
}
|
||||
function FlexColumnItem(props: { children: React.ReactNode }) {
|
||||
return isIE11 ? <div {...props} /> : <EuiFlexItem {...props} />;
|
||||
}
|
||||
|
||||
export function Contents({
|
||||
selectedNodeData,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
import { render } from '@testing-library/react';
|
||||
import React, { FunctionComponent } from 'react';
|
||||
import React, { ReactNode } from 'react';
|
||||
import { License } from '../../../../../licensing/common/license';
|
||||
import { LicenseContext } from '../../../context/LicenseContext';
|
||||
import { ServiceMap } from './';
|
||||
|
@ -22,13 +22,13 @@ const expiredLicense = new License({
|
|||
},
|
||||
});
|
||||
|
||||
const Wrapper: FunctionComponent = ({ children }) => {
|
||||
function Wrapper({ children }: { children?: ReactNode }) {
|
||||
return (
|
||||
<LicenseContext.Provider value={expiredLicense}>
|
||||
<MockApmPluginContextWrapper>{children}</MockApmPluginContextWrapper>
|
||||
</LicenseContext.Provider>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
describe('ServiceMap', () => {
|
||||
describe('with an inactive license', () => {
|
||||
|
|
|
@ -29,7 +29,7 @@ interface ServiceMapProps {
|
|||
serviceName?: string;
|
||||
}
|
||||
|
||||
export const ServiceMap = ({ serviceName }: ServiceMapProps) => {
|
||||
export function ServiceMap({ serviceName }: ServiceMapProps) {
|
||||
const theme = useTheme();
|
||||
const license = useLicense();
|
||||
const { urlParams } = useUrlParams();
|
||||
|
@ -101,4 +101,4 @@ export const ServiceMap = ({ serviceName }: ServiceMapProps) => {
|
|||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ const ServiceNodeName = styled.div`
|
|||
${truncate(px(8 * unit))}
|
||||
`;
|
||||
|
||||
const ServiceNodeOverview = () => {
|
||||
function ServiceNodeOverview() {
|
||||
const { uiFilters, urlParams } = useUrlParams();
|
||||
const { serviceName, start, end } = urlParams;
|
||||
|
||||
|
@ -182,6 +182,6 @@ const ServiceNodeOverview = () => {
|
|||
</EuiFlexGroup>
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export { ServiceNodeOverview };
|
||||
|
|
|
@ -38,7 +38,7 @@ interface Props {
|
|||
refetch: () => void;
|
||||
}
|
||||
|
||||
export const AgentConfigurationList = ({ status, data, refetch }: Props) => {
|
||||
export function AgentConfigurationList({ status, data, refetch }: Props) {
|
||||
const theme = useTheme();
|
||||
const [configToBeDeleted, setConfigToBeDeleted] = useState<Config | null>(
|
||||
null
|
||||
|
@ -219,4 +219,4 @@ export const AgentConfigurationList = ({ status, data, refetch }: Props) => {
|
|||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,15 +7,13 @@ import React from 'react';
|
|||
import { EuiButton } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
export const CreateCustomLinkButton = ({
|
||||
onClick,
|
||||
}: {
|
||||
onClick: () => void;
|
||||
}) => (
|
||||
<EuiButton color="primary" fill onClick={onClick}>
|
||||
{i18n.translate(
|
||||
'xpack.apm.settings.customizeUI.customLink.createCustomLink',
|
||||
{ defaultMessage: 'Create custom link' }
|
||||
)}
|
||||
</EuiButton>
|
||||
);
|
||||
export function CreateCustomLinkButton({ onClick }: { onClick: () => void }) {
|
||||
return (
|
||||
<EuiButton color="primary" fill onClick={onClick}>
|
||||
{i18n.translate(
|
||||
'xpack.apm.settings.customizeUI.customLink.createCustomLink',
|
||||
{ defaultMessage: 'Create custom link' }
|
||||
)}
|
||||
</EuiButton>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -9,8 +9,14 @@ import { ElasticDocsLink } from '../../../../../shared/Links/ElasticDocsLink';
|
|||
interface Props {
|
||||
label: string;
|
||||
}
|
||||
export const Documentation = ({ label }: Props) => (
|
||||
<ElasticDocsLink section="/kibana" path="/custom-links.html" target="_blank">
|
||||
{label}
|
||||
</ElasticDocsLink>
|
||||
);
|
||||
export function Documentation({ label }: Props) {
|
||||
return (
|
||||
<ElasticDocsLink
|
||||
section="/kibana"
|
||||
path="/custom-links.html"
|
||||
target="_blank"
|
||||
>
|
||||
{label}
|
||||
</ElasticDocsLink>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -26,13 +26,13 @@ import {
|
|||
getSelectOptions,
|
||||
} from './helper';
|
||||
|
||||
export const FiltersSection = ({
|
||||
export function FiltersSection({
|
||||
filters,
|
||||
onChangeFilters,
|
||||
}: {
|
||||
filters: Filter[];
|
||||
onChangeFilters: (filters: Filter[]) => void;
|
||||
}) => {
|
||||
}) {
|
||||
const onChangeFilter = (
|
||||
key: Filter['key'],
|
||||
value: Filter['value'],
|
||||
|
@ -147,25 +147,27 @@ export const FiltersSection = ({
|
|||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
const AddFilterButton = ({
|
||||
function AddFilterButton({
|
||||
onClick,
|
||||
isDisabled,
|
||||
}: {
|
||||
onClick: () => void;
|
||||
isDisabled: boolean;
|
||||
}) => (
|
||||
<EuiButtonEmpty
|
||||
iconType="plusInCircle"
|
||||
onClick={onClick}
|
||||
disabled={isDisabled}
|
||||
>
|
||||
{i18n.translate(
|
||||
'xpack.apm.settings.customizeUI.customLink.flyout.filters.addAnotherFilter',
|
||||
{
|
||||
defaultMessage: 'Add another filter',
|
||||
}
|
||||
)}
|
||||
</EuiButtonEmpty>
|
||||
);
|
||||
}) {
|
||||
return (
|
||||
<EuiButtonEmpty
|
||||
iconType="plusInCircle"
|
||||
onClick={onClick}
|
||||
disabled={isDisabled}
|
||||
>
|
||||
{i18n.translate(
|
||||
'xpack.apm.settings.customizeUI.customLink.flyout.filters.addAnotherFilter',
|
||||
{
|
||||
defaultMessage: 'Add another filter',
|
||||
}
|
||||
)}
|
||||
</EuiButtonEmpty>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import {
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { DeleteButton } from './DeleteButton';
|
||||
|
||||
export const FlyoutFooter = ({
|
||||
export function FlyoutFooter({
|
||||
onClose,
|
||||
isSaving,
|
||||
onDelete,
|
||||
|
@ -26,7 +26,7 @@ export const FlyoutFooter = ({
|
|||
onDelete: () => void;
|
||||
customLinkId?: string;
|
||||
isSaveButtonEnabled: boolean;
|
||||
}) => {
|
||||
}) {
|
||||
return (
|
||||
<EuiFlyoutFooter>
|
||||
<EuiFlexGroup justifyContent="spaceBetween">
|
||||
|
@ -61,4 +61,4 @@ export const FlyoutFooter = ({
|
|||
</EuiFlexGroup>
|
||||
</EuiFlyoutFooter>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ const fetchTransaction = debounce(
|
|||
|
||||
const getTextColor = (value?: string) => (value ? 'default' : 'subdued');
|
||||
|
||||
export const LinkPreview = ({ label, url, filters }: Props) => {
|
||||
export function LinkPreview({ label, url, filters }: Props) {
|
||||
const [transaction, setTransaction] = useState<Transaction | undefined>();
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -128,4 +128,4 @@ export const LinkPreview = ({ label, url, filters }: Props) => {
|
|||
</EuiFlexGroup>
|
||||
</EuiPanel>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -31,12 +31,7 @@ interface Props {
|
|||
onChangeUrl: (url: string) => void;
|
||||
}
|
||||
|
||||
export const LinkSection = ({
|
||||
label,
|
||||
onChangeLabel,
|
||||
url,
|
||||
onChangeUrl,
|
||||
}: Props) => {
|
||||
export function LinkSection({ label, onChangeLabel, url, onChangeUrl }: Props) {
|
||||
const inputFields: InputField[] = [
|
||||
{
|
||||
name: 'label',
|
||||
|
@ -145,4 +140,4 @@ export const LinkSection = ({
|
|||
})}
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -37,13 +37,13 @@ interface Props {
|
|||
|
||||
const filtersEmptyState: Filter[] = [{ key: '', value: '' }];
|
||||
|
||||
export const CustomLinkFlyout = ({
|
||||
export function CustomLinkFlyout({
|
||||
onClose,
|
||||
onSave,
|
||||
onDelete,
|
||||
defaults,
|
||||
customLinkId,
|
||||
}: Props) => {
|
||||
}: Props) {
|
||||
const { toasts } = useApmPluginContext().core.notifications;
|
||||
const [isSaving, setIsSaving] = useState(false);
|
||||
|
||||
|
@ -139,4 +139,4 @@ export const CustomLinkFlyout = ({
|
|||
</form>
|
||||
</EuiPortal>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -24,10 +24,7 @@ interface Props {
|
|||
onCustomLinkSelected: (customLink: CustomLink) => void;
|
||||
}
|
||||
|
||||
export const CustomLinkTable = ({
|
||||
items = [],
|
||||
onCustomLinkSelected,
|
||||
}: Props) => {
|
||||
export function CustomLinkTable({ items = [], onCustomLinkSelected }: Props) {
|
||||
const [searchTerm, setSearchTerm] = useState('');
|
||||
|
||||
const columns = [
|
||||
|
@ -121,20 +118,22 @@ export const CustomLinkTable = ({
|
|||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
const NoResultFound = ({ value }: { value: string }) => (
|
||||
<EuiFlexGroup justifyContent="spaceAround">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiText size="s">
|
||||
{i18n.translate(
|
||||
'xpack.apm.settings.customizeUI.customLink.table.noResultFound',
|
||||
{
|
||||
defaultMessage: `No results for "{value}".`,
|
||||
values: { value },
|
||||
}
|
||||
)}
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
function NoResultFound({ value }: { value: string }) {
|
||||
return (
|
||||
<EuiFlexGroup justifyContent="spaceAround">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiText size="s">
|
||||
{i18n.translate(
|
||||
'xpack.apm.settings.customizeUI.customLink.table.noResultFound',
|
||||
{
|
||||
defaultMessage: `No results for "{value}".`,
|
||||
values: { value },
|
||||
}
|
||||
)}
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -8,11 +8,11 @@ import { i18n } from '@kbn/i18n';
|
|||
import React from 'react';
|
||||
import { CreateCustomLinkButton } from './CreateCustomLinkButton';
|
||||
|
||||
export const EmptyPrompt = ({
|
||||
export function EmptyPrompt({
|
||||
onCreateCustomLinkClick,
|
||||
}: {
|
||||
onCreateCustomLinkClick: () => void;
|
||||
}) => {
|
||||
}) {
|
||||
return (
|
||||
<EuiEmptyPrompt
|
||||
iconType="link"
|
||||
|
@ -43,4 +43,4 @@ export const EmptyPrompt = ({
|
|||
actions={<CreateCustomLinkButton onClick={onCreateCustomLinkClick} />}
|
||||
/>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,34 +7,36 @@ import { EuiFlexGroup, EuiFlexItem, EuiIconTip, EuiTitle } from '@elastic/eui';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import React from 'react';
|
||||
|
||||
export const Title = () => (
|
||||
<EuiFlexGroup alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiTitle size="s">
|
||||
<EuiFlexGroup alignItems="center" gutterSize="s" responsive={false}>
|
||||
<EuiFlexItem grow={false}>
|
||||
<h1>
|
||||
{i18n.translate('xpack.apm.settings.customizeUI.customLink', {
|
||||
defaultMessage: 'Custom Links',
|
||||
})}
|
||||
</h1>
|
||||
</EuiFlexItem>
|
||||
export function Title() {
|
||||
return (
|
||||
<EuiFlexGroup alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiTitle size="s">
|
||||
<EuiFlexGroup alignItems="center" gutterSize="s" responsive={false}>
|
||||
<EuiFlexItem grow={false}>
|
||||
<h1>
|
||||
{i18n.translate('xpack.apm.settings.customizeUI.customLink', {
|
||||
defaultMessage: 'Custom Links',
|
||||
})}
|
||||
</h1>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiIconTip
|
||||
type="iInCircle"
|
||||
position="top"
|
||||
content={i18n.translate(
|
||||
'xpack.apm.settings.customizeUI.customLink.info',
|
||||
{
|
||||
defaultMessage:
|
||||
'These links will be shown in the Actions context menu for transactions.',
|
||||
}
|
||||
)}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiTitle>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiIconTip
|
||||
type="iInCircle"
|
||||
position="top"
|
||||
content={i18n.translate(
|
||||
'xpack.apm.settings.customizeUI.customLink.info',
|
||||
{
|
||||
defaultMessage:
|
||||
'These links will be shown in the Actions context menu for transactions.',
|
||||
}
|
||||
)}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiTitle>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ import { Title } from './Title';
|
|||
import { CreateCustomLinkButton } from './CreateCustomLinkButton';
|
||||
import { LicensePrompt } from '../../../../shared/LicensePrompt';
|
||||
|
||||
export const CustomLinkOverview = () => {
|
||||
export function CustomLinkOverview() {
|
||||
const license = useLicense();
|
||||
const hasValidLicense = license?.isActive && license?.hasAtLeast('gold');
|
||||
|
||||
|
@ -107,4 +107,4 @@ export const CustomLinkOverview = () => {
|
|||
</EuiPanel>
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import { EuiTitle, EuiSpacer } from '@elastic/eui';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { CustomLinkOverview } from './CustomLink';
|
||||
|
||||
export const CustomizeUI = () => {
|
||||
export function CustomizeUI() {
|
||||
return (
|
||||
<>
|
||||
<EuiTitle size="l">
|
||||
|
@ -23,4 +23,4 @@ export const CustomizeUI = () => {
|
|||
<CustomLinkOverview />
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -31,11 +31,11 @@ interface Props {
|
|||
onCreateJobSuccess: () => void;
|
||||
onCancel: () => void;
|
||||
}
|
||||
export const AddEnvironments = ({
|
||||
export function AddEnvironments({
|
||||
currentEnvironments,
|
||||
onCreateJobSuccess,
|
||||
onCancel,
|
||||
}: Props) => {
|
||||
}: Props) {
|
||||
const { notifications, application } = useApmPluginContext().core;
|
||||
const canCreateJob = !!application.capabilities.ml.canCreateJob;
|
||||
const { toasts } = notifications;
|
||||
|
@ -175,4 +175,4 @@ export const AddEnvironments = ({
|
|||
<EuiSpacer size="l" />
|
||||
</EuiPanel>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ const DEFAULT_VALUE: AnomalyDetectionApiResponse = {
|
|||
errorCode: undefined,
|
||||
};
|
||||
|
||||
export const AnomalyDetection = () => {
|
||||
export function AnomalyDetection() {
|
||||
const plugin = useApmPluginContext();
|
||||
const canGetJobs = !!plugin.core.application.capabilities.ml.canGetJobs;
|
||||
const license = useLicense();
|
||||
|
@ -112,4 +112,4 @@ export const AnomalyDetection = () => {
|
|||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ interface Props {
|
|||
status: FETCH_STATUS;
|
||||
onAddEnvironments: () => void;
|
||||
}
|
||||
export const JobsList = ({ data, status, onAddEnvironments }: Props) => {
|
||||
export function JobsList({ data, status, onAddEnvironments }: Props) {
|
||||
const { jobs, hasLegacyJobs, errorCode } = data;
|
||||
|
||||
return (
|
||||
|
@ -127,7 +127,7 @@ export const JobsList = ({ data, status, onAddEnvironments }: Props) => {
|
|||
{hasLegacyJobs && <LegacyJobsCallout />}
|
||||
</EuiPanel>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
function getNoItemsMessage({
|
||||
status,
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, { ReactNode } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import {
|
||||
EuiButtonEmpty,
|
||||
|
@ -17,7 +17,7 @@ import { HomeLink } from '../../shared/Links/apm/HomeLink';
|
|||
import { useLocation } from '../../../hooks/useLocation';
|
||||
import { getAPMHref } from '../../shared/Links/apm/APMLink';
|
||||
|
||||
export const Settings: React.FC = (props) => {
|
||||
export function Settings(props: { children: ReactNode }) {
|
||||
const { search, pathname } = useLocation();
|
||||
return (
|
||||
<>
|
||||
|
@ -84,4 +84,4 @@ export const Settings: React.FC = (props) => {
|
|||
</EuiPage>
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ const redirectToTracePage = ({
|
|||
},
|
||||
});
|
||||
|
||||
export const TraceLink = () => {
|
||||
export function TraceLink() {
|
||||
const { urlParams } = useUrlParams();
|
||||
const { traceIdLink: traceId, rangeFrom, rangeTo } = urlParams;
|
||||
|
||||
|
@ -93,4 +93,4 @@ export const TraceLink = () => {
|
|||
<EuiEmptyPrompt iconType="apmTrace" title={<h2>Fetching trace...</h2>} />
|
||||
</CentralizedContainer>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -7,19 +7,19 @@
|
|||
import { EuiIconTip, EuiTitle } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import d3 from 'd3';
|
||||
import React, { FunctionComponent, useCallback } from 'react';
|
||||
import { isEmpty } from 'lodash';
|
||||
import React, { useCallback } from 'react';
|
||||
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
|
||||
import { TransactionDistributionAPIResponse } from '../../../../../server/lib/transactions/distribution';
|
||||
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
|
||||
import { IBucket } from '../../../../../server/lib/transactions/distribution/get_buckets/transform';
|
||||
import { IUrlParams } from '../../../../context/UrlParamsContext/types';
|
||||
import { getDurationFormatter } from '../../../../utils/formatters';
|
||||
import { history } from '../../../../utils/history';
|
||||
// @ts-ignore
|
||||
import Histogram from '../../../shared/charts/Histogram';
|
||||
import { EmptyMessage } from '../../../shared/EmptyMessage';
|
||||
import { fromQuery, toQuery } from '../../../shared/Links/url_helpers';
|
||||
import { history } from '../../../../utils/history';
|
||||
import { LoadingStatePrompt } from '../../../shared/LoadingStatePrompt';
|
||||
|
||||
interface IChartPoint {
|
||||
|
@ -99,9 +99,7 @@ interface Props {
|
|||
bucketIndex: number;
|
||||
}
|
||||
|
||||
export const TransactionDistribution: FunctionComponent<Props> = (
|
||||
props: Props
|
||||
) => {
|
||||
export function TransactionDistribution(props: Props) {
|
||||
const {
|
||||
distribution,
|
||||
urlParams: { transactionType },
|
||||
|
@ -211,4 +209,4 @@ export const TransactionDistribution: FunctionComponent<Props> = (
|
|||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -12,21 +12,23 @@ interface Props {
|
|||
count: number;
|
||||
}
|
||||
|
||||
export const ErrorCount = ({ count }: Props) => (
|
||||
<EuiText size="xs">
|
||||
<h4>
|
||||
<EuiTextColor
|
||||
color="danger"
|
||||
onClick={(e: React.MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
{i18n.translate('xpack.apm.transactionDetails.errorCount', {
|
||||
defaultMessage:
|
||||
'{errorCount, number} {errorCount, plural, one {Error} other {Errors}}',
|
||||
values: { errorCount: count },
|
||||
})}
|
||||
</EuiTextColor>
|
||||
</h4>
|
||||
</EuiText>
|
||||
);
|
||||
export function ErrorCount({ count }: Props) {
|
||||
return (
|
||||
<EuiText size="xs">
|
||||
<h4>
|
||||
<EuiTextColor
|
||||
color="danger"
|
||||
onClick={(e: React.MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
{i18n.translate('xpack.apm.transactionDetails.errorCount', {
|
||||
defaultMessage:
|
||||
'{errorCount, number} {errorCount, plural, one {Error} other {Errors}}',
|
||||
values: { errorCount: count },
|
||||
})}
|
||||
</EuiTextColor>
|
||||
</h4>
|
||||
</EuiText>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { EuiIcon, EuiLink } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React, { Fragment, useEffect, useRef, useState } from 'react';
|
||||
import React, { Fragment, ReactNode, useEffect, useRef, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { px, units } from '../../../../../../../style/variables';
|
||||
|
||||
|
@ -16,13 +16,11 @@ const ToggleButtonContainer = styled.div`
|
|||
`;
|
||||
|
||||
interface Props {
|
||||
children: ReactNode;
|
||||
previewHeight: number;
|
||||
}
|
||||
|
||||
export const TruncateHeightSection: React.FC<Props> = ({
|
||||
children,
|
||||
previewHeight,
|
||||
}) => {
|
||||
export function TruncateHeightSection({ children, previewHeight }: Props) {
|
||||
const contentContainerEl = useRef<HTMLDivElement>(null);
|
||||
|
||||
const [showToggle, setShowToggle] = useState(true);
|
||||
|
@ -73,4 +71,4 @@ export const TruncateHeightSection: React.FC<Props> = ({
|
|||
) : null}
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -15,12 +15,13 @@ interface Props {
|
|||
location: Location;
|
||||
toggleFlyout: ({ location }: { location: Location }) => void;
|
||||
}
|
||||
export const WaterfallFlyout: React.FC<Props> = ({
|
||||
|
||||
export function WaterfallFlyout({
|
||||
waterfallItemId,
|
||||
waterfall,
|
||||
location,
|
||||
toggleFlyout,
|
||||
}) => {
|
||||
}: Props) {
|
||||
const currentItem = waterfall.items.find(
|
||||
(item) => item.id === waterfallItemId
|
||||
);
|
||||
|
@ -58,4 +59,4 @@ export const WaterfallFlyout: React.FC<Props> = ({
|
|||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, { ReactNode } from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { EuiIcon, EuiText, EuiTitle, EuiToolTip } from '@elastic/eui';
|
||||
|
@ -109,13 +109,11 @@ function PrefixIcon({ item }: { item: IWaterfallItem }) {
|
|||
}
|
||||
|
||||
interface SpanActionToolTipProps {
|
||||
children: ReactNode;
|
||||
item?: IWaterfallItem;
|
||||
}
|
||||
|
||||
const SpanActionToolTip: React.FC<SpanActionToolTipProps> = ({
|
||||
item,
|
||||
children,
|
||||
}) => {
|
||||
function SpanActionToolTip({ item, children }: SpanActionToolTipProps) {
|
||||
if (item?.docType === 'span') {
|
||||
return (
|
||||
<EuiToolTip content={`${item.doc.span.subtype}.${item.doc.span.action}`}>
|
||||
|
@ -124,7 +122,7 @@ const SpanActionToolTip: React.FC<SpanActionToolTipProps> = ({
|
|||
);
|
||||
}
|
||||
return <>{children}</>;
|
||||
};
|
||||
}
|
||||
|
||||
function Duration({ item }: { item: IWaterfallItem }) {
|
||||
return (
|
||||
|
|
|
@ -67,12 +67,12 @@ interface Props {
|
|||
exceedsMax: boolean;
|
||||
}
|
||||
|
||||
export const Waterfall: React.FC<Props> = ({
|
||||
export function Waterfall({
|
||||
waterfall,
|
||||
exceedsMax,
|
||||
waterfallItemId,
|
||||
location,
|
||||
}) => {
|
||||
}: Props) {
|
||||
const itemContainerHeight = 58; // TODO: This is a nasty way to calculate the height of the svg element. A better approach should be found
|
||||
const waterfallHeight = itemContainerHeight * waterfall.items.length;
|
||||
|
||||
|
@ -81,7 +81,7 @@ export const Waterfall: React.FC<Props> = ({
|
|||
const agentMarks = getAgentMarks(waterfall.entryTransaction);
|
||||
const errorMarks = getErrorMarks(waterfall.errorItems, serviceColors);
|
||||
|
||||
const renderWaterfallItem = (item: IWaterfallItem) => {
|
||||
function renderWaterfallItem(item: IWaterfallItem) {
|
||||
const errorCount =
|
||||
item.docType === 'transaction'
|
||||
? waterfall.errorsPerTransaction[item.doc.transaction.id]
|
||||
|
@ -99,7 +99,7 @@ export const Waterfall: React.FC<Props> = ({
|
|||
onClick={() => toggleFlyout({ item, location })}
|
||||
/>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<Container>
|
||||
|
@ -134,4 +134,4 @@ export const Waterfall: React.FC<Props> = ({
|
|||
/>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -37,14 +37,14 @@ interface Props {
|
|||
traceSamples: IBucket['samples'];
|
||||
}
|
||||
|
||||
export const WaterfallWithSummmary: React.FC<Props> = ({
|
||||
export function WaterfallWithSummmary({
|
||||
urlParams,
|
||||
location,
|
||||
waterfall,
|
||||
exceedsMax,
|
||||
isLoading,
|
||||
traceSamples,
|
||||
}) => {
|
||||
}: Props) {
|
||||
const [sampleActivePage, setSampleActivePage] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -135,4 +135,4 @@ export const WaterfallWithSummmary: React.FC<Props> = ({
|
|||
/>
|
||||
</EuiPanel>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -5,29 +5,31 @@
|
|||
*/
|
||||
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
|
||||
import React from 'react';
|
||||
import React, { ReactNode } from 'react';
|
||||
import { KueryBar } from '../KueryBar';
|
||||
import { DatePicker } from '../DatePicker';
|
||||
import { EnvironmentFilter } from '../EnvironmentFilter';
|
||||
|
||||
export const ApmHeader: React.FC = ({ children }) => (
|
||||
<>
|
||||
<EuiFlexGroup alignItems="center" gutterSize="s">
|
||||
<EuiFlexItem>{children}</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<DatePicker />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
export function ApmHeader({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<>
|
||||
<EuiFlexGroup alignItems="center" gutterSize="s">
|
||||
<EuiFlexItem>{children}</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<DatePicker />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
<EuiSpacer />
|
||||
<EuiSpacer />
|
||||
|
||||
<EuiFlexGroup alignItems="flexStart" gutterSize="s">
|
||||
<EuiFlexItem grow={3}>
|
||||
<KueryBar />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={1}>
|
||||
<EnvironmentFilter />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</>
|
||||
);
|
||||
<EuiFlexGroup alignItems="flexStart" gutterSize="s">
|
||||
<EuiFlexItem grow={3}>
|
||||
<KueryBar />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={1}>
|
||||
<EnvironmentFilter />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, { ReactNode } from 'react';
|
||||
import { LocationProvider } from '../../../../context/LocationContext';
|
||||
import {
|
||||
UrlParamsContext,
|
||||
|
@ -21,18 +21,24 @@ import { MockApmPluginContextWrapper } from '../../../../context/ApmPluginContex
|
|||
|
||||
const mockHistoryPush = jest.spyOn(history, 'push');
|
||||
const mockRefreshTimeRange = jest.fn();
|
||||
const MockUrlParamsProvider: React.FC<{
|
||||
function MockUrlParamsProvider({
|
||||
params = {},
|
||||
children,
|
||||
}: {
|
||||
children: ReactNode;
|
||||
params?: IUrlParams;
|
||||
}> = ({ params = {}, children }) => (
|
||||
<UrlParamsContext.Provider
|
||||
value={{
|
||||
urlParams: params,
|
||||
refreshTimeRange: mockRefreshTimeRange,
|
||||
uiFilters: useUiFilters(params),
|
||||
}}
|
||||
children={children}
|
||||
/>
|
||||
);
|
||||
}) {
|
||||
return (
|
||||
<UrlParamsContext.Provider
|
||||
value={{
|
||||
urlParams: params,
|
||||
refreshTimeRange: mockRefreshTimeRange,
|
||||
uiFilters: useUiFilters(params),
|
||||
}}
|
||||
children={children}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function mountDatePicker(params?: IUrlParams) {
|
||||
return mount(
|
||||
|
|
|
@ -14,7 +14,7 @@ interface Props {
|
|||
hideSubheading?: boolean;
|
||||
}
|
||||
|
||||
const EmptyMessage: React.FC<Props> = ({
|
||||
function EmptyMessage({
|
||||
heading = i18n.translate('xpack.apm.emptyMessage.noDataFoundLabel', {
|
||||
defaultMessage: 'No data found.',
|
||||
}),
|
||||
|
@ -22,7 +22,7 @@ const EmptyMessage: React.FC<Props> = ({
|
|||
defaultMessage: 'Try another time range or reset the search filter.',
|
||||
}),
|
||||
hideSubheading = false,
|
||||
}) => {
|
||||
}: Props) {
|
||||
return (
|
||||
<EuiEmptyPrompt
|
||||
titleSize="s"
|
||||
|
@ -30,6 +30,6 @@ const EmptyMessage: React.FC<Props> = ({
|
|||
body={!hideSubheading && subheading}
|
||||
/>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export { EmptyMessage };
|
||||
|
|
|
@ -11,7 +11,7 @@ import { EuiBadge, EuiToolTip } from '@elastic/eui';
|
|||
interface Props {
|
||||
environments: string[];
|
||||
}
|
||||
export const EnvironmentBadge: React.FC<Props> = ({ environments = [] }) => {
|
||||
export function EnvironmentBadge({ environments = [] }: Props) {
|
||||
if (environments.length < 3) {
|
||||
return (
|
||||
<>
|
||||
|
@ -42,4 +42,4 @@ export const EnvironmentBadge: React.FC<Props> = ({ environments = [] }) => {
|
|||
</EuiBadge>
|
||||
</EuiToolTip>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ function getOptions(environments: string[]) {
|
|||
];
|
||||
}
|
||||
|
||||
export const EnvironmentFilter: React.FC = () => {
|
||||
export function EnvironmentFilter() {
|
||||
const location = useLocation();
|
||||
const { uiFilters, urlParams } = useUrlParams();
|
||||
|
||||
|
@ -90,4 +90,4 @@ export const EnvironmentFilter: React.FC = () => {
|
|||
isLoading={status === 'loading'}
|
||||
/>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ const Wrapper = styled.div<{ isSelected: boolean }>`
|
|||
}
|
||||
`;
|
||||
|
||||
const EuiTabLink = (props: Props) => {
|
||||
function EuiTabLink(props: Props) {
|
||||
const { isSelected, children } = props;
|
||||
|
||||
const className = cls('euiTab', {
|
||||
|
@ -44,6 +44,6 @@ const EuiTabLink = (props: Props) => {
|
|||
<span className={'euiTab__content'}>{children}</span>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export { EuiTabLink };
|
||||
|
|
|
@ -6,7 +6,12 @@
|
|||
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
|
||||
export const HeightRetainer: React.FC = (props) => {
|
||||
export function HeightRetainer(
|
||||
props: React.DetailedHTMLProps<
|
||||
React.HTMLAttributes<HTMLDivElement>,
|
||||
HTMLDivElement
|
||||
>
|
||||
) {
|
||||
const containerElement = useRef<HTMLDivElement>(null);
|
||||
const minHeight = useRef<number>(0);
|
||||
|
||||
|
@ -26,4 +31,4 @@ export const HeightRetainer: React.FC = (props) => {
|
|||
style={{ minHeight: minHeight.current }}
|
||||
/>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -112,7 +112,6 @@ export function KueryBar() {
|
|||
|
||||
setState({ ...state, suggestions, isLoadingSuggestions: false });
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Error while fetching suggestions', e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ interface Props {
|
|||
showBetaBadge?: boolean;
|
||||
}
|
||||
|
||||
export const LicensePrompt = ({ text, showBetaBadge = false }: Props) => {
|
||||
export function LicensePrompt({ text, showBetaBadge = false }: Props) {
|
||||
const licensePageUrl = useKibanaUrl(
|
||||
'/app/kibana',
|
||||
'/management/stack/license_management/home'
|
||||
|
@ -60,4 +60,4 @@ export const LicensePrompt = ({ text, showBetaBadge = false }: Props) => {
|
|||
);
|
||||
|
||||
return <>{showBetaBadge ? renderWithBetaBadge : renderLicenseBody}</>;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, { ReactNode } from 'react';
|
||||
import {
|
||||
ERROR_GROUP_ID,
|
||||
SERVICE_NAME,
|
||||
|
@ -32,13 +32,18 @@ function getDiscoverQuery(error: APMError, kuery?: string) {
|
|||
};
|
||||
}
|
||||
|
||||
const DiscoverErrorLink: React.FC<{
|
||||
function DiscoverErrorLink({
|
||||
error,
|
||||
kuery,
|
||||
children,
|
||||
}: {
|
||||
children?: ReactNode;
|
||||
readonly error: APMError;
|
||||
readonly kuery?: string;
|
||||
}> = ({ error, kuery, children }) => {
|
||||
}) {
|
||||
return (
|
||||
<DiscoverLink query={getDiscoverQuery(error, kuery)} children={children} />
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export { DiscoverErrorLink };
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, { ReactNode } from 'react';
|
||||
import { SPAN_ID } from '../../../../../common/elasticsearch_fieldnames';
|
||||
import { Span } from '../../../../../typings/es_schemas/ui/span';
|
||||
import { DiscoverLink } from './DiscoverLink';
|
||||
|
@ -22,8 +22,12 @@ function getDiscoverQuery(span: Span) {
|
|||
};
|
||||
}
|
||||
|
||||
export const DiscoverSpanLink: React.FC<{
|
||||
export function DiscoverSpanLink({
|
||||
span,
|
||||
children,
|
||||
}: {
|
||||
readonly span: Span;
|
||||
}> = ({ span, children }) => {
|
||||
children?: ReactNode;
|
||||
}) {
|
||||
return <DiscoverLink query={getDiscoverQuery(span)} children={children} />;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, { ReactNode } from 'react';
|
||||
import {
|
||||
PROCESSOR_EVENT,
|
||||
TRACE_ID,
|
||||
|
@ -32,10 +32,14 @@ export function getDiscoverQuery(transaction: Transaction) {
|
|||
};
|
||||
}
|
||||
|
||||
export const DiscoverTransactionLink: React.FC<{
|
||||
export function DiscoverTransactionLink({
|
||||
transaction,
|
||||
children,
|
||||
}: {
|
||||
readonly transaction: Transaction;
|
||||
}> = ({ transaction, children }) => {
|
||||
children?: ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<DiscoverLink query={getDiscoverQuery(transaction)} children={children} />
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -4,24 +4,25 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, { ReactNode } from 'react';
|
||||
import { EuiLink } from '@elastic/eui';
|
||||
import { useTimeSeriesExplorerHref } from './useTimeSeriesExplorerHref';
|
||||
|
||||
interface Props {
|
||||
children?: ReactNode;
|
||||
jobId: string;
|
||||
external?: boolean;
|
||||
serviceName?: string;
|
||||
transactionType?: string;
|
||||
}
|
||||
|
||||
export const MLJobLink: React.FC<Props> = ({
|
||||
export function MLJobLink({
|
||||
jobId,
|
||||
serviceName,
|
||||
transactionType,
|
||||
external,
|
||||
children,
|
||||
}) => {
|
||||
}: Props) {
|
||||
const href = useTimeSeriesExplorerHref({
|
||||
jobId,
|
||||
serviceName,
|
||||
|
@ -36,4 +37,4 @@ export const MLJobLink: React.FC<Props> = ({
|
|||
target={external ? '_blank' : undefined}
|
||||
/>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -11,13 +11,13 @@ interface Props extends APMLinkExtendProps {
|
|||
errorGroupId: string;
|
||||
}
|
||||
|
||||
const ErrorDetailLink = ({ serviceName, errorGroupId, ...rest }: Props) => {
|
||||
function ErrorDetailLink({ serviceName, errorGroupId, ...rest }: Props) {
|
||||
return (
|
||||
<APMLink
|
||||
path={`/services/${serviceName}/errors/${errorGroupId}`}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export { ErrorDetailLink };
|
||||
|
|
|
@ -14,7 +14,7 @@ interface Props extends APMLinkExtendProps {
|
|||
query?: APMQueryParams;
|
||||
}
|
||||
|
||||
const ErrorOverviewLink = ({ serviceName, query, ...rest }: Props) => {
|
||||
function ErrorOverviewLink({ serviceName, query, ...rest }: Props) {
|
||||
const { urlParams } = useUrlParams();
|
||||
|
||||
const persistedFilters = pickKeys(
|
||||
|
@ -35,6 +35,6 @@ const ErrorOverviewLink = ({ serviceName, query, ...rest }: Props) => {
|
|||
{...rest}
|
||||
/>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export { ErrorOverviewLink };
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
import React from 'react';
|
||||
import { APMLink, APMLinkExtendProps } from './APMLink';
|
||||
|
||||
const HomeLink = (props: APMLinkExtendProps) => {
|
||||
function HomeLink(props: APMLinkExtendProps) {
|
||||
return <APMLink path="/" {...props} />;
|
||||
};
|
||||
}
|
||||
|
||||
export { HomeLink };
|
||||
|
|
|
@ -12,7 +12,7 @@ interface Props extends APMLinkExtendProps {
|
|||
serviceName: string;
|
||||
}
|
||||
|
||||
const MetricOverviewLink = ({ serviceName, ...rest }: Props) => {
|
||||
function MetricOverviewLink({ serviceName, ...rest }: Props) {
|
||||
const { urlParams } = useUrlParams();
|
||||
|
||||
const persistedFilters = pickKeys(
|
||||
|
@ -30,6 +30,6 @@ const MetricOverviewLink = ({ serviceName, ...rest }: Props) => {
|
|||
{...rest}
|
||||
/>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export { MetricOverviewLink };
|
||||
|
|
|
@ -16,11 +16,11 @@ interface ServiceMapLinkProps extends APMLinkExtendProps {
|
|||
serviceName?: string;
|
||||
}
|
||||
|
||||
const ServiceMapLink = ({ serviceName, ...rest }: ServiceMapLinkProps) => {
|
||||
function ServiceMapLink({ serviceName, ...rest }: ServiceMapLinkProps) {
|
||||
const path = serviceName
|
||||
? `/services/${serviceName}/service-map`
|
||||
: '/service-map';
|
||||
return <APMLink path={path} {...rest} />;
|
||||
};
|
||||
}
|
||||
|
||||
export { ServiceMapLink };
|
||||
|
|
|
@ -13,11 +13,11 @@ interface Props extends APMLinkExtendProps {
|
|||
serviceNodeName: string;
|
||||
}
|
||||
|
||||
const ServiceNodeMetricOverviewLink = ({
|
||||
function ServiceNodeMetricOverviewLink({
|
||||
serviceName,
|
||||
serviceNodeName,
|
||||
...rest
|
||||
}: Props) => {
|
||||
}: Props) {
|
||||
const { urlParams } = useUrlParams();
|
||||
|
||||
const persistedFilters = pickKeys(
|
||||
|
@ -37,6 +37,6 @@ const ServiceNodeMetricOverviewLink = ({
|
|||
{...rest}
|
||||
/>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export { ServiceNodeMetricOverviewLink };
|
||||
|
|
|
@ -12,7 +12,7 @@ interface Props extends APMLinkExtendProps {
|
|||
serviceName: string;
|
||||
}
|
||||
|
||||
const ServiceNodeOverviewLink = ({ serviceName, ...rest }: Props) => {
|
||||
function ServiceNodeOverviewLink({ serviceName, ...rest }: Props) {
|
||||
const { urlParams } = useUrlParams();
|
||||
|
||||
const persistedFilters = pickKeys(
|
||||
|
@ -30,6 +30,6 @@ const ServiceNodeOverviewLink = ({ serviceName, ...rest }: Props) => {
|
|||
{...rest}
|
||||
/>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export { ServiceNodeOverviewLink };
|
||||
|
|
|
@ -14,12 +14,12 @@ import { APMLink, APMLinkExtendProps } from './APMLink';
|
|||
import { useUrlParams } from '../../../../hooks/useUrlParams';
|
||||
import { pickKeys } from '../../../../../common/utils/pick_keys';
|
||||
|
||||
const ServiceOverviewLink = (props: APMLinkExtendProps) => {
|
||||
function ServiceOverviewLink(props: APMLinkExtendProps) {
|
||||
const { urlParams } = useUrlParams();
|
||||
|
||||
const persistedFilters = pickKeys(urlParams, 'host', 'agentName');
|
||||
|
||||
return <APMLink path="/services" query={persistedFilters} {...props} />;
|
||||
};
|
||||
}
|
||||
|
||||
export { ServiceOverviewLink };
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
import React from 'react';
|
||||
import { APMLink, APMLinkExtendProps } from './APMLink';
|
||||
|
||||
const SettingsLink = (props: APMLinkExtendProps) => {
|
||||
function SettingsLink(props: APMLinkExtendProps) {
|
||||
return <APMLink path="/settings" {...props} />;
|
||||
};
|
||||
}
|
||||
|
||||
export { SettingsLink };
|
||||
|
|
|
@ -14,7 +14,7 @@ import { APMLink, APMLinkExtendProps } from './APMLink';
|
|||
import { useUrlParams } from '../../../../hooks/useUrlParams';
|
||||
import { pickKeys } from '../../../../../common/utils/pick_keys';
|
||||
|
||||
const TraceOverviewLink = (props: APMLinkExtendProps) => {
|
||||
function TraceOverviewLink(props: APMLinkExtendProps) {
|
||||
const { urlParams } = useUrlParams();
|
||||
|
||||
const persistedFilters = pickKeys(
|
||||
|
@ -26,6 +26,6 @@ const TraceOverviewLink = (props: APMLinkExtendProps) => {
|
|||
);
|
||||
|
||||
return <APMLink path="/traces" query={persistedFilters} {...props} />;
|
||||
};
|
||||
}
|
||||
|
||||
export { TraceOverviewLink };
|
||||
|
|
|
@ -17,14 +17,14 @@ interface Props extends APMLinkExtendProps {
|
|||
transactionType: string;
|
||||
}
|
||||
|
||||
export const TransactionDetailLink = ({
|
||||
export function TransactionDetailLink({
|
||||
serviceName,
|
||||
traceId,
|
||||
transactionId,
|
||||
transactionName,
|
||||
transactionType,
|
||||
...rest
|
||||
}: Props) => {
|
||||
}: Props) {
|
||||
const { urlParams } = useUrlParams();
|
||||
|
||||
const persistedFilters = pickKeys(
|
||||
|
@ -46,4 +46,4 @@ export const TransactionDetailLink = ({
|
|||
{...rest}
|
||||
/>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ interface Props extends APMLinkExtendProps {
|
|||
serviceName: string;
|
||||
}
|
||||
|
||||
const TransactionOverviewLink = ({ serviceName, ...rest }: Props) => {
|
||||
function TransactionOverviewLink({ serviceName, ...rest }: Props) {
|
||||
const { urlParams } = useUrlParams();
|
||||
|
||||
const persistedFilters = pickKeys(
|
||||
|
@ -31,6 +31,6 @@ const TransactionOverviewLink = ({ serviceName, ...rest }: Props) => {
|
|||
{...rest}
|
||||
/>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export { TransactionOverviewLink };
|
||||
|
|
|
@ -20,24 +20,26 @@ interface Props {
|
|||
onRemove: (val: string) => void;
|
||||
}
|
||||
|
||||
const FilterBadgeList = ({ onRemove, value }: Props) => (
|
||||
<EuiFlexGrid gutterSize="s">
|
||||
{value.map((val) => (
|
||||
<EuiFlexItem key={val} grow={false}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
onRemove(val);
|
||||
}}
|
||||
>
|
||||
<EuiBadge color="hollow">
|
||||
<BadgeText>{val}</BadgeText>
|
||||
<EuiIcon type="cross" />
|
||||
</EuiBadge>
|
||||
</button>
|
||||
</EuiFlexItem>
|
||||
))}
|
||||
</EuiFlexGrid>
|
||||
);
|
||||
function FilterBadgeList({ onRemove, value }: Props) {
|
||||
return (
|
||||
<EuiFlexGrid gutterSize="s">
|
||||
{value.map((val) => (
|
||||
<EuiFlexItem key={val} grow={false}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
onRemove(val);
|
||||
}}
|
||||
>
|
||||
<EuiBadge color="hollow">
|
||||
<BadgeText>{val}</BadgeText>
|
||||
<EuiIcon type="cross" />
|
||||
</EuiBadge>
|
||||
</button>
|
||||
</EuiFlexItem>
|
||||
))}
|
||||
</EuiFlexGrid>
|
||||
);
|
||||
}
|
||||
|
||||
export { FilterBadgeList };
|
||||
|
|
|
@ -24,7 +24,7 @@ const Button = styled(EuiButtonEmpty).attrs(() => ({
|
|||
|
||||
type Props = React.ComponentProps<typeof Button>;
|
||||
|
||||
export const FilterTitleButton = (props: Props) => {
|
||||
export function FilterTitleButton(props: Props) {
|
||||
return (
|
||||
<Button {...props}>
|
||||
<EuiTitle size="xxxs" textTransform="uppercase">
|
||||
|
@ -32,4 +32,4 @@ export const FilterTitleButton = (props: Props) => {
|
|||
</EuiTitle>
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -66,14 +66,7 @@ interface Props {
|
|||
|
||||
type Option = EuiSelectable['props']['options'][0];
|
||||
|
||||
const Filter = ({
|
||||
name,
|
||||
title,
|
||||
options,
|
||||
onChange,
|
||||
value,
|
||||
showCount,
|
||||
}: Props) => {
|
||||
function Filter({ name, title, options, onChange, value, showCount }: Props) {
|
||||
const [showPopover, setShowPopover] = useState(false);
|
||||
|
||||
const toggleShowPopover = () => setShowPopover((show) => !show);
|
||||
|
@ -176,6 +169,6 @@ const Filter = ({
|
|||
) : null}
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export { Filter };
|
||||
|
|
|
@ -21,7 +21,7 @@ interface Props {
|
|||
loading: boolean;
|
||||
}
|
||||
|
||||
const ServiceNameFilter = ({ loading, serviceNames }: Props) => {
|
||||
function ServiceNameFilter({ loading, serviceNames }: Props) {
|
||||
const {
|
||||
urlParams: { serviceName },
|
||||
} = useUrlParams();
|
||||
|
@ -72,6 +72,6 @@ const ServiceNameFilter = ({ loading, serviceNames }: Props) => {
|
|||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export { ServiceNameFilter };
|
||||
|
|
|
@ -20,7 +20,7 @@ interface Props {
|
|||
transactionTypes: string[];
|
||||
}
|
||||
|
||||
const TransactionTypeFilter = ({ transactionTypes }: Props) => {
|
||||
function TransactionTypeFilter({ transactionTypes }: Props) {
|
||||
const {
|
||||
urlParams: { transactionType },
|
||||
} = useUrlParams();
|
||||
|
@ -59,6 +59,6 @@ const TransactionTypeFilter = ({ transactionTypes }: Props) => {
|
|||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export { TransactionTypeFilter };
|
||||
|
|
|
@ -31,13 +31,13 @@ const ButtonWrapper = styled.div`
|
|||
display: inline-block;
|
||||
`;
|
||||
|
||||
const LocalUIFilters = ({
|
||||
function LocalUIFilters({
|
||||
projection,
|
||||
params,
|
||||
filterNames,
|
||||
children,
|
||||
showCount = true,
|
||||
}: Props) => {
|
||||
}: Props) {
|
||||
const { filters, setFilterValue, clearValues } = useLocalUIFilters({
|
||||
filterNames,
|
||||
projection,
|
||||
|
@ -91,6 +91,6 @@ const LocalUIFilters = ({
|
|||
) : null}
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export { LocalUIFilters };
|
||||
|
|
|
@ -91,18 +91,20 @@ export function MetadataTable({ sections }: Props) {
|
|||
);
|
||||
}
|
||||
|
||||
const NoResultFound = ({ value }: { value: string }) => (
|
||||
<EuiFlexGroup justifyContent="spaceAround">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiText size="s">
|
||||
{i18n.translate(
|
||||
'xpack.apm.propertiesTable.agentFeature.noResultFound',
|
||||
{
|
||||
defaultMessage: `No results for "{value}".`,
|
||||
values: { value },
|
||||
}
|
||||
)}
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
function NoResultFound({ value }: { value: string }) {
|
||||
return (
|
||||
<EuiFlexGroup justifyContent="spaceAround">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiText size="s">
|
||||
{i18n.translate(
|
||||
'xpack.apm.propertiesTable.agentFeature.noResultFound',
|
||||
{
|
||||
defaultMessage: `No results for "{value}".`,
|
||||
values: { value },
|
||||
}
|
||||
)}
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ const DEFAULT_PLACEHOLDER = i18n.translate('xpack.apm.selectPlaceholder', {
|
|||
* with `hasNoInitialSelection`. It uses the `placeholder` prop to populate
|
||||
* the first option as the initial, not selected option.
|
||||
*/
|
||||
// eslint-disable-next-line react/function-component-definition
|
||||
export const SelectWithPlaceholder: typeof EuiSelect = (props) => {
|
||||
const placeholder = props.placeholder || DEFAULT_PLACEHOLDER;
|
||||
return (
|
||||
|
|
|
@ -13,7 +13,7 @@ interface Props {
|
|||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
export const PopoverExpression = (props: Props) => {
|
||||
export function PopoverExpression(props: Props) {
|
||||
const { title, value, children } = props;
|
||||
|
||||
const [popoverOpen, setPopoverOpen] = useState(false);
|
||||
|
@ -36,4 +36,4 @@ export const PopoverExpression = (props: Props) => {
|
|||
{children}
|
||||
</EuiPopover>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ interface Props {
|
|||
isLibraryFrame: boolean;
|
||||
}
|
||||
|
||||
const FrameHeading: React.FC<Props> = ({ stackframe, isLibraryFrame }) => {
|
||||
function FrameHeading({ stackframe, isLibraryFrame }: Props) {
|
||||
const FileDetail = isLibraryFrame
|
||||
? LibraryFrameFileDetail
|
||||
: AppFrameFileDetail;
|
||||
|
@ -50,6 +50,6 @@ const FrameHeading: React.FC<Props> = ({ stackframe, isLibraryFrame }) => {
|
|||
)}
|
||||
</FileDetails>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export { FrameHeading };
|
||||
|
|
|
@ -23,7 +23,7 @@ interface Props {
|
|||
vars: IStackframe['vars'];
|
||||
}
|
||||
|
||||
export const Variables = ({ vars }: Props) => {
|
||||
export function Variables({ vars }: Props) {
|
||||
if (!vars) {
|
||||
return null;
|
||||
}
|
||||
|
@ -46,4 +46,4 @@ export const Variables = ({ vars }: Props) => {
|
|||
</VariablesContainer>
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -15,11 +15,7 @@ interface Props {
|
|||
parentType: 'trace' | 'transaction';
|
||||
}
|
||||
|
||||
const DurationSummaryItem = ({
|
||||
duration,
|
||||
totalDuration,
|
||||
parentType,
|
||||
}: Props) => {
|
||||
function DurationSummaryItem({ duration, totalDuration, parentType }: Props) {
|
||||
const calculatedTotalDuration =
|
||||
totalDuration === undefined ? duration : totalDuration;
|
||||
|
||||
|
@ -41,6 +37,6 @@ const DurationSummaryItem = ({
|
|||
</EuiText>
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export { DurationSummaryItem };
|
||||
|
|
|
@ -19,7 +19,7 @@ const Badge = (styled(EuiBadge)`
|
|||
margin-top: ${px(units.eighth)};
|
||||
` as unknown) as typeof EuiBadge;
|
||||
|
||||
export const ErrorCountSummaryItemBadge = ({ count }: Props) => {
|
||||
export function ErrorCountSummaryItemBadge({ count }: Props) {
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
|
@ -31,4 +31,4 @@ export const ErrorCountSummaryItemBadge = ({ count }: Props) => {
|
|||
})}
|
||||
</Badge>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ interface Props {
|
|||
errorCount: number;
|
||||
}
|
||||
|
||||
const getTransactionResultSummaryItem = (transaction: Transaction) => {
|
||||
function getTransactionResultSummaryItem(transaction: Transaction) {
|
||||
const result = transaction.transaction.result;
|
||||
const isRumAgent = isRumAgentName(transaction.agent.name);
|
||||
const url = isRumAgent
|
||||
|
@ -39,13 +39,9 @@ const getTransactionResultSummaryItem = (transaction: Transaction) => {
|
|||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
const TransactionSummary = ({
|
||||
transaction,
|
||||
totalDuration,
|
||||
errorCount,
|
||||
}: Props) => {
|
||||
function TransactionSummary({ transaction, totalDuration, errorCount }: Props) {
|
||||
const items = [
|
||||
<TimestampTooltip time={transaction.timestamp.us / 1000} />,
|
||||
<DurationSummaryItem
|
||||
|
@ -61,6 +57,6 @@ const TransactionSummary = ({
|
|||
];
|
||||
|
||||
return <Summary items={items} />;
|
||||
};
|
||||
}
|
||||
|
||||
export { TransactionSummary };
|
||||
|
|
|
@ -26,7 +26,7 @@ const Item = styled(EuiFlexItem)`
|
|||
}
|
||||
`;
|
||||
|
||||
const Summary = ({ items }: Props) => {
|
||||
function Summary({ items }: Props) {
|
||||
const filteredItems = items.filter(Boolean) as React.ReactElement[];
|
||||
|
||||
return (
|
||||
|
@ -38,6 +38,6 @@ const Summary = ({ items }: Props) => {
|
|||
))}
|
||||
</EuiFlexGrid>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export { Summary };
|
||||
|
|
|
@ -24,7 +24,7 @@ const ScrollableContainer = styled.div`
|
|||
overflow: scroll;
|
||||
`;
|
||||
|
||||
export const CustomLinkPopover = ({
|
||||
export function CustomLinkPopover({
|
||||
customLinks,
|
||||
onCreateCustomLinkClick,
|
||||
onClose,
|
||||
|
@ -34,7 +34,7 @@ export const CustomLinkPopover = ({
|
|||
onCreateCustomLinkClick: () => void;
|
||||
onClose: () => void;
|
||||
transaction: Transaction;
|
||||
}) => {
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
<EuiPopoverTitle>
|
||||
|
@ -71,4 +71,4 @@ export const CustomLinkPopover = ({
|
|||
</ScrollableContainer>
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -24,28 +24,30 @@ const TruncateText = styled(EuiText)`
|
|||
${truncate(px(units.unit * 25))}
|
||||
`;
|
||||
|
||||
export const CustomLinkSection = ({
|
||||
export function CustomLinkSection({
|
||||
customLinks,
|
||||
transaction,
|
||||
}: {
|
||||
customLinks: CustomLink[];
|
||||
transaction: Transaction;
|
||||
}) => (
|
||||
<ul>
|
||||
{customLinks.map((link) => {
|
||||
let href = link.url;
|
||||
try {
|
||||
href = Mustache.render(link.url, transaction);
|
||||
} catch (e) {
|
||||
// ignores any error that happens
|
||||
}
|
||||
return (
|
||||
<LinkContainer key={link.id}>
|
||||
<EuiLink href={href} target="_blank">
|
||||
<TruncateText size="s">{link.label}</TruncateText>
|
||||
</EuiLink>
|
||||
</LinkContainer>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
);
|
||||
}) {
|
||||
return (
|
||||
<ul>
|
||||
{customLinks.map((link) => {
|
||||
let href = link.url;
|
||||
try {
|
||||
href = Mustache.render(link.url, transaction);
|
||||
} catch (e) {
|
||||
// ignores any error that happens
|
||||
}
|
||||
return (
|
||||
<LinkContainer key={link.id}>
|
||||
<EuiLink href={href} target="_blank">
|
||||
<TruncateText size="s">{link.label}</TruncateText>
|
||||
</EuiLink>
|
||||
</LinkContainer>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -14,46 +14,48 @@ import {
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { APMLink } from '../../Links/apm/APMLink';
|
||||
|
||||
export const ManageCustomLink = ({
|
||||
export function ManageCustomLink({
|
||||
onCreateCustomLinkClick,
|
||||
showCreateCustomLinkButton = true,
|
||||
}: {
|
||||
onCreateCustomLinkClick: () => void;
|
||||
showCreateCustomLinkButton?: boolean;
|
||||
}) => (
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem>
|
||||
<EuiFlexGroup justifyContent="flexEnd" gutterSize="none">
|
||||
<EuiFlexItem grow={false} style={{ justifyContent: 'center' }}>
|
||||
<EuiToolTip
|
||||
position="top"
|
||||
content={i18n.translate('xpack.apm.customLink.buttom.manage', {
|
||||
defaultMessage: 'Manage custom links',
|
||||
})}
|
||||
>
|
||||
<APMLink path={`/settings/customize-ui`}>
|
||||
<EuiIcon
|
||||
type="gear"
|
||||
color="text"
|
||||
aria-label="Custom links settings page"
|
||||
/>
|
||||
</APMLink>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
{showCreateCustomLinkButton && (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonEmpty
|
||||
iconType="plusInCircle"
|
||||
size="xs"
|
||||
onClick={onCreateCustomLinkClick}
|
||||
>
|
||||
{i18n.translate('xpack.apm.customLink.buttom.create.title', {
|
||||
defaultMessage: 'Create',
|
||||
}) {
|
||||
return (
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem>
|
||||
<EuiFlexGroup justifyContent="flexEnd" gutterSize="none">
|
||||
<EuiFlexItem grow={false} style={{ justifyContent: 'center' }}>
|
||||
<EuiToolTip
|
||||
position="top"
|
||||
content={i18n.translate('xpack.apm.customLink.buttom.manage', {
|
||||
defaultMessage: 'Manage custom links',
|
||||
})}
|
||||
</EuiButtonEmpty>
|
||||
>
|
||||
<APMLink path={`/settings/customize-ui`}>
|
||||
<EuiIcon
|
||||
type="gear"
|
||||
color="text"
|
||||
aria-label="Custom links settings page"
|
||||
/>
|
||||
</APMLink>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
{showCreateCustomLinkButton && (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonEmpty
|
||||
iconType="plusInCircle"
|
||||
size="xs"
|
||||
onClick={onCreateCustomLinkClick}
|
||||
>
|
||||
{i18n.translate('xpack.apm.customLink.buttom.create.title', {
|
||||
defaultMessage: 'Create',
|
||||
})}
|
||||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ const SeeMoreButton = styled.button<{ show: boolean }>`
|
|||
}
|
||||
`;
|
||||
|
||||
export const CustomLink = ({
|
||||
export function CustomLink({
|
||||
customLinks,
|
||||
status,
|
||||
onCreateCustomLinkClick,
|
||||
|
@ -49,7 +49,7 @@ export const CustomLink = ({
|
|||
onCreateCustomLinkClick: () => void;
|
||||
onSeeMoreClick: () => void;
|
||||
transaction: Transaction;
|
||||
}) => {
|
||||
}) {
|
||||
const renderEmptyPrompt = (
|
||||
<>
|
||||
<EuiText size="xs" grow={false} style={{ width: px(300) }}>
|
||||
|
@ -125,4 +125,4 @@ export const CustomLink = ({
|
|||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,10 +6,8 @@
|
|||
|
||||
import { EuiButtonEmpty } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React, { FunctionComponent, useMemo, useState, MouseEvent } from 'react';
|
||||
import React, { MouseEvent, useMemo, useState } from 'react';
|
||||
import url from 'url';
|
||||
import { Filter } from '../../../../common/custom_link/custom_link_types';
|
||||
import { Transaction } from '../../../../typings/es_schemas/ui/transaction';
|
||||
import {
|
||||
ActionMenu,
|
||||
ActionMenuDivider,
|
||||
|
@ -19,32 +17,34 @@ import {
|
|||
SectionSubtitle,
|
||||
SectionTitle,
|
||||
} from '../../../../../observability/public';
|
||||
import { Filter } from '../../../../common/custom_link/custom_link_types';
|
||||
import { Transaction } from '../../../../typings/es_schemas/ui/transaction';
|
||||
import { useApmPluginContext } from '../../../hooks/useApmPluginContext';
|
||||
import { useFetcher } from '../../../hooks/useFetcher';
|
||||
import { useLicense } from '../../../hooks/useLicense';
|
||||
import { useLocation } from '../../../hooks/useLocation';
|
||||
import { useUrlParams } from '../../../hooks/useUrlParams';
|
||||
import { CustomLinkFlyout } from '../../app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout';
|
||||
import { convertFiltersToQuery } from '../../app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/helper';
|
||||
import { CustomLink } from './CustomLink';
|
||||
import { CustomLinkPopover } from './CustomLink/CustomLinkPopover';
|
||||
import { getSections } from './sections';
|
||||
import { useLicense } from '../../../hooks/useLicense';
|
||||
import { convertFiltersToQuery } from '../../app/Settings/CustomizeUI/CustomLink/CustomLinkFlyout/helper';
|
||||
|
||||
interface Props {
|
||||
readonly transaction: Transaction;
|
||||
}
|
||||
|
||||
const ActionMenuButton = ({ onClick }: { onClick: () => void }) => (
|
||||
<EuiButtonEmpty iconType="arrowDown" iconSide="right" onClick={onClick}>
|
||||
{i18n.translate('xpack.apm.transactionActionMenu.actionsButtonLabel', {
|
||||
defaultMessage: 'Actions',
|
||||
})}
|
||||
</EuiButtonEmpty>
|
||||
);
|
||||
function ActionMenuButton({ onClick }: { onClick: () => void }) {
|
||||
return (
|
||||
<EuiButtonEmpty iconType="arrowDown" iconSide="right" onClick={onClick}>
|
||||
{i18n.translate('xpack.apm.transactionActionMenu.actionsButtonLabel', {
|
||||
defaultMessage: 'Actions',
|
||||
})}
|
||||
</EuiButtonEmpty>
|
||||
);
|
||||
}
|
||||
|
||||
export const TransactionActionMenu: FunctionComponent<Props> = ({
|
||||
transaction,
|
||||
}: Props) => {
|
||||
export function TransactionActionMenu({ transaction }: Props) {
|
||||
const license = useLicense();
|
||||
const hasValidLicense = license?.isActive && license?.hasAtLeast('gold');
|
||||
|
||||
|
@ -211,4 +211,4 @@ export const TransactionActionMenu: FunctionComponent<Props> = ({
|
|||
</ActionMenu>
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ const formatTooltipValue = (coordinate: Coordinate) => {
|
|||
: NOT_AVAILABLE_LABEL;
|
||||
};
|
||||
|
||||
const TransactionBreakdownGraph: React.FC<Props> = (props) => {
|
||||
function TransactionBreakdownGraph(props: Props) {
|
||||
const { timeseries } = props;
|
||||
const trackApmEvent = useUiTracker({ app: 'apm' });
|
||||
const handleHover = useMemo(
|
||||
|
@ -49,6 +49,6 @@ const TransactionBreakdownGraph: React.FC<Props> = (props) => {
|
|||
onHover={handleHover}
|
||||
/>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export { TransactionBreakdownGraph };
|
||||
|
|
|
@ -31,10 +31,7 @@ const Description = styled.span`
|
|||
}
|
||||
`;
|
||||
|
||||
const KpiDescription: React.FC<{
|
||||
name: string;
|
||||
color: string;
|
||||
}> = ({ name, color }) => {
|
||||
function KpiDescription({ name, color }: { name: string; color: string }) {
|
||||
return (
|
||||
<EuiFlexGroup
|
||||
alignItems="center"
|
||||
|
@ -52,9 +49,9 @@ const KpiDescription: React.FC<{
|
|||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
const TransactionBreakdownKpiList: React.FC<Props> = ({ kpis }) => {
|
||||
function TransactionBreakdownKpiList({ kpis }: Props) {
|
||||
return (
|
||||
<EuiFlexGrid>
|
||||
{kpis.map((kpi) => (
|
||||
|
@ -73,6 +70,6 @@ const TransactionBreakdownKpiList: React.FC<Props> = ({ kpis }) => {
|
|||
))}
|
||||
</EuiFlexGrid>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export { TransactionBreakdownKpiList };
|
||||
|
|
|
@ -21,7 +21,7 @@ const emptyMessage = i18n.translate('xpack.apm.transactionBreakdown.noData', {
|
|||
defaultMessage: 'No data within this time range.',
|
||||
});
|
||||
|
||||
const TransactionBreakdown = () => {
|
||||
function TransactionBreakdown() {
|
||||
const { data, status } = useTransactionBreakdown();
|
||||
const { kpis, timeseries } = data;
|
||||
const noHits = data.kpis.length === 0 && status === FETCH_STATUS.SUCCESS;
|
||||
|
@ -51,6 +51,6 @@ const TransactionBreakdown = () => {
|
|||
</EuiFlexGroup>
|
||||
</EuiPanel>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export { TransactionBreakdown };
|
||||
|
|
|
@ -26,7 +26,7 @@ interface Props {
|
|||
overlay: Maybe<HTMLElement>;
|
||||
}
|
||||
|
||||
export const AnnotationsPlot = ({ plotValues, annotations }: Props) => {
|
||||
export function AnnotationsPlot({ plotValues, annotations }: Props) {
|
||||
const theme = useTheme();
|
||||
const tickValues = annotations.map((annotation) => annotation['@timestamp']);
|
||||
|
||||
|
@ -70,4 +70,4 @@ export const AnnotationsPlot = ({ plotValues, annotations }: Props) => {
|
|||
))}
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ const tickFormatY = (y?: number) => {
|
|||
return asPercent(y || 0, 1);
|
||||
};
|
||||
|
||||
export const ErroneousTransactionsRateChart = () => {
|
||||
export function ErroneousTransactionsRateChart() {
|
||||
const { urlParams, uiFilters } = useUrlParams();
|
||||
const syncedChartsProps = useChartsSync();
|
||||
|
||||
|
@ -105,4 +105,4 @@ export const ErroneousTransactionsRateChart = () => {
|
|||
/>
|
||||
</EuiPanel>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue