Monitoring Angular directives to use React components (#19183)

* remove some webpack aliases for jest

* remove status icon angular directive

* fix some component import problems
This commit is contained in:
Tim Sullivan 2018-07-19 14:29:25 -07:00 committed by GitHub
parent 80833cde95
commit 2216b226d6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 291 additions and 130 deletions

View file

@ -5,8 +5,8 @@
*/
import React, { Fragment } from 'react';
import { MonitoringTimeseriesContainer } from 'plugins/monitoring/components';
import { formatMetric } from 'plugins/monitoring/lib/format_number';
import { MonitoringTimeseriesContainer } from '../../chart';
import { formatMetric } from '../../../lib/format_number';
function renderTransportAddress(summary) {
let output = null;

View file

@ -9,7 +9,7 @@ import { LatestActive } from './latest_active';
import { LatestVersions } from './latest_versions';
import { LatestTypes } from './latest_types';
import { Stats } from '../';
import { MonitoringTimeseriesContainer } from 'plugins/monitoring/components';
import { MonitoringTimeseriesContainer } from '../../chart';
import { EuiCallOut } from '@elastic/eui';
function renderLatestActive(latestActive, latestTypes, latestVersions) {

View file

@ -11,7 +11,7 @@ import { LARGE_FLOAT, LARGE_BYTES, LARGE_ABBREVIATED } from '../../../../common/
import { formatMetric } from '../../../lib/format_number';
import { ElasticsearchStatusIcon } from '../status_icon';
import { ClusterStatus } from '../cluster_status';
import { MonitoringTable } from '../../';
import { MonitoringTable } from '../../table';
import { EuiLink } from '@elastic/eui';
import { KuiTableRowCell, KuiTableRow } from '@kbn/ui-framework/components';
import { SystemIndicesCheckbox } from './system_indices_checkbox';

View file

@ -10,7 +10,7 @@ import { SORT_ASCENDING } from '../../../../common/constants';
import { NodeStatusIcon } from '../node';
import { extractIp } from '../../../lib/extract_ip'; // TODO this is only used for elasticsearch nodes summary / node detail, so it should be moved to components/elasticsearch/nodes/lib
import { ClusterStatus } from '../cluster_status';
import { MonitoringTable } from '../../';
import { MonitoringTable } from '../../table';
import { MetricCell, OfflineCell } from './cells';
import { EuiLink, EuiToolTip } from '@elastic/eui';
import { KuiTableRowCell, KuiTableRow } from '@kbn/ui-framework/components';

View file

@ -7,7 +7,7 @@
import React, { Fragment } from 'react';
import { ClusterStatus } from '../cluster_status';
import { ShardActivity } from '../shard_activity';
import { MonitoringTimeseriesContainer } from 'plugins/monitoring/components';
import { MonitoringTimeseriesContainer } from '../../chart';
export function ElasticsearchOverview({
clusterStatus,

View file

@ -4,13 +4,13 @@
* you may not use this file except in compliance with the Elastic License.
*/
export { MonitoringTimeseriesContainer } from './chart';
export { MonitoringTable } from './table';
export { Tooltip } from './tooltip';
/*
* This file should only export page-level components for view controllers to
* mount React to the DOM
*/
export { NoData } from './no_data';
export { License } from './license';
export { StatusIcon } from './status_icon';
export { SummaryStatus } from './summary_status'; // TODO this line can be removed, component is only used by other components
export { PageLoading } from './page_loading';
export {
ElasticsearchOverview,

View file

@ -0,0 +1,143 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Summary Status Component should allow label to be optional 1`] = `
<div
class="monitoring-summary-status"
role="status"
>
<div
class="monitoring-summary-status__content"
>
<div
class="euiFlexGroup euiFlexGroup--gutterExtraSmall euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow euiFlexGroup--responsive"
>
<div
class="euiFlexItem euiFlexItem--flexGrowZero monitoring-summary-status__eui-content"
data-test-subj="transportAddress"
>
<strong>
127.0.0.1:9300
</strong>
</div>
<div
class="euiFlexItem euiFlexItem--flexGrowZero monitoring-summary-status__eui-content"
data-test-subj="documentCount"
>
Documents:
<strong>
24.8k
</strong>
</div>
<div
class="euiFlexItem monitoring-summary-status__eui-content"
>
<div
class="monitoring-summary-status__status-indicator"
>
Status:
<span
class="kuiStatusText"
>
<img
alt="Status: yellow"
data-test-subj="statusIcon"
src="../plugins/monitoring/icons/health-yellow.svg"
/>
</span>
Yellow
</div>
</div>
</div>
</div>
</div>
`;
exports[`Summary Status Component should allow status to be optional 1`] = `
<div
class="monitoring-summary-status"
role="status"
>
<div
class="monitoring-summary-status__content"
>
<div
class="euiFlexGroup euiFlexGroup--gutterExtraSmall euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow euiFlexGroup--responsive"
>
<div
class="euiFlexItem euiFlexItem--flexGrowZero monitoring-summary-status__eui-content"
data-test-subj="freeDiskSpace"
>
Free Disk Space:
<strong>
173.9 GB
</strong>
</div>
<div
class="euiFlexItem euiFlexItem--flexGrowZero monitoring-summary-status__eui-content"
data-test-subj="documentCount"
>
Documents:
<strong>
24.8k
</strong>
</div>
<div
class="euiFlexItem monitoring-summary-status__eui-content"
/>
</div>
</div>
</div>
`;
exports[`Summary Status Component should render metrics in a summary bar 1`] = `
<div
class="monitoring-summary-status"
role="status"
>
<div
class="monitoring-summary-status__content"
>
<div
class="euiFlexGroup euiFlexGroup--gutterExtraSmall euiFlexGroup--alignItemsCenter euiFlexGroup--directionRow euiFlexGroup--responsive"
>
<div
class="euiFlexItem euiFlexItem--flexGrowZero monitoring-summary-status__eui-content"
data-test-subj="freeDiskSpace"
>
Free Disk Space:
<strong>
173.9 GB
</strong>
</div>
<div
class="euiFlexItem euiFlexItem--flexGrowZero monitoring-summary-status__eui-content"
data-test-subj="documentCount"
>
Documents:
<strong>
24.8k
</strong>
</div>
<div
class="euiFlexItem monitoring-summary-status__eui-content"
>
<div
class="monitoring-summary-status__status-indicator"
>
Status:
<span
class="kuiStatusText"
>
<img
alt="Status: green"
data-test-subj="statusIcon"
src="../plugins/monitoring/icons/health-green.svg"
/>
</span>
Green
</div>
</div>
</div>
</div>
</div>
`;

View file

@ -4,64 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import { isEmpty, capitalize } from 'lodash';
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { StatusIcon } from '../';
const wrapChild = ({ label, value, dataTestSubj }, index) => (
<EuiFlexItem
key={`summary-status-item-${index}`}
grow={false}
className="monitoring-summary-status__eui-content"
data-test-subj={dataTestSubj}
>
{label ? label + ': ' : null}
<strong>{value}</strong>
</EuiFlexItem>
);
const DefaultIconComponent = ({ status }) => (
<Fragment>
Status: {(
<StatusIcon type={status.toUpperCase()} label={`Status: ${status}`} />
)}
</Fragment>
);
const StatusIndicator = ({ status, isOnline, IconComponent }) => {
if (isEmpty(status)) {
return null;
}
return (
<div className="monitoring-summary-status__status-indicator">
<IconComponent status={status} isOnline={isOnline} />{' '}
{capitalize(status)}
</div>
);
};
export function SummaryStatus({ metrics, status, isOnline, IconComponent = DefaultIconComponent, ...props }) {
return (
<div className="monitoring-summary-status" role="status">
<div className="monitoring-summary-status__content" {...props}>
<EuiFlexGroup gutterSize="xs" alignItems="center">
{metrics.map(wrapChild)}
<EuiFlexItem
grow={true}
className="monitoring-summary-status__eui-content"
>
<StatusIndicator status={status} IconComponent={IconComponent} isOnline={isOnline} />
</EuiFlexItem>
</EuiFlexGroup>
</div>
</div>
);
}
SummaryStatus.propTypes = {
metrics: PropTypes.array.isRequired
};
export { SummaryStatus } from './summary_status';

View file

@ -0,0 +1,67 @@
/*
* 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, { Fragment } from 'react';
import PropTypes from 'prop-types';
import { isEmpty, capitalize } from 'lodash';
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { StatusIcon } from '../status_icon';
const wrapChild = ({ label, value, dataTestSubj }, index) => (
<EuiFlexItem
key={`summary-status-item-${index}`}
grow={false}
className="monitoring-summary-status__eui-content"
data-test-subj={dataTestSubj}
>
{label ? label + ': ' : null}
<strong>{value}</strong>
</EuiFlexItem>
);
const DefaultIconComponent = ({ status }) => (
<Fragment>
Status: {(
<StatusIcon type={status.toUpperCase()} label={`Status: ${status}`} />
)}
</Fragment>
);
const StatusIndicator = ({ status, isOnline, IconComponent }) => {
if (isEmpty(status)) {
return null;
}
return (
<div className="monitoring-summary-status__status-indicator">
<IconComponent status={status} isOnline={isOnline} />{' '}
{capitalize(status)}
</div>
);
};
export function SummaryStatus({ metrics, status, isOnline, IconComponent = DefaultIconComponent, ...props }) {
return (
<div className="monitoring-summary-status" role="status">
<div className="monitoring-summary-status__content" {...props}>
<EuiFlexGroup gutterSize="xs" alignItems="center">
{metrics.map(wrapChild)}
<EuiFlexItem
grow={true}
className="monitoring-summary-status__eui-content"
>
<StatusIndicator status={status} IconComponent={IconComponent} isOnline={isOnline} />
</EuiFlexItem>
</EuiFlexGroup>
</div>
</div>
);
}
SummaryStatus.propTypes = {
metrics: PropTypes.array.isRequired
};

View file

@ -0,0 +1,69 @@
/*
* 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 { render } from 'enzyme';
import { SummaryStatus } from './summary_status';
describe('Summary Status Component', () => {
it('should render metrics in a summary bar', () => {
const props = {
metrics: [
{
label: 'Free Disk Space',
value: '173.9 GB',
dataTestSubj: 'freeDiskSpace'
},
{
label: 'Documents',
value: '24.8k',
dataTestSubj: 'documentCount'
},
],
status: 'green'
};
expect(render(<SummaryStatus {...props} />)).toMatchSnapshot();
});
it('should allow label to be optional', () => {
const props = {
metrics: [
{
value: '127.0.0.1:9300',
dataTestSubj: 'transportAddress'
},
{
label: 'Documents',
value: '24.8k',
dataTestSubj: 'documentCount'
},
],
status: 'yellow'
};
expect(render(<SummaryStatus {...props} />)).toMatchSnapshot();
});
it('should allow status to be optional', () => {
const props = {
metrics: [
{
label: 'Free Disk Space',
value: '173.9 GB',
dataTestSubj: 'freeDiskSpace'
},
{
label: 'Documents',
value: '24.8k',
dataTestSubj: 'documentCount'
},
]
};
expect(render(<SummaryStatus {...props} />)).toMatchSnapshot();
});
});

View file

@ -8,7 +8,6 @@ import './main';
import './chart';
import './sparkline';
import './alerts';
import './status_icon';
import './cluster/overview';
import './cluster/listing';
import './elasticsearch/cluster_status';

View file

@ -1,57 +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 React from 'react';
import ReactDOM from 'react-dom';
import { uiModules } from 'ui/modules';
import { ElasticsearchStatusIcon } from 'plugins/monitoring/components/elasticsearch/status_icon';
import { NodeStatusIcon } from 'plugins/monitoring/components/elasticsearch/node/status_icon';
import { KibanaStatusIcon } from 'plugins/monitoring/components/kibana/status_icon';
const uiModule = uiModules.get('monitoring/directives', []);
function linkStatusIconComponent(scope, $el, StatusIconComponent) {
// The watch callback always runs the first time connecting the data to the directive
// The first time callback runs, unmountComponentAtNode does nothing
scope.$watch('status', (status) => {
ReactDOM.unmountComponentAtNode($el[0]);
ReactDOM.render((
<div title={scope.title}>
<StatusIconComponent status={status} />
</div>
), $el[0]);
});
}
uiModule.directive('monitoringKibanaStatusIcon', function () {
return {
restrict: 'E',
scope: { status: '=' },
link(scope, $el) {
linkStatusIconComponent(scope, $el, KibanaStatusIcon);
}
};
});
uiModule.directive('monitoringElasticsearchStatusIcon', function () {
return {
restrict: 'E',
scope: { status: '=' },
link(scope, $el) {
linkStatusIconComponent(scope, $el, ElasticsearchStatusIcon);
}
};
});
uiModule.directive('monitoringElasticsearchNodeStatusIcon', function () {
return {
restrict: 'E',
scope: { status: '=' },
link(scope, $el) {
linkStatusIconComponent(scope, $el, NodeStatusIcon);
}
};
});