From 63560881c6b4121e6cff16bc14099def90979436 Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Mon, 22 Jul 2019 10:12:09 -0400 Subject: [PATCH] [Monitoring] Metricbeat migration net new user experience (#39832) * ES net new user experience * Adding sorting support * WIP * Progress on the ES nodes listing page * Fix the loading page * Kibana net new user experience * Remove unnecessary files * Remove this one too * Add this file back in * Add a way to add the cluster uuid to global state once monitoring is enabled on a stack product * Ensure this PR can be merged to master by hiding the functionality behind direct links * Add messaging for net new user experience on Kibana instances page * Ensure we poll for more data as soon as they are done in the flyout * PR feedback * Fix api tests * Add `skipLiveData` flag to avoid fetching data from the running stack products * Add comment --- .../cluster/overview/elasticsearch_panel.js | 62 ++++++-- .../components/cluster/overview/helpers.js | 4 +- .../components/cluster/overview/index.js | 7 +- .../cluster/overview/kibana_panel.js | 84 ++++++++--- .../components/elasticsearch/nodes/nodes.js | 133 ++++++++++++++---- .../components/kibana/instances/instances.js | 106 +++++++++++--- .../metricbeat_migration/flyout/flyout.js | 56 ++++++-- .../common_elasticsearch_instructions.js | 4 + .../enable_metricbeat_instructions.js | 6 +- .../kibana/common_kibana_instructions.js | 4 + .../kibana/enable_metricbeat_instructions.js | 6 +- .../public/components/renderers/setup_mode.js | 16 ++- .../public/components/table/eui_table.js | 68 ++++++++- .../public/directives/main/index.html | 117 +++++++-------- .../public/directives/main/index.js | 14 ++ .../public/lib/get_cluster_from_clusters.js | 28 ++++ .../monitoring/public/lib/route_init.js | 38 ++--- .../monitoring/public/lib/setup_mode.js | 33 +++-- .../plugins/monitoring/public/views/all.js | 1 + .../public/views/cluster/overview/index.js | 21 ++- .../public/views/elasticsearch/nodes/index.js | 34 ++++- .../public/views/loading/index.html | 5 + .../monitoring/public/views/loading/index.js | 68 +++++++++ .../nodes/get_nodes/get_live_nodes.js | 20 +++ .../setup/collection/get_collection_status.js | 88 ++++++++++-- .../api/v1/setup/cluster_setup_status.js | 13 +- .../api/v1/setup/clusters_setup_status.js | 13 +- .../monitoring/server/routes/api/v1/ui.js | 2 +- .../monitoring/setup/collection/detect_apm.js | 4 +- .../setup/collection/detect_beats.js | 4 +- .../collection/detect_beats_management.js | 5 +- .../setup/collection/detect_logstash.js | 5 +- .../collection/detect_logstash_management.js | 5 +- .../collection/es_and_kibana_exclusive_mb.js | 4 +- .../setup/collection/es_and_kibana_mb.js | 4 +- .../setup/collection/fixtures/detect_apm.json | 7 +- .../collection/fixtures/detect_beats.json | 19 +-- .../fixtures/detect_beats_management.json | 7 +- .../collection/fixtures/detect_logstash.json | 7 +- .../fixtures/detect_logstash_management.json | 7 +- .../fixtures/es_and_kibana_exclusive_mb.json | 35 +++-- .../collection/fixtures/es_and_kibana_mb.json | 33 +++-- .../fixtures/kibana_exclusive_mb.json | 35 +++-- .../setup/collection/fixtures/kibana_mb.json | 33 +++-- .../setup/collection/kibana_exclusive_mb.js | 2 +- .../monitoring/setup/collection/kibana_mb.js | 2 +- 46 files changed, 956 insertions(+), 313 deletions(-) create mode 100644 x-pack/legacy/plugins/monitoring/public/lib/get_cluster_from_clusters.js create mode 100644 x-pack/legacy/plugins/monitoring/public/views/loading/index.html create mode 100644 x-pack/legacy/plugins/monitoring/public/views/loading/index.js create mode 100644 x-pack/legacy/plugins/monitoring/server/lib/elasticsearch/nodes/get_nodes/get_live_nodes.js diff --git a/x-pack/legacy/plugins/monitoring/public/components/cluster/overview/elasticsearch_panel.js b/x-pack/legacy/plugins/monitoring/public/components/cluster/overview/elasticsearch_panel.js index 7294331b66748..c891bc5373db3 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/cluster/overview/elasticsearch_panel.js +++ b/x-pack/legacy/plugins/monitoring/public/components/cluster/overview/elasticsearch_panel.js @@ -139,6 +139,7 @@ export function ElasticsearchPanel(props) { const clusterStats = props.cluster_stats || {}; const nodes = clusterStats.nodes; const indices = clusterStats.indices; + const setupMode = props.setupMode; const goToElasticsearch = () => props.changeUrl('elasticsearch'); const goToNodes = () => props.changeUrl('elasticsearch/nodes'); @@ -175,6 +176,34 @@ export function ElasticsearchPanel(props) { const licenseText = ; + let setupModeNodesData = null; + if (setupMode.enabled && setupMode.data) { + const elasticsearchData = get(setupMode.data, 'elasticsearch.byUuid'); + const migratedNodesCount = Object.values(elasticsearchData).filter(node => node.isFullyMigrated).length; + const totalNodesCount = Object.values(elasticsearchData).length; + + const badgeColor = migratedNodesCount === totalNodesCount + ? 'secondary' + : 'danger'; + + setupModeNodesData = ( + + + + {formatNumber(migratedNodesCount, 'int_commas')}/{formatNumber(totalNodesCount, 'int_commas')} + + + + ); + } + return ( - -

- - - -

-
+ + + +

+ + + +

+
+
+ {setupModeNodesData} +
diff --git a/x-pack/legacy/plugins/monitoring/public/components/cluster/overview/helpers.js b/x-pack/legacy/plugins/monitoring/public/components/cluster/overview/helpers.js index b4446177f0bb8..af495b97270a2 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/cluster/overview/helpers.js +++ b/x-pack/legacy/plugins/monitoring/public/components/cluster/overview/helpers.js @@ -26,14 +26,14 @@ export function HealthStatusIndicator(props) { red: 'danger' }; - const statusColor = statusColorMap[props.status]; + const statusColor = statusColorMap[props.status] || 'n/a'; return ( ); diff --git a/x-pack/legacy/plugins/monitoring/public/components/cluster/overview/index.js b/x-pack/legacy/plugins/monitoring/public/components/cluster/overview/index.js index 4cebf627ba835..56814b6fae128 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/cluster/overview/index.js +++ b/x-pack/legacy/plugins/monitoring/public/components/cluster/overview/index.js @@ -32,9 +32,14 @@ export function Overview(props) { ml={props.cluster.ml} changeUrl={props.changeUrl} license={props.cluster.license} + setupMode={props.setupMode} showLicenseExpiration={props.showLicenseExpiration} /> - + ) : null diff --git a/x-pack/legacy/plugins/monitoring/public/components/cluster/overview/kibana_panel.js b/x-pack/legacy/plugins/monitoring/public/components/cluster/overview/kibana_panel.js index ccbc62968b134..a6f75446d94f5 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/cluster/overview/kibana_panel.js +++ b/x-pack/legacy/plugins/monitoring/public/components/cluster/overview/kibana_panel.js @@ -7,9 +7,10 @@ import React from 'react'; import { formatNumber } from 'plugins/monitoring/lib/format_number'; import { ClusterItemContainer, HealthStatusIndicator, BytesPercentageUsage } from './helpers'; - +import { get } from 'lodash'; import { EuiFlexGrid, + EuiFlexGroup, EuiFlexItem, EuiLink, EuiTitle, @@ -18,12 +19,16 @@ import { EuiDescriptionListTitle, EuiDescriptionListDescription, EuiHorizontalRule, + EuiBadge, + EuiToolTip } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; export function KibanaPanel(props) { - if (!props.count) { + const setupMode = props.setupMode; + const showDetectedKibanas = setupMode.enabled && get(setupMode.data, 'kibana.detected.doesExist', false); + if (!props.count && !showDetectedKibanas) { return null; } @@ -34,6 +39,34 @@ export function KibanaPanel(props) { const goToKibana = () => props.changeUrl('kibana'); const goToInstances = () => props.changeUrl('kibana/instances'); + let setupModeInstancesData = null; + if (setupMode.enabled && setupMode.data) { + const kibanaData = get(setupMode.data, 'kibana.byUuid'); + const migratedNodesCount = Object.values(kibanaData).filter(node => node.isFullyMigrated).length; + const totalNodesCount = Object.values(kibanaData).length; + + const badgeColor = migratedNodesCount === totalNodesCount + ? 'secondary' + : 'danger'; + + setupModeInstancesData = ( + + + + {formatNumber(migratedNodesCount, 'int_commas')}/{formatNumber(totalNodesCount, 'int_commas')} + + + + ); + } + return ( - -

- - { props.count }) }} - /> - -

-
+ + + +

+ + { props.count }) }} + /> + +

