Skip to content

Commit

Permalink
Time Series Metric Visualizations (#10662)
Browse files Browse the repository at this point in the history
Backports PR #9725

**Commit 1:**
Initial import

* Original sha: f9d527e
* Authored by Chris Cowan <[email protected]> on 2016-12-21T00:27:11Z

**Commit 2:**
Merge branch 'master' of github.com:elastic/kibana into metrics

* Original sha: c5e936f
* Authored by Chris Cowan <[email protected]> on 2016-12-21T14:26:16Z

**Commit 3:**
updating the editor width to match the new specs

* Original sha: 0d0f4c6
* Authored by Chris Cowan <[email protected]> on 2017-01-02T16:51:06Z

**Commit 4:**
Merge branch 'master' of github.com:elastic/kibana into metrics

* Original sha: 2fb42d0
* Authored by Chris Cowan <[email protected]> on 2017-01-02T16:54:40Z

**Commit 5:**
Adding tribe node support

* Original sha: 63a736a
* Authored by Chris Cowan <[email protected]> on 2017-01-02T16:57:40Z

**Commit 6:**
Adding tests for server libs

* Original sha: 6ede79b
* Authored by Chris Cowan <[email protected]> on 2017-01-02T22:34:57Z

**Commit 7:**
removing bluebird

* Original sha: 1cb2860
* Authored by Chris Cowan <[email protected]> on 2017-01-02T22:39:23Z

**Commit 8:**
removing extra cruft

* Original sha: 4efe0ec
* Authored by Chris Cowan <[email protected]> on 2017-01-04T17:01:32Z

**Commit 9:**
Fixing the font sizes

* Original sha: 33f4d53
* Authored by Chris Cowan <[email protected]> on 2017-01-04T18:09:08Z

**Commit 10:**
Fixed the updating code

* Original sha: 51ff9f8
* Authored by Chris Cowan <[email protected]> on 2017-01-04T18:56:29Z

**Commit 11:**
Adding brushing

* Original sha: 2ba0463
* Authored by Chris Cowan <[email protected]> on 2017-01-04T20:23:46Z

**Commit 12:**
Fixing linting issues

* Original sha: 09b6ada
* Authored by Chris Cowan <[email protected]> on 2017-01-04T20:33:12Z

**Commit 13:**
Adding global filters

* Original sha: 985ec1c
* Authored by Chris Cowan <[email protected]> on 2017-01-04T21:44:20Z

**Commit 14:**
Adding missing packages

* Original sha: bd87e89
* Authored by Chris Cowan <[email protected]> on 2017-01-05T13:16:15Z

**Commit 15:**
Default gauge style to half circle

* Original sha: 5ce7d85
* Authored by Chris Cowan <[email protected]> on 2017-01-05T15:10:51Z

**Commit 16:**
Fixing the markdown css bug

* Original sha: 0b72290
* Authored by Chris Cowan <[email protected]> on 2017-01-05T15:26:53Z

**Commit 17:**
Adding tests for the get_vis_data api

* Original sha: a6e91ba
* Authored by Chris Cowan <[email protected]> on 2017-01-12T15:16:05Z

**Commit 18:**
Adding time offset

* Original sha: 5ee12ac
* Authored by Chris Cowan <[email protected]> on 2017-01-12T17:36:56Z

**Commit 19:**
Adding time offset to each type

* Original sha: ee52e34
* Authored by Chris Cowan <[email protected]> on 2017-01-12T17:42:33Z

**Commit 20:**
fixing bugs from time offset

* Original sha: 16b7469
* Authored by Chris Cowan <[email protected]> on 2017-01-13T23:12:18Z

**Commit 21:**
adding index pattern option to series

* Original sha: 1e64c7c
* Authored by Chris Cowan <[email protected]> on 2017-01-17T21:57:13Z

**Commit 22:**
Merge branch 'master' of github.com:elastic/kibana into metrics

* Original sha: b4ce642
* Authored by Chris Cowan <[email protected]> on 2017-01-17T23:05:40Z

**Commit 23:**
Adding index pattern overrides

* Original sha: b5ff6c6
* Authored by Chris Cowan <[email protected]> on 2017-01-18T05:29:25Z

**Commit 24:**
Adding index pattern overrides

* Original sha: 6641c8e
* Authored by Chris Cowan <[email protected]> on 2017-01-18T05:38:12Z

**Commit 25:**
Fixing tests

* Original sha: b7822ec
* Authored by Chris Cowan <[email protected]> on 2017-01-18T05:43:56Z

**Commit 26:**
Fixing brushing in the vis editor

* Original sha: 74dc57f
* Authored by Chris Cowan <[email protected]> on 2017-01-18T17:14:04Z

**Commit 27:**
Changing the label

* Original sha: 95e58b0
* Authored by Chris Cowan <[email protected]> on 2017-01-18T17:19:03Z

**Commit 28:**
Change the behavior of selecting a pipeline agg when only one exists.

* Original sha: 5d2bf42
* Authored by Chris Cowan <[email protected]> on 2017-01-18T18:18:57Z

**Commit 29:**
Refactoring series a bit

* Original sha: f1ff198
* Authored by Chris Cowan <[email protected]> on 2017-01-18T18:33:15Z

**Commit 30:**
Changing series options to just options

* Original sha: 23821b5
* Authored by Chris Cowan <[email protected]> on 2017-01-18T20:34:59Z
  • Loading branch information
elastic-jasper authored and simianhacker committed Mar 2, 2017
1 parent 48e0046 commit 6bb9e1d
Show file tree
Hide file tree
Showing 247 changed files with 16,793 additions and 5 deletions.
4 changes: 2 additions & 2 deletions docs/timelion.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
Timelion is a time series data visualizer that enables you to combine totally
independent data sources within a single visualization. It's driven by a simple
expression language you use to retrieve time series data, perform calculations
to tease out the answers to complex questions, and visualize the results.
to tease out the answers to complex questions, and visualize the results.

For example, Timelion enables you to easily get the answers to questions like:

Expand All @@ -32,7 +32,7 @@ Timelion expression as a Kibana dashboard panel. You can then add it to
a dashboard like any other visualization.

TIP: You can also create time series visualizations right from the Visualize
app--just select the Timeseries visualization type and enter a Timelion
app--just select the Timelion visualization type and enter a Timelion
expression in the expression field.


Expand Down
2 changes: 1 addition & 1 deletion docs/visualize.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ instructions.
<<tagcloud-chart,Tag cloud>>:: Display words as a cloud in which the size of the word correspond to its importance
<<tilemap,Tile map>>:: Associate the results of an aggregation with geographic
locations.
Timeseries:: Compute and combine data from multiple time series
Timelion:: Compute and combine data from multiple time series
data sets.

. Specify a search query to retrieve the data for your visualization:
Expand Down
14 changes: 14 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
"brace": "0.5.1",
"bunyan": "1.7.1",
"check-hash": "1.0.1",
"color": "1.0.3",
"commander": "2.8.1",
"css-loader": "0.17.0",
"d3": "3.5.6",
Expand Down Expand Up @@ -186,12 +187,14 @@
"classnames": "2.2.5",
"del": "1.2.1",
"elasticdump": "2.1.1",
"enzyme": "2.7.0",
"eslint": "3.11.1",
"eslint-plugin-babel": "4.0.0",
"eslint-plugin-mocha": "4.7.0",
"event-stream": "3.3.2",
"expect.js": "0.3.1",
"faker": "1.1.0",
"flot-charts": "^0.8.3",
"grunt": "1.0.1",
"grunt-aws-s3": "0.14.5",
"grunt-babel": "6.0.0",
Expand All @@ -211,6 +214,7 @@
"image-diff": "1.6.0",
"intern": "3.2.3",
"istanbul-instrumenter-loader": "0.1.3",
"jsdom": "9.9.1",
"karma": "1.2.0",
"karma-chrome-launcher": "0.2.0",
"karma-coverage": "0.5.1",
Expand All @@ -231,15 +235,25 @@
"npm": "3.10.10",
"portscanner": "1.0.0",
"proxyquire": "1.7.10",
"pui-react-overlay-trigger": "^7.0.0",
"pui-react-tooltip": "^7.0.0",
"react": "15.2.0",
"react-ace": "3.7.0",
"react-addons-test-utils": "15.2.0",
"react-anything-sortable": "^1.6.1",
"react-color": "^2.2.7",
"react-dom": "15.2.0",
"react-markdown": "^2.4.2",
"react-redux": "4.4.5",
"react-router": "2.0.0",
"react-router-redux": "4.0.4",
"react-select": "^1.0.0-rc.1",
"react-sortable": "^1.1.0",
"reactcss": "^1.0.7",
"redux": "3.0.0",
"redux-thunk": "0.1.0",
"sass-loader": "4.0.0",
"simianhacker-react-resize-aware": "^1.0.11",
"simple-git": "1.37.0",
"sinon": "1.17.2",
"source-map": "0.5.6",
Expand Down
31 changes: 31 additions & 0 deletions src/core_plugins/metrics/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import fieldsRoutes from './server/routes/fields';
import visDataRoutes from './server/routes/vis';

export default function (kibana) {
return new kibana.Plugin({
require: ['kibana','elasticsearch'],

uiExports: {
visTypes: [
'plugins/metrics/kbn_vis_types'
]
},

config(Joi) {
return Joi.object({
enabled: Joi.boolean().default(true),
chartResolution: Joi.number().default(150),
minimumBucketSize: Joi.number().default(10)
}).default();
},


init(server, options) {
const { status } = server.plugins.elasticsearch;
fieldsRoutes(server);
visDataRoutes(server);
}


});
}
6 changes: 6 additions & 0 deletions src/core_plugins/metrics/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"author": "Chris Cowan<[email protected]>",
"name": "metrics",
"version": "kibana"
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// import React from 'react';
// import { expect } from 'chai';
// import { shallow } from 'enzyme';
// import sinon from 'sinon';
// import AddDeleteButtons from '../add_delete_buttons';
// import Tooltip from '../tooltip';

// describe('<AddDeleteButtons />', () => {

// it('calls onAdd={handleAdd}', () => {
// const handleAdd = sinon.spy();
// const wrapper = shallow(
// <AddDeleteButtons onAdd={handleAdd} />
// );
// wrapper.find('a').at(0).simulate('click');
// expect(handleAdd.calledOnce).to.equal(true);
// });

// it('calls onDelete={handleDelete}', () => {
// const handleDelete = sinon.spy();
// const wrapper = shallow(
// <AddDeleteButtons onDelete={handleDelete} />
// );
// wrapper.find('a').at(1).simulate('click');
// expect(handleDelete.calledOnce).to.equal(true);
// });

// it('calls onClone={handleClone}', () => {
// const handleClone = sinon.spy();
// const wrapper = shallow(
// <AddDeleteButtons onClone={handleClone} />
// );
// wrapper.find('a').at(0).simulate('click');
// expect(handleClone.calledOnce).to.equal(true);
// });

// it('disableDelete={true}', () => {
// const wrapper = shallow(
// <AddDeleteButtons disableDelete={true} />
// );
// expect(wrapper.find({ text: 'Delete' })).to.have.length(0);
// });

// it('disableAdd={true}', () => {
// const wrapper = shallow(
// <AddDeleteButtons disableAdd={true} />
// );
// expect(wrapper.find({ text: 'Add' })).to.have.length(0);
// });

// it('should not display clone by default', () => {
// const wrapper = shallow(
// <AddDeleteButtons />
// );
// expect(wrapper.find({ text: 'Clone' })).to.have.length(0);
// });

// it('should not display clone when disableAdd={true}', () => {
// const fn = sinon.spy();
// const wrapper = shallow(
// <AddDeleteButtons onClone={fn} disableAdd={true} />
// );
// expect(wrapper.find({ text: 'Clone' })).to.have.length(0);
// });

// });

33 changes: 33 additions & 0 deletions src/core_plugins/metrics/public/components/__tests__/yes_no.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// import React from 'react';
// import { expect } from 'chai';
// import { shallow } from 'enzyme';
// import sinon from 'sinon';
// import YesNo from '../yes_no';

// describe('<YesNo />', () => {

// it('call onChange={handleChange} on yes', () => {
// const handleChange = sinon.spy();
// const wrapper = shallow(
// <YesNo name="test" onChange={handleChange} />
// );
// wrapper.find('input').first().simulate('change');
// expect(handleChange.calledOnce).to.equal(true);
// expect(handleChange.firstCall.args[0]).to.eql({
// test: 1
// });
// });

// it('call onChange={handleChange} on no', () => {
// const handleChange = sinon.spy();
// const wrapper = shallow(
// <YesNo name="test" onChange={handleChange} />
// );
// wrapper.find('input').last().simulate('change');
// expect(handleChange.calledOnce).to.equal(true);
// expect(handleChange.firstCall.args[0]).to.eql({
// test: 0
// });
// });

// });
58 changes: 58 additions & 0 deletions src/core_plugins/metrics/public/components/add_delete_buttons.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React, { Component, PropTypes } from 'react';
import Tooltip from './tooltip';

function AddDeleteButtons(props) {
const createDelete = () => {
if (props.disableDelete) {
return null;
}
return (
<Tooltip text="Delete">
<a className="thor__button-outlined-danger sm" onClick={ props.onDelete }>
<i className="fa fa-trash-o"></i>
</a>
</Tooltip>
);
};
const createAdd = () => {
if (props.disableAdd) {
return null;
}
return (
<Tooltip text="Add">
<a className="thor__button-outlined-default sm" onClick={ props.onAdd }>
<i className="fa fa-plus"></i>
</a>
</Tooltip>
);
};
const deleteBtn = createDelete();
const addBtn = createAdd();
let clone;
if (props.onClone && !props.disableAdd) {
clone = (
<Tooltip text="Clone">
<a className="thor__button-outlined-default sm" onClick={ props.onClone }>
<i className="fa fa-files-o"></i>
</a>
</Tooltip>
);
}
return (
<div className="add_delete__buttons">
{ clone }
{ addBtn }
{ deleteBtn }
</div>
);
}

AddDeleteButtons.propTypes = {
disableAdd: PropTypes.bool,
disableDelete: PropTypes.bool,
onClone: PropTypes.func,
onAdd: PropTypes.func,
onDelete: PropTypes.func
};

export default AddDeleteButtons;
51 changes: 51 additions & 0 deletions src/core_plugins/metrics/public/components/aggs/agg.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React, { PropTypes } from 'react';
import StdAgg from './std_agg';
import aggToComponent from '../lib/agg_to_component';
import { sortable } from 'react-anything-sortable';

function Agg(props) {
const { model } = props;
let Component = aggToComponent[model.type];
if (!Component) {
Component = StdAgg;
}
const style = Object.assign({ cursor: 'default' }, props.style);
return (
<div
className={props.className}
style={style}
onMouseDown={props.onMouseDown}
onTouchStart={props.onTouchStart}>
<Component
fields={props.fields}
disableDelete={props.disableDelete}
model={props.model}
onAdd={props.onAdd}
onChange={props.onChange}
onDelete={props.onDelete}
panel={props.panel}
series={props.series}
siblings={props.siblings}/>
</div>
);

}

Agg.propTypes = {
disableDelete: PropTypes.bool,
fields: PropTypes.object,
model: PropTypes.object,
onAdd: PropTypes.func,
onChange: PropTypes.func,
onDelete: PropTypes.func,
onMouseDown: PropTypes.func,
onSortableItemMount: PropTypes.func,
onSortableItemReadyToMove: PropTypes.func,
onTouchStart: PropTypes.func,
panel: PropTypes.object,
series: PropTypes.object,
siblings: PropTypes.array,
sortData: PropTypes.string,
};

export default sortable(Agg);
53 changes: 53 additions & 0 deletions src/core_plugins/metrics/public/components/aggs/agg_row.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React, { PropTypes } from 'react';
import _ from 'lodash';
import AddDeleteButtons from '../add_delete_buttons';
import Tooltip from '../tooltip';

function AggRow(props) {
let iconClassName = 'fa fa-eye-slash';
let iconRowClassName = 'vis_editor__agg_row-icon';
const last = _.last(props.siblings);
if (last.id === props.model.id) {
iconClassName = 'fa fa-eye';
iconRowClassName += ' last';
}

let dragHandle;
if (!props.disableDelete) {
dragHandle = (
<div>
<Tooltip text="Sort">
<div className="vis_editor__agg_sort thor__button-outlined-default sm">
<i className="fa fa-sort"></i>
</div>
</Tooltip>
</div>
);
}

return (
<div className="vis_editor__agg_row">
<div className="vis_editor__agg_row-item">
<div className={iconRowClassName}>
<i className={iconClassName}></i>
</div>
{props.children}
{ dragHandle }
<AddDeleteButtons
onAdd={props.onAdd}
onDelete={props.onDelete}
disableDelete={props.disableDelete}/>
</div>
</div>
);
}

AggRow.propTypes = {
disableDelete: PropTypes.bool,
model: PropTypes.object,
onAdd: PropTypes.func,
onDelete: PropTypes.func,
siblings: PropTypes.array,
};

export default AggRow;
Loading

0 comments on commit 6bb9e1d

Please sign in to comment.