mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[Lens] Fixes the types of the DatasourceLayers (#138371)
* [Lens] Fixes the types of the DatasourceLayers * Remove unecessary if
This commit is contained in:
parent
b40663299a
commit
9e690e6669
24 changed files with 142 additions and 107 deletions
|
@ -47,7 +47,7 @@ export function DraggableDimensionButton({
|
|||
group: VisualizationDimensionGroupConfig;
|
||||
label: string;
|
||||
children: ReactElement;
|
||||
layerDatasource: Datasource<unknown, unknown>;
|
||||
layerDatasource?: Datasource<unknown, unknown>;
|
||||
datasourceLayers: DatasourceLayers;
|
||||
state: unknown;
|
||||
accessorIndex: number;
|
||||
|
|
|
@ -118,7 +118,7 @@ export function EmptyDimensionButton({
|
|||
onDrop: (source: DragDropIdentifier, dropTarget: DragDropIdentifier, dropType?: DropType) => void;
|
||||
onClick: (id: string) => void;
|
||||
group: VisualizationDimensionGroupConfig;
|
||||
layerDatasource: Datasource<unknown, unknown>;
|
||||
layerDatasource?: Datasource<unknown, unknown>;
|
||||
datasourceLayers: DatasourceLayers;
|
||||
state: unknown;
|
||||
}) {
|
||||
|
|
|
@ -75,20 +75,22 @@ export function LayerPanels(
|
|||
[activeVisualization, dispatchLens]
|
||||
);
|
||||
const updateDatasource = useMemo(
|
||||
() => (datasourceId: string, newState: unknown) => {
|
||||
dispatchLens(
|
||||
updateDatasourceState({
|
||||
updater: (prevState: unknown) =>
|
||||
typeof newState === 'function' ? newState(prevState) : newState,
|
||||
datasourceId,
|
||||
clearStagedPreview: false,
|
||||
})
|
||||
);
|
||||
() => (datasourceId: string | undefined, newState: unknown) => {
|
||||
if (datasourceId) {
|
||||
dispatchLens(
|
||||
updateDatasourceState({
|
||||
updater: (prevState: unknown) =>
|
||||
typeof newState === 'function' ? newState(prevState) : newState,
|
||||
datasourceId,
|
||||
clearStagedPreview: false,
|
||||
})
|
||||
);
|
||||
}
|
||||
},
|
||||
[dispatchLens]
|
||||
);
|
||||
const updateDatasourceAsync = useMemo(
|
||||
() => (datasourceId: string, newState: unknown) => {
|
||||
() => (datasourceId: string | undefined, newState: unknown) => {
|
||||
// React will synchronously update if this is triggered from a third party component,
|
||||
// which we don't want. The timeout lets user interaction have priority, then React updates.
|
||||
setTimeout(() => {
|
||||
|
@ -99,43 +101,49 @@ export function LayerPanels(
|
|||
);
|
||||
|
||||
const updateAll = useMemo(
|
||||
() => (datasourceId: string, newDatasourceState: unknown, newVisualizationState: unknown) => {
|
||||
// React will synchronously update if this is triggered from a third party component,
|
||||
// which we don't want. The timeout lets user interaction have priority, then React updates.
|
||||
() =>
|
||||
(
|
||||
datasourceId: string | undefined,
|
||||
newDatasourceState: unknown,
|
||||
newVisualizationState: unknown
|
||||
) => {
|
||||
if (!datasourceId) return;
|
||||
// React will synchronously update if this is triggered from a third party component,
|
||||
// which we don't want. The timeout lets user interaction have priority, then React updates.
|
||||
|
||||
setTimeout(() => {
|
||||
dispatchLens(
|
||||
updateState({
|
||||
updater: (prevState) => {
|
||||
const updatedDatasourceState =
|
||||
typeof newDatasourceState === 'function'
|
||||
? newDatasourceState(prevState.datasourceStates[datasourceId].state)
|
||||
: newDatasourceState;
|
||||
setTimeout(() => {
|
||||
dispatchLens(
|
||||
updateState({
|
||||
updater: (prevState) => {
|
||||
const updatedDatasourceState =
|
||||
typeof newDatasourceState === 'function'
|
||||
? newDatasourceState(prevState.datasourceStates[datasourceId].state)
|
||||
: newDatasourceState;
|
||||
|
||||
const updatedVisualizationState =
|
||||
typeof newVisualizationState === 'function'
|
||||
? newVisualizationState(prevState.visualization.state)
|
||||
: newVisualizationState;
|
||||
const updatedVisualizationState =
|
||||
typeof newVisualizationState === 'function'
|
||||
? newVisualizationState(prevState.visualization.state)
|
||||
: newVisualizationState;
|
||||
|
||||
return {
|
||||
...prevState,
|
||||
datasourceStates: {
|
||||
...prevState.datasourceStates,
|
||||
[datasourceId]: {
|
||||
state: updatedDatasourceState,
|
||||
isLoading: false,
|
||||
return {
|
||||
...prevState,
|
||||
datasourceStates: {
|
||||
...prevState.datasourceStates,
|
||||
[datasourceId]: {
|
||||
state: updatedDatasourceState,
|
||||
isLoading: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
visualization: {
|
||||
...prevState.visualization,
|
||||
state: updatedVisualizationState,
|
||||
},
|
||||
};
|
||||
},
|
||||
})
|
||||
);
|
||||
}, 0);
|
||||
},
|
||||
visualization: {
|
||||
...prevState.visualization,
|
||||
state: updatedVisualizationState,
|
||||
},
|
||||
};
|
||||
},
|
||||
})
|
||||
);
|
||||
}, 0);
|
||||
},
|
||||
[dispatchLens]
|
||||
);
|
||||
|
||||
|
@ -187,10 +195,10 @@ export function LayerPanels(
|
|||
onRemoveLayer={() => {
|
||||
const datasourcePublicAPI = props.framePublicAPI.datasourceLayers?.[layerId];
|
||||
const datasourceId = datasourcePublicAPI?.datasourceId;
|
||||
const layerDatasource = datasourceMap[datasourceId];
|
||||
const layerDatasourceState = datasourceStates?.[datasourceId]?.state;
|
||||
|
||||
if (datasourceId) {
|
||||
const layerDatasource = datasourceMap[datasourceId];
|
||||
const layerDatasourceState = datasourceStates?.[datasourceId]?.state;
|
||||
const trigger = props.uiActions.getTrigger(UPDATE_FILTER_REFERENCES_TRIGGER);
|
||||
const action = props.uiActions.getAction(UPDATE_FILTER_REFERENCES_ACTION);
|
||||
|
||||
|
|
|
@ -54,10 +54,10 @@ export function LayerPanel(
|
|||
layerIndex: number;
|
||||
isOnlyLayer: boolean;
|
||||
updateVisualization: StateSetter<unknown>;
|
||||
updateDatasource: (datasourceId: string, newState: unknown) => void;
|
||||
updateDatasourceAsync: (datasourceId: string, newState: unknown) => void;
|
||||
updateDatasource: (datasourceId: string | undefined, newState: unknown) => void;
|
||||
updateDatasourceAsync: (datasourceId: string | undefined, newState: unknown) => void;
|
||||
updateAll: (
|
||||
datasourceId: string,
|
||||
datasourceId: string | undefined,
|
||||
newDatasourcestate: unknown,
|
||||
newVisualizationState: unknown
|
||||
) => void;
|
||||
|
@ -112,8 +112,8 @@ export function LayerPanel(
|
|||
|
||||
const datasourcePublicAPI = framePublicAPI.datasourceLayers?.[layerId];
|
||||
const datasourceId = datasourcePublicAPI?.datasourceId;
|
||||
const layerDatasourceState = datasourceStates?.[datasourceId]?.state;
|
||||
const layerDatasource = props.datasourceMap[datasourceId];
|
||||
const layerDatasourceState = datasourceId ? datasourceStates?.[datasourceId]?.state : undefined;
|
||||
const layerDatasource = datasourceId ? props.datasourceMap[datasourceId] : undefined;
|
||||
|
||||
const layerDatasourceConfigProps = {
|
||||
state: layerDatasourceState,
|
||||
|
@ -339,11 +339,11 @@ export function LayerPanel(
|
|||
nextPublicAPI.getTableSpec().map(({ columnId }) => columnId)
|
||||
);
|
||||
const removed = datasourcePublicAPI
|
||||
.getTableSpec()
|
||||
?.getTableSpec()
|
||||
.map(({ columnId }) => columnId)
|
||||
.filter((columnId) => !nextTable.has(columnId));
|
||||
let nextVisState = props.visualizationState;
|
||||
removed.forEach((columnId) => {
|
||||
removed?.forEach((columnId) => {
|
||||
nextVisState = activeVisualization.removeDimension({
|
||||
layerId,
|
||||
columnId,
|
||||
|
@ -433,7 +433,7 @@ export function LayerPanel(
|
|||
groupIndex={groupIndex}
|
||||
key={columnId}
|
||||
state={layerDatasourceState}
|
||||
label={columnLabelMap?.[columnId]}
|
||||
label={columnLabelMap?.[columnId] ?? ''}
|
||||
layerDatasource={layerDatasource}
|
||||
datasourceLayers={framePublicAPI.datasourceLayers}
|
||||
layerIndex={layerIndex}
|
||||
|
@ -445,7 +445,7 @@ export function LayerPanel(
|
|||
<div className="lnsLayerPanel__dimension">
|
||||
<DimensionButton
|
||||
accessorConfig={accessorConfig}
|
||||
label={columnLabelMap?.[accessorConfig.columnId]}
|
||||
label={columnLabelMap?.[accessorConfig.columnId] ?? ''}
|
||||
group={group}
|
||||
onClick={(id: string) => {
|
||||
setActiveDimension({
|
||||
|
@ -508,7 +508,7 @@ export function LayerPanel(
|
|||
<>
|
||||
{activeVisualization?.renderDimensionTrigger?.({
|
||||
columnId,
|
||||
label: columnLabelMap[columnId],
|
||||
label: columnLabelMap?.[columnId] ?? '',
|
||||
hideTooltip,
|
||||
invalid: group.invalid,
|
||||
invalidMessage: group.invalidMessage,
|
||||
|
|
|
@ -269,7 +269,7 @@ export function getTopSuggestionForField(
|
|||
field: DragDropIdentifier
|
||||
) {
|
||||
const hasData = Object.values(datasourceLayers).some(
|
||||
(datasourceLayer) => datasourceLayer.getTableSpec().length > 0
|
||||
(datasourceLayer) => datasourceLayer && datasourceLayer.getTableSpec().length > 0
|
||||
);
|
||||
|
||||
const activeVisualization = visualization.activeId
|
||||
|
|
|
@ -197,7 +197,7 @@ describe('chart_switch', () => {
|
|||
const visualizationMap = mockVisualizationMap();
|
||||
visualizationMap.visB.getSuggestions.mockReturnValueOnce([]);
|
||||
const frame = mockFrame(['a']);
|
||||
(frame.datasourceLayers.a.getTableSpec as jest.Mock).mockReturnValue([]);
|
||||
(frame.datasourceLayers.a?.getTableSpec as jest.Mock).mockReturnValue([]);
|
||||
const datasourceMap = mockDatasourceMap();
|
||||
const datasourceStates = mockDatasourceStates();
|
||||
const { instance, lensStore } = await mountWithProvider(
|
||||
|
@ -407,7 +407,7 @@ describe('chart_switch', () => {
|
|||
const visualizationMap = mockVisualizationMap();
|
||||
visualizationMap.visB.getSuggestions.mockReturnValueOnce([]);
|
||||
const frame = mockFrame(['a']);
|
||||
(frame.datasourceLayers.a.getTableSpec as jest.Mock).mockReturnValue([]);
|
||||
(frame.datasourceLayers.a?.getTableSpec as jest.Mock).mockReturnValue([]);
|
||||
|
||||
const { instance } = await mountWithProvider(
|
||||
<ChartSwitch
|
||||
|
@ -599,7 +599,8 @@ describe('chart_switch', () => {
|
|||
|
||||
it('should not remove layers and initialize with existing state when switching between subtypes without data', async () => {
|
||||
const frame = mockFrame(['a']);
|
||||
frame.datasourceLayers.a.getTableSpec = jest.fn().mockReturnValue([]);
|
||||
const datasourceLayers = frame.datasourceLayers as Record<string, DatasourcePublicAPI>;
|
||||
datasourceLayers.a.getTableSpec = jest.fn().mockReturnValue([]);
|
||||
const visualizationMap = mockVisualizationMap();
|
||||
visualizationMap.visC.getSuggestions = jest.fn().mockReturnValue([]);
|
||||
visualizationMap.visC.switchVisualizationType = jest.fn(() => 'switched');
|
||||
|
|
|
@ -155,7 +155,7 @@ export const ChartSwitch = memo(function ChartSwitch(props: Props) {
|
|||
((_type: string, initialState: unknown) => initialState);
|
||||
const layers = Object.entries(props.framePublicAPI.datasourceLayers);
|
||||
const containsData = layers.some(
|
||||
([_layerId, datasource]) => datasource.getTableSpec().length > 0
|
||||
([_layerId, datasource]) => datasource && datasource.getTableSpec().length > 0
|
||||
);
|
||||
// Always show the active visualization as a valid selection
|
||||
if (
|
||||
|
@ -190,7 +190,7 @@ export const ChartSwitch = memo(function ChartSwitch(props: Props) {
|
|||
dataLoss = 'everything';
|
||||
} else if (layers.length > 1 && layers.length !== topSuggestion.keptLayerIds.length) {
|
||||
dataLoss = 'layers';
|
||||
} else if (topSuggestion.columns !== layers[0][1].getTableSpec().length) {
|
||||
} else if (topSuggestion.columns !== layers[0][1]?.getTableSpec().length) {
|
||||
dataLoss = 'columns';
|
||||
} else {
|
||||
dataLoss = 'nothing';
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import { Datatable } from '@kbn/expressions-plugin/common';
|
||||
import { createMockDatasource } from '../../mocks';
|
||||
import { FramePublicAPI, OperationDescriptor } from '../../types';
|
||||
import { OperationDescriptor, DatasourcePublicAPI } from '../../types';
|
||||
import {
|
||||
hasNumericHistogramDimension,
|
||||
validateAxisDomain,
|
||||
|
@ -58,7 +58,7 @@ describe('validateZeroInclusivityExtent', () => {
|
|||
});
|
||||
|
||||
describe('hasNumericHistogramDimension', () => {
|
||||
const datasourceLayers: FramePublicAPI['datasourceLayers'] = {
|
||||
const datasourceLayers: Record<string, DatasourcePublicAPI> = {
|
||||
first: createMockDatasource('test').publicAPIMock,
|
||||
};
|
||||
it('should return true if a numeric histogram is present', () => {
|
||||
|
|
|
@ -45,7 +45,7 @@ export function validateAxisDomain(extents?: { lowerBound?: number; upperBound?:
|
|||
* @returns boolean
|
||||
*/
|
||||
export function hasNumericHistogramDimension(
|
||||
datasourceLayer: DatasourcePublicAPI,
|
||||
datasourceLayer: DatasourcePublicAPI | undefined,
|
||||
columnId?: string
|
||||
) {
|
||||
if (!columnId) {
|
||||
|
|
|
@ -718,7 +718,7 @@ export interface VisualizationSuggestion<T = unknown> {
|
|||
previewIcon: IconType;
|
||||
}
|
||||
|
||||
export type DatasourceLayers = Record<string, DatasourcePublicAPI>;
|
||||
export type DatasourceLayers = Partial<Record<string, DatasourcePublicAPI>>;
|
||||
|
||||
export interface FramePublicAPI {
|
||||
datasourceLayers: DatasourceLayers;
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
FramePublicAPI,
|
||||
OperationDescriptor,
|
||||
VisualizationDimensionEditorProps,
|
||||
DatasourcePublicAPI,
|
||||
} from '../../../types';
|
||||
import { DatatableVisualizationState } from '../visualization';
|
||||
import { createMockDatasource, createMockFramePublicAPI } from '../../../mocks';
|
||||
|
@ -221,7 +222,8 @@ describe('data table dimension editor', () => {
|
|||
|
||||
it('should not show the dynamic coloring option for a bucketed operation', () => {
|
||||
frame.activeData!.first.columns[0].meta.type = 'number';
|
||||
frame.datasourceLayers.first.getOperationForColumnId = jest.fn(
|
||||
const datasourceLayers = frame.datasourceLayers as Record<string, DatasourcePublicAPI>;
|
||||
datasourceLayers.first.getOperationForColumnId = jest.fn(
|
||||
() => ({ isBucketed: true } as OperationDescriptor)
|
||||
);
|
||||
state.columns[0].colorMode = 'cell';
|
||||
|
|
|
@ -587,10 +587,10 @@ function getDataSourceAndSortedColumns(
|
|||
layerId: string
|
||||
) {
|
||||
const datasource = datasourceLayers[state.layerId];
|
||||
const originalOrder = datasource.getTableSpec().map(({ columnId }) => columnId);
|
||||
const originalOrder = datasource?.getTableSpec().map(({ columnId }) => columnId);
|
||||
// When we add a column it could be empty, and therefore have no order
|
||||
const sortedColumns = Array.from(
|
||||
new Set(originalOrder.concat(state.columns.map(({ columnId }) => columnId)))
|
||||
new Set(originalOrder?.concat(state.columns.map(({ columnId }) => columnId)))
|
||||
);
|
||||
return { datasource, sortedColumns };
|
||||
}
|
||||
|
|
|
@ -122,7 +122,7 @@ const toExpression = (
|
|||
const datasource = datasourceLayers[state.layerId];
|
||||
const datasourceExpression = datasourceExpressionsByLayers[state.layerId];
|
||||
|
||||
const originalOrder = datasource.getTableSpec().map(({ columnId }) => columnId);
|
||||
const originalOrder = datasource?.getTableSpec().map(({ columnId }) => columnId);
|
||||
if (!originalOrder || !state.metricAccessor) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@ export const getHeatmapVisualization = ({
|
|||
getConfiguration({ state, frame, layerId }) {
|
||||
const datasourceLayer = frame.datasourceLayers[layerId];
|
||||
|
||||
const originalOrder = datasourceLayer.getTableSpec().map(({ columnId }) => columnId);
|
||||
const originalOrder = datasourceLayer?.getTableSpec().map(({ columnId }) => columnId);
|
||||
if (!originalOrder) {
|
||||
return { groups: [] };
|
||||
}
|
||||
|
@ -312,7 +312,7 @@ export const getHeatmapVisualization = ({
|
|||
const datasource = datasourceLayers[state.layerId];
|
||||
const datasourceExpression = datasourceExpressionsByLayers[state.layerId];
|
||||
|
||||
const originalOrder = datasource.getTableSpec().map(({ columnId }) => columnId);
|
||||
const originalOrder = datasource?.getTableSpec().map(({ columnId }) => columnId);
|
||||
// When we add a column it could be empty, and therefore have no order
|
||||
|
||||
if (!originalOrder || !state.valueAccessor) {
|
||||
|
@ -402,7 +402,7 @@ export const getHeatmapVisualization = ({
|
|||
const datasource = datasourceLayers[state.layerId];
|
||||
const datasourceExpression = datasourceExpressionsByLayers[state.layerId];
|
||||
|
||||
const originalOrder = datasource.getTableSpec().map(({ columnId }) => columnId);
|
||||
const originalOrder = datasource?.getTableSpec().map(({ columnId }) => columnId);
|
||||
// When we add a column it could be empty, and therefore have no order
|
||||
|
||||
if (!originalOrder) {
|
||||
|
@ -513,7 +513,7 @@ export const getHeatmapVisualization = ({
|
|||
const hasArrayValues = rows.some((row) => Array.isArray(row[state.valueAccessor!]));
|
||||
|
||||
const datasource = frame.datasourceLayers[state.layerId];
|
||||
const operation = datasource.getOperationForColumnId(state.valueAccessor);
|
||||
const operation = datasource?.getOperationForColumnId(state.valueAccessor);
|
||||
|
||||
return hasArrayValues
|
||||
? [
|
||||
|
|
|
@ -78,7 +78,7 @@ const toExpression = (
|
|||
const maxPossibleTiles =
|
||||
// if there's a collapse function, no need to calculate since we're dealing with a single tile
|
||||
state.breakdownByAccessor && !state.collapseFn
|
||||
? datasource.getMaxPossibleNumValues(state.breakdownByAccessor)
|
||||
? datasource?.getMaxPossibleNumValues(state.breakdownByAccessor)
|
||||
: null;
|
||||
|
||||
const getCollapseFnArguments = () => {
|
||||
|
@ -91,7 +91,7 @@ const toExpression = (
|
|||
return state.collapseFn;
|
||||
} else {
|
||||
const isMaxStatic = Boolean(
|
||||
datasource.getOperationForColumnId(state.maxAccessor!)?.isStaticValue
|
||||
datasource?.getOperationForColumnId(state.maxAccessor!)?.isStaticValue
|
||||
);
|
||||
// we do this because the user expects the static value they set to be the same
|
||||
// even if they define a collapse on the breakdown by
|
||||
|
|
|
@ -59,13 +59,16 @@ type GenerateLabelsAstArguments = (
|
|||
layer: PieLayerState
|
||||
) => [Ast];
|
||||
|
||||
export const getSortedGroups = (datasource: DatasourcePublicAPI, layer: PieLayerState) => {
|
||||
export const getSortedGroups = (
|
||||
datasource: DatasourcePublicAPI | undefined,
|
||||
layer: PieLayerState
|
||||
) => {
|
||||
const originalOrder = datasource
|
||||
.getTableSpec()
|
||||
?.getTableSpec()
|
||||
.map(({ columnId }: { columnId: string }) => columnId)
|
||||
.filter((columnId: string) => layer.groups.includes(columnId));
|
||||
// When we add a column it could be empty, and therefore have no order
|
||||
return Array.from(new Set(originalOrder.concat(layer.groups)));
|
||||
return Array.from(new Set(originalOrder?.concat(layer.groups)));
|
||||
};
|
||||
|
||||
const prepareDimension = (accessor: string) => {
|
||||
|
@ -264,7 +267,7 @@ function expressionHelper(
|
|||
const operations = groups
|
||||
.map((columnId) => ({
|
||||
columnId,
|
||||
operation: datasource.getOperationForColumnId(columnId) as Operation | null,
|
||||
operation: datasource?.getOperationForColumnId(columnId) as Operation | null,
|
||||
}))
|
||||
.filter((o): o is { columnId: string; operation: Operation } => !!o.operation);
|
||||
|
||||
|
|
|
@ -299,7 +299,7 @@ export const getPieVisualization = ({
|
|||
);
|
||||
}
|
||||
|
||||
const columnToLabel = frame.datasourceLayers[layerId].getOperationForColumnId(metric)?.label;
|
||||
const columnToLabel = frame.datasourceLayers[layerId]?.getOperationForColumnId(metric)?.label;
|
||||
const hasArrayValues = rows.some((row) => Array.isArray(row[metric]));
|
||||
if (hasArrayValues) {
|
||||
warningMessages.push(
|
||||
|
|
|
@ -65,13 +65,13 @@ export const getSeriesColor = (layer: XYLayerConfig, accessor: string) => {
|
|||
|
||||
export const getColumnToLabelMap = (
|
||||
layer: XYDataLayerConfig | XYReferenceLineLayerConfig,
|
||||
datasource: DatasourcePublicAPI
|
||||
datasource?: DatasourcePublicAPI
|
||||
) => {
|
||||
const columnToLabel: Record<string, string> = {};
|
||||
layer.accessors
|
||||
.concat(isDataLayer(layer) && layer.splitAccessor ? [layer.splitAccessor] : [])
|
||||
.forEach((accessor) => {
|
||||
const operation = datasource.getOperationForColumnId(accessor);
|
||||
const operation = datasource?.getOperationForColumnId(accessor);
|
||||
if (operation?.label) {
|
||||
columnToLabel[accessor] = operation.label;
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ export function hasHistogramSeries(
|
|||
return false;
|
||||
}
|
||||
|
||||
const xAxisOperation = datasourceLayers[layerId].getOperationForColumnId(xAccessor);
|
||||
const xAxisOperation = datasourceLayers[layerId]?.getOperationForColumnId(xAccessor);
|
||||
return (
|
||||
xAxisOperation &&
|
||||
xAxisOperation.isBucketed &&
|
||||
|
|
|
@ -35,7 +35,7 @@ import { layerTypes } from '../../../common';
|
|||
import { axisExtentConfigToExpression } from '../../shared_components';
|
||||
|
||||
export const getSortedAccessors = (
|
||||
datasource: DatasourcePublicAPI,
|
||||
datasource: DatasourcePublicAPI | undefined,
|
||||
layer: XYDataLayerConfig | XYReferenceLineLayerConfig
|
||||
) => {
|
||||
const originalOrder = datasource
|
||||
|
@ -66,7 +66,8 @@ export const toExpression = (
|
|||
const datasource = datasourceLayers[layer.layerId];
|
||||
if (datasource) {
|
||||
datasource.getTableSpec().forEach((column) => {
|
||||
const operation = datasourceLayers[layer.layerId].getOperationForColumnId(column.columnId);
|
||||
const operation =
|
||||
datasourceLayers[layer.layerId]?.getOperationForColumnId(column.columnId) ?? null;
|
||||
metadata[layer.layerId][column.columnId] = operation;
|
||||
});
|
||||
}
|
||||
|
@ -375,7 +376,7 @@ const yAxisConfigsToExpression = (yAxisConfigs: AxisConfig[]): Ast[] => {
|
|||
|
||||
const referenceLineLayerToExpression = (
|
||||
layer: XYReferenceLineLayerConfig,
|
||||
datasourceLayer: DatasourcePublicAPI,
|
||||
datasourceLayer: DatasourcePublicAPI | undefined,
|
||||
datasourceExpression: Ast
|
||||
): Ast => {
|
||||
return {
|
||||
|
@ -425,7 +426,7 @@ const annotationLayerToExpression = (
|
|||
const dataLayerToExpression = (
|
||||
layer: ValidXYDataLayerConfig,
|
||||
yAxisConfigs: AxisConfig[],
|
||||
datasourceLayer: DatasourcePublicAPI,
|
||||
datasourceLayer: DatasourcePublicAPI | undefined,
|
||||
metadata: Record<string, Record<string, OperationMetadata | null>>,
|
||||
paletteService: PaletteRegistry,
|
||||
datasourceExpression: Ast
|
||||
|
|
|
@ -7,7 +7,13 @@
|
|||
|
||||
import { getXyVisualization } from './visualization';
|
||||
import { Position } from '@elastic/charts';
|
||||
import { Operation, VisualizeEditorContext, Suggestion, OperationDescriptor } from '../../types';
|
||||
import {
|
||||
Operation,
|
||||
VisualizeEditorContext,
|
||||
Suggestion,
|
||||
OperationDescriptor,
|
||||
DatasourcePublicAPI,
|
||||
} from '../../types';
|
||||
import type {
|
||||
State,
|
||||
XYState,
|
||||
|
@ -269,7 +275,8 @@ describe('xy_visualization', () => {
|
|||
frame.datasourceLayers = {
|
||||
first: mockDatasource.publicAPIMock,
|
||||
};
|
||||
frame.datasourceLayers.first.getOperationForColumnId = jest.fn((accessor) => {
|
||||
const datasourceLayers = frame.datasourceLayers as Record<string, DatasourcePublicAPI>;
|
||||
datasourceLayers.first.getOperationForColumnId = jest.fn((accessor) => {
|
||||
if (accessor === 'a') {
|
||||
return {
|
||||
dataType: 'date',
|
||||
|
@ -1547,7 +1554,8 @@ describe('xy_visualization', () => {
|
|||
(state.layers[0] as XYDataLayerConfig).accessors = [];
|
||||
(state.layers[1] as XYReferenceLineLayerConfig).yConfig = []; // empty the configuration
|
||||
// set the xAccessor as date_histogram
|
||||
frame.datasourceLayers.referenceLine.getOperationForColumnId = jest.fn((accessor) => {
|
||||
const datasourceLayers = frame.datasourceLayers as Record<string, DatasourcePublicAPI>;
|
||||
datasourceLayers.referenceLine.getOperationForColumnId = jest.fn((accessor) => {
|
||||
if (accessor === 'b') {
|
||||
return {
|
||||
dataType: 'date',
|
||||
|
@ -1576,7 +1584,8 @@ describe('xy_visualization', () => {
|
|||
(state.layers[0] as XYDataLayerConfig).accessors = [];
|
||||
(state.layers[1] as XYReferenceLineLayerConfig).yConfig![0].axisMode = 'bottom';
|
||||
// set the xAccessor as date_histogram
|
||||
frame.datasourceLayers.referenceLine.getOperationForColumnId = jest.fn((accessor) => {
|
||||
const datasourceLayers = frame.datasourceLayers as Record<string, DatasourcePublicAPI>;
|
||||
datasourceLayers.referenceLine.getOperationForColumnId = jest.fn((accessor) => {
|
||||
if (accessor === 'b') {
|
||||
return {
|
||||
dataType: 'date',
|
||||
|
@ -1618,8 +1627,9 @@ describe('xy_visualization', () => {
|
|||
{ forAccessor: 'b', axisMode: 'right' },
|
||||
{ forAccessor: 'a', axisMode: 'left' },
|
||||
];
|
||||
const datasourceLayers = frame.datasourceLayers as Record<string, DatasourcePublicAPI>;
|
||||
// set the xAccessor as number histogram
|
||||
frame.datasourceLayers.referenceLine.getOperationForColumnId = jest.fn((accessor) => {
|
||||
datasourceLayers.referenceLine.getOperationForColumnId = jest.fn((accessor) => {
|
||||
if (accessor === 'c') {
|
||||
return {
|
||||
dataType: 'number',
|
||||
|
@ -1650,7 +1660,8 @@ describe('xy_visualization', () => {
|
|||
(state.layers[0] as XYDataLayerConfig).accessors = [];
|
||||
(state.layers[1] as XYReferenceLineLayerConfig).yConfig = []; // empty the configuration
|
||||
// set the xAccessor as top values
|
||||
frame.datasourceLayers.referenceLine.getOperationForColumnId = jest.fn((accessor) => {
|
||||
const datasourceLayers = frame.datasourceLayers as Record<string, DatasourcePublicAPI>;
|
||||
datasourceLayers.referenceLine.getOperationForColumnId = jest.fn((accessor) => {
|
||||
if (accessor === 'b') {
|
||||
return {
|
||||
dataType: 'string',
|
||||
|
@ -1679,7 +1690,8 @@ describe('xy_visualization', () => {
|
|||
(state.layers[0] as XYDataLayerConfig).accessors = [];
|
||||
(state.layers[1] as XYReferenceLineLayerConfig).yConfig![0].axisMode = 'bottom';
|
||||
// set the xAccessor as date_histogram
|
||||
frame.datasourceLayers.referenceLine.getOperationForColumnId = jest.fn((accessor) => {
|
||||
const datasourceLayers = frame.datasourceLayers as Record<string, DatasourcePublicAPI>;
|
||||
datasourceLayers.referenceLine.getOperationForColumnId = jest.fn((accessor) => {
|
||||
if (accessor === 'b') {
|
||||
return {
|
||||
dataType: 'string',
|
||||
|
@ -1787,7 +1799,8 @@ describe('xy_visualization', () => {
|
|||
frame.datasourceLayers = {
|
||||
first: mockDatasource.publicAPIMock,
|
||||
};
|
||||
frame.datasourceLayers.first.getOperationForColumnId = jest.fn((accessor) => {
|
||||
const datasourceLayers = frame.datasourceLayers as Record<string, DatasourcePublicAPI>;
|
||||
datasourceLayers.first.getOperationForColumnId = jest.fn((accessor) => {
|
||||
if (accessor === 'a') {
|
||||
return {
|
||||
dataType: 'date',
|
||||
|
@ -1935,7 +1948,8 @@ describe('xy_visualization', () => {
|
|||
});
|
||||
|
||||
it('should pass name of current series along', () => {
|
||||
(frame.datasourceLayers.first.getOperationForColumnId as jest.Mock).mockReturnValue({
|
||||
const datasourceLayers = frame.datasourceLayers as Record<string, DatasourcePublicAPI>;
|
||||
(datasourceLayers.first.getOperationForColumnId as jest.Mock).mockReturnValue({
|
||||
label: 'Overwritten label',
|
||||
});
|
||||
const palette = paletteServiceMock.get('default');
|
||||
|
@ -2418,7 +2432,8 @@ describe('xy_visualization', () => {
|
|||
};
|
||||
});
|
||||
it('should return a warning when numeric accessors contain array', () => {
|
||||
(frame.datasourceLayers.first.getOperationForColumnId as jest.Mock).mockReturnValue({
|
||||
const datasourceLayers = frame.datasourceLayers as Record<string, DatasourcePublicAPI>;
|
||||
(datasourceLayers.first.getOperationForColumnId as jest.Mock).mockReturnValue({
|
||||
label: 'Label B',
|
||||
});
|
||||
const warningMessages = xyVisualization.getWarningMessages!(
|
||||
|
|
|
@ -104,7 +104,7 @@ export function DataDimensionEditor(
|
|||
const overwriteColor = getSeriesColor(layer, accessor);
|
||||
const assignedColor = useMemo(() => {
|
||||
const sortedAccessors: string[] = getSortedAccessors(
|
||||
props.frame.datasourceLayers[layer.layerId] ?? layer.accessors,
|
||||
props.frame.datasourceLayers[layer.layerId],
|
||||
layer
|
||||
);
|
||||
const colorAssignments = getColorAssignments(
|
||||
|
|
|
@ -213,7 +213,8 @@ export const XyToolbar = memo(function XyToolbar(
|
|||
(layer) =>
|
||||
!layer.xAccessor ||
|
||||
getScaleType(
|
||||
props.frame.datasourceLayers[layer.layerId].getOperationForColumnId(layer.xAccessor),
|
||||
props.frame.datasourceLayers[layer.layerId]?.getOperationForColumnId(layer.xAccessor) ??
|
||||
null,
|
||||
ScaleType.Linear
|
||||
) !== 'ordinal'
|
||||
);
|
||||
|
@ -223,7 +224,8 @@ export const XyToolbar = memo(function XyToolbar(
|
|||
(layer) =>
|
||||
layer.xAccessor &&
|
||||
getScaleType(
|
||||
props.frame.datasourceLayers[layer.layerId].getOperationForColumnId(layer.xAccessor),
|
||||
props.frame.datasourceLayers[layer.layerId]?.getOperationForColumnId(layer.xAccessor) ??
|
||||
null,
|
||||
ScaleType.Linear
|
||||
) === 'time'
|
||||
)
|
||||
|
@ -295,7 +297,8 @@ export const XyToolbar = memo(function XyToolbar(
|
|||
if (!xAccessor) {
|
||||
return false;
|
||||
}
|
||||
const xAccessorOp = props.frame.datasourceLayers[layerId].getOperationForColumnId(xAccessor);
|
||||
const xAccessorOp =
|
||||
props.frame.datasourceLayers[layerId]?.getOperationForColumnId(xAccessor) ?? null;
|
||||
return (
|
||||
getScaleType(xAccessorOp, ScaleType.Linear) === ScaleType.Time &&
|
||||
xAccessorOp?.isBucketed &&
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import React from 'react';
|
||||
import { shallowWithIntl as shallow } from '@kbn/test-jest-helpers';
|
||||
import { Position } from '@elastic/charts';
|
||||
import type { FramePublicAPI } from '../../../../types';
|
||||
import type { FramePublicAPI, DatasourcePublicAPI } from '../../../../types';
|
||||
import { createMockDatasource, createMockFramePublicAPI } from '../../../../mocks';
|
||||
import { State, XYLayerConfig } from '../../types';
|
||||
import { VisualOptionsPopover } from '.';
|
||||
|
@ -111,7 +111,8 @@ describe('Visual options popover', () => {
|
|||
|
||||
it('should disabled the popover if there is histogram series', () => {
|
||||
// make it detect an histogram series
|
||||
frame.datasourceLayers.first.getOperationForColumnId = jest.fn().mockReturnValueOnce({
|
||||
const datasourceLayers = frame.datasourceLayers as Record<string, DatasourcePublicAPI>;
|
||||
datasourceLayers.first.getOperationForColumnId = jest.fn().mockReturnValueOnce({
|
||||
isBucketed: true,
|
||||
scale: 'interval',
|
||||
});
|
||||
|
|
|
@ -12,7 +12,7 @@ import { createDatatableUtilitiesMock } from '@kbn/data-plugin/common/mocks';
|
|||
import { XyToolbar } from '.';
|
||||
import { DimensionEditor } from './dimension_editor';
|
||||
import { AxisSettingsPopover } from './axis_settings_popover';
|
||||
import { FramePublicAPI } from '../../../types';
|
||||
import { FramePublicAPI, DatasourcePublicAPI } from '../../../types';
|
||||
import { State, XYState, XYDataLayerConfig } from '../types';
|
||||
import { Position } from '@elastic/charts';
|
||||
import { createMockFramePublicAPI, createMockDatasource } from '../../../mocks';
|
||||
|
@ -109,7 +109,8 @@ describe('XY Config panels', () => {
|
|||
});
|
||||
|
||||
it('should pass in endzone visibility setter and current sate for time chart', () => {
|
||||
(frame.datasourceLayers.first.getOperationForColumnId as jest.Mock).mockReturnValue({
|
||||
const datasourceLayers = frame.datasourceLayers as Record<string, DatasourcePublicAPI>;
|
||||
(datasourceLayers.first.getOperationForColumnId as jest.Mock).mockReturnValue({
|
||||
dataType: 'date',
|
||||
});
|
||||
const state = testState();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue