mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
TSVB less to sass - and some UI work (#24250)
Fixes #16483, Fixes #20115, Fixes #17852, Fixes #16768, Fixes #14348, Fixes #17842, closes #15580, closes #14938
This commit is contained in:
parent
8143d58ea4
commit
2b3bff34b8
137 changed files with 4239 additions and 4229 deletions
|
@ -27,7 +27,8 @@ export default function (kibana) {
|
|||
uiExports: {
|
||||
visTypes: [
|
||||
'plugins/metrics/kbn_vis_types'
|
||||
]
|
||||
],
|
||||
styleSheetPaths: `${__dirname}/public/index.scss`,
|
||||
},
|
||||
|
||||
config(Joi) {
|
||||
|
|
128
src/core_plugins/metrics/public/_hacks.scss
Normal file
128
src/core_plugins/metrics/public/_hacks.scss
Normal file
|
@ -0,0 +1,128 @@
|
|||
// EUITODO: Create our own Markdown styles
|
||||
.tvbMarkdown__content {
|
||||
color: rgba(0,0,0,1);
|
||||
|
||||
pre, code, tt {
|
||||
border-radius: 0;
|
||||
font: 1em/1.5em 'Andale Mono', 'Lucida Console', monospace;
|
||||
}
|
||||
|
||||
h1 { font-size: 30px; }
|
||||
h2 { font-size: 26px; }
|
||||
h3 { font-size: 22px; }
|
||||
h4 { font-size: 18px; }
|
||||
h5 { font-size: 16px; }
|
||||
h6 { font-size: 16px; }
|
||||
|
||||
h1, h2, h3, h4, h5, h6, b, strong {
|
||||
margin:0 0 15px 0;
|
||||
font-weight: bold;
|
||||
}
|
||||
em, i, dfn {
|
||||
font-style: italic;
|
||||
}
|
||||
dfn {
|
||||
font-weight:bold;
|
||||
}
|
||||
p, code, pre, kbd {
|
||||
margin:0 0 15px 0;
|
||||
}
|
||||
blockquote {
|
||||
margin:0 15px 15px 15px;
|
||||
}
|
||||
cite {
|
||||
font-style: italic;
|
||||
}
|
||||
li ul, li ol {
|
||||
margin:0 15px;
|
||||
}
|
||||
ul, ol {
|
||||
margin:0 15px 15px 15px;
|
||||
}
|
||||
ul {
|
||||
list-style-type:disc;
|
||||
}
|
||||
ol {
|
||||
list-style-type:decimal;
|
||||
}
|
||||
ol ol {
|
||||
list-style: upper-alpha;
|
||||
}
|
||||
ol ol ol {
|
||||
list-style: lower-roman;
|
||||
}
|
||||
ol ol ol ol {
|
||||
list-style: lower-alpha;
|
||||
}
|
||||
dl {
|
||||
margin:0 0 15px 0;
|
||||
}
|
||||
dl dt {
|
||||
font-weight:bold;
|
||||
}
|
||||
dd {
|
||||
margin-left:1.5em;
|
||||
}
|
||||
table {
|
||||
margin-bottom:1.4em;
|
||||
width:100%;
|
||||
}
|
||||
th {
|
||||
font-weight:bold;
|
||||
}
|
||||
th, td, caption {
|
||||
padding:4px 15px 4px 5px;
|
||||
}
|
||||
tfoot {
|
||||
font-style:italic;
|
||||
}
|
||||
sup, sub {
|
||||
line-height:0;
|
||||
}
|
||||
abbr, acronym {
|
||||
border-bottom: 1px dotted;
|
||||
}
|
||||
address {
|
||||
margin:0 0 15px;
|
||||
font-style:italic;
|
||||
}
|
||||
del {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
pre {
|
||||
margin: 15px 0;
|
||||
white-space: pre;
|
||||
}
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
pre, code, tt {
|
||||
background-color: rgba(0,0,0,0.1);
|
||||
color: red;
|
||||
code {
|
||||
color: rgba(0,0,0,1);
|
||||
background-color: transparent;
|
||||
}
|
||||
border: none;
|
||||
}
|
||||
|
||||
.tvbMarkdown.reversed & {
|
||||
.table > thead > tr > th {
|
||||
color: rgba(255,255,255,0.5);
|
||||
border-bottom: 2px solid rgba(255,255,255,0.2);
|
||||
}
|
||||
.table > tbody > tr > td {
|
||||
border-top: 1px solid rgba(255,255,255,0.2);
|
||||
}
|
||||
color: rgba(255,255,255,1);
|
||||
pre, code, tt {
|
||||
background-color: rgba(255,255,255,0.2);
|
||||
color: #ffa5a8;
|
||||
code {
|
||||
color: rgba(255,255,255,1);
|
||||
background-color: transparent;
|
||||
}
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
14
src/core_plugins/metrics/public/_mixins.scss
Normal file
14
src/core_plugins/metrics/public/_mixins.scss
Normal file
|
@ -0,0 +1,14 @@
|
|||
@import 'node_modules/@elastic/eui/src/components/form/variables';
|
||||
@import 'node_modules/@elastic/eui/src/components/form/mixins';
|
||||
|
||||
@mixin tvbEditor__repeatingRow {
|
||||
background-color: $euiColorLightestShade;
|
||||
padding: $euiSizeS;
|
||||
margin-bottom: $euiSizeS;
|
||||
}
|
||||
|
||||
// SASSTODO: These need to be converted to EUI,
|
||||
// but they have type errors
|
||||
@mixin tvbEditor__input {
|
||||
@include euiFormControlStyle($borderOnly: false, $includeStates: true, $includeSizes: false);
|
||||
}
|
41
src/core_plugins/metrics/public/_ui_sortable.scss
Normal file
41
src/core_plugins/metrics/public/_ui_sortable.scss
Normal file
|
@ -0,0 +1,41 @@
|
|||
// react-anything-sortable overrides
|
||||
// Scoped to just the TSVB editor
|
||||
|
||||
.tvbEditor {
|
||||
|
||||
.ui-sortable {
|
||||
display: block;
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
user-select: none;
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
content: " ";
|
||||
display: table;
|
||||
}
|
||||
|
||||
&:after {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.ui-sortable-item.ui-sortable-dragging {
|
||||
position: absolute;
|
||||
z-index: $euiZLevel2;
|
||||
}
|
||||
|
||||
.ui-sortable-placeholder {
|
||||
display: none;
|
||||
|
||||
&.visible {
|
||||
display: block;
|
||||
opacity: 0.5;
|
||||
z-index: -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
11
src/core_plugins/metrics/public/_variables.scss
Normal file
11
src/core_plugins/metrics/public/_variables.scss
Normal file
|
@ -0,0 +1,11 @@
|
|||
$tvbLineColor: transparentize($euiColorFullShade,0.8);
|
||||
$tvbLineColorReversed: transparentize($euiColorEmptyShade,0.6);
|
||||
|
||||
$tvbTextColor: transparentize($euiColorFullShade,0.6);
|
||||
$tvbTextColorReversed: transparentize($euiColorEmptyShade,0.4);
|
||||
|
||||
$tvbValueColor: transparentize($euiColorFullShade,0.3);
|
||||
$tvbValueColorReversed: transparentize($euiColorEmptyShade,0.2);
|
||||
|
||||
$tvbHoverBackgroundColor: transparentize($euiColorFullShade,0.9);
|
||||
$tvbHoverBackgroundColorReversed: transparentize($euiColorEmptyShade,0.9);
|
|
@ -0,0 +1,13 @@
|
|||
@import 'node_modules/@elastic/eui/src/components/panel/mixins';
|
||||
|
||||
.tvbAnnotationsEditor__container {
|
||||
padding: $euiSize;
|
||||
background-color: $euiColorLightestShade;
|
||||
}
|
||||
|
||||
@include euiPanel('tvbAnnotationsEditor');
|
||||
|
||||
.tvbAnnotationsEditor {
|
||||
margin-bottom: $euiSize;
|
||||
padding: $euiSizeS;
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
// EUITODO: Convert to EuiColorPicker
|
||||
|
||||
@import 'node_modules/@elastic/eui/src/components/color_picker/index';
|
||||
|
||||
.tvbColorPicker {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tvbColorPicker__swatch-empty,
|
||||
.tvbColorPicker__swatch {
|
||||
@extend .euiColorPicker__swatch;
|
||||
}
|
||||
|
||||
.tvbColorPicker__swatch-empty {
|
||||
background-color: transparent;
|
||||
background-size: 22px 22px;
|
||||
background-image: repeating-linear-gradient(
|
||||
-45deg,
|
||||
$euiColorDanger,
|
||||
$euiColorDanger 2px,
|
||||
transparent 2px,
|
||||
transparent $euiSize
|
||||
);
|
||||
}
|
||||
|
||||
.tvbColorPicker__clear {
|
||||
margin-left: $euiSizeXS;
|
||||
}
|
||||
|
||||
.tvbColorPicker__popover {
|
||||
position: absolute;
|
||||
top: $euiSizeL;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.tvbColorPicker__cover {
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
.tvbColorRules__rule {
|
||||
@include tvbEditor__repeatingRow;
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
// EUITODO: Convert to EuiColorPicker
|
||||
// with additional support for alpha, saturation, swatches
|
||||
|
||||
// SASSTODO: This custom picker moved all styles from react-color inline styles
|
||||
// to SASS, but it should be in EUI.
|
||||
// Also, some pixel values were kept as is to match inline styles from react-color
|
||||
.tvbColorPickerPopUp {
|
||||
@include euiBottomShadowMedium();
|
||||
background-color: $euiColorEmptyShade;
|
||||
border-radius: $euiBorderRadius;
|
||||
box-sizing: initial;
|
||||
width: 275px;
|
||||
font-family: 'Menlo';
|
||||
}
|
||||
|
||||
.tvbColorPickerPopUp__saturation {
|
||||
width: 100%;
|
||||
padding-bottom: 55%;
|
||||
position: relative;
|
||||
border-radius: $euiBorderRadius $euiBorderRadius 0 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tvbColorPickerPopUp__body {
|
||||
padding: $euiSize;
|
||||
}
|
||||
|
||||
.tvbColorPickerPopUp__controls {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.tvbColorPickerPopUp__color {
|
||||
width: $euiSizeXL;
|
||||
|
||||
// The color indicator doesn't work, hiding it until it does
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tvbColorPickerPopUp__color-disableAlpha {
|
||||
width: $euiSizeL;
|
||||
}
|
||||
|
||||
.tvbColorPickerPopUp__swatch {
|
||||
margin-top: 6px;
|
||||
width: $euiSize;
|
||||
height: $euiSize;
|
||||
border-radius: $euiSizeS;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tvbColorPickerPopUp__swatch-disableAlpha {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.tvbColorPickerPopUp__active {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
border-radius: $euiSizeS;
|
||||
box-shadow: inset 0 0 0 1px rgba(0,0,0,0.1);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.tvbColorPickerPopUp__toggles {
|
||||
flex: 1
|
||||
}
|
||||
|
||||
.tvbColorPickerPopUp__hue {
|
||||
height: 10px;
|
||||
position: relative;
|
||||
margin-bottom: $euiSizeS;
|
||||
}
|
||||
|
||||
.tvbColorPickerPopUp__hue-disableAlpha {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.tvbColorPickerPopUp__alpha {
|
||||
height: 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tvbColorPickerPopUp__alpha-disableAlpha {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tvbColorPickerPopUp__swatches {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
margin-top: $euiSize;
|
||||
}
|
33
src/core_plugins/metrics/public/components/_error.scss
Normal file
33
src/core_plugins/metrics/public/components/_error.scss
Normal file
|
@ -0,0 +1,33 @@
|
|||
// EUITODO: Convert to EuiCallout
|
||||
.tvbError {
|
||||
padding: $euiSize;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
// Calculate colors similar to EuiCallout
|
||||
$tempBackgroundColor: tintOrShade($euiColorDanger, 90%, 70%);
|
||||
background-color: $tempBackgroundColor;
|
||||
|
||||
.tvbError__title {
|
||||
@include euiTitle("xs");
|
||||
color: makeHighContrastColor($euiColorDanger, $tempBackgroundColor);
|
||||
}
|
||||
}
|
||||
|
||||
.tvbError__additional,
|
||||
.tvbError__stack {
|
||||
margin-top: $euiSizeS;
|
||||
}
|
||||
|
||||
// EUITODO: Convert to EuiCodeBlock
|
||||
.tvbError__stack {
|
||||
padding: $euiSizeS;
|
||||
background: $euiCodeBlockBackgroundColor;
|
||||
color: $euiCodeBlockColor;
|
||||
line-height: $euiLineHeight;
|
||||
font-family: $euiCodeFontFamily;
|
||||
font-weight: $euiFontWeightRegular;
|
||||
white-space: pre-wrap;
|
||||
}
|
16
src/core_plugins/metrics/public/components/_index.scss
Normal file
16
src/core_plugins/metrics/public/components/_index.scss
Normal file
|
@ -0,0 +1,16 @@
|
|||
@import './annotations_editor';
|
||||
@import './color_rules';
|
||||
@import './color_picker';
|
||||
@import './custom_color_picker';
|
||||
@import './error';
|
||||
@import './no_data';
|
||||
@import './markdown_editor';
|
||||
@import './series_editor';
|
||||
@import './vis_editor';
|
||||
@import './vis_editor_visualization';
|
||||
@import './vis_picker';
|
||||
@import './vis_with_splits';
|
||||
|
||||
@import './aggs/index';
|
||||
@import './panel_config/index';
|
||||
@import './vis_types/index';
|
|
@ -0,0 +1,28 @@
|
|||
.tvbMarkdownEditor {
|
||||
display: flex;
|
||||
background-color: $euiColorEmptyShade;
|
||||
height: 500px;
|
||||
}
|
||||
|
||||
.tvbMarkdownEditor__editor,
|
||||
.tvbMarkdownEditor__variables {
|
||||
width: 50%;
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
|
||||
.tvbMarkdownEditor__editor {
|
||||
border-right: 2px solid $euiColorLightestShade;
|
||||
}
|
||||
|
||||
.tvbMarkdownEditor__variables {
|
||||
padding: $euiSizeS;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.tvbMarkdownEditor__noVariables {
|
||||
display: block;
|
||||
padding-bottom: $euiSizeXXL;
|
||||
padding-top: $euiSizeXXL - $euiSizeL;
|
||||
text-align: center;
|
||||
border-bottom: $euiBorderThin;
|
||||
}
|
17
src/core_plugins/metrics/public/components/_no_data.scss
Normal file
17
src/core_plugins/metrics/public/components/_no_data.scss
Normal file
|
@ -0,0 +1,17 @@
|
|||
// EUITODO: Convert to EuiCallout
|
||||
.tvbNoData {
|
||||
padding: $euiSize;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
// Calculate colors similar to EuiCallout
|
||||
$tempBackgroundColor: tintOrShade($euiColorPrimary, 90%, 70%);
|
||||
background-color: $tempBackgroundColor;
|
||||
|
||||
.tvbNoData__title {
|
||||
@include euiTitle("xs");
|
||||
color: makeHighContrastColor($euiColorPrimary, $tempBackgroundColor);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
@import 'node_modules/@elastic/eui/src/components/panel/mixins';
|
||||
|
||||
.tvbSeriesEditor__container {
|
||||
padding: $euiSize;
|
||||
background-color: $euiColorLightestShade;
|
||||
}
|
||||
|
||||
@include euiPanel('tvbSeriesEditor');
|
||||
|
||||
.tvbSeriesEditor {
|
||||
margin-bottom: $euiSize;
|
||||
padding: $euiSizeS;
|
||||
|
||||
// When dragging a collapsed item, make sure the contents doesn't show
|
||||
&.ui-sortable-dragging {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.tvbSeries__body {
|
||||
margin-left: $euiSizeXL;
|
||||
margin-top: $euiSizeS;
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
.tvbEditor {
|
||||
flex: 1;
|
||||
background: $euiColorLightestShade;
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
.tvbEditorVisualization {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1 0 auto;
|
||||
width: 100%;
|
||||
height: $euiSizeL * 10;
|
||||
line-height: normal;
|
||||
background-color: $euiColorEmptyShade;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.tvbEditorVisualization__apply {
|
||||
padding: $euiSizeS;
|
||||
}
|
||||
|
||||
.tvbEditorVisualization__draghandle {
|
||||
@include kibana-resizer($size: ($euiSizeM + 2px), $direction: vertical);
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
.tvbVisPickerItem {
|
||||
font-size: $euiFontSizeM;
|
||||
font-weight: $euiFontWeightMedium;
|
||||
}
|
|
@ -1,16 +1,11 @@
|
|||
.splitVis {
|
||||
.tvbSplitVis {
|
||||
display: flex;
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
|
||||
.splitVis_split {
|
||||
.tvbSplitVis__split {
|
||||
display: flex;
|
||||
flex: 1 0 0;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.splitVis_visualization {
|
||||
position: relative;
|
||||
flex: 1 0 auto;
|
||||
}
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { EuiToolTip } from '@elastic/eui';
|
||||
import { EuiToolTip, EuiButtonIcon, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
|
||||
function AddDeleteButtons(props) {
|
||||
const { testSubj } = props;
|
||||
|
@ -28,16 +28,17 @@ function AddDeleteButtons(props) {
|
|||
return null;
|
||||
}
|
||||
return (
|
||||
<EuiToolTip content={props.deleteTooltip}>
|
||||
<button
|
||||
data-test-subj={`${testSubj}DeleteBtn`}
|
||||
aria-label={props.deleteTooltip}
|
||||
className="thor__button-outlined-danger thor__button-delete sm"
|
||||
onClick={props.onDelete}
|
||||
>
|
||||
<i className="fa fa-trash-o" />
|
||||
</button>
|
||||
</EuiToolTip>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiToolTip content={props.deleteTooltip}>
|
||||
<EuiButtonIcon
|
||||
data-test-subj={`${testSubj}DeleteBtn`}
|
||||
aria-label={props.deleteTooltip}
|
||||
color="danger"
|
||||
iconType="trash"
|
||||
onClick={props.onDelete}
|
||||
/>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
);
|
||||
};
|
||||
const createAdd = () => {
|
||||
|
@ -45,16 +46,16 @@ function AddDeleteButtons(props) {
|
|||
return null;
|
||||
}
|
||||
return (
|
||||
<EuiToolTip content={props.addTooltip}>
|
||||
<button
|
||||
data-test-subj={`${testSubj}AddBtn`}
|
||||
aria-label={props.addTooltip}
|
||||
className="thor__button-outlined-default sm thor__button-add"
|
||||
onClick={props.onAdd}
|
||||
>
|
||||
<i className="fa fa-plus" />
|
||||
</button>
|
||||
</EuiToolTip>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiToolTip content={props.addTooltip}>
|
||||
<EuiButtonIcon
|
||||
data-test-subj={`${testSubj}AddBtn`}
|
||||
aria-label={props.addTooltip}
|
||||
iconType="plusInCircle"
|
||||
onClick={props.onAdd}
|
||||
/>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
);
|
||||
};
|
||||
const deleteBtn = createDelete();
|
||||
|
@ -62,24 +63,24 @@ function AddDeleteButtons(props) {
|
|||
let clone;
|
||||
if (props.onClone && !props.disableAdd) {
|
||||
clone = (
|
||||
<EuiToolTip content={props.cloneTooltip}>
|
||||
<button
|
||||
data-test-subj={`${testSubj}CloneBtn`}
|
||||
aria-label={props.cloneTooltip}
|
||||
className="thor__button-outlined-default thor__button-clone sm"
|
||||
onClick={props.onClone}
|
||||
>
|
||||
<i className="fa fa-files-o" />
|
||||
</button>
|
||||
</EuiToolTip>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiToolTip content={props.cloneTooltip}>
|
||||
<EuiButtonIcon
|
||||
data-test-subj={`${testSubj}CloneBtn`}
|
||||
aria-label={props.cloneTooltip}
|
||||
iconType="copy"
|
||||
onClick={props.onClone}
|
||||
/>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className="add_delete__buttons">
|
||||
<EuiFlexGroup gutterSize="s" responsive={props.responsive} justifyContent="flexEnd">
|
||||
{ clone }
|
||||
{ addBtn }
|
||||
{ deleteBtn }
|
||||
</div>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -98,7 +99,8 @@ AddDeleteButtons.propTypes = {
|
|||
disableDelete: PropTypes.bool,
|
||||
onClone: PropTypes.func,
|
||||
onAdd: PropTypes.func,
|
||||
onDelete: PropTypes.func
|
||||
onDelete: PropTypes.func,
|
||||
responsive: PropTypes.bool,
|
||||
};
|
||||
|
||||
export default AddDeleteButtons;
|
||||
|
|
|
@ -29,7 +29,7 @@ describe('AddDeleteButtons', () => {
|
|||
const wrapper = shallow(
|
||||
<AddDeleteButtons onAdd={handleAdd} />
|
||||
);
|
||||
wrapper.find('button').at(0).simulate('click');
|
||||
wrapper.find('EuiButtonIcon').at(0).simulate('click');
|
||||
expect(handleAdd.calledOnce).to.equal(true);
|
||||
});
|
||||
|
||||
|
@ -38,7 +38,7 @@ describe('AddDeleteButtons', () => {
|
|||
const wrapper = shallow(
|
||||
<AddDeleteButtons onDelete={handleDelete} />
|
||||
);
|
||||
wrapper.find('button').at(1).simulate('click');
|
||||
wrapper.find('EuiButtonIcon').at(1).simulate('click');
|
||||
expect(handleDelete.calledOnce).to.equal(true);
|
||||
});
|
||||
|
||||
|
@ -47,7 +47,7 @@ describe('AddDeleteButtons', () => {
|
|||
const wrapper = shallow(
|
||||
<AddDeleteButtons onClone={handleClone} />
|
||||
);
|
||||
wrapper.find('button').at(0).simulate('click');
|
||||
wrapper.find('EuiButtonIcon').at(0).simulate('click');
|
||||
expect(handleClone.calledOnce).to.equal(true);
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
.tvbAggRow {
|
||||
@include tvbEditor__repeatingRow;
|
||||
}
|
||||
|
||||
.tvbAggRow--split {
|
||||
padding-left: $euiSizeXL;
|
||||
}
|
||||
|
||||
.tvbAggRow__visibilityIcon {
|
||||
margin-top: $euiSizeXS;
|
||||
}
|
||||
|
||||
.tvbAggRow__children {
|
||||
padding-top: $euiSizeS - 2px;
|
||||
}
|
||||
|
||||
.tvbAggRow__unavailable {
|
||||
margin-top: -$euiSizeXS;
|
||||
}
|
||||
|
||||
.tvbAgg__input {
|
||||
@include euiFormControlStyle($borderOnly: false, $includeStates: true, $includeSizes: false);
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
@import './agg_row';
|
|
@ -21,47 +21,49 @@ import PropTypes from 'prop-types';
|
|||
import React from 'react';
|
||||
import _ from 'lodash';
|
||||
import AddDeleteButtons from '../add_delete_buttons';
|
||||
import { EuiToolTip } from '@elastic/eui';
|
||||
import { EuiToolTip, EuiButtonIcon, EuiIcon, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
|
||||
function AggRow(props) {
|
||||
let iconClassName = 'fa fa-eye-slash';
|
||||
let iconRowClassName = 'vis_editor__agg_row-icon';
|
||||
let iconType = 'eyeClosed';
|
||||
let iconColor = 'subdued';
|
||||
const last = _.last(props.siblings);
|
||||
if (last.id === props.model.id) {
|
||||
iconClassName = 'fa fa-eye';
|
||||
iconRowClassName += ' last';
|
||||
iconType = 'eye';
|
||||
iconColor = 'text';
|
||||
}
|
||||
|
||||
let dragHandle;
|
||||
if (!props.disableDelete) {
|
||||
dragHandle = (
|
||||
<div>
|
||||
<EuiToolTip content="Sort">
|
||||
<div className="vis_editor__agg_sort thor__button-outlined-default sm">
|
||||
<i className="fa fa-sort" />
|
||||
</div>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiToolTip content="Drag to sort">
|
||||
<EuiButtonIcon className="tvbAggRow__sortHandle" aria-label="Drag to sort" iconType="grab" />
|
||||
</EuiToolTip>
|
||||
</div>
|
||||
</EuiFlexItem>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="vis_editor__agg_row">
|
||||
<div className="vis_editor__agg_row-item" data-test-subj="aggRow">
|
||||
<div className={iconRowClassName}>
|
||||
<i className={iconClassName} />
|
||||
</div>
|
||||
{props.children}
|
||||
{ dragHandle }
|
||||
<AddDeleteButtons
|
||||
testSubj="addMetric"
|
||||
addTooltip="Add Metric"
|
||||
deleteTooltip="Delete Metric"
|
||||
onAdd={props.onAdd}
|
||||
onDelete={props.onDelete}
|
||||
disableDelete={props.disableDelete}
|
||||
/>
|
||||
</div>
|
||||
<div className="tvbAggRow">
|
||||
<EuiFlexGroup data-test-subj="aggRow" gutterSize="s" alignItems="flexStart" responsive={false}>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiIcon className="tvbAggRow__visibilityIcon" type={iconType} color={iconColor} />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem className="tvbAggRow__children">
|
||||
{props.children}
|
||||
</EuiFlexItem>
|
||||
{dragHandle}
|
||||
<EuiFlexItem grow={false}>
|
||||
<AddDeleteButtons
|
||||
testSubj="addMetric"
|
||||
addTooltip="Add metric"
|
||||
deleteTooltip="Delete metric"
|
||||
onAdd={props.onAdd}
|
||||
onDelete={props.onDelete}
|
||||
disableDelete={props.disableDelete}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ function filterByPanelType(panelType) {
|
|||
}
|
||||
|
||||
function AggSelect(props) {
|
||||
const { siblings, panelType, value } = props;
|
||||
const { siblings, panelType, value, onChange, ...rest } = props;
|
||||
|
||||
const selectedOption = allAggOptions.find(option => {
|
||||
return value === option.value;
|
||||
|
@ -120,18 +120,19 @@ function AggSelect(props) {
|
|||
|
||||
const handleChange = selectedOptions => {
|
||||
if (!selectedOptions || selectedOptions.length <= 0) return;
|
||||
props.onChange(selectedOptions);
|
||||
onChange(selectedOptions);
|
||||
};
|
||||
|
||||
return (
|
||||
<div data-test-subj="aggSelector" className="vis_editor__row_item">
|
||||
<div data-test-subj="aggSelector">
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
placeholder="Select aggregation"
|
||||
options={options}
|
||||
selectedOptions={selectedOptions}
|
||||
onChange={handleChange}
|
||||
singleSelection={true}
|
||||
singleSelection={{ asPlainText: true }}
|
||||
{...rest}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -29,7 +29,15 @@ import createSelectHandler from '../lib/create_select_handler';
|
|||
import createTextHandler from '../lib/create_text_handler';
|
||||
import Vars from './vars';
|
||||
|
||||
import { htmlIdGenerator } from '@elastic/eui';
|
||||
import {
|
||||
htmlIdGenerator,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormLabel,
|
||||
EuiTextArea,
|
||||
EuiFormRow,
|
||||
EuiCode,
|
||||
} from '@elastic/eui';
|
||||
|
||||
class CalculationAgg extends Component {
|
||||
|
||||
|
@ -61,40 +69,49 @@ class CalculationAgg extends Component {
|
|||
onDelete={this.props.onDelete}
|
||||
siblings={this.props.siblings}
|
||||
>
|
||||
<div className="vis_editor__row_item">
|
||||
<div>
|
||||
<div className="vis_editor__label">Aggregation</div>
|
||||
<EuiFlexGroup direction="column" gutterSize="l">
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('aggregation')}>Aggregation</EuiFormLabel>
|
||||
<AggSelect
|
||||
id={htmlId('aggregation')}
|
||||
panelType={this.props.panel.type}
|
||||
siblings={this.props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
/>
|
||||
<div className="vis_editor__variables">
|
||||
<div className="vis_editor__label">Variables</div>
|
||||
<Vars
|
||||
metrics={siblings}
|
||||
onChange={handleChange}
|
||||
name="variables"
|
||||
model={model}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__row_item">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('painless')}>
|
||||
Painless Script - Variables are keys on the <code>params</code>
|
||||
object, i.e. <code>params.<name></code>.
|
||||
To access the bucket interval (in milliseconds) use <code>params._interval</code>.
|
||||
</label>
|
||||
<input
|
||||
id={htmlId('painless')}
|
||||
className="vis_editor__input-grows-100"
|
||||
type="text"
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('variables')}>Variables</EuiFormLabel>
|
||||
<Vars
|
||||
id={htmlId('variables')}
|
||||
metrics={siblings}
|
||||
onChange={handleChange}
|
||||
name="variables"
|
||||
model={model}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('painless')}
|
||||
label="Painless Script"
|
||||
fullWidth
|
||||
helpText={
|
||||
<div>
|
||||
Variables are keys on the <EuiCode>params</EuiCode> object, i.e. <EuiCode>params.<name></EuiCode>.
|
||||
To access the bucket interval (in milliseconds) use <EuiCode>params._interval</EuiCode>.
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<EuiTextArea
|
||||
onChange={handleTextChange('script')}
|
||||
value={model.script}
|
||||
fullWidth
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</AggRow>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -24,9 +24,11 @@ import AggSelect from './agg_select';
|
|||
import MetricSelect from './metric_select';
|
||||
import createChangeHandler from '../lib/create_change_handler';
|
||||
import createSelectHandler from '../lib/create_select_handler';
|
||||
import { htmlIdGenerator, EuiFlexGroup, EuiFlexItem, EuiFormLabel, EuiFormRow } from '@elastic/eui';
|
||||
|
||||
function CumulativeSumAgg(props) {
|
||||
const { model, siblings } = props;
|
||||
const htmlId = htmlIdGenerator();
|
||||
const handleChange = createChangeHandler(props.onChange, model);
|
||||
const handleSelectChange = createSelectHandler(handleChange);
|
||||
return (
|
||||
|
@ -37,24 +39,31 @@ function CumulativeSumAgg(props) {
|
|||
onDelete={props.onDelete}
|
||||
siblings={props.siblings}
|
||||
>
|
||||
<div className="vis_editor__row_item">
|
||||
<div className="vis_editor__label">Aggregation</div>
|
||||
<AggSelect
|
||||
panelType={props.panel.type}
|
||||
siblings={props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__row_item">
|
||||
<div className="vis_editor__label">Metric</div>
|
||||
<MetricSelect
|
||||
onChange={handleSelectChange('field')}
|
||||
metrics={siblings}
|
||||
metric={model}
|
||||
value={model.field}
|
||||
/>
|
||||
</div>
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('aggregation')}>Aggregation</EuiFormLabel>
|
||||
<AggSelect
|
||||
id={htmlId('aggregation')}
|
||||
panelType={props.panel.type}
|
||||
siblings={props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('metric')}
|
||||
label="Metric"
|
||||
>
|
||||
<MetricSelect
|
||||
onChange={handleSelectChange('field')}
|
||||
metrics={siblings}
|
||||
metric={model}
|
||||
value={model.field}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</AggRow>
|
||||
);
|
||||
|
||||
|
|
|
@ -25,7 +25,14 @@ import AggRow from './agg_row';
|
|||
import createChangeHandler from '../lib/create_change_handler';
|
||||
import createSelectHandler from '../lib/create_select_handler';
|
||||
import createTextHandler from '../lib/create_text_handler';
|
||||
import { htmlIdGenerator } from '@elastic/eui';
|
||||
import {
|
||||
htmlIdGenerator,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormLabel,
|
||||
EuiFieldText,
|
||||
EuiFormRow,
|
||||
} from '@elastic/eui';
|
||||
|
||||
export const DerivativeAgg = props => {
|
||||
const { siblings } = props;
|
||||
|
@ -47,36 +54,47 @@ export const DerivativeAgg = props => {
|
|||
onDelete={props.onDelete}
|
||||
siblings={props.siblings}
|
||||
>
|
||||
<div className="vis_editor__row_item">
|
||||
<div className="vis_editor__label">Aggregation</div>
|
||||
<AggSelect
|
||||
panelType={props.panel.type}
|
||||
siblings={props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__row_item">
|
||||
<div className="vis_editor__label">Metric</div>
|
||||
<MetricSelect
|
||||
onChange={handleSelectChange('field')}
|
||||
metrics={siblings}
|
||||
metric={model}
|
||||
value={model.field}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('units')}>
|
||||
Units (1s, 1m, etc)
|
||||
</label>
|
||||
<input
|
||||
id={htmlId('units')}
|
||||
className="vis_editor__input"
|
||||
onChange={handleTextChange('unit')}
|
||||
value={model.unit}
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('aggregation')}>Aggregation</EuiFormLabel>
|
||||
<AggSelect
|
||||
id={htmlId('aggregation')}
|
||||
panelType={props.panel.type}
|
||||
siblings={props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('metric')}
|
||||
label="Metric"
|
||||
fullWidth
|
||||
>
|
||||
<MetricSelect
|
||||
onChange={handleSelectChange('field')}
|
||||
metrics={siblings}
|
||||
metric={model}
|
||||
value={model.field}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('units')}
|
||||
label="Units (1s, 1m, etc)"
|
||||
fullWidth
|
||||
>
|
||||
<EuiFieldText
|
||||
onChange={handleTextChange('unit')}
|
||||
value={model.unit}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</AggRow>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -25,12 +25,12 @@ import {
|
|||
import generateByTypeFilter from '../lib/generate_by_type_filter';
|
||||
|
||||
function FieldSelect(props) {
|
||||
const { type, fields, indexPattern, value, onChange, disabled } = props;
|
||||
const { type, fields, indexPattern, value, onChange, disabled, restrict, ...rest } = props;
|
||||
if (type === 'count') {
|
||||
return null;
|
||||
}
|
||||
const options = (fields[indexPattern] || [])
|
||||
.filter(generateByTypeFilter(props.restrict))
|
||||
.filter(generateByTypeFilter(restrict))
|
||||
.map(field => {
|
||||
return { label: field.name, value: field.name };
|
||||
});
|
||||
|
@ -47,7 +47,8 @@ function FieldSelect(props) {
|
|||
options={options}
|
||||
selectedOptions={selectedOptions}
|
||||
onChange={onChange}
|
||||
singleSelection={true}
|
||||
singleSelection={{ asPlainText: true }}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -25,7 +25,15 @@ import AggRow from './agg_row';
|
|||
import createChangeHandler from '../lib/create_change_handler';
|
||||
import createSelectHandler from '../lib/create_select_handler';
|
||||
import createTextHandler from '../lib/create_text_handler';
|
||||
import { htmlIdGenerator } from '@elastic/eui';
|
||||
import {
|
||||
htmlIdGenerator,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormLabel,
|
||||
EuiFieldText,
|
||||
EuiSpacer,
|
||||
EuiFormRow,
|
||||
} from '@elastic/eui';
|
||||
|
||||
export const FilterRatioAgg = props => {
|
||||
const {
|
||||
|
@ -58,59 +66,58 @@ export const FilterRatioAgg = props => {
|
|||
onDelete={props.onDelete}
|
||||
siblings={props.siblings}
|
||||
>
|
||||
<div style={{ flex: '1 0 auto' }}>
|
||||
<div style={{ flex: '1 0 auto', display: 'flex' }}>
|
||||
<div className="vis_editor__row_item">
|
||||
<div className="vis_editor__label">Aggregation</div>
|
||||
<AggSelect
|
||||
panelType={props.panel.type}
|
||||
siblings={props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__row_item">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('numerator')}>
|
||||
Numerator
|
||||
</label>
|
||||
<input
|
||||
id={htmlId('numerator')}
|
||||
className="vis_editor__input-grows-100"
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('aggregation')}>Aggregation</EuiFormLabel>
|
||||
<AggSelect
|
||||
id={htmlId('aggregation')}
|
||||
panelType={props.panel.type}
|
||||
siblings={props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('numerator')} label="Numerator">
|
||||
<EuiFieldText
|
||||
onChange={handleTextChange('numerator')}
|
||||
value={model.numerator}
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__row_item">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('denominator')}>
|
||||
Denominator
|
||||
</label>
|
||||
<input
|
||||
id={htmlId('denominator')}
|
||||
className="vis_editor__input-grows-100"
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('denominator')} label="Denominator">
|
||||
<EuiFieldText
|
||||
onChange={handleTextChange('denominator')}
|
||||
value={model.denominator}
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ flex: '1 0 auto', display: 'flex', marginTop: '10px' }}>
|
||||
<div className="vis_editor__row_item">
|
||||
<div className="vis_editor__label">Metric Aggregation</div>
|
||||
<AggSelect
|
||||
siblings={props.siblings}
|
||||
panelType="metrics"
|
||||
value={model.metric_agg}
|
||||
onChange={handleSelectChange('metric_agg')}
|
||||
/>
|
||||
</div>
|
||||
{ model.metric_agg !== 'count' ? (
|
||||
<div className="vis_editor__row_item">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('aggField')}>
|
||||
Field
|
||||
</label>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
|
||||
</EuiFlexGroup>
|
||||
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('metric')}>Metric Aggregation</EuiFormLabel>
|
||||
<AggSelect
|
||||
id={htmlId('metric')}
|
||||
siblings={props.siblings}
|
||||
panelType="metrics"
|
||||
value={model.metric_agg}
|
||||
onChange={handleSelectChange('metric_agg')}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
{ model.metric_agg !== 'count' ? (
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('aggField')} label="Field">
|
||||
<FieldSelect
|
||||
id={htmlId('aggField')}
|
||||
fields={fields}
|
||||
type={model.metric_agg}
|
||||
restrict={restrictMode}
|
||||
|
@ -118,9 +125,10 @@ export const FilterRatioAgg = props => {
|
|||
value={model.field}
|
||||
onChange={handleSelectChange('field')}
|
||||
/>
|
||||
</div>) : null }
|
||||
</div>
|
||||
</div>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>) : null }
|
||||
|
||||
</EuiFlexGroup>
|
||||
</AggRow>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -28,6 +28,16 @@ import createChangeHandler from '../lib/create_change_handler';
|
|||
import createSelectHandler from '../lib/create_select_handler';
|
||||
import createTextHandler from '../lib/create_text_handler';
|
||||
import Vars from './vars';
|
||||
import {
|
||||
htmlIdGenerator,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormLabel,
|
||||
EuiTextArea,
|
||||
EuiLink,
|
||||
EuiFormRow,
|
||||
EuiCode,
|
||||
} from '@elastic/eui';
|
||||
|
||||
class MathAgg extends Component {
|
||||
componentWillMount() {
|
||||
|
@ -42,6 +52,7 @@ class MathAgg extends Component {
|
|||
|
||||
render() {
|
||||
const { siblings } = this.props;
|
||||
const htmlId = htmlIdGenerator();
|
||||
|
||||
const defaults = { script: '' };
|
||||
const model = { ...defaults, ...this.props.model };
|
||||
|
@ -58,60 +69,63 @@ class MathAgg extends Component {
|
|||
onDelete={this.props.onDelete}
|
||||
siblings={this.props.siblings}
|
||||
>
|
||||
<div className="vis_editor__row_item">
|
||||
<div>
|
||||
<div className="vis_editor__label">Aggregation</div>
|
||||
<EuiFlexGroup direction="column" gutterSize="l">
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('aggregation')}>Aggregation</EuiFormLabel>
|
||||
<AggSelect
|
||||
id={htmlId('aggregation')}
|
||||
siblings={this.props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
/>
|
||||
<div className="vis_editor__variables">
|
||||
<div className="vis_editor__label">Variables</div>
|
||||
<Vars
|
||||
metrics={siblings}
|
||||
onChange={handleChange}
|
||||
name="variables"
|
||||
model={model}
|
||||
includeSiblings={true}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__row_item">
|
||||
<label
|
||||
className="vis_editor__label"
|
||||
htmlFor="mathExpressionInput"
|
||||
>
|
||||
Expression
|
||||
</label>
|
||||
<textarea
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('variables')}>Variables</EuiFormLabel>
|
||||
<Vars
|
||||
id={htmlId('variables')}
|
||||
metrics={siblings}
|
||||
onChange={handleChange}
|
||||
name="variables"
|
||||
model={model}
|
||||
includeSiblings={true}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id="mathExpressionInput"
|
||||
label="Expression"
|
||||
fullWidth
|
||||
helpText={
|
||||
<div>
|
||||
This field uses basic math expressions (see{' '}
|
||||
<EuiLink
|
||||
href="https://github.com/elastic/tinymath/blob/master/docs/functions.md"
|
||||
target="_blank"
|
||||
>
|
||||
TinyMath
|
||||
</EuiLink>) - Variables are keys on the <EuiCode>params</EuiCode> object,
|
||||
i.e. <EuiCode>params.<name></EuiCode> To access all the data use
|
||||
<EuiCode>params._all.<name>.values</EuiCode> for an array of the
|
||||
values and <EuiCode>params._all.<name>.timestamps</EuiCode>
|
||||
for an array of the timestamps. <EuiCode>params._timestamp</EuiCode>
|
||||
is available for the current bucket's timestamp,
|
||||
<EuiCode>params._index</EuiCode> is available for the current
|
||||
bucket's index, and <EuiCode>params._interval</EuiCode>s
|
||||
available for the interval in milliseconds.
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<EuiTextArea
|
||||
data-test-subj="mathExpression"
|
||||
id="mathExpressionInput"
|
||||
aria-describedby="mathExpressionDescription"
|
||||
className="vis_editor__input-grows-100"
|
||||
onChange={handleTextChange('script')}
|
||||
>
|
||||
{model.script}
|
||||
</textarea>
|
||||
<div className="vis_editor__note" id="mathExpressionDescription">
|
||||
This field uses basic math expressions (see{' '}
|
||||
<a
|
||||
href="https://github.com/elastic/tinymath/blob/master/docs/functions.md"
|
||||
target="_blank"
|
||||
>
|
||||
TinyMath
|
||||
</a>) - Variables are keys on the <code>params</code> object,
|
||||
i.e. <code>params.<name></code> To access all the data use
|
||||
<code>params._all.<name>.values</code> for an array of the
|
||||
values and <code>params._all.<name>.timestamps</code>
|
||||
for an array of the timestamps. <code>params._timestamp</code>
|
||||
is available for the current bucket's timestamp,
|
||||
<code>params._index</code> is available for the current
|
||||
bucket's index, and <code>params._interval</code>s
|
||||
available for the interval in milliseconds.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
fullWidth
|
||||
value={model.script}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</AggRow>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -59,11 +59,11 @@ export function filterRows(includeSiblings) {
|
|||
}
|
||||
|
||||
function MetricSelect(props) {
|
||||
const { restrict, metric, onChange, value, exclude, includeSiblings } = props;
|
||||
const { additionalOptions, restrict, metric, metrics, onChange, value, exclude, includeSiblings, clearable, ...rest } = props;
|
||||
|
||||
const metrics = props.metrics.filter(createTypeFilter(restrict, exclude));
|
||||
const calculatedMetrics = metrics.filter(createTypeFilter(restrict, exclude));
|
||||
|
||||
const siblings = calculateSiblings(metrics, metric);
|
||||
const siblings = calculateSiblings(calculatedMetrics, metric);
|
||||
|
||||
// Percentiles need to be handled differently because one percentile aggregation
|
||||
// could have multiple percentiles associated with it. So the user needs a way
|
||||
|
@ -71,7 +71,7 @@ function MetricSelect(props) {
|
|||
const percentileOptions = siblings
|
||||
.filter(row => /^percentile/.test(row.type))
|
||||
.reduce((acc, row) => {
|
||||
const label = calculateLabel(row, metrics);
|
||||
const label = calculateLabel(row, calculatedMetrics);
|
||||
row.percentiles.forEach(p => {
|
||||
if (p.value) {
|
||||
const value = /\./.test(p.value) ? p.value : `${p.value}.0`;
|
||||
|
@ -85,10 +85,10 @@ function MetricSelect(props) {
|
|||
}, []);
|
||||
|
||||
const options = siblings.filter(filterRows(includeSiblings)).map(row => {
|
||||
const label = calculateLabel(row, metrics);
|
||||
const label = calculateLabel(row, calculatedMetrics);
|
||||
return { value: row.id, label };
|
||||
});
|
||||
const allOptions = [...options, ...props.additionalOptions, ...percentileOptions];
|
||||
const allOptions = [...options, ...additionalOptions, ...percentileOptions];
|
||||
|
||||
const selectedOption = allOptions.find(option => {
|
||||
return value === option.value;
|
||||
|
@ -101,7 +101,9 @@ function MetricSelect(props) {
|
|||
options={allOptions}
|
||||
selectedOptions={selectedOptions}
|
||||
onChange={onChange}
|
||||
singleSelection={true}
|
||||
singleSelection={{ asPlainText: true }}
|
||||
isClearable={clearable}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -28,7 +28,14 @@ import createTextHandler from '../lib/create_text_handler';
|
|||
import createNumberHandler from '../lib/create_number_handler';
|
||||
import {
|
||||
htmlIdGenerator,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormLabel,
|
||||
EuiComboBox,
|
||||
EuiSpacer,
|
||||
EuiFormRow,
|
||||
EuiCode,
|
||||
EuiTextArea,
|
||||
} from '@elastic/eui';
|
||||
|
||||
export const MovingAverageAgg = props => {
|
||||
|
@ -71,91 +78,109 @@ export const MovingAverageAgg = props => {
|
|||
onDelete={props.onDelete}
|
||||
siblings={props.siblings}
|
||||
>
|
||||
<div className="vis_editor__row_item">
|
||||
<div className="vis_editor__agg_row-item">
|
||||
<div className="vis_editor__row_item">
|
||||
<div className="vis_editor__label">Aggregation</div>
|
||||
<AggSelect
|
||||
panelType={props.panel.type}
|
||||
siblings={props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__row_item">
|
||||
<div className="vis_editor__label">Metric</div>
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('aggregation')}>Aggregation</EuiFormLabel>
|
||||
<AggSelect
|
||||
id={htmlId('aggregation')}
|
||||
panelType={props.panel.type}
|
||||
siblings={props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('metric')}
|
||||
label="Metric"
|
||||
>
|
||||
<MetricSelect
|
||||
onChange={handleSelectChange('field')}
|
||||
metrics={siblings}
|
||||
metric={model}
|
||||
value={model.field}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="vis_editor__agg_row-item">
|
||||
<div className="vis_editor__row_item">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('model')}>Model</label>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('model')}
|
||||
label="Model"
|
||||
>
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
id={htmlId('model')}
|
||||
placeholder="Select..."
|
||||
placeholder="Select"
|
||||
options={modelOptions}
|
||||
selectedOptions={selectedModelOption ? [selectedModelOption] : []}
|
||||
onChange={handleSelectChange('model')}
|
||||
singleSelection={true}
|
||||
singleSelection={{ asPlainText: true }}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__row_item">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('windowSize')}>
|
||||
Window Size
|
||||
</label>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('windowSize')} label="Window size">
|
||||
{/*
|
||||
EUITODO: The following input couldn't be converted to EUI because of type mis-match.
|
||||
Should it be text or number?
|
||||
*/}
|
||||
<input
|
||||
id={htmlId('windowSize')}
|
||||
className="vis_editor__input-grows-100"
|
||||
className="tvbAgg__input"
|
||||
type="text"
|
||||
onChange={handleNumberChange('window')}
|
||||
value={model.window}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__row_item">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('minimize')}>Minimize</label>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('minimize')} label="Minimize">
|
||||
<EuiComboBox
|
||||
id={htmlId('minimize')}
|
||||
placeholder="Select..."
|
||||
placeholder="Select"
|
||||
options={minimizeOptions}
|
||||
selectedOptions={selectedMinimizeOption ? [selectedMinimizeOption] : []}
|
||||
onChange={handleSelectChange('minimize')}
|
||||
singleSelection={true}
|
||||
singleSelection={{ asPlainText: true }}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__row_item">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('windowSize')}>
|
||||
Predict
|
||||
</label>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('predict')} label="Predict">
|
||||
{/*
|
||||
EUITODO: The following input couldn't be converted to EUI because of type mis-match.
|
||||
Should it be text or number?
|
||||
*/}
|
||||
<input
|
||||
id={htmlId('predict')}
|
||||
className="vis_editor__input-grows-100"
|
||||
className="tvbAgg__input"
|
||||
type="text"
|
||||
onChange={handleNumberChange('predict')}
|
||||
value={model.predict}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="vis_editor__agg_row-item">
|
||||
<div className="vis_editor__row_item">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('settings')}>
|
||||
Settings (<code>Key=Value</code> space-delimited)
|
||||
</label>
|
||||
<input
|
||||
id={htmlId('settings')}
|
||||
className="vis_editor__input-grows-100"
|
||||
type="text"
|
||||
onChange={handleTextChange('settings')}
|
||||
value={model.settings}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
fullWidth
|
||||
id={htmlId('settings')}
|
||||
label="Settings"
|
||||
helpText={
|
||||
<span><EuiCode>Key=Value</EuiCode> space-delimited</span>
|
||||
}
|
||||
>
|
||||
<EuiTextArea
|
||||
onChange={handleTextChange('settings')}
|
||||
value={model.settings}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</AggRow>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -30,8 +30,15 @@ import createChangeHandler from '../lib/create_change_handler';
|
|||
import createSelectHandler from '../lib/create_select_handler';
|
||||
import {
|
||||
htmlIdGenerator,
|
||||
EuiSpacer,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormLabel,
|
||||
EuiComboBox,
|
||||
EuiFieldNumber,
|
||||
EuiFormRow,
|
||||
} from '@elastic/eui';
|
||||
|
||||
const newPercentile = (opts) => {
|
||||
return _.assign({ id: uuid.v1(), mode: 'line', shade: 0.2 }, opts);
|
||||
};
|
||||
|
@ -65,64 +72,74 @@ class Percentiles extends Component {
|
|||
if (model.mode === 'line') {
|
||||
optionsStyle.display = 'none';
|
||||
}
|
||||
const labelStyle = { marginBottom: 0 };
|
||||
const htmlId = htmlIdGenerator(model.id);
|
||||
const selectedModeOption = modeOptions.find(option => {
|
||||
return model.mode === option.value;
|
||||
});
|
||||
return (
|
||||
<div className="vis_editor__percentiles-row" key={model.id}>
|
||||
<div className="vis_editor__percentiles-content">
|
||||
<input
|
||||
aria-label="Percentile"
|
||||
placeholder="Percentile"
|
||||
className="vis_editor__input-grows"
|
||||
type="number"
|
||||
step="1"
|
||||
onChange={this.handleTextChange(model, 'value')}
|
||||
value={model.value}
|
||||
/>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('mode')}>Mode</label>
|
||||
<div className="vis_editor__row_item">
|
||||
<EuiFlexItem key={model.id}>
|
||||
<EuiFlexGroup alignItems="center" responsive={false} gutterSize="s">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFieldNumber
|
||||
aria-label="Percentile"
|
||||
placeholder="Percentile"
|
||||
step={1}
|
||||
onChange={this.handleTextChange(model, 'value')}
|
||||
value={Number(model.value)}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel style={labelStyle} htmlFor={htmlId('mode')}>Mode:</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
id={htmlId('mode')}
|
||||
options={modeOptions}
|
||||
selectedOptions={selectedModeOption ? [selectedModeOption] : []}
|
||||
onChange={this.handleTextChange(model, 'mode')}
|
||||
singleSelection={true}
|
||||
singleSelection={{ asPlainText: true }}
|
||||
/>
|
||||
</div>
|
||||
<label style={optionsStyle} className="vis_editor__label" htmlFor={htmlId('fillTo')}>
|
||||
Fill To
|
||||
</label>
|
||||
<input
|
||||
id={htmlId('fillTo')}
|
||||
style={optionsStyle}
|
||||
className="vis_editor__input-grows"
|
||||
type="number"
|
||||
step="1"
|
||||
onChange={this.handleTextChange(model, 'percentile')}
|
||||
value={model.percentile}
|
||||
/>
|
||||
<label style={optionsStyle} className="vis_editor__label" htmlFor={htmlId('shade')}>
|
||||
Shade (0 to 1)
|
||||
</label>
|
||||
<input
|
||||
id={htmlId('shade')}
|
||||
style={optionsStyle}
|
||||
className="vis_editor__input-grows"
|
||||
type="number"
|
||||
step="0.1"
|
||||
onChange={this.handleTextChange(model, 'shade')}
|
||||
value={model.shade}
|
||||
/>
|
||||
</div>
|
||||
<AddDeleteButtons
|
||||
onAdd={handleAdd}
|
||||
onDelete={handleDelete}
|
||||
disableDelete={items.length < 2}
|
||||
/>
|
||||
</div>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem style={optionsStyle} grow={false}>
|
||||
<EuiFormLabel style={labelStyle} htmlFor={htmlId('fillTo')}>Fill to:</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem style={optionsStyle} grow={false}>
|
||||
<EuiFieldNumber
|
||||
id={htmlId('fillTo')}
|
||||
step={1}
|
||||
onChange={this.handleTextChange(model, 'percentile')}
|
||||
value={Number(model.percentile)}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem style={optionsStyle} grow={false}>
|
||||
<EuiFormLabel style={labelStyle} htmlFor={htmlId('shade')}>Shade (0 to 1):</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem style={optionsStyle} grow={false}>
|
||||
<EuiFieldNumber
|
||||
id={htmlId('shade')}
|
||||
style={optionsStyle}
|
||||
step={0.1}
|
||||
onChange={this.handleTextChange(model, 'shade')}
|
||||
value={Number(model.shade)}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem>
|
||||
<AddDeleteButtons
|
||||
onAdd={handleAdd}
|
||||
onDelete={handleDelete}
|
||||
disableDelete={items.length < 2}
|
||||
responsive={false}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -132,9 +149,9 @@ class Percentiles extends Component {
|
|||
|
||||
const rows = model[name].map(this.renderRow);
|
||||
return (
|
||||
<div className="vis_editor__percentiles">
|
||||
<EuiFlexGroup direction="column" gutterSize="s">
|
||||
{ rows }
|
||||
</div>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -166,6 +183,7 @@ class PercentileAgg extends Component { // eslint-disable-line react/no-multi-co
|
|||
const handleChange = createChangeHandler(this.props.onChange, model);
|
||||
const handleSelectChange = createSelectHandler(handleChange);
|
||||
const indexPattern = series.override_index_pattern && series.series_index_pattern || panel.index_pattern;
|
||||
const htmlId = htmlIdGenerator();
|
||||
|
||||
return (
|
||||
<AggRow
|
||||
|
@ -175,19 +193,19 @@ class PercentileAgg extends Component { // eslint-disable-line react/no-multi-co
|
|||
onDelete={this.props.onDelete}
|
||||
siblings={this.props.siblings}
|
||||
>
|
||||
<div className="vis_editor__row_item">
|
||||
<div className="vis_editor__agg_row-item">
|
||||
<div className="vis_editor__row_item">
|
||||
<div className="vis_editor__label">Aggregation</div>
|
||||
<AggSelect
|
||||
panelType={this.props.panel.type}
|
||||
siblings={this.props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__row_item">
|
||||
<div className="vis_editor__label">Field</div>
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('aggregation')}>Aggregation</EuiFormLabel>
|
||||
<AggSelect
|
||||
id={htmlId('aggregation')}
|
||||
panelType={this.props.panel.type}
|
||||
siblings={this.props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('field')} label="Field">
|
||||
<FieldSelect
|
||||
fields={fields}
|
||||
type={model.type}
|
||||
|
@ -196,14 +214,18 @@ class PercentileAgg extends Component { // eslint-disable-line react/no-multi-co
|
|||
value={model.field}
|
||||
onChange={handleSelectChange('field')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Percentiles
|
||||
onChange={handleChange}
|
||||
name="percentiles"
|
||||
model={model}
|
||||
/>
|
||||
</div>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
<Percentiles
|
||||
onChange={handleChange}
|
||||
name="percentiles"
|
||||
model={model}
|
||||
/>
|
||||
|
||||
</AggRow>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -25,7 +25,14 @@ import AggRow from './agg_row';
|
|||
import createChangeHandler from '../lib/create_change_handler';
|
||||
import createSelectHandler from '../lib/create_select_handler';
|
||||
import createTextHandler from '../lib/create_text_handler';
|
||||
import { htmlIdGenerator } from '@elastic/eui';
|
||||
import {
|
||||
htmlIdGenerator,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormLabel,
|
||||
EuiFieldText,
|
||||
EuiFormRow,
|
||||
} from '@elastic/eui';
|
||||
|
||||
export const PercentileRankAgg = props => {
|
||||
const { series, panel, fields } = props;
|
||||
|
@ -47,36 +54,38 @@ export const PercentileRankAgg = props => {
|
|||
onDelete={props.onDelete}
|
||||
siblings={props.siblings}
|
||||
>
|
||||
<div className="vis_editor__row_item">
|
||||
<div className="vis_editor__label">Aggregation</div>
|
||||
<AggSelect
|
||||
panelType={props.panel.type}
|
||||
siblings={props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__row_item">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('field')}>Field</label>
|
||||
<FieldSelect
|
||||
id={htmlId('field')}
|
||||
fields={fields}
|
||||
type={model.type}
|
||||
restrict="numeric"
|
||||
indexPattern={indexPattern}
|
||||
value={model.field}
|
||||
onChange={handleSelectChange('field')}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__percentile_rank_value">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('value')}>Value</label>
|
||||
<input
|
||||
id={htmlId('value')}
|
||||
className="vis_editor__input-grows"
|
||||
value={model.value}
|
||||
onChange={handleTextChange('value')}
|
||||
/>
|
||||
</div>
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('aggregation')}>Aggregation</EuiFormLabel>
|
||||
<AggSelect
|
||||
id={htmlId('aggregation')}
|
||||
panelType={props.panel.type}
|
||||
siblings={props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('field')} label="Field">
|
||||
<FieldSelect
|
||||
fields={fields}
|
||||
type={model.type}
|
||||
restrict="numeric"
|
||||
indexPattern={indexPattern}
|
||||
value={model.field}
|
||||
onChange={handleSelectChange('field')}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('value')} label="Value">
|
||||
<EuiFieldText
|
||||
value={model.value}
|
||||
onChange={handleTextChange('value')}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</AggRow>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -24,6 +24,7 @@ import MetricSelect from './metric_select';
|
|||
import AggRow from './agg_row';
|
||||
import createChangeHandler from '../lib/create_change_handler';
|
||||
import createSelectHandler from '../lib/create_select_handler';
|
||||
import { htmlIdGenerator, EuiFlexGroup, EuiFlexItem, EuiFormLabel, EuiFormRow } from '@elastic/eui';
|
||||
|
||||
export const PositiveOnlyAgg = props => {
|
||||
const { siblings } = props;
|
||||
|
@ -31,6 +32,7 @@ export const PositiveOnlyAgg = props => {
|
|||
const defaults = { unit: '' };
|
||||
const model = { ...defaults, ...props.model };
|
||||
|
||||
const htmlId = htmlIdGenerator();
|
||||
const handleChange = createChangeHandler(props.onChange, model);
|
||||
const handleSelectChange = createSelectHandler(handleChange);
|
||||
|
||||
|
@ -42,24 +44,31 @@ export const PositiveOnlyAgg = props => {
|
|||
onDelete={props.onDelete}
|
||||
siblings={props.siblings}
|
||||
>
|
||||
<div className="vis_editor__row_item">
|
||||
<div className="vis_editor__label">Aggregation</div>
|
||||
<AggSelect
|
||||
panelType={props.panel.type}
|
||||
siblings={props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__row_item">
|
||||
<div className="vis_editor__label">Metric</div>
|
||||
<MetricSelect
|
||||
onChange={handleSelectChange('field')}
|
||||
metrics={siblings}
|
||||
metric={model}
|
||||
value={model.field}
|
||||
/>
|
||||
</div>
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('aggregation')}>Aggregation</EuiFormLabel>
|
||||
<AggSelect
|
||||
id={htmlId('aggregation')}
|
||||
panelType={props.panel.type}
|
||||
siblings={props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('metric')}
|
||||
label="Metric"
|
||||
>
|
||||
<MetricSelect
|
||||
onChange={handleSelectChange('field')}
|
||||
metrics={siblings}
|
||||
metric={model}
|
||||
value={model.field}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</AggRow>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -25,7 +25,7 @@ import AggRow from './agg_row';
|
|||
import createChangeHandler from '../lib/create_change_handler';
|
||||
import createSelectHandler from '../lib/create_select_handler';
|
||||
import createNumberHandler from '../lib/create_number_handler';
|
||||
import { htmlIdGenerator } from '@elastic/eui';
|
||||
import { htmlIdGenerator, EuiFlexGroup, EuiFlexItem, EuiFormLabel, EuiFormRow } from '@elastic/eui';
|
||||
|
||||
export const SerialDiffAgg = props => {
|
||||
const { siblings } = props;
|
||||
|
@ -46,34 +46,45 @@ export const SerialDiffAgg = props => {
|
|||
onDelete={props.onDelete}
|
||||
siblings={props.siblings}
|
||||
>
|
||||
<div className="vis_editor__row_item">
|
||||
<div className="vis_editor__label">Aggregation</div>
|
||||
<AggSelect
|
||||
panelType={props.panel.type}
|
||||
siblings={props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__row_item">
|
||||
<div className="vis_editor__label">Metric</div>
|
||||
<MetricSelect
|
||||
onChange={handleSelectChange('field')}
|
||||
metrics={siblings}
|
||||
metric={model}
|
||||
value={model.field}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('lag')}>Lag</label>
|
||||
<input
|
||||
id={htmlId('lag')}
|
||||
className="vis_editor__input"
|
||||
onChange={handleNumberChange('lag')}
|
||||
value={model.lag}
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('aggregation')}>Aggregation</EuiFormLabel>
|
||||
<AggSelect
|
||||
id={htmlId('aggregation')}
|
||||
panelType={props.panel.type}
|
||||
siblings={props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('metric')}
|
||||
label="Metric"
|
||||
>
|
||||
<MetricSelect
|
||||
onChange={handleSelectChange('field')}
|
||||
metrics={siblings}
|
||||
metric={model}
|
||||
value={model.field}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('lag')} label="Lag">
|
||||
{/*
|
||||
EUITODO: The following input couldn't be converted to EUI because of type mis-match.
|
||||
Should it be text or number?
|
||||
*/}
|
||||
<input
|
||||
className="tvbAgg__input"
|
||||
onChange={handleNumberChange('lag')}
|
||||
value={model.lag}
|
||||
type="text"
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</AggRow>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -25,7 +25,12 @@ import createChangeHandler from '../lib/create_change_handler';
|
|||
import createSelectHandler from '../lib/create_select_handler';
|
||||
import {
|
||||
htmlIdGenerator,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormLabel,
|
||||
EuiComboBox,
|
||||
EuiTitle,
|
||||
EuiFormRow,
|
||||
} from '@elastic/eui';
|
||||
|
||||
function SeriesAgg(props) {
|
||||
|
@ -60,11 +65,9 @@ function SeriesAgg(props) {
|
|||
onDelete={props.onDelete}
|
||||
siblings={props.siblings}
|
||||
>
|
||||
<div className="vis_editor__item">
|
||||
<div className="vis_editor__label">
|
||||
Series Agg is not compatible with the table visualization.
|
||||
</div>
|
||||
</div>
|
||||
<EuiTitle className="tvbAggRow__unavailable" size="xxxs">
|
||||
<span>Series Agg is not compatible with the table visualization.</span>
|
||||
</EuiTitle>
|
||||
</AggRow>
|
||||
);
|
||||
}
|
||||
|
@ -77,25 +80,28 @@ function SeriesAgg(props) {
|
|||
onDelete={props.onDelete}
|
||||
siblings={props.siblings}
|
||||
>
|
||||
<div className="vis_editor__item">
|
||||
<div className="vis_editor__label">Aggregation</div>
|
||||
<AggSelect
|
||||
panelType={panel.type}
|
||||
siblings={props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__item">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('function')}>Function</label>
|
||||
<EuiComboBox
|
||||
id={htmlId('function')}
|
||||
options={functionOptions}
|
||||
selectedOptions={selectedFunctionOption ? [selectedFunctionOption] : []}
|
||||
onChange={handleSelectChange('function')}
|
||||
singleSelection={true}
|
||||
/>
|
||||
</div>
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('aggregation')}>Aggregation</EuiFormLabel>
|
||||
<AggSelect
|
||||
id={htmlId('aggregation')}
|
||||
panelType={panel.type}
|
||||
siblings={props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('function')} label="Function">
|
||||
<EuiComboBox
|
||||
options={functionOptions}
|
||||
selectedOptions={selectedFunctionOption ? [selectedFunctionOption] : []}
|
||||
onChange={handleSelectChange('function')}
|
||||
singleSelection={{ asPlainText: true }}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</AggRow>
|
||||
);
|
||||
|
||||
|
|
|
@ -24,7 +24,14 @@ import AggRow from './agg_row';
|
|||
import createChangeHandler from '../lib/create_change_handler';
|
||||
import createSelectHandler from '../lib/create_select_handler';
|
||||
import createTextHandler from '../lib/create_text_handler';
|
||||
import { htmlIdGenerator } from '@elastic/eui';
|
||||
import {
|
||||
htmlIdGenerator,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormLabel,
|
||||
EuiFieldNumber,
|
||||
EuiFormRow,
|
||||
} from '@elastic/eui';
|
||||
|
||||
export const Static = props => {
|
||||
const handleChange = createChangeHandler(props.onChange, props.model);
|
||||
|
@ -48,32 +55,27 @@ export const Static = props => {
|
|||
onDelete={props.onDelete}
|
||||
siblings={props.siblings}
|
||||
>
|
||||
<div style={{ flex: '1 0 auto' }}>
|
||||
<div style={{ flex: '1 0 auto', display: 'flex' }}>
|
||||
<div className="vis_editor__row_item">
|
||||
<div className="vis_editor__label">Aggregation</div>
|
||||
<AggSelect
|
||||
panelType={props.panel.type}
|
||||
siblings={props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__row_item">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('staticValue')}>
|
||||
Static Value
|
||||
</label>
|
||||
<input
|
||||
id={htmlId('staticValue')}
|
||||
className="vis_editor__input-grows-100"
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('aggregation')}>Aggregation</EuiFormLabel>
|
||||
<AggSelect
|
||||
id={htmlId('aggregation')}
|
||||
panelType={props.panel.type}
|
||||
siblings={props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('staticValue')} label="Static value">
|
||||
<EuiFieldNumber
|
||||
onChange={handleTextChange('value')}
|
||||
value={model.value}
|
||||
step="0.1"
|
||||
type="number"
|
||||
value={Number(model.value)}
|
||||
step={0.1}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</AggRow>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -24,7 +24,7 @@ import FieldSelect from './field_select';
|
|||
import AggRow from './agg_row';
|
||||
import createChangeHandler from '../lib/create_change_handler';
|
||||
import createSelectHandler from '../lib/create_select_handler';
|
||||
import { htmlIdGenerator } from '@elastic/eui';
|
||||
import { htmlIdGenerator, EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiFormLabel } from '@elastic/eui';
|
||||
|
||||
function StandardAgg(props) {
|
||||
const { model, panel, series, fields } = props;
|
||||
|
@ -47,32 +47,39 @@ function StandardAgg(props) {
|
|||
onDelete={props.onDelete}
|
||||
siblings={props.siblings}
|
||||
>
|
||||
<div className="vis_editor__item">
|
||||
<div className="vis_editor__label">Aggregation</div>
|
||||
<AggSelect
|
||||
panelType={props.panel.type}
|
||||
siblings={props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
/>
|
||||
</div>
|
||||
{
|
||||
model.type !== 'count'
|
||||
? (
|
||||
<div className="vis_editor__item">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('field')}>Field</label>
|
||||
<FieldSelect
|
||||
id={htmlId('field')}
|
||||
fields={fields}
|
||||
type={model.type}
|
||||
restrict={restrict}
|
||||
indexPattern={indexPattern}
|
||||
value={model.field}
|
||||
onChange={handleSelectChange('field')}
|
||||
/>
|
||||
</div>
|
||||
) : null
|
||||
}
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('aggregation')}>Aggregation</EuiFormLabel>
|
||||
<AggSelect
|
||||
id={htmlId('aggregation')}
|
||||
panelType={props.panel.type}
|
||||
siblings={props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
{
|
||||
model.type !== 'count'
|
||||
? (
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('field')} label="Field" fullWidth>
|
||||
<FieldSelect
|
||||
fields={fields}
|
||||
type={model.type}
|
||||
restrict={restrict}
|
||||
indexPattern={indexPattern}
|
||||
value={model.field}
|
||||
onChange={handleSelectChange('field')}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
) : null
|
||||
}
|
||||
|
||||
</EuiFlexGroup>
|
||||
</AggRow>
|
||||
);
|
||||
|
||||
|
|
|
@ -27,7 +27,12 @@ import createSelectHandler from '../lib/create_select_handler';
|
|||
import createTextHandler from '../lib/create_text_handler';
|
||||
import {
|
||||
htmlIdGenerator,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormLabel,
|
||||
EuiComboBox,
|
||||
EuiFieldText,
|
||||
EuiFormRow,
|
||||
} from '@elastic/eui';
|
||||
|
||||
export const StandardDeviationAgg = props => {
|
||||
|
@ -63,46 +68,48 @@ export const StandardDeviationAgg = props => {
|
|||
onDelete={props.onDelete}
|
||||
siblings={props.siblings}
|
||||
>
|
||||
<div className="vis_editor__row_item">
|
||||
<div className="vis_editor__label">Aggregation</div>
|
||||
<AggSelect
|
||||
panelType={props.panel.type}
|
||||
siblings={props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__std_deviation-field">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('field')}>Field</label>
|
||||
<FieldSelect
|
||||
id={htmlId('field')}
|
||||
fields={fields}
|
||||
type={model.type}
|
||||
restrict="numeric"
|
||||
indexPattern={indexPattern}
|
||||
value={model.field}
|
||||
onChange={handleSelectChange('field')}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__std_deviation-sigma_item">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('sigma')}>Sigma</label>
|
||||
<input
|
||||
id={htmlId('sigma')}
|
||||
className="vis_editor__std_deviation-sigma"
|
||||
value={model.sigma}
|
||||
onChange={handleTextChange('sigma')}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__row_item">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('mode')}>Mode</label>
|
||||
<EuiComboBox
|
||||
id={htmlId('mode')}
|
||||
options={modeOptions}
|
||||
selectedOptions={selectedModeOption ? [selectedModeOption] : []}
|
||||
onChange={handleSelectChange('mode')}
|
||||
singleSelection={true}
|
||||
/>
|
||||
</div>
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('aggregation')}>Aggregation</EuiFormLabel>
|
||||
<AggSelect
|
||||
id={htmlId('aggregation')}
|
||||
panelType={props.panel.type}
|
||||
siblings={props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('field')} label="Field">
|
||||
<FieldSelect
|
||||
fields={fields}
|
||||
type={model.type}
|
||||
restrict="numeric"
|
||||
indexPattern={indexPattern}
|
||||
value={model.field}
|
||||
onChange={handleSelectChange('field')}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow id={htmlId('sigma')} label="Sigma">
|
||||
<EuiFieldText
|
||||
value={model.sigma}
|
||||
onChange={handleTextChange('sigma')}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('mode')} label="Mode">
|
||||
<EuiComboBox
|
||||
options={modeOptions}
|
||||
selectedOptions={selectedModeOption ? [selectedModeOption] : []}
|
||||
onChange={handleSelectChange('mode')}
|
||||
singleSelection={{ asPlainText: true }}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</AggRow>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -27,7 +27,12 @@ import createSelectHandler from '../lib/create_select_handler';
|
|||
import createTextHandler from '../lib/create_text_handler';
|
||||
import {
|
||||
htmlIdGenerator,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFieldText,
|
||||
EuiComboBox,
|
||||
EuiFormLabel,
|
||||
EuiFormRow,
|
||||
} from '@elastic/eui';
|
||||
|
||||
export const StandardSiblingAgg = props => {
|
||||
|
@ -43,15 +48,14 @@ export const StandardSiblingAgg = props => {
|
|||
const stdDev = {};
|
||||
if (model.type === 'std_deviation_bucket') {
|
||||
stdDev.sigma = (
|
||||
<div className="vis_editor__std_deviation-sigma_item">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('sigma')}>Sigma</label>
|
||||
<input
|
||||
id={htmlId('sigma')}
|
||||
className="vis_editor__std_deviation-sigma"
|
||||
value={model.sigma}
|
||||
onChange={handleTextChange('sigma')}
|
||||
/>
|
||||
</div>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow id={htmlId('sigma')} label="Sigma">
|
||||
<EuiFieldText
|
||||
value={model.sigma}
|
||||
onChange={handleTextChange('sigma')}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
);
|
||||
|
||||
const modeOptions = [
|
||||
|
@ -65,16 +69,16 @@ export const StandardSiblingAgg = props => {
|
|||
});
|
||||
|
||||
stdDev.mode = (
|
||||
<div className="vis_editor__row_item">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('mode')}>Mode</label>
|
||||
<EuiComboBox
|
||||
id={htmlId('mode')}
|
||||
options={modeOptions}
|
||||
selectedOptions={selectedModeOption ? [selectedModeOption] : []}
|
||||
onChange={handleSelectChange('mode')}
|
||||
singleSelection={true}
|
||||
/>
|
||||
</div>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('mode')} label="Mode">
|
||||
<EuiComboBox
|
||||
options={modeOptions}
|
||||
selectedOptions={selectedModeOption ? [selectedModeOption] : []}
|
||||
onChange={handleSelectChange('mode')}
|
||||
singleSelection={{ asPlainText: true }}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -86,27 +90,34 @@ export const StandardSiblingAgg = props => {
|
|||
onDelete={props.onDelete}
|
||||
siblings={props.siblings}
|
||||
>
|
||||
<div className="vis_editor__row_item">
|
||||
<div className="vis_editor__label">Aggregation</div>
|
||||
<AggSelect
|
||||
panelType={props.panel.type}
|
||||
siblings={props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__std_sibling-metric">
|
||||
<div className="vis_editor__label">Metric</div>
|
||||
<MetricSelect
|
||||
onChange={handleSelectChange('field')}
|
||||
exclude={['percentile']}
|
||||
metrics={siblings}
|
||||
metric={model}
|
||||
value={model.field}
|
||||
/>
|
||||
</div>
|
||||
{ stdDev.sigma }
|
||||
{ stdDev.mode }
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('aggregation')}>Aggregation</EuiFormLabel>
|
||||
<AggSelect
|
||||
id={htmlId('aggregation')}
|
||||
panelType={props.panel.type}
|
||||
siblings={props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('metric')}
|
||||
label="Metric"
|
||||
>
|
||||
<MetricSelect
|
||||
onChange={handleSelectChange('field')}
|
||||
exclude={['percentile']}
|
||||
metrics={siblings}
|
||||
metric={model}
|
||||
value={model.field}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
{ stdDev.sigma }
|
||||
{ stdDev.mode }
|
||||
</EuiFlexGroup>
|
||||
</AggRow>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -26,7 +26,12 @@ import createSelectHandler from '../lib/create_select_handler';
|
|||
import createTextHandler from '../lib/create_text_handler';
|
||||
import {
|
||||
htmlIdGenerator,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormLabel,
|
||||
EuiComboBox,
|
||||
EuiSpacer,
|
||||
EuiFormRow,
|
||||
} from '@elastic/eui';
|
||||
|
||||
export const TopHitAgg = props => {
|
||||
|
@ -72,23 +77,20 @@ export const TopHitAgg = props => {
|
|||
onDelete={props.onDelete}
|
||||
siblings={props.siblings}
|
||||
>
|
||||
<div className="vis_editor__row_item">
|
||||
<div className="vis_editor__agg_row-item">
|
||||
<div className="vis_editor__row_item">
|
||||
<div className="vis_editor__label">Aggregation</div>
|
||||
<AggSelect
|
||||
panelType={props.panel.type}
|
||||
siblings={props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__row_item">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('field')}>
|
||||
Field
|
||||
</label>
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiFormLabel htmlFor={htmlId('aggregation')}>Aggregation</EuiFormLabel>
|
||||
<AggSelect
|
||||
id={htmlId('aggregation')}
|
||||
panelType={props.panel.type}
|
||||
siblings={props.siblings}
|
||||
value={model.type}
|
||||
onChange={handleSelectChange('type')}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('field')} label="Field">
|
||||
<FieldSelect
|
||||
id={htmlId('field')}
|
||||
fields={fields}
|
||||
type={model.type}
|
||||
restrict="numeric"
|
||||
|
@ -96,63 +98,62 @@ export const TopHitAgg = props => {
|
|||
value={model.field}
|
||||
onChange={handleSelectChange('field')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="vis_editor__agg_row-item">
|
||||
<div className="vis_editor__row_item">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('size')}>
|
||||
Size
|
||||
</label>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow id={htmlId('size')} label="Size">
|
||||
{/*
|
||||
EUITODO: The following input couldn't be converted to EUI because of type mis-match.
|
||||
Should it be text or number?
|
||||
*/}
|
||||
<input
|
||||
id={htmlId('size')}
|
||||
className="vis_editor__input-grows-100"
|
||||
className="tvbAgg__input"
|
||||
value={model.size}
|
||||
onChange={handleTextChange('size')}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__row_item">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('agg_with')}>
|
||||
Aggregate with
|
||||
</label>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('agg_with')} label="Aggregate with">
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
id={htmlId('agg_with')}
|
||||
placeholder="Select..."
|
||||
placeholder="Select"
|
||||
options={aggWithOptions}
|
||||
selectedOptions={selectedAggWithOption ? [selectedAggWithOption] : []}
|
||||
onChange={handleSelectChange('agg_with')}
|
||||
singleSelection={true}
|
||||
singleSelection={{ asPlainText: true }}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__row_item">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('order_by')}>
|
||||
Order by
|
||||
</label>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('order_by')} label="Order by">
|
||||
<FieldSelect
|
||||
id={htmlId('order_by')}
|
||||
restrict="date"
|
||||
value={model.order_by}
|
||||
onChange={handleSelectChange('order_by')}
|
||||
indexPattern={indexPattern}
|
||||
fields={fields}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__row_item">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('order')}>
|
||||
Order
|
||||
</label>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('order')} label="Order">
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
id={htmlId('order')}
|
||||
placeholder="Select..."
|
||||
options={orderOptions}
|
||||
selectedOptions={selectedOrderOption ? [selectedOrderOption] : []}
|
||||
onChange={handleSelectChange('order')}
|
||||
singleSelection={true}
|
||||
singleSelection={{ asPlainText: true }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</AggRow>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
import AggRow from './agg_row';
|
||||
import React from 'react';
|
||||
import { EuiCode, EuiTitle } from '@elastic/eui';
|
||||
|
||||
export function UnsupportedAgg(props) {
|
||||
return (
|
||||
<AggRow
|
||||
|
@ -28,12 +30,9 @@ export function UnsupportedAgg(props) {
|
|||
onDelete={props.onDelete}
|
||||
siblings={props.siblings}
|
||||
>
|
||||
<div className="vis_editor__row_item">
|
||||
<p>
|
||||
The <code>{props.model.type}</code> aggregation is no longer
|
||||
supported.
|
||||
</p>
|
||||
</div>
|
||||
<EuiTitle className="tvbAggRow__unavailable" size="xxxs">
|
||||
<span>The <EuiCode>{props.model.type}</EuiCode> aggregation is no longer supported.</span>
|
||||
</EuiTitle>
|
||||
</AggRow>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import _ from 'lodash';
|
|||
import AddDeleteButtons from '../add_delete_buttons';
|
||||
import * as collectionActions from '../lib/collection_actions';
|
||||
import MetricSelect from './metric_select';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiFieldText } from '@elastic/eui';
|
||||
|
||||
class CalculationVars extends Component {
|
||||
|
||||
|
@ -44,34 +45,36 @@ class CalculationVars extends Component {
|
|||
const handleAdd = collectionActions.handleAdd.bind(null, this.props);
|
||||
const handleDelete = collectionActions.handleDelete.bind(null, this.props, row);
|
||||
return (
|
||||
<div className="vis_editor__calc_vars-row" key={row.id} data-test-subj="varRow">
|
||||
<div className="vis_editor__calc_vars-name">
|
||||
<input
|
||||
aria-label="Variable name"
|
||||
placeholder="Variable Name"
|
||||
className="vis_editor__input-grows-100"
|
||||
type="text"
|
||||
onChange={this.handleChange(row, 'name')}
|
||||
value={row.name}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__calc_vars-var">
|
||||
<MetricSelect
|
||||
onChange={this.handleChange(row, 'field')}
|
||||
metrics={this.props.metrics}
|
||||
metric={this.props.model}
|
||||
value={row.field}
|
||||
includeSiblings={this.props.includeSiblings}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__calc_vars-control">
|
||||
<AddDeleteButtons
|
||||
onAdd={handleAdd}
|
||||
onDelete={handleDelete}
|
||||
disableDelete={items.length < 2}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<EuiFlexItem key={row.id} data-test-subj="varRow">
|
||||
<EuiFlexGroup alignItems="center" responsive={false} gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiFieldText
|
||||
className="tvbAggs__varName"
|
||||
aria-label="Variable name"
|
||||
placeholder="Variable name"
|
||||
onChange={this.handleChange(row, 'name')}
|
||||
value={row.name}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem className="tvbAggs__varMetricWrapper">
|
||||
<MetricSelect
|
||||
onChange={this.handleChange(row, 'field')}
|
||||
metrics={this.props.metrics}
|
||||
metric={this.props.model}
|
||||
value={row.field}
|
||||
includeSiblings={this.props.includeSiblings}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<AddDeleteButtons
|
||||
onAdd={handleAdd}
|
||||
onDelete={handleDelete}
|
||||
disableDelete={items.length < 2}
|
||||
responsive={false}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -80,9 +83,9 @@ class CalculationVars extends Component {
|
|||
if (!model[name]) return (<div/>);
|
||||
const rows = model[name].map(this.renderRow);
|
||||
return (
|
||||
<div className="vis_editor__calc_vars">
|
||||
<EuiFlexGroup direction="column" gutterSize="s">
|
||||
{ rows }
|
||||
</div>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,15 @@ import YesNo from './yes_no';
|
|||
|
||||
import {
|
||||
htmlIdGenerator,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormRow,
|
||||
EuiFormLabel,
|
||||
EuiSpacer,
|
||||
EuiFieldText,
|
||||
EuiTitle,
|
||||
EuiButton,
|
||||
EuiCode,
|
||||
EuiText,
|
||||
} from '@elastic/eui';
|
||||
|
||||
|
@ -74,118 +83,133 @@ class AnnotationsEditor extends Component {
|
|||
const handleDelete = collectionActions.handleDelete
|
||||
.bind(null, this.props, model);
|
||||
return (
|
||||
<div className="vis_editor__annotations-row" key={model.id}>
|
||||
<div className="vis_editor__annotations-color">
|
||||
<ColorPicker
|
||||
disableTrash={true}
|
||||
onChange={handleChange}
|
||||
name="color"
|
||||
value={model.color}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__annotations-content">
|
||||
<div className="vis_editor__row">
|
||||
<div className="vis_editor__row-item">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('indexPattern')}>
|
||||
Index Pattern (required)
|
||||
</label>
|
||||
<input
|
||||
id={htmlId('indexPattern')}
|
||||
className="vis_editor__input-grows-100"
|
||||
type="text"
|
||||
onChange={this.handleChange(model, 'index_pattern')}
|
||||
value={model.index_pattern}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__row-item">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('timeField')}>
|
||||
Time Field (required)
|
||||
</label>
|
||||
<FieldSelect
|
||||
id={htmlId('timeField')}
|
||||
restrict="date"
|
||||
value={model.time_field}
|
||||
onChange={this.handleChange(model, 'time_field')}
|
||||
indexPattern={model.index_pattern}
|
||||
fields={this.props.fields}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="vis_editor__row">
|
||||
<div className="vis_editor__row-item">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('queryString')}>
|
||||
Query String
|
||||
</label>
|
||||
<input
|
||||
id={htmlId('queryString')}
|
||||
className="vis_editor__input-grows-100"
|
||||
type="text"
|
||||
onChange={this.handleChange(model, 'query_string')}
|
||||
value={model.query_string}
|
||||
/>
|
||||
</div>
|
||||
<fieldset className="vis_editor__row-item-small">
|
||||
<legend className="vis_editor__label">Ignore Global Filters</legend>
|
||||
<YesNo
|
||||
value={model.ignore_global_filters}
|
||||
name="ignore_global_filters"
|
||||
onChange={handleChange}
|
||||
/>
|
||||
<div className="tvbAnnotationsEditor" key={model.id}>
|
||||
<EuiFlexGroup responsive={false}>
|
||||
<EuiFlexItem grow={false}>
|
||||
<ColorPicker
|
||||
disableTrash={true}
|
||||
onChange={handleChange}
|
||||
name="color"
|
||||
value={model.color}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
</fieldset>
|
||||
<fieldset className="vis_editor__row-item-small">
|
||||
<legend className="vis_editor__label">Ignore Panel Filters</legend>
|
||||
<YesNo
|
||||
value={model.ignore_panel_filters}
|
||||
name="ignore_panel_filters"
|
||||
onChange={handleChange}
|
||||
/>
|
||||
<EuiFlexItem className="tvbAggRow__children">
|
||||
<EuiFlexGroup responsive={false} wrap={true} gutterSize="m">
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('indexPattern')}
|
||||
label="Index pattern (required)"
|
||||
fullWidth
|
||||
>
|
||||
<EuiFieldText
|
||||
onChange={this.handleChange(model, 'index_pattern')}
|
||||
value={model.index_pattern}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('timeField')} label="Time field (required)" fullWidth>
|
||||
<FieldSelect
|
||||
restrict="date"
|
||||
value={model.time_field}
|
||||
onChange={this.handleChange(model, 'time_field')}
|
||||
indexPattern={model.index_pattern}
|
||||
fields={this.props.fields}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
</fieldset>
|
||||
</div>
|
||||
<div className="vis_editor__row">
|
||||
<div className="vis_editor__row-item">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('icon')}>Icon (required)</label>
|
||||
<div className="vis_editor__item">
|
||||
<IconSelect
|
||||
id={htmlId('icon')}
|
||||
value={model.icon}
|
||||
onChange={this.handleChange(model, 'icon')}
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
<EuiFlexGroup responsive={false} wrap={true} gutterSize="m">
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('queryString')}
|
||||
label="Query string"
|
||||
fullWidth
|
||||
>
|
||||
<EuiFieldText
|
||||
onChange={this.handleChange(model, 'query_string')}
|
||||
value={model.query_string}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel>Ignore global filters?</EuiFormLabel>
|
||||
<EuiSpacer size="s" />
|
||||
<YesNo
|
||||
value={model.ignore_global_filters}
|
||||
name="ignore_global_filters"
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="vis_editor__row-item">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('fields')}>
|
||||
Fields (required - comma separated paths)
|
||||
</label>
|
||||
<input
|
||||
id={htmlId('fields')}
|
||||
className="vis_editor__input-grows-100"
|
||||
type="text"
|
||||
onChange={this.handleChange(model, 'fields')}
|
||||
value={model.fields}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__row-item">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('rowTemplate')}>
|
||||
Row Template (required - eg.<code>{'{{field}}'}</code>)
|
||||
</label>
|
||||
<input
|
||||
id={htmlId('rowTemplate')}
|
||||
className="vis_editor__input-grows-100"
|
||||
type="text"
|
||||
onChange={this.handleChange(model, 'template')}
|
||||
value={model.template}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="vis_editor__annotations-controls">
|
||||
<AddDeleteButtons
|
||||
onAdd={handleAdd}
|
||||
onDelete={handleDelete}
|
||||
/>
|
||||
</div>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel>Ignore panel filters?</EuiFormLabel>
|
||||
<EuiSpacer size="s" />
|
||||
<YesNo
|
||||
value={model.ignore_panel_filters}
|
||||
name="ignore_panel_filters"
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
<EuiFlexGroup responsive={false} wrap={true} gutterSize="m">
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('icon')} label="Icon (required)">
|
||||
<IconSelect
|
||||
value={model.icon}
|
||||
onChange={this.handleChange(model, 'icon')}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('fields')}
|
||||
label="Fields (required - comma separated paths)"
|
||||
fullWidth
|
||||
>
|
||||
<EuiFieldText
|
||||
onChange={this.handleChange(model, 'fields')}
|
||||
value={model.fields}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('rowTemplate')}
|
||||
label="Row template (required)"
|
||||
helpText={
|
||||
<span>eg. <EuiCode>{'{{field}}'}</EuiCode></span>
|
||||
}
|
||||
fullWidth
|
||||
>
|
||||
<EuiFieldText
|
||||
onChange={this.handleChange(model, 'template')}
|
||||
value={model.template}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
<AddDeleteButtons
|
||||
onAdd={handleAdd}
|
||||
onDelete={handleDelete}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -197,36 +221,26 @@ class AnnotationsEditor extends Component {
|
|||
const handleAdd = collectionActions.handleAdd
|
||||
.bind(null, this.props, newAnnotation);
|
||||
content = (
|
||||
<div className="vis_editor__annotations-missing">
|
||||
<EuiText>
|
||||
<p>Click the button below to create an annotation data source.</p>
|
||||
<button
|
||||
className="thor__button-outlined-default large"
|
||||
onClick={handleAdd}
|
||||
>Add Data Source
|
||||
</button>
|
||||
</EuiText>
|
||||
</div>
|
||||
<EuiText textAlign="center">
|
||||
<p>Click the button below to create an annotation data source.</p>
|
||||
<EuiButton fill onClick={handleAdd}>Add data source</EuiButton>
|
||||
</EuiText>
|
||||
);
|
||||
} else {
|
||||
const annotations = model.annotations.map(this.renderRow);
|
||||
content = (
|
||||
<div className="vis_editor__annotations">
|
||||
<div className="kbnTabs sm" role="tablist">
|
||||
<button
|
||||
role="tab"
|
||||
aria-selected={true}
|
||||
className="kbnTabs__tab-active"
|
||||
>
|
||||
Data Sources
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<EuiTitle size="s">
|
||||
<span>Data sources</span>
|
||||
</EuiTitle>
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
{ annotations }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return(
|
||||
<div className="vis_editor__container">
|
||||
<div className="tvbAnnotationsEditor__container">
|
||||
{ content }
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { EuiToolTip, } from '@elastic/eui';
|
||||
import { EuiIconTip, } from '@elastic/eui';
|
||||
import Picker from './custom_color_picker';
|
||||
|
||||
class ColorPicker extends Component {
|
||||
|
@ -66,7 +66,7 @@ class ColorPicker extends Component {
|
|||
return (
|
||||
<button
|
||||
aria-label="Color picker, not accessible"
|
||||
className="vis_editor__color_picker-swatch-empty"
|
||||
className="tvbColorPicker__swatch-empty"
|
||||
onClick={this.handleClick}
|
||||
/>
|
||||
);
|
||||
|
@ -75,7 +75,7 @@ class ColorPicker extends Component {
|
|||
<button
|
||||
aria-label={`Color picker ({this.props.value}), not accessible`}
|
||||
style={{ backgroundColor: this.props.value }}
|
||||
className="vis_editor__color_picker-swatch"
|
||||
className="tvbColorPicker__swatch"
|
||||
onClick={this.handleClick}
|
||||
/>
|
||||
);
|
||||
|
@ -87,23 +87,21 @@ class ColorPicker extends Component {
|
|||
let clear;
|
||||
if (!this.props.disableTrash) {
|
||||
clear = (
|
||||
<div className="vis_editor__color_picker-clear" onClick={this.handleClear}>
|
||||
<EuiToolTip content="Clear">
|
||||
<i className="fa fa-ban"/>
|
||||
</EuiToolTip>
|
||||
<div className="tvbColorPicker__clear" onClick={this.handleClear}>
|
||||
<EuiIconTip size="s" type="cross" color="danger" content="Clear" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className="vis_editor__color_picker">
|
||||
<div className="tvbColorPicker">
|
||||
{ swatch }
|
||||
{ clear }
|
||||
{
|
||||
this.state.displayPicker
|
||||
? (
|
||||
<div className="vis_editor__color_picker-popover">
|
||||
<div className="tvbColorPicker__popover">
|
||||
<div
|
||||
className="vis_editor__color_picker-cover"
|
||||
className="tvbColorPicker__cover"
|
||||
onClick={this.handleClose}
|
||||
/>
|
||||
<Picker
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import _ from 'lodash';
|
||||
import AddDeleteButtons from './add_delete_buttons';
|
||||
import * as collectionActions from './lib/collection_actions';
|
||||
|
@ -26,6 +26,10 @@ import ColorPicker from './color_picker';
|
|||
import {
|
||||
htmlIdGenerator,
|
||||
EuiComboBox,
|
||||
EuiFieldNumber,
|
||||
EuiFormLabel,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
} from '@elastic/eui';
|
||||
|
||||
class ColorRules extends Component {
|
||||
|
@ -66,55 +70,72 @@ class ColorRules extends Component {
|
|||
return model.operator === option.value;
|
||||
});
|
||||
|
||||
const labelStyle = { marginBottom: 0 };
|
||||
|
||||
let secondary;
|
||||
if (!this.props.hideSecondary) {
|
||||
secondary = (
|
||||
<div className="color_rules__secondary">
|
||||
<div className="color_rules__label">and {this.props.secondaryName} to</div>
|
||||
<ColorPicker
|
||||
onChange={handleColorChange}
|
||||
name={this.props.secondaryVarName}
|
||||
value={model[this.props.secondaryVarName]}
|
||||
/>
|
||||
</div>
|
||||
<Fragment>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel style={labelStyle}>and {this.props.secondaryName} to</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<ColorPicker
|
||||
onChange={handleColorChange}
|
||||
name={this.props.secondaryVarName}
|
||||
value={model[this.props.secondaryVarName]}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div key={model.id} className="color_rules__rule">
|
||||
<div className="color_rules__label">Set {this.props.primaryName} to</div>
|
||||
<ColorPicker
|
||||
onChange={handleColorChange}
|
||||
name={this.props.primaryVarName}
|
||||
value={model[this.props.primaryVarName]}
|
||||
/>
|
||||
<EuiFlexGroup wrap={true} responsive={false} gutterSize="s" key={model.id} alignItems="center" className="tvbColorRules__rule">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel style={labelStyle}>Set {this.props.primaryName} to</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<ColorPicker
|
||||
onChange={handleColorChange}
|
||||
name={this.props.primaryVarName}
|
||||
value={model[this.props.primaryVarName]}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
{ secondary }
|
||||
<label className="color_rules__label" htmlFor={htmlId('ifMetricIs')}>
|
||||
if metric is
|
||||
</label>
|
||||
<div className="color_rules__item">
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel style={labelStyle} htmlFor={htmlId('ifMetricIs')}>if metric is</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiComboBox
|
||||
id={htmlId('ifMetricIs')}
|
||||
options={operatorOptions}
|
||||
selectedOptions={selectedOperatorOption ? [selectedOperatorOption] : []}
|
||||
onChange={this.handleChange(model, 'operator')}
|
||||
singleSelection={true}
|
||||
fullWidth
|
||||
/>
|
||||
</div>
|
||||
<input
|
||||
aria-label="Value"
|
||||
className="color_rules__input"
|
||||
type="number"
|
||||
value={model.value}
|
||||
onChange={this.handleChange(model, 'value', Number)}
|
||||
/>
|
||||
<div className="color_rules__control">
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem>
|
||||
<EuiFieldNumber
|
||||
aria-label="Value"
|
||||
value={model.value}
|
||||
onChange={this.handleChange(model, 'value', Number)}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
<AddDeleteButtons
|
||||
onAdd={handleAdd}
|
||||
onDelete={handleDelete}
|
||||
disableDelete={items.length < 2}
|
||||
responsive={false}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -123,7 +144,7 @@ class ColorRules extends Component {
|
|||
if (!model[name]) return (<div/>);
|
||||
const rows = model[name].map(this.renderRow);
|
||||
return (
|
||||
<div className="color_rules">
|
||||
<div>
|
||||
{ rows }
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -82,8 +82,8 @@ export class CustomColorPicker extends Component {
|
|||
});
|
||||
|
||||
return (
|
||||
<div className="custom-picker color_picker">
|
||||
<div className="color_picker__saturation">
|
||||
<div className="tvbColorPickerPopUp">
|
||||
<div className="tvbColorPickerPopUp__saturation">
|
||||
<Saturation
|
||||
style={styles.Saturation}
|
||||
{...this.props}
|
||||
|
@ -91,16 +91,16 @@ export class CustomColorPicker extends Component {
|
|||
onChange={this.handleChange}
|
||||
/>
|
||||
</div>
|
||||
<div className="color_picker__body">
|
||||
<div className="color_picker__controls flexbox-fix">
|
||||
<div className={this.props.disableAlpha ? 'color_picker__color-disable_alpha' : 'color_picker__color'}>
|
||||
<div className={this.props.disableAlpha ? 'color_picker__swatch-disable_alpha' : 'color_picker__swatch'}>
|
||||
<div className="color_picker__active" />
|
||||
<div className="tvbColorPickerPopUp__body">
|
||||
<div className="tvbColorPickerPopUp__controls">
|
||||
<div className={this.props.disableAlpha ? 'tvbColorPickerPopUp__color-disableAlpha' : 'tvbColorPickerPopUp__color'}>
|
||||
<div className={this.props.disableAlpha ? 'tvbColorPickerPopUp__swatch-disableAlpha' : 'tvbColorPickerPopUp__swatch'}>
|
||||
<div className="tvbColorPickerPopUp__active" />
|
||||
<Checkboard />
|
||||
</div>
|
||||
</div>
|
||||
<div className="color_picker__toggles">
|
||||
<div className={this.props.disableAlpha ? 'color_picker__hue-disable_alpha' : 'color_picker__hue'}>
|
||||
<div className="tvbColorPickerPopUp__toggles">
|
||||
<div className={this.props.disableAlpha ? 'tvbColorPickerPopUp__hue-disableAlpha' : 'tvbColorPickerPopUp__hue'}>
|
||||
<Hue
|
||||
style={styles.Hue}
|
||||
{...this.props}
|
||||
|
@ -108,7 +108,7 @@ export class CustomColorPicker extends Component {
|
|||
onChange={this.handleChange}
|
||||
/>
|
||||
</div>
|
||||
<div className={this.props.disableAlpha ? 'color_picker__alpha-disable_alpha' : 'color_picker__alpha'}>
|
||||
<div className={this.props.disableAlpha ? 'tvbColorPickerPopUp__alpha-disableAlpha' : 'tvbColorPickerPopUp__alpha'}>
|
||||
<Alpha
|
||||
style={styles.Alpha}
|
||||
{...this.props}
|
||||
|
@ -123,7 +123,7 @@ export class CustomColorPicker extends Component {
|
|||
onChange={this.handleChange}
|
||||
disableAlpha={this.props.disableAlpha}
|
||||
/>
|
||||
<div className="color_picker__swatches flexbox-fix">
|
||||
<div className="tvbColorPickerPopUp__swatches">
|
||||
{swatches}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -21,7 +21,7 @@ import PropTypes from 'prop-types';
|
|||
import React, { Component } from 'react';
|
||||
import _ from 'lodash';
|
||||
import {
|
||||
EuiComboBox,
|
||||
htmlIdGenerator, EuiComboBox, EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiFieldText, EuiLink,
|
||||
} from '@elastic/eui';
|
||||
import { durationOutputOptions, durationInputOptions } from './lib/durations';
|
||||
const durationFormatTest = /[pnumshdwMY]+,[pnumshdwMY]+/;
|
||||
|
@ -91,6 +91,7 @@ class DataFormatPicker extends Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const htmlId = htmlIdGenerator();
|
||||
const value = this.props.value || '';
|
||||
let defaultValue = value;
|
||||
if (!_.includes(['bytes', 'number', 'percent'], value)) {
|
||||
|
@ -120,11 +121,74 @@ class DataFormatPicker extends Component {
|
|||
return to === option.value;
|
||||
});
|
||||
return (
|
||||
<div className="vis_editor__data_format_picker-container">
|
||||
<div className="vis_editor__label">
|
||||
{this.props.label}
|
||||
</div>
|
||||
<div className="vis_editor__item">
|
||||
<EuiFlexGroup responsive={false} gutterSize="s">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow id={htmlId('date')} label={this.props.label}>
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
options={options}
|
||||
selectedOptions={selectedOption ? [selectedOption] : []}
|
||||
onChange={this.handleChange}
|
||||
singleSelection={true}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow id={htmlId('from')} label="From">
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
options={durationInputOptions}
|
||||
selectedOptions={selectedFrom ? [selectedFrom] : []}
|
||||
onChange={this.handleDurationChange('from')}
|
||||
singleSelection={true}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow id={htmlId('to')} label="To">
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
options={durationOutputOptions}
|
||||
selectedOptions={selectedTo ? [selectedTo] : []}
|
||||
onChange={this.handleDurationChange('to')}
|
||||
singleSelection={true}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow id={htmlId('decimal')} label="Decimal places">
|
||||
<EuiFieldText
|
||||
defaultValue={decimals}
|
||||
inputRef={(el) => this.decimals = el}
|
||||
onChange={this.handleDurationChange('decimals')}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
if (defaultValue === 'custom') {
|
||||
custom = (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow
|
||||
label="Format string"
|
||||
helpText={
|
||||
<span>See <EuiLink href="http://numeraljs.com/#format" target="_BLANK">Numeral.js</EuiLink></span>
|
||||
}
|
||||
>
|
||||
<EuiFieldText
|
||||
defaultValue={value}
|
||||
inputRef={(el) => this.custom = el}
|
||||
onChange={this.handleCustomChange}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<EuiFlexGroup responsive={false} gutterSize="s">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow label={this.props.label}>
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
options={options}
|
||||
|
@ -132,72 +196,10 @@ class DataFormatPicker extends Component {
|
|||
onChange={this.handleChange}
|
||||
singleSelection={true}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__label">From</div>
|
||||
<div className="vis_editor__item">
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
options={durationInputOptions}
|
||||
selectedOptions={selectedFrom ? [selectedFrom] : []}
|
||||
onChange={this.handleDurationChange('from')}
|
||||
singleSelection={true}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__label">To</div>
|
||||
<div className="vis_editor__item">
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
options={durationOutputOptions}
|
||||
selectedOptions={selectedTo ? [selectedTo] : []}
|
||||
onChange={this.handleDurationChange('to')}
|
||||
singleSelection={true}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__label">Decimal Places</div>
|
||||
<input
|
||||
style={{ width: 60 }}
|
||||
className="vis_editor__input"
|
||||
defaultValue={decimals}
|
||||
ref={(el) => this.decimals = el}
|
||||
onChange={this.handleDurationChange('decimals')}
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (defaultValue === 'custom') {
|
||||
custom = (
|
||||
<div className="vis_editor__data_format_picker-custom_row">
|
||||
<div className="vis_editor__label">
|
||||
Format String (See <a href="http://numeraljs.com/#format" target="_BLANK">Numeral.js</a>)
|
||||
</div>
|
||||
<input
|
||||
style={{ width: 100 }}
|
||||
className="vis_editor__input"
|
||||
defaultValue={value}
|
||||
ref={(el) => this.custom = el}
|
||||
onChange={this.handleCustomChange}
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className="vis_editor__data_format_picker-container">
|
||||
<div className="vis_editor__label">
|
||||
{this.props.label}
|
||||
</div>
|
||||
<div className="vis_editor__item">
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
options={options}
|
||||
selectedOptions={selectedOption ? [selectedOption] : []}
|
||||
onChange={this.handleChange}
|
||||
singleSelection={true}
|
||||
/>
|
||||
</div>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
{custom}
|
||||
</div>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,22 +36,22 @@ function ErrorComponent(props) {
|
|||
const scriptStack = _.get(error, 'error.caused_by.script_stack');
|
||||
reason = _.get(error, 'error.caused_by.caused_by.reason');
|
||||
additionalInfo = (
|
||||
<div className="metrics_error__additional">
|
||||
<div className="metrics_error__reason">{reason}</div>
|
||||
<div className="metrics_error__stack">{scriptStack.join('\n')}</div>
|
||||
<div className="tvbError__additional">
|
||||
<div className="tvbError__reason">{reason}</div>
|
||||
<div className="tvbError__stack">{scriptStack.join('\n')}</div>
|
||||
</div>
|
||||
);
|
||||
} else if (reason) {
|
||||
additionalInfo = (
|
||||
<div className="metrics_error__additional">
|
||||
<div className="metrics_error__reason">{reason}</div>
|
||||
<div className="tvbError__additional">
|
||||
<div className="tvbError__reason">{reason}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="metrics_error">
|
||||
<div className="metrics_error__title">{title || 'The request for this panel failed.'}</div>
|
||||
<div className="tvbError">
|
||||
<div className="tvbError__title">{title || 'The request for this panel failed'}</div>
|
||||
{additionalInfo}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -27,15 +27,10 @@ function renderOption(option) {
|
|||
const icon = option.value;
|
||||
const label = option.label;
|
||||
return (
|
||||
<div className="Select-value">
|
||||
<span
|
||||
className="Select-value-label"
|
||||
aria-label={`${label} icon`}
|
||||
>
|
||||
<span className={`vis_editor__icon_select-value kuiIcon ${icon}`} />
|
||||
{ label }
|
||||
</span>
|
||||
</div>
|
||||
<span>
|
||||
<span className={`kuiIcon ${icon}`} aria-hidden="true" />
|
||||
{` ${label}`}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,15 @@ import FieldSelect from './aggs/field_select';
|
|||
import createSelectHandler from './lib/create_select_handler';
|
||||
import createTextHandler from './lib/create_text_handler';
|
||||
import YesNo from './yes_no';
|
||||
import { htmlIdGenerator } from '@elastic/eui';
|
||||
import {
|
||||
htmlIdGenerator,
|
||||
EuiFieldText,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormRow,
|
||||
EuiFormLabel,
|
||||
EuiSpacer,
|
||||
} from '@elastic/eui';
|
||||
|
||||
export const IndexPattern = props => {
|
||||
const { fields, prefix } = props;
|
||||
|
@ -45,48 +53,63 @@ export const IndexPattern = props => {
|
|||
const model = { ...defaults, ...props.model };
|
||||
return (
|
||||
<div className={props.className}>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('indexPattern')}>
|
||||
Index Pattern
|
||||
</label>
|
||||
<input
|
||||
id={htmlId('indexPattern')}
|
||||
className="vis_editor__input"
|
||||
disabled={props.disabled}
|
||||
onChange={handleTextChange(indexPatternName, '*')}
|
||||
value={model[indexPatternName]}
|
||||
data-test-subj="metricsIndexPatternInput"
|
||||
/>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('timeField')}>
|
||||
Time Field
|
||||
</label>
|
||||
<div className="vis_editor__index_pattern-fields">
|
||||
<FieldSelect
|
||||
id={htmlId('timeField')}
|
||||
restrict="date"
|
||||
value={model[timeFieldName]}
|
||||
disabled={props.disabled}
|
||||
onChange={handleSelectChange(timeFieldName)}
|
||||
indexPattern={model[indexPatternName]}
|
||||
fields={fields}
|
||||
data-test-subj="metricsIndexPatternFieldsSelect"
|
||||
/>
|
||||
</div>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('interval')}>
|
||||
Interval (auto, 1m, 1d, 7d, 1y, >=1m)
|
||||
</label>
|
||||
<input
|
||||
id={htmlId('interval')}
|
||||
className="vis_editor__input"
|
||||
disabled={props.disabled}
|
||||
onChange={handleTextChange(intervalName, 'auto')}
|
||||
value={model[intervalName]}
|
||||
/>
|
||||
<div className="vis_editor__label">Drop Last Bucket</div>
|
||||
<YesNo
|
||||
value={model[dropBucketName]}
|
||||
name={dropBucketName}
|
||||
onChange={props.onChange}
|
||||
/>
|
||||
<EuiFlexGroup responsive={false} wrap={true}>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('indexPattern')}
|
||||
label="Index pattern"
|
||||
fullWidth
|
||||
>
|
||||
<EuiFieldText
|
||||
data-test-subj="metricsIndexPatternInput"
|
||||
disabled={props.disabled}
|
||||
onChange={handleTextChange(indexPatternName, '*')}
|
||||
value={model[indexPatternName]}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('timeField')}
|
||||
label="Time field"
|
||||
fullWidth
|
||||
>
|
||||
<FieldSelect
|
||||
data-test-subj="metricsIndexPatternFieldsSelect"
|
||||
restrict="date"
|
||||
value={model[timeFieldName]}
|
||||
disabled={props.disabled}
|
||||
onChange={handleSelectChange(timeFieldName)}
|
||||
indexPattern={model[indexPatternName]}
|
||||
fields={fields}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow
|
||||
id={htmlId('interval')}
|
||||
label="Interval"
|
||||
helpText="Examples: auto, 1m, 1d, 7d, 1y, >=1m"
|
||||
>
|
||||
<EuiFieldText
|
||||
disabled={props.disabled}
|
||||
onChange={handleTextChange(intervalName, 'auto')}
|
||||
value={model[intervalName]}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel>Drop last bucket?</EuiFormLabel>
|
||||
<EuiSpacer size="s" />
|
||||
<YesNo
|
||||
value={model[dropBucketName]}
|
||||
name={dropBucketName}
|
||||
onChange={props.onChange}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -94,7 +117,6 @@ export const IndexPattern = props => {
|
|||
IndexPattern.defaultProps = {
|
||||
prefix: '',
|
||||
disabled: false,
|
||||
className: 'vis_editor__row'
|
||||
};
|
||||
|
||||
IndexPattern.propTypes = {
|
||||
|
|
|
@ -34,6 +34,8 @@ import 'brace/theme/github';
|
|||
import {
|
||||
EuiText,
|
||||
EuiCodeBlock,
|
||||
EuiSpacer,
|
||||
EuiTitle,
|
||||
} from '@elastic/eui';
|
||||
|
||||
class MarkdownEditor extends Component {
|
||||
|
@ -131,8 +133,8 @@ class MarkdownEditor extends Component {
|
|||
walk(variables);
|
||||
|
||||
return (
|
||||
<div className="vis_editor__markdown">
|
||||
<div className="vis_editor__markdown-editor">
|
||||
<div className="tvbMarkdownEditor">
|
||||
<div className="tvbMarkdownEditor__editor">
|
||||
<KuiCodeEditor
|
||||
onLoad={this.handleOnLoad}
|
||||
mode="markdown"
|
||||
|
@ -145,13 +147,15 @@ class MarkdownEditor extends Component {
|
|||
onChange={this.handleChange}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__markdown-variables">
|
||||
<div className="tvbMarkdownEditor__variables">
|
||||
<EuiText>
|
||||
The following variables can be used in the Markdown by using the Handlebar (mustache) syntax.{' '}
|
||||
<a href="http://handlebarsjs.com/expressions.html" target="_BLANK">
|
||||
Click here for documentation
|
||||
</a>{' '}
|
||||
on the available expressions.
|
||||
<p>
|
||||
The following variables can be used in the Markdown by using the Handlebar (mustache) syntax.{' '}
|
||||
<a href="http://handlebarsjs.com/expressions.html" target="_BLANK">
|
||||
Click here for documentation
|
||||
</a>{' '}
|
||||
on the available expressions.
|
||||
</p>
|
||||
</EuiText>
|
||||
<table className="table">
|
||||
<thead>
|
||||
|
@ -162,25 +166,30 @@ class MarkdownEditor extends Component {
|
|||
</thead>
|
||||
<tbody>{rows}</tbody>
|
||||
</table>
|
||||
|
||||
{rows.length === 0 && (
|
||||
<div className="vis_editor__no-markdown-variables">No variables available for the selected data metrics.</div>
|
||||
<EuiTitle size="xxs" className="tvbMarkdownEditor__noVariables">
|
||||
<span>No variables available for the selected data metrics.</span>
|
||||
</EuiTitle>
|
||||
)}
|
||||
|
||||
<div className="vis_editor__markdown-code-desc">
|
||||
<EuiText>
|
||||
<p>
|
||||
There is also a special variable named <code>_all</code> which you can use to access the entire tree. This is useful for
|
||||
creating lists with data from a group by...
|
||||
</p>
|
||||
</EuiText>
|
||||
</div>
|
||||
<EuiSpacer />
|
||||
|
||||
<EuiText>
|
||||
<p>
|
||||
There is also a special variable named <code>_all</code> which you can use to access the entire tree. This is useful for
|
||||
creating lists with data from a group by...
|
||||
</p>
|
||||
</EuiText>
|
||||
|
||||
<EuiSpacer />
|
||||
|
||||
<EuiCodeBlock>
|
||||
{`# All servers:
|
||||
|
||||
{{#each _all}}
|
||||
- {{ label }} {{ last.formatted }}
|
||||
{{/each}}`}
|
||||
{{#each _all}}
|
||||
- {{ label }} {{ last.formatted }}
|
||||
{{/each}}`}
|
||||
</EuiCodeBlock>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -21,8 +21,8 @@ import React from 'react';
|
|||
|
||||
function NoDataComponent() {
|
||||
return (
|
||||
<div className="metrics_issue" data-test-subj="noTSVBDataMessage">
|
||||
<div className="metrics_issue__title">No data to display for the selected metrics .</div>
|
||||
<div className="tvbNoData" data-test-subj="noTSVBDataMessage">
|
||||
<div className="tvbNoData__title">No data to display for the selected metrics</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
@import './panel_config';
|
|
@ -0,0 +1,4 @@
|
|||
.tvbPanelConfig__container {
|
||||
padding: $euiSize;
|
||||
background-color: $euiColorLightestShade;
|
||||
}
|
|
@ -30,6 +30,18 @@ import YesNo from '../yes_no';
|
|||
import {
|
||||
htmlIdGenerator,
|
||||
EuiComboBox,
|
||||
EuiTabs,
|
||||
EuiTab,
|
||||
EuiPanel,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormRow,
|
||||
EuiFormLabel,
|
||||
EuiSpacer,
|
||||
EuiFieldText,
|
||||
EuiFieldNumber,
|
||||
EuiTitle,
|
||||
EuiHorizontalRule,
|
||||
} from '@elastic/eui';
|
||||
|
||||
class GaugePanelConfig extends Component {
|
||||
|
@ -90,92 +102,137 @@ class GaugePanelConfig extends Component {
|
|||
);
|
||||
} else {
|
||||
view = (
|
||||
<div className="vis_editor__container">
|
||||
<IndexPattern
|
||||
fields={this.props.fields}
|
||||
model={this.props.model}
|
||||
onChange={this.props.onChange}
|
||||
/>
|
||||
<div className="vis_editor__vis_config-row">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('panelFilter')}>
|
||||
Panel Filter
|
||||
</label>
|
||||
<input
|
||||
id={htmlId('panelFilter')}
|
||||
className="vis_editor__input-grows"
|
||||
type="text"
|
||||
onChange={handleTextChange('filter')}
|
||||
value={model.filter}
|
||||
/>
|
||||
<div className="vis_editor__label">Ignore Global Filter</div>
|
||||
<YesNo
|
||||
value={model.ignore_global_filter}
|
||||
name="ignore_global_filter"
|
||||
<div className="tvbPanelConfig__container">
|
||||
<EuiPanel>
|
||||
<EuiTitle size="s"><span>Data</span></EuiTitle>
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
<IndexPattern
|
||||
fields={this.props.fields}
|
||||
model={this.props.model}
|
||||
onChange={this.props.onChange}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__vis_config-row">
|
||||
<div className="vis_editor__label">Background Color</div>
|
||||
<ColorPicker
|
||||
onChange={this.props.onChange}
|
||||
name="background_color"
|
||||
value={model.background_color}
|
||||
/>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('gaugeMax')}>
|
||||
Gauge Max (empty for auto)
|
||||
</label>
|
||||
<input
|
||||
id={htmlId('gaugeMax')}
|
||||
className="vis_editor__input-grows"
|
||||
type="number"
|
||||
onChange={handleTextChange('gauge_max')}
|
||||
value={model.gauge_max}
|
||||
/>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('gaugeStyle')}>
|
||||
Gauge Style
|
||||
</label>
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
id={htmlId('gaugeStyle')}
|
||||
options={styleOptions}
|
||||
selectedOptions={selectedGaugeStyleOption ? [selectedGaugeStyleOption] : []}
|
||||
onChange={handleSelectChange('gauge_style')}
|
||||
singleSelection={true}
|
||||
/>
|
||||
|
||||
</div>
|
||||
<div className="vis_editor__vis_config-row">
|
||||
<div className="vis_editor__label">Inner Color</div>
|
||||
<ColorPicker
|
||||
onChange={this.props.onChange}
|
||||
name="gauge_inner_color"
|
||||
value={model.gauge_inner_color}
|
||||
/>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('innerLine')}>
|
||||
Inner Line Width
|
||||
</label>
|
||||
<input
|
||||
id={htmlId('innerLine')}
|
||||
className="vis_editor__input-grows"
|
||||
type="number"
|
||||
onChange={handleTextChange('gauge_inner_width')}
|
||||
value={model.gauge_inner_width}
|
||||
/>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('gaugeLine')}>
|
||||
Gauge Line Width
|
||||
</label>
|
||||
<input
|
||||
id={htmlId('gaugeLine')}
|
||||
className="vis_editor__input-grows"
|
||||
type="number"
|
||||
onChange={handleTextChange('gauge_width')}
|
||||
value={model.gauge_width}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div className="vis_editor__label">Color Rules</div>
|
||||
</div>
|
||||
<div className="vis_editor__vis_config-row">
|
||||
<EuiHorizontalRule />
|
||||
|
||||
<EuiFlexGroup responsive={false} wrap={true}>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('panelFilter')}
|
||||
label="Panel filter"
|
||||
fullWidth
|
||||
>
|
||||
<EuiFieldText
|
||||
onChange={handleTextChange('filter')}
|
||||
value={model.filter}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel>Ignore global filter?</EuiFormLabel>
|
||||
<EuiSpacer size="s" />
|
||||
<YesNo
|
||||
value={model.ignore_global_filter}
|
||||
name="ignore_global_filter"
|
||||
onChange={this.props.onChange}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiPanel>
|
||||
|
||||
<EuiSpacer />
|
||||
|
||||
<EuiPanel>
|
||||
<EuiTitle size="s"><span>Style</span></EuiTitle>
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
<EuiFlexGroup responsive={false} wrap={true}>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('gaugeMax')}
|
||||
label="Gauge max (empty for auto)"
|
||||
>
|
||||
{/*
|
||||
EUITODO: The following input couldn't be converted to EUI because of type mis-match.
|
||||
It accepts a null value, but is passed a empty string.
|
||||
*/}
|
||||
<input
|
||||
id={htmlId('gaugeMax')}
|
||||
className="tvbAgg__input"
|
||||
type="number"
|
||||
onChange={handleTextChange('gauge_max')}
|
||||
value={model.gauge_max}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('gaugeStyle')}
|
||||
label="Gauge style"
|
||||
>
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
options={styleOptions}
|
||||
selectedOptions={selectedGaugeStyleOption ? [selectedGaugeStyleOption] : []}
|
||||
onChange={handleSelectChange('gauge_style')}
|
||||
singleSelection={{ asPlainText: true }}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('innerLine')}
|
||||
label="Inner line width"
|
||||
>
|
||||
<EuiFieldNumber
|
||||
onChange={handleTextChange('gauge_inner_width')}
|
||||
value={Number(model.gauge_inner_width)}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('gaugeLine')}
|
||||
label="Gauge line width"
|
||||
>
|
||||
<EuiFieldNumber
|
||||
onChange={handleTextChange('gauge_width')}
|
||||
value={Number(model.gauge_width)}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
<EuiHorizontalRule />
|
||||
|
||||
<EuiFlexGroup responsive={false} wrap={true} alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel style={{ marginBottom: 0 }}>Background color:</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<ColorPicker
|
||||
onChange={this.props.onChange}
|
||||
name="background_color"
|
||||
value={model.background_color}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel style={{ marginBottom: 0 }}>Inner color:</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<ColorPicker
|
||||
onChange={this.props.onChange}
|
||||
name="gauge_inner_color"
|
||||
value={model.gauge_inner_color}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
<EuiHorizontalRule />
|
||||
|
||||
<EuiTitle size="xxs"><span>Color rules</span></EuiTitle>
|
||||
<EuiSpacer size="s" />
|
||||
<ColorRules
|
||||
primaryName="gauge color"
|
||||
primaryVarName="gauge"
|
||||
|
@ -185,28 +242,26 @@ class GaugePanelConfig extends Component {
|
|||
onChange={this.props.onChange}
|
||||
name="gauge_color_rules"
|
||||
/>
|
||||
</div>
|
||||
</EuiPanel>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<div className="kbnTabs" role="tablist">
|
||||
<button
|
||||
role="tab"
|
||||
aria-selected={selectedTab === 'data'}
|
||||
className={`kbnTabs__tab${selectedTab === 'data' && '-active' || ''}`}
|
||||
<EuiTabs size="s">
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'data'}
|
||||
onClick={() => this.switchTab('data')}
|
||||
>Data
|
||||
</button>
|
||||
<button
|
||||
role="tab"
|
||||
aria-selected={selectedTab === 'options'}
|
||||
className={`kbnTabs__tab${selectedTab === 'options' && '-active' || ''}`}
|
||||
>
|
||||
Data
|
||||
</EuiTab>
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'options'}
|
||||
onClick={() => this.switchTab('options')}
|
||||
>Panel Options
|
||||
</button>
|
||||
</div>
|
||||
>
|
||||
Panel options
|
||||
</EuiTab>
|
||||
</EuiTabs>
|
||||
{view}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -32,6 +32,17 @@ import { KuiCodeEditor } from '@kbn/ui-framework/components';
|
|||
import {
|
||||
htmlIdGenerator,
|
||||
EuiComboBox,
|
||||
EuiTabs,
|
||||
EuiTab,
|
||||
EuiPanel,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormRow,
|
||||
EuiFormLabel,
|
||||
EuiSpacer,
|
||||
EuiFieldText,
|
||||
EuiTitle,
|
||||
EuiHorizontalRule,
|
||||
} from '@elastic/eui';
|
||||
const lessC = less(window, { env: 'production' });
|
||||
|
||||
|
@ -93,61 +104,91 @@ class MarkdownPanelConfig extends Component {
|
|||
);
|
||||
} else {
|
||||
view = (
|
||||
<div className="vis_editor__container">
|
||||
<IndexPattern
|
||||
fields={this.props.fields}
|
||||
model={this.props.model}
|
||||
onChange={this.props.onChange}
|
||||
/>
|
||||
<div className="vis_editor__vis_config-row">
|
||||
<div className="vis_editor__label">Background Color</div>
|
||||
<ColorPicker
|
||||
onChange={this.props.onChange}
|
||||
name="background_color"
|
||||
value={model.background_color}
|
||||
/>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('panelFilter')}>
|
||||
Panel Filter
|
||||
</label>
|
||||
<input
|
||||
id={htmlId('panelFilter')}
|
||||
className="vis_editor__input-grows"
|
||||
type="text"
|
||||
onChange={handleTextChange('filter')}
|
||||
value={model.filter}
|
||||
/>
|
||||
<div className="vis_editor__label">Ignore Global Filter</div>
|
||||
<YesNo
|
||||
value={model.ignore_global_filter}
|
||||
name="ignore_global_filter"
|
||||
<div className="tvbPanelConfig__container">
|
||||
<EuiPanel>
|
||||
<EuiTitle size="s"><span>Data</span></EuiTitle>
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
<IndexPattern
|
||||
fields={this.props.fields}
|
||||
model={this.props.model}
|
||||
onChange={this.props.onChange}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__vis_config-row">
|
||||
<div className="vis_editor__label">Show Scrollbars</div>
|
||||
<YesNo
|
||||
value={model.markdown_scrollbars}
|
||||
name="markdown_scrollbars"
|
||||
onChange={this.props.onChange}
|
||||
/>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('valign')}>
|
||||
Vertical Alignment
|
||||
</label>
|
||||
<div className="vis_editor__row_item">
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
id={htmlId('valign')}
|
||||
options={alignOptions}
|
||||
selectedOptions={selectedAlignOption ? [selectedAlignOption] : []}
|
||||
onChange={handleSelectChange('markdown_vertical_align')}
|
||||
singleSelection={true}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="vis_editor__vis_config-row">
|
||||
<div className="vis_editor__label">Custom CSS (supports Less)</div>
|
||||
</div>
|
||||
<div className="vis_editor__ace-editor">
|
||||
|
||||
<EuiHorizontalRule />
|
||||
|
||||
<EuiFlexGroup responsive={false} wrap={true}>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('panelFilter')}
|
||||
label="Panel filter"
|
||||
fullWidth
|
||||
>
|
||||
<EuiFieldText
|
||||
onChange={handleTextChange('filter')}
|
||||
value={model.filter}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel>Ignore global filter?</EuiFormLabel>
|
||||
<EuiSpacer size="s" />
|
||||
<YesNo
|
||||
value={model.ignore_global_filter}
|
||||
name="ignore_global_filter"
|
||||
onChange={this.props.onChange}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiPanel>
|
||||
|
||||
<EuiSpacer />
|
||||
|
||||
<EuiPanel>
|
||||
<EuiTitle size="s"><span>Style</span></EuiTitle>
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
<EuiFlexGroup responsive={false} wrap={true} alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel style={{ marginBottom: 0 }}>Background color:</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<ColorPicker
|
||||
onChange={this.props.onChange}
|
||||
name="background_color"
|
||||
value={model.background_color}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel style={{ marginBottom: 0 }}>Show scrollbars?</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<YesNo
|
||||
value={model.markdown_scrollbars}
|
||||
name="markdown_scrollbars"
|
||||
onChange={this.props.onChange}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel style={{ marginBottom: 0 }} htmlFor={htmlId('valign')}>Vertical alignment:</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiComboBox
|
||||
id={htmlId('valign')}
|
||||
isClearable={false}
|
||||
options={alignOptions}
|
||||
selectedOptions={selectedAlignOption ? [selectedAlignOption] : []}
|
||||
onChange={handleSelectChange('markdown_vertical_align')}
|
||||
singleSelection={{ asPlainText: true }}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
<EuiHorizontalRule />
|
||||
|
||||
<EuiTitle size="xxs"><span>Custom CSS (supports Less)</span></EuiTitle>
|
||||
<EuiSpacer size="s" />
|
||||
<KuiCodeEditor
|
||||
mode="less"
|
||||
theme="github"
|
||||
|
@ -157,36 +198,33 @@ class MarkdownPanelConfig extends Component {
|
|||
value={model.markdown_less}
|
||||
onChange={this.handleCSSChange}
|
||||
/>
|
||||
</div>
|
||||
</EuiPanel>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<div className="kbnTabs" role="tablist">
|
||||
<button
|
||||
role="tab"
|
||||
aria-selected={selectedTab === 'markdown'}
|
||||
className={`kbnTabs__tab${selectedTab === 'markdown' && '-active' || ''}`}
|
||||
<EuiTabs size="s">
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'markdown'}
|
||||
onClick={() => this.switchTab('markdown')}
|
||||
>Markdown
|
||||
</button>
|
||||
<button
|
||||
>
|
||||
Markdown
|
||||
</EuiTab>
|
||||
<EuiTab
|
||||
data-test-subj="markdownDataBtn"
|
||||
role="tab"
|
||||
aria-selected={selectedTab === 'data'}
|
||||
className={`kbnTabs__tab${selectedTab === 'data' && '-active' || ''}`}
|
||||
isSelected={selectedTab === 'data'}
|
||||
onClick={() => this.switchTab('data')}
|
||||
>Data
|
||||
</button>
|
||||
<button
|
||||
role="tab"
|
||||
aria-selected={selectedTab === 'options'}
|
||||
className={`kbnTabs__tab${selectedTab === 'options' && '-active' || ''}`}
|
||||
>
|
||||
Data
|
||||
</EuiTab>
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'options'}
|
||||
onClick={() => this.switchTab('options')}
|
||||
>Panel Options
|
||||
</button>
|
||||
</div>
|
||||
>
|
||||
Panel options
|
||||
</EuiTab>
|
||||
</EuiTabs>
|
||||
{view}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -25,7 +25,20 @@ import createTextHandler from '../lib/create_text_handler';
|
|||
import ColorRules from '../color_rules';
|
||||
import YesNo from '../yes_no';
|
||||
import uuid from 'uuid';
|
||||
import { htmlIdGenerator } from '@elastic/eui';
|
||||
import {
|
||||
htmlIdGenerator,
|
||||
EuiTabs,
|
||||
EuiTab,
|
||||
EuiPanel,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormRow,
|
||||
EuiFormLabel,
|
||||
EuiSpacer,
|
||||
EuiFieldText,
|
||||
EuiTitle,
|
||||
EuiHorizontalRule,
|
||||
} from '@elastic/eui';
|
||||
|
||||
class MetricPanelConfig extends Component {
|
||||
|
||||
|
@ -67,62 +80,77 @@ class MetricPanelConfig extends Component {
|
|||
);
|
||||
} else {
|
||||
view = (
|
||||
<div className="vis_editor__container">
|
||||
<IndexPattern
|
||||
fields={this.props.fields}
|
||||
model={this.props.model}
|
||||
onChange={this.props.onChange}
|
||||
/>
|
||||
<div className="vis_editor__vis_config-row">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('panelFilter')}>
|
||||
Panel Filter
|
||||
</label>
|
||||
<input
|
||||
id={htmlId('panelFilter')}
|
||||
className="vis_editor__input-grows"
|
||||
type="text"
|
||||
onChange={handleTextChange('filter')}
|
||||
value={model.filter}
|
||||
/>
|
||||
<div className="vis_editor__label">Ignore Global Filter</div>
|
||||
<YesNo
|
||||
value={model.ignore_global_filter}
|
||||
name="ignore_global_filter"
|
||||
<div className="tvbPanelConfig__container">
|
||||
<EuiPanel>
|
||||
<EuiTitle size="s"><span>Data</span></EuiTitle>
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
<IndexPattern
|
||||
fields={this.props.fields}
|
||||
model={this.props.model}
|
||||
onChange={this.props.onChange}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div className="vis_editor__label">Color Rules</div>
|
||||
</div>
|
||||
<div className="vis_editor__vis_config-row">
|
||||
|
||||
<EuiHorizontalRule />
|
||||
|
||||
<EuiFlexGroup responsive={false} wrap={true}>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('panelFilter')}
|
||||
label="Panel filter"
|
||||
fullWidth
|
||||
>
|
||||
<EuiFieldText
|
||||
onChange={handleTextChange('filter')}
|
||||
value={model.filter}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel>Ignore global filter?</EuiFormLabel>
|
||||
<EuiSpacer size="s" />
|
||||
<YesNo
|
||||
value={model.ignore_global_filter}
|
||||
name="ignore_global_filter"
|
||||
onChange={this.props.onChange}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiPanel>
|
||||
|
||||
<EuiSpacer />
|
||||
|
||||
<EuiPanel>
|
||||
<EuiTitle size="s"><span>Color rules</span></EuiTitle>
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
<ColorRules
|
||||
model={model}
|
||||
onChange={this.props.onChange}
|
||||
name="background_color_rules"
|
||||
/>
|
||||
</div>
|
||||
</EuiPanel>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<div className="kbnTabs" role="tablist">
|
||||
<button
|
||||
role="tab"
|
||||
aria-selected={selectedTab === 'data'}
|
||||
className={`kbnTabs__tab${selectedTab === 'data' && '-active' || ''}`}
|
||||
<EuiTabs size="s">
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'data'}
|
||||
onClick={() => this.switchTab('data')}
|
||||
>Data
|
||||
</button>
|
||||
<button
|
||||
role="tab"
|
||||
aria-selected={selectedTab === 'options'}
|
||||
className={`kbnTabs__tab${selectedTab === 'options' && '-active' || ''}`}
|
||||
>
|
||||
Data
|
||||
</EuiTab>
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'options'}
|
||||
onClick={() => this.switchTab('options')}
|
||||
data-test-subj="metricEditorPanelOptionsBtn"
|
||||
>Panel Options
|
||||
</button>
|
||||
</div>
|
||||
>
|
||||
Panel options
|
||||
</EuiTab>
|
||||
</EuiTabs>
|
||||
{view}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -26,7 +26,22 @@ import createTextHandler from '../lib/create_text_handler';
|
|||
import createSelectHandler from '../lib/create_select_handler';
|
||||
import uuid from 'uuid';
|
||||
import YesNo from '../yes_no';
|
||||
import { htmlIdGenerator } from '@elastic/eui';
|
||||
import {
|
||||
htmlIdGenerator,
|
||||
EuiTabs,
|
||||
EuiTab,
|
||||
EuiPanel,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormRow,
|
||||
EuiFormLabel,
|
||||
EuiSpacer,
|
||||
EuiFieldText,
|
||||
EuiTitle,
|
||||
EuiHorizontalRule,
|
||||
EuiCode,
|
||||
EuiText,
|
||||
} from '@elastic/eui';
|
||||
|
||||
class TablePanelConfig extends Component {
|
||||
|
||||
|
@ -59,45 +74,63 @@ class TablePanelConfig extends Component {
|
|||
if (selectedTab === 'data') {
|
||||
view = (
|
||||
<div>
|
||||
<div className="vis_editor__table-pivot-fields">
|
||||
<div className="vis_editor__container">
|
||||
<div className="vis_editor__vis_config-row">
|
||||
<div className="tvbPanelConfig__container">
|
||||
<EuiPanel>
|
||||
<EuiText>
|
||||
<p>
|
||||
For the table visualization you need to define a field to
|
||||
group by using a terms aggregation.
|
||||
</p>
|
||||
</div>
|
||||
<div className="vis_editor__vis_config-row">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('field')}>Group By Field</label>
|
||||
<div className="vis_editor__row_item" data-test-subj="groupByField">
|
||||
<FieldSelect
|
||||
id={htmlId('field')}
|
||||
fields={this.props.fields}
|
||||
value={model.pivot_id}
|
||||
indexPattern={model.index_pattern}
|
||||
onChange={handleSelectChange('pivot_id')}
|
||||
/>
|
||||
</div>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('pivotLabelInput')}>Column Label</label>
|
||||
<input
|
||||
id={htmlId('pivotLabelInput')}
|
||||
className="vis_editor__input-grows"
|
||||
data-test-subj="columnLabelName"
|
||||
type="text"
|
||||
onChange={handleTextChange('pivot_label')}
|
||||
value={model.pivot_label}
|
||||
/>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('pivotRowsInput')}>Rows</label>
|
||||
<input
|
||||
id={htmlId('pivotRowsInput')}
|
||||
className="vis_editor__input-number"
|
||||
type="number"
|
||||
onChange={handleTextChange('pivot_rows')}
|
||||
value={model.pivot_rows}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</EuiText>
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
<EuiFlexGroup responsive={false} wrap={true}>
|
||||
<EuiFlexItem data-test-subj="groupByField">
|
||||
<EuiFormRow id={htmlId('field')} label="Group by field">
|
||||
<FieldSelect
|
||||
fields={this.props.fields}
|
||||
value={model.pivot_id}
|
||||
indexPattern={model.index_pattern}
|
||||
onChange={handleSelectChange('pivot_id')}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('pivotLabelInput')}
|
||||
label="Column label"
|
||||
fullWidth
|
||||
>
|
||||
<EuiFieldText
|
||||
data-test-subj="columnLabelName"
|
||||
onChange={handleTextChange('pivot_label')}
|
||||
value={model.pivot_label}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow
|
||||
id={htmlId('pivotRowsInput')}
|
||||
label="Rows"
|
||||
>
|
||||
{/*
|
||||
EUITODO: The following input couldn't be converted to EUI because of type mis-match.
|
||||
Should it be number or string?
|
||||
*/}
|
||||
<input
|
||||
className="tvbAgg__input"
|
||||
type="number"
|
||||
onChange={handleTextChange('pivot_rows')}
|
||||
value={model.pivot_rows}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiPanel>
|
||||
</div>
|
||||
|
||||
<SeriesEditor
|
||||
fields={this.props.fields}
|
||||
model={this.props.model}
|
||||
|
@ -108,59 +141,81 @@ class TablePanelConfig extends Component {
|
|||
);
|
||||
} else {
|
||||
view = (
|
||||
<div className="vis_editor__container">
|
||||
<div className="vis_editor__vis_config-row">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('drilldownInput')}>Item Url (This supports mustache templating.
|
||||
<code>{'{{key}}'}</code> is set to the term)
|
||||
</label>
|
||||
<input
|
||||
<div className="tvbPanelConfig__container">
|
||||
<EuiPanel>
|
||||
<EuiTitle size="s"><span>Data</span></EuiTitle>
|
||||
<EuiSpacer size="m" />
|
||||
<EuiFormRow
|
||||
id={htmlId('drilldownInput')}
|
||||
className="vis_editor__input-grows"
|
||||
onChange={handleTextChange('drilldown_url')}
|
||||
value={model.drilldown_url}
|
||||
/>
|
||||
</div>
|
||||
<IndexPattern
|
||||
fields={this.props.fields}
|
||||
model={this.props.model}
|
||||
onChange={this.props.onChange}
|
||||
/>
|
||||
<div className="vis_editor__vis_config-row">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('panelFilterInput')}>Panel Filter</label>
|
||||
<input
|
||||
id={htmlId('panelFilterInput')}
|
||||
className="vis_editor__input-grows"
|
||||
type="text"
|
||||
onChange={handleTextChange('filter')}
|
||||
value={model.filter}
|
||||
/>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('globalFilterOption')}>Ignore Global Filter</label>
|
||||
<YesNo
|
||||
id={htmlId('globalFilterOption')}
|
||||
value={model.ignore_global_filter}
|
||||
name="ignore_global_filter"
|
||||
label="Item url"
|
||||
helpText={
|
||||
<span>
|
||||
This supports mustache templating.
|
||||
<EuiCode>{'{{key}}'}</EuiCode> is set to the term.
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<EuiFieldText
|
||||
onChange={handleTextChange('drilldown_url')}
|
||||
value={model.drilldown_url}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
|
||||
<EuiHorizontalRule />
|
||||
|
||||
<IndexPattern
|
||||
fields={this.props.fields}
|
||||
model={this.props.model}
|
||||
onChange={this.props.onChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<EuiHorizontalRule />
|
||||
|
||||
<EuiFlexGroup responsive={false} wrap={true}>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('panelFilterInput')}
|
||||
label="Panel filter"
|
||||
fullWidth
|
||||
>
|
||||
<EuiFieldText
|
||||
onChange={handleTextChange('filter')}
|
||||
value={model.filter}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel htmlFor={htmlId('globalFilterOption')}>Ignore global filter?</EuiFormLabel>
|
||||
<EuiSpacer size="s" />
|
||||
<YesNo
|
||||
id={htmlId('globalFilterOption')}
|
||||
value={model.ignore_global_filter}
|
||||
name="ignore_global_filter"
|
||||
onChange={this.props.onChange}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiPanel>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<div className="kbnTabs">
|
||||
<div
|
||||
className={`kbnTabs__tab${selectedTab === 'data' && '-active' || ''}`}
|
||||
<EuiTabs size="s">
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'data'}
|
||||
onClick={() => this.switchTab('data')}
|
||||
>
|
||||
Columns
|
||||
</div>
|
||||
<div
|
||||
className={`kbnTabs__tab${selectedTab === 'options' && '-active' || ''}`}
|
||||
</EuiTab>
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'options'}
|
||||
onClick={() => this.switchTab('options')}
|
||||
>
|
||||
Panel Options
|
||||
</div>
|
||||
</div>
|
||||
Panel options
|
||||
</EuiTab>
|
||||
</EuiTabs>
|
||||
{view}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -29,6 +29,17 @@ import YesNo from '../yes_no';
|
|||
import {
|
||||
htmlIdGenerator,
|
||||
EuiComboBox,
|
||||
EuiTabs,
|
||||
EuiTab,
|
||||
EuiPanel,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormRow,
|
||||
EuiFormLabel,
|
||||
EuiSpacer,
|
||||
EuiFieldText,
|
||||
EuiTitle,
|
||||
EuiHorizontalRule,
|
||||
} from '@elastic/eui';
|
||||
|
||||
class TimeseriesPanelConfig extends Component {
|
||||
|
@ -99,127 +110,165 @@ class TimeseriesPanelConfig extends Component {
|
|||
);
|
||||
} else {
|
||||
view = (
|
||||
<div className="vis_editor__container">
|
||||
<IndexPattern
|
||||
fields={this.props.fields}
|
||||
model={this.props.model}
|
||||
onChange={this.props.onChange}
|
||||
/>
|
||||
<div className="vis_editor__vis_config-row">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('axisMin')}>Axis Min</label>
|
||||
<input
|
||||
id={htmlId('axisMin')}
|
||||
className="vis_editor__input-grows"
|
||||
type="text"
|
||||
onChange={handleTextChange('axis_min')}
|
||||
value={model.axis_min}
|
||||
/>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('axisMax')}>Axis Max</label>
|
||||
<input
|
||||
id={htmlId('axisMax')}
|
||||
className="vis_editor__input-grows"
|
||||
type="text"
|
||||
onChange={handleTextChange('axis_max')}
|
||||
value={model.axis_max}
|
||||
/>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('axisPos')}>Axis Position</label>
|
||||
<div className="vis_editor__row_item">
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
id={htmlId('axisPos')}
|
||||
options={positionOptions}
|
||||
selectedOptions={selectedPositionOption ? [selectedPositionOption] : []}
|
||||
onChange={handleSelectChange('axis_position')}
|
||||
singleSelection={true}
|
||||
/>
|
||||
</div>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('axisPos')}>Axis Scale</label>
|
||||
<div className="vis_editor__row_item">
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
id={htmlId('axisScale')}
|
||||
options={scaleOptions}
|
||||
selectedOptions={selectedAxisScaleOption ? [selectedAxisScaleOption] : []}
|
||||
onChange={handleSelectChange('axis_scale')}
|
||||
singleSelection={true}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="vis_editor__vis_config-row">
|
||||
<div className="vis_editor__label">Background Color</div>
|
||||
<ColorPicker
|
||||
onChange={this.props.onChange}
|
||||
name="background_color"
|
||||
value={model.background_color}
|
||||
/>
|
||||
<div className="vis_editor__label">Show Legend</div>
|
||||
<YesNo
|
||||
value={model.show_legend}
|
||||
name="show_legend"
|
||||
<div className="tvbPanelConfig__container">
|
||||
<EuiPanel>
|
||||
<EuiTitle size="s"><span>Data</span></EuiTitle>
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
<IndexPattern
|
||||
fields={this.props.fields}
|
||||
model={this.props.model}
|
||||
onChange={this.props.onChange}
|
||||
/>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('legendPos')}>Legend Position</label>
|
||||
<div className="vis_editor__row_item">
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
id={htmlId('legendPos')}
|
||||
options={legendPositionOptions}
|
||||
selectedOptions={selectedLegendPosOption ? [selectedLegendPosOption] : []}
|
||||
onChange={handleSelectChange('legend_position')}
|
||||
singleSelection={true}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__label">Display Grid</div>
|
||||
<YesNo
|
||||
value={model.show_grid}
|
||||
name="show_grid"
|
||||
onChange={this.props.onChange}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__vis_config-row">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('panelFilter')}>Panel Filter</label>
|
||||
<input
|
||||
id={htmlId('panelFilter')}
|
||||
className="vis_editor__input-grows"
|
||||
type="text"
|
||||
onChange={handleTextChange('filter')}
|
||||
value={model.filter}
|
||||
/>
|
||||
<div className="vis_editor__label">Ignore Global Filter</div>
|
||||
<YesNo
|
||||
value={model.ignore_global_filter}
|
||||
name="ignore_global_filter"
|
||||
onChange={this.props.onChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<EuiHorizontalRule />
|
||||
|
||||
<EuiFlexGroup responsive={false} wrap={true}>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('panelFilter')}
|
||||
label="Panel filter"
|
||||
fullWidth
|
||||
>
|
||||
<EuiFieldText
|
||||
onChange={handleTextChange('filter')}
|
||||
value={model.filter}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel>Ignore global filter?</EuiFormLabel>
|
||||
<EuiSpacer size="s" />
|
||||
<YesNo
|
||||
value={model.ignore_global_filter}
|
||||
name="ignore_global_filter"
|
||||
onChange={this.props.onChange}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiPanel>
|
||||
|
||||
<EuiSpacer />
|
||||
|
||||
<EuiPanel>
|
||||
<EuiTitle size="s"><span>Style</span></EuiTitle>
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
<EuiFlexGroup responsive={false} wrap={true} alignItems="center">
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('axisMin')} label="Axis min">
|
||||
<EuiFieldText
|
||||
onChange={handleTextChange('axis_min')}
|
||||
value={model.axis_min}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('axisMax')} label="Axis max">
|
||||
<EuiFieldText
|
||||
onChange={handleTextChange('axis_max')}
|
||||
value={model.axis_max}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('axisPos')} label="Axis position">
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
options={positionOptions}
|
||||
selectedOptions={selectedPositionOption ? [selectedPositionOption] : []}
|
||||
onChange={handleSelectChange('axis_position')}
|
||||
singleSelection={{ asPlainText: true }}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('axisScale')} label="Axis scale">
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
options={scaleOptions}
|
||||
selectedOptions={selectedAxisScaleOption ? [selectedAxisScaleOption] : []}
|
||||
onChange={handleSelectChange('axis_scale')}
|
||||
singleSelection={{ asPlainText: true }}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
<EuiHorizontalRule />
|
||||
|
||||
<EuiFlexGroup responsive={false} wrap={true} alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel style={{ marginBottom: 0 }}>Background color:</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<ColorPicker
|
||||
onChange={this.props.onChange}
|
||||
name="background_color"
|
||||
value={model.background_color}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel style={{ marginBottom: 0 }}>Show legend?</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<YesNo
|
||||
value={model.show_legend}
|
||||
name="show_legend"
|
||||
onChange={this.props.onChange}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel style={{ marginBottom: 0 }} htmlFor={htmlId('legendPos')}>Legend position</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
id={htmlId('legendPos')}
|
||||
options={legendPositionOptions}
|
||||
selectedOptions={selectedLegendPosOption ? [selectedLegendPosOption] : []}
|
||||
onChange={handleSelectChange('legend_position')}
|
||||
singleSelection={{ asPlainText: true }}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel style={{ marginBottom: 0 }}>Display grid</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<YesNo
|
||||
value={model.show_grid}
|
||||
name="show_grid"
|
||||
onChange={this.props.onChange}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiPanel>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<div className="kbnTabs" role="tablist">
|
||||
<button
|
||||
role="tab"
|
||||
aria-selected={selectedTab === 'data'}
|
||||
className={`kbnTabs__tab${selectedTab === 'data' && '-active' || ''}`}
|
||||
<EuiTabs size="s">
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'data'}
|
||||
onClick={() => this.switchTab('data')}
|
||||
>Data
|
||||
</button>
|
||||
<button
|
||||
role="tab"
|
||||
aria-selected={selectedTab === 'options'}
|
||||
className={`kbnTabs__tab${selectedTab === 'options' && '-active' || ''}`}
|
||||
>
|
||||
Data
|
||||
</EuiTab>
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'options'}
|
||||
onClick={() => this.switchTab('options')}
|
||||
>Panel Options
|
||||
</button>
|
||||
<button
|
||||
role="tab"
|
||||
aria-selected={selectedTab === 'annotations'}
|
||||
className={`kbnTabs__tab${selectedTab === 'annotations' && '-active' || ''}`}
|
||||
>
|
||||
Panel options
|
||||
</EuiTab>
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'annotations'}
|
||||
onClick={() => this.switchTab('annotations')}
|
||||
>Annotations
|
||||
</button>
|
||||
</div>
|
||||
>
|
||||
Annotations
|
||||
</EuiTab>
|
||||
</EuiTabs>
|
||||
{view}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -26,7 +26,21 @@ import ColorRules from '../color_rules';
|
|||
import ColorPicker from '../color_picker';
|
||||
import uuid from 'uuid';
|
||||
import YesNo from '../yes_no';
|
||||
import { htmlIdGenerator } from '@elastic/eui';
|
||||
import {
|
||||
htmlIdGenerator,
|
||||
EuiTabs,
|
||||
EuiTab,
|
||||
EuiPanel,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormRow,
|
||||
EuiFormLabel,
|
||||
EuiSpacer,
|
||||
EuiFieldText,
|
||||
EuiTitle,
|
||||
EuiHorizontalRule,
|
||||
EuiCode,
|
||||
} from '@elastic/eui';
|
||||
|
||||
class TopNPanelConfig extends Component {
|
||||
|
||||
|
@ -67,52 +81,85 @@ class TopNPanelConfig extends Component {
|
|||
);
|
||||
} else {
|
||||
view = (
|
||||
<div className="vis_editor__container">
|
||||
<div className="vis_editor__vis_config-row">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('itemUrl')}>
|
||||
Item Url (This supports mustache templating.
|
||||
<code>{'{{key}}'}</code> is set to the term)
|
||||
</label>
|
||||
<input
|
||||
<div className="tvbPanelConfig__container">
|
||||
<EuiPanel>
|
||||
<EuiTitle size="s"><span>Data</span></EuiTitle>
|
||||
<EuiSpacer size="m" />
|
||||
<EuiFormRow
|
||||
id={htmlId('itemUrl')}
|
||||
className="vis_editor__input-grows"
|
||||
onChange={handleTextChange('drilldown_url')}
|
||||
value={model.drilldown_url}
|
||||
/>
|
||||
</div>
|
||||
<IndexPattern
|
||||
fields={this.props.fields}
|
||||
model={this.props.model}
|
||||
onChange={this.props.onChange}
|
||||
/>
|
||||
<div className="vis_editor__vis_config-row">
|
||||
<div className="vis_editor__label">Background Color</div>
|
||||
<ColorPicker
|
||||
onChange={this.props.onChange}
|
||||
name="background_color"
|
||||
value={model.background_color}
|
||||
/>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('panelFilter')}>
|
||||
Panel Filter
|
||||
</label>
|
||||
<input
|
||||
id={htmlId('panelFilter')}
|
||||
className="vis_editor__input-grows"
|
||||
type="text"
|
||||
onChange={handleTextChange('filter')}
|
||||
value={model.filter}
|
||||
/>
|
||||
<div className="vis_editor__label">Ignore Global Filter</div>
|
||||
<YesNo
|
||||
value={model.ignore_global_filter}
|
||||
name="ignore_global_filter"
|
||||
label="Item url"
|
||||
helpText={
|
||||
<span>
|
||||
This supports mustache templating.
|
||||
<EuiCode>{'{{key}}'}</EuiCode> is set to the term.
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<EuiFieldText
|
||||
onChange={handleTextChange('drilldown_url')}
|
||||
value={model.drilldown_url}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
|
||||
<EuiHorizontalRule />
|
||||
|
||||
<IndexPattern
|
||||
fields={this.props.fields}
|
||||
model={this.props.model}
|
||||
onChange={this.props.onChange}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div className="vis_editor__label">Color Rules</div>
|
||||
</div>
|
||||
<div className="vis_editor__vis_config-row">
|
||||
|
||||
<EuiHorizontalRule />
|
||||
|
||||
<EuiFlexGroup responsive={false} wrap={true}>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('panelFilter')}
|
||||
label="Panel filter"
|
||||
fullWidth
|
||||
>
|
||||
<EuiFieldText
|
||||
onChange={handleTextChange('filter')}
|
||||
value={model.filter}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel>Ignore global filter?</EuiFormLabel>
|
||||
<EuiSpacer size="s" />
|
||||
<YesNo
|
||||
value={model.ignore_global_filter}
|
||||
name="ignore_global_filter"
|
||||
onChange={this.props.onChange}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiPanel>
|
||||
|
||||
<EuiSpacer />
|
||||
|
||||
<EuiPanel>
|
||||
<EuiTitle size="s"><span>Style</span></EuiTitle>
|
||||
<EuiSpacer size="m" />
|
||||
|
||||
<EuiFlexGroup responsive={false} wrap={true} alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel style={{ marginBottom: 0 }}>Background color:</EuiFormLabel>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<ColorPicker
|
||||
onChange={this.props.onChange}
|
||||
name="background_color"
|
||||
value={model.background_color}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
<EuiHorizontalRule />
|
||||
|
||||
<EuiTitle size="xxs"><span>Color rules</span></EuiTitle>
|
||||
<EuiSpacer size="s" />
|
||||
<ColorRules
|
||||
model={model}
|
||||
primaryVarName="bar_color"
|
||||
|
@ -121,28 +168,26 @@ class TopNPanelConfig extends Component {
|
|||
onChange={this.props.onChange}
|
||||
name="bar_color_rules"
|
||||
/>
|
||||
</div>
|
||||
</EuiPanel>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<div className="kbnTabs" role="tablist">
|
||||
<button
|
||||
role="tab"
|
||||
aria-selected={selectedTab === 'data'}
|
||||
className={`kbnTabs__tab${selectedTab === 'data' && '-active' || ''}`}
|
||||
<EuiTabs size="s">
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'data'}
|
||||
onClick={() => this.switchTab('data')}
|
||||
>Data
|
||||
</button>
|
||||
<button
|
||||
role="tab"
|
||||
aria-selected={selectedTab === 'options'}
|
||||
className={`kbnTabs__tab${selectedTab === 'options' && '-active' || ''}`}
|
||||
>
|
||||
Data
|
||||
</EuiTab>
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'options'}
|
||||
onClick={() => this.switchTab('options')}
|
||||
>Panel Options
|
||||
</button>
|
||||
</div>
|
||||
>
|
||||
Panel options
|
||||
</EuiTab>
|
||||
</EuiTabs>
|
||||
{view}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -24,7 +24,17 @@ import createSelectHandler from './lib/create_select_handler';
|
|||
import createTextHandler from './lib/create_text_handler';
|
||||
import YesNo from './yes_no';
|
||||
import { IndexPattern } from './index_pattern';
|
||||
import { htmlIdGenerator } from '@elastic/eui';
|
||||
import {
|
||||
htmlIdGenerator,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFieldText,
|
||||
EuiFormRow,
|
||||
EuiCode,
|
||||
EuiHorizontalRule,
|
||||
EuiFormLabel,
|
||||
EuiSpacer,
|
||||
} from '@elastic/eui';
|
||||
|
||||
export const SeriesConfig = props => {
|
||||
const defaults = { offset_time: '', value_template: '' };
|
||||
|
@ -34,65 +44,81 @@ export const SeriesConfig = props => {
|
|||
const htmlId = htmlIdGenerator();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="vis_editor__series_config-container">
|
||||
<div className="vis_editor__series_config-row">
|
||||
<DataFormatPicker
|
||||
onChange={handleSelectChange('formatter')}
|
||||
value={model.formatter}
|
||||
/>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('template')}>
|
||||
Template (eg.<code>{'{{value}}/s'}</code>)
|
||||
</label>
|
||||
<input
|
||||
style={{ width: 100 }}
|
||||
<div className="tvbAggRow">
|
||||
|
||||
<DataFormatPicker
|
||||
onChange={handleSelectChange('formatter')}
|
||||
value={model.formatter}
|
||||
/>
|
||||
|
||||
<EuiHorizontalRule margin="s" />
|
||||
|
||||
<EuiFormRow
|
||||
id={htmlId('series_filter')}
|
||||
label="Filter"
|
||||
fullWidth
|
||||
>
|
||||
<EuiFieldText
|
||||
onChange={handleTextChange('filter')}
|
||||
value={model.filter}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFormRow>
|
||||
|
||||
<EuiHorizontalRule margin="s" />
|
||||
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('template')}
|
||||
className="vis_editor__input-grows"
|
||||
onChange={handleTextChange('value_template')}
|
||||
value={model.value_template}
|
||||
/>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('offsetSeries')}>
|
||||
Offset series time by (1m, 1h, 1w, 1d)
|
||||
</label>
|
||||
<input
|
||||
data-test-subj="offsetTimeSeries"
|
||||
style={{ width: 100 }}
|
||||
label="Template"
|
||||
helpText={<span>eg.<EuiCode>{'{{value}}/s'}</EuiCode></span>}
|
||||
fullWidth
|
||||
>
|
||||
<EuiFieldText
|
||||
onChange={handleTextChange('value_template')}
|
||||
value={model.value_template}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('offsetSeries')}
|
||||
className="vis_editor__input-grows"
|
||||
type="text"
|
||||
onChange={handleTextChange('offset_time')}
|
||||
value={model.offset_time}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__series_config-row">
|
||||
<div className="vis_editor__label">Override Index Pattern</div>
|
||||
label="Offset series time by (1m, 1h, 1w, 1d)"
|
||||
>
|
||||
<EuiFieldText
|
||||
data-test-subj="offsetTimeSeries"
|
||||
onChange={handleTextChange('offset_time')}
|
||||
value={model.offset_time}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
<EuiHorizontalRule margin="s" />
|
||||
|
||||
<EuiFlexGroup gutterSize="s" responsive={false} wrap={true}>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel>Override Index Pattern?</EuiFormLabel>
|
||||
<EuiSpacer size="s" />
|
||||
<YesNo
|
||||
value={model.override_index_pattern}
|
||||
name="override_index_pattern"
|
||||
onChange={props.onChange}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<IndexPattern
|
||||
onChange={props.onChange}
|
||||
model={props.model}
|
||||
fields={props.fields}
|
||||
prefix="series_"
|
||||
className="vis_editor__row_item vis_editor__row"
|
||||
disabled={!model.override_index_pattern}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__series_config-row">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('series_filter')}>
|
||||
Filter
|
||||
</label>
|
||||
<input
|
||||
id={htmlId('series_filter')}
|
||||
className="vis_editor__input-grows"
|
||||
type="text"
|
||||
onChange={handleTextChange('filter')}
|
||||
value={model.filter}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -61,6 +61,7 @@ class SeriesEditor extends Component {
|
|||
const { fields, model, name, limit, colorPicker } = props;
|
||||
return (
|
||||
<Series
|
||||
className="tvbSeriesEditor"
|
||||
colorPicker={colorPicker}
|
||||
disableAdd={model[name].length >= limit}
|
||||
disableDelete={model[name].length < 2}
|
||||
|
@ -88,12 +89,12 @@ class SeriesEditor extends Component {
|
|||
this.props.onChange({ series });
|
||||
};
|
||||
return (
|
||||
<div className="vis_editor__series_editor-container">
|
||||
<div className="tvbSeriesEditor__container">
|
||||
<Sortable
|
||||
dynamic={true}
|
||||
direction="vertical"
|
||||
onSort={handleSort}
|
||||
sortHandle="vis_editor__sort"
|
||||
sortHandle="tvbSeries__sortHandle"
|
||||
>
|
||||
{ series }
|
||||
</Sortable>
|
||||
|
|
|
@ -21,20 +21,23 @@ import createSelectHandler from '../lib/create_select_handler';
|
|||
import GroupBySelect from './group_by_select';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { htmlIdGenerator, EuiFlexGroup, EuiFlexItem, EuiFormRow } from '@elastic/eui';
|
||||
|
||||
function SplitByEverything(props) {
|
||||
const { onChange, model } = props;
|
||||
const htmlId = htmlIdGenerator();
|
||||
const handleSelectChange = createSelectHandler(onChange);
|
||||
return (
|
||||
<div className="vis_editor__split-container">
|
||||
<div className="vis_editor__label">Group By</div>
|
||||
<div className="vis_editor__split-selects">
|
||||
<GroupBySelect
|
||||
value={model.split_mode}
|
||||
onChange={handleSelectChange('split_mode')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<EuiFlexGroup alignItems="center">
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('group')} label="Group by">
|
||||
<GroupBySelect
|
||||
value={model.split_mode}
|
||||
onChange={handleSelectChange('split_mode')}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
|
||||
}
|
||||
|
|
|
@ -22,29 +22,34 @@ import createSelectHandler from '../lib/create_select_handler';
|
|||
import GroupBySelect from './group_by_select';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { htmlIdGenerator, EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiFieldText } from '@elastic/eui';
|
||||
|
||||
export const SplitByFilter = props => {
|
||||
const { onChange } = props;
|
||||
const defaults = { filter: '' };
|
||||
const model = { ...defaults, ...props.model };
|
||||
const htmlId = htmlIdGenerator();
|
||||
const handleTextChange = createTextHandler(onChange);
|
||||
const handleSelectChange = createSelectHandler(onChange);
|
||||
return (
|
||||
<div className="vis_editor__split-container">
|
||||
<div className="vis_editor__label">Group By</div>
|
||||
<div className="vis_editor__split-selects">
|
||||
<GroupBySelect
|
||||
value={model.split_mode}
|
||||
onChange={handleSelectChange('split_mode')}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__label">Query String</div>
|
||||
<input
|
||||
className="vis_editor__split-filter"
|
||||
value={model.filter}
|
||||
onChange={handleTextChange('filter')}
|
||||
/>
|
||||
</div>
|
||||
<EuiFlexGroup alignItems="center">
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('group')} label="Group by">
|
||||
<GroupBySelect
|
||||
value={model.split_mode}
|
||||
onChange={handleSelectChange('split_mode')}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('query')} label="Query string">
|
||||
<EuiFieldText
|
||||
value={model.filter}
|
||||
onChange={handleTextChange('filter')}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ import * as collectionActions from '../lib/collection_actions';
|
|||
import AddDeleteButtons from '../add_delete_buttons';
|
||||
import ColorPicker from '../color_picker';
|
||||
import uuid from 'uuid';
|
||||
import { EuiFieldText, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
class FilterItems extends Component {
|
||||
|
||||
constructor(props) {
|
||||
|
@ -53,41 +54,42 @@ class FilterItems extends Component {
|
|||
const handleDelete = collectionActions.handleDelete
|
||||
.bind(null, this.props, model);
|
||||
return (
|
||||
<div className="vis_editor__split-filter-row" key={model.id}>
|
||||
<div className="vis_editor__split-filter-color">
|
||||
<EuiFlexGroup gutterSize="s" className="tvbAggRow" alignItems="center" key={model.id}>
|
||||
<EuiFlexItem grow={false}>
|
||||
<ColorPicker
|
||||
disableTrash={true}
|
||||
onChange={handleChange}
|
||||
name="color"
|
||||
value={model.color}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__split-filter-item">
|
||||
<input
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFieldText
|
||||
placeholder="Filter"
|
||||
className="vis_editor__input-grows-100"
|
||||
type="text"
|
||||
aria-label="Filter"
|
||||
onChange={this.handleChange(model, 'filter')}
|
||||
value={model.filter}
|
||||
fullWidth
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__split-filter-item">
|
||||
<input
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFieldText
|
||||
placeholder="Label"
|
||||
className="vis_editor__input-grows-100"
|
||||
type="text"
|
||||
aria-label="Label"
|
||||
onChange={this.handleChange(model, 'label')}
|
||||
value={model.label}
|
||||
fullWidth
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__split-filter-control">
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<AddDeleteButtons
|
||||
onAdd={handleAdd}
|
||||
onDelete={handleDelete}
|
||||
disableDelete={items.length < 2}
|
||||
responsive={false}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -96,7 +98,7 @@ class FilterItems extends Component {
|
|||
if (!model[name]) return (<div/>);
|
||||
const rows = model[name].map(this.renderRow);
|
||||
return (
|
||||
<div className="vis_editor__split-filters">
|
||||
<div>
|
||||
{ rows }
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -22,29 +22,30 @@ import GroupBySelect from './group_by_select';
|
|||
import FilterItems from './filter_items';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { htmlIdGenerator, EuiFlexGroup, EuiFlexItem, EuiFormRow } from '@elastic/eui';
|
||||
|
||||
function SplitByFilters(props) {
|
||||
const { onChange, model } = props;
|
||||
const htmlId = htmlIdGenerator();
|
||||
const handleSelectChange = createSelectHandler(onChange);
|
||||
return(
|
||||
<div className="vis_editor__item">
|
||||
<div className="vis_editor__split-container">
|
||||
<div className="vis_editor__label">Group By</div>
|
||||
<div className="vis_editor__split-selects">
|
||||
<GroupBySelect
|
||||
value={model.split_mode}
|
||||
onChange={handleSelectChange('split_mode')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="vis_editor__split-container">
|
||||
<div className="vis_editor__row vis_editor__item">
|
||||
<FilterItems
|
||||
name="split_filters"
|
||||
model={model}
|
||||
onChange={onChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<EuiFlexGroup alignItems="center">
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('group')} label="Group by">
|
||||
<GroupBySelect
|
||||
value={model.split_mode}
|
||||
onChange={handleSelectChange('split_mode')}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
<FilterItems
|
||||
name="split_filters"
|
||||
model={model}
|
||||
onChange={onChange}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ function GroupBySelect(props) {
|
|||
});
|
||||
return (
|
||||
<EuiComboBox
|
||||
id={props.id}
|
||||
isClearable={false}
|
||||
options={modeOptions}
|
||||
selectedOptions={[selectedOption]}
|
||||
|
|
|
@ -24,11 +24,10 @@ import createTextHandler from '../lib/create_text_handler';
|
|||
import createSelectHandler from '../lib/create_select_handler';
|
||||
import FieldSelect from '../aggs/field_select';
|
||||
import MetricSelect from '../aggs/metric_select';
|
||||
import {
|
||||
EuiComboBox,
|
||||
} from '@elastic/eui';
|
||||
import { htmlIdGenerator, EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiFieldNumber, EuiComboBox, EuiSpacer } from '@elastic/eui';
|
||||
|
||||
export const SplitByTerms = props => {
|
||||
const htmlId = htmlIdGenerator();
|
||||
const handleTextChange = createTextHandler(props.onChange);
|
||||
const handleSelectChange = createSelectHandler(props.onChange);
|
||||
const { indexPattern } = props;
|
||||
|
@ -47,52 +46,64 @@ export const SplitByTerms = props => {
|
|||
});
|
||||
|
||||
return (
|
||||
<div className="vis_editor__split-container">
|
||||
<div className="vis_editor__label">Group By</div>
|
||||
<div className="vis_editor__split-selects">
|
||||
<GroupBySelect
|
||||
value={model.split_mode}
|
||||
onChange={handleSelectChange('split_mode')}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__label">By</div>
|
||||
<div className="vis_editor__item">
|
||||
<FieldSelect
|
||||
indexPattern={indexPattern}
|
||||
onChange={handleSelectChange('terms_field')}
|
||||
value={model.terms_field}
|
||||
fields={props.fields}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__label">Top</div>
|
||||
<input
|
||||
placeholder="Size..."
|
||||
type="number"
|
||||
value={model.terms_size}
|
||||
className="vis_editor__split-term_count"
|
||||
onChange={handleTextChange('terms_size')}
|
||||
/>
|
||||
<div className="vis_editor__label">Order By</div>
|
||||
<div className="vis_editor__split-aggs">
|
||||
<MetricSelect
|
||||
metrics={metrics}
|
||||
clearable={false}
|
||||
additionalOptions={[defaultCount, terms]}
|
||||
onChange={handleSelectChange('terms_order_by')}
|
||||
restrict="basic"
|
||||
value={model.terms_order_by}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__label">Direction</div>
|
||||
<div className="vis_editor__split-aggs">
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
options={dirOptions}
|
||||
selectedOptions={selectedDirectionOption ? [selectedDirectionOption] : []}
|
||||
onChange={handleSelectChange('terms_direction')}
|
||||
singleSelection={true}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<EuiFlexGroup alignItems="center">
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('group')} label="Group by">
|
||||
<GroupBySelect
|
||||
value={model.split_mode}
|
||||
onChange={handleSelectChange('split_mode')}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('by')} label="By">
|
||||
<FieldSelect
|
||||
indexPattern={indexPattern}
|
||||
onChange={handleSelectChange('terms_field')}
|
||||
value={model.terms_field}
|
||||
fields={props.fields}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
<EuiSpacer />
|
||||
|
||||
<EuiFlexGroup alignItems="center">
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('top')} label="Top">
|
||||
<EuiFieldNumber
|
||||
placeholder="Size"
|
||||
value={Number(model.terms_size)}
|
||||
onChange={handleTextChange('terms_size')}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('order')} label="Order by">
|
||||
<MetricSelect
|
||||
metrics={metrics}
|
||||
clearable={false}
|
||||
additionalOptions={[defaultCount, terms]}
|
||||
onChange={handleSelectChange('terms_order_by')}
|
||||
restrict="basic"
|
||||
value={model.terms_order_by}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow id={htmlId('direction')} label="Direction">
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
options={dirOptions}
|
||||
selectedOptions={selectedDirectionOption ? [selectedDirectionOption] : []}
|
||||
onChange={handleSelectChange('terms_direction')}
|
||||
singleSelection={true}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -149,8 +149,8 @@ class VisEditor extends Component {
|
|||
|
||||
if (model) {
|
||||
return (
|
||||
<div className="vis_editor">
|
||||
<div className="vis-editor-hide-for-reporting">
|
||||
<div className="tvbEditor">
|
||||
<div className="tvbEditor--hideForReporting">
|
||||
<VisPicker model={model} onChange={this.handleChange} />
|
||||
</div>
|
||||
<VisEditorVisualization
|
||||
|
@ -171,7 +171,7 @@ class VisEditor extends Component {
|
|||
dateFormat={this.props.config.get('dateFormat')}
|
||||
onDataChange={this.onDataChange}
|
||||
/>
|
||||
<div className="vis-editor-hide-for-reporting">
|
||||
<div className="tvbEditor--hideForReporting">
|
||||
<PanelConfig
|
||||
fields={this.state.visFields}
|
||||
model={model}
|
||||
|
|
|
@ -19,9 +19,7 @@
|
|||
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { keyCodes } from '@elastic/eui';
|
||||
import Toggle from 'react-toggle';
|
||||
import 'react-toggle/style.css';
|
||||
import { keyCodes, EuiFlexGroup, EuiFlexItem, EuiButton, EuiText, EuiSwitch } from '@elastic/eui';
|
||||
import { getVisualizeLoader } from 'ui/visualize/loader/visualize_loader';
|
||||
|
||||
const MIN_CHART_HEIGHT = 250;
|
||||
|
@ -142,47 +140,41 @@ class VisEditorVisualization extends Component {
|
|||
style.userSelect = 'none';
|
||||
}
|
||||
|
||||
const applyButtonClassName = dirty ? 'thor__button-solid-default' : 'thor__button-outlined-grayLight';
|
||||
let applyMessage = 'The latest changes have been applied.';
|
||||
if (dirty) applyMessage = 'The changes to this visualization have not been applied.';
|
||||
if (autoApply) applyMessage = 'The changes will be automatically applied.';
|
||||
const applyButton = (
|
||||
<div className="vis_editor__dirty_controls">
|
||||
<label
|
||||
className="vis_editor__dirty_controls-toggle-label"
|
||||
id="tsvbAutoApply"
|
||||
htmlFor="tsvbAutoApplyInput"
|
||||
>
|
||||
Auto Apply
|
||||
</label>
|
||||
<div className="vis_editor__dirty_controls-toggle">
|
||||
<Toggle
|
||||
<EuiFlexGroup className="tvbEditorVisualization__apply" alignItems="center">
|
||||
<EuiFlexItem grow={true}>
|
||||
<EuiSwitch
|
||||
id="tsvbAutoApplyInput"
|
||||
defaultChecked={autoApply}
|
||||
icons={false}
|
||||
label="Auto apply"
|
||||
checked={autoApply}
|
||||
onChange={this.props.onToggleAutoApply}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__dirty_controls-button">
|
||||
<button
|
||||
disabled={!dirty}
|
||||
onClick={this.props.onCommit}
|
||||
className={`${applyButtonClassName} md`}
|
||||
>
|
||||
<i className="fa fa-play" /> Apply Changes
|
||||
</button>
|
||||
</div>
|
||||
<div className={`vis_editor__dirty_controls-message${dirty ? '-dirty' : ''}`}>
|
||||
{applyMessage}
|
||||
</div>
|
||||
</div>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiText color={dirty ? 'default' : 'subdued'} size="xs">
|
||||
<p>
|
||||
{applyMessage}
|
||||
</p>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
|
||||
{!autoApply &&
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton iconType="play" fill size="s" onClick={this.props.onCommit} disabled={!dirty}>Apply changes</EuiButton>
|
||||
</EuiFlexItem>
|
||||
}
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
style={style}
|
||||
className="vis_editor__visualization"
|
||||
className="tvbEditorVisualization"
|
||||
data-shared-items-container
|
||||
data-shared-item
|
||||
data-title={this.props.title}
|
||||
|
@ -190,10 +182,10 @@ class VisEditorVisualization extends Component {
|
|||
data-render-complete="disabled"
|
||||
ref={this._visEl}
|
||||
/>
|
||||
<div className="vis-editor-hide-for-reporting">
|
||||
<div className="tvbEditor--hideForReporting">
|
||||
{applyButton}
|
||||
<button
|
||||
className="vis_editor__visualization-draghandle"
|
||||
className="tvbEditorVisualization__draghandle"
|
||||
onMouseDown={this.handleMouseDown}
|
||||
onMouseUp={this.handleMouseUp}
|
||||
onKeyDown={this.onSizeHandleKeyDown}
|
||||
|
|
|
@ -19,36 +19,25 @@
|
|||
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { EuiTabs, EuiTab } from '@elastic/eui';
|
||||
|
||||
function VisPickerItem(props) {
|
||||
const { label, icon, type } = props;
|
||||
let itemClassName = 'vis_editor__vis_picker-item';
|
||||
let iconClassName = 'vis_editor__vis_picker-icon';
|
||||
let labelClassName = 'vis_editor__vis_picker-label';
|
||||
if (props.selected) {
|
||||
itemClassName += ' selected';
|
||||
iconClassName += ' selected';
|
||||
labelClassName += ' selected';
|
||||
}
|
||||
const { label, type, selected } = props;
|
||||
const itemClassName = 'tvbVisPickerItem';
|
||||
|
||||
return (
|
||||
<button
|
||||
role="tab"
|
||||
<EuiTab
|
||||
className={itemClassName}
|
||||
isSelected={selected}
|
||||
onClick={() => props.onClick(type)}
|
||||
data-test-subj={`${type}TsvbTypeBtn`}
|
||||
>
|
||||
<div className={iconClassName}>
|
||||
<i className={`fa ${icon}`} />
|
||||
</div>
|
||||
<div className={labelClassName}>
|
||||
{ label }
|
||||
</div>
|
||||
</button>
|
||||
{ label }
|
||||
</EuiTab>
|
||||
);
|
||||
}
|
||||
|
||||
VisPickerItem.propTypes = {
|
||||
icon: PropTypes.string,
|
||||
label: PropTypes.string,
|
||||
onClick: PropTypes.func,
|
||||
type: PropTypes.string,
|
||||
|
@ -61,13 +50,13 @@ function VisPicker(props) {
|
|||
};
|
||||
|
||||
const { model } = props;
|
||||
const icons = [
|
||||
{ type: 'timeseries', icon: 'fa-line-chart', label: 'Time Series' },
|
||||
{ type: 'metric', icon: 'fa-superscript', label: 'Metric' },
|
||||
{ type: 'top_n', icon: 'fa-bar-chart fa-rotate-90', label: 'Top N' },
|
||||
{ type: 'gauge', icon: 'fa-circle-o-notch', label: 'Gauge' },
|
||||
{ type: 'markdown', icon: 'fa-paragraph', label: 'Markdown' },
|
||||
{ type: 'table', icon: 'fa-paragraph', label: 'Table' }
|
||||
const tabs = [
|
||||
{ type: 'timeseries', label: 'Time Series' },
|
||||
{ type: 'metric', label: 'Metric' },
|
||||
{ type: 'top_n', label: 'Top N' },
|
||||
{ type: 'gauge', label: 'Gauge' },
|
||||
{ type: 'markdown', label: 'Markdown' },
|
||||
{ type: 'table', label: 'Table' }
|
||||
].map(item => {
|
||||
return (
|
||||
<VisPickerItem
|
||||
|
@ -80,9 +69,9 @@ function VisPicker(props) {
|
|||
});
|
||||
|
||||
return (
|
||||
<div className="vis_editor__vis_picker-container" role="tablist">
|
||||
{ icons }
|
||||
</div>
|
||||
<EuiTabs>
|
||||
{ tabs }
|
||||
</EuiTabs>
|
||||
);
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
@import './vis_types';
|
||||
|
||||
@import './markdown/markdown';
|
|
@ -0,0 +1,6 @@
|
|||
.tvbVis {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1 1 100%;
|
||||
padding: $euiSizeS;
|
||||
}
|
|
@ -24,7 +24,7 @@ import AddDeleteButtons from '../../add_delete_buttons';
|
|||
import { SeriesConfig } from '../../series_config';
|
||||
import Sortable from 'react-anything-sortable';
|
||||
import Split from '../../split';
|
||||
import { EuiToolTip } from '@elastic/eui';
|
||||
import { EuiToolTip, EuiTabs, EuiTab, EuiFlexGroup, EuiFlexItem, EuiFieldText, EuiButtonIcon } from '@elastic/eui';
|
||||
import createAggRowRender from '../../lib/create_agg_row_render';
|
||||
import createTextHandler from '../../lib/create_text_handler';
|
||||
import { createUpDownHandler } from '../../lib/sort_keyhandler';
|
||||
|
@ -48,15 +48,11 @@ function GaugeSeries(props) {
|
|||
const handleChange = createTextHandler(onChange);
|
||||
const aggs = model.metrics.map(createAggRowRender(props));
|
||||
|
||||
let caretClassName = 'fa fa-caret-down';
|
||||
if (!visible) caretClassName = 'fa fa-caret-right';
|
||||
let caretIcon = 'arrowDown';
|
||||
if (!visible) caretIcon = 'arrowRight';
|
||||
|
||||
let body = null;
|
||||
if (visible) {
|
||||
let metricsClassName = 'kbnTabs__tab';
|
||||
let optionsClassname = 'kbnTabs__tab';
|
||||
if (selectedTab === 'metrics') metricsClassName += '-active';
|
||||
if (selectedTab === 'options') optionsClassname += '-active';
|
||||
let seriesBody;
|
||||
if (selectedTab === 'metrics') {
|
||||
const handleSort = (data) => {
|
||||
|
@ -70,19 +66,17 @@ function GaugeSeries(props) {
|
|||
dynamic={true}
|
||||
direction="vertical"
|
||||
onSort={handleSort}
|
||||
sortHandle="vis_editor__agg_sort"
|
||||
sortHandle="tvbAggRow__sortHandle"
|
||||
>
|
||||
{ aggs }
|
||||
</Sortable>
|
||||
<div className="vis_editor__series_row">
|
||||
<div className="vis_editor__series_row-item">
|
||||
<Split
|
||||
onChange={props.onChange}
|
||||
fields={fields}
|
||||
panel={panel}
|
||||
model={model}
|
||||
/>
|
||||
</div>
|
||||
<div className="tvbAggRow tvbAggRow--split">
|
||||
<Split
|
||||
onChange={props.onChange}
|
||||
fields={fields}
|
||||
panel={panel}
|
||||
model={model}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -96,24 +90,22 @@ function GaugeSeries(props) {
|
|||
);
|
||||
}
|
||||
body = (
|
||||
<div className="vis_editor__series-row">
|
||||
<div className="kbnTabs sm" role="tablist">
|
||||
<button
|
||||
role="tab"
|
||||
aria-selected={selectedTab === 'metrics'}
|
||||
className={metricsClassName}
|
||||
<div className="tvbSeries__body">
|
||||
<EuiTabs size="s">
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'metrics'}
|
||||
onClick={() => props.switchTab('metrics')}
|
||||
>Metrics
|
||||
</button>
|
||||
<button
|
||||
role="tab"
|
||||
>
|
||||
Metrics
|
||||
</EuiTab>
|
||||
<EuiTab
|
||||
data-test-subj="seriesOptions"
|
||||
aria-selected={selectedTab === 'options'}
|
||||
className={optionsClassname}
|
||||
isSelected={selectedTab === 'options'}
|
||||
onClick={() => props.switchTab('options')}
|
||||
>Options
|
||||
</button>
|
||||
</div>
|
||||
>
|
||||
Options
|
||||
</EuiTab>
|
||||
</EuiTabs>
|
||||
{seriesBody}
|
||||
</div>
|
||||
);
|
||||
|
@ -131,45 +123,54 @@ function GaugeSeries(props) {
|
|||
let dragHandle;
|
||||
if (!props.disableDelete) {
|
||||
dragHandle = (
|
||||
<EuiToolTip content="Sort">
|
||||
<button
|
||||
className="vis_editor__sort thor__button-outlined-default sm"
|
||||
aria-label="Sort series by pressing up/down"
|
||||
onKeyDown={createUpDownHandler(props.onShouldSortItem)}
|
||||
>
|
||||
<i className="fa fa-sort" />
|
||||
</button>
|
||||
</EuiToolTip>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiToolTip content="Drag to sort">
|
||||
<EuiButtonIcon
|
||||
className="tvbSeries__sortHandle"
|
||||
iconType="grab"
|
||||
aria-label="Sort series by pressing up/down"
|
||||
onKeyDown={createUpDownHandler(props.onShouldSortItem)}
|
||||
/>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`${props.className} vis_editor__series`}
|
||||
className={`${props.className}`}
|
||||
style={props.style}
|
||||
onMouseDown={props.onMouseDown}
|
||||
onTouchStart={props.onTouchStart}
|
||||
>
|
||||
<div className="vis_editor__container">
|
||||
<div className="vis_editor__series-details">
|
||||
<button
|
||||
className="vis_editor__series-visibility-toggle"
|
||||
|
||||
<EuiFlexGroup responsive={false} gutterSize="s" alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonIcon
|
||||
iconType={caretIcon}
|
||||
color="text"
|
||||
onClick={props.toggleVisible}
|
||||
aria-label="Toggle series editor"
|
||||
aria-expanded={props.visible}
|
||||
>
|
||||
<i className={caretClassName}/>
|
||||
</button>
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
{ colorPicker }
|
||||
<div className="vis_editor__row vis_editor__row_item">
|
||||
<input
|
||||
className="vis_editor__input-grows"
|
||||
onChange={handleChange('label')}
|
||||
placeholder="Label"
|
||||
value={model.label}
|
||||
/>
|
||||
</div>
|
||||
{ dragHandle }
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem>
|
||||
<EuiFieldText
|
||||
fullWidth
|
||||
onChange={handleChange('label')}
|
||||
placeholder="Label"
|
||||
value={model.label}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
{ dragHandle }
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
<AddDeleteButtons
|
||||
addTooltip="Add Series"
|
||||
deleteTooltip="Delete Series"
|
||||
|
@ -179,9 +180,11 @@ function GaugeSeries(props) {
|
|||
onAdd={onAdd}
|
||||
disableDelete={disableDelete}
|
||||
disableAdd={disableAdd}
|
||||
responsive={false}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
{ body }
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -83,7 +83,7 @@ function GaugeVisualization(props) {
|
|||
const style = { backgroundColor: panelBackgroundColor };
|
||||
|
||||
return (
|
||||
<div className="dashboard__visualization" style={style}>
|
||||
<div className="tvbVis" style={style}>
|
||||
<Gauge {...params} />
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
.tvbMarkdown {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1 0 auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tvbMarkdown__content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1 0 auto;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
overflow: hidden;
|
||||
|
||||
&.middle {
|
||||
justify-content: center;
|
||||
}
|
||||
&.bottom {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
&.scrolling {
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -25,6 +25,7 @@ import Sortable from 'react-anything-sortable';
|
|||
import Split from '../../split';
|
||||
import createAggRowRender from '../../lib/create_agg_row_render';
|
||||
import createTextHandler from '../../lib/create_text_handler';
|
||||
import { EuiTabs, EuiTab, EuiFlexGroup, EuiFlexItem, EuiFieldText, EuiButtonIcon } from '@elastic/eui';
|
||||
|
||||
function MarkdownSeries(props) {
|
||||
const {
|
||||
|
@ -45,15 +46,11 @@ function MarkdownSeries(props) {
|
|||
const handleChange = createTextHandler(onChange);
|
||||
const aggs = model.metrics.map(createAggRowRender(props));
|
||||
|
||||
let caretClassName = 'fa fa-caret-down';
|
||||
if (!visible) caretClassName = 'fa fa-caret-right';
|
||||
let caretIcon = 'arrowDown';
|
||||
if (!visible) caretIcon = 'arrowRight';
|
||||
|
||||
let body = null;
|
||||
if (visible) {
|
||||
let metricsClassName = 'kbnTabs__tab';
|
||||
let optionsClassname = 'kbnTabs__tab';
|
||||
if (selectedTab === 'metrics') metricsClassName += '-active';
|
||||
if (selectedTab === 'options') optionsClassname += '-active';
|
||||
let seriesBody;
|
||||
if (selectedTab === 'metrics') {
|
||||
const handleSort = (data) => {
|
||||
|
@ -67,19 +64,17 @@ function MarkdownSeries(props) {
|
|||
dynamic={true}
|
||||
direction="vertical"
|
||||
onSort={handleSort}
|
||||
sortHandle="vis_editor__agg_sort"
|
||||
sortHandle="tvbAggRow__sortHandle"
|
||||
>
|
||||
{ aggs }
|
||||
</Sortable>
|
||||
<div className="vis_editor__series_row">
|
||||
<div className="vis_editor__series_row-item">
|
||||
<Split
|
||||
onChange={props.onChange}
|
||||
fields={fields}
|
||||
panel={panel}
|
||||
model={model}
|
||||
/>
|
||||
</div>
|
||||
<div className="tvbAggRow tvbAggRow--split">
|
||||
<Split
|
||||
onChange={props.onChange}
|
||||
fields={fields}
|
||||
panel={panel}
|
||||
model={model}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -93,24 +88,22 @@ function MarkdownSeries(props) {
|
|||
);
|
||||
}
|
||||
body = (
|
||||
<div className="vis_editor__series-row">
|
||||
<div className="kbnTabs sm" role="tablist">
|
||||
<button
|
||||
role="tab"
|
||||
aria-selected={selectedTab === 'metrics'}
|
||||
className={metricsClassName}
|
||||
<div className="tvbSeries__body">
|
||||
<EuiTabs size="s">
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'metrics'}
|
||||
onClick={() => props.switchTab('metrics')}
|
||||
>Metrics
|
||||
</button>
|
||||
<button
|
||||
role="tab"
|
||||
>
|
||||
Metrics
|
||||
</EuiTab>
|
||||
<EuiTab
|
||||
data-test-subj="seriesOptions"
|
||||
aria-selected={selectedTab === 'metrics'}
|
||||
className={optionsClassname}
|
||||
isSelected={selectedTab === 'options'}
|
||||
onClick={() => props.switchTab('options')}
|
||||
>Options
|
||||
</button>
|
||||
</div>
|
||||
>
|
||||
Options
|
||||
</EuiTab>
|
||||
</EuiTabs>
|
||||
{seriesBody}
|
||||
</div>
|
||||
);
|
||||
|
@ -118,47 +111,55 @@ function MarkdownSeries(props) {
|
|||
|
||||
return (
|
||||
<div
|
||||
className={`${props.className} vis_editor__series`}
|
||||
className={`${props.className}`}
|
||||
style={props.style}
|
||||
onMouseDown={props.onMouseDown}
|
||||
onTouchStart={props.onTouchStart}
|
||||
>
|
||||
<div className="vis_editor__container">
|
||||
<div className="vis_editor__series-details">
|
||||
<button
|
||||
className="vis_editor__series-visibility-toggle"
|
||||
<EuiFlexGroup responsive={false} gutterSize="s" alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonIcon
|
||||
iconType={caretIcon}
|
||||
color="text"
|
||||
onClick={props.toggleVisible}
|
||||
aria-label="Toggle series editor"
|
||||
aria-expanded={props.visible}
|
||||
>
|
||||
<i className={caretClassName}/>
|
||||
</button>
|
||||
<div className="vis_editor__row vis_editor__row_item">
|
||||
<input
|
||||
className="vis_editor__input-grows vis_editor__row_item"
|
||||
onChange={handleChange('label')}
|
||||
placeholder="Label"
|
||||
value={model.label}
|
||||
/>
|
||||
<input
|
||||
className="vis_editor__input-grows"
|
||||
onChange={handleChange('var_name')}
|
||||
placeholder="Variable Name"
|
||||
value={model.var_name}
|
||||
/>
|
||||
</div>
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem>
|
||||
<EuiFieldText
|
||||
fullWidth
|
||||
onChange={handleChange('label')}
|
||||
placeholder="Label"
|
||||
value={model.label}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem>
|
||||
<EuiFieldText
|
||||
fullWidth
|
||||
onChange={handleChange('var_name')}
|
||||
placeholder="Variable name"
|
||||
value={model.var_name}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
<AddDeleteButtons
|
||||
addTooltip="Add Series"
|
||||
deleteTooltip="Delete Series"
|
||||
cloneTooltip="Clone Series"
|
||||
addTooltip="Add series"
|
||||
deleteTooltip="Delete series"
|
||||
cloneTooltip="Clone series"
|
||||
onDelete={onDelete}
|
||||
onClone={props.onClone}
|
||||
onAdd={onAdd}
|
||||
disableDelete={disableDelete}
|
||||
disableAdd={disableAdd}
|
||||
responsive={false}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
{ body }
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -47,8 +47,8 @@ function MarkdownVisualization(props) {
|
|||
...variables
|
||||
}
|
||||
);
|
||||
let className = 'thorMarkdown';
|
||||
let contentClassName = `thorMarkdown__content ${model.markdown_vertical_align}`;
|
||||
let className = 'tvbMarkdown';
|
||||
let contentClassName = `tvbMarkdown__content ${model.markdown_vertical_align}`;
|
||||
if (model.markdown_scrollbars) contentClassName += ' scrolling';
|
||||
if (reversed) className += ' reversed';
|
||||
const markdownError = markdownSource instanceof Error ? markdownSource : null;
|
||||
|
@ -63,7 +63,7 @@ function MarkdownVisualization(props) {
|
|||
);
|
||||
}
|
||||
return (
|
||||
<div className="dashboard__visualization" style={style}>
|
||||
<div className="tvbVis" style={style}>
|
||||
{markdown}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -24,7 +24,7 @@ import AddDeleteButtons from '../../add_delete_buttons';
|
|||
import { SeriesConfig } from '../../series_config';
|
||||
import Sortable from 'react-anything-sortable';
|
||||
import Split from '../../split';
|
||||
import { EuiToolTip } from '@elastic/eui';
|
||||
import { EuiToolTip, EuiTabs, EuiTab, EuiFlexGroup, EuiFlexItem, EuiFieldText, EuiButtonIcon } from '@elastic/eui';
|
||||
import createAggRowRender from '../../lib/create_agg_row_render';
|
||||
import createTextHandler from '../../lib/create_text_handler';
|
||||
import { createUpDownHandler } from '../../lib/sort_keyhandler';
|
||||
|
@ -48,15 +48,11 @@ function MetricSeries(props) {
|
|||
const handleChange = createTextHandler(onChange);
|
||||
const aggs = model.metrics.map(createAggRowRender(props));
|
||||
|
||||
let caretClassName = 'fa fa-caret-down';
|
||||
if (!visible) caretClassName = 'fa fa-caret-right';
|
||||
let caretIcon = 'arrowDown';
|
||||
if (!visible) caretIcon = 'arrowRight';
|
||||
|
||||
let body = null;
|
||||
if (visible) {
|
||||
let metricsClassName = 'kbnTabs__tab';
|
||||
let optionsClassname = 'kbnTabs__tab';
|
||||
if (selectedTab === 'metrics') metricsClassName += '-active';
|
||||
if (selectedTab === 'options') optionsClassname += '-active';
|
||||
let seriesBody;
|
||||
if (selectedTab === 'metrics') {
|
||||
const handleSort = (data) => {
|
||||
|
@ -70,19 +66,17 @@ function MetricSeries(props) {
|
|||
dynamic={true}
|
||||
direction="vertical"
|
||||
onSort={handleSort}
|
||||
sortHandle="vis_editor__agg_sort"
|
||||
sortHandle="tvbAggRow__sortHandle"
|
||||
>
|
||||
{ aggs }
|
||||
</Sortable>
|
||||
<div className="vis_editor__series_row">
|
||||
<div className="vis_editor__series_row-item">
|
||||
<Split
|
||||
onChange={props.onChange}
|
||||
fields={fields}
|
||||
panel={panel}
|
||||
model={model}
|
||||
/>
|
||||
</div>
|
||||
<div className="tvbAggRow tvbAggRow--split">
|
||||
<Split
|
||||
onChange={props.onChange}
|
||||
fields={fields}
|
||||
panel={panel}
|
||||
model={model}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -96,24 +90,22 @@ function MetricSeries(props) {
|
|||
);
|
||||
}
|
||||
body = (
|
||||
<div className="vis_editor__series-row">
|
||||
<div className="kbnTabs sm" role="tablist">
|
||||
<button
|
||||
role="tab"
|
||||
aria-selected={selectedTab === 'metrics'}
|
||||
className={metricsClassName}
|
||||
<div className="tvbSeries__body">
|
||||
<EuiTabs size="s">
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'metrics'}
|
||||
onClick={() => props.switchTab('metrics')}
|
||||
>Metrics
|
||||
</button>
|
||||
<button
|
||||
role="tab"
|
||||
>
|
||||
Metrics
|
||||
</EuiTab>
|
||||
<EuiTab
|
||||
data-test-subj="seriesOptions"
|
||||
aria-selected={selectedTab === 'options'}
|
||||
className={optionsClassname}
|
||||
isSelected={selectedTab === 'options'}
|
||||
onClick={() => props.switchTab('options')}
|
||||
>Options
|
||||
</button>
|
||||
</div>
|
||||
>
|
||||
Options
|
||||
</EuiTab>
|
||||
</EuiTabs>
|
||||
{seriesBody}
|
||||
</div>
|
||||
);
|
||||
|
@ -122,57 +114,65 @@ function MetricSeries(props) {
|
|||
let colorPicker;
|
||||
if (props.colorPicker) {
|
||||
colorPicker = (
|
||||
<ColorPicker
|
||||
disableTrash={true}
|
||||
onChange={props.onChange}
|
||||
name="color"
|
||||
value={model.color}
|
||||
/>
|
||||
<EuiFlexItem grow={false}>
|
||||
<ColorPicker
|
||||
disableTrash={true}
|
||||
onChange={props.onChange}
|
||||
name="color"
|
||||
value={model.color}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
);
|
||||
}
|
||||
|
||||
let dragHandle;
|
||||
if (!props.disableDelete) {
|
||||
dragHandle = (
|
||||
<EuiToolTip content="Sort">
|
||||
<button
|
||||
className="vis_editor__sort thor__button-outlined-default sm"
|
||||
aria-label="Sort series by pressing up/down"
|
||||
onKeyDown={createUpDownHandler(props.onShouldSortItem)}
|
||||
>
|
||||
<i className="fa fa-sort" />
|
||||
</button>
|
||||
</EuiToolTip>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiToolTip content="Drag to sort">
|
||||
<EuiButtonIcon
|
||||
className="tvbSeries__sortHandle"
|
||||
iconType="grab"
|
||||
aria-label="Sort series by pressing up/down"
|
||||
onKeyDown={createUpDownHandler(props.onShouldSortItem)}
|
||||
/>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`${props.className} vis_editor__series`}
|
||||
className={`${props.className}`}
|
||||
style={props.style}
|
||||
onMouseDown={props.onMouseDown}
|
||||
onTouchStart={props.onTouchStart}
|
||||
>
|
||||
<div className="vis_editor__container">
|
||||
<div className="vis_editor__series-details">
|
||||
<button
|
||||
className="vis_editor__series-visibility-toggle"
|
||||
<EuiFlexGroup responsive={false} gutterSize="s" alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonIcon
|
||||
iconType={caretIcon}
|
||||
color="text"
|
||||
onClick={props.toggleVisible}
|
||||
aria-label="Toggle series editor"
|
||||
aria-expanded={props.visible}
|
||||
>
|
||||
<i className={caretClassName}/>
|
||||
</button>
|
||||
{ colorPicker }
|
||||
<div className="vis_editor__row vis_editor__row_item">
|
||||
<input
|
||||
className="vis_editor__input-grows"
|
||||
onChange={handleChange('label')}
|
||||
placeholder="Label"
|
||||
value={model.label}
|
||||
/>
|
||||
</div>
|
||||
{ dragHandle }
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
{ colorPicker }
|
||||
|
||||
<EuiFlexItem>
|
||||
<EuiFieldText
|
||||
fullWidth
|
||||
onChange={handleChange('label')}
|
||||
placeholder="Label"
|
||||
value={model.label}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
{ dragHandle }
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
<AddDeleteButtons
|
||||
addTooltip="Add Series"
|
||||
deleteTooltip="Delete Series"
|
||||
|
@ -182,9 +182,11 @@ function MetricSeries(props) {
|
|||
onAdd={onAdd}
|
||||
disableDelete={disableDelete}
|
||||
disableAdd={disableAdd}
|
||||
responsive={false}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
{ body }
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -74,8 +74,10 @@ function MetricVisualization(props) {
|
|||
params.reversed = color(panelBackgroundColor).luminosity() < 0.45;
|
||||
}
|
||||
const style = { backgroundColor: panelBackgroundColor };
|
||||
params.backgroundColor = panelBackgroundColor;
|
||||
|
||||
return (
|
||||
<div className="dashboard__visualization" style={style}>
|
||||
<div className="tvbVis" style={style}>
|
||||
<Metric {...params}/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -29,6 +29,15 @@ import ColorRules from '../../color_rules';
|
|||
import {
|
||||
htmlIdGenerator,
|
||||
EuiComboBox,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFieldText,
|
||||
EuiFormRow,
|
||||
EuiCode,
|
||||
EuiHorizontalRule,
|
||||
EuiFormLabel,
|
||||
EuiSpacer,
|
||||
EuiTitle,
|
||||
} from '@elastic/eui';
|
||||
|
||||
class TableSeriesConfig extends Component {
|
||||
|
@ -65,67 +74,102 @@ class TableSeriesConfig extends Component {
|
|||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="vis_editor__series_config-container">
|
||||
<div className="vis_editor__series_config-row">
|
||||
<div className="tvbAggRow">
|
||||
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem grow={false}>
|
||||
<DataFormatPicker
|
||||
onChange={handleSelectChange('formatter')}
|
||||
value={model.formatter}
|
||||
/>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('valueTemplateInput')}>Template (eg.<code>{'{{value}}/s'}</code>)</label>
|
||||
<input
|
||||
id={htmlId('valueTemplateInput')}
|
||||
className="vis_editor__input-grows"
|
||||
onChange={handleTextChange('value_template')}
|
||||
value={model.value_template}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__series_config-row">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('filterInput')}>Filter</label>
|
||||
<input
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('template')}
|
||||
label="Template"
|
||||
helpText={<span>eg.<EuiCode>{'{{value}}/s'}</EuiCode></span>}
|
||||
fullWidth
|
||||
>
|
||||
<EuiFieldText
|
||||
onChange={handleTextChange('value_template')}
|
||||
value={model.value_template}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
<EuiHorizontalRule margin="s" />
|
||||
|
||||
<EuiFlexGroup responsive={false} wrap={true}>
|
||||
<EuiFlexItem grow={true}>
|
||||
<EuiFormRow
|
||||
id={htmlId('filterInput')}
|
||||
className="vis_editor__input-grows"
|
||||
onChange={handleTextChange('filter')}
|
||||
value={model.filter}
|
||||
/>
|
||||
<label className="vis_editor__label">Show Trend Arrows</label>
|
||||
label="Filter"
|
||||
fullWidth
|
||||
>
|
||||
<EuiFieldText
|
||||
onChange={handleTextChange('filter')}
|
||||
value={model.filter}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel>Show trend arrows?</EuiFormLabel>
|
||||
<EuiSpacer size="s" />
|
||||
<YesNo
|
||||
value={model.trend_arrows}
|
||||
name="trend_arrows"
|
||||
onChange={this.props.onChange}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__series_config-row">
|
||||
<div className="vis_editor__row_item">
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
<EuiHorizontalRule margin="s" />
|
||||
|
||||
<EuiFlexGroup responsive={false} wrap={true}>
|
||||
<EuiFlexItem grow={true}>
|
||||
<EuiFormRow id={htmlId('field')} label="Field">
|
||||
<FieldSelect
|
||||
fields={this.props.fields}
|
||||
indexPattern={this.props.panel.index_pattern}
|
||||
value={model.aggregate_by}
|
||||
onChange={handleSelectChange('aggregate_by')}
|
||||
fullWidth
|
||||
/>
|
||||
</div>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('aggregateFunctionInput')}>Aggregate Function</label>
|
||||
<div className="vis_editor__row_item">
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={true}>
|
||||
<EuiFormRow
|
||||
id={htmlId('aggregateFunctionInput')}
|
||||
label="Aggregate function"
|
||||
fullWidth
|
||||
>
|
||||
<EuiComboBox
|
||||
id={htmlId('aggregateFunctionInput')}
|
||||
options={functionOptions}
|
||||
selectedOptions={selectedAggFuncOption ? [selectedAggFuncOption] : []}
|
||||
onChange={handleSelectChange('aggregate_function')}
|
||||
singleSelection={true}
|
||||
fullWidth
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="vis_editor__series_config-row summarize__colorRules">
|
||||
<ColorRules
|
||||
primaryName="text"
|
||||
primaryVarName="text"
|
||||
hideSecondary={true}
|
||||
model={model}
|
||||
onChange={this.props.onChange}
|
||||
name="color_rules"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
<EuiHorizontalRule margin="s" />
|
||||
|
||||
<EuiTitle size="xxs"><span>Color rules</span></EuiTitle>
|
||||
<EuiSpacer size="s" />
|
||||
|
||||
<ColorRules
|
||||
primaryName="text"
|
||||
primaryVarName="text"
|
||||
hideSecondary={true}
|
||||
model={model}
|
||||
onChange={this.props.onChange}
|
||||
name="color_rules"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ import PropTypes from 'prop-types';
|
|||
import AddDeleteButtons from '../../add_delete_buttons';
|
||||
import SeriesConfig from './config';
|
||||
import Sortable from 'react-anything-sortable';
|
||||
import { EuiToolTip } from '@elastic/eui';
|
||||
import { EuiToolTip, EuiTabs, EuiTab, EuiFlexGroup, EuiFlexItem, EuiFieldText, EuiButtonIcon } from '@elastic/eui';
|
||||
import createTextHandler from '../../lib/create_text_handler';
|
||||
import createAggRowRender from '../../lib/create_agg_row_render';
|
||||
import { createUpDownHandler } from '../../lib/sort_keyhandler';
|
||||
|
@ -42,15 +42,11 @@ function TopNSeries(props) {
|
|||
const handleChange = createTextHandler(onChange);
|
||||
const aggs = model.metrics.map(createAggRowRender(props));
|
||||
|
||||
let caretClassName = 'fa fa-caret-down';
|
||||
if (!visible) caretClassName = 'fa fa-caret-right';
|
||||
let caretIcon = 'arrowDown';
|
||||
if (!visible) caretIcon = 'arrowRight';
|
||||
|
||||
let body = null;
|
||||
if (visible) {
|
||||
let metricsClassName = 'kbnTabs__tab';
|
||||
let optionsClassname = 'kbnTabs__tab';
|
||||
if (selectedTab === 'metrics') metricsClassName += '-active';
|
||||
if (selectedTab === 'options') optionsClassname += '-active';
|
||||
let seriesBody;
|
||||
if (selectedTab === 'metrics') {
|
||||
const handleSort = (data) => {
|
||||
|
@ -64,7 +60,7 @@ function TopNSeries(props) {
|
|||
dynamic={true}
|
||||
direction="vertical"
|
||||
onSort={handleSort}
|
||||
sortHandle="vis_editor__agg_sort"
|
||||
sortHandle="tvbAggRow__sortHandle"
|
||||
>
|
||||
{ aggs }
|
||||
</Sortable>
|
||||
|
@ -81,22 +77,22 @@ function TopNSeries(props) {
|
|||
);
|
||||
}
|
||||
body = (
|
||||
<div className="vis_editor__series-row">
|
||||
<div className="kbnTabs sm">
|
||||
<div
|
||||
className={metricsClassName}
|
||||
<div className="tvbSeries__body">
|
||||
<EuiTabs size="s">
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'metrics'}
|
||||
onClick={() => props.switchTab('metrics')}
|
||||
>
|
||||
Metrics
|
||||
</div>
|
||||
<div
|
||||
</EuiTab>
|
||||
<EuiTab
|
||||
data-test-subj="seriesOptions"
|
||||
className={optionsClassname}
|
||||
isSelected={selectedTab === 'options'}
|
||||
onClick={() => props.switchTab('options')}
|
||||
>
|
||||
Options
|
||||
</div>
|
||||
</div>
|
||||
</EuiTab>
|
||||
</EuiTabs>
|
||||
{seriesBody}
|
||||
</div>
|
||||
);
|
||||
|
@ -105,40 +101,50 @@ function TopNSeries(props) {
|
|||
let dragHandle;
|
||||
if (!props.disableDelete) {
|
||||
dragHandle = (
|
||||
<EuiToolTip content="Sort">
|
||||
<button
|
||||
className="vis_editor__sort thor__button-outlined-default sm"
|
||||
aria-label="Sort series by pressing up/down"
|
||||
onKeyDown={createUpDownHandler(props.onShouldSortItem)}
|
||||
>
|
||||
<i className="fa fa-sort" />
|
||||
</button>
|
||||
</EuiToolTip>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiToolTip content="Drag to sort">
|
||||
<EuiButtonIcon
|
||||
className="tvbSeries__sortHandle"
|
||||
iconType="grab"
|
||||
aria-label="Sort series by pressing up/down"
|
||||
onKeyDown={createUpDownHandler(props.onShouldSortItem)}
|
||||
/>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`${props.className} vis_editor__series`}
|
||||
className={`${props.className}`}
|
||||
style={props.style}
|
||||
onMouseDown={props.onMouseDown}
|
||||
onTouchStart={props.onTouchStart}
|
||||
>
|
||||
<div className="vis_editor__container">
|
||||
<div className="vis_editor__series-details">
|
||||
<button className="vis_editor__series-visibility-toggle" onClick={props.toggleVisible}>
|
||||
<i className={caretClassName}/>
|
||||
</button>
|
||||
<div className="vis_editor__row vis_editor__row_item">
|
||||
<input
|
||||
aria-label="Label"
|
||||
className="vis_editor__input-grows"
|
||||
onChange={handleChange('label')}
|
||||
placeholder="Label"
|
||||
value={model.label}
|
||||
/>
|
||||
</div>
|
||||
{ dragHandle }
|
||||
<EuiFlexGroup responsive={false} gutterSize="s" alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonIcon
|
||||
iconType={caretIcon}
|
||||
color="text"
|
||||
onClick={props.toggleVisible}
|
||||
aria-label="Toggle series editor"
|
||||
aria-expanded={props.visible}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem>
|
||||
<EuiFieldText
|
||||
fullWidth
|
||||
aria-label="Label"
|
||||
onChange={handleChange('label')}
|
||||
placeholder="Label"
|
||||
value={model.label}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
{ dragHandle }
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
<AddDeleteButtons
|
||||
addTooltip="Add Series"
|
||||
deleteTooltip="Delete Series"
|
||||
|
@ -148,9 +154,11 @@ function TopNSeries(props) {
|
|||
onAdd={onAdd}
|
||||
disableDelete={disableDelete}
|
||||
disableAdd={disableAdd}
|
||||
responsive={false}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
{ body }
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -23,7 +23,7 @@ import PropTypes from 'prop-types';
|
|||
import tickFormatter from '../../lib/tick_formatter';
|
||||
import calculateLabel from '../../../../common/calculate_label';
|
||||
import { isSortable } from './is_sortable';
|
||||
import { EuiToolTip } from '@elastic/eui';
|
||||
import { EuiToolTip, EuiIcon } from '@elastic/eui';
|
||||
import replaceVars from '../../lib/replace_vars';
|
||||
|
||||
function getColor(rules, colorKey, value) {
|
||||
|
@ -62,24 +62,24 @@ class TableVis extends Component {
|
|||
const value = formatter(item.last);
|
||||
let trend;
|
||||
if (column.trend_arrows) {
|
||||
const trendClass = item.slope > 0 ? 'fa-long-arrow-up' : 'fa-long-arrow-down';
|
||||
const trendIcon = item.slope > 0 ? 'sortUp' : 'sortDown';
|
||||
trend = (
|
||||
<span className="tsvb-table__trend">
|
||||
<i className={`fa ${trendClass}`}/>
|
||||
<span>
|
||||
<EuiIcon type={trendIcon} color="subdued" />
|
||||
</span>
|
||||
);
|
||||
}
|
||||
const style = { color: getColor(column.color_rules, 'text', item.last) };
|
||||
return (
|
||||
<td key={`${rowId}-${item.id}`} className="tsvb-table__value" style={style}>
|
||||
<span className="tsvb-table__value-display">{ value }</span>
|
||||
<td key={`${rowId}-${item.id}`} data-test-subj="tvbTableVis__value" className="eui-textRight" style={style}>
|
||||
<span>{ value }</span>
|
||||
{trend}
|
||||
</td>
|
||||
);
|
||||
});
|
||||
return (
|
||||
<tr key={rowId}>
|
||||
<td className="tsvb-table__fieldName">{rowDisplay}</td>
|
||||
<td>{rowDisplay}</td>
|
||||
{columns}
|
||||
</tr>
|
||||
);
|
||||
|
@ -109,12 +109,12 @@ class TableVis extends Component {
|
|||
if (isSortable(metric)) {
|
||||
let sortIcon;
|
||||
if (sort.column === item.id) {
|
||||
sortIcon = sort.order === 'asc' ? 'sort-asc' : 'sort-desc';
|
||||
sortIcon = sort.order === 'asc' ? 'sortUp' : 'sortDown';
|
||||
} else {
|
||||
sortIcon = 'sort';
|
||||
sortIcon = 'empty';
|
||||
}
|
||||
sortComponent = (
|
||||
<i className={`fa fa-${sortIcon}`} />
|
||||
<EuiIcon type={sortIcon} />
|
||||
);
|
||||
}
|
||||
let headerContent = (
|
||||
|
@ -122,13 +122,12 @@ class TableVis extends Component {
|
|||
);
|
||||
if (!isSortable(metric)) {
|
||||
headerContent = (
|
||||
<EuiToolTip content="This Column is Not Sortable">{headerContent}</EuiToolTip>
|
||||
<EuiToolTip content="This column is not sortable">{headerContent}</EuiToolTip>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<th
|
||||
className="tsvb-table__columnName"
|
||||
onClick={handleClick}
|
||||
key={item.id}
|
||||
scope="col"
|
||||
|
@ -140,12 +139,12 @@ class TableVis extends Component {
|
|||
const label = model.pivot_label || model.pivot_field || model.pivot_id;
|
||||
let sortIcon;
|
||||
if (sort.column === '_default_') {
|
||||
sortIcon = sort.order === 'asc' ? 'sort-asc' : 'sort-desc';
|
||||
sortIcon = sort.order === 'asc' ? 'sortUp' : 'sortDown';
|
||||
} else {
|
||||
sortIcon = 'sort';
|
||||
sortIcon = 'empty';
|
||||
}
|
||||
const sortComponent = (
|
||||
<i className={`fa fa-${sortIcon}`} />
|
||||
<EuiIcon type={sortIcon} />
|
||||
);
|
||||
const handleSortClick = () => {
|
||||
let order;
|
||||
|
@ -158,7 +157,7 @@ class TableVis extends Component {
|
|||
};
|
||||
return (
|
||||
<tr>
|
||||
<th scope="col" onClick={handleSortClick}>{label} {sortComponent}</th>
|
||||
<th className="eui-textLeft" scope="col" onClick={handleSortClick}>{label} {sortComponent}</th>
|
||||
{ columns }
|
||||
</tr>
|
||||
);
|
||||
|
@ -184,7 +183,6 @@ class TableVis extends Component {
|
|||
rows = (
|
||||
<tr>
|
||||
<td
|
||||
className="tsvb-table__noResults"
|
||||
colSpan={model.series.length + 1}
|
||||
>
|
||||
{message}
|
||||
|
@ -193,7 +191,7 @@ class TableVis extends Component {
|
|||
);
|
||||
}
|
||||
return(
|
||||
<div className={`dashboard__visualization ${reversedClass}`} data-test-subj="tableView">
|
||||
<div className={`tvbVis ${reversedClass}`} data-test-subj="tableView">
|
||||
<table className="table">
|
||||
<thead>
|
||||
{header}
|
||||
|
|
|
@ -27,6 +27,15 @@ import { IndexPattern } from '../../index_pattern';
|
|||
import {
|
||||
htmlIdGenerator,
|
||||
EuiComboBox,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFieldText,
|
||||
EuiFormRow,
|
||||
EuiCode,
|
||||
EuiHorizontalRule,
|
||||
EuiFieldNumber,
|
||||
EuiFormLabel,
|
||||
EuiSpacer,
|
||||
} from '@elastic/eui';
|
||||
|
||||
function TimeseriesConfig(props) {
|
||||
|
@ -84,252 +93,311 @@ function TimeseriesConfig(props) {
|
|||
let type;
|
||||
if (model.chart_type === 'line') {
|
||||
type = (
|
||||
<div className="vis_editor__series_config-row">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('chartType')}>
|
||||
Chart Type
|
||||
</label>
|
||||
<div className="vis_editor__item">
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
<EuiFlexGroup gutterSize="s" responsive={false} wrap={true}>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow
|
||||
id={htmlId('chartType')}
|
||||
options={chartTypeOptions}
|
||||
selectedOptions={selectedChartTypeOption ? [selectedChartTypeOption] : []}
|
||||
onChange={handleSelectChange('chart_type')}
|
||||
singleSelection={true}
|
||||
/>
|
||||
</div>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('stacked')}>
|
||||
Stacked
|
||||
</label>
|
||||
<div className="vis_editor__item">
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
label="Chart type"
|
||||
>
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
options={chartTypeOptions}
|
||||
selectedOptions={selectedChartTypeOption ? [selectedChartTypeOption] : []}
|
||||
onChange={handleSelectChange('chart_type')}
|
||||
singleSelection={true}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow
|
||||
id={htmlId('stacked')}
|
||||
options={stackedOptions}
|
||||
selectedOptions={selectedStackedOption ? [selectedStackedOption] : []}
|
||||
onChange={handleSelectChange('stacked')}
|
||||
singleSelection={true}
|
||||
label="Stacked"
|
||||
>
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
options={stackedOptions}
|
||||
selectedOptions={selectedStackedOption ? [selectedStackedOption] : []}
|
||||
onChange={handleSelectChange('stacked')}
|
||||
singleSelection={true}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow
|
||||
id={htmlId('fill')}
|
||||
label="Fill (0 to 1)"
|
||||
>
|
||||
<EuiFieldNumber
|
||||
step={0.1}
|
||||
onChange={handleTextChange('fill')}
|
||||
value={Number(model.fill)}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow
|
||||
id={htmlId('lineWidth')}
|
||||
label="Line width"
|
||||
>
|
||||
<EuiFieldNumber
|
||||
onChange={handleTextChange('line_width')}
|
||||
value={Number(model.line_width)}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow
|
||||
id={htmlId('pointSize')}
|
||||
label="Point size"
|
||||
>
|
||||
<EuiFieldNumber
|
||||
onChange={handleTextChange('point_size')}
|
||||
value={Number(model.point_size)}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel>Steps</EuiFormLabel>
|
||||
<EuiSpacer size="s" />
|
||||
<YesNo
|
||||
value={model.steps}
|
||||
name="steps"
|
||||
onChange={props.onChange}
|
||||
/>
|
||||
</div>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('fill')}>
|
||||
Fill (0 to 1)
|
||||
</label>
|
||||
<input
|
||||
id={htmlId('fill')}
|
||||
className="vis_editor__input-grows"
|
||||
type="number"
|
||||
step="0.1"
|
||||
onChange={handleTextChange('fill')}
|
||||
value={model.fill}
|
||||
/>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('lineWidth')}>
|
||||
Line Width
|
||||
</label>
|
||||
<input
|
||||
id={htmlId('lineWidth')}
|
||||
className="vis_editor__input-grows"
|
||||
type="number"
|
||||
onChange={handleTextChange('line_width')}
|
||||
value={model.line_width}
|
||||
/>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('pointSize')}>
|
||||
Point Size
|
||||
</label>
|
||||
<input
|
||||
id={htmlId('pointSize')}
|
||||
className="vis_editor__input-grows"
|
||||
type="number"
|
||||
onChange={handleTextChange('point_size')}
|
||||
value={model.point_size}
|
||||
/>
|
||||
<div className="vis_editor__label">Steps</div>
|
||||
<YesNo
|
||||
value={model.steps}
|
||||
name="steps"
|
||||
onChange={props.onChange}
|
||||
/>
|
||||
</div>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
if (model.chart_type === 'bar') {
|
||||
type = (
|
||||
<div className="vis_editor__series_config-row">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('chartType')}>
|
||||
Chart Type
|
||||
</label>
|
||||
<div className="vis_editor__item">
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
<EuiFlexGroup gutterSize="s" responsive={false} wrap={true}>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow
|
||||
id={htmlId('chartType')}
|
||||
options={chartTypeOptions}
|
||||
selectedOptions={selectedChartTypeOption ? [selectedChartTypeOption] : []}
|
||||
onChange={handleSelectChange('chart_type')}
|
||||
singleSelection={true}
|
||||
/>
|
||||
</div>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('stacked')}>
|
||||
Stacked
|
||||
</label>
|
||||
<div className="vis_editor__item">
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
label="Chart type"
|
||||
>
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
options={chartTypeOptions}
|
||||
selectedOptions={selectedChartTypeOption ? [selectedChartTypeOption] : []}
|
||||
onChange={handleSelectChange('chart_type')}
|
||||
singleSelection={true}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow
|
||||
id={htmlId('stacked')}
|
||||
options={stackedOptions}
|
||||
selectedOptions={selectedStackedOption ? [selectedStackedOption] : []}
|
||||
onChange={handleSelectChange('stacked')}
|
||||
singleSelection={true}
|
||||
/>
|
||||
</div>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('fill')}>
|
||||
Fill (0 to 1)
|
||||
</label>
|
||||
<input
|
||||
id={htmlId('fill')}
|
||||
className="vis_editor__input-grows"
|
||||
type="number"
|
||||
step="0.5"
|
||||
onChange={handleTextChange('fill')}
|
||||
value={model.fill}
|
||||
/>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('lineWidth')}>
|
||||
Line Width
|
||||
</label>
|
||||
<input
|
||||
id={htmlId('lineWidth')}
|
||||
className="vis_editor__input-grows"
|
||||
type="number"
|
||||
onChange={handleTextChange('line_width')}
|
||||
value={model.line_width}
|
||||
/>
|
||||
</div>
|
||||
label="Stacked"
|
||||
>
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
options={stackedOptions}
|
||||
selectedOptions={selectedStackedOption ? [selectedStackedOption] : []}
|
||||
onChange={handleSelectChange('stacked')}
|
||||
singleSelection={true}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow
|
||||
id={htmlId('fill')}
|
||||
label="Fill (0 to 1)"
|
||||
>
|
||||
<EuiFieldNumber
|
||||
step={0.5}
|
||||
onChange={handleTextChange('fill')}
|
||||
value={Number(model.fill)}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow
|
||||
id={htmlId('lineWidth')}
|
||||
label="Line width"
|
||||
>
|
||||
<EuiFieldNumber
|
||||
onChange={handleTextChange('line_width')}
|
||||
value={Number(model.line_width)}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
|
||||
const disableSeparateYaxis = model.separate_axis ? false : true;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="vis_editor__series_config-container">
|
||||
<div className="vis_editor__series_config-row">
|
||||
<div className="tvbAggRow">
|
||||
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem grow={false}>
|
||||
<DataFormatPicker
|
||||
onChange={handleSelectChange('formatter')}
|
||||
value={model.formatter}
|
||||
/>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('template')}>
|
||||
Template (eg.<code>{'{{value}}/s'}</code>)
|
||||
</label>
|
||||
<input
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiFormRow
|
||||
id={htmlId('template')}
|
||||
className="vis_editor__input-grows"
|
||||
onChange={handleTextChange('value_template')}
|
||||
value={model.value_template}
|
||||
/>
|
||||
</div>
|
||||
{ type }
|
||||
<div className="vis_editor__series_config-row">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('offset')}>
|
||||
Offset series time by (1m, 1h, 1w, 1d)
|
||||
</label>
|
||||
<input
|
||||
label="Template"
|
||||
helpText={<span>eg.<EuiCode>{'{{value}}/s'}</EuiCode></span>}
|
||||
fullWidth
|
||||
>
|
||||
<EuiFieldText
|
||||
onChange={handleTextChange('value_template')}
|
||||
value={model.value_template}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
<EuiHorizontalRule margin="s" />
|
||||
|
||||
<EuiFormRow
|
||||
id={htmlId('series_filter')}
|
||||
label="Filter"
|
||||
fullWidth
|
||||
>
|
||||
<EuiFieldText
|
||||
onChange={handleTextChange('filter')}
|
||||
value={model.filter}
|
||||
fullWidth
|
||||
/>
|
||||
</EuiFormRow>
|
||||
|
||||
<EuiHorizontalRule margin="s" />
|
||||
|
||||
{ type }
|
||||
|
||||
<EuiHorizontalRule margin="s" />
|
||||
|
||||
<EuiFlexGroup responsive={false} wrap={true}>
|
||||
<EuiFlexItem grow={true}>
|
||||
<EuiFormRow
|
||||
id={htmlId('offset')}
|
||||
data-test-subj="offsetTimeSeries"
|
||||
className="vis_editor__input-grows"
|
||||
type="text"
|
||||
onChange={handleTextChange('offset_time')}
|
||||
value={model.offset_time}
|
||||
/>
|
||||
<div className="vis_editor__label">Hide in Legend</div>
|
||||
label="Offset series time by (1m, 1h, 1w, 1d)"
|
||||
>
|
||||
<EuiFieldText
|
||||
data-test-subj="offsetTimeSeries"
|
||||
onChange={handleTextChange('offset_time')}
|
||||
value={model.offset_time}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={true}>
|
||||
<EuiFormLabel>Hide in legend</EuiFormLabel>
|
||||
<EuiSpacer size="s" />
|
||||
<YesNo
|
||||
value={model.hide_in_legend}
|
||||
name="hide_in_legend"
|
||||
onChange={props.onChange}
|
||||
/>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('splitColor')}>
|
||||
Split Color Theme
|
||||
</label>
|
||||
<div className="vis_editor__row_item">
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={true}>
|
||||
<EuiFormRow
|
||||
id={htmlId('splitColor')}
|
||||
label="Split color theme"
|
||||
>
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
id={htmlId('splitColor')}
|
||||
options={splitColorOptions}
|
||||
selectedOptions={selectedSplitColorOption ? [selectedSplitColorOption] : []}
|
||||
onChange={handleSelectChange('split_color_mode')}
|
||||
singleSelection={true}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="vis_editor__series_config-row">
|
||||
<div className="vis_editor__label">Separate Axis</div>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
<EuiHorizontalRule margin="s" />
|
||||
|
||||
<EuiFlexGroup responsive={false} wrap={true}>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel>Separate axis?</EuiFormLabel>
|
||||
<EuiSpacer size="s" />
|
||||
<YesNo
|
||||
value={model.separate_axis}
|
||||
name="separate_axis"
|
||||
onChange={props.onChange}
|
||||
/>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('axisMin')}>
|
||||
Axis Min
|
||||
</label>
|
||||
<input
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow
|
||||
id={htmlId('axisMin')}
|
||||
className="vis_editor__input-grows"
|
||||
type="number"
|
||||
disabled={disableSeparateYaxis}
|
||||
onChange={handleTextChange('axis_min')}
|
||||
value={model.axis_min}
|
||||
/>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('axisMax')}>
|
||||
Axis Max
|
||||
</label>
|
||||
<input
|
||||
label="Axis min"
|
||||
>
|
||||
{/*
|
||||
EUITODO: The following input couldn't be converted to EUI because of type mis-match.
|
||||
It accepts a null value, but is passed a empty string.
|
||||
*/}
|
||||
<input
|
||||
className="tvbAgg__input"
|
||||
type="number"
|
||||
disabled={disableSeparateYaxis}
|
||||
onChange={handleTextChange('axis_min')}
|
||||
value={model.axis_min}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow
|
||||
id={htmlId('axisMax')}
|
||||
className="vis_editor__input-grows"
|
||||
type="number"
|
||||
disabled={disableSeparateYaxis}
|
||||
onChange={handleTextChange('axis_max')}
|
||||
value={model.axis_max}
|
||||
/>
|
||||
<label className="vis_editor__label" htmlFor={htmlId('axisPos')}>
|
||||
Axis Position
|
||||
</label>
|
||||
<div className="vis_editor__row_item">
|
||||
label="Axis max"
|
||||
>
|
||||
{/*
|
||||
EUITODO: The following input couldn't be converted to EUI because of type mis-match.
|
||||
It accepts a null value, but is passed a empty string.
|
||||
*/}
|
||||
<input
|
||||
className="tvbAgg__input"
|
||||
disabled={disableSeparateYaxis}
|
||||
onChange={handleTextChange('axis_max')}
|
||||
value={model.axis_max}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormRow
|
||||
id={htmlId('axisPos')}
|
||||
label="Axis position"
|
||||
>
|
||||
<EuiComboBox
|
||||
isClearable={false}
|
||||
isDisabled={disableSeparateYaxis}
|
||||
id={htmlId('axisPos')}
|
||||
options={positionOptions}
|
||||
selectedOptions={selectedAxisPosOption ? [selectedAxisPosOption] : []}
|
||||
onChange={handleSelectChange('axis_position')}
|
||||
singleSelection={true}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="vis_editor__series_config-row">
|
||||
<div className="vis_editor__label">Override Index Pattern</div>
|
||||
</EuiFormRow>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
<EuiHorizontalRule margin="s" />
|
||||
|
||||
<EuiFlexGroup gutterSize="s" responsive={false} wrap={true}>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFormLabel>Override Index Pattern?</EuiFormLabel>
|
||||
<EuiSpacer size="s" />
|
||||
<YesNo
|
||||
value={model.override_index_pattern}
|
||||
name="override_index_pattern"
|
||||
onChange={props.onChange}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<IndexPattern
|
||||
{...props}
|
||||
prefix="series_"
|
||||
className="vis_editor__row_item vis_editor__row"
|
||||
disabled={!model.override_index_pattern}
|
||||
with-interval={true}
|
||||
/>
|
||||
</div>
|
||||
<div className="vis_editor__series_config-row">
|
||||
<label className="vis_editor__label" htmlFor={htmlId('series_filter')}>
|
||||
Filter
|
||||
</label>
|
||||
<input
|
||||
id={htmlId('series_filter')}
|
||||
className="vis_editor__input-grows"
|
||||
type="text"
|
||||
onChange={handleTextChange('filter')}
|
||||
value={model.filter}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
</div>
|
||||
);
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ import ColorPicker from '../../color_picker';
|
|||
import AddDeleteButtons from '../../add_delete_buttons';
|
||||
import SeriesConfig from './config';
|
||||
import Sortable from 'react-anything-sortable';
|
||||
import { EuiToolTip } from '@elastic/eui';
|
||||
import { EuiToolTip, EuiTabs, EuiTab, EuiFlexGroup, EuiFlexItem, EuiFieldText, EuiButtonIcon } from '@elastic/eui';
|
||||
import Split from '../../split';
|
||||
import createAggRowRender from '../../lib/create_agg_row_render';
|
||||
import createTextHandler from '../../lib/create_text_handler';
|
||||
|
@ -48,15 +48,11 @@ function TimeseriesSeries(props) {
|
|||
const handleChange = createTextHandler(onChange);
|
||||
const aggs = model.metrics.map(createAggRowRender(props));
|
||||
|
||||
let caretClassName = 'fa fa-caret-down';
|
||||
if (!visible) caretClassName = 'fa fa-caret-right';
|
||||
let caretIcon = 'arrowDown';
|
||||
if (!visible) caretIcon = 'arrowRight';
|
||||
|
||||
let body = null;
|
||||
if (visible) {
|
||||
let metricsClassName = 'kbnTabs__tab';
|
||||
let optionsClassname = 'kbnTabs__tab';
|
||||
if (selectedTab === 'metrics') metricsClassName += '-active';
|
||||
if (selectedTab === 'options') optionsClassname += '-active';
|
||||
let seriesBody;
|
||||
if (selectedTab === 'metrics') {
|
||||
const handleSort = (data) => {
|
||||
|
@ -70,19 +66,17 @@ function TimeseriesSeries(props) {
|
|||
dynamic={true}
|
||||
direction="vertical"
|
||||
onSort={handleSort}
|
||||
sortHandle="vis_editor__agg_sort"
|
||||
sortHandle="tvbAggRow__sortHandle"
|
||||
>
|
||||
{ aggs }
|
||||
</Sortable>
|
||||
<div className="vis_editor__series_row">
|
||||
<div className="vis_editor__series_row-item">
|
||||
<Split
|
||||
onChange={props.onChange}
|
||||
fields={fields}
|
||||
panel={panel}
|
||||
model={model}
|
||||
/>
|
||||
</div>
|
||||
<div className="tvbAggRow tvbAggRow--split">
|
||||
<Split
|
||||
onChange={props.onChange}
|
||||
fields={fields}
|
||||
panel={panel}
|
||||
model={model}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -96,24 +90,22 @@ function TimeseriesSeries(props) {
|
|||
);
|
||||
}
|
||||
body = (
|
||||
<div className="vis_editor__series-row">
|
||||
<div className="kbnTabs sm" role="tablist">
|
||||
<button
|
||||
role="tab"
|
||||
aria-selected={selectedTab === 'metrics'}
|
||||
className={metricsClassName}
|
||||
<div className="tvbSeries__body">
|
||||
<EuiTabs size="s">
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'metrics'}
|
||||
onClick={() => props.switchTab('metrics')}
|
||||
>Metrics
|
||||
</button>
|
||||
<button
|
||||
role="tab"
|
||||
>
|
||||
Metrics
|
||||
</EuiTab>
|
||||
<EuiTab
|
||||
data-test-subj="seriesOptions"
|
||||
aria-selected={selectedTab === 'options'}
|
||||
className={optionsClassname}
|
||||
isSelected={selectedTab === 'options'}
|
||||
onClick={() => props.switchTab('options')}
|
||||
>Options
|
||||
</button>
|
||||
</div>
|
||||
>
|
||||
Options
|
||||
</EuiTab>
|
||||
</EuiTabs>
|
||||
{seriesBody}
|
||||
</div>
|
||||
);
|
||||
|
@ -131,45 +123,53 @@ function TimeseriesSeries(props) {
|
|||
let dragHandle;
|
||||
if (!props.disableDelete) {
|
||||
dragHandle = (
|
||||
<EuiToolTip content="Sort">
|
||||
<button
|
||||
className="vis_editor__sort thor__button-outlined-default sm"
|
||||
aria-label="Sort series by pressing up/down"
|
||||
onKeyDown={createUpDownHandler(props.onShouldSortItem)}
|
||||
>
|
||||
<i className="fa fa-sort" />
|
||||
</button>
|
||||
</EuiToolTip>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiToolTip content="Drag to sort">
|
||||
<EuiButtonIcon
|
||||
className="tvbSeries__sortHandle"
|
||||
iconType="grab"
|
||||
aria-label="Sort series by pressing up/down"
|
||||
onKeyDown={createUpDownHandler(props.onShouldSortItem)}
|
||||
/>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`${props.className} vis_editor__series`}
|
||||
className={`${props.className}`}
|
||||
style={props.style}
|
||||
onMouseDown={props.onMouseDown}
|
||||
onTouchStart={props.onTouchStart}
|
||||
>
|
||||
<div className="vis_editor__container">
|
||||
<div className="vis_editor__series-details">
|
||||
<button
|
||||
className="vis_editor__series-visibility-toggle"
|
||||
<EuiFlexGroup responsive={false} gutterSize="s" alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonIcon
|
||||
iconType={caretIcon}
|
||||
color="text"
|
||||
onClick={props.toggleVisible}
|
||||
aria-label="Toggle series editor"
|
||||
aria-expanded={props.visible}
|
||||
>
|
||||
<i className={caretClassName}/>
|
||||
</button>
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
{ colorPicker }
|
||||
<div className="vis_editor__row vis_editor__row_item">
|
||||
<input
|
||||
className="vis_editor__input-grows"
|
||||
onChange={handleChange('label')}
|
||||
placeholder="Label"
|
||||
value={model.label}
|
||||
/>
|
||||
</div>
|
||||
{ dragHandle }
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem>
|
||||
<EuiFieldText
|
||||
fullWidth
|
||||
onChange={handleChange('label')}
|
||||
placeholder="Label"
|
||||
value={model.label}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
{ dragHandle }
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
<AddDeleteButtons
|
||||
addTooltip="Add Series"
|
||||
deleteTooltip="Delete Series"
|
||||
|
@ -179,9 +179,11 @@ function TimeseriesSeries(props) {
|
|||
onAdd={onAdd}
|
||||
disableDelete={disableDelete}
|
||||
disableAdd={disableAdd}
|
||||
responsive={false}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
{ body }
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -201,7 +201,7 @@ class TimeseriesVisualization extends Component {
|
|||
params.reversed = color(panelBackgroundColor || backgroundColor).luminosity() < 0.45;
|
||||
}
|
||||
return (
|
||||
<div className="dashboard__visualization" style={style}>
|
||||
<div className="tvbVis" style={style}>
|
||||
<Timeseries {...params}/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -24,7 +24,7 @@ import AddDeleteButtons from '../../add_delete_buttons';
|
|||
import { SeriesConfig } from '../../series_config';
|
||||
import Sortable from 'react-anything-sortable';
|
||||
import Split from '../../split';
|
||||
import { EuiToolTip } from '@elastic/eui';
|
||||
import { EuiToolTip, EuiTabs, EuiTab, EuiFlexGroup, EuiFlexItem, EuiFieldText, EuiButtonIcon } from '@elastic/eui';
|
||||
import createTextHandler from '../../lib/create_text_handler';
|
||||
import createAggRowRender from '../../lib/create_agg_row_render';
|
||||
import { createUpDownHandler } from '../../lib/sort_keyhandler';
|
||||
|
@ -46,15 +46,11 @@ function TopNSeries(props) {
|
|||
const handleChange = createTextHandler(onChange);
|
||||
const aggs = model.metrics.map(createAggRowRender(props));
|
||||
|
||||
let caretClassName = 'fa fa-caret-down';
|
||||
if (!visible) caretClassName = 'fa fa-caret-right';
|
||||
let caretIcon = 'arrowDown';
|
||||
if (!visible) caretIcon = 'arrowRight';
|
||||
|
||||
let body = null;
|
||||
if (visible) {
|
||||
let metricsClassName = 'kbnTabs__tab';
|
||||
let optionsClassname = 'kbnTabs__tab';
|
||||
if (selectedTab === 'metrics') metricsClassName += '-active';
|
||||
if (selectedTab === 'options') optionsClassname += '-active';
|
||||
let seriesBody;
|
||||
if (selectedTab === 'metrics') {
|
||||
const handleSort = (data) => {
|
||||
|
@ -68,19 +64,17 @@ function TopNSeries(props) {
|
|||
dynamic={true}
|
||||
direction="vertical"
|
||||
onSort={handleSort}
|
||||
sortHandle="vis_editor__agg_sort"
|
||||
sortHandle="tvbAggRow__sortHandle"
|
||||
>
|
||||
{ aggs }
|
||||
</Sortable>
|
||||
<div className="vis_editor__series_row">
|
||||
<div className="vis_editor__series_row-item">
|
||||
<Split
|
||||
onChange={props.onChange}
|
||||
fields={fields}
|
||||
panel={panel}
|
||||
model={model}
|
||||
/>
|
||||
</div>
|
||||
<div className="tvbAggRow tvbAggRow--split">
|
||||
<Split
|
||||
onChange={props.onChange}
|
||||
fields={fields}
|
||||
panel={panel}
|
||||
model={model}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -94,24 +88,22 @@ function TopNSeries(props) {
|
|||
);
|
||||
}
|
||||
body = (
|
||||
<div className="vis_editor__series-row">
|
||||
<div className="kbnTabs sm" role="tablist">
|
||||
<button
|
||||
role="tab"
|
||||
aria-selected={selectedTab === 'metrics'}
|
||||
className={metricsClassName}
|
||||
<div className="tvbSeries__body">
|
||||
<EuiTabs size="s">
|
||||
<EuiTab
|
||||
isSelected={selectedTab === 'metrics'}
|
||||
onClick={() => props.switchTab('metrics')}
|
||||
>Metrics
|
||||
</button>
|
||||
<button
|
||||
role="tab"
|
||||
>
|
||||
Metrics
|
||||
</EuiTab>
|
||||
<EuiTab
|
||||
data-test-subj="seriesOptions"
|
||||
aria-selected={selectedTab === 'options'}
|
||||
className={optionsClassname}
|
||||
isSelected={selectedTab === 'options'}
|
||||
onClick={() => props.switchTab('options')}
|
||||
>Options
|
||||
</button>
|
||||
</div>
|
||||
>
|
||||
Options
|
||||
</EuiTab>
|
||||
</EuiTabs>
|
||||
{seriesBody}
|
||||
</div>
|
||||
);
|
||||
|
@ -129,45 +121,53 @@ function TopNSeries(props) {
|
|||
let dragHandle;
|
||||
if (!props.disableDelete) {
|
||||
dragHandle = (
|
||||
<EuiToolTip content="Sort">
|
||||
<button
|
||||
className="vis_editor__sort thor__button-outlined-default sm"
|
||||
aria-label="Sort series by pressing up/down"
|
||||
onKeyDown={createUpDownHandler(props.onShouldSortItem)}
|
||||
>
|
||||
<i className="fa fa-sort" />
|
||||
</button>
|
||||
</EuiToolTip>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiToolTip content="Drag to sort">
|
||||
<EuiButtonIcon
|
||||
className="tvbSeries__sortHandle"
|
||||
iconType="grab"
|
||||
aria-label="Sort series by pressing up/down"
|
||||
onKeyDown={createUpDownHandler(props.onShouldSortItem)}
|
||||
/>
|
||||
</EuiToolTip>
|
||||
</EuiFlexItem>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`${props.className} vis_editor__series`}
|
||||
className={`${props.className}`}
|
||||
style={props.style}
|
||||
onMouseDown={props.onMouseDown}
|
||||
onTouchStart={props.onTouchStart}
|
||||
>
|
||||
<div className="vis_editor__container">
|
||||
<div className="vis_editor__series-details">
|
||||
<button
|
||||
className="vis_editor__series-visibility-toggle"
|
||||
<EuiFlexGroup responsive={false} gutterSize="s" alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonIcon
|
||||
iconType={caretIcon}
|
||||
color="text"
|
||||
onClick={props.toggleVisible}
|
||||
aria-label="Toggle series editor"
|
||||
aria-expanded={props.visible}
|
||||
>
|
||||
<i className={caretClassName}/>
|
||||
</button>
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
{ colorPicker }
|
||||
<div className="vis_editor__row vis_editor__row_item">
|
||||
<input
|
||||
className="vis_editor__input-grows"
|
||||
onChange={handleChange('label')}
|
||||
placeholder="Label"
|
||||
value={model.label}
|
||||
/>
|
||||
</div>
|
||||
{ dragHandle }
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem>
|
||||
<EuiFieldText
|
||||
fullWidth
|
||||
onChange={handleChange('label')}
|
||||
placeholder="Label"
|
||||
value={model.label}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
{ dragHandle }
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
<AddDeleteButtons
|
||||
addTooltip="Add Series"
|
||||
deleteTooltip="Delete Series"
|
||||
|
@ -177,9 +177,11 @@ function TopNSeries(props) {
|
|||
onAdd={onAdd}
|
||||
disableDelete={disableDelete}
|
||||
disableAdd={disableAdd}
|
||||
responsive={false}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
{ body }
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -93,7 +93,7 @@ function TopNVisualization(props) {
|
|||
}
|
||||
const style = { backgroundColor: panelBackgroundColor };
|
||||
return (
|
||||
<div className="dashboard__visualization" style={style}>
|
||||
<div className="tvbVis" style={style}>
|
||||
<TopN {...params}/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -65,22 +65,20 @@ export function visWithSplits(WrappedComponent) {
|
|||
}
|
||||
};
|
||||
return (
|
||||
<div key={key} className="splitVis_split">
|
||||
<div className="splitVis_visualization">
|
||||
<WrappedComponent
|
||||
model={model}
|
||||
visData={newVisData}
|
||||
onBrush={props.onBrush}
|
||||
additionalLabel={label}
|
||||
backgroundColor={props.backgroundColor}
|
||||
/>
|
||||
</div>
|
||||
<div key={key} className="tvbSplitVis__split">
|
||||
<WrappedComponent
|
||||
model={model}
|
||||
visData={newVisData}
|
||||
onBrush={props.onBrush}
|
||||
additionalLabel={label}
|
||||
backgroundColor={props.backgroundColor}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="splitVis">{rows}</div>
|
||||
<div className="tvbSplitVis">{rows}</div>
|
||||
);
|
||||
}
|
||||
SplitVisComponent.displayName = `SplitVisComponent(${getDisplayName(WrappedComponent)})`;
|
||||
|
|
|
@ -79,10 +79,6 @@ function Visualization(props) {
|
|||
return <div className={props.className} />;
|
||||
}
|
||||
|
||||
Visualization.defaultProps = {
|
||||
className: 'thor__visualization'
|
||||
};
|
||||
|
||||
Visualization.propTypes = {
|
||||
backgroundColor: PropTypes.string,
|
||||
className: PropTypes.string,
|
||||
|
@ -97,4 +93,8 @@ Visualization.propTypes = {
|
|||
getConfig: PropTypes.func
|
||||
};
|
||||
|
||||
Visualization.defaultProps = {
|
||||
className: 'tvbVis'
|
||||
};
|
||||
|
||||
export default Visualization;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import _ from 'lodash';
|
||||
import { EuiRadio, htmlIdGenerator } from '@elastic/eui';
|
||||
|
||||
function YesNo(props) {
|
||||
const { name, value } = props;
|
||||
|
@ -30,29 +31,31 @@ function YesNo(props) {
|
|||
props.onChange(parts);
|
||||
};
|
||||
};
|
||||
const htmlId = htmlIdGenerator();
|
||||
const inputName = name + _.uniqueId();
|
||||
return (
|
||||
<div className="thor__yes_no">
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
name={inputName}
|
||||
checked={Boolean(value)}
|
||||
value="yes"
|
||||
onChange={handleChange(1)}
|
||||
/>
|
||||
Yes
|
||||
</label>
|
||||
<label>
|
||||
<input
|
||||
type="radio"
|
||||
name={inputName}
|
||||
checked={!Boolean(value)}
|
||||
value="no"
|
||||
onChange={handleChange(0)}
|
||||
/>
|
||||
No
|
||||
</label>
|
||||
<div>
|
||||
<EuiRadio
|
||||
id={htmlId('yes')}
|
||||
label="Yes"
|
||||
className="eui-displayInlineBlock"
|
||||
name={inputName}
|
||||
checked={Boolean(value)}
|
||||
value="yes"
|
||||
onChange={handleChange(1)}
|
||||
/>
|
||||
|
||||
 
|
||||
|
||||
<EuiRadio
|
||||
id={htmlId('no')}
|
||||
label="No"
|
||||
className="eui-displayInlineBlock"
|
||||
name={inputName}
|
||||
checked={!Boolean(value)}
|
||||
value="no"
|
||||
onChange={handleChange(0)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ describe('YesNo', () => {
|
|||
const wrapper = shallow(
|
||||
<YesNo name="test" onChange={handleChange} />
|
||||
);
|
||||
wrapper.find('input').first().simulate('change');
|
||||
wrapper.find('EuiRadio').first().simulate('change');
|
||||
expect(handleChange.calledOnce).to.equal(true);
|
||||
expect(handleChange.firstCall.args[0]).to.eql({
|
||||
test: 1
|
||||
|
@ -41,7 +41,7 @@ describe('YesNo', () => {
|
|||
const wrapper = shallow(
|
||||
<YesNo name="test" onChange={handleChange} />
|
||||
);
|
||||
wrapper.find('input').last().simulate('change');
|
||||
wrapper.find('EuiRadio').last().simulate('change');
|
||||
expect(handleChange.calledOnce).to.equal(true);
|
||||
expect(handleChange.firstCall.args[0]).to.eql({
|
||||
test: 0
|
||||
|
|
23
src/core_plugins/metrics/public/index.scss
Normal file
23
src/core_plugins/metrics/public/index.scss
Normal file
|
@ -0,0 +1,23 @@
|
|||
@import 'src/ui/public/styles/styling_constants';
|
||||
|
||||
// Prefix all styles with "tvb" to avoid conflicts.
|
||||
// Examples
|
||||
// tvbChart
|
||||
// tvbChart__legend
|
||||
// tvbChart__legend--small
|
||||
// tvbChart__legend-isLoading
|
||||
|
||||
@import './variables';
|
||||
@import './mixins';
|
||||
|
||||
// Hacks (mostly todo's)
|
||||
@import './hacks';
|
||||
|
||||
// Library overrides
|
||||
@import './ui_sortable';
|
||||
|
||||
// Components
|
||||
@import './components/index';
|
||||
|
||||
// Visualizations
|
||||
@import './visualizations/components/index';
|
|
@ -17,8 +17,6 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import '../visualizations/less/main.less';
|
||||
import '../less/main.less';
|
||||
import { MetricsRequestHandlerProvider } from './request_handler';
|
||||
import { ReactEditorControllerProvider } from './editor_controller';
|
||||
import { VisFactoryProvider } from 'ui/vis/vis_factory';
|
||||
|
|
|
@ -1,89 +0,0 @@
|
|||
.color_picker {
|
||||
background-color: #fff;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0 0 2px rgba(0,0,0,0.3), 0 4px 8px rgba(0,0,0,0.3);
|
||||
box-sizing: initial;
|
||||
width: 275px;
|
||||
font-family: 'Menlo';
|
||||
}
|
||||
|
||||
.color_picker__saturation {
|
||||
width: 100%;
|
||||
padding-bottom: 55%;
|
||||
position: relative;
|
||||
border-radius: 2px 2px 0 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.color_picker__body {
|
||||
padding: 16px 16px 12px;
|
||||
}
|
||||
|
||||
.color_picker__controls {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.color_picker__color {
|
||||
width: 32px;
|
||||
}
|
||||
|
||||
.color_picker__color-disable_alpha {
|
||||
width: 22px;
|
||||
}
|
||||
|
||||
.color_picker__swatch {
|
||||
margin-top: 6px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 8px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.color_picker__swatch-disable_alpha {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.color_picker__active {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
border-radius: 8px;
|
||||
box-shadow: inset 0 0 0 1px rgba(0,0,0,0.1);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.color_picker__toggles {
|
||||
flex: 1
|
||||
}
|
||||
|
||||
.color_picker__hue {
|
||||
height: 10px;
|
||||
position: relative;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.color_picker__hue-disable_alpha {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.color_picker__alpha {
|
||||
height: 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.color_picker__alpha-disable_alpha {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.color_picker__swatches {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
.color_rules {
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
|
||||
.color_rules__rule {
|
||||
background-color: @grayLightest;
|
||||
padding: 10px;
|
||||
margin-bottom: 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
|
||||
.color_rules__item {
|
||||
flex: 1 0 auto;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.color_rules__label {
|
||||
font-weight: normal;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
.color_rules__input {
|
||||
padding: 6px 10px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid @grayLight;
|
||||
flex: 1 0 auto;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.color_rules__secondary {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
|
@ -1,607 +0,0 @@
|
|||
@borderRadius: 4px;
|
||||
|
||||
.vis_editor {
|
||||
flex: 1;
|
||||
}
|
||||
.vis_editor_container {
|
||||
background: @pageColor;
|
||||
}
|
||||
|
||||
// general styles
|
||||
.vis_editor__title {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
align-items: center;
|
||||
font-size: 20px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
i.fa {
|
||||
color: @grayLighter;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
i.fa-pencil {
|
||||
&:hover {
|
||||
color: @gray;
|
||||
}
|
||||
}
|
||||
|
||||
i.fa-check-square {
|
||||
color: @esGreen;
|
||||
&:hover {
|
||||
color: darken(@esGreen, 10%);
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
padding: 0 10px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid @grayLighter;
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
.vis_editor__container {
|
||||
padding: 10px;
|
||||
background-color: @white;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
.vis_editor__label {
|
||||
display: block;
|
||||
font-size: 1em;
|
||||
font-weight: normal;
|
||||
color: @gray;
|
||||
margin: 0 10px;
|
||||
flex-shrink: 0;
|
||||
&:first-child {
|
||||
margin: 0 10px 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.vis_editor__note {
|
||||
.vis_editor__label;
|
||||
font-style: italic;
|
||||
}
|
||||
.vis_editor__input {
|
||||
padding: 8px 10px;
|
||||
border-radius: @borderRadius;
|
||||
border: 1px solid @grayLight;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
.vis_editor__input-grows {
|
||||
.vis_editor__input;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.vis_editor__input-grows-100 {
|
||||
.vis_editor__input-grows;
|
||||
width: 100%;
|
||||
}
|
||||
.vis_editor__input-number {
|
||||
.vis_editor__input;
|
||||
width: 60px;
|
||||
}
|
||||
.vis_editor__row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.vis_editor__item {
|
||||
flex-grow: 1;
|
||||
}
|
||||
.vis_editor__row_item {
|
||||
flex-grow: 1;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.vis_editor__subhead {
|
||||
font-size: 12px;
|
||||
color: @gray;
|
||||
margin: 5px 0;
|
||||
}
|
||||
.vis_editor__subhead-main {
|
||||
font-size: 18px;
|
||||
color: @gray;
|
||||
margin: 10px 10px 5px;
|
||||
}
|
||||
.vis_editor__note {
|
||||
font-size: 14px;
|
||||
color: @gray;
|
||||
margin: 5px 0 10px 0;
|
||||
}
|
||||
|
||||
// color_picker.js
|
||||
.vis_editor__color_picker {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
}
|
||||
.vis_editor__color_picker-swatch {
|
||||
border: 1px solid @grayDark;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.vis_editor__color_picker-swatch-empty {
|
||||
.vis_editor__color_picker-swatch;
|
||||
background-color: transparent;
|
||||
background-size: 20px 20px;
|
||||
background-image: repeating-linear-gradient(
|
||||
-45deg,
|
||||
#c00,
|
||||
#c00 2px,
|
||||
transparent 2px,
|
||||
transparent 16px
|
||||
);
|
||||
}
|
||||
.vis_editor__color_picker-clear {
|
||||
margin-left: 5px;
|
||||
color: #c00;
|
||||
}
|
||||
.vis_editor__color_picker-popover {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
z-index: 2;
|
||||
}
|
||||
.vis_editor__color_picker-cover {
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
}
|
||||
|
||||
// data_format_picker
|
||||
.vis_editor__data_format_picker-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.vis_editor__data_format_picker-custom_row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
> .vis_editor__label {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
// index_pattern.js
|
||||
.vis_editor__index_pattern-fields {
|
||||
margin-right: 10px;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
// series.js
|
||||
// mainRow == .vis_editor__container
|
||||
.vis_editor__series {
|
||||
background-color: @white;
|
||||
padding: 10px;
|
||||
border-top: 2px solid @lineColor;
|
||||
&:first-child {
|
||||
border-top: none;
|
||||
}
|
||||
}
|
||||
.vis_editor__series-row {
|
||||
.vis_editor__container;
|
||||
padding: 0 10px 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
.vis_editor__series-details {
|
||||
.vis_editor__row;
|
||||
flex-grow: 1;
|
||||
> * {
|
||||
margin-right: 10px;
|
||||
}
|
||||
> .vis_editor__sort {
|
||||
cursor: move;
|
||||
margin-right: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.vis_editor__series-visibility-toggle {
|
||||
appearance: none;
|
||||
background: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
// series_config.js
|
||||
.vis_editor__series_config-subhead {
|
||||
.vis_editor__subhead;
|
||||
margin: 10px 0 5px;
|
||||
}
|
||||
|
||||
// series_editor.js
|
||||
.vis_editor__series_editor-container {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
//split.js
|
||||
.vis_editor__split-container {
|
||||
.vis_editor__row;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.vis_editor__split-filter {
|
||||
.vis_editor__input;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.vis_editor__split-selects {
|
||||
.vis_editor__item;
|
||||
}
|
||||
.vis_editor__split-aggs {
|
||||
flex-grow: 1;
|
||||
}
|
||||
.vis_editor__split-term_count {
|
||||
.vis_editor__input;
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
// vis_picker.js
|
||||
.vis_editor__vis_picker-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.vis_editor__vis_picker-item {
|
||||
appearance: none;
|
||||
background: none;
|
||||
border: none;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 18px;
|
||||
padding: 5px 0;
|
||||
margin: 0 10px;
|
||||
&:hover {
|
||||
border-bottom: 2px solid @grayDarker;
|
||||
}
|
||||
&.selected {
|
||||
border-bottom: 2px solid @grayDarker;
|
||||
}
|
||||
}
|
||||
.vis_editor__vis_picker-icon {
|
||||
display: none;
|
||||
margin-right: 5px;
|
||||
color: @grayDark;
|
||||
&:hover,
|
||||
&.selected {
|
||||
color: @grayDarker;
|
||||
}
|
||||
}
|
||||
.vis_editor__vis_picker-label {
|
||||
font-size: 18px;
|
||||
color: @grayDark;
|
||||
&:hover,
|
||||
&.selected {
|
||||
color: @grayDarker;
|
||||
}
|
||||
}
|
||||
|
||||
.vis_editor__vis_picker-controls {
|
||||
flex: 1 0 auto;
|
||||
text-align: right;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
// visualization.js
|
||||
.vis_editor__visualization {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1 0 auto;
|
||||
width: 100%;
|
||||
height: 250px;
|
||||
line-height: normal;
|
||||
background-color: @white;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.vis_editor__visualization-draghandle {
|
||||
text-align: center;
|
||||
color: @grayLight;
|
||||
cursor: row-resize;
|
||||
width: 100%;
|
||||
display: block;
|
||||
appearance: none;
|
||||
background: none;
|
||||
border: none;
|
||||
&:hover {
|
||||
color: @gray;
|
||||
}
|
||||
&:focus {
|
||||
color: @esBlue;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
.vis_editor__visualization-title {
|
||||
color: @gray;
|
||||
font-weight: 500;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
font-size: 16px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
// aggs/agg_row
|
||||
.vis_editor__agg_row-icon {
|
||||
margin-right: 10px;
|
||||
color: @gray;
|
||||
&.last {
|
||||
color: @grayDark;
|
||||
}
|
||||
}
|
||||
|
||||
.vis_editor__series_row {
|
||||
display: flex;
|
||||
background-color: @grayLightest;
|
||||
margin-bottom: 2px;
|
||||
padding: 10px;
|
||||
align-items: center;
|
||||
.vis_editor__note,
|
||||
.vis_editor__label {
|
||||
margin-bottom: 5px;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.vis_editor__agg_row {
|
||||
.vis_editor__series_row;
|
||||
}
|
||||
|
||||
.vis_editor__series_row-item {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.vis_editor__agg_row-item {
|
||||
.vis_editor__series_row-item;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
// aggs/std_deviation.js
|
||||
.vis_editor__std_deviation-field {
|
||||
.vis_editor__row_item;
|
||||
flex-grow: 2;
|
||||
}
|
||||
.vis_editor__std_deviation-sigma_item {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.vis_editor__std_deviation-sigma {
|
||||
.vis_editor__input;
|
||||
width: 50px;
|
||||
}
|
||||
|
||||
.vis_editor__percentile_rank_value {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
// aggs/std_sibling.js
|
||||
.vis_editor__std_sibling-metric {
|
||||
.vis_editor__row_item;
|
||||
flex-grow: 2;
|
||||
}
|
||||
|
||||
// aggs/vis_config
|
||||
.vis_editor__vis_config-row {
|
||||
.vis_editor__row;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
// aggs/series_config
|
||||
.vis_editor__series_config-container {
|
||||
background-color: @grayLightest;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.vis_editor__series_config-row {
|
||||
.vis_editor__row;
|
||||
padding: 5px 0;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.vis_editor__percentiles,
|
||||
.vis_editor__variables {
|
||||
.vis_editor__row_item;
|
||||
margin: 10px 0;
|
||||
}
|
||||
.vis_editor__calc_vars {
|
||||
// background-color: @white;
|
||||
// padding: 10px;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.vis_editor__percentiles-row,
|
||||
.vis_editor__calc_vars-row {
|
||||
display: flex;
|
||||
margin-bottom: 10px;
|
||||
align-items: center;
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.vis_editor__calc_vars-name {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.vis_editor__calc_vars-var {
|
||||
flex-grow: 1;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.vis_editor__percentiles-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-grow: 1;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.vis_editor__markdown {
|
||||
display: flex;
|
||||
background-color: @white;
|
||||
min-height: 500px;
|
||||
}
|
||||
|
||||
.vis_editor__markdown-editor {
|
||||
border: 2px solid @lineColor;
|
||||
width: 50%;
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
|
||||
.vis_editor__markdown-variables {
|
||||
padding: 10px;
|
||||
flex: 1 0 auto;
|
||||
max-height: 500px;
|
||||
overflow: auto;
|
||||
width: 50%;
|
||||
.table a {
|
||||
text-decoration: none;
|
||||
}
|
||||
pre {
|
||||
border-radius: 0;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.vis_editor__no-markdown-variables {
|
||||
margin-top: 60px;
|
||||
margin-bottom: 10px;
|
||||
padding-bottom: 60px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
border-bottom: 1px solid #d9d9d9;
|
||||
}
|
||||
|
||||
.vis_editor__markdown-code-desc {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.vis_editor__ace-editor {
|
||||
border: 2px solid @lineColor;
|
||||
}
|
||||
|
||||
.vis_editor__split-filters {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
padding: 10px 20px;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.vis_editor__split-filter-row {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
margin-bottom: 10px;
|
||||
align-items: center;
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.vis_editor__split-filter-item {
|
||||
flex-grow: 1;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.vis_editor__split-filter-color {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.vis_editor__annotations-color,
|
||||
.vis_editor__annotations-controls {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.vis_editor__annotations-row {
|
||||
display: flex;
|
||||
padding: 10px;
|
||||
background-color: @lineColor;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.vis_editor__annotations-missing {
|
||||
padding: 30px 10px;
|
||||
font-size: 16px;
|
||||
p {
|
||||
font-size: 16px;
|
||||
}
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.vis_editor__annotations-content {
|
||||
margin: 0 10px;
|
||||
flex-grow: 1;
|
||||
.vis_editor__row {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.vis_editor__row-item {
|
||||
flex-grow: 1;
|
||||
margin-left: 10px;
|
||||
&:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
.vis_editor__label {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
}
|
||||
.vis_editor__row-item-small {
|
||||
.vis_editor__row-item;
|
||||
flex-grow: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.vis_editor__icon_select-option {
|
||||
margin: 0 5px;
|
||||
}
|
||||
.vis_editor__icon_select-value {
|
||||
margin: 0 5px 0 0;
|
||||
}
|
||||
|
||||
.vis_editor__agg_select-heading {
|
||||
color: @black;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.vis_editor__agg_select-note {
|
||||
margin-left: 10px;
|
||||
color: @gray;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.vis_editor__dirty_controls {
|
||||
padding: 8px 6px;
|
||||
background-color: @grayLightest;
|
||||
display: flex;
|
||||
align-content: center;
|
||||
}
|
||||
|
||||
.vis_editor__dirty_controls-button {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.vis_editor__dirty_controls-message {
|
||||
flex: 1 0 auto;
|
||||
color: @grayLight;
|
||||
padding: 4px 10px 0;
|
||||
}
|
||||
|
||||
.vis_editor__dirty_controls-message-dirty {
|
||||
flex: 1 0 auto;
|
||||
color: @gray;
|
||||
padding: 4px 10px 0;
|
||||
}
|
||||
|
||||
.vis_editor__dirty_controls-toggle-label {
|
||||
padding: 4px 10px 0;
|
||||
flex: 0 0 auto;
|
||||
color: @gray;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.vis_editor__dirty_controls-toggle {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.vis_editor__table-pivot-fields {
|
||||
border-bottom: 2px solid @lineColor;
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
.metrics_issue {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1 0 auto;
|
||||
background-color: #b3ccd5;
|
||||
color: #0079a5;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.metrics_issue__title {
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.metrics_error {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1 0 auto;
|
||||
background-color: #ffd9d9;
|
||||
color: #c00;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.metrics_error__title {
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.metrics_error__additional {
|
||||
margin-top: 10px;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.metrics_error__reason {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.metrics_error__stack {
|
||||
margin-top: 10px;
|
||||
color: #fff;
|
||||
border: 10px solid #fff;
|
||||
background-color: #000;
|
||||
font-family: "Courier New", Courier, monospace;
|
||||
white-space: pre;
|
||||
padding: 10px;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue