mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-19 06:58:32 +02:00
allow type/id syntax in id hash param, and add support for notes
This commit is contained in:
@@ -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') {
|
||||
|
||||
+32
-9
@@ -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;
|
||||
|
||||
+12
-2
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user