kepler.gl.geoiq
Version:
kepler.gl is a webgl based application to visualize large scale location data in the browser
355 lines (325 loc) • 10.6 kB
JavaScript
// Copyright (c) 2023 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import React, {Component} from 'react';
import PropTypes from 'prop-types';
// import styled from "styled-components";
import {connect} from 'react-redux';
import {listDatasetDownload} from '../../../store/actions/datasetActions';
import {withStyles} from '@material-ui/core/styles';
import Grid from '@material-ui/core/Grid';
import Paper from '@material-ui/core/Paper';
import Checkbox from '@material-ui/core/Checkbox';
import Button from '@material-ui/core/Button';
// import Avatar from "@material-ui/core/Avatar";
import Typography from '@material-ui/core/Typography';
import Pagination from 'material-ui-flat-pagination';
import LoadingSpinner from '../loading-spinner';
import Radio from '@material-ui/core/Radio';
// import CircularProgress from "@material-ui/core/CircularProgress";
const styles = theme => ({
root: {
flexGrow: 1,
height: '320px'
},
button: {
margin: theme.spacing.unit,
maxHeight: '30px'
}
});
/*
Inspired by https://github.com/okonet/react-dropzone/blob/master/src/index.js
*/
export class ListUpload extends Component {
state = {
currentPage: 1,
datasetsPerPage: 4,
offset: 0,
datasetFilter: '',
filteredDatasets: [],
selectedValue: ''
};
// static propTypes = {
// onUpload: PropTypes.func.isRequired
// };
// _setState = s => {
// this.setState({ [s]: true });
// };
handlePageChange = (offset, page) => {
// console.log("active page is" + page);
this.setState({offset, currentPage: page});
};
_onMount = datasets => {
return datasets.map(dataset => this.setState({[dataset.id]: false}));
};
componentDidMount() {
// console.log(this.state);
// this.setState({datasets: this.props.dataset.datasets})
const datasets = this.props.dataset.datasets;
if (datasets) {
this._onMount(datasets);
}
}
_blobToFile(theBlob, fileName) {
// A Blob() is almost a File() - it's just missing the two properties below which we will add
// console.log(theBlob);
theBlob.lastModifiedDate = new Date();
theBlob.name = fileName;
return theBlob;
}
_loadData(response, file) {
return file;
}
_downloadDataset = datasets => {
this.props.dispatch(listDatasetDownload(datasets));
};
_files = () => {
var files = [];
const datasetId = this.state;
// console.log(datasetId);
for (const [key, value] of Object.entries(datasetId)) {
if (value === true) {
const datasets = this.props.dataset.datasets;
datasets.map(dataset => {
if (dataset.id === this.state.selectedValue) {
// console.log(dataset);
files.push(dataset);
// console.log(files);
return this._downloadDataset(dataset);
}
return dataset;
});
}
}
};
_onClick = () => {
// return this._files();
const dataset = this.props.dataset.datasets.map(dataset => {
if (dataset.id === this.state.selectedValue) {
return this._downloadDataset(dataset);
}
});
return dataset;
};
_onChange = ({target: {files}}) => {
files = this.props.dataset.listDatasets;
if (!files) {
return;
}
this.props.onUpload(files);
};
handleChange = name => event => {
this.props.dataset.datasets.map(dataset => {
// console.log(dataset.id);
const id = dataset.id.toString();
this.setState({[id]: false});
});
// console.log(this.state);
this.setState({[name]: event.target.checked});
};
handleRadioChange = event => {
this.setState({selectedValue: event.target.value});
};
_renderNoDatasetMessage() {
return (
<div>
<p>you have no file(s) in Datahub </p>
</div>
);
}
_filterDatasets = datasetFilter => {
const {datasets} = this.props.dataset;
const filteredDatasets = datasets.filter(dataset => {
const datasetName = dataset.name.toLowerCase();
return datasetName.indexOf(datasetFilter.toLowerCase()) !== -1;
});
this.setState({filteredDatasets});
};
_handleFilterChange = e => {
this.setState({
datasetFilter: e.target.value
});
this._filterDatasets(e.target.value);
};
render() {
const {classes} = this.props;
let {datasets} = this.props.dataset;
const {
currentPage,
datasetsPerPage,
filteredDatasets,
datasetFilter
} = this.state;
const indexOfLastDataset = currentPage * datasetsPerPage;
const indexOfFirstDataset = indexOfLastDataset - datasetsPerPage;
let currentDatasets = [];
if (datasetFilter.length === 0) {
currentDatasets = datasets.slice(indexOfFirstDataset, indexOfLastDataset);
} else {
currentDatasets = filteredDatasets.slice(
indexOfFirstDataset,
indexOfLastDataset
);
datasets = filteredDatasets;
}
// const currentDatasets = datasets.slice(
// indexOfFirstDataset,
// indexOfLastDataset
// );
const renderDatasets = currentDatasets.map(dataset => {
const ID = dataset.id.toString();
// console.log(this.state[ID]);
return (
<Grid
key={dataset.id}
item
xs={12}
style={{paddingBottom: '0px', width: '100%'}}
>
<Paper className={classes.paper}>
<Grid container wrap="nowrap" spacing={16} style={{margin: 'auto'}}>
<Grid item style={{padding: '0px'}}>
<Radio
checked={this.state.selectedValue === ID}
onChange={this.handleRadioChange}
value={dataset.id}
name="radio-button-demo"
aria-label="A"
/>
{/* <Checkbox
// style={{ checked: [this.state[ID]] }}
// checkedIcon={this.state[ID]}
checked={this.state[ID]}
onChange={this.handleChange(ID)}
value={dataset.name}
/> */}
</Grid>
<Grid item xs style={{margin: 'auto'}}>
<Typography>
{dataset.name}-{dataset.availabilityStatus}
</Typography>
</Grid>
</Grid>
</Paper>
</Grid>
);
});
const _renderNoDatasetMessage = () => {
return (
<div>
<p style={{fontSize: '14px', marginBottom: '12px', color: 'black'}}>
You have no files in Datahub{' '}
</p>
</div>
);
};
// const loading = "OPEN";
const _renderButton = () => {
const {datasets} = this.props.dataset;
// const loadingDataset = true;
if (datasets.length) {
if (this.props.ui.progressAddDataStatus === 'OPEN') {
// if (loading === "OPEN") {
return (
<div style={{margin: 'auto'}}>
<LoadingSpinner />
</div>
);
}
return (
<Button
// disabled={loadingDataset}
className={classes.button}
onClick={this._onClick}
>
Add Data
{/* {loadingDataset && (
<CircularProgress
size={60}
thickness={3}
className={classes.tableProgress}
/>
)} */}
</Button>
);
}
return _renderNoDatasetMessage();
};
// console.log(datasets);
return (
<React.Fragment>
<div className={classes.root} style={{display: 'grid'}}>
<div style={{marginLeft: '12px'}}>
<label htmlFor="filter">Search: </label>
<input
style={{
borderTopStyle: 'hidden',
borderLeftStyle: 'hidden',
borderRightStyle: 'hidden',
borderBottomStyle: 'solid',
borderBottomWidth: 'thin',
borderBottomColor: 'lightgray'
}}
type="text"
id="filter"
value={this.state.datasetFilter}
onChange={this._handleFilterChange}
/>
</div>
<Grid
container
spacing={24}
style={{
display: 'inline-block',
margin: 'auto',
width: '100%',
minHeight: '240px'
}}
>
{renderDatasets}
</Grid>
<Pagination
otherPageColor="black"
style={{margin: 'auto'}}
activePage={this.state.currentPage}
limit={this.state.datasetsPerPage}
offset={this.state.offset}
total={datasets.length}
onClick={(e, offset, page) => this.handlePageChange(offset, page)}
/>
{_renderButton()}
</div>
</React.Fragment>
);
}
}
ListUpload.propTypes = {
classes: PropTypes.object.isRequired
};
const mapStateToProps = state => state;
export default connect(mapStateToProps, null)(withStyles(styles)(ListUpload));
// <Wrapper>
// <input
// type="file"
// ref={ref => {this._fileInput = ref}}
// style={{display: 'none'}}
// onChange={this._onChange}
// />
// <span onClick={this._onClick}>{this.props.children}</span>
// </Wrapper>