Skip to content

Commit

Permalink
[feat] Layer Column Mode (#2662)
Browse files Browse the repository at this point in the history
- Layer Column Mode
-  add ColumnMode support for TripLayer 
- Choose between geoJson and CSV columns for trip layer
- create new component for column mode config
- calculate animation config when update layer column
- Fill all columns from column mode when initializing it from prop
- Auto detect lat, lng, altitude field pairs
- Auto create trip layer if a dataset contain field pairs, timestamp, and `id` | `uuid` fie
- Add column config component test

Signed-off-by: Ihor Dykhta <dikhta.igor@gmail.com>
  • Loading branch information
igorDykhta authored Sep 23, 2024
1 parent ef32f71 commit add6192
Show file tree
Hide file tree
Showing 46 changed files with 1,019 additions and 252 deletions.
23 changes: 13 additions & 10 deletions examples/demo-app/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,26 +171,29 @@ class App extends Component {
}

_loadSampleData() {
this._loadPointData();
this._loadGeojsonData();
// this._loadPointData();
// this._loadGeojsonData();
// this._loadTripGeoJson();
// this._loadIconData();
// this._loadH3HexagonData();
// this._loadS2Data();
// this._loadScenegraphLayer();
// this._loadGpsData();
this._loadGpsData();
}

_loadPointData() {
this.props.dispatch(
addDataToMap({
datasets: {
info: {
label: 'Sample Taxi Trips in New York City',
id: 'test_trip_data'
},
data: sampleTripData
},
datasets: [
{
info: {
label: 'Sample Taxi Trips in New York City',
id: 'test_trip_data',
color: [255, 0, 0]
},
data: sampleTripData
}
],
options: {
// centerMap: true,
keepExistingConfig: true
Expand Down
1 change: 1 addition & 0 deletions src/components/src/common/checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ interface CheckboxProps {
id: string;
type?: string;
label?: ReactNode;
name?: string;
className?: string;
value?: string | 'indeterminate';
checked?: boolean;
Expand Down
27 changes: 27 additions & 0 deletions src/components/src/common/icons/help.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: MIT
// Copyright contributors to the kepler.gl project

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import Base from './base';

export default class Help extends Component {
static propTypes = {
/** Set the height of the icon, ex. '16px' */
height: PropTypes.string
};

static defaultProps = {
height: '16px',
predefinedClassName: 'data-ex-icons-info'
};

render() {
return (
<Base viewBox="0 0 16 16" {...this.props}>
<path d="M8 15.375C3.933 15.375.625 12.067.625 8S3.933.625 8 .625 15.375 3.933 15.375 8 12.067 15.375 8 15.375zM8 1.89C4.608 1.89 1.868 4.63 1.868 8A6.138 6.138 0 008 14.132 6.124 6.124 0 0014.132 8C14.11 4.629 11.372 1.89 8 1.89z" />
<path d="M7.81 10.044a.634.634 0 01-.632-.632c0-.97.632-1.812 1.538-2.086.4-.127.675-.485.654-.906 0-.759-.632-1.391-1.391-1.391s-1.39.632-1.39 1.39a.634.634 0 01-.633.633.634.634 0 01-.632-.632C5.366 4.966 6.546 3.786 8 3.786a2.635 2.635 0 012.634 2.634c0 .969-.632 1.812-1.538 2.086-.4.126-.675.484-.653.906a.648.648 0 01-.633.632zM7.81 12.109a.759.759 0 100-1.517.759.759 0 000 1.517z" />
</Base>
);
}
}
1 change: 1 addition & 0 deletions src/components/src/common/icons/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export {default as FilterFunnel} from './filter-funnel';
export {default as FreeWindow} from './free-window';
export {default as Gear} from './gear';
export {default as Hash} from './hash';
export {default as Help} from './help';
export {default as Histogram} from './histogram';
export {default as IconWrapper} from './base';
export {default as Info} from './info';
Expand Down
3 changes: 3 additions & 0 deletions src/components/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
LayerColorRangeSelectorFactory,
ArcLayerColorSelectorFactory
} from './side-panel/layer-panel/layer-color-selector';
import LayerColumnModeConfigFactory from './side-panel/layer-panel/layer-column-mode-config';
import {appInjector} from './container';

// Components
Expand Down Expand Up @@ -398,6 +399,7 @@ export const RangeSlider = appInjector.get(RangeSliderFactory);
export const VisConfigSlider = appInjector.get(VisConfigSliderFactory);
export const VisConfigSwitch = appInjector.get(VisConfigSwitchFactory);
export const LayerConfigGroup = appInjector.get(LayerConfigGroupFactory);
export const LayerColumnModeConfig = appInjector.get(LayerColumnModeConfigFactory);
export const LayerColumnConfig = appInjector.get(LayerColumnConfigFactory);
export const ChannelByValueSelector = appInjector.get(ChannelByValueSelectorFactory);
export const FieldSelector = appInjector.get(FieldSelectorFactory);
Expand All @@ -424,6 +426,7 @@ export {
InfoHelperFactory,
ColorSelectorFactory,
LayerColorSelectorFactory,
LayerColumnModeConfigFactory,
LayerColorRangeSelectorFactory,
ArcLayerColorSelectorFactory
};
Expand Down
3 changes: 3 additions & 0 deletions src/components/src/map-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,7 @@ export default function MapContainerFactory(
clicked,
datasets,
interactionConfig,
animationConfig,
layers,
mousePos: {mousePosition, coordinate, pinned}
}
Expand All @@ -601,6 +602,7 @@ export default function MapContainerFactory(
}

const layerHoverProp = getLayerHoverProp({
animationConfig,
interactionConfig,
hoverInfo,
layers,
Expand All @@ -620,6 +622,7 @@ export default function MapContainerFactory(
const lngLat = clicked ? clicked.coordinate : pinned.coordinate;
pinnedPosition = this._getHoverXY(viewport, lngLat);
layerPinnedProp = getLayerHoverProp({
animationConfig,
interactionConfig,
hoverInfo: clicked,
layers,
Expand Down
18 changes: 6 additions & 12 deletions src/components/src/side-panel/layer-panel/column-selector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,14 @@ import {FormattedMessage} from '@kepler.gl/localization';
import {PanelLabel} from '../../common/styled-components';
import FieldSelectorFactory from '../../common/field-selector';
import {validateColumn} from '@kepler.gl/reducers';
import {LayerColumn, LayerColumns} from '@kepler.gl/layers';
import {Field, FieldPair} from '@kepler.gl/types';
import {LayerColumn, LayerColumns, EnhancedFieldPair} from '@kepler.gl/types';
import {MinimalField} from '../../common/field-selector';

type Pair = {
name: string;
type: string;
pair: FieldPair['pair'];
};

type ColumnSelectorProps = {
export type ColumnSelectorProps<FieldOption extends MinimalField> = {
column: LayerColumn;
columns: LayerColumns;
label: string;
allFields: Field[];
allFields: FieldOption[];
onSelect: (
items:
| ReadonlyArray<string | number | boolean | object>
Expand All @@ -30,7 +24,7 @@ type ColumnSelectorProps = {
| object
| null
) => void;
fieldPairs?: Pair[] | null;
fieldPairs: EnhancedFieldPair[] | null;
};

const ColumnRow = styled.div`
Expand All @@ -52,7 +46,7 @@ const ColumnSelect = styled.div`
ColumnSelectorFactory.deps = [FieldSelectorFactory];

function ColumnSelectorFactory(FieldSelector: ReturnType<typeof FieldSelectorFactory>) {
const ColumnSelector: React.FC<ColumnSelectorProps> = ({
const ColumnSelector: React.FC<ColumnSelectorProps<any>> = ({
column,
columns,
label,
Expand Down
37 changes: 12 additions & 25 deletions src/components/src/side-panel/layer-panel/layer-column-config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,34 @@
// Copyright contributors to the kepler.gl project

import React, {useCallback, useMemo} from 'react';
import styled from 'styled-components';

import {ColumnPairs, LayerColumns, LayerBaseConfig} from '@kepler.gl/layers';
import {FormattedMessage} from '@kepler.gl/localization';
import {FieldPair, Field} from '@kepler.gl/types';
import {LayerBaseConfig} from '@kepler.gl/layers';
import {
FieldPair,
Field,
ColumnPairs,
LayerColumns,
ColumnLabels,
EnhancedFieldPair
} from '@kepler.gl/types';
import {toArray} from '@kepler.gl/utils';

import ColumnSelectorFactory from './column-selector';
import {MinimalField} from '../../common/field-selector';
import {PanelLabel, SidePanelSection} from '../../common/styled-components';
import {SidePanelSection} from '../../common/styled-components';

export type LayerColumnConfigProps<FieldOption extends MinimalField> = {
columns: LayerColumns;
fields: FieldOption[];
assignColumnPairs: (key: string, pair: string) => LayerColumns;
assignColumn: (key: string, field: FieldOption) => LayerColumns;
updateLayerConfig: (newConfig: Partial<LayerBaseConfig>) => void;
updateLayerType?: (newType: string) => void;
columnPairs?: ColumnPairs | null;
fieldPairs?: FieldPair[];
columnLabels?: Record<string, string>;
columnLabels: ColumnLabels | null;
};

export type EnhancedFieldPair = {
name: string;
type: 'point';
pair: FieldPair['pair'];
};

const TopRow = styled.div`
display: flex;
justify-content: space-between;
`;

/**
* only provide suggested field pairs if there is a match,
* otherwise the user can select a suggested field pair that will create invalid columns and a hard crash
Expand Down Expand Up @@ -102,14 +97,6 @@ function LayerColumnConfigFactory(ColumnSelector: ReturnType<typeof ColumnSelect
<div>
<SidePanelSection>
<div className="layer-config__column">
<TopRow>
<PanelLabel>
<FormattedMessage id={'columns.title'} />
</PanelLabel>
<PanelLabel>
<FormattedMessage id="layer.required" />
</PanelLabel>
</TopRow>
{Object.keys(columns).map(key => (
<ColumnSelector
column={columns[key]}
Expand Down
Loading

0 comments on commit add6192

Please sign in to comment.