Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: use our fork of csv2geojson to be able to parse lat/lon with commas #2263

Merged
merged 2 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"@placemarkio/tokml": "0.3.4",
"@tmcw/togeojson": "^5.8.0",
"colorbrewer": "1.5.7",
"csv2geojson": "5.1.2",
"csv2geojson": "github:umap-project/csv2geojson#patched",
"dompurify": "3.1.7",
"georsstogeojson": "^0.2.0",
"jsdom": "^24.0.0",
Expand Down
6 changes: 5 additions & 1 deletion umap/static/umap/js/modules/formatter.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ export class Formatter {
{
delimiter: 'auto',
includeLatLon: false,
sexagesimal: false,
parseLatLon: (raw) => Number.parseFloat(raw.toString().replace(',', '.')),
},
(err, result) => {
// csv2geojson fallback to null geometries when it cannot determine
Expand Down Expand Up @@ -115,7 +117,9 @@ export class Formatter {
}

async fromGeoRSS(str) {
const GeoRSSToGeoJSON = await import('../../vendors/georsstogeojson/GeoRSSToGeoJSON.js')
const GeoRSSToGeoJSON = await import(
'../../vendors/georsstogeojson/GeoRSSToGeoJSON.js'
)
return GeoRSSToGeoJSON.parse(this.toDom(str))
}

Expand Down
21 changes: 13 additions & 8 deletions umap/static/umap/vendors/csv2geojson/csv2geojson.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ function csv2geojson(x, options, callback) {
}

options.delimiter = options.delimiter || ',';
options.parseLatLon = options.parseLatLon || parseFloat;
options.sexagesimal = options.sexagesimal !== false;

var latfield = options.latfield || '',
lonfield = options.lonfield || '',
Expand Down Expand Up @@ -129,6 +131,7 @@ function csv2geojson(x, options, callback) {

if (!latfield) latfield = guessLatHeader(parsed[0]);
if (!lonfield) lonfield = guessLonHeader(parsed[0]);

var noGeometry = (!latfield || !lonfield);

if (noGeometry) {
Expand All @@ -152,13 +155,15 @@ function csv2geojson(x, options, callback) {
lonf, latf,
a;

a = sexagesimal(lonk, 'EW');
if (a) lonk = a;
a = sexagesimal(latk, 'NS');
if (a) latk = a;
if (options.sexagesimal) {
a = sexagesimal(lonk, 'EW');
if (a) lonk = a;
a = sexagesimal(latk, 'NS');
if (a) latk = a;
}

lonf = parseFloat(lonk);
latf = parseFloat(latk);
lonf = options.parseLatLon(lonk);
latf = options.parseLatLon(latk);

if (isNaN(lonf) ||
isNaN(latf)) {
Expand All @@ -179,8 +184,8 @@ function csv2geojson(x, options, callback) {
geometry: {
type: 'Point',
coordinates: [
parseFloat(lonf),
parseFloat(latf)
lonf,
latf
]
}
});
Expand Down
33 changes: 33 additions & 0 deletions umap/tests/integration/test_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,39 @@ def test_import_csv_without_valid_latlon_headers(tilelayer, live_server, page):
expect(page.locator('umap-alert div[data-level="error"]')).to_be_visible()


def test_import_csv_with_commas_in_latlon(tilelayer, live_server, page, settings):
settings.UMAP_ALLOW_ANONYMOUS = True
page.goto(f"{live_server.url}/map/new/")
page.get_by_title("Open browser").click()
layers = page.locator(".umap-browser .datalayer")
markers = page.locator(".leaflet-marker-icon")
page.get_by_title("Import data").click()
textarea = page.locator(".umap-upload textarea")
textarea.fill("lat;lon;foobar\n12,24;48,34;mypoint\n12,23;48,35;mypoint2")
page.locator('select[name="format"]').select_option("csv")
page.get_by_role("button", name="Import data", exact=True).click()
expect(layers).to_have_count(1)
expect(markers).to_have_count(2)
with page.expect_response(re.compile(r".*/datalayer/create/.*")):
page.get_by_role("button", name="Save").click()
datalayer = DataLayer.objects.last()
saved_data = json.loads(Path(datalayer.geojson.path).read_text())
assert saved_data["features"][0]["geometry"] == {
"coordinates": [
48.35,
12.23,
],
"type": "Point",
}
assert saved_data["features"][1]["geometry"] == {
"coordinates": [
48.34,
12.24,
],
"type": "Point",
}


def test_create_remote_data(page, live_server, tilelayer):
def handle(route):
route.fulfill(
Expand Down