diff --git a/CHANGELOG.md b/CHANGELOG.md index 950c3b0e8..5aaefcebf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Not released +- Use unique feature id from tileset if provided [#463](https://github.com/CartoDB/carto-react/pull/463) + ## 1.4 ### 1.4.0-alpha.4 (2022-08-02) diff --git a/packages/react-core/__tests__/filters/tileFeatures.test.js b/packages/react-core/__tests__/filters/tileFeatures.test.js index d24e1e4a6..c286032a5 100644 --- a/packages/react-core/__tests__/filters/tileFeatures.test.js +++ b/packages/react-core/__tests__/filters/tileFeatures.test.js @@ -350,7 +350,58 @@ describe('viewport features with binary mode', () => { }); describe('uniqueIdProperty is undefined', () => { - describe('dataset has cartodb_id field', () => { + describe('tiles provide unique id field', () => { + test('linestrings', () => { + const linestrings = [...Array(3)].map((_, i) => ({ + type: 'Feature', + geometry: { + type: 'LineString', + // prettier-ignore + coordinates: [[0, 0], [0, 1], [1, 2]] + }, + properties: { + other_prop: i + } + })); + + // Two tiles, linestrings[0] is present in both + const binaryData1 = geojsonToBinary([linestrings[0], linestrings[1]]); + // @ts-ignore + binaryData1.lines.fields = [{ id: 100 }, { id: 101 }]; + + const binaryData2 = geojsonToBinary([linestrings[0], linestrings[2]]); + // @ts-ignore + binaryData2.lines.fields = [{ id: 100 }, { id: 102 }]; + + const mockedTiles = [ + { + isVisible: true, + data: binaryData1, + bbox: { west, east, north, south } + }, + { + isVisible: true, + data: binaryData2, + bbox: { west, east, north, south } + } + ]; + + const properties = tileFeatures({ + tiles: mockedTiles, + viewport, + uniqueIdProperty: undefined + }); + + // prettier-ignore + expect(properties).toEqual([ + { 'other_prop': 0 }, + { 'other_prop': 1 }, + { 'other_prop': 2 } + ]); + }); + }); + + describe('features have cartodb_id field', () => { test('points', () => { const points = [...Array(3)].map((_, i) => ({ type: 'Feature', @@ -386,7 +437,7 @@ describe('viewport features with binary mode', () => { }); }); - describe('dataset has geoid field', () => { + describe('features have geoid field', () => { test('points', () => { const points = [...Array(3)].map((_, i) => ({ type: 'Feature', @@ -422,7 +473,7 @@ describe('viewport features with binary mode', () => { }); }); - describe('dataset has no cartodb_id or geoid fields', () => { + describe('no explicit id field', () => { test('points', () => { const points = [...Array(3)].map((_, i) => ({ type: 'Feature', diff --git a/packages/react-core/src/filters/tileFeaturesGeometries.js b/packages/react-core/src/filters/tileFeaturesGeometries.js index 43ae46b30..3195c23d4 100644 --- a/packages/react-core/src/filters/tileFeaturesGeometries.js +++ b/packages/react-core/src/filters/tileFeaturesGeometries.js @@ -48,8 +48,9 @@ function getFeatureId(data, startIndex) { function getPropertiesFromTile(data, startIndex) { const featureId = getFeatureId(data, startIndex); - const { properties, numericProps } = data; + const { properties, numericProps, fields } = data; const result = { + uniqueId: fields?.[featureId]?.id, properties: properties[featureId], numericProps: {} }; @@ -71,6 +72,10 @@ function getUniquePropertyValue(tileProps, uniqueIdProperty, map) { return getValueFromTileProps(tileProps, uniqueIdProperty); } + if (tileProps.uniqueId) { + return tileProps.uniqueId; + } + const artificialId = map.size + 1; // a counter, assumed as a valid new id return ( getValueFromTileProps(tileProps, 'cartodb_id') ||