[Maps] Add draw wizard (#100278)

This commit is contained in:
Thomas Neirynck 2021-05-26 11:21:38 -04:00 committed by GitHub
parent 639df23aa4
commit c5aa39835d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 483 additions and 48 deletions

View file

@ -5,16 +5,16 @@
* 2.0.
*/
import React from 'react';
import { FileUploadComponentProps, lazyLoadModules } from '../lazy_load_bundle';
import { lazyLoadModules } from '../lazy_load_bundle';
import type { IImporter, ImportFactoryOptions } from '../importer';
import { IndexNameFormProps } from '../';
import type { HasImportPermission, FindFileStructureResponse } from '../../common';
import type { getMaxBytes, getMaxBytesFormatted } from '../importer/get_max_bytes';
import { JsonUploadAndParseAsyncWrapper } from './json_upload_and_parse_async_wrapper';
import { IndexNameFormAsyncWrapper } from './index_name_form_async_wrapper';
export interface FileUploadStartApi {
getFileUploadComponent(): ReturnType<typeof getFileUploadComponent>;
getIndexNameFormComponent(): Promise<React.ComponentType<IndexNameFormProps>>;
FileUploadComponent: typeof JsonUploadAndParseAsyncWrapper;
IndexNameFormComponent: typeof IndexNameFormAsyncWrapper;
importerFactory: typeof importerFactory;
getMaxBytes: typeof getMaxBytes;
getMaxBytesFormatted: typeof getMaxBytesFormatted;
@ -30,19 +30,8 @@ export interface GetTimeFieldRangeResponse {
end: { epoch: number; string: string };
}
export async function getFileUploadComponent(): Promise<
React.ComponentType<FileUploadComponentProps>
> {
const fileUploadModules = await lazyLoadModules();
return fileUploadModules.JsonUploadAndParse;
}
export async function getIndexNameFormComponent(): Promise<
React.ComponentType<IndexNameFormProps>
> {
const fileUploadModules = await lazyLoadModules();
return fileUploadModules.IndexNameForm;
}
export const FileUploadComponent = JsonUploadAndParseAsyncWrapper;
export const IndexNameFormComponent = IndexNameFormAsyncWrapper;
export async function importerFactory(
format: string,

View file

@ -0,0 +1,43 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React from 'react';
import { EuiLoadingContent } from '@elastic/eui';
import { lazyLoadModules } from '../lazy_load_bundle';
import { IndexNameFormProps } from '../index';
interface State {
IndexNameForm: React.ComponentType<IndexNameFormProps> | null;
}
export class IndexNameFormAsyncWrapper extends React.Component<IndexNameFormProps, State> {
state: State = {
IndexNameForm: null,
};
private _isMounted = false;
componentWillUnmount(): void {
this._isMounted = false;
}
componentDidMount() {
this._isMounted = true;
lazyLoadModules().then((modules) => {
if (this._isMounted) {
this.setState({
IndexNameForm: modules.IndexNameForm,
});
}
});
}
render() {
const { IndexNameForm } = this.state;
return IndexNameForm ? <IndexNameForm {...this.props} /> : <EuiLoadingContent lines={3} />;
}
}

View file

@ -0,0 +1,48 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React from 'react';
import { EuiLoadingContent } from '@elastic/eui';
import { FileUploadComponentProps, lazyLoadModules } from '../lazy_load_bundle';
interface State {
JsonUploadAndParse: React.ComponentType<FileUploadComponentProps> | null;
}
export class JsonUploadAndParseAsyncWrapper extends React.Component<
FileUploadComponentProps,
State
> {
state: State = {
JsonUploadAndParse: null,
};
private _isMounted = false;
componentDidMount() {
this._isMounted = true;
lazyLoadModules().then((modules) => {
if (this._isMounted) {
this.setState({
JsonUploadAndParse: modules.JsonUploadAndParse,
});
}
});
}
componentWillUnmount(): void {
this._isMounted = false;
}
render() {
const { JsonUploadAndParse } = this.state;
return JsonUploadAndParse ? (
<JsonUploadAndParse {...this.props} />
) : (
<EuiLoadingContent lines={3} />
);
}
}

View file

@ -32,7 +32,7 @@ export interface FileUploadComponentProps {
let loadModulesPromise: Promise<LazyLoadedFileUploadModules>;
interface LazyLoadedFileUploadModules {
export interface LazyLoadedFileUploadModules {
JsonUploadAndParse: React.ComponentType<FileUploadComponentProps>;
IndexNameForm: React.ComponentType<IndexNameFormProps>;
importerFactory: (format: string, options: ImportFactoryOptions) => IImporter | undefined;

View file

@ -8,10 +8,10 @@
import { CoreStart, Plugin } from '../../../../src/core/public';
import {
FileUploadStartApi,
getFileUploadComponent,
FileUploadComponent,
importerFactory,
hasImportPermission,
getIndexNameFormComponent,
IndexNameFormComponent,
checkIndexExists,
getTimeFieldRange,
analyzeFile,
@ -42,8 +42,8 @@ export class FileUploadPlugin
public start(core: CoreStart, plugins: FileUploadStartDependencies): FileUploadStartApi {
setStartServices(core, plugins);
return {
getFileUploadComponent,
getIndexNameFormComponent,
FileUploadComponent,
IndexNameFormComponent,
importerFactory,
getMaxBytes,
getMaxBytesFormatted,

View file

@ -41,6 +41,7 @@ export const GIS_API_PATH = `api/${APP_ID}`;
export const INDEX_SETTINGS_API_PATH = `${GIS_API_PATH}/indexSettings`;
export const FONTS_API_PATH = `${GIS_API_PATH}/fonts`;
export const INDEX_SOURCE_API_PATH = `${GIS_API_PATH}/docSource`;
export const INDEX_FEATURE_PATH = `/${GIS_API_PATH}/feature`;
export const API_ROOT_PATH = `/${GIS_API_PATH}`;
export const MVT_GETTILE_API_PATH = 'mvt/getTile';

View file

@ -6,6 +6,7 @@
*/
export interface CreateDocSourceResp {
indexPatternId?: string;
success: boolean;
error?: Error;
}

View file

@ -10,7 +10,6 @@ import { AnyAction, Dispatch } from 'redux';
import { ThunkDispatch } from 'redux-thunk';
import turfBboxPolygon from '@turf/bbox-polygon';
import turfBooleanContains from '@turf/boolean-contains';
import { Filter, Query, TimeRange } from 'src/plugins/data/public';
import { MapStoreState } from '../reducers/store';
import {

View file

@ -11,13 +11,13 @@ import React, { Component } from 'react';
import { FeatureCollection } from 'geojson';
import { EuiPanel } from '@elastic/eui';
import { DEFAULT_MAX_RESULT_WINDOW, SCALING_TYPES } from '../../../../common/constants';
import { getFileUpload } from '../../../kibana_services';
import { GeoJsonFileSource } from '../../sources/geojson_file_source';
import { VectorLayer } from '../../layers/vector_layer';
import { createDefaultLayerDescriptor } from '../../sources/es_search_source';
import { RenderWizardArguments } from '../../layers/layer_wizard_registry';
import { FileUploadComponentProps, FileUploadGeoResults } from '../../../../../file_upload/public';
import { FileUploadGeoResults } from '../../../../../file_upload/public';
import { ES_FIELD_TYPES } from '../../../../../../../src/plugins/data/public';
import { getFileUploadComponent } from '../../../kibana_services';
export enum UPLOAD_STEPS {
CONFIGURE_UPLOAD = 'CONFIGURE_UPLOAD',
@ -34,7 +34,6 @@ enum INDEXING_STAGE {
interface State {
indexingStage: INDEXING_STAGE;
fileUploadComponent: React.ComponentType<FileUploadComponentProps> | null;
results?: FileUploadGeoResults;
}
@ -43,12 +42,10 @@ export class ClientFileCreateSourceEditor extends Component<RenderWizardArgument
state: State = {
indexingStage: INDEXING_STAGE.CONFIGURE,
fileUploadComponent: null,
};
componentDidMount() {
this._isMounted = true;
this._loadFileUploadComponent();
}
componentWillUnmount() {
@ -91,13 +88,6 @@ export class ClientFileCreateSourceEditor extends Component<RenderWizardArgument
this.props.advanceToNextStep();
});
async _loadFileUploadComponent() {
const fileUploadComponent = await getFileUpload().getFileUploadComponent();
if (this._isMounted) {
this.setState({ fileUploadComponent });
}
}
_onFileSelect = (geojsonFile: FeatureCollection, name: string, previewCoverage: number) => {
if (!this._isMounted) {
return;
@ -157,11 +147,8 @@ export class ClientFileCreateSourceEditor extends Component<RenderWizardArgument
};
render() {
if (!this.state.fileUploadComponent) {
return null;
}
const FileUpload = getFileUploadComponent();
const FileUpload = this.state.fileUploadComponent;
return (
<EuiPanel>
<FileUpload

View file

@ -0,0 +1,37 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React, { FunctionComponent } from 'react';
export const DrawLayerIcon: FunctionComponent = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="49"
height="25"
fill="none"
viewBox="0 0 49 25"
className="mapLayersWizardIcon"
>
<path
className="mapLayersWizardIcon__background"
d="M12.281 3l-6.625 7.625 1.657 8.938 35.218-.813v-13l-10.625-3.5-9.781 9.5L12.281 3z"
/>
<path
className="mapLayersWizardIcon__highlight"
fillRule="evenodd"
d="M31.775 1.68l11.256 3.708v13.85l-36.133.834-1.777-9.593 7.114-8.189 9.875 8.778 9.665-9.388zm.262 1.14l-9.897 9.612-9.813-8.722-6.135 7.06 1.535 8.283 34.304-.792V6.111L32.037 2.82z"
clipRule="evenodd"
/>
<circle cx="7.281" cy="19.5" r="2.5" className="mapLayersWizardIcon__highlight" />
<circle cx="5.656" cy="10.25" r="2.5" className="mapLayersWizardIcon__highlight" />
<circle cx="12.156" cy="3.625" r="2.5" className="mapLayersWizardIcon__highlight" />
<circle cx="22" cy="11.6" r="2.5" className="mapLayersWizardIcon__highlight" />
<circle cx="31.969" cy="2.5" r="2.5" className="mapLayersWizardIcon__highlight" />
<circle cx="42.344" cy="6.125" r="2.5" className="mapLayersWizardIcon__highlight" />
<circle cx="42.344" cy="19" r="2.5" className="mapLayersWizardIcon__highlight" />
</svg>
);

View file

@ -30,6 +30,8 @@ import { mvtVectorSourceWizardConfig } from '../sources/mvt_single_layer_vector_
import { ObservabilityLayerWizardConfig } from './solution_layers/observability';
import { SecurityLayerWizardConfig } from './solution_layers/security';
import { choroplethLayerWizardConfig } from './choropleth_layer_wizard';
import { newVectorLayerWizardConfig } from './new_vector_layer_wizard';
import { getMapAppConfig } from '../../kibana_services';
let registered = false;
export function registerLayerWizards() {
@ -39,6 +41,9 @@ export function registerLayerWizards() {
// Registration order determines display order
registerLayerWizard(uploadLayerWizardConfig);
if (getMapAppConfig().enableDrawingFeature) {
registerLayerWizard(newVectorLayerWizardConfig);
}
registerLayerWizard(esDocumentsLayerWizardConfig);
// @ts-ignore
registerLayerWizard(choroplethLayerWizardConfig);

View file

@ -0,0 +1,49 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { i18n } from '@kbn/i18n';
import React from 'react';
import { LayerWizard, RenderWizardArguments } from '../../layers/layer_wizard_registry';
import { NewVectorLayerEditor } from './wizard';
import { DrawLayerIcon } from '../../layers/icons/draw_layer_icon';
import { getFileUpload } from '../../../kibana_services';
import { LAYER_WIZARD_CATEGORY } from '../../../../common';
const ADD_VECTOR_DRAWING_LAYER = 'ADD_VECTOR_DRAWING_LAYER';
export const newVectorLayerWizardConfig: LayerWizard = {
categories: [LAYER_WIZARD_CATEGORY.ELASTICSEARCH],
description: i18n.translate('xpack.maps.newVectorLayerWizard.description', {
defaultMessage: 'Creates a new empty layer. Use this to add shapes to the map',
}),
disabledReason: i18n.translate('xpack.maps.newVectorLayerWizard.disabledDesc', {
defaultMessage:
'Unable to draw vector shapes, you are missing the Kibana privilege "Index Pattern Management".',
}),
getIsDisabled: async () => {
const hasImportPermission = await getFileUpload().hasImportPermission({
checkCreateIndexPattern: true,
checkHasManagePipeline: false,
});
return !hasImportPermission;
},
icon: DrawLayerIcon,
prerequisiteSteps: [
{
id: ADD_VECTOR_DRAWING_LAYER,
label: i18n.translate('xpack.maps.newVectorLayerWizard.indexNewLayer', {
defaultMessage: 'Index new layer',
}),
},
],
renderWizard: (renderWizardArguments: RenderWizardArguments) => {
return <NewVectorLayerEditor {...renderWizardArguments} />;
},
title: i18n.translate('xpack.maps.newVectorLayerWizard.title', {
defaultMessage: 'Create new layer',
}),
};

View file

@ -0,0 +1,27 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { getHttp } from '../../../kibana_services';
import { CreateDocSourceResp, INDEX_SOURCE_API_PATH } from '../../../../common';
export const createNewIndexAndPattern = async (indexName: string) => {
return await getHttp().fetch<CreateDocSourceResp>({
path: `/${INDEX_SOURCE_API_PATH}`,
method: 'POST',
body: JSON.stringify({
index: indexName,
// Initially set to static mappings
mappings: {
properties: {
coordinates: {
type: 'geo_shape',
},
},
},
}),
});
};

View file

@ -0,0 +1,8 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
export { newVectorLayerWizardConfig } from './config';

View file

@ -0,0 +1,161 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React, { Component, Fragment } from 'react';
import { EuiEmptyPrompt, EuiPanel, EuiCallOut } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { createNewIndexAndPattern } from './create_new_index_pattern';
import { RenderWizardArguments } from '../layer_wizard_registry';
import { VectorLayer } from '../vector_layer';
import { ESSearchSource } from '../../sources/es_search_source';
import { ADD_LAYER_STEP_ID } from '../../../connected_components/add_layer_panel/view';
import { getIndexNameFormComponent } from '../../../kibana_services';
interface State {
indexName: string;
indexNameError: string;
indexingTriggered: boolean;
createIndexError: string;
}
export class NewVectorLayerEditor extends Component<RenderWizardArguments, State> {
private _isMounted: boolean = false;
state: State = {
indexName: '',
indexNameError: '',
indexingTriggered: false,
createIndexError: '',
};
componentDidMount() {
this._isMounted = true;
}
componentWillUnmount() {
this._isMounted = false;
}
async componentDidUpdate() {
if (this.props.currentStepId === ADD_LAYER_STEP_ID && !this.state.indexingTriggered) {
this.setState({ indexingTriggered: true });
await this._createNewIndex();
}
}
_setCreateIndexError(errorMessage: string) {
if (!this._isMounted) {
return;
}
this.setState({
createIndexError: errorMessage,
});
}
_createNewIndex = async () => {
let indexPatternId: string | undefined;
try {
const response = await createNewIndexAndPattern(this.state.indexName);
indexPatternId = response.indexPatternId;
} catch (e) {
this._setCreateIndexError(e.message);
return;
}
if (!indexPatternId) {
this._setCreateIndexError(
i18n.translate('xpack.maps.layers.newVectorLayerWizard.createIndexError', {
defaultMessage: 'Could not create index with name {message}',
values: {
message: this.state.indexName,
},
})
);
return;
}
if (!this._isMounted) {
return;
}
// Creates empty layer
const sourceDescriptor = ESSearchSource.createDescriptor({
indexPatternId,
geoField: 'coordinates',
filterByMapBounds: false,
});
const layerDescriptor = VectorLayer.createDescriptor(
{ sourceDescriptor },
this.props.mapColors
);
this.props.previewLayers([layerDescriptor]);
this.props.advanceToNextStep();
};
_onIndexChange = (indexName: string, indexError?: string) => {
this.setState({
indexName,
indexNameError: indexError ? indexError : '',
});
if (indexName && !indexError) {
this.props.enableNextBtn();
} else {
this.props.disableNextBtn();
}
};
render() {
if (this.state.createIndexError) {
return (
<EuiCallOut
title={i18n.translate('xpack.maps.layers.newVectorLayerWizard.createIndexErrorTitle', {
defaultMessage: 'Sorry, could not create index pattern',
})}
color="danger"
iconType="alert"
>
<p>{this.state.createIndexError}</p>
</EuiCallOut>
);
}
const IndexNameForm = getIndexNameFormComponent();
return (
<EuiPanel>
<>
<EuiEmptyPrompt
title={
<h4>
{i18n.translate('xpack.maps.layers.newVectorLayerWizard.createNewLayer', {
defaultMessage: 'Create new layer',
})}
</h4>
}
body={
<Fragment>
<p>
{i18n.translate(
'xpack.maps.layers.newVectorLayerWizard.vectorEditorDescription',
{
defaultMessage: `Creates a new vector layer. This can be used to draw and store new shapes.`,
}
)}
</p>
</Fragment>
}
/>
<IndexNameForm
indexName={this.state.indexName}
indexNameError={this.state.indexNameError}
onIndexNameChange={this._onIndexChange}
onIndexNameValidationStart={() => {}}
onIndexNameValidationEnd={() => {}}
/>
</>
</EuiPanel>
);
}
}

View file

@ -21,7 +21,7 @@ import { FlyoutBody } from './flyout_body';
import { LayerDescriptor } from '../../../common/descriptor_types';
import { LayerWizard } from '../../classes/layers/layer_wizard_registry';
const ADD_LAYER_STEP_ID = 'ADD_LAYER_STEP_ID';
export const ADD_LAYER_STEP_ID = 'ADD_LAYER_STEP_ID';
const ADD_LAYER_STEP_LABEL = i18n.translate('xpack.maps.addLayerPanel.addLayer', {
defaultMessage: 'Add layer',
});

View file

@ -418,11 +418,11 @@ export class MBMap extends Component<Props, State> {
};
render() {
let drawControl;
let drawFilterControl;
let tooltipControl;
let scaleControl;
if (this.state.mbMap) {
drawControl = this.props.addFilters ? (
drawFilterControl = this.props.addFilters ? (
<DrawFilterControl mbMap={this.state.mbMap} addFilters={this.props.addFilters} />
) : null;
tooltipControl = !this.props.settings.disableTooltipControl ? (
@ -447,7 +447,7 @@ export class MBMap extends Component<Props, State> {
ref={this._setContainerRef}
data-test-subj="mapContainer"
>
{drawControl}
{drawFilterControl}
{scaleControl}
{tooltipControl}
</div>

View file

@ -0,0 +1,25 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React, { FunctionComponent } from 'react';
export const VectorCircleIcon: FunctionComponent = () => (
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="euiIcon"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M8 15C11.866 15 15 11.866 15 8C15 4.13401 11.866 1 8 1C4.13401 1 1 4.13401 1 8C1 11.866 4.13401 15 8 15ZM8 14C11.3137 14 14 11.3137 14 8C14 4.68629 11.3137 2 8 2C4.68629 2 2 4.68629 2 8C2 11.3137 4.68629 14 8 14Z"
/>
</svg>
);

View file

@ -0,0 +1,26 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React, { FunctionComponent } from 'react';
export const VectorLineIcon: FunctionComponent = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="none"
viewBox="0 0 16 16"
className="euiIcon"
>
<path d="M11.506 3.881l.707.707-7.594 7.594-.707-.707z" />
<path
fillRule="evenodd"
d="M5 11H1v4h4v-4zm-1 1H2v2h2v-2zM15 1h-4v4h4V1zm-1 1h-2v2h2V2z"
clipRule="evenodd"
/>
</svg>
);

View file

@ -0,0 +1,25 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React, { FunctionComponent } from 'react';
export const VectorSquareIcon: FunctionComponent = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="none"
viewBox="0 0 16 16"
className="euiIcon"
>
<path
fillRule="evenodd"
d="M1.5 2a.5.5 0 01.5-.5h12a.5.5 0 01.5.5v12a.5.5 0 01-.5.5H2a.5.5 0 01-.5-.5V2zm1 .5v11h11v-11h-11z"
clipRule="evenodd"
/>
</svg>
);

View file

@ -22,6 +22,9 @@ export function setStartServices(core: CoreStart, plugins: MapsPluginStartDepend
coreStart = core;
pluginsStart = plugins;
}
export const getIndexNameFormComponent = () => pluginsStart.fileUpload.IndexNameFormComponent;
export const getFileUploadComponent = () => pluginsStart.fileUpload.FileUploadComponent;
export const getIndexPatternService = () => pluginsStart.data.indexPatterns;
export const getAutocompleteService = () => pluginsStart.data.autocomplete;
export const getInspector = () => pluginsStart.inspector;
@ -55,7 +58,6 @@ let mapAppConfig: MapsConfigType;
export const setMapAppConfig = (config: MapsConfigType) => (mapAppConfig = config);
export const getMapAppConfig = () => mapAppConfig;
export const getEnabled = () => getMapAppConfig().enabled;
export const getShowMapsInspectorAdapter = () => getMapAppConfig().showMapsInspectorAdapter;
export const getPreserveDrawingBuffer = () => getMapAppConfig().preserveDrawingBuffer;

View file

@ -29,9 +29,10 @@ export async function createDocSource(
): Promise<CreateDocSourceResp> {
try {
await createIndex(index, mappings, asCurrentUser);
await indexPatternsService.createAndSave({ title: index }, true);
const { id: indexPatternId } = await indexPatternsService.createAndSave({ title: index }, true);
return {
indexPatternId,
success: true,
};
} catch (error) {

View file

@ -11,8 +11,8 @@ import { IRouter } from 'src/core/server';
import type { DataRequestHandlerContext } from 'src/plugins/data/server';
import {
INDEX_SOURCE_API_PATH,
GIS_API_PATH,
MAX_DRAWING_SIZE_BYTES,
INDEX_FEATURE_PATH,
} from '../../common/constants';
import { createDocSource } from './create_doc_source';
import { writeDataToIndex } from './index_data';
@ -70,7 +70,7 @@ export function initIndexingRoutes({
router.post(
{
path: `/${GIS_API_PATH}/feature`,
path: INDEX_FEATURE_PATH,
validate: {
body: schema.object({
index: schema.string(),

View file

@ -16,6 +16,7 @@ export const config: PluginConfigDescriptor<MapsXPackConfig> = {
exposeToBrowser: {
enabled: true,
showMapVisualizationTypes: true,
enableDrawingFeature: true,
showMapsInspectorAdapter: true,
preserveDrawingBuffer: true,
},