[Vis: Default editor] Euification of Metric options tab (#46930)

* EUIfication of metric_vis_options

* Small fixes

* Remove unused translations

* Fix style comments

* Remove unused styles
This commit is contained in:
Daniil Suleiman 2019-10-08 23:37:24 +03:00 committed by GitHub
parent bbdc0bf595
commit b25df015d5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 323 additions and 817 deletions

View file

@ -38,6 +38,7 @@ interface ColorSchemaOptionsProps extends ColorSchemaVislibParams {
colorSchemas: ColorSchema[];
uiState: VisOptionsProps['uiState'];
setValue: SetColorSchemaOptionsValue;
showHelpText?: boolean;
}
function ColorSchemaOptions({
@ -47,6 +48,7 @@ function ColorSchemaOptions({
invertColors,
uiState,
setValue,
showHelpText = true,
}: ColorSchemaOptionsProps) {
const [isCustomColors, setIsCustomColors] = useState(() => !!uiState.get('vis.colors'));
@ -76,12 +78,12 @@ function ColorSchemaOptions({
<>
<SelectOption
disabled={disabled}
helpText={i18n.translate(
'kbnVislibVisTypes.controls.colorSchema.howToChangeColorsDescription',
{
helpText={
showHelpText &&
i18n.translate('kbnVislibVisTypes.controls.colorSchema.howToChangeColorsDescription', {
defaultMessage: 'Individual colors can be changed in the legend.',
}
)}
})
}
label={i18n.translate('kbnVislibVisTypes.controls.colorSchema.colorSchemaLabel', {
defaultMessage: 'Color schema',
})}

View file

@ -19,7 +19,7 @@
export { BasicOptions } from './basic_options';
export { ColorRanges } from './color_ranges';
export { ColorSchemaOptions } from './color_schema';
export { ColorSchemaOptions, SetColorSchemaOptionsValue } from './color_schema';
export { NumberInputOption } from './number_input';
export { RangeOption } from './range';
export { SelectOption } from './select';

View file

@ -27,6 +27,8 @@ interface RangeOptionProps<ParamName extends string> {
min: number;
paramName: ParamName;
showInput?: boolean;
showLabels?: boolean;
showValue?: boolean;
step?: number;
value: '' | number;
setValue: (paramName: ParamName, value: number) => void;
@ -37,6 +39,8 @@ function RangeOption<ParamName extends string>({
max,
min,
showInput,
showLabels,
showValue = true,
step,
paramName,
value,
@ -65,10 +69,11 @@ function RangeOption<ParamName extends string>({
<EuiRange
compressed
fullWidth
showValue
max={max}
min={min}
showInput={showInput}
showLabels={showLabels}
showValue={showValue}
step={step}
value={stateValue}
onChange={onChangeHandler}

View file

@ -23,11 +23,11 @@ import { EuiFormRow, EuiFieldNumber } from '@elastic/eui';
interface TruncateLabelsOptionProps {
disabled?: boolean;
value: number | null;
value?: number | null;
setValue: (paramName: 'truncate', value: null | number) => void;
}
function TruncateLabelsOption({ disabled, value, setValue }: TruncateLabelsOptionProps) {
function TruncateLabelsOption({ disabled, value = null, setValue }: TruncateLabelsOptionProps) {
const onChange = (ev: ChangeEvent<HTMLInputElement>) =>
setValue('truncate', ev.target.value === '' ? null : parseFloat(ev.target.value));

View file

@ -167,16 +167,13 @@ function HeatmapOptions(props: VisOptionsProps<HeatmapVisParams>) {
/>
{stateParams.setColorRange && (
<>
<EuiSpacer size="s" />
<ColorRanges
data-test-subj="heatmapColorRange"
colorsRange={stateParams.colorsRange}
setValue={setValue}
setTouched={setTouched}
setValidity={setIsColorRangesValid}
/>
</>
<ColorRanges
data-test-subj="heatmapColorRange"
colorsRange={stateParams.colorsRange}
setValue={setValue}
setTouched={setTouched}
setValidity={setIsColorRangesValid}
/>
)}
</EuiPanel>

View file

@ -17,7 +17,7 @@
* under the License.
*/
import { Axis, ValueAxis, SeriesParam } from '../../../types';
import { Axis, ValueAxis, SeriesParam, Style } from '../../../types';
import {
ChartTypes,
ChartModes,
@ -31,7 +31,7 @@ const defaultValueAxisId = 'ValueAxis-1';
const axis = {
show: true,
style: {},
style: {} as Style,
title: {
text: '',
},

View file

@ -19,7 +19,7 @@
import { RangeValues } from 'ui/vis/editors/default/controls/ranges';
import { Alignments, GaugeTypes } from './utils/collections';
import { ColorSchemaVislibParams } from './types';
import { ColorSchemaVislibParams, Labels, Style } from './types';
interface Gauge extends ColorSchemaVislibParams {
backStyle: 'Full';
@ -30,18 +30,14 @@ interface Gauge extends ColorSchemaVislibParams {
colorsRange: RangeValues[];
extendRange: boolean;
gaugeType: GaugeTypes;
labels: {
show: boolean;
};
labels: Labels;
percentageMode: boolean;
scale: {
show: boolean;
labels: false;
color: 'rgba(105,112,125,0.2)';
};
style: {
subText: string;
};
style: Style;
}
export interface GaugeVisParams {

View file

@ -23,7 +23,7 @@ import { Schemas } from 'ui/vis/editors/default/schemas';
import { AggGroupNames } from 'ui/vis/editors/default';
import { ColorSchemas } from 'ui/vislib/components/color/colormaps';
import { GaugeOptions } from './components/options';
import { getGaugeCollections, Alignments, GaugeColorModes, GaugeTypes } from './utils/collections';
import { getGaugeCollections, Alignments, ColorModes, GaugeTypes } from './utils/collections';
import { vislibVisController } from './controller';
export default function GaugeVisType() {
@ -49,7 +49,7 @@ export default function GaugeVisType() {
backStyle: 'Full',
orientation: 'vertical',
colorSchema: ColorSchemas.GreenToRed,
gaugeColorMode: GaugeColorModes.LABELS,
gaugeColorMode: ColorModes.LABELS,
colorsRange: [
{ from: 0, to: 50 },
{ from: 50, to: 75 },

View file

@ -22,7 +22,7 @@ import { Schemas } from 'ui/vis/editors/default/schemas';
import { AggGroupNames } from 'ui/vis/editors/default';
import { ColorSchemas } from 'ui/vislib/components/color/colormaps';
import { GaugeOptions } from './components/options';
import { getGaugeCollections, GaugeTypes, GaugeColorModes } from './utils/collections';
import { getGaugeCollections, GaugeTypes, ColorModes } from './utils/collections';
import { vislibVisController } from './controller';
import { visFactory } from '../../../ui/public/vis/vis_factory';
@ -52,7 +52,7 @@ export default function GoalVisType() {
orientation: 'vertical',
useRanges: false,
colorSchema: ColorSchemas.GreenToRed,
gaugeColorMode: GaugeColorModes.NONE,
gaugeColorMode: ColorModes.NONE,
colorsRange: [
{ from: 0, to: 10000 }
],

View file

@ -41,13 +41,21 @@ export interface ColorSchemaVislibParams {
invertColors: boolean;
}
interface Labels {
color: string;
filter: boolean;
export interface Labels {
color?: string;
filter?: boolean;
overwriteColor?: boolean;
rotate?: Rotates;
show: boolean;
truncate: number | null;
truncate?: number | null;
}
export interface Style {
bgFill: string;
bgColor: boolean;
labelColor: boolean;
subText: string;
fontSize: number;
}
export interface Scale {
@ -74,7 +82,7 @@ export interface Axis {
position: Positions;
scale: Scale;
show: boolean;
style: object;
style: Style;
title: { text: string };
type: AxisTypes;
}

View file

@ -253,7 +253,8 @@ export enum GaugeTypes {
CIRCLE = 'Circle',
}
export enum GaugeColorModes {
export enum ColorModes {
BACKGROUND = 'Background',
LABELS = 'Labels',
NONE = 'None',
}

View file

@ -0,0 +1,197 @@
/*
* 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 {
EuiButtonGroup,
EuiButtonGroupProps,
EuiFormRow,
EuiPanel,
EuiSpacer,
EuiTitle,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { VisOptionsProps } from 'ui/vis/editors/default';
import {
ColorRanges,
ColorSchemaOptions,
SwitchOption,
RangeOption,
SetColorSchemaOptionsValue,
} from '../../../kbn_vislib_vis_types/public/components';
import { ColorModes } from '../../../kbn_vislib_vis_types/public/utils/collections';
import { MetricVisParam, VisParams } from '../types';
function MetricVisOptions({
stateParams,
setValue,
setValidity,
setTouched,
vis,
uiState,
}: VisOptionsProps<VisParams>) {
const setMetricValue: <T extends keyof MetricVisParam>(
paramName: T,
value: MetricVisParam[T]
) => void = useCallback(
(paramName, value) =>
setValue('metric', {
...stateParams.metric,
[paramName]: value,
}),
[setValue, stateParams.metric]
);
const setMetricLabels: <T extends keyof MetricVisParam['labels']>(
paramName: T,
value: MetricVisParam['labels'][T]
) => void = useCallback(
(paramName, value) =>
setMetricValue('labels', {
...stateParams.metric.labels,
[paramName]: value,
}),
[setMetricValue, stateParams.metric.labels]
);
const setMetricStyle: <T extends keyof MetricVisParam['style']>(
paramName: T,
value: MetricVisParam['style'][T]
) => void = useCallback(
(paramName, value) =>
setMetricValue('style', {
...stateParams.metric.style,
[paramName]: value,
}),
[setMetricValue, stateParams.metric.style]
);
const setColorMode: EuiButtonGroupProps['onChange'] = useCallback(
id => setMetricValue('metricColorMode', id as ColorModes),
[setMetricValue]
);
const metricColorModeLabel = i18n.translate('visTypeMetric.params.color.useForLabel', {
defaultMessage: 'Use color for',
});
return (
<>
<EuiPanel paddingSize="s">
<EuiTitle size="xs">
<h3>
<FormattedMessage id="visTypeMetric.params.settingsTitle" defaultMessage="Settings" />
</h3>
</EuiTitle>
<EuiSpacer size="s" />
<SwitchOption
label={i18n.translate('visTypeMetric.params.percentageModeLabel', {
defaultMessage: 'Percentage mode',
})}
paramName="percentageMode"
value={stateParams.metric.percentageMode}
setValue={setMetricValue}
/>
<SwitchOption
label={i18n.translate('visTypeMetric.params.showTitleLabel', {
defaultMessage: 'Show title',
})}
paramName="show"
value={stateParams.metric.labels.show}
setValue={setMetricLabels}
/>
</EuiPanel>
<EuiSpacer size="s" />
<EuiPanel paddingSize="s">
<EuiTitle size="xs">
<h3>
<FormattedMessage id="visTypeMetric.params.rangesTitle" defaultMessage="Ranges" />
</h3>
</EuiTitle>
<EuiSpacer size="s" />
<ColorRanges
data-test-subj="metricColorRange"
colorsRange={stateParams.metric.colorsRange}
setValue={setMetricValue}
setTouched={setTouched}
setValidity={setValidity}
/>
<EuiFormRow fullWidth display="rowCompressed" label={metricColorModeLabel}>
<EuiButtonGroup
buttonSize="compressed"
idSelected={stateParams.metric.metricColorMode}
isDisabled={stateParams.metric.colorsRange.length === 1}
isFullWidth={true}
legend={metricColorModeLabel}
options={vis.type.editorConfig.collections.metricColorMode}
onChange={setColorMode}
/>
</EuiFormRow>
<ColorSchemaOptions
colorSchema={stateParams.metric.colorSchema}
colorSchemas={vis.type.editorConfig.collections.colorSchemas}
disabled={
stateParams.metric.colorsRange.length === 1 ||
stateParams.metric.metricColorMode === ColorModes.NONE
}
invertColors={stateParams.metric.invertColors}
setValue={setMetricValue as SetColorSchemaOptionsValue}
showHelpText={false}
uiState={uiState}
/>
</EuiPanel>
<EuiSpacer size="s" />
<EuiPanel paddingSize="s">
<EuiTitle size="xs">
<h3>
<FormattedMessage id="visTypeMetric.params.style.styleTitle" defaultMessage="Style" />
</h3>
</EuiTitle>
<EuiSpacer size="s" />
<RangeOption
label={i18n.translate('visTypeMetric.params.style.fontSizeLabel', {
defaultMessage: 'Metric font size in points',
})}
min={12}
max={120}
paramName="fontSize"
value={stateParams.metric.style.fontSize}
setValue={setMetricStyle}
showInput={true}
showLabels={true}
showValue={false}
/>
</EuiPanel>
</>
);
}
export { MetricVisOptions };

View file

@ -1,20 +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.
*/
export { MetricVisParams } from './metric_vis_params';

View file

@ -1,249 +0,0 @@
<div class="visEditorSidebar__section">
<div class="visEditorSidebar__formRow">
<label
class="visEditorSidebar__formLabel"
for="percentageMode"
i18n-id="visTypeMetric.params.percentageModeLabel"
i18n-default-message="Percentage Mode"
>
</label>
<div class="visEditorSidebar__formControl">
<input class="kuiCheckBox" id="percentageMode" type="checkbox" ng-model="editorState.params.metric.percentageMode">
</div>
</div>
<div class="visEditorSidebar__formRow">
<label
class="visEditorSidebar__formLabel"
for="showLabels"
i18n-id="visTypeMetric.params.showLabelsLabel"
i18n-default-message="Show Labels"
>
</label>
<div class="visEditorSidebar__formControl">
<input class="kuiCheckBox" id="showLabels" type="checkbox" ng-model="editorState.params.metric.labels.show">
</div>
</div>
<div class="visEditorSidebar__collapsible--margin">
<div class="visEditorSidebar__collapsibleTitle">
<div
kbn-accessible-click
aria-expanded="{{!!showColorRange}}"
aria-controls="metricOptionsRanges"
aria-label="{{::'visTypeMetric.params.ranges.toggleOptionsAriaLabel' | i18n: { defaultMessage: '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="visTypeMetric.params.rangesTitle"
i18n-default-message="Ranges"
>
</span>
</div>
</div>
<div id="metricOptionsRanges" ng-show="showColorRange">
<table class="visEditorAgg__rangesTable form-group" ng-show="editorState.params.metric.colorsRange.length">
<tr>
<th scope="col">
<label
id="metricOptionsCustomRangeFrom"
i18n-id="visTypeMetric.params.ranges.fromLabel"
i18n-default-message="From"
>
</label>
</th>
<th scope="col" colspan="2">
<label
id="metricOptionsCustomRangeTo"
i18n-id="visTypeMetric.params.ranges.toLabel"
i18n-default-message="To"
>
</label>
</th>
</tr>
<tr ng-repeat="range in editorState.params.metric.colorsRange track by $index">
<td>
<input
aria-labelledby="metricOptionsCustomRangeFrom"
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="metricOptionsCustomRangeTo"
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.metric.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.metric.colorsRange.length">
<p>
<i class="fa fa-danger text-danger"></i>
<span
i18n-id="visTypeMetric.params.ranges.warning.specifyRangeDescription"
i18n-default-message="{requiredDescription} You must specify at least one range."
i18n-values="{ html_requiredDescription: '<strong>' + editorState.requiredDescription + '</strong>' }"
>
</span>
</p>
</div>
<div
ng-click="addRange()"
class="kuiButton kuiButton--primary kuiButton--fullWidth"
i18n-id="visTypeMetric.params.ranges.addRangeButtonLabel"
i18n-default-message="Add Range"
>
</div>
</div>
</div>
<div ng-show="editorState.params.metric.colorsRange.length > 1" class="visEditorSidebar__collapsible--margin">
<div class="visEditorSidebar__collapsibleTitle">
<div
kbn-accessible-click
aria-expanded="{{!!showColorOptions}}"
aria-controls="metricOptionsColors"
aria-label="{{::'visTypeMetric.params.color.toggleOptionsAriaLabel' | i18n: { defaultMessage: '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="visTypeMetric.params.color.colorOptionsTitle"
i18n-default-message="Color Options"
>
</span>
</div>
</div>
<div id="metricOptionsColors" ng-if="showColorOptions">
<div class="visEditorSidebar__formRow" ng-show="editorState.params.metric.colorsRange.length > 1">
<label
class="visEditorSidebar__formLabel"
for="metricColorMode"
i18n-id="visTypeMetric.params.color.useForLabel"
i18n-default-message="Use Color For"
>
</label>
<div class="visEditorSidebar__formControl">
<select
id="metricColorMode"
class="kuiSelect visEditorSidebar__select"
ng-model="editorState.params.metric.metricColorMode"
ng-options="mode.id as mode.label for mode in collections.metricColorMode"
></select>
</div>
</div>
<div class="visEditorSidebar__formRow" ng-show="editorState.params.metric.metricColorMode !== 'None'">
<label
class="visEditorSidebar__formLabel"
for="colorSchema"
i18n-id="visTypeMetric.params.color.schemaLabel"
i18n-default-message="Color Schema"
>
</label>
<div class="visEditorSidebar__formControl">
<select
id="colorSchema"
class="kuiSelect visEditorSidebar__select"
ng-model="editorState.params.metric.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="visTypeMetric.params.color.resetColorDescription"
i18n-default-message="reset colors"
>
</div>
</div>
<div class="visEditorSidebar__formRow" ng-show="editorState.params.metric.metricColorMode !== 'None'">
<label
class="visEditorSidebar__formLabel"
for="invertColors"
i18n-id="visTypeMetric.params.color.reverseSchemaLabel"
i18n-default-message="Reverse Color Schema"
>
</label>
<div class="visEditorSidebar__formControl">
<input class="kuiCheckBox" id="invertColors" type="checkbox" ng-model="editorState.params.metric.invertColors">
</div>
</div>
</div>
</div>
<div class="visEditorSidebar__collapsible--margin">
<div class="visEditorSidebar__collapsibleTitle">
<div
kbn-accessible-click
aria-expanded="{{!!showStyle}}"
aria-controls="metricOptionsStyle"
aria-label="{{::'visTypeMetric.params.style.toggleOptionsAriaLabel' | i18n: { defaultMessage: '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="visTypeMetric.params.style.styleTitle"
i18n-default-message="Style"
>
</span>
</div>
</div>
<div id="metricOptionsStyle" ng-if="showStyle">
<div class="visEditorSidebar__formRow">
<label class="visEditorSidebar__formLabel" for="metricFontSize">
<span
i18n-id="visTypeMetric.params.style.fontSizeLabel"
i18n-default-message="Font Size ({fontSize}pt)"
i18n-values="{ fontSize: editorState.params.metric.style.fontSize }"
>
</span>
</label>
<div class="visEditorSidebar__formControl">
<input id="metricFontSize" type="range" ng-model="editorState.params.metric.style.fontSize" class="form-control" min="12" max="120" />
</div>
</div>
</div>
</div>
</div>

View file

@ -1,86 +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 _ from 'lodash';
import { i18n } from '@kbn/i18n';
import metricVisParamsTemplate from './metric_vis_params.html';
export function MetricVisParams() {
return {
restrict: 'E',
template: metricVisParamsTemplate,
replace: true,
link: function ($scope) {
$scope.collections = $scope.vis.type.editorConfig.collections;
$scope.showColorRange = true;
$scope.$watch('editorState.params.metric.metricColorMode', newValue => {
switch (newValue) {
case 'Labels':
$scope.editorState.params.metric.style.labelColor = true;
$scope.editorState.params.metric.style.bgColor = false;
break;
case 'Background':
$scope.editorState.params.metric.style.labelColor = false;
$scope.editorState.params.metric.style.bgColor = true;
break;
case 'None':
$scope.editorState.params.metric.style.labelColor = false;
$scope.editorState.params.metric.style.bgColor = false;
break;
}
});
$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.metric.colorsRange[index - 1].to;
};
$scope.addRange = function () {
const previousRange = _.last($scope.editorState.params.metric.colorsRange);
const from = previousRange ? previousRange.to : 0;
const to = previousRange ? from + (previousRange.to - previousRange.from) : 100;
$scope.editorState.params.metric.colorsRange.push({ from: from, to: to });
};
$scope.removeRange = function (index) {
$scope.editorState.params.metric.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.editorState.requiredDescription = i18n.translate(
'visTypeMetric.params.ranges.warning.requiredDescription', { defaultMessage: 'Required:' });
},
};
}

View file

@ -22,16 +22,11 @@ import { npSetup, npStart } from 'ui/new_platform';
import { setup as visualizationsSetup } from '../../visualizations/public/np_ready/public/legacy';
import { MetricVisPluginSetupDependencies } from './plugin';
import { LegacyDependenciesPlugin } from './shim';
import { plugin } from '.';
const plugins: Readonly<MetricVisPluginSetupDependencies> = {
expressions: npSetup.plugins.expressions,
visualizations: visualizationsSetup,
// Temporary solution
// It will be removed when all dependent services are migrated to the new platform.
__LEGACY: new LegacyDependenciesPlugin(),
};
const pluginInstance = plugin({} as PluginInitializerContext);

View file

@ -19,9 +19,10 @@
import { i18n } from '@kbn/i18n';
// @ts-ignore
import { vislibColorMaps } from 'ui/vislib/components/color/colormaps';
import { ExpressionFunction, KibanaDatatable, Render, Range, Style } from '../../interpreter/types';
import { vislibColorMaps, ColorSchemas } from 'ui/vislib/components/color/colormaps';
import { ExpressionFunction, KibanaDatatable, Range, Render, Style } from '../../interpreter/types';
import { ColorModes } from '../../kbn_vislib_vis_types/public/utils/collections';
import { visType, DimensionsVisParam, VisParams } from './types';
type Context = KibanaDatatable;
@ -29,8 +30,8 @@ const name = 'metricVis';
interface Arguments {
percentage: boolean;
colorScheme: string;
colorMode: string;
colorScheme: ColorSchemas;
colorMode: ColorModes;
useRanges: boolean;
invertColors: boolean;
showLabels: boolean;
@ -42,39 +43,10 @@ interface Arguments {
bucket: any; // these aren't typed yet
}
interface VisParams {
dimensions: DimensionsVisParam;
metric: MetricVisParam;
}
interface DimensionsVisParam {
metrics: any;
bucket?: any;
}
interface MetricVisParam {
percentageMode: Arguments['percentage'];
useRanges: Arguments['useRanges'];
colorSchema: Arguments['colorScheme'];
metricColorMode: Arguments['colorMode'];
colorsRange: Arguments['colorRange'];
labels: {
show: Arguments['showLabels'];
};
invertColors: Arguments['invertColors'];
style: {
bgFill: Arguments['bgFill'];
bgColor: boolean;
labelColor: boolean;
subText: Arguments['subText'];
fontSize: number;
};
}
interface RenderValue {
visType: 'metric';
visType: typeof visType;
visData: Context;
visConfig: VisParams;
visConfig: Pick<VisParams, 'metric' | 'dimensions'>;
params: any;
}
@ -113,7 +85,7 @@ export const createMetricVisFn = (): ExpressionFunction<
colorMode: {
types: ['string'],
default: '"None"',
options: ['None', 'Label', 'Background'],
options: [ColorModes.NONE, ColorModes.LABELS, ColorModes.BACKGROUND],
help: i18n.translate('visTypeMetric.function.colorMode.help', {
defaultMessage: 'Which part of metric to color',
}),
@ -206,7 +178,7 @@ export const createMetricVisFn = (): ExpressionFunction<
as: 'visualization',
value: {
visData: context,
visType: 'metric',
visType,
visConfig: {
metric: {
percentageMode: args.percentage,
@ -220,8 +192,8 @@ export const createMetricVisFn = (): ExpressionFunction<
invertColors: args.invertColors,
style: {
bgFill: args.bgFill,
bgColor: args.colorMode === 'Background',
labelColor: args.colorMode === 'Labels',
bgColor: args.colorMode === ColorModes.BACKGROUND,
labelColor: args.colorMode === ColorModes.LABELS,
subText: args.subText,
fontSize,
},

View file

@ -21,12 +21,16 @@ import { i18n } from '@kbn/i18n';
// @ts-ignore
import { Schemas } from 'ui/vis/editors/default/schemas';
// @ts-ignore
import { vislibColorMaps } from 'ui/vislib/components/color/colormaps';
import { AggGroupNames } from 'ui/vis/editors/default';
import { colorSchemas, ColorSchemas } from 'ui/vislib/components/color/colormaps';
// @ts-ignore
import { MetricVisComponent } from './components/metric_vis_controller';
import { visFactory } from '../../visualizations/public';
import { MetricVisOptions } from './components/metric_vis_options';
import { ColorModes } from '../../kbn_vislib_vis_types/public/utils/collections';
export const createMetricVisTypeDefinition = () => {
return visFactory.createReactVisualization({
@ -45,8 +49,8 @@ export const createMetricVisTypeDefinition = () => {
metric: {
percentageMode: false,
useRanges: false,
colorSchema: 'Green to Red',
metricColorMode: 'None',
colorSchema: ColorSchemas.GreenToRed,
metricColorMode: ColorModes.NONE,
colorsRange: [{ from: 0, to: 10000 }],
labels: {
show: true,
@ -66,33 +70,30 @@ export const createMetricVisTypeDefinition = () => {
collections: {
metricColorMode: [
{
id: 'None',
id: ColorModes.NONE,
label: i18n.translate('visTypeMetric.colorModes.noneOptionLabel', {
defaultMessage: 'None',
}),
},
{
id: 'Labels',
id: ColorModes.LABELS,
label: i18n.translate('visTypeMetric.colorModes.labelsOptionLabel', {
defaultMessage: 'Labels',
}),
},
{
id: 'Background',
id: ColorModes.BACKGROUND,
label: i18n.translate('visTypeMetric.colorModes.backgroundOptionLabel', {
defaultMessage: 'Background',
}),
},
],
colorSchemas: Object.values(vislibColorMaps).map((value: any) => ({
id: value.id,
label: value.label,
})),
colorSchemas,
},
optionsTemplate: '<metric-vis-params></metric-vis-params>',
optionsTemplate: MetricVisOptions,
schemas: new Schemas([
{
group: 'metrics',
group: AggGroupNames.Metrics,
name: 'metric',
title: i18n.translate('visTypeMetric.schemas.metricTitle', { defaultMessage: 'Metric' }),
min: 1,
@ -118,7 +119,7 @@ export const createMetricVisTypeDefinition = () => {
],
},
{
group: 'buckets',
group: AggGroupNames.Buckets,
name: 'group',
title: i18n.translate('visTypeMetric.schemas.splitGroupTitle', {
defaultMessage: 'Split group',

View file

@ -18,19 +18,16 @@
*/
import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../../core/public';
import { LegacyDependenciesPlugin } from './shim';
import { Plugin as ExpressionsPublicPlugin } from '../../../../plugins/expressions/public';
import { VisualizationsSetup } from '../../visualizations/public';
import { createMetricVisFn } from './metric_vis_fn';
// @ts-ignore
import { createMetricVisTypeDefinition } from './metric_vis_type';
/** @internal */
export interface MetricVisPluginSetupDependencies {
expressions: ReturnType<ExpressionsPublicPlugin['setup']>;
visualizations: VisualizationsSetup;
__LEGACY: LegacyDependenciesPlugin;
}
/** @internal */
@ -41,12 +38,7 @@ export class MetricVisPlugin implements Plugin<void, void> {
this.initializerContext = initializerContext;
}
public setup(
core: CoreSetup,
{ expressions, visualizations, __LEGACY }: MetricVisPluginSetupDependencies
) {
__LEGACY.setup();
public setup(core: CoreSetup, { expressions, visualizations }: MetricVisPluginSetupDependencies) {
expressions.registerFunction(createMetricVisFn);
visualizations.types.registerVisualization(createMetricVisTypeDefinition);
}

View file

@ -1,20 +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.
*/
export * from './legacy_dependencies_plugin';

View file

@ -1,31 +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 { CoreStart, Plugin } from 'kibana/public';
import { initMetricVisLegacyModule } from './metric_vis_legacy_module';
export class LegacyDependenciesPlugin implements Plugin<void, void> {
public setup() {
// Init kibana/metric_vis AngularJS module.
initMetricVisLegacyModule();
}
public start(core: CoreStart) {
// nothing to do here yet
}
}

View file

@ -1,31 +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 { once } from 'lodash';
// @ts-ignore
import { uiModules } from 'ui/modules';
// @ts-ignore
import 'ui/directives/inequality';
// @ts-ignore
import { MetricVisParams } from '../components/metric_vis_params';
/** @internal */
export const initMetricVisLegacyModule = once((): void => {
uiModules.get('kibana/metric_vis', ['kibana']).directive('metricVisParams', MetricVisParams);
});

View file

@ -0,0 +1,50 @@
/*
* 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';
import { RangeValues } from 'ui/vis/editors/default/controls/ranges';
import { SchemaConfig } from 'ui/visualize/loader/pipeline_helpers/build_pipeline';
import { ColorModes } from '../../kbn_vislib_vis_types/public/utils/collections';
import { Labels, Style } from '../../kbn_vislib_vis_types/public/types';
export const visType = 'metric';
export interface DimensionsVisParam {
metrics: SchemaConfig[];
bucket?: SchemaConfig[];
}
export interface MetricVisParam {
percentageMode: boolean;
useRanges: boolean;
colorSchema: ColorSchemas;
metricColorMode: ColorModes;
colorsRange: RangeValues[];
labels: Labels;
invertColors: boolean;
style: Style;
}
export interface VisParams {
addTooltip: boolean;
addLegend: boolean;
dimensions: DimensionsVisParam;
metric: MetricVisParam;
type: typeof visType;
}

View file

@ -1,124 +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 expect from '@kbn/expect';
import ngMock from 'ng_mock';
import '../inequality';
describe('greater_than model validator directive', function () {
let $compile;
let $rootScope;
let html;
beforeEach(ngMock.module('kibana'));
beforeEach(ngMock.inject(function (_$compile_, _$rootScope_) {
$compile = _$compile_;
$rootScope = _$rootScope_;
}));
describe('without value', function () {
let element;
beforeEach(function () {
html = '<input type="text" ng-model="value" greater-than />';
element = $compile(html)($rootScope);
});
it('should be valid when larger than 0', function () {
$rootScope.value = '1';
$rootScope.$digest();
expect(element.hasClass('ng-valid')).to.be.ok();
});
it('should be valid for 0', function () {
$rootScope.value = '0';
$rootScope.$digest();
expect(element.hasClass('ng-valid')).to.be.ok();
});
it('should be valid for negatives', function () {
$rootScope.value = '-10';
$rootScope.$digest();
expect(element.hasClass('ng-valid')).to.be.ok();
});
});
describe('with string values', function () {
let element;
beforeEach(function () {
html = `<input type="text" ng-model="value" greater-than="'10'" />`;
element = $compile(html)($rootScope);
});
it('should be valid for greater than 10', function () {
$rootScope.value = '15';
$rootScope.$digest();
expect(element.hasClass('ng-valid')).to.be.ok();
});
it('should be invalid for 10', function () {
$rootScope.value = '10';
$rootScope.$digest();
expect(element.hasClass('ng-invalid')).to.be.ok();
});
// Edge case because '5' > '10' as strings
it('should be invalid less than 10', function () {
$rootScope.value = '5';
$rootScope.$digest();
expect(element.hasClass('ng-invalid')).to.be.ok();
});
});
[0, 1, 10, 42, -12].forEach(function (num) {
describe('with value ' + num, function () {
let element;
beforeEach(function () {
html = '<input type="text" ng-model="value" greater-than="' + num + '" />';
element = $compile(html)($rootScope);
});
it('should be valid when larger than ' + num, function () {
$rootScope.value = num + 1;
$rootScope.$digest();
expect(element.hasClass('ng-valid')).to.be.ok();
});
it('should be invalid for ' + num, function () {
$rootScope.value = num;
$rootScope.$digest();
expect(element.hasClass('ng-invalid')).to.be.ok();
});
it('should be invalid for less than ' + num, function () {
$rootScope.value = num - 1;
$rootScope.$digest();
expect(element.hasClass('ng-invalid')).to.be.ok();
});
it('should be valid for empty model values', () => {
[undefined, null, ''].forEach(val => {
$rootScope.value = val;
$rootScope.$digest();
expect(element.hasClass('ng-valid')).to.be.ok();
});
});
});
});
});

View file

@ -1,65 +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 '../modules';
function makeDirectiveDef(id, compare) {
return function ($parse) {
return {
require: 'ngModel',
link: function ($scope, $el, $attr, ngModel) {
const getBound = function () { return $parse($attr[id])($scope); };
ngModel.$parsers.push(validate);
ngModel.$formatters.push(validate);
$scope.$watch(getBound, function () {
validate(ngModel.$viewValue);
});
// We only set it to invalid when both the model value and the value to compare against are
// provided, and the values do not meet the condition.
function validate(val) {
const bound = getBound();
const left = parseFloat(val);
const right = parseFloat(bound);
const isValid = isEmpty(val) || isEmpty(bound) || compare(left, right);
ngModel.$setValidity(id, isValid);
return val;
}
function isEmpty(val) {
return typeof val === 'undefined' || val === null || val === '';
}
}
};
};
}
uiModules
.get('kibana')
.directive('greaterThan', makeDirectiveDef('greaterThan', function (a, b) {
return a > b;
}))
.directive('lessThan', makeDirectiveDef('lessThan', function (a, b) {
return a < b;
}))
.directive('greaterOrEqualThan', makeDirectiveDef('greaterOrEqualThan', function (a, b) {
return a >= b;
}));

View file

@ -1,17 +1,3 @@
//
// Misc elements -- found in agg_types/controls/*.html
//
.visEditorAgg__rangesTable {
td {
padding: 0 $euiSizeS $euiSizeS 0;
&:last-child {
padding-right: 0;
}
}
}
.visEditorAgg__subAgg {
border: $euiBorderThick;
border-radius: $euiBorderRadius;

View file

@ -122,49 +122,10 @@
background-color: lightOrDarkTheme($euiPageBackgroundColor, $euiColorLightestShade);
}
.visEditorSidebar__collapsible--margin {
margin-top: $euiSizeM;
}
.visEditorSidebar__collapsible--marginBottom {
margin-bottom: $euiSizeM;
}
.visEditorSidebar__collapsibleTitle {
@include euiFontSizeS;
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
white-space: nowrap;
+ * {
margin-top: $euiSize;
display: block;
}
+ .form-group {
margin-top: $euiSizeXS;
}
label {
margin-bottom: 0 !important; // For filters
}
}
.visEditorSidebar__collapsibleTitleLabel {
color: $euiColorPrimary;
display: flex;
align-items: center;
margin-right: $euiSizeXS;
line-height: $euiLineHeight;
}
.visEditorSidebar__collapsibleTitleText {
@include euiTextTruncate;
margin-left: $euiSizeS;
}
//
// FORMS
//

View file

@ -41,6 +41,7 @@ const generateId = htmlIdGenerator();
const isEmpty = (value: any) => value === undefined || value === null;
export interface RangeValues {
type?: 'range';
from?: number;
to?: number;
}

View file

@ -2656,24 +2656,8 @@
"visTypeMetric.function.help": "メトリックビジュアライゼーション",
"visTypeMetric.metricDescription": "計算結果を単独の数字として表示します。",
"visTypeMetric.metricTitle": "メトリック",
"visTypeMetric.params.color.colorOptionsTitle": "カラーオプション",
"visTypeMetric.params.color.resetColorDescription": "色をリセットします",
"visTypeMetric.params.color.reverseSchemaLabel": "カラースキームを反転",
"visTypeMetric.params.color.schemaLabel": "カラースキーム",
"visTypeMetric.params.color.toggleOptionsAriaLabel": "カラーオプションを切り替える",
"visTypeMetric.params.color.useForLabel": "色の使用",
"visTypeMetric.params.percentageModeLabel": "パーセンテージモード",
"visTypeMetric.params.ranges.addRangeButtonLabel": "範囲を追加",
"visTypeMetric.params.ranges.fromLabel": "From",
"visTypeMetric.params.ranges.toggleOptionsAriaLabel": "範囲オプションを切り替える",
"visTypeMetric.params.ranges.toLabel": "To",
"visTypeMetric.params.ranges.warning.requiredDescription": "必須:",
"visTypeMetric.params.ranges.warning.specifyRangeDescription": "{requiredDescription} 範囲を最低 1 つ指定する必要があります。",
"visTypeMetric.params.rangesTitle": "範囲",
"visTypeMetric.params.showLabelsLabel": "ラベルを表示",
"visTypeMetric.params.style.fontSizeLabel": "フォントサイズ ({fontSize} pt)",
"visTypeMetric.params.style.styleTitle": "スタイル",
"visTypeMetric.params.style.toggleOptionsAriaLabel": "スタイルオプションを切り替える",
"visTypeMetric.schemas.metricTitle": "メトリック",
"visTypeMetric.schemas.splitGroupTitle": "グループを分割",
"visTypeMetric.function.bgFill.help": "html 16 進数コード (#123456)、html 色 (red、blue)、または rgba 値 (rgba(255,255,255,1))。",

View file

@ -2657,24 +2657,8 @@
"visTypeMetric.function.help": "指标可视化",
"visTypeMetric.metricDescription": "将计算结果显示为单个数字",
"visTypeMetric.metricTitle": "指标",
"visTypeMetric.params.color.colorOptionsTitle": "颜色选项",
"visTypeMetric.params.color.resetColorDescription": "重置颜色",
"visTypeMetric.params.color.reverseSchemaLabel": "反色模式",
"visTypeMetric.params.color.schemaLabel": "颜色模式",
"visTypeMetric.params.color.toggleOptionsAriaLabel": "切换颜色选项",
"visTypeMetric.params.color.useForLabel": "将颜色用于",
"visTypeMetric.params.percentageModeLabel": "百分比模式",
"visTypeMetric.params.ranges.addRangeButtonLabel": "添加范围",
"visTypeMetric.params.ranges.fromLabel": "从",
"visTypeMetric.params.ranges.toggleOptionsAriaLabel": "切换范围选项",
"visTypeMetric.params.ranges.toLabel": "到",
"visTypeMetric.params.ranges.warning.requiredDescription": "必需:",
"visTypeMetric.params.ranges.warning.specifyRangeDescription": "{requiredDescription}您必须指定至少一个范围。",
"visTypeMetric.params.rangesTitle": "范围",
"visTypeMetric.params.showLabelsLabel": "显示标签",
"visTypeMetric.params.style.fontSizeLabel": "字体大小({fontSize} 磅)",
"visTypeMetric.params.style.styleTitle": "样式",
"visTypeMetric.params.style.toggleOptionsAriaLabel": "切换样式选项",
"visTypeMetric.schemas.metricTitle": "指标",
"visTypeMetric.schemas.splitGroupTitle": "拆分组",
"visTypeMetric.function.bgFill.help": "将颜色表示为 html 十六进制代码 (#123456)、html 颜色red、blue或 rgba 值 (rgba(255,255,255,1))。",