mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Vis: Default editor] EUIficate gauge/goal options tab (#43265)
* Euificate gauge options * Changes params places * Add ranges validation * Get rid of legacy translates * Fix functional tests * Split gauge to panel components * Disable alignment option
This commit is contained in:
parent
7602710bdc
commit
e568c3dfde
23 changed files with 2123 additions and 1688 deletions
|
@ -1,383 +0,0 @@
|
|||
<div class="visEditorSidebar__section">
|
||||
<div class="visEditorSidebar__formRow">
|
||||
<label
|
||||
class="visEditorSidebar__formLabel"
|
||||
for="gaugeType"
|
||||
i18n-id="kbnVislibVisTypes.controls.gaugeOptions.gaugeTypeLabel"
|
||||
i18n-default-message="Gauge Type"
|
||||
></label>
|
||||
<div class="visEditorSidebar__formControl">
|
||||
<select
|
||||
id="gaugeType"
|
||||
class="kuiSelect visEditorSidebar__select"
|
||||
ng-model="editorState.params.gauge.gaugeType"
|
||||
ng-options="mode for mode in collections.gaugeTypes"
|
||||
></select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="visEditorSidebar__formRow">
|
||||
<label
|
||||
class="visEditorSidebar__formLabel"
|
||||
for="percentageMode"
|
||||
i18n-id="kbnVislibVisTypes.controls.gaugeOptions.percentageModeLabel"
|
||||
i18n-default-message="Percentage Mode"
|
||||
></label>
|
||||
<div class="visEditorSidebar__formControl">
|
||||
<input class="kuiCheckBox" id="percentageMode" type="checkbox" ng-model="editorState.params.gauge.percentageMode">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="visEditorSidebar__formRow" ng-hide="editorState.params.gauge.type === 'simple'">
|
||||
<label
|
||||
class="visEditorSidebar__formLabel"
|
||||
for="alignment"
|
||||
i18n-id="kbnVislibVisTypes.controls.gaugeOptions.alignmentLabel"
|
||||
i18n-default-message="Alignment"
|
||||
></label>
|
||||
<div class="visEditorSidebar__formControl">
|
||||
<select
|
||||
id="alignment"
|
||||
class="kuiSelect visEditorSidebar__select"
|
||||
ng-model="editorState.params.gauge.alignment"
|
||||
ng-options="alignment.id as alignment.label for alignment in collections.alignments"
|
||||
></select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="visEditorSidebar__formRow">
|
||||
<label
|
||||
class="visEditorSidebar__formLabel"
|
||||
for="displayWarnings"
|
||||
i18n-id="kbnVislibVisTypes.controls.gaugeOptions.displayWarningsLabel"
|
||||
i18n-default-message="Display warnings"
|
||||
></label>
|
||||
|
||||
<div class="visEditorSidebar__formControl">
|
||||
<input class="kuiCheckBox" id="displayWarnings" type="checkbox" ng-model="editorState.params.isDisplayWarning">
|
||||
|
||||
<icon-tip
|
||||
content="'Turns on/off warnings. When turned on, a warning will be shown if not all labels could be displayed.'"
|
||||
position="'right'"
|
||||
></icon-tip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="visEditorSidebar__formRow">
|
||||
<label
|
||||
class="visEditorSidebar__formLabel"
|
||||
for="addLegend"
|
||||
i18n-id="kbnVislibVisTypes.controls.gaugeOptions.showLegendLabel"
|
||||
i18n-default-message="Show Legend"
|
||||
></label>
|
||||
<div class="visEditorSidebar__formControl">
|
||||
<input class="kuiCheckBox" id="addLegend" type="checkbox" ng-model="editorState.params.addLegend">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="visEditorSidebar__formRow">
|
||||
<label
|
||||
class="visEditorSidebar__formLabel"
|
||||
for="showLabels"
|
||||
i18n-id="kbnVislibVisTypes.controls.gaugeOptions.showLabelsLabel"
|
||||
i18n-default-message="Show Labels"
|
||||
></label>
|
||||
<div class="visEditorSidebar__formControl">
|
||||
<input class="kuiCheckBox" id="showLabels" type="checkbox" ng-model="editorState.params.gauge.labels.show">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="visEditorSidebar__formRow" ng-show="editorState.params.gauge.labels.show">
|
||||
<label
|
||||
class="visEditorSidebar__formLabel"
|
||||
for="subText"
|
||||
i18n-id="kbnVislibVisTypes.controls.gaugeOptions.subTextLabel"
|
||||
i18n-default-message="Sub Text"
|
||||
></label>
|
||||
<div class="visEditorSidebar__formControl">
|
||||
<input
|
||||
id="subText"
|
||||
class="kuiInput visEditorSidebar__input"
|
||||
ng-model="editorState.params.gauge.style.subText"
|
||||
type="text"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="visEditorSidebar__formRow"
|
||||
ng-hide="editorState.params.gauge.type === 'simple'"
|
||||
ng-show="editorState.params.gauge.colorsRange.length > 1"
|
||||
>
|
||||
<label
|
||||
class="visEditorSidebar__formLabel"
|
||||
for="extendRange"
|
||||
i18n-id="kbnVislibVisTypes.controls.gaugeOptions.autoExtendRangeLabel"
|
||||
i18n-default-message="Auto Extend Range"
|
||||
></label>
|
||||
<div class="visEditorSidebar__formControl">
|
||||
<input class="kuiCheckBox" id="extendRange" type="checkbox" ng-model="editorState.params.gauge.extendRange">
|
||||
|
||||
<icon-tip
|
||||
content="'Extends range to the maximum value in your data'"
|
||||
position="'right'"
|
||||
></icon-tip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="visEditorSidebar__collapsible--margin">
|
||||
<div class="visEditorSidebar__collapsibleTitle">
|
||||
<div
|
||||
kbn-accessible-click
|
||||
aria-expanded="{{!!showColorRange}}"
|
||||
aria-controls="gaugeOptionsRanges"
|
||||
aria-label="Toggle range options"
|
||||
class="visEditorSidebar__collapsibleTitleLabel"
|
||||
ng-click="showColorRange = !showColorRange"
|
||||
>
|
||||
<icon color="'primary'" aria-hidden="true" ng-if="showColorRange" type="'arrowDown'" size="'s'"></icon>
|
||||
<icon color="'primary'" aria-hidden="true" ng-if="!showColorRange" type="'arrowRight'" size="'s'"></icon>
|
||||
|
||||
<span
|
||||
class="visEditorSidebar__collapsibleTitleText"
|
||||
i18n-id="kbnVislibVisTypes.controls.gaugeOptions.rangesTitle"
|
||||
i18n-default-message="Ranges"
|
||||
></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="gaugeOptionsRanges" ng-show="showColorRange">
|
||||
|
||||
<table class="visEditorAgg__rangesTable form-group" ng-show="editorState.params.gauge.colorsRange.length">
|
||||
<tr>
|
||||
<th scope="col">
|
||||
<label
|
||||
id="gaugeOptionsCustomRangeFrom"
|
||||
i18n-id="kbnVislibVisTypes.controls.gaugeOptions.fromTitle"
|
||||
i18n-default-message="From"
|
||||
></label>
|
||||
</th>
|
||||
<th scope="col" colspan="2">
|
||||
<label
|
||||
id="gaugeOptionsCustomRangeTo"
|
||||
i18n-id="kbnVislibVisTypes.controls.gaugeOptions.toTitle"
|
||||
i18n-default-message="To"
|
||||
></label>
|
||||
</th>
|
||||
</tr>
|
||||
|
||||
<tr ng-repeat="range in editorState.params.gauge.colorsRange track by $index">
|
||||
<td>
|
||||
<input
|
||||
aria-labelledby="gaugeOptionsCustomRangeFrom"
|
||||
ng-model="range.from"
|
||||
type="number"
|
||||
class="form-control"
|
||||
name="range.from"
|
||||
greater-or-equal-than="getGreaterThan($index)"
|
||||
required
|
||||
step="any" />
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
aria-labelledby="gaugeOptionsCustomRangeTo"
|
||||
ng-model="range.to"
|
||||
type="number"
|
||||
class="form-control"
|
||||
name="range.to"
|
||||
greater-or-equal-than="range.from"
|
||||
required
|
||||
step="any" />
|
||||
</td>
|
||||
<td>
|
||||
<button
|
||||
type="button"
|
||||
ng-click="removeRange($index)"
|
||||
ng-show="editorState.params.gauge.colorsRange.length > 1"
|
||||
class="kuiButton kuiButton--danger kuiButton--small">
|
||||
<i class="fa fa-times"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="hintbox" ng-show="!editorState.params.gauge.colorsRange.length">
|
||||
<p>
|
||||
<i class="fa fa-danger text-danger"></i>
|
||||
<span
|
||||
i18n-id="kbnVislibVisTypes.controls.gaugeOptions.specifiedRangeNumberWarningMessage"
|
||||
i18n-default-message="{required} You must specify at least one range."
|
||||
i18n-values="{ html_required: '<strong>' + requiredText + '</strong>' }"
|
||||
></span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div
|
||||
ng-click="addRange()"
|
||||
class="kuiButton kuiButton--primary kuiButton--fullWidth"
|
||||
i18n-id="kbnVislibVisTypes.controls.gaugeOptions.addRangeTitle"
|
||||
i18n-default-message="Add Range"
|
||||
></div>
|
||||
<div
|
||||
class="euiFormHelpText"
|
||||
i18n-id="kbnVislibVisTypes.controls.gaugeOptions.howToChangeColorsDescription"
|
||||
i18n-default-message="Note: colors can be changed in the legend"
|
||||
></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="visEditorSidebar__collapsible--margin" ng-show="editorState.params.gauge.colorsRange.length > 1">
|
||||
<div class="visEditorSidebar__collapsibleTitle">
|
||||
<div
|
||||
kbn-accessible-click
|
||||
aria-expanded="{{!!showColorOptions}}"
|
||||
aria-controls="gaugeOptionsColors"
|
||||
aria-label="Toggle color options"
|
||||
class="visEditorSidebar__collapsibleTitleLabel"
|
||||
ng-click="showColorOptions = !showColorOptions"
|
||||
>
|
||||
<icon color="'primary'" aria-hidden="true" ng-if="showColorOptions" type="'arrowDown'" size="'s'"></icon>
|
||||
<icon color="'primary'" aria-hidden="true" ng-if="!showColorOptions" type="'arrowRight'" size="'s'"></icon>
|
||||
|
||||
<span
|
||||
class="visEditorSidebar__collapsibleTitleText"
|
||||
i18n-id="kbnVislibVisTypes.controls.gaugeOptions.colorOptionsTitle"
|
||||
i18n-default-message="Color Options"
|
||||
></span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="gaugeOptionsColors" ng-if="showColorOptions">
|
||||
|
||||
<div class="visEditorSidebar__formRow">
|
||||
<label
|
||||
class="visEditorSidebar__formLabel"
|
||||
for="colorSchema"
|
||||
i18n-id="kbnVislibVisTypes.controls.gaugeOptions.colorSchemaLabel"
|
||||
i18n-default-message="Color Schema"
|
||||
></label>
|
||||
<div class="visEditorSidebar__formControl">
|
||||
<select
|
||||
id="colorSchema"
|
||||
class="kuiSelect visEditorSidebar__select"
|
||||
ng-model="editorState.params.gauge.colorSchema"
|
||||
ng-options="mode.id as mode.label for mode in collections.colorSchemas"
|
||||
></select>
|
||||
</div>
|
||||
<div
|
||||
class="text-info text-center"
|
||||
ng-show="customColors"
|
||||
ng-click="resetColors()"
|
||||
i18n-id="kbnVislibVisTypes.controls.gaugeOptions.resetColorsTitle"
|
||||
i18n-default-message="reset colors"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<div class="visEditorSidebar__formRow">
|
||||
<label
|
||||
class="visEditorSidebar__formLabel"
|
||||
for="invertColors"
|
||||
i18n-id="kbnVislibVisTypes.controls.gaugeOptions.reverseColorSchemaLabel"
|
||||
i18n-default-message="Reverse Color Schema"
|
||||
></label>
|
||||
<div class="visEditorSidebar__formControl">
|
||||
<input class="kuiCheckBox" id="invertColors" type="checkbox" ng-model="editorState.params.gauge.invertColors">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="visEditorSidebar__collapsible--margin">
|
||||
<div class="visEditorSidebar__collapsibleTitle">
|
||||
<div
|
||||
kbn-accessible-click
|
||||
aria-expanded="{{!!showStyle}}"
|
||||
aria-controls="gaugeOptionsStyle"
|
||||
aria-label="Toggle style options"
|
||||
class="visEditorSidebar__collapsibleTitleLabel"
|
||||
ng-click="showStyle = !showStyle"
|
||||
>
|
||||
<icon color="'primary'" aria-hidden="true" ng-if="showStyle" type="'arrowDown'" size="'s'"></icon>
|
||||
<icon color="'primary'" aria-hidden="true" ng-if="!showStyle" type="'arrowRight'" size="'s'"></icon>
|
||||
|
||||
<span
|
||||
class="visEditorSidebar__collapsibleTitleText"
|
||||
i18n-id="kbnVislibVisTypes.controls.gaugeOptions.styleTitle"
|
||||
i18n-default-message="Style"
|
||||
></span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="gaugeOptionsStyle" ng-if="showStyle">
|
||||
<div ng-hide="editorState.params.gauge.type === 'simple'">
|
||||
<div class="visEditorSidebar__formRow" ng-show="editorState.params.gauge.colorsRange.length > 1">
|
||||
<label
|
||||
class="visEditorSidebar__formLabel"
|
||||
for="labelColor"
|
||||
i18n-id="kbnVislibVisTypes.controls.gaugeOptions.colorLabelsLabel"
|
||||
i18n-default-message="Color Labels"
|
||||
></label>
|
||||
<div class="visEditorSidebar__formControl">
|
||||
<input class="kuiCheckBox" id="labelColor" type="checkbox" ng-model="editorState.params.gauge.style.labelColor">
|
||||
</div>
|
||||
</div>
|
||||
<div class="visEditorSidebar__formRow">
|
||||
<label
|
||||
class="visEditorSidebar__formLabel"
|
||||
for="showScale"
|
||||
i18n-id="kbnVislibVisTypes.controls.gaugeOptions.showScaleLabel"
|
||||
i18n-default-message="Show Scale"
|
||||
></label>
|
||||
<div class="visEditorSidebar__formControl">
|
||||
<input class="kuiCheckBox" id="showScale" type="checkbox" ng-model="editorState.params.gauge.scale.show">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-show="editorState.params.gauge.type === 'simple'">
|
||||
<div class="visEditorSidebar__formRow">
|
||||
<label
|
||||
class="visEditorSidebar__formLabel"
|
||||
for="gaugeColorMode"
|
||||
i18n-id="kbnVislibVisTypes.controls.gaugeOptions.colorLabel"
|
||||
i18n-default-message="Color"
|
||||
></label>
|
||||
<div class="visEditorSidebar__formControl">
|
||||
<select
|
||||
id="gaugeColorMode"
|
||||
class="kuiSelect visEditorSidebar__select"
|
||||
ng-model="editorState.params.gauge.gaugeColorMode"
|
||||
ng-options="mode for mode in collections.gaugeColorMode"
|
||||
></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="visEditorSidebar__formRow">
|
||||
<label
|
||||
class="visEditorSidebar__formLabel"
|
||||
for="backColor"
|
||||
i18n-id="kbnVislibVisTypes.controls.gaugeOptions.backTextColorLabel"
|
||||
i18n-default-message="Back/Text Color"
|
||||
></label>
|
||||
<div class="visEditorSidebar__formControl">
|
||||
<input
|
||||
id="backTextColor"
|
||||
class="kuiInput visEditorSidebar__input"
|
||||
ng-model="editorState.params.gauge.style.bgFill"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="visEditorSidebar__formRow">
|
||||
<label
|
||||
class="visEditorSidebar__formLabel"
|
||||
for="showScale"
|
||||
i18n-id="kbnVislibVisTypes.controls.gaugeOptions.fontSizeLabel"
|
||||
i18n-default-message="Font Size ({fontSize}pt)"
|
||||
i18n-values="{ fontSize: editorState.params.gauge.style.fontSize }"
|
||||
></label>
|
||||
<div class="visEditorSidebar__formControl">
|
||||
<input type="range" ng-model="editorState.params.gauge.style.fontSize" class="form-control" min="12" max="120" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,117 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { uiModules } from 'ui/modules';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import gaugeOptionsTemplate from './gauge_options.html';
|
||||
import _ from 'lodash';
|
||||
const module = uiModules.get('kibana');
|
||||
|
||||
module.directive('gaugeOptions', function () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
template: gaugeOptionsTemplate,
|
||||
replace: true,
|
||||
link: function ($scope) {
|
||||
$scope.collections = $scope.vis.type.editorConfig.collections;
|
||||
$scope.showColorRange = true;
|
||||
|
||||
$scope.$watch('editorState.params.gauge.gaugeType', type => {
|
||||
switch (type) {
|
||||
case 'Arc':
|
||||
$scope.editorState.params.gauge.type = 'meter';
|
||||
$scope.editorState.params.gauge.minAngle = undefined;
|
||||
$scope.editorState.params.gauge.maxAngle = undefined;
|
||||
break;
|
||||
case 'Circle':
|
||||
$scope.editorState.params.gauge.type = 'meter';
|
||||
$scope.editorState.params.gauge.minAngle = 0;
|
||||
$scope.editorState.params.gauge.maxAngle = 2 * Math.PI;
|
||||
break;
|
||||
case 'Metric':
|
||||
$scope.editorState.params.gauge.type = 'simple';
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const updateLegend = () => {
|
||||
if (!$scope.editorState.params.gauge.style.bgColor && !$scope.editorState.params.gauge.style.labelColor) {
|
||||
$scope.editorState.params.addLegend = false;
|
||||
} else {
|
||||
$scope.editorState.params.addLegend = true;
|
||||
}
|
||||
};
|
||||
|
||||
$scope.$watch('editorState.params.gauge.gaugeColorMode', newValue => {
|
||||
switch (newValue) {
|
||||
case 'Labels':
|
||||
$scope.editorState.params.gauge.style.labelColor = true;
|
||||
$scope.editorState.params.gauge.style.bgColor = false;
|
||||
break;
|
||||
case 'Background':
|
||||
$scope.editorState.params.gauge.style.labelColor = false;
|
||||
$scope.editorState.params.gauge.style.bgColor = true;
|
||||
break;
|
||||
case 'None':
|
||||
$scope.editorState.params.gauge.style.labelColor = false;
|
||||
$scope.editorState.params.gauge.style.bgColor = false;
|
||||
break;
|
||||
}
|
||||
updateLegend();
|
||||
});
|
||||
|
||||
$scope.resetColors = function () {
|
||||
$scope.uiState.set('vis.colors', null);
|
||||
$scope.customColors = false;
|
||||
};
|
||||
|
||||
$scope.getGreaterThan = function (index) {
|
||||
if (index === 0) return -Infinity;
|
||||
return $scope.editorState.params.gauge.colorsRange[index - 1].to;
|
||||
};
|
||||
|
||||
$scope.addRange = function () {
|
||||
const previousRange = _.last($scope.editorState.params.gauge.colorsRange);
|
||||
const from = previousRange ? previousRange.to : 0;
|
||||
const to = previousRange ? from + (previousRange.to - previousRange.from) : 100;
|
||||
$scope.editorState.params.gauge.colorsRange.push({ from: from, to: to });
|
||||
};
|
||||
|
||||
$scope.removeRange = function (index) {
|
||||
$scope.editorState.params.gauge.colorsRange.splice(index, 1);
|
||||
};
|
||||
|
||||
$scope.getColor = function (index) {
|
||||
const defaultColors = this.uiState.get('vis.defaultColors');
|
||||
const overwriteColors = this.uiState.get('vis.colors');
|
||||
const colors = defaultColors ? _.defaults({}, overwriteColors, defaultColors) : overwriteColors;
|
||||
return colors ? Object.values(colors)[index] : 'transparent';
|
||||
};
|
||||
|
||||
$scope.uiState.on('colorChanged', () => {
|
||||
$scope.customColors = true;
|
||||
});
|
||||
|
||||
$scope.requiredText = i18n.translate('kbnVislibVisTypes.controls.gaugeOptions.requiredText', {
|
||||
defaultMessage: 'Required:'
|
||||
});
|
||||
|
||||
}
|
||||
};
|
||||
});
|
|
@ -21,6 +21,8 @@ import React from 'react';
|
|||
import { EuiFormRow, EuiSelect } from '@elastic/eui';
|
||||
|
||||
interface SelectOptionProps<ParamName extends string, ValidParamValues extends string> {
|
||||
disabled?: boolean;
|
||||
helpText?: React.ReactNode;
|
||||
id?: string;
|
||||
label: string;
|
||||
labelAppend?: React.ReactNode;
|
||||
|
@ -33,6 +35,8 @@ interface SelectOptionProps<ParamName extends string, ValidParamValues extends s
|
|||
const emptyValue = { text: '', value: 'EMPTY_VALUE', disabled: true, hidden: true };
|
||||
|
||||
function SelectOption<ParamName extends string, ValidParamValues extends string>({
|
||||
disabled,
|
||||
helpText,
|
||||
id,
|
||||
label,
|
||||
labelAppend,
|
||||
|
@ -42,8 +46,16 @@ function SelectOption<ParamName extends string, ValidParamValues extends string>
|
|||
setValue,
|
||||
}: SelectOptionProps<ParamName, ValidParamValues>) {
|
||||
return (
|
||||
<EuiFormRow id={id} label={label} fullWidth={true} compressed labelAppend={labelAppend}>
|
||||
<EuiFormRow
|
||||
compressed
|
||||
fullWidth
|
||||
helpText={helpText}
|
||||
id={id}
|
||||
label={label}
|
||||
labelAppend={labelAppend}
|
||||
>
|
||||
<EuiSelect
|
||||
disabled={disabled}
|
||||
options={[emptyValue, ...options]}
|
||||
value={value || emptyValue.value}
|
||||
onChange={ev => setValue(paramName, ev.target.value as ValidParamValues)}
|
||||
|
|
|
@ -21,6 +21,7 @@ import React from 'react';
|
|||
import { EuiFormRow, EuiFieldText } from '@elastic/eui';
|
||||
|
||||
interface TextInputOptionProps<ParamName extends string> {
|
||||
disabled?: boolean;
|
||||
helpText?: React.ReactNode;
|
||||
label?: React.ReactNode;
|
||||
paramName: ParamName;
|
||||
|
@ -29,6 +30,7 @@ interface TextInputOptionProps<ParamName extends string> {
|
|||
}
|
||||
|
||||
function TextInputOption<ParamName extends string>({
|
||||
disabled,
|
||||
helpText,
|
||||
label,
|
||||
paramName,
|
||||
|
@ -37,7 +39,12 @@ function TextInputOption<ParamName extends string>({
|
|||
}: TextInputOptionProps<ParamName>) {
|
||||
return (
|
||||
<EuiFormRow helpText={helpText} label={label} fullWidth compressed>
|
||||
<EuiFieldText fullWidth value={value} onChange={ev => setValue(paramName, ev.target.value)} />
|
||||
<EuiFieldText
|
||||
fullWidth
|
||||
disabled={disabled}
|
||||
value={value}
|
||||
onChange={ev => setValue(paramName, ev.target.value)}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
<!-- vis type specific options -->
|
||||
<gauge-options></gauge-options>
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React, { useCallback } from 'react';
|
||||
import { EuiSpacer } from '@elastic/eui';
|
||||
|
||||
import { VisOptionsProps } from 'ui/vis/editors/default';
|
||||
import { GaugeVisParams } from '../../gauge';
|
||||
import { RangesPanel } from './ranges_panel';
|
||||
import { StylePanel } from './style_panel';
|
||||
import { LabelsPanel } from './labels_panel';
|
||||
|
||||
export type GaugeOptionsInternalProps = VisOptionsProps<GaugeVisParams> & {
|
||||
setGaugeValue: <T extends keyof GaugeVisParams['gauge']>(
|
||||
paramName: T,
|
||||
value: GaugeVisParams['gauge'][T]
|
||||
) => void;
|
||||
};
|
||||
|
||||
function GaugeOptions(props: VisOptionsProps<GaugeVisParams>) {
|
||||
const { stateParams, setValue } = props;
|
||||
|
||||
const setGaugeValue: GaugeOptionsInternalProps['setGaugeValue'] = useCallback(
|
||||
(paramName, value) =>
|
||||
setValue('gauge', {
|
||||
...stateParams.gauge,
|
||||
[paramName]: value,
|
||||
}),
|
||||
[setValue, stateParams.gauge]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<StylePanel {...props} setGaugeValue={setGaugeValue} />
|
||||
|
||||
<EuiSpacer size="s" />
|
||||
|
||||
<RangesPanel {...props} setGaugeValue={setGaugeValue} />
|
||||
|
||||
<EuiSpacer size="s" />
|
||||
|
||||
<LabelsPanel {...props} setGaugeValue={setGaugeValue} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export { GaugeOptions };
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
|
||||
import { SwitchOption } from '../../controls/switch';
|
||||
import { TextInputOption } from '../../controls/text_input';
|
||||
import { GaugeOptionsInternalProps } from '.';
|
||||
|
||||
function LabelsPanel({ stateParams, setValue, setGaugeValue }: GaugeOptionsInternalProps) {
|
||||
return (
|
||||
<EuiPanel paddingSize="s">
|
||||
<EuiTitle size="xs">
|
||||
<h2>
|
||||
<FormattedMessage
|
||||
id="kbnVislibVisTypes.controls.gaugeOptions.labelsTitle"
|
||||
defaultMessage="Labels"
|
||||
/>
|
||||
</h2>
|
||||
</EuiTitle>
|
||||
<EuiSpacer size="s" />
|
||||
|
||||
<SwitchOption
|
||||
label={i18n.translate('kbnVislibVisTypes.controls.gaugeOptions.showLabelsLabel', {
|
||||
defaultMessage: 'Show labels',
|
||||
})}
|
||||
paramName="show"
|
||||
value={stateParams.gauge.labels.show}
|
||||
setValue={(paramName, value) =>
|
||||
setGaugeValue('labels', { ...stateParams.gauge.labels, [paramName]: value })
|
||||
}
|
||||
/>
|
||||
<EuiSpacer size="s" />
|
||||
|
||||
<TextInputOption
|
||||
disabled={!stateParams.gauge.labels.show}
|
||||
label={i18n.translate('kbnVislibVisTypes.controls.gaugeOptions.subTextLabel', {
|
||||
defaultMessage: 'Sub label',
|
||||
})}
|
||||
paramName="subText"
|
||||
value={stateParams.gauge.style.subText}
|
||||
setValue={(paramName, value) =>
|
||||
setGaugeValue('style', { ...stateParams.gauge.style, [paramName]: value })
|
||||
}
|
||||
/>
|
||||
|
||||
<SwitchOption
|
||||
disabled={!stateParams.gauge.labels.show}
|
||||
label={i18n.translate('kbnVislibVisTypes.controls.gaugeOptions.displayWarningsLabel', {
|
||||
defaultMessage: 'Display warnings',
|
||||
})}
|
||||
tooltip={i18n.translate('kbnVislibVisTypes.controls.gaugeOptions.switchWarningsTooltip', {
|
||||
defaultMessage:
|
||||
'Turns on/off warnings. When turned on, a warning will be shown if not all labels could be displayed.',
|
||||
})}
|
||||
paramName="isDisplayWarning"
|
||||
value={stateParams.isDisplayWarning}
|
||||
setValue={setValue}
|
||||
/>
|
||||
</EuiPanel>
|
||||
);
|
||||
}
|
||||
|
||||
export { LabelsPanel };
|
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { last } from 'lodash';
|
||||
import { EuiLink, EuiPanel, EuiSpacer, EuiText, EuiTitle } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
|
||||
import { RangesParamEditor } from 'ui/agg_types/controls/ranges';
|
||||
import { SelectOption } from '../../controls/select';
|
||||
import { SwitchOption } from '../../controls/switch';
|
||||
import { GaugeOptionsInternalProps } from '.';
|
||||
|
||||
function RangesPanel({
|
||||
setGaugeValue,
|
||||
setTouched,
|
||||
setValidity,
|
||||
setValue,
|
||||
stateParams,
|
||||
uiState,
|
||||
vis,
|
||||
}: GaugeOptionsInternalProps) {
|
||||
const [isCustomColors, setIsCustomColors] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
uiState.on('colorChanged', () => {
|
||||
setIsCustomColors(true);
|
||||
});
|
||||
}, [uiState]);
|
||||
|
||||
const addRangeValues = useCallback(() => {
|
||||
const previousRange = last(stateParams.gauge.colorsRange);
|
||||
const from = previousRange.to ? previousRange.to : 0;
|
||||
const to = previousRange.to ? from + (previousRange.to - (previousRange.from || 0)) : 100;
|
||||
|
||||
return { from, to };
|
||||
}, [stateParams.gauge.colorsRange]);
|
||||
|
||||
const validateRange = useCallback(
|
||||
({ from, to }, index) => {
|
||||
const leftBound = index === 0 ? -Infinity : stateParams.gauge.colorsRange[index - 1].to || 0;
|
||||
const isFromValid = from >= leftBound;
|
||||
const isToValid = to >= from;
|
||||
|
||||
return [isFromValid, isToValid];
|
||||
},
|
||||
[stateParams.gauge.colorsRange]
|
||||
);
|
||||
|
||||
const resetColorsButton = (
|
||||
<EuiText size="xs">
|
||||
<EuiLink
|
||||
onClick={() => {
|
||||
uiState.set('vis.colors', null);
|
||||
setIsCustomColors(false);
|
||||
}}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="kbnVislibVisTypes.controls.gaugeOptions.resetColorsButtonLabel"
|
||||
defaultMessage="Reset colors"
|
||||
/>
|
||||
</EuiLink>
|
||||
</EuiText>
|
||||
);
|
||||
|
||||
return (
|
||||
<EuiPanel paddingSize="s">
|
||||
<EuiTitle size="xs">
|
||||
<h2>
|
||||
<FormattedMessage
|
||||
id="kbnVislibVisTypes.controls.gaugeOptions.rangesTitle"
|
||||
defaultMessage="Ranges"
|
||||
/>
|
||||
</h2>
|
||||
</EuiTitle>
|
||||
<EuiSpacer size="s" />
|
||||
|
||||
<RangesParamEditor
|
||||
dataTestSubj="gaugeColorRange"
|
||||
error={i18n.translate('kbnVislibVisTypes.controls.gaugeOptions.errorText', {
|
||||
defaultMessage: 'Each range should be greater than previous.',
|
||||
})}
|
||||
hidePlaceholders={true}
|
||||
value={stateParams.gauge.colorsRange}
|
||||
setValue={value => setGaugeValue('colorsRange', value)}
|
||||
setTouched={setTouched}
|
||||
setValidity={setValidity}
|
||||
addRangeValues={addRangeValues}
|
||||
validateRange={validateRange}
|
||||
/>
|
||||
|
||||
<SwitchOption
|
||||
disabled={stateParams.gauge.colorsRange.length < 2}
|
||||
label={i18n.translate('kbnVislibVisTypes.controls.gaugeOptions.autoExtendRangeLabel', {
|
||||
defaultMessage: 'Auto extend range',
|
||||
})}
|
||||
tooltip={i18n.translate('kbnVislibVisTypes.controls.gaugeOptions.extendRangeTooltip', {
|
||||
defaultMessage: 'Extends range to the maximum value in your data.',
|
||||
})}
|
||||
paramName="extendRange"
|
||||
value={stateParams.gauge.extendRange}
|
||||
setValue={setGaugeValue}
|
||||
/>
|
||||
|
||||
<SwitchOption
|
||||
dataTestSubj="gaugePercentageMode"
|
||||
label={i18n.translate('kbnVislibVisTypes.controls.gaugeOptions.percentageModeLabel', {
|
||||
defaultMessage: 'Percentage mode',
|
||||
})}
|
||||
paramName="percentageMode"
|
||||
value={stateParams.gauge.percentageMode}
|
||||
setValue={setGaugeValue}
|
||||
/>
|
||||
<EuiSpacer size="s" />
|
||||
|
||||
<SelectOption
|
||||
disabled={stateParams.gauge.colorsRange.length < 2}
|
||||
helpText={i18n.translate(
|
||||
'kbnVislibVisTypes.controls.gaugeOptions.howToChangeColorsDescription',
|
||||
{
|
||||
defaultMessage: 'Note: colors can be changed in the legend.',
|
||||
}
|
||||
)}
|
||||
label={i18n.translate('kbnVislibVisTypes.controls.gaugeOptions.colorSchemaLabel', {
|
||||
defaultMessage: 'Color schema',
|
||||
})}
|
||||
labelAppend={isCustomColors && resetColorsButton}
|
||||
options={vis.type.editorConfig.collections.colorSchemas}
|
||||
paramName="colorSchema"
|
||||
value={stateParams.gauge.colorSchema}
|
||||
setValue={setGaugeValue}
|
||||
/>
|
||||
|
||||
<SwitchOption
|
||||
disabled={stateParams.gauge.colorsRange.length < 2}
|
||||
label={i18n.translate('kbnVislibVisTypes.controls.gaugeOptions.reverseColorSchemaLabel', {
|
||||
defaultMessage: 'Reverse schema',
|
||||
})}
|
||||
paramName="invertColors"
|
||||
value={stateParams.gauge.invertColors}
|
||||
setValue={setGaugeValue}
|
||||
/>
|
||||
|
||||
<SwitchOption
|
||||
label={i18n.translate('kbnVislibVisTypes.controls.gaugeOptions.showLegendLabel', {
|
||||
defaultMessage: 'Show legend',
|
||||
})}
|
||||
paramName="addLegend"
|
||||
value={stateParams.addLegend}
|
||||
setValue={setValue}
|
||||
/>
|
||||
|
||||
<SwitchOption
|
||||
label={i18n.translate('kbnVislibVisTypes.controls.gaugeOptions.showScaleLabel', {
|
||||
defaultMessage: 'Show scale',
|
||||
})}
|
||||
paramName="show"
|
||||
value={stateParams.gauge.scale.show}
|
||||
setValue={(paramName, value) =>
|
||||
setGaugeValue('scale', { ...stateParams.gauge.scale, [paramName]: value })
|
||||
}
|
||||
/>
|
||||
</EuiPanel>
|
||||
);
|
||||
}
|
||||
|
||||
export { RangesPanel };
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React, { useCallback } from 'react';
|
||||
import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
|
||||
import { AggGroupNames } from 'ui/vis/editors/default';
|
||||
import { SelectOption } from '../../controls/select';
|
||||
import { GaugeVisParams } from '../../gauge';
|
||||
import { GaugeOptionsInternalProps } from '.';
|
||||
|
||||
function StylePanel({
|
||||
aggs,
|
||||
setGaugeValue,
|
||||
stateParams,
|
||||
setValue,
|
||||
vis,
|
||||
}: GaugeOptionsInternalProps) {
|
||||
const diasableAlignment =
|
||||
aggs.bySchemaGroup[AggGroupNames.Metrics].length === 1 &&
|
||||
!aggs.bySchemaGroup[AggGroupNames.Buckets];
|
||||
|
||||
const setGaugeType = useCallback(
|
||||
(paramName: 'gaugeType', value: GaugeVisParams['gauge']['gaugeType']) => {
|
||||
const minAngle = value === 'Arc' ? undefined : 0;
|
||||
const maxAngle = value === 'Arc' ? undefined : 2 * Math.PI;
|
||||
|
||||
setValue('gauge', {
|
||||
...stateParams.gauge,
|
||||
[paramName]: value,
|
||||
minAngle,
|
||||
maxAngle,
|
||||
});
|
||||
},
|
||||
[setValue, stateParams.gauge]
|
||||
);
|
||||
|
||||
return (
|
||||
<EuiPanel paddingSize="s">
|
||||
<EuiTitle size="xs">
|
||||
<h2>
|
||||
<FormattedMessage
|
||||
id="kbnVislibVisTypes.controls.gaugeOptions.styleTitle"
|
||||
defaultMessage="Style"
|
||||
/>
|
||||
</h2>
|
||||
</EuiTitle>
|
||||
<EuiSpacer size="s" />
|
||||
|
||||
<SelectOption
|
||||
label={i18n.translate('kbnVislibVisTypes.controls.gaugeOptions.gaugeTypeLabel', {
|
||||
defaultMessage: 'Gauge type',
|
||||
})}
|
||||
options={vis.type.editorConfig.collections.gaugeTypes}
|
||||
paramName="gaugeType"
|
||||
value={stateParams.gauge.gaugeType}
|
||||
setValue={setGaugeType}
|
||||
/>
|
||||
|
||||
<SelectOption
|
||||
disabled={diasableAlignment}
|
||||
label={i18n.translate('kbnVislibVisTypes.controls.gaugeOptions.alignmentLabel', {
|
||||
defaultMessage: 'Alignment',
|
||||
})}
|
||||
options={vis.type.editorConfig.collections.alignments}
|
||||
paramName="alignment"
|
||||
value={stateParams.gauge.alignment}
|
||||
setValue={setGaugeValue}
|
||||
/>
|
||||
</EuiPanel>
|
||||
);
|
||||
}
|
||||
|
||||
export { StylePanel };
|
53
src/legacy/core_plugins/kbn_vislib_vis_types/public/gauge.d.ts
vendored
Normal file
53
src/legacy/core_plugins/kbn_vislib_vis_types/public/gauge.d.ts
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { ColorSchemas } from 'ui/vislib/components/color/colormaps';
|
||||
|
||||
export interface GaugeVisParams {
|
||||
readonly type: 'gauge';
|
||||
addTooltip: boolean;
|
||||
addLegend: boolean;
|
||||
isDisplayWarning: boolean;
|
||||
gauge: {
|
||||
readonly backStyle: 'Full';
|
||||
readonly gaugeStyle: 'Full';
|
||||
readonly orientation: 'vertical';
|
||||
readonly type: 'meter';
|
||||
alignment: 'automatic' | 'horizontal' | 'vertical';
|
||||
colorsRange: Array<{ from?: number; to?: number }>;
|
||||
colorSchema: ColorSchemas;
|
||||
extendRange: boolean;
|
||||
invertColors: boolean;
|
||||
gaugeType: 'Arc' | 'Circle';
|
||||
labels: {
|
||||
show: boolean;
|
||||
};
|
||||
minAngle?: number;
|
||||
maxAngle?: number;
|
||||
percentageMode: boolean;
|
||||
scale: {
|
||||
show: boolean;
|
||||
readonly labels: false;
|
||||
readonly color: 'rgba(105,112,125,0.2)';
|
||||
};
|
||||
style: {
|
||||
subText: string;
|
||||
};
|
||||
};
|
||||
}
|
|
@ -17,11 +17,11 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { VisFactoryProvider } from 'ui/vis/vis_factory';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { VisFactoryProvider } from 'ui/vis/vis_factory';
|
||||
import { Schemas } from 'ui/vis/editors/default/schemas';
|
||||
import gaugeTemplate from './editors/gauge.html';
|
||||
import { vislibColorMaps } from 'ui/vislib/components/color/colormaps';
|
||||
import { colorSchemas } from 'ui/vislib/components/color/colormaps';
|
||||
import { GaugeOptions } from './editors/gauge';
|
||||
|
||||
export default function GaugeVisType(Private) {
|
||||
const VisFactory = Private(VisFactoryProvider);
|
||||
|
@ -84,25 +84,36 @@ export default function GaugeVisType(Private) {
|
|||
},
|
||||
editorConfig: {
|
||||
collections: {
|
||||
gaugeTypes: ['Arc', 'Circle'],
|
||||
gaugeColorMode: ['None', 'Labels', 'Background'],
|
||||
gaugeTypes: [
|
||||
{
|
||||
text: i18n.translate('kbnVislibVisTypes.gauge.gaugeTypes.arcText', {
|
||||
defaultMessage: 'Arc',
|
||||
}),
|
||||
value: 'Arc',
|
||||
},
|
||||
{
|
||||
text: i18n.translate('kbnVislibVisTypes.gauge.gaugeTypes.circleText', {
|
||||
defaultMessage: 'Circle',
|
||||
}),
|
||||
value: 'Circle',
|
||||
},
|
||||
],
|
||||
alignments: [
|
||||
{
|
||||
id: 'automatic',
|
||||
label: i18n.translate('kbnVislibVisTypes.gauge.alignmentAutomaticTitle', { defaultMessage: 'Automatic' })
|
||||
value: 'automatic',
|
||||
text: i18n.translate('kbnVislibVisTypes.gauge.alignmentAutomaticTitle', { defaultMessage: 'Automatic' })
|
||||
},
|
||||
{
|
||||
id: 'horizontal',
|
||||
label: i18n.translate('kbnVislibVisTypes.gauge.alignmentHorizontalTitle', { defaultMessage: 'Horizontal' })
|
||||
value: 'horizontal',
|
||||
text: i18n.translate('kbnVislibVisTypes.gauge.alignmentHorizontalTitle', { defaultMessage: 'Horizontal' })
|
||||
},
|
||||
{
|
||||
id: 'vertical',
|
||||
label: i18n.translate('kbnVislibVisTypes.gauge.alignmentVerticalTitle', { defaultMessage: 'Vertical' }) },
|
||||
value: 'vertical',
|
||||
text: i18n.translate('kbnVislibVisTypes.gauge.alignmentVerticalTitle', { defaultMessage: 'Vertical' }) },
|
||||
],
|
||||
scales: ['linear', 'log', 'square root'],
|
||||
colorSchemas: Object.values(vislibColorMaps).map(value => ({ id: value.id, label: value.label })),
|
||||
colorSchemas,
|
||||
},
|
||||
optionsTemplate: gaugeTemplate,
|
||||
optionsTemplate: GaugeOptions,
|
||||
schemas: new Schemas([
|
||||
{
|
||||
group: 'metrics',
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
import { VisFactoryProvider } from 'ui/vis/vis_factory';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { Schemas } from 'ui/vis/editors/default/schemas';
|
||||
import gaugeTemplate from './editors/gauge.html';
|
||||
import { vislibColorMaps } from 'ui/vislib/components/color/colormaps';
|
||||
import { colorSchemas } from 'ui/vislib/components/color/colormaps';
|
||||
import { GaugeOptions } from './editors/gauge';
|
||||
|
||||
export default function GoalVisType(Private) {
|
||||
const VisFactory = Private(VisFactoryProvider);
|
||||
|
@ -80,12 +80,36 @@ export default function GoalVisType(Private) {
|
|||
},
|
||||
editorConfig: {
|
||||
collections: {
|
||||
gaugeTypes: ['Arc', 'Circle'],
|
||||
gaugeColorMode: ['None', 'Labels', 'Background'],
|
||||
scales: ['linear', 'log', 'square root'],
|
||||
colorSchemas: Object.values(vislibColorMaps).map(value => ({ id: value.id, label: value.label })),
|
||||
gaugeTypes: [
|
||||
{
|
||||
text: i18n.translate('kbnVislibVisTypes.gauge.gaugeTypes.arcText', {
|
||||
defaultMessage: 'Arc',
|
||||
}),
|
||||
value: 'Arc',
|
||||
},
|
||||
{
|
||||
text: i18n.translate('kbnVislibVisTypes.gauge.gaugeTypes.circleText', {
|
||||
defaultMessage: 'Circle',
|
||||
}),
|
||||
value: 'Circle',
|
||||
},
|
||||
],
|
||||
alignments: [
|
||||
{
|
||||
value: 'automatic',
|
||||
text: i18n.translate('kbnVislibVisTypes.gauge.alignmentAutomaticTitle', { defaultMessage: 'Automatic' })
|
||||
},
|
||||
{
|
||||
value: 'horizontal',
|
||||
text: i18n.translate('kbnVislibVisTypes.gauge.alignmentHorizontalTitle', { defaultMessage: 'Horizontal' })
|
||||
},
|
||||
{
|
||||
value: 'vertical',
|
||||
text: i18n.translate('kbnVislibVisTypes.gauge.alignmentVerticalTitle', { defaultMessage: 'Vertical' }) },
|
||||
],
|
||||
colorSchemas,
|
||||
},
|
||||
optionsTemplate: gaugeTemplate,
|
||||
optionsTemplate: GaugeOptions,
|
||||
schemas: new Schemas([
|
||||
{
|
||||
group: 'metrics',
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { BucketAggType } from './_bucket_agg_type';
|
||||
import { createFilterRange } from './create_filter/range';
|
||||
import { FieldFormat } from '../../../field_formats/field_format';
|
||||
|
@ -91,7 +92,7 @@ export const rangeBucketAgg = new BucketAggType({
|
|||
{ from: 0, to: 1000 },
|
||||
{ from: 1000, to: 2000 }
|
||||
],
|
||||
editorComponent: RangesParamEditor,
|
||||
editorComponent: ({ value, setValue }) => <RangesParamEditor value={value} setValue={setValue}/>,
|
||||
write: function (aggConfig, output) {
|
||||
output.params.ranges = aggConfig.params.ranges;
|
||||
output.params.keyed = true;
|
||||
|
|
|
@ -111,7 +111,7 @@ function DateRangesParamEditor({
|
|||
);
|
||||
|
||||
return (
|
||||
<EuiFormRow compressed>
|
||||
<EuiFormRow compressed fullWidth>
|
||||
<>
|
||||
<EuiText size="xs">
|
||||
<EuiLink href={getDocLink('date.dateMath')} target="_blank" rel="noopener">
|
||||
|
|
|
@ -24,6 +24,7 @@ import {
|
|||
EuiFieldNumber,
|
||||
EuiFlexItem,
|
||||
EuiFlexGroup,
|
||||
EuiFormErrorText,
|
||||
EuiIcon,
|
||||
EuiSpacer,
|
||||
EuiButtonEmpty,
|
||||
|
@ -32,7 +33,6 @@ import {
|
|||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { isEqual, omit } from 'lodash';
|
||||
import { AggParamEditorProps } from 'ui/vis/editors/default';
|
||||
|
||||
const FROM_PLACEHOLDER = '\u2212\u221E';
|
||||
const TO_PLACEHOLDER = '+\u221E';
|
||||
|
@ -49,7 +49,29 @@ interface RangeValuesModel extends RangeValues {
|
|||
id: string;
|
||||
}
|
||||
|
||||
function RangesParamEditor({ agg, value = [], setValue }: AggParamEditorProps<RangeValues[]>) {
|
||||
interface RangesParamEditorProps {
|
||||
dataTestSubj?: string;
|
||||
error?: React.ReactNode;
|
||||
value?: RangeValues[];
|
||||
hidePlaceholders?: boolean;
|
||||
setValue(value: RangeValues[]): void;
|
||||
setValidity?(isValid: boolean): void;
|
||||
setTouched?(isTouched: boolean): void;
|
||||
addRangeValues?(): RangeValues;
|
||||
validateRange?(range: RangeValues, index: number): boolean[];
|
||||
}
|
||||
|
||||
function RangesParamEditor({
|
||||
addRangeValues,
|
||||
dataTestSubj = 'range',
|
||||
error,
|
||||
value = [],
|
||||
hidePlaceholders,
|
||||
setValue,
|
||||
setTouched,
|
||||
setValidity,
|
||||
validateRange,
|
||||
}: RangesParamEditorProps) {
|
||||
const [ranges, setRanges] = useState(() => value.map(range => ({ ...range, id: generateId() })));
|
||||
|
||||
// set up an initial range when there is no default range
|
||||
|
@ -73,8 +95,15 @@ function RangesParamEditor({ agg, value = [], setValue }: AggParamEditorProps<Ra
|
|||
// do not set internal id parameter into saved object
|
||||
setValue(rangeValues.map(range => omit(range, 'id')));
|
||||
setRanges(rangeValues);
|
||||
|
||||
if (setTouched) {
|
||||
setTouched(true);
|
||||
}
|
||||
};
|
||||
const onAddRange = () => updateRanges([...ranges, { id: generateId() }]);
|
||||
const onAddRange = () =>
|
||||
addRangeValues
|
||||
? updateRanges([...ranges, { ...addRangeValues(), id: generateId() }])
|
||||
: updateRanges([...ranges, { id: generateId() }]);
|
||||
const onRemoveRange = (id: string) => updateRanges(ranges.filter(range => range.id !== id));
|
||||
const onChangeRange = (id: string, key: string, newValue: string) =>
|
||||
updateRanges(
|
||||
|
@ -88,10 +117,24 @@ function RangesParamEditor({ agg, value = [], setValue }: AggParamEditorProps<Ra
|
|||
)
|
||||
);
|
||||
|
||||
const hasInvalidRange =
|
||||
validateRange &&
|
||||
ranges.some(({ from, to, id }, index) => {
|
||||
const [isFromValid, isToValid] = validateRange({ from, to }, index);
|
||||
|
||||
return !isFromValid || !isToValid;
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (setValidity) {
|
||||
setValidity(!hasInvalidRange);
|
||||
}
|
||||
}, [hasInvalidRange, setValidity]);
|
||||
|
||||
return (
|
||||
<EuiFormRow compressed>
|
||||
<EuiFormRow compressed fullWidth>
|
||||
<>
|
||||
{ranges.map(({ from, to, id }) => {
|
||||
{ranges.map(({ from, to, id }, index) => {
|
||||
const deleteBtnTitle = i18n.translate(
|
||||
'common.ui.aggTypes.ranges.removeRangeButtonAriaLabel',
|
||||
{
|
||||
|
@ -103,19 +146,28 @@ function RangesParamEditor({ agg, value = [], setValue }: AggParamEditorProps<Ra
|
|||
}
|
||||
);
|
||||
|
||||
let isFromValid = true;
|
||||
let isToValid = true;
|
||||
|
||||
if (validateRange) {
|
||||
[isFromValid, isToValid] = validateRange({ from, to }, index);
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment key={id}>
|
||||
<EuiFlexGroup gutterSize="s" alignItems="center">
|
||||
<EuiFlexGroup gutterSize="s" alignItems="center" responsive={false}>
|
||||
<EuiFlexItem>
|
||||
<EuiFieldNumber
|
||||
aria-label={i18n.translate('common.ui.aggTypes.ranges.fromLabel', {
|
||||
defaultMessage: 'From',
|
||||
})}
|
||||
data-test-subj={`${dataTestSubj}${index}__from`}
|
||||
value={isEmpty(from) ? '' : from}
|
||||
placeholder={FROM_PLACEHOLDER}
|
||||
placeholder={hidePlaceholders ? undefined : FROM_PLACEHOLDER}
|
||||
onChange={ev => onChangeRange(id, 'from', ev.target.value)}
|
||||
fullWidth={true}
|
||||
compressed={true}
|
||||
isInvalid={!isFromValid}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
|
@ -126,11 +178,13 @@ function RangesParamEditor({ agg, value = [], setValue }: AggParamEditorProps<Ra
|
|||
aria-label={i18n.translate('common.ui.aggTypes.ranges.toLabel', {
|
||||
defaultMessage: 'To',
|
||||
})}
|
||||
data-test-subj={`${dataTestSubj}${index}__to`}
|
||||
value={isEmpty(to) ? '' : to}
|
||||
placeholder={TO_PLACEHOLDER}
|
||||
placeholder={hidePlaceholders ? undefined : TO_PLACEHOLDER}
|
||||
onChange={ev => onChangeRange(id, 'to', ev.target.value)}
|
||||
fullWidth={true}
|
||||
compressed={true}
|
||||
isInvalid={!isToValid}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
|
@ -149,6 +203,8 @@ function RangesParamEditor({ agg, value = [], setValue }: AggParamEditorProps<Ra
|
|||
);
|
||||
})}
|
||||
|
||||
{hasInvalidRange && error && <EuiFormErrorText>{error}</EuiFormErrorText>}
|
||||
|
||||
<EuiSpacer size="s" />
|
||||
<EuiFlexItem>
|
||||
<EuiButtonEmpty iconType="plusInCircleFilled" onClick={onAddRange} size="xs">
|
||||
|
|
|
@ -174,6 +174,7 @@
|
|||
<div class="visEditorSidebar__config" ng-repeat="tab in vis.type.editorConfig.optionTabs" ng-show="sidebar.section == tab.name">
|
||||
<vis-editor-vis-options
|
||||
class="visEditorSidebar__options"
|
||||
ng-model="_internalNgModelState"
|
||||
editor-state="state"
|
||||
has-histogram-agg="hasHistogramAgg"
|
||||
vis="vis"
|
||||
|
|
|
@ -31,14 +31,19 @@ uiModules
|
|||
.get('app/visualize')
|
||||
.directive('visOptionsReactWrapper', reactDirective => reactDirective(wrapInI18nContext(VisOptionsReactWrapper), [
|
||||
['component', { wrapApply: false }],
|
||||
['aggs', { watchDepth: 'collection' }],
|
||||
['stateParams', { watchDepth: 'collection' }],
|
||||
['vis', { watchDepth: 'collection' }],
|
||||
['uiState', { watchDepth: 'collection' }],
|
||||
['setValue', { watchDepth: 'reference' }],
|
||||
['setValidity', { watchDepth: 'reference' }],
|
||||
['setTouched', { watchDepth: 'reference' }],
|
||||
'hasHistogramAgg',
|
||||
]))
|
||||
.directive('visEditorVisOptions', function ($compile) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
require: '?^ngModel',
|
||||
scope: {
|
||||
vis: '=',
|
||||
visData: '=',
|
||||
|
@ -49,18 +54,34 @@ uiModules
|
|||
onAggParamsChange: '=',
|
||||
hasHistogramAgg: '=',
|
||||
},
|
||||
link: function ($scope, $el) {
|
||||
link: function ($scope, $el, attrs, ngModelCtrl) {
|
||||
$scope.setValue = (paramName, value) =>
|
||||
$scope.onAggParamsChange($scope.editorState.params, paramName, value);
|
||||
|
||||
$scope.setValidity = isValid => {
|
||||
ngModelCtrl.$setValidity(`visOptions`, isValid);
|
||||
};
|
||||
|
||||
$scope.setTouched = isTouched => {
|
||||
if (isTouched) {
|
||||
ngModelCtrl.$setTouched();
|
||||
} else {
|
||||
ngModelCtrl.$setUntouched();
|
||||
}
|
||||
};
|
||||
|
||||
const comp = typeof $scope.editor === 'string' ?
|
||||
$scope.editor :
|
||||
`<vis-options-react-wrapper
|
||||
component="editor"
|
||||
aggs="editorState.aggs"
|
||||
has-histogram-agg="hasHistogramAgg"
|
||||
state-params="editorState.params"
|
||||
vis="vis"
|
||||
set-value="setValue">
|
||||
ui-state="uiState"
|
||||
set-value="setValue"
|
||||
set-validity="setValidity"
|
||||
set-touched="setTouched">
|
||||
</vis-options-react-wrapper>`;
|
||||
const $editor = $compile(comp)($scope);
|
||||
$el.append($editor);
|
||||
|
|
|
@ -17,11 +17,17 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import { PersistedState } from 'ui/persisted_state';
|
||||
import { AggConfigs } from 'ui/vis/agg_configs';
|
||||
import { Vis } from './../..';
|
||||
|
||||
export interface VisOptionsProps<VisParamType = unknown> {
|
||||
aggs: AggConfigs;
|
||||
hasHistogramAgg: boolean;
|
||||
stateParams: VisParamType;
|
||||
vis: Vis;
|
||||
uiState: PersistedState;
|
||||
setValue<T extends keyof VisParamType>(paramName: T, value: VisParamType[T]): void;
|
||||
setValidity(isValid: boolean): void;
|
||||
setTouched(isTouched: boolean): void;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
import 'plugins/kbn_vislib_vis_types/controls/point_series_options';
|
||||
import 'plugins/kbn_vislib_vis_types/controls/line_interpolation_option';
|
||||
import 'plugins/kbn_vislib_vis_types/controls/heatmap_options';
|
||||
import 'plugins/kbn_vislib_vis_types/controls/gauge_options';
|
||||
import 'plugins/kbn_vislib_vis_types/controls/point_series';
|
||||
import { CUSTOM_LEGEND_VIS_TYPES } from './vislib_vis_legend';
|
||||
import { BaseVisType } from './base_vis_type';
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -23,7 +23,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
const log = getService('log');
|
||||
const retry = getService('retry');
|
||||
const inspector = getService('inspector');
|
||||
const find = getService('find');
|
||||
const testSubjects = getService('testSubjects');
|
||||
const PageObjects = getPageObjects(['common', 'visualize', 'timePicker']);
|
||||
|
||||
describe('gauge chart', function indexPatternCreation() {
|
||||
|
@ -100,12 +100,8 @@ export default function ({ getService, getPageObjects }) {
|
|||
await PageObjects.visualize.selectAggregation('Average', 'metrics');
|
||||
await PageObjects.visualize.selectField('bytes', 'metrics');
|
||||
await PageObjects.visualize.clickOptionsTab();
|
||||
const table = await find.byClassName('visEditorAgg__rangesTable');
|
||||
const lastRow = await table.findByCssSelector('tr:last-child');
|
||||
const toCell = await lastRow.findByCssSelector('td:nth-child(2) input');
|
||||
await toCell.clearValue();
|
||||
await toCell.type('10000', { charByChar: true });
|
||||
await find.clickByCssSelector('#percentageMode');
|
||||
await testSubjects.setValue('gaugeColorRange2__to', '10000');
|
||||
await testSubjects.click('gaugePercentageMode');
|
||||
await PageObjects.visualize.waitForVisualizationRenderingStabilized();
|
||||
await PageObjects.visualize.clickGo();
|
||||
|
||||
|
|
|
@ -2459,31 +2459,12 @@
|
|||
"kbnVislibVisTypes.area.radiusTitle": "点のサイズ",
|
||||
"kbnVislibVisTypes.area.segmentTitle": "X 軸",
|
||||
"kbnVislibVisTypes.area.splitTitle": "チャートを分割",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.addRangeTitle": "範囲を追加",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.alignmentLabel": "アラインメント",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.autoExtendRangeLabel": "範囲を自動拡張",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.backTextColorLabel": "背景/文字の色",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.colorLabel": "色",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.colorLabelsLabel": "カラーラベル",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.colorOptionsTitle": "カラーオプション",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.colorSchemaLabel": "カラースキーム",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.displayWarningsLabel": "警告を表示",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.fontSizeLabel": "フォントサイズ ({fontSize} pt)",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.fromTitle": "開始:",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.gaugeTypeLabel": "ゲージタイプ",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.howToChangeColorsDescription": "注: 色は凡例で変更できます",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.percentageModeLabel": "パーセンテージモード",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.rangesTitle": "範囲",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.requiredText": "必須:",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.resetColorsTitle": "色のリセット",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.reverseColorSchemaLabel": "カラースキームを反転",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.showLabelsLabel": "ラベルを表示",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.showLegendLabel": "凡例を表示",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.showScaleLabel": "スケールを表示",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.specifiedRangeNumberWarningMessage": "{required} 範囲を最低 1 つ指定する必要があります。",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.styleTitle": "スタイル",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.subTextLabel": "サブテキスト",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.toTitle": "To",
|
||||
"kbnVislibVisTypes.controls.heatmapOptions.addRangeButtonLabel": "範囲を追加",
|
||||
"kbnVislibVisTypes.controls.heatmapOptions.colorLabel": "色",
|
||||
"kbnVislibVisTypes.controls.heatmapOptions.colorScaleLabel": "カラースケール",
|
||||
|
|
|
@ -2459,31 +2459,12 @@
|
|||
"kbnVislibVisTypes.area.radiusTitle": "点大小",
|
||||
"kbnVislibVisTypes.area.segmentTitle": "X 轴",
|
||||
"kbnVislibVisTypes.area.splitTitle": "拆分图表",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.addRangeTitle": "添加范围",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.alignmentLabel": "对齐方式",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.autoExtendRangeLabel": "自动扩展范围",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.backTextColorLabel": "背景/文本颜色",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.colorLabel": "颜色",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.colorLabelsLabel": "颜色标签",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.colorOptionsTitle": "颜色选项",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.colorSchemaLabel": "颜色模式",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.displayWarningsLabel": "显示警告",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.fontSizeLabel": "字体大小({fontSize} 磅)",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.fromTitle": "从",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.gaugeTypeLabel": "仪表类型",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.howToChangeColorsDescription": "注意:可以更改图例颜色",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.percentageModeLabel": "百分比模式",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.rangesTitle": "范围",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.requiredText": "必需:",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.resetColorsTitle": "重置颜色",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.reverseColorSchemaLabel": "反色模式",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.showLabelsLabel": "显示标签",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.showLegendLabel": "显示图例",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.showScaleLabel": "显示比例",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.specifiedRangeNumberWarningMessage": "{required}您必须指定至少一个范围。",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.styleTitle": "样式",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.subTextLabel": "子文本",
|
||||
"kbnVislibVisTypes.controls.gaugeOptions.toTitle": "到",
|
||||
"kbnVislibVisTypes.controls.heatmapOptions.addRangeButtonLabel": "添加范围",
|
||||
"kbnVislibVisTypes.controls.heatmapOptions.colorLabel": "颜色",
|
||||
"kbnVislibVisTypes.controls.heatmapOptions.colorScaleLabel": "颜色比例",
|
||||
|
@ -10629,4 +10610,4 @@
|
|||
"xpack.watcher.watchActions.logging.logTextIsRequiredValidationMessage": "“日志文本”必填。",
|
||||
"xpack.watcher.watcherDescription": "通过创建、管理和监测警报来检测数据中的更改。"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue