From 180a2bbd507411c2394bd5d0a368b48738d1bd20 Mon Sep 17 00:00:00 2001 From: Kyle Hensel Date: Sat, 25 May 2024 16:01:04 +1000 Subject: [PATCH 01/13] render oneway arrows for the `conveying` tag --- modules/osm/tags.js | 5 +++++ modules/svg/lines.js | 13 +++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/modules/osm/tags.js b/modules/osm/tags.js index eeb40e8b1..cb77b5672 100644 --- a/modules/osm/tags.js +++ b/modules/osm/tags.js @@ -135,6 +135,11 @@ export var osmOneWayTags = { 't-bar': true, 'zip_line': true }, + 'conveying': { + 'forward': true, + 'backward': true, + 'reversible': true, + }, 'highway': { 'motorway': true }, diff --git a/modules/svg/lines.js b/modules/svg/lines.js index d380c5658..e960087f2 100644 --- a/modules/svg/lines.js +++ b/modules/svg/lines.js @@ -254,9 +254,18 @@ export function svgLines(projection, context) { var onewayArr = v.filter(function(d) { return d.isOneWay(); }); var onewaySegments = svgMarkerSegments( projection, graph, 35, - function shouldReverse(entity) { return entity.tags.oneway === '-1'; }, + function shouldReverse(entity) { + return ( + entity.tags.oneway === '-1' + || entity.tags.conveying === 'backward' + ); + }, function bothDirections(entity) { - return entity.tags.oneway === 'reversible' || entity.tags.oneway === 'alternating'; + return ( + entity.tags.oneway === 'alternating' + || entity.tags.oneway === 'reversible' + || entity.tags.conveying === 'reversible' + ); } ); onewaydata[k] = utilArrayFlatten(onewayArr.map(onewaySegments)); From c7731f5499d85692c97edca92d0ccd428ba10eaa Mon Sep 17 00:00:00 2001 From: Kyle Hensel Date: Sat, 25 May 2024 16:25:59 +1000 Subject: [PATCH 02/13] support `highway=ladder` --- css/30_highways.css | 26 ++++++++++++++++++++------ css/50_misc.css | 28 +++++++++++++++++++++------- modules/osm/tags.js | 4 ++-- modules/osm/way.js | 2 +- modules/renderer/features.js | 1 + modules/ui/fields/access.js | 6 ++++++ 6 files changed, 51 insertions(+), 16 deletions(-) diff --git a/css/30_highways.css b/css/30_highways.css index 179157129..d1f41360e 100644 --- a/css/30_highways.css +++ b/css/30_highways.css @@ -253,6 +253,7 @@ path.line.shadow.tag-highway-footway, path.line.shadow.tag-highway-cycleway, path.line.shadow.tag-highway-bridleway, path.line.shadow.tag-highway-corridor, +path.line.shadow.tag-highway-ladder, path.line.shadow.tag-highway-steps { stroke-width: 16; } @@ -261,6 +262,7 @@ path.line.casing.tag-highway-footway, path.line.casing.tag-highway-cycleway, path.line.casing.tag-highway-bridleway, path.line.casing.tag-highway-corridor, +path.line.casing.tag-highway-ladder, path.line.casing.tag-highway-steps { stroke-width: 5; } @@ -269,6 +271,7 @@ path.line.stroke.tag-highway-footway, path.line.stroke.tag-highway-cycleway, path.line.stroke.tag-highway-bridleway, path.line.stroke.tag-highway-corridor, +path.line.stroke.tag-highway-ladder, path.line.stroke.tag-highway-steps { stroke-width: 3; } @@ -306,6 +309,7 @@ path.line.stroke.tag-highway-steps { .low-zoom path.line.shadow.tag-highway-cycleway, .low-zoom path.line.shadow.tag-highway-bridleway, .low-zoom path.line.shadow.tag-highway-corridor, +.low-zoom path.line.shadow.tag-highway-ladder, .low-zoom path.line.shadow.tag-highway-steps { stroke-width: 12; } @@ -314,6 +318,7 @@ path.line.stroke.tag-highway-steps { .low-zoom path.line.casing.tag-highway-cycleway, .low-zoom path.line.casing.tag-highway-bridleway, .low-zoom path.line.casing.tag-highway-corridor, +.low-zoom path.line.casing.tag-highway-ladder, .low-zoom path.line.casing.tag-highway-steps { stroke-width: 3; } @@ -322,6 +327,7 @@ path.line.stroke.tag-highway-steps { .low-zoom path.line.stroke.tag-highway-cycleway, .low-zoom path.line.stroke.tag-highway-bridleway, .low-zoom path.line.stroke.tag-highway-corridor, +.low-zoom path.line.stroke.tag-highway-ladder, .low-zoom path.line.stroke.tag-highway-steps { stroke-width: 1; } @@ -565,27 +571,34 @@ path.line.stroke.tag-leisure-track, } /* steps */ -.preset-icon .icon.tag-highway-steps { +.preset-icon .icon.tag-highway-steps, +.preset-icon .icon.tag-highway-ladder { color: #81d25c; fill: #fff; } -path.line.stroke.tag-highway-steps { +path.line.stroke.tag-highway-steps, +path.line.stroke.tag-highway-ladder { stroke-linecap: butt; stroke-dasharray: 3, 3; } -.low-zoom path.line.stroke.tag-highway-steps { +.low-zoom path.line.stroke.tag-highway-steps, +.low-zoom path.line.stroke.tag-highway-ladder { stroke-dasharray: 2, 2; } -path.line.casing.tag-highway-steps { +path.line.casing.tag-highway-steps, +path.line.casing.tag-highway-ladder { stroke: #fff; stroke-linecap: round; stroke-dasharray: none; } path.line.stroke.tag-highway-steps, -.preset-icon-container path.line.casing.tag-highway-steps { +path.line.stroke.tag-highway-ladder, +.preset-icon-container path.line.casing.tag-highway-steps, +.preset-icon-container path.line.casing.tag-highway-ladder { stroke: #81d25c; } -.preset-icon-container path.line.stroke.tag-highway-steps { +.preset-icon-container path.line.stroke.tag-highway-steps, +.preset-icon-container path.line.stroke.tag-highway-ladder { stroke: #fff; } @@ -638,6 +651,7 @@ path.line.stroke.tag-highway.tag-footway-access_aisle { /* highway midpoints */ g.midpoint.tag-highway-corridor .fill, g.midpoint.tag-highway-steps .fill, +g.midpoint.tag-highway-ladder .fill, g.midpoint.tag-highway-path .fill, g.midpoint.tag-highway-footway .fill, g.midpoint.tag-highway-cycleway .fill, diff --git a/css/50_misc.css b/css/50_misc.css index 721aca674..7b4a2295e 100644 --- a/css/50_misc.css +++ b/css/50_misc.css @@ -287,6 +287,7 @@ path.line.shadow.tag-highway-pedestrian.tag-bridge, path.line.shadow.tag-highway-service.tag-bridge, path.line.shadow.tag-highway-track.tag-bridge, path.line.shadow.tag-highway-steps.tag-bridge, +path.line.shadow.tag-highway-ladder.tag-bridge, path.line.shadow.tag-highway-footway.tag-bridge, path.line.shadow.tag-highway-cycleway.tag-bridge, path.line.shadow.tag-highway-bridleway.tag-bridge { @@ -300,6 +301,7 @@ path.line.casing.tag-highway-pedestrian.tag-bridge, path.line.casing.tag-highway-service.tag-bridge, path.line.casing.tag-highway-track.tag-bridge, path.line.casing.tag-highway-steps.tag-bridge, +path.line.casing.tag-highway-ladder.tag-bridge, path.line.casing.tag-highway-footway.tag-bridge, path.line.casing.tag-highway-cycleway.tag-bridge, path.line.casing.tag-highway-bridleway.tag-bridge { @@ -314,6 +316,7 @@ path.line.casing.tag-highway-bridleway.tag-bridge { .low-zoom path.line.shadow.tag-highway-service.tag-bridge, .low-zoom path.line.shadow.tag-highway-track.tag-bridge, .low-zoom path.line.shadow.tag-highway-steps.tag-bridge, +.low-zoom path.line.shadow.tag-highway-ladder.tag-bridge, .low-zoom path.line.shadow.tag-highway-footway.tag-bridge, .low-zoom path.line.shadow.tag-highway-cycleway.tag-bridge, .low-zoom path.line.shadow.tag-highway-bridleway.tag-bridge { @@ -327,6 +330,7 @@ path.line.casing.tag-highway-bridleway.tag-bridge { .low-zoom path.line.casing.tag-highway-service.tag-bridge, .low-zoom path.line.casing.tag-highway-track.tag-bridge, .low-zoom path.line.casing.tag-highway-steps.tag-bridge, +.low-zoom path.line.casing.tag-highway-ladder.tag-bridge, .low-zoom path.line.casing.tag-highway-footway.tag-bridge, .low-zoom path.line.casing.tag-highway-cycleway.tag-bridge, .low-zoom path.line.casing.tag-highway-bridleway.tag-bridge { @@ -455,14 +459,18 @@ path.line.shadow.tag-highway.tag-status.tag-status-construction.tag-construction path.line.shadow.tag-highway.tag-status.tag-status-construction.tag-construction-footway, path.line.shadow.tag-highway.tag-status.tag-status-construction.tag-construction-cycleway, path.line.shadow.tag-highway.tag-status.tag-status-construction.tag-construction-bridleway, -path.line.shadow.tag-highway.tag-status.tag-status-construction.tag-construction-steps { +path.line.shadow.tag-highway.tag-status.tag-status-construction.tag-construction-corridor, +path.line.shadow.tag-highway.tag-status.tag-status-construction.tag-construction-steps, +path.line.shadow.tag-highway.tag-status.tag-status-construction.tag-construction-ladder { stroke-width: 15; } path.line.casing.tag-highway.tag-status.tag-status-construction.tag-construction-path, path.line.casing.tag-highway.tag-status.tag-status-construction.tag-construction-footway, path.line.casing.tag-highway.tag-status.tag-status-construction.tag-construction-cycleway, path.line.casing.tag-highway.tag-status.tag-status-construction.tag-construction-bridleway, -path.line.casing.tag-highway.tag-status.tag-status-construction.tag-construction-steps { +path.line.casing.tag-highway.tag-status.tag-status-construction.tag-construction-corridor, +path.line.casing.tag-highway.tag-status.tag-status-construction.tag-construction-steps, +path.line.casing.tag-highway.tag-status.tag-status-construction.tag-construction-ladder { stroke-width: 5; stroke-linecap: butt; stroke-dasharray: none @@ -471,7 +479,9 @@ path.line.stroke.tag-highway.tag-status.tag-status-construction.tag-construction path.line.stroke.tag-highway.tag-status.tag-status-construction.tag-construction-footway, path.line.stroke.tag-highway.tag-status.tag-status-construction.tag-construction-cycleway, path.line.stroke.tag-highway.tag-status.tag-status-construction.tag-construction-bridleway, -path.line.stroke.tag-highway.tag-status.tag-status-construction.tag-construction-steps { +path.line.stroke.tag-highway.tag-status.tag-status-construction.tag-construction-corridor, +path.line.stroke.tag-highway.tag-status.tag-status-construction.tag-construction-steps, +path.line.stroke.tag-highway.tag-status.tag-status-construction.tag-construction-ladder { stroke-width: 4; stroke-linecap: butt; stroke-dasharray: 10, 10; @@ -482,28 +492,32 @@ path.line.shadow.tag-highway.tag-status.tag-status-proposed.tag-proposed-path, path.line.shadow.tag-highway.tag-status.tag-status-proposed.tag-proposed-footway, path.line.shadow.tag-highway.tag-status.tag-status-proposed.tag-proposed-cycleway, path.line.shadow.tag-highway.tag-status.tag-status-proposed.tag-proposed-bridleway, -path.line.shadow.tag-highway.tag-status.tag-status-proposed.tag-proposed-steps { +path.line.shadow.tag-highway.tag-status.tag-status-proposed.tag-proposed-steps, +path.line.shadow.tag-highway.tag-status.tag-status-proposed.tag-proposed-ladder { stroke-width: 15; } path.line.casing.tag-highway.tag-status.tag-status-proposed.tag-proposed-path, path.line.casing.tag-highway.tag-status.tag-status-proposed.tag-proposed-footway, path.line.casing.tag-highway.tag-status.tag-status-proposed.tag-proposed-cycleway, path.line.casing.tag-highway.tag-status.tag-status-proposed.tag-proposed-bridleway, -path.line.casing.tag-highway.tag-status.tag-status-proposed.tag-proposed-steps { +path.line.casing.tag-highway.tag-status.tag-status-proposed.tag-proposed-steps, +path.line.casing.tag-highway.tag-status.tag-status-proposed.tag-proposed-ladder { stroke-width: 4.5; } path.line.casing.tag-highway.tag-bridge.tag-status.tag-status-proposed.tag-proposed-path, path.line.casing.tag-highway.tag-bridge.tag-status.tag-status-proposed.tag-proposed-footway, path.line.casing.tag-highway.tag-bridge.tag-status.tag-status-proposed.tag-proposed-cycleway, path.line.casing.tag-highway.tag-bridge.tag-status.tag-status-proposed.tag-proposed-bridleway, -path.line.casing.tag-highway.tag-bridge.tag-status.tag-status-proposed.tag-proposed-steps { +path.line.casing.tag-highway.tag-bridge.tag-status.tag-status-proposed.tag-proposed-steps, +path.line.casing.tag-highway.tag-bridge.tag-status.tag-status-proposed.tag-proposed-ladder { stroke-width: 10; } path.line.stroke.tag-highway.tag-status.tag-status-proposed.tag-proposed-path, path.line.stroke.tag-highway.tag-status.tag-status-proposed.tag-proposed-footway, path.line.stroke.tag-highway.tag-status.tag-status-proposed.tag-proposed-cycleway, path.line.stroke.tag-highway.tag-status.tag-status-proposed.tag-proposed-bridleway, -path.line.stroke.tag-highway.tag-status.tag-status-proposed.tag-proposed-steps { +path.line.stroke.tag-highway.tag-status.tag-status-proposed.tag-proposed-steps, +path.line.stroke.tag-highway.tag-status.tag-status-proposed.tag-proposed-ladder { stroke-width: 3; } diff --git a/modules/osm/tags.js b/modules/osm/tags.js index eeb40e8b1..88abc342a 100644 --- a/modules/osm/tags.js +++ b/modules/osm/tags.js @@ -224,11 +224,11 @@ export var osmRoutableHighwayTagValues = { motorway: true, trunk: true, primary: true, secondary: true, tertiary: true, residential: true, motorway_link: true, trunk_link: true, primary_link: true, secondary_link: true, tertiary_link: true, unclassified: true, road: true, service: true, track: true, living_street: true, bus_guideway: true, busway: true, - path: true, footway: true, cycleway: true, bridleway: true, pedestrian: true, corridor: true, steps: true + path: true, footway: true, cycleway: true, bridleway: true, pedestrian: true, corridor: true, steps: true, ladder: true }; // "highway" tag values that generally do not allow motor vehicles export var osmPathHighwayTagValues = { - path: true, footway: true, cycleway: true, bridleway: true, pedestrian: true, corridor: true, steps: true + path: true, footway: true, cycleway: true, bridleway: true, pedestrian: true, corridor: true, steps: true, ladder: true }; // "railway" tag values representing existing railroad tracks (purposely does not include 'abandoned') diff --git a/modules/osm/way.js b/modules/osm/way.js index 7b9f81921..281639d4d 100644 --- a/modules/osm/way.js +++ b/modules/osm/way.js @@ -111,7 +111,7 @@ Object.assign(osmWay.prototype, { primary_link: 4, secondary_link: 4, tertiary_link: 4, unclassified: 4, road: 4, living_street: 4, bus_guideway: 4, busway: 4, pedestrian: 4, residential: 3.5, service: 3.5, track: 3, cycleway: 2.5, - bridleway: 2, corridor: 2, steps: 2, path: 1.5, footway: 1.5 + bridleway: 2, corridor: 2, steps: 2, path: 1.5, footway: 1.5, ladder: 0.5, }, railway: { // width includes ties and rail bed, not just track gauge rail: 2.5, light_rail: 2.5, tram: 2.5, subway: 2.5, diff --git a/modules/renderer/features.js b/modules/renderer/features.js index 5ef8f0826..58a65ed5b 100644 --- a/modules/renderer/features.js +++ b/modules/renderer/features.js @@ -40,6 +40,7 @@ export function rendererFeatures(context) { 'cycleway': true, 'bridleway': true, 'steps': true, + 'ladder': true, 'pedestrian': true }; diff --git a/modules/ui/fields/access.js b/modules/ui/fields/access.js index b9867aae4..68589c470 100644 --- a/modules/ui/fields/access.js +++ b/modules/ui/fields/access.js @@ -120,6 +120,12 @@ export function uiFieldAccess(field, context) { bicycle: 'no', horse: 'no' }, + ladder: { + foot: 'yes', + motor_vehicle: 'no', + bicycle: 'no', + horse: 'no' + }, pedestrian: { foot: 'yes', motor_vehicle: 'no' From 6dcb7d5d1cac826202aba9541e975b80732889e9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 May 2024 16:09:27 +0200 Subject: [PATCH 03/13] Bump core-js-bundle from 3.37.0 to 3.37.1 (#10263) Bumps [core-js-bundle](https://github.com/zloirock/core-js/tree/HEAD/packages/core-js-bundle) from 3.37.0 to 3.37.1. - [Release notes](https://github.com/zloirock/core-js/releases) - [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md) - [Commits](https://github.com/zloirock/core-js/commits/v3.37.1/packages/core-js-bundle) --- updated-dependencies: - dependency-name: core-js-bundle dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1ac917a92..59c8b1094 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "abortcontroller-polyfill": "^1.7.5", "aes-js": "^3.1.2", "alif-toolkit": "^1.2.9", - "core-js-bundle": "^3.37.0", + "core-js-bundle": "^3.37.1", "diacritics": "1.3.0", "exifr": "^7.1.3", "fast-deep-equal": "~3.1.1", @@ -2601,9 +2601,9 @@ } }, "node_modules/core-js-bundle": { - "version": "3.37.0", - "resolved": "https://registry.npmjs.org/core-js-bundle/-/core-js-bundle-3.37.0.tgz", - "integrity": "sha512-AdUUF5R8+2ytuozAN2idBfGiDqtdsRVClilMCQSso/MBaZ+Uc4ENgzQkrRV4VRspari6L5te8sROcxGS7sncGQ==", + "version": "3.37.1", + "resolved": "https://registry.npmjs.org/core-js-bundle/-/core-js-bundle-3.37.1.tgz", + "integrity": "sha512-Bt9sorQku7bA6xoaY2NYdeaEnitLg9peHJ+eAijrARCQ5FhkoUW1eF4oI35XfP9kyeyljw71uCud4ju8tjGhsg==", "hasInstallScript": true, "funding": { "type": "opencollective", @@ -10649,9 +10649,9 @@ "dev": true }, "core-js-bundle": { - "version": "3.37.0", - "resolved": "https://registry.npmjs.org/core-js-bundle/-/core-js-bundle-3.37.0.tgz", - "integrity": "sha512-AdUUF5R8+2ytuozAN2idBfGiDqtdsRVClilMCQSso/MBaZ+Uc4ENgzQkrRV4VRspari6L5te8sROcxGS7sncGQ==" + "version": "3.37.1", + "resolved": "https://registry.npmjs.org/core-js-bundle/-/core-js-bundle-3.37.1.tgz", + "integrity": "sha512-Bt9sorQku7bA6xoaY2NYdeaEnitLg9peHJ+eAijrARCQ5FhkoUW1eF4oI35XfP9kyeyljw71uCud4ju8tjGhsg==" }, "core-util-is": { "version": "1.0.3", diff --git a/package.json b/package.json index 1546a0f83..f00c5a2b0 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "abortcontroller-polyfill": "^1.7.5", "aes-js": "^3.1.2", "alif-toolkit": "^1.2.9", - "core-js-bundle": "^3.37.0", + "core-js-bundle": "^3.37.1", "diacritics": "1.3.0", "exifr": "^7.1.3", "fast-deep-equal": "~3.1.1", From 342a03bcfe0c0b9eaee0c4b840f68f2e451e4d63 Mon Sep 17 00:00:00 2001 From: Martin Raifer Date: Tue, 28 May 2024 20:06:55 +0200 Subject: [PATCH 04/13] allow type/id syntax in id hash param, and add support for notes --- API.md | 2 +- CHANGELOG.md | 1 + modules/behavior/hash.js | 29 +++++++++++++++++++-------- modules/core/context.js | 41 +++++++++++++++++++++++++++++--------- modules/renderer/map.js | 14 +++++++++++-- modules/ui/feature_list.js | 16 +-------------- 6 files changed, 68 insertions(+), 35 deletions(-) diff --git a/API.md b/API.md index 2646035ff..64670d9c3 100644 --- a/API.md +++ b/API.md @@ -29,7 +29,7 @@ of iD (e.g. `https://ideditor-release.netlify.app`), the following parameters ar optional and will be added automatically. (Note that hashtag-like strings are automatically detected in the `comment`).
_Example:_ `hashtags=%23hotosm-task-592,%23MissingMaps` -* __`id`__ - The character 'n', 'w', or 'r', followed by the OSM ID of a node, way or relation, respectively. Selects the specified entity, and, unless a `map` parameter is also provided, centers the map on it.
+* __`id`__ - Selects the specified OSM node, way, relation or note, and, unless a `map` parameter is also provided, centers the map on it. Supported formats are: a) `[nwr]` where the character 'n', 'w', or 'r' correspond to a OSM node, way or relation, repectively; or b) `/` which also allows to specify OSM notes (example: `note/1`).
_Example:_ `id=n1207480649` * __`locale`__ - A code specifying the localization to use, affecting the language, layout, and keyboard shortcuts. Multiple codes may be specified in order of preference. The first valid code will be the locale, while the rest will be used as fallbacks if certain text hasn't been translated. The default locale preferences are set by the browser.
_Example:_ `locale=ja`, `locale=pt-BR`, `locale=nl,fr,de`
diff --git a/CHANGELOG.md b/CHANGELOG.md index aef6a67da..d190ed4c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ _Breaking developer changes, which may affect downstream projects or sites that # Unreleased (2.30.0-dev) #### :tada: New Features +* Allow to start up iD with a preselected OSM note or multiselection of OSM ids in the `id` hash parameter #### :sparkles: Usability & Accessibility * Login/logout pages are now using the user's locale ([#3595], thanks [@k-yle]) * Sort preset-specific optional fields before universal fields in "Add field" dropdown ([#10181], thanks [@zbycz]) diff --git a/modules/behavior/hash.js b/modules/behavior/hash.js index 65a785b80..b0e61da05 100644 --- a/modules/behavior/hash.js +++ b/modules/behavior/hash.js @@ -4,12 +4,13 @@ import { select as d3_select } from 'd3-selection'; import { geoSphericalDistance } from '../geo'; import { modeBrowse } from '../modes/browse'; -import { modeSelect } from '../modes/select'; +import { modeSelect, modeSelectNote } from '../modes'; import { utilDisplayLabel, utilObjectOmit, utilQsString, utilStringQs } from '../util'; import { utilArrayIdentical } from '../util/array'; import { t } from '../core/localizer'; import { prefs } from '../core/preferences'; + export function behaviorHash(context) { // cached window.location.hash @@ -33,6 +34,8 @@ export function behaviorHash(context) { }); if (selected.length) { newParams.id = selected.join(','); + } else if (context.selectedNoteID()) { + newParams.id = `note/${context.selectedNoteID()}`; } newParams.map = zoom.toFixed(2) + @@ -147,11 +150,14 @@ export function behaviorHash(context) { if (q.id && mode) { var ids = q.id.split(',').filter(function(id) { - return context.hasEntity(id); + return context.hasEntity(id) || id.startsWith('note/'); }); - if (ids.length && - (mode.id === 'browse' || (mode.id === 'select' && !utilArrayIdentical(mode.selectedIDs(), ids)))) { - context.enter(modeSelect(context, ids)); + if (ids.length && ['browse', 'select-note', 'select'].includes(mode.id)) { + if (ids.length === 1 && ids[0].startsWith('note/')) { + context.enter(modeSelectNote(context, ids[0])); + } else if (!utilArrayIdentical(mode.selectedIDs(), ids)) { + context.enter(modeSelect(context, ids)); + } return; } } @@ -185,10 +191,17 @@ export function behaviorHash(context) { var q = utilStringQs(window.location.hash); if (q.id) { - //if (!context.history().hasRestorableChanges()) { // targeting specific features: download, select, and zoom to them - context.zoomToEntity(q.id.split(',')[0], !q.map); - //} + const selectIds = q.id.split(','); + if (selectIds.length === 1 && selectIds[0].startsWith('note/')) { + const noteId = selectIds[0].split('/')[1]; + context.zoomToNote(noteId, !q.map); + } else { + context.zoomToEntities( + // convert ids to short form id: node/123 -> n123 + selectIds.map(id => id.replace(/([nwr])[^/]*\//, '$1')), + !q.map); + } } if (q.walkthrough === 'true') { diff --git a/modules/core/context.js b/modules/core/context.js index 73b9e9219..fc9a76e4d 100644 --- a/modules/core/context.js +++ b/modules/core/context.js @@ -1,4 +1,5 @@ import _debounce from 'lodash-es/debounce'; +import _throttle from 'lodash-es/throttle'; import { dispatch as d3_dispatch } from 'd3-dispatch'; import { json as d3_json } from 'd3-fetch'; @@ -14,7 +15,7 @@ import { coreHistory } from './history'; import { coreValidator } from './validator'; import { coreUploader } from './uploader'; import { geoRawMercator } from '../geo/raw_mercator'; -import { modeSelect } from '../modes/select'; +import { modeSelect, modeSelectNote } from '../modes'; import { presetManager } from '../presets'; import { rendererBackground, rendererFeatures, rendererMap, rendererPhotos } from '../renderer'; import { services } from '../services'; @@ -176,6 +177,7 @@ export function coreContext() { _connection.loadEntityRelations(entityID, afterLoad(cid, callback)); } }; + // Download single note context.loadNote = (entityID, callback) => { if (_connection) { @@ -185,23 +187,26 @@ export function coreContext() { }; context.zoomToEntity = (entityID, zoomTo) => { + context.zoomToEntities([entityID], zoomTo); + }; + context.zoomToEntities = (entityIDs, zoomTo) => { // be sure to load the entity even if we're not going to zoom to it - context.loadEntity(entityID, (err, result) => { + let loadedEntities = []; + const throttledZoomTo = _throttle(() => _map.zoomTo(loadedEntities), 500); + entityIDs.forEach(entityID => context.loadEntity(entityID, (err, result) => { if (err) return; + loadedEntities.push(result.data.find(e => e.id === entityID)); if (zoomTo !== false) { - const entity = result.data.find(e => e.id === entityID); - if (entity) { - _map.zoomTo(entity); - } + throttledZoomTo(); } - }); + })); _map.on('drawn.zoomToEntity', () => { - if (!context.hasEntity(entityID)) return; + if (!entityIDs.every(entityID => context.hasEntity(entityID))) return; _map.on('drawn.zoomToEntity', null); context.on('enter.zoomToEntity', null); - context.enter(modeSelect(context, [entityID])); + context.enter(modeSelect(context, entityIDs)); }); context.on('enter.zoomToEntity', () => { @@ -212,6 +217,24 @@ export function coreContext() { }); }; + context.zoomToNote = (noteId, zoomTo) => { + context.loadNote(noteId, (err, result) => { + if (err) return; + if (zoomTo === false) return; + const entity = result.data.find(e => e.id === noteId); + if (entity) { + // zoom to, used note loc + const note = services.osm.getNote(noteId); + context.map().centerZoom(note.loc,15); + // open note layer + const noteLayer = context.layers().layer('notes'); + noteLayer.enabled(true); + // select the note + context.enter(modeSelectNote(context, noteId)); + } + }); + }; + let _minEditableZoom = 16; context.minEditableZoom = function(val) { if (!arguments.length) return _minEditableZoom; diff --git a/modules/renderer/map.js b/modules/renderer/map.js index e14a7fb95..0e5a7127c 100644 --- a/modules/renderer/map.js +++ b/modules/renderer/map.js @@ -17,6 +17,7 @@ import { utilGetDimensions } from '../util/dimensions'; import { utilRebind } from '../util/rebind'; import { utilZoomPan } from '../util/zoom_pan'; import { utilDoubleUp } from '../util/double_up'; +import { isArray } from 'lodash-es'; // constants var TILESIZE = 256; @@ -908,8 +909,17 @@ export function rendererMap(context) { }; - map.zoomTo = function(entity) { - var extent = entity.extent(context.graph()); + map.zoomTo = function(entities) { + if (!isArray(entities)) { + entities = [entities]; + } + + if (entities.length === 0) return map; + + var extent = entities + .map(entity => entity.extent(context.graph())) + .reduce((a, b) => a.extend(b)); + if (!isFinite(extent.area())) return map; var z2 = clamp(map.trimmedExtentZoom(extent), 0, 20); diff --git a/modules/ui/feature_list.js b/modules/ui/feature_list.js index b57747294..c7cd95523 100644 --- a/modules/ui/feature_list.js +++ b/modules/ui/feature_list.js @@ -15,7 +15,6 @@ import { isColourValid } from '../osm/tags'; import { services } from '../services'; import { svgIcon } from '../svg/icon'; import { uiCmd } from './cmd'; -import { modeSelectNote } from '../modes'; import { utilDisplayName, @@ -366,20 +365,7 @@ export function uiFeatureList(context) { const noteId = d.id.replace(/\D/g, ''); // load note - context.loadNote(noteId, (err, result) => { - if (err) return; - const entity = result.data.find(e => e.id === noteId); - if (entity) { - // zoom to, used note loc - const note = services.osm.getNote(noteId); - context.map().centerZoom(note.loc,15); - // open note layer - const noteLayer = context.layers().layer('notes'); - noteLayer.enabled(true); - // select the note - context.enter(modeSelectNote(context, noteId)); - } - }); + context.zoomToNote(noteId); } else { // download, zoom to, and select the entity with the given ID context.zoomToEntity(d.id); From 1e9a4631955c0cc50c4433faa068abeaa3fb3f8b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 May 2024 15:08:55 +0200 Subject: [PATCH 05/13] Bump osm-community-index from 5.7.0 to 5.7.1 (#10266) Bumps [osm-community-index](https://github.com/osmlab/osm-community-index) from 5.7.0 to 5.7.1. - [Release notes](https://github.com/osmlab/osm-community-index/releases) - [Changelog](https://github.com/osmlab/osm-community-index/blob/main/CHANGELOG.md) - [Commits](https://github.com/osmlab/osm-community-index/compare/v5.7.0...v5.7.1) --- updated-dependencies: - dependency-name: osm-community-index dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index 59c8b1094..237b3692e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -76,7 +76,7 @@ "mocha": "^10.4.0", "name-suggestion-index": "~6.0", "npm-run-all": "^4.0.0", - "osm-community-index": "~5.7.0", + "osm-community-index": "~5.7.1", "postcss": "^8.4.38", "postcss-selector-prepend": "^0.5.0", "shelljs": "^0.8.0", @@ -6619,9 +6619,9 @@ } }, "node_modules/osm-community-index": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/osm-community-index/-/osm-community-index-5.7.0.tgz", - "integrity": "sha512-r5h58L9mGh2Wu4XcJoGKLdw3oBY41jWAMUVBNE9tBS9sZINwSZccrImhxuOS5DmpslTjZ6w1cn7x9sE8tnFGpQ==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/osm-community-index/-/osm-community-index-5.7.1.tgz", + "integrity": "sha512-E+Xib5m//WliNq2iqeUXyKqZk7yhZu/vSJbwwyxDAPzcNWxgIMoO0B7cUMeFNckhMQsKM2UuC2BAjWuVfbYf1Q==", "dev": true, "dependencies": { "diacritics": "^1.3.0" @@ -13356,9 +13356,9 @@ "integrity": "sha512-w3NnYbt+0PIih2Kwr1sLfQWehdLbcA3gZNJhX4VOBfeRtvm30iZA3nURphuZDokZ8Kmdv4LWB+AiIng2b+KvIA==" }, "osm-community-index": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/osm-community-index/-/osm-community-index-5.7.0.tgz", - "integrity": "sha512-r5h58L9mGh2Wu4XcJoGKLdw3oBY41jWAMUVBNE9tBS9sZINwSZccrImhxuOS5DmpslTjZ6w1cn7x9sE8tnFGpQ==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/osm-community-index/-/osm-community-index-5.7.1.tgz", + "integrity": "sha512-E+Xib5m//WliNq2iqeUXyKqZk7yhZu/vSJbwwyxDAPzcNWxgIMoO0B7cUMeFNckhMQsKM2UuC2BAjWuVfbYf1Q==", "dev": true, "requires": { "diacritics": "^1.3.0" diff --git a/package.json b/package.json index f00c5a2b0..a89668910 100644 --- a/package.json +++ b/package.json @@ -111,7 +111,7 @@ "mocha": "^10.4.0", "name-suggestion-index": "~6.0", "npm-run-all": "^4.0.0", - "osm-community-index": "~5.7.0", + "osm-community-index": "~5.7.1", "postcss": "^8.4.38", "postcss-selector-prepend": "^0.5.0", "shelljs": "^0.8.0", From 3087b1a6609cb44ceeca650550c08ff7d2a2425e Mon Sep 17 00:00:00 2001 From: Nathan Hadley <116459177+linfindel@users.noreply.github.com> Date: Wed, 29 May 2024 14:10:17 +0100 Subject: [PATCH 06/13] Fix typo (#10264) --- API.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/API.md b/API.md index 64670d9c3..551a224f3 100644 --- a/API.md +++ b/API.md @@ -29,7 +29,7 @@ of iD (e.g. `https://ideditor-release.netlify.app`), the following parameters ar optional and will be added automatically. (Note that hashtag-like strings are automatically detected in the `comment`).
_Example:_ `hashtags=%23hotosm-task-592,%23MissingMaps` -* __`id`__ - Selects the specified OSM node, way, relation or note, and, unless a `map` parameter is also provided, centers the map on it. Supported formats are: a) `[nwr]` where the character 'n', 'w', or 'r' correspond to a OSM node, way or relation, repectively; or b) `/` which also allows to specify OSM notes (example: `note/1`).
+* __`id`__ - Selects the specified OSM node, way, relation or note, and, unless a `map` parameter is also provided, centers the map on it. Supported formats are: a) `[nwr]` where the character 'n', 'w', or 'r' correspond to a OSM node, way or relation, respectively; or b) `/` which also allows to specify OSM notes (example: `note/1`).
_Example:_ `id=n1207480649` * __`locale`__ - A code specifying the localization to use, affecting the language, layout, and keyboard shortcuts. Multiple codes may be specified in order of preference. The first valid code will be the locale, while the rest will be used as fallbacks if certain text hasn't been translated. The default locale preferences are set by the browser.
_Example:_ `locale=ja`, `locale=pt-BR`, `locale=nl,fr,de`
From 379be391a3fa8c95c2b142a3ce224d060bd4cebc Mon Sep 17 00:00:00 2001 From: Martin Raifer Date: Fri, 31 May 2024 14:14:26 +0200 Subject: [PATCH 07/13] fix crash in zoomToEntity when entity has parent relations --- modules/core/context.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/core/context.js b/modules/core/context.js index fc9a76e4d..8e6fdd655 100644 --- a/modules/core/context.js +++ b/modules/core/context.js @@ -196,7 +196,9 @@ export function coreContext() { const throttledZoomTo = _throttle(() => _map.zoomTo(loadedEntities), 500); entityIDs.forEach(entityID => context.loadEntity(entityID, (err, result) => { if (err) return; - loadedEntities.push(result.data.find(e => e.id === entityID)); + const entity = result.data.find(e => e.id === entityID); + if (!entity) return; + loadedEntities.push(entity); if (zoomTo !== false) { throttledZoomTo(); } From b45c021a9d43c4d98d5a17cc029034163aa96e0a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 5 Jun 2024 12:39:57 +0200 Subject: [PATCH 08/13] Bump eslint from 9.3.0 to 9.4.0 (#10269) Bumps [eslint](https://github.com/eslint/eslint) from 9.3.0 to 9.4.0. - [Release notes](https://github.com/eslint/eslint/releases) - [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md) - [Commits](https://github.com/eslint/eslint/compare/v9.3.0...v9.4.0) --- updated-dependencies: - dependency-name: eslint dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 111 ++++++++++++++++++++++++---------------------- package.json | 2 +- 2 files changed, 58 insertions(+), 55 deletions(-) diff --git a/package-lock.json b/package-lock.json index 237b3692e..37e6bdc4d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -59,7 +59,7 @@ "editor-layer-index": "github:osmlab/editor-layer-index#gh-pages", "esbuild": "^0.21.4", "esbuild-visualizer": "^0.6.0", - "eslint": "^9.3.0", + "eslint": "^9.4.0", "fetch-mock": "^9.11.0", "gaze": "^1.1.3", "glob": "^10.4.1", @@ -984,6 +984,20 @@ "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/config-array": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.15.1.tgz", + "integrity": "sha512-K4gzNq+yymn/EVsXYmf+SBcBro8MTf+aXJZUphM96CdzUEr+ClGDvAbpmaEK+cGVigVXIgs9gNmvHAlrzzY5JQ==", + "dev": true, + "dependencies": { + "@eslint/object-schema": "^2.1.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", @@ -1008,9 +1022,18 @@ } }, "node_modules/@eslint/js": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.3.0.tgz", - "integrity": "sha512-niBqk8iwv96+yuTwjM6bWg8ovzAPF9qkICsGtcoa5/dmqcEMfdwNAX7+/OHcJHc7wj7XqPxH98oAHytFYlw6Sw==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.4.0.tgz", + "integrity": "sha512-fdI7VJjP3Rvc70lC4xkFXHB0fiPeojiL1PxVG6t1ZvXQrarj893PweuBTujxDUFk0Fxj4R7PIIAZ/aiiyZPZcg==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.3.tgz", + "integrity": "sha512-HAbhAYKfsAC2EkTqve00ibWIZlaU74Z1EHwAjYr4PXF0YU2VEA1zSIKSSpKszRLRWwHzzRZXvK632u+uXzvsvw==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1108,20 +1131,6 @@ "node": ">=6" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "dev": true, @@ -1134,12 +1143,6 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "dev": true - }, "node_modules/@humanwhocodes/retry": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", @@ -3666,16 +3669,16 @@ } }, "node_modules/eslint": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.3.0.tgz", - "integrity": "sha512-5Iv4CsZW030lpUqHBapdPo3MJetAPtejVW8B84GIcIIv8+ohFaddXsrn1Gn8uD9ijDb+kcYKFUVmC8qG8B2ORQ==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.4.0.tgz", + "integrity": "sha512-sjc7Y8cUD1IlwYcTS9qPSvGjAC8Ne9LctpxKKu3x/1IC9bnOg98Zy6GxEJUfr1NojMgVPlyANXYns8oE2c1TAA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", + "@eslint/config-array": "^0.15.1", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.3.0", - "@humanwhocodes/config-array": "^0.13.0", + "@eslint/js": "9.4.0", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", @@ -9580,6 +9583,17 @@ "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", "dev": true }, + "@eslint/config-array": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.15.1.tgz", + "integrity": "sha512-K4gzNq+yymn/EVsXYmf+SBcBro8MTf+aXJZUphM96CdzUEr+ClGDvAbpmaEK+cGVigVXIgs9gNmvHAlrzzY5JQ==", + "dev": true, + "requires": { + "@eslint/object-schema": "^2.1.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + } + }, "@eslint/eslintrc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", @@ -9598,9 +9612,15 @@ } }, "@eslint/js": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.3.0.tgz", - "integrity": "sha512-niBqk8iwv96+yuTwjM6bWg8ovzAPF9qkICsGtcoa5/dmqcEMfdwNAX7+/OHcJHc7wj7XqPxH98oAHytFYlw6Sw==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.4.0.tgz", + "integrity": "sha512-fdI7VJjP3Rvc70lC4xkFXHB0fiPeojiL1PxVG6t1ZvXQrarj893PweuBTujxDUFk0Fxj4R7PIIAZ/aiiyZPZcg==", + "dev": true + }, + "@eslint/object-schema": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.3.tgz", + "integrity": "sha512-HAbhAYKfsAC2EkTqve00ibWIZlaU74Z1EHwAjYr4PXF0YU2VEA1zSIKSSpKszRLRWwHzzRZXvK632u+uXzvsvw==", "dev": true }, "@fortawesome/fontawesome-svg-core": { @@ -9671,27 +9691,10 @@ } } }, - "@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - } - }, "@humanwhocodes/module-importer": { "version": "1.0.1", "dev": true }, - "@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "dev": true - }, "@humanwhocodes/retry": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", @@ -11355,16 +11358,16 @@ } }, "eslint": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.3.0.tgz", - "integrity": "sha512-5Iv4CsZW030lpUqHBapdPo3MJetAPtejVW8B84GIcIIv8+ohFaddXsrn1Gn8uD9ijDb+kcYKFUVmC8qG8B2ORQ==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.4.0.tgz", + "integrity": "sha512-sjc7Y8cUD1IlwYcTS9qPSvGjAC8Ne9LctpxKKu3x/1IC9bnOg98Zy6GxEJUfr1NojMgVPlyANXYns8oE2c1TAA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", + "@eslint/config-array": "^0.15.1", "@eslint/eslintrc": "^3.1.0", - "@eslint/js": "9.3.0", - "@humanwhocodes/config-array": "^0.13.0", + "@eslint/js": "9.4.0", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", diff --git a/package.json b/package.json index a89668910..63fc40710 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ "editor-layer-index": "github:osmlab/editor-layer-index#gh-pages", "esbuild": "^0.21.4", "esbuild-visualizer": "^0.6.0", - "eslint": "^9.3.0", + "eslint": "^9.4.0", "fetch-mock": "^9.11.0", "gaze": "^1.1.3", "glob": "^10.4.1", From 3b9b622294082119cb85952d9e430f2fee4242e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ky=E2=84=93e=20Hensel?= Date: Wed, 5 Jun 2024 20:53:42 +1000 Subject: [PATCH 09/13] fix wikidata styling not applying to vertices (#10258) --- css/20_map.css | 6 ++++-- modules/svg/vertices.js | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/css/20_map.css b/css/20_map.css index a7122ce2a..8f2f6b138 100644 --- a/css/20_map.css +++ b/css/20_map.css @@ -294,12 +294,14 @@ text.point { /* Wikidata-tagged */ -g.point.tag-wikidata path.stroke { +g.point.tag-wikidata path.stroke, +g.vertex.tag-wikidata circle.stroke { stroke-width: 2px; stroke: #666; fill: #eee; } -g.point.tag-wikidata .icon { +g.point.tag-wikidata .icon, +g.vertex.tag-wikidata .icon { color: #666; } diff --git a/modules/svg/vertices.js b/modules/svg/vertices.js index 21e18c581..172b8df0a 100644 --- a/modules/svg/vertices.js +++ b/modules/svg/vertices.js @@ -5,6 +5,7 @@ import { presetManager } from '../presets'; import { geoScaleToZoom } from '../geo'; import { osmEntity } from '../osm'; import { svgPassiveVertex, svgPointTransform } from './helpers'; +import { svgTagClasses } from './tag_classes'; export function svgVertices(projection, context) { var radiuses = { @@ -140,6 +141,7 @@ export function svgVertices(projection, context) { .classed('retagged', function(d) { return base.entities[d.id] && !deepEqual(graph.entities[d.id].tags, base.entities[d.id].tags); }) + .call(svgTagClasses()) .call(updateAttributes); // Vertices with icons get a `use`. From b2fc4a43c03c96b111d121ed75840fb2c1b2c41d Mon Sep 17 00:00:00 2001 From: Dimitar <19364673+Dimitar5555@users.noreply.github.com> Date: Wed, 5 Jun 2024 15:47:19 +0300 Subject: [PATCH 10/13] Consider lifecycle prefixed tags in Future/Past features (#10228) and sharpen landuse filter --- CHANGELOG.md | 3 +++ modules/renderer/features.js | 18 ++++++++++++------ test/spec/renderer/features.js | 5 +++-- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13f1ca900..87c99f6cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,8 @@ _Breaking developer changes, which may affect downstream projects or sites that * Fix bug which required a second button click when resolving/reopening of OSM notes ([#8994], thanks [@laigyu]) * Fix API URLs for ImproveOSM QA service ([#9993], thanks [@k-yle]) * Fix icons with inline css styles not properly being displayed on osm.org +* Properly sort map features with lifecycle prefixes in the _Past/Futures_ features ([#7582]) +* Only consider features with either `landuse`, `natural`, `amentiy` or `leisure` tag to be classified as _Landuse_ areas #### :earth_asia: Localization #### :hourglass: Performance #### :mortar_board: Walkthrough / Help @@ -60,6 +62,7 @@ _Breaking developer changes, which may affect downstream projects or sites that * Update dependencies, including `osm-community-index` to v5.7, `osm-auth` to v2.5 [#3595]: https://github.com/openstreetmap/iD/issues/3595 +[#7582]: https://github.com/openstreetmap/iD/issues/7582 [#8994]: https://github.com/openstreetmap/iD/issues/8994 [#9993]: https://github.com/openstreetmap/iD/issues/9993 [#10181]: https://github.com/openstreetmap/iD/pull/10181 diff --git a/modules/renderer/features.js b/modules/renderer/features.js index 58a65ed5b..232e4a5ce 100644 --- a/modules/renderer/features.js +++ b/modules/renderer/features.js @@ -132,7 +132,12 @@ export function rendererFeatures(context) { }); defineRule('landuse', function isLanduse(tags, geometry) { - return geometry === 'area' && + return geometry === 'area' && ( + !!tags.landuse || + !!tags.natural || + !!tags.leisure || + !!tags.amenity + ) && !_rules.buildings.filter(tags) && !_rules.building_parts.filter(tags) && !_rules.indoor.filter(tags) && @@ -188,7 +193,7 @@ export function rendererFeatures(context) { return tags['piste:type']; }); - defineRule('aerialways', function isPiste(tags) { + defineRule('aerialways', function isAerialways(tags) { return tags.aerialway && tags.aerialway !== 'yes' && tags.aerialway !== 'station'; @@ -206,11 +211,12 @@ export function rendererFeatures(context) { paths[tags.highway] ) { return false; } - var strings = Object.keys(tags); + const keys = Object.keys(tags); - for (var i = 0; i < strings.length; i++) { - var s = strings[i]; - if (osmLifecyclePrefixes[s] || osmLifecyclePrefixes[tags[s]]) return true; + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + const s = key.split(':')[0]; + if (osmLifecyclePrefixes[s] || osmLifecyclePrefixes[tags[key]]) return true; } return false; }); diff --git a/test/spec/renderer/features.js b/test/spec/renderer/features.js index 76752ea28..addbe2e7c 100644 --- a/test/spec/renderer/features.js +++ b/test/spec/renderer/features.js @@ -152,6 +152,7 @@ describe('iD.rendererFeatures', function() { iD.osmWay({id: 'scrub', tags: {area: 'yes', natural: 'scrub'}, version: 1}), iD.osmWay({id: 'industrial', tags: {area: 'yes', landuse: 'industrial'}, version: 1}), iD.osmWay({id: 'parkinglot', tags: {area: 'yes', amenity: 'parking', parking: 'surface'}, version: 1}), + iD.osmWay({id: 'park', tags: {area: 'yes', leisure: 'park', parking: 'surface'}, version: 1}), // Landuse Multipolygon iD.osmWay({id: 'outer', version: 1}), @@ -550,13 +551,13 @@ describe('iD.rendererFeatures', function() { }); it('hides uninteresting (e.g. untagged or "other") member ways on a hidden multipolygon relation', function() { - var outer = iD.osmWay({id: 'outer', tags: {area: 'yes', natural: 'wood'}, version: 1}); + var outer = iD.osmWay({id: 'outer', tags: {}, version: 1}); var inner1 = iD.osmWay({id: 'inner1', tags: {barrier: 'fence'}, version: 1}); var inner2 = iD.osmWay({id: 'inner2', version: 1}); var inner3 = iD.osmWay({id: 'inner3', tags: {highway: 'residential'}, version: 1}); var r = iD.osmRelation({ id: 'r', - tags: {type: 'multipolygon'}, + tags: {type: 'multipolygon', natural: 'wood'}, members: [ {id: outer.id, role: 'outer', type: 'way'}, {id: inner1.id, role: 'inner', type: 'way'}, From 97d1aa5e2d003b8fb21924b536ca87c4eb3257b9 Mon Sep 17 00:00:00 2001 From: Martin Raifer Date: Wed, 5 Jun 2024 19:41:56 +0200 Subject: [PATCH 11/13] Fix address field overwriting existing data when switching features fixes #12060 This bug can occur occasionally under the following circumstances: * map feature 1 is selected * the cursor is in an address (sub) field * map feature 2 gets selected directly * now, in some cases, the contents of the address fields of feature 2 are written into feature 1's tags --- CHANGELOG.md | 2 ++ modules/ui/fields/address.js | 45 ++++++++++++++++++------------------ 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87c99f6cc..8b56b93d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,6 +52,7 @@ _Breaking developer changes, which may affect downstream projects or sites that * Fix icons with inline css styles not properly being displayed on osm.org * Properly sort map features with lifecycle prefixes in the _Past/Futures_ features ([#7582]) * Only consider features with either `landuse`, `natural`, `amentiy` or `leisure` tag to be classified as _Landuse_ areas +* Fix address field overwriting existing data when switching selected map features under certain circumstances ([#10260]) #### :earth_asia: Localization #### :hourglass: Performance #### :mortar_board: Walkthrough / Help @@ -68,6 +69,7 @@ _Breaking developer changes, which may affect downstream projects or sites that [#10181]: https://github.com/openstreetmap/iD/pull/10181 [#10255]: https://github.com/openstreetmap/iD/pull/10255 [#10257]: https://github.com/openstreetmap/iD/pull/10257 +[#10260]: https://github.com/openstreetmap/iD/issues/10260 [@zbycz]: https://github.com/zbycz diff --git a/modules/ui/fields/address.js b/modules/ui/fields/address.js index bbde62162..27cdbb1d1 100644 --- a/modules/ui/fields/address.js +++ b/modules/ui/fields/address.js @@ -6,7 +6,7 @@ import { presetManager } from '../../presets'; import { fileFetcher } from '../../core/file_fetcher'; import { geoExtent, geoChooseEdge, geoSphericalDistance } from '../../geo'; import { uiCombobox } from '../combobox'; -import { utilArrayUniqBy, utilGetSetValue, utilNoAuto, utilRebind, utilTotalExtent } from '../../util'; +import { utilArrayUniqBy, utilGetSetValue, utilNoAuto, utilRebind, utilTotalExtent, utilTriggerEvent } from '../../util'; import { t } from '../../core/localizer'; @@ -235,6 +235,7 @@ export function uiFieldAddress(field, context) { if (d.isAutoStreetPlace) { // set subtag depending on selected entry d.id = selected ? selected.type : 'street'; + utilTriggerEvent(d3_select(this), 'change'); } }) ); @@ -283,35 +284,33 @@ export function uiFieldAddress(field, context) { function change(onInput) { return function() { - setTimeout(() => { - var tags = {}; + var tags = {}; - _wrap.selectAll('input') - .each(function (subfield) { - var key = field.key + ':' + subfield.id; + _wrap.selectAll('input') + .each(function (subfield) { + var key = field.key + ':' + subfield.id; - var value = this.value; - if (!onInput) value = context.cleanTagValue(value); + var value = this.value; + if (!onInput) value = context.cleanTagValue(value); - // don't override multiple values with blank string - if (Array.isArray(_tags[key]) && !value) return; + // don't override multiple values with blank string + if (Array.isArray(_tags[key]) && !value) return; - if (subfield.isAutoStreetPlace) { - if (subfield.id === 'street') { - tags[`${field.key}:place`] = undefined; - } else if (subfield.id === 'place') { - tags[`${field.key}:street`] = undefined; - } + if (subfield.isAutoStreetPlace) { + if (subfield.id === 'street') { + tags[`${field.key}:place`] = undefined; + } else if (subfield.id === 'place') { + tags[`${field.key}:street`] = undefined; } + } - tags[key] = value || undefined; - }); + tags[key] = value || undefined; + }); - Object.keys(tags) - .filter(k => tags[k]) - .forEach(k => _tags[k] = tags[k]); - dispatch.call('change', this, tags, onInput); - }, 0); + Object.keys(tags) + .filter(k => tags[k]) + .forEach(k => _tags[k] = tags[k]); + dispatch.call('change', this, tags, onInput); }; } From 49492a0e06aef71f90e96ab3ed50098df0f4ce93 Mon Sep 17 00:00:00 2001 From: Martin Raifer Date: Wed, 5 Jun 2024 19:56:56 +0200 Subject: [PATCH 12/13] keep chosen dropdown item if user clicked on one fixes a bug where in case multiple items with the same `value` are present in the combobox' dropdown, always the first one is returned in the `accept` event --- modules/ui/combobox.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/ui/combobox.js b/modules/ui/combobox.js index 3914fd186..275e86ce3 100644 --- a/modules/ui/combobox.js +++ b/modules/ui/combobox.js @@ -439,7 +439,9 @@ export function uiCombobox(context, klass) { var val = utilGetSetValue(input); thiz.setSelectionRange(val.length, val.length); - d = _fetched[val]; + if (!d) { + d = _fetched[val]; + } dispatch.call('accept', thiz, d, val); hide(); } From b2b3009a649ecc048060240c6e7a21024755167f Mon Sep 17 00:00:00 2001 From: Martin Raifer Date: Fri, 5 Jul 2024 16:15:47 +0200 Subject: [PATCH 13/13] .env oauth2 config: drop client secret; use URL if API_URL is empty --- API.md | 2 +- config/envs.mjs | 2 +- config/id.js | 14 +++++--------- modules/services/osm.js | 1 - test/spec/services/osm.js | 1 - 5 files changed, 7 insertions(+), 13 deletions(-) diff --git a/API.md b/API.md index 551a224f3..a06ff0c7b 100644 --- a/API.md +++ b/API.md @@ -106,7 +106,7 @@ In addition, the following parameters are available as **URL query parameters**: Environment variables or a dotenv file can be used to configure certain aspects of iD at build time. -* __`ID_API_CONNECTION_URL`__, __`ID_API_CONNECTION_CLIENT_ID`__, __`ID_API_CONNECTION_CLIENT_SECRET`__ - Custom [OAuth2](https://wiki.openstreetmap.org/wiki/OAuth#OAuth_2.0_2) connection details to an OSM API server. +* __`ID_API_CONNECTION_URL`__, [__`ID_API_CONNECTION_API_URL`__,] __`ID_API_CONNECTION_CLIENT_ID`__ - Custom [OAuth2](https://wiki.openstreetmap.org/wiki/OAuth#OAuth_2.0_2) connection details to an OSM API server. * __`ID_API_CONNECTION_API_URL`__ Optional url to use for OSM API calls aftern the initial authentication is complete when using a custom OAuth2 connection (see above). If unspecified, `ID_API_CONNECTION_URL` will be used for both the authentication and subsequent API calls. * __`ID_API_CONNECTION`__ - Either `live` or `dev`, if only either one should be made offered for editing. * __`ID_PRESETS_CDN_URL`__ - The URL where iD should fetch it's tagging presets from. Needs to point to a CORS enabled web server which is serving the `package.json` and `dist` folder of a repository built on [`@ideditor/schema-builder`](https://github.com/ideditor/schema-builder). diff --git a/config/envs.mjs b/config/envs.mjs index 06e05a40b..2a30e7e81 100644 --- a/config/envs.mjs +++ b/config/envs.mjs @@ -10,8 +10,8 @@ const envs = { ENV__ID_WMF_SITEMATRIX_CDN_URL: JSON.stringify(process.env.ID_WMF_SITEMATRIX_CDN_URL || null), ENV__ID_API_CONNECTION_URL: JSON.stringify(process.env.ID_API_CONNECTION_URL || null), + ENV__ID_API_CONNECTION_API_URL: JSON.stringify(process.env.ID_API_CONNECTION_API_URL || null), ENV__ID_API_CONNECTION_CLIENT_ID: JSON.stringify(process.env.ID_API_CONNECTION_CLIENT_ID || null), - ENV__ID_API_CONNECTION_CLIENT_SECRET: JSON.stringify(process.env.ID_API_CONNECTION_CLIENT_SECRET || null), ENV__ID_API_CONNECTION: JSON.stringify(process.env.ID_API_CONNECTION || null), ENV__ID_TAGINFO_API_URL: JSON.stringify(process.env.ID_TAGINFO_API_URL || null), diff --git a/config/id.js b/config/id.js index 6bf65dd4b..2a30cd395 100644 --- a/config/id.js +++ b/config/id.js @@ -15,26 +15,22 @@ const defaultOsmApiConnections = { live: { url: 'https://www.openstreetmap.org', apiUrl: 'https://api.openstreetmap.org', - client_id: '0tmNTmd0Jo1dQp4AUmMBLtGiD9YpMuXzHefitcuVStc', - client_secret: 'BTlNrNxIPitHdL4sP2clHw5KLoee9aKkA7dQbc0Bj7Q' + client_id: '0tmNTmd0Jo1dQp4AUmMBLtGiD9YpMuXzHefitcuVStc' }, dev: { url: 'https://api06.dev.openstreetmap.org', - client_id: 'Ee1wWJ6UlpERbF6BfTNOpwn0R8k_06mvMXdDUkeHMgw', - client_secret: 'OnfWFC-JkZNHyYdr_viNn_h_RTZXRslKcUxllOXqf5g' + client_id: 'Ee1wWJ6UlpERbF6BfTNOpwn0R8k_06mvMXdDUkeHMgw' } }; const osmApiConnections = []; if (ENV__ID_API_CONNECTION_URL !== null && - ENV__ID_API_CONNECTION_CLIENT_ID !== null && - ENV__ID_API_CONNECTION_CLIENT_SECRET !== null) { + ENV__ID_API_CONNECTION_CLIENT_ID !== null) { // user specified API Oauth2 connection details // see https://wiki.openstreetmap.org/wiki/OAuth#OAuth_2.0_2 osmApiConnections.push({ url: ENV__ID_API_CONNECTION_URL, - apiUrl: ENV__ID_API_CONNECTION_API_URL, - client_id: ENV__ID_API_CONNECTION_CLIENT_ID, - client_secret: ENV__ID_API_CONNECTION_CLIENT_SECRET + apiUrl: ENV__ID_API_CONNECTION_API_URL || ENV__ID_API_CONNECTION_URL, + client_id: ENV__ID_API_CONNECTION_CLIENT_ID }); } else if (ENV__ID_API_CONNECTION !== null && defaultOsmApiConnections[ENV__ID_API_CONNECTION] !== undefined) { diff --git a/modules/services/osm.js b/modules/services/osm.js index 6602873de..07baebe20 100644 --- a/modules/services/osm.js +++ b/modules/services/osm.js @@ -24,7 +24,6 @@ var oauth = osmAuth({ url: urlroot, apiUrl: apiUrlroot, client_id: osmApiConnections[0].client_id, - client_secret: osmApiConnections[0].client_secret, scope: 'read_prefs write_prefs write_api read_gpx write_notes', redirect_uri: redirectPath + 'land.html', loading: authLoading, diff --git a/test/spec/services/osm.js b/test/spec/services/osm.js index 411875432..36cdee910 100644 --- a/test/spec/services/osm.js +++ b/test/spec/services/osm.js @@ -6,7 +6,6 @@ describe('iD.serviceOsm', function () { connection.switch({ url: 'https://www.openstreetmap.org', client_id: '0tmNTmd0Jo1dQp4AUmMBLtGiD9YpMuXzHefitcuVStc', - client_secret: 'BTlNrNxIPitHdL4sP2clHw5KLoee9aKkA7dQbc0Bj7Q', access_token: 'foo' // preauth }); }