Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 1 addition & 9 deletions x-pack/plugins/maps/public/actions/ui_actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import { Dispatch } from 'redux';
import { MapStoreState } from '../reducers/store';
import { getFlyoutDisplay } from '../selectors/ui_selectors';
import { FLYOUT_STATE, INDEXING_STAGE } from '../reducers/ui';
import { FLYOUT_STATE } from '../reducers/ui';
import { trackMapSettings } from './map_actions';
import { setSelectedLayer } from './layer_actions';

Expand All @@ -20,7 +20,6 @@ export const SET_READ_ONLY = 'SET_READ_ONLY';
export const SET_OPEN_TOC_DETAILS = 'SET_OPEN_TOC_DETAILS';
export const SHOW_TOC_DETAILS = 'SHOW_TOC_DETAILS';
export const HIDE_TOC_DETAILS = 'HIDE_TOC_DETAILS';
export const UPDATE_INDEXING_STAGE = 'UPDATE_INDEXING_STAGE';

export function exitFullScreen() {
return {
Expand Down Expand Up @@ -95,10 +94,3 @@ export function hideTOCDetails(layerId: string) {
layerId,
};
}

export function updateIndexingStage(stage: INDEXING_STAGE | null) {
return {
type: UPDATE_INDEXING_STAGE,
stage,
};
}
20 changes: 12 additions & 8 deletions x-pack/plugins/maps/public/classes/layers/layer_wizard_registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,26 @@ import { LayerDescriptor } from '../../../common/descriptor_types';
import { LAYER_WIZARD_CATEGORY } from '../../../common/constants';

export type RenderWizardArguments = {
previewLayers: (layerDescriptors: LayerDescriptor[], isIndexingSource?: boolean) => void;
previewLayers: (layerDescriptors: LayerDescriptor[]) => void;
mapColors: string[];
// upload arguments
isIndexingTriggered: boolean;
onRemove: () => void;
onIndexReady: (indexReady: boolean) => void;
importSuccessHandler: (indexResponses: unknown) => void;
importErrorHandler: (indexResponses: unknown) => void;
// multi-step arguments for wizards that supply 'prerequisiteSteps'
currentStepId: string | null;
enableNextBtn: () => void;
disableNextBtn: () => void;
startStepLoading: () => void;
stopStepLoading: () => void;
// Typically, next step will be triggered via user clicking next button.
// However, this method is made available to trigger next step manually
// for async task completion that triggers the next step.
advanceToNextStep: () => void;
};

export type LayerWizard = {
categories: LAYER_WIZARD_CATEGORY[];
checkVisibility?: () => Promise<boolean>;
description: string;
icon: string;
isIndexingSource?: boolean;
prerequisiteSteps?: Array<{ id: string; label: string }>;
renderWizard(renderWizardArguments: RenderWizardArguments): ReactElement<any>;
title: string;
};
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import React, { Component } from 'react';
import { IFieldType } from 'src/plugins/data/public';
import {
ES_GEO_FIELD_TYPE,
DEFAULT_MAX_RESULT_WINDOW,
SCALING_TYPES,
} from '../../../../common/constants';
import { getFileUploadComponent } from '../../../kibana_services';
// @ts-ignore
import { GeojsonFileSource } from './geojson_file_source';
import { VectorLayer } from '../../layers/vector_layer/vector_layer';
// @ts-ignore
import { createDefaultLayerDescriptor } from '../es_search_source';
import { RenderWizardArguments } from '../../layers/layer_wizard_registry';

export const INDEX_SETUP_STEP_ID = 'INDEX_SETUP_STEP_ID';
export const INDEXING_STEP_ID = 'INDEXING_STEP_ID';

enum INDEXING_STAGE {
READY = 'READY',
TRIGGERED = 'TRIGGERED',
SUCCESS = 'SUCCESS',
ERROR = 'ERROR',
}

interface State {
indexingStage: INDEXING_STAGE | null;
}

export class ClientFileCreateSourceEditor extends Component<RenderWizardArguments, State> {
private _isMounted: boolean = false;

state = {
indexingStage: null,
};

componentDidMount() {
this._isMounted = true;
}

componentWillUnmount() {
this._isMounted = false;
}

componentDidUpdate() {
if (
this.props.currentStepId === INDEXING_STEP_ID &&
this.state.indexingStage === INDEXING_STAGE.READY
) {
this.setState({ indexingStage: INDEXING_STAGE.TRIGGERED });
this.props.startStepLoading();
}
}

_onFileUpload = (geojsonFile: unknown, name: string) => {
if (!this._isMounted) {
return;
}

if (!geojsonFile) {
this.props.previewLayers([]);
return;
}

const sourceDescriptor = GeojsonFileSource.createDescriptor(geojsonFile, name);
const layerDescriptor = VectorLayer.createDescriptor(
{ sourceDescriptor },
this.props.mapColors
);
this.props.previewLayers([layerDescriptor]);
};

_onIndexingComplete = (indexResponses: { indexDataResp: unknown; indexPatternResp: unknown }) => {
if (!this._isMounted) {
return;
}

this.props.advanceToNextStep();

const { indexDataResp, indexPatternResp } = indexResponses;

// @ts-ignore
const indexCreationFailed = !(indexDataResp && indexDataResp.success);
// @ts-ignore
const allDocsFailed = indexDataResp.failures.length === indexDataResp.docCount;
// @ts-ignore
const indexPatternCreationFailed = !(indexPatternResp && indexPatternResp.success);
if (indexCreationFailed || allDocsFailed || indexPatternCreationFailed) {
this.setState({ indexingStage: INDEXING_STAGE.ERROR });
return;
}

// @ts-ignore
const { fields, id: indexPatternId } = indexPatternResp;
const geoField = fields.find((field: IFieldType) =>
[ES_GEO_FIELD_TYPE.GEO_POINT as string, ES_GEO_FIELD_TYPE.GEO_SHAPE as string].includes(
field.type
)
);
if (!indexPatternId || !geoField) {
this.setState({ indexingStage: INDEXING_STAGE.ERROR });
this.props.previewLayers([]);
} else {
const esSearchSourceConfig = {
indexPatternId,
geoField: geoField.name,
// Only turn on bounds filter for large doc counts
// @ts-ignore
filterByMapBounds: indexDataResp.docCount > DEFAULT_MAX_RESULT_WINDOW,
scalingType:
geoField.type === ES_GEO_FIELD_TYPE.GEO_POINT
? SCALING_TYPES.CLUSTERS
: SCALING_TYPES.LIMIT,
};
this.setState({ indexingStage: INDEXING_STAGE.SUCCESS });
this.props.previewLayers([
createDefaultLayerDescriptor(esSearchSourceConfig, this.props.mapColors),
]);
}
};

// Called on file upload screen when UI state changes
_onIndexReady = (indexReady: boolean) => {
if (!this._isMounted) {
return;
}
this.setState({ indexingStage: indexReady ? INDEXING_STAGE.READY : null });
if (indexReady) {
this.props.enableNextBtn();
} else {
this.props.disableNextBtn();
}
};

// Called on file upload screen when upload file is changed or removed
_onFileRemove = () => {
this.props.previewLayers([]);
};

render() {
const FileUpload = getFileUploadComponent();
return (
<FileUpload
appName={'Maps'}
isIndexingTriggered={this.state.indexingStage === INDEXING_STAGE.TRIGGERED}
onFileUpload={this._onFileUpload}
onFileRemove={this._onFileRemove}
onIndexReady={this._onIndexReady}
transformDetails={'geo'}
onIndexingComplete={this._onIndexingComplete}
/>
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,102 +6,37 @@

import { i18n } from '@kbn/i18n';
import React from 'react';
import { IFieldType } from 'src/plugins/data/public';
import {
ES_GEO_FIELD_TYPE,
DEFAULT_MAX_RESULT_WINDOW,
SCALING_TYPES,
} from '../../../../common/constants';
// @ts-ignore
import { createDefaultLayerDescriptor } from '../es_search_source';
import { LayerWizard, RenderWizardArguments } from '../../layers/layer_wizard_registry';
// @ts-ignore
import { ClientFileCreateSourceEditor } from './create_client_file_source_editor';
// @ts-ignore
import { GeojsonFileSource } from './geojson_file_source';
import { VectorLayer } from '../../layers/vector_layer/vector_layer';
import {
ClientFileCreateSourceEditor,
INDEX_SETUP_STEP_ID,
INDEXING_STEP_ID,
} from './create_client_file_source_editor';

export const uploadLayerWizardConfig: LayerWizard = {
categories: [],
description: i18n.translate('xpack.maps.source.geojsonFileDescription', {
description: i18n.translate('xpack.maps.fileUploadWizard.description', {
defaultMessage: 'Index GeoJSON data in Elasticsearch',
}),
icon: 'importAction',
isIndexingSource: true,
renderWizard: ({
previewLayers,
mapColors,
isIndexingTriggered,
onRemove,
onIndexReady,
importSuccessHandler,
importErrorHandler,
}: RenderWizardArguments) => {
function previewGeojsonFile(geojsonFile: unknown, name: string) {
if (!geojsonFile) {
previewLayers([]);
return;
}
const sourceDescriptor = GeojsonFileSource.createDescriptor(geojsonFile, name);
const layerDescriptor = VectorLayer.createDescriptor({ sourceDescriptor }, mapColors);
// TODO figure out a better way to handle passing this information back to layer_addpanel
previewLayers([layerDescriptor], true);
}

function viewIndexedData(indexResponses: {
indexDataResp: unknown;
indexPatternResp: unknown;
}) {
const { indexDataResp, indexPatternResp } = indexResponses;

// @ts-ignore
const indexCreationFailed = !(indexDataResp && indexDataResp.success);
// @ts-ignore
const allDocsFailed = indexDataResp.failures.length === indexDataResp.docCount;
// @ts-ignore
const indexPatternCreationFailed = !(indexPatternResp && indexPatternResp.success);

if (indexCreationFailed || allDocsFailed || indexPatternCreationFailed) {
importErrorHandler(indexResponses);
return;
}
// @ts-ignore
const { fields, id: indexPatternId } = indexPatternResp;
const geoField = fields.find((field: IFieldType) =>
[ES_GEO_FIELD_TYPE.GEO_POINT as string, ES_GEO_FIELD_TYPE.GEO_SHAPE as string].includes(
field.type
)
);
if (!indexPatternId || !geoField) {
previewLayers([]);
} else {
const esSearchSourceConfig = {
indexPatternId,
geoField: geoField.name,
// Only turn on bounds filter for large doc counts
// @ts-ignore
filterByMapBounds: indexDataResp.docCount > DEFAULT_MAX_RESULT_WINDOW,
scalingType:
geoField.type === ES_GEO_FIELD_TYPE.GEO_POINT
? SCALING_TYPES.CLUSTERS
: SCALING_TYPES.LIMIT,
};
previewLayers([createDefaultLayerDescriptor(esSearchSourceConfig, mapColors)]);
importSuccessHandler(indexResponses);
}
}

return (
<ClientFileCreateSourceEditor
previewGeojsonFile={previewGeojsonFile}
isIndexingTriggered={isIndexingTriggered}
onIndexingComplete={viewIndexedData}
onRemove={onRemove}
onIndexReady={onIndexReady}
/>
);
prerequisiteSteps: [
{
id: INDEX_SETUP_STEP_ID,
label: i18n.translate('xpack.maps.fileUploadWizard.importFileSetupLabel', {
defaultMessage: 'Import file',
}),
},
{
id: INDEXING_STEP_ID,
label: i18n.translate('xpack.maps.fileUploadWizard.indexingLabel', {
defaultMessage: 'Importing file',
}),
},
],
renderWizard: (renderWizardArguments: RenderWizardArguments) => {
return <ClientFileCreateSourceEditor {...renderWizardArguments} />;
},
title: i18n.translate('xpack.maps.source.geojsonFileTitle', {
title: i18n.translate('xpack.maps.fileUploadWizard.title', {
defaultMessage: 'Upload GeoJSON',
}),
};
Loading