mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
Convert file_upload components to typescript (#93814)
* Convert file_upload components to typescript * i18n cleanup * api doc updates * fix i18n files * tslint after merge Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
52787e9379
commit
7507d6417e
13 changed files with 329 additions and 330 deletions
|
@ -372,7 +372,7 @@
|
|||
"type": "Function",
|
||||
"label": "import",
|
||||
"signature": [
|
||||
"(id: string, index: string, pipelineId: string, setImportProgress: (progress: number) => void) => Promise<",
|
||||
"(id: string, index: string, pipelineId: string | undefined, setImportProgress: (progress: number) => void) => Promise<",
|
||||
{
|
||||
"pluginId": "fileUpload",
|
||||
"scope": "public",
|
||||
|
@ -413,9 +413,9 @@
|
|||
{
|
||||
"type": "string",
|
||||
"label": "pipelineId",
|
||||
"isRequired": true,
|
||||
"isRequired": false,
|
||||
"signature": [
|
||||
"string"
|
||||
"string | undefined"
|
||||
],
|
||||
"description": [],
|
||||
"source": {
|
||||
|
|
|
@ -8,23 +8,22 @@
|
|||
import React, { Component } from 'react';
|
||||
import { EuiFilePicker, EuiFormRow } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { MB } from '../../common';
|
||||
import { getMaxBytesFormatted } from '../get_max_bytes';
|
||||
import { validateFile } from '../importer';
|
||||
import { GeoJsonImporter, GeoJsonPreview, GEOJSON_FILE_TYPES } from '../importer/geojson_importer';
|
||||
import { MB } from '../../../common';
|
||||
import { getMaxBytesFormatted } from '../../get_max_bytes';
|
||||
import { validateFile } from '../../importer';
|
||||
import {
|
||||
GeoJsonImporter,
|
||||
GeoJsonPreview,
|
||||
GEOJSON_FILE_TYPES,
|
||||
} from '../../importer/geojson_importer';
|
||||
|
||||
export type OnFileSelectParameters = GeoJsonPreview & {
|
||||
indexName: string;
|
||||
importer: GeoJsonImporter;
|
||||
};
|
||||
|
||||
interface Props {
|
||||
onSelect: ({
|
||||
features,
|
||||
hasPoints,
|
||||
hasShapes,
|
||||
importer,
|
||||
indexName,
|
||||
previewCoverage,
|
||||
}: GeoJsonPreview & {
|
||||
indexName: string;
|
||||
importer: GeoJsonImporter;
|
||||
}) => void;
|
||||
onSelect: (onFileSelectParameters: OnFileSelectParameters) => void;
|
||||
onClear: () => void;
|
||||
}
|
||||
|
|
@ -0,0 +1,227 @@
|
|||
/*
|
||||
* 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, { ChangeEvent, Component } from 'react';
|
||||
import { EuiForm, EuiFormRow, EuiFieldText, EuiSelect, EuiCallOut, EuiSpacer } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { GeoJsonFilePicker, OnFileSelectParameters } from './geojson_file_picker';
|
||||
import { ES_FIELD_TYPES } from '../../../../../../src/plugins/data/public';
|
||||
import {
|
||||
getExistingIndexNames,
|
||||
getExistingIndexPatternNames,
|
||||
checkIndexPatternValid,
|
||||
// @ts-expect-error
|
||||
} from '../../util/indexing_service';
|
||||
|
||||
const GEO_FIELD_TYPE_OPTIONS = [
|
||||
{
|
||||
text: ES_FIELD_TYPES.GEO_POINT,
|
||||
value: ES_FIELD_TYPES.GEO_POINT,
|
||||
},
|
||||
{
|
||||
text: ES_FIELD_TYPES.GEO_SHAPE,
|
||||
value: ES_FIELD_TYPES.GEO_SHAPE,
|
||||
},
|
||||
];
|
||||
|
||||
interface Props {
|
||||
geoFieldType: ES_FIELD_TYPES.GEO_POINT | ES_FIELD_TYPES.GEO_SHAPE;
|
||||
indexName: string;
|
||||
indexNameError?: string;
|
||||
onFileClear: () => void;
|
||||
onFileSelect: (onFileSelectParameters: OnFileSelectParameters) => void;
|
||||
onGeoFieldTypeSelect: (geoFieldType: ES_FIELD_TYPES.GEO_POINT | ES_FIELD_TYPES.GEO_SHAPE) => void;
|
||||
onIndexNameChange: (name: string, error?: string) => void;
|
||||
}
|
||||
|
||||
interface State {
|
||||
hasFile: boolean;
|
||||
isPointsOnly: boolean;
|
||||
indexNames: string[];
|
||||
}
|
||||
|
||||
export class GeoJsonUploadForm extends Component<Props, State> {
|
||||
private _isMounted = false;
|
||||
|
||||
state: State = {
|
||||
hasFile: false,
|
||||
isPointsOnly: false,
|
||||
indexNames: [],
|
||||
};
|
||||
|
||||
async componentDidMount() {
|
||||
this._isMounted = true;
|
||||
this._loadIndexNames();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this._isMounted = false;
|
||||
}
|
||||
|
||||
_loadIndexNames = async () => {
|
||||
const indexNameList = await getExistingIndexNames();
|
||||
const indexPatternList = await getExistingIndexPatternNames();
|
||||
if (this._isMounted) {
|
||||
this.setState({
|
||||
indexNames: [...indexNameList, ...indexPatternList],
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
_onFileSelect = (onFileSelectParameters: OnFileSelectParameters) => {
|
||||
this.setState({
|
||||
hasFile: true,
|
||||
isPointsOnly: onFileSelectParameters.hasPoints && !onFileSelectParameters.hasShapes,
|
||||
});
|
||||
|
||||
this.props.onFileSelect(onFileSelectParameters);
|
||||
|
||||
this._onIndexNameChange(onFileSelectParameters.indexName);
|
||||
|
||||
const geoFieldType =
|
||||
onFileSelectParameters.hasPoints && !onFileSelectParameters.hasShapes
|
||||
? ES_FIELD_TYPES.GEO_POINT
|
||||
: ES_FIELD_TYPES.GEO_SHAPE;
|
||||
this.props.onGeoFieldTypeSelect(geoFieldType);
|
||||
};
|
||||
|
||||
_onFileClear = () => {
|
||||
this.setState({
|
||||
hasFile: false,
|
||||
isPointsOnly: false,
|
||||
});
|
||||
|
||||
this.props.onFileClear();
|
||||
|
||||
this._onIndexNameChange('');
|
||||
};
|
||||
|
||||
_onGeoFieldTypeSelect = (event: ChangeEvent<HTMLSelectElement>) => {
|
||||
return this.props.onGeoFieldTypeSelect(
|
||||
event.target.value as ES_FIELD_TYPES.GEO_POINT | ES_FIELD_TYPES.GEO_SHAPE
|
||||
);
|
||||
};
|
||||
|
||||
_onIndexNameChange = (name: string) => {
|
||||
let error: string | undefined;
|
||||
if (this.state.indexNames.includes(name)) {
|
||||
error = i18n.translate('xpack.fileUpload.indexSettings.indexNameAlreadyExistsErrorMessage', {
|
||||
defaultMessage: 'Index name already exists.',
|
||||
});
|
||||
} else if (!checkIndexPatternValid(name)) {
|
||||
error = i18n.translate(
|
||||
'xpack.fileUpload.indexSettings.indexNameContainsIllegalCharactersErrorMessage',
|
||||
{
|
||||
defaultMessage: 'Index name contains illegal characters.',
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
this.props.onIndexNameChange(name, error);
|
||||
};
|
||||
|
||||
_onIndexNameChangeEvent = (event: ChangeEvent<HTMLInputElement>) => {
|
||||
this._onIndexNameChange(event.target.value);
|
||||
};
|
||||
|
||||
_renderGeoFieldTypeSelect() {
|
||||
return this.state.hasFile && this.state.isPointsOnly ? (
|
||||
<EuiFormRow
|
||||
label={i18n.translate('xpack.fileUpload.indexSettings.enterIndexTypeLabel', {
|
||||
defaultMessage: 'Index type',
|
||||
})}
|
||||
>
|
||||
<EuiSelect
|
||||
data-test-subj="fileImportIndexSelect"
|
||||
options={GEO_FIELD_TYPE_OPTIONS}
|
||||
value={this.props.geoFieldType}
|
||||
onChange={this._onGeoFieldTypeSelect}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
) : null;
|
||||
}
|
||||
|
||||
_renderIndexNameInput() {
|
||||
const isInvalid = this.props.indexNameError !== undefined;
|
||||
return this.state.hasFile ? (
|
||||
<>
|
||||
<EuiFormRow
|
||||
label={i18n.translate('xpack.fileUpload.indexSettings.enterIndexNameLabel', {
|
||||
defaultMessage: 'Index name',
|
||||
})}
|
||||
isInvalid={isInvalid}
|
||||
error={isInvalid ? [this.props.indexNameError] : []}
|
||||
>
|
||||
<EuiFieldText
|
||||
data-test-subj="fileUploadIndexNameInput"
|
||||
value={this.props.indexName}
|
||||
onChange={this._onIndexNameChangeEvent}
|
||||
isInvalid={isInvalid}
|
||||
aria-label={i18n.translate('xpack.fileUpload.indexNameReqField', {
|
||||
defaultMessage: 'Index name, required field',
|
||||
})}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiSpacer size="m" />
|
||||
<EuiCallOut
|
||||
title={i18n.translate('xpack.fileUpload.indexSettings.indexNameGuidelines', {
|
||||
defaultMessage: 'Index name guidelines',
|
||||
})}
|
||||
size="s"
|
||||
>
|
||||
<ul style={{ marginBottom: 0 }}>
|
||||
<li>
|
||||
{i18n.translate('xpack.fileUpload.indexSettings.guidelines.mustBeNewIndex', {
|
||||
defaultMessage: 'Must be a new index',
|
||||
})}
|
||||
</li>
|
||||
<li>
|
||||
{i18n.translate('xpack.fileUpload.indexSettings.guidelines.lowercaseOnly', {
|
||||
defaultMessage: 'Lowercase only',
|
||||
})}
|
||||
</li>
|
||||
<li>
|
||||
{i18n.translate('xpack.fileUpload.indexSettings.guidelines.cannotInclude', {
|
||||
defaultMessage:
|
||||
'Cannot include \\\\, /, *, ?, ", <, >, |, \
|
||||
" " (space character), , (comma), #',
|
||||
})}
|
||||
</li>
|
||||
<li>
|
||||
{i18n.translate('xpack.fileUpload.indexSettings.guidelines.cannotStartWith', {
|
||||
defaultMessage: 'Cannot start with -, _, +',
|
||||
})}
|
||||
</li>
|
||||
<li>
|
||||
{i18n.translate('xpack.fileUpload.indexSettings.guidelines.cannotBe', {
|
||||
defaultMessage: 'Cannot be . or ..',
|
||||
})}
|
||||
</li>
|
||||
<li>
|
||||
{i18n.translate('xpack.fileUpload.indexSettings.guidelines.length', {
|
||||
defaultMessage:
|
||||
'Cannot be longer than 255 bytes (note it is bytes, \
|
||||
so multi-byte characters will count towards the 255 \
|
||||
limit faster)',
|
||||
})}
|
||||
</li>
|
||||
</ul>
|
||||
</EuiCallOut>
|
||||
</>
|
||||
) : null;
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<EuiForm>
|
||||
<GeoJsonFilePicker onSelect={this._onFileSelect} onClear={this._onFileClear} />
|
||||
{this._renderGeoFieldTypeSelect()}
|
||||
{this._renderIndexNameInput()}
|
||||
</EuiForm>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* 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 { GeoJsonUploadForm } from './geojson_upload_form';
|
||||
export { OnFileSelectParameters } from './geojson_file_picker';
|
|
@ -20,14 +20,14 @@ import {
|
|||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { CodeEditor, KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public';
|
||||
import { getHttp, getUiSettings } from '../kibana_services';
|
||||
import { ImportResponse } from '../../common';
|
||||
import { ImportResults } from '../importer';
|
||||
|
||||
const services = {
|
||||
uiSettings: getUiSettings(),
|
||||
};
|
||||
|
||||
interface Props {
|
||||
importResp?: ImportResponse;
|
||||
importResults?: ImportResults;
|
||||
indexPatternResp?: object;
|
||||
}
|
||||
|
||||
|
@ -90,7 +90,7 @@ export class ImportCompleteView extends Component<Props, {}> {
|
|||
}
|
||||
|
||||
_getStatusMsg() {
|
||||
if (!this.props.importResp || !this.props.importResp.success) {
|
||||
if (!this.props.importResults || !this.props.importResults.success) {
|
||||
return i18n.translate('xpack.fileUpload.uploadFailureMsg', {
|
||||
defaultMessage: 'File upload failed.',
|
||||
});
|
||||
|
@ -99,15 +99,15 @@ export class ImportCompleteView extends Component<Props, {}> {
|
|||
const successMsg = i18n.translate('xpack.fileUpload.uploadSuccessMsg', {
|
||||
defaultMessage: 'File upload complete: indexed {numFeatures} features.',
|
||||
values: {
|
||||
numFeatures: this.props.importResp.docCount,
|
||||
numFeatures: this.props.importResults.docCount,
|
||||
},
|
||||
});
|
||||
|
||||
const failedFeaturesMsg = this.props.importResp.failures.length
|
||||
const failedFeaturesMsg = this.props.importResults.failures?.length
|
||||
? i18n.translate('xpack.fileUpload.failedFeaturesMsg', {
|
||||
defaultMessage: 'Unable to index {numFailures} features.',
|
||||
values: {
|
||||
numFailures: this.props.importResp.failures.length,
|
||||
numFailures: this.props.importResults.failures.length,
|
||||
},
|
||||
})
|
||||
: '';
|
||||
|
@ -122,7 +122,7 @@ export class ImportCompleteView extends Component<Props, {}> {
|
|||
<p>{this._getStatusMsg()}</p>
|
||||
</EuiText>
|
||||
{this._renderCodeEditor(
|
||||
this.props.importResp,
|
||||
this.props.importResults,
|
||||
i18n.translate('xpack.fileUpload.jsonImport.indexingResponse', {
|
||||
defaultMessage: 'Import response',
|
||||
}),
|
||||
|
|
|
@ -1,201 +0,0 @@
|
|||
/*
|
||||
* 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, { Fragment, Component } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { EuiFormRow, EuiFieldText, EuiSelect, EuiCallOut, EuiSpacer } from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import {
|
||||
getExistingIndexNames,
|
||||
getExistingIndexPatternNames,
|
||||
checkIndexPatternValid,
|
||||
} from '../util/indexing_service';
|
||||
|
||||
export class IndexSettings extends Component {
|
||||
state = {
|
||||
indexNameError: '',
|
||||
indexDisabled: true,
|
||||
indexName: '',
|
||||
indexNameList: [],
|
||||
indexPatternList: [],
|
||||
};
|
||||
|
||||
async componentDidMount() {
|
||||
this._isMounted = true;
|
||||
this.loadExistingIndexData();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this._isMounted = false;
|
||||
}
|
||||
|
||||
loadExistingIndexData = async () => {
|
||||
const indexNameList = await getExistingIndexNames();
|
||||
const indexPatternList = await getExistingIndexPatternNames();
|
||||
if (this._isMounted) {
|
||||
this.setState({
|
||||
indexNameList,
|
||||
indexPatternList,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
const { indexNameError, indexName } = this.state;
|
||||
if (prevState.indexNameError !== indexNameError) {
|
||||
this.props.setHasIndexErrors(!!indexNameError);
|
||||
}
|
||||
const { disabled, indexTypes } = this.props;
|
||||
const indexDisabled = disabled || !indexTypes || !indexTypes.length;
|
||||
if (indexDisabled !== this.state.indexDisabled) {
|
||||
this.setState({ indexDisabled });
|
||||
}
|
||||
if (this.props.indexName !== indexName) {
|
||||
this._setIndexName(this.props.indexName);
|
||||
}
|
||||
}
|
||||
|
||||
_setIndexName = async (name) => {
|
||||
const errorMessage = await this._isIndexNameAndPatternValid(name);
|
||||
return this.setState({
|
||||
indexName: name,
|
||||
indexNameError: errorMessage,
|
||||
});
|
||||
};
|
||||
|
||||
_onIndexChange = async ({ target }) => {
|
||||
const name = target.value;
|
||||
await this._setIndexName(name);
|
||||
this.props.setIndexName(name);
|
||||
};
|
||||
|
||||
_isIndexNameAndPatternValid = async (name) => {
|
||||
const { indexNameList, indexPatternList } = this.state;
|
||||
const nameAlreadyInUse = [...indexNameList, ...indexPatternList].includes(name);
|
||||
if (nameAlreadyInUse) {
|
||||
return (
|
||||
<FormattedMessage
|
||||
id="xpack.fileUpload.indexSettings.indexNameAlreadyExistsErrorMessage"
|
||||
defaultMessage="Index name or pattern already exists."
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const indexPatternValid = checkIndexPatternValid(name);
|
||||
if (!indexPatternValid) {
|
||||
return (
|
||||
<FormattedMessage
|
||||
id="xpack.fileUpload.indexSettings.indexNameContainsIllegalCharactersErrorMessage"
|
||||
defaultMessage="Index name contains illegal characters."
|
||||
/>
|
||||
);
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
render() {
|
||||
const { setSelectedIndexType, indexTypes } = this.props;
|
||||
const { indexNameError, indexDisabled, indexName } = this.state;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<EuiFormRow
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="xpack.fileUpload.indexSettings.enterIndexTypeLabel"
|
||||
defaultMessage="Index type"
|
||||
/>
|
||||
}
|
||||
>
|
||||
<EuiSelect
|
||||
data-test-subj="fileImportIndexSelect"
|
||||
disabled={indexDisabled}
|
||||
options={indexTypes.map((indexType) => ({
|
||||
text: indexType,
|
||||
value: indexType,
|
||||
}))}
|
||||
value={this.props.selectedIndexType}
|
||||
onChange={({ target }) => setSelectedIndexType(target.value)}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
<EuiFormRow
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="xpack.fileUpload.indexSettings.enterIndexNameLabel"
|
||||
defaultMessage="Index name"
|
||||
/>
|
||||
}
|
||||
isInvalid={indexNameError !== ''}
|
||||
error={[indexNameError]}
|
||||
>
|
||||
<EuiFieldText
|
||||
data-test-subj="fileUploadIndexNameInput"
|
||||
disabled={indexDisabled}
|
||||
placeholder={i18n.translate('xpack.fileUpload.enterIndexName', {
|
||||
defaultMessage: 'Enter Index Name',
|
||||
})}
|
||||
value={indexName}
|
||||
onChange={this._onIndexChange}
|
||||
isInvalid={indexNameError !== ''}
|
||||
aria-label={i18n.translate('xpack.fileUpload.indexNameReqField', {
|
||||
defaultMessage: 'Index name, required field',
|
||||
})}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
{indexDisabled ? null : (
|
||||
<Fragment>
|
||||
<EuiSpacer size="m" />
|
||||
<EuiCallOut
|
||||
title={i18n.translate('xpack.fileUpload.indexSettings.indexNameGuidelines', {
|
||||
defaultMessage: 'Index name guidelines',
|
||||
})}
|
||||
size="s"
|
||||
>
|
||||
<ul style={{ marginBottom: 0 }}>
|
||||
<li>
|
||||
{i18n.translate('xpack.fileUpload.indexSettings.guidelines.mustBeNewIndex', {
|
||||
defaultMessage: 'Must be a new index',
|
||||
})}
|
||||
</li>
|
||||
<li>
|
||||
{i18n.translate('xpack.fileUpload.indexSettings.guidelines.lowercaseOnly', {
|
||||
defaultMessage: 'Lowercase only',
|
||||
})}
|
||||
</li>
|
||||
<li>
|
||||
{i18n.translate('xpack.fileUpload.indexSettings.guidelines.cannotInclude', {
|
||||
defaultMessage:
|
||||
'Cannot include \\\\, /, *, ?, ", <, >, |, \
|
||||
" " (space character), , (comma), #',
|
||||
})}
|
||||
</li>
|
||||
<li>
|
||||
{i18n.translate('xpack.fileUpload.indexSettings.guidelines.cannotStartWith', {
|
||||
defaultMessage: 'Cannot start with -, _, +',
|
||||
})}
|
||||
</li>
|
||||
<li>
|
||||
{i18n.translate('xpack.fileUpload.indexSettings.guidelines.cannotBe', {
|
||||
defaultMessage: 'Cannot be . or ..',
|
||||
})}
|
||||
</li>
|
||||
<li>
|
||||
{i18n.translate('xpack.fileUpload.indexSettings.guidelines.length', {
|
||||
defaultMessage:
|
||||
'Cannot be longer than 255 bytes (note it is bytes, \
|
||||
so multi-byte characters will count towards the 255 \
|
||||
limit faster)',
|
||||
})}
|
||||
</li>
|
||||
</ul>
|
||||
</EuiCallOut>
|
||||
</Fragment>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -7,41 +7,48 @@
|
|||
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { EuiForm, EuiProgress, EuiText } from '@elastic/eui';
|
||||
import PropTypes from 'prop-types';
|
||||
import { IndexSettings } from './index_settings';
|
||||
import { EuiProgress, EuiText } from '@elastic/eui';
|
||||
import { getIndexPatternService } from '../kibana_services';
|
||||
import { GeoJsonFilePicker } from './geojson_file_picker';
|
||||
import { GeoJsonUploadForm, OnFileSelectParameters } from './geojson_upload_form';
|
||||
import { ImportCompleteView } from './import_complete_view';
|
||||
import { ES_FIELD_TYPES } from '../../../../../src/plugins/data/public';
|
||||
import { FileUploadComponentProps } from '../lazy_load_bundle';
|
||||
import { ImportResults } from '../importer';
|
||||
import { GeoJsonImporter } from '../importer/geojson_importer';
|
||||
import { IngestPipeline, Settings } from '../../common';
|
||||
|
||||
const PHASE = {
|
||||
CONFIGURE: 'CONFIGURE',
|
||||
IMPORT: 'IMPORT',
|
||||
COMPLETE: 'COMPLETE',
|
||||
};
|
||||
enum PHASE {
|
||||
CONFIGURE = 'CONFIGURE',
|
||||
IMPORT = 'IMPORT',
|
||||
COMPLETE = 'COMPLETE',
|
||||
}
|
||||
|
||||
function getWritingToIndexMsg(progress) {
|
||||
function getWritingToIndexMsg(progress: number) {
|
||||
return i18n.translate('xpack.fileUpload.jsonUploadAndParse.writingToIndex', {
|
||||
defaultMessage: 'Writing to index: {progress}% complete',
|
||||
values: { progress },
|
||||
});
|
||||
}
|
||||
|
||||
export class JsonUploadAndParse extends Component {
|
||||
state = {
|
||||
// Index state
|
||||
indexTypes: [],
|
||||
selectedIndexType: '',
|
||||
indexName: '',
|
||||
hasIndexErrors: false,
|
||||
isIndexReady: false,
|
||||
interface State {
|
||||
geoFieldType: ES_FIELD_TYPES.GEO_POINT | ES_FIELD_TYPES.GEO_SHAPE;
|
||||
importStatus: string;
|
||||
importResults?: ImportResults;
|
||||
indexName: string;
|
||||
indexNameError?: string;
|
||||
indexPatternResp?: object;
|
||||
phase: PHASE;
|
||||
}
|
||||
|
||||
// Progress-tracking state
|
||||
export class JsonUploadAndParse extends Component<FileUploadComponentProps, State> {
|
||||
private _geojsonImporter?: GeoJsonImporter;
|
||||
private _isMounted = false;
|
||||
|
||||
state: State = {
|
||||
geoFieldType: ES_FIELD_TYPES.GEO_SHAPE,
|
||||
importStatus: '',
|
||||
indexName: '',
|
||||
phase: PHASE.CONFIGURE,
|
||||
importResp: undefined,
|
||||
indexPatternResp: undefined,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
|
@ -52,45 +59,35 @@ export class JsonUploadAndParse extends Component {
|
|||
this._isMounted = false;
|
||||
if (this._geojsonImporter) {
|
||||
this._geojsonImporter.destroy();
|
||||
this._geojsonImporter = null;
|
||||
this._geojsonImporter = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this._setIndexReady();
|
||||
if (this.props.isIndexingTriggered && this.state.phase === PHASE.CONFIGURE) {
|
||||
this._import();
|
||||
}
|
||||
}
|
||||
|
||||
_setIndexReady = () => {
|
||||
const isIndexReady =
|
||||
this._geojsonImporter !== undefined &&
|
||||
!!this.state.selectedIndexType &&
|
||||
!!this.state.indexName &&
|
||||
!this.state.hasIndexErrors &&
|
||||
this.state.phase === PHASE.CONFIGURE;
|
||||
if (isIndexReady !== this.state.isIndexReady) {
|
||||
this.setState({ isIndexReady });
|
||||
this.props.onIndexReady(isIndexReady);
|
||||
}
|
||||
};
|
||||
|
||||
_import = async () => {
|
||||
if (!this._geojsonImporter) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// create index
|
||||
//
|
||||
const settings = {
|
||||
const settings = ({
|
||||
number_of_shards: 1,
|
||||
};
|
||||
} as unknown) as Settings;
|
||||
const mappings = {
|
||||
properties: {
|
||||
coordinates: {
|
||||
type: this.state.selectedIndexType,
|
||||
type: this.state.geoFieldType,
|
||||
},
|
||||
},
|
||||
};
|
||||
const ingestPipeline = {};
|
||||
const ingestPipeline = ({} as unknown) as IngestPipeline;
|
||||
this.setState({
|
||||
importStatus: i18n.translate('xpack.fileUpload.jsonUploadAndParse.dataIndexingStarted', {
|
||||
defaultMessage: 'Creating index: {indexName}',
|
||||
|
@ -98,7 +95,7 @@ export class JsonUploadAndParse extends Component {
|
|||
}),
|
||||
phase: PHASE.IMPORT,
|
||||
});
|
||||
this._geojsonImporter.setGeoFieldType(this.state.selectedIndexType);
|
||||
this._geojsonImporter.setGeoFieldType(this.state.geoFieldType);
|
||||
const initializeImportResp = await this._geojsonImporter.initializeImport(
|
||||
this.state.indexName,
|
||||
settings,
|
||||
|
@ -122,7 +119,7 @@ export class JsonUploadAndParse extends Component {
|
|||
this.setState({
|
||||
importStatus: getWritingToIndexMsg(0),
|
||||
});
|
||||
const importResp = await this._geojsonImporter.import(
|
||||
const importResults = await this._geojsonImporter.import(
|
||||
initializeImportResp.id,
|
||||
this.state.indexName,
|
||||
initializeImportResp.pipelineId,
|
||||
|
@ -138,9 +135,9 @@ export class JsonUploadAndParse extends Component {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!importResp.success) {
|
||||
if (!importResults.success) {
|
||||
this.setState({
|
||||
importResp,
|
||||
importResults,
|
||||
importStatus: i18n.translate('xpack.fileUpload.jsonUploadAndParse.dataIndexingError', {
|
||||
defaultMessage: 'Data indexing error',
|
||||
}),
|
||||
|
@ -154,7 +151,7 @@ export class JsonUploadAndParse extends Component {
|
|||
// create index pattern
|
||||
//
|
||||
this.setState({
|
||||
importResp,
|
||||
importResults,
|
||||
importStatus: i18n.translate('xpack.fileUpload.jsonUploadAndParse.creatingIndexPattern', {
|
||||
defaultMessage: 'Creating index pattern: {indexName}',
|
||||
values: { indexName: this.state.indexName },
|
||||
|
@ -197,35 +194,14 @@ export class JsonUploadAndParse extends Component {
|
|||
importStatus: '',
|
||||
});
|
||||
this.props.onIndexingComplete({
|
||||
indexDataResp: importResp,
|
||||
indexDataResp: importResults,
|
||||
indexPattern,
|
||||
});
|
||||
};
|
||||
|
||||
_onFileSelect = ({ features, hasPoints, hasShapes, importer, indexName, previewCoverage }) => {
|
||||
_onFileSelect = ({ features, importer, indexName, previewCoverage }: OnFileSelectParameters) => {
|
||||
this._geojsonImporter = importer;
|
||||
|
||||
const geoFieldTypes = hasPoints
|
||||
? [ES_FIELD_TYPES.GEO_POINT, ES_FIELD_TYPES.GEO_SHAPE]
|
||||
: [ES_FIELD_TYPES.GEO_SHAPE];
|
||||
|
||||
const newState = {
|
||||
indexTypes: geoFieldTypes,
|
||||
indexName,
|
||||
};
|
||||
if (!this.state.selectedIndexType) {
|
||||
// auto select index type
|
||||
newState.selectedIndexType =
|
||||
hasPoints && !hasShapes ? ES_FIELD_TYPES.GEO_POINT : ES_FIELD_TYPES.GEO_SHAPE;
|
||||
} else if (
|
||||
this.state.selectedIndexType &&
|
||||
!geoFieldTypes.includes(this.state.selectedIndexType)
|
||||
) {
|
||||
// unselected indexType if selected type is not longer an option
|
||||
newState.selectedIndexType = '';
|
||||
}
|
||||
this.setState(newState);
|
||||
|
||||
this.props.onFileUpload(
|
||||
{
|
||||
type: 'FeatureCollection',
|
||||
|
@ -243,12 +219,20 @@ export class JsonUploadAndParse extends Component {
|
|||
}
|
||||
|
||||
this.props.onFileRemove();
|
||||
};
|
||||
|
||||
_onGeoFieldTypeSelect = (geoFieldType: ES_FIELD_TYPES.GEO_POINT | ES_FIELD_TYPES.GEO_SHAPE) => {
|
||||
this.setState({ geoFieldType });
|
||||
};
|
||||
|
||||
_onIndexNameChange = (name: string, error?: string) => {
|
||||
this.setState({
|
||||
indexTypes: [],
|
||||
selectedIndexType: '',
|
||||
indexName: '',
|
||||
indexName: name,
|
||||
indexNameError: error,
|
||||
});
|
||||
|
||||
const isReadyToImport = !!name && error === undefined;
|
||||
this.props.onIndexReady(isReadyToImport);
|
||||
};
|
||||
|
||||
render() {
|
||||
|
@ -266,38 +250,22 @@ export class JsonUploadAndParse extends Component {
|
|||
if (this.state.phase === PHASE.COMPLETE) {
|
||||
return (
|
||||
<ImportCompleteView
|
||||
importResp={this.state.importResp}
|
||||
importResults={this.state.importResults}
|
||||
indexPatternResp={this.state.indexPatternResp}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<EuiForm>
|
||||
<GeoJsonFilePicker onSelect={this._onFileSelect} onClear={this._onFileClear} />
|
||||
<IndexSettings
|
||||
disabled={this._geojsonImporter === undefined}
|
||||
indexName={this.state.indexName}
|
||||
setIndexName={(indexName) => this.setState({ indexName })}
|
||||
indexTypes={this.state.indexTypes}
|
||||
selectedIndexType={this.state.selectedIndexType}
|
||||
setSelectedIndexType={(selectedIndexType) => this.setState({ selectedIndexType })}
|
||||
setHasIndexErrors={(hasIndexErrors) => this.setState({ hasIndexErrors })}
|
||||
/>
|
||||
</EuiForm>
|
||||
<GeoJsonUploadForm
|
||||
geoFieldType={this.state.geoFieldType}
|
||||
indexName={this.state.indexName}
|
||||
indexNameError={this.state.indexNameError}
|
||||
onFileClear={this._onFileClear}
|
||||
onFileSelect={this._onFileSelect}
|
||||
onGeoFieldTypeSelect={this._onGeoFieldTypeSelect}
|
||||
onIndexNameChange={this._onIndexNameChange}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
JsonUploadAndParse.defaultProps = {
|
||||
isIndexingTriggered: false,
|
||||
};
|
||||
|
||||
JsonUploadAndParse.propTypes = {
|
||||
isIndexingTriggered: PropTypes.bool,
|
||||
onIndexReadyStatusChange: PropTypes.func,
|
||||
onIndexingComplete: PropTypes.func,
|
||||
onIndexingError: PropTypes.func,
|
||||
onFileUpload: PropTypes.func,
|
||||
onFileRemove: PropTypes.func,
|
||||
};
|
|
@ -77,7 +77,7 @@ export class GeoJsonImporter extends Importer {
|
|||
public async import(
|
||||
id: string,
|
||||
index: string,
|
||||
pipelineId: string,
|
||||
pipelineId: string | undefined,
|
||||
setImportProgress: (progress: number) => void
|
||||
): Promise<ImportResults> {
|
||||
if (!id || !index) {
|
||||
|
@ -163,7 +163,7 @@ export class GeoJsonImporter extends Importer {
|
|||
private async _importBlock(
|
||||
id: string,
|
||||
index: string,
|
||||
pipelineId: string,
|
||||
pipelineId: string | undefined,
|
||||
chunks: ImportDoc[][],
|
||||
blockSizeInBytes: number,
|
||||
setImportProgress: (progress: number) => void
|
||||
|
|
|
@ -85,7 +85,7 @@ export abstract class Importer implements IImporter {
|
|||
public async import(
|
||||
id: string,
|
||||
index: string,
|
||||
pipelineId: string,
|
||||
pipelineId: string | undefined,
|
||||
setImportProgress: (progress: number) => void
|
||||
): Promise<ImportResults> {
|
||||
if (!id || !index) {
|
||||
|
|
|
@ -51,7 +51,7 @@ export interface IImporter {
|
|||
import(
|
||||
id: string,
|
||||
index: string,
|
||||
pipelineId: string,
|
||||
pipelineId: string | undefined,
|
||||
setImportProgress: (progress: number) => void
|
||||
): Promise<ImportResults>;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,5 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
// @ts-expect-error
|
||||
export { JsonUploadAndParse } from '../../components/json_upload_and_parse';
|
||||
export { importerFactory } from '../../importer';
|
||||
|
|
|
@ -8194,7 +8194,6 @@
|
|||
"xpack.features.ossFeatures.visualizeShortUrlSubFeatureName": "短い URL",
|
||||
"xpack.features.savedObjectsManagementFeatureName": "保存されたオブジェクトの管理",
|
||||
"xpack.features.visualizeFeatureName": "Visualizeライブラリ",
|
||||
"xpack.fileUpload.enterIndexName": "インデックス名を入力",
|
||||
"xpack.fileUpload.httpService.fetchError": "フェッチ実行エラー:{error}",
|
||||
"xpack.fileUpload.httpService.noUrl": "URLが指定されていません",
|
||||
"xpack.fileUpload.indexNameReqField": "インデックス名、必須フィールド",
|
||||
|
|
|
@ -8264,7 +8264,6 @@
|
|||
"xpack.features.ossFeatures.visualizeShortUrlSubFeatureName": "短 URL",
|
||||
"xpack.features.savedObjectsManagementFeatureName": "已保存对象管理",
|
||||
"xpack.features.visualizeFeatureName": "Visualize 库",
|
||||
"xpack.fileUpload.enterIndexName": "输入索引名称",
|
||||
"xpack.fileUpload.httpService.fetchError": "执行提取时出错:{error}",
|
||||
"xpack.fileUpload.httpService.noUrl": "未提供 URL",
|
||||
"xpack.fileUpload.indexNameReqField": "索引名称,必填字段",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue