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

View file

@ -8,10 +8,10 @@
import { CoreStart, Plugin } from '../../../../src/core/public'; import { CoreStart, Plugin } from '../../../../src/core/public';
import { import {
FileUploadStartApi, FileUploadStartApi,
getFileUploadComponent, FileUploadComponent,
importerFactory, importerFactory,
hasImportPermission, hasImportPermission,
getIndexNameFormComponent, IndexNameFormComponent,
checkIndexExists, checkIndexExists,
getTimeFieldRange, getTimeFieldRange,
analyzeFile, analyzeFile,
@ -42,8 +42,8 @@ export class FileUploadPlugin
public start(core: CoreStart, plugins: FileUploadStartDependencies): FileUploadStartApi { public start(core: CoreStart, plugins: FileUploadStartDependencies): FileUploadStartApi {
setStartServices(core, plugins); setStartServices(core, plugins);
return { return {
getFileUploadComponent, FileUploadComponent,
getIndexNameFormComponent, IndexNameFormComponent,
importerFactory, importerFactory,
getMaxBytes, getMaxBytes,
getMaxBytesFormatted, 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 INDEX_SETTINGS_API_PATH = `${GIS_API_PATH}/indexSettings`;
export const FONTS_API_PATH = `${GIS_API_PATH}/fonts`; export const FONTS_API_PATH = `${GIS_API_PATH}/fonts`;
export const INDEX_SOURCE_API_PATH = `${GIS_API_PATH}/docSource`; 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 API_ROOT_PATH = `/${GIS_API_PATH}`;
export const MVT_GETTILE_API_PATH = 'mvt/getTile'; export const MVT_GETTILE_API_PATH = 'mvt/getTile';

View file

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

View file

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

View file

@ -11,13 +11,13 @@ import React, { Component } from 'react';
import { FeatureCollection } from 'geojson'; import { FeatureCollection } from 'geojson';
import { EuiPanel } from '@elastic/eui'; import { EuiPanel } from '@elastic/eui';
import { DEFAULT_MAX_RESULT_WINDOW, SCALING_TYPES } from '../../../../common/constants'; import { DEFAULT_MAX_RESULT_WINDOW, SCALING_TYPES } from '../../../../common/constants';
import { getFileUpload } from '../../../kibana_services';
import { GeoJsonFileSource } from '../../sources/geojson_file_source'; import { GeoJsonFileSource } from '../../sources/geojson_file_source';
import { VectorLayer } from '../../layers/vector_layer'; import { VectorLayer } from '../../layers/vector_layer';
import { createDefaultLayerDescriptor } from '../../sources/es_search_source'; import { createDefaultLayerDescriptor } from '../../sources/es_search_source';
import { RenderWizardArguments } from '../../layers/layer_wizard_registry'; 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 { ES_FIELD_TYPES } from '../../../../../../../src/plugins/data/public';
import { getFileUploadComponent } from '../../../kibana_services';
export enum UPLOAD_STEPS { export enum UPLOAD_STEPS {
CONFIGURE_UPLOAD = 'CONFIGURE_UPLOAD', CONFIGURE_UPLOAD = 'CONFIGURE_UPLOAD',
@ -34,7 +34,6 @@ enum INDEXING_STAGE {
interface State { interface State {
indexingStage: INDEXING_STAGE; indexingStage: INDEXING_STAGE;
fileUploadComponent: React.ComponentType<FileUploadComponentProps> | null;
results?: FileUploadGeoResults; results?: FileUploadGeoResults;
} }
@ -43,12 +42,10 @@ export class ClientFileCreateSourceEditor extends Component<RenderWizardArgument
state: State = { state: State = {
indexingStage: INDEXING_STAGE.CONFIGURE, indexingStage: INDEXING_STAGE.CONFIGURE,
fileUploadComponent: null,
}; };
componentDidMount() { componentDidMount() {
this._isMounted = true; this._isMounted = true;
this._loadFileUploadComponent();
} }
componentWillUnmount() { componentWillUnmount() {
@ -91,13 +88,6 @@ export class ClientFileCreateSourceEditor extends Component<RenderWizardArgument
this.props.advanceToNextStep(); this.props.advanceToNextStep();
}); });
async _loadFileUploadComponent() {
const fileUploadComponent = await getFileUpload().getFileUploadComponent();
if (this._isMounted) {
this.setState({ fileUploadComponent });
}
}
_onFileSelect = (geojsonFile: FeatureCollection, name: string, previewCoverage: number) => { _onFileSelect = (geojsonFile: FeatureCollection, name: string, previewCoverage: number) => {
if (!this._isMounted) { if (!this._isMounted) {
return; return;
@ -157,11 +147,8 @@ export class ClientFileCreateSourceEditor extends Component<RenderWizardArgument
}; };
render() { render() {
if (!this.state.fileUploadComponent) { const FileUpload = getFileUploadComponent();
return null;
}
const FileUpload = this.state.fileUploadComponent;
return ( return (
<EuiPanel> <EuiPanel>
<FileUpload <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 { ObservabilityLayerWizardConfig } from './solution_layers/observability';
import { SecurityLayerWizardConfig } from './solution_layers/security'; import { SecurityLayerWizardConfig } from './solution_layers/security';
import { choroplethLayerWizardConfig } from './choropleth_layer_wizard'; import { choroplethLayerWizardConfig } from './choropleth_layer_wizard';
import { newVectorLayerWizardConfig } from './new_vector_layer_wizard';
import { getMapAppConfig } from '../../kibana_services';
let registered = false; let registered = false;
export function registerLayerWizards() { export function registerLayerWizards() {
@ -39,6 +41,9 @@ export function registerLayerWizards() {
// Registration order determines display order // Registration order determines display order
registerLayerWizard(uploadLayerWizardConfig); registerLayerWizard(uploadLayerWizardConfig);
if (getMapAppConfig().enableDrawingFeature) {
registerLayerWizard(newVectorLayerWizardConfig);
}
registerLayerWizard(esDocumentsLayerWizardConfig); registerLayerWizard(esDocumentsLayerWizardConfig);
// @ts-ignore // @ts-ignore
registerLayerWizard(choroplethLayerWizardConfig); 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 { LayerDescriptor } from '../../../common/descriptor_types';
import { LayerWizard } from '../../classes/layers/layer_wizard_registry'; 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', { const ADD_LAYER_STEP_LABEL = i18n.translate('xpack.maps.addLayerPanel.addLayer', {
defaultMessage: 'Add layer', defaultMessage: 'Add layer',
}); });

View file

@ -418,11 +418,11 @@ export class MBMap extends Component<Props, State> {
}; };
render() { render() {
let drawControl; let drawFilterControl;
let tooltipControl; let tooltipControl;
let scaleControl; let scaleControl;
if (this.state.mbMap) { if (this.state.mbMap) {
drawControl = this.props.addFilters ? ( drawFilterControl = this.props.addFilters ? (
<DrawFilterControl mbMap={this.state.mbMap} addFilters={this.props.addFilters} /> <DrawFilterControl mbMap={this.state.mbMap} addFilters={this.props.addFilters} />
) : null; ) : null;
tooltipControl = !this.props.settings.disableTooltipControl ? ( tooltipControl = !this.props.settings.disableTooltipControl ? (
@ -447,7 +447,7 @@ export class MBMap extends Component<Props, State> {
ref={this._setContainerRef} ref={this._setContainerRef}
data-test-subj="mapContainer" data-test-subj="mapContainer"
> >
{drawControl} {drawFilterControl}
{scaleControl} {scaleControl}
{tooltipControl} {tooltipControl}
</div> </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; coreStart = core;
pluginsStart = plugins; pluginsStart = plugins;
} }
export const getIndexNameFormComponent = () => pluginsStart.fileUpload.IndexNameFormComponent;
export const getFileUploadComponent = () => pluginsStart.fileUpload.FileUploadComponent;
export const getIndexPatternService = () => pluginsStart.data.indexPatterns; export const getIndexPatternService = () => pluginsStart.data.indexPatterns;
export const getAutocompleteService = () => pluginsStart.data.autocomplete; export const getAutocompleteService = () => pluginsStart.data.autocomplete;
export const getInspector = () => pluginsStart.inspector; export const getInspector = () => pluginsStart.inspector;
@ -55,7 +58,6 @@ let mapAppConfig: MapsConfigType;
export const setMapAppConfig = (config: MapsConfigType) => (mapAppConfig = config); export const setMapAppConfig = (config: MapsConfigType) => (mapAppConfig = config);
export const getMapAppConfig = () => mapAppConfig; export const getMapAppConfig = () => mapAppConfig;
export const getEnabled = () => getMapAppConfig().enabled;
export const getShowMapsInspectorAdapter = () => getMapAppConfig().showMapsInspectorAdapter; export const getShowMapsInspectorAdapter = () => getMapAppConfig().showMapsInspectorAdapter;
export const getPreserveDrawingBuffer = () => getMapAppConfig().preserveDrawingBuffer; export const getPreserveDrawingBuffer = () => getMapAppConfig().preserveDrawingBuffer;

View file

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

View file

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

View file

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