From bc57318a216681c980b0440fe6cef3273010ab12 Mon Sep 17 00:00:00 2001 From: Igor Dykhta Date: Sun, 31 Mar 2024 04:23:51 +0300 Subject: [PATCH] [Feat] add geojson column mode for point layer Signed-off-by: Ihor Dykhta --- examples/demo-app/src/app.js | 8 +- src/layers/src/geojson-layer/geojson-utils.ts | 37 ++ src/layers/src/point-layer/point-layer.ts | 114 +++-- .../side-panel/layer-configurator-test.js | 19 +- test/browser/layer-tests/point-layer-specs.js | 412 +++++++++++++++++- test/fixtures/state-saved-v0.js | 2 + test/fixtures/state-saved-v1-3.js | 2 + test/fixtures/state-saved-v1-4.js | 2 + test/helpers/mock-state.js | 2 + test/node/reducers/vis-state-test.js | 16 +- 10 files changed, 553 insertions(+), 61 deletions(-) diff --git a/examples/demo-app/src/app.js b/examples/demo-app/src/app.js index d96c397d1a..e5e3bdfb17 100644 --- a/examples/demo-app/src/app.js +++ b/examples/demo-app/src/app.js @@ -313,11 +313,11 @@ class App extends Component { { info: {label: 'Bart Stops Geo', id: 'bart-stops-geo'}, data: processGeojson(sampleGeojsonPoints) - }, - { - info: {label: 'SF Zip Geo', id: 'sf-zip-geo'}, - data: processGeojson(sampleGeojson) } + // { + // info: {label: 'SF Zip Geo', id: 'sf-zip-geo'}, + // data: processGeojson(sampleGeojson) + // } ], options: { keepExistingConfig: true diff --git a/src/layers/src/geojson-layer/geojson-utils.ts b/src/layers/src/geojson-layer/geojson-utils.ts index 7a20ec6c21..1ab3fc3576 100644 --- a/src/layers/src/geojson-layer/geojson-utils.ts +++ b/src/layers/src/geojson-layer/geojson-utils.ts @@ -21,6 +21,7 @@ import {LayerBaseConfig} from '../base-layer'; export type GetFeature = (d: any) => Feature; export type GeojsonDataMaps = (Feature | BinaryFeatureCollection | null)[]; +export type GeojsonPointDataMaps = (number[] | number[][] | null)[]; export const COLUMN_MODE_GEOJSON = 'geojson'; @@ -160,6 +161,42 @@ export function getGeojsonDataMaps( return dataToFeature; } +/** + * Parse raw data to GeoJson point feature coordinates + */ +export function getGeojsonPointDataMaps( + dataContainer: DataContainerInterface, + getFeature: GetFeature +): GeojsonPointDataMaps { + const acceptableTypes = ['Point', 'MultiPoint', 'GeometryCollection']; + + const dataToFeature: GeojsonPointDataMaps = []; + + for (let index = 0; index < dataContainer.numRows(); index++) { + const feature = parseGeoJsonRawFeature(getFeature(dataContainer.rowAsArray(index))); + + if (feature && feature.geometry && acceptableTypes.includes(feature.geometry.type)) { + dataToFeature[index] = + feature.geometry.type === 'Point' || feature.geometry.type === 'MultiPoint' + ? feature.geometry.coordinates + : //@ts-expect-error Property 'geometries' does not exist on type 'LineString' + (feature.geometry.geometries || []).reduce((accu, f) => { + if (f.type === 'Point') { + accu.push(f.coordinates); + } else if (f.type === 'MultiPoint') { + accu.push(...f.coordinates); + } + + return accu; + }, []); + } else { + dataToFeature[index] = null; + } + } + + return dataToFeature; +} + /** * Parse geojson from string * @param {String} geoString diff --git a/src/layers/src/point-layer/point-layer.ts b/src/layers/src/point-layer/point-layer.ts index 9e93204763..ac15173f9e 100644 --- a/src/layers/src/point-layer/point-layer.ts +++ b/src/layers/src/point-layer/point-layer.ts @@ -11,7 +11,7 @@ import Layer, { LayerSizeConfig, LayerStrokeColorConfig } from '../base-layer'; -import {hexToRgb, findDefaultColorField} from '@kepler.gl/utils'; +import {hexToRgb, findDefaultColorField, DataContainerInterface} from '@kepler.gl/utils'; import {default as KeplerTable} from '@kepler.gl/table'; import PointLayerIcon from './point-layer-icon'; import { @@ -23,6 +23,7 @@ import { import {getTextOffsetByRadius, formatTextLabelData} from '../layer-text-label'; import {assignPointPairToLayerColumn} from '../layer-utils'; +import {getGeojsonPointDataMaps, GeojsonPointDataMaps} from '../geojson-layer/geojson-utils'; import { Merge, RGBColor, @@ -52,6 +53,7 @@ export type PointLayerColumnsConfig = { lng: LayerColumn; altitude?: LayerColumn; neighbors?: LayerColumn; + geojson: LayerColumn; }; export type PointLayerVisConfig = { @@ -86,19 +88,54 @@ export type PointLayerData = { export const pointPosAccessor = ({lat, lng, altitude}: PointLayerColumnsConfig) => - dc => - d => + (dc: DataContainerInterface) => + (d: {index: number}) => [ dc.valueAt(d.index, lng.fieldIdx), dc.valueAt(d.index, lat.fieldIdx), altitude && altitude.fieldIdx > -1 ? dc.valueAt(d.index, altitude.fieldIdx) : 0 ]; +export const geojsonPosAccessor = + ({geojson}: {geojson: LayerColumn}) => + d => + d[geojson.fieldIdx]; + +export const COLUMN_MODE_POINTS = 'points'; +export const COLUMN_MODE_GEOJSON = 'geojson'; + export const pointRequiredColumns: ['lat', 'lng'] = ['lat', 'lng']; export const pointOptionalColumns: ['altitude', 'neighbors'] = ['altitude', 'neighbors']; +export const geojsonRequiredColumns: ['geojson'] = ['geojson']; + +const SUPPORTED_COLUMN_MODES = [ + { + key: COLUMN_MODE_POINTS, + label: 'Point Columns', + requiredColumns: pointRequiredColumns, + optionalColumns: pointOptionalColumns + }, + { + key: COLUMN_MODE_GEOJSON, + label: 'GeoJSON Feature', + requiredColumns: geojsonRequiredColumns + } +]; +const DEFAULT_COLUMN_MODE = COLUMN_MODE_POINTS; const brushingExtension = new BrushingExtension(); +function pushPointPosition(data: any[], pos: number[], index: number, neighbors: number[]) { + if (pos.every(Number.isFinite)) { + data.push({ + position: pos, + // index is important for filter + index, + ...(neighbors ? {neighbors} : {}) + }); + } +} + export const pointVisConfigs: { radius: 'radius'; fixedRadius: 'fixedRadius'; @@ -138,12 +175,16 @@ export const pointVisConfigs: { export default class PointLayer extends Layer { declare config: PointLayerConfig; declare visConfigSettings: PointLayerVisConfigSettings; + dataToFeature: GeojsonPointDataMaps = []; + constructor(props) { super(props); this.registerVisConfig(pointVisConfigs); - this.getPositionAccessor = dataContainer => - pointPosAccessor(this.config.columns)(dataContainer); + this.getPositionAccessor = (dataContainer: DataContainerInterface) => + this.config.columnMode === COLUMN_MODE_POINTS + ? pointPosAccessor(this.config.columns)(dataContainer) + : geojsonPosAccessor(this.config.columns); } get type(): 'point' { @@ -157,9 +198,6 @@ export default class PointLayer extends Layer { get layerIcon() { return PointLayerIcon; } - get requiredLayerColumns() { - return pointRequiredColumns; - } get optionalColumns() { return pointOptionalColumns; @@ -169,6 +207,10 @@ export default class PointLayer extends Layer { return this.defaultPointColumnPairs; } + get supportedColumnModes() { + return SUPPORTED_COLUMN_MODES; + } + get noneLayerDataAffectingProps() { return [...super.noneLayerDataAffectingProps, 'radius']; } @@ -252,6 +294,7 @@ export default class PointLayer extends Layer { if (props.length === 0) { prop.isVisible = true; } + //@ts-expect-error logically separate geojson column type? prop.columns = assignPointPairToLayerColumn(pair, true); props.push(prop); @@ -263,6 +306,7 @@ export default class PointLayer extends Layer { getDefaultLayerConfig(props: LayerBaseConfigPartial) { return { ...super.getDefaultLayerConfig(props), + columnMode: props?.columnMode ?? DEFAULT_COLUMN_MODE, // add stroke color visual channel strokeColorField: null, @@ -278,25 +322,32 @@ export default class PointLayer extends Layer { const index = filteredIndex[i]; let neighbors; - if (this.config.columns.neighbors?.value) { - const {fieldIdx} = this.config.columns.neighbors; - neighbors = Array.isArray(dataContainer.valueAt(index, fieldIdx)) - ? dataContainer.valueAt(index, fieldIdx) - : []; - } - const pos = getPosition({index}); - - // if doesn't have point lat or lng, do not add the point - // deck.gl can't handle position = null - if (pos.every(Number.isFinite)) { - data.push({ - position: pos, - // index is important for filter - index, - neighbors - }); + if (this.config.columnMode === COLUMN_MODE_POINTS) { + if (this.config.columns.neighbors?.value) { + const {fieldIdx} = this.config.columns.neighbors; + neighbors = Array.isArray(dataContainer.valueAt(index, fieldIdx)) + ? dataContainer.valueAt(index, fieldIdx) + : []; + } + const pos = getPosition({index}); + + // if doesn't have point lat or lng, do not add the point + // deck.gl can't handle position = null + pushPointPosition(data, pos, index, neighbors); + } else { + // point from geojson coordinates + const coordinates = this.dataToFeature[i]; + // if multi points + if (coordinates && Array.isArray(coordinates[0])) { + coordinates.forEach(coord => { + pushPointPosition(data, coord, index, neighbors); + }); + } else if (coordinates && Number.isFinite(coordinates[0])) { + pushPointPosition(data, coordinates as number[], index, neighbors); + } } } + return data; } @@ -307,7 +358,7 @@ export default class PointLayer extends Layer { const {textLabel} = this.config; const {gpuFilter, dataContainer} = datasets[this.config.dataId]; const {data, triggerChanged} = this.updateData(datasets, oldLayerData); - const getPosition = this.getPositionAccessor(dataContainer); + const getPosition = d => d.position; // get all distinct characters in the text labels const textLabels = formatTextLabelData({ @@ -331,9 +382,14 @@ export default class PointLayer extends Layer { /* eslint-enable complexity */ updateLayerMeta(dataContainer) { - const getPosition = this.getPositionAccessor(dataContainer); - const bounds = this.getPointsBounds(dataContainer, getPosition); - this.updateMeta({bounds}); + if (this.config.columnMode === COLUMN_MODE_GEOJSON) { + const getFeature = this.getPositionAccessor(); + this.dataToFeature = getGeojsonPointDataMaps(dataContainer, getFeature); + } else { + const getPosition = this.getPositionAccessor(dataContainer); + const bounds = this.getPointsBounds(dataContainer, getPosition); + this.updateMeta({bounds}); + } } // eslint-disable-next-line complexity diff --git a/test/browser/components/side-panel/layer-configurator-test.js b/test/browser/components/side-panel/layer-configurator-test.js index 49b26c5d85..0b6f4161ac 100644 --- a/test/browser/components/side-panel/layer-configurator-test.js +++ b/test/browser/components/side-panel/layer-configurator-test.js @@ -156,12 +156,21 @@ test('Components -> LayerConfigurator.mount -> LayerColumnConfig', t => { 1, 'should render 1 LayerColumnModeConfig' ); - t.equal(baseConfigGroup.find(LayerColumnConfig).length, 1, 'should render 1 LayerColumnConfig'); + t.equal(baseConfigGroup.find(LayerColumnConfig).length, 2, 'should render 2 LayerColumnConfig'); t.equal( baseConfigGroup.find(LayerColumnConfig).at(0).find(ColumnSelector).length, 4, - 'Should render 4 ColumnSelector' + 'Should render 4 ColumnSelector for Point columns' + ); + + t.equal( + baseConfigGroup + .find(LayerColumnConfig) + .at(1) + .find(ColumnSelector).length, + 1, + 'Should render 1 ColumnSelector for GeoJSON feature' ); // open fieldSelector @@ -214,7 +223,8 @@ test('Components -> LayerConfigurator.mount -> LayerColumnConfig', t => { fieldIdx: 2 }, altitude: {value: null, fieldIdx: -1, optional: true}, - neighbors: {value: null, fieldIdx: -1, optional: true} + neighbors: {value: null, fieldIdx: -1, optional: true}, + geojson: {value: null, fieldIdx: -1} } } ], @@ -247,7 +257,8 @@ test('Components -> LayerConfigurator.mount -> LayerColumnConfig', t => { // fieldIdx: 2 // }, // altitude: {value: null, fieldIdx: -1, optional: true}, - // neighbors: {value: null, fieldIdx: -1, optional: true} + // neighbors: {value: null, fieldIdx: -1, optional: true}, + // geojson: {value: null, fieldIdx: -1} // } // } // ], diff --git a/test/browser/layer-tests/point-layer-specs.js b/test/browser/layer-tests/point-layer-specs.js index c91b22d804..6d724c5765 100644 --- a/test/browser/layer-tests/point-layer-specs.js +++ b/test/browser/layer-tests/point-layer-specs.js @@ -15,12 +15,15 @@ import { pointLayerMeta, fieldDomain } from 'test/helpers/layer-utils'; +import {processGeojson} from '@kepler.gl/processors'; +import {geoJsonWithStyle, geojsonData} from 'test/fixtures/geojson'; import testArcData, {pointFromNeighbor, dataId as ArcDataId} from 'test/fixtures/test-arc-data'; import {StateWArcNeighbors} from 'test/helpers/mock-state'; -import {copyTableAndUpdate} from '@kepler.gl/table'; +import {copyTableAndUpdate, createNewDataEntry} from '@kepler.gl/table'; import {KeplerGlLayers} from '@kepler.gl/layers'; import {INITIAL_MAP_STATE} from '@kepler.gl/reducers'; import {DEFAULT_TEXT_LABEL, PROJECTED_PIXEL_SIZE_MULTIPLIER} from '@kepler.gl/constants'; +import cloneDeep from 'lodash.clonedeep'; const {PointLayer} = KeplerGlLayers; @@ -113,13 +116,11 @@ test('#PointLayer -> formatLayerData', t => { data: [ { index: 0, - position: [testRows[0][2], testRows[0][1], testRows[0][7]], - neighbors: undefined + position: [testRows[0][2], testRows[0][1], testRows[0][7]] }, { index: 4, - position: [testRows[4][2], testRows[4][1], testRows[4][7]], - neighbors: undefined + position: [testRows[4][2], testRows[4][1], testRows[4][7]] } ], getFilterValue: () => {}, @@ -225,13 +226,11 @@ test('#PointLayer -> formatLayerData', t => { data: [ { index: 0, - position: [testRows[0][2], testRows[0][1], 0], - neighbors: undefined + position: [testRows[0][2], testRows[0][1], 0] }, { index: 4, - position: [testRows[4][2], testRows[4][1], 0], - neighbors: undefined + position: [testRows[4][2], testRows[4][1], 0] } ], getFilterValue: () => {}, @@ -319,13 +318,11 @@ test('#PointLayer -> formatLayerData', t => { data: [ { index: 0, - position: [testRows[0][2], testRows[0][1], 0], - neighbors: undefined + position: [testRows[0][2], testRows[0][1], 0] }, { index: 4, - position: [testRows[4][2], testRows[4][1], 0], - neighbors: undefined + position: [testRows[4][2], testRows[4][1], 0] } ], getFilterValue: () => {}, @@ -404,13 +401,11 @@ test('#PointLayer -> formatLayerData', t => { data: [ { index: 0, - position: [testRows[0][2], testRows[0][1], 0], - neighbors: undefined + position: [testRows[0][2], testRows[0][1], 0] }, { index: 4, - position: [testRows[4][2], testRows[4][1], 0], - neighbors: undefined + position: [testRows[4][2], testRows[4][1], 0] } ], getFilterValue: () => {}, @@ -732,3 +727,386 @@ test('#PointLayer -> updateLayer', t => { testUpdateLayer(t, {layerConfig, shouldUpdate}); t.end(); }); + +test('#PointLayer -> formatLayerData -> Geojson column mode', t => { + // create a mockup GeoJson dataset with Point and MultiPoint geometry + const geoJsonWithMultiPoint = cloneDeep(geoJsonWithStyle); + geoJsonWithMultiPoint.features.push({ + type: 'Feature', + properties: { + fillColor: [1, 2, 3], + lineColor: [4, 5, 6], + lineWidth: 1, + elevation: 10, + radius: 5 + }, + geometry: { + type: 'MultiPoint', + coordinates: [ + [-122.0, 37.4], + [-121.9, 37.5] + ] + } + }); + + const geoJsonWithGeometryCollection = cloneDeep(geoJsonWithStyle); + geoJsonWithGeometryCollection.features.push({ + type: 'Feature', + properties: { + fillColor: [1, 2, 3], + lineColor: [4, 5, 6], + lineWidth: 1, + elevation: 10, + radius: 5 + }, + geometry: { + type: 'GeometryCollection', + geometries: [ + { + type: 'Point', + coordinates: [-121.8, 37.6] + }, + { + type: 'MultiPoint', + coordinates: [ + [-122.0, 37.4], + [-121.9, 37.5] + ] + } + ] + } + }); + + const geoJsonWithNull = cloneDeep(geoJsonWithStyle); + + const geojsonPointDataset = processGeojson(geoJsonWithStyle); + const geojsonPolygonDataset = processGeojson(geojsonData); + const geojsonMultiPolygonDataset = processGeojson(geoJsonWithMultiPoint); + const geojsonGeometryCollectionDataset = processGeojson(geoJsonWithGeometryCollection); + + // mockup invalid geojson object or string geojson object + const geojsonPointWithNullDataset = processGeojson(geoJsonWithNull); + geojsonPointWithNullDataset.rows.push([undefined, [7, 8, 9], [4, 5, 6], 3, 10, 5]); + geojsonPointWithNullDataset.rows.push(['', [7, 8, 9], [4, 5, 6], 3, 10, 5]); + + const TEST_CASES = [ + { + name: 'Geojson point.1', + layer: { + type: 'point', + id: 'test_geojson_layer_1', + config: { + color: [1, 2, 3], + dataId, + label: 'some geometry file', + columnMode: 'geojson', + columns: { + geojson: '_geojson' + } + } + }, + datasets: createNewDataEntry({ + info: {id: dataId}, + data: geojsonPointDataset + }), + assert: result => { + const {layerData} = result; + // ! layerData is empty here + const expectedLayerData = { + data: [ + { + index: 0, + position: [-122.1, 37.3] + }, + { + index: 1, + position: [-122.2, 37.2] + }, + { + index: 2, + position: [-122.3, 37.1] + } + ], + getFilterValue: () => {}, + getLineColor: () => {}, + getFillColor: () => {}, + getRadius: () => {}, + getPosition: () => {}, + textLabels: [] + }; + t.deepEqual( + Object.keys(layerData).sort, + Object.keys(expectedLayerData).sort, + 'layerData should have 7 keys' + ); + // data + t.deepEqual( + layerData.data, + expectedLayerData.data, + 'should format correct geojson layerData' + ); + + // getPosition + t.deepEqual( + layerData.getPosition(layerData.data[0]), + [-122.1, 37.3], + 'getPosition should return correct lat lng' + ); + } + }, + { + name: 'Geojson polygon.2', + layer: { + type: 'point', + id: 'test_geojson_layer_2', + config: { + color: [1, 2, 3], + dataId, + label: 'some geometry file', + columnMode: 'geojson', + columns: { + geojson: '_geojson' + } + } + }, + datasets: createNewDataEntry({ + info: {id: dataId}, + data: geojsonPolygonDataset + }), + assert: result => { + const {layerData} = result; + const expectedLayerData = { + data: [], + getFilterValue: () => {}, + getLineColor: () => {}, + getFillColor: () => {}, + getRadius: () => {}, + getPosition: () => {}, + textLabels: [] + }; + t.deepEqual( + Object.keys(layerData).sort, + Object.keys(expectedLayerData).sort, + 'layerData should have 7 keys' + ); + // data + t.deepEqual( + layerData.data, + expectedLayerData.data, + 'should format correct geojson layerData' + ); + // empty data since Point layer only supports GeoJson column with Point geometries + t.equal(layerData.data.length, 0, 'geojson layerData.data should be empty'); + } + }, + { + name: 'Geojson point.3', + layer: { + type: 'point', + id: 'test_geojson_layer_3', + config: { + color: [1, 2, 3], + dataId, + label: 'some geometry file', + columnMode: 'geojson', + columns: { + geojson: '_geojson' + } + } + }, + datasets: createNewDataEntry({ + info: {id: dataId}, + data: geojsonMultiPolygonDataset + }), + assert: result => { + const {layerData} = result; + const expectedLayerData = { + data: [ + { + index: 0, + position: [-122.1, 37.3] + }, + { + index: 1, + position: [-122.2, 37.2] + }, + { + index: 2, + position: [-122.3, 37.1] + }, + { + index: 3, + position: [-122.0, 37.4] + }, + { + index: 3, + position: [-121.9, 37.5] + } + ], + getFilterValue: () => {}, + getLineColor: () => {}, + getFillColor: () => {}, + getRadius: () => {}, + getPosition: () => {}, + textLabels: [] + }; + t.deepEqual( + Object.keys(layerData).sort, + Object.keys(expectedLayerData).sort, + 'layerData should have 7 keys' + ); + // data + t.deepEqual( + layerData.data, + expectedLayerData.data, + 'should format correct geojson layerData' + ); + // getPosition + t.deepEqual( + layerData.getPosition(layerData.data[0]), + [-122.1, 37.3], + 'getPosition should return correct lat lng' + ); + } + }, + { + name: 'Geojson GeometryCollection point.4', + layer: { + type: 'point', + id: 'test_geojson_layer_4', + config: { + color: [1, 2, 3], + dataId, + label: 'some geometry file', + columnMode: 'geojson', + columns: { + geojson: '_geojson' + } + } + }, + datasets: createNewDataEntry({ + info: {id: dataId}, + data: geojsonGeometryCollectionDataset + }), + assert: result => { + const {layerData} = result; + const expectedLayerData = { + data: [ + { + index: 0, + position: [-122.1, 37.3] + }, + { + index: 1, + position: [-122.2, 37.2] + }, + { + index: 2, + position: [-122.3, 37.1] + }, + { + index: 3, + position: [-121.8, 37.6] + }, + { + index: 3, + position: [-122.0, 37.4] + }, + { + index: 3, + position: [-121.9, 37.5] + } + ], + getFilterValue: () => {}, + getLineColor: () => {}, + getFillColor: () => {}, + getRadius: () => {}, + getPosition: () => {}, + textLabels: [] + }; + t.deepEqual( + Object.keys(layerData).sort, + Object.keys(expectedLayerData).sort, + 'layerData should have 7 keys' + ); + // data + t.deepEqual( + layerData.data, + expectedLayerData.data, + 'should format correct geojson layerData' + ); + // getPosition + t.deepEqual( + layerData.getPosition(layerData.data[0]), + [-122.1, 37.3], + 'getPosition should return correct lat lng' + ); + } + }, + { + name: 'Geojson with null point.5', + layer: { + type: 'point', + id: 'test_geojson_layer_5', + config: { + color: [1, 2, 3], + dataId, + label: 'some geometry file', + columnMode: 'geojson', + columns: { + geojson: '_geojson' + } + } + }, + datasets: createNewDataEntry({ + info: {id: dataId}, + data: geojsonPointWithNullDataset + }), + assert: result => { + const {layerData} = result; + const expectedLayerData = { + data: [ + { + index: 0, + position: [-122.1, 37.3] + }, + { + index: 1, + position: [-122.2, 37.2] + }, + { + index: 2, + position: [-122.3, 37.1] + } + ], + getFilterValue: () => {}, + getLineColor: () => {}, + getFillColor: () => {}, + getRadius: () => {}, + getPosition: () => {}, + textLabels: [] + }; + t.deepEqual( + Object.keys(layerData).sort, + Object.keys(expectedLayerData).sort, + 'layerData should have 7 keys' + ); + // data + t.deepEqual( + layerData.data, + expectedLayerData.data, + 'should format correct geojson layerData' + ); + // getPosition + t.deepEqual( + layerData.getPosition(layerData.data[0]), + [-122.1, 37.3], + 'getPosition should return correct lat lng' + ); + } + } + ]; + + testFormatLayerDataCases(t, PointLayer, TEST_CASES); + t.end(); +}); diff --git a/test/fixtures/state-saved-v0.js b/test/fixtures/state-saved-v0.js index 62c5943f74..f7d3b8ff26 100644 --- a/test/fixtures/state-saved-v0.js +++ b/test/fixtures/state-saved-v0.js @@ -995,6 +995,7 @@ const mergedLayer0 = new PointLayer({ id: '1eh', dataId: '9h10t7fyb', label: 'dropoff', + columnMode: 'points', color: [76, 154, 78], columns: { lat: { @@ -1119,6 +1120,7 @@ const mergedLayer2 = new PointLayer({ mergedLayer2.config = { dataId: '9h10t7fyb', label: 'begintrip', + columnMode: 'points', color: [218, 112, 191], columns: { lat: { diff --git a/test/fixtures/state-saved-v1-3.js b/test/fixtures/state-saved-v1-3.js index d4d83e8479..c26f6db73e 100644 --- a/test/fixtures/state-saved-v1-3.js +++ b/test/fixtures/state-saved-v1-3.js @@ -191,6 +191,7 @@ export const savedStateV1 = { config: { dataId: 'fm8v2jcza', label: 'restaurant', + columnMode: 'points', color: [18, 147, 154], columns: { lat: 'restaurant_lat', @@ -322,6 +323,7 @@ const mergedLayer0 = new PointLayer({ mergedLayer0.config = { dataId: 'fm8v2jcza', label: 'restaurant', + columnMode: 'points', color: [18, 147, 154], columns: { lat: { diff --git a/test/fixtures/state-saved-v1-4.js b/test/fixtures/state-saved-v1-4.js index 38f39c5461..dfb7a531bb 100644 --- a/test/fixtures/state-saved-v1-4.js +++ b/test/fixtures/state-saved-v1-4.js @@ -81,6 +81,7 @@ export const stateSavedV1 = { config: { dataId: '8ppj5gfrs', label: 'point', + columnMode: 'points', color: [23, 184, 190, 255], columns: { lat: 'point_lat', @@ -174,6 +175,7 @@ const mergedLayer0 = new PointLayer({ mergedLayer0.config = { dataId: '8ppj5gfrs', label: 'point', + columnMode: 'points', color: [23, 184, 190, 255], columns: { lat: { diff --git a/test/helpers/mock-state.js b/test/helpers/mock-state.js index 185d3c4191..4b64e49d57 100644 --- a/test/helpers/mock-state.js +++ b/test/helpers/mock-state.js @@ -751,6 +751,7 @@ export const expectedSavedLayer1 = { config: { dataId: testCsvDataId, label: 'gps_data', + columnMode: 'points', highlightColor: DEFAULT_HIGHLIGHT_COLOR, color: [0, 0, 0], columns: { @@ -809,6 +810,7 @@ export const expectedLoadedLayer1 = { config: { dataId: testCsvDataId, label: 'gps_data', + columnMode: 'points', highlightColor: DEFAULT_HIGHLIGHT_COLOR, color: [0, 0, 0], columns: { diff --git a/test/node/reducers/vis-state-test.js b/test/node/reducers/vis-state-test.js index 611562a466..f767260fdf 100644 --- a/test/node/reducers/vis-state-test.js +++ b/test/node/reducers/vis-state-test.js @@ -864,7 +864,8 @@ test('visStateReducer -> layerDataIdChangeUpdater -> validation', t => { altitude: {value: null, fieldIdx: -1, optional: true}, lat: {value: 'gps_data.lat', fieldIdx: 1}, lng: {value: 'gps_data.lng', fieldIdx: 2}, - neighbors: {value: null, fieldIdx: -1, optional: true} + neighbors: {value: null, fieldIdx: -1, optional: true}, + geojson: {value: null, fieldIdx: -1} }, 'should update point layer column' ); @@ -2026,6 +2027,7 @@ test('#visStateReducer -> setFilter.dynamicDomain & cpu', t => { const expectedLayer1 = new PointLayer({ isVisible: true, dataId: 'smoothie', + columnMode: 'points', label: 'gps_data', columns: { lat: {value: 'gps_data.lat', fieldIdx: 1}, @@ -2207,12 +2209,12 @@ test('#visStateReducer -> setFilter.dynamicDomain & cpu', t => { const expectedLayerData1 = { data: [ - {index: 17, position: [31.2165983, 30.0538936, 0], neighbors: undefined}, - {index: 18, position: [31.2148748, 30.060911, 0], neighbors: undefined}, - {index: 19, position: [31.2212278, 30.060334, 0], neighbors: undefined}, - {index: 20, position: [31.2288985, 30.0554663, 0], neighbors: undefined}, - {index: 21, position: [31.2187021, 30.0614122, 0], neighbors: undefined}, - {index: 22, position: [31.2191059, 30.0612697, 0], neighbors: undefined} + {index: 17, position: [31.2165983, 30.0538936, 0]}, + {index: 18, position: [31.2148748, 30.060911, 0]}, + {index: 19, position: [31.2212278, 30.060334, 0]}, + {index: 20, position: [31.2288985, 30.0554663, 0]}, + {index: 21, position: [31.2187021, 30.0614122, 0]}, + {index: 22, position: [31.2191059, 30.0612697, 0]} ], getPosition: () => {}, getColor: () => {},