mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-31 20:21:36 +02:00
Merge branch 'master' into tyrasd-patch4968-onlyrestrictions
This commit is contained in:
@@ -3,8 +3,8 @@ import { actionDeleteNode } from './delete_node';
|
||||
|
||||
// Connect the ways at the given nodes.
|
||||
//
|
||||
// The last node will survive. All other nodes will be replaced with
|
||||
// the surviving node in parent ways, and then removed.
|
||||
// First choose a node to be the survivor, with preference given
|
||||
// to an existing (not new) node.
|
||||
//
|
||||
// Tags and relation memberships of of non-surviving nodes are merged
|
||||
// to the survivor.
|
||||
@@ -17,11 +17,20 @@ import { actionDeleteNode } from './delete_node';
|
||||
//
|
||||
export function actionConnect(nodeIds) {
|
||||
return function(graph) {
|
||||
var last = nodeIds[nodeIds.length - 1];
|
||||
var survivor = graph.entity(last);
|
||||
var survivor;
|
||||
var node;
|
||||
var i;
|
||||
|
||||
for (var i = 0; i < nodeIds.length - 1; i++) {
|
||||
var node = graph.entity(nodeIds[i]);
|
||||
// Choose a survivor node, prefer an existing (not new) node - #4974
|
||||
for (i = 0; i < nodeIds.length; i++) {
|
||||
survivor = graph.entity(nodeIds[i]);
|
||||
if (survivor.version) break; // found one
|
||||
}
|
||||
|
||||
// Replace all non-surviving nodes with the survivor and merge tags.
|
||||
for (i = 0; i < nodeIds.length; i++) {
|
||||
node = graph.entity(nodeIds[i]);
|
||||
if (node.id === survivor.id) continue;
|
||||
|
||||
/* eslint-disable no-loop-func */
|
||||
graph.parentWays(node).forEach(function(parent) {
|
||||
|
||||
@@ -316,6 +316,7 @@ export function coreContext() {
|
||||
tile: false, // tile boundaries
|
||||
collision: false, // label collision bounding boxes
|
||||
imagery: false, // imagery bounding polygons
|
||||
community: false, // community bounding polygons
|
||||
imperial: false, // imperial (not metric) bounding polygons
|
||||
driveLeft: false, // driveLeft bounding polygons
|
||||
target: false // touch targets
|
||||
|
||||
@@ -28,6 +28,8 @@ import {
|
||||
modeSelect
|
||||
} from './index';
|
||||
|
||||
import { services } from '../services';
|
||||
|
||||
import {
|
||||
uiConflicts,
|
||||
uiConfirm,
|
||||
@@ -66,6 +68,7 @@ export function modeSave(context) {
|
||||
var _conflicts = [];
|
||||
var _errors = [];
|
||||
var _origChanges;
|
||||
var _location;
|
||||
|
||||
|
||||
function cancel(selectedID) {
|
||||
@@ -305,6 +308,7 @@ export function modeSave(context) {
|
||||
var history = context.history();
|
||||
var changes = history.changes(actionDiscardTags(history.difference()));
|
||||
if (changes.modified.length || changes.created.length || changes.deleted.length) {
|
||||
loadLocation(); // so it is ready when we display the save screen
|
||||
osm.putChangeset(changeset, changes, uploadCallback);
|
||||
} else { // changes were insignificant or reverted by user
|
||||
d3_select('.inspector-wrap *').remove();
|
||||
@@ -468,6 +472,7 @@ export function modeSave(context) {
|
||||
|
||||
var ui = uiSuccess(context)
|
||||
.changeset(changeset)
|
||||
.location(_location)
|
||||
.on('cancel', function() { context.ui().sidebar.hide(); });
|
||||
|
||||
context.enter(modeBrowse(context).sidebar(ui));
|
||||
@@ -486,6 +491,27 @@ export function modeSave(context) {
|
||||
}
|
||||
|
||||
|
||||
// Reverse geocode current map location so we can display a message on
|
||||
// the success screen like "Thank you for editing around city, state."
|
||||
function loadLocation() {
|
||||
_location = null;
|
||||
if (!services.geocoder) return;
|
||||
|
||||
services.geocoder.reverse(context.map().center(), function(err, result) {
|
||||
if (err || !result || !result.address) return;
|
||||
|
||||
var parts = [];
|
||||
var addr = result.address;
|
||||
var city = addr && (addr.suburb || addr.city || addr.county);
|
||||
if (city) parts.push(city);
|
||||
var region = addr && (addr.state || addr.country);
|
||||
if (region) parts.push(region);
|
||||
|
||||
_location = parts.join(', ');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
mode.enter = function() {
|
||||
function done() {
|
||||
context.ui().sidebar.show(commit);
|
||||
|
||||
@@ -138,7 +138,13 @@ export function rendererFeatures(context) {
|
||||
});
|
||||
|
||||
defineFeature('boundaries', function isBoundary(entity) {
|
||||
return !!entity.tags.boundary;
|
||||
return (
|
||||
!!entity.tags.boundary
|
||||
) && !(
|
||||
traffic_roads[entity.tags.highway] ||
|
||||
service_roads[entity.tags.highway] ||
|
||||
paths[entity.tags.highway]
|
||||
);
|
||||
});
|
||||
|
||||
defineFeature('water', function isWater(entity) {
|
||||
@@ -483,7 +489,7 @@ export function rendererFeatures(context) {
|
||||
var storageDisabled = storage.replace(/;/g, ',').split(',');
|
||||
storageDisabled.forEach(features.disable);
|
||||
}
|
||||
|
||||
|
||||
var q = utilStringQs(window.location.hash.substring(1));
|
||||
if (q.disable_features) {
|
||||
var hashDisabled = q.disable_features.replace(/;/g, ',').split(',');
|
||||
|
||||
+18
-1
@@ -1,3 +1,5 @@
|
||||
import _values from 'lodash-es/values';
|
||||
|
||||
import { select as d3_select } from 'd3-selection';
|
||||
|
||||
import { geoPolygonIntersectsPolygon } from '../geo';
|
||||
@@ -20,6 +22,7 @@ export function svgDebug(projection, context) {
|
||||
var showsTile = context.getDebug('tile');
|
||||
var showsCollision = context.getDebug('collision');
|
||||
var showsImagery = context.getDebug('imagery');
|
||||
var showsCommunity = context.getDebug('community');
|
||||
var showsImperial = context.getDebug('imperial');
|
||||
var showsDriveLeft = context.getDebug('driveLeft');
|
||||
var showsTouchTargets = context.getDebug('target');
|
||||
@@ -34,6 +37,9 @@ export function svgDebug(projection, context) {
|
||||
if (showsImagery) {
|
||||
debugData.push({ class: 'orange', label: 'imagery' });
|
||||
}
|
||||
if (showsCommunity) {
|
||||
debugData.push({ class: 'blue', label: 'community' });
|
||||
}
|
||||
if (showsImperial) {
|
||||
debugData.push({ class: 'cyan', label: 'imperial' });
|
||||
}
|
||||
@@ -71,7 +77,7 @@ export function svgDebug(projection, context) {
|
||||
|
||||
|
||||
var layer = selection.selectAll('.layer-debug')
|
||||
.data(showsImagery || showsImperial || showsDriveLeft ? [0] : []);
|
||||
.data(showsImagery || showsCommunity || showsImperial || showsDriveLeft ? [0] : []);
|
||||
|
||||
layer.exit()
|
||||
.remove();
|
||||
@@ -102,6 +108,17 @@ export function svgDebug(projection, context) {
|
||||
.attr('class', 'debug-imagery debug orange');
|
||||
|
||||
|
||||
var community = layer.selectAll('path.debug-community')
|
||||
.data(showsCommunity ? _values(data.community.features) : []);
|
||||
|
||||
community.exit()
|
||||
.remove();
|
||||
|
||||
community.enter()
|
||||
.append('path')
|
||||
.attr('class', 'debug-community debug blue');
|
||||
|
||||
|
||||
var imperial = layer
|
||||
.selectAll('path.debug-imperial')
|
||||
.data(showsImperial ? [dataImperial] : []);
|
||||
|
||||
+2
-1
@@ -134,6 +134,7 @@ export function svgDefs(context) {
|
||||
// symbol spritesheets
|
||||
defs
|
||||
.call(SVGSpriteDefinition('iD-sprite', context.imagePath('iD-sprite.svg')))
|
||||
.call(SVGSpriteDefinition('maki-sprite', context.imagePath('maki-sprite.svg')));
|
||||
.call(SVGSpriteDefinition('maki-sprite', context.imagePath('maki-sprite.svg')))
|
||||
.call(SVGSpriteDefinition('community-sprite', context.imagePath('community-sprite.svg')));
|
||||
};
|
||||
}
|
||||
|
||||
@@ -126,10 +126,17 @@ export function uiFieldCheck(field, context) {
|
||||
|
||||
input
|
||||
.on('click', function() {
|
||||
d3_event.stopPropagation();
|
||||
var t = {};
|
||||
t[field.key] = values[(values.indexOf(_value) + 1) % values.length];
|
||||
|
||||
// Don't cycle through `alternating` or `reversible` states - #4970
|
||||
// (They are supported as translated strings, but should not toggle with clicks)
|
||||
if (t[field.key] === 'reversible' || t[field.key] === 'alternating') {
|
||||
t[field.key] = values[0];
|
||||
}
|
||||
|
||||
dispatch.call('change', this, t);
|
||||
d3_event.stopPropagation();
|
||||
});
|
||||
|
||||
if (field.type === 'onewayCheck') {
|
||||
|
||||
@@ -96,8 +96,8 @@ export function uiPanelHistory(context) {
|
||||
|
||||
|
||||
function redraw(selection) {
|
||||
var selected = _filter(context.selectedIDs(), function(e) { return context.hasEntity(e); }),
|
||||
singular = selected.length === 1 ? selected[0] : null;
|
||||
var selected = _filter(context.selectedIDs(), function(e) { return context.hasEntity(e); });
|
||||
var singular = selected.length === 1 ? selected[0] : null;
|
||||
|
||||
osm = context.connection();
|
||||
|
||||
@@ -112,6 +112,13 @@ export function uiPanelHistory(context) {
|
||||
|
||||
var entity = context.entity(singular);
|
||||
|
||||
if (!entity.version) {
|
||||
selection
|
||||
.append('div')
|
||||
.text(t('info_panels.history.no_history'));
|
||||
return;
|
||||
}
|
||||
|
||||
var list = selection
|
||||
.append('ul');
|
||||
|
||||
|
||||
+305
-36
@@ -1,15 +1,35 @@
|
||||
import _filter from 'lodash-es/filter';
|
||||
|
||||
import { dispatch as d3_dispatch } from 'd3-dispatch';
|
||||
import { select as d3_select } from 'd3-selection';
|
||||
|
||||
import { t } from '../util/locale';
|
||||
import { tooltip } from '../util/tooltip';
|
||||
import { data } from '../../data';
|
||||
import { svgIcon } from '../svg';
|
||||
import { uiDisclosure } from '../ui';
|
||||
import { utilDetect } from '../util/detect';
|
||||
import { utilRebind } from '../util/rebind';
|
||||
|
||||
|
||||
export function uiSuccess(context) {
|
||||
var dispatch = d3_dispatch('cancel'),
|
||||
changeset;
|
||||
var MAXEVENTS = 2;
|
||||
|
||||
// All else being equal, rank more "social" communities higher
|
||||
// (anything not in this list receives no adjustment)
|
||||
var COMMUNITYRANK = {
|
||||
'meetup': +5,
|
||||
'slack': +4,
|
||||
'facebook': +3,
|
||||
'reddit': +2,
|
||||
'forum': -2,
|
||||
'mailinglist': -3,
|
||||
'irc': -4
|
||||
};
|
||||
|
||||
var detected = utilDetect();
|
||||
var dispatch = d3_dispatch('cancel');
|
||||
var _changeset;
|
||||
var _location;
|
||||
|
||||
|
||||
function success(selection) {
|
||||
@@ -31,67 +51,316 @@ export function uiSuccess(context) {
|
||||
.append('div')
|
||||
.attr('class', 'body save-success fillL');
|
||||
|
||||
body
|
||||
.append('p')
|
||||
.html(t('success.help_html'));
|
||||
var summary = body
|
||||
.append('div')
|
||||
.attr('class', 'save-summary');
|
||||
|
||||
body
|
||||
summary
|
||||
.append('h3')
|
||||
.text(t('success.thank_you' + (_location ? '_location' : ''), { where: _location }));
|
||||
|
||||
summary
|
||||
.append('p')
|
||||
.text(t('success.help_html'))
|
||||
.append('a')
|
||||
.attr('class', 'details')
|
||||
.attr('class', 'link-out')
|
||||
.attr('target', '_blank')
|
||||
.attr('tabindex', -1)
|
||||
.call(svgIcon('#icon-out-link', 'inline'))
|
||||
.attr('href', t('success.help_link_url'))
|
||||
.call(svgIcon('#icon-out-link', 'inline'))
|
||||
.append('span')
|
||||
.text(t('success.help_link_text'));
|
||||
|
||||
var osm = context.connection();
|
||||
if (!osm) return;
|
||||
|
||||
var changesetURL = osm.changesetURL(changeset.id);
|
||||
var changesetURL = osm.changesetURL(_changeset.id);
|
||||
|
||||
var viewOnOsm = body
|
||||
var table = summary
|
||||
.append('table')
|
||||
.attr('class', 'summary-table');
|
||||
|
||||
var row = table
|
||||
.append('tr')
|
||||
.attr('class', 'summary-row');
|
||||
|
||||
row
|
||||
.append('td')
|
||||
.attr('class', 'cell-icon summary-icon')
|
||||
.append('a')
|
||||
.attr('class', 'button col12 osm')
|
||||
.attr('target', '_blank')
|
||||
.attr('href', changesetURL);
|
||||
|
||||
viewOnOsm
|
||||
.attr('href', changesetURL)
|
||||
.append('svg')
|
||||
.attr('class', 'logo logo-osm')
|
||||
.attr('class', 'logo-small')
|
||||
.append('use')
|
||||
.attr('xlink:href', '#logo-osm');
|
||||
|
||||
viewOnOsm
|
||||
.append('div')
|
||||
var summaryDetail = row
|
||||
.append('td')
|
||||
.attr('class', 'cell-detail summary-detail');
|
||||
|
||||
summaryDetail
|
||||
.append('a')
|
||||
.attr('class', 'cell-detail summary-view-on-osm')
|
||||
.attr('target', '_blank')
|
||||
.attr('href', changesetURL)
|
||||
.text(t('success.view_on_osm'));
|
||||
|
||||
var message = (changeset.tags.comment || t('success.edited_osm')).substring(0, 130) +
|
||||
' ' + changesetURL;
|
||||
summaryDetail
|
||||
.append('div')
|
||||
.text(t('success.changeset_id', { changeset_id: _changeset.id }));
|
||||
|
||||
var sharing = [
|
||||
{ key: 'facebook', value: 'https://facebook.com/sharer/sharer.php?u=' + encodeURIComponent(changesetURL) },
|
||||
{ key: 'twitter', value: 'https://twitter.com/intent/tweet?source=webclient&text=' + encodeURIComponent(message) },
|
||||
{ key: 'google', value: 'https://plus.google.com/share?url=' + encodeURIComponent(changesetURL) }
|
||||
];
|
||||
|
||||
body.selectAll('.button.social')
|
||||
.data(sharing)
|
||||
.enter()
|
||||
// Gather community polygon IDs intersecting the map..
|
||||
var matchFeatures = data.community.query(context.map().center(), true);
|
||||
var matchIDs = matchFeatures.map(function(feature) { return feature.id; });
|
||||
|
||||
// Gather community resources that are either global or match a polygon.
|
||||
var matchResources = _filter(data.community.resources, function(v) {
|
||||
return !v.featureId || matchIDs.indexOf(v.featureId) !== -1;
|
||||
});
|
||||
|
||||
if (matchResources.length) {
|
||||
// sort by size ascending, then by community rank
|
||||
matchResources.sort(function(a, b) {
|
||||
var aSize = Infinity;
|
||||
var bSize = Infinity;
|
||||
var aRank = COMMUNITYRANK[a.type] || 0;
|
||||
var bRank = COMMUNITYRANK[b.type] || 0;
|
||||
|
||||
if (a.featureId) {
|
||||
aSize = data.community.features[a.featureId].properties.area;
|
||||
}
|
||||
if (b.featureId) {
|
||||
bSize = data.community.features[b.featureId].properties.area;
|
||||
}
|
||||
|
||||
return aSize < bSize ? -1 : aSize > bSize ? 1 : bRank - aRank;
|
||||
});
|
||||
|
||||
body
|
||||
.call(showCommunityLinks, matchResources);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function showCommunityLinks(selection, matchResources) {
|
||||
var communityLinks = selection
|
||||
.append('div')
|
||||
.attr('class', 'save-communityLinks');
|
||||
|
||||
communityLinks
|
||||
.append('h3')
|
||||
.text(t('success.like_osm'));
|
||||
|
||||
var table = communityLinks
|
||||
.append('table')
|
||||
.attr('class', 'community-table');
|
||||
|
||||
var row = table.selectAll('.community-row')
|
||||
.data(matchResources);
|
||||
|
||||
var rowEnter = row.enter()
|
||||
.append('tr')
|
||||
.attr('class', 'community-row');
|
||||
|
||||
rowEnter
|
||||
.append('td')
|
||||
.attr('class', 'cell-icon community-icon')
|
||||
.append('a')
|
||||
.attr('class', 'button social col4')
|
||||
.attr('target', '_blank')
|
||||
.attr('href', function(d) { return d.value; })
|
||||
.call(tooltip()
|
||||
.title(function(d) { return t('success.' + d.key); })
|
||||
.placement('bottom'))
|
||||
.each(function(d) { d3_select(this).call(svgIcon('#logo-' + d.key, 'social')); });
|
||||
.attr('href', function(d) { return d.url; })
|
||||
.append('svg')
|
||||
.attr('class', 'logo-small')
|
||||
.append('use')
|
||||
.attr('xlink:href', function(d) { return '#community-' + d.type; });
|
||||
|
||||
var communityDetail = rowEnter
|
||||
.append('td')
|
||||
.attr('class', 'cell-detail community-detail');
|
||||
|
||||
communityDetail
|
||||
.each(showCommunityDetails);
|
||||
|
||||
communityLinks
|
||||
.append('div')
|
||||
.attr('class', 'community-missing')
|
||||
.text(t('success.missing'))
|
||||
.append('a')
|
||||
.attr('class', 'link-out')
|
||||
.attr('target', '_blank')
|
||||
.attr('tabindex', -1)
|
||||
.call(svgIcon('#icon-out-link', 'inline'))
|
||||
.attr('href', 'https://github.com/osmlab/osm-community-index/issues')
|
||||
.append('span')
|
||||
.text(t('success.tell_us'));
|
||||
}
|
||||
|
||||
|
||||
function showCommunityDetails(d) {
|
||||
var selection = d3_select(this);
|
||||
var communityID = d.id;
|
||||
var replacements = {
|
||||
url: linkify(d.url),
|
||||
signupUrl: linkify(d.signupUrl || d.url)
|
||||
};
|
||||
|
||||
selection
|
||||
.append('div')
|
||||
.attr('class', 'community-name')
|
||||
.append('a')
|
||||
.attr('target', '_blank')
|
||||
.attr('href', d.url)
|
||||
.text(t('community.' + d.id + '.name'));
|
||||
|
||||
selection
|
||||
.append('div')
|
||||
.attr('class', 'community-description')
|
||||
.html(t('community.' + d.id + '.description', replacements));
|
||||
|
||||
if (d.extendedDescription || (d.languageCodes && d.languageCodes.length)) {
|
||||
selection
|
||||
.append('div')
|
||||
.call(uiDisclosure(context, 'community-more-' + d.id, false)
|
||||
.expanded(false)
|
||||
.updatePreference(false)
|
||||
.title(t('success.more'))
|
||||
.content(showMore)
|
||||
);
|
||||
}
|
||||
|
||||
var nextEvents = (d.events || [])
|
||||
.map(function(event) { // add parsed date
|
||||
event.date = new Date(event.when);
|
||||
return event;
|
||||
})
|
||||
.filter(function(event) { // date is valid and future (or today)
|
||||
var t = event.date.getTime();
|
||||
var now = (new Date()).setHours(0,0,0,0);
|
||||
return !isNaN(t) && t >= now;
|
||||
})
|
||||
.sort(function(a, b) { // sort by date ascending
|
||||
return a.date < b.date ? -1 : a.date > b.date ? 1 : 0;
|
||||
})
|
||||
.slice(0, MAXEVENTS); // limit number of events shown
|
||||
|
||||
if (nextEvents.length) {
|
||||
selection
|
||||
.append('div')
|
||||
.call(uiDisclosure(context, 'community-events-' + d.id, false)
|
||||
.expanded(false)
|
||||
.updatePreference(false)
|
||||
.title(t('success.events'))
|
||||
.content(showNextEvents)
|
||||
)
|
||||
.select('.hide-toggle')
|
||||
.append('span')
|
||||
.attr('class', 'badge-text')
|
||||
.text(nextEvents.length);
|
||||
}
|
||||
|
||||
|
||||
function showMore(selection) {
|
||||
var more = selection
|
||||
.append('div')
|
||||
.attr('class', 'community-more');
|
||||
|
||||
if (d.extendedDescription) {
|
||||
more
|
||||
.append('div')
|
||||
.attr('class', 'community-extended-description')
|
||||
.html(t('community.' + d.id + '.extendedDescription', replacements));
|
||||
}
|
||||
|
||||
if (d.languageCodes && d.languageCodes.length) {
|
||||
more
|
||||
.append('div')
|
||||
.attr('class', 'community-languages')
|
||||
.text(t('success.languages', { languages: d.languageCodes.join(', ') }));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function showNextEvents(selection) {
|
||||
var events = selection
|
||||
.append('div')
|
||||
.attr('class', 'community-events');
|
||||
|
||||
var item = events.selectAll('.community-event')
|
||||
.data(nextEvents);
|
||||
|
||||
var itemEnter = item.enter()
|
||||
.append('div')
|
||||
.attr('class', 'community-event');
|
||||
|
||||
itemEnter
|
||||
.append('div')
|
||||
.attr('class', 'community-event-name')
|
||||
.append('a')
|
||||
.attr('target', '_blank')
|
||||
.attr('href', function(d) { return d.url; })
|
||||
.text(function(d) {
|
||||
var name = d.name;
|
||||
if (d.i18n && d.id) {
|
||||
name = t('community.' + communityID + '.events.' + d.id + '.name', { default: name });
|
||||
}
|
||||
return name;
|
||||
});
|
||||
|
||||
itemEnter
|
||||
.append('div')
|
||||
.attr('class', 'community-event-when')
|
||||
.text(function(d) {
|
||||
var options = {
|
||||
weekday: 'short', day: 'numeric', month: 'short', year: 'numeric'
|
||||
};
|
||||
if (d.date.getHours() || d.date.getMinutes()) { // include time if it has one
|
||||
options.hour = 'numeric';
|
||||
options.minute = 'numeric';
|
||||
}
|
||||
return d.date.toLocaleString(detected.locale, options);
|
||||
});
|
||||
|
||||
itemEnter
|
||||
.append('div')
|
||||
.attr('class', 'community-event-where')
|
||||
.text(function(d) {
|
||||
var where = d.where;
|
||||
if (d.i18n && d.id) {
|
||||
where = t('community.' + communityID + '.events.' + d.id + '.where', { default: where });
|
||||
}
|
||||
return where;
|
||||
});
|
||||
|
||||
itemEnter
|
||||
.append('div')
|
||||
.attr('class', 'community-event-description')
|
||||
.text(function(d) {
|
||||
var description = d.description;
|
||||
if (d.i18n && d.id) {
|
||||
description = t('community.' + communityID + '.events.' + d.id + '.description', { default: description });
|
||||
}
|
||||
return description;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function linkify(url) {
|
||||
return '<a target="_blank" href="' + url + '">' + url + '</a>';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
success.changeset = function(_) {
|
||||
if (!arguments.length) return changeset;
|
||||
changeset = _;
|
||||
if (!arguments.length) return _changeset;
|
||||
_changeset = _;
|
||||
return success;
|
||||
};
|
||||
|
||||
|
||||
success.location = function(_) {
|
||||
if (!arguments.length) return _location;
|
||||
_location = _;
|
||||
return success;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user