UNPKG

terriajs

Version:

Geospatial data visualization platform.

206 lines 11.5 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import { observer } from "mobx-react"; import { runInAction } from "mobx"; import PropTypes from "prop-types"; import { Component } from "react"; import { Trans, withTranslation } from "react-i18next"; import { Category, DatatabAction } from "../../../../Core/AnalyticEvents/analyticEvents"; import getDataType from "../../../../Core/getDataType"; import TimeVarying from "../../../../ModelMixins/TimeVarying"; import addUserCatalogMember from "../../../../Models/Catalog/addUserCatalogMember"; import addUserFiles from "../../../../Models/Catalog/addUserFiles"; import CatalogMemberFactory from "../../../../Models/Catalog/CatalogMemberFactory"; import createCatalogItemFromFileOrUrl from "../../../../Models/Catalog/createCatalogItemFromFileOrUrl"; import CommonStrata from "../../../../Models/Definition/CommonStrata"; import upsertModelFromJson from "../../../../Models/Definition/upsertModelFromJson"; import Icon from "../../../../Styled/Icon"; import Dropdown from "../../../Generic/Dropdown"; import Loader from "../../../Loader"; import Styles from "./add-data.scss"; import FileInput from "./FileInput"; import { parseCustomMarkdownToReactWithOptions } from "../../../Custom/parseCustomMarkdownToReact"; import loadJson from "../../../../Core/loadJson"; import TerriaError from "../../../../Core/TerriaError"; /** * Add data panel in modal window -> My data tab */ let AddData = class AddData extends Component { static propTypes = { terria: PropTypes.object, viewState: PropTypes.object, resetTab: PropTypes.func, activeTab: PropTypes.string, // localDataTypes & remoteDataTypes specifies the file types to show in dropdowns for local and remote data uploads. // These default to the lists defined in getDataType.ts // Some external components use these props to customize the types shown. localDataTypes: PropTypes.arrayOf(PropTypes.object), remoteDataTypes: PropTypes.arrayOf(PropTypes.object), onFileAddFinished: PropTypes.func.isRequired, onUrlAddFinished: PropTypes.func.isRequired, t: PropTypes.func.isRequired }; constructor(props) { super(props); const remoteDataTypes = this.props.remoteDataTypes ?? getDataType().remoteDataType; // Automatically suffix supported extension types to localDataType names const localDataTypes = (this.props.localDataTypes ?? getDataType().localDataType).map((dataType) => { const extensions = dataType.extensions?.length ? ` (${buildExtensionsList(dataType.extensions)})` : ""; return { ...dataType, name: `${dataType.name}${extensions}` }; }); this.state = { remoteDataTypes, localDataTypes, localDataType: localDataTypes[0], remoteUrl: "", // By default there's no remote url isLoading: false }; } selectLocalOption(option) { this.setState({ localDataType: option }); } selectRemoteOption(option) { runInAction(() => { this.props.viewState.remoteDataType = option; }); } handleUploadFile(e) { this.setState({ isLoading: true }); addUserFiles(e.target.files, this.props.terria, this.props.viewState, this.state.localDataType).then((addedCatalogItems) => { if (addedCatalogItems && addedCatalogItems.length > 0) { this.props.onFileAddFinished(addedCatalogItems); } this.setState({ isLoading: false }); // reset active tab when file handling is done this.props.resetTab(); }); } async handleUrl(e) { const url = this.state.remoteUrl; e.preventDefault(); this.props.terria.analytics?.logEvent(Category.dataTab, DatatabAction.addDataUrl, url); this.setState({ isLoading: true }); let promise; if (!this.props.viewState.remoteDataType || this.props.viewState.remoteDataType.value === "auto") { promise = createCatalogItemFromFileOrUrl(this.props.terria, this.state.remoteUrl, this.props.viewState.remoteDataType?.value); } else if (this.props.viewState.remoteDataType.value === "json") { promise = loadJson(this.state.remoteUrl) .then((data) => { if (data.error) { return Promise.reject(data.error); } this.props.terria.catalog.group .addMembersFromJson(CommonStrata.user, data.catalog) .raiseError(this.props.terria, "Failed to load catalog from file"); }) .then(() => { this.props.onUrlAddFinished(); }) .catch((error) => TerriaError.from(error).raiseError(this.props.terria, `An error occurred trying to add data from URL: ${this.state.remoteUrl}`)) .finally(() => { this.setState({ isLoading: false }); }); } else { try { const newItem = upsertModelFromJson(CatalogMemberFactory, this.props.terria, "", CommonStrata.defaults, { type: this.props.viewState.remoteDataType.value, name: url }, {}).throwIfUndefined({ message: `An error occurred trying to add data from URL: ${url}` }); newItem.setTrait(CommonStrata.user, "url", url); promise = newItem.loadMetadata().then((result) => { if (result.error) { return Promise.reject(result.error); } return Promise.resolve(newItem); }); } catch (e) { promise = Promise.reject(e); } } addUserCatalogMember(this.props.terria, promise).then((addedItem) => { if (addedItem) { this.props.onFileAddFinished([addedItem]); if (TimeVarying.is(addedItem)) { this.props.terria.timelineStack.addToTop(addedItem); } } // FIXME: Setting state here might result in a react warning if the // component unmounts before the promise finishes this.setState({ isLoading: false }); this.props.resetTab(); }); } onRemoteUrlChange(event) { this.setState({ remoteUrl: event.target.value }); } renderPanels() { const { t } = this.props; const dropdownTheme = { dropdown: Styles.dropdown, list: Styles.dropdownList, isOpen: Styles.dropdownListIsOpen, icon: _jsx(Icon, { glyph: Icon.GLYPHS.opened }) }; const dataTypes = this.state.localDataTypes.reduce(function (result, currentDataType) { if (currentDataType.extensions) { return result.concat(currentDataType.extensions.map((extension) => "." + extension)); } else { return result; } }, []); const remoteDataType = this.props.viewState.remoteDataType ?? this.state.remoteDataTypes[0]; return (_jsxs("div", { className: Styles.tabPanels, children: [this.props.activeTab === "local" && (_jsxs(_Fragment, { children: [_jsx("div", { className: Styles.tabHeading, children: t("addData.localAdd") }), _jsxs("section", { className: Styles.tabPanel, children: [_jsx("label", { className: Styles.label, children: _jsxs(Trans, { i18nKey: "addData.localFileType", children: [_jsx("strong", { children: "Step 1:" }), " Select file type"] }) }), _jsx(Dropdown, { options: this.state.localDataTypes, selected: this.state.localDataType, selectOption: this.selectLocalOption.bind(this), matchWidth: true, theme: dropdownTheme }), this.state.localDataType?.description ? parseCustomMarkdownToReactWithOptions(this.state.localDataType?.description) : null, _jsx("label", { className: Styles.label, children: _jsxs(Trans, { i18nKey: "addData.localFile", children: [_jsx("strong", { children: "Step 2:" }), " Select file"] }) }), _jsx(FileInput, { accept: dataTypes.join(","), onChange: this.handleUploadFile.bind(this) }), this.state.isLoading && _jsx(Loader, {})] })] })), this.props.activeTab === "web" && (_jsxs(_Fragment, { children: [_jsx("div", { className: Styles.tabHeading, children: t("addData.webAdd") }), _jsxs("section", { className: Styles.tabPanel, children: [_jsx("label", { className: Styles.label, children: _jsxs(Trans, { i18nKey: "addData.webFileType", children: [_jsx("strong", { children: "Step 1:" }), " Select file or web service type"] }) }), _jsx(Dropdown, { options: this.state.remoteDataTypes, selected: remoteDataType, selectOption: this.selectRemoteOption.bind(this), matchWidth: true, theme: dropdownTheme }), remoteDataType?.description ? parseCustomMarkdownToReactWithOptions(remoteDataType?.description) : null, remoteDataType?.customComponent ? this.renderCustomComponent(remoteDataType?.customComponent) : this.renderDefaultForWebDataType(t)] })] }))] })); } renderCustomComponent(CustomComponent) { return _jsx(CustomComponent, {}); } renderDefaultForWebDataType(t) { return (_jsxs(_Fragment, { children: [_jsx("label", { className: Styles.label, children: _jsxs(Trans, { i18nKey: "addData.webFile", children: [_jsx("strong", { children: "Step 2:" }), " Enter the URL of the data file or web service"] }) }), _jsxs("form", { className: Styles.urlInput, children: [_jsx("input", { value: this.state.remoteUrl, onChange: this.onRemoteUrlChange.bind(this), className: Styles.urlInputTextBox, type: "text", placeholder: "e.g. http://data.gov.au/geoserver/wms" }), _jsx("button", { disabled: this.state.remoteUrl.length === 0, type: "submit", onClick: this.handleUrl.bind(this), className: Styles.urlInputBtn, children: t("addData.urlInputBtn") }), this.state.isLoading && _jsx(Loader, {})] })] })); } render() { return _jsx("div", { className: Styles.inner, children: this.renderPanels() }); } }; AddData = __decorate([ observer ], AddData); /** * @param extensions - string[] * @returns Comma separated string of extensions */ function buildExtensionsList(extensions) { return extensions.map((ext) => `.${ext}`).join(", "); } export default withTranslation()(AddData); //# sourceMappingURL=AddData.js.map