mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
parent
83fe6feb1c
commit
2cab61f1e1
25 changed files with 224 additions and 105 deletions
|
@ -415,7 +415,7 @@ the infrastructure monitoring use-case within Kibana.
|
|||
|
||||
|
||||
|{kib-repo}blob/{branch}/x-pack/plugins/lens/readme.md[lens]
|
||||
|Run all tests from the x-pack root directory
|
||||
|Visualization editor allowing to quickly and easily configure compelling visualizations to use on dashboards and canvas workpads.
|
||||
|
||||
|
||||
|{kib-repo}blob/{branch}/x-pack/plugins/license_management/README.md[licenseManagement]
|
||||
|
|
|
@ -19,7 +19,11 @@ import {
|
|||
} from '@elastic/eui';
|
||||
import { IndexPattern } from 'src/plugins/data/public';
|
||||
import { CoreStart } from 'kibana/public';
|
||||
import { TypedLensByValueInput } from '../../../plugins/lens/public';
|
||||
import {
|
||||
TypedLensByValueInput,
|
||||
PersistedIndexPatternLayer,
|
||||
XYState,
|
||||
} from '../../../plugins/lens/public';
|
||||
import { StartDependencies } from './plugin';
|
||||
|
||||
// Generate a Lens state based on some app-specific input parameters.
|
||||
|
@ -28,6 +32,48 @@ function getLensAttributes(
|
|||
defaultIndexPattern: IndexPattern,
|
||||
color: string
|
||||
): TypedLensByValueInput['attributes'] {
|
||||
const dataLayer: PersistedIndexPatternLayer = {
|
||||
columnOrder: ['col1', 'col2'],
|
||||
columns: {
|
||||
col2: {
|
||||
dataType: 'number',
|
||||
isBucketed: false,
|
||||
label: 'Count of records',
|
||||
operationType: 'count',
|
||||
scale: 'ratio',
|
||||
sourceField: 'Records',
|
||||
},
|
||||
col1: {
|
||||
dataType: 'date',
|
||||
isBucketed: true,
|
||||
label: '@timestamp',
|
||||
operationType: 'date_histogram',
|
||||
params: { interval: 'auto' },
|
||||
scale: 'interval',
|
||||
sourceField: defaultIndexPattern.timeFieldName!,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const xyConfig: XYState = {
|
||||
axisTitlesVisibilitySettings: { x: true, yLeft: true, yRight: true },
|
||||
fittingFunction: 'None',
|
||||
gridlinesVisibilitySettings: { x: true, yLeft: true, yRight: true },
|
||||
layers: [
|
||||
{
|
||||
accessors: ['col2'],
|
||||
layerId: 'layer1',
|
||||
seriesType: 'bar_stacked',
|
||||
xAccessor: 'col1',
|
||||
yConfig: [{ forAccessor: 'col2', color }],
|
||||
},
|
||||
],
|
||||
legend: { isVisible: true, position: 'right' },
|
||||
preferredSeriesType: 'bar_stacked',
|
||||
tickLabelsVisibilitySettings: { x: true, yLeft: true, yRight: true },
|
||||
valueLabels: 'hide',
|
||||
};
|
||||
|
||||
return {
|
||||
visualizationType: 'lnsXY',
|
||||
title: 'Prefilled from example app',
|
||||
|
@ -47,51 +93,13 @@ function getLensAttributes(
|
|||
datasourceStates: {
|
||||
indexpattern: {
|
||||
layers: {
|
||||
layer1: {
|
||||
columnOrder: ['col1', 'col2'],
|
||||
columns: {
|
||||
col2: {
|
||||
dataType: 'number',
|
||||
isBucketed: false,
|
||||
label: 'Count of records',
|
||||
operationType: 'count',
|
||||
scale: 'ratio',
|
||||
sourceField: 'Records',
|
||||
},
|
||||
col1: {
|
||||
dataType: 'date',
|
||||
isBucketed: true,
|
||||
label: '@timestamp',
|
||||
operationType: 'date_histogram',
|
||||
params: { interval: 'auto' },
|
||||
scale: 'interval',
|
||||
sourceField: defaultIndexPattern.timeFieldName!,
|
||||
},
|
||||
},
|
||||
},
|
||||
layer1: dataLayer,
|
||||
},
|
||||
},
|
||||
},
|
||||
filters: [],
|
||||
query: { language: 'kuery', query: '' },
|
||||
visualization: {
|
||||
axisTitlesVisibilitySettings: { x: true, yLeft: true, yRight: true },
|
||||
fittingFunction: 'None',
|
||||
gridlinesVisibilitySettings: { x: true, yLeft: true, yRight: true },
|
||||
layers: [
|
||||
{
|
||||
accessors: ['col2'],
|
||||
layerId: 'layer1',
|
||||
seriesType: 'bar_stacked',
|
||||
xAccessor: 'col1',
|
||||
yConfig: [{ forAccessor: 'col2', color }],
|
||||
},
|
||||
],
|
||||
legend: { isVisible: true, position: 'right' },
|
||||
preferredSeriesType: 'bar_stacked',
|
||||
tickLabelsVisibilitySettings: { x: true, yLeft: true, yRight: true },
|
||||
valueLabels: 'hide',
|
||||
},
|
||||
visualization: xyConfig,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -16,13 +16,13 @@ import type {
|
|||
import type { DatatableColumnWidth } from './components/types';
|
||||
import { LensIconChartDatatable } from '../assets/chart_datatable';
|
||||
|
||||
export interface LayerState {
|
||||
export interface DatatableLayerState {
|
||||
layerId: string;
|
||||
columns: string[];
|
||||
}
|
||||
|
||||
export interface DatatableVisualizationState {
|
||||
layers: LayerState[];
|
||||
layers: DatatableLayerState[];
|
||||
sorting?: {
|
||||
columnId: string | undefined;
|
||||
direction: 'asc' | 'desc' | 'none';
|
||||
|
@ -30,7 +30,7 @@ export interface DatatableVisualizationState {
|
|||
columnWidth?: DatatableColumnWidth[];
|
||||
}
|
||||
|
||||
function newLayerState(layerId: string): LayerState {
|
||||
function newLayerState(layerId: string): DatatableLayerState {
|
||||
return {
|
||||
layerId,
|
||||
columns: [],
|
||||
|
@ -300,7 +300,7 @@ function getDataSourceAndSortedColumns(
|
|||
datasourceLayers: Record<string, DatasourcePublicAPI>,
|
||||
layerId: string
|
||||
) {
|
||||
const layer = state.layers.find((l: LayerState) => l.layerId === layerId);
|
||||
const layer = state.layers.find((l: DatatableLayerState) => l.layerId === layerId);
|
||||
if (!layer) {
|
||||
return undefined;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import type { IndexPatternPersistedState } from '../../indexpattern_datasource/t
|
|||
import type { XYState } from '../../xy_visualization/types';
|
||||
import type { PieVisualizationState } from '../../pie_visualization/types';
|
||||
import type { DatatableVisualizationState } from '../../datatable_visualization/visualization';
|
||||
import type { State as MetricState } from '../../metric_visualization/types';
|
||||
import type { MetricState } from '../../metric_visualization/types';
|
||||
|
||||
type LensAttributes<TVisType, TVisState> = Omit<
|
||||
Document,
|
||||
|
|
|
@ -10,11 +10,49 @@ export {
|
|||
EmbeddableComponentProps,
|
||||
TypedLensByValueInput,
|
||||
} from './editor_frame_service/embeddable/embeddable_component';
|
||||
export type { XYState } from './xy_visualization/types';
|
||||
export type { PieVisualizationState } from './pie_visualization/types';
|
||||
export type { DatatableVisualizationState } from './datatable_visualization/visualization';
|
||||
export type { State as MetricState } from './metric_visualization/types';
|
||||
export type { IndexPatternPersistedState } from './indexpattern_datasource/types';
|
||||
export type {
|
||||
XYState,
|
||||
AxesSettingsConfig,
|
||||
XYLayerConfig,
|
||||
LegendConfig,
|
||||
SeriesType,
|
||||
ValueLabelConfig,
|
||||
YAxisMode,
|
||||
} from './xy_visualization/types';
|
||||
export type {
|
||||
PieVisualizationState,
|
||||
PieLayerState,
|
||||
SharedPieLayerState,
|
||||
} from './pie_visualization/types';
|
||||
export type {
|
||||
DatatableVisualizationState,
|
||||
DatatableLayerState,
|
||||
} from './datatable_visualization/visualization';
|
||||
export type { MetricState } from './metric_visualization/types';
|
||||
export type {
|
||||
IndexPatternPersistedState,
|
||||
PersistedIndexPatternLayer,
|
||||
IndexPatternColumn,
|
||||
OperationType,
|
||||
IncompleteColumn,
|
||||
FiltersIndexPatternColumn,
|
||||
RangeIndexPatternColumn,
|
||||
TermsIndexPatternColumn,
|
||||
DateHistogramIndexPatternColumn,
|
||||
MinIndexPatternColumn,
|
||||
MaxIndexPatternColumn,
|
||||
AvgIndexPatternColumn,
|
||||
CardinalityIndexPatternColumn,
|
||||
SumIndexPatternColumn,
|
||||
MedianIndexPatternColumn,
|
||||
PercentileIndexPatternColumn,
|
||||
CountIndexPatternColumn,
|
||||
LastValueIndexPatternColumn,
|
||||
CumulativeSumIndexPatternColumn,
|
||||
CounterRateIndexPatternColumn,
|
||||
DerivativeIndexPatternColumn,
|
||||
MovingAverageIndexPatternColumn,
|
||||
} from './indexpattern_datasource/types';
|
||||
export { LensPublicStart } from './plugin';
|
||||
|
||||
export const plugin = () => new LensPlugin();
|
||||
|
|
|
@ -71,6 +71,28 @@ export type FieldBasedIndexPatternColumn = Extract<IndexPatternColumn, { sourceF
|
|||
|
||||
export { IncompleteColumn } from './column_types';
|
||||
|
||||
export { TermsIndexPatternColumn } from './terms';
|
||||
export { FiltersIndexPatternColumn } from './filters';
|
||||
export { CardinalityIndexPatternColumn } from './cardinality';
|
||||
export { PercentileIndexPatternColumn } from './percentile';
|
||||
export {
|
||||
MinIndexPatternColumn,
|
||||
AvgIndexPatternColumn,
|
||||
SumIndexPatternColumn,
|
||||
MaxIndexPatternColumn,
|
||||
MedianIndexPatternColumn,
|
||||
} from './metrics';
|
||||
export { DateHistogramIndexPatternColumn } from './date_histogram';
|
||||
export {
|
||||
CumulativeSumIndexPatternColumn,
|
||||
CounterRateIndexPatternColumn,
|
||||
DerivativeIndexPatternColumn,
|
||||
MovingAverageIndexPatternColumn,
|
||||
} from './calculations';
|
||||
export { CountIndexPatternColumn } from './count';
|
||||
export { LastValueIndexPatternColumn } from './last_value';
|
||||
export { RangeIndexPatternColumn } from './ranges';
|
||||
|
||||
// List of all operation definitions registered to this data source.
|
||||
// If you want to implement a new operation, add the definition to this array and
|
||||
// the column type to the `IndexPatternColumn` union type below.
|
||||
|
|
|
@ -13,6 +13,23 @@ export {
|
|||
FieldBasedIndexPatternColumn,
|
||||
IncompleteColumn,
|
||||
RequiredReference,
|
||||
FiltersIndexPatternColumn,
|
||||
RangeIndexPatternColumn,
|
||||
TermsIndexPatternColumn,
|
||||
DateHistogramIndexPatternColumn,
|
||||
MinIndexPatternColumn,
|
||||
MaxIndexPatternColumn,
|
||||
AvgIndexPatternColumn,
|
||||
CardinalityIndexPatternColumn,
|
||||
SumIndexPatternColumn,
|
||||
MedianIndexPatternColumn,
|
||||
PercentileIndexPatternColumn,
|
||||
CountIndexPatternColumn,
|
||||
LastValueIndexPatternColumn,
|
||||
CumulativeSumIndexPatternColumn,
|
||||
CounterRateIndexPatternColumn,
|
||||
DerivativeIndexPatternColumn,
|
||||
MovingAverageIndexPatternColumn,
|
||||
} from './definitions';
|
||||
|
||||
export { createMockedReferenceOperation } from './mocks';
|
||||
|
|
|
@ -8,6 +8,29 @@ import { IFieldType } from 'src/plugins/data/common';
|
|||
import { IndexPatternColumn, IncompleteColumn } from './operations';
|
||||
import { IndexPatternAggRestrictions } from '../../../../../src/plugins/data/public';
|
||||
|
||||
export {
|
||||
IndexPatternColumn,
|
||||
OperationType,
|
||||
IncompleteColumn,
|
||||
FiltersIndexPatternColumn,
|
||||
RangeIndexPatternColumn,
|
||||
TermsIndexPatternColumn,
|
||||
DateHistogramIndexPatternColumn,
|
||||
MinIndexPatternColumn,
|
||||
MaxIndexPatternColumn,
|
||||
AvgIndexPatternColumn,
|
||||
CardinalityIndexPatternColumn,
|
||||
SumIndexPatternColumn,
|
||||
MedianIndexPatternColumn,
|
||||
PercentileIndexPatternColumn,
|
||||
CountIndexPatternColumn,
|
||||
LastValueIndexPatternColumn,
|
||||
CumulativeSumIndexPatternColumn,
|
||||
CounterRateIndexPatternColumn,
|
||||
DerivativeIndexPatternColumn,
|
||||
MovingAverageIndexPatternColumn,
|
||||
} from './operations';
|
||||
|
||||
export interface IndexPattern {
|
||||
id: string;
|
||||
fields: IndexPatternField[];
|
||||
|
@ -43,6 +66,7 @@ export interface IndexPatternPersistedState {
|
|||
layers: Record<string, Omit<IndexPatternLayer, 'indexPatternId'>>;
|
||||
}
|
||||
|
||||
export type PersistedIndexPatternLayer = Omit<IndexPatternLayer, 'indexPatternId'>;
|
||||
export interface IndexPatternPrivateState {
|
||||
currentIndexPatternId: string;
|
||||
layers: Record<string, IndexPatternLayer>;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
import { SuggestionRequest, VisualizationSuggestion, TableSuggestion } from '../types';
|
||||
import { State } from './types';
|
||||
import { MetricState } from './types';
|
||||
import { LensIconChartMetric } from '../assets/chart_metric';
|
||||
|
||||
/**
|
||||
|
@ -17,7 +17,7 @@ export function getSuggestions({
|
|||
table,
|
||||
state,
|
||||
keptLayerIds,
|
||||
}: SuggestionRequest<State>): Array<VisualizationSuggestion<State>> {
|
||||
}: SuggestionRequest<MetricState>): Array<VisualizationSuggestion<MetricState>> {
|
||||
// We only render metric charts for single-row queries. We require a single, numeric column.
|
||||
if (
|
||||
table.isMultiRow ||
|
||||
|
@ -37,7 +37,7 @@ export function getSuggestions({
|
|||
return [getSuggestion(table)];
|
||||
}
|
||||
|
||||
function getSuggestion(table: TableSuggestion): VisualizationSuggestion<State> {
|
||||
function getSuggestion(table: TableSuggestion): VisualizationSuggestion<MetricState> {
|
||||
const col = table.columns[0];
|
||||
const title = table.label || col.operation.label;
|
||||
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export interface State {
|
||||
export interface MetricState {
|
||||
layerId: string;
|
||||
accessor?: string;
|
||||
}
|
||||
|
||||
export interface MetricConfig extends State {
|
||||
export interface MetricConfig extends MetricState {
|
||||
title: string;
|
||||
description: string;
|
||||
metricTitle: string;
|
||||
|
|
|
@ -5,14 +5,14 @@
|
|||
*/
|
||||
|
||||
import { metricVisualization } from './visualization';
|
||||
import { State } from './types';
|
||||
import { MetricState } from './types';
|
||||
import { createMockDatasource, createMockFramePublicAPI } from '../editor_frame_service/mocks';
|
||||
import { generateId } from '../id_generator';
|
||||
import { DatasourcePublicAPI, FramePublicAPI } from '../types';
|
||||
|
||||
jest.mock('../id_generator');
|
||||
|
||||
function exampleState(): State {
|
||||
function exampleState(): MetricState {
|
||||
return {
|
||||
accessor: 'a',
|
||||
layerId: 'l1',
|
||||
|
|
|
@ -9,10 +9,10 @@ import { Ast } from '@kbn/interpreter/target/common';
|
|||
import { getSuggestions } from './metric_suggestions';
|
||||
import { LensIconChartMetric } from '../assets/chart_metric';
|
||||
import { Visualization, OperationMetadata, DatasourcePublicAPI } from '../types';
|
||||
import { State } from './types';
|
||||
import { MetricState } from './types';
|
||||
|
||||
const toExpression = (
|
||||
state: State,
|
||||
state: MetricState,
|
||||
datasourceLayers: Record<string, DatasourcePublicAPI>,
|
||||
attributes?: { mode?: 'reduced' | 'full'; title?: string; description?: string }
|
||||
): Ast | null => {
|
||||
|
@ -41,7 +41,7 @@ const toExpression = (
|
|||
};
|
||||
};
|
||||
|
||||
export const metricVisualization: Visualization<State> = {
|
||||
export const metricVisualization: Visualization<MetricState> = {
|
||||
id: 'lnsMetric',
|
||||
|
||||
visualizationTypes: [
|
||||
|
|
|
@ -17,12 +17,15 @@ import {
|
|||
} from '@elastic/eui';
|
||||
import { Position } from '@elastic/charts';
|
||||
import { DEFAULT_PERCENT_DECIMALS } from './constants';
|
||||
import { PieVisualizationState, SharedLayerState } from './types';
|
||||
import { PieVisualizationState, SharedPieLayerState } from './types';
|
||||
import { VisualizationDimensionEditorProps, VisualizationToolbarProps } from '../types';
|
||||
import { ToolbarPopover, LegendSettingsPopover } from '../shared_components';
|
||||
import { PalettePicker } from '../shared_components';
|
||||
|
||||
const numberOptions: Array<{ value: SharedLayerState['numberDisplay']; inputDisplay: string }> = [
|
||||
const numberOptions: Array<{
|
||||
value: SharedPieLayerState['numberDisplay'];
|
||||
inputDisplay: string;
|
||||
}> = [
|
||||
{
|
||||
value: 'hidden',
|
||||
inputDisplay: i18n.translate('xpack.lens.pieChart.hiddenNumbersLabel', {
|
||||
|
@ -44,7 +47,7 @@ const numberOptions: Array<{ value: SharedLayerState['numberDisplay']; inputDisp
|
|||
];
|
||||
|
||||
const categoryOptions: Array<{
|
||||
value: SharedLayerState['categoryDisplay'];
|
||||
value: SharedPieLayerState['categoryDisplay'];
|
||||
inputDisplay: string;
|
||||
}> = [
|
||||
{
|
||||
|
@ -68,7 +71,7 @@ const categoryOptions: Array<{
|
|||
];
|
||||
|
||||
const categoryOptionsTreemap: Array<{
|
||||
value: SharedLayerState['categoryDisplay'];
|
||||
value: SharedPieLayerState['categoryDisplay'];
|
||||
inputDisplay: string;
|
||||
}> = [
|
||||
{
|
||||
|
@ -86,7 +89,7 @@ const categoryOptionsTreemap: Array<{
|
|||
];
|
||||
|
||||
const legendOptions: Array<{
|
||||
value: SharedLayerState['legendDisplay'];
|
||||
value: SharedPieLayerState['legendDisplay'];
|
||||
label: string;
|
||||
id: string;
|
||||
}> = [
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
import { PaletteOutput } from 'src/plugins/charts/public';
|
||||
import { LensMultiTable } from '../types';
|
||||
|
||||
export interface SharedLayerState {
|
||||
export interface SharedPieLayerState {
|
||||
groups: string[];
|
||||
metric?: string;
|
||||
numberDisplay: 'hidden' | 'percent' | 'value';
|
||||
|
@ -18,17 +18,17 @@ export interface SharedLayerState {
|
|||
percentDecimals?: number;
|
||||
}
|
||||
|
||||
export type LayerState = SharedLayerState & {
|
||||
export type PieLayerState = SharedPieLayerState & {
|
||||
layerId: string;
|
||||
};
|
||||
|
||||
export interface PieVisualizationState {
|
||||
shape: 'donut' | 'pie' | 'treemap';
|
||||
layers: LayerState[];
|
||||
layers: PieLayerState[];
|
||||
palette?: PaletteOutput;
|
||||
}
|
||||
|
||||
export type PieExpressionArgs = SharedLayerState & {
|
||||
export type PieExpressionArgs = SharedPieLayerState & {
|
||||
title?: string;
|
||||
description?: string;
|
||||
shape: 'pie' | 'donut' | 'treemap';
|
||||
|
|
|
@ -11,12 +11,12 @@ import { I18nProvider } from '@kbn/i18n/react';
|
|||
import { PaletteRegistry } from 'src/plugins/charts/public';
|
||||
import { Visualization, OperationMetadata, AccessorConfig } from '../types';
|
||||
import { toExpression, toPreviewExpression } from './to_expression';
|
||||
import { LayerState, PieVisualizationState } from './types';
|
||||
import { PieLayerState, PieVisualizationState } from './types';
|
||||
import { suggestions } from './suggestions';
|
||||
import { CHART_NAMES, MAX_PIE_BUCKETS, MAX_TREEMAP_BUCKETS } from './constants';
|
||||
import { DimensionEditor, PieToolbar } from './toolbar';
|
||||
|
||||
function newLayerState(layerId: string): LayerState {
|
||||
function newLayerState(layerId: string): PieLayerState {
|
||||
return {
|
||||
layerId,
|
||||
groups: [],
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { LayerConfig } from './types';
|
||||
import { XYLayerConfig } from './types';
|
||||
import { Datatable, SerializedFieldFormat } from '../../../../../src/plugins/expressions/public';
|
||||
import { IFieldFormat } from '../../../../../src/plugins/data/public';
|
||||
|
||||
|
@ -29,7 +29,7 @@ export function isFormatterCompatible(
|
|||
}
|
||||
|
||||
export function getAxesConfiguration(
|
||||
layers: LayerConfig[],
|
||||
layers: XYLayerConfig[],
|
||||
shouldRotate: boolean,
|
||||
tables?: Record<string, Datatable>,
|
||||
formatFactory?: (mapping: SerializedFieldFormat) => IFieldFormat
|
||||
|
|
|
@ -15,7 +15,7 @@ import {
|
|||
IconType,
|
||||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { LayerConfig, AxesSettingsConfig } from './types';
|
||||
import { XYLayerConfig, AxesSettingsConfig } from './types';
|
||||
import { ToolbarPopover } from '../shared_components';
|
||||
import { isHorizontalChart } from './state_helpers';
|
||||
import { EuiIconAxisBottom } from '../assets/axis_bottom';
|
||||
|
@ -33,7 +33,7 @@ export interface AxisSettingsPopoverProps {
|
|||
/**
|
||||
* Contains the chart layers
|
||||
*/
|
||||
layers?: LayerConfig[];
|
||||
layers?: XYLayerConfig[];
|
||||
/**
|
||||
* Determines the axis title
|
||||
*/
|
||||
|
|
|
@ -9,7 +9,7 @@ import { PaletteOutput, PaletteRegistry } from 'src/plugins/charts/public';
|
|||
import { Datatable } from 'src/plugins/expressions';
|
||||
import { AccessorConfig, FormatFactory, FramePublicAPI } from '../types';
|
||||
import { getColumnToLabelMap } from './state_helpers';
|
||||
import { LayerConfig } from './types';
|
||||
import { XYLayerConfig } from './types';
|
||||
|
||||
const isPrimitive = (value: unknown): boolean => value != null && typeof value !== 'object';
|
||||
|
||||
|
@ -95,7 +95,7 @@ export function getColorAssignments(
|
|||
export function getAccessorColorConfig(
|
||||
colorAssignments: ColorAssignments,
|
||||
frame: FramePublicAPI,
|
||||
layer: LayerConfig,
|
||||
layer: XYLayerConfig,
|
||||
paletteService: PaletteRegistry
|
||||
): AccessorConfig[] {
|
||||
const layerContainsSplits = Boolean(layer.splitAccessor);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { EuiIconType } from '@elastic/eui/src/components/icon/icon';
|
||||
import { FramePublicAPI, DatasourcePublicAPI } from '../types';
|
||||
import { SeriesType, visualizationTypes, LayerConfig, YConfig, ValidLayer } from './types';
|
||||
import { SeriesType, visualizationTypes, XYLayerConfig, YConfig, ValidLayer } from './types';
|
||||
|
||||
export function isHorizontalSeries(seriesType: SeriesType) {
|
||||
return (
|
||||
|
@ -30,7 +30,7 @@ export function getIconForSeries(type: SeriesType): EuiIconType {
|
|||
return (definition.icon as EuiIconType) || 'empty';
|
||||
}
|
||||
|
||||
export const getSeriesColor = (layer: LayerConfig, accessor: string) => {
|
||||
export const getSeriesColor = (layer: XYLayerConfig, accessor: string) => {
|
||||
if (layer.splitAccessor) {
|
||||
return null;
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ export const getSeriesColor = (layer: LayerConfig, accessor: string) => {
|
|||
);
|
||||
};
|
||||
|
||||
export const getColumnToLabelMap = (layer: LayerConfig, datasource: DatasourcePublicAPI) => {
|
||||
export const getColumnToLabelMap = (layer: XYLayerConfig, datasource: DatasourcePublicAPI) => {
|
||||
const columnToLabel: Record<string, string> = {};
|
||||
|
||||
layer.accessors.concat(layer.splitAccessor ? [layer.splitAccessor] : []).forEach((accessor) => {
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
import { Ast } from '@kbn/interpreter/common';
|
||||
import { ScaleType } from '@elastic/charts';
|
||||
import { PaletteRegistry } from 'src/plugins/charts/public';
|
||||
import { State, ValidLayer, LayerConfig } from './types';
|
||||
import { State, ValidLayer, XYLayerConfig } from './types';
|
||||
import { OperationMetadata, DatasourcePublicAPI } from '../types';
|
||||
import { getColumnToLabelMap } from './state_helpers';
|
||||
|
||||
export const getSortedAccessors = (datasource: DatasourcePublicAPI, layer: LayerConfig) => {
|
||||
export const getSortedAccessors = (datasource: DatasourcePublicAPI, layer: XYLayerConfig) => {
|
||||
const originalOrder = datasource
|
||||
.getTableSpec()
|
||||
.map(({ columnId }: { columnId: string }) => columnId)
|
||||
|
|
|
@ -372,7 +372,7 @@ export interface YConfig {
|
|||
color?: string;
|
||||
}
|
||||
|
||||
export interface LayerConfig {
|
||||
export interface XYLayerConfig {
|
||||
hide?: boolean;
|
||||
layerId: string;
|
||||
xAccessor?: string;
|
||||
|
@ -383,11 +383,11 @@ export interface LayerConfig {
|
|||
palette?: PaletteOutput;
|
||||
}
|
||||
|
||||
export interface ValidLayer extends LayerConfig {
|
||||
xAccessor: NonNullable<LayerConfig['xAccessor']>;
|
||||
export interface ValidLayer extends XYLayerConfig {
|
||||
xAccessor: NonNullable<XYLayerConfig['xAccessor']>;
|
||||
}
|
||||
|
||||
export type LayerArgs = LayerConfig & {
|
||||
export type LayerArgs = XYLayerConfig & {
|
||||
columnToLabel?: string; // Actually a JSON key-value pair
|
||||
yScaleType: 'time' | 'linear' | 'log' | 'sqrt';
|
||||
xScaleType: 'time' | 'linear' | 'ordinal';
|
||||
|
@ -420,7 +420,7 @@ export interface XYState {
|
|||
legend: LegendConfig;
|
||||
valueLabels?: ValueLabelConfig;
|
||||
fittingFunction?: FittingFunction;
|
||||
layers: LayerConfig[];
|
||||
layers: XYLayerConfig[];
|
||||
xTitle?: string;
|
||||
yTitle?: string;
|
||||
yRightTitle?: string;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
import { getXyVisualization } from './visualization';
|
||||
import { Position } from '@elastic/charts';
|
||||
import { Operation } from '../types';
|
||||
import { State, SeriesType, LayerConfig } from './types';
|
||||
import { State, SeriesType, XYLayerConfig } from './types';
|
||||
import { createMockDatasource, createMockFramePublicAPI } from '../editor_frame_service/mocks';
|
||||
import { LensIconChartBar } from '../assets/chart_bar';
|
||||
import { chartPluginMock } from '../../../../../src/plugins/charts/public/mocks';
|
||||
|
@ -422,7 +422,7 @@ describe('xy_visualization', () => {
|
|||
});
|
||||
|
||||
describe('color assignment', () => {
|
||||
function callConfig(layerConfigOverride: Partial<LayerConfig>) {
|
||||
function callConfig(layerConfigOverride: Partial<XYLayerConfig>) {
|
||||
const baseState = exampleState();
|
||||
const options = xyVisualization.getConfiguration({
|
||||
state: {
|
||||
|
@ -441,16 +441,16 @@ describe('xy_visualization', () => {
|
|||
return options;
|
||||
}
|
||||
|
||||
function callConfigForYConfigs(layerConfigOverride: Partial<LayerConfig>) {
|
||||
function callConfigForYConfigs(layerConfigOverride: Partial<XYLayerConfig>) {
|
||||
return callConfig(layerConfigOverride).find(({ groupId }) => groupId === 'y');
|
||||
}
|
||||
|
||||
function callConfigForBreakdownConfigs(layerConfigOverride: Partial<LayerConfig>) {
|
||||
function callConfigForBreakdownConfigs(layerConfigOverride: Partial<XYLayerConfig>) {
|
||||
return callConfig(layerConfigOverride).find(({ groupId }) => groupId === 'breakdown');
|
||||
}
|
||||
|
||||
function callConfigAndFindYConfig(
|
||||
layerConfigOverride: Partial<LayerConfig>,
|
||||
layerConfigOverride: Partial<XYLayerConfig>,
|
||||
assertionAccessor: string
|
||||
) {
|
||||
const accessorConfig = callConfigForYConfigs(layerConfigOverride)?.accessors.find(
|
||||
|
|
|
@ -15,7 +15,7 @@ import { DataPublicPluginStart } from 'src/plugins/data/public';
|
|||
import { getSuggestions } from './xy_suggestions';
|
||||
import { LayerContextMenu, XyToolbar, DimensionEditor } from './xy_config_panel';
|
||||
import { Visualization, OperationMetadata, VisualizationType, AccessorConfig } from '../types';
|
||||
import { State, SeriesType, visualizationTypes, LayerConfig } from './types';
|
||||
import { State, SeriesType, visualizationTypes, XYLayerConfig } from './types';
|
||||
import { isHorizontalChart } from './state_helpers';
|
||||
import { toExpression, toPreviewExpression, getSortedAccessors } from './to_expression';
|
||||
import { LensIconChartBarStacked } from '../assets/chart_bar_stacked';
|
||||
|
@ -341,9 +341,9 @@ export const getXyVisualization = ({
|
|||
|
||||
getErrorMessages(state, frame) {
|
||||
// Data error handling below here
|
||||
const hasNoAccessors = ({ accessors }: LayerConfig) =>
|
||||
const hasNoAccessors = ({ accessors }: XYLayerConfig) =>
|
||||
accessors == null || accessors.length === 0;
|
||||
const hasNoSplitAccessor = ({ splitAccessor, seriesType }: LayerConfig) =>
|
||||
const hasNoSplitAccessor = ({ splitAccessor, seriesType }: XYLayerConfig) =>
|
||||
seriesType.includes('percentage') && splitAccessor == null;
|
||||
|
||||
const errors: Array<{
|
||||
|
@ -354,14 +354,14 @@ export const getXyVisualization = ({
|
|||
// check if the layers in the state are compatible with this type of chart
|
||||
if (state && state.layers.length > 1) {
|
||||
// Order is important here: Y Axis is fundamental to exist to make it valid
|
||||
const checks: Array<[string, (layer: LayerConfig) => boolean]> = [
|
||||
const checks: Array<[string, (layer: XYLayerConfig) => boolean]> = [
|
||||
['Y', hasNoAccessors],
|
||||
['Break down', hasNoSplitAccessor],
|
||||
];
|
||||
|
||||
// filter out those layers with no accessors at all
|
||||
const filteredLayers = state.layers.filter(
|
||||
({ accessors, xAccessor, splitAccessor }: LayerConfig) =>
|
||||
({ accessors, xAccessor, splitAccessor }: XYLayerConfig) =>
|
||||
accessors.length > 0 || xAccessor != null || splitAccessor != null
|
||||
);
|
||||
for (const [dimension, criteria] of checks) {
|
||||
|
@ -382,7 +382,7 @@ export const getXyVisualization = ({
|
|||
|
||||
const layers = state.layers;
|
||||
|
||||
const filteredLayers = layers.filter(({ accessors }: LayerConfig) => accessors.length > 0);
|
||||
const filteredLayers = layers.filter(({ accessors }: XYLayerConfig) => accessors.length > 0);
|
||||
const accessorsWithArrayValues = [];
|
||||
for (const layer of filteredLayers) {
|
||||
const { layerId, accessors } = layer;
|
||||
|
@ -409,8 +409,8 @@ export const getXyVisualization = ({
|
|||
|
||||
function validateLayersForDimension(
|
||||
dimension: string,
|
||||
layers: LayerConfig[],
|
||||
missingCriteria: (layer: LayerConfig) => boolean
|
||||
layers: XYLayerConfig[],
|
||||
missingCriteria: (layer: XYLayerConfig) => boolean
|
||||
):
|
||||
| { valid: true }
|
||||
| {
|
||||
|
@ -480,7 +480,7 @@ function getMessageIdsForDimension(dimension: string, layers: number[], isHorizo
|
|||
return { shortMessage: '', longMessage: '' };
|
||||
}
|
||||
|
||||
function newLayerState(seriesType: SeriesType, layerId: string): LayerConfig {
|
||||
function newLayerState(seriesType: SeriesType, layerId: string): XYLayerConfig {
|
||||
return {
|
||||
layerId,
|
||||
seriesType,
|
||||
|
|
|
@ -15,7 +15,7 @@ import {
|
|||
TableSuggestion,
|
||||
TableChangeType,
|
||||
} from '../types';
|
||||
import { State, SeriesType, XYState, visualizationTypes, LayerConfig } from './types';
|
||||
import { State, SeriesType, XYState, visualizationTypes, XYLayerConfig } from './types';
|
||||
import { getIconForSeries } from './state_helpers';
|
||||
|
||||
const columnSortOrder = {
|
||||
|
@ -485,7 +485,7 @@ function buildSuggestion({
|
|||
splitBy = xValue;
|
||||
xValue = undefined;
|
||||
}
|
||||
const existingLayer: LayerConfig | {} = getExistingLayer(currentState, layerId) || {};
|
||||
const existingLayer: XYLayerConfig | {} = getExistingLayer(currentState, layerId) || {};
|
||||
const accessors = yValues.map((col) => col.columnId);
|
||||
const newLayer = {
|
||||
...existingLayer,
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
# Lens
|
||||
|
||||
Visualization editor allowing to quickly and easily configure compelling visualizations to use on dashboards and canvas workpads.
|
||||
|
||||
## Embedding
|
||||
|
||||
It's possible to embed Lens visualizations in other apps using `EmbeddableComponent` and `navigateToPrefilledEditor`
|
||||
exposed via contract. For more information check out the example in `x-pack/examples/embedded_lens_example`.
|
||||
|
||||
## Testing
|
||||
|
||||
Run all tests from the `x-pack` root directory
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue