mirror of
https://github.com/FoggedLens/iD.git
synced 2026-06-05 14:38:05 +02:00
Merge branch 'master' into validation
This commit is contained in:
+24
-4
@@ -21,7 +21,8 @@ import { rendererBackground, rendererFeatures, rendererMap } from '../renderer';
|
||||
import { services } from '../services';
|
||||
import { uiInit } from '../ui/init';
|
||||
import { utilDetect } from '../util/detect';
|
||||
import { utilCallWhenIdle, utilKeybinding, utilRebind } from '../util';
|
||||
import { utilCallWhenIdle, utilKeybinding, utilRebind, utilStringQs } from '../util';
|
||||
|
||||
|
||||
|
||||
export var areaKeys = {};
|
||||
@@ -470,6 +471,18 @@ export function coreContext() {
|
||||
features = rendererFeatures(context);
|
||||
presets = presetIndex();
|
||||
|
||||
if (services.maprules && utilStringQs(window.location.hash).validations) {
|
||||
var validations = utilStringQs(window.location.hash).validations;
|
||||
d3_json(validations, function (err, mapcss) {
|
||||
if (err) return;
|
||||
services.maprules.init(context.presets().areaKeys());
|
||||
_each(mapcss, function(mapcssSelector) {
|
||||
return services.maprules.addRule(mapcssSelector);
|
||||
});
|
||||
context.validationRules = true;
|
||||
});
|
||||
}
|
||||
|
||||
map = rendererMap(context);
|
||||
context.mouse = map.mouse;
|
||||
context.extent = map.extent;
|
||||
@@ -488,9 +501,16 @@ export function coreContext() {
|
||||
|
||||
background.init();
|
||||
features.init();
|
||||
presets.init();
|
||||
areaKeys = presets.areaKeys();
|
||||
|
||||
if (utilStringQs(window.location.hash).presets) {
|
||||
var external = utilStringQs(window.location.hash).presets;
|
||||
presets.fromExternal(external, function(externalPresets) {
|
||||
context.presets = function() { return externalPresets; }; // default + external presets...
|
||||
areaKeys = presets.areaKeys();
|
||||
});
|
||||
} else {
|
||||
presets.init();
|
||||
areaKeys = presets.areaKeys();
|
||||
}
|
||||
|
||||
return utilRebind(context, dispatch, 'on');
|
||||
}
|
||||
|
||||
@@ -281,9 +281,9 @@ export function coreHistory(context) {
|
||||
|
||||
|
||||
validate: function(changes) {
|
||||
return _flatten(
|
||||
_map(Validations, function(fn) { return fn()(changes, _stack[_index].graph); })
|
||||
);
|
||||
return _flatten(_map(Validations, function(fn) {
|
||||
return fn()(changes, _stack[_index].graph);
|
||||
}));
|
||||
},
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import _filter from 'lodash-es/filter';
|
||||
import _find from 'lodash-es/find';
|
||||
import _findIndex from 'lodash-es/findIndex';
|
||||
import _some from 'lodash-es/some';
|
||||
import _uniq from 'lodash-es/uniq';
|
||||
import _values from 'lodash-es/values';
|
||||
@@ -23,6 +24,11 @@ export function presetCollection(collection) {
|
||||
});
|
||||
},
|
||||
|
||||
index: function(id) {
|
||||
return _findIndex(this.collection, function(d) {
|
||||
return d.id === id;
|
||||
});
|
||||
},
|
||||
|
||||
matchGeometry: function(geometry) {
|
||||
return presetCollection(this.collection.filter(function(d) {
|
||||
|
||||
@@ -21,7 +21,7 @@ export function presetField(id, field) {
|
||||
|
||||
|
||||
field.label = function() {
|
||||
return field.t('label', {'default': id});
|
||||
return field.overrideLabel || field.t('label', {'default': id});
|
||||
};
|
||||
|
||||
|
||||
|
||||
+57
-13
@@ -3,6 +3,8 @@ import _forEach from 'lodash-es/forEach';
|
||||
import _reject from 'lodash-es/reject';
|
||||
import _uniq from 'lodash-es/uniq';
|
||||
|
||||
import { json as d3_json } from 'd3-request';
|
||||
|
||||
import { data } from '../../data/index';
|
||||
import { presetCategory } from './category';
|
||||
import { presetCollection } from './collection';
|
||||
@@ -70,7 +72,6 @@ export function presetIndex() {
|
||||
if (address && (!match || match.isFallback())) {
|
||||
match = address;
|
||||
}
|
||||
|
||||
return match || all.item(geometry);
|
||||
});
|
||||
};
|
||||
@@ -120,16 +121,7 @@ export function presetIndex() {
|
||||
return areaKeys;
|
||||
};
|
||||
|
||||
|
||||
all.init = function() {
|
||||
var d = data.presets;
|
||||
|
||||
all.collection = [];
|
||||
_recent.collection = [];
|
||||
_fields = {};
|
||||
_universal = [];
|
||||
_index = { point: {}, vertex: {}, line: {}, area: {}, relation: {} };
|
||||
|
||||
all.build = function(d, visible) {
|
||||
if (d.fields) {
|
||||
_forEach(d.fields, function(d, id) {
|
||||
_fields[id] = presetField(id, d);
|
||||
@@ -145,13 +137,23 @@ export function presetIndex() {
|
||||
|
||||
if (d.presets) {
|
||||
_forEach(d.presets, function(d, id) {
|
||||
all.collection.push(presetPreset(id, d, _fields));
|
||||
var existing = all.index(id);
|
||||
if (existing !== -1) {
|
||||
all.collection[existing] = presetPreset(id, d, _fields, visible);
|
||||
} else {
|
||||
all.collection.push(presetPreset(id, d, _fields, visible));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (d.categories) {
|
||||
_forEach(d.categories, function(d, id) {
|
||||
all.collection.push(presetCategory(id, d, all));
|
||||
var existing = all.index(id);
|
||||
if (existing !== -1) {
|
||||
all.collection[existing] = presetCategory(id, d, all);
|
||||
} else {
|
||||
all.collection.push(presetCategory(id, d, all));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -177,10 +179,52 @@ export function presetIndex() {
|
||||
}
|
||||
}
|
||||
}
|
||||
return all;
|
||||
};
|
||||
|
||||
all.init = function() {
|
||||
all.collection = [];
|
||||
_recent.collection = [];
|
||||
_fields = {};
|
||||
_universal = [];
|
||||
_index = { point: {}, vertex: {}, line: {}, area: {}, relation: {} };
|
||||
|
||||
return all.build(data.presets, true);
|
||||
};
|
||||
|
||||
|
||||
all.reset = function() {
|
||||
all.collection = [];
|
||||
_defaults = { area: all, line: all, point: all, vertex: all, relation: all };
|
||||
_fields = {};
|
||||
_universal = [];
|
||||
_recent = presetCollection([]);
|
||||
|
||||
// Index of presets by (geometry, tag key).
|
||||
_index = {
|
||||
point: {},
|
||||
vertex: {},
|
||||
line: {},
|
||||
area: {},
|
||||
relation: {}
|
||||
};
|
||||
|
||||
return all;
|
||||
};
|
||||
|
||||
all.fromExternal = function(external, done) {
|
||||
all.reset();
|
||||
d3_json(external, function(err, externalPresets) {
|
||||
if (err) {
|
||||
all.init();
|
||||
} else {
|
||||
all.build(data.presets, false); // make default presets hidden to begin
|
||||
all.build(externalPresets, true); // make the external visible
|
||||
}
|
||||
done(all);
|
||||
});
|
||||
};
|
||||
|
||||
all.field = function(id) {
|
||||
return _fields[id];
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@ import { t } from '../util/locale';
|
||||
import { areaKeys } from '../core/context';
|
||||
|
||||
|
||||
export function presetPreset(id, preset, fields) {
|
||||
export function presetPreset(id, preset, fields, visible) {
|
||||
preset = _clone(preset);
|
||||
|
||||
preset.id = id;
|
||||
@@ -13,6 +13,7 @@ export function presetPreset(id, preset, fields) {
|
||||
preset.moreFields = (preset.moreFields || []).map(getFields);
|
||||
preset.geometry = (preset.geometry || []);
|
||||
|
||||
visible = visible || false;
|
||||
|
||||
function getFields(f) {
|
||||
return fields[f];
|
||||
@@ -71,6 +72,12 @@ export function presetPreset(id, preset, fields) {
|
||||
return tagCount === 0 || (tagCount === 1 && preset.tags.hasOwnProperty('area'));
|
||||
};
|
||||
|
||||
preset.visible = function(_) {
|
||||
if (!arguments.length) return visible;
|
||||
visible = _;
|
||||
return visible;
|
||||
};
|
||||
|
||||
|
||||
var reference = preset.reference || {};
|
||||
preset.reference = function(geometry) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import serviceMapillary from './mapillary';
|
||||
import serviceMapRules from './maprules';
|
||||
import serviceNominatim from './nominatim';
|
||||
import serviceOpenstreetcam from './openstreetcam';
|
||||
import serviceOsm from './osm';
|
||||
@@ -8,11 +9,13 @@ import serviceVectorTile from './vector_tile';
|
||||
import serviceWikidata from './wikidata';
|
||||
import serviceWikipedia from './wikipedia';
|
||||
|
||||
|
||||
export var services = {
|
||||
geocoder: serviceNominatim,
|
||||
mapillary: serviceMapillary,
|
||||
openstreetcam: serviceOpenstreetcam,
|
||||
osm: serviceOsm,
|
||||
maprules: serviceMapRules,
|
||||
streetside: serviceStreetside,
|
||||
taginfo: serviceTaginfo,
|
||||
vectorTile: serviceVectorTile,
|
||||
@@ -22,6 +25,7 @@ export var services = {
|
||||
|
||||
export {
|
||||
serviceMapillary,
|
||||
serviceMapRules,
|
||||
serviceNominatim,
|
||||
serviceOpenstreetcam,
|
||||
serviceOsm,
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
import _isMatch from 'lodash-es/isMatch';
|
||||
import _intersection from 'lodash-es/intersection';
|
||||
import _reduce from 'lodash-es/reduce';
|
||||
import _every from 'lodash-es/every';
|
||||
|
||||
var buildRuleChecks = function() {
|
||||
return {
|
||||
equals: function (equals) {
|
||||
return function(tags) {
|
||||
return _isMatch(tags, equals);
|
||||
};
|
||||
},
|
||||
notEquals: function (notEquals) {
|
||||
return function(tags) {
|
||||
return !_isMatch(tags, notEquals);
|
||||
};
|
||||
},
|
||||
absence: function(absence) {
|
||||
return function(tags) {
|
||||
return Object.keys(tags).indexOf(absence) === -1;
|
||||
};
|
||||
},
|
||||
presence: function(presence) {
|
||||
return function(tags) {
|
||||
return Object.keys(tags).indexOf(presence) > -1;
|
||||
};
|
||||
},
|
||||
greaterThan: function(greaterThan) {
|
||||
var key = Object.keys(greaterThan)[0];
|
||||
var value = greaterThan[key];
|
||||
|
||||
return function(tags) {
|
||||
return tags[key] > value;
|
||||
};
|
||||
},
|
||||
greaterThanEqual: function(greaterThanEqual) {
|
||||
var key = Object.keys(greaterThanEqual)[0];
|
||||
var value = greaterThanEqual[key];
|
||||
|
||||
return function(tags) {
|
||||
return tags[key] >= value;
|
||||
};
|
||||
},
|
||||
lessThan: function(lessThan) {
|
||||
var key = Object.keys(lessThan)[0];
|
||||
var value = lessThan[key];
|
||||
|
||||
return function(tags) {
|
||||
return tags[key] < value;
|
||||
};
|
||||
},
|
||||
lessThanEqual: function(lessThanEqual) {
|
||||
var key = Object.keys(lessThanEqual)[0];
|
||||
var value = lessThanEqual[key];
|
||||
|
||||
return function(tags) {
|
||||
return tags[key] <= value;
|
||||
};
|
||||
},
|
||||
positiveRegex: function(positiveRegex) {
|
||||
var tagKey = Object.keys(positiveRegex)[0];
|
||||
var expression = positiveRegex[tagKey].join('|');
|
||||
var regex = new RegExp(expression);
|
||||
|
||||
return function(tags) {
|
||||
return regex.test(tags[tagKey]);
|
||||
};
|
||||
},
|
||||
negativeRegex: function(negativeRegex) {
|
||||
var tagKey = Object.keys(negativeRegex)[0];
|
||||
var expression = negativeRegex[tagKey].join('|');
|
||||
var regex = new RegExp(expression);
|
||||
|
||||
return function(tags) {
|
||||
return !regex.test(tags[tagKey]);
|
||||
};
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
var buildLineKeys = function() {
|
||||
return {
|
||||
highway: {
|
||||
rest_area: true,
|
||||
services: true
|
||||
},
|
||||
railway: {
|
||||
roundhouse: true,
|
||||
station: true,
|
||||
traverser: true,
|
||||
turntable: true,
|
||||
wash: true
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export default {
|
||||
init: function(areaKeys) {
|
||||
this._ruleChecks = buildRuleChecks();
|
||||
this._validationRules = [];
|
||||
this._areaKeys = areaKeys;
|
||||
this._lineKeys = buildLineKeys();
|
||||
},
|
||||
// list of rules only relevant to tag checks...
|
||||
filterRuleChecks: function(selector) {
|
||||
var _ruleChecks = this._ruleChecks;
|
||||
return _reduce(Object.keys(selector), function(rules, key) {
|
||||
if (['geometry', 'error', 'warning'].indexOf(key) === -1) {
|
||||
rules.push(_ruleChecks[key](selector[key]));
|
||||
}
|
||||
return rules;
|
||||
}, []);
|
||||
},
|
||||
// builds tagMap from mapcss-parse selector object...
|
||||
buildTagMap: function(selector) {
|
||||
var getRegexValues = function(regexes) {
|
||||
return regexes.map(function(regex) {
|
||||
return regex.replace(/\$|\^/g, '');
|
||||
});
|
||||
};
|
||||
|
||||
var selectorKeys = Object.keys(selector);
|
||||
var tagMap = _reduce(selectorKeys, function (expectedTags, key) {
|
||||
var values;
|
||||
var isRegex = /regex/gi.test(key);
|
||||
var isEqual = /equals/gi.test(key);
|
||||
|
||||
if (isRegex || isEqual) {
|
||||
Object.keys(selector[key]).forEach(function(selectorKey) {
|
||||
values = isEqual ? [selector[key][selectorKey]] : getRegexValues(selector[key][selectorKey]);
|
||||
|
||||
if (expectedTags.hasOwnProperty(selectorKey)) {
|
||||
values = values.concat(expectedTags[selectorKey]);
|
||||
}
|
||||
|
||||
expectedTags[selectorKey] = values;
|
||||
});
|
||||
|
||||
} else if (/(greater|less)Than(Equal)?|presence/g.test(key)) {
|
||||
var tagKey = /presence/.test(key) ? selector[key] : Object.keys(selector[key])[0];
|
||||
|
||||
values = [selector[key][tagKey]];
|
||||
|
||||
if (expectedTags.hasOwnProperty(tagKey)) {
|
||||
values = values.concat(expectedTags[tagKey]);
|
||||
}
|
||||
|
||||
expectedTags[tagKey] = values;
|
||||
}
|
||||
|
||||
return expectedTags;
|
||||
}, {});
|
||||
|
||||
return tagMap;
|
||||
},
|
||||
// inspired by osmWay#isArea()
|
||||
inferGeometry: function(tagMap) {
|
||||
var _lineKeys = this._lineKeys;
|
||||
var _areaKeys = this._areaKeys;
|
||||
|
||||
var isAreaKeyBlackList = function(key) {
|
||||
return _intersection(tagMap[key], Object.keys(_areaKeys[key])).length > 0;
|
||||
};
|
||||
var isLineKeysWhiteList = function(key) {
|
||||
return _intersection(tagMap[key], Object.keys(_lineKeys[key])).length > 0;
|
||||
};
|
||||
|
||||
if (tagMap.hasOwnProperty('area')) {
|
||||
if (tagMap.area.indexOf('yes') > -1) {
|
||||
return 'area';
|
||||
}
|
||||
if (tagMap.area.indexOf('no') > -1) {
|
||||
return 'line';
|
||||
}
|
||||
}
|
||||
|
||||
for (var key in tagMap) {
|
||||
if (key in _areaKeys && !isAreaKeyBlackList(key)) {
|
||||
return 'area';
|
||||
}
|
||||
if (key in _lineKeys && isLineKeysWhiteList(key)) {
|
||||
return 'area';
|
||||
}
|
||||
}
|
||||
|
||||
return 'line';
|
||||
},
|
||||
// adds from mapcss-parse selector check...
|
||||
addRule: function(selector) {
|
||||
var rule = {
|
||||
// checks relevant to mapcss-selector
|
||||
checks: this.filterRuleChecks(selector),
|
||||
// true if all conditions for a tag error are true..
|
||||
matches: function(entity) {
|
||||
return _every(this.checks, function(check) {
|
||||
return check(entity.tags);
|
||||
});
|
||||
},
|
||||
// borrowed from Way#isArea()
|
||||
inferredGeometry: this.inferGeometry(this.buildTagMap(selector), this._areaKeys),
|
||||
geometryMatches: function(entity, graph) {
|
||||
if (entity.type === 'node' || entity.type === 'relation') {
|
||||
return selector.geometry === entity.type;
|
||||
} else if (entity.type === 'way') {
|
||||
return this.inferredGeometry === entity.geometry(graph);
|
||||
}
|
||||
},
|
||||
// when geometries match and tag matches are present, return a warning...
|
||||
findWarnings: function (entity, graph, warnings) {
|
||||
if (this.geometryMatches(entity, graph) && this.matches(entity)) {
|
||||
var type = Object.keys(selector).indexOf('error') > -1 ? 'error' : 'warning';
|
||||
warnings.push({
|
||||
severity: type,
|
||||
message: selector[type],
|
||||
entity: entity
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
this._validationRules.push(rule);
|
||||
},
|
||||
clearRules: function() { this._validationRules = []; },
|
||||
// returns validationRules...
|
||||
validationRules: function() { return this._validationRules; },
|
||||
// returns ruleChecks
|
||||
ruleChecks: function() { return this._ruleChecks; }
|
||||
};
|
||||
@@ -3,91 +3,108 @@ import { modeSelect } from '../modes';
|
||||
import { svgIcon } from '../svg';
|
||||
import { tooltip } from '../util/tooltip';
|
||||
import { utilEntityOrMemberSelector } from '../util';
|
||||
|
||||
import _reduce from 'lodash-es/reduce';
|
||||
import _forEach from 'lodash-es/forEach';
|
||||
import _uniqBy from 'lodash-es/uniqBy';
|
||||
|
||||
export function uiCommitWarnings(context) {
|
||||
|
||||
function commitWarnings(selection) {
|
||||
|
||||
var changes = context.history().changes();
|
||||
var warnings = context.history().validate(changes);
|
||||
var validations = context.history().validate(changes);
|
||||
|
||||
var container = selection.selectAll('.warning-section')
|
||||
.data(warnings.length ? [0] : []);
|
||||
|
||||
container.exit()
|
||||
.remove();
|
||||
|
||||
var containerEnter = container.enter()
|
||||
.append('div')
|
||||
.attr('class', 'modal-section warning-section fillL2');
|
||||
|
||||
containerEnter
|
||||
.append('h3')
|
||||
.text(t('commit.warnings'));
|
||||
|
||||
containerEnter
|
||||
.append('ul')
|
||||
.attr('class', 'changeset-list');
|
||||
|
||||
container = containerEnter
|
||||
.merge(container);
|
||||
|
||||
|
||||
var items = container.select('ul').selectAll('li')
|
||||
.data(warnings);
|
||||
|
||||
items.exit()
|
||||
.remove();
|
||||
|
||||
var itemsEnter = items.enter()
|
||||
.append('li')
|
||||
.attr('class', 'warning-item');
|
||||
|
||||
itemsEnter
|
||||
.call(svgIcon('#iD-icon-alert', 'pre-text'));
|
||||
|
||||
itemsEnter
|
||||
.append('strong')
|
||||
.text(function(d) { return d.message; });
|
||||
|
||||
itemsEnter.filter(function(d) { return d.tooltip; })
|
||||
.call(tooltip()
|
||||
.title(function(d) { return d.tooltip; })
|
||||
.placement('top')
|
||||
);
|
||||
|
||||
items = itemsEnter
|
||||
.merge(items);
|
||||
|
||||
items
|
||||
.on('mouseover', mouseover)
|
||||
.on('mouseout', mouseout)
|
||||
.on('click', warningClick);
|
||||
|
||||
|
||||
function mouseover(d) {
|
||||
if (d.entity) {
|
||||
context.surface().selectAll(
|
||||
utilEntityOrMemberSelector([d.entity.id], context.graph())
|
||||
).classed('hover', true);
|
||||
validations = _reduce(validations, function(validations, val) {
|
||||
var severity = val.severity;
|
||||
if (validations.hasOwnProperty(severity)) {
|
||||
validations[severity].push(val);
|
||||
} else {
|
||||
validations[severity] = [val];
|
||||
}
|
||||
}
|
||||
return validations;
|
||||
}, {});
|
||||
|
||||
_forEach(validations, function(instances, type) {
|
||||
instances = _uniqBy(instances, function(val) { return val.id + '_' + val.message.replace(/\s+/g,''); });
|
||||
var section = type + '-section';
|
||||
var instanceItem = type + '-item';
|
||||
|
||||
var container = selection.selectAll('.' + section)
|
||||
.data(instances.length ? [0] : []);
|
||||
|
||||
container.exit()
|
||||
.remove();
|
||||
|
||||
var containerEnter = container.enter()
|
||||
.append('div')
|
||||
.attr('class', 'modal-section ' + section + ' fillL2');
|
||||
|
||||
containerEnter
|
||||
.append('h3')
|
||||
.text(type === 'warning' ? t('commit.warnings') : t('commit.errors'));
|
||||
|
||||
containerEnter
|
||||
.append('ul')
|
||||
.attr('class', 'changeset-list');
|
||||
|
||||
container = containerEnter
|
||||
.merge(container);
|
||||
|
||||
|
||||
function mouseout() {
|
||||
context.surface().selectAll('.hover')
|
||||
.classed('hover', false);
|
||||
}
|
||||
var items = container.select('ul').selectAll('li')
|
||||
.data(instances);
|
||||
|
||||
items.exit()
|
||||
.remove();
|
||||
|
||||
var itemsEnter = items.enter()
|
||||
.append('li')
|
||||
.attr('class', instanceItem);
|
||||
|
||||
itemsEnter
|
||||
.call(svgIcon('#iD-icon-alert', 'pre-text'));
|
||||
|
||||
itemsEnter
|
||||
.append('strong')
|
||||
.text(function(d) { return d.message; });
|
||||
|
||||
itemsEnter.filter(function(d) { return d.tooltip; })
|
||||
.call(tooltip()
|
||||
.title(function(d) { return d.tooltip; })
|
||||
.placement('top')
|
||||
);
|
||||
|
||||
items = itemsEnter
|
||||
.merge(items);
|
||||
|
||||
items
|
||||
.on('mouseover', mouseover)
|
||||
.on('mouseout', mouseout)
|
||||
.on('click', warningClick);
|
||||
|
||||
|
||||
function warningClick(d) {
|
||||
if (d.entity) {
|
||||
context.map().zoomTo(d.entity);
|
||||
context.enter(modeSelect(context, [d.entity.id]));
|
||||
function mouseover(d) {
|
||||
if (d.entity) {
|
||||
context.surface().selectAll(
|
||||
utilEntityOrMemberSelector([d.entity.id], context.graph())
|
||||
).classed('hover', true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function mouseout() {
|
||||
context.surface().selectAll('.hover')
|
||||
.classed('hover', false);
|
||||
}
|
||||
|
||||
|
||||
function warningClick(d) {
|
||||
if (d.entity) {
|
||||
context.map().zoomTo(d.entity);
|
||||
context.enter(modeSelect(context, [d.entity.id]));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -38,7 +38,6 @@ export function uiEntityEditor(context) {
|
||||
var rawMemberEditor = uiRawMemberEditor(context);
|
||||
var rawMembershipEditor = uiRawMembershipEditor(context);
|
||||
|
||||
|
||||
function entityEditor(selection) {
|
||||
var entity = context.entity(_entityID);
|
||||
var tags = _clone(entity.tags);
|
||||
|
||||
@@ -467,7 +467,7 @@ export function uiMapData(context) {
|
||||
|
||||
|
||||
function renderDataLayers(selection) {
|
||||
var container = selection.selectAll('data-layer-container')
|
||||
var container = selection.selectAll('.data-layer-container')
|
||||
.data([0]);
|
||||
|
||||
_dataLayerContainer = container.enter()
|
||||
@@ -478,7 +478,7 @@ export function uiMapData(context) {
|
||||
|
||||
|
||||
function renderFillList(selection) {
|
||||
var container = selection.selectAll('layer-fill-list')
|
||||
var container = selection.selectAll('.layer-fill-list')
|
||||
.data([0]);
|
||||
|
||||
_fillList = container.enter()
|
||||
@@ -489,7 +489,7 @@ export function uiMapData(context) {
|
||||
|
||||
|
||||
function renderFeatureList(selection) {
|
||||
var container = selection.selectAll('layer-feature-list')
|
||||
var container = selection.selectAll('.layer-feature-list')
|
||||
.data([0]);
|
||||
|
||||
_featureList = container.enter()
|
||||
|
||||
@@ -14,7 +14,6 @@ import { svgIcon } from '../svg';
|
||||
import { tooltip } from '../util/tooltip';
|
||||
import { uiTooltipHtml } from './tooltipHtml';
|
||||
|
||||
|
||||
export function uiModes(context) {
|
||||
var modes = [
|
||||
modeAddPoint(context),
|
||||
@@ -23,7 +22,6 @@ export function uiModes(context) {
|
||||
modeAddNote(context)
|
||||
];
|
||||
|
||||
|
||||
function editable() {
|
||||
var mode = context.mode();
|
||||
return context.editable() && mode && mode.id !== 'save';
|
||||
@@ -39,7 +37,6 @@ export function uiModes(context) {
|
||||
return context.map().notesEditable() && mode && mode.id !== 'save';
|
||||
}
|
||||
|
||||
|
||||
return function(selection) {
|
||||
context
|
||||
.on('enter.editor', function(entered) {
|
||||
|
||||
@@ -151,9 +151,14 @@ export function uiPresetList(context) {
|
||||
|
||||
|
||||
function drawList(list, presets) {
|
||||
var collection = presets.collection.map(function(preset) {
|
||||
return preset.members ? CategoryItem(preset) : PresetItem(preset);
|
||||
});
|
||||
var collection = presets.collection.reduce(function(collection, preset) {
|
||||
if (preset.members) {
|
||||
collection.push(CategoryItem(preset));
|
||||
} else if (preset.visible()) {
|
||||
collection.push(PresetItem(preset));
|
||||
}
|
||||
return collection;
|
||||
}, []);
|
||||
|
||||
var items = list.selectAll('.preset-list-item')
|
||||
.data(collection, function(d) { return d.preset.id; });
|
||||
|
||||
@@ -8,6 +8,8 @@ export { utilEditDistance } from './util';
|
||||
export { utilEntitySelector } from './util';
|
||||
export { utilEntityOrMemberSelector } from './util';
|
||||
export { utilEntityOrDeepMemberSelector } from './util';
|
||||
export { utilExternalPresets } from './util';
|
||||
export { utilExternalValidationRules } from './util';
|
||||
export { utilFastMouse } from './util';
|
||||
export { utilFunctor } from './util';
|
||||
export { utilGetAllNodes } from './util';
|
||||
@@ -25,6 +27,7 @@ export { utilRebind } from './rebind';
|
||||
export { utilSetTransform } from './util';
|
||||
export { utilSessionMutex } from './session_mutex';
|
||||
export { utilStringQs } from './util';
|
||||
// export { utilSuggestNames } from './suggest_names';
|
||||
export { utilTagText } from './util';
|
||||
export { utilTiler } from './tiler';
|
||||
export { utilTriggerEvent } from './trigger_event';
|
||||
|
||||
@@ -293,6 +293,13 @@ export function utilNoAuto(selection) {
|
||||
.attr('spellcheck', isText ? 'true' : 'false');
|
||||
}
|
||||
|
||||
export function utilExternalPresets() {
|
||||
return utilStringQs(window.location.hash).hasOwnProperty('presets');
|
||||
}
|
||||
|
||||
export function utilExternalValidationRules() {
|
||||
return utilStringQs(window.location.hash).hasOwnProperty('validations');
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/194846/is-there-any-kind-of-hash-code-function-in-javascript
|
||||
// https://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
export { validationDeprecatedTag } from './deprecated_tag';
|
||||
export { validationDisconnectedHighway } from './disconnected_highway';
|
||||
export { validationManyDeletions } from './many_deletions';
|
||||
export { validationMapCSSChecks } from './mapcss_checks';
|
||||
export { validationMissingTag } from './missing_tag';
|
||||
export { validationOldMultipolygon } from './old_multipolygon';
|
||||
export { validationTagSuggestsArea } from './tag_suggests_area';
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import { services } from '../services';
|
||||
|
||||
export function validationMapCSSChecks() {
|
||||
var validation = function(changes, graph) {
|
||||
if (!services.maprules) return [];
|
||||
|
||||
var rules = services.maprules.validationRules();
|
||||
var warnings = [];
|
||||
var createdModified = ['created', 'modified'];
|
||||
|
||||
for (var i = 0; i < rules.length; i++) {
|
||||
var rule = rules[i];
|
||||
for (var j = 0; j < createdModified.length; j++) {
|
||||
var type = createdModified[j];
|
||||
var entities = changes[type];
|
||||
for (var k = 0; k < entities.length; k++) {
|
||||
rule.findWarnings(entities[k], graph, warnings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return warnings;
|
||||
};
|
||||
return validation;
|
||||
}
|
||||
Reference in New Issue
Block a user