+
+
+ {setupModeInstancesData} +
diff --git a/x-pack/legacy/plugins/monitoring/public/components/elasticsearch/nodes/nodes.js b/x-pack/legacy/plugins/monitoring/public/components/elasticsearch/nodes/nodes.js index a5db041d9be37..f976438f2f35d 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/elasticsearch/nodes/nodes.js +++ b/x-pack/legacy/plugins/monitoring/public/components/elasticsearch/nodes/nodes.js @@ -26,7 +26,7 @@ import { i18n } from '@kbn/i18n'; import _ from 'lodash'; const getSortHandler = (type) => (item) => _.get(item, [type, 'summary', 'lastVal']); -const getColumns = showCgroupMetricsElasticsearch => { +const getColumns = (showCgroupMetricsElasticsearch, setupMode) => { const cols = []; const cpuUsageColumnTitle = i18n.translate('xpack.monitoring.elasticsearch.nodes.cpuUsageColumnTitle', { @@ -40,32 +40,46 @@ const getColumns = showCgroupMetricsElasticsearch => { width: '20%', field: 'name', sortable: true, - render: (value, node) => ( -
-
- - - - -   - - { + let nameLink = ( + + {value} + + ); + + if (setupMode && setupMode.enabled) { + const list = _.get(setupMode, 'data.byUuid', {}); + const status = list[node.resolver] || {}; + if (status.isNetNewUser) { + nameLink = value; + } + } + + return ( +
+
+ + - {value} - - - -
-
- {extractIp(node.transport_address)} + + +   + + {nameLink} + + +
+
+ {extractIp(node.transport_address)} +
-
- ) + ); + } }); cols.push({ @@ -207,13 +221,36 @@ const getColumns = showCgroupMetricsElasticsearch => { return cols; }; -export function ElasticsearchNodes({ clusterStatus, nodes, showCgroupMetricsElasticsearch, ...props }) { - const columns = getColumns(showCgroupMetricsElasticsearch); +export function ElasticsearchNodes({ clusterStatus, showCgroupMetricsElasticsearch, ...props }) { const { sorting, pagination, onTableChange, setupMode } = props; + const columns = getColumns(showCgroupMetricsElasticsearch, setupMode); + // Merge the nodes data with the setup data if enabled + const nodes = props.nodes || []; + if (setupMode.enabled && setupMode.data) { + // We want to create a seamless experience for the user by merging in the setup data + // and the node data from monitoring indices in the likely scenario where some nodes + // are using MB collection and some are using no collection + const nodesByUuid = nodes.reduce((byUuid, node) => ({ + ...byUuid, + [node.id || node.resolver]: node + }), {}); + + nodes.push(...Object.entries(setupMode.data.byUuid) + .reduce((nodes, [nodeUuid, instance]) => { + if (!nodesByUuid[nodeUuid]) { + nodes.push(instance.node); + } + return nodes; + }, [])); + } + + let netNewUserMessage = null; let disableInternalCollectionForMigrationMessage = null; if (setupMode.data) { - if (setupMode.data.totalUniquePartiallyMigratedCount === setupMode.data.totalUniqueInstanceCount) { + // Think net new user scenario + const hasInstances = setupMode.data.totalUniqueInstanceCount > 0; + if (hasInstances && setupMode.data.totalUniquePartiallyMigratedCount === setupMode.data.totalUniqueInstanceCount) { disableInternalCollectionForMigrationMessage = ( ); } + else if (!hasInstances) { + netNewUserMessage = ( + + +

+ {i18n.translate('xpack.monitoring.elasticsearch.nodes.metribeatMigration.netNewUserDescription', { + defaultMessage: `We did not detect any monitoring data, but we did detect the following Elasticsearch nodes. + Each detected node is listed below along with a Setup button. Clicking this button will guide you through + the process of enabling monitoring for each node.` + })} +

+
+ +
+ ); + } } - return ( - - + function renderClusterStatus() { + if (!clusterStatus) { + return null; + } + return ( + + + ); + } + + return ( + + + {renderClusterStatus()} {disableInternalCollectionForMigrationMessage} + {netNewUserMessage} { +const getColumns = (kbnUrl, scope, setupMode) => { const columns = [ { name: i18n.translate('xpack.monitoring.kibana.listing.nameColumnTitle', { defaultMessage: 'Name' }), field: 'name', - render: (name, kibana) => ( - { - scope.$evalAsync(() => { - kbnUrl.changePath(`/kibana/instances/${kibana.kibana.uuid}`); - }); - }} - data-test-subj={`kibanaLink-${name}`} - > - { name } - - ) + render: (name, kibana) => { + if (setupMode && setupMode.enabled) { + const list = get(setupMode, 'data.byUuid', {}); + const status = list[get(kibana, 'kibana.uuid')] || {}; + if (status.isNetNewUser) { + return name; + } + } + + return ( + { + scope.$evalAsync(() => { + kbnUrl.changePath(`/kibana/instances/${kibana.kibana.uuid}`); + }); + }} + data-test-subj={`kibanaLink-${name}`} + > + { name } + + ); + } }, { name: i18n.translate('xpack.monitoring.kibana.listing.statusColumnTitle', { @@ -125,7 +144,6 @@ const getColumns = (kbnUrl, scope) => { export class KibanaInstances extends PureComponent { render() { const { - instances, clusterStatus, angular, setupMode, @@ -134,12 +152,63 @@ export class KibanaInstances extends PureComponent { onTableChange } = this.props; + let netNewUserMessage = null; + // Merge the instances data with the setup data if enabled + const instances = this.props.instances || []; + if (setupMode.enabled && setupMode.data) { + // We want to create a seamless experience for the user by merging in the setup data + // and the node data from monitoring indices in the likely scenario where some instances + // are using MB collection and some are using no collection + const instancesByUuid = instances.reduce((byUuid, instance) => ({ + ...byUuid, + [get(instance, 'kibana.uuid')]: instance + }), {}); + + instances.push(...Object.entries(setupMode.data.byUuid) + .reduce((instances, [nodeUuid, instance]) => { + if (!instancesByUuid[nodeUuid]) { + instances.push({ + kibana: { + ...instance.instance.kibana, + status: StatusIcon.TYPES.GRAY + } + }); + } + return instances; + }, [])); + + const hasInstances = setupMode.data.totalUniqueInstanceCount > 0; + if (!hasInstances) { + netNewUserMessage = ( + + +

+ {i18n.translate('xpack.monitoring.kibana.nodes.metribeatMigration.netNewUserDescription', { + defaultMessage: `We did not detect any monitoring data, but we did detect the following Kibana instance. + This detected instance is listed below along with a Setup button. Clicking this button will guide you through + the process of enabling monitoring for this instance.` + })} +

+
+ +
+ ); + } + } + const dataFlattened = instances.map(item => ({ ...item, name: item.kibana.name, status: item.kibana.status, })); + return ( @@ -147,11 +216,12 @@ export class KibanaInstances extends PureComponent { + {netNewUserMessage} this.finishedFlyout()} > {i18n.translate('xpack.monitoring.metricbeatMigration.flyout.doneButtonLabel', { defaultMessage: 'Done' @@ -259,7 +277,7 @@ export class Flyout extends Component { } render() { - const { onClose, instance, productName } = this.props; + const { onClose, instance, productName, product } = this.props; let instanceType = null; let instanceName = instance ? instance.name : null; @@ -282,6 +300,24 @@ export class Flyout extends Component { } } + let title = i18n.translate('xpack.monitoring.metricbeatMigration.flyout.flyoutTitle', { + defaultMessage: 'Migrate {instanceName} {instanceType} to Metricbeat', + values: { + instanceName, + instanceType + } + }); + + if (product.isNetNewUser) { + title = i18n.translate('xpack.monitoring.metricbeatMigration.flyout.flyoutTitleNewUser', { + defaultMessage: 'Monitor {instanceName} {instanceType} with Metricbeat', + values: { + instanceName, + instanceType + } + }); + } + return (

- {i18n.translate('xpack.monitoring.metricbeatMigration.flyout.flyoutTitle', { - defaultMessage: 'Migrate {instanceName} {instanceType} to Metricbeat', - values: { - instanceName, - instanceType - } - })} + {title}

{this.getDocumentationTitle()} diff --git a/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/elasticsearch/common_elasticsearch_instructions.js b/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/elasticsearch/common_elasticsearch_instructions.js index 215de10c68b84..3c55fef3ab7f3 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/elasticsearch/common_elasticsearch_instructions.js +++ b/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/elasticsearch/common_elasticsearch_instructions.js @@ -8,3 +8,7 @@ import { i18n } from '@kbn/i18n'; export const statusTitle = i18n.translate('xpack.monitoring.metricbeatMigration.elasticsearchInstructions.statusTitle', { defaultMessage: `Migration status` }); + +export const statusTitleNewUser = i18n.translate('xpack.monitoring.metricbeatMigration.elasticsearchInstructions.statusTitleNewUser', { + defaultMessage: `Monitoring status` +}); diff --git a/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/elasticsearch/enable_metricbeat_instructions.js b/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/elasticsearch/enable_metricbeat_instructions.js index a8e2b81ec724d..80c9878c9182f 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/elasticsearch/enable_metricbeat_instructions.js +++ b/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/elasticsearch/enable_metricbeat_instructions.js @@ -17,7 +17,7 @@ import { } from '@elastic/eui'; import { Monospace } from '../components/monospace'; import { FormattedMessage } from '@kbn/i18n/react'; -import { statusTitle } from './common_elasticsearch_instructions'; +import { statusTitle, statusTitleNewUser } from './common_elasticsearch_instructions'; import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links'; export function getElasticsearchInstructionsForEnablingMetricbeat(product, _meta, { @@ -177,7 +177,7 @@ export function getElasticsearchInstructionsForEnablingMetricbeat(product, _meta }; let migrationStatusStep = null; - if (product.isInternalCollector) { + if (product.isInternalCollector || product.isNetNewUser) { let status = null; if (hasCheckedStatus) { status = ( @@ -210,7 +210,7 @@ export function getElasticsearchInstructionsForEnablingMetricbeat(product, _meta } migrationStatusStep = { - title: statusTitle, + title: product.isNetNewUser ? statusTitleNewUser : statusTitle, status: 'incomplete', children: ( diff --git a/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/kibana/common_kibana_instructions.js b/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/kibana/common_kibana_instructions.js index c4cf1c0e91028..25b869e32b9b7 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/kibana/common_kibana_instructions.js +++ b/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/kibana/common_kibana_instructions.js @@ -8,3 +8,7 @@ import { i18n } from '@kbn/i18n'; export const statusTitle = i18n.translate('xpack.monitoring.metricbeatMigration.kibanaInstructions.statusTitle', { defaultMessage: `Migration status` }); + +export const statusTitleNewUser = i18n.translate('xpack.monitoring.metricbeatMigration.kibanaInstructions.statusTitleNewUser', { + defaultMessage: `Monitoring status` +}); diff --git a/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/kibana/enable_metricbeat_instructions.js b/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/kibana/enable_metricbeat_instructions.js index f8fa01087d123..7871f45ad8a30 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/kibana/enable_metricbeat_instructions.js +++ b/x-pack/legacy/plugins/monitoring/public/components/metricbeat_migration/instruction_steps/kibana/enable_metricbeat_instructions.js @@ -17,7 +17,7 @@ import { } from '@elastic/eui'; import { Monospace } from '../components/monospace'; import { FormattedMessage } from '@kbn/i18n/react'; -import { statusTitle } from './common_kibana_instructions'; +import { statusTitle, statusTitleNewUser } from './common_kibana_instructions'; import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links'; export function getKibanaInstructionsForEnablingMetricbeat(product, _meta, { @@ -173,7 +173,7 @@ export function getKibanaInstructionsForEnablingMetricbeat(product, _meta, { }; let migrationStatusStep = null; - if (product.isInternalCollector) { + if (product.isInternalCollector || product.isNetNewUser) { let status = null; if (hasCheckedStatus) { status = ( @@ -206,7 +206,7 @@ export function getKibanaInstructionsForEnablingMetricbeat(product, _meta, { } migrationStatusStep = { - title: statusTitle, + title: product.isNetNewUser ? statusTitleNewUser : statusTitle, status: 'incomplete', children: ( diff --git a/x-pack/legacy/plugins/monitoring/public/components/renderers/setup_mode.js b/x-pack/legacy/plugins/monitoring/public/components/renderers/setup_mode.js index 17f877267549d..097b5e2428cfe 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/renderers/setup_mode.js +++ b/x-pack/legacy/plugins/monitoring/public/components/renderers/setup_mode.js @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ import React from 'react'; -import { setAngularState, getSetupModeState, initSetupModeState, updateSetupModeData } from '../../lib/setup_mode'; +import { getSetupModeState, initSetupModeState, updateSetupModeData } from '../../lib/setup_mode'; import { Flyout } from '../metricbeat_migration/flyout'; import { ELASTICSEARCH_CUSTOM_ID } from '../../../common/constants'; @@ -17,8 +17,7 @@ export class SetupModeRenderer extends React.Component { componentWillMount() { const { scope, injector } = this.props; - setAngularState(scope, injector); - initSetupModeState(() => this.setState({ renderState: true })); + initSetupModeState(scope, injector, () => this.setState({ renderState: true })); } getFlyout(data, meta) { @@ -50,7 +49,16 @@ export class SetupModeRenderer extends React.Component { render() { const { render, productName } = this.props; const setupModeState = getSetupModeState(); - const data = setupModeState.data ? setupModeState.data[productName] : null; + + let data = null; + if (setupModeState.data) { + if (productName) { + data = setupModeState.data[productName]; + } + else { + data = setupModeState.data; + } + } const meta = setupModeState.data ? setupModeState.data._meta : null; return render({ diff --git a/x-pack/legacy/plugins/monitoring/public/components/table/eui_table.js b/x-pack/legacy/plugins/monitoring/public/components/table/eui_table.js index 89fa530547ad0..09e60bdd6b8c2 100644 --- a/x-pack/legacy/plugins/monitoring/public/components/table/eui_table.js +++ b/x-pack/legacy/plugins/monitoring/public/components/table/eui_table.js @@ -51,10 +51,31 @@ export class EuiMonitoringTable extends React.PureComponent { name: i18n.translate('xpack.monitoring.euiTable.setupStatusTitle', { defaultMessage: 'Setup Status' }), - field: uuidField, - render: (uuid) => { + sortable: product => { const list = get(setupMode, 'data.byUuid', {}); - const status = list[uuid] || {}; + const status = list[get(product, uuidField)] || {}; + + if (status.isInternalCollector) { + return 4; + } + + if (status.isPartiallyMigrated) { + return 3; + } + + if (status.isFullyMigrated) { + return 2; + } + + if (status.isNetNewUser) { + return 1; + } + + return 0; + }, + render: (product) => { + const list = get(setupMode, 'data.byUuid', {}); + const status = list[get(product, uuidField)] || {}; let statusBadge = null; if (status.isInternalCollector) { @@ -84,6 +105,15 @@ export class EuiMonitoringTable extends React.PureComponent { ); } + else if (status.isNetNewUser) { + statusBadge = ( + + {i18n.translate('xpack.monitoring.euiTable.isNetNewUserLabel', { + defaultMessage: 'No monitoring detected' + })} + + ); + } else { statusBadge = i18n.translate('xpack.monitoring.euiTable.migrationStatusUnknown', { defaultMessage: 'N/A' @@ -98,8 +128,26 @@ export class EuiMonitoringTable extends React.PureComponent { name: i18n.translate('xpack.monitoring.euiTable.setupActionTitle', { defaultMessage: 'Setup Action' }), - field: uuidField, - render: (uuid, product) => { + sortable: product => { + const list = get(setupMode, 'data.byUuid', {}); + const status = list[get(product, uuidField)] || {}; + + if (status.isInternalCollector || status.isNetNewUser) { + return 1; + } + + if (status.isPartiallyMigrated) { + if (setupMode.productName === ELASTICSEARCH_CUSTOM_ID) { + // See comment for same conditional in render function + return 0; + } + return 1; + } + + return 0; + }, + render: (product) => { + const uuid = get(product, uuidField); const list = get(setupMode, 'data.byUuid', {}); const status = list[uuid] || {}; const instance = { @@ -124,6 +172,16 @@ export class EuiMonitoringTable extends React.PureComponent { ); } + if (status.isNetNewUser) { + return ( + setupMode.openFlyout(instance)}> + {i18n.translate('xpack.monitoring.euiTable.setupButtonLabel', { + defaultMessage: 'Setup' + })} + + ); + } + return null; } }); diff --git a/x-pack/legacy/plugins/monitoring/public/directives/main/index.html b/x-pack/legacy/plugins/monitoring/public/directives/main/index.html index 8936162a19a10..823b3f763521c 100644 --- a/x-pack/legacy/plugins/monitoring/public/directives/main/index.html +++ b/x-pack/legacy/plugins/monitoring/public/directives/main/index.html @@ -4,52 +4,59 @@
-