Skip to content

Commit f35f5ff

Browse files
[Maps] remove indexing state from redux (#69765)
* [Maps] remove indexing state from redux * add indexing step * tslint * tslint fixes * tslint item * clear preview when file changes * review feedback * use prevState instead of this.state in setState Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
1 parent 39b2d71 commit f35f5ff

15 files changed

Lines changed: 356 additions & 368 deletions

File tree

x-pack/plugins/maps/public/actions/ui_actions.ts

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import { Dispatch } from 'redux';
88
import { MapStoreState } from '../reducers/store';
99
import { getFlyoutDisplay } from '../selectors/ui_selectors';
10-
import { FLYOUT_STATE, INDEXING_STAGE } from '../reducers/ui';
10+
import { FLYOUT_STATE } from '../reducers/ui';
1111
import { trackMapSettings } from './map_actions';
1212
import { setSelectedLayer } from './layer_actions';
1313

@@ -20,7 +20,6 @@ export const SET_READ_ONLY = 'SET_READ_ONLY';
2020
export const SET_OPEN_TOC_DETAILS = 'SET_OPEN_TOC_DETAILS';
2121
export const SHOW_TOC_DETAILS = 'SHOW_TOC_DETAILS';
2222
export const HIDE_TOC_DETAILS = 'HIDE_TOC_DETAILS';
23-
export const UPDATE_INDEXING_STAGE = 'UPDATE_INDEXING_STAGE';
2423

2524
export function exitFullScreen() {
2625
return {
@@ -95,10 +94,3 @@ export function hideTOCDetails(layerId: string) {
9594
layerId,
9695
};
9796
}
98-
99-
export function updateIndexingStage(stage: INDEXING_STAGE | null) {
100-
return {
101-
type: UPDATE_INDEXING_STAGE,
102-
stage,
103-
};
104-
}

x-pack/plugins/maps/public/classes/layers/layer_wizard_registry.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,26 @@ import { LayerDescriptor } from '../../../common/descriptor_types';
1010
import { LAYER_WIZARD_CATEGORY } from '../../../common/constants';
1111

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

2327
export type LayerWizard = {
2428
categories: LAYER_WIZARD_CATEGORY[];
2529
checkVisibility?: () => Promise<boolean>;
2630
description: string;
2731
icon: string;
28-
isIndexingSource?: boolean;
32+
prerequisiteSteps?: Array<{ id: string; label: string }>;
2933
renderWizard(renderWizardArguments: RenderWizardArguments): ReactElement<any>;
3034
title: string;
3135
};

x-pack/plugins/maps/public/classes/sources/client_file_source/create_client_file_source_editor.js

Lines changed: 0 additions & 29 deletions
This file was deleted.
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import React, { Component } from 'react';
8+
import { IFieldType } from 'src/plugins/data/public';
9+
import {
10+
ES_GEO_FIELD_TYPE,
11+
DEFAULT_MAX_RESULT_WINDOW,
12+
SCALING_TYPES,
13+
} from '../../../../common/constants';
14+
import { getFileUploadComponent } from '../../../kibana_services';
15+
// @ts-ignore
16+
import { GeojsonFileSource } from './geojson_file_source';
17+
import { VectorLayer } from '../../layers/vector_layer/vector_layer';
18+
// @ts-ignore
19+
import { createDefaultLayerDescriptor } from '../es_search_source';
20+
import { RenderWizardArguments } from '../../layers/layer_wizard_registry';
21+
22+
export const INDEX_SETUP_STEP_ID = 'INDEX_SETUP_STEP_ID';
23+
export const INDEXING_STEP_ID = 'INDEXING_STEP_ID';
24+
25+
enum INDEXING_STAGE {
26+
READY = 'READY',
27+
TRIGGERED = 'TRIGGERED',
28+
SUCCESS = 'SUCCESS',
29+
ERROR = 'ERROR',
30+
}
31+
32+
interface State {
33+
indexingStage: INDEXING_STAGE | null;
34+
}
35+
36+
export class ClientFileCreateSourceEditor extends Component<RenderWizardArguments, State> {
37+
private _isMounted: boolean = false;
38+
39+
state = {
40+
indexingStage: null,
41+
};
42+
43+
componentDidMount() {
44+
this._isMounted = true;
45+
}
46+
47+
componentWillUnmount() {
48+
this._isMounted = false;
49+
}
50+
51+
componentDidUpdate() {
52+
if (
53+
this.props.currentStepId === INDEXING_STEP_ID &&
54+
this.state.indexingStage === INDEXING_STAGE.READY
55+
) {
56+
this.setState({ indexingStage: INDEXING_STAGE.TRIGGERED });
57+
this.props.startStepLoading();
58+
}
59+
}
60+
61+
_onFileUpload = (geojsonFile: unknown, name: string) => {
62+
if (!this._isMounted) {
63+
return;
64+
}
65+
66+
if (!geojsonFile) {
67+
this.props.previewLayers([]);
68+
return;
69+
}
70+
71+
const sourceDescriptor = GeojsonFileSource.createDescriptor(geojsonFile, name);
72+
const layerDescriptor = VectorLayer.createDescriptor(
73+
{ sourceDescriptor },
74+
this.props.mapColors
75+
);
76+
this.props.previewLayers([layerDescriptor]);
77+
};
78+
79+
_onIndexingComplete = (indexResponses: { indexDataResp: unknown; indexPatternResp: unknown }) => {
80+
if (!this._isMounted) {
81+
return;
82+
}
83+
84+
this.props.advanceToNextStep();
85+
86+
const { indexDataResp, indexPatternResp } = indexResponses;
87+
88+
// @ts-ignore
89+
const indexCreationFailed = !(indexDataResp && indexDataResp.success);
90+
// @ts-ignore
91+
const allDocsFailed = indexDataResp.failures.length === indexDataResp.docCount;
92+
// @ts-ignore
93+
const indexPatternCreationFailed = !(indexPatternResp && indexPatternResp.success);
94+
if (indexCreationFailed || allDocsFailed || indexPatternCreationFailed) {
95+
this.setState({ indexingStage: INDEXING_STAGE.ERROR });
96+
return;
97+
}
98+
99+
// @ts-ignore
100+
const { fields, id: indexPatternId } = indexPatternResp;
101+
const geoField = fields.find((field: IFieldType) =>
102+
[ES_GEO_FIELD_TYPE.GEO_POINT as string, ES_GEO_FIELD_TYPE.GEO_SHAPE as string].includes(
103+
field.type
104+
)
105+
);
106+
if (!indexPatternId || !geoField) {
107+
this.setState({ indexingStage: INDEXING_STAGE.ERROR });
108+
this.props.previewLayers([]);
109+
} else {
110+
const esSearchSourceConfig = {
111+
indexPatternId,
112+
geoField: geoField.name,
113+
// Only turn on bounds filter for large doc counts
114+
// @ts-ignore
115+
filterByMapBounds: indexDataResp.docCount > DEFAULT_MAX_RESULT_WINDOW,
116+
scalingType:
117+
geoField.type === ES_GEO_FIELD_TYPE.GEO_POINT
118+
? SCALING_TYPES.CLUSTERS
119+
: SCALING_TYPES.LIMIT,
120+
};
121+
this.setState({ indexingStage: INDEXING_STAGE.SUCCESS });
122+
this.props.previewLayers([
123+
createDefaultLayerDescriptor(esSearchSourceConfig, this.props.mapColors),
124+
]);
125+
}
126+
};
127+
128+
// Called on file upload screen when UI state changes
129+
_onIndexReady = (indexReady: boolean) => {
130+
if (!this._isMounted) {
131+
return;
132+
}
133+
this.setState({ indexingStage: indexReady ? INDEXING_STAGE.READY : null });
134+
if (indexReady) {
135+
this.props.enableNextBtn();
136+
} else {
137+
this.props.disableNextBtn();
138+
}
139+
};
140+
141+
// Called on file upload screen when upload file is changed or removed
142+
_onFileRemove = () => {
143+
this.props.previewLayers([]);
144+
};
145+
146+
render() {
147+
const FileUpload = getFileUploadComponent();
148+
return (
149+
<FileUpload
150+
appName={'Maps'}
151+
isIndexingTriggered={this.state.indexingStage === INDEXING_STAGE.TRIGGERED}
152+
onFileUpload={this._onFileUpload}
153+
onFileRemove={this._onFileRemove}
154+
onIndexReady={this._onIndexReady}
155+
transformDetails={'geo'}
156+
onIndexingComplete={this._onIndexingComplete}
157+
/>
158+
);
159+
}
160+
}

x-pack/plugins/maps/public/classes/sources/client_file_source/upload_layer_wizard.tsx

Lines changed: 23 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -6,102 +6,37 @@
66

77
import { i18n } from '@kbn/i18n';
88
import React from 'react';
9-
import { IFieldType } from 'src/plugins/data/public';
10-
import {
11-
ES_GEO_FIELD_TYPE,
12-
DEFAULT_MAX_RESULT_WINDOW,
13-
SCALING_TYPES,
14-
} from '../../../../common/constants';
15-
// @ts-ignore
16-
import { createDefaultLayerDescriptor } from '../es_search_source';
179
import { LayerWizard, RenderWizardArguments } from '../../layers/layer_wizard_registry';
18-
// @ts-ignore
19-
import { ClientFileCreateSourceEditor } from './create_client_file_source_editor';
20-
// @ts-ignore
21-
import { GeojsonFileSource } from './geojson_file_source';
22-
import { VectorLayer } from '../../layers/vector_layer/vector_layer';
10+
import {
11+
ClientFileCreateSourceEditor,
12+
INDEX_SETUP_STEP_ID,
13+
INDEXING_STEP_ID,
14+
} from './create_client_file_source_editor';
2315

2416
export const uploadLayerWizardConfig: LayerWizard = {
2517
categories: [],
26-
description: i18n.translate('xpack.maps.source.geojsonFileDescription', {
18+
description: i18n.translate('xpack.maps.fileUploadWizard.description', {
2719
defaultMessage: 'Index GeoJSON data in Elasticsearch',
2820
}),
2921
icon: 'importAction',
30-
isIndexingSource: true,
31-
renderWizard: ({
32-
previewLayers,
33-
mapColors,
34-
isIndexingTriggered,
35-
onRemove,
36-
onIndexReady,
37-
importSuccessHandler,
38-
importErrorHandler,
39-
}: RenderWizardArguments) => {
40-
function previewGeojsonFile(geojsonFile: unknown, name: string) {
41-
if (!geojsonFile) {
42-
previewLayers([]);
43-
return;
44-
}
45-
const sourceDescriptor = GeojsonFileSource.createDescriptor(geojsonFile, name);
46-
const layerDescriptor = VectorLayer.createDescriptor({ sourceDescriptor }, mapColors);
47-
// TODO figure out a better way to handle passing this information back to layer_addpanel
48-
previewLayers([layerDescriptor], true);
49-
}
50-
51-
function viewIndexedData(indexResponses: {
52-
indexDataResp: unknown;
53-
indexPatternResp: unknown;
54-
}) {
55-
const { indexDataResp, indexPatternResp } = indexResponses;
56-
57-
// @ts-ignore
58-
const indexCreationFailed = !(indexDataResp && indexDataResp.success);
59-
// @ts-ignore
60-
const allDocsFailed = indexDataResp.failures.length === indexDataResp.docCount;
61-
// @ts-ignore
62-
const indexPatternCreationFailed = !(indexPatternResp && indexPatternResp.success);
63-
64-
if (indexCreationFailed || allDocsFailed || indexPatternCreationFailed) {
65-
importErrorHandler(indexResponses);
66-
return;
67-
}
68-
// @ts-ignore
69-
const { fields, id: indexPatternId } = indexPatternResp;
70-
const geoField = fields.find((field: IFieldType) =>
71-
[ES_GEO_FIELD_TYPE.GEO_POINT as string, ES_GEO_FIELD_TYPE.GEO_SHAPE as string].includes(
72-
field.type
73-
)
74-
);
75-
if (!indexPatternId || !geoField) {
76-
previewLayers([]);
77-
} else {
78-
const esSearchSourceConfig = {
79-
indexPatternId,
80-
geoField: geoField.name,
81-
// Only turn on bounds filter for large doc counts
82-
// @ts-ignore
83-
filterByMapBounds: indexDataResp.docCount > DEFAULT_MAX_RESULT_WINDOW,
84-
scalingType:
85-
geoField.type === ES_GEO_FIELD_TYPE.GEO_POINT
86-
? SCALING_TYPES.CLUSTERS
87-
: SCALING_TYPES.LIMIT,
88-
};
89-
previewLayers([createDefaultLayerDescriptor(esSearchSourceConfig, mapColors)]);
90-
importSuccessHandler(indexResponses);
91-
}
92-
}
93-
94-
return (
95-
<ClientFileCreateSourceEditor
96-
previewGeojsonFile={previewGeojsonFile}
97-
isIndexingTriggered={isIndexingTriggered}
98-
onIndexingComplete={viewIndexedData}
99-
onRemove={onRemove}
100-
onIndexReady={onIndexReady}
101-
/>
102-
);
22+
prerequisiteSteps: [
23+
{
24+
id: INDEX_SETUP_STEP_ID,
25+
label: i18n.translate('xpack.maps.fileUploadWizard.importFileSetupLabel', {
26+
defaultMessage: 'Import file',
27+
}),
28+
},
29+
{
30+
id: INDEXING_STEP_ID,
31+
label: i18n.translate('xpack.maps.fileUploadWizard.indexingLabel', {
32+
defaultMessage: 'Importing file',
33+
}),
34+
},
35+
],
36+
renderWizard: (renderWizardArguments: RenderWizardArguments) => {
37+
return <ClientFileCreateSourceEditor {...renderWizardArguments} />;
10338
},
104-
title: i18n.translate('xpack.maps.source.geojsonFileTitle', {
39+
title: i18n.translate('xpack.maps.fileUploadWizard.title', {
10540
defaultMessage: 'Upload GeoJSON',
10641
}),
10742
};

0 commit comments

Comments
 (0)