/* * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 */ import './vector_upload_options.scss'; import React, { useState } from 'react'; import path from 'path'; import { EuiButton, EuiFilePicker, EuiFlexItem, EuiFlexGroup, EuiText, EuiSpacer, EuiCard, EuiFieldText, EuiTextColor, EuiFormRow, EuiCodeBlock, } from '@elastic/eui'; import { getIndex, postGeojson } from '../services'; import { ShowErrorModal } from './show_error_modal'; import { ALLOWED_FILE_EXTENSIONS, MAX_FILE_PAYLOAD_SIZE, MAX_FILE_PAYLOAD_SIZE_IN_MB, } from '../../common'; import { toMountPoint, useOpenSearchDashboards, } from '../../../../src/plugins/opensearch_dashboards_react/public'; import { RegionMapOptionsProps } from '../../../../src/plugins/region_map/public'; const VectorUploadOptions = (props: RegionMapOptionsProps) => { const opensearchDashboards = useOpenSearchDashboards(); const notifications = opensearchDashboards.services.notifications; const http = opensearchDashboards.services.http; const INDEX_NAME_SUFFIX = '-map'; const INDEX_NAME_UPPERCASE_CHECK = /[A-Z]+/; const INDEX_NAME_SPECIAL_CHARACTERS_CHECK = /[`!@#$%^&*()\=\[\]{};':"\\|,.<>\/?~]/; const INDEX_NAME_NOT_BEGINS_WITH_CHECK = /^[-+_.]/; const INDEX_NAME_BEGINS_WITH_CHECK = /^[a-z]/; const INDEX_NAME_NOT_ENDS_WITH_CHECK = /.*-map$/; const MAX_LENGTH_OF_INDEX_NAME = 250; const GEO_SHAPE_TYPE = 'geo_shape'; const [value, setValue] = useState(''); const [isLoading, setLoading] = useState(false); const [fileContent, setFileContent] = useState(); const onTextChange = (e) => { setValue(e.target.value); }; const onChange = (files) => { if (files[0]) { validateGeojsonFileFormat(files); validateFileSize(files); setFileContent(files); } }; const validateGeojsonFileFormat = (files) => { const uploadedFileExtension = path.extname(files[0].name); if (ALLOWED_FILE_EXTENSIONS.includes(uploadedFileExtension.toLowerCase())) { return true; } else { notifications.toasts.addDanger( 'Error. File format is incorrect. It should be either json or geojson file.' ); return; } }; const fetchElementByName = (elementName: string) => { return document.getElementsByName(elementName)[0]; }; const validateIndexName = (typedIndexName: string, isIndexNameWithSuffix: boolean) => { const error = []; const errorIndexNameDiv = fetchElementByName('errorIndexName'); // check for presence of index name entered by the user if (!typedIndexName) { error.push('Required'); } else { // check for restriction on length of the index name if (MAX_LENGTH_OF_INDEX_NAME < typedIndexName.length) { error.push('Map name should be less than ' + MAX_LENGTH_OF_INDEX_NAME + ' characters.\n'); } // check for restriction on the usage of upper case characters in the index name if (INDEX_NAME_UPPERCASE_CHECK.test(typedIndexName)) { error.push('Upper case letters are not allowed.\n'); } // check for restriction on the usage of special characters in the index name if (INDEX_NAME_SPECIAL_CHARACTERS_CHECK.test(typedIndexName)) { error.push('Special characters are not allowed.\n'); } // check for restriction on the usage of characters at the beginning in the index name if ( INDEX_NAME_NOT_BEGINS_WITH_CHECK.test(typedIndexName) || !INDEX_NAME_BEGINS_WITH_CHECK.test(typedIndexName) ) { error.push("Map name can't start with + , _ , - or . It should start with a-z.\n"); } // check for restriction on the usage of -map in map name if entered by the user if (!isIndexNameWithSuffix && INDEX_NAME_NOT_ENDS_WITH_CHECK.test(typedIndexName)) { error.push("Map name can't end with -map.\n"); } } if (error.length > 0) { errorIndexNameDiv.textContent = error.join(' '); setLoading(false); return false; } errorIndexNameDiv.textContent = ''; return true; }; const validateFileSize = async (files) => { // check if the file size is permitted if (MAX_FILE_PAYLOAD_SIZE < files[0].size) { notifications.toasts.addDanger( 'File size should be less than ' + MAX_FILE_PAYLOAD_SIZE_IN_MB + ' MB.' ); setLoading(false); return false; } if (files[0].size === 0) { notifications.toasts.addDanger( 'Error. File does not contain valid features. Check your json format.' ); setLoading(false); return false; } return true; }; const clearUserInput = () => { setValue(''); }; const getFileData = async (files) => { const fileData = await files[0].text(); return fileData; }; const handleSubmit = async () => { // show import button as loading setLoading(true); const newIndexName = fetchElementByName('customIndex').value + INDEX_NAME_SUFFIX; // if index name is valid, validate the file size and upload the geojson data const isValidIndexName = validateIndexName(newIndexName, true); const files = fileContent; let fileData; if (isValidIndexName) { if (files && validateGeojsonFileFormat(files) && validateFileSize(files)) { fileData = await getFileData(files); await handleUploadGeojson(newIndexName, fileData); } } // removes loading symbol from import button setLoading(false); clearUserInput(); }; const checkIfIndexExists = async (indexName: string) => { try { const result = await getIndex(indexName, http); return result.ok; } catch (e) { return false; } }; const formatSuccessToast = (indexName: string, totalRecords: number) => { const textContent = totalRecords > 1 ? 'Successfully added ' + totalRecords + ' features to ' + indexName + '.' : 'Successfully added 1 feature to ' + indexName + '.'; notifications.toasts.addSuccess({ text: toMountPoint(
{textContent} Refresh to visualize the uploaded map.
{textContent} Refresh to visualize the uploaded map.
Formats accepted: .json, .geojson Max size: 25 MB Coordinates must be in EPSG:4326 coordinate reference system.