Skip to content

Commit

Permalink
Feat: axis configuration (elastic#341)
Browse files Browse the repository at this point in the history
* fix: remove debugging output

* feat: axisConfig function

* feat: add axis config ui

* feat: use axis config in plot chart

* feat: add horizontalBars arg to seriesStyle

use the setting in the plot function
  • Loading branch information
w33ble authored Feb 22, 2018
1 parent 5453e04 commit f390dce
Show file tree
Hide file tree
Showing 13 changed files with 184 additions and 17 deletions.
26 changes: 26 additions & 0 deletions common/functions/axisConfig.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
export const axisConfig = () => ({
name: 'axisConfig',
aliases: [],
type: 'axisConfig',
context: {
types: ['datatable'],
},
help: 'Configure axis of a visualization',
args: {
show: {
types: ['boolean'],
help: 'Show the axis labels?',
default: true,
},
position: {
types: ['string'],
help: 'Position of the axis labels',
},
},
fn: (context, args) => {
return {
type: 'axisConfig',
...args,
};
},
});
4 changes: 3 additions & 1 deletion common/functions/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { alterColumn } from './alterColumn';
import { asFn } from './as.js';
import { asFn } from './as';
import { axisConfig } from './axisConfig';
import { compare } from './compare';
import { containerStyle } from './containerStyle';
import { context } from './context';
Expand Down Expand Up @@ -43,6 +44,7 @@ import { timefilterControl } from './timefilterControl';
export const commonFunctions = [
alterColumn,
asFn,
axisConfig,
containerStyle,
compare,
columns,
Expand Down
33 changes: 25 additions & 8 deletions common/functions/plot.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { groupBy, get, set, map, sortBy } from 'lodash';
import keyBy from 'lodash.keyby';
import chroma from 'chroma-js';
import { getType } from '../lib/get_type';

export const plot = () => ({
name: 'plot',
Expand Down Expand Up @@ -38,14 +39,12 @@ export const plot = () => ({
default: 'nw',
},
yaxis: {
types: ['boolean'],
help: 'Show the y-axis?',
default: true,
types: ['boolean', 'axisConfig'],
help: 'Axis configuration, or false to disable',
},
xaxis: {
types: ['boolean'],
help: 'Show the x-axis?',
default: true,
types: ['boolean', 'axisConfig'],
help: 'Axis configuration, or false to disable',
},
},
fn: (context, args) => {
Expand All @@ -68,6 +67,7 @@ export const plot = () => ({
barWidth: get(seriesStyle, 'bars'),
fill: 1,
align: 'center',
horizontal: get(seriesStyle, 'horizontalBars', false),
},
// This is here intentionally even though it is the default.
// We use the `size` plugins for this and if the user says they want points
Expand Down Expand Up @@ -154,6 +154,23 @@ export const plot = () => ({
return args.legend;
}

function axisConfig(name, argValue) {
if (getType(argValue) === 'axisConfig') {
// first value is used as the default
const acceptedPositions = name === 'x' ? ['bottom', 'top'] : ['left', 'right'];

const config = { show: true };
config.position = acceptedPositions.includes(argValue.position)
? argValue.position
: acceptedPositions[0];
return config;
}

if (getType(argValue) === 'boolean') return { show: argValue };

return { show: true };
}

const result = {
type: 'render',
as: 'plot',
Expand Down Expand Up @@ -182,15 +199,15 @@ export const plot = () => ({
},
},
xaxis: {
show: args.xaxis,
...axisConfig('x', args.xaxis),
ticks:
get(context.columns, 'x.type') === 'string'
? map(ticks.x.hash, (position, name) => [position, name])
: undefined,
mode: get(context.columns, 'x.type') === 'date' ? 'time' : undefined,
},
yaxis: {
show: args.yaxis,
...axisConfig('y', args.yaxis),
ticks:
get(context.columns, 'y.type') === 'string'
? map(ticks.y.hash, (position, name) => [position, name])
Expand Down
1 change: 0 additions & 1 deletion common/functions/repeatImage/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ export const repeatImage = () => ({
},
},
fn: (count, args) => {
console.log('WTF', count, args);
return {
type: 'render',
as: 'repeatImage',
Expand Down
6 changes: 6 additions & 0 deletions common/functions/seriesStyle.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ export const seriesStyle = () => ({
help:
'Should we stack the series? This is the stack "id". Series with the same stack id will be stacked together',
},
horizontalBars: {
types: ['null', 'boolean'],
displayName: 'Horizontal Bars Orientation',
help: 'Sets the orientation of bars in the chart to horizontal',
default: false,
},
},
fn: (context, args) => ({ type: name, ...args }),
});
16 changes: 16 additions & 0 deletions public/expression_types/arg_types/axis_config/axis_config.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
@import (reference) "../../../style/variables";

.canvas__argtype--axis_config--disabled {
color: @mediumGrey;
font-size: 0.8em;
}

.canvas__argtype--axis_config--configure {
.form-group {
display: flex;

label {
padding: @spacingXS @spacingS;
}
}
}
70 changes: 70 additions & 0 deletions public/expression_types/arg_types/axis_config/extended_template.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import React from 'react';
import PropTypes from 'prop-types';
import { get } from 'lodash';
import { set } from 'object-path-immutable';
import { LabeledInput } from '../../../components/labeled_input';

const defaultExpression = {
type: 'expression',
chain: [
{
type: 'function',
function: 'axisConfig',
arguments: {},
},
],
};

export class ExtendedTemplate extends React.PureComponent {
static propTypes = {
onValueChange: PropTypes.func.isRequired,
argValue: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.shape({
chain: PropTypes.array,
}).isRequired,
]),
typeInstance: PropTypes.object.isRequired,
};

// TODO: this should be in a helper, it's the same code from container_style
getArgValue = (name, alt) => {
return get(this.props.argValue, ['chain', 0, 'arguments', name, 0], alt);
};

// TODO: this should be in a helper, it's the same code from container_style
setArgValue = name => ev => {
const val = ev.target.value;
const { argValue, onValueChange } = this.props;
const oldVal = typeof argValue === 'boolean' ? defaultExpression : argValue;
const newValue = set(oldVal, ['chain', 0, 'arguments', name, 0], val);
onValueChange(newValue);
};

render() {
const isDisabled = typeof this.props.argValue === 'boolean' && this.props.argValue === false;

if (isDisabled)
return <div className="canvas__argtype--axis_config--disabled">The axis is disabled</div>;

const positions = {
xaxis: ['bottom', 'top'],
yaxis: ['left', 'right'],
};
const argName = this.props.typeInstance.name;
const position = this.getArgValue('position', positions[argName][0]);

return (
<div className="canvas__argtype--axis_config--configure">
<LabeledInput
type="select"
className="position"
label="Position"
value={position}
values={positions[argName]}
onChange={this.setArgValue('position')}
/>
</div>
);
}
}
11 changes: 11 additions & 0 deletions public/expression_types/arg_types/axis_config/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { SimpleTemplate } from './simple_template';
import { ExtendedTemplate } from './extended_template';
import './axis_config.less';

export const axisConfig = () => ({
name: 'axisConfig',
displayName: 'Axis Config',
help: 'Visualization axis configuration',
simpleTemplate: SimpleTemplate,
template: ExtendedTemplate,
});
16 changes: 16 additions & 0 deletions public/expression_types/arg_types/axis_config/simple_template.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Toggle } from '../../../components/toggle';

const isEnabled = argValue => typeof argValue !== 'boolean' || argValue !== false;

export const SimpleTemplate = ({ onValueChange, argValue }) => (
<div className="canvas__argtype--axis_config--enable">
<Toggle value={isEnabled(argValue)} onChange={onValueChange} />
</div>
);

SimpleTemplate.propTypes = {
onValueChange: PropTypes.func.isRequired,
argValue: PropTypes.oneOfType([PropTypes.bool, PropTypes.object]),
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { extendedTemplate } from './extended_template';
import './container_style.less';

const wrap = Component =>
// TODO: this should be in a helper
withHandlers({
getArgValue: ({ argValue }) => (name, alt) => {
const args = get(argValue, 'chain.0.arguments', {});
Expand Down
2 changes: 2 additions & 0 deletions public/expression_types/arg_types/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { axisConfig } from './axis_config';
import { containerStyle } from './container_style';
import { checkbox } from './checkbox';
import { datacolumn } from './datacolumn';
Expand All @@ -13,6 +14,7 @@ import { string } from './string';
import { font } from './font';

export const argTypeSpecs = [
axisConfig,
containerStyle,
checkbox,
datacolumn,
Expand Down
5 changes: 4 additions & 1 deletion public/expression_types/arg_types/select.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import React from 'react';
import PropTypes from 'prop-types';
import { FormControl } from 'react-bootstrap';

const getArgValueString = argValue => (typeof argValue === 'string' ? argValue : argValue.value);
const getArgValueString = argValue => {
if (typeof argValue === 'object' && argValue !== null) return argValue.value;
return String(argValue);
};

const SelectArgInput = ({ typeInstance, onValueChange, argValue }) => {
const choices = typeInstance.options.choices;
Expand Down
10 changes: 4 additions & 6 deletions public/expression_types/views/plot.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,14 @@ export const plot = () => ({
{
name: 'xaxis',
displayName: 'X-Axis',
help: 'Enable or disable the x-axis',
argType: 'checkbox',
default: 'true',
help: 'Configure or disable the x-axis',
argType: 'axisConfig',
},
{
name: 'yaxis',
displayName: 'Y-Axis',
help: 'Enable or disable the Y-axis',
argType: 'checkbox',
default: 'true',
help: 'Configure or disable the Y-axis',
argType: 'axisConfig',
},
{
name: 'font',
Expand Down

0 comments on commit f390dce

Please sign in to comment.