mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[ML] Prevent overflow of large metric values in data visualizer/file data visualizer cards (#36932) (#37268)
* filedataviz cards - abbrev long numeric values * add directive for index dataviz values * Add arg to indicate format. update tests * truncate with ellipsis * use eui ellipsis truncation * increase card content height * ensure truncation for firefox and safari
This commit is contained in:
parent
7da631e095
commit
256b4c21c3
9 changed files with 99 additions and 12 deletions
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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 {
|
||||
EuiToolTip
|
||||
} from '@elastic/eui';
|
||||
|
||||
|
||||
const MAX_CHARS = 12;
|
||||
|
||||
export function DisplayValue({ value }) {
|
||||
const length = String(value).length;
|
||||
let formattedValue;
|
||||
|
||||
if (length <= MAX_CHARS) {
|
||||
formattedValue = value;
|
||||
} else {
|
||||
formattedValue = (
|
||||
<EuiToolTip content={value} anchorClassName="valueWrapper">
|
||||
<span>
|
||||
{value}
|
||||
</span>
|
||||
</EuiToolTip>
|
||||
);
|
||||
}
|
||||
|
||||
return formattedValue;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { DisplayValue } from './display_value';
|
|
@ -45,7 +45,7 @@
|
|||
@include euiPanel($selector: 'card-contents');
|
||||
|
||||
.card-contents {
|
||||
height: 393px;
|
||||
height: 400px;
|
||||
border-radius: 0px 0px $euiBorderRadius $euiBorderRadius;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
@ -68,6 +68,15 @@
|
|||
display: inline-block;
|
||||
}
|
||||
|
||||
.stat.min.value, .stat.max.value, .stat.median.value {
|
||||
font-size: $euiFontSizeS;
|
||||
@include euiTextTruncate;
|
||||
}
|
||||
|
||||
.valueWrapper {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.not-exist-message {
|
||||
padding: 50px 30px 0px 30px;
|
||||
text-align: center;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div ng-if="card.existsInDocs === true" class="card-contents">
|
||||
<div class="stats euiText">
|
||||
<div class="stats euiText--small">
|
||||
<div class="stat"><i class="fa fa-files-o" aria-hidden="true"></i>
|
||||
<span
|
||||
i18n-id="xpack.ml.fieldDataCard.cardNumber.cardStatsCountDocumentsPercentsLabel"
|
||||
|
@ -37,9 +37,18 @@
|
|||
></div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="stat min">{{ card.stats.min | formatField:card.fieldFormat }}</div>
|
||||
<div class="stat median">{{ card.stats.median | formatField:card.fieldFormat }}</div>
|
||||
<div class="stat max">{{ card.stats.max | formatField:card.fieldFormat }}</div>
|
||||
<div class="stat min value">
|
||||
<ml-display-value value="card.stats.min | formatField:card.fieldFormat">
|
||||
</ml-display-value>
|
||||
</div>
|
||||
<div class="stat median value">
|
||||
<ml-display-value value="card.stats.median | formatField:card.fieldFormat">
|
||||
</ml-display-value>
|
||||
</div>
|
||||
<div class="stat max value">
|
||||
<ml-display-value value="card.stats.max | formatField:card.fieldFormat">
|
||||
</ml-display-value>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* 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 'ngreact';
|
||||
import { uiModules } from 'ui/modules';
|
||||
const module = uiModules.get('apps/ml', ['react']);
|
||||
|
||||
import { DisplayValue } from '../../components/display_value';
|
||||
|
||||
module.directive('mlDisplayValue', function (reactDirective) {
|
||||
return reactDirective(
|
||||
DisplayValue,
|
||||
undefined,
|
||||
{ restrict: 'E' }
|
||||
);
|
||||
});
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
|
||||
import './document_count_chart_directive';
|
||||
import './display_value_directive';
|
||||
import './field_data_card_directive';
|
||||
import './metric_distribution_chart_directive';
|
||||
import './top_values_directive';
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
</div>
|
||||
<div
|
||||
ng-if="card.stats.isTopValuesSampled === true"
|
||||
class="sampled-message euiText"
|
||||
class="sampled-message euiText--small"
|
||||
i18n-id="xpack.ml.fieldDataCard.calculatedFromSampleDescription"
|
||||
i18n-default-message="Calculated from sample of {topValuesSamplerShardSize} documents per shard"
|
||||
i18n-values="{
|
||||
|
|
|
@ -11,6 +11,7 @@ import {
|
|||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
|
||||
import { FieldTypeIcon } from '../../../components/field_type_icon';
|
||||
import { DisplayValue } from '../../../components/display_value';
|
||||
import { getMLJobTypeAriaLabel } from '../../../util/field_types_utils';
|
||||
|
||||
export function FieldStatsCard({ field }) {
|
||||
|
@ -93,9 +94,15 @@ export function FieldStatsCard({ field }) {
|
|||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="stat min heading">{field.min_value}</div>
|
||||
<div className="stat median heading">{field.median_value}</div>
|
||||
<div className="stat max heading">{field.max_value}</div>
|
||||
<div className="stat min value">
|
||||
<DisplayValue value={field.min_value}/>
|
||||
</div>
|
||||
<div className="stat median value">
|
||||
<DisplayValue value={field.median_value}/>
|
||||
</div>
|
||||
<div className="stat max value">
|
||||
<DisplayValue value={field.max_value}/>
|
||||
</div>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
}
|
||||
|
|
|
@ -12,9 +12,8 @@
|
|||
*/
|
||||
import numeral from '@elastic/numeral';
|
||||
|
||||
export function abbreviateWholeNumber(value, maxDigits) {
|
||||
const maxNumDigits = (maxDigits !== undefined ? maxDigits : 3);
|
||||
if (Math.abs(value) < Math.pow(10, maxNumDigits)) {
|
||||
export function abbreviateWholeNumber(value, maxDigits = 3) {
|
||||
if (Math.abs(value) < Math.pow(10, maxDigits)) {
|
||||
return value;
|
||||
} else {
|
||||
return numeral(value).format('0a');
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue