working on isArea-ish equivalent for mapcss selector objects

ref #remote-presets
This commit is contained in:
Max Grossman
2018-08-02 18:03:13 -04:00
parent 5b1dee3779
commit b93444de75
8 changed files with 158 additions and 98 deletions
+4
View File
@@ -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
View File
@@ -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
View File
@@ -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);
})
);
},
+1 -1
View File
@@ -121,7 +121,7 @@ export function presetIndex() {
areaKeys[key][value] = true;
}
});
console.log(areaKeys);
return areaKeys;
};
+87 -71
View File
@@ -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]));
}
}
});
}
+44 -2
View File
@@ -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);
}
},
+2 -2
View File
@@ -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);
-6
View File
@@ -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); });