mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-14 21:28:11 +02:00
working on isArea-ish equivalent for mapcss selector objects
ref #remote-presets
This commit is contained in:
@@ -3909,6 +3909,10 @@ svg.mouseclick use.right {
|
||||
background: #ffb;
|
||||
}
|
||||
|
||||
.mode-save .error-section {
|
||||
background: #ffa5a5;
|
||||
}
|
||||
|
||||
.mode-save .warning-section .changeset-list button {
|
||||
border-left: 1px solid #ccc;
|
||||
}
|
||||
|
||||
+10
-8
@@ -7,6 +7,8 @@ import _isObject from 'lodash-es/isObject';
|
||||
import _isString from 'lodash-es/isString';
|
||||
import _map from 'lodash-es/map';
|
||||
|
||||
import mapcssParse from 'mapcss-parse';
|
||||
|
||||
import { dispatch as d3_dispatch } from 'd3-dispatch';
|
||||
|
||||
import {
|
||||
@@ -455,14 +457,14 @@ export function coreContext() {
|
||||
locale = locale.split('-')[0];
|
||||
}
|
||||
|
||||
// if (utilExternalValidationRules()) {
|
||||
// var validationsUrl = utilStringQs(window.location.hash).validations;
|
||||
// d3_text(validationsUrl, function (err, mapcss) {
|
||||
// if (err) return;
|
||||
// var validations = _map(mapcssParse(mapcss), function(mapcssConfig) { return utilMapCSSRule(mapcssConfig); });
|
||||
// context.validationRules = function() { return validations; };
|
||||
// });
|
||||
// }
|
||||
if (utilExternalValidationRules()) {
|
||||
var validationsUrl = utilStringQs(window.location.hash).validations;
|
||||
d3_text(validationsUrl, function (err, mapcss) {
|
||||
if (err) return;
|
||||
var validations = _map(mapcssParse(mapcss), function(mapcssConfig) { return utilMapCSSRule(mapcssConfig, context.presets().areaKeys()); });
|
||||
context.validationRules = function() { return validations; };
|
||||
});
|
||||
}
|
||||
|
||||
history = coreHistory(context);
|
||||
context.graph = history.graph;
|
||||
|
||||
+10
-8
@@ -9,6 +9,7 @@ import _isEmpty from 'lodash-es/isEmpty';
|
||||
import _forEach from 'lodash-es/forEach';
|
||||
import _map from 'lodash-es/map';
|
||||
import _omit from 'lodash-es/omit';
|
||||
import _pickBy from 'lodash-es/pickBy';
|
||||
import _reject from 'lodash-es/reject';
|
||||
import _values from 'lodash-es/values';
|
||||
import _without from 'lodash-es/without';
|
||||
@@ -281,15 +282,16 @@ export function coreHistory(context) {
|
||||
|
||||
|
||||
validate: function(changes) {
|
||||
// strip mapcss checks if no mapcss to check against.
|
||||
var validationsToRun = _pickBy(Validations, function(validation) {
|
||||
return validation === Validations.validationMapCSSChecks && context.hasOwnProperty('validationRules') ||
|
||||
validation !== Validations.validationMapCSSChecks;
|
||||
});
|
||||
return _flatten(
|
||||
_map(Validations, function(fn) {
|
||||
var warnings;
|
||||
if (fn === Validations.validationMapCSSChecks && context.hasOwnProperty('validationRules')) {
|
||||
warnings = fn()(changes, _stack[_index].graph, context.validationRules());
|
||||
} else {
|
||||
warnings = fn()(changes, _stack[_index].graph);
|
||||
}
|
||||
return warnings;
|
||||
_map(validationsToRun, function(fn, name) {
|
||||
return name === 'validationMapCSSChecks' ?
|
||||
fn()(changes, _stack[_index].graph, context.validationRules()) :
|
||||
fn()(changes, _stack[_index].graph);
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
@@ -121,7 +121,7 @@ export function presetIndex() {
|
||||
areaKeys[key][value] = true;
|
||||
}
|
||||
});
|
||||
|
||||
console.log(areaKeys);
|
||||
return areaKeys;
|
||||
};
|
||||
|
||||
|
||||
@@ -3,91 +3,107 @@ 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';
|
||||
|
||||
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 type = val.id === 'mapcss_error' ? 'error' : 'warning';
|
||||
if (validations.hasOwnProperty(type)) {
|
||||
validations[type].push(val);
|
||||
} else {
|
||||
validations[type] = [val];
|
||||
}
|
||||
}
|
||||
return validations;
|
||||
}, {});
|
||||
|
||||
_forEach(validations, function(instances, type) {
|
||||
|
||||
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]));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import _isMatch from 'lodash-es/isMatch';
|
||||
import _reduce from 'lodash-es/reduce';
|
||||
|
||||
export function utilMapCSSRule(selector) {
|
||||
export function utilMapCSSRule(selector, areaKeys) {
|
||||
var ruleChecks = {
|
||||
equals: function (tags) {
|
||||
return _isMatch(tags, selector.equals);
|
||||
@@ -60,12 +61,53 @@ export function utilMapCSSRule(selector) {
|
||||
matches: function(entity) {
|
||||
return this.buildChecks().every(function(check) { return check(entity.tags); });
|
||||
|
||||
},
|
||||
// borrowed from Way#isArea()
|
||||
inferGeometry() {
|
||||
// keys is a map of osm key + all found values across the selector map.
|
||||
var selectorKeys = _reduce(Object.keys(selector), function(expectedTags, key) {
|
||||
var values;
|
||||
if(/regex/gi.test(key)) {
|
||||
Object.keys(p[key]).forEach(function(regexKey) {
|
||||
values = p[key][rKey].map(function(val) { return val.replace(/\$|\^/g, '') })
|
||||
if (expectedTags.hasOwnProperty(regexKey)) {
|
||||
values = values.concat(expectedTags[regexKey])
|
||||
|
||||
}
|
||||
expectedTags[regexKey] = values
|
||||
})
|
||||
}
|
||||
if (key === 'equals') {
|
||||
var equalsKey = Object.keys(p[key])[0]
|
||||
values = [p[key][equalsKey]]
|
||||
if (expectedTags.hasOwnProperty(equalsKey)) {
|
||||
values = values.concat(expectedTags[equalsKey])
|
||||
}
|
||||
expectedTags[equalsKey] = values
|
||||
}
|
||||
return expectedTags
|
||||
}, {})
|
||||
|
||||
if (Object.keys(keys).indexOf('area') > -1) {
|
||||
inferredGeometry = 'area';
|
||||
return;
|
||||
}
|
||||
|
||||
for (var key in Object.keys(keys)) {
|
||||
if (key in areaKeys) {
|
||||
if (keys[key] !== 'absence' && key in ) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
geometryMatches: function(entity, graph) {
|
||||
if (entity.type === 'node' || entity.type === 'relation') {
|
||||
return selector.geometry === entity.type;
|
||||
} else if (entity.type === 'way') {
|
||||
return selector.geometry === entity.geometry(graph);
|
||||
return this.inferGeometry() === entity.geometry(graph);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
export function validationMapCSSChecks() {
|
||||
var validation = function(changes, graph, rules) {
|
||||
var validation = function(changes, graph, rules, areaKeys) {
|
||||
var warnings = [];
|
||||
var createdModified = ['created', 'modified'];
|
||||
for (var i = 0; i < createdModified.length; i++) {
|
||||
var entities = changes[createdModified[i]];
|
||||
for (var j = 0; j < entities.length; j++) {
|
||||
var entity = entities[i];
|
||||
var entity = entities[j];
|
||||
for (var k = 0; k < rules.length; k++) {
|
||||
var rule = rules[k];
|
||||
rule.findWarnings(entity, graph, warnings);
|
||||
|
||||
@@ -41,12 +41,6 @@ describe('iD.utilMapCSSRule', function() {
|
||||
'presence': 'amenity',
|
||||
'positiveRegex': { amenity: ['^school$', '^healthcare$'] },
|
||||
'error': 'amenity cannot be healthcare or school!'
|
||||
},
|
||||
{
|
||||
'geometry': 'node',
|
||||
'presence': 'amenity',
|
||||
'negativeRegex': { amenity: ['^school$', '^healthcare$'] },
|
||||
'error': 'amenity must be healtcare or school!'
|
||||
}
|
||||
];
|
||||
var rules = selectors.map(function(s) { return iD.utilMapCSSRule(s); });
|
||||
|
||||
Reference in New Issue
Block a user