Skip to content

Commit

Permalink
validate url of Add data modal (#1837)
Browse files Browse the repository at this point in the history
* fix modal styles

Signed-off-by: Evgeny Zhgulev <evgeny.zhgulev@actionengine.com>

* validate url input

Signed-off-by: Evgeny Zhgulev <evgeny.zhgulev@actionengine.com>

* add http to url regexp

Signed-off-by: Evgeny Zhgulev <evgeny.zhgulev@actionengine.com>

* fix linter error

Signed-off-by: Evgeny Zhgulev <evgeny.zhgulev@actionengine.com>
  • Loading branch information
jagerts committed Jun 1, 2022
1 parent b7d8edf commit 9bee093
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 8 deletions.
Expand Up @@ -25,6 +25,7 @@ import styled from 'styled-components';
import {CORS_LINK} from '../../constants/default-settings';
import {FormattedHTMLMessage, FormattedMessage} from 'react-intl';
import {Button} from 'kepler.gl/components';
import {validateUrl} from '../../utils/url';

const propTypes = {
onLoadRemoteMap: PropTypes.func.isRequired
Expand Down Expand Up @@ -92,26 +93,33 @@ const Error = ({error, url}) => (

class LoadRemoteMap extends Component {
state = {
dataUrl: ''
dataUrl: '',
error: null,
submitted: false
};

onMapUrlChange = e => {
// TODO: validate url
this.setState({
dataUrl: e.target.value
dataUrl: e.target.value,
error: !validateUrl(e.target.value) ? {message: 'Incorrect URL'} : null
});
};

onLoadRemoteMap = () => {
const {dataUrl} = this.state;
if (!dataUrl) {
const {dataUrl, error} = this.state;

this.setState({submitted: true});

if (!dataUrl || error) {
return;
}

this.props.onLoadRemoteMap({dataUrl});
};

render() {
const displayedError = this.props.error || this.state.submitted ? this.state.error : null;

return (
<div>
<InputForm>
Expand All @@ -138,13 +146,13 @@ class LoadRemoteMap extends Component {
type="text"
placeholder="Url"
value={this.state.dataUrl}
error={this.props.error}
error={displayedError}
/>
<Button type="submit" cta size="small" onClick={this.onLoadRemoteMap}>
<FormattedMessage id={'loadRemoteMap.fetch'} />
</Button>
</StyledFromGroup>
{this.props.error && <Error error={this.props.error} url={this.props.option.dataUrl} />}
{displayedError && <Error error={displayedError} url={this.props.option?.dataUrl} />}
</InputForm>
</div>
);
Expand Down
8 changes: 8 additions & 0 deletions examples/demo-app/src/utils/url.js
Expand Up @@ -66,3 +66,11 @@ parseUri.options = {
loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
}
};

/**
* Validates an url
* @param str
*/
export function validateUrl(str) {
return str?.match(/^(ftp|http|https?):\/\/+(www\.)?[a-z0-9\-\.]{3,}\.[a-z]{3}$/);
}
3 changes: 3 additions & 0 deletions src/components/modal-container.tsx
Expand Up @@ -20,6 +20,7 @@

import React, {Component} from 'react';
import {css} from 'styled-components';
import {findDOMNode} from 'react-dom';
import {createSelector} from 'reselect';
import get from 'lodash.get';
import document from 'global/document';
Expand Down Expand Up @@ -274,6 +275,7 @@ export default function ModalContainerFactory(
mapState,
uiState,
visState,
rootNode,
visStateActions,
uiStateActions,
providerState
Expand Down Expand Up @@ -545,6 +547,7 @@ export default function ModalContainerFactory(

return this.props.rootNode ? (
<ModalDialog
parentSelector={() => findDOMNode(rootNode)}
isOpen={Boolean(currentModal)}
onCancel={this._closeModal}
{...modalProps}
Expand Down
2 changes: 1 addition & 1 deletion src/components/side-panel/common/types.ts
Expand Up @@ -59,7 +59,7 @@ export type DatasetItemProps = {
};

export type SourceDataSelectorProps = {
dataId: string | string[];
dataId: string | string[] | null;
datasets: Datasets;
disabled: boolean;
defaultValue?: string;
Expand Down

0 comments on commit 9bee093

Please sign in to comment.