UNPKG

kepler.gl.geoiq

Version:

kepler.gl is a webgl based application to visualize large scale location data in the browser

195 lines (176 loc) 6 kB
// 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 Sortable from 'react-anything-sortable'; import styled from 'styled-components'; import {createSelector} from 'reselect'; import WidgetPanelFactory from './widget-panel/widget-panel'; import SourceDataCatalogFactory from './common/source-data-catalog'; import {Add} from 'components/common/icons'; import { SidePanelDivider, SidePanelSection, Button } from 'components/common/styled-components'; const StyledSortable = styled.div` .ui-sortable { display: block; position: relative; overflow: visible; user-select: none; :before { content: ' '; display: table; } :after { content: ' '; display: table; } } .ui-sortable-item.ui-sortable-dragging { position: absolute; z-index: 1688; cursor: move; } .ui-sortable-item.ui-sortable-dragging:hover { cursor: move; opacity: 0.5; } .ui-sortable-placeholder { display: none; } .ui-sortable-placeholder.visible { display: block; opacity: 0; z-index: -1; } `; WidgetManagerFactory.deps = [WidgetPanelFactory, SourceDataCatalogFactory]; function WidgetManagerFactory(WidgetPanel, SourceDataCatalog) { return class WidgetManager extends Component { static propTypes = { addWidget: PropTypes.func.isRequired, datasets: PropTypes.object.isRequired, widgetClasses: PropTypes.object.isRequired, widgets: PropTypes.arrayOf(PropTypes.any).isRequired, widgetConfigChange: PropTypes.func.isRequired, widgetVisualChannelConfigChange: PropTypes.func.isRequired, widgetTypeChange: PropTypes.func.isRequired, widgetVisConfigChange: PropTypes.func.isRequired, // layers: propTypes.arrayOf(propTypes.any), openModal: PropTypes.func.isRequired, removeWidget: PropTypes.func.isRequired, showDatasetTable: PropTypes.func.isRequired, updateWidgetOrder: PropTypes.func.isRequired, mapState: PropTypes.object.isRequired, auth: PropTypes.object.isRequired, project: PropTypes.object.isRequired }; widgetClassSelector = props => props.widgetClasses; widgetTypeOptionsSelector = createSelector( this.widgetClassSelector, widgetClasses => Object.keys(widgetClasses).map(key => { const widget = new widgetClasses[key](); return { id: key, label: widget.name, icon: widget.widgetIcon }; }) ); _addEmptyNewWidget = () => { this.props.addWidget(); }; _handleSort = order => { this.props.updateWidgetOrder(order); }; render() { const { widgets, layers, datasets, widgetOrder, openModal, mapState, filters, auth, project } = this.props; const hadDataset = Object.keys(datasets).length; const hadEmptyWidget = widgets.some(w => !w.name); const widgetTypeOptions = this.widgetTypeOptionsSelector(this.props); const widgetActions = { widgetConfigChange: this.props.widgetConfigChange, widgetVisualChannelConfigChange: this.props .widgetVisualChannelConfigChange, widgetTypeChange: this.props.widgetTypeChange, widgetVisConfigChange: this.props.widgetVisConfigChange, removeWidget: this.props.removeWidget }; const panelProps = {datasets, openModal, widgetTypeOptions}; return ( <StyledSortable className="widget-manager"> <SourceDataCatalog datasets={datasets} showDatasetTable={this.props.showDatasetTable} /> <SidePanelDivider /> <SidePanelSection> <Sortable onSort={this._handleSort} direction="vertical" sortHandle="sort--handle" dynamic > {widgetOrder.map(idx => ( <WidgetPanel {...panelProps} {...widgetActions} sortData={idx} key={widgets[idx].id} idx={idx} widget={widgets[idx]} layers={layers} filters={filters} mapState={mapState} auth={auth} project={project} /> ))} </Sortable> </SidePanelSection> <SidePanelSection> <Button inactive={hadEmptyWidget || !hadDataset} onClick={this._addEmptyNewWidget} width="auto" > <Add height="12px" /> Add Widget </Button> </SidePanelSection> </StyledSortable> ); } }; } export default WidgetManagerFactory;