Skip to content

Commit

Permalink
[discover] add elastic-charts bar chart to discover
Browse files Browse the repository at this point in the history
  • Loading branch information
Emma Cunningham committed Jun 13, 2019
1 parent 4260d82 commit 1372ed3
Show file tree
Hide file tree
Showing 8 changed files with 238 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/legacy/core_plugins/kibana/public/discover/_index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

@import 'components/fetch_error/index';
@import 'components/field_chooser/index';
@import 'components/histogram/index';
@import 'directives/index';
@import 'doc_table/index';

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.dscHistogram__header--partial {
font-weight: $euiFontWeightRegular;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import 'ngreact';
import { uiModules } from 'ui/modules';
import { DiscoverHistogram } from './histogram';

import { wrapInI18nContext } from 'ui/i18n';

const app = uiModules.get('apps/discover', ['react']);

app.directive('discoverHistogram', reactDirective => reactDirective(wrapInI18nContext(DiscoverHistogram)));
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiSpacer } from '@elastic/eui';
import moment from 'moment';
import React, { Component } from 'react';
import PropTypes from 'prop-types';

import {
AnnotationDomainTypes,
Axis,
Chart,
HistogramBarSeries,
getAnnotationId,
getAxisId,
getSpecId,
LineAnnotation,
Position,
ScaleType,
Settings,
RectAnnotation,
TooltipValue,
} from '@elastic/charts';

export interface DiscoverHistogramProps {
chartData: any; // TODO: make this unknown?
}

export class DiscoverHistogram extends Component<DiscoverHistogramProps> {
static propTypes = {
chartData: PropTypes.object,
};

render() {
if (!this.props.chartData || !this.props.chartData.series[0]) {
return null;
}

const data = this.props.chartData.series[0].values;
const format = this.props.chartData.xAxisFormat.params.pattern;

const formatter = (val: string) => {
return moment(val).format(format);
};

const currentTime = {
dataValue: moment(),
details: '',
};

const lineAnnotationStyle = {
line: {
strokeWidth: 2,
stroke: '#c80000',
opacity: 0.3,
},
};

const domain = this.props.chartData.ordered;
const domainStart = domain.min.valueOf();
const domainEnd = domain.max.valueOf();

const rectAnnotations = [
{
coordinates: {
x0: domainStart,
},
details: 'This area may contain partial data',
},
{
coordinates: {
x1: domainEnd,
},
details: 'This area may contain partial data',
},
];

const domainMin = data[0].x > domainStart ? domainStart : data[0].x;

const xDomain = {
min: domainMin,
// max: domainMax,
};

const onBrushEnd = (min: number, max: number) => {
// console.log(min, max);
};

const xInterval = this.props.chartData.ordered.interval;
// TODO: localize
const partialDataText =
'Part of this bucket may contain partial data. The selected time range does not fully cover it.';

const tooltipHeaderFormater = (headerData: TooltipValue): JSX.Element | string => {
const headerDataValue = headerData.value;
const formattedValue = formatter(headerDataValue);

if (headerDataValue < domainStart || headerDataValue + xInterval > domainEnd) {
return (
<React.Fragment>
<EuiFlexGroup alignItems="center" className="dscHistogram__header--partial">
<EuiFlexItem grow={false}>
<EuiIcon type="iInCircle" />
</EuiFlexItem>
<EuiFlexItem>{partialDataText}</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer size="m" />
<p>{formattedValue}</p>
</React.Fragment>
);
}

return formattedValue;
};

const tooltipProps = {
headerFormatter: tooltipHeaderFormater,
};

return (
<Chart>
<Settings xDomain={xDomain} onBrushEnd={onBrushEnd} tooltip={tooltipProps} />
<Axis
id={getAxisId('discover-histogram-left-axis')}
position={Position.Left}
title={this.props.chartData.yAxisLabel}
/>
<Axis
id={getAxisId('discover-histogram-bottom-axis')}
position={Position.Bottom}
title={this.props.chartData.xAxisLabel}
tickFormat={formatter}
/>
<LineAnnotation
annotationId={getAnnotationId('line-annotation')}
domainType={AnnotationDomainTypes.XDomain}
dataValues={[currentTime]}
hideTooltips={true}
style={lineAnnotationStyle}
/>
<RectAnnotation
dataValues={rectAnnotations}
annotationId={getAnnotationId('rect-annotation')}
zIndex={2}
/>
<HistogramBarSeries
id={getSpecId('discover-histogram')}
xScaleType={ScaleType.Time}
yScaleType={ScaleType.Linear}
xAccessor="x"
yAccessors={['y']}
data={data}
timeZone={'local'}
name={'Count'}
/>
</Chart>
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import './directive';
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import { VisualizeLoaderProvider } from 'ui/visualize/loader/visualize_loader';
import { recentlyAccessed } from 'ui/persisted_log';
import { getDocLink } from 'ui/documentation_links';
import '../components/fetch_error';
import '../components/histogram';
import { getPainlessError } from './get_painless_error';
import { showShareContextMenu, ShareContextMenuExtensionsRegistryProvider } from 'ui/share';
import { getUnhashableStatesProvider } from 'ui/state_management/state_hashing';
Expand Down Expand Up @@ -739,6 +740,7 @@ function discoverController(
.resolve(buildVislibDimensions($scope.vis, { timeRange: $scope.timeRange, searchSource: $scope.searchSource }))
.then(resp => responseHandler(tabifiedData, resp))
.then(resp => {
$scope.histogramData = resp;
visualizeHandler.render({
as: 'visualization',
value: {
Expand Down
7 changes: 7 additions & 0 deletions src/legacy/core_plugins/kibana/public/discover/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,13 @@ <h1 id="kui_local_breadcrumb" class="kuiLocalBreadcrumb" ng-if="opts.savedSearch

</header>

<discover-histogram
style="display: flex; height: 200px"
ng-show="vis && rows.length !== 0"
chart-data="histogramData"
watch-depth="reference"
></discover-histogram>

<div id="discoverHistogram"
ng-show="vis && rows.length !== 0"
style="display: flex; height: 200px"
Expand Down
2 changes: 2 additions & 0 deletions src/legacy/ui/ui_render/ui_render_mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export function uiRenderMixin(kbnServer, server, config) {

server.exposeStaticDir('/node_modules/@elastic/eui/dist/{path*}', fromRoot('node_modules/@elastic/eui/dist'));
server.exposeStaticDir('/node_modules/@kbn/ui-framework/dist/{path*}', fromRoot('node_modules/@kbn/ui-framework/dist'));
server.exposeStaticDir('/node_modules/@elastic/charts/dist/{path*}', fromRoot('node_modules/@elastic/charts/dist'));

const translationsCache = { translations: null, hash: null };
server.route({
Expand Down Expand Up @@ -125,6 +126,7 @@ export function uiRenderMixin(kbnServer, server, config) {
`${basePath}/node_modules/@kbn/ui-framework/dist/kui_light.css`,
]
),
`${basePath}/node_modules/@elastic/charts/dist/style.css`,
`${regularBundlePath}/${darkMode ? 'dark' : 'light'}_theme.style.css`,
`${regularBundlePath}/commons.style.css`,
`${regularBundlePath}/${app.getId()}.style.css`,
Expand Down

0 comments on commit 1372ed3

Please sign in to comment